diff --git a/cloud/aws/deploy/config/config.go b/cloud/aws/deploy/config/config.go index c059a0e1d..9c97e986f 100644 --- a/cloud/aws/deploy/config/config.go +++ b/cloud/aws/deploy/config/config.go @@ -22,8 +22,14 @@ import ( "github.com/nitrictech/nitric/cloud/common/deploy/config" ) +type AwsImports struct { + // A map of nitric names to ARNs + Secrets map[string]string +} + type AwsConfig struct { ScheduleTimezone string `mapstructure:"schedule-timezone,omitempty"` + Import AwsImports config.AbstractConfig[*AwsConfigItem] } diff --git a/cloud/aws/deploy/secret/secretsmanager.go b/cloud/aws/deploy/secret/secretsmanager.go index b89c1de7b..5e64e6d37 100644 --- a/cloud/aws/deploy/secret/secretsmanager.go +++ b/cloud/aws/deploy/secret/secretsmanager.go @@ -17,6 +17,8 @@ package secret import ( + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/resourcegroupstaggingapi" common "github.com/nitrictech/nitric/cloud/common/deploy/tags" v1 "github.com/nitrictech/nitric/core/pkg/api/nitric/deploy/v1" "github.com/pulumi/pulumi-aws/sdk/v5/go/aws/secretsmanager" @@ -31,7 +33,10 @@ type SecretsManagerSecret struct { type SecretsManagerSecretArgs struct { StackID pulumi.StringInput - Secret *v1.Secret + // Import an existing secret + Import string + Secret *v1.Secret + Client *resourcegroupstaggingapi.ResourceGroupsTaggingAPI } // Create a new SecretsManager secret @@ -45,14 +50,54 @@ func NewSecretsManagerSecret(ctx *pulumi.Context, name string, args *SecretsMana return nil, err } - sec, err := secretsmanager.NewSecret(ctx, name, &secretsmanager.SecretArgs{ - Tags: common.Tags(ctx, args.StackID, name), - }) - if err != nil { - return nil, err - } + if args.Import != "" { + secretLookup, err := secretsmanager.LookupSecret(ctx, &secretsmanager.LookupSecretArgs{ + Arn: aws.String(args.Import), + }) + if err != nil { + return nil, err + } - res.SecretsManager = sec + // apply nitric tags + // This will apply nitric tags for resource resolution + _ = args.StackID.ToStringOutput().ApplyT(func(stackId string) (bool, error) { + _, err := args.Client.TagResources(&resourcegroupstaggingapi.TagResourcesInput{ + ResourceARNList: aws.StringSlice([]string{secretLookup.Arn}), + Tags: aws.StringMap(map[string]string{ + "x-nitric-project": ctx.Project(), + "x-nitric-name": name, + "x-nitric-stack-name": ctx.Stack(), + "x-nitric-stack": stackId, + }), + }) + if err != nil { + return false, err + } + + return true, nil + }) + + // import an existing secret + res.SecretsManager, err = secretsmanager.GetSecret( + ctx, + name, + pulumi.ID(secretLookup.Id), + nil, + // not our resource so we'll keep it around + pulumi.RetainOnDelete(true), + ) + if err != nil { + return nil, err + } + } else { + // create a new secret + res.SecretsManager, err = secretsmanager.NewSecret(ctx, name, &secretsmanager.SecretArgs{ + Tags: common.Tags(ctx, args.StackID, name), + }) + if err != nil { + return nil, err + } + } return res, nil } diff --git a/cloud/aws/deploy/up.go b/cloud/aws/deploy/up.go index 3b647be24..44aa69fd0 100644 --- a/cloud/aws/deploy/up.go +++ b/cloud/aws/deploy/up.go @@ -24,6 +24,7 @@ import ( "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/lambda" + "github.com/aws/aws-sdk-go/service/resourcegroupstaggingapi" "github.com/getkin/kin-openapi/openapi3" "github.com/nitrictech/nitric/cloud/aws/deploy/api" "github.com/nitrictech/nitric/cloud/aws/deploy/bucket" @@ -76,6 +77,7 @@ func (d *DeployServer) Up(request *deploy.DeployUpRequest, stream deploy.DeployS SharedConfigState: session.SharedConfigEnable, })) lambdaClient := lambda.New(sess, &aws.Config{Region: aws.String(details.Region)}) + resourceTaggingClient := resourcegroupstaggingapi.New(sess) pulumiStack, err := auto.UpsertStackInlineSource(context.TODO(), details.FullStackName, details.Project, func(ctx *pulumi.Context) error { principals := map[v1.ResourceType]map[string]*iam.Role{} @@ -105,9 +107,17 @@ func (d *DeployServer) Up(request *deploy.DeployUpRequest, stream deploy.DeployS for _, res := range request.Spec.Resources { switch c := res.Config.(type) { case *deploy.Resource_Secret: + importArn := "" + + if config.Import.Secrets != nil { + importArn = config.Import.Secrets[res.Name] + } + secrets[res.Name], err = secret.NewSecretsManagerSecret(ctx, res.Name, &secret.SecretsManagerSecretArgs{ StackID: stackID, Secret: c.Secret, + Import: importArn, + Client: resourceTaggingClient, }) if err != nil { return err diff --git a/cloud/aws/runtime/secret/secrets_manager.go b/cloud/aws/runtime/secret/secrets_manager.go index 05f20a901..d75ec78bd 100644 --- a/cloud/aws/runtime/secret/secrets_manager.go +++ b/cloud/aws/runtime/secret/secrets_manager.go @@ -153,6 +153,12 @@ func (s *secretsManagerSecretService) Access(ctx context.Context, sv *secret.Sec ) } + returnValue := result.SecretBinary + + if returnValue == nil && result.SecretString != nil { + returnValue = []byte(*result.SecretString) + } + return &secret.SecretAccessResponse{ SecretVersion: &secret.SecretVersion{ Secret: &secret.Secret{ @@ -160,7 +166,7 @@ func (s *secretsManagerSecretService) Access(ctx context.Context, sv *secret.Sec }, Version: *result.VersionId, }, - Value: result.SecretBinary, + Value: returnValue, }, nil }