Co-authored-by: hashicorp-copywrite[bot] <110428419+hashicorp-copywrite[bot]@users.noreply.github.com>
92 lines
2.5 KiB
Go
92 lines
2.5 KiB
Go
// Copyright IBM Corp. 2025, 2026
|
|
// SPDX-License-Identifier: MPL-2.0
|
|
|
|
package storage
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/hashicorp/boundary-plugin-minio/internal/client"
|
|
)
|
|
|
|
const (
|
|
defaultPolicyTemplate = `{
|
|
"Statement": [
|
|
{
|
|
"Action": [
|
|
"s3:GetObject",
|
|
"s3:GetObjectAttributes",
|
|
"s3:PutObject",
|
|
"s3:DeleteObject"
|
|
],
|
|
"Effect": "Allow",
|
|
"Resource": "arn:aws:s3:::%[1]s/*"
|
|
},
|
|
{
|
|
"Action": "s3:ListBucket",
|
|
"Effect": "Allow",
|
|
"Resource": "arn:aws:s3:::%[1]s"
|
|
},
|
|
{
|
|
"Action": [
|
|
"admin:CreateServiceAccount",
|
|
"admin:RemoveServiceAccount"
|
|
],
|
|
"Effect": "Allow"
|
|
}
|
|
],
|
|
"Version": "2012-10-17"
|
|
}`
|
|
)
|
|
|
|
type deleteInputCredsFn func() error
|
|
|
|
// rotateCredentials uses the incoming service account credentials to generate a
|
|
// new service account. It returns a new StorageSecrets object with the new
|
|
// service account credentials and a callback function to delete the service
|
|
// account provided in the input.
|
|
func rotateCredentials(ctx context.Context, bucketName string, sa *StorageAttributes, inSec *StorageSecrets) (*StorageSecrets, deleteInputCredsFn, error) {
|
|
err := ensureServiceAccount(ctx, sa, inSec)
|
|
if err != nil {
|
|
return nil, nil, fmt.Errorf("failed to ensure minio service account credentials: %w", err)
|
|
}
|
|
|
|
ac, err := client.New(sa.EndpointUrl, inSec.AccessKeyId, inSec.SecretAccessKey, client.WithUseSsl(sa.UseSSL))
|
|
if err != nil {
|
|
return nil, nil, fmt.Errorf("failed to create new client: %w", err)
|
|
}
|
|
|
|
policy := json.RawMessage(fmt.Sprintf(defaultPolicyTemplate, bucketName))
|
|
newCreds, err := ac.AddServiceAccount(ctx, client.AddServiceAccountReq{
|
|
Name: "Boundary MinIO Service Account",
|
|
Description: fmt.Sprintf("Boundary-managed MinIO service account for storage bucket '%s'", bucketName),
|
|
Policy: policy,
|
|
})
|
|
if err != nil {
|
|
return nil, nil, fmt.Errorf("failed to create new minio service account: %w", err)
|
|
}
|
|
|
|
newSec := &StorageSecrets{
|
|
AccessKeyId: newCreds.AccessKeyId,
|
|
SecretAccessKey: newCreds.SecretAccessKey,
|
|
LastRotatedTime: time.Now(),
|
|
}
|
|
|
|
inCl := inSec.Clone()
|
|
return newSec, sync.OnceValue(func() error {
|
|
ac, err := client.New(sa.EndpointUrl, inCl.AccessKeyId, inCl.SecretAccessKey, client.WithUseSsl(sa.UseSSL))
|
|
if err != nil {
|
|
return fmt.Errorf("failed to create new client: %w", err)
|
|
}
|
|
err = ac.DeleteServiceAccount(ctx, inCl.AccessKeyId)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to delete minio service account: %w", err)
|
|
}
|
|
return nil
|
|
}), nil
|
|
}
|