Service accounts: Creation logic simplification (#63884)

* SA creation improvements

* PR feedback - put salt and rand back in and remove an unneeded line:
This commit is contained in:
Ieva
2023-03-01 16:31:20 +00:00
committed by GitHub
parent a534119c44
commit 3fb1894739
9 changed files with 43 additions and 108 deletions

View File

@@ -16,7 +16,6 @@ import (
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
"github.com/grafana/grafana/pkg/services/org"
"github.com/grafana/grafana/pkg/services/serviceaccounts"
"github.com/grafana/grafana/pkg/services/serviceaccounts/database"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/util"
"github.com/grafana/grafana/pkg/web"
@@ -133,7 +132,7 @@ func (api *ServiceAccountsAPI) CreateServiceAccount(c *contextmodel.ReqContext)
serviceAccount, err := api.service.CreateServiceAccount(c.Req.Context(), c.OrgID, &cmd)
switch {
case errors.Is(err, database.ErrServiceAccountAlreadyExists):
case errors.Is(err, serviceaccounts.ErrServiceAccountAlreadyExists):
return response.Error(http.StatusBadRequest, "Failed to create service account", err)
case err != nil:
return response.Error(http.StatusInternalServerError, "Failed to create service account", err)

View File

@@ -12,7 +12,6 @@ import (
"github.com/grafana/grafana/pkg/services/apikey"
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
"github.com/grafana/grafana/pkg/services/serviceaccounts"
"github.com/grafana/grafana/pkg/services/serviceaccounts/database"
"github.com/grafana/grafana/pkg/web"
)
@@ -177,10 +176,10 @@ func (api *ServiceAccountsAPI) CreateToken(c *contextmodel.ReqContext) response.
apiKey, err := api.service.AddServiceAccountToken(c.Req.Context(), saID, &cmd)
if err != nil {
if errors.Is(err, database.ErrInvalidTokenExpiration) {
if errors.Is(err, serviceaccounts.ErrInvalidTokenExpiration) {
return response.Error(http.StatusBadRequest, err.Error(), nil)
}
if errors.Is(err, database.ErrDuplicateToken) {
if errors.Is(err, serviceaccounts.ErrDuplicateToken) {
return response.Error(http.StatusConflict, err.Error(), nil)
}
return response.Error(http.StatusInternalServerError, "Failed to add service account token", err)

View File

@@ -1,13 +0,0 @@
package database
import (
"errors"
)
var (
ErrServiceAccountAlreadyExists = errors.New("service account already exists")
ErrServiceAccountTokenNotFound = errors.New("service account token not found")
ErrInvalidTokenExpiration = errors.New("invalid SecondsToLive value")
ErrDuplicateToken = errors.New("service account token with given name already exists in the organization")
ErrServiceAccountAndTokenMismatch = errors.New("API token does not belong to the given service account")
)

View File

@@ -3,7 +3,6 @@ package database
//nolint:goimports
import (
"context"
"errors"
"fmt"
"strings"
"time"
@@ -55,40 +54,17 @@ func (s *ServiceAccountsStoreImpl) CreateServiceAccount(ctx context.Context, org
if saForm.Role != nil {
role = *saForm.Role
}
var newSA *user.User
createErr := s.sqlStore.WithTransactionalDbSession(ctx, func(sess *db.Session) (err error) {
var errUser error
newSA, errUser = s.userService.CreateServiceAccount(ctx, &user.CreateUserCommand{
Login: generatedLogin,
OrgID: orgId,
Name: saForm.Name,
IsDisabled: isDisabled,
IsServiceAccount: true,
SkipOrgSetup: true,
})
if errUser != nil {
return errUser
}
errAddOrgUser := s.orgService.AddOrgUser(ctx, &org.AddOrgUserCommand{
Role: role,
OrgID: orgId,
UserID: newSA.ID,
AllowAddingServiceAccount: true,
})
if errAddOrgUser != nil {
return errAddOrgUser
}
return nil
newSA, err := s.userService.CreateServiceAccount(ctx, &user.CreateUserCommand{
Login: generatedLogin,
OrgID: orgId,
Name: saForm.Name,
IsDisabled: isDisabled,
IsServiceAccount: true,
DefaultOrgRole: string(role),
})
if createErr != nil {
if errors.Is(createErr, user.ErrUserAlreadyExists) {
return nil, ErrServiceAccountAlreadyExists
}
return nil, fmt.Errorf("failed to create service account: %w", createErr)
if err != nil {
return nil, fmt.Errorf("failed to create service account: %w", err)
}
return &serviceaccounts.ServiceAccountDTO{
@@ -473,7 +449,7 @@ func (s *ServiceAccountsStoreImpl) RevertApiKey(ctx context.Context, saId int64,
}
if *key.ServiceAccountId != saId {
return ErrServiceAccountAndTokenMismatch
return serviceaccounts.ErrServiceAccountAndTokenMismatch
}
tokens, err := s.ListTokens(ctx, &serviceaccounts.GetSATokensQuery{

View File

@@ -328,7 +328,7 @@ func TestStore_RevertApiKey(t *testing.T) {
desc: "should fail reverting to api key when the token is assigned to a different service account",
key: tests.TestApiKey{Name: "Test1", Role: org.RoleEditor, OrgId: 1},
forceMismatchServiceAccount: true,
expectedErr: ErrServiceAccountAndTokenMismatch,
expectedErr: serviceaccounts.ErrServiceAccountAndTokenMismatch,
},
}

View File

@@ -58,9 +58,9 @@ func (s *ServiceAccountsStoreImpl) AddServiceAccountToken(ctx context.Context, s
if err := s.apiKeyService.AddAPIKey(ctx, addKeyCmd); err != nil {
switch {
case errors.Is(err, apikey.ErrDuplicate):
return ErrDuplicateToken
return serviceaccounts.ErrDuplicateToken
case errors.Is(err, apikey.ErrInvalidExpiration):
return ErrInvalidTokenExpiration
return serviceaccounts.ErrInvalidTokenExpiration
}
return err
@@ -81,7 +81,7 @@ func (s *ServiceAccountsStoreImpl) DeleteServiceAccountToken(ctx context.Context
}
affected, err := result.RowsAffected()
if affected == 0 {
return ErrServiceAccountTokenNotFound
return serviceaccounts.ErrServiceAccountTokenNotFound
}
return err
@@ -98,7 +98,7 @@ func (s *ServiceAccountsStoreImpl) RevokeServiceAccountToken(ctx context.Context
}
affected, err := result.RowsAffected()
if affected == 0 {
return ErrServiceAccountTokenNotFound
return serviceaccounts.ErrServiceAccountTokenNotFound
}
return err

View File

@@ -6,6 +6,7 @@ import (
"github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/org"
"github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/util/errutil"
)
var (
@@ -22,6 +23,14 @@ const (
ActionPermissionsWrite = "serviceaccounts.permissions:write"
)
var (
ErrServiceAccountAlreadyExists = errutil.NewBase(errutil.StatusBadRequest, "serviceaccounts.ErrAlreadyExists", errutil.WithPublicMessage("service account already exists"))
ErrServiceAccountTokenNotFound = errutil.NewBase(errutil.StatusNotFound, "serviceaccounts.ErrTokenNotFound", errutil.WithPublicMessage("service account token not found"))
ErrInvalidTokenExpiration = errutil.NewBase(errutil.StatusValidationFailed, "serviceaccounts.ErrInvalidInput", errutil.WithPublicMessage("invalid SecondsToLive value"))
ErrDuplicateToken = errutil.NewBase(errutil.StatusBadRequest, "serviceaccounts.ErrTokenAlreadyExists", errutil.WithPublicMessage("service account token with given name already exists in the organization"))
ErrServiceAccountAndTokenMismatch = errutil.NewBase(errutil.StatusBadRequest, "serviceaccounts.ErrToeknMismatch", errutil.WithPublicMessage("API token does not belong to the given service account"))
)
type ServiceAccount struct {
Id int64
}