diff --git a/client/stack.go b/client/stack.go index dd09224..53f10fe 100644 --- a/client/stack.go +++ b/client/stack.go @@ -145,3 +145,45 @@ func (g *Grafana) DeleteGrafanaServiceAccountFromCloud(stack string, serviceAcco return nil } + +func (g *Grafana) CreateTemporaryStackGrafanaClient(stackSlug string, tempSaPrefix string, tempKeyDuration time.Duration) (tempClient *Grafana, cleanup func() error, err error) { + stack, err := g.StackBySlug(stackSlug) + if err != nil { + return nil, nil, err + } + + name := fmt.Sprintf("%s%d", tempSaPrefix, time.Now().UnixNano()) + + req := CreateServiceAccountInput{ + Name: name, + Role: "Admin", + } + + sa, err := g.CreateGrafanaServiceAccountFromCloud(stackSlug, req) + if err != nil { + return nil, nil, fmt.Errorf("error creating temporary service account: %w", err) + } + + tokenRequest := CreateServiceAccountTokenInput{ + Name: name, + ServiceAccountID: sa.ID, + SecondsToLive: int64(tempKeyDuration.Seconds()), + } + + token, err := g.CreateGrafanaServiceAccountTokenFromCloud(stackSlug, tokenRequest) + if err != nil { + return nil, nil, fmt.Errorf("error creating temporary service account token: %w", err) + } + + client, err := New(stack.URL, token.Key) + if err != nil { + return nil, nil, fmt.Errorf("error creating temporary client: %w", err) + } + + cleanup = func() error { + err = client.DeleteServiceAccount(sa.ID) + return err + } + + return client, cleanup, nil +} diff --git a/path_credentials.go b/path_credentials.go index 72e9a50..42dd137 100644 --- a/path_credentials.go +++ b/path_credentials.go @@ -5,6 +5,7 @@ import ( "encoding/json" "errors" "fmt" + "time" "github.com/Boostport/vault-plugin-secrets-grafana/client" "github.com/google/uuid" @@ -178,6 +179,49 @@ func createCloudServiceAccountToken(c *client.Grafana, credentialName string, ro return nil, fmt.Errorf("error creating service account: %w", err) } + if len(roleEntry.RBACRoles) > 0 { + instanceClient, cleanup, err := c.CreateTemporaryStackGrafanaClient(roleEntry.Stack, "vault-temp-service-account-", 5*time.Minute) + + if err != nil { + err := c.DeleteGrafanaServiceAccountFromCloud(roleEntry.Stack, serviceAccount.ID) + + if err != nil { + return nil, fmt.Errorf("error deleting service account after error creating temporary client: %w", err) + } + + return nil, fmt.Errorf("error creating temporary client: %w", err) + } + + defer cleanup() + + roleUIDs, err := customRBACRoleNamesToIDs(instanceClient, roleEntry.RBACRoles) + + if err != nil { + err := c.DeleteGrafanaServiceAccountFromCloud(roleEntry.Stack, serviceAccount.ID) + + if err != nil { + return nil, fmt.Errorf("error deleting service account after error converting role names to IDs: %w", err) + } + return nil, fmt.Errorf("error converting role names to IDs: %w", err) + } + + err = instanceClient.SetServiceAccountRoleAssignments(client.ServiceAccountRoleAssignmentsInput{ + ServiceAccountID: serviceAccount.ID, + RoleUIDs: roleUIDs, + }) + + if err != nil { + err := c.DeleteGrafanaServiceAccountFromCloud(roleEntry.Stack, serviceAccount.ID) + + if err != nil { + return nil, fmt.Errorf("error deleting service account after error setting role assignments: %w", err) + + } + + return nil, fmt.Errorf("error setting service account role assignments: %w", err) + } + } + token, err := c.CreateGrafanaServiceAccountTokenFromCloud(roleEntry.Stack, client.CreateServiceAccountTokenInput{ Name: credentialName, ServiceAccountID: serviceAccount.ID,