IAM: Create Service Account API and legacy store impl (#110411)
* wip * IAM: Create Service Account * Add dual writer * Update openapi_test.go * Add integration tests * Add sql tests * Add Role to SA spec, add validation, add DBTime, add tests * Format, update test * Fixes * Add check for External * Address feedback * Update tests * Address feedback * make gen-go * Simplify a bit * Fixes * make update-workspace * Update pkg/registry/apis/iam/serviceaccount/store.go Co-authored-by: Ryan McKinley <ryantxu@gmail.com> * Address feedback, add test for generateName --------- Co-authored-by: Ryan McKinley <ryantxu@gmail.com>
This commit is contained in:
@@ -43,22 +43,9 @@ func ProvideServiceAccountsStore(cfg *setting.Cfg, store db.DB, apiKeyService ap
|
||||
}
|
||||
}
|
||||
|
||||
// generateLogin makes a generated string to have a ID for the service account across orgs and it's name
|
||||
// this causes you to create a service account with the same name in different orgs
|
||||
// not the same name in the same org
|
||||
// -- WARNING:
|
||||
// -- if you change this function you need to change the ExtSvcLoginPrefix as well
|
||||
// -- to make sure they are not considered as regular service accounts
|
||||
func generateLogin(prefix string, orgId int64, name string) string {
|
||||
generatedLogin := fmt.Sprintf("%v-%v-%v", prefix, orgId, strings.ToLower(name))
|
||||
// in case the name has multiple spaces or dashes in the prefix or otherwise, replace them with a single dash
|
||||
generatedLogin = strings.Replace(generatedLogin, "--", "-", 1)
|
||||
return strings.ReplaceAll(generatedLogin, " ", "-")
|
||||
}
|
||||
|
||||
// CreateServiceAccount creates service account
|
||||
func (s *ServiceAccountsStoreImpl) CreateServiceAccount(ctx context.Context, orgId int64, saForm *serviceaccounts.CreateServiceAccountForm) (*serviceaccounts.ServiceAccountDTO, error) {
|
||||
login := generateLogin(serviceaccounts.ServiceAccountPrefix, orgId, saForm.Name)
|
||||
login := serviceaccounts.GenerateLogin(serviceaccounts.ServiceAccountPrefix, orgId, saForm.Name)
|
||||
isDisabled := false
|
||||
role := org.RoleViewer
|
||||
if saForm.IsDisabled != nil {
|
||||
@@ -483,7 +470,7 @@ func (s *ServiceAccountsStoreImpl) MigrateApiKeysToServiceAccounts(ctx context.C
|
||||
func (s *ServiceAccountsStoreImpl) CreateServiceAccountFromApikey(ctx context.Context, key *apikey.APIKey) error {
|
||||
prefix := "sa-autogen"
|
||||
cmd := user.CreateUserCommand{
|
||||
Login: generateLogin(prefix, key.OrgID, key.Name),
|
||||
Login: serviceaccounts.GenerateLogin(prefix, key.OrgID, key.Name),
|
||||
Name: fmt.Sprintf("%v-%v", prefix, key.Name),
|
||||
OrgID: key.OrgID,
|
||||
DefaultOrgRole: string(key.Role),
|
||||
@@ -501,7 +488,7 @@ func (s *ServiceAccountsStoreImpl) CreateServiceAccountFromApikey(ctx context.Co
|
||||
// a unique service account by adding suffixes to the initial login name (e.g. -001, -002, ... , -010).
|
||||
for i := 1; errCreateSA != nil && i <= attempts; i++ {
|
||||
serviceAccountName := fmt.Sprintf("%s-%03d", key.Name, i)
|
||||
cmd.Login = generateLogin(prefix, key.OrgID, serviceAccountName)
|
||||
cmd.Login = serviceaccounts.GenerateLogin(prefix, key.OrgID, serviceAccountName)
|
||||
newSA, errCreateSA = s.userService.CreateServiceAccount(tctx, &cmd)
|
||||
if errCreateSA != nil && !errors.Is(errCreateSA, serviceaccounts.ErrServiceAccountAlreadyExists) {
|
||||
break
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
package serviceaccounts
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/apimachinery/errutil"
|
||||
@@ -217,16 +215,3 @@ var AccessEvaluator = accesscontrol.EvalAny(
|
||||
accesscontrol.EvalPermission(ActionRead),
|
||||
accesscontrol.EvalPermission(ActionCreate),
|
||||
)
|
||||
|
||||
func ExtSvcLoginPrefix(orgID int64) string {
|
||||
return fmt.Sprintf("%s%d-%s", ServiceAccountPrefix, orgID, ExtSvcPrefix)
|
||||
}
|
||||
|
||||
func IsExternalServiceAccount(login string) bool {
|
||||
parts := strings.SplitAfter(login, "-")
|
||||
if len(parts) < 4 {
|
||||
return false
|
||||
}
|
||||
|
||||
return parts[0] == ServiceAccountPrefix && parts[2] == ExtSvcPrefix
|
||||
}
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
package serviceaccounts
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// generateLogin makes a generated string to have a ID for the service account across orgs and it's name
|
||||
// this causes you to create a service account with the same name in different orgs
|
||||
// not the same name in the same org
|
||||
// -- WARNING:
|
||||
// -- if you change this function you need to change the ExtSvcLoginPrefix as well
|
||||
// -- to make sure they are not considered as regular service accounts
|
||||
func GenerateLogin(prefix string, orgId int64, name string) string {
|
||||
generatedLogin := fmt.Sprintf("%v-%v-%v", prefix, orgId, strings.ToLower(name))
|
||||
// in case the name has multiple spaces or dashes in the prefix or otherwise, replace them with a single dash
|
||||
generatedLogin = strings.Replace(generatedLogin, "--", "-", 1)
|
||||
return strings.ReplaceAll(generatedLogin, " ", "-")
|
||||
}
|
||||
|
||||
func ExtSvcLoginPrefix(orgID int64) string {
|
||||
return fmt.Sprintf("%s%d-%s", ServiceAccountPrefix, orgID, ExtSvcPrefix)
|
||||
}
|
||||
|
||||
func IsExternalServiceAccount(login string) bool {
|
||||
parts := strings.SplitAfter(login, "-")
|
||||
if len(parts) < 4 {
|
||||
return false
|
||||
}
|
||||
|
||||
return parts[0] == ServiceAccountPrefix && parts[2] == ExtSvcPrefix
|
||||
}
|
||||
Reference in New Issue
Block a user