|
|
|
|
@ -7,6 +7,7 @@ import ( |
|
|
|
|
"github.com/stretchr/testify/mock" |
|
|
|
|
"github.com/stretchr/testify/require" |
|
|
|
|
|
|
|
|
|
"github.com/grafana/grafana/pkg/components/satokengen" |
|
|
|
|
"github.com/grafana/grafana/pkg/infra/localcache" |
|
|
|
|
"github.com/grafana/grafana/pkg/infra/log" |
|
|
|
|
"github.com/grafana/grafana/pkg/infra/tracing" |
|
|
|
|
@ -199,6 +200,8 @@ func TestExtSvcAccountsService_ManageExtSvcAccount(t *testing.T) { |
|
|
|
|
|
|
|
|
|
func TestExtSvcAccountsService_SaveExternalService(t *testing.T) { |
|
|
|
|
extSvcSlug := "grafana-test-app" |
|
|
|
|
validToken, err := satokengen.New(extSvcSlug) |
|
|
|
|
require.NoError(t, err, "failed to generate a valid token for the tests") |
|
|
|
|
tmpOrgID := int64(1) |
|
|
|
|
extSvcAccID := int64(10) |
|
|
|
|
extSvcPerms := []ac.Permission{{Action: ac.ActionUsersRead, Scope: ac.ScopeUsersAll}} |
|
|
|
|
@ -235,7 +238,7 @@ func TestExtSvcAccountsService_SaveExternalService(t *testing.T) { |
|
|
|
|
})). |
|
|
|
|
Return(nil) |
|
|
|
|
// A token was previously stored in the secret store
|
|
|
|
|
_ = env.SkvStore.Set(context.Background(), tmpOrgID, extSvcSlug, kvStoreType, "ExtSvcSecretToken") |
|
|
|
|
_ = env.SkvStore.Set(context.Background(), tmpOrgID, extSvcSlug, kvStoreType, validToken.ClientSecret) |
|
|
|
|
}, |
|
|
|
|
cmd: extsvcauth.ExternalServiceRegistration{ |
|
|
|
|
Name: extSvcSlug, |
|
|
|
|
@ -264,7 +267,7 @@ func TestExtSvcAccountsService_SaveExternalService(t *testing.T) { |
|
|
|
|
env.SaSvc.On("DeleteServiceAccount", mock.Anything, tmpOrgID, extSvcAccID).Return(nil) |
|
|
|
|
env.AcStore.On("DeleteExternalServiceRole", mock.Anything, extSvcSlug).Return(nil) |
|
|
|
|
// A token was previously stored in the secret store
|
|
|
|
|
_ = env.SkvStore.Set(context.Background(), tmpOrgID, extSvcSlug, kvStoreType, "ExtSvcSecretToken") |
|
|
|
|
_ = env.SkvStore.Set(context.Background(), tmpOrgID, extSvcSlug, kvStoreType, validToken.ClientSecret) |
|
|
|
|
}, |
|
|
|
|
cmd: extsvcauth.ExternalServiceRegistration{ |
|
|
|
|
Name: extSvcSlug, |
|
|
|
|
@ -335,7 +338,52 @@ func TestExtSvcAccountsService_SaveExternalService(t *testing.T) { |
|
|
|
|
Return(nil) |
|
|
|
|
env.SaSvc.On("EnableServiceAccount", mock.Anything, extsvcauth.TmpOrgID, int64(11), true).Return(nil) |
|
|
|
|
// This time we don't add a token but rely on the secret store
|
|
|
|
|
_ = env.SkvStore.Set(context.Background(), tmpOrgID, extSvcSlug, kvStoreType, "ExtSvcSecretToken") |
|
|
|
|
_ = env.SkvStore.Set(context.Background(), tmpOrgID, extSvcSlug, kvStoreType, validToken.ClientSecret) |
|
|
|
|
}, |
|
|
|
|
cmd: extsvcauth.ExternalServiceRegistration{ |
|
|
|
|
Name: extSvcSlug, |
|
|
|
|
Self: extsvcauth.SelfCfg{ |
|
|
|
|
Enabled: true, |
|
|
|
|
Permissions: extSvcPerms, |
|
|
|
|
}, |
|
|
|
|
}, |
|
|
|
|
want: &extsvcauth.ExternalService{ |
|
|
|
|
Name: extSvcSlug, |
|
|
|
|
ID: extSvcSlug, |
|
|
|
|
Secret: "not empty", |
|
|
|
|
}, |
|
|
|
|
wantErr: false, |
|
|
|
|
}, |
|
|
|
|
{ |
|
|
|
|
name: "should recover from a failed token encryption", |
|
|
|
|
init: func(env *TestEnv) { |
|
|
|
|
// A previous service account was attached to this slug
|
|
|
|
|
env.SaSvc.On("RetrieveServiceAccountIdByName", mock.Anything, tmpOrgID, sa.ExtSvcPrefix+extSvcSlug). |
|
|
|
|
Return(int64(11), nil) |
|
|
|
|
env.AcStore.On("SaveExternalServiceRole", |
|
|
|
|
mock.Anything, |
|
|
|
|
mock.MatchedBy(func(cmd ac.SaveExternalServiceRoleCommand) bool { |
|
|
|
|
return cmd.ServiceAccountID == int64(11) && cmd.ExternalServiceID == extSvcSlug && |
|
|
|
|
cmd.AssignmentOrgID == tmpOrgID && len(cmd.Permissions) == 1 && |
|
|
|
|
cmd.Permissions[0] == extSvcPerms[0] |
|
|
|
|
})). |
|
|
|
|
Return(nil) |
|
|
|
|
env.SaSvc.On("EnableServiceAccount", mock.Anything, extsvcauth.TmpOrgID, int64(11), true).Return(nil) |
|
|
|
|
|
|
|
|
|
// This time the token in the secret store is invalid
|
|
|
|
|
_ = env.SkvStore.Set(context.Background(), tmpOrgID, extSvcSlug, kvStoreType, "failedTokenEncryption") |
|
|
|
|
// Delete the API key and entry in the skv store
|
|
|
|
|
env.SaSvc.On("ListTokens", mock.Anything, mock.Anything). |
|
|
|
|
Return([]apikey.APIKey{{ID: 3, Name: tokenNamePrefix + "-" + extSvcSlug}}, nil) |
|
|
|
|
env.SaSvc.On("DeleteServiceAccountToken", mock.Anything, mock.Anything, int64(11), int64(3)).Return(nil) |
|
|
|
|
// Recreate the API key
|
|
|
|
|
env.SaSvc.On("AddServiceAccountToken", mock.Anything, mock.Anything, mock.Anything).Return(&apikey.APIKey{}, nil) |
|
|
|
|
}, |
|
|
|
|
checks: func(t *testing.T, env *TestEnv) { |
|
|
|
|
// Make sure the secret was updated
|
|
|
|
|
v, ok, _ := env.SkvStore.Get(context.Background(), tmpOrgID, extSvcSlug, kvStoreType) |
|
|
|
|
require.True(t, ok, "secret should have been removed from store") |
|
|
|
|
require.NotEqual(t, "failedTokenEncryption", v) |
|
|
|
|
}, |
|
|
|
|
cmd: extsvcauth.ExternalServiceRegistration{ |
|
|
|
|
Name: extSvcSlug, |
|
|
|
|
|