CloudMigration: Create authapi service (#96581)

This commit is contained in:
lean.dev
2024-11-21 15:46:06 -03:00
committed by GitHub
parent c8bc1f8637
commit e9fae5bd7f
17 changed files with 837 additions and 452 deletions
@@ -19,6 +19,8 @@ import (
"github.com/grafana/grafana/pkg/infra/kvstore"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/infra/tracing"
"github.com/grafana/grafana/pkg/services/authapi"
"github.com/grafana/grafana/pkg/services/authapi/fake"
"github.com/grafana/grafana/pkg/services/cloudmigration"
"github.com/grafana/grafana/pkg/services/cloudmigration/api"
"github.com/grafana/grafana/pkg/services/cloudmigration/gmsclient"
@@ -62,6 +64,7 @@ type Service struct {
dsService datasources.DataSourceService
gcomService gcom.Service
authApiService authapi.Service
dashboardService dashboards.DashboardService
folderService folder.Service
pluginStore pluginstore.Store
@@ -151,9 +154,23 @@ func ProvideService(
return nil, fmt.Errorf("creating http client for GCOM: %w", err)
}
s.gcomService = gcom.New(gcom.Config{ApiURL: cfg.GrafanaComAPIURL, Token: cfg.CloudMigration.GcomAPIToken}, httpClientGcom)
if features.IsEnabledGlobally(featuremgmt.FlagOnPremToCloudMigrationsAuthApiMig) {
s.log.Info("using authapi client because feature flag is enabled")
httpClientAuthApi, err := httpClientProvider.New()
if err != nil {
return nil, fmt.Errorf("creating http client for AuthApi: %w", err)
}
// the api token is the same as for gcom
s.authApiService = authapi.New(authapi.Config{ApiURL: cfg.CloudMigration.AuthAPIUrl, Token: cfg.CloudMigration.GcomAPIToken}, httpClientAuthApi)
} else {
s.log.Info("using gcom client for auth")
s.authApiService = gcom.New(gcom.Config{ApiURL: cfg.GrafanaComAPIURL, Token: cfg.CloudMigration.GcomAPIToken}, httpClientGcom).(*gcom.GcomClient)
}
} else {
s.gmsClient = gmsclient.NewInMemoryClient()
s.gcomService = &gcomStub{policies: map[string]gcom.AccessPolicy{}, token: nil}
s.gcomService = &gcomStub{}
s.authApiService = &fake.AuthapiStub{Policies: map[string]authapi.AccessPolicy{}, Token: nil}
s.cfg.StackID = "12345"
}
@@ -169,7 +186,7 @@ func ProvideService(
return s, nil
}
func (s *Service) GetToken(ctx context.Context) (gcom.TokenView, error) {
func (s *Service) GetToken(ctx context.Context) (authapi.TokenView, error) {
ctx, span := s.tracer.Start(ctx, "CloudMigrationService.GetToken")
defer span.End()
logger := s.log.FromContext(ctx)
@@ -179,7 +196,7 @@ func (s *Service) GetToken(ctx context.Context) (gcom.TokenView, error) {
defer cancel()
instance, err := s.gcomService.GetInstanceByID(timeoutCtx, requestID, s.cfg.StackID)
if err != nil {
return gcom.TokenView{}, fmt.Errorf("fetching instance by id: id=%s %w", s.cfg.StackID, err)
return authapi.TokenView{}, fmt.Errorf("fetching instance by id: id=%s %w", s.cfg.StackID, err)
}
logger.Info("instance found", "slug", instance.Slug)
@@ -189,14 +206,14 @@ func (s *Service) GetToken(ctx context.Context) (gcom.TokenView, error) {
timeoutCtx, cancel = context.WithTimeout(ctx, s.cfg.CloudMigration.ListTokensTimeout)
defer cancel()
tokens, err := s.gcomService.ListTokens(timeoutCtx, gcom.ListTokenParams{
tokens, err := s.authApiService.ListTokens(timeoutCtx, authapi.ListTokenParams{
RequestID: requestID,
Region: instance.RegionSlug,
AccessPolicyName: accessPolicyName,
TokenName: accessTokenName,
Region: instance.RegionSlug,
})
if err != nil {
return gcom.TokenView{}, fmt.Errorf("listing tokens: %w", err)
return authapi.TokenView{}, fmt.Errorf("listing tokens: %w", err)
}
logger.Info("found access tokens", "num_tokens", len(tokens))
@@ -208,7 +225,7 @@ func (s *Service) GetToken(ctx context.Context) (gcom.TokenView, error) {
}
logger.Info("cloud migration token not found")
return gcom.TokenView{}, fmt.Errorf("fetching cloud migration token: instance=%+v accessPolicyName=%s accessTokenName=%s %w",
return authapi.TokenView{}, fmt.Errorf("fetching cloud migration token: instance=%+v accessPolicyName=%s accessTokenName=%s %w",
instance, accessPolicyName, accessTokenName, cloudmigration.ErrTokenNotFound)
}
@@ -231,7 +248,7 @@ func (s *Service) CreateToken(ctx context.Context) (cloudmigration.CreateAccessT
timeoutCtx, cancel = context.WithTimeout(ctx, s.cfg.CloudMigration.FetchAccessPolicyTimeout)
defer cancel()
existingAccessPolicy, err := s.findAccessPolicyByName(timeoutCtx, instance.RegionSlug, accessPolicyName)
existingAccessPolicy, err := s.findAccessPolicyByName(timeoutCtx, accessPolicyName, instance.RegionSlug)
if err != nil {
return cloudmigration.CreateAccessTokenResponse{}, fmt.Errorf("fetching access policy by name: name=%s %w", accessPolicyName, err)
}
@@ -239,7 +256,7 @@ func (s *Service) CreateToken(ctx context.Context) (cloudmigration.CreateAccessT
if existingAccessPolicy != nil {
timeoutCtx, cancel := context.WithTimeout(ctx, s.cfg.CloudMigration.DeleteAccessPolicyTimeout)
defer cancel()
if _, err := s.gcomService.DeleteAccessPolicy(timeoutCtx, gcom.DeleteAccessPolicyParams{
if _, err := s.authApiService.DeleteAccessPolicy(timeoutCtx, authapi.DeleteAccessPolicyParams{
RequestID: requestID,
AccessPolicyID: existingAccessPolicy.ID,
Region: instance.RegionSlug,
@@ -251,15 +268,15 @@ func (s *Service) CreateToken(ctx context.Context) (cloudmigration.CreateAccessT
timeoutCtx, cancel = context.WithTimeout(ctx, s.cfg.CloudMigration.CreateAccessPolicyTimeout)
defer cancel()
accessPolicy, err := s.gcomService.CreateAccessPolicy(timeoutCtx,
gcom.CreateAccessPolicyParams{
accessPolicy, err := s.authApiService.CreateAccessPolicy(timeoutCtx,
authapi.CreateAccessPolicyParams{
RequestID: requestID,
Region: instance.RegionSlug,
},
gcom.CreateAccessPolicyPayload{
authapi.CreateAccessPolicyPayload{
Name: accessPolicyName,
DisplayName: accessPolicyDisplayName,
Realms: []gcom.Realm{{Type: "stack", Identifier: s.cfg.StackID, LabelPolicies: []gcom.LabelPolicy{}}},
Realms: []authapi.Realm{{Type: "stack", Identifier: s.cfg.StackID, LabelPolicies: []authapi.LabelPolicy{}}},
Scopes: []string{"cloud-migrations:read", "cloud-migrations:write"},
})
if err != nil {
@@ -273,9 +290,12 @@ func (s *Service) CreateToken(ctx context.Context) (cloudmigration.CreateAccessT
timeoutCtx, cancel = context.WithTimeout(ctx, s.cfg.CloudMigration.CreateTokenTimeout)
defer cancel()
token, err := s.gcomService.CreateToken(timeoutCtx,
gcom.CreateTokenParams{RequestID: requestID, Region: instance.RegionSlug},
gcom.CreateTokenPayload{
token, err := s.authApiService.CreateToken(timeoutCtx,
authapi.CreateTokenParams{
RequestID: requestID,
Region: instance.RegionSlug,
},
authapi.CreateTokenPayload{
AccessPolicyID: accessPolicy.ID,
Name: accessTokenName,
DisplayName: accessTokenDisplayName,
@@ -303,14 +323,14 @@ func (s *Service) CreateToken(ctx context.Context) (cloudmigration.CreateAccessT
return cloudmigration.CreateAccessTokenResponse{Token: base64.StdEncoding.EncodeToString(bytes)}, nil
}
func (s *Service) findAccessPolicyByName(ctx context.Context, regionSlug, accessPolicyName string) (*gcom.AccessPolicy, error) {
accessPolicies, err := s.gcomService.ListAccessPolicies(ctx, gcom.ListAccessPoliciesParams{
func (s *Service) findAccessPolicyByName(ctx context.Context, accessPolicyName string, region string) (*authapi.AccessPolicy, error) {
accessPolicies, err := s.authApiService.ListAccessPolicies(ctx, authapi.ListAccessPoliciesParams{
RequestID: tracing.TraceIDFromContext(ctx, false),
Region: regionSlug,
Name: accessPolicyName,
Region: region,
})
if err != nil {
return nil, fmt.Errorf("listing access policies: name=%s region=%s :%w", accessPolicyName, regionSlug, err)
return nil, fmt.Errorf("listing access policies: name=%s :%w", accessPolicyName, err)
}
for _, accessPolicy := range accessPolicies {
@@ -349,10 +369,10 @@ func (s *Service) DeleteToken(ctx context.Context, tokenID string) error {
timeoutCtx, cancel = context.WithTimeout(ctx, s.cfg.CloudMigration.DeleteTokenTimeout)
defer cancel()
if err := s.gcomService.DeleteToken(timeoutCtx, gcom.DeleteTokenParams{
if err := s.authApiService.DeleteToken(timeoutCtx, authapi.DeleteTokenParams{
RequestID: tracing.TraceIDFromContext(ctx, false),
Region: instance.RegionSlug,
TokenID: tokenID,
Region: instance.RegionSlug,
}); err != nil && !errors.Is(err, gcom.ErrTokenNotFound) {
return fmt.Errorf("deleting cloud migration token: tokenID=%s %w", tokenID, err)
}
@@ -3,8 +3,8 @@ package cloudmigrationimpl
import (
"context"
"github.com/grafana/grafana/pkg/services/authapi"
"github.com/grafana/grafana/pkg/services/cloudmigration"
"github.com/grafana/grafana/pkg/services/gcom"
"github.com/grafana/grafana/pkg/services/user"
)
@@ -13,8 +13,8 @@ type NoopServiceImpl struct{}
var _ cloudmigration.Service = (*NoopServiceImpl)(nil)
func (s *NoopServiceImpl) GetToken(ctx context.Context) (gcom.TokenView, error) {
return gcom.TokenView{}, cloudmigration.ErrFeatureDisabledError
func (s *NoopServiceImpl) GetToken(ctx context.Context) (authapi.TokenView, error) {
return authapi.TokenView{}, cloudmigration.ErrFeatureDisabledError
}
func (s *NoopServiceImpl) CreateToken(ctx context.Context) (cloudmigration.CreateAccessTokenResponse, error) {
@@ -6,8 +6,8 @@ import (
"sort"
"time"
"github.com/grafana/grafana/pkg/services/authapi"
"github.com/grafana/grafana/pkg/services/cloudmigration"
"github.com/grafana/grafana/pkg/services/gcom"
"github.com/grafana/grafana/pkg/services/user"
)
@@ -20,11 +20,11 @@ type FakeServiceImpl struct {
var _ cloudmigration.Service = (*FakeServiceImpl)(nil)
func (m FakeServiceImpl) GetToken(_ context.Context) (gcom.TokenView, error) {
func (m FakeServiceImpl) GetToken(_ context.Context) (authapi.TokenView, error) {
if m.ReturnError {
return gcom.TokenView{}, fmt.Errorf("mock error")
return authapi.TokenView{}, fmt.Errorf("mock error")
}
return gcom.TokenView{ID: "mock_id", DisplayName: "mock_name"}, nil
return authapi.TokenView{ID: "mock_id", DisplayName: "mock_name"}, nil
}
func (m FakeServiceImpl) CreateToken(_ context.Context) (cloudmigration.CreateAccessTokenResponse, error) {
@@ -6,16 +6,12 @@ import (
"strconv"
"github.com/grafana/grafana/pkg/services/gcom"
"github.com/grafana/grafana/pkg/util"
)
type gcomStub struct {
// The cloud migration token created by this stub.
token *gcom.TokenView
policies map[string]gcom.AccessPolicy
}
func (client *gcomStub) GetInstanceByID(ctx context.Context, requestID string, instanceID string) (gcom.Instance, error) {
func (client *gcomStub) GetInstanceByID(_ context.Context, _ string, instanceID string) (gcom.Instance, error) {
id, err := strconv.Atoi(instanceID)
if err != nil {
return gcom.Instance{}, fmt.Errorf("parsing instanceID: %w", err)
@@ -27,55 +23,3 @@ func (client *gcomStub) GetInstanceByID(ctx context.Context, requestID string, i
ClusterSlug: "fake-cluser",
}, nil
}
func (client *gcomStub) CreateAccessPolicy(ctx context.Context, params gcom.CreateAccessPolicyParams, payload gcom.CreateAccessPolicyPayload) (gcom.AccessPolicy, error) {
randStr := fmt.Sprintf("random-policy-%s", util.GenerateShortUID())
policy := gcom.AccessPolicy{
ID: randStr,
Name: randStr,
}
client.policies[policy.ID] = policy
return policy, nil
}
func (client *gcomStub) DeleteAccessPolicy(ctx context.Context, params gcom.DeleteAccessPolicyParams) (bool, error) {
delete(client.policies, params.AccessPolicyID)
return true, nil
}
func (client *gcomStub) ListAccessPolicies(ctx context.Context, params gcom.ListAccessPoliciesParams) ([]gcom.AccessPolicy, error) {
items := make([]gcom.AccessPolicy, 0)
for _, v := range client.policies {
items = append(items, v)
}
return items, nil
}
func (client *gcomStub) ListTokens(ctx context.Context, params gcom.ListTokenParams) ([]gcom.TokenView, error) {
if client.token == nil {
return []gcom.TokenView{}, nil
}
return []gcom.TokenView{*client.token}, nil
}
func (client *gcomStub) CreateToken(ctx context.Context, params gcom.CreateTokenParams, payload gcom.CreateTokenPayload) (gcom.Token, error) {
token := gcom.Token{
ID: fmt.Sprintf("random-token-%s", util.GenerateShortUID()),
Name: payload.Name,
AccessPolicyID: payload.AccessPolicyID,
Token: fmt.Sprintf("completely_fake_token_%s", util.GenerateShortUID()),
}
client.token = &gcom.TokenView{
ID: token.ID,
Name: token.Name,
AccessPolicyID: token.AccessPolicyID,
DisplayName: token.Name,
}
return token, nil
}
func (client *gcomStub) DeleteToken(ctx context.Context, params gcom.DeleteTokenParams) error {
client.token = nil
return nil
}