auth: implement feature flag for service account proxy (#77129)

* add FlagExternalServiceAccounts to proxy service

* add FlagExternalServiceAccounts value to tests

---------

Co-authored-by: Gabriel MABILLE <gamab@users.noreply.github.com>
This commit is contained in:
linoman 2023-10-25 16:44:05 +02:00 committed by GitHub
parent 5f2fd8935d
commit dff7403b29
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 59 additions and 45 deletions

View File

@ -2,11 +2,11 @@ package proxy
import (
"context"
"fmt"
"strings"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/services/apikey"
"github.com/grafana/grafana/pkg/services/featuremgmt"
"github.com/grafana/grafana/pkg/services/serviceaccounts"
"github.com/grafana/grafana/pkg/services/serviceaccounts/extsvcaccounts"
"github.com/grafana/grafana/pkg/services/serviceaccounts/manager"
@ -19,14 +19,17 @@ import (
type ServiceAccountsProxy struct {
log log.Logger
proxiedService serviceaccounts.Service
isProxyEnabled bool
}
func ProvideServiceAccountsProxy(
features *featuremgmt.FeatureManager,
proxiedService *manager.ServiceAccountsService,
) (*ServiceAccountsProxy, error) {
s := &ServiceAccountsProxy{
log: log.New("serviceaccounts.proxy"),
proxiedService: proxiedService,
isProxyEnabled: features.IsEnabled(featuremgmt.FlagExternalServiceAccounts) || features.IsEnabled(featuremgmt.FlagExternalServiceAuth),
}
return s, nil
}
@ -34,6 +37,7 @@ func ProvideServiceAccountsProxy(
var _ serviceaccounts.Service = (*ServiceAccountsProxy)(nil)
func (s *ServiceAccountsProxy) AddServiceAccountToken(ctx context.Context, serviceAccountID int64, cmd *serviceaccounts.AddServiceAccountTokenCommand) (*apikey.APIKey, error) {
if s.isProxyEnabled {
sa, err := s.proxiedService.RetrieveServiceAccount(ctx, cmd.OrgId, serviceAccountID)
if err != nil {
return nil, err
@ -43,19 +47,23 @@ func (s *ServiceAccountsProxy) AddServiceAccountToken(ctx context.Context, servi
s.log.Error("unable to create tokens for external service accounts", "serviceAccountID", serviceAccountID)
return nil, extsvcaccounts.ErrCannotCreateToken
}
}
return s.proxiedService.AddServiceAccountToken(ctx, serviceAccountID, cmd)
}
func (s *ServiceAccountsProxy) CreateServiceAccount(ctx context.Context, orgID int64, saForm *serviceaccounts.CreateServiceAccountForm) (*serviceaccounts.ServiceAccountDTO, error) {
if s.isProxyEnabled {
if !isNameValid(saForm.Name) {
s.log.Error("Unable to create service account with a protected name", "name", saForm.Name)
return nil, extsvcaccounts.ErrInvalidName
}
}
return s.proxiedService.CreateServiceAccount(ctx, orgID, saForm)
}
func (s *ServiceAccountsProxy) DeleteServiceAccount(ctx context.Context, orgID, serviceAccountID int64) error {
if s.isProxyEnabled {
sa, err := s.proxiedService.RetrieveServiceAccount(ctx, orgID, serviceAccountID)
if err != nil {
return err
@ -65,24 +73,23 @@ func (s *ServiceAccountsProxy) DeleteServiceAccount(ctx context.Context, orgID,
s.log.Error("unable to delete external service accounts", "serviceAccountID", serviceAccountID)
return extsvcaccounts.ErrCannotBeDeleted
}
}
return s.proxiedService.DeleteServiceAccount(ctx, orgID, serviceAccountID)
}
func (s *ServiceAccountsProxy) DeleteServiceAccountToken(ctx context.Context, orgID int64, serviceAccountID int64, tokenID int64) error {
sa, err := s.proxiedService.RetrieveServiceAccount(ctx, 0, serviceAccountID)
if s.isProxyEnabled {
sa, err := s.proxiedService.RetrieveServiceAccount(ctx, orgID, serviceAccountID)
if err != nil {
return err
}
fmt.Println("sa.Login: ", sa.Login)
if isExternalServiceAccount(sa.Login) {
s.log.Error("unable to delete tokens for external service accounts", "serviceAccountID", serviceAccountID)
return extsvcaccounts.ErrCannotDeleteToken
}
return s.proxiedService.DeleteServiceAccountToken(ctx, sa.OrgId, serviceAccountID, tokenID)
}
return s.proxiedService.DeleteServiceAccountToken(ctx, orgID, serviceAccountID, tokenID)
}
func (s *ServiceAccountsProxy) ListTokens(ctx context.Context, query *serviceaccounts.GetSATokensQuery) ([]apikey.APIKey, error) {
@ -103,7 +110,9 @@ func (s *ServiceAccountsProxy) RetrieveServiceAccount(ctx context.Context, orgID
return nil, err
}
if s.isProxyEnabled {
sa.IsExternal = isExternalServiceAccount(sa.Login)
}
return sa, nil
}
@ -113,6 +122,7 @@ func (s *ServiceAccountsProxy) RetrieveServiceAccountIdByName(ctx context.Contex
}
func (s *ServiceAccountsProxy) UpdateServiceAccount(ctx context.Context, orgID, serviceAccountID int64, saForm *serviceaccounts.UpdateServiceAccountForm) (*serviceaccounts.ServiceAccountProfileDTO, error) {
if s.isProxyEnabled {
if !isNameValid(*saForm.Name) {
s.log.Error("Invalid service account name", "name", *saForm.Name)
return nil, extsvcaccounts.ErrInvalidName
@ -125,6 +135,7 @@ func (s *ServiceAccountsProxy) UpdateServiceAccount(ctx context.Context, orgID,
s.log.Error("unable to update external service accounts", "serviceAccountID", serviceAccountID)
return nil, extsvcaccounts.ErrCannotBeUpdated
}
}
return s.proxiedService.UpdateServiceAccount(ctx, orgID, serviceAccountID, saForm)
}
@ -135,9 +146,11 @@ func (s *ServiceAccountsProxy) SearchOrgServiceAccounts(ctx context.Context, que
return nil, err
}
if s.isProxyEnabled {
for i := range sa.ServiceAccounts {
sa.ServiceAccounts[i].IsExternal = isExternalServiceAccount(sa.ServiceAccounts[i].Login)
}
}
return sa, nil
}

View File

@ -23,6 +23,7 @@ func TestProvideServiceAccount_crudServiceAccount(t *testing.T) {
svc := ServiceAccountsProxy{
log.New("test"),
serviceMock,
true,
}
t.Run("should create service account", func(t *testing.T) {