Skip to content

Commit

Permalink
Merge branch 'main' into appregistry-stack-id
Browse files Browse the repository at this point in the history
  • Loading branch information
alexpulver authored Oct 22, 2022
2 parents ccca4c2 + d8b4c09 commit 6e389ed
Show file tree
Hide file tree
Showing 701 changed files with 28,086 additions and 1,698 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/auto-approve.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,6 @@ jobs:
permissions:
pull-requests: write
steps:
- uses: hmarr/auto-approve-action@v2.4.0
- uses: hmarr/auto-approve-action@v3.0.0
with:
github-token: "${{ secrets.GITHUB_TOKEN }}"
13 changes: 13 additions & 0 deletions CHANGELOG.v2.alpha.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,19 @@

All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.

## [2.47.0-alpha.0](https://github.com/aws/aws-cdk/compare/v2.46.0-alpha.0...v2.47.0-alpha.0) (2022-10-20)


### Features

* **redshift:** support enhanced vpc routing when creating redshift cluster ([#22499](https://github.com/aws/aws-cdk/issues/22499)) ([e2b18e7](https://github.com/aws/aws-cdk/commit/e2b18e7b47eb7a87ae37356a9719c055e58e6e6c))


### Bug Fixes

* **integ-runner:** Fix call to spawnSync for hooks commands ([#22429](https://github.com/aws/aws-cdk/issues/22429)) ([9139ca9](https://github.com/aws/aws-cdk/commit/9139ca96ffc010e13393aff927d7b7eacfbae4f9)), closes [#22344](https://github.com/aws/aws-cdk/issues/22344)
* **lambda-python:** root-owned cache items not cleaned up after install ([#22512](https://github.com/aws/aws-cdk/issues/22512)) ([5ef65e0](https://github.com/aws/aws-cdk/commit/5ef65e042c747bedf9d770b47e540393454762f2)), closes [#22398](https://github.com/aws/aws-cdk/issues/22398)

## [2.46.0-alpha.0](https://github.com/aws/aws-cdk/compare/v2.45.0-alpha.0...v2.46.0-alpha.0) (2022-10-13)


Expand Down
22 changes: 22 additions & 0 deletions CHANGELOG.v2.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,28 @@

All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.

## [2.47.0](https://github.com/aws/aws-cdk/compare/v2.46.0...v2.47.0) (2022-10-20)


### Features

* **apigateway:** support multi-level paths for custom domains ([#22463](https://github.com/aws/aws-cdk/issues/22463)) ([cdc5753](https://github.com/aws/aws-cdk/commit/cdc5753982d8f674dab2362ea63790abb736fa32)), closes [#15904](https://github.com/aws/aws-cdk/issues/15904)
* **config:** add custom policy rule constructs ([#21794](https://github.com/aws/aws-cdk/issues/21794)) ([09a5cc4](https://github.com/aws/aws-cdk/commit/09a5cc4ff55cb7d001c14059c12ada0a2801acd4)), closes [#21441](https://github.com/aws/aws-cdk/issues/21441)
* **elbv2:** add dropInvalidHeaderFields for elbv2 ([#22466](https://github.com/aws/aws-cdk/issues/22466)) ([91767f0](https://github.com/aws/aws-cdk/commit/91767f03e76db8a63c18882b44854999b15aaff4)), closes [/docs.aws.amazon.com/securityhub/latest/userguide/securityhub-standards-fsbp-controls.html#fsbp-elb-4](https://github.com/aws//docs.aws.amazon.com/securityhub/latest/userguide/securityhub-standards-fsbp-controls.html/issues/fsbp-elb-4)


### Bug Fixes

* breaking change to deployment config props ([#22567](https://github.com/aws/aws-cdk/issues/22567)) ([be6074a](https://github.com/aws/aws-cdk/commit/be6074a67b68ec2f295196ad73ddb6e92984bdf3)), closes [#22566](https://github.com/aws/aws-cdk/issues/22566)
* **apigateway:** validation for path parts does not allow creation of resources with colon ([#22531](https://github.com/aws/aws-cdk/issues/22531)) ([73c443a](https://github.com/aws/aws-cdk/commit/73c443a7cd14ad27776907095bf19100e903093f)), closes [#22477](https://github.com/aws/aws-cdk/issues/22477) [#22477](https://github.com/aws/aws-cdk/issues/22477)
* **cli:** hotswap deploy fails on multiple CfnEvaluationException ([#22339](https://github.com/aws/aws-cdk/issues/22339)) ([7b47f41](https://github.com/aws/aws-cdk/commit/7b47f4178e4a4b9fe3dcb54daa3ec9f94fbd2a31)), closes [#22323](https://github.com/aws/aws-cdk/issues/22323)
* **cloudwatch:** remove region from dashboard ARN ([#22524](https://github.com/aws/aws-cdk/issues/22524)) ([558d192](https://github.com/aws/aws-cdk/commit/558d1925d7c3b01d7681e28f7b85bc851e403556))
* **codeguruprofiler:** incorrect profiling group name is returned when using importing ([#22554](https://github.com/aws/aws-cdk/issues/22554)) ([9934619](https://github.com/aws/aws-cdk/commit/9934619970dcb582106e9b2bf0d373d730de1fee))
* **cognito:** cannot use same lambda function as trigger in multiple user pools ([#22444](https://github.com/aws/aws-cdk/issues/22444)) ([b26fc00](https://github.com/aws/aws-cdk/commit/b26fc007465ce9466cecfaf5c0bb337d741c77e8)), closes [#22315](https://github.com/aws/aws-cdk/issues/22315)
* **config:** Creating multiple rules from the same lambda ([#21594](https://github.com/aws/aws-cdk/issues/21594)) ([0d2b529](https://github.com/aws/aws-cdk/commit/0d2b5291a10a318bed8d77166eae2bd317dee62e)), closes [#17582](https://github.com/aws/aws-cdk/issues/17582)
* **iam:** missing validation for actions added post instantiation of a policy statement ([#21906](https://github.com/aws/aws-cdk/issues/21906)) ([10974d9](https://github.com/aws/aws-cdk/commit/10974d95693dd75e993b8f0b5808b775b55b3afd)), closes [40aws-cdk/aws-iam/lib/policy-statement.ts#L88-L95](https://github.com/40aws-cdk/aws-iam/lib/policy-statement.ts/issues/L88-L95)
* **stepfunctions:** JsonPath.listAt does not accept strings starting with `$[` ([#22472](https://github.com/aws/aws-cdk/issues/22472)) ([6f332ef](https://github.com/aws/aws-cdk/commit/6f332efb1ae5c22f1c3b02221362018e3f4b575f)), closes [#22471](https://github.com/aws/aws-cdk/issues/22471)

## [2.46.0](https://github.com/aws/aws-cdk/compare/v2.45.0...v2.46.0) (2022-10-13)


Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
"devDependencies": {
"@types/prettier": "2.6.0",
"@yarnpkg/lockfile": "^1.1.0",
"cdk-generate-synthetic-examples": "^0.1.29",
"cdk-generate-synthetic-examples": "^0.1.36",
"conventional-changelog-cli": "^2.2.2",
"fs-extra": "^9.1.0",
"graceful-fs": "^4.2.10",
Expand Down
53 changes: 46 additions & 7 deletions packages/@aws-cdk/aws-apigateway/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1083,14 +1083,53 @@ new route53.ARecord(this, 'CustomDomainAliasRecord', {
});
```

### Custom Domains with multi-level api mapping

Additional requirements for creating multi-level path mappings for RestApis:

(both are defaults)

- Must use `SecurityPolicy.TLS_1_2`
- DomainNames must be `EndpointType.REGIONAL`

```ts
declare const acmCertificateForExampleCom: any;
declare const restApi: apigateway.RestApi;

new apigateway.DomainName(this, 'custom-domain', {
domainName: 'example.com',
certificate: acmCertificateForExampleCom,
mapping: restApi,
basePath: 'orders/v1/api',
});
```

To then add additional mappings to a domain you can use the `addApiMapping` method.

```ts
declare const acmCertificateForExampleCom: any;
declare const restApi: apigateway.RestApi;
declare const secondRestApi: apigateway.RestApi;

const domain = new apigateway.DomainName(this, 'custom-domain', {
domainName: 'example.com',
certificate: acmCertificateForExampleCom,
mapping: restApi,
});

domain.addApiMapping(secondRestApi.deploymentStage, {
basePath: 'orders/v2/api',
});
```

## Access Logging

Access logging creates logs every time an API method is accessed. Access logs can have information on
who has accessed the API, how the caller accessed the API and what responses were generated.
Access logs are configured on a Stage of the RestApi.
Access logs can be expressed in a format of your choosing, and can contain any access details, with a
minimum that it must include the 'requestId'. The list of variables that can be expressed in the access
log can be found
minimum that it must include either 'requestId' or 'extendedRequestId'. The list of variables that
can be expressed in the access log can be found
[here](https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-mapping-template-reference.html#context-variable-reference).
Read more at [Setting Up CloudWatch API Logging in API
Gateway](https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-logging.html)
Expand All @@ -1101,9 +1140,9 @@ const prdLogGroup = new logs.LogGroup(this, "PrdLogs");
const api = new apigateway.RestApi(this, 'books', {
deployOptions: {
accessLogDestination: new apigateway.LogGroupLogDestination(prdLogGroup),
accessLogFormat: apigateway.AccessLogFormat.jsonWithStandardFields()
}
})
accessLogFormat: apigateway.AccessLogFormat.jsonWithStandardFields(),
},
});
const deployment = new apigateway.Deployment(this, 'Deployment', {api});

// development stage
Expand All @@ -1120,8 +1159,8 @@ new apigateway.Stage(this, 'dev', {
resourcePath: true,
responseLength: true,
status: true,
user: true
})
user: true,
}),
});
```

Expand Down
2 changes: 1 addition & 1 deletion packages/@aws-cdk/aws-apigateway/lib/authorizers/lambda.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export interface LambdaAuthorizerProps {
/**
* An optional human friendly name for the authorizer. Note that, this is not the primary identifier of the authorizer.
*
* @default - the unique construcrt ID
* @default - the unique construct ID
*/
readonly authorizerName?: string;

Expand Down
101 changes: 90 additions & 11 deletions packages/@aws-cdk/aws-apigateway/lib/domain-name.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,30 @@
import * as apigwv2 from '@aws-cdk/aws-apigatewayv2';
import * as acm from '@aws-cdk/aws-certificatemanager';
import { IBucket } from '@aws-cdk/aws-s3';
import { IResource, Names, Resource, Token } from '@aws-cdk/core';
import { Construct } from 'constructs';
import { CfnDomainName } from './apigateway.generated';
import { BasePathMapping, BasePathMappingOptions } from './base-path-mapping';
import { EndpointType, IRestApi } from './restapi';
import { IStage } from './stage';

/**
* Options for creating an api mapping
*/
export interface ApiMappingOptions {
/**
* The api path name that callers of the API must provide in the URL after
* the domain name (e.g. `example.com/base-path`). If you specify this
* property, it can't be an empty string.
*
* If this is undefined, a mapping will be added for the empty path. Any request
* that does not match a mapping will get sent to the API that has been mapped
* to the empty path.
*
* @default - map requests from the domain root (e.g. `example.com`).
*/
readonly basePath?: string;
}

/**
* The minimum version of the SSL protocol that you want API Gateway to use for HTTPS connections.
Expand Down Expand Up @@ -54,8 +74,7 @@ export interface DomainNameOptions {
* the domain name (e.g. `example.com/base-path`). If you specify this
* property, it can't be an empty string.
*
* @default - map requests from the domain root (e.g. `example.com`). If this
* is undefined, no additional mappings will be allowed on this domain name.
* @default - map requests from the domain root (e.g. `example.com`).
*/
readonly basePath?: string;
}
Expand All @@ -64,8 +83,7 @@ export interface DomainNameProps extends DomainNameOptions {
/**
* If specified, all requests to this domain will be mapped to the production
* deployment of this API. If you wish to map this domain to multiple APIs
* with different base paths, don't specify this option and use
* `addBasePathMapping`.
* with different base paths, use `addBasePathMapping` or `addApiMapping`.
*
* @default - you will have to call `addBasePathMapping` to map this domain to
* API endpoints.
Expand Down Expand Up @@ -115,12 +133,15 @@ export class DomainName extends Resource implements IDomainName {
public readonly domainNameAliasDomainName: string;
public readonly domainNameAliasHostedZoneId: string;
private readonly basePaths = new Set<string | undefined>();
private readonly securityPolicy?: SecurityPolicy;
private readonly endpointType: EndpointType;

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

const endpointType = props.endpointType || EndpointType.REGIONAL;
const edge = endpointType === EndpointType.EDGE;
this.endpointType = props.endpointType || EndpointType.REGIONAL;
const edge = this.endpointType === EndpointType.EDGE;
this.securityPolicy = props.securityPolicy;

if (!Token.isUnresolved(props.domainName) && /[A-Z]/.test(props.domainName)) {
throw new Error(`Domain name does not support uppercase letters. Got: ${props.domainName}`);
Expand All @@ -131,7 +152,7 @@ export class DomainName extends Resource implements IDomainName {
domainName: props.domainName,
certificateArn: edge ? props.certificate.certificateArn : undefined,
regionalCertificateArn: edge ? undefined : props.certificate.certificateArn,
endpointConfiguration: { types: [endpointType] },
endpointConfiguration: { types: [this.endpointType] },
mutualTlsAuthentication: mtlsConfig,
securityPolicy: props.securityPolicy,
});
Expand All @@ -146,22 +167,54 @@ export class DomainName extends Resource implements IDomainName {
? resource.attrDistributionHostedZoneId
: resource.attrRegionalHostedZoneId;

if (props.mapping) {

const multiLevel = this.validateBasePath(props.basePath);
if (props.mapping && !multiLevel) {
this.addBasePathMapping(props.mapping, {
basePath: props.basePath,
});
} else if (props.mapping && multiLevel) {
this.addApiMapping(props.mapping.deploymentStage, {
basePath: props.basePath,
});
}
}

private validateBasePath(path?: string): boolean {
if (this.isMultiLevel(path)) {
if (this.endpointType === EndpointType.EDGE) {
throw new Error('multi-level basePath is only supported when endpointType is EndpointType.REGIONAL');
}
if (this.securityPolicy && this.securityPolicy !== SecurityPolicy.TLS_1_2) {
throw new Error('securityPolicy must be set to TLS_1_2 if multi-level basePath is provided');
}
return true;
}
return false;
}

private isMultiLevel(path?: string): boolean {
return (path?.split('/').filter(x => !!x) ?? []).length >= 2;
}

/**
* Maps this domain to an API endpoint.
*
* This uses the BasePathMapping from ApiGateway v1 which does not support multi-level paths.
*
* If you need to create a mapping for a multi-level path use `addApiMapping` instead.
*
* @param targetApi That target API endpoint, requests will be mapped to the deployment stage.
* @param options Options for mapping to base path with or without a stage
*/
public addBasePathMapping(targetApi: IRestApi, options: BasePathMappingOptions = { }) {
if (this.basePaths.has(undefined)) {
throw new Error('This domain name already has an empty base path. No additional base paths are allowed.');
public addBasePathMapping(targetApi: IRestApi, options: BasePathMappingOptions = { }): BasePathMapping {
if (this.basePaths.has(options.basePath)) {
throw new Error(`DomainName ${this.node.id} already has a mapping for path ${options.basePath}`);
}
if (this.isMultiLevel(options.basePath)) {
throw new Error('BasePathMapping does not support multi-level paths. Use "addApiMapping instead.');
}

this.basePaths.add(options.basePath);
const basePath = options.basePath || '/';
const id = `Map:${basePath}=>${Names.nodeUniqueId(targetApi.node)}`;
Expand All @@ -172,6 +225,32 @@ export class DomainName extends Resource implements IDomainName {
});
}

/**
* Maps this domain to an API endpoint.
*
* This uses the ApiMapping from ApiGatewayV2 which supports multi-level paths, but
* also only supports:
* - SecurityPolicy.TLS_1_2
* - EndpointType.REGIONAL
*
* @param targetStage the target API stage.
* @param options Options for mapping to a stage
*/
public addApiMapping(targetStage: IStage, options: ApiMappingOptions = {}): void {
if (this.basePaths.has(options.basePath)) {
throw new Error(`DomainName ${this.node.id} already has a mapping for path ${options.basePath}`);
}
this.validateBasePath(options.basePath);
this.basePaths.add(options.basePath);
const id = `Map:${options.basePath ?? 'none'}=>${Names.nodeUniqueId(targetStage.node)}`;
new apigwv2.CfnApiMapping(this, id, {
apiId: targetStage.restApi.restApiId,
stage: targetStage.stageName,
domainName: this.domainName,
apiMappingKey: options.basePath,
});
}

private configureMTLS(mtlsConfig?: MTLSConfig): CfnDomainName.MutualTlsAuthenticationProperty | undefined {
if (!mtlsConfig) return undefined;
return {
Expand Down
4 changes: 2 additions & 2 deletions packages/@aws-cdk/aws-apigateway/lib/resource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -558,8 +558,8 @@ function validateResourcePathPart(part: string) {
}
}

if (!/^[a-zA-Z0-9\.\_\-]+$/.test(part)) {
throw new Error(`Resource's path part only allow [a-zA-Z0-9._-], an optional trailing '+'
if (!/^[a-zA-Z0-9:\.\_\-]+$/.test(part)) {
throw new Error(`Resource's path part only allow [a-zA-Z0-9:._-], an optional trailing '+'
and curly braces at the beginning and the end: ${part}`);
}
}
8 changes: 5 additions & 3 deletions packages/@aws-cdk/aws-apigateway/lib/stage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,9 @@ export interface StageOptions extends MethodDeploymentOptions {

/**
* A single line format of access logs of data, as specified by selected $content variables.
* The format must include at least `AccessLogFormat.contextRequestId()`.
* The format must include either `AccessLogFormat.contextRequestId()`
* or `AccessLogFormat.contextExtendedRequestId()`.
*
* @see https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-mapping-template-reference.html#context-variable-reference
*
* @default - Common Log Format
Expand Down Expand Up @@ -387,9 +389,9 @@ export class Stage extends StageBase {
} else {
if (accessLogFormat !== undefined &&
!Token.isUnresolved(accessLogFormat.toString()) &&
!/.*\$context.requestId.*/.test(accessLogFormat.toString())) {
!/.*\$context.(requestId|extendedRequestId)\b.*/.test(accessLogFormat.toString())) {

throw new Error('Access log must include at least `AccessLogFormat.contextRequestId()`');
throw new Error('Access log must include either `AccessLogFormat.contextRequestId()` or `AccessLogFormat.contextExtendedRequestId()`');
}
if (accessLogFormat !== undefined && accessLogDestination === undefined) {
throw new Error('Access log format is specified without a destination');
Expand Down
8 changes: 8 additions & 0 deletions packages/@aws-cdk/aws-apigateway/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@
"@aws-cdk/assertions": "0.0.0",
"@aws-cdk/cdk-build-tools": "0.0.0",
"@aws-cdk/integ-runner": "0.0.0",
"@aws-cdk/aws-route53": "0.0.0",
"@aws-cdk/cfn2ts": "0.0.0",
"@aws-cdk/pkglint": "0.0.0",
"@types/jest": "^27.5.2"
Expand All @@ -100,6 +101,7 @@
"@aws-cdk/aws-s3": "0.0.0",
"@aws-cdk/aws-s3-assets": "0.0.0",
"@aws-cdk/aws-stepfunctions": "0.0.0",
"@aws-cdk/aws-apigatewayv2": "0.0.0",
"@aws-cdk/core": "0.0.0",
"@aws-cdk/cx-api": "0.0.0",
"constructs": "^10.0.0"
Expand All @@ -117,6 +119,7 @@
"@aws-cdk/aws-s3": "0.0.0",
"@aws-cdk/aws-s3-assets": "0.0.0",
"@aws-cdk/aws-stepfunctions": "0.0.0",
"@aws-cdk/aws-apigatewayv2": "0.0.0",
"@aws-cdk/core": "0.0.0",
"@aws-cdk/cx-api": "0.0.0",
"constructs": "^10.0.0"
Expand All @@ -132,6 +135,11 @@
"lib/apigatewayv2.js"
]
},
"pkglint": {
"exclude": [
"no-experimental-dependencies"
]
},
"awslint": {
"exclude": [
"from-method:@aws-cdk/aws-apigateway.Resource",
Expand Down
Loading

0 comments on commit 6e389ed

Please sign in to comment.