Skip to content

Commit c5a77ac

Browse files
authored
Merge branch 'master' into nija-at/exppkgs-assertions
2 parents 14dc0ba + d77e9dc commit c5a77ac

9 files changed

Lines changed: 132 additions & 18 deletions

File tree

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,8 @@
9393
"@aws-cdk/aws-eks/yaml/**",
9494
"@aws-cdk/aws-events-targets/aws-sdk",
9595
"@aws-cdk/aws-events-targets/aws-sdk/**",
96+
"@aws-cdk/aws-s3-deployment/case",
97+
"@aws-cdk/aws-s3-deployment/case/**",
9698
"@aws-cdk/cloud-assembly-schema/jsonschema",
9799
"@aws-cdk/cloud-assembly-schema/jsonschema/**",
98100
"@aws-cdk/cloud-assembly-schema/semver",

packages/@aws-cdk/aws-chatbot/lib/slack-channel-configuration.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -204,9 +204,9 @@ export class SlackChannelConfiguration extends SlackChannelConfigurationBase {
204204
*/
205205
public static fromSlackChannelConfigurationArn(scope: Construct, id: string, slackChannelConfigurationArn: string): ISlackChannelConfiguration {
206206
const re = /^slack-channel\//;
207-
const resourceName = cdk.Stack.of(scope).parseArn(slackChannelConfigurationArn).resourceName as string;
207+
const resourceName = cdk.Arn.extractResourceName(slackChannelConfigurationArn, 'chat-configuration');
208208

209-
if (!re.test(resourceName)) {
209+
if (!cdk.Token.isUnresolved(slackChannelConfigurationArn) && !re.test(resourceName)) {
210210
throw new Error('The ARN of a Slack integration must be in the form: arn:aws:chatbot:{region}:{account}:chat-configuration/slack-channel/{slackChannelName}');
211211
}
212212

@@ -227,11 +227,19 @@ export class SlackChannelConfiguration extends SlackChannelConfigurationBase {
227227
* The ArnComponents API will return `slack-channel/my-slack`
228228
* It need to handle that to gets a correct name.`my-slack`
229229
*/
230-
readonly slackChannelConfigurationName = resourceName.substring('slack-channel/'.length);
230+
readonly slackChannelConfigurationName: string;
231231

232232
constructor(s: Construct, i: string) {
233233
super(s, i);
234234
this.grantPrincipal = new iam.UnknownPrincipal({ resource: this });
235+
236+
// handle slackChannelConfigurationName as specified above
237+
if (cdk.Token.isUnresolved(slackChannelConfigurationArn)) {
238+
this.slackChannelConfigurationName = cdk.Fn.select(1, cdk.Fn.split('slack-channel/', resourceName));
239+
} else {
240+
this.slackChannelConfigurationName = resourceName.substring('slack-channel/'.length);
241+
}
242+
235243
}
236244
}
237245

packages/@aws-cdk/aws-chatbot/test/slack-channel-configuration.test.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,4 +245,22 @@ describe('SlackChannelConfiguration', () => {
245245
expect(imported.slackChannelConfigurationName).toEqual('my-slack');
246246
expect(imported.slackChannelConfigurationArn).toEqual('arn:aws:chatbot::1234567890:chat-configuration/slack-channel/my-slack');
247247
});
248+
249+
test('skip validation for tokenized values', () => {
250+
// invalid ARN because of underscores, no error because tokenized value
251+
expect(() => chatbot.SlackChannelConfiguration.fromSlackChannelConfigurationArn(stack, 'MySlackChannel',
252+
cdk.Lazy.string({ produce: () => 'arn:aws:chatbot::1234567890:chat-configuration/slack_channel/my_slack' }))).not.toThrow();
253+
});
254+
255+
test('test name and ARN from slack channel configuration ARN', () => {
256+
const imported = chatbot.SlackChannelConfiguration.fromSlackChannelConfigurationArn(stack, 'MySlackChannel', cdk.Token.asString({ Ref: 'ARN' }));
257+
258+
// THEN
259+
expect(stack.resolve(imported.slackChannelConfigurationName)).toStrictEqual({
260+
'Fn::Select': [1, { 'Fn::Split': ['slack-channel/', { 'Fn::Select': [1, { 'Fn::Split': [':chat-configuration/', { Ref: 'ARN' }] }] }] }],
261+
});
262+
expect(stack.resolve(imported.slackChannelConfigurationArn)).toStrictEqual({
263+
Ref: 'ARN',
264+
});
265+
});
248266
});

packages/@aws-cdk/aws-lambda/lib/lambda-insights.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { Aws, CfnMapping, Fn, IResolveContext, Lazy, Stack, Token } from '@aws-cdk/core';
22
import { FactName, RegionInfo } from '@aws-cdk/region-info';
3-
import { CLOUDWATCH_LAMBDA_INSIGHTS_ARNS } from '@aws-cdk/region-info/build-tools/fact-tables';
43

54
// This is the name of the mapping that will be added to the CloudFormation template, if a stack is region agnostic
65
const DEFAULT_MAPPING_PREFIX = 'LambdaInsightsVersions';
@@ -49,8 +48,9 @@ export abstract class LambdaInsightsVersion {
4948
private static fromInsightsVersion(insightsVersion: string): LambdaInsightsVersion {
5049

5150
// Check if insights version is valid. This should only happen if one of the public static readonly versions are set incorrectly
52-
if (!(insightsVersion in CLOUDWATCH_LAMBDA_INSIGHTS_ARNS)) {
53-
throw new Error(`Insights version ${insightsVersion} does not exist. Available versions are ${CLOUDWATCH_LAMBDA_INSIGHTS_ARNS.keys()}`);
51+
const versionExists = RegionInfo.regions.some(regionInfo => regionInfo.cloudwatchLambdaInsightsArn(insightsVersion));
52+
if (!versionExists) {
53+
throw new Error(`Insights version ${insightsVersion} does not exist.`);
5454
}
5555

5656
class InsightsVersion extends LambdaInsightsVersion {
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,32 @@
11
AWS Cloud Development Kit (AWS CDK)
22
Copyright 2018-2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
4+
-------------------------------------------------------------------------------
5+
6+
The AWS CDK includes the following third-party software/licensing:
7+
8+
** case - https://www.npmjs.com/package/case
9+
Copyright (c) 2013 Nathan Bubna
10+
11+
Permission is hereby granted, free of charge, to any person
12+
obtaining a copy of this software and associated documentation
13+
files (the "Software"), to deal in the Software without
14+
restriction, including without limitation the rights to use,
15+
copy, modify, merge, publish, distribute, sublicense, and/or sell
16+
copies of the Software, and to permit persons to whom the
17+
Software is furnished to do so, subject to the following
18+
conditions:
19+
20+
The above copyright notice and this permission notice shall be
21+
included in all copies or substantial portions of the Software.
22+
23+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
25+
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
27+
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
28+
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
29+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
30+
OTHER DEALINGS IN THE SOFTWARE.
31+
32+
----------------

packages/@aws-cdk/aws-s3-deployment/README.md

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -147,17 +147,22 @@ User-defined metadata are not used by S3 and keys always begin with `x-amz-meta-
147147

148148
System defined metadata keys include the following:
149149

150-
- cache-control
151-
- content-disposition
152-
- content-encoding
153-
- content-language
154-
- content-type
155-
- expires
156-
- server-side-encryption
157-
- storage-class
158-
- website-redirect-location
159-
- ssekms-key-id
160-
- sse-customer-algorithm
150+
- cache-control (`--cache-control` in `aws s3 sync`)
151+
- content-disposition (`--content-disposition` in `aws s3 sync`)
152+
- content-encoding (`--content-encoding` in `aws s3 sync`)
153+
- content-language (`--content-language` in `aws s3 sync`)
154+
- content-type (`--content-type` in `aws s3 sync`)
155+
- expires (`--expires` in `aws s3 sync`)
156+
- x-amz-storage-class (`--storage-class` in `aws s3 sync`)
157+
- x-amz-website-redirect-location (`--website-redirect` in `aws s3 sync`)
158+
- x-amz-server-side-encryption (`--sse` in `aws s3 sync`)
159+
- x-amz-server-side-encryption-aws-kms-key-id (`--sse-kms-key-id` in `aws s3 sync`)
160+
- x-amz-server-side-encryption-customer-algorithm (`--sse-c-copy-source` in `aws s3 sync`)
161+
- x-amz-acl (`--acl` in `aws s3 sync`)
162+
163+
You can find more information about system defined metadata keys in
164+
[S3 PutObject documentation](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html)
165+
and [`aws s3 sync` documentation](https://docs.aws.amazon.com/cli/latest/reference/s3/sync.html).
161166

162167
```ts
163168
const websiteBucket = new s3.Bucket(this, 'WebsiteBucket', {
@@ -177,6 +182,7 @@ new s3deploy.BucketDeployment(this, 'DeployWebsite', {
177182
storageClass: StorageClass.INTELLIGENT_TIERING,
178183
serverSideEncryption: ServerSideEncryption.AES_256,
179184
cacheControl: [CacheControl.setPublic(), CacheControl.maxAge(cdk.Duration.hours(1))],
185+
accessControl: s3.BucketAccessControl.BUCKET_OWNER_FULL_CONTROL,
180186
});
181187
```
182188

@@ -230,7 +236,7 @@ size of the AWS Lambda resource handler.
230236
## Development
231237

232238
The custom resource is implemented in Python 3.6 in order to be able to leverage
233-
the AWS CLI for "aws sync". The code is under [`lib/lambda`](https://github.com/aws/aws-cdk/tree/master/packages/%40aws-cdk/aws-s3-deployment/lib/lambda) and
239+
the AWS CLI for "aws s3 sync". The code is under [`lib/lambda`](https://github.com/aws/aws-cdk/tree/master/packages/%40aws-cdk/aws-s3-deployment/lib/lambda) and
234240
unit tests are under [`test/lambda`](https://github.com/aws/aws-cdk/tree/master/packages/%40aws-cdk/aws-s3-deployment/test/lambda).
235241

236242
This package requires Python 3.6 during build time in order to create the custom

packages/@aws-cdk/aws-s3-deployment/lib/bucket-deployment.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import * as lambda from '@aws-cdk/aws-lambda';
66
import * as s3 from '@aws-cdk/aws-s3';
77
import * as cdk from '@aws-cdk/core';
88
import { AwsCliLayer } from '@aws-cdk/lambda-layer-awscli';
9+
import { kebab as toKebabCase } from 'case';
910
import { Construct } from 'constructs';
1011
import { ISource, SourceConfig } from './source';
1112

@@ -164,6 +165,12 @@ export interface BucketDeploymentProps {
164165
* @see https://docs.aws.amazon.com/AmazonS3/latest/dev/ServerSideEncryptionCustomerKeys.html#sse-c-how-to-programmatically-intro
165166
*/
166167
readonly serverSideEncryptionCustomerAlgorithm?: string;
168+
/**
169+
* System-defined x-amz-acl metadata to be set on all objects in the deployment.
170+
* @default - Not set.
171+
* @see https://docs.aws.amazon.com/AmazonS3/latest/userguide/acl-overview.html#canned-acl
172+
*/
173+
readonly accessControl?: s3.BucketAccessControl;
167174

168175
/**
169176
* The VPC network to place the deployment lambda handler in.
@@ -282,6 +289,7 @@ function mapSystemMetadata(metadata: BucketDeploymentProps) {
282289
if (metadata.websiteRedirectLocation) { res['website-redirect'] = metadata.websiteRedirectLocation; }
283290
if (metadata.serverSideEncryptionAwsKmsKeyId) { res['sse-kms-key-id'] = metadata.serverSideEncryptionAwsKmsKeyId; }
284291
if (metadata.serverSideEncryptionCustomerAlgorithm) { res['sse-c-copy-source'] = metadata.serverSideEncryptionCustomerAlgorithm; }
292+
if (metadata.accessControl) { res.acl = toKebabCase(metadata.accessControl.toString()); }
285293

286294
return Object.keys(res).length === 0 ? undefined : res;
287295
}

packages/@aws-cdk/aws-s3-deployment/package.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@
9696
"@aws-cdk/aws-s3-assets": "0.0.0",
9797
"@aws-cdk/lambda-layer-awscli": "0.0.0",
9898
"@aws-cdk/core": "0.0.0",
99+
"case": "1.6.3",
99100
"constructs": "^3.3.69"
100101
},
101102
"homepage": "https://github.com/aws/aws-cdk",
@@ -110,6 +111,9 @@
110111
"@aws-cdk/core": "0.0.0",
111112
"constructs": "^3.3.69"
112113
},
114+
"bundledDependencies": [
115+
"case"
116+
],
113117
"engines": {
114118
"node": ">= 10.13.0 <13 || >=13.7.0"
115119
},

packages/@aws-cdk/aws-s3-deployment/test/bucket-deployment.test.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,7 @@ test('system metadata is correctly transformed', () => {
325325
websiteRedirectLocation: 'example',
326326
cacheControl: [s3deploy.CacheControl.setPublic(), s3deploy.CacheControl.maxAge(cdk.Duration.hours(1))],
327327
expires: expiration,
328+
accessControl: s3.BucketAccessControl.BUCKET_OWNER_FULL_CONTROL,
328329
});
329330

330331
// THEN
@@ -340,10 +341,47 @@ test('system metadata is correctly transformed', () => {
340341
'expires': expiration.date.toUTCString(),
341342
'sse-c-copy-source': 'rot13',
342343
'website-redirect': 'example',
344+
'acl': 'bucket-owner-full-control',
343345
},
344346
});
345347
});
346348

349+
// type checking structure that forces to update it if BucketAccessControl changes
350+
// see `--acl` here: https://docs.aws.amazon.com/cli/latest/reference/s3/sync.html
351+
const accessControlMap: Record<s3.BucketAccessControl, string> = {
352+
[s3.BucketAccessControl.PRIVATE]: 'private',
353+
[s3.BucketAccessControl.PUBLIC_READ]: 'public-read',
354+
[s3.BucketAccessControl.PUBLIC_READ_WRITE]: 'public-read-write',
355+
[s3.BucketAccessControl.AUTHENTICATED_READ]: 'authenticated-read',
356+
[s3.BucketAccessControl.AWS_EXEC_READ]: 'aws-exec-read',
357+
[s3.BucketAccessControl.BUCKET_OWNER_READ]: 'bucket-owner-read',
358+
[s3.BucketAccessControl.BUCKET_OWNER_FULL_CONTROL]: 'bucket-owner-full-control',
359+
[s3.BucketAccessControl.LOG_DELIVERY_WRITE]: 'log-delivery-write',
360+
};
361+
362+
test.each(Object.entries(accessControlMap) as [s3.BucketAccessControl, string][])(
363+
'system metadata acl %s is correctly transformed',
364+
(accessControl, systemMetadataKeyword) => {
365+
// GIVEN
366+
const stack = new cdk.Stack();
367+
const bucket = new s3.Bucket(stack, 'Dest');
368+
369+
// WHEN
370+
new s3deploy.BucketDeployment(stack, 'Deploy', {
371+
sources: [s3deploy.Source.asset(path.join(__dirname, 'my-website.zip'))],
372+
destinationBucket: bucket,
373+
accessControl: accessControl,
374+
});
375+
376+
// THEN
377+
expect(stack).toHaveResource('Custom::CDKBucketDeployment', {
378+
SystemMetadata: {
379+
acl: systemMetadataKeyword,
380+
},
381+
});
382+
},
383+
);
384+
347385
test('expires type has correct values', () => {
348386
expect(cdk.Expiration.atDate(new Date('Sun, 26 Jan 2020 00:53:20 GMT')).date.toUTCString()).toEqual('Sun, 26 Jan 2020 00:53:20 GMT');
349387
expect(cdk.Expiration.atTimestamp(1580000000000).date.toUTCString()).toEqual('Sun, 26 Jan 2020 00:53:20 GMT');

0 commit comments

Comments
 (0)