Skip to content

Commit

Permalink
feat(app-delivery) IAM policy for deploy stack
Browse files Browse the repository at this point in the history
 * The changeset and apply changeset can now apply role IAM permissions,
 and CloudFormation Capabilities
 * Document updates for proper build stage configuration
 * Fixes aws#1151
  • Loading branch information
moofish32 committed Nov 15, 2018
1 parent d397dd7 commit 0d1fdb9
Show file tree
Hide file tree
Showing 4 changed files with 277 additions and 9 deletions.
32 changes: 28 additions & 4 deletions packages/@aws-cdk/app-delivery/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,17 @@ const source = new codepipeline.GitHubSourceAction(pipelineStack, 'GitHub', {
/* ... */
});
const project = new codebuild.PipelineProject(pipelineStack, 'CodeBuild', {
/* ... */
/**
* Choose an environment configuration that meets your use case. For NodeJS
* this might be
* environment: {
* buildImage: codebuild.LinuxBuildImage.UBUNTU_14_04_NODEJS_10_1_0,
* },
*/
});
const synthesizedApp = project.outputArtifact;
const buildStage = pipeline.addStage('build');
const buildAction = project.addBuildToPipeline(buildStage, 'CodeBuild');
const synthesizedApp = buildAction.outputArtifact;

// Optionally, self-update the pipeline stack
const selfUpdateStage = pipeline.addStage('SelfUpdate');
Expand All @@ -69,26 +77,42 @@ const deployStage = pipeline.addStage('Deploy');
const serviceStackA = new MyServiceStackA(app, 'ServiceStackA', { /* ... */ });
const serviceStackB = new MyServiceStackB(app, 'ServiceStackB', { /* ... */ });
// Add actions to deploy the stacks in the deploy stage:
new cicd.PipelineDeployStackAction(pipelineStack, 'DeployServiceStackA', {
const deployServiceAAction = new cicd.PipelineDeployStackAction(pipelineStack, 'DeployServiceStackA', {
stage: deployStage,
stack: serviceStackA,
inputArtifact: synthesizedApp,
});
new cicd.PipelineDeployStackAction(pipelineStack, 'DeployServiceStackB', {

deployServiceAAction.role.addToPolicy(
// new iam.PolicyStatement().
// ... addAction('actions that you need').
// add resource
);

const deployServiceBAction = new cicd.PipelineDeployStackAction(pipelineStack, 'DeployServiceStackB', {
stage: deployStage,
stack: serviceStackB,
inputArtifact: synthesizedApp,
createChangeSetRunOrder: 998,
});
deployServiceBAction.role.addToPolicy(
// new iam.PolicyStatement().
// ... addAction('actions that you need').
// add resource
);
```

#### `buildspec.yml`
The repository can contain a file at the root level named `buildspec.yml`, or
you can in-line the buildspec. Note that `buildspec.yaml` is not compatible.

The `PipelineDeployStackAction` expects it's `inputArtifact` to contain the result of synthesizing a CDK App using the
`cdk synth -o <directory>` command.

For example, a *TypeScript* or *Javascript* CDK App can add the following `buildspec.yml` at the root of the repository
configured in the `Source` stage:

Example contents of `buildspec.yml`.
```yml
version: 0.2
phases:
Expand Down
59 changes: 56 additions & 3 deletions packages/@aws-cdk/app-delivery/lib/pipeline-deploy-stack-action.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@

import cfn = require('@aws-cdk/aws-cloudformation');
import codepipeline = require('@aws-cdk/aws-codepipeline-api');
import iam = require('@aws-cdk/aws-iam');
import cdk = require('@aws-cdk/cdk');
import cxapi = require('@aws-cdk/cx-api');

Expand Down Expand Up @@ -41,6 +41,48 @@ export interface PipelineDeployStackActionProps {
* @default ``createChangeSetRunOrder + 1``
*/
executeChangeSetRunOrder?: number;

/**
* IAM role to assume when deploying changes.
*
* If not specified, a fresh role is created. The role is created with zero
* permissions unless `fullPermissions` is true, in which case the role will have
* full permissions.
*
* @default A fresh role with full or no permissions (depending on the value of `fullPermissions`).
*/
role?: iam.Role;

/**
* Acknowledge certain changes made as part of deployment
*
* For stacks that contain certain resources, explicit acknowledgement that AWS CloudFormation
* might create or update those resources. For example, you must specify CAPABILITY_IAM if your
* stack template contains AWS Identity and Access Management (IAM) resources. For more
* information, see [Acknowledging IAM Resources in AWS CloudFormation Templates](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-iam-template.html#using-iam-capabilities).
*
* @default No capabitilities passed, unless `fullPermissions` is true
*/
capabilities?: cfn.CloudFormationCapabilities[];

/**
* Whether to grant full permissions to CloudFormation while deploying this template.
*
* Setting this to `true` affects the defaults for `role` and `capabilities`, if you
* don't specify any alternatives.
*
* The default role that will be created for you will have full (i.e., `*`)
* permissions on all resources, and the deployment will have named IAM
* capabilities (i.e., able to create all IAM resources).
*
* This is a shorthand that you can use if you fully trust the templates that
* are deployed in this pipeline. If you want more fine-grained permissions,
* use `addToRolePolicy` and `capabilities` to control what the CloudFormation
* deployment is allowed to do.
*
* @default false
*/
fullPermissions?: boolean;
}

/**
Expand All @@ -52,6 +94,12 @@ export interface PipelineDeployStackActionProps {
* CodePipeline is hosted.
*/
export class PipelineDeployStackAction extends cdk.Construct {

/**
* The role used by CloudFormation for the deploy action
*/
public readonly role: iam.Role;

private readonly stack: cdk.Stack;

constructor(parent: cdk.Construct, id: string, props: PipelineDeployStackActionProps) {
Expand All @@ -69,16 +117,21 @@ export class PipelineDeployStackAction extends cdk.Construct {
throw new Error(`createChangeSetRunOrder (${createChangeSetRunOrder}) must be < executeChangeSetRunOrder (${executeChangeSetRunOrder})`);
}

this.stack = props.stack;
const changeSetName = props.changeSetName || 'CDK-CodePipeline-ChangeSet';

new cfn.PipelineCreateReplaceChangeSetAction(this, 'ChangeSet', {
this.stack = props.stack;

const changeSetAction = new cfn.PipelineCreateReplaceChangeSetAction(this, 'ChangeSet', {
changeSetName,
runOrder: createChangeSetRunOrder,
stackName: props.stack.name,
stage: props.stage,
templatePath: props.inputArtifact.atPath(`${props.stack.name}.template.yaml`),
fullPermissions: props.fullPermissions,
role: props.role,
capabilities: props.capabilities,
});
this.role = changeSetAction.role;

new cfn.PipelineExecuteChangeSetAction(this, 'Execute', {
changeSetName,
Expand Down
24 changes: 23 additions & 1 deletion packages/@aws-cdk/app-delivery/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@
"integ": "cdk-integ"
},
"dependencies": {
"@aws-cdk/aws-cloudformation": "^0.17.0",
"@aws-cdk/aws-codebuild": "^0.17.0",
"@aws-cdk/aws-codepipeline-api": "^0.17.0",
"@aws-cdk/cdk": "^0.17.0",
"@aws-cdk/cx-api": "^0.17.0",
"@aws-cdk/aws-cloudformation": "^0.17.0",
"@aws-cdk/aws-codebuild": "^0.17.0",
"@aws-cdk/aws-codepipeline-api": "^0.17.0",
Expand All @@ -46,6 +51,21 @@
"fast-check": "^1.7.0",
"pkglint": "^0.17.0"
},
"repository": {
},
"devDependencies": {
"@aws-cdk/aws-codepipeline": "^0.17.0",
"@aws-cdk/aws-s3": "^0.17.0",
"cdk-build-tools": "^0.17.0",
"cdk-integ-tools": "^0.17.0",
"@aws-cdk/aws-codepipeline": "^0.17.0",
"@aws-cdk/assert": "^0.17.0",
"@aws-cdk/aws-s3": "^0.17.0",
"cdk-build-tools": "^0.17.0",
"cdk-integ-tools": "^0.17.0",
"fast-check": "^1.7.0",
"pkglint": "^0.17.0"
},
"repository": {
"type": "git",
"url": "https://github.com/awslabs/aws-cdk.git"
Expand All @@ -63,6 +83,8 @@
],
"peerDependencies": {
"@aws-cdk/aws-codepipeline-api": "^0.17.0",
"@aws-cdk/aws-iam": "^0.17.0",
"@aws-cdk/aws-cloudformation": "^0.17.0",
"@aws-cdk/cdk": "^0.17.0"
}
}
}
Loading

0 comments on commit 0d1fdb9

Please sign in to comment.