mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
212 lines
7.7 KiB
Go
212 lines
7.7 KiB
Go
|
|
package extsvcaccounts
|
||
|
|
|
||
|
|
import (
|
||
|
|
"context"
|
||
|
|
"testing"
|
||
|
|
|
||
|
|
"github.com/grafana/grafana/pkg/infra/localcache"
|
||
|
|
"github.com/grafana/grafana/pkg/infra/log"
|
||
|
|
"github.com/grafana/grafana/pkg/models/roletype"
|
||
|
|
ac "github.com/grafana/grafana/pkg/services/accesscontrol"
|
||
|
|
"github.com/grafana/grafana/pkg/services/accesscontrol/acimpl"
|
||
|
|
"github.com/grafana/grafana/pkg/services/accesscontrol/actest"
|
||
|
|
"github.com/grafana/grafana/pkg/services/extsvcauth"
|
||
|
|
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||
|
|
sa "github.com/grafana/grafana/pkg/services/serviceaccounts"
|
||
|
|
"github.com/grafana/grafana/pkg/services/serviceaccounts/tests"
|
||
|
|
"github.com/grafana/grafana/pkg/setting"
|
||
|
|
"github.com/stretchr/testify/mock"
|
||
|
|
"github.com/stretchr/testify/require"
|
||
|
|
)
|
||
|
|
|
||
|
|
type TestEnv struct {
|
||
|
|
S *ExtSvcAccountsService
|
||
|
|
AcStore *actest.MockStore
|
||
|
|
SaSvc *tests.MockServiceAccountService
|
||
|
|
}
|
||
|
|
|
||
|
|
func setupTestEnv(t *testing.T) *TestEnv {
|
||
|
|
t.Helper()
|
||
|
|
|
||
|
|
cfg := setting.NewCfg()
|
||
|
|
fmgt := featuremgmt.WithFeatures(featuremgmt.FlagExternalServiceAuth)
|
||
|
|
|
||
|
|
env := &TestEnv{
|
||
|
|
AcStore: &actest.MockStore{},
|
||
|
|
SaSvc: &tests.MockServiceAccountService{},
|
||
|
|
}
|
||
|
|
env.S = &ExtSvcAccountsService{
|
||
|
|
acSvc: acimpl.ProvideOSSService(cfg, env.AcStore, localcache.New(0, 0), fmgt),
|
||
|
|
logger: log.New("extsvcaccounts.test"),
|
||
|
|
saSvc: env.SaSvc,
|
||
|
|
}
|
||
|
|
return env
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestExtSvcAccountsService_ManageExtSvcAccount(t *testing.T) {
|
||
|
|
extSvcSlug := "grafana-test-app"
|
||
|
|
extSvcOrgID := int64(20)
|
||
|
|
extSvcAccID := int64(10)
|
||
|
|
extSvcPerms := []ac.Permission{{Action: ac.ActionUsersRead, Scope: ac.ScopeUsersAll}}
|
||
|
|
extSvcAccount := &sa.ServiceAccountDTO{
|
||
|
|
Id: extSvcAccID,
|
||
|
|
Name: extSvcSlug,
|
||
|
|
Login: extSvcSlug,
|
||
|
|
OrgId: extSvcOrgID,
|
||
|
|
IsDisabled: false,
|
||
|
|
Role: string(roletype.RoleNone),
|
||
|
|
}
|
||
|
|
|
||
|
|
tests := []struct {
|
||
|
|
name string
|
||
|
|
init func(env *TestEnv)
|
||
|
|
cmd extsvcauth.ManageExtSvcAccountCmd
|
||
|
|
checks func(t *testing.T, env *TestEnv)
|
||
|
|
want int64
|
||
|
|
wantErr bool
|
||
|
|
}{
|
||
|
|
{
|
||
|
|
name: "should remove service account when disabled",
|
||
|
|
init: func(env *TestEnv) {
|
||
|
|
// A previous service account was attached to this slug
|
||
|
|
env.SaSvc.On("RetrieveServiceAccountIdByName", mock.Anything, mock.Anything, mock.Anything).Return(extSvcAccID, nil)
|
||
|
|
env.SaSvc.On("DeleteServiceAccount", mock.Anything, mock.Anything, mock.Anything).Return(nil)
|
||
|
|
env.AcStore.On("DeleteExternalServiceRole", mock.Anything, mock.Anything).Return(nil)
|
||
|
|
},
|
||
|
|
cmd: extsvcauth.ManageExtSvcAccountCmd{
|
||
|
|
ExtSvcSlug: extSvcSlug,
|
||
|
|
Enabled: false,
|
||
|
|
OrgID: extSvcOrgID,
|
||
|
|
Permissions: extSvcPerms,
|
||
|
|
},
|
||
|
|
checks: func(t *testing.T, env *TestEnv) {
|
||
|
|
env.SaSvc.AssertCalled(t, "RetrieveServiceAccountIdByName", mock.Anything,
|
||
|
|
mock.MatchedBy(func(orgID int64) bool { return orgID == extSvcOrgID }),
|
||
|
|
mock.MatchedBy(func(slug string) bool { return slug == extSvcSlug }))
|
||
|
|
env.SaSvc.AssertCalled(t, "DeleteServiceAccount", mock.Anything,
|
||
|
|
mock.MatchedBy(func(orgID int64) bool { return orgID == extSvcOrgID }),
|
||
|
|
mock.MatchedBy(func(saID int64) bool { return saID == extSvcAccID }))
|
||
|
|
env.AcStore.AssertCalled(t, "DeleteExternalServiceRole", mock.Anything,
|
||
|
|
mock.MatchedBy(func(slug string) bool { return slug == extSvcSlug }))
|
||
|
|
},
|
||
|
|
want: 0,
|
||
|
|
wantErr: false,
|
||
|
|
},
|
||
|
|
{
|
||
|
|
name: "should remove service account when no permission",
|
||
|
|
init: func(env *TestEnv) {
|
||
|
|
// A previous service account was attached to this slug
|
||
|
|
env.SaSvc.On("RetrieveServiceAccountIdByName", mock.Anything, mock.Anything, mock.Anything).Return(extSvcAccID, nil)
|
||
|
|
env.SaSvc.On("DeleteServiceAccount", mock.Anything, mock.Anything, mock.Anything).Return(nil)
|
||
|
|
env.AcStore.On("DeleteExternalServiceRole", mock.Anything, mock.Anything).Return(nil)
|
||
|
|
},
|
||
|
|
cmd: extsvcauth.ManageExtSvcAccountCmd{
|
||
|
|
ExtSvcSlug: extSvcSlug,
|
||
|
|
Enabled: true,
|
||
|
|
OrgID: extSvcOrgID,
|
||
|
|
Permissions: []ac.Permission{},
|
||
|
|
},
|
||
|
|
checks: func(t *testing.T, env *TestEnv) {
|
||
|
|
env.SaSvc.AssertCalled(t, "RetrieveServiceAccountIdByName", mock.Anything,
|
||
|
|
mock.MatchedBy(func(orgID int64) bool { return orgID == extSvcOrgID }),
|
||
|
|
mock.MatchedBy(func(slug string) bool { return slug == extSvcSlug }))
|
||
|
|
env.SaSvc.AssertCalled(t, "DeleteServiceAccount", mock.Anything,
|
||
|
|
mock.MatchedBy(func(orgID int64) bool { return orgID == extSvcOrgID }),
|
||
|
|
mock.MatchedBy(func(saID int64) bool { return saID == extSvcAccID }))
|
||
|
|
env.AcStore.AssertCalled(t, "DeleteExternalServiceRole", mock.Anything,
|
||
|
|
mock.MatchedBy(func(slug string) bool { return slug == extSvcSlug }))
|
||
|
|
},
|
||
|
|
want: 0,
|
||
|
|
wantErr: false,
|
||
|
|
},
|
||
|
|
{
|
||
|
|
name: "should create new service account",
|
||
|
|
init: func(env *TestEnv) {
|
||
|
|
// No previous service account was attached to this slug
|
||
|
|
env.SaSvc.On("RetrieveServiceAccountIdByName", mock.Anything, mock.Anything, mock.Anything).
|
||
|
|
Return(int64(0), sa.ErrServiceAccountNotFound.Errorf("mock"))
|
||
|
|
env.SaSvc.On("CreateServiceAccount", mock.Anything, mock.Anything, mock.Anything).
|
||
|
|
Return(extSvcAccount, nil)
|
||
|
|
env.AcStore.On("SaveExternalServiceRole", mock.Anything, mock.Anything).Return(nil)
|
||
|
|
},
|
||
|
|
cmd: extsvcauth.ManageExtSvcAccountCmd{
|
||
|
|
ExtSvcSlug: extSvcSlug,
|
||
|
|
Enabled: true,
|
||
|
|
OrgID: extSvcOrgID,
|
||
|
|
Permissions: extSvcPerms,
|
||
|
|
},
|
||
|
|
checks: func(t *testing.T, env *TestEnv) {
|
||
|
|
env.SaSvc.AssertCalled(t, "RetrieveServiceAccountIdByName", mock.Anything,
|
||
|
|
mock.MatchedBy(func(orgID int64) bool { return orgID == extSvcOrgID }),
|
||
|
|
mock.MatchedBy(func(slug string) bool { return slug == extSvcSlug }))
|
||
|
|
env.SaSvc.AssertCalled(t, "CreateServiceAccount", mock.Anything,
|
||
|
|
mock.MatchedBy(func(orgID int64) bool { return orgID == extSvcOrgID }),
|
||
|
|
mock.MatchedBy(func(cmd *sa.CreateServiceAccountForm) bool {
|
||
|
|
return cmd.Name == extSvcSlug && *cmd.Role == roletype.RoleNone
|
||
|
|
}),
|
||
|
|
)
|
||
|
|
env.AcStore.AssertCalled(t, "SaveExternalServiceRole", mock.Anything,
|
||
|
|
mock.MatchedBy(func(cmd ac.SaveExternalServiceRoleCommand) bool {
|
||
|
|
return cmd.ServiceAccountID == extSvcAccount.Id && cmd.ExternalServiceID == extSvcSlug &&
|
||
|
|
cmd.OrgID == int64(ac.GlobalOrgID) && len(cmd.Permissions) == 1 &&
|
||
|
|
cmd.Permissions[0] == extSvcPerms[0]
|
||
|
|
}))
|
||
|
|
},
|
||
|
|
want: extSvcAccID,
|
||
|
|
wantErr: false,
|
||
|
|
},
|
||
|
|
{
|
||
|
|
name: "should update service account",
|
||
|
|
init: func(env *TestEnv) {
|
||
|
|
// A previous service account was attached to this slug
|
||
|
|
env.SaSvc.On("RetrieveServiceAccountIdByName", mock.Anything, mock.Anything, mock.Anything).
|
||
|
|
Return(int64(11), nil)
|
||
|
|
env.AcStore.On("SaveExternalServiceRole", mock.Anything, mock.Anything).Return(nil)
|
||
|
|
},
|
||
|
|
cmd: extsvcauth.ManageExtSvcAccountCmd{
|
||
|
|
ExtSvcSlug: extSvcSlug,
|
||
|
|
Enabled: true,
|
||
|
|
OrgID: extSvcOrgID,
|
||
|
|
Permissions: extSvcPerms,
|
||
|
|
},
|
||
|
|
checks: func(t *testing.T, env *TestEnv) {
|
||
|
|
env.SaSvc.AssertCalled(t, "RetrieveServiceAccountIdByName", mock.Anything,
|
||
|
|
mock.MatchedBy(func(orgID int64) bool { return orgID == extSvcOrgID }),
|
||
|
|
mock.MatchedBy(func(slug string) bool { return slug == extSvcSlug }))
|
||
|
|
env.AcStore.AssertCalled(t, "SaveExternalServiceRole", mock.Anything,
|
||
|
|
mock.MatchedBy(func(cmd ac.SaveExternalServiceRoleCommand) bool {
|
||
|
|
return cmd.ServiceAccountID == int64(11) && cmd.ExternalServiceID == extSvcSlug &&
|
||
|
|
cmd.OrgID == int64(ac.GlobalOrgID) && len(cmd.Permissions) == 1 &&
|
||
|
|
cmd.Permissions[0] == extSvcPerms[0]
|
||
|
|
}))
|
||
|
|
},
|
||
|
|
want: 11,
|
||
|
|
wantErr: false,
|
||
|
|
},
|
||
|
|
}
|
||
|
|
for _, tt := range tests {
|
||
|
|
t.Run(tt.name, func(t *testing.T) {
|
||
|
|
ctx := context.Background()
|
||
|
|
|
||
|
|
env := setupTestEnv(t)
|
||
|
|
if tt.init != nil {
|
||
|
|
tt.init(env)
|
||
|
|
}
|
||
|
|
|
||
|
|
got, err := env.S.ManageExtSvcAccount(ctx, &tt.cmd)
|
||
|
|
|
||
|
|
if tt.wantErr {
|
||
|
|
require.Error(t, err)
|
||
|
|
return
|
||
|
|
}
|
||
|
|
require.NoError(t, err)
|
||
|
|
|
||
|
|
if tt.checks != nil {
|
||
|
|
tt.checks(t, env)
|
||
|
|
}
|
||
|
|
|
||
|
|
require.Equal(t, tt.want, got)
|
||
|
|
})
|
||
|
|
}
|
||
|
|
}
|