Skip to content

Commit

Permalink
feat(secretsmanager): adds grantWrite to Secret (aws#7858)
Browse files Browse the repository at this point in the history
### Commit Message
feat(secretsmanager): adds grantWrite to Secret
### End Commit Message

Implements: aws#7682

#### Testing

I deployed the following:
```
#!/usr/bin/env node

import * as cdk from '@aws-cdk/core';
import * as kms from '@aws-cdk/aws-kms';
import * as secretsmanager from '@aws-cdk/aws-secretsmanager';
import * as ec2 from '@aws-cdk/aws-ec2';

const app = new cdk.App();

const stack = new cdk.Stack(app, 'Stack', {});
const key = new kms.Key(stack, 'KMS');
const secret = new secretsmanager.Secret(stack, 'Secret', { encryptionKey: key });
const secret2 = new secretsmanager.Secret(stack, 'Secret2', {});

const vpc = ec2.Vpc.fromVpcAttributes(stack, 'Vpc', {
    vpcId: "vpc-XXXX",
    availabilityZones: [ "us-west-2a" ],
    publicSubnetIds: [ "subnet-XXXX" ],
});
const instance = new ec2.BastionHostLinux(stack, 'Bastion', { 
    vpc: vpc
});
secret.grantRead(instance);
secret.grantWrite(instance);
secret2.grantRead(instance);
secret2.grantWrite(instance);

app.synth();
```

Then, once the stack is deployed I used ssm to connect to the bastion and ran:
```
for secret in <secret name 1> <secret name 2>
do
	aws --region us-west-2 secretsmanager put-secret-value --secret-id ${secret} --secret-string "FooValue"
	aws --region us-west-2 secretsmanager get-secret-value --secret-id ${secret}
done
```

Finally, I verified the contents of the two secrets in the SecretsManager console.

----

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
  • Loading branch information
ddneilson authored and karupanerura committed May 21, 2020
1 parent 7abc61e commit ade8f85
Show file tree
Hide file tree
Showing 3 changed files with 296 additions and 286 deletions.
24 changes: 24 additions & 0 deletions packages/@aws-cdk/aws-secretsmanager/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,30 @@ const secret = secretsmanager.Secret.fromSecretAttributes(scope, 'ImportedSecret
SecretsManager secret values can only be used in select set of properties. For the
list of properties, see [the CloudFormation Dynamic References documentation](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/dynamic-references.html).

### Grant permission to use the secret to a role

You must grant permission to a resource for that resource to be allowed to
use a secret. This can be achieved with the `Secret.grantRead` and/or
`Secret.grantWrite` method, depending on your need:

```ts
const role = new iam.Role(stack, 'SomeRole', { assumedBy: new iam.AccountRootPrincipal() });
const secret = new secretsmanager.Secret(stack, 'Secret');
secret.grantRead(role);
secret.grantWrite(role);
```

If, as in the following example, your secret was created with a KMS key:
```ts
const key = new kms.Key(stack, 'KMS');
const secret = new secretsmanager.Secret(stack, 'Secret', { encryptionKey: key });
secret.grantRead(role);
secret.grantWrite(role);
```
then `Secret.grantRead` and `Secret.grantWrite` will also grant the role the
relevant encrypt and decrypt permissions to the KMS key through the
SecretsManager service principal.

### Rotating a Secret with a custom Lambda function
A rotation schedule can be added to a Secret using a custom Lambda function:
```ts
Expand Down
26 changes: 26 additions & 0 deletions packages/@aws-cdk/aws-secretsmanager/lib/secret.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,13 @@ export interface ISecret extends IResource {
*/
grantRead(grantee: iam.IGrantable, versionStages?: string[]): iam.Grant;

/**
* Grants writing the secret value to some role.
*
* @param grantee the principal being granted permission.
*/
grantWrite(grantee: iam.IGrantable): iam.Grant;

/**
* Adds a rotation schedule to the secret.
*/
Expand Down Expand Up @@ -148,6 +155,25 @@ abstract class SecretBase extends Resource implements ISecret {
return result;
}

public grantWrite(grantee: iam.IGrantable): iam.Grant {
// See https://docs.aws.amazon.com/secretsmanager/latest/userguide/auth-and-access_identity-based-policies.html
const result = iam.Grant.addToPrincipal({
grantee,
actions: ['secretsmanager:PutSecretValue'],
resourceArns: [this.secretArn],
scope: this,
});

if (this.encryptionKey) {
// See https://docs.aws.amazon.com/kms/latest/developerguide/services-secrets-manager.html
this.encryptionKey.grantEncrypt(
new kms.ViaServicePrincipal(`secretsmanager.${Stack.of(this).region}.amazonaws.com`, grantee.grantPrincipal),
);
}

return result;
}

public get secretValue() {
return this.secretValueFromJson('');
}
Expand Down
Loading

0 comments on commit ade8f85

Please sign in to comment.