Files
core/iam/identity_test.go
2023-02-17 17:27:39 +01:00

820 lines
18 KiB
Go

package iam
import (
"testing"
"github.com/datarhei/core/v16/io/fs"
"github.com/stretchr/testify/require"
)
func TestUserName(t *testing.T) {
user := User{}
err := user.validate()
require.Error(t, err)
user.Name = "foobar_5"
err = user.validate()
require.NoError(t, err)
user.Name = "$foob:ar"
err = user.validate()
require.Error(t, err)
}
func TestUserAuth(t *testing.T) {
user := User{
Name: "foobar",
}
err := user.validate()
require.NoError(t, err)
user.Auth.API.Userpass.Enable = true
err = user.validate()
require.Error(t, err)
user.Auth.API.Userpass.Password = "secret"
err = user.validate()
require.NoError(t, err)
user.Auth.API.Auth0.Enable = true
err = user.validate()
require.Error(t, err)
user.Auth.API.Auth0.User = "auth0|123456"
err = user.validate()
require.NoError(t, err)
user.Auth.Services.Basic.Enable = true
err = user.validate()
require.Error(t, err)
user.Auth.Services.Basic.Password = "secret"
err = user.validate()
require.NoError(t, err)
}
func TestIdentity(t *testing.T) {
user := User{
Name: "foobar",
}
identity := user.marshalIdentity()
require.Equal(t, "foobar", identity.Name())
require.False(t, identity.isValid())
identity.valid = true
require.True(t, identity.isValid())
require.False(t, identity.IsSuperuser())
identity.user.Superuser = true
require.True(t, identity.IsSuperuser())
dummyfs, err := fs.NewMemFilesystem(fs.MemConfig{})
require.NoError(t, err)
im, err := NewIdentityManager(IdentityConfig{
FS: dummyfs,
Superuser: User{Name: "foobar"},
JWTRealm: "test-realm",
JWTSecret: "abc123",
Logger: nil,
})
require.NoError(t, err)
require.NotNil(t, im)
id, err := im.GetVerifier("unknown")
require.Error(t, err)
require.Nil(t, id)
}
func TestDefaultIdentity(t *testing.T) {
dummyfs, err := fs.NewMemFilesystem(fs.MemConfig{})
require.NoError(t, err)
im, err := NewIdentityManager(IdentityConfig{
FS: dummyfs,
Superuser: User{Name: "foobar"},
JWTRealm: "test-realm",
JWTSecret: "abc123",
Logger: nil,
})
require.NoError(t, err)
require.NotNil(t, im)
identity, err := im.GetDefaultVerifier()
require.NoError(t, err)
require.NotNil(t, identity)
require.Equal(t, "foobar", identity.Name())
}
func TestIdentityAPIAuth(t *testing.T) {
user := User{
Name: "foobar",
}
identity := user.marshalIdentity()
ok, err := identity.VerifyAPIPassword("secret")
require.False(t, ok)
require.Error(t, err)
identity.user.Auth.API.Userpass.Enable = true
identity.user.Auth.API.Userpass.Password = "secret"
ok, err = identity.VerifyAPIPassword("secret")
require.False(t, ok)
require.Error(t, err)
identity.valid = true
ok, err = identity.VerifyAPIPassword("secret")
require.True(t, ok)
require.NoError(t, err)
identity.user.Auth.API.Userpass.Enable = false
ok, err = identity.VerifyAPIPassword("secret")
require.False(t, ok)
require.Error(t, err)
identity.user.Auth.API.Userpass.Enable = true
identity.user.Auth.API.Userpass.Password = "terces"
ok, err = identity.VerifyAPIPassword("secret")
require.False(t, ok)
require.NoError(t, err)
}
func TestIdentityServiceBasicAuth(t *testing.T) {
user := User{
Name: "foobar",
}
identity := user.marshalIdentity()
ok, err := identity.VerifyServiceBasicAuth("secret")
require.False(t, ok)
require.Error(t, err)
identity.user.Auth.Services.Basic.Enable = true
identity.user.Auth.Services.Basic.Password = "secret"
ok, err = identity.VerifyServiceBasicAuth("secret")
require.False(t, ok)
require.Error(t, err)
identity.valid = true
ok, err = identity.VerifyServiceBasicAuth("secret")
require.True(t, ok)
require.NoError(t, err)
identity.user.Auth.Services.Basic.Enable = false
ok, err = identity.VerifyServiceBasicAuth("secret")
require.False(t, ok)
require.Error(t, err)
identity.user.Auth.Services.Basic.Enable = true
identity.user.Auth.Services.Basic.Password = "terces"
ok, err = identity.VerifyServiceBasicAuth("secret")
require.False(t, ok)
require.NoError(t, err)
password := identity.GetServiceBasicAuth()
require.Equal(t, "terces", password)
}
func TestIdentityServiceTokenAuth(t *testing.T) {
user := User{
Name: "foobar",
}
identity := user.marshalIdentity()
ok, err := identity.VerifyServiceToken("secret")
require.False(t, ok)
require.Error(t, err)
identity.user.Auth.Services.Token = []string{"secret"}
ok, err = identity.VerifyServiceToken("secret")
require.False(t, ok)
require.Error(t, err)
identity.valid = true
ok, err = identity.VerifyServiceToken("secret")
require.True(t, ok)
require.NoError(t, err)
identity.user.Auth.Services.Token = []string{"terces"}
ok, err = identity.VerifyServiceToken("secret")
require.False(t, ok)
require.NoError(t, err)
token := identity.GetServiceToken()
require.Equal(t, "foobar:terces", token)
}
func TestJWT(t *testing.T) {
dummyfs, err := fs.NewMemFilesystem(fs.MemConfig{})
require.NoError(t, err)
im, err := NewIdentityManager(IdentityConfig{
FS: dummyfs,
Superuser: User{Name: "foobar"},
JWTRealm: "test-realm",
JWTSecret: "abc123",
Logger: nil,
})
require.NoError(t, err)
require.NotNil(t, im)
access, refresh, err := im.CreateJWT("foobaz")
require.Error(t, err)
require.Equal(t, "", access)
require.Equal(t, "", refresh)
access, refresh, err = im.CreateJWT("foobar")
require.NoError(t, err)
identity, err := im.GetVerifier("foobar")
require.NoError(t, err)
require.NotNil(t, identity)
ok, err := identity.VerifyJWT("something")
require.Error(t, err)
require.False(t, ok)
ok, err = identity.VerifyJWT(access)
require.NoError(t, err)
require.True(t, ok)
ok, err = identity.VerifyJWT(refresh)
require.NoError(t, err)
require.True(t, ok)
err = im.Create(User{Name: "foobaz"})
require.NoError(t, err)
access, refresh, err = im.CreateJWT("foobaz")
require.NoError(t, err)
ok, err = identity.VerifyJWT(access)
require.Error(t, err)
require.False(t, ok)
ok, err = identity.VerifyJWT(refresh)
require.Error(t, err)
require.False(t, ok)
}
func TestCreateUser(t *testing.T) {
dummyfs, err := fs.NewMemFilesystem(fs.MemConfig{})
require.NoError(t, err)
im, err := NewIdentityManager(IdentityConfig{
FS: dummyfs,
Superuser: User{Name: "foobar"},
JWTRealm: "test-realm",
JWTSecret: "abc123",
Logger: nil,
})
require.NoError(t, err)
require.NotNil(t, im)
err = im.Create(User{Name: "foobar"})
require.Error(t, err)
err = im.Create(User{Name: "foobaz"})
require.NoError(t, err)
err = im.Create(User{Name: "foobaz"})
require.Error(t, err)
}
func TestCreateUserAuth0(t *testing.T) {
dummyfs, err := fs.NewMemFilesystem(fs.MemConfig{})
require.NoError(t, err)
im, err := NewIdentityManager(IdentityConfig{
FS: dummyfs,
Superuser: User{Name: "foobar"},
JWTRealm: "test-realm",
JWTSecret: "abc123",
Logger: nil,
})
require.NoError(t, err)
require.NotNil(t, im)
require.ElementsMatch(t, []string{"localjwt"}, im.Validators())
err = im.Create(User{
Name: "foobaz",
Superuser: false,
Auth: UserAuth{
API: UserAuthAPI{
Auth0: UserAuthAPIAuth0{
Enable: true,
User: "auth0|123456",
Tenant: Auth0Tenant{
Domain: "example.com",
Audience: "https://api.example.com/",
ClientID: "123456",
},
},
},
},
})
require.Error(t, err)
err = im.Create(User{
Name: "foobaz",
Superuser: false,
Auth: UserAuth{
API: UserAuthAPI{
Auth0: UserAuthAPIAuth0{
Enable: true,
User: "auth0|123456",
Tenant: Auth0Tenant{
Domain: "datarhei-demo.eu.auth0.com",
Audience: "https://datarhei-demo.eu.auth0.com/api/v2/",
ClientID: "123456",
},
},
},
},
})
require.NoError(t, err)
identity, err := im.GetVerifierByAuth0("foobaz")
require.Error(t, err)
require.Nil(t, identity)
identity, err = im.GetVerifierByAuth0("auth0|123456")
require.NoError(t, err)
require.NotNil(t, identity)
manager, ok := im.(*identityManager)
require.True(t, ok)
require.NotNil(t, manager)
require.Equal(t, 1, len(manager.tenants))
require.Equal(t, map[string]string{"auth0|123456": "foobaz"}, manager.auth0UserIdentityMap)
require.ElementsMatch(t, []string{
"localjwt",
"auth0 domain=datarhei-demo.eu.auth0.com audience=https://datarhei-demo.eu.auth0.com/api/v2/ clientid=123456",
}, im.Validators())
err = im.Create(User{
Name: "fooboz",
Superuser: false,
Auth: UserAuth{
API: UserAuthAPI{
Auth0: UserAuthAPIAuth0{
Enable: true,
User: "auth0|123456",
Tenant: Auth0Tenant{
Domain: "datarhei-demo.eu.auth0.com",
Audience: "https://datarhei-demo.eu.auth0.com/api/v2/",
ClientID: "123456",
},
},
},
},
})
require.Error(t, err)
err = im.Create(User{
Name: "fooboz",
Superuser: false,
Auth: UserAuth{
API: UserAuthAPI{
Auth0: UserAuthAPIAuth0{
Enable: true,
User: "auth0|987654",
Tenant: Auth0Tenant{
Domain: "datarhei-demo.eu.auth0.com",
Audience: "https://datarhei-demo.eu.auth0.com/api/v2/",
ClientID: "987654",
},
},
},
},
})
require.NoError(t, err)
require.Equal(t, 1, len(manager.tenants))
require.Equal(t, map[string]string{"auth0|123456": "foobaz", "auth0|987654": "fooboz"}, manager.auth0UserIdentityMap)
require.ElementsMatch(t, []string{
"localjwt",
"auth0 domain=datarhei-demo.eu.auth0.com audience=https://datarhei-demo.eu.auth0.com/api/v2/ clientid=123456",
"auth0 domain=datarhei-demo.eu.auth0.com audience=https://datarhei-demo.eu.auth0.com/api/v2/ clientid=987654",
}, im.Validators())
im.Close()
}
func TestLoadAndSave(t *testing.T) {
dummyfs, err := fs.NewMemFilesystem(fs.MemConfig{})
require.NoError(t, err)
im, err := NewIdentityManager(IdentityConfig{
FS: dummyfs,
Superuser: User{Name: "foobar"},
JWTRealm: "test-realm",
JWTSecret: "abc123",
Logger: nil,
})
require.NoError(t, err)
require.NotNil(t, im)
err = im.Save()
require.NoError(t, err)
_, err = dummyfs.Stat("./users.json")
require.NoError(t, err)
data, err := dummyfs.ReadFile("./users.json")
require.NoError(t, err)
require.Equal(t, []byte("[]"), data)
err = im.Create(User{Name: "foobaz"})
require.NoError(t, err)
identity, err := im.GetVerifier("foobaz")
require.NoError(t, err)
require.NotNil(t, identity)
err = im.Save()
require.NoError(t, err)
im, err = NewIdentityManager(IdentityConfig{
FS: dummyfs,
Superuser: User{Name: "foobar"},
JWTRealm: "test-realm",
JWTSecret: "abc123",
Logger: nil,
})
require.NoError(t, err)
require.NotNil(t, im)
identity, err = im.GetVerifier("foobaz")
require.NoError(t, err)
require.NotNil(t, identity)
}
func TestUpdateUser(t *testing.T) {
dummyfs, err := fs.NewMemFilesystem(fs.MemConfig{})
require.NoError(t, err)
im, err := NewIdentityManager(IdentityConfig{
FS: dummyfs,
Superuser: User{Name: "foobar"},
JWTRealm: "test-realm",
JWTSecret: "abc123",
Logger: nil,
})
require.NoError(t, err)
require.NotNil(t, im)
err = im.Create(User{Name: "fooboz"})
require.NoError(t, err)
err = im.Update("unknown", User{Name: "fooboz"})
require.Error(t, err)
err = im.Update("foobar", User{Name: "foobar"})
require.Error(t, err)
err = im.Update("foobar", User{Name: "fooboz"})
require.Error(t, err)
identity, err := im.GetVerifier("foobar")
require.NoError(t, err)
require.NotNil(t, identity)
require.Equal(t, "foobar", identity.Name())
err = im.Update("foobar", User{Name: "foobaz"})
require.Error(t, err)
require.Equal(t, "foobar", identity.Name())
identity, err = im.GetVerifier("foobaz")
require.Error(t, err)
require.Nil(t, identity)
identity, err = im.GetVerifier("fooboz")
require.NoError(t, err)
require.NotNil(t, identity)
require.Equal(t, "fooboz", identity.Name())
err = im.Update("fooboz", User{Name: "foobaz"})
require.NoError(t, err)
}
func TestUpdateUserAuth0(t *testing.T) {
dummyfs, err := fs.NewMemFilesystem(fs.MemConfig{})
require.NoError(t, err)
im, err := NewIdentityManager(IdentityConfig{
FS: dummyfs,
Superuser: User{Name: "foobar"},
JWTRealm: "test-realm",
JWTSecret: "abc123",
Logger: nil,
})
require.NoError(t, err)
require.NotNil(t, im)
err = im.Create(User{
Name: "foobaz",
Superuser: false,
Auth: UserAuth{
API: UserAuthAPI{
Auth0: UserAuthAPIAuth0{
Enable: true,
User: "auth0|123456",
Tenant: Auth0Tenant{
Domain: "datarhei-demo.eu.auth0.com",
Audience: "https://datarhei-demo.eu.auth0.com/api/v2/",
ClientID: "123456",
},
},
},
},
})
require.NoError(t, err)
identity, err := im.GetVerifierByAuth0("auth0|123456")
require.NoError(t, err)
require.NotNil(t, identity)
identity, err = im.GetVerifier("foobaz")
require.NoError(t, err)
require.NotNil(t, identity)
user, err := im.Get("foobaz")
require.NoError(t, err)
user.Name = "fooboz"
err = im.Update("foobaz", user)
require.NoError(t, err)
identity, err = im.GetVerifierByAuth0("auth0|123456")
require.NoError(t, err)
require.NotNil(t, identity)
identity, err = im.GetVerifier("fooboz")
require.NoError(t, err)
require.NotNil(t, identity)
}
func TestRemoveUser(t *testing.T) {
dummyfs, err := fs.NewMemFilesystem(fs.MemConfig{})
require.NoError(t, err)
im, err := NewIdentityManager(IdentityConfig{
FS: dummyfs,
Superuser: User{Name: "foobar"},
JWTRealm: "test-realm",
JWTSecret: "abc123",
Logger: nil,
})
require.NoError(t, err)
require.NotNil(t, im)
err = im.Delete("fooboz")
require.Error(t, err)
err = im.Delete("foobar")
require.Error(t, err)
err = im.Create(User{
Name: "foobaz",
Superuser: false,
Auth: UserAuth{
API: UserAuthAPI{
Userpass: UserAuthPassword{
Enable: true,
Password: "apisecret",
},
Auth0: UserAuthAPIAuth0{},
},
Services: UserAuthServices{
Basic: UserAuthPassword{
Enable: true,
Password: "secret",
},
Token: []string{"tokensecret"},
},
},
})
require.NoError(t, err)
identity, err := im.GetVerifier("foobaz")
require.NoError(t, err)
require.NotNil(t, identity)
ok, err := identity.VerifyAPIPassword("apisecret")
require.True(t, ok)
require.NoError(t, err)
ok, err = identity.VerifyServiceBasicAuth("secret")
require.True(t, ok)
require.NoError(t, err)
ok, err = identity.VerifyServiceToken("tokensecret")
require.True(t, ok)
require.NoError(t, err)
access, refresh, err := im.CreateJWT("foobaz")
require.NoError(t, err)
ok, err = identity.VerifyJWT(access)
require.True(t, ok)
require.NoError(t, err)
ok, err = identity.VerifyJWT(refresh)
require.True(t, ok)
require.NoError(t, err)
err = im.Delete("foobaz")
require.NoError(t, err)
ok, err = identity.VerifyAPIPassword("apisecret")
require.False(t, ok)
require.Error(t, err)
ok, err = identity.VerifyServiceBasicAuth("secret")
require.False(t, ok)
require.Error(t, err)
ok, err = identity.VerifyServiceToken("tokensecret")
require.False(t, ok)
require.Error(t, err)
ok, err = identity.VerifyJWT(access)
require.False(t, ok)
require.Error(t, err)
ok, err = identity.VerifyJWT(refresh)
require.False(t, ok)
require.Error(t, err)
identity, err = im.GetVerifier("foobaz")
require.Error(t, err)
require.Nil(t, identity)
access, refresh, err = im.CreateJWT("foobaz")
require.Error(t, err)
require.Empty(t, access)
require.Empty(t, refresh)
}
func TestRemoveUserAuth0(t *testing.T) {
dummyfs, err := fs.NewMemFilesystem(fs.MemConfig{})
require.NoError(t, err)
im, err := NewIdentityManager(IdentityConfig{
FS: dummyfs,
Superuser: User{Name: "foobar"},
JWTRealm: "test-realm",
JWTSecret: "abc123",
Logger: nil,
})
require.NoError(t, err)
require.NotNil(t, im)
err = im.Create(User{
Name: "foobaz",
Superuser: false,
Auth: UserAuth{
API: UserAuthAPI{
Auth0: UserAuthAPIAuth0{
Enable: true,
User: "auth0|123456",
Tenant: Auth0Tenant{
Domain: "datarhei-demo.eu.auth0.com",
Audience: "https://datarhei-demo.eu.auth0.com/api/v2/",
ClientID: "123456",
},
},
},
},
})
require.NoError(t, err)
err = im.Create(User{
Name: "fooboz",
Superuser: false,
Auth: UserAuth{
API: UserAuthAPI{
Auth0: UserAuthAPIAuth0{
Enable: true,
User: "auth0|987654",
Tenant: Auth0Tenant{
Domain: "datarhei-demo.eu.auth0.com",
Audience: "https://datarhei-demo.eu.auth0.com/api/v2/",
ClientID: "987654",
},
},
},
},
})
require.NoError(t, err)
manager, ok := im.(*identityManager)
require.True(t, ok)
require.NotNil(t, manager)
require.Equal(t, 1, len(manager.tenants))
require.Equal(t, map[string]string{"auth0|123456": "foobaz", "auth0|987654": "fooboz"}, manager.auth0UserIdentityMap)
require.ElementsMatch(t, []string{
"localjwt",
"auth0 domain=datarhei-demo.eu.auth0.com audience=https://datarhei-demo.eu.auth0.com/api/v2/ clientid=123456",
"auth0 domain=datarhei-demo.eu.auth0.com audience=https://datarhei-demo.eu.auth0.com/api/v2/ clientid=987654",
}, im.Validators())
err = im.Delete("foobaz")
require.NoError(t, err)
require.Equal(t, 1, len(manager.tenants))
require.Equal(t, map[string]string{"auth0|987654": "fooboz"}, manager.auth0UserIdentityMap)
require.ElementsMatch(t, []string{
"localjwt",
"auth0 domain=datarhei-demo.eu.auth0.com audience=https://datarhei-demo.eu.auth0.com/api/v2/ clientid=987654",
}, im.Validators())
err = im.Delete("fooboz")
require.NoError(t, err)
require.Equal(t, 0, len(manager.tenants))
require.ElementsMatch(t, []string{
"localjwt",
}, im.Validators())
}
func TestAutosave(t *testing.T) {
dummyfs, err := fs.NewMemFilesystem(fs.MemConfig{})
require.NoError(t, err)
im, err := NewIdentityManager(IdentityConfig{
FS: dummyfs,
Superuser: User{Name: "foobar"},
JWTRealm: "test-realm",
JWTSecret: "abc123",
Logger: nil,
})
require.NoError(t, err)
require.NotNil(t, im)
err = im.Save()
require.NoError(t, err)
_, err = dummyfs.Stat("./users.json")
require.NoError(t, err)
data, err := dummyfs.ReadFile("./users.json")
require.NoError(t, err)
require.Equal(t, []byte("[]"), data)
im.Autosave(true)
err = im.Create(User{Name: "foobaz"})
require.NoError(t, err)
data, err = dummyfs.ReadFile("./users.json")
require.NoError(t, err)
require.NotEqual(t, []byte("[]"), data)
user, err := im.Get("foobaz")
require.NoError(t, err)
user.Name = "fooboz"
err = im.Update("foobaz", user)
require.NoError(t, err)
data, err = dummyfs.ReadFile("./users.json")
require.NoError(t, err)
require.NotEqual(t, []byte("[]"), data)
err = im.Delete("fooboz")
require.NoError(t, err)
data, err = dummyfs.ReadFile("./users.json")
require.NoError(t, err)
require.Equal(t, []byte("[]"), data)
}