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

feat(codepipeline): cross-environment (account+region) actions #3694

Merged
Merged
Show file tree
Hide file tree
Changes from all 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
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,20 @@
"DeletionPolicy": "Retain",
"UpdateReplacePolicy": "Retain"
},
"PipelineArtifactsBucketEncryptionKeyAlias5C510EEE": {
"Type": "AWS::KMS::Alias",
"Properties": {
"AliasName": "alias/codepipeline-awscdkcodepipelinecloudformationpipeline7dbde619",
"TargetKeyId": {
"Fn::GetAtt": [
"PipelineArtifactsBucketEncryptionKey01D58D69",
"Arn"
]
}
},
"DeletionPolicy": "Retain",
"UpdateReplacePolicy": "Retain"
},
"PipelineRoleD68726F7": {
"Type": "AWS::IAM::Role",
"Properties": {
Expand Down Expand Up @@ -379,10 +393,7 @@
"ArtifactStore": {
"EncryptionKey": {
"Id": {
"Fn::GetAtt": [
"PipelineArtifactsBucketEncryptionKey01D58D69",
"Arn"
]
"Ref": "PipelineArtifactsBucketEncryptionKey01D58D69"
},
"Type": "KMS"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,20 @@
"DeletionPolicy": "Retain",
"UpdateReplacePolicy": "Retain"
},
"PipelineArtifactsBucketEncryptionKeyAlias5C510EEE": {
"Type": "AWS::KMS::Alias",
"Properties": {
"AliasName": "alias/codepipeline-pipelinestackpipeline9db740af",
"TargetKeyId": {
"Fn::GetAtt": [
"PipelineArtifactsBucketEncryptionKey01D58D69",
"Arn"
]
}
},
"DeletionPolicy": "Retain",
"UpdateReplacePolicy": "Retain"
},
"PipelineRoleD68726F7": {
"Type": "AWS::IAM::Role",
"Properties": {
Expand Down Expand Up @@ -504,10 +518,7 @@
"ArtifactStore": {
"EncryptionKey": {
"Id": {
"Fn::GetAtt": [
"PipelineArtifactsBucketEncryptionKey01D58D69",
"Arn"
]
"Ref": "PipelineArtifactsBucketEncryptionKey01D58D69"
},
"Type": "KMS"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,20 @@
"DeletionPolicy": "Retain",
"UpdateReplacePolicy": "Retain"
},
"PipelineArtifactsBucketEncryptionKeyAlias5C510EEE": {
"Type": "AWS::KMS::Alias",
"Properties": {
"AliasName": "alias/codepipeline-awscdkcodepipelinelambdapipeline87a4b3d3",
"TargetKeyId": {
"Fn::GetAtt": [
"PipelineArtifactsBucketEncryptionKey01D58D69",
"Arn"
]
}
},
"DeletionPolicy": "Retain",
"UpdateReplacePolicy": "Retain"
},
"PipelineRoleD68726F7": {
"Type": "AWS::IAM::Role",
"Properties": {
Expand Down Expand Up @@ -282,10 +296,7 @@
"ArtifactStore": {
"EncryptionKey": {
"Id": {
"Fn::GetAtt": [
"PipelineArtifactsBucketEncryptionKey01D58D69",
"Arn"
]
"Ref": "PipelineArtifactsBucketEncryptionKey01D58D69"
},
"Type": "KMS"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,20 @@
"DeletionPolicy": "Retain",
"UpdateReplacePolicy": "Retain"
},
"PipelineArtifactsBucketEncryptionKeyAlias5C510EEE": {
"Type": "AWS::KMS::Alias",
"Properties": {
"AliasName": "alias/codepipeline-awscdkcodepipelinealexadeploypipeline961107f5",
"TargetKeyId": {
"Fn::GetAtt": [
"PipelineArtifactsBucketEncryptionKey01D58D69",
"Arn"
]
}
},
"DeletionPolicy": "Retain",
"UpdateReplacePolicy": "Retain"
},
"PipelineRoleD68726F7": {
"Type": "AWS::IAM::Role",
"Properties": {
Expand Down Expand Up @@ -281,10 +295,7 @@
"ArtifactStore": {
"EncryptionKey": {
"Id": {
"Fn::GetAtt": [
"PipelineArtifactsBucketEncryptionKey01D58D69",
"Arn"
]
"Ref": "PipelineArtifactsBucketEncryptionKey01D58D69"
},
"Type": "KMS"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,20 @@
"DeletionPolicy": "Retain",
"UpdateReplacePolicy": "Retain"
},
"PipelineArtifactsBucketEncryptionKeyAlias5C510EEE": {
"Type": "AWS::KMS::Alias",
"Properties": {
"AliasName": "alias/codepipeline-awscdkcodepipelinecloudformationpipeline7dbde619",
"TargetKeyId": {
"Fn::GetAtt": [
"PipelineArtifactsBucketEncryptionKey01D58D69",
"Arn"
]
}
},
"DeletionPolicy": "Retain",
"UpdateReplacePolicy": "Retain"
},
"PipelineRoleD68726F7": {
"Type": "AWS::IAM::Role",
"Properties": {
Expand Down Expand Up @@ -367,10 +381,7 @@
"ArtifactStore": {
"EncryptionKey": {
"Id": {
"Fn::GetAtt": [
"PipelineArtifactsBucketEncryptionKey01D58D69",
"Arn"
]
"Ref": "PipelineArtifactsBucketEncryptionKey01D58D69"
},
"Type": "KMS"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,20 @@
"DeletionPolicy": "Retain",
"UpdateReplacePolicy": "Retain"
},
"PipelineArtifactsBucketEncryptionKeyAlias5C510EEE": {
"Type": "AWS::KMS::Alias",
"Properties": {
"AliasName": "alias/codepipeline-awscdkcodepipelinecodecommitcodebuildpipeline9540e1f5",
"TargetKeyId": {
"Fn::GetAtt": [
"PipelineArtifactsBucketEncryptionKey01D58D69",
"Arn"
]
}
},
"UpdateReplacePolicy": "Retain",
"DeletionPolicy": "Retain"
},
"PipelineRoleD68726F7": {
"Type": "AWS::IAM::Role",
"Properties": {
Expand Down Expand Up @@ -579,10 +593,7 @@
"ArtifactStore": {
"EncryptionKey": {
"Id": {
"Fn::GetAtt": [
"PipelineArtifactsBucketEncryptionKey01D58D69",
"Arn"
]
"Ref": "PipelineArtifactsBucketEncryptionKey01D58D69"
},
"Type": "KMS"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,20 @@
"DeletionPolicy": "Retain",
"UpdateReplacePolicy": "Retain"
},
"PipelineArtifactsBucketEncryptionKeyAlias5C510EEE": {
"Type": "AWS::KMS::Alias",
"Properties": {
"AliasName": "alias/codepipeline-awscdkcodepipelinecodecommitpipelinef780ca18",
"TargetKeyId": {
"Fn::GetAtt": [
"PipelineArtifactsBucketEncryptionKey01D58D69",
"Arn"
]
}
},
"DeletionPolicy": "Retain",
"UpdateReplacePolicy": "Retain"
},
"PipelineRoleD68726F7": {
"Type": "AWS::IAM::Role",
"Properties": {
Expand Down Expand Up @@ -353,10 +367,7 @@
"ArtifactStore": {
"EncryptionKey": {
"Id": {
"Fn::GetAtt": [
"PipelineArtifactsBucketEncryptionKey01D58D69",
"Arn"
]
"Ref": "PipelineArtifactsBucketEncryptionKey01D58D69"
},
"Type": "KMS"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,20 @@
"DeletionPolicy": "Retain",
"UpdateReplacePolicy": "Retain"
},
"MyPipelineArtifactsBucketEncryptionKeyAlias9D4F8C59": {
"Type": "AWS::KMS::Alias",
"Properties": {
"AliasName": "alias/codepipeline-awscdkpipelineeventtargetmypipeline4ae5d407",
"TargetKeyId": {
"Fn::GetAtt": [
"MyPipelineArtifactsBucketEncryptionKey8BF0A7F3",
"Arn"
]
}
},
"DeletionPolicy": "Retain",
"UpdateReplacePolicy": "Retain"
},
"MyPipelineRoleC0D47CA4": {
"Type": "AWS::IAM::Role",
"Properties": {
Expand Down Expand Up @@ -316,10 +330,7 @@
"ArtifactStore": {
"EncryptionKey": {
"Id": {
"Fn::GetAtt": [
"MyPipelineArtifactsBucketEncryptionKey8BF0A7F3",
"Arn"
]
"Ref": "MyPipelineArtifactsBucketEncryptionKey8BF0A7F3"
},
"Type": "KMS"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,20 @@
"DeletionPolicy": "Retain",
"UpdateReplacePolicy": "Retain"
},
"PipelineArtifactsBucketEncryptionKeyAlias5C510EEE": {
"Type": "AWS::KMS::Alias",
"Properties": {
"AliasName": "alias/codepipeline-awscdkcodepipelines3deploypipeline907bf1e7",
"TargetKeyId": {
"Fn::GetAtt": [
"PipelineArtifactsBucketEncryptionKey01D58D69",
"Arn"
]
}
},
"DeletionPolicy": "Retain",
"UpdateReplacePolicy": "Retain"
},
"PipelineRoleD68726F7": {
"Type": "AWS::IAM::Role",
"Properties": {
Expand Down Expand Up @@ -318,10 +332,7 @@
"ArtifactStore": {
"EncryptionKey": {
"Id": {
"Fn::GetAtt": [
"PipelineArtifactsBucketEncryptionKey01D58D69",
"Arn"
]
"Ref": "PipelineArtifactsBucketEncryptionKey01D58D69"
},
"Type": "KMS"
},
Expand Down
58 changes: 55 additions & 3 deletions packages/@aws-cdk/aws-codepipeline/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,13 +88,18 @@ into a different region than your Pipeline is in.

It works like this:

```ts
```typescript
const pipeline = new codepipeline.Pipeline(this, 'MyFirstPipeline', {
// ...
crossRegionReplicationBuckets: {
// note that a physical name of the replication Bucket must be known at synthesis time
'us-west-1': s3.Bucket.fromBucketName(this, 'UsWest1ReplicationBucket',
'my-us-west-1-replication-bucket'),
'us-west-1': s3.Bucket.fromBucketAttributes(this, 'UsWest1ReplicationBucket', {
bucketName: 'my-us-west-1-replication-bucket',
// optional KMS key
encryptionKey: kms.Key.fromKeyArn(this, 'UsWest1ReplicationKey',
'arn:aws:kms:us-west-1:123456789012:key/1234-5678-9012'
),
}),
},
});

Expand Down Expand Up @@ -128,6 +133,53 @@ $ cdk deploy MyMainStack
See [the AWS docs here](https://docs.aws.amazon.com/codepipeline/latest/userguide/actions-create-cross-region.html)
for more information on cross-region CodePipelines.

#### Creating an encrypted replication bucket

If you're passing a replication bucket created in a different stack,
Copy link
Contributor

Choose a reason for hiding this comment

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

This documentation is weird. Should mostly describe how to do things and not what doesn't work...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I just wanted to point out a potential "gotcha!" that might trip people up.

If you have a suggestion how to re-structure this documentation, I'm all ears.

like this:

```typescript
const replicationStack = new Stack(app, 'ReplicationStack', {
env: {
region: 'us-west-1',
},
});
const key = new kms.Key(replicationStack, 'ReplicationKey');
const replicationBucket = new s3.Bucket(replicationStack, 'ReplicationBucket', {
// like was said above - replication buckets need a set physical name
bucketName: PhysicalName.GENERATE_IF_NEEDED,
encryptionKey: key, // does not work!
Copy link
Contributor

Choose a reason for hiding this comment

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

what "does not work!" mean?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You'll get a "Can only reference cross stacks in the same region and account." error.

Copy link
Contributor

Choose a reason for hiding this comment

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

Please follow up with @jerry-aws in a separate PR and revisit this doc. I think he will be able to help.

});

// later...
new codepipeline.Pipeline(pipelineStack, 'Pipeline', {
crossRegionReplicationBuckets: {
'us-west-1': replicationBucket,
},
});
```

When trying to encrypt it
(and note that if any of the cross-region actions happen to be cross-account as well,
the bucket *has to* be encrypted - otherwise the pipeline will fail at runtime),
you cannot use a key directly - KMS keys don't have physical names,
and so you can't reference them across environments.

In this case, you need to use an alias in place of the key when creating the bucket:

```typescript
const key = new kms.Key(replicationStack, 'ReplicationKey');
const alias = new kms.Alias(replicationStack, 'ReplicationAlias', {
// aliasName is required
aliasName: PhysicalName.GENERATE_IF_NEEDED,
targetKey: key,
});
const replicationBucket = new s3.Bucket(replicationStack, 'ReplicationBucket', {
bucketName: PhysicalName.GENERATE_IF_NEEDED,
encryptionKey: alias,
});
```

### Events

#### Using a pipeline as an event target
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import kms = require('@aws-cdk/aws-kms');
import s3 = require('@aws-cdk/aws-s3');
import cdk = require('@aws-cdk/core');

Expand Down Expand Up @@ -44,8 +45,15 @@ export class CrossRegionSupportStack extends cdk.Stack {
},
});

const encryptionKey = new kms.Key(this, 'CrossRegionCodePipelineReplicationBucketEncryptionKey');
const encryptionAlias = new kms.Alias(this, 'CrossRegionCodePipelineReplicationBucketEncryptionAlias', {
targetKey: encryptionKey,
aliasName: cdk.PhysicalName.GENERATE_IF_NEEDED,
removalPolicy: cdk.RemovalPolicy.RETAIN,
});
this.replicationBucket = new s3.Bucket(this, 'CrossRegionCodePipelineReplicationBucket', {
bucketName: cdk.PhysicalName.GENERATE_IF_NEEDED,
encryptionKey: encryptionAlias,
});
}
}
Expand Down
Loading