Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(core): remove cdk.Secret #2068

Merged
merged 7 commits into from
Apr 1, 2019
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/@aws-cdk/alexa-ask/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@

```ts
const alexaAsk = require('@aws-cdk/alexa-ask');
```
```
2 changes: 1 addition & 1 deletion packages/@aws-cdk/app-delivery/test/integ.cicd.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const source = new cpactions.GitHubSourceAction({
actionName: 'GitHub',
owner: 'awslabs',
repo: 'aws-cdk',
oauthToken: new cdk.Secret('DummyToken'),
oauthToken: cdk.Secret.unsafeSecret('DummyToken'),
pollForSourceChanges: true,
outputArtifactName: 'Artifact_CICDGitHubF8BA7ADD',
});
Expand Down
6 changes: 3 additions & 3 deletions packages/@aws-cdk/aws-codebuild/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,9 @@ Example:
const gitHubSource = new codebuild.GitHubSource({
owner: 'awslabs',
repo: 'aws-cdk',
oauthToken: new cdk.SecretParameter(this, 'GitHubOAuthToken', {
ssmParameter: 'my-github-token',
}).value,
oauthToken: new secretsmanager.SecretString(this, 'GitHubOAuthToken', {
secretId: 'my-github-token',
}).stringValue,
webhook: true, // optional, default: false
});
```
Expand Down
10 changes: 6 additions & 4 deletions packages/@aws-cdk/aws-codebuild/lib/source.ts
Original file line number Diff line number Diff line change
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: cdk.Secret;
readonly oauthToken: string;

/**
* Whether to create a webhook that will trigger a build every time a commit is pushed to the GitHub repository.
Expand All @@ -236,12 +236,13 @@ export interface GitHubSourceProps extends GitBuildSourceProps {
export class GitHubSource extends GitBuildSource {
public readonly type: SourceType = SourceType.GitHub;
private readonly httpsCloneUrl: string;
private readonly oauthToken: cdk.Secret;
private readonly oauthToken: string;
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 @@ -277,7 +278,7 @@ export interface GitHubEnterpriseSourceProps extends GitBuildSourceProps {
/**
* The OAuth token used to authenticate when cloning the git repository.
*/
readonly oauthToken: cdk.Secret;
readonly oauthToken: string;

/**
* Whether to ignore SSL errors when connecting to the repository.
Expand All @@ -293,11 +294,12 @@ export interface GitHubEnterpriseSourceProps extends GitBuildSourceProps {
export class GitHubEnterpriseSource extends GitBuildSource {
public readonly type: SourceType = SourceType.GitHubEnterprise;
private readonly httpsCloneUrl: string;
private readonly oauthToken: cdk.Secret;
private readonly oauthToken: string;
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
8 changes: 4 additions & 4 deletions packages/@aws-cdk/aws-codebuild/test/test.project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ export = {
owner: 'testowner',
repo: 'testrepo',
cloneDepth: 3,
oauthToken: new cdk.Secret("test_oauth_token")
oauthToken: cdk.Secret.unsafeSecret("test_oauth_token"),
})
});

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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,17 @@ export interface AlexaSkillDeployActionProps extends codepipeline.CommonActionPr
/**
* The client id of the developer console token
*/
readonly clientId: cdk.Secret;
readonly clientId: string;

/**
* The client secret of the developer console token
*/
readonly clientSecret: cdk.Secret;
readonly clientSecret: string;

/**
* The refresh token of the developer console token
*/
readonly refreshToken: cdk.Secret;
readonly refreshToken: string;

/**
* The Alexa skill id
Expand All @@ -41,6 +41,9 @@ 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
Expand Up @@ -31,13 +31,12 @@ export interface GitHubSourceActionProps extends codepipeline.CommonActionProps
/**
* A GitHub OAuth token to use for authentication.
*
* It is recommended to use a `SecretParameter` to obtain the token from the SSM
* Parameter Store:
* It is recommended to use a Secrets Manager `SecretString` to obtain the token:
*
* const oauth = new cdk.SecretParameter(this, 'GitHubOAuthToken', { ssmParameter: 'my-github-token' });
* const oauth = new secretsmanager.SecretString(this, 'GitHubOAuthToken', { secretId: 'my-github-token' });
* new GitHubSource(this, 'GitHubAction', { oauthToken: oauth.value, ... });
*/
readonly oauthToken: cdk.Secret;
readonly oauthToken: string;

/**
* Whether AWS CodePipeline should poll for source changes.
Expand All @@ -55,6 +54,8 @@ 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 @@ -77,7 +78,7 @@ export class GitHubSourceAction extends codepipeline.SourceAction {
new codepipeline.CfnWebhook(info.scope, 'WebhookResource', {
authentication: 'GITHUB_HMAC',
authenticationConfiguration: {
secretToken: this.props.oauthToken.toString(),
secretToken: this.props.oauthToken,
},
filters: [
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ const deployStage = {
actionName: 'DeploySkill',
runOrder: 1,
inputArtifact: sourceAction.outputArtifact,
clientId: new cdk.Secret('clientId'),
clientSecret: new cdk.Secret('clientSecret'),
refreshToken: new cdk.Secret('refreshToken'),
clientId: 'clientId',
clientSecret: cdk.Secret.unsafeSecret('clientSecret'),
refreshToken: cdk.Secret.unsafeSecret('refreshToken'),
skillId: 'amzn1.ask.skill.12345678-1234-1234-1234-123456789012',
}),
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ export = {
'github action uses ThirdParty owner'(test: Test) {
const stack = new cdk.Stack();

const secret = new cdk.SecretParameter(stack, 'GitHubToken', { ssmParameter: 'my-token' });
const secret = new cdk.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.value,
oauthToken: secret.stringValue,
owner: 'foo',
repo: 'bar'
}),
Expand Down Expand Up @@ -122,7 +122,7 @@ export = {
"Repo": "bar",
"Branch": "branch",
"OAuthToken": {
"Ref": "GitHubTokenParameterBB166B9D"
"Ref": "GitHubToken"
},
"PollForSourceChanges": false
},
Expand Down
5 changes: 2 additions & 3 deletions packages/@aws-cdk/cdk/lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,11 @@ export * from './dynamic-reference';
export * from './tag';
export * from './removal-policy';
export * from './arn';
export * from './secret';

export * from './app';
export * from './context';
export * from './environment';

export * from './runtime';

export * from './synthesis';
export * from './secret';
export * from './synthesis';
115 changes: 34 additions & 81 deletions packages/@aws-cdk/cdk/lib/secret.ts
Original file line number Diff line number Diff line change
@@ -1,94 +1,47 @@
import { CfnParameter } from './cfn-parameter';
import { Construct } from './construct';
import { Token } from './token';
import { Token } from "./token";
import { unresolved } from "./unresolved";

/**
* A token that represents a value that's expected to be a secret, like
* passwords and keys.
* Work with secret values in the CDK
*
* It is recommended to use the `SecretParameter` construct in order to import
* secret values from the SSM Parameter Store instead of storing them in your
* code.
* Secret values in the CDK (such as those retrieved from SecretsManager) are
* represented as regular strings, just like other values that are only
* available at deployment time.
*
* However, you can also just pass in values, like any other token: `new Secret('bla')`
* To help you avoid accidental mistakes which would lead to you putting your
* secret values directly into a CloudFormation template, constructs that take
* secret values will not allow you to pass in a literal secret value. They do
* so by calling `Secret.assertSafeSecret()`.
*
* You can escape the check by calling `Secret.unsafeSecret()`, but doing
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe instead of Secret.unsafeSecret we can do Secret.clearText or Secret.plainText? Less about policy, more about mechanism...

* so is highly discouraged.
*/
export class Secret extends Token { }

export interface SecretParameterProps {
/**
* The name of the SSM parameter where the secret value is stored.
*/
readonly ssmParameter: string;

/**
* A string of up to 4000 characters that describes the parameter.
* @default No description
*/
readonly description?: string;

/**
* A regular expression that represents the patterns to allow for String types.
*/
readonly allowedPattern?: string;

/**
* An array containing the list of values allowed for the parameter.
*/
readonly allowedValues?: string[];

export class Secret {
/**
* A string that explains a constraint when the constraint is violated.
* For example, without a constraint description, a parameter that has an allowed
* pattern of [A-Za-z0-9]+ displays the following error message when the user specifies
* an invalid value:
* Validate that a given secret value is not a literal
*
* If the value is a literal, throw an error.
*/
readonly constraintDescription?: string;
public static assertSafeSecret(secretValue: string, parameterName?: string) {
if (!unresolved(secretValue)) {
const theParameter = parameterName ? `'${parameterName}'` : 'The value';

/**
* An integer value that determines the largest number of characters you want to allow for String types.
*/
readonly maxLength?: number;
// tslint:disable-next-line:max-line-length
throw new Error(`${theParameter} should be a secret. Store it in SecretsManager or Systems Manager Parameter Store and retrieve it from there. Secret.unsafeSecret() can be used to bypass this check, but do so for testing purposes only.`);
}
}

/**
* An integer value that determines the smallest number of characters you want to allow for String types.
* Construct a literal secret value for use with secret-aware constructs
*
* *Do not use this method for any secrets that you care about.*
*
* The only reasonable use case for using this method is when you are testing.
*/
readonly minLength?: number;
}

/**
* Defines a secret value resolved from the Systems Manager (SSM) Parameter
* Store during deployment. This is useful for referencing values that you do
* not wish to include in your code base, such as secrets, passwords and keys.
*
* This construct will add a CloudFormation parameter to your template bound to
* an SSM parameter (of type "AWS::SSM::Parameter::Value<String>"). Deployment
* will fail if the value doesn't exist in the target environment.
*
* Important: For values other than secrets, prefer to use the
* `SSMParameterProvider` which resolves SSM parameter in design-time, and
* ensures that stack deployments are deterministic.
*/
export class SecretParameter extends Construct {
/**
* The value of the secret parameter.
*/
public value: Secret;

constructor(scope: Construct, id: string, props: SecretParameterProps) {
super(scope, id);

const param = new CfnParameter(this, 'Parameter', {
type: 'AWS::SSM::Parameter::Value<String>',
default: props.ssmParameter,
description: props.description,
allowedPattern: props.allowedPattern,
allowedValues: props.allowedValues,
constraintDescription: props.constraintDescription,
maxLength: props.maxLength,
minLength: props.minLength,
noEcho: true,
});
public static unsafeSecret(secret: string): string {
return new Token(() => secret).toString();
}

this.value = new Secret(param.ref);
private constructor() {
}
}
}
2 changes: 1 addition & 1 deletion packages/@aws-cdk/cdk/lib/token.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,4 +139,4 @@ export interface IResolvedValuePostProcessor {
*/
export function isResolvedValuePostProcessor(x: any): x is IResolvedValuePostProcessor {
return x.postProcess !== undefined;
}
}
Loading