Skip to content

Commit

Permalink
Merge branch 'master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
mergify[bot] authored Nov 30, 2020
2 parents 5c53786 + c072981 commit e57eabc
Show file tree
Hide file tree
Showing 23 changed files with 833 additions and 54 deletions.
2 changes: 1 addition & 1 deletion packages/@aws-cdk/aws-cognito/lib/user-pool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export interface SignInAliases {
readonly phone?: boolean;

/**
* Whether a user is allowed to ign in with a secondary username, that can be set and modified after sign up.
* Whether a user is allowed to sign in with a secondary username, that can be set and modified after sign up.
* Can only be used in conjunction with `USERNAME`.
* @default false
*/
Expand Down
16 changes: 16 additions & 0 deletions packages/@aws-cdk/aws-ecr/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,22 @@ repository.onImageScanCompleted('ImageScanComplete')
.addTarget(...)
```

### Authorization Token

Besides the Amazon ECR APIs, ECR also allows the Docker CLI or a language-specific Docker library to push and pull
images from an ECR repository. However, the Docker CLI does not support native IAM authentication methods and
additional steps must be taken so that Amazon ECR can authenticate and authorize Docker push and pull requests.
More information can be found at at [Registry Authentication](https://docs.aws.amazon.com/AmazonECR/latest/userguide/Registries.html#registry_auth).

A Docker authorization token can be obtained using the `GetAuthorizationToken` ECR API. The following code snippets
grants an IAM user access to call this API.

```ts
import * as iam from '@aws-cdk/aws-iam';

const user = new iam.User(this, 'User', { ... });
AuthorizationToken.grantRead(user);
```

### Automatically clean up repositories

Expand Down
20 changes: 20 additions & 0 deletions packages/@aws-cdk/aws-ecr/lib/auth-token.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import * as iam from '@aws-cdk/aws-iam';

/**
* Authorization token to access ECR repositories via Docker CLI.
*/
export class AuthorizationToken {
/**
* Grant access to retrieve an authorization token.
*/
public static grantRead(grantee: iam.IGrantable) {
grantee.grantPrincipal.addToPrincipalPolicy(new iam.PolicyStatement({
actions: ['ecr:GetAuthorizationToken'],
// GetAuthorizationToken only allows '*'. See https://docs.aws.amazon.com/service-authorization/latest/reference/list_amazonelasticcontainerregistry.html#amazonelasticcontainerregistry-actions-as-permissions
resources: ['*'],
}));
}

private constructor() {
}
}
1 change: 1 addition & 0 deletions packages/@aws-cdk/aws-ecr/lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ export * from './ecr.generated';

export * from './repository';
export * from './lifecycle';
export * from './auth-token';
31 changes: 31 additions & 0 deletions packages/@aws-cdk/aws-ecr/test/test.auth-token.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { expect, haveResourceLike } from '@aws-cdk/assert';
import * as iam from '@aws-cdk/aws-iam';
import { Stack } from '@aws-cdk/core';
import { Test } from 'nodeunit';
import { AuthorizationToken } from '../lib';

export = {
'grant()'(test: Test) {
// GIVEN
const stack = new Stack();
const user = new iam.User(stack, 'User');

// WHEN
AuthorizationToken.grantRead(user);

// THEN
expect(stack).to(haveResourceLike('AWS::IAM::Policy', {
PolicyDocument: {
Statement: [
{
Action: 'ecr:GetAuthorizationToken',
Effect: 'Allow',
Resource: '*',
},
],
},
}));

test.done();
},
};
2 changes: 1 addition & 1 deletion packages/@aws-cdk/aws-lambda-nodejs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@
"cdk-build-tools": "0.0.0",
"cdk-integ-tools": "0.0.0",
"delay": "4.4.0",
"esbuild": "^0.8.9",
"esbuild": "^0.8.17",
"pkglint": "0.0.0"
},
"dependencies": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
"Properties": {
"Code": {
"S3Bucket": {
"Ref": "AssetParametersa366acc095e9c09f74bf0dd7cd338214dc3b201ad849c56e33912eb3c85785e1S3Bucket70E87BF4"
"Ref": "AssetParameters2ff0fab1efcce787182abdd9a3c77a111379358a40cb16d90d7eb7c71ed11835S3BucketF29906B2"
},
"S3Key": {
"Fn::Join": [
Expand All @@ -49,7 +49,7 @@
"Fn::Split": [
"||",
{
"Ref": "AssetParametersa366acc095e9c09f74bf0dd7cd338214dc3b201ad849c56e33912eb3c85785e1S3VersionKey888B2605"
"Ref": "AssetParameters2ff0fab1efcce787182abdd9a3c77a111379358a40cb16d90d7eb7c71ed11835S3VersionKey320A7F12"
}
]
}
Expand All @@ -62,7 +62,7 @@
"Fn::Split": [
"||",
{
"Ref": "AssetParametersa366acc095e9c09f74bf0dd7cd338214dc3b201ad849c56e33912eb3c85785e1S3VersionKey888B2605"
"Ref": "AssetParameters2ff0fab1efcce787182abdd9a3c77a111379358a40cb16d90d7eb7c71ed11835S3VersionKey320A7F12"
}
]
}
Expand Down Expand Up @@ -92,17 +92,17 @@
}
},
"Parameters": {
"AssetParametersa366acc095e9c09f74bf0dd7cd338214dc3b201ad849c56e33912eb3c85785e1S3Bucket70E87BF4": {
"AssetParameters2ff0fab1efcce787182abdd9a3c77a111379358a40cb16d90d7eb7c71ed11835S3BucketF29906B2": {
"Type": "String",
"Description": "S3 bucket for asset \"a366acc095e9c09f74bf0dd7cd338214dc3b201ad849c56e33912eb3c85785e1\""
"Description": "S3 bucket for asset \"2ff0fab1efcce787182abdd9a3c77a111379358a40cb16d90d7eb7c71ed11835\""
},
"AssetParametersa366acc095e9c09f74bf0dd7cd338214dc3b201ad849c56e33912eb3c85785e1S3VersionKey888B2605": {
"AssetParameters2ff0fab1efcce787182abdd9a3c77a111379358a40cb16d90d7eb7c71ed11835S3VersionKey320A7F12": {
"Type": "String",
"Description": "S3 key for asset version \"a366acc095e9c09f74bf0dd7cd338214dc3b201ad849c56e33912eb3c85785e1\""
"Description": "S3 key for asset version \"2ff0fab1efcce787182abdd9a3c77a111379358a40cb16d90d7eb7c71ed11835\""
},
"AssetParametersa366acc095e9c09f74bf0dd7cd338214dc3b201ad849c56e33912eb3c85785e1ArtifactHash01A9D743": {
"AssetParameters2ff0fab1efcce787182abdd9a3c77a111379358a40cb16d90d7eb7c71ed11835ArtifactHash9E439F77": {
"Type": "String",
"Description": "Artifact hash for asset \"a366acc095e9c09f74bf0dd7cd338214dc3b201ad849c56e33912eb3c85785e1\""
"Description": "Artifact hash for asset \"2ff0fab1efcce787182abdd9a3c77a111379358a40cb16d90d7eb7c71ed11835\""
}
}
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/// !cdk-integ pragma:ignore-assets
import * as path from 'path';
import { Runtime } from '@aws-cdk/aws-lambda';
import { App, Stack, StackProps } from '@aws-cdk/core';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
"Properties": {
"Code": {
"S3Bucket": {
"Ref": "AssetParameters87629d6d123a6c9871926864abde04a406be93834dc008b18672bd287d37756eS3BucketDF2E98AE"
"Ref": "AssetParameters1f516d02fb984ea91e74064999e8508f09dd0001d2cf198ccc376d2c0fcd14dcS3Bucket499E594B"
},
"S3Key": {
"Fn::Join": [
Expand All @@ -49,7 +49,7 @@
"Fn::Split": [
"||",
{
"Ref": "AssetParameters87629d6d123a6c9871926864abde04a406be93834dc008b18672bd287d37756eS3VersionKey240B23FB"
"Ref": "AssetParameters1f516d02fb984ea91e74064999e8508f09dd0001d2cf198ccc376d2c0fcd14dcS3VersionKey0D51A516"
}
]
}
Expand All @@ -62,7 +62,7 @@
"Fn::Split": [
"||",
{
"Ref": "AssetParameters87629d6d123a6c9871926864abde04a406be93834dc008b18672bd287d37756eS3VersionKey240B23FB"
"Ref": "AssetParameters1f516d02fb984ea91e74064999e8508f09dd0001d2cf198ccc376d2c0fcd14dcS3VersionKey0D51A516"
}
]
}
Expand Down Expand Up @@ -835,17 +835,17 @@
}
},
"Parameters": {
"AssetParameters87629d6d123a6c9871926864abde04a406be93834dc008b18672bd287d37756eS3BucketDF2E98AE": {
"AssetParameters1f516d02fb984ea91e74064999e8508f09dd0001d2cf198ccc376d2c0fcd14dcS3Bucket499E594B": {
"Type": "String",
"Description": "S3 bucket for asset \"87629d6d123a6c9871926864abde04a406be93834dc008b18672bd287d37756e\""
"Description": "S3 bucket for asset \"1f516d02fb984ea91e74064999e8508f09dd0001d2cf198ccc376d2c0fcd14dc\""
},
"AssetParameters87629d6d123a6c9871926864abde04a406be93834dc008b18672bd287d37756eS3VersionKey240B23FB": {
"AssetParameters1f516d02fb984ea91e74064999e8508f09dd0001d2cf198ccc376d2c0fcd14dcS3VersionKey0D51A516": {
"Type": "String",
"Description": "S3 key for asset version \"87629d6d123a6c9871926864abde04a406be93834dc008b18672bd287d37756e\""
"Description": "S3 key for asset version \"1f516d02fb984ea91e74064999e8508f09dd0001d2cf198ccc376d2c0fcd14dc\""
},
"AssetParameters87629d6d123a6c9871926864abde04a406be93834dc008b18672bd287d37756eArtifactHashC957048B": {
"AssetParameters1f516d02fb984ea91e74064999e8508f09dd0001d2cf198ccc376d2c0fcd14dcArtifactHashECB545C0": {
"Type": "String",
"Description": "Artifact hash for asset \"87629d6d123a6c9871926864abde04a406be93834dc008b18672bd287d37756e\""
"Description": "Artifact hash for asset \"1f516d02fb984ea91e74064999e8508f09dd0001d2cf198ccc376d2c0fcd14dc\""
},
"AssetParameters565126ff75ab727f0b3a67e78cf0fa9996426d1458123e8d6ee81c7ea93a6cfaS3BucketDFAA619E": {
"Type": "String",
Expand Down
1 change: 1 addition & 0 deletions packages/@aws-cdk/aws-lambda-nodejs/test/integ.function.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/// !cdk-integ pragma:ignore-assets
import * as path from 'path';
import { Vpc } from '@aws-cdk/aws-ec2';
import { Runtime } from '@aws-cdk/aws-lambda';
Expand Down
46 changes: 43 additions & 3 deletions packages/@aws-cdk/aws-secretsmanager/lib/secret.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import * as iam from '@aws-cdk/aws-iam';
import * as kms from '@aws-cdk/aws-kms';
import { IResource, RemovalPolicy, Resource, SecretValue, Stack, Token } from '@aws-cdk/core';
import { FeatureFlags, Fn, IResource, RemovalPolicy, Resource, SecretValue, Stack, Token } from '@aws-cdk/core';
import * as cxapi from '@aws-cdk/cx-api';
import { IConstruct, Construct } from 'constructs';
import { ResourcePolicy } from './policy';
import { RotationSchedule, RotationScheduleOptions } from './rotation-schedule';
Expand Down Expand Up @@ -30,7 +31,10 @@ export interface ISecret extends IResource {
readonly secretFullArn?: string;

/**
* The name of the secret
* The name of the secret.
*
* For "owned" secrets, this will be the full resource name (secret name + suffix), unless the
* '@aws-cdk/aws-secretsmanager:parseOwnedSecretName' feature flag is set.
*/
readonly secretName: string;

Expand Down Expand Up @@ -437,7 +441,10 @@ export class Secret extends SecretBase {
});

this.encryptionKey = props.encryptionKey;
this.secretName = parseSecretName(this, this.secretArn);
const parseOwnedSecretName = FeatureFlags.of(this).isEnabled(cxapi.SECRETS_MANAGER_PARSE_OWNED_SECRET_NAME);
this.secretName = parseOwnedSecretName
? parseSecretNameForOwnedSecret(this, this.secretArn, props.secretName)
: parseSecretName(this, this.secretArn);

// @see https://docs.aws.amazon.com/kms/latest/developerguide/services-secrets-manager.html#asm-authz
const principal =
Expand Down Expand Up @@ -707,6 +714,39 @@ function parseSecretName(construct: IConstruct, secretArn: string) {
throw new Error('invalid ARN format; no secret name provided');
}

/**
* Parses the secret name from the ARN of an owned secret. With owned secrets we know a few things we don't with imported secrets:
* - The ARN is guaranteed to be a full ARN, with suffix.
* - The name -- if provided -- will tell us how many hyphens to expect in the final secret name.
* - If the name is not provided, we know the format used by CloudFormation for auto-generated names.
*
* Note: This is done rather than just returning the secret name passed in by the user to keep the relationship
* explicit between the Secret and wherever the secretName might be used (i.e., using Tokens).
*/
function parseSecretNameForOwnedSecret(construct: Construct, secretArn: string, secretName?: string) {
const resourceName = Stack.of(construct).parseArn(secretArn, ':').resourceName;
if (!resourceName) {
throw new Error('invalid ARN format; no secret name provided');
}

// Secret name was explicitly provided, but is unresolved; best option is to use it directly.
// If it came from another Secret, it should (hopefully) already be properly formatted.
if (secretName && Token.isUnresolved(secretName)) {
return secretName;
}

// If no secretName was provided, the name will be automatically generated by CloudFormation.
// The autogenerated names have the form of `${logicalID}-${random}`.
// Otherwise, we can use the existing secretName to determine how to parse the resulting resourceName.
const secretNameHyphenatedSegments = secretName ? secretName.split('-').length : 2;
// 2 => [0, 1]
const segmentIndexes = [...new Array(secretNameHyphenatedSegments)].map((_, i) => i);

// Create the secret name from the resource name by joining all the known segments together.
// This should have the effect of stripping the final hyphen and SecretManager suffix.
return Fn.join('-', segmentIndexes.map(i => Fn.select(i, Fn.split('-', resourceName))));
}

/** Performs a best guess if an ARN is complete, based on if it ends with a 6-character suffix. */
function arnIsComplete(secretArn: string): boolean {
return Token.isUnresolved(secretArn) || /-[a-z0-9]{6}$/i.test(secretArn);
Expand Down
2 changes: 2 additions & 0 deletions packages/@aws-cdk/aws-secretsmanager/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@
"@aws-cdk/aws-lambda": "0.0.0",
"@aws-cdk/aws-sam": "0.0.0",
"@aws-cdk/core": "0.0.0",
"@aws-cdk/cx-api": "0.0.0",
"constructs": "^3.2.0"
},
"peerDependencies": {
Expand All @@ -95,6 +96,7 @@
"@aws-cdk/aws-lambda": "0.0.0",
"@aws-cdk/aws-sam": "0.0.0",
"@aws-cdk/core": "0.0.0",
"@aws-cdk/cx-api": "0.0.0",
"constructs": "^3.2.0"
},
"engines": {
Expand Down
Loading

0 comments on commit e57eabc

Please sign in to comment.