Skip to content

Commit

Permalink
refactor: introduce SecretValue to represent secrets (#2161)
Browse files Browse the repository at this point in the history
The class `cdk.SecretValue` is a token that represents a value that should
be treated as a secret. It can be created through one of the factory methods:
`SecretValue.secretsManager(id)` or `SecretValue.plainText(text)`.

Constructs that reference secrets have been converted to use this type
instead of plain strings.

The `secretsmanager.Secret` construct now has `secretValue` and 
`secretJsonValue` which return `SecretValue` objects with a dynamic reference.

The `DynamicReference` class is now a `Token`.

BREAKING CHANGE: The `secretsmanager.SecretString` class has been removed in favor of `cdk.SecretValue.secretsManager(id[, options])`

The following prop types have been changed from `string` to `cdk.SecretValue`: `codepipeline-actions.AlexaSkillDeployAction.clientSecret`, `codepipeline-actions.AlexaSkillDeployAction.refreshToken`, `codepipeline-actions.GitHubSourceAction.oauthToken`, `iam.User.password`

`secretsmanager.Secret.stringValue` and `jsonFieldValue` have been removed. Use `secretsmanage.Secret.secretValue` and `secretJsonValue` instead.

`secretsmanager.Secret.secretString` have been removed. Use `cdk.SecretValue.secretsManager()` or `secretsmanager.Secret.import(..).secretValue`.

The class `cdk.Secret` has been removed. Use `cdk.SecretValue` instead.

The class `cdk.DynamicReference` is no longer a construct, and it's
constructor signature was changed and was renamed `cdk.CfnDynamicReference`.
  • Loading branch information
Elad Ben-Israel authored Apr 4, 2019
1 parent 732aa5b commit a3d9f2e
Show file tree
Hide file tree
Showing 37 changed files with 438 additions and 390 deletions.
12 changes: 5 additions & 7 deletions packages/@aws-cdk/aws-codebuild/lib/source.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import codecommit = require('@aws-cdk/aws-codecommit');
import iam = require('@aws-cdk/aws-iam');
import s3 = require('@aws-cdk/aws-s3');
import cdk = require('@aws-cdk/cdk');
import { SecretValue } from '@aws-cdk/cdk';
import { CfnProject } from './codebuild.generated';
import { Project } from './project';

Expand Down Expand Up @@ -213,7 +213,7 @@ export interface GitHubSourceProps extends GitBuildSourceProps {
* Note that you need to give CodeBuild permissions to your GitHub account in order for the token to work.
* That is a one-time operation that can be done through the AWS Console for CodeBuild.
*/
readonly oauthToken: string;
readonly oauthToken: SecretValue;

/**
* Whether to create a webhook that will trigger a build every time a commit is pushed to the GitHub repository.
Expand All @@ -236,13 +236,12 @@ export interface GitHubSourceProps extends GitBuildSourceProps {
export class GitHubSource extends GitBuildSource {
public readonly type: SourceType = SourceType.GitHub;
private readonly httpsCloneUrl: string;
private readonly oauthToken: string;
private readonly oauthToken: SecretValue;
private readonly reportBuildStatus: boolean;
private readonly webhook?: boolean;

constructor(props: GitHubSourceProps) {
super(props);
cdk.Secret.assertSafeSecret(props.oauthToken, 'oauthToken');
this.httpsCloneUrl = `https://github.com/${props.owner}/${props.repo}.git`;
this.oauthToken = props.oauthToken;
this.webhook = props.webhook;
Expand Down Expand Up @@ -278,7 +277,7 @@ export interface GitHubEnterpriseSourceProps extends GitBuildSourceProps {
/**
* The OAuth token used to authenticate when cloning the git repository.
*/
readonly oauthToken: string;
readonly oauthToken: SecretValue;

/**
* Whether to ignore SSL errors when connecting to the repository.
Expand All @@ -294,12 +293,11 @@ export interface GitHubEnterpriseSourceProps extends GitBuildSourceProps {
export class GitHubEnterpriseSource extends GitBuildSource {
public readonly type: SourceType = SourceType.GitHubEnterprise;
private readonly httpsCloneUrl: string;
private readonly oauthToken: string;
private readonly oauthToken: SecretValue;
private readonly ignoreSslErrors?: boolean;

constructor(props: GitHubEnterpriseSourceProps) {
super(props);
cdk.Secret.assertSafeSecret(props.oauthToken, 'oauthToken');
this.httpsCloneUrl = props.httpsCloneUrl;
this.oauthToken = props.oauthToken;
this.ignoreSslErrors = props.ignoreSslErrors;
Expand Down
9 changes: 5 additions & 4 deletions packages/@aws-cdk/aws-codebuild/test/test.project.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { expect, haveResource, haveResourceLike } from '@aws-cdk/assert';
import assets = require('@aws-cdk/assets');
import cdk = require('@aws-cdk/cdk');
import { SecretValue } from '@aws-cdk/cdk';
import { Test } from 'nodeunit';
import codebuild = require('../lib');

Expand Down Expand Up @@ -58,7 +59,7 @@ export = {
owner: 'testowner',
repo: 'testrepo',
cloneDepth: 3,
oauthToken: cdk.Secret.plainText("test_oauth_token"),
oauthToken: SecretValue.plainText("test_oauth_token"),
})
});

Expand Down Expand Up @@ -88,7 +89,7 @@ export = {
source: new codebuild.GitHubSource({
owner: 'testowner',
repo: 'testrepo',
oauthToken: cdk.Secret.plainText("test_oauth_token"),
oauthToken: SecretValue.plainText("test_oauth_token"),
reportBuildStatus: false,
})
});
Expand All @@ -112,7 +113,7 @@ export = {
source: new codebuild.GitHubSource({
owner: 'testowner',
repo: 'testrepo',
oauthToken: cdk.Secret.plainText("test_oauth_token"),
oauthToken: SecretValue.plainText("test_oauth_token"),
webhook: true,
})
});
Expand All @@ -138,7 +139,7 @@ export = {
httpsCloneUrl: 'https://github.testcompany.com/testowner/testrepo',
ignoreSslErrors: true,
cloneDepth: 4,
oauthToken: cdk.Secret.plainText("test_oauth_token"),
oauthToken: SecretValue.plainText("test_oauth_token"),
})
});

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import codepipeline = require('@aws-cdk/aws-codepipeline');
import cdk = require('@aws-cdk/cdk');
import { SecretValue } from '@aws-cdk/cdk';

/**
* Construction properties of the {@link AlexaSkillDeployAction Alexa deploy Action}.
Expand All @@ -13,12 +13,12 @@ export interface AlexaSkillDeployActionProps extends codepipeline.CommonActionPr
/**
* The client secret of the developer console token
*/
readonly clientSecret: string;
readonly clientSecret: SecretValue;

/**
* The refresh token of the developer console token
*/
readonly refreshToken: string;
readonly refreshToken: SecretValue;

/**
* The Alexa skill id
Expand All @@ -41,9 +41,6 @@ export interface AlexaSkillDeployActionProps extends codepipeline.CommonActionPr
*/
export class AlexaSkillDeployAction extends codepipeline.DeployAction {
constructor(props: AlexaSkillDeployActionProps) {
cdk.Secret.assertSafeSecret(props.clientSecret, 'clientSecret');
cdk.Secret.assertSafeSecret(props.refreshToken, 'refreshToken');

super({
...props,
artifactBounds: {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import codepipeline = require('@aws-cdk/aws-codepipeline');
import cdk = require('@aws-cdk/cdk');
import { SecretValue } from '@aws-cdk/cdk';

/**
* Construction properties of the {@link GitHubSourceAction GitHub source action}.
Expand Down Expand Up @@ -36,7 +36,7 @@ export interface GitHubSourceActionProps extends codepipeline.CommonActionProps
* const oauth = new secretsmanager.SecretString(this, 'GitHubOAuthToken', { secretId: 'my-github-token' });
* new GitHubSource(this, 'GitHubAction', { oauthToken: oauth.value, ... });
*/
readonly oauthToken: string;
readonly oauthToken: SecretValue;

/**
* Whether AWS CodePipeline should poll for source changes.
Expand All @@ -54,8 +54,6 @@ export class GitHubSourceAction extends codepipeline.SourceAction {
private readonly props: GitHubSourceActionProps;

constructor(props: GitHubSourceActionProps) {
cdk.Secret.assertSafeSecret(props.oauthToken, 'oauthToken');

super({
...props,
owner: 'ThirdParty',
Expand All @@ -64,7 +62,7 @@ export class GitHubSourceAction extends codepipeline.SourceAction {
Owner: props.owner,
Repo: props.repo,
Branch: props.branch || "master",
OAuthToken: props.oauthToken,
OAuthToken: props.oauthToken.toString(),
PollForSourceChanges: props.pollForSourceChanges || false,
},
outputArtifactName: props.outputArtifactName
Expand All @@ -78,7 +76,7 @@ export class GitHubSourceAction extends codepipeline.SourceAction {
new codepipeline.CfnWebhook(info.scope, 'WebhookResource', {
authentication: 'GITHUB_HMAC',
authenticationConfiguration: {
secretToken: this.props.oauthToken,
secretToken: this.props.oauthToken.toString(),
},
filters: [
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import codepipeline = require('@aws-cdk/aws-codepipeline');
import s3 = require('@aws-cdk/aws-s3');
import cdk = require('@aws-cdk/cdk');
import { App, RemovalPolicy, SecretValue, Stack } from '@aws-cdk/cdk';
import cpactions = require('../lib');

const app = new cdk.App();
const app = new App();

const stack = new cdk.Stack(app, 'aws-cdk-codepipeline-alexa-deploy');
const stack = new Stack(app, 'aws-cdk-codepipeline-alexa-deploy');

const bucket = new s3.Bucket(stack, 'PipelineBucket', {
versioned: true,
removalPolicy: cdk.RemovalPolicy.Destroy,
removalPolicy: RemovalPolicy.Destroy,
});
const sourceAction = new cpactions.S3SourceAction({
actionName: 'Source',
Expand All @@ -30,8 +30,8 @@ const deployStage = {
runOrder: 1,
inputArtifact: sourceAction.outputArtifact,
clientId: 'clientId',
clientSecret: cdk.Secret.plainText('clientSecret'),
refreshToken: cdk.Secret.plainText('refreshToken'),
clientSecret: SecretValue.plainText('clientSecret'),
refreshToken: SecretValue.plainText('refreshToken'),
skillId: 'amzn1.ask.skill.12345678-1234-1234-1234-123456789012',
}),
],
Expand Down
32 changes: 16 additions & 16 deletions packages/@aws-cdk/aws-codepipeline-actions/test/test.pipeline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@ import codepipeline = require('@aws-cdk/aws-codepipeline');
import lambda = require('@aws-cdk/aws-lambda');
import s3 = require('@aws-cdk/aws-s3');
import sns = require('@aws-cdk/aws-sns');
import cdk = require('@aws-cdk/cdk');
import { App, CfnParameter, SecretValue, Stack } from '@aws-cdk/cdk';
import { Test } from 'nodeunit';
import cpactions = require('../lib');

// tslint:disable:object-literal-key-quotes

export = {
'basic pipeline'(test: Test) {
const stack = new cdk.Stack();
const stack = new Stack();

const repository = new codecommit.Repository(stack, 'MyRepo', {
repositoryName: 'my-repo',
Expand Down Expand Up @@ -50,7 +50,7 @@ export = {
},

'Tokens can be used as physical names of the Pipeline'(test: Test) {
const stack = new cdk.Stack(undefined, 'StackName');
const stack = new Stack(undefined, 'StackName');

new codepipeline.Pipeline(stack, 'Pipeline', {
pipelineName: stack.stackName,
Expand All @@ -66,9 +66,9 @@ export = {
},

'github action uses ThirdParty owner'(test: Test) {
const stack = new cdk.Stack();
const stack = new Stack();

const secret = new cdk.CfnParameter(stack, 'GitHubToken', { type: 'String', default: 'my-token' });
const secret = new CfnParameter(stack, 'GitHubToken', { type: 'String', default: 'my-token' });

const p = new codepipeline.Pipeline(stack, 'P');

Expand All @@ -80,7 +80,7 @@ export = {
runOrder: 8,
outputArtifactName: 'A',
branch: 'branch',
oauthToken: secret.stringValue,
oauthToken: SecretValue.plainText(secret.stringValue),
owner: 'foo',
repo: 'bar'
}),
Expand Down Expand Up @@ -163,7 +163,7 @@ export = {
},

'onStateChange'(test: Test) {
const stack = new cdk.Stack();
const stack = new Stack();

const topic = new sns.Topic(stack, 'Topic');

Expand Down Expand Up @@ -256,7 +256,7 @@ export = {

'manual approval Action': {
'allows passing an SNS Topic when constructing it'(test: Test) {
const stack = new cdk.Stack();
const stack = new Stack();
const topic = new sns.Topic(stack, 'Topic');
const manualApprovalAction = new cpactions.ManualApprovalAction({
actionName: 'Approve',
Expand All @@ -273,7 +273,7 @@ export = {
'PipelineProject': {
'with a custom Project Name': {
'sets the source and artifacts to CodePipeline'(test: Test) {
const stack = new cdk.Stack();
const stack = new Stack();

new codebuild.PipelineProject(stack, 'MyProject', {
projectName: 'MyProject',
Expand Down Expand Up @@ -307,7 +307,7 @@ export = {
},

'Lambda PipelineInvokeAction can be used to invoke Lambda functions from a CodePipeline'(test: Test) {
const stack = new cdk.Stack();
const stack = new Stack();

const lambdaFun = new lambda.Function(stack, 'Function', {
code: new lambda.InlineCode('bla'),
Expand Down Expand Up @@ -437,7 +437,7 @@ export = {

'CodeCommit Action': {
'does not poll for changes by default'(test: Test) {
const stack = new cdk.Stack();
const stack = new Stack();
const sourceAction = new cpactions.CodeCommitSourceAction({
actionName: 'stage',
outputArtifactName: 'SomeArtifact',
Expand All @@ -450,7 +450,7 @@ export = {
},

'does not poll for source changes when explicitly set to false'(test: Test) {
const stack = new cdk.Stack();
const stack = new Stack();
const sourceAction = new cpactions.CodeCommitSourceAction({
actionName: 'stage',
outputArtifactName: 'SomeArtifact',
Expand All @@ -469,9 +469,9 @@ export = {
const pipelineRegion = 'us-west-2';
const pipelineAccount = '123';

const app = new cdk.App();
const app = new App();

const stack = new cdk.Stack(app, 'TestStack', {
const stack = new Stack(app, 'TestStack', {
env: {
region: pipelineRegion,
account: pipelineAccount,
Expand Down Expand Up @@ -582,12 +582,12 @@ export = {
},
};

function stageForTesting(stack: cdk.Stack): codepipeline.IStage {
function stageForTesting(stack: Stack): codepipeline.IStage {
const pipeline = new codepipeline.Pipeline(stack, 'pipeline');
return pipeline.addStage({ name: 'stage' });
}

function repositoryForTesting(stack: cdk.Stack): codecommit.Repository {
function repositoryForTesting(stack: Stack): codecommit.Repository {
return new codecommit.Repository(stack, 'Repository', {
repositoryName: 'Repository'
});
Expand Down
9 changes: 6 additions & 3 deletions packages/@aws-cdk/aws-iam/lib/user.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Construct } from '@aws-cdk/cdk';
import { Construct, SecretValue } from '@aws-cdk/cdk';
import { Group } from './group';
import { CfnUser } from './iam.generated';
import { IIdentity } from './identity-base';
Expand Down Expand Up @@ -50,9 +50,12 @@ export interface UserProps {
* The password for the user. This is required so the user can access the
* AWS Management Console.
*
* You can use `SecretValue.plainText` to specify a password in plain text or
* use `secretsmanager.Secret.import` to reference a secret in Secrets Manager.
*
* @default User won't be able to access the management console without a password.
*/
readonly password?: string;
readonly password?: SecretValue;

/**
* Specifies whether the user is required to set a new password the next
Expand Down Expand Up @@ -147,7 +150,7 @@ export class User extends Construct implements IIdentity {
private parseLoginProfile(props: UserProps): CfnUser.LoginProfileProperty | undefined {
if (props.password) {
return {
password: props.password,
password: props.password.toString(),
passwordResetRequired: props.passwordResetRequired
};
}
Expand Down
3 changes: 2 additions & 1 deletion packages/@aws-cdk/aws-iam/test/example.attaching.lit.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import cdk = require('@aws-cdk/cdk');
import { SecretValue } from '@aws-cdk/cdk';
import { Group, Policy, User } from '../lib';

export class ExampleConstruct extends cdk.Construct {
constructor(scope: cdk.Construct, id: string) {
super(scope, id);

/// !show
const user = new User(this, 'MyUser', { password: '1234' });
const user = new User(this, 'MyUser', { password: SecretValue.plainText('1234') });
const group = new Group(this, 'MyGroup');

const policy = new Policy(this, 'MyPolicy');
Expand Down
4 changes: 2 additions & 2 deletions packages/@aws-cdk/aws-iam/test/integ.user.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { App, Stack } from "@aws-cdk/cdk";
import { App, SecretValue, Stack } from "@aws-cdk/cdk";
import { User } from "../lib";

const app = new App();
Expand All @@ -7,7 +7,7 @@ const stack = new Stack(app, 'aws-cdk-iam-user');

new User(stack, 'MyUser', {
userName: 'benisrae',
password: '1234',
password: SecretValue.plainText('1234'),
passwordResetRequired: true
});

Expand Down
Loading

0 comments on commit a3d9f2e

Please sign in to comment.