Files

288 lines
9.3 KiB
Go

package proxy
import (
"context"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/grafana/grafana/pkg/infra/log"
sa "github.com/grafana/grafana/pkg/services/serviceaccounts"
"github.com/grafana/grafana/pkg/services/serviceaccounts/extsvcaccounts"
"github.com/grafana/grafana/pkg/services/serviceaccounts/tests"
)
var (
_ sa.Service = (*tests.FakeServiceAccountService)(nil)
autoAssignOrgID = int64(2)
)
func TestProvideServiceAccount_crudServiceAccount(t *testing.T) {
testServiceAccountId := int64(1)
testServiceAccountTokenId := int64(1)
serviceMock := &tests.FakeServiceAccountService{}
svc := ServiceAccountsProxy{
log.New("test"),
serviceMock,
true,
}
t.Run("should create service account", func(t *testing.T) {
testCases := []struct {
description string
form sa.CreateServiceAccountForm
expectedError error
}{
{
description: "should create service account and not return error",
form: sa.CreateServiceAccountForm{
Name: "my-service-account",
},
expectedError: nil,
},
{
description: "should not allow to create a service account with extsvc- prefix",
form: sa.CreateServiceAccountForm{
Name: "extsvc-my-service-account",
},
expectedError: extsvcaccounts.ErrInvalidName,
},
{
description: "should not allow to create a service account with extsvc prefix",
form: sa.CreateServiceAccountForm{
Name: "extsvc my-service-account",
},
expectedError: extsvcaccounts.ErrInvalidName,
},
}
for _, tc := range testCases {
t.Run(tc.description, func(t *testing.T) {
tc := tc
_, err := svc.CreateServiceAccount(context.Background(), autoAssignOrgID, &tc.form)
assert.Equal(t, err, tc.expectedError, tc.description)
})
}
})
t.Run("should delete service account", func(t *testing.T) {
testCases := []struct {
description string
expectedError error
expectedServiceAccount *sa.ServiceAccountProfileDTO
}{
{
description: "should allow to delete a service account",
expectedError: nil,
expectedServiceAccount: &sa.ServiceAccountProfileDTO{
Login: "my-service-account",
},
},
{
description: "should not allow to delete a service account with " + sa.ExtSvcLoginPrefix(autoAssignOrgID) + " prefix",
expectedError: extsvcaccounts.ErrCannotBeDeleted,
expectedServiceAccount: &sa.ServiceAccountProfileDTO{
Login: sa.ExtSvcLoginPrefix(autoAssignOrgID) + "my-service-account",
},
},
}
for _, tc := range testCases {
t.Run(tc.description, func(t *testing.T) {
serviceMock.ExpectedServiceAccountProfile = tc.expectedServiceAccount
err := svc.DeleteServiceAccount(context.Background(), autoAssignOrgID, testServiceAccountId)
assert.Equal(t, err, tc.expectedError, tc.description)
})
}
})
t.Run("should delete service account token", func(t *testing.T) {
testCases := []struct {
description string
expectedError error
expectedServiceAccount *sa.ServiceAccountProfileDTO
}{
{
description: "should allow to delete a service account token",
expectedError: nil,
expectedServiceAccount: &sa.ServiceAccountProfileDTO{
Login: "my-service-account",
},
},
{
description: "should not allow to delete a external service account token",
expectedError: extsvcaccounts.ErrCannotDeleteToken,
expectedServiceAccount: &sa.ServiceAccountProfileDTO{
Login: sa.ExtSvcLoginPrefix(autoAssignOrgID) + "my-service-account",
},
},
}
for _, tc := range testCases {
t.Run(tc.description, func(t *testing.T) {
serviceMock.ExpectedServiceAccountProfile = tc.expectedServiceAccount
err := svc.DeleteServiceAccountToken(context.Background(), autoAssignOrgID, testServiceAccountId, testServiceAccountTokenId)
assert.Equal(t, err, tc.expectedError, tc.description)
})
}
})
t.Run("should retrieve service account with IsExternal field", func(t *testing.T) {
testCases := []struct {
description string
expectedServiceAccount *sa.ServiceAccountProfileDTO
expectedIsExternal bool
}{
{
description: "should not mark as external",
expectedServiceAccount: &sa.ServiceAccountProfileDTO{
Login: "my-service-account",
},
expectedIsExternal: false,
},
{
description: "should mark as external",
expectedServiceAccount: &sa.ServiceAccountProfileDTO{
Login: sa.ExtSvcLoginPrefix(autoAssignOrgID) + "my-service-account",
},
expectedIsExternal: true,
},
}
for _, tc := range testCases {
t.Run(tc.description, func(t *testing.T) {
serviceMock.ExpectedServiceAccountProfile = tc.expectedServiceAccount
sa, err := svc.RetrieveServiceAccount(context.Background(), &sa.GetServiceAccountQuery{OrgID: autoAssignOrgID, ID: testServiceAccountId})
assert.NoError(t, err, tc.description)
assert.Equal(t, tc.expectedIsExternal, sa.IsExternal, tc.description)
})
}
})
t.Run("should flag external service accounts correctly", func(t *testing.T) {
serviceMock.ExpectedSearchOrgServiceAccountsResult = &sa.SearchOrgServiceAccountsResult{
TotalCount: 2,
ServiceAccounts: []*sa.ServiceAccountDTO{
{Login: "test"},
{Login: sa.ExtSvcLoginPrefix(autoAssignOrgID) + "test"},
},
Page: 1,
PerPage: 2,
}
res, err := svc.SearchOrgServiceAccounts(context.Background(), &sa.SearchOrgServiceAccountsQuery{OrgID: 1})
require.Len(t, res.ServiceAccounts, 2)
require.NoError(t, err)
require.False(t, res.ServiceAccounts[0].IsExternal)
require.True(t, res.ServiceAccounts[1].IsExternal)
})
t.Run("should update service account", func(t *testing.T) {
nameWithoutProtectedPrefix := "my-updated-service-account"
nameWithProtectedPrefix := "extsvc-my-updated-service-account"
testCases := []struct {
description string
form sa.UpdateServiceAccountForm
expectedServiceAccount *sa.ServiceAccountProfileDTO
expectedError error
}{
{
description: "should update a non-external service account with a valid name",
form: sa.UpdateServiceAccountForm{
Name: &nameWithoutProtectedPrefix,
},
expectedServiceAccount: &sa.ServiceAccountProfileDTO{
Login: "my-service-account",
},
expectedError: nil,
},
{
description: "should not allow to update a non-external service account with extsvc prefix",
form: sa.UpdateServiceAccountForm{
Name: &nameWithProtectedPrefix,
},
expectedServiceAccount: &sa.ServiceAccountProfileDTO{
Login: "my-service-account",
},
expectedError: extsvcaccounts.ErrInvalidName,
},
{
description: "should not allow to update an external service account with a valid name",
form: sa.UpdateServiceAccountForm{
Name: &nameWithoutProtectedPrefix,
},
expectedServiceAccount: &sa.ServiceAccountProfileDTO{
Login: sa.ExtSvcLoginPrefix(autoAssignOrgID) + "my-service-account",
},
expectedError: extsvcaccounts.ErrCannotBeUpdated,
},
{
description: "should not allow to update an external service account with a extsvc prefix",
form: sa.UpdateServiceAccountForm{
Name: &nameWithProtectedPrefix,
},
expectedServiceAccount: &sa.ServiceAccountProfileDTO{
Login: sa.ExtSvcLoginPrefix(autoAssignOrgID) + "my-service-account",
},
expectedError: extsvcaccounts.ErrInvalidName,
},
}
for _, tc := range testCases {
t.Run(tc.description, func(t *testing.T) {
tc := tc
serviceMock.ExpectedServiceAccountProfile = tc.expectedServiceAccount
_, err := svc.UpdateServiceAccount(context.Background(), autoAssignOrgID, testServiceAccountId, &tc.form)
assert.Equal(t, tc.expectedError, err, tc.description)
})
}
})
t.Run("should add service account tokens", func(t *testing.T) {
testCases := []struct {
description string
cmd sa.AddServiceAccountTokenCommand
expectedServiceAccount *sa.ServiceAccountProfileDTO
expectedError error
}{
{
description: "should allow to create a service account token",
cmd: sa.AddServiceAccountTokenCommand{
OrgId: autoAssignOrgID,
},
expectedServiceAccount: &sa.ServiceAccountProfileDTO{
Login: "my-service-account",
},
expectedError: nil,
},
{
description: "should not allow to create a service account token",
cmd: sa.AddServiceAccountTokenCommand{
OrgId: autoAssignOrgID,
},
expectedServiceAccount: &sa.ServiceAccountProfileDTO{
Login: sa.ExtSvcLoginPrefix(autoAssignOrgID) + "my-service-account",
},
expectedError: extsvcaccounts.ErrCannotCreateToken,
},
}
for _, tc := range testCases {
t.Run(tc.description, func(t *testing.T) {
tc := tc
serviceMock.ExpectedServiceAccountProfile = tc.expectedServiceAccount
_, err := svc.AddServiceAccountToken(context.Background(), testServiceAccountId, &tc.cmd)
assert.Equal(t, tc.expectedError, err, tc.description)
})
}
})
t.Run("should identify service account logins for being external or not", func(t *testing.T) {
assert.False(t, sa.IsExternalServiceAccount("my-service-account"))
assert.False(t, sa.IsExternalServiceAccount("sa-my-service-account"))
assert.False(t, sa.IsExternalServiceAccount(sa.ExtSvcPrefix+"my-service-account")) // It's not a external service account login
assert.True(t, sa.IsExternalServiceAccount(sa.ExtSvcLoginPrefix(autoAssignOrgID)+"my-service-account"))
})
}