diff --git a/.github/workflows/cr-checklist.yml b/.github/workflows/cr-checklist.yml index cdca37051a4d5..5badcb02eb2ac 100644 --- a/.github/workflows/cr-checklist.yml +++ b/.github/workflows/cr-checklist.yml @@ -9,7 +9,7 @@ jobs: name: Creates a checklist for PRs that contain changes to custom resources steps: - name: Checkout repo - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Dynamic checklist action uses: vishalsinha21/dynamic-checklist@v1 with: diff --git a/.github/workflows/pr-linter.yml b/.github/workflows/pr-linter.yml index 8231b94fa2319..73cc7b595e00d 100644 --- a/.github/workflows/pr-linter.yml +++ b/.github/workflows/pr-linter.yml @@ -21,7 +21,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Install & Build prlint run: yarn install --frozen-lockfile && cd tools/@aws-cdk/prlint && yarn build+test diff --git a/.github/workflows/v2-pull-request.yml b/.github/workflows/v2-pull-request.yml index 351ee2c8c427f..8e7e00acdbc25 100644 --- a/.github/workflows/v2-pull-request.yml +++ b/.github/workflows/v2-pull-request.yml @@ -23,7 +23,7 @@ jobs: runs-on: ubuntu-latest steps: - name: checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: branch: ${{ github.event.pull_request.head.ref }} token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/yarn-upgrade.yml b/.github/workflows/yarn-upgrade.yml index e694f383740ab..c9c6edb8d82b5 100644 --- a/.github/workflows/yarn-upgrade.yml +++ b/.github/workflows/yarn-upgrade.yml @@ -15,7 +15,7 @@ jobs: steps: - name: Check Out - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Set up Node uses: actions/setup-node@v3 @@ -87,7 +87,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check Out - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Download patch uses: actions/download-artifact@v2 diff --git a/CHANGELOG.md b/CHANGELOG.md index 14e18e06c3054..435ac9555c58a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,35 @@ 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. +## [1.147.0](https://github.com/aws/aws-cdk/compare/v1.146.0...v1.147.0) (2022-03-01) + + +### Features + +* **cfnspec:** cloudformation spec v58.0.0 ([#19153](https://github.com/aws/aws-cdk/issues/19153)) ([a6b0a10](https://github.com/aws/aws-cdk/commit/a6b0a1018694a0696ed27635d4def5d1630b8f9a)) +* **cli:** hotswap support for resources in nested stacks ([#18950](https://github.com/aws/aws-cdk/issues/18950)) ([2ea9da1](https://github.com/aws/aws-cdk/commit/2ea9da118794809265d215e3d2f554bbcb91b271)) +* **ec2:** add c6a instances ([#19113](https://github.com/aws/aws-cdk/issues/19113)) ([427cdfd](https://github.com/aws/aws-cdk/commit/427cdfde5e8c48ed7c1f86b275ccb2516a901239)) + + +### Bug Fixes + +* **apigateway:** fix strange vtl template for cors preflight request ([#19104](https://github.com/aws/aws-cdk/issues/19104)) ([59ef06a](https://github.com/aws/aws-cdk/commit/59ef06ae2a70fcb1800fcc1f40eec671c77440f0)), closes [/datatracker.ietf.org/doc/html/rfc6454#section-7](https://github.com/aws//datatracker.ietf.org/doc/html/rfc6454/issues/section-7) +* **aws-apigateway:** api gateway usage plan ([#19023](https://github.com/aws/aws-cdk/issues/19023)) ([5b764cc](https://github.com/aws/aws-cdk/commit/5b764cc397de4f4b203f5c69fa0128c6dced49f9)), closes [#18994](https://github.com/aws/aws-cdk/issues/18994) +* **aws-lambda-python:** skip default docker build when image passed ([#19143](https://github.com/aws/aws-cdk/issues/19143)) ([7300f2e](https://github.com/aws/aws-cdk/commit/7300f2eee9e1593eef271d7a953edf80a8962e08)), closes [#18082](https://github.com/aws/aws-cdk/issues/18082) +* **cli:** cdk version displays notices ([#19181](https://github.com/aws/aws-cdk/issues/19181)) ([fa16f7a](https://github.com/aws/aws-cdk/commit/fa16f7a9c11981da75e44ffc83adcdc6edad94fc)) +* **cli:** long connection timeout slows the CLI down ([#19187](https://github.com/aws/aws-cdk/issues/19187)) ([6595d04](https://github.com/aws/aws-cdk/commit/6595d044e29fb262fb62430783ad08359e16bc30)) +* **custom-resources:** physical resource id must be determined before isComplete ([#18630](https://github.com/aws/aws-cdk/issues/18630)) ([c190367](https://github.com/aws/aws-cdk/commit/c1903678aba31ca5b23a3bebb84249921e15dd5c)) +* **dynamodb:** `grant*Data()` methods are missing the `dynamodb:DescribeTable` permission ([#19129](https://github.com/aws/aws-cdk/issues/19129)) ([4a44a65](https://github.com/aws/aws-cdk/commit/4a44a65bb4634081e04811966d5f4e2fd49bc7c6)), closes [#18773](https://github.com/aws/aws-cdk/issues/18773) +* **dynamodb:** `Table.grantWriteData()` doesn't include enough KMS permissions ([#19102](https://github.com/aws/aws-cdk/issues/19102)) ([77f1e0b](https://github.com/aws/aws-cdk/commit/77f1e0b57bd4508ade86be7733e71e94a47d7f4c)), closes [#10010](https://github.com/aws/aws-cdk/issues/10010) +* **ec2:** invalid volume type check for iops ([#19073](https://github.com/aws/aws-cdk/issues/19073)) ([3f49f02](https://github.com/aws/aws-cdk/commit/3f49f020090142c77feb892894c54e62dc4de7ae)) +* **eks:** Helm charts fail to install when provided as an asset ([#19180](https://github.com/aws/aws-cdk/issues/19180)) ([9961257](https://github.com/aws/aws-cdk/commit/99612574bbaf97379482e9e424e1d1115809d74b)) +* **lambda-nodejs:** `logLevel` property of `BundlingOptions` is ignored when `nodeModules` are defined ([#18456](https://github.com/aws/aws-cdk/issues/18456)) ([5c40b90](https://github.com/aws/aws-cdk/commit/5c40b90707b869f62e59613d50d5deaafbaa52f1)), closes [#18383](https://github.com/aws/aws-cdk/issues/18383) +* **stepfunctions-tasks:** RUN_JOB integration pattern not supported for CallAwsService ([#19186](https://github.com/aws/aws-cdk/issues/19186)) ([4b134b7](https://github.com/aws/aws-cdk/commit/4b134b785115f026a0eaa37b699cd32c85ff8e73)), closes [#19174](https://github.com/aws/aws-cdk/issues/19174) +* apply tags to nested stack ([#19128](https://github.com/aws/aws-cdk/issues/19128)) ([3af329b](https://github.com/aws/aws-cdk/commit/3af329bcb66b9dffce0c03f0816b33e91e901808)), closes [#17463](https://github.com/aws/aws-cdk/issues/17463) +* **triggers:** not published as part of v2 ([#19168](https://github.com/aws/aws-cdk/issues/19168)) ([8f727d1](https://github.com/aws/aws-cdk/commit/8f727d15f8f87d4ca323fee449826908db7971a4)), closes [#19164](https://github.com/aws/aws-cdk/issues/19164) +* construct paths are not printed for nested stacks in CLI output ([#18725](https://github.com/aws/aws-cdk/issues/18725)) ([b0e0155](https://github.com/aws/aws-cdk/commit/b0e0155f87a65c34a75e11776f98d55b83d2b220)) +* **rds:** MySQL Cluster version 8.0 uses wrong Parameter for S3 import ([#19145](https://github.com/aws/aws-cdk/issues/19145)) ([96b2034](https://github.com/aws/aws-cdk/commit/96b2034c44b441a96cfe19855d343b0f983c8772)), closes [#19126](https://github.com/aws/aws-cdk/issues/19126) + ## [1.146.0](https://github.com/aws/aws-cdk/compare/v1.145.0...v1.146.0) (2022-02-24) diff --git a/CHANGELOG.v2.alpha.md b/CHANGELOG.v2.alpha.md index 22d1df727ae1a..ad449167b2f66 100644 --- a/CHANGELOG.v2.alpha.md +++ b/CHANGELOG.v2.alpha.md @@ -2,6 +2,23 @@ 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.16.0-alpha.0](https://github.com/aws/aws-cdk/compare/v2.15.0-alpha.0...v2.16.0-alpha.0) (2022-03-11) + + +### Features + +* **aws-s3objectlambda:** add L2 construct for S3 Object Lambda ([#15833](https://github.com/aws/aws-cdk/issues/15833)) ([fe9f750](https://github.com/aws/aws-cdk/commit/fe9f750bd9dd9974b9ae6f73c78fcd12ab2edd91)), closes [#13675](https://github.com/aws/aws-cdk/issues/13675) +* **iotevents:** support actions ([#18869](https://github.com/aws/aws-cdk/issues/18869)) ([e01654e](https://github.com/aws/aws-cdk/commit/e01654e792708ee283d7a31e1370d0d1ae383171)) +* **iotevents:** support setting Events on input and exit for State ([#19249](https://github.com/aws/aws-cdk/issues/19249)) ([ffa9e0d](https://github.com/aws/aws-cdk/commit/ffa9e0d287d0a86e1e0eb7dc2dec16d9f3e84450)) +* **servicecatalog:** Service Catalog is now in Developer Preview ([#19204](https://github.com/aws/aws-cdk/issues/19204)) ([6dfc254](https://github.com/aws/aws-cdk/commit/6dfc254e1925597b4ef2ece9c132b1a0e580dd6d)) + + +### Bug Fixes + +* **apigatewayv2-integrations:** in case of multiple routes, only one execute permission is created ([#18716](https://github.com/aws/aws-cdk/issues/18716)) ([1e352ca](https://github.com/aws/aws-cdk/commit/1e352ca2ab458bfe4e1de6cf431166654ce9aa58)) +* **lambda-python:** asset bundling fails on windows ([#19270](https://github.com/aws/aws-cdk/issues/19270)) ([0da57da](https://github.com/aws/aws-cdk/commit/0da57da9606d982788350a6257f0f0ed6e9fd92a)), closes [#18861](https://github.com/aws/aws-cdk/issues/18861) +* **lambda-python:** docker image gets built even when we don't need to bundle assets ([#16192](https://github.com/aws/aws-cdk/issues/16192)) ([5dc61ea](https://github.com/aws/aws-cdk/commit/5dc61eabc0ea3e6294f83db5deb8528461a1d5bc)), closes [#14747](https://github.com/aws/aws-cdk/issues/14747) + ## [2.15.0-alpha.0](https://github.com/aws/aws-cdk/compare/v2.14.0-alpha.0...v2.15.0-alpha.0) (2022-03-01) diff --git a/CHANGELOG.v2.md b/CHANGELOG.v2.md index 9300d6005b68e..caa1bb9ab4552 100644 --- a/CHANGELOG.v2.md +++ b/CHANGELOG.v2.md @@ -2,6 +2,33 @@ 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.16.0](https://github.com/aws/aws-cdk/compare/v2.15.0...v2.16.0) (2022-03-11) + + +### Features + +* **aws-apigateway:** add ability to include authorizer context in apigw sfn integration ([#18892](https://github.com/aws/aws-cdk/issues/18892)) ([e7c0c75](https://github.com/aws/aws-cdk/commit/e7c0c75dbc7cf71164673626dc0ab63fb3706223)), closes [#18891](https://github.com/aws/aws-cdk/issues/18891) +* **cfnspec:** cloudformation spec v59.0.0 ([#19236](https://github.com/aws/aws-cdk/issues/19236)) ([f46a14d](https://github.com/aws/aws-cdk/commit/f46a14da9bec1aad7096b62666cb80ce42f04b53)) +* **codebuild:** improved support for ARM build images ([#19052](https://github.com/aws/aws-cdk/issues/19052)) ([4eac4de](https://github.com/aws/aws-cdk/commit/4eac4deb98411e921e5a2e6477185207b8588f75)), closes [#18916](https://github.com/aws/aws-cdk/issues/18916) [#9817](https://github.com/aws/aws-cdk/issues/9817) +* **eks:** Service Account names validation ([#19251](https://github.com/aws/aws-cdk/issues/19251)) ([7c3099e](https://github.com/aws/aws-cdk/commit/7c3099e958d7bf0ddb5a7b08afb672a0c652b27d)), closes [#18189](https://github.com/aws/aws-cdk/issues/18189) +* **elasticsearch:** Decouple setting access policies from domain constructor ([#15876](https://github.com/aws/aws-cdk/issues/15876)) ([cefdfd3](https://github.com/aws/aws-cdk/commit/cefdfd384eeac1752567f672452296def68b1206)) +* **lambda-nodejs:** support esbuild inject ([#19221](https://github.com/aws/aws-cdk/issues/19221)) ([3432c45](https://github.com/aws/aws-cdk/commit/3432c457fe38a83743d7ce2a5cb6c36a6ec01b8f)), closes [#19133](https://github.com/aws/aws-cdk/issues/19133) +* **s3:** add `s3:ObjectRestore:Delete` to `EventType` for notification ([#19250](https://github.com/aws/aws-cdk/issues/19250)) ([e0f863a](https://github.com/aws/aws-cdk/commit/e0f863a4c56041860e14c75b9aa5a6d35860fae6)), closes [#19223](https://github.com/aws/aws-cdk/issues/19223) + + +### Bug Fixes + +* **aws-apigateway:** missing comma to make failure response payload valid json ([#19253](https://github.com/aws/aws-cdk/issues/19253)) ([b1fce4f](https://github.com/aws/aws-cdk/commit/b1fce4f1641c90a4b7d1d33139453260b452d5cd)), closes [#19252](https://github.com/aws/aws-cdk/issues/19252) +* **aws-route53-targets:** add support for custom cname_prefix urls in elastic beanstalk environment endpoint target ([#18804](https://github.com/aws/aws-cdk/issues/18804)) ([289a794](https://github.com/aws/aws-cdk/commit/289a79467d9974ee3582c9e30843b0eb9e90b467)) +* **cli:** `watch` logs always end with the 'truncated' message ([#19241](https://github.com/aws/aws-cdk/issues/19241)) ([d3fdfe5](https://github.com/aws/aws-cdk/commit/d3fdfe5264e64cb333795b32edbad36cfaab3dc7)), closes [#18805](https://github.com/aws/aws-cdk/issues/18805) +* **cli:** deprecated stack ids printed at the end of synth ([#19216](https://github.com/aws/aws-cdk/issues/19216)) ([7d8a479](https://github.com/aws/aws-cdk/commit/7d8a4792a142f45109f35a51c6e1b3888d4111d3)), closes [#18599](https://github.com/aws/aws-cdk/issues/18599) +* **cli:** notices refresh doesn't respect the --no-notices flag ([#19226](https://github.com/aws/aws-cdk/issues/19226)) ([b3c5fe8](https://github.com/aws/aws-cdk/commit/b3c5fe8d0b695e06558bce23a6dd39b20265594f)) +* **efs:** fix bug when setting both lifecyclePolicy and outOfInfrequentAccessPolicy ([#19082](https://github.com/aws/aws-cdk/issues/19082)) ([d435ab6](https://github.com/aws/aws-cdk/commit/d435ab6120c47464427489d98bea9347983a2123)), closes [#19058](https://github.com/aws/aws-cdk/issues/19058) +* **lambda-nodejs:** local tsc detection with pre compilation ([#19266](https://github.com/aws/aws-cdk/issues/19266)) ([5de7b86](https://github.com/aws/aws-cdk/commit/5de7b86d916be6ab892e75e18c54a327fe1f65ff)), closes [#19242](https://github.com/aws/aws-cdk/issues/19242) +* **rds:** allow cluster from snapshot to enable encrypted storage ([#19175](https://github.com/aws/aws-cdk/issues/19175)) ([bd4141d](https://github.com/aws/aws-cdk/commit/bd4141d864612974829c95d530085d4f18bdfeb8)), closes [#17241](https://github.com/aws/aws-cdk/issues/17241) +* **rds:** read replica instance cannot join domain ([#19202](https://github.com/aws/aws-cdk/issues/19202)) ([cef8fec](https://github.com/aws/aws-cdk/commit/cef8fec1b0410daa6b57c152e9bad73dcc034397)), closes [#18786](https://github.com/aws/aws-cdk/issues/18786) +* **rds:** subnet selection not respected for multi user secret rotation ([#19237](https://github.com/aws/aws-cdk/issues/19237)) ([dc7a17c](https://github.com/aws/aws-cdk/commit/dc7a17cd20198a6eb52c2ab25857e73bd7048d26)), closes [#19233](https://github.com/aws/aws-cdk/issues/19233) + ## [2.15.0](https://github.com/aws/aws-cdk/compare/v2.14.0...v2.15.0) (2022-03-01) diff --git a/packages/@aws-cdk/aws-apigateway/README.md b/packages/@aws-cdk/aws-apigateway/README.md index 83e9d04cd31c6..8dae2d1cf9165 100644 --- a/packages/@aws-cdk/aws-apigateway/README.md +++ b/packages/@aws-cdk/aws-apigateway/README.md @@ -126,7 +126,7 @@ Other metadata such as billing details, AWS account ID and resource ARNs are not By default, a `prod` stage is provisioned. -In order to reduce the payload size sent to AWS Step Functions, `headers` are not forwarded to the Step Functions execution input. It is possible to choose whether `headers`, `requestContext`, `path` and `querystring` are included or not. By default, `headers` are excluded in all requests. +In order to reduce the payload size sent to AWS Step Functions, `headers` are not forwarded to the Step Functions execution input. It is possible to choose whether `headers`, `requestContext`, `path`, `querystring`, and `authorizer` are included or not. By default, `headers` are excluded in all requests. More details about AWS Step Functions payload limit can be found at https://docs.aws.amazon.com/step-functions/latest/dg/limits-overview.html#service-limits-task-executions. @@ -184,7 +184,7 @@ AWS Step Functions will receive the following execution input: } ``` -Additional information around the request such as the request context and headers can be included as part of the input +Additional information around the request such as the request context, authorizer context, and headers can be included as part of the input forwarded to the state machine. The following example enables headers to be included in the input but not query string. ```ts fixture=stepfunctions @@ -193,6 +193,7 @@ new apigateway.StepFunctionsRestApi(this, 'StepFunctionsRestApi', { headers: true, path: false, querystring: false, + authorizer: false, requestContext: { caller: true, user: true, diff --git a/packages/@aws-cdk/aws-apigateway/lib/integrations/stepfunctions.ts b/packages/@aws-cdk/aws-apigateway/lib/integrations/stepfunctions.ts index 339e7b2949198..f9461eb0b44e8 100644 --- a/packages/@aws-cdk/aws-apigateway/lib/integrations/stepfunctions.ts +++ b/packages/@aws-cdk/aws-apigateway/lib/integrations/stepfunctions.ts @@ -68,6 +68,20 @@ export interface StepFunctionsExecutionIntegrationOptions extends IntegrationOpt * @default false */ readonly headers?: boolean; + + /** + * If the whole authorizer object, including custom context values should be in the execution input. The execution input will include a new key `authorizer`: + * + * { + * "body": {}, + * "authorizer": { + * "key": "value" + * } + * } + * + * @default false + */ + readonly authorizer?: boolean; } /** @@ -189,7 +203,7 @@ function integrationResponse() { '#if($input.path(\'$.status\').toString().equals("FAILED"))', '#set($context.responseOverride.status = 500)', '{', - '"error": "$input.path(\'$.error\')"', + '"error": "$input.path(\'$.error\')",', '"cause": "$input.path(\'$.cause\')"', '}', '#else', @@ -241,6 +255,7 @@ function templateString( const includeHeader = options.headers?? false; const includeQueryString = options.querystring?? true; const includePath = options.path?? true; + const includeAuthorizer = options.authorizer ?? false; if (options.requestContext && Object.keys(options.requestContext).length > 0) { requestContextStr = requestContext(options.requestContext); @@ -251,6 +266,7 @@ function templateString( templateStr = templateStr.replace('%INCLUDE_HEADERS%', String(includeHeader)); templateStr = templateStr.replace('%INCLUDE_QUERYSTRING%', String(includeQueryString)); templateStr = templateStr.replace('%INCLUDE_PATH%', String(includePath)); + templateStr = templateStr.replace('%INCLUDE_AUTHORIZER%', String(includeAuthorizer)); templateStr = templateStr.replace('%REQUESTCONTEXT%', requestContextStr); return templateStr; diff --git a/packages/@aws-cdk/aws-apigateway/lib/integrations/stepfunctions.vtl b/packages/@aws-cdk/aws-apigateway/lib/integrations/stepfunctions.vtl index df4eda7c279d5..f389662efd6ed 100644 --- a/packages/@aws-cdk/aws-apigateway/lib/integrations/stepfunctions.vtl +++ b/packages/@aws-cdk/aws-apigateway/lib/integrations/stepfunctions.vtl @@ -9,6 +9,7 @@ #set($includeHeaders = %INCLUDE_HEADERS%) #set($includeQueryString = %INCLUDE_QUERYSTRING%) #set($includePath = %INCLUDE_PATH%) +#set($includeAuthorizer = %INCLUDE_AUTHORIZER%) #set($allParams = $input.params()) { "stateMachineArn": "%STATEMACHINE%", @@ -49,6 +50,17 @@ #set($inputString = "$inputString }") #end + #if ($includeAuthorizer) + #set($inputString = "$inputString, @@authorizer@@:{") + #foreach($paramName in $context.authorizer.keySet()) + #set($inputString = "$inputString @@$paramName@@: @@$util.escapeJavaScript($context.authorizer.get($paramName))@@") + #if($foreach.hasNext) + #set($inputString = "$inputString,") + #end + #end + #set($inputString = "$inputString }") + #end + #set($requestContext = "%REQUESTCONTEXT%") ## Check if the request context should be included as part of the execution input #if($requestContext && !$requestContext.empty) diff --git a/packages/@aws-cdk/aws-apigateway/lib/stepfunctions-api.ts b/packages/@aws-cdk/aws-apigateway/lib/stepfunctions-api.ts index 69addc0619383..bbae7158f1ac1 100644 --- a/packages/@aws-cdk/aws-apigateway/lib/stepfunctions-api.ts +++ b/packages/@aws-cdk/aws-apigateway/lib/stepfunctions-api.ts @@ -11,12 +11,12 @@ import { Model } from './model'; * */ export interface StepFunctionsRestApiProps extends RestApiProps { -/** - * The default State Machine that handles all requests from this API. - * - * This stateMachine will be used as a the default integration for all methods in - * this API, unless specified otherwise in `addMethod`. - */ + /** + * The default State Machine that handles all requests from this API. + * + * This stateMachine will be used as a the default integration for all methods in + * this API, unless specified otherwise in `addMethod`. + */ readonly stateMachine: sfn.IStateMachine; /** @@ -75,6 +75,20 @@ export interface StepFunctionsRestApiProps extends RestApiProps { * @default false */ readonly headers?: boolean; + + /** + * If the whole authorizer object, including custom context values should be in the execution input. The execution input will include a new key `authorizer`: + * + * { + * "body": {}, + * "authorizer": { + * "key": "value" + * } + * } + * + * @default false + */ + readonly authorizer?: boolean; } /** @@ -96,6 +110,7 @@ export class StepFunctionsRestApi extends RestApi { path: props.path?? true, querystring: props.querystring?? true, headers: props.headers, + authorizer: props.authorizer, }); super(scope, id, props); diff --git a/packages/@aws-cdk/aws-apigateway/test/integ.stepfunctions-api.expected.json b/packages/@aws-cdk/aws-apigateway/test/integ.stepfunctions-api.expected.json index 33976c0937cf5..afbccd88a73ae 100644 --- a/packages/@aws-cdk/aws-apigateway/test/integ.stepfunctions-api.expected.json +++ b/packages/@aws-cdk/aws-apigateway/test/integ.stepfunctions-api.expected.json @@ -160,7 +160,7 @@ "IntegrationResponses": [ { "ResponseTemplates": { - "application/json": "#set($inputRoot = $input.path('$'))\n#if($input.path('$.status').toString().equals(\"FAILED\"))\n#set($context.responseOverride.status = 500)\n{\n\"error\": \"$input.path('$.error')\"\n\"cause\": \"$input.path('$.cause')\"\n}\n#else\n$input.path('$.output')\n#end" + "application/json": "#set($inputRoot = $input.path('$'))\n#if($input.path('$.status').toString().equals(\"FAILED\"))\n#set($context.responseOverride.status = 500)\n{\n\"error\": \"$input.path('$.error')\",\n\"cause\": \"$input.path('$.cause')\"\n}\n#else\n$input.path('$.output')\n#end" }, "StatusCode": "200" }, @@ -185,11 +185,11 @@ "Fn::Join": [ "", [ - "## Velocity Template used for API Gateway request mapping template\n##\n## This template forwards the request body, header, path, and querystring\n## to the execution input of the state machine.\n##\n## \"@@\" is used here as a placeholder for '\"' to avoid using escape characters.\n\n#set($inputString = '')\n#set($includeHeaders = true)\n#set($includeQueryString = false)\n#set($includePath = false)\n#set($allParams = $input.params())\n{\n \"stateMachineArn\": \"", + "## Velocity Template used for API Gateway request mapping template\n##\n## This template forwards the request body, header, path, and querystring\n## to the execution input of the state machine.\n##\n## \"@@\" is used here as a placeholder for '\"' to avoid using escape characters.\n\n#set($inputString = '')\n#set($includeHeaders = true)\n#set($includeQueryString = false)\n#set($includePath = false)\n#set($includeAuthorizer = false)\n#set($allParams = $input.params())\n{\n \"stateMachineArn\": \"", { "Ref": "StateMachine2E01A3A5" }, - "\",\n\n #set($inputString = \"$inputString,@@body@@: $input.body\")\n\n #if ($includeHeaders)\n #set($inputString = \"$inputString, @@header@@:{\")\n #foreach($paramName in $allParams.header.keySet())\n #set($inputString = \"$inputString @@$paramName@@: @@$util.escapeJavaScript($allParams.header.get($paramName))@@\")\n #if($foreach.hasNext)\n #set($inputString = \"$inputString,\")\n #end\n #end\n #set($inputString = \"$inputString }\")\n \n #end\n\n #if ($includeQueryString)\n #set($inputString = \"$inputString, @@querystring@@:{\")\n #foreach($paramName in $allParams.querystring.keySet())\n #set($inputString = \"$inputString @@$paramName@@: @@$util.escapeJavaScript($allParams.querystring.get($paramName))@@\")\n #if($foreach.hasNext)\n #set($inputString = \"$inputString,\")\n #end\n #end\n #set($inputString = \"$inputString }\")\n #end\n\n #if ($includePath)\n #set($inputString = \"$inputString, @@path@@:{\")\n #foreach($paramName in $allParams.path.keySet())\n #set($inputString = \"$inputString @@$paramName@@: @@$util.escapeJavaScript($allParams.path.get($paramName))@@\")\n #if($foreach.hasNext)\n #set($inputString = \"$inputString,\")\n #end\n #end\n #set($inputString = \"$inputString }\")\n #end\n \n #set($requestContext = \"{@@accountId@@:@@$context.identity.accountId@@,@@userArn@@:@@$context.identity.userArn@@}\")\n ## Check if the request context should be included as part of the execution input\n #if($requestContext && !$requestContext.empty)\n #set($inputString = \"$inputString,\")\n #set($inputString = \"$inputString @@requestContext@@: $requestContext\")\n #end\n\n #set($inputString = \"$inputString}\")\n #set($inputString = $inputString.replaceAll(\"@@\",'\"'))\n #set($len = $inputString.length() - 1)\n \"input\": \"{$util.escapeJavaScript($inputString.substring(1,$len))}\"\n}\n" + "\",\n\n #set($inputString = \"$inputString,@@body@@: $input.body\")\n\n #if ($includeHeaders)\n #set($inputString = \"$inputString, @@header@@:{\")\n #foreach($paramName in $allParams.header.keySet())\n #set($inputString = \"$inputString @@$paramName@@: @@$util.escapeJavaScript($allParams.header.get($paramName))@@\")\n #if($foreach.hasNext)\n #set($inputString = \"$inputString,\")\n #end\n #end\n #set($inputString = \"$inputString }\")\n \n #end\n\n #if ($includeQueryString)\n #set($inputString = \"$inputString, @@querystring@@:{\")\n #foreach($paramName in $allParams.querystring.keySet())\n #set($inputString = \"$inputString @@$paramName@@: @@$util.escapeJavaScript($allParams.querystring.get($paramName))@@\")\n #if($foreach.hasNext)\n #set($inputString = \"$inputString,\")\n #end\n #end\n #set($inputString = \"$inputString }\")\n #end\n\n #if ($includePath)\n #set($inputString = \"$inputString, @@path@@:{\")\n #foreach($paramName in $allParams.path.keySet())\n #set($inputString = \"$inputString @@$paramName@@: @@$util.escapeJavaScript($allParams.path.get($paramName))@@\")\n #if($foreach.hasNext)\n #set($inputString = \"$inputString,\")\n #end\n #end\n #set($inputString = \"$inputString }\")\n #end\n \n #if ($includeAuthorizer)\n #set($inputString = \"$inputString, @@authorizer@@:{\")\n #foreach($paramName in $context.authorizer.keySet())\n #set($inputString = \"$inputString @@$paramName@@: @@$util.escapeJavaScript($context.authorizer.get($paramName))@@\")\n #if($foreach.hasNext)\n #set($inputString = \"$inputString,\")\n #end\n #end\n #set($inputString = \"$inputString }\")\n #end\n\n #set($requestContext = \"{@@accountId@@:@@$context.identity.accountId@@,@@userArn@@:@@$context.identity.userArn@@}\")\n ## Check if the request context should be included as part of the execution input\n #if($requestContext && !$requestContext.empty)\n #set($inputString = \"$inputString,\")\n #set($inputString = \"$inputString @@requestContext@@: $requestContext\")\n #end\n\n #set($inputString = \"$inputString}\")\n #set($inputString = $inputString.replaceAll(\"@@\",'\"'))\n #set($len = $inputString.length() - 1)\n \"input\": \"{$util.escapeJavaScript($inputString.substring(1,$len))}\"\n}\n" ] ] } diff --git a/packages/@aws-cdk/aws-apigateway/test/integrations/stepfunctions.test.ts b/packages/@aws-cdk/aws-apigateway/test/integrations/stepfunctions.test.ts index 830ca2a8e2000..32fd13c5741c0 100644 --- a/packages/@aws-cdk/aws-apigateway/test/integrations/stepfunctions.test.ts +++ b/packages/@aws-cdk/aws-apigateway/test/integrations/stepfunctions.test.ts @@ -52,11 +52,11 @@ describe('StepFunctionsIntegration', () => { 'Fn::Join': [ '', [ - "## Velocity Template used for API Gateway request mapping template\n##\n## This template forwards the request body, header, path, and querystring\n## to the execution input of the state machine.\n##\n## \"@@\" is used here as a placeholder for '\"' to avoid using escape characters.\n\n#set($inputString = '')\n#set($includeHeaders = false)\n#set($includeQueryString = true)\n#set($includePath = true)\n#set($allParams = $input.params())\n{\n \"stateMachineArn\": \"", + "## Velocity Template used for API Gateway request mapping template\n##\n## This template forwards the request body, header, path, and querystring\n## to the execution input of the state machine.\n##\n## \"@@\" is used here as a placeholder for '\"' to avoid using escape characters.\n\n#set($inputString = '')\n#set($includeHeaders = false)\n#set($includeQueryString = true)\n#set($includePath = true)\n#set($includeAuthorizer = false)\n#set($allParams = $input.params())\n{\n \"stateMachineArn\": \"", { Ref: 'StateMachine2E01A3A5', }, - "\",\n\n #set($inputString = \"$inputString,@@body@@: $input.body\")\n\n #if ($includeHeaders)\n #set($inputString = \"$inputString, @@header@@:{\")\n #foreach($paramName in $allParams.header.keySet())\n #set($inputString = \"$inputString @@$paramName@@: @@$util.escapeJavaScript($allParams.header.get($paramName))@@\")\n #if($foreach.hasNext)\n #set($inputString = \"$inputString,\")\n #end\n #end\n #set($inputString = \"$inputString }\")\n \n #end\n\n #if ($includeQueryString)\n #set($inputString = \"$inputString, @@querystring@@:{\")\n #foreach($paramName in $allParams.querystring.keySet())\n #set($inputString = \"$inputString @@$paramName@@: @@$util.escapeJavaScript($allParams.querystring.get($paramName))@@\")\n #if($foreach.hasNext)\n #set($inputString = \"$inputString,\")\n #end\n #end\n #set($inputString = \"$inputString }\")\n #end\n\n #if ($includePath)\n #set($inputString = \"$inputString, @@path@@:{\")\n #foreach($paramName in $allParams.path.keySet())\n #set($inputString = \"$inputString @@$paramName@@: @@$util.escapeJavaScript($allParams.path.get($paramName))@@\")\n #if($foreach.hasNext)\n #set($inputString = \"$inputString,\")\n #end\n #end\n #set($inputString = \"$inputString }\")\n #end\n \n #set($requestContext = \"\")\n ## Check if the request context should be included as part of the execution input\n #if($requestContext && !$requestContext.empty)\n #set($inputString = \"$inputString,\")\n #set($inputString = \"$inputString @@requestContext@@: $requestContext\")\n #end\n\n #set($inputString = \"$inputString}\")\n #set($inputString = $inputString.replaceAll(\"@@\",'\"'))\n #set($len = $inputString.length() - 1)\n \"input\": \"{$util.escapeJavaScript($inputString.substring(1,$len))}\"\n}\n", + "\",\n\n #set($inputString = \"$inputString,@@body@@: $input.body\")\n\n #if ($includeHeaders)\n #set($inputString = \"$inputString, @@header@@:{\")\n #foreach($paramName in $allParams.header.keySet())\n #set($inputString = \"$inputString @@$paramName@@: @@$util.escapeJavaScript($allParams.header.get($paramName))@@\")\n #if($foreach.hasNext)\n #set($inputString = \"$inputString,\")\n #end\n #end\n #set($inputString = \"$inputString }\")\n \n #end\n\n #if ($includeQueryString)\n #set($inputString = \"$inputString, @@querystring@@:{\")\n #foreach($paramName in $allParams.querystring.keySet())\n #set($inputString = \"$inputString @@$paramName@@: @@$util.escapeJavaScript($allParams.querystring.get($paramName))@@\")\n #if($foreach.hasNext)\n #set($inputString = \"$inputString,\")\n #end\n #end\n #set($inputString = \"$inputString }\")\n #end\n\n #if ($includePath)\n #set($inputString = \"$inputString, @@path@@:{\")\n #foreach($paramName in $allParams.path.keySet())\n #set($inputString = \"$inputString @@$paramName@@: @@$util.escapeJavaScript($allParams.path.get($paramName))@@\")\n #if($foreach.hasNext)\n #set($inputString = \"$inputString,\")\n #end\n #end\n #set($inputString = \"$inputString }\")\n #end\n \n #if ($includeAuthorizer)\n #set($inputString = \"$inputString, @@authorizer@@:{\")\n #foreach($paramName in $context.authorizer.keySet())\n #set($inputString = \"$inputString @@$paramName@@: @@$util.escapeJavaScript($context.authorizer.get($paramName))@@\")\n #if($foreach.hasNext)\n #set($inputString = \"$inputString,\")\n #end\n #end\n #set($inputString = \"$inputString }\")\n #end\n\n #set($requestContext = \"\")\n ## Check if the request context should be included as part of the execution input\n #if($requestContext && !$requestContext.empty)\n #set($inputString = \"$inputString,\")\n #set($inputString = \"$inputString @@requestContext@@: $requestContext\")\n #end\n\n #set($inputString = \"$inputString}\")\n #set($inputString = $inputString.replaceAll(\"@@\",'\"'))\n #set($len = $inputString.length() - 1)\n \"input\": \"{$util.escapeJavaScript($inputString.substring(1,$len))}\"\n}\n", ], ], }, @@ -264,6 +264,34 @@ describe('StepFunctionsIntegration', () => { }); }); + test('authorizer context is included when specified by the integration', () => { + //GIVEN + const { stack, api, stateMachine } = givenSetup(); + + //WHEN + const integ = apigw.StepFunctionsIntegration.startExecution(stateMachine, { + authorizer: true, + }); + api.root.addMethod('GET', integ); + + Template.fromStack(stack).hasResourceProperties('AWS::ApiGateway::Method', { + Integration: { + RequestTemplates: { + 'application/json': { + 'Fn::Join': [ + '', + [ + Match.stringLikeRegexp('#set\\(\\$includeAuthorizer = true\\)'), + { Ref: 'StateMachine2E01A3A5' }, + Match.anyValue(), + ], + ], + }, + }, + }, + }); + }); + test('works for imported RestApi', () => { const stack = new cdk.Stack(); const api = apigw.RestApi.fromRestApiAttributes(stack, 'RestApi', { @@ -390,7 +418,7 @@ function getIntegrationResponse() { '#if($input.path(\'$.status\').toString().equals("FAILED"))', '#set($context.responseOverride.status = 500)', '{', - '"error": "$input.path(\'$.error\')"', + '"error": "$input.path(\'$.error\')",', '"cause": "$input.path(\'$.cause\')"', '}', '#else', diff --git a/packages/@aws-cdk/aws-apigateway/test/stepfunctions-api.test.ts b/packages/@aws-cdk/aws-apigateway/test/stepfunctions-api.test.ts index 51426a4ffe6c3..5922d61025965 100644 --- a/packages/@aws-cdk/aws-apigateway/test/stepfunctions-api.test.ts +++ b/packages/@aws-cdk/aws-apigateway/test/stepfunctions-api.test.ts @@ -44,11 +44,11 @@ describe('Step Functions api', () => { 'Fn::Join': [ '', [ - "## Velocity Template used for API Gateway request mapping template\n##\n## This template forwards the request body, header, path, and querystring\n## to the execution input of the state machine.\n##\n## \"@@\" is used here as a placeholder for '\"' to avoid using escape characters.\n\n#set($inputString = '')\n#set($includeHeaders = false)\n#set($includeQueryString = true)\n#set($includePath = true)\n#set($allParams = $input.params())\n{\n \"stateMachineArn\": \"", + "## Velocity Template used for API Gateway request mapping template\n##\n## This template forwards the request body, header, path, and querystring\n## to the execution input of the state machine.\n##\n## \"@@\" is used here as a placeholder for '\"' to avoid using escape characters.\n\n#set($inputString = '')\n#set($includeHeaders = false)\n#set($includeQueryString = true)\n#set($includePath = true)\n#set($includeAuthorizer = false)\n#set($allParams = $input.params())\n{\n \"stateMachineArn\": \"", { Ref: 'StateMachine2E01A3A5', }, - "\",\n\n #set($inputString = \"$inputString,@@body@@: $input.body\")\n\n #if ($includeHeaders)\n #set($inputString = \"$inputString, @@header@@:{\")\n #foreach($paramName in $allParams.header.keySet())\n #set($inputString = \"$inputString @@$paramName@@: @@$util.escapeJavaScript($allParams.header.get($paramName))@@\")\n #if($foreach.hasNext)\n #set($inputString = \"$inputString,\")\n #end\n #end\n #set($inputString = \"$inputString }\")\n \n #end\n\n #if ($includeQueryString)\n #set($inputString = \"$inputString, @@querystring@@:{\")\n #foreach($paramName in $allParams.querystring.keySet())\n #set($inputString = \"$inputString @@$paramName@@: @@$util.escapeJavaScript($allParams.querystring.get($paramName))@@\")\n #if($foreach.hasNext)\n #set($inputString = \"$inputString,\")\n #end\n #end\n #set($inputString = \"$inputString }\")\n #end\n\n #if ($includePath)\n #set($inputString = \"$inputString, @@path@@:{\")\n #foreach($paramName in $allParams.path.keySet())\n #set($inputString = \"$inputString @@$paramName@@: @@$util.escapeJavaScript($allParams.path.get($paramName))@@\")\n #if($foreach.hasNext)\n #set($inputString = \"$inputString,\")\n #end\n #end\n #set($inputString = \"$inputString }\")\n #end\n \n #set($requestContext = \"\")\n ## Check if the request context should be included as part of the execution input\n #if($requestContext && !$requestContext.empty)\n #set($inputString = \"$inputString,\")\n #set($inputString = \"$inputString @@requestContext@@: $requestContext\")\n #end\n\n #set($inputString = \"$inputString}\")\n #set($inputString = $inputString.replaceAll(\"@@\",'\"'))\n #set($len = $inputString.length() - 1)\n \"input\": \"{$util.escapeJavaScript($inputString.substring(1,$len))}\"\n}\n", + "\",\n\n #set($inputString = \"$inputString,@@body@@: $input.body\")\n\n #if ($includeHeaders)\n #set($inputString = \"$inputString, @@header@@:{\")\n #foreach($paramName in $allParams.header.keySet())\n #set($inputString = \"$inputString @@$paramName@@: @@$util.escapeJavaScript($allParams.header.get($paramName))@@\")\n #if($foreach.hasNext)\n #set($inputString = \"$inputString,\")\n #end\n #end\n #set($inputString = \"$inputString }\")\n \n #end\n\n #if ($includeQueryString)\n #set($inputString = \"$inputString, @@querystring@@:{\")\n #foreach($paramName in $allParams.querystring.keySet())\n #set($inputString = \"$inputString @@$paramName@@: @@$util.escapeJavaScript($allParams.querystring.get($paramName))@@\")\n #if($foreach.hasNext)\n #set($inputString = \"$inputString,\")\n #end\n #end\n #set($inputString = \"$inputString }\")\n #end\n\n #if ($includePath)\n #set($inputString = \"$inputString, @@path@@:{\")\n #foreach($paramName in $allParams.path.keySet())\n #set($inputString = \"$inputString @@$paramName@@: @@$util.escapeJavaScript($allParams.path.get($paramName))@@\")\n #if($foreach.hasNext)\n #set($inputString = \"$inputString,\")\n #end\n #end\n #set($inputString = \"$inputString }\")\n #end\n \n #if ($includeAuthorizer)\n #set($inputString = \"$inputString, @@authorizer@@:{\")\n #foreach($paramName in $context.authorizer.keySet())\n #set($inputString = \"$inputString @@$paramName@@: @@$util.escapeJavaScript($context.authorizer.get($paramName))@@\")\n #if($foreach.hasNext)\n #set($inputString = \"$inputString,\")\n #end\n #end\n #set($inputString = \"$inputString }\")\n #end\n\n #set($requestContext = \"\")\n ## Check if the request context should be included as part of the execution input\n #if($requestContext && !$requestContext.empty)\n #set($inputString = \"$inputString,\")\n #set($inputString = \"$inputString @@requestContext@@: $requestContext\")\n #end\n\n #set($inputString = \"$inputString}\")\n #set($inputString = $inputString.replaceAll(\"@@\",'\"'))\n #set($len = $inputString.length() - 1)\n \"input\": \"{$util.escapeJavaScript($inputString.substring(1,$len))}\"\n}\n", ], ], }, @@ -181,7 +181,7 @@ function getIntegrationResponse() { '#if($input.path(\'$.status\').toString().equals("FAILED"))', '#set($context.responseOverride.status = 500)', '{', - '"error": "$input.path(\'$.error\')"', + '"error": "$input.path(\'$.error\')",', '"cause": "$input.path(\'$.cause\')"', '}', '#else', diff --git a/packages/@aws-cdk/aws-apigatewayv2-integrations/lib/http/lambda.ts b/packages/@aws-cdk/aws-apigatewayv2-integrations/lib/http/lambda.ts index 2417fffe1610d..69019e0c2866a 100644 --- a/packages/@aws-cdk/aws-apigatewayv2-integrations/lib/http/lambda.ts +++ b/packages/@aws-cdk/aws-apigatewayv2-integrations/lib/http/lambda.ts @@ -50,7 +50,7 @@ export class HttpLambdaIntegration extends HttpRouteIntegration { this._id = id; } - public bind(options: HttpRouteIntegrationBindOptions): HttpRouteIntegrationConfig { + protected completeBind(options: HttpRouteIntegrationBindOptions) { const route = options.route; this.handler.addPermission(`${this._id}-Permission`, { scope: options.scope, @@ -61,7 +61,9 @@ export class HttpLambdaIntegration extends HttpRouteIntegration { resourceName: `*/*${route.path ?? ''}`, // empty string in the case of the catch-all route $default }), }); + } + public bind(_: HttpRouteIntegrationBindOptions): HttpRouteIntegrationConfig { return { type: HttpIntegrationType.AWS_PROXY, uri: this.handler.functionArn, diff --git a/packages/@aws-cdk/aws-apigatewayv2-integrations/test/http/lambda.test.ts b/packages/@aws-cdk/aws-apigatewayv2-integrations/test/http/lambda.test.ts index 5c318e1629842..f832921ad995b 100644 --- a/packages/@aws-cdk/aws-apigatewayv2-integrations/test/http/lambda.test.ts +++ b/packages/@aws-cdk/aws-apigatewayv2-integrations/test/http/lambda.test.ts @@ -1,4 +1,4 @@ -import { Template } from '@aws-cdk/assertions'; +import { Match, Template } from '@aws-cdk/assertions'; import { HttpApi, HttpRoute, HttpRouteKey, MappingValue, ParameterMapping, PayloadFormatVersion } from '@aws-cdk/aws-apigatewayv2'; import { Code, Function, Runtime } from '@aws-cdk/aws-lambda'; import { App, Stack } from '@aws-cdk/core'; @@ -71,6 +71,41 @@ describe('LambdaProxyIntegration', () => { expect(() => app.synth()).not.toThrow(); }); + + test('multiple routes for the same lambda integration', () => { + const app = new App(); + const lambdaStack = new Stack(app, 'lambdaStack'); + const fooFn = fooFunction(lambdaStack, 'Fn'); + + const stack = new Stack(app, 'apigwStack'); + const api = new HttpApi(stack, 'httpApi'); + const integration = new HttpLambdaIntegration('Integration', fooFn); + + api.addRoutes({ + path: '/foo', + integration, + }); + + api.addRoutes({ + path: '/bar', + integration, + }); + + // Make sure we have two permissions -- one for each method -- but a single integration + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Permission', { + SourceArn: { + 'Fn::Join': ['', Match.arrayWith([':execute-api:', '/*/*/foo'])], + }, + }); + + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Permission', { + SourceArn: { + 'Fn::Join': ['', Match.arrayWith([':execute-api:', '/*/*/bar'])], + }, + }); + + Template.fromStack(stack).resourceCountIs('AWS::ApiGatewayV2::Integration', 1); + }); }); function fooFunction(stack: Stack, id: string) { diff --git a/packages/@aws-cdk/aws-apigatewayv2/lib/http/integration.ts b/packages/@aws-cdk/aws-apigatewayv2/lib/http/integration.ts index 7b38e1e526028..827904de96918 100644 --- a/packages/@aws-cdk/aws-apigatewayv2/lib/http/integration.ts +++ b/packages/@aws-cdk/aws-apigatewayv2/lib/http/integration.ts @@ -328,9 +328,22 @@ export abstract class HttpRouteIntegration { credentials: config.credentials, }); } + this.completeBind(options); return { integrationId: this.integration.integrationId }; } + /** + * Complete the binding of the integration to the route. In some cases, there is + * some additional work to do, such as adding permissions for the API to access + * the target. This work is necessary whether the integration has just been + * created for this route or it is an existing one, previously created for other + * routes. In most cases, however, concrete implementations do not need to + * override this method. + */ + protected completeBind(_options: HttpRouteIntegrationBindOptions): void { + // no-op by default + } + /** * Bind this integration to the route. */ diff --git a/packages/@aws-cdk/aws-codebuild/README.md b/packages/@aws-cdk/aws-codebuild/README.md index 4bccbbc68cfa1..3be027de2404c 100644 --- a/packages/@aws-cdk/aws-codebuild/README.md +++ b/packages/@aws-cdk/aws-codebuild/README.md @@ -280,11 +280,12 @@ can use the `environment` property to customize the build environment: ## Images The CodeBuild library supports both Linux and Windows images via the -`LinuxBuildImage` and `WindowsBuildImage` classes, respectively. +`LinuxBuildImage` (or `LinuxArmBuildImage`), and `WindowsBuildImage` classes, respectively. You can specify one of the predefined Windows/Linux images by using one of the constants such as `WindowsBuildImage.WIN_SERVER_CORE_2019_BASE`, -`WindowsBuildImage.WINDOWS_BASE_2_0` or `LinuxBuildImage.STANDARD_2_0`. +`WindowsBuildImage.WINDOWS_BASE_2_0`, `LinuxBuildImage.STANDARD_2_0`, or +`LinuxArmBuildImage.AMAZON_LINUX_2_ARM`. Alternatively, you can specify a custom image using one of the static methods on `LinuxBuildImage`: @@ -302,6 +303,10 @@ or one of the corresponding methods on `WindowsBuildImage`: * `WindowsBuildImage.fromEcrRepository(repo[, tag, imageType])` * `WindowsBuildImage.fromAsset(parent, id, props, [, imageType])` +or one of the corresponding methods on `LinuxArmBuildImage`: + +* `LinuxArmBuildImage.fromEcrRepository(repo[, tag])` + Note that the `WindowsBuildImage` version of the static methods accepts an optional parameter of type `WindowsImageType`, which can be either `WindowsImageType.STANDARD`, the default, or `WindowsImageType.SERVER_2019`: diff --git a/packages/@aws-cdk/aws-codebuild/lib/index.ts b/packages/@aws-cdk/aws-codebuild/lib/index.ts index 5c2de5f3119c2..e2abd2da98db8 100644 --- a/packages/@aws-cdk/aws-codebuild/lib/index.ts +++ b/packages/@aws-cdk/aws-codebuild/lib/index.ts @@ -11,6 +11,7 @@ export * from './build-spec'; export * from './file-location'; export * from './linux-gpu-build-image'; export * from './untrusted-code-boundary-policy'; +export * from './linux-arm-build-image'; // AWS::CodeBuild CloudFormation Resources: export * from './codebuild.generated'; diff --git a/packages/@aws-cdk/aws-codebuild/lib/linux-arm-build-image.ts b/packages/@aws-cdk/aws-codebuild/lib/linux-arm-build-image.ts new file mode 100644 index 0000000000000..12a7d2e54daf6 --- /dev/null +++ b/packages/@aws-cdk/aws-codebuild/lib/linux-arm-build-image.ts @@ -0,0 +1,105 @@ +import * as ecr from '@aws-cdk/aws-ecr'; +import * as secretsmanager from '@aws-cdk/aws-secretsmanager'; +import { BuildSpec } from './build-spec'; +import { runScriptLinuxBuildSpec } from './private/run-script-linux-build-spec'; +import { BuildEnvironment, ComputeType, IBuildImage, ImagePullPrincipalType } from './project'; + +/** + * Construction properties of {@link LinuxArmBuildImage}. + * Module-private, as the constructor of {@link LinuxArmBuildImage} is private. + */ +interface LinuxArmBuildImageProps { + readonly imageId: string; + readonly imagePullPrincipalType?: ImagePullPrincipalType; + readonly secretsManagerCredentials?: secretsmanager.ISecret; + readonly repository?: ecr.IRepository; +} + +/** + * A CodeBuild image running aarch64 Linux. + * + * This class has a bunch of public constants that represent the CodeBuild ARM images. + * + * You can also specify a custom image using the static method: + * + * - LinuxBuildImage.fromEcrRepository(repo[, tag]) + * + * + * @see https://docs.aws.amazon.com/codebuild/latest/userguide/build-env-ref-available.html + */ +export class LinuxArmBuildImage implements IBuildImage { + /** Image "aws/codebuild/amazonlinux2-aarch64-standard:1.0". */ + public static readonly AMAZON_LINUX_2_STANDARD_1_0 = LinuxArmBuildImage.fromCodeBuildImageId('aws/codebuild/amazonlinux2-aarch64-standard:1.0'); + /** Image "aws/codebuild/amazonlinux2-aarch64-standard:2.0". */ + public static readonly AMAZON_LINUX_2_STANDARD_2_0 = LinuxArmBuildImage.fromCodeBuildImageId('aws/codebuild/amazonlinux2-aarch64-standard:2.0'); + + /** + * Returns an ARM image running Linux from an ECR repository. + * + * NOTE: if the repository is external (i.e. imported), then we won't be able to add + * a resource policy statement for it so CodeBuild can pull the image. + * + * @see https://docs.aws.amazon.com/codebuild/latest/userguide/sample-ecr.html + * + * @param repository The ECR repository + * @param tag Image tag (default "latest") + * @returns An aarch64 Linux build image from an ECR repository. + */ + public static fromEcrRepository(repository: ecr.IRepository, tag: string = 'latest'): IBuildImage { + return new LinuxArmBuildImage({ + imageId: repository.repositoryUriForTag(tag), + imagePullPrincipalType: ImagePullPrincipalType.SERVICE_ROLE, + repository, + }); + } + + /** + * Uses a Docker image provided by CodeBuild. + * + * @see https://docs.aws.amazon.com/codebuild/latest/userguide/build-env-ref-available.html + * + * @param id The image identifier + * @example 'aws/codebuild/amazonlinux2-aarch64-standard:1.0' + * @returns A Docker image provided by CodeBuild. + */ + public static fromCodeBuildImageId(id: string): IBuildImage { + return new LinuxArmBuildImage({ + imageId: id, + imagePullPrincipalType: ImagePullPrincipalType.CODEBUILD, + }); + } + + public readonly type = 'ARM_CONTAINER'; + public readonly defaultComputeType = ComputeType.LARGE; + public readonly imageId: string; + public readonly imagePullPrincipalType?: ImagePullPrincipalType; + public readonly secretsManagerCredentials?: secretsmanager.ISecret; + public readonly repository?: ecr.IRepository; + + private constructor(props: LinuxArmBuildImageProps) { + this.imageId = props.imageId; + this.imagePullPrincipalType = props.imagePullPrincipalType; + this.secretsManagerCredentials = props.secretsManagerCredentials; + this.repository = props.repository; + } + + /** + * Validates by checking the BuildEnvironment computeType as aarch64 images only support ComputeType.SMALL and + * ComputeType.LARGE + * @param buildEnvironment BuildEnvironment + */ + public validate(buildEnvironment: BuildEnvironment): string[] { + const ret = []; + if (buildEnvironment.computeType && + buildEnvironment.computeType !== ComputeType.SMALL && + buildEnvironment.computeType !== ComputeType.LARGE) { + ret.push(`ARM images only support ComputeTypes '${ComputeType.SMALL}' and '${ComputeType.LARGE}' - ` + + `'${buildEnvironment.computeType}' was given`); + } + return ret; + } + + public runScriptBuildspec(entrypoint: string): BuildSpec { + return runScriptLinuxBuildSpec(entrypoint); + } +} diff --git a/packages/@aws-cdk/aws-codebuild/lib/project.ts b/packages/@aws-cdk/aws-codebuild/lib/project.ts index 77c5d8a445a08..8cc6917dd78cd 100644 --- a/packages/@aws-cdk/aws-codebuild/lib/project.ts +++ b/packages/@aws-cdk/aws-codebuild/lib/project.ts @@ -1637,32 +1637,6 @@ export interface IBindableBuildImage extends IBuildImage { bind(scope: Construct, project: IProject, options: BuildImageBindOptions): BuildImageConfig; } -class ArmBuildImage implements IBuildImage { - public readonly type = 'ARM_CONTAINER'; - public readonly defaultComputeType = ComputeType.LARGE; - public readonly imagePullPrincipalType = ImagePullPrincipalType.CODEBUILD; - public readonly imageId: string; - - constructor(imageId: string) { - this.imageId = imageId; - } - - public validate(buildEnvironment: BuildEnvironment): string[] { - const ret = []; - if (buildEnvironment.computeType && - buildEnvironment.computeType !== ComputeType.SMALL && - buildEnvironment.computeType !== ComputeType.LARGE) { - ret.push(`ARM images only support ComputeTypes '${ComputeType.SMALL}' and '${ComputeType.LARGE}' - ` + - `'${buildEnvironment.computeType}' was given`); - } - return ret; - } - - public runScriptBuildspec(entrypoint: string): BuildSpec { - return runScriptLinuxBuildSpec(entrypoint); - } -} - /** * The options when creating a CodeBuild Docker build image * using {@link LinuxBuildImage.fromDockerRegistry} @@ -1690,8 +1664,12 @@ interface LinuxBuildImageProps { readonly repository?: ecr.IRepository; } +// Keep around to resolve a circular dependency until removing deprecated ARM image constants from LinuxBuildImage +// eslint-disable-next-line no-duplicate-imports, import/order +import { LinuxArmBuildImage } from './linux-arm-build-image'; + /** - * A CodeBuild image running Linux. + * A CodeBuild image running x86-64 Linux. * * This class has a bunch of public constants that represent the most popular images. * @@ -1718,9 +1696,13 @@ export class LinuxBuildImage implements IBuildImage { /** The Amazon Linux 2 x86_64 standard image, version `3.0`. */ public static readonly AMAZON_LINUX_2_3 = LinuxBuildImage.codeBuildImage('aws/codebuild/amazonlinux2-x86_64-standard:3.0'); - public static readonly AMAZON_LINUX_2_ARM: IBuildImage = new ArmBuildImage('aws/codebuild/amazonlinux2-aarch64-standard:1.0'); - /** Image "aws/codebuild/amazonlinux2-aarch64-standard:2.0". */ - public static readonly AMAZON_LINUX_2_ARM_2: IBuildImage = new ArmBuildImage('aws/codebuild/amazonlinux2-aarch64-standard:2.0'); + /** @deprecated Use LinuxArmBuildImage.AMAZON_LINUX_2_STANDARD_1_0 instead. */ + public static readonly AMAZON_LINUX_2_ARM = LinuxArmBuildImage.AMAZON_LINUX_2_STANDARD_1_0; + /** + * Image "aws/codebuild/amazonlinux2-aarch64-standard:2.0". + * @deprecated Use LinuxArmBuildImage.AMAZON_LINUX_2_STANDARD_2_0 instead. + * */ + public static readonly AMAZON_LINUX_2_ARM_2 = LinuxArmBuildImage.AMAZON_LINUX_2_STANDARD_2_0; /** @deprecated Use {@link STANDARD_2_0} and specify runtime in buildspec runtime-versions section */ public static readonly UBUNTU_14_04_BASE = LinuxBuildImage.codeBuildImage('aws/codebuild/ubuntu-base:14.04'); @@ -1784,7 +1766,7 @@ export class LinuxBuildImage implements IBuildImage { public static readonly UBUNTU_14_04_DOTNET_CORE_2_1 = LinuxBuildImage.codeBuildImage('aws/codebuild/dot-net:core-2.1'); /** - * @returns a Linux build image from a Docker Hub image. + * @returns a x86-64 Linux build image from a Docker Hub image. */ public static fromDockerRegistry(name: string, options: DockerImageOptions = {}): IBuildImage { return new LinuxBuildImage({ @@ -1795,7 +1777,7 @@ export class LinuxBuildImage implements IBuildImage { } /** - * @returns A Linux build image from an ECR repository. + * @returns A x86-64 Linux build image from an ECR repository. * * NOTE: if the repository is external (i.e. imported), then we won't be able to add * a resource policy statement for it so CodeBuild can pull the image. @@ -1814,7 +1796,7 @@ export class LinuxBuildImage implements IBuildImage { } /** - * Uses an Docker image asset as a Linux build image. + * Uses an Docker image asset as a x86-64 Linux build image. */ public static fromAsset(scope: Construct, id: string, props: DockerImageAssetProps): IBuildImage { const asset = new DockerImageAsset(scope, id, props); @@ -1956,7 +1938,7 @@ export class WindowsBuildImage implements IBuildImage { } /** - * @returns A Linux build image from an ECR repository. + * @returns A Windows build image from an ECR repository. * * NOTE: if the repository is external (i.e. imported), then we won't be able to add * a resource policy statement for it so CodeBuild can pull the image. @@ -2120,4 +2102,4 @@ export enum ProjectNotificationEvents { function isBindableBuildImage(x: unknown): x is IBindableBuildImage { return typeof x === 'object' && !!x && !!(x as any).bind; -} \ No newline at end of file +} diff --git a/packages/@aws-cdk/aws-codebuild/test/linux-arm-build-image.test.ts b/packages/@aws-cdk/aws-codebuild/test/linux-arm-build-image.test.ts new file mode 100644 index 0000000000000..389fbc0529b22 --- /dev/null +++ b/packages/@aws-cdk/aws-codebuild/test/linux-arm-build-image.test.ts @@ -0,0 +1,328 @@ +import { Match, Template } from '@aws-cdk/assertions'; +import * as ecr from '@aws-cdk/aws-ecr'; +import * as cdk from '@aws-cdk/core'; +import * as codebuild from '../lib'; + +describe('Linux ARM build image', () => { + describe('AMAZON_LINUX_2_STANDARD_1_0', () => { + test('has type ARM_CONTAINER and default ComputeType LARGE', () => { + const stack = new cdk.Stack(); + new codebuild.PipelineProject(stack, 'Project', { + environment: { + buildImage: codebuild.LinuxArmBuildImage.AMAZON_LINUX_2_STANDARD_1_0, + }, + }); + + Template.fromStack(stack).hasResourceProperties('AWS::CodeBuild::Project', { + Environment: { + Type: 'ARM_CONTAINER', + ComputeType: 'BUILD_GENERAL1_LARGE', + }, + }); + }); + + test('can be used with ComputeType SMALL', () => { + const stack = new cdk.Stack(); + new codebuild.PipelineProject(stack, 'Project', { + environment: { + computeType: codebuild.ComputeType.SMALL, + buildImage: codebuild.LinuxArmBuildImage.AMAZON_LINUX_2_STANDARD_1_0, + }, + }); + + Template.fromStack(stack).hasResourceProperties('AWS::CodeBuild::Project', { + Environment: { + Type: 'ARM_CONTAINER', + ComputeType: 'BUILD_GENERAL1_SMALL', + }, + }); + }); + + test('cannot be used in conjunction with ComputeType MEDIUM', () => { + const stack = new cdk.Stack(); + + expect(() => { + new codebuild.PipelineProject(stack, 'Project', { + environment: { + buildImage: codebuild.LinuxArmBuildImage.AMAZON_LINUX_2_STANDARD_1_0, + computeType: codebuild.ComputeType.MEDIUM, + }, + }); + }).toThrow(/ARM images only support ComputeTypes 'BUILD_GENERAL1_SMALL' and 'BUILD_GENERAL1_LARGE' - 'BUILD_GENERAL1_MEDIUM' was given/); + }); + + test('can be used with ComputeType LARGE', () => { + const stack = new cdk.Stack(); + new codebuild.PipelineProject(stack, 'Project', { + environment: { + computeType: codebuild.ComputeType.LARGE, + buildImage: codebuild.LinuxArmBuildImage.AMAZON_LINUX_2_STANDARD_1_0, + }, + }); + + Template.fromStack(stack).hasResourceProperties('AWS::CodeBuild::Project', { + Environment: { + Type: 'ARM_CONTAINER', + ComputeType: 'BUILD_GENERAL1_LARGE', + }, + }); + }); + + test('cannot be used in conjunction with ComputeType X2_LARGE', () => { + const stack = new cdk.Stack(); + + expect(() => { + new codebuild.PipelineProject(stack, 'Project', { + environment: { + buildImage: codebuild.LinuxArmBuildImage.AMAZON_LINUX_2_STANDARD_1_0, + computeType: codebuild.ComputeType.X2_LARGE, + }, + }); + }).toThrow(/ARM images only support ComputeTypes 'BUILD_GENERAL1_SMALL' and 'BUILD_GENERAL1_LARGE' - 'BUILD_GENERAL1_2XLARGE' was given/); + }); + }); + + describe('AMAZON_LINUX_2_STANDARD_2_0', () => { + test('has type ARM_CONTAINER and default ComputeType LARGE', () => { + const stack = new cdk.Stack(); + new codebuild.PipelineProject(stack, 'Project', { + environment: { + buildImage: codebuild.LinuxArmBuildImage.AMAZON_LINUX_2_STANDARD_2_0, + }, + }); + + Template.fromStack(stack).hasResourceProperties('AWS::CodeBuild::Project', { + Environment: { + Type: 'ARM_CONTAINER', + ComputeType: 'BUILD_GENERAL1_LARGE', + }, + }); + }); + + test('can be used with ComputeType SMALL', () => { + const stack = new cdk.Stack(); + new codebuild.PipelineProject(stack, 'Project', { + environment: { + computeType: codebuild.ComputeType.SMALL, + buildImage: codebuild.LinuxArmBuildImage.AMAZON_LINUX_2_STANDARD_2_0, + }, + }); + + Template.fromStack(stack).hasResourceProperties('AWS::CodeBuild::Project', { + Environment: { + Type: 'ARM_CONTAINER', + ComputeType: 'BUILD_GENERAL1_SMALL', + }, + }); + }); + + test('cannot be used in conjunction with ComputeType MEDIUM', () => { + const stack = new cdk.Stack(); + + expect(() => { + new codebuild.PipelineProject(stack, 'Project', { + environment: { + buildImage: codebuild.LinuxArmBuildImage.AMAZON_LINUX_2_STANDARD_2_0, + computeType: codebuild.ComputeType.MEDIUM, + }, + }); + }).toThrow(/ARM images only support ComputeTypes 'BUILD_GENERAL1_SMALL' and 'BUILD_GENERAL1_LARGE' - 'BUILD_GENERAL1_MEDIUM' was given/); + }); + + test('can be used with ComputeType LARGE', () => { + const stack = new cdk.Stack(); + new codebuild.PipelineProject(stack, 'Project', { + environment: { + computeType: codebuild.ComputeType.LARGE, + buildImage: codebuild.LinuxArmBuildImage.AMAZON_LINUX_2_STANDARD_2_0, + }, + }); + + Template.fromStack(stack).hasResourceProperties('AWS::CodeBuild::Project', { + Environment: { + Type: 'ARM_CONTAINER', + ComputeType: 'BUILD_GENERAL1_LARGE', + }, + }); + }); + + test('cannot be used in conjunction with ComputeType X2_LARGE', () => { + const stack = new cdk.Stack(); + + expect(() => { + new codebuild.PipelineProject(stack, 'Project', { + environment: { + buildImage: codebuild.LinuxArmBuildImage.AMAZON_LINUX_2_STANDARD_2_0, + computeType: codebuild.ComputeType.X2_LARGE, + }, + }); + }).toThrow(/ARM images only support ComputeTypes 'BUILD_GENERAL1_SMALL' and 'BUILD_GENERAL1_LARGE' - 'BUILD_GENERAL1_2XLARGE' was given/); + }); + }); + + describe('ECR Repository', () => { + test('allows creating a build image from a new ECR repository', () => { + const stack = new cdk.Stack(); + + const repository = new ecr.Repository(stack, 'my-repo'); + + new codebuild.Project(stack, 'Project', { + buildSpec: codebuild.BuildSpec.fromObject({ + version: '0.2', + phases: { + build: { commands: ['ls'] }, + }, + }), + environment: { + buildImage: codebuild.LinuxArmBuildImage.fromEcrRepository(repository, 'v1'), + }, + }); + + Template.fromStack(stack).hasResourceProperties('AWS::CodeBuild::Project', { + Environment: { + ComputeType: 'BUILD_GENERAL1_LARGE', + Image: { + 'Fn::Join': ['', [ + { + 'Fn::Select': [4, { + 'Fn::Split': [':', { + 'Fn::GetAtt': ['myrepo5DFA62E5', 'Arn'], + }], + }], + }, + '.dkr.ecr.', + { + 'Fn::Select': [3, { + 'Fn::Split': [':', { + 'Fn::GetAtt': ['myrepo5DFA62E5', 'Arn'], + }], + }], + }, + '.', + { Ref: 'AWS::URLSuffix' }, + '/', + { Ref: 'myrepo5DFA62E5' }, + ':v1', + ]], + }, + }, + }); + + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { + PolicyDocument: { + Statement: Match.arrayWith([Match.objectLike({ + Action: [ + 'ecr:BatchCheckLayerAvailability', + 'ecr:GetDownloadUrlForLayer', + 'ecr:BatchGetImage', + ], + Resource: { + 'Fn::GetAtt': ['myrepo5DFA62E5', 'Arn'], + }, + })]), + }, + }); + }); + + test('allows creating a build image from an existing ECR repository', () => { + const stack = new cdk.Stack(); + + const repository = ecr.Repository.fromRepositoryName(stack, 'my-imported-repo', 'test-repo'); + + new codebuild.Project(stack, 'Project', { + buildSpec: codebuild.BuildSpec.fromObject({ + version: '0.2', + phases: { + build: { commands: ['ls'] }, + }, + }), + environment: { + buildImage: codebuild.LinuxArmBuildImage.fromEcrRepository(repository), + }, + }); + + Template.fromStack(stack).hasResourceProperties('AWS::CodeBuild::Project', { + Environment: { + ComputeType: 'BUILD_GENERAL1_LARGE', + Image: { + 'Fn::Join': ['', [ + { Ref: 'AWS::AccountId' }, + '.dkr.ecr.', + { Ref: 'AWS::Region' }, + '.', + { Ref: 'AWS::URLSuffix' }, + '/test-repo:latest', + ]], + }, + }, + }); + + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { + PolicyDocument: { + Statement: Match.arrayWith([Match.objectLike({ + Action: [ + 'ecr:BatchCheckLayerAvailability', + 'ecr:GetDownloadUrlForLayer', + 'ecr:BatchGetImage', + ], + Resource: { + 'Fn::Join': ['', [ + 'arn:', + { Ref: 'AWS::Partition' }, + ':ecr:', + { Ref: 'AWS::Region' }, + ':', + { Ref: 'AWS::AccountId' }, + ':repository/test-repo', + ]], + }, + })]), + }, + }); + }); + + test('allows creating a build image from an existing cross-account ECR repository', () => { + const stack = new cdk.Stack(); + + const repository = ecr.Repository.fromRepositoryArn(stack, 'my-cross-acount-repo', 'arn:aws:ecr:us-east-1:585695036304:repository/foo/bar/foo/fooo'); + + new codebuild.Project(stack, 'Project', { + buildSpec: codebuild.BuildSpec.fromObject({ + version: '0.2', + phases: { + build: { commands: ['ls'] }, + }, + }), + environment: { + buildImage: codebuild.LinuxArmBuildImage.fromEcrRepository(repository), + }, + }); + + Template.fromStack(stack).hasResourceProperties('AWS::CodeBuild::Project', { + Environment: { + ComputeType: 'BUILD_GENERAL1_LARGE', + Image: { + 'Fn::Join': ['', [ + '585695036304.dkr.ecr.us-east-1.', + { Ref: 'AWS::URLSuffix' }, + '/foo/bar/foo/fooo:latest', + ]], + }, + }, + }); + + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { + PolicyDocument: { + Statement: Match.arrayWith([Match.objectLike({ + Action: [ + 'ecr:BatchCheckLayerAvailability', + 'ecr:GetDownloadUrlForLayer', + 'ecr:BatchGetImage', + ], + Resource: 'arn:aws:ecr:us-east-1:585695036304:repository/foo/bar/foo/fooo', + })]), + }, + }); + }); + }); +}); diff --git a/packages/@aws-cdk/aws-cognito/README.md b/packages/@aws-cdk/aws-cognito/README.md index 96629cf13decd..c7348ad5e9b0c 100644 --- a/packages/@aws-cdk/aws-cognito/README.md +++ b/packages/@aws-cdk/aws-cognito/README.md @@ -31,7 +31,7 @@ The two main components of Amazon Cognito are [user pools](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-identity-pools.html) and [identity pools](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-identity.html). User pools are user directories that provide sign-up and sign-in options for your app users. Identity pools enable you to grant your users access to -other AWS services. Identity Pool L2 Constructs can be found [here](../aws-cognito-identitypool). +other AWS services. Identity Pool L2 Constructs can be found [here](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cognito-identitypool-alpha-readme.html). This module is part of the [AWS Cloud Development Kit](https://github.com/aws/aws-cdk) project. diff --git a/packages/@aws-cdk/aws-ec2/README.md b/packages/@aws-cdk/aws-ec2/README.md index dde3951dced96..af8c5ff64594e 100644 --- a/packages/@aws-cdk/aws-ec2/README.md +++ b/packages/@aws-cdk/aws-ec2/README.md @@ -601,6 +601,73 @@ const sg = ec2.SecurityGroup.fromLookupById(this, 'SecurityGroupLookup', 'sg-123 The result of `SecurityGroup.fromLookupByName` and `SecurityGroup.fromLookupById` operations will be written to a file called `cdk.context.json`. You must commit this file to source control so that the lookup values are available in non-privileged environments such as CI build steps, and to ensure your template builds are repeatable. +### Cross Stack Connections + +If you are attempting to add a connection from a peer in one stack to a peer in a different stack, sometimes it is necessary to ensure that you are making the connection in +a specific stack in order to avoid a cyclic reference. If there are no other dependencies between stacks then it will not matter in which stack you make +the connection, but if there are existing dependencies (i.e. stack1 already depends on stack2), then it is important to make the connection in the dependent stack (i.e. stack1). + +Whenever you make a `connections` function call, the ingress and egress security group rules will be added to the stack that the calling object exists in. +So if you are doing something like `peer1.connections.allowFrom(peer2)`, then the security group rules (both ingress and egress) will be created in `peer1`'s Stack. + +As an example, if we wanted to allow a connection from a security group in one stack (egress) to a security group in a different stack (ingress), +we would make the connection like: + +**If Stack1 depends on Stack2** + +```ts fixture=with-vpc +// Stack 1 +declare const stack1: Stack; +declare const stack2: Stack; + +const sg1 = new ec2.SecurityGroup(stack1, 'SG1', { + allowAllOutbound: false, // if this is `true` then no egress rule will be created + vpc, +}); + +// Stack 2 +const sg2 = new ec2.SecurityGroup(stack2, 'SG2', { + allowAllOutbound: false, // if this is `true` then no egress rule will be created + vpc, +}); + + +// `connections.allowTo` on `sg1` since we want the +// rules to be created in Stack1 +sg1.connections.allowTo(sg2, ec2.Port.tcp(3333)); +``` + +In this case both the Ingress Rule for `sg2` and the Egress Rule for `sg1` will both be created +in `Stack 1` which avoids the cyclic reference. + + +**If Stack2 depends on Stack1** + +```ts fixture=with-vpc +// Stack 1 +declare const stack1: Stack; +declare const stack2: Stack; + +const sg1 = new ec2.SecurityGroup(stack1, 'SG1', { + allowAllOutbound: false, // if this is `true` then no egress rule will be created + vpc, +}); + +// Stack 2 +const sg2 = new ec2.SecurityGroup(stack2, 'SG2', { + allowAllOutbound: false, // if this is `true` then no egress rule will be created + vpc, +}); + + +// `connections.allowFrom` on `sg2` since we want the +// rules to be created in Stack2 +sg2.connections.allowFrom(sg1, ec2.Port.tcp(3333)); +``` + +In this case both the Ingress Rule for `sg2` and the Egress Rule for `sg1` will both be created +in `Stack 2` which avoids the cyclic reference. + ## Machine Images (AMIs) AMIs control the OS that gets launched when you start your EC2 instance. The EC2 diff --git a/packages/@aws-cdk/aws-ec2/lib/vpc.ts b/packages/@aws-cdk/aws-ec2/lib/vpc.ts index 94ffdc7976769..5a7fceadd7085 100644 --- a/packages/@aws-cdk/aws-ec2/lib/vpc.ts +++ b/packages/@aws-cdk/aws-ec2/lib/vpc.ts @@ -2218,6 +2218,24 @@ const DUMMY_VPC_PROPS: cxapi.VpcContextResponse = { }, ], }, + { + name: 'Isolated', + type: cxapi.VpcSubnetGroupType.ISOLATED, + subnets: [ + { + availabilityZone: 'dummy1a', + subnetId: 'p-12345', + routeTableId: 'rtb-12345p', + cidr: '1.2.3.4/5', + }, + { + availabilityZone: 'dummy1b', + subnetId: 'p-67890', + routeTableId: 'rtb-57890p', + cidr: '1.2.3.4/5', + }, + ], + }, ], vpcId: 'vpc-12345', }; diff --git a/packages/@aws-cdk/aws-efs/lib/efs-file-system.ts b/packages/@aws-cdk/aws-efs/lib/efs-file-system.ts index 355d296cfae25..b6f512ed071e6 100644 --- a/packages/@aws-cdk/aws-efs/lib/efs-file-system.ts +++ b/packages/@aws-cdk/aws-efs/lib/efs-file-system.ts @@ -338,15 +338,21 @@ export class FileSystem extends FileSystemBase { const encrypted = props.encrypted ?? (FeatureFlags.of(this).isEnabled( cxapi.EFS_DEFAULT_ENCRYPTION_AT_REST) ? true : undefined); + // LifecyclePolicies is an array of lists containing a single policy + let lifecyclePolicies = []; + + if (props.lifecyclePolicy) { + lifecyclePolicies.push({ transitionToIa: props.lifecyclePolicy }); + } + + if (props.outOfInfrequentAccessPolicy) { + lifecyclePolicies.push({ transitionToPrimaryStorageClass: props.outOfInfrequentAccessPolicy }); + } + const filesystem = new CfnFileSystem(this, 'Resource', { encrypted: encrypted, kmsKeyId: props.kmsKey?.keyArn, - lifecyclePolicies: ( - (props.lifecyclePolicy || props.outOfInfrequentAccessPolicy) ? - [{ - transitionToIa: props.lifecyclePolicy, - transitionToPrimaryStorageClass: props.outOfInfrequentAccessPolicy, - }] : undefined), + lifecyclePolicies: lifecyclePolicies.length > 0 ? lifecyclePolicies : undefined, performanceMode: props.performanceMode, throughputMode: props.throughputMode, provisionedThroughputInMibps: props.provisionedThroughputPerSecond?.toMebibytes(), diff --git a/packages/@aws-cdk/aws-efs/test/efs-file-system.test.ts b/packages/@aws-cdk/aws-efs/test/efs-file-system.test.ts index 7e22cd7602472..f6eb888575078 100644 --- a/packages/@aws-cdk/aws-efs/test/efs-file-system.test.ts +++ b/packages/@aws-cdk/aws-efs/test/efs-file-system.test.ts @@ -137,10 +137,14 @@ test('file system is created correctly with a life cycle property and out of inf }); // THEN Template.fromStack(stack).hasResourceProperties('AWS::EFS::FileSystem', { - LifecyclePolicies: [{ - TransitionToIA: 'AFTER_7_DAYS', - TransitionToPrimaryStorageClass: 'AFTER_1_ACCESS', - }], + LifecyclePolicies: [ + { + TransitionToIA: 'AFTER_7_DAYS', + }, + { + TransitionToPrimaryStorageClass: 'AFTER_1_ACCESS', + }, + ], }); }); diff --git a/packages/@aws-cdk/aws-eks/lib/service-account.ts b/packages/@aws-cdk/aws-eks/lib/service-account.ts index 9917911500b24..ea1fd9322a388 100644 --- a/packages/@aws-cdk/aws-eks/lib/service-account.ts +++ b/packages/@aws-cdk/aws-eks/lib/service-account.ts @@ -10,12 +10,18 @@ import { KubernetesManifest } from './k8s-manifest'; export interface ServiceAccountOptions { /** * The name of the service account. + * + * The name of a ServiceAccount object must be a valid DNS subdomain name. + * https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/ * @default - If no name is given, it will use the id of the resource. */ readonly name?: string; /** * The namespace of the service account. + * + * All namespace names must be valid RFC 1123 DNS labels. + * https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/#namespaces-and-dns * @default "default" */ readonly namespace?: string; @@ -61,6 +67,16 @@ export class ServiceAccount extends Construct implements IPrincipal { this.serviceAccountName = props.name ?? Names.uniqueId(this).toLowerCase(); this.serviceAccountNamespace = props.namespace ?? 'default'; + // From K8s docs: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/ + if (!this.isValidDnsSubdomainName(this.serviceAccountName)) { + throw RangeError('The name of a ServiceAccount object must be a valid DNS subdomain name.'); + } + + // From K8s docs: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/#namespaces-and-dns + if (!this.isValidDnsLabelName(this.serviceAccountNamespace)) { + throw RangeError('All namespace names must be valid RFC 1123 DNS labels.'); + } + /* Add conditions to the role to improve security. This prevents other pods in the same namespace to assume the role. * See documentation: https://docs.aws.amazon.com/eks/latest/userguide/create-service-account-iam-policy-and-role.html */ @@ -113,4 +129,22 @@ export class ServiceAccount extends Construct implements IPrincipal { public addToPrincipalPolicy(statement: PolicyStatement): AddToPrincipalPolicyResult { return this.role.addToPrincipalPolicy(statement); } + + /** + * If the value is a DNS subdomain name as defined in RFC 1123, from K8s docs. + * + * https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#dns-subdomain-names + */ + private isValidDnsSubdomainName(value: string): boolean { + return value.length <= 253 && /^[a-z0-9]+[a-z0-9-.]*[a-z0-9]+$/.test(value); + } + + /** + * If the value follows DNS label standard as defined in RFC 1123, from K8s docs. + * + * https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#dns-label-names + */ + private isValidDnsLabelName(value: string): boolean { + return value.length <= 63 && /^[a-z0-9]+[a-z0-9-]*[a-z0-9]+$/.test(value); + } } diff --git a/packages/@aws-cdk/aws-eks/test/service-account.test.ts b/packages/@aws-cdk/aws-eks/test/service-account.test.ts index e4db2f6680a97..7ece468d200d0 100644 --- a/packages/@aws-cdk/aws-eks/test/service-account.test.ts +++ b/packages/@aws-cdk/aws-eks/test/service-account.test.ts @@ -174,4 +174,101 @@ describe('service account', () => { }); }); + + describe('Service Account name must follow Kubernetes spec', () => { + test('throw error on capital letters', () => { + // GIVEN + const { cluster } = testFixtureCluster(); + + // WHEN + expect(() => cluster.addServiceAccount('InvalidServiceAccount', { + name: 'XXX', + })) + // THEN + .toThrowError(RangeError); + }); + test('throw error if ends with dot', () => { + // GIVEN + const { cluster } = testFixtureCluster(); + + // WHEN + expect(() => cluster.addServiceAccount('InvalidServiceAccount', { + name: 'test.', + })) + // THEN + .toThrowError(RangeError); + }); + test('dot in the name is allowed', () => { + // GIVEN + const { cluster } = testFixtureCluster(); + const valueWithDot = 'test.name'; + + // WHEN + const sa = cluster.addServiceAccount('InvalidServiceAccount', { + name: valueWithDot, + }); + + // THEN + expect(sa.serviceAccountName).toEqual(valueWithDot); + }); + test('throw error if name is too long', () => { + // GIVEN + const { cluster } = testFixtureCluster(); + + // WHEN + expect(() => cluster.addServiceAccount('InvalidServiceAccount', { + name: 'x'.repeat(255), + })) + // THEN + .toThrowError(RangeError); + }); + }); + + describe('Service Account namespace must follow Kubernetes spec', () => { + test('throw error on capital letters', () => { + // GIVEN + const { cluster } = testFixtureCluster(); + + // WHEN + expect(() => cluster.addServiceAccount('InvalidServiceAccount', { + namespace: 'XXX', + })) + // THEN + .toThrowError(RangeError); + }); + test('throw error if ends with dot', () => { + // GIVEN + const { cluster } = testFixtureCluster(); + + // WHEN + expect(() => cluster.addServiceAccount('InvalidServiceAccount', { + namespace: 'test.', + })) + // THEN + .toThrowError(RangeError); + }); + test('throw error if dot is in the name', () => { + // GIVEN + const { cluster } = testFixtureCluster(); + const valueWithDot = 'test.name'; + + // WHEN + expect(() => cluster.addServiceAccount('InvalidServiceAccount', { + namespace: valueWithDot, + })) + // THEN + .toThrowError(RangeError); + }); + test('throw error if name is too long', () => { + // GIVEN + const { cluster } = testFixtureCluster(); + + // WHEN + expect(() => cluster.addServiceAccount('InvalidServiceAccount', { + namespace: 'x'.repeat(65), + })) + // THEN + .toThrowError(RangeError); + }); + }); }); diff --git a/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/alb/application-listener.ts b/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/alb/application-listener.ts index dff37d4174ac4..38d9b19153cd0 100644 --- a/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/alb/application-listener.ts +++ b/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/alb/application-listener.ts @@ -880,7 +880,8 @@ export interface AddApplicationTargetsProps extends AddRuleProps { /** * Health check configuration * - * @default No health check + * @default - The default value for each property in this configuration varies depending on the target. + * @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-elasticloadbalancingv2-targetgroup.html#aws-resource-elasticloadbalancingv2-targetgroup-properties */ readonly healthCheck?: HealthCheck; diff --git a/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/nlb/network-listener.ts b/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/nlb/network-listener.ts index 4cfed265217f5..d48dbafc8202a 100644 --- a/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/nlb/network-listener.ts +++ b/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/nlb/network-listener.ts @@ -361,7 +361,8 @@ export interface AddNetworkTargetsProps { /** * Health check configuration * - * @default No health check + * @default - The default value for each property in this configuration varies depending on the target. + * @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-elasticloadbalancingv2-targetgroup.html#aws-resource-elasticloadbalancingv2-targetgroup-properties */ readonly healthCheck?: HealthCheck; } diff --git a/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/shared/base-target-group.ts b/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/shared/base-target-group.ts index b83002b73444f..2155579164ee3 100644 --- a/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/shared/base-target-group.ts +++ b/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/shared/base-target-group.ts @@ -41,7 +41,8 @@ export interface BaseTargetGroupProps { /** * Health check configuration * - * @default - None. + * @default - The default value for each property in this configuration varies depending on the target. + * @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-elasticloadbalancingv2-targetgroup.html#aws-resource-elasticloadbalancingv2-targetgroup-properties */ readonly healthCheck?: HealthCheck; diff --git a/packages/@aws-cdk/aws-elasticsearch/README.md b/packages/@aws-cdk/aws-elasticsearch/README.md index 6de168cf70f7b..4aaa5c72d75c8 100644 --- a/packages/@aws-cdk/aws-elasticsearch/README.md +++ b/packages/@aws-cdk/aws-elasticsearch/README.md @@ -233,7 +233,62 @@ const domain = new es.Domain(this, 'Domain', { const masterUserPassword = domain.masterUserPassword; ``` +## Custom access policies +If the domain requires custom access control it can be configured either as a +constructor property, or later by means of a helper method. + +For simple permissions the `accessPolicies` constructor may be sufficient: + +```ts +const domain = new es.Domain(this, 'Domain', { + version: es.ElasticsearchVersion.V7_1, + accessPolicies: [ + new iam.PolicyStatement({ + actions: ['es:*ESHttpPost', 'es:ESHttpPut*'], + effect: iam.Effect.ALLOW, + principals: [new iam.AccountPrincipal('123456789012')], + resources: ['*'], + }), + ] +}); +``` + +For more complex use-cases, for example, to set the domain up to receive data from a +[cross-account Kinesis Firehose](https://aws.amazon.com/premiumsupport/knowledge-center/kinesis-firehose-cross-account-streaming/) the `addAccessPolicies` helper method +allows for policies that include the explicit domain ARN. + +```ts +const domain = new es.Domain(this, 'Domain', { + version: es.ElasticsearchVersion.V7_1, +}); + +domain.addAccessPolicies( + new iam.PolicyStatement({ + actions: ['es:ESHttpPost', 'es:ESHttpPut'], + effect: iam.Effect.ALLOW, + principals: [new iam.AccountPrincipal('123456789012')], + resources: [domain.domainArn, `${domain.domainArn}/*`], + }), + new iam.PolicyStatement({ + actions: ['es:ESHttpGet'], + effect: iam.Effect.ALLOW, + principals: [new iam.AccountPrincipal('123456789012')], + resources: [ + `${domain.domainArn}/_all/_settings`, + `${domain.domainArn}/_cluster/stats`, + `${domain.domainArn}/index-name*/_mapping/type-name`, + `${domain.domainArn}/roletest*/_mapping/roletest`, + `${domain.domainArn}/_nodes`, + `${domain.domainArn}/_nodes/stats`, + `${domain.domainArn}/_nodes/*/stats`, + `${domain.domainArn}/_stats`, + `${domain.domainArn}/index-name*/_stats`, + `${domain.domainArn}/roletest*/_stat`, + ], + }), +); +``` ## Audit logs @@ -400,7 +455,7 @@ Make the following modifications to your CDK application to migrate to the `@aws Follow these steps to migrate your application without data loss: - Ensure that the [removal policy](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_core.RemovalPolicy.html) on your domains are set to `RemovalPolicy.RETAIN`. This is the default for the domain construct, so nothing is required unless you have specifically set the removal policy to some other value. -- Remove the domain resource from your CloudFormation stacks by manually modifying the synthesized templates used to create the CloudFormation stacks. This may also involve modifying or deleting dependent resources, such as the custom resources that CDK creates to manage the domain's access policy or any other resource you have connected to the domain. You will need to search for references to each domain's logical ID to determine which other resources refer to it and replace or delete those references. Do not remove resources that are dependencies of the domain or you will have to recreate or import them before importing the domain. After modification, deploy the stacks through the AWS Management Console or using the AWS CLI. +- Remove the domain resource from your CloudFormation stacks by manually modifying the synthesized templates used to create the CloudFormation stacks. This may also involve modifying or deleting dependent resources, such as the custom resources that CDK creates to manage the domain's access policy or any other resource you have connected to the domain. You will need to search for references to each domain's logical ID to determine which other resources refer to it and replace or delete those references. Do not remove resources that are dependencies of the domain or you will have to recreate or import them before importing the domain. After modification, deploy the stacks through the AWS Management Console or using the AWS CLI. - Migrate your CDK application to use the new `@aws-cdk/aws-opensearchservice` module by applying the necessary modifications listed above. Synthesize your application and obtain the resulting stack templates. - Copy just the definition of the domain from the "migrated" templates to the corresponding "stripped" templates that you deployed above. [Import](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/resource-import-existing-stack.html) the orphaned domains into your CloudFormation stacks using these templates. - Synthesize and deploy your CDK application to reconfigure/recreate the modified dependent resources. The CloudFormation stacks should now contain the same resources as existed prior to migration. diff --git a/packages/@aws-cdk/aws-elasticsearch/lib/domain.ts b/packages/@aws-cdk/aws-elasticsearch/lib/domain.ts index e8808958929fc..88930526b81a5 100644 --- a/packages/@aws-cdk/aws-elasticsearch/lib/domain.ts +++ b/packages/@aws-cdk/aws-elasticsearch/lib/domain.ts @@ -1264,6 +1264,9 @@ export class Domain extends DomainBase implements IDomain, ec2.IConnectable { private readonly domain: CfnDomain; + private accessPolicy?: ElasticsearchAccessPolicy + private encryptionAtRestOptions?: EncryptionAtRestOptions + private readonly _connections: ec2.Connections | undefined; constructor(scope: Construct, id: string, props: DomainProps) { @@ -1720,33 +1723,12 @@ export class Domain extends DomainBase implements IDomain, ec2.IConnectable { }); } - const accessPolicyStatements: iam.PolicyStatement[] | undefined = unsignedBasicAuthEnabled - ? (props.accessPolicies ?? []).concat(unsignedAccessPolicy) - : props.accessPolicies; - - if (accessPolicyStatements != null) { - const accessPolicy = new ElasticsearchAccessPolicy(this, 'ESAccessPolicy', { - domainName: this.domainName, - domainArn: this.domainArn, - accessPolicies: accessPolicyStatements, - }); - - if (props.encryptionAtRest?.kmsKey) { - - // https://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/encryption-at-rest.html - - // these permissions are documented as required during domain creation. - // while not strictly documented for updates as well, it stands to reason that an update - // operation might require these in case the cluster uses a kms key. - // empircal evidence shows this is indeed required: https://github.com/aws/aws-cdk/issues/11412 - accessPolicy.grantPrincipal.addToPrincipalPolicy(new iam.PolicyStatement({ - actions: ['kms:List*', 'kms:Describe*', 'kms:CreateGrant'], - resources: [props.encryptionAtRest.kmsKey.keyArn], - effect: iam.Effect.ALLOW, - })); - } - - accessPolicy.node.addDependency(this.domain); + this.encryptionAtRestOptions = props.encryptionAtRest; + if (props.accessPolicies) { + this.addAccessPolicies(...props.accessPolicies); + } + if (unsignedBasicAuthEnabled) { + this.addAccessPolicies(unsignedAccessPolicy); } } @@ -1760,6 +1742,38 @@ export class Domain extends DomainBase implements IDomain, ec2.IConnectable { } return this._connections; } + + /** + * Add policy statements to the domain access policy + */ + public addAccessPolicies(...accessPolicyStatements: iam.PolicyStatement[]) { + if (accessPolicyStatements.length > 0) { + if (!this.accessPolicy) { + // Only create the custom resource after there are statements to set. + this.accessPolicy = new ElasticsearchAccessPolicy(this, 'ESAccessPolicy', { + domainName: this.domainName, + domainArn: this.domainArn, + accessPolicies: accessPolicyStatements, + }); + + if (this.encryptionAtRestOptions?.kmsKey) { + // https://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/encryption-at-rest.html + + // these permissions are documented as required during domain creation. + // while not strictly documented for updates as well, it stands to reason that an update + // operation might require these in case the cluster uses a kms key. + // empircal evidence shows this is indeed required: https://github.com/aws/aws-cdk/issues/11412 + this.accessPolicy.grantPrincipal.addToPrincipalPolicy(new iam.PolicyStatement({ + actions: ['kms:List*', 'kms:Describe*', 'kms:CreateGrant'], + resources: [this.encryptionAtRestOptions.kmsKey.keyArn], + effect: iam.Effect.ALLOW, + })); + } + } else { + this.accessPolicy.addAccessPolicies(...accessPolicyStatements); + } + } + } } /** diff --git a/packages/@aws-cdk/aws-elasticsearch/lib/elasticsearch-access-policy.ts b/packages/@aws-cdk/aws-elasticsearch/lib/elasticsearch-access-policy.ts index e45e6df0a2462..af8a4d31a77ae 100644 --- a/packages/@aws-cdk/aws-elasticsearch/lib/elasticsearch-access-policy.ts +++ b/packages/@aws-cdk/aws-elasticsearch/lib/elasticsearch-access-policy.ts @@ -1,4 +1,5 @@ import * as iam from '@aws-cdk/aws-iam'; +import * as cdk from '@aws-cdk/core'; import * as cr from '@aws-cdk/custom-resources'; import { Construct } from 'constructs'; @@ -26,11 +27,10 @@ export interface ElasticsearchAccessPolicyProps { * Creates LogGroup resource policies. */ export class ElasticsearchAccessPolicy extends cr.AwsCustomResource { - constructor(scope: Construct, id: string, props: ElasticsearchAccessPolicyProps) { - const policyDocument = new iam.PolicyDocument({ - statements: props.accessPolicies, - }); + private accessPolicyStatements: iam.PolicyStatement[] = []; + + constructor(scope: Construct, id: string, props: ElasticsearchAccessPolicyProps) { super(scope, id, { resourceType: 'Custom::ElasticsearchAccessPolicy', onUpdate: { @@ -38,7 +38,13 @@ export class ElasticsearchAccessPolicy extends cr.AwsCustomResource { service: 'ES', parameters: { DomainName: props.domainName, - AccessPolicies: JSON.stringify(policyDocument.toJSON()), + AccessPolicies: cdk.Lazy.string({ + produce: () => JSON.stringify( + new iam.PolicyDocument({ + statements: this.accessPolicyStatements, + }).toJSON(), + ), + }), }, // this is needed to limit the response body, otherwise it exceeds the CFN 4k limit outputPaths: ['DomainConfig.ElasticsearchClusterConfig.AccessPolicies'], @@ -46,5 +52,14 @@ export class ElasticsearchAccessPolicy extends cr.AwsCustomResource { }, policy: cr.AwsCustomResourcePolicy.fromSdkCalls({ resources: [props.domainArn] }), }); + + this.addAccessPolicies(...props.accessPolicies); + } + + /** + * Add policy statements to the domain access policy + */ + public addAccessPolicies(...accessPolicyStatements: iam.PolicyStatement[]) { + this.accessPolicyStatements.push(...accessPolicyStatements); } } diff --git a/packages/@aws-cdk/aws-elasticsearch/test/domain.test.ts b/packages/@aws-cdk/aws-elasticsearch/test/domain.test.ts index 3242e75d2c253..63387de5ee64f 100644 --- a/packages/@aws-cdk/aws-elasticsearch/test/domain.test.ts +++ b/packages/@aws-cdk/aws-elasticsearch/test/domain.test.ts @@ -200,6 +200,67 @@ test('can enable version upgrade update policy', () => { }); }); +test('can set a self-referencing custom policy', () => { + const domain = new Domain(stack, 'Domain', { + version: ElasticsearchVersion.V7_1, + }); + + domain.addAccessPolicies( + new iam.PolicyStatement({ + actions: ['es:ESHttpPost', 'es:ESHttpPut'], + effect: iam.Effect.ALLOW, + principals: [new iam.AccountPrincipal('5678')], + resources: [domain.domainArn, `${domain.domainArn}/*`], + }), + ); + + const expectedPolicy = { + 'Fn::Join': [ + '', + [ + '{"action":"updateElasticsearchDomainConfig","service":"ES","parameters":{"DomainName":"', + { + Ref: 'Domain66AC69E0', + }, + '","AccessPolicies":"{\\"Statement\\":[{\\"Action\\":[\\"es:ESHttpPost\\",\\"es:ESHttpPut\\"],\\"Effect\\":\\"Allow\\",\\"Principal\\":{\\"AWS\\":\\"arn:', + { + Ref: 'AWS::Partition', + }, + ':iam::5678:root\\"},\\"Resource\\":[\\"', + { + 'Fn::GetAtt': [ + 'Domain66AC69E0', + 'Arn', + ], + }, + '\\",\\"', + { + 'Fn::GetAtt': [ + 'Domain66AC69E0', + 'Arn', + ], + }, + '/*\\"]}],\\"Version\\":\\"2012-10-17\\"}"},"outputPaths":["DomainConfig.ElasticsearchClusterConfig.AccessPolicies"],"physicalResourceId":{"id":"', + { + Ref: 'Domain66AC69E0', + }, + 'AccessPolicy"}}', + ], + ], + }; + Template.fromStack(stack).hasResourceProperties('Custom::ElasticsearchAccessPolicy', { + ServiceToken: { + 'Fn::GetAtt': [ + 'AWS679f53fac002430cb0da5b7982bd22872D164C4C', + 'Arn', + ], + }, + Create: expectedPolicy, + Update: expectedPolicy, + }); +}); + + describe('UltraWarm instances', () => { test('can enable UltraWarm instances', () => { diff --git a/packages/@aws-cdk/aws-elasticsearch/test/elasticsearch-access-policy.test.ts b/packages/@aws-cdk/aws-elasticsearch/test/elasticsearch-access-policy.test.ts index 38ffc94c0c05b..53086622c5231 100644 --- a/packages/@aws-cdk/aws-elasticsearch/test/elasticsearch-access-policy.test.ts +++ b/packages/@aws-cdk/aws-elasticsearch/test/elasticsearch-access-policy.test.ts @@ -55,3 +55,55 @@ test('minimal example renders correctly', () => { }), }); }); + +test('support access policy added inline and later', () => { + const elasticsearchAccessPolicy = new ElasticsearchAccessPolicy(stack, 'ElasticsearchAccessPolicy', { + domainName: 'TestDomain', + domainArn: 'test:arn', + accessPolicies: [ + new iam.PolicyStatement({ + effect: iam.Effect.ALLOW, + actions: ['es:ESHttp*'], + principals: [new iam.AnyPrincipal()], + resources: ['test:arn'], + }), + ], + }); + elasticsearchAccessPolicy.addAccessPolicies( + new iam.PolicyStatement({ + effect: iam.Effect.ALLOW, + actions: ['*'], + principals: [new iam.AnyPrincipal()], + resources: ['test:arn'], + }), + ); + + Template.fromStack(stack).hasResourceProperties('Custom::ElasticsearchAccessPolicy', { + ServiceToken: { + 'Fn::GetAtt': [ + 'AWS679f53fac002430cb0da5b7982bd22872D164C4C', + 'Arn', + ], + }, + Create: JSON.stringify({ + action: 'updateElasticsearchDomainConfig', + service: 'ES', + parameters: { + DomainName: 'TestDomain', + AccessPolicies: '{"Statement":[{"Action":"es:ESHttp*","Effect":"Allow","Principal":{"AWS":"*"},"Resource":"test:arn"},{"Action":"*","Effect":"Allow","Principal":{"AWS":"*"},"Resource":"test:arn"}],"Version":"2012-10-17"}', + }, + outputPaths: ['DomainConfig.ElasticsearchClusterConfig.AccessPolicies'], + physicalResourceId: { id: 'TestDomainAccessPolicy' }, + }), + Update: JSON.stringify({ + action: 'updateElasticsearchDomainConfig', + service: 'ES', + parameters: { + DomainName: 'TestDomain', + AccessPolicies: '{"Statement":[{"Action":"es:ESHttp*","Effect":"Allow","Principal":{"AWS":"*"},"Resource":"test:arn"},{"Action":"*","Effect":"Allow","Principal":{"AWS":"*"},"Resource":"test:arn"}],"Version":"2012-10-17"}', + }, + outputPaths: ['DomainConfig.ElasticsearchClusterConfig.AccessPolicies'], + physicalResourceId: { id: 'TestDomainAccessPolicy' }, + }), + }); +}); diff --git a/packages/@aws-cdk/aws-elasticsearch/test/integ.elasticsearch.custom-kms-key.expected.json b/packages/@aws-cdk/aws-elasticsearch/test/integ.elasticsearch.custom-kms-key.expected.json index 636acfc906b05..de4a51d454b8d 100644 --- a/packages/@aws-cdk/aws-elasticsearch/test/integ.elasticsearch.custom-kms-key.expected.json +++ b/packages/@aws-cdk/aws-elasticsearch/test/integ.elasticsearch.custom-kms-key.expected.json @@ -222,10 +222,7 @@ "Ref": "AWS679f53fac002430cb0da5b7982bd2287ServiceRoleC1EA0FF2" } ] - }, - "DependsOn": [ - "Domain66AC69E0" - ] + } }, "DomainESAccessPolicy89986F33": { "Type": "Custom::ElasticsearchAccessPolicy", @@ -287,8 +284,7 @@ "InstallLatestAwsSdk": true }, "DependsOn": [ - "DomainESAccessPolicyCustomResourcePolicy9747FC42", - "Domain66AC69E0" + "DomainESAccessPolicyCustomResourcePolicy9747FC42" ], "UpdateReplacePolicy": "Delete", "DeletionPolicy": "Delete" diff --git a/packages/@aws-cdk/aws-elasticsearch/test/integ.elasticsearch.expected.json b/packages/@aws-cdk/aws-elasticsearch/test/integ.elasticsearch.expected.json index 73c6624609fd4..40a3ba4cacb28 100644 --- a/packages/@aws-cdk/aws-elasticsearch/test/integ.elasticsearch.expected.json +++ b/packages/@aws-cdk/aws-elasticsearch/test/integ.elasticsearch.expected.json @@ -189,10 +189,7 @@ "Ref": "AWS679f53fac002430cb0da5b7982bd2287ServiceRoleC1EA0FF2" } ] - }, - "DependsOn": [ - "Domain19FCBCB91" - ] + } }, "Domain1ESAccessPolicy5D846A31": { "Type": "Custom::ElasticsearchAccessPolicy", @@ -254,8 +251,7 @@ "InstallLatestAwsSdk": true }, "DependsOn": [ - "Domain1ESAccessPolicyCustomResourcePolicyC04432B6", - "Domain19FCBCB91" + "Domain1ESAccessPolicyCustomResourcePolicyC04432B6" ], "UpdateReplacePolicy": "Delete", "DeletionPolicy": "Delete" @@ -535,10 +531,7 @@ "Ref": "AWS679f53fac002430cb0da5b7982bd2287ServiceRoleC1EA0FF2" } ] - }, - "DependsOn": [ - "Domain2644FE48C" - ] + } }, "Domain2ESAccessPolicy3DF4C2BA": { "Type": "Custom::ElasticsearchAccessPolicy", @@ -600,8 +593,7 @@ "InstallLatestAwsSdk": true }, "DependsOn": [ - "Domain2ESAccessPolicyCustomResourcePolicy8EED1F24", - "Domain2644FE48C" + "Domain2ESAccessPolicyCustomResourcePolicy8EED1F24" ], "UpdateReplacePolicy": "Delete", "DeletionPolicy": "Delete" diff --git a/packages/@aws-cdk/aws-elasticsearch/test/integ.elasticsearch.unsignedbasicauth.expected.json b/packages/@aws-cdk/aws-elasticsearch/test/integ.elasticsearch.unsignedbasicauth.expected.json index 2793a8beb231f..6e0b5573a7b39 100644 --- a/packages/@aws-cdk/aws-elasticsearch/test/integ.elasticsearch.unsignedbasicauth.expected.json +++ b/packages/@aws-cdk/aws-elasticsearch/test/integ.elasticsearch.unsignedbasicauth.expected.json @@ -88,10 +88,7 @@ "Ref": "AWS679f53fac002430cb0da5b7982bd2287ServiceRoleC1EA0FF2" } ] - }, - "DependsOn": [ - "Domain66AC69E0" - ] + } }, "DomainESAccessPolicy89986F33": { "Type": "Custom::ElasticsearchAccessPolicy", @@ -151,8 +148,7 @@ "InstallLatestAwsSdk": true }, "DependsOn": [ - "DomainESAccessPolicyCustomResourcePolicy9747FC42", - "Domain66AC69E0" + "DomainESAccessPolicyCustomResourcePolicy9747FC42" ], "UpdateReplacePolicy": "Delete", "DeletionPolicy": "Delete" diff --git a/packages/@aws-cdk/aws-events-targets/README.md b/packages/@aws-cdk/aws-events-targets/README.md index d98b08d652086..34157fef412b5 100644 --- a/packages/@aws-cdk/aws-events-targets/README.md +++ b/packages/@aws-cdk/aws-events-targets/README.md @@ -167,13 +167,13 @@ const role = new iam.Role(this, 'Role', { assumedBy: new iam.ServicePrincipal('events.amazonaws.com'), }); const stateMachine = new sfn.StateMachine(this, 'SM', { - definition: new sfn.Wait(this, 'Hello', { time: sfn.WaitTime.duration(cdk.Duration.seconds(10)) }), - role, + definition: new sfn.Wait(this, 'Hello', { time: sfn.WaitTime.duration(cdk.Duration.seconds(10)) }) }); rule.addTarget(new targets.SfnStateMachine(stateMachine, { input: events.RuleTargetInput.fromObject({ SomeParam: 'SomeValue' }), deadLetterQueue: dlq, + role: role })); ``` diff --git a/packages/@aws-cdk/aws-events-targets/test/stepfunctions/statemachine.test.ts b/packages/@aws-cdk/aws-events-targets/test/stepfunctions/statemachine.test.ts index 158b19f34fa0a..6327213b7a744 100644 --- a/packages/@aws-cdk/aws-events-targets/test/stepfunctions/statemachine.test.ts +++ b/packages/@aws-cdk/aws-events-targets/test/stepfunctions/statemachine.test.ts @@ -68,12 +68,12 @@ test('Existing role can be used for State machine Rule target', () => { }); const stateMachine = new sfn.StateMachine(stack, 'SM', { definition: new sfn.Wait(stack, 'Hello', { time: sfn.WaitTime.duration(cdk.Duration.seconds(10)) }), - role, }); // WHEN rule.addTarget(new targets.SfnStateMachine(stateMachine, { input: events.RuleTargetInput.fromObject({ SomeParam: 'SomeValue' }), + role: role, })); // THEN @@ -125,13 +125,13 @@ test('specifying retry policy', () => { }); const stateMachine = new sfn.StateMachine(stack, 'SM', { definition: new sfn.Wait(stack, 'Hello', { time: sfn.WaitTime.duration(cdk.Duration.seconds(10)) }), - role, }); rule.addTarget(new targets.SfnStateMachine(stateMachine, { input: events.RuleTargetInput.fromObject({ SomeParam: 'SomeValue' }), maxEventAge: cdk.Duration.hours(2), retryAttempts: 2, + role: role, })); // THEN @@ -151,7 +151,7 @@ test('specifying retry policy', () => { }, RoleArn: { 'Fn::GetAtt': [ - 'SMEventsRoleB320A902', + 'Role1ABCC5F0', 'Arn', ], }, @@ -176,13 +176,13 @@ test('use a Dead Letter Queue for the rule target', () => { }); const stateMachine = new sfn.StateMachine(stack, 'SM', { definition: new sfn.Wait(stack, 'Hello', { time: sfn.WaitTime.duration(cdk.Duration.seconds(10)) }), - role, }); // WHEN rule.addTarget(new targets.SfnStateMachine(stateMachine, { input: events.RuleTargetInput.fromObject({ SomeParam: 'SomeValue' }), deadLetterQueue: dlq, + role: role, })); // the Permission resource should be in the event stack @@ -206,7 +206,7 @@ test('use a Dead Letter Queue for the rule target', () => { Input: '{"SomeParam":"SomeValue"}', RoleArn: { 'Fn::GetAtt': [ - 'SMEventsRoleB320A902', + 'Role1ABCC5F0', 'Arn', ], }, diff --git a/packages/@aws-cdk/aws-iotevents-actions/README.md b/packages/@aws-cdk/aws-iotevents-actions/README.md index 4ee5362b7cc9b..eb88dc82bb3c3 100644 --- a/packages/@aws-cdk/aws-iotevents-actions/README.md +++ b/packages/@aws-cdk/aws-iotevents-actions/README.md @@ -18,3 +18,33 @@ This library contains integration classes to specify actions of state events of Detector Model in `@aws-cdk/aws-iotevents`. Instances of these classes should be passed to `State` defined in `@aws-cdk/aws-iotevents` You can define built-in actions to use a timer or set a variable, or send data to other AWS resources. + +This library contains integration classes to use a timer or set a variable, or send data to other AWS resources. +AWS IoT Events can trigger actions when it detects a specified event or transition event. + +Currently supported are: + +- Invoke a Lambda function + +## Invoke a Lambda function + +The code snippet below creates an Action that invoke a Lambda function +when it is triggered. + +```ts +import * as iotevents from '@aws-cdk/aws-iotevents'; +import * as actions from '@aws-cdk/aws-iotevents-actions'; +import * as lambda from '@aws-cdk/aws-lambda'; + +declare const input: iotevents.IInput; +declare const func: lambda.IFunction; + +const state = new iotevents.State({ + stateName: 'MyState', + onEnter: [{ + eventName: 'test-event', + condition: iotevents.Expression.currentInput(input), + actions: [new actions.LambdaInvokeAction(func)], + }], +}); +``` diff --git a/packages/@aws-cdk/aws-iotevents-actions/lib/index.ts b/packages/@aws-cdk/aws-iotevents-actions/lib/index.ts index 3e4b0ef0a73d4..4b2ec39329315 100644 --- a/packages/@aws-cdk/aws-iotevents-actions/lib/index.ts +++ b/packages/@aws-cdk/aws-iotevents-actions/lib/index.ts @@ -1,2 +1 @@ -// this is placeholder for monocdk -export const dummy = true; +export * from './lambda-invoke-action'; diff --git a/packages/@aws-cdk/aws-iotevents-actions/lib/lambda-invoke-action.ts b/packages/@aws-cdk/aws-iotevents-actions/lib/lambda-invoke-action.ts new file mode 100644 index 0000000000000..af9dec5d32472 --- /dev/null +++ b/packages/@aws-cdk/aws-iotevents-actions/lib/lambda-invoke-action.ts @@ -0,0 +1,25 @@ +import * as iotevents from '@aws-cdk/aws-iotevents'; +import * as lambda from '@aws-cdk/aws-lambda'; +import { Construct } from 'constructs'; + +/** + * The action to write the data to an AWS Lambda function. + */ +export class LambdaInvokeAction implements iotevents.IAction { + /** + * @param func the AWS Lambda function to be invoked by this action + */ + constructor(private readonly func: lambda.IFunction) { + } + + bind(_scope: Construct, options: iotevents.ActionBindOptions): iotevents.ActionConfig { + this.func.grantInvoke(options.role); + return { + configuration: { + lambda: { + functionArn: this.func.functionArn, + }, + }, + }; + } +} diff --git a/packages/@aws-cdk/aws-iotevents-actions/package.json b/packages/@aws-cdk/aws-iotevents-actions/package.json index 203d207219909..55e474f5f0904 100644 --- a/packages/@aws-cdk/aws-iotevents-actions/package.json +++ b/packages/@aws-cdk/aws-iotevents-actions/package.json @@ -78,11 +78,17 @@ "jest": "^27.5.1" }, "dependencies": { + "@aws-cdk/aws-iam": "0.0.0", + "@aws-cdk/aws-iotevents": "0.0.0", + "@aws-cdk/aws-lambda": "0.0.0", "@aws-cdk/core": "0.0.0", "constructs": "^10.0.0" }, "homepage": "https://github.com/aws/aws-cdk", "peerDependencies": { + "@aws-cdk/aws-iam": "0.0.0", + "@aws-cdk/aws-iotevents": "0.0.0", + "@aws-cdk/aws-lambda": "0.0.0", "@aws-cdk/core": "0.0.0", "constructs": "^10.0.0" }, diff --git a/packages/@aws-cdk/aws-iotevents-actions/test/iotevents-actions.test.ts b/packages/@aws-cdk/aws-iotevents-actions/test/iotevents-actions.test.ts deleted file mode 100644 index 465c7bdea0693..0000000000000 --- a/packages/@aws-cdk/aws-iotevents-actions/test/iotevents-actions.test.ts +++ /dev/null @@ -1,6 +0,0 @@ -import '@aws-cdk/assertions'; -import {} from '../lib'; - -test('No tests are specified for this package', () => { - expect(true).toBe(true); -}); diff --git a/packages/@aws-cdk/aws-iotevents-actions/test/lambda/integ.lambda-invoke-action.expected.json b/packages/@aws-cdk/aws-iotevents-actions/test/lambda/integ.lambda-invoke-action.expected.json new file mode 100644 index 0000000000000..7e5d5b881d01d --- /dev/null +++ b/packages/@aws-cdk/aws-iotevents-actions/test/lambda/integ.lambda-invoke-action.expected.json @@ -0,0 +1,161 @@ +{ + "Resources": { + "MyInput08947B23": { + "Type": "AWS::IoTEvents::Input", + "Properties": { + "InputDefinition": { + "Attributes": [ + { + "JsonPath": "payload.deviceId" + } + ] + }, + "InputName": "test_input" + } + }, + "MyFunctionServiceRole3C357FF2": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ] + ] + } + ] + } + }, + "MyFunction3BAA72D1": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "ZipFile": "\n exports.handler = (event) => {\n console.log(\"It is test for lambda action of AWS IoT Rule.\", event);\n };" + }, + "Role": { + "Fn::GetAtt": [ + "MyFunctionServiceRole3C357FF2", + "Arn" + ] + }, + "Handler": "index.handler", + "Runtime": "nodejs14.x" + }, + "DependsOn": [ + "MyFunctionServiceRole3C357FF2" + ] + }, + "MyDetectorModelDetectorModelRoleF2FB4D88": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "iotevents.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "MyDetectorModelDetectorModelRoleDefaultPolicy82887422": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": "lambda:InvokeFunction", + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "MyFunction3BAA72D1", + "Arn" + ] + } + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "MyDetectorModelDetectorModelRoleDefaultPolicy82887422", + "Roles": [ + { + "Ref": "MyDetectorModelDetectorModelRoleF2FB4D88" + } + ] + } + }, + "MyDetectorModel559C0B0E": { + "Type": "AWS::IoTEvents::DetectorModel", + "Properties": { + "DetectorModelDefinition": { + "InitialStateName": "MyState", + "States": [ + { + "OnEnter": { + "Events": [ + { + "Actions": [ + { + "Lambda": { + "FunctionArn": { + "Fn::GetAtt": [ + "MyFunction3BAA72D1", + "Arn" + ] + } + } + } + ], + "Condition": { + "Fn::Join": [ + "", + [ + "currentInput(\"", + { + "Ref": "MyInput08947B23" + }, + "\")" + ] + ] + }, + "EventName": "test-event" + } + ] + }, + "StateName": "MyState" + } + ] + }, + "RoleArn": { + "Fn::GetAtt": [ + "MyDetectorModelDetectorModelRoleF2FB4D88", + "Arn" + ] + }, + "Key": "payload.deviceId" + } + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-iotevents-actions/test/lambda/integ.lambda-invoke-action.ts b/packages/@aws-cdk/aws-iotevents-actions/test/lambda/integ.lambda-invoke-action.ts new file mode 100644 index 0000000000000..2084f2cb7bd9c --- /dev/null +++ b/packages/@aws-cdk/aws-iotevents-actions/test/lambda/integ.lambda-invoke-action.ts @@ -0,0 +1,48 @@ +/** + * Stack verification steps: + * * put a message + * * aws iotevents-data batch-put-message --messages=messageId=(date | md5),inputName=test_input,payload=(echo '{"payload":{"temperature":31.9,"deviceId":"000"}}' | base64) + * * verify that the lambda logs be put + */ +import * as iotevents from '@aws-cdk/aws-iotevents'; +import * as lambda from '@aws-cdk/aws-lambda'; +import * as cdk from '@aws-cdk/core'; +import * as actions from '../../lib'; + +class TestStack extends cdk.Stack { + constructor(scope: cdk.App, id: string, props?: cdk.StackProps) { + super(scope, id, props); + + const input = new iotevents.Input(this, 'MyInput', { + inputName: 'test_input', + attributeJsonPaths: ['payload.deviceId'], + }); + const func = new lambda.Function(this, 'MyFunction', { + runtime: lambda.Runtime.NODEJS_14_X, + handler: 'index.handler', + code: lambda.Code.fromInline(` + exports.handler = (event) => { + console.log("It is test for lambda action of AWS IoT Rule.", event); + };`, + ), + }); + + const state = new iotevents.State({ + stateName: 'MyState', + onEnter: [{ + eventName: 'test-event', + condition: iotevents.Expression.currentInput(input), + actions: [new actions.LambdaInvokeAction(func)], + }], + }); + + new iotevents.DetectorModel(this, 'MyDetectorModel', { + detectorKey: 'payload.deviceId', + initialState: state, + }); + } +} + +const app = new cdk.App(); +new TestStack(app, 'lambda-invoke-action-test-stack'); +app.synth(); diff --git a/packages/@aws-cdk/aws-iotevents-actions/test/lambda/lambda-invoke-action.test.ts b/packages/@aws-cdk/aws-iotevents-actions/test/lambda/lambda-invoke-action.test.ts new file mode 100644 index 0000000000000..493114dbd3bb5 --- /dev/null +++ b/packages/@aws-cdk/aws-iotevents-actions/test/lambda/lambda-invoke-action.test.ts @@ -0,0 +1,64 @@ +import { Template } from '@aws-cdk/assertions'; +import * as iotevents from '@aws-cdk/aws-iotevents'; +import * as lambda from '@aws-cdk/aws-lambda'; +import * as cdk from '@aws-cdk/core'; +import * as actions from '../../lib'; + +let stack: cdk.Stack; +let input: iotevents.IInput; +let func: lambda.IFunction; +beforeEach(() => { + stack = new cdk.Stack(); + input = iotevents.Input.fromInputName(stack, 'MyInput', 'test-input'); + func = lambda.Function.fromFunctionAttributes(stack, 'MyFunction', { + functionArn: 'arn:aws:lambda:us-east-1:123456789012:function:MyFn', + sameEnvironment: true, + }); +}); + +test('Default property', () => { + // WHEN + new iotevents.DetectorModel(stack, 'MyDetectorModel', { + initialState: new iotevents.State({ + stateName: 'test-state', + onEnter: [{ + eventName: 'test-eventName', + condition: iotevents.Expression.currentInput(input), + actions: [new actions.LambdaInvokeAction(func)], + }], + }), + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::IoTEvents::DetectorModel', { + DetectorModelDefinition: { + States: [{ + OnEnter: { + Events: [{ + Actions: [{ + Lambda: { + FunctionArn: 'arn:aws:lambda:us-east-1:123456789012:function:MyFn', + }, + }], + }], + }, + }], + }, + RoleArn: { + 'Fn::GetAtt': ['MyDetectorModelDetectorModelRoleF2FB4D88', 'Arn'], + }, + }); + + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { + PolicyDocument: { + Statement: [{ + Action: 'lambda:InvokeFunction', + Effect: 'Allow', + Resource: 'arn:aws:lambda:us-east-1:123456789012:function:MyFn', + }], + }, + Roles: [{ + Ref: 'MyDetectorModelDetectorModelRoleF2FB4D88', + }], + }); +}); diff --git a/packages/@aws-cdk/aws-iotevents/README.md b/packages/@aws-cdk/aws-iotevents/README.md index 809bac071ef7d..9089fdec07cbd 100644 --- a/packages/@aws-cdk/aws-iotevents/README.md +++ b/packages/@aws-cdk/aws-iotevents/README.md @@ -46,8 +46,15 @@ The following example creates an AWS IoT Events detector model to your stack. The detector model need a reference to at least one AWS IoT Events input. AWS IoT Events inputs enable the detector to get MQTT payload values from IoT Core rules. +You can define built-in actions to use a timer or set a variable, or send data to other AWS resources. +See also [@aws-cdk/aws-iotevents-actions](https://docs.aws.amazon.com/cdk/api/v1/docs/aws-iotevents-actions-readme.html) for other actions. + ```ts import * as iotevents from '@aws-cdk/aws-iotevents'; +import * as actions from '@aws-cdk/aws-iotevents-actions'; +import * as lambda from '@aws-cdk/aws-lambda'; + +declare const func: lambda.IFunction; const input = new iotevents.Input(this, 'MyInput', { inputName: 'my_input', // optional @@ -57,8 +64,17 @@ const input = new iotevents.Input(this, 'MyInput', { const warmState = new iotevents.State({ stateName: 'warm', onEnter: [{ - eventName: 'test-event', + eventName: 'test-enter-event', condition: iotevents.Expression.currentInput(input), + actions: [new actions.LambdaInvokeAction(func)], // optional + }], + onInput: [{ // optional + eventName: 'test-input-event', + actions: [new actions.LambdaInvokeAction(func)], + }], + onExit: [{ // optional + eventName: 'test-exit-event', + actions: [new actions.LambdaInvokeAction(func)], }], }); const coldState = new iotevents.State({ @@ -72,6 +88,7 @@ warmState.transitionTo(coldState, { iotevents.Expression.inputAttribute(input, 'payload.temperature'), iotevents.Expression.fromString('10'), ), + executing: [new actions.LambdaInvokeAction(func)], // optional }); // transit to warmState when temperature is 20 coldState.transitionTo(warmState, { diff --git a/packages/@aws-cdk/aws-iotevents/lib/action.ts b/packages/@aws-cdk/aws-iotevents/lib/action.ts new file mode 100644 index 0000000000000..f43c6b6c91626 --- /dev/null +++ b/packages/@aws-cdk/aws-iotevents/lib/action.ts @@ -0,0 +1,33 @@ +import * as iam from '@aws-cdk/aws-iam'; +import { Construct } from 'constructs'; +import { CfnDetectorModel } from './iotevents.generated'; + +/** + * Options when binding a Action to a detector model. + */ +export interface ActionBindOptions { + /** + * The IAM role assumed by IoT Events to perform the action. + */ + readonly role: iam.IRole; +} + +/** + * An abstract action for DetectorModel. + */ +export interface IAction { + /** + * Returns the AWS IoT Events action specification. + */ + bind(scope: Construct, options: ActionBindOptions): ActionConfig; +} + +/** + * Properties for a AWS IoT Events action + */ +export interface ActionConfig { + /** + * The configuration for this action. + */ + readonly configuration: CfnDetectorModel.ActionProperty; +} diff --git a/packages/@aws-cdk/aws-iotevents/lib/detector-model.ts b/packages/@aws-cdk/aws-iotevents/lib/detector-model.ts index 35128bc4531e6..1545e8ec69446 100644 --- a/packages/@aws-cdk/aws-iotevents/lib/detector-model.ts +++ b/packages/@aws-cdk/aws-iotevents/lib/detector-model.ts @@ -124,7 +124,7 @@ export class DetectorModel extends Resource implements IDetectorModel { key: props.detectorKey, detectorModelDefinition: { initialStateName: props.initialState.stateName, - states: props.initialState._collectStateJsons(new Set()), + states: props.initialState._collectStateJsons(this, { role }, new Set()), }, roleArn: role.roleArn, }); diff --git a/packages/@aws-cdk/aws-iotevents/lib/event.ts b/packages/@aws-cdk/aws-iotevents/lib/event.ts index 610469db9c32c..fd452686e054e 100644 --- a/packages/@aws-cdk/aws-iotevents/lib/event.ts +++ b/packages/@aws-cdk/aws-iotevents/lib/event.ts @@ -1,7 +1,8 @@ +import { IAction } from './action'; import { Expression } from './expression'; /** - * Specifies the actions to be performed when the condition evaluates to TRUE. + * Specifies the actions to be performed when the condition evaluates to `true`. */ export interface Event { /** @@ -10,9 +11,16 @@ export interface Event { readonly eventName: string; /** - * The Boolean expression that, when TRUE, causes the actions to be performed. + * The Boolean expression that, when `true`, causes the actions to be performed. * * @default - none (the actions are always executed) */ readonly condition?: Expression; + + /** + * The actions to be performed. + * + * @default - no actions will be performed + */ + readonly actions?: IAction[]; } diff --git a/packages/@aws-cdk/aws-iotevents/lib/index.ts b/packages/@aws-cdk/aws-iotevents/lib/index.ts index 24913635ebe50..b949a47454c3a 100644 --- a/packages/@aws-cdk/aws-iotevents/lib/index.ts +++ b/packages/@aws-cdk/aws-iotevents/lib/index.ts @@ -1,3 +1,4 @@ +export * from './action'; export * from './detector-model'; export * from './event'; export * from './expression'; diff --git a/packages/@aws-cdk/aws-iotevents/lib/state.ts b/packages/@aws-cdk/aws-iotevents/lib/state.ts index 67ee6a32802ec..ef8ce689fec47 100644 --- a/packages/@aws-cdk/aws-iotevents/lib/state.ts +++ b/packages/@aws-cdk/aws-iotevents/lib/state.ts @@ -1,3 +1,5 @@ +import { Construct } from 'constructs'; +import { IAction, ActionBindOptions } from './action'; import { Event } from './event'; import { Expression } from './expression'; import { CfnDetectorModel } from './iotevents.generated'; @@ -15,13 +17,20 @@ export interface TransitionOptions { /** * The condition that is used to determine to cause the state transition and the actions. - * When this was evaluated to TRUE, the state transition and the actions are triggered. + * When this was evaluated to `true`, the state transition and the actions are triggered. */ readonly when: Expression; + + /** + * The actions to be performed with the transition. + * + * @default - no actions will be performed + */ + readonly executing?: IAction[]; } /** - * Specifies the state transition and the actions to be performed when the condition evaluates to TRUE. + * Specifies the state transition and the actions to be performed when the condition evaluates to `true`. */ interface TransitionEvent { /** @@ -30,12 +39,19 @@ interface TransitionEvent { readonly eventName: string; /** - * The Boolean expression that, when TRUE, causes the state transition and the actions to be performed. + * The Boolean expression that, when `true`, causes the state transition and the actions to be performed. */ readonly condition: Expression; /** - * The next state to transit to. When the resuld of condition expression is TRUE, the state is transited. + * The actions to be performed. + * + * @default - no actions will be performed + */ + readonly actions?: IAction[]; + + /** + * The next state to transit to. When the resuld of condition expression is `true`, the state is transited. */ readonly nextState: State; } @@ -50,12 +66,28 @@ export interface StateProps { readonly stateName: string; /** - * Specifies the events on enter. the conditions of the events are evaluated when the state is entered. - * If the condition is `TRUE`, the actions of the event are performed. + * Specifies the events on enter. The conditions of the events will be evaluated when entering this state. + * If the condition of the event evaluates to `true`, the actions of the event will be executed. * - * @default - events on enter will not be set + * @default - no events will trigger on entering this state */ readonly onEnter?: Event[]; + + /** + * Specifies the events on input. The conditions of the events will be evaluated when any input is received. + * If the condition of the event evaluates to `true`, the actions of the event will be executed. + * + * @default - no events will trigger on input in this state + */ + readonly onInput?: Event[]; + + /** + * Specifies the events on exit. The conditions of the events are evaluated when an exiting this state. + * If the condition evaluates to `true`, the actions of the event will be executed. + * + * @default - no events will trigger on exiting this state + */ + readonly onExit?: Event[]; } /** @@ -75,7 +107,7 @@ export class State { /** * Add a transition event to the state. - * The transition event will be triggered if condition is evaluated to TRUE. + * The transition event will be triggered if condition is evaluated to `true`. * * @param targetState the state that will be transit to when the event triggered * @param options transition options including the condition that causes the state transition @@ -90,6 +122,7 @@ export class State { eventName: options.eventName ?? `${this.stateName}_to_${targetState.stateName}`, nextState: targetState, condition: options.when, + actions: options.executing, }); } @@ -100,16 +133,16 @@ export class State { * * @internal */ - public _collectStateJsons(collectedStates: Set): CfnDetectorModel.StateProperty[] { + public _collectStateJsons(scope: Construct, actionBindOptions: ActionBindOptions, collectedStates: Set): CfnDetectorModel.StateProperty[] { if (collectedStates.has(this)) { return []; } collectedStates.add(this); return [ - this.toStateJson(), + this.toStateJson(scope, actionBindOptions), ...this.transitionEvents.flatMap(transitionEvent => { - return transitionEvent.nextState._collectStateJsons(collectedStates); + return transitionEvent.nextState._collectStateJsons(scope, actionBindOptions, collectedStates); }), ]; } @@ -123,26 +156,41 @@ export class State { return this.props.onEnter?.some(event => event.condition) ?? false; } - private toStateJson(): CfnDetectorModel.StateProperty { - const { onEnter } = this.props; + private toStateJson(scope: Construct, actionBindOptions: ActionBindOptions): CfnDetectorModel.StateProperty { + const { onEnter, onInput, onExit } = this.props; return { stateName: this.stateName, - onEnter: onEnter && { events: toEventsJson(onEnter) }, - onInput: { - transitionEvents: toTransitionEventsJson(this.transitionEvents), + onEnter: onEnter && { + events: toEventsJson(scope, actionBindOptions, onEnter), + }, + onInput: (onInput || this.transitionEvents.length !== 0) ? { + events: toEventsJson(scope, actionBindOptions, onInput), + transitionEvents: toTransitionEventsJson(scope, actionBindOptions, this.transitionEvents), + } : undefined, + onExit: onExit && { + events: toEventsJson(scope, actionBindOptions, onExit), }, }; } } -function toEventsJson(events: Event[]): CfnDetectorModel.EventProperty[] { - return events.map(event => ({ +function toEventsJson( + scope: Construct, + actionBindOptions: ActionBindOptions, + events?: Event[], +): CfnDetectorModel.EventProperty[] | undefined { + return events?.map(event => ({ eventName: event.eventName, condition: event.condition?.evaluate(), + actions: event.actions?.map(action => action.bind(scope, actionBindOptions).configuration), })); } -function toTransitionEventsJson(transitionEvents: TransitionEvent[]): CfnDetectorModel.TransitionEventProperty[] | undefined { +function toTransitionEventsJson( + scope: Construct, + actionBindOptions: ActionBindOptions, + transitionEvents: TransitionEvent[], +): CfnDetectorModel.TransitionEventProperty[] | undefined { if (transitionEvents.length === 0) { return undefined; } @@ -150,6 +198,7 @@ function toTransitionEventsJson(transitionEvents: TransitionEvent[]): CfnDetecto return transitionEvents.map(transitionEvent => ({ eventName: transitionEvent.eventName, condition: transitionEvent.condition.evaluate(), + actions: transitionEvent.actions?.map(action => action.bind(scope, actionBindOptions).configuration), nextState: transitionEvent.nextState.stateName, })); } diff --git a/packages/@aws-cdk/aws-iotevents/test/detector-model.test.ts b/packages/@aws-cdk/aws-iotevents/test/detector-model.test.ts index c90a10cf34374..e3844ce7915ba 100644 --- a/packages/@aws-cdk/aws-iotevents/test/detector-model.test.ts +++ b/packages/@aws-cdk/aws-iotevents/test/detector-model.test.ts @@ -139,6 +139,158 @@ test('can set multiple events to State', () => { }); }); +test('can set actions to events', () => { + // WHEN + new iotevents.DetectorModel(stack, 'MyDetectorModel', { + initialState: new iotevents.State({ + stateName: 'test-state', + onEnter: [{ + eventName: 'test-eventName1', + condition: iotevents.Expression.currentInput(input), + actions: [{ + bind: () => ({ + configuration: { + lambda: { + functionArn: 'arn:aws:lambda:us-east-1:123456789012:function:MyFn', + }, + }, + }), + }], + }], + }), + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::IoTEvents::DetectorModel', { + DetectorModelDefinition: { + States: [ + Match.objectLike({ + OnEnter: { + Events: [{ + Actions: [{ Lambda: { FunctionArn: 'arn:aws:lambda:us-east-1:123456789012:function:MyFn' } }], + }], + }, + }), + ], + }, + }); +}); + +test.each([ + ['onInput', { onInput: [{ eventName: 'test-eventName1' }] }, { OnInput: { Events: [{ EventName: 'test-eventName1' }] } }], + ['onExit', { onExit: [{ eventName: 'test-eventName1' }] }, { OnExit: { Events: [{ EventName: 'test-eventName1' }] } }], +])('can set %s to State', (_, events, expected) => { + // WHEN + new iotevents.DetectorModel(stack, 'MyDetectorModel', { + initialState: new iotevents.State({ + stateName: 'test-state', + onEnter: [{ eventName: 'test-eventName1', condition: iotevents.Expression.currentInput(input) }], + ...events, + }), + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::IoTEvents::DetectorModel', { + DetectorModelDefinition: { + States: [Match.objectLike(expected)], + }, + }); +}); + +test('can set an action to multiple detector models', () => { + // GIVEN an action + const action: iotevents.IAction = { + bind: (_, { role }) => { + role.addToPrincipalPolicy(new iam.PolicyStatement({ + actions: ['lambda:InvokeFunction'], + resources: ['arn:aws:lambda:us-east-1:123456789012:function:MyFn'], + })); + return { + configuration: { + lambda: { functionArn: 'arn:aws:lambda:us-east-1:123456789012:function:MyFn' }, + }, + }; + }, + }; + + // WHEN the action is set to two detector models + new iotevents.DetectorModel(stack, 'MyDetectorModel1', { + detectorModelName: 'MyDetectorModel1', + initialState: new iotevents.State({ + stateName: 'test-state', + onEnter: [{ + eventName: 'test-eventName1', + condition: iotevents.Expression.currentInput(input), + actions: [action], + }], + }), + }); + new iotevents.DetectorModel(stack, 'MyDetectorModel2', { + detectorModelName: 'MyDetectorModel2', + initialState: new iotevents.State({ + stateName: 'test-state', + onEnter: [{ + eventName: 'test-eventName1', + condition: iotevents.Expression.currentInput(input), + actions: [action], + }], + }), + }); + + // THEN creates two detector model resouces and two iam policy resources + Template.fromStack(stack).resourceCountIs('AWS::IoTEvents::DetectorModel', 2); + Template.fromStack(stack).resourceCountIs('AWS::IAM::Policy', 2); + + Template.fromStack(stack).hasResourceProperties('AWS::IoTEvents::DetectorModel', { + DetectorModelName: 'MyDetectorModel1', + DetectorModelDefinition: { + States: [ + Match.objectLike({ + OnEnter: { + Events: [{ + Actions: [{ Lambda: { FunctionArn: 'arn:aws:lambda:us-east-1:123456789012:function:MyFn' } }], + }], + }, + }), + ], + }, + }); + Template.fromStack(stack).hasResourceProperties('AWS::IoTEvents::DetectorModel', { + DetectorModelName: 'MyDetectorModel2', + DetectorModelDefinition: { + States: [ + Match.objectLike({ + OnEnter: { + Events: [{ + Actions: [{ Lambda: { FunctionArn: 'arn:aws:lambda:us-east-1:123456789012:function:MyFn' } }], + }], + }, + }), + ], + }, + }); + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { + Roles: [{ Ref: 'MyDetectorModel1DetectorModelRoleB36845CD' }], + PolicyDocument: { + Statement: [{ + Action: 'lambda:InvokeFunction', + Effect: 'Allow', + Resource: 'arn:aws:lambda:us-east-1:123456789012:function:MyFn', + }], + }, + }); + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { + Roles: [{ Ref: 'MyDetectorModel2DetectorModelRole3C437E90' }], + PolicyDocument: { + Statement: [{ + Action: 'lambda:InvokeFunction', + Effect: 'Allow', + Resource: 'arn:aws:lambda:us-east-1:123456789012:function:MyFn', + }], + }, + }); +}); + test('can set states with transitions', () => { // GIVEN const firstState = new iotevents.State({ @@ -222,6 +374,47 @@ test('can set states with transitions', () => { }); }); +test('can set actions to transitions', () => { + // GIVEN + const firstState = new iotevents.State({ + stateName: 'firstState', + onEnter: [{ + eventName: 'test-eventName', + condition: iotevents.Expression.currentInput(input), + }], + }); + const secondState = new iotevents.State({ + stateName: 'secondState', + }); + + // WHEN + firstState.transitionTo(secondState, { + when: iotevents.Expression.eq( + iotevents.Expression.inputAttribute(input, 'payload.temperature'), + iotevents.Expression.fromString('12'), + ), + executing: [{ bind: () => ({ configuration: { setTimer: { timerName: 'test-timer' } } }) }], + }); + + new iotevents.DetectorModel(stack, 'MyDetectorModel', { + initialState: firstState, + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::IoTEvents::DetectorModel', { + DetectorModelDefinition: { + States: Match.arrayWith([Match.objectLike({ + StateName: 'firstState', + OnInput: { + TransitionEvents: [{ + Actions: [{ SetTimer: { TimerName: 'test-timer' } }], + }], + }, + })]), + }, + }); +}); + test('can set role', () => { // WHEN const role = iam.Role.fromRoleArn(stack, 'test-role', 'arn:aws:iam::123456789012:role/ForTest'); diff --git a/packages/@aws-cdk/aws-iotevents/test/integ.detector-model.expected.json b/packages/@aws-cdk/aws-iotevents/test/integ.detector-model.expected.json index 888869a41e68e..3b24a7f7776d8 100644 --- a/packages/@aws-cdk/aws-iotevents/test/integ.detector-model.expected.json +++ b/packages/@aws-cdk/aws-iotevents/test/integ.detector-model.expected.json @@ -63,7 +63,43 @@ } ] }, + "OnExit": { + "Events": [ + { + "Condition": { + "Fn::Join": [ + "", + [ + "$input.", + { + "Ref": "MyInput08947B23" + }, + ".payload.temperature == 31.7" + ] + ] + }, + "EventName": "test-exit-event" + } + ] + }, "OnInput": { + "Events": [ + { + "Condition": { + "Fn::Join": [ + "", + [ + "$input.", + { + "Ref": "MyInput08947B23" + }, + ".payload.temperature == 31.6" + ] + ] + }, + "EventName": "test-input-event" + } + ], "TransitionEvents": [ { "Condition": { diff --git a/packages/@aws-cdk/aws-iotevents/test/integ.detector-model.ts b/packages/@aws-cdk/aws-iotevents/test/integ.detector-model.ts index 5f6d2839f3a93..1c3996b226623 100644 --- a/packages/@aws-cdk/aws-iotevents/test/integ.detector-model.ts +++ b/packages/@aws-cdk/aws-iotevents/test/integ.detector-model.ts @@ -23,6 +23,20 @@ class TestStack extends cdk.Stack { ), ), }], + onInput: [{ + eventName: 'test-input-event', + condition: iotevents.Expression.eq( + iotevents.Expression.inputAttribute(input, 'payload.temperature'), + iotevents.Expression.fromString('31.6'), + ), + }], + onExit: [{ + eventName: 'test-exit-event', + condition: iotevents.Expression.eq( + iotevents.Expression.inputAttribute(input, 'payload.temperature'), + iotevents.Expression.fromString('31.7'), + ), + }], }); const offlineState = new iotevents.State({ stateName: 'offline', diff --git a/packages/@aws-cdk/aws-lambda-nodejs/README.md b/packages/@aws-cdk/aws-lambda-nodejs/README.md index 95d7559cf25f3..1ce7d9786a4d1 100644 --- a/packages/@aws-cdk/aws-lambda-nodejs/README.md +++ b/packages/@aws-cdk/aws-lambda-nodejs/README.md @@ -198,6 +198,7 @@ new lambda.NodejsFunction(this, 'my-handler', { charset: lambda.Charset.UTF8, // do not escape non-ASCII characters, defaults to Charset.ASCII format: lambda.OutputFormat.ESM, // ECMAScript module output format, defaults to OutputFormat.CJS (OutputFormat.ESM requires Node.js 14.x) mainFields: ['module', 'main'], // prefer ECMAScript versions of dependencies + inject: ['./my-shim.js', './other-shim.js'] // allows to automatically replace a global variable with an import from another file }, }); ``` diff --git a/packages/@aws-cdk/aws-lambda-nodejs/lib/bundling.ts b/packages/@aws-cdk/aws-lambda-nodejs/lib/bundling.ts index c7506ceed8c28..ee6b395c5d262 100644 --- a/packages/@aws-cdk/aws-lambda-nodejs/lib/bundling.ts +++ b/packages/@aws-cdk/aws-lambda-nodejs/lib/bundling.ts @@ -89,7 +89,7 @@ export class Bundling implements cdk.BundlingOptions { this.packageManager = PackageManager.fromLockFile(props.depsLockFilePath, props.logLevel); Bundling.esbuildInstallation = Bundling.esbuildInstallation ?? PackageInstallation.detect('esbuild'); - Bundling.tscInstallation = Bundling.tscInstallation ?? PackageInstallation.detect('tsc'); + Bundling.tscInstallation = Bundling.tscInstallation ?? PackageInstallation.detect('typescript'); this.projectRoot = props.projectRoot; this.relativeEntryPath = path.relative(this.projectRoot, path.resolve(props.entry)); @@ -198,6 +198,7 @@ export class Bundling implements cdk.BundlingOptions { ...this.props.footer ? [`--footer:js=${JSON.stringify(this.props.footer)}`] : [], ...this.props.charset ? [`--charset=${this.props.charset}`] : [], ...this.props.mainFields ? [`--main-fields=${this.props.mainFields.join(',')}`] : [], + ...this.props.inject ? this.props.inject.map(i => `--inject:${i}`) : [], ]; let depsCommand = ''; diff --git a/packages/@aws-cdk/aws-lambda-nodejs/lib/types.ts b/packages/@aws-cdk/aws-lambda-nodejs/lib/types.ts index ff99b722b998e..7b6b5c642f755 100644 --- a/packages/@aws-cdk/aws-lambda-nodejs/lib/types.ts +++ b/packages/@aws-cdk/aws-lambda-nodejs/lib/types.ts @@ -279,6 +279,15 @@ export interface BundlingOptions { * @default ['main', 'module'] */ readonly mainFields?: string[]; + + /** + * This option allows you to automatically replace a global variable with an + * import from another file. + * + * @see https://esbuild.github.io/api/#inject + * @default - no code is injected + */ + readonly inject?: string[] } /** diff --git a/packages/@aws-cdk/aws-lambda-nodejs/test/bundling.test.ts b/packages/@aws-cdk/aws-lambda-nodejs/test/bundling.test.ts index 1557e687d75ed..37e7fa0c94b6b 100644 --- a/packages/@aws-cdk/aws-lambda-nodejs/test/bundling.test.ts +++ b/packages/@aws-cdk/aws-lambda-nodejs/test/bundling.test.ts @@ -16,6 +16,7 @@ beforeEach(() => { jest.resetAllMocks(); jest.restoreAllMocks(); Bundling.clearEsbuildInstallationCache(); + Bundling.clearTscInstallationCache(); jest.spyOn(Code, 'fromAsset'); @@ -208,6 +209,7 @@ test('esbuild bundling with esbuild options', () => { 'process.env.STRING': JSON.stringify('this is a "test"'), }, format: OutputFormat.ESM, + inject: ['./my-shim.js'], }); // Correctly bundles with esbuild @@ -224,7 +226,7 @@ test('esbuild bundling with esbuild options', () => { defineInstructions, '--log-level=silent --keep-names --tsconfig=/asset-input/lib/custom-tsconfig.ts', '--metafile=/asset-output/index.meta.json --banner:js="/* comments */" --footer:js="/* comments */"', - '--charset=utf8 --main-fields=module,main', + '--charset=utf8 --main-fields=module,main --inject:./my-shim.js', ].join(' '), ], }), @@ -601,6 +603,8 @@ test('esbuild bundling with pre compilations', () => { ], }), }); + + expect(detectPackageInstallationMock).toHaveBeenCalledWith('typescript'); }); test('throws with pre compilation and not found tsconfig', () => { diff --git a/packages/@aws-cdk/aws-lambda-python/lib/bundling.ts b/packages/@aws-cdk/aws-lambda-python/lib/bundling.ts index 28afa880602fc..27c8d24f83558 100644 --- a/packages/@aws-cdk/aws-lambda-python/lib/bundling.ts +++ b/packages/@aws-cdk/aws-lambda-python/lib/bundling.ts @@ -34,6 +34,13 @@ export interface BundlingProps extends BundlingOptions { * @default Architecture.X86_64 */ readonly architecture?: Architecture; + + /** + * Whether or not the bundling process should be skipped + * + * @default - Does not skip bundling + */ + readonly skip?: boolean; } /** @@ -45,7 +52,7 @@ export class Bundling implements CdkBundlingOptions { assetHash: options.assetHash, assetHashType: options.assetHashType, exclude: DEPENDENCY_EXCLUDES, - bundling: new Bundling(options), + bundling: options.skip ? undefined : new Bundling(options), }); } @@ -62,7 +69,7 @@ export class Bundling implements CdkBundlingOptions { image, } = props; - const outputPath = path.join(AssetStaging.BUNDLING_OUTPUT_DIR, outputPathSuffix); + const outputPath = path.posix.join(AssetStaging.BUNDLING_OUTPUT_DIR, outputPathSuffix); const bundlingCommands = this.createBundlingCommand({ entry, @@ -72,7 +79,7 @@ export class Bundling implements CdkBundlingOptions { this.image = image ?? DockerImage.fromBuild(path.join(__dirname, '../lib'), { buildArgs: { - ...props.buildArgs ?? {}, + ...props.buildArgs, IMAGE: runtime.bundlingImage.image, }, platform: architecture.dockerPlatform, diff --git a/packages/@aws-cdk/aws-lambda-python/lib/function.ts b/packages/@aws-cdk/aws-lambda-python/lib/function.ts index 7c24ed2be09d5..61a91b8138fc0 100644 --- a/packages/@aws-cdk/aws-lambda-python/lib/function.ts +++ b/packages/@aws-cdk/aws-lambda-python/lib/function.ts @@ -2,6 +2,7 @@ import * as fs from 'fs'; import * as path from 'path'; import { Construct } from 'constructs'; import { Function, FunctionOptions, Runtime, RuntimeFamily } from '@aws-cdk/aws-lambda'; +import { Stack } from '@aws-cdk/core'; import { Bundling } from './bundling'; import { BundlingOptions } from './types'; @@ -75,6 +76,7 @@ export class PythonFunction extends Function { code: Bundling.bundle({ entry, runtime, + skip: !Stack.of(scope).bundlingRequired, ...props.bundling, }), handler: resolvedHandler, diff --git a/packages/@aws-cdk/aws-lambda-python/lib/layer.ts b/packages/@aws-cdk/aws-lambda-python/lib/layer.ts index 20908e7625cf3..3ed2f30a25c46 100644 --- a/packages/@aws-cdk/aws-lambda-python/lib/layer.ts +++ b/packages/@aws-cdk/aws-lambda-python/lib/layer.ts @@ -1,9 +1,13 @@ import * as path from 'path'; import * as lambda from '@aws-cdk/aws-lambda'; -import { Construct } from 'constructs'; +import { Stack } from '@aws-cdk/core'; import { Bundling } from './bundling'; import { BundlingOptions } from './types'; +// keep this import separate from other imports to reduce chance for merge conflicts with v2-main +// eslint-disable-next-line no-duplicate-imports, import/order +import { Construct } from 'constructs'; + /** * Properties for PythonLayerVersion */ @@ -64,6 +68,7 @@ export class PythonLayerVersion extends lambda.LayerVersion { runtime, architecture, outputPathSuffix: 'python', + skip: !Stack.of(scope).bundlingRequired, ...props.bundling, }), }); diff --git a/packages/@aws-cdk/aws-lambda-python/test/bundling.test.ts b/packages/@aws-cdk/aws-lambda-python/test/bundling.test.ts index 6bf90aeb090a1..ca2142cce0667 100644 --- a/packages/@aws-cdk/aws-lambda-python/test/bundling.test.ts +++ b/packages/@aws-cdk/aws-lambda-python/test/bundling.test.ts @@ -249,3 +249,25 @@ test('Bundling with custom environment vars`', () => { }), })); }); + +test('Do not build docker image when skipping bundling', () => { + const entry = path.join(__dirname, 'lambda-handler'); + Bundling.bundle({ + entry: entry, + runtime: Runtime.PYTHON_3_7, + skip: true, + }); + + expect(DockerImage.fromBuild).not.toHaveBeenCalled(); +}); + +test('Build docker image when bundling is not skipped', () => { + const entry = path.join(__dirname, 'lambda-handler'); + Bundling.bundle({ + entry: entry, + runtime: Runtime.PYTHON_3_7, + skip: false, + }); + + expect(DockerImage.fromBuild).toHaveBeenCalled(); +}); diff --git a/packages/@aws-cdk/aws-lambda-python/test/function.test.ts b/packages/@aws-cdk/aws-lambda-python/test/function.test.ts index 7eac6ad3df9ec..6fd12540b78c3 100644 --- a/packages/@aws-cdk/aws-lambda-python/test/function.test.ts +++ b/packages/@aws-cdk/aws-lambda-python/test/function.test.ts @@ -167,3 +167,35 @@ test('Allows use of custom bundling image', () => { image, })); }); + +test('Skip bundling when stack does not require it', () => { + const spy = jest.spyOn(stack, 'bundlingRequired', 'get').mockReturnValue(false); + const entry = path.join(__dirname, 'lambda-handler'); + + new PythonFunction(stack, 'function', { + entry, + runtime: Runtime.PYTHON_3_8, + }); + + expect(Bundling.bundle).toHaveBeenCalledWith(expect.objectContaining({ + skip: true, + })); + + spy.mockRestore(); +}); + +test('Do not skip bundling when stack requires it', () => { + const spy = jest.spyOn(stack, 'bundlingRequired', 'get').mockReturnValue(true); + const entry = path.join(__dirname, 'lambda-handler'); + + new PythonFunction(stack, 'function', { + entry, + runtime: Runtime.PYTHON_3_8, + }); + + expect(Bundling.bundle).toHaveBeenCalledWith(expect.objectContaining({ + skip: false, + })); + + spy.mockRestore(); +}); diff --git a/packages/@aws-cdk/aws-lambda-python/test/layer.test.ts b/packages/@aws-cdk/aws-lambda-python/test/layer.test.ts index a254e82d48af6..eb12017072030 100644 --- a/packages/@aws-cdk/aws-lambda-python/test/layer.test.ts +++ b/packages/@aws-cdk/aws-lambda-python/test/layer.test.ts @@ -63,3 +63,33 @@ test('Allows use of custom bundling image', () => { image, })); }); + +test('Skip bundling when stack does not require it', () => { + const spy = jest.spyOn(stack, 'bundlingRequired', 'get').mockReturnValue(false); + const entry = path.join(__dirname, 'lambda-handler-project'); + + new PythonLayerVersion(stack, 'layer', { + entry, + }); + + expect(Bundling.bundle).toHaveBeenCalledWith(expect.objectContaining({ + skip: true, + })); + + spy.mockRestore(); +}); + +test('Do not skip bundling when stack requires it', () => { + const spy = jest.spyOn(stack, 'bundlingRequired', 'get').mockReturnValue(true); + const entry = path.join(__dirname, 'lambda-handler-project'); + + new PythonLayerVersion(stack, 'layer', { + entry, + }); + + expect(Bundling.bundle).toHaveBeenCalledWith(expect.objectContaining({ + skip: false, + })); + + spy.mockRestore(); +}); diff --git a/packages/@aws-cdk/aws-lambda/lib/event-source-mapping.ts b/packages/@aws-cdk/aws-lambda/lib/event-source-mapping.ts index 172d681d1fef9..7840a465b87b2 100644 --- a/packages/@aws-cdk/aws-lambda/lib/event-source-mapping.ts +++ b/packages/@aws-cdk/aws-lambda/lib/event-source-mapping.ts @@ -91,7 +91,7 @@ export interface EventSourceMappingOptions { * Valid Range: Minimum value of 1. Maximum value of 10000. * * @default - Amazon Kinesis, Amazon DynamoDB, and Amazon MSK is 100 records. - * Both the default and maximum for Amazon SQS are 10 messages. + * The default for Amazon SQS is 10 messages. For standard SQS queues, the maximum is 10,000. For FIFO SQS queues, the maximum is 10. */ readonly batchSize?: number; diff --git a/packages/@aws-cdk/aws-lambda/lib/lambda-version.ts b/packages/@aws-cdk/aws-lambda/lib/lambda-version.ts index dbbd1496d8d8c..50a3e5ade12dd 100644 --- a/packages/@aws-cdk/aws-lambda/lib/lambda-version.ts +++ b/packages/@aws-cdk/aws-lambda/lib/lambda-version.ts @@ -93,16 +93,17 @@ export interface VersionAttributes { } /** - * A single newly-deployed version of a Lambda function. + * Tag the current state of a Function with a Version number * - * This object exists to--at deploy time--query the "then-current" version of - * the Lambda function that it refers to. This Version object can then be - * used in `Alias` to refer to a particular deployment of a Lambda. + * Avoid using this resource directly. If you need a Version object, use + * `function.currentVersion` instead. That will add a Version object to your + * template, and make sure the Version is invalidated whenever the Function + * object changes. If you use the `Version` resource directly, you are + * responsible for making sure it is invalidated (by changing its + * logical ID) whenever necessary. * - * This means that for every new update you deploy to your Lambda (using the - * CDK and Aliases), you must always create a new Version object. In - * particular, it must have a different name, so that a new resource is - * created. + * Version resources can then be used in `Alias` resources to refer to a + * particular deployment of a Lambda. * * If you want to ensure that you're associating the right version with * the right deployment, specify the `codeSha256` property while diff --git a/packages/@aws-cdk/aws-opensearchservice/README.md b/packages/@aws-cdk/aws-opensearchservice/README.md index 79d2289dcfffb..db737d1b84741 100644 --- a/packages/@aws-cdk/aws-opensearchservice/README.md +++ b/packages/@aws-cdk/aws-opensearchservice/README.md @@ -235,6 +235,61 @@ const domain = new opensearch.Domain(this, 'Domain', { const masterUserPassword = domain.masterUserPassword; ``` +## Custom access policies + +If the domain requires custom access control it can be configured either as a +constructor property, or later by means of a helper method. + +For simple permissions the `accessPolicies` constructor may be sufficient: + +```ts +const domain = new opensearch.Domain(this, 'Domain', { + version: opensearch.EngineVersion.OPENSEARCH_1_0, + accessPolicies: [ + new iam.PolicyStatement({ + actions: ['es:*ESHttpPost', 'es:ESHttpPut*'], + effect: iam.Effect.ALLOW, + principals: [new iam.AccountPrincipal('123456789012')], + resources: ['*'], + }), + ] +}); +``` + +For more complex use-cases, for example, to set the domain up to receive data from a +[cross-account Kinesis Firehose](https://aws.amazon.com/premiumsupport/knowledge-center/kinesis-firehose-cross-account-streaming/) the `addAccessPolicies` helper method +allows for policies that include the explicit domain ARN. + +```ts +const domain = new opensearch.Domain(this, 'Domain', { + version: opensearch.EngineVersion.OPENSEARCH_1_0, +}); +domain.addAccessPolicies( + new iam.PolicyStatement({ + actions: ['es:ESHttpPost', 'es:ESHttpPut'], + effect: iam.Effect.ALLOW, + principals: [new iam.AccountPrincipal('123456789012')], + resources: [domain.domainArn, `${domain.domainArn}/*`], + }), + new iam.PolicyStatement({ + actions: ['es:ESHttpGet'], + effect: iam.Effect.ALLOW, + principals: [new iam.AccountPrincipal('123456789012')], + resources: [ + `${domain.domainArn}/_all/_settings`, + `${domain.domainArn}/_cluster/stats`, + `${domain.domainArn}/index-name*/_mapping/type-name`, + `${domain.domainArn}/roletest*/_mapping/roletest`, + `${domain.domainArn}/_nodes`, + `${domain.domainArn}/_nodes/stats`, + `${domain.domainArn}/_nodes/*/stats`, + `${domain.domainArn}/_stats`, + `${domain.domainArn}/index-name*/_stats`, + `${domain.domainArn}/roletest*/_stat`, + ], + }), +); +``` ## Audit logs diff --git a/packages/@aws-cdk/aws-opensearchservice/lib/domain.ts b/packages/@aws-cdk/aws-opensearchservice/lib/domain.ts index aadf9e011b827..fbcd1d9f33d51 100644 --- a/packages/@aws-cdk/aws-opensearchservice/lib/domain.ts +++ b/packages/@aws-cdk/aws-opensearchservice/lib/domain.ts @@ -1195,6 +1195,10 @@ export class Domain extends DomainBase implements IDomain, ec2.IConnectable { private readonly domain: CfnDomain; + private accessPolicy?: OpenSearchAccessPolicy + + private encryptionAtRestOptions?: EncryptionAtRestOptions + private readonly _connections: ec2.Connections | undefined; constructor(scope: Construct, id: string, props: DomainProps) { @@ -1654,33 +1658,12 @@ export class Domain extends DomainBase implements IDomain, ec2.IConnectable { }); } - const accessPolicyStatements: iam.PolicyStatement[] | undefined = unsignedBasicAuthEnabled - ? (props.accessPolicies ?? []).concat(unsignedAccessPolicy) - : props.accessPolicies; - - if (accessPolicyStatements != null) { - const accessPolicy = new OpenSearchAccessPolicy(this, 'Access Policy', { - domainName: this.domainName, - domainArn: this.domainArn, - accessPolicies: accessPolicyStatements, - }); - - if (props.encryptionAtRest?.kmsKey) { - - // https://docs.aws.amazon.com/opensearch-service/latest/developerguide/encryption-at-rest.html - - // these permissions are documented as required during domain creation. - // while not strictly documented for updates as well, it stands to reason that an update - // operation might require these in case the cluster uses a kms key. - // empircal evidence shows this is indeed required: https://github.com/aws/aws-cdk/issues/11412 - accessPolicy.grantPrincipal.addToPrincipalPolicy(new iam.PolicyStatement({ - actions: ['kms:List*', 'kms:Describe*', 'kms:CreateGrant'], - resources: [props.encryptionAtRest.kmsKey.keyArn], - effect: iam.Effect.ALLOW, - })); - } - - accessPolicy.node.addDependency(this.domain); + this.encryptionAtRestOptions = props.encryptionAtRest; + if (props.accessPolicies) { + this.addAccessPolicies(...props.accessPolicies); + } + if (unsignedBasicAuthEnabled) { + this.addAccessPolicies(unsignedAccessPolicy); } } @@ -1694,6 +1677,39 @@ export class Domain extends DomainBase implements IDomain, ec2.IConnectable { } return this._connections; } + + + /** + * Add policy statements to the domain access policy + */ + public addAccessPolicies(...accessPolicyStatements: iam.PolicyStatement[]) { + if (accessPolicyStatements.length > 0) { + if (!this.accessPolicy) { + // Only create the custom resource after there are statements to set. + this.accessPolicy = new OpenSearchAccessPolicy(this, 'AccessPolicy', { + domainName: this.domainName, + domainArn: this.domainArn, + accessPolicies: accessPolicyStatements, + }); + + if (this.encryptionAtRestOptions?.kmsKey) { + // https://docs.aws.amazon.com/opensearch-service/latest/developerguide/encryption-at-rest.html + + // these permissions are documented as required during domain creation. + // while not strictly documented for updates as well, it stands to reason that an update + // operation might require these in case the cluster uses a kms key. + // empircal evidence shows this is indeed required: https://github.com/aws/aws-cdk/issues/11412 + this.accessPolicy.grantPrincipal.addToPrincipalPolicy(new iam.PolicyStatement({ + actions: ['kms:List*', 'kms:Describe*', 'kms:CreateGrant'], + resources: [this.encryptionAtRestOptions.kmsKey.keyArn], + effect: iam.Effect.ALLOW, + })); + } + } else { + this.accessPolicy.addAccessPolicies(...accessPolicyStatements); + } + } + } } /** diff --git a/packages/@aws-cdk/aws-opensearchservice/lib/opensearch-access-policy.ts b/packages/@aws-cdk/aws-opensearchservice/lib/opensearch-access-policy.ts index 3d5b58fb40200..9f2b8f4df905f 100644 --- a/packages/@aws-cdk/aws-opensearchservice/lib/opensearch-access-policy.ts +++ b/packages/@aws-cdk/aws-opensearchservice/lib/opensearch-access-policy.ts @@ -1,4 +1,5 @@ import * as iam from '@aws-cdk/aws-iam'; +import * as cdk from '@aws-cdk/core'; import * as cr from '@aws-cdk/custom-resources'; // keep this import separate from other imports to reduce chance for merge conflicts with v2-main @@ -29,11 +30,10 @@ export interface OpenSearchAccessPolicyProps { * Creates LogGroup resource policies. */ export class OpenSearchAccessPolicy extends cr.AwsCustomResource { - constructor(scope: Construct, id: string, props: OpenSearchAccessPolicyProps) { - const policyDocument = new iam.PolicyDocument({ - statements: props.accessPolicies, - }); + private accessPolicyStatements: iam.PolicyStatement[] = []; + + constructor(scope: Construct, id: string, props: OpenSearchAccessPolicyProps) { super(scope, id, { resourceType: 'Custom::OpenSearchAccessPolicy', onUpdate: { @@ -41,7 +41,13 @@ export class OpenSearchAccessPolicy extends cr.AwsCustomResource { service: 'OpenSearch', parameters: { DomainName: props.domainName, - AccessPolicies: JSON.stringify(policyDocument.toJSON()), + AccessPolicies: cdk.Lazy.string({ + produce: () => JSON.stringify( + new iam.PolicyDocument({ + statements: this.accessPolicyStatements, + }).toJSON(), + ), + }), }, // this is needed to limit the response body, otherwise it exceeds the CFN 4k limit outputPaths: ['DomainConfig.AccessPolicies'], @@ -49,5 +55,14 @@ export class OpenSearchAccessPolicy extends cr.AwsCustomResource { }, policy: cr.AwsCustomResourcePolicy.fromStatements([new iam.PolicyStatement({ actions: ['es:UpdateDomainConfig'], resources: [props.domainArn] })]), }); + + this.addAccessPolicies(...props.accessPolicies); + } + + /** + * Add policy statements to the domain access policy + */ + public addAccessPolicies(...accessPolicyStatements: iam.PolicyStatement[]) { + this.accessPolicyStatements.push(...accessPolicyStatements); } } diff --git a/packages/@aws-cdk/aws-opensearchservice/test/domain.test.ts b/packages/@aws-cdk/aws-opensearchservice/test/domain.test.ts index 3739031d6f3b2..5ffcb3140c791 100644 --- a/packages/@aws-cdk/aws-opensearchservice/test/domain.test.ts +++ b/packages/@aws-cdk/aws-opensearchservice/test/domain.test.ts @@ -204,6 +204,66 @@ test('can enable version upgrade update policy', () => { }); }); +test('can set a self-referencing custom policy', () => { + const domain = new Domain(stack, 'Domain', { + version: defaultVersion, + }); + + domain.addAccessPolicies( + new iam.PolicyStatement({ + actions: ['es:ESHttpPost', 'es:ESHttpPut'], + effect: iam.Effect.ALLOW, + principals: [new iam.AccountPrincipal('5678')], + resources: [domain.domainArn, `${domain.domainArn}/*`], + }), + ); + + const expectedPolicy = { + 'Fn::Join': [ + '', + [ + '{"action":"updateDomainConfig","service":"OpenSearch","parameters":{"DomainName":"', + { + Ref: 'Domain66AC69E0', + }, + '","AccessPolicies":"{\\"Statement\\":[{\\"Action\\":[\\"es:ESHttpPost\\",\\"es:ESHttpPut\\"],\\"Effect\\":\\"Allow\\",\\"Principal\\":{\\"AWS\\":\\"arn:', + { + Ref: 'AWS::Partition', + }, + ':iam::5678:root\\"},\\"Resource\\":[\\"', + { + 'Fn::GetAtt': [ + 'Domain66AC69E0', + 'Arn', + ], + }, + '\\",\\"', + { + 'Fn::GetAtt': [ + 'Domain66AC69E0', + 'Arn', + ], + }, + '/*\\"]}],\\"Version\\":\\"2012-10-17\\"}"},"outputPaths":["DomainConfig.AccessPolicies"],"physicalResourceId":{"id":"', + { + Ref: 'Domain66AC69E0', + }, + 'AccessPolicy"}}', + ], + ], + }; + Template.fromStack(stack).hasResourceProperties('Custom::OpenSearchAccessPolicy', { + ServiceToken: { + 'Fn::GetAtt': [ + 'AWS679f53fac002430cb0da5b7982bd22872D164C4C', + 'Arn', + ], + }, + Create: expectedPolicy, + Update: expectedPolicy, + }); +}); + describe('UltraWarm instances', () => { test('can enable UltraWarm instances', () => { diff --git a/packages/@aws-cdk/aws-opensearchservice/test/integ.opensearch.custom-kms-key.expected.json b/packages/@aws-cdk/aws-opensearchservice/test/integ.opensearch.custom-kms-key.expected.json index 63a1cb0c236d5..e232a90c60ae8 100644 --- a/packages/@aws-cdk/aws-opensearchservice/test/integ.opensearch.custom-kms-key.expected.json +++ b/packages/@aws-cdk/aws-opensearchservice/test/integ.opensearch.custom-kms-key.expected.json @@ -71,7 +71,7 @@ "UpdateReplacePolicy": "Delete", "DeletionPolicy": "Delete" }, - "DomainAccessPolicyCustomResourcePolicy107E31EB": { + "DomainAccessPolicyCustomResourcePolicyE61F1845": { "Type": "AWS::IAM::Policy", "Properties": { "PolicyDocument": { @@ -89,18 +89,15 @@ ], "Version": "2012-10-17" }, - "PolicyName": "DomainAccessPolicyCustomResourcePolicy107E31EB", + "PolicyName": "DomainAccessPolicyCustomResourcePolicyE61F1845", "Roles": [ { "Ref": "AWS679f53fac002430cb0da5b7982bd2287ServiceRoleC1EA0FF2" } ] - }, - "DependsOn": [ - "Domain66AC69E0" - ] + } }, - "DomainAccessPolicyFCD6BE37": { + "DomainAccessPolicyEE735B04": { "Type": "Custom::OpenSearchAccessPolicy", "Properties": { "ServiceToken": { @@ -160,8 +157,7 @@ "InstallLatestAwsSdk": true }, "DependsOn": [ - "DomainAccessPolicyCustomResourcePolicy107E31EB", - "Domain66AC69E0" + "DomainAccessPolicyCustomResourcePolicyE61F1845" ], "UpdateReplacePolicy": "Delete", "DeletionPolicy": "Delete" diff --git a/packages/@aws-cdk/aws-opensearchservice/test/integ.opensearch.expected.json b/packages/@aws-cdk/aws-opensearchservice/test/integ.opensearch.expected.json index da98a9b24ab35..4bc5879ad543f 100644 --- a/packages/@aws-cdk/aws-opensearchservice/test/integ.opensearch.expected.json +++ b/packages/@aws-cdk/aws-opensearchservice/test/integ.opensearch.expected.json @@ -165,7 +165,7 @@ "UpdateReplacePolicy": "Delete", "DeletionPolicy": "Delete" }, - "Domain1AccessPolicyCustomResourcePolicy3BDE9B82": { + "Domain1AccessPolicyCustomResourcePolicy3BA04487": { "Type": "AWS::IAM::Policy", "Properties": { "PolicyDocument": { @@ -183,18 +183,15 @@ ], "Version": "2012-10-17" }, - "PolicyName": "Domain1AccessPolicyCustomResourcePolicy3BDE9B82", + "PolicyName": "Domain1AccessPolicyCustomResourcePolicy3BA04487", "Roles": [ { "Ref": "AWS679f53fac002430cb0da5b7982bd2287ServiceRoleC1EA0FF2" } ] - }, - "DependsOn": [ - "Domain19FCBCB91" - ] + } }, - "Domain1AccessPolicy4A36C656": { + "Domain1AccessPolicy1FDDB3CF": { "Type": "Custom::OpenSearchAccessPolicy", "Properties": { "ServiceToken": { @@ -254,8 +251,7 @@ "InstallLatestAwsSdk": true }, "DependsOn": [ - "Domain1AccessPolicyCustomResourcePolicy3BDE9B82", - "Domain19FCBCB91" + "Domain1AccessPolicyCustomResourcePolicy3BA04487" ], "UpdateReplacePolicy": "Delete", "DeletionPolicy": "Delete" @@ -511,7 +507,7 @@ "UpdateReplacePolicy": "Delete", "DeletionPolicy": "Delete" }, - "Domain2AccessPolicyCustomResourcePolicy1FB37294": { + "Domain2AccessPolicyCustomResourcePolicy7C8260FD": { "Type": "AWS::IAM::Policy", "Properties": { "PolicyDocument": { @@ -529,18 +525,15 @@ ], "Version": "2012-10-17" }, - "PolicyName": "Domain2AccessPolicyCustomResourcePolicy1FB37294", + "PolicyName": "Domain2AccessPolicyCustomResourcePolicy7C8260FD", "Roles": [ { "Ref": "AWS679f53fac002430cb0da5b7982bd2287ServiceRoleC1EA0FF2" } ] - }, - "DependsOn": [ - "Domain2644FE48C" - ] + } }, - "Domain2AccessPolicy8AB4B908": { + "Domain2AccessPolicyB81CB6CE": { "Type": "Custom::OpenSearchAccessPolicy", "Properties": { "ServiceToken": { @@ -600,8 +593,7 @@ "InstallLatestAwsSdk": true }, "DependsOn": [ - "Domain2AccessPolicyCustomResourcePolicy1FB37294", - "Domain2644FE48C" + "Domain2AccessPolicyCustomResourcePolicy7C8260FD" ], "UpdateReplacePolicy": "Delete", "DeletionPolicy": "Delete" diff --git a/packages/@aws-cdk/aws-opensearchservice/test/integ.opensearch.unsignedbasicauth.expected.json b/packages/@aws-cdk/aws-opensearchservice/test/integ.opensearch.unsignedbasicauth.expected.json index b1a9048f14dc1..3e5f7e92c5ced 100644 --- a/packages/@aws-cdk/aws-opensearchservice/test/integ.opensearch.unsignedbasicauth.expected.json +++ b/packages/@aws-cdk/aws-opensearchservice/test/integ.opensearch.unsignedbasicauth.expected.json @@ -64,7 +64,7 @@ "UpdateReplacePolicy": "Delete", "DeletionPolicy": "Delete" }, - "DomainAccessPolicyCustomResourcePolicy107E31EB": { + "DomainAccessPolicyCustomResourcePolicyE61F1845": { "Type": "AWS::IAM::Policy", "Properties": { "PolicyDocument": { @@ -82,18 +82,15 @@ ], "Version": "2012-10-17" }, - "PolicyName": "DomainAccessPolicyCustomResourcePolicy107E31EB", + "PolicyName": "DomainAccessPolicyCustomResourcePolicyE61F1845", "Roles": [ { "Ref": "AWS679f53fac002430cb0da5b7982bd2287ServiceRoleC1EA0FF2" } ] - }, - "DependsOn": [ - "Domain66AC69E0" - ] + } }, - "DomainAccessPolicyFCD6BE37": { + "DomainAccessPolicyEE735B04": { "Type": "Custom::OpenSearchAccessPolicy", "Properties": { "ServiceToken": { @@ -151,8 +148,7 @@ "InstallLatestAwsSdk": true }, "DependsOn": [ - "DomainAccessPolicyCustomResourcePolicy107E31EB", - "Domain66AC69E0" + "DomainAccessPolicyCustomResourcePolicyE61F1845" ], "UpdateReplacePolicy": "Delete", "DeletionPolicy": "Delete" diff --git a/packages/@aws-cdk/aws-opensearchservice/test/opensearch-access-policy.test.ts b/packages/@aws-cdk/aws-opensearchservice/test/opensearch-access-policy.test.ts index 6e449d3521adb..429cdca5a89cb 100644 --- a/packages/@aws-cdk/aws-opensearchservice/test/opensearch-access-policy.test.ts +++ b/packages/@aws-cdk/aws-opensearchservice/test/opensearch-access-policy.test.ts @@ -16,7 +16,7 @@ beforeEach(() => { test('minimal example renders correctly', () => { const domainArn = 'test:arn'; - new OpenSearchAccessPolicy(stack, 'ElasticsearchAccessPolicy', { + new OpenSearchAccessPolicy(stack, 'OpenSearchAccessPolicy', { domainName: 'TestDomain', domainArn: domainArn, accessPolicies: [new iam.PolicyStatement({ @@ -66,3 +66,55 @@ test('minimal example renders correctly', () => { }, }); }); + +test('support access policy added inline and later', () => { + const opensearchAccessPolicy = new OpenSearchAccessPolicy(stack, 'OpenSearchAccessPolicy', { + domainName: 'TestDomain', + domainArn: 'test:arn', + accessPolicies: [ + new iam.PolicyStatement({ + effect: iam.Effect.ALLOW, + actions: ['es:ESHttp*'], + principals: [new iam.AnyPrincipal()], + resources: ['test:arn'], + }), + ], + }); + opensearchAccessPolicy.addAccessPolicies( + new iam.PolicyStatement({ + effect: iam.Effect.ALLOW, + actions: ['*'], + principals: [new iam.AnyPrincipal()], + resources: ['test:arn'], + }), + ); + + Template.fromStack(stack).hasResourceProperties('Custom::OpenSearchAccessPolicy', { + ServiceToken: { + 'Fn::GetAtt': [ + 'AWS679f53fac002430cb0da5b7982bd22872D164C4C', + 'Arn', + ], + }, + Create: JSON.stringify({ + action: 'updateDomainConfig', + service: 'OpenSearch', + parameters: { + DomainName: 'TestDomain', + AccessPolicies: '{"Statement":[{"Action":"es:ESHttp*","Effect":"Allow","Principal":{"AWS":"*"},"Resource":"test:arn"},{"Action":"*","Effect":"Allow","Principal":{"AWS":"*"},"Resource":"test:arn"}],"Version":"2012-10-17"}', + }, + outputPaths: ['DomainConfig.AccessPolicies'], + physicalResourceId: { id: 'TestDomainAccessPolicy' }, + }), + Update: JSON.stringify({ + action: 'updateDomainConfig', + service: 'OpenSearch', + parameters: { + DomainName: 'TestDomain', + AccessPolicies: '{"Statement":[{"Action":"es:ESHttp*","Effect":"Allow","Principal":{"AWS":"*"},"Resource":"test:arn"},{"Action":"*","Effect":"Allow","Principal":{"AWS":"*"},"Resource":"test:arn"}],"Version":"2012-10-17"}', + }, + outputPaths: ['DomainConfig.AccessPolicies'], + physicalResourceId: { id: 'TestDomainAccessPolicy' }, + }), + }); +}); diff --git a/packages/@aws-cdk/aws-rds/README.md b/packages/@aws-cdk/aws-rds/README.md index 78d58f64041ec..2cd840e202504 100644 --- a/packages/@aws-cdk/aws-rds/README.md +++ b/packages/@aws-cdk/aws-rds/README.md @@ -326,6 +326,8 @@ You can also authenticate to a database instance using AWS Identity and Access M See for more information and a list of supported versions and limitations. +**Note**: `grantConnect()` does not currently work - see [this GitHub issue](https://github.com/aws/aws-cdk/issues/11851). + The following example shows enabling IAM authentication for a database instance and granting connection access to an IAM role. ```ts diff --git a/packages/@aws-cdk/aws-rds/lib/cluster.ts b/packages/@aws-cdk/aws-rds/lib/cluster.ts index 72d922d618a36..5ac2ce91e652a 100644 --- a/packages/@aws-cdk/aws-rds/lib/cluster.ts +++ b/packages/@aws-cdk/aws-rds/lib/cluster.ts @@ -11,7 +11,7 @@ import { IClusterEngine } from './cluster-engine'; import { DatabaseClusterAttributes, IDatabaseCluster } from './cluster-ref'; import { Endpoint } from './endpoint'; import { IParameterGroup, ParameterGroup } from './parameter-group'; -import { DEFAULT_PASSWORD_EXCLUDE_CHARS, defaultDeletionProtection, renderCredentials, setupS3ImportExport, helperRemovalPolicy, renderUnless } from './private/util'; +import { applyDefaultRotationOptions, defaultDeletionProtection, renderCredentials, setupS3ImportExport, helperRemovalPolicy, renderUnless } from './private/util'; import { BackupProps, Credentials, InstanceProps, PerformanceInsightRetention, RotationSingleUserOptions, RotationMultiUserOptions } from './props'; import { DatabaseProxy, DatabaseProxyOptions, ProxyTarget } from './proxy'; import { CfnDBCluster, CfnDBClusterProps, CfnDBInstance } from './rds.generated'; @@ -250,6 +250,21 @@ interface DatabaseClusterBaseProps { * @default false */ readonly iamAuthentication?: boolean; + + /** + * Whether to enable storage encryption. + * + * @default - true if storageEncryptionKey is provided, false otherwise + */ + readonly storageEncrypted?: boolean + + /** + * The KMS key for storage encryption. + * If specified, {@link storageEncrypted} will be set to `true`. + * + * @default - if storageEncrypted is true then the default master key, no key otherwise + */ + readonly storageEncryptionKey?: kms.IKey; } /** @@ -402,6 +417,9 @@ abstract class DatabaseClusterNew extends DatabaseClusterBase { preferredMaintenanceWindow: props.preferredMaintenanceWindow, databaseName: props.defaultDatabaseName, enableCloudwatchLogsExports: props.cloudwatchLogsExports, + // Encryption + kmsKeyId: props.storageEncryptionKey?.keyArn, + storageEncrypted: props.storageEncryptionKey ? true : props.storageEncrypted, }; } } @@ -479,21 +497,6 @@ export interface DatabaseClusterProps extends DatabaseClusterBaseProps { */ readonly credentials?: Credentials; - /** - * Whether to enable storage encryption. - * - * @default - true if storageEncryptionKey is provided, false otherwise - */ - readonly storageEncrypted?: boolean - - /** - * The KMS key for storage encryption. - * If specified, {@link storageEncrypted} will be set to `true`. - * - * @default - if storageEncrypted is true then the default master key, no key otherwise - */ - readonly storageEncryptionKey?: kms.IKey; - /** * Whether to copy tags to the snapshot when a snapshot is created. * @@ -550,9 +553,7 @@ export class DatabaseCluster extends DatabaseClusterNew { // Admin masterUsername: credentials.username, masterUserPassword: credentials.password?.toString(), - // Encryption - kmsKeyId: props.storageEncryptionKey?.keyArn, - storageEncrypted: props.storageEncryptionKey ? true : props.storageEncrypted, + // Tags copyTagsToSnapshot: props.copyTagsToSnapshot ?? true, }); @@ -594,13 +595,11 @@ export class DatabaseCluster extends DatabaseClusterNew { } return new secretsmanager.SecretRotation(this, id, { + ...applyDefaultRotationOptions(options, this.vpcSubnets), secret: this.secret, application: this.singleUserRotationApplication, vpc: this.vpc, - vpcSubnets: this.vpcSubnets, target: this, - ...options, - excludeCharacters: options.excludeCharacters ?? DEFAULT_PASSWORD_EXCLUDE_CHARS, }); } @@ -611,13 +610,13 @@ export class DatabaseCluster extends DatabaseClusterNew { if (!this.secret) { throw new Error('Cannot add multi user rotation for a cluster without secret.'); } + return new secretsmanager.SecretRotation(this, id, { - ...options, - excludeCharacters: options.excludeCharacters ?? DEFAULT_PASSWORD_EXCLUDE_CHARS, + ...applyDefaultRotationOptions(options, this.vpcSubnets), + secret: options.secret, masterSecret: this.secret, application: this.multiUserRotationApplication, vpc: this.vpc, - vpcSubnets: this.vpcSubnets, target: this, }); } diff --git a/packages/@aws-cdk/aws-rds/lib/instance.ts b/packages/@aws-cdk/aws-rds/lib/instance.ts index 6236fe0fbc156..fd4d10ae7afbd 100644 --- a/packages/@aws-cdk/aws-rds/lib/instance.ts +++ b/packages/@aws-cdk/aws-rds/lib/instance.ts @@ -13,7 +13,7 @@ import { Endpoint } from './endpoint'; import { IInstanceEngine } from './instance-engine'; import { IOptionGroup } from './option-group'; import { IParameterGroup, ParameterGroup } from './parameter-group'; -import { DEFAULT_PASSWORD_EXCLUDE_CHARS, defaultDeletionProtection, engineDescription, renderCredentials, setupS3ImportExport, helperRemovalPolicy, renderUnless } from './private/util'; +import { applyDefaultRotationOptions, defaultDeletionProtection, engineDescription, renderCredentials, setupS3ImportExport, helperRemovalPolicy, renderUnless } from './private/util'; import { Credentials, PerformanceInsightRetention, RotationMultiUserOptions, RotationSingleUserOptions, SnapshotCredentials } from './props'; import { DatabaseProxy, DatabaseProxyOptions, ProxyTarget } from './proxy'; import { CfnDBInstance, CfnDBInstanceProps } from './rds.generated'; @@ -66,6 +66,8 @@ export interface IDatabaseInstance extends IResource, ec2.IConnectable, secretsm /** * Grant the given identity connection access to the database. + * **Note**: this method does not currently work, see https://github.com/aws/aws-cdk/issues/11851 for details. + * @see https://github.com/aws/aws-cdk/issues/11851 */ grantConnect(grantee: iam.IGrantable): iam.Grant; @@ -931,13 +933,11 @@ abstract class DatabaseInstanceSource extends DatabaseInstanceNew implements IDa } return new secretsmanager.SecretRotation(this, id, { + ...applyDefaultRotationOptions(options, this.vpcPlacement), secret: this.secret, application: this.singleUserRotationApplication, vpc: this.vpc, - vpcSubnets: this.vpcPlacement, target: this, - ...options, - excludeCharacters: options.excludeCharacters ?? DEFAULT_PASSWORD_EXCLUDE_CHARS, }); } @@ -948,13 +948,13 @@ abstract class DatabaseInstanceSource extends DatabaseInstanceNew implements IDa if (!this.secret) { throw new Error('Cannot add multi user rotation for an instance without secret.'); } + return new secretsmanager.SecretRotation(this, id, { - ...options, - excludeCharacters: options.excludeCharacters ?? DEFAULT_PASSWORD_EXCLUDE_CHARS, + ...applyDefaultRotationOptions(options, this.vpcPlacement), + secret: options.secret, masterSecret: this.secret, application: this.multiUserRotationApplication, vpc: this.vpc, - vpcSubnets: this.vpcPlacement, target: this, }); } @@ -1171,12 +1171,18 @@ export class DatabaseInstanceReadReplica extends DatabaseInstanceNew implements throw new Error(`Cannot set 'backupRetention', as engine '${engineDescription(props.sourceDatabaseInstance.engine)}' does not support automatic backups for read replicas`); } + // The read replica instance always uses the same engine as the source instance + // but some CF validations require the engine to be explicitely passed when some + // properties are specified. + const shouldPassEngine = props.domain != null; + const instance = new CfnDBInstance(this, 'Resource', { ...this.newCfnProps, // this must be ARN, not ID, because of https://github.com/terraform-providers/terraform-provider-aws/issues/528#issuecomment-391169012 sourceDbInstanceIdentifier: props.sourceDatabaseInstance.instanceArn, kmsKeyId: props.storageEncryptionKey?.keyArn, storageEncrypted: props.storageEncryptionKey ? true : props.storageEncrypted, + engine: shouldPassEngine ? props.sourceDatabaseInstance.engine?.engineType : undefined, }); this.instanceType = props.instanceType; diff --git a/packages/@aws-cdk/aws-rds/lib/private/util.ts b/packages/@aws-cdk/aws-rds/lib/private/util.ts index 5e9c1e42e44d4..9bace496400cd 100644 --- a/packages/@aws-cdk/aws-rds/lib/private/util.ts +++ b/packages/@aws-cdk/aws-rds/lib/private/util.ts @@ -1,9 +1,10 @@ +import * as ec2 from '@aws-cdk/aws-ec2'; import * as iam from '@aws-cdk/aws-iam'; import * as s3 from '@aws-cdk/aws-s3'; import { RemovalPolicy } from '@aws-cdk/core'; import { DatabaseSecret } from '../database-secret'; import { IEngine } from '../engine'; -import { Credentials } from '../props'; +import { CommonRotationUserOptions, Credentials } from '../props'; // keep this import separate from other imports to reduce chance for merge conflicts with v2-main // eslint-disable-next-line no-duplicate-imports, import/order @@ -134,3 +135,14 @@ export function helperRemovalPolicy(basePolicy?: RemovalPolicy): RemovalPolicy { export function renderUnless(value: A, suppressValue: A): A | undefined { return value === suppressValue ? undefined : value; } + +/** + * Applies defaults for rotation options + */ +export function applyDefaultRotationOptions(options: CommonRotationUserOptions, defaultvpcSubnets?: ec2.SubnetSelection): CommonRotationUserOptions { + return { + excludeCharacters: DEFAULT_PASSWORD_EXCLUDE_CHARS, + vpcSubnets: defaultvpcSubnets, + ...options, + }; +} diff --git a/packages/@aws-cdk/aws-rds/lib/props.ts b/packages/@aws-cdk/aws-rds/lib/props.ts index 663719431d640..6338fa0368849 100644 --- a/packages/@aws-cdk/aws-rds/lib/props.ts +++ b/packages/@aws-cdk/aws-rds/lib/props.ts @@ -456,7 +456,7 @@ export abstract class SnapshotCredentials { /** * Properties common to single-user and multi-user rotation options. */ -interface CommonRotationUserOptions { +export interface CommonRotationUserOptions { /** * Specifies the number of days after the previous rotation * before Secrets Manager triggers the next automatic rotation. diff --git a/packages/@aws-cdk/aws-rds/lib/serverless-cluster.ts b/packages/@aws-cdk/aws-rds/lib/serverless-cluster.ts index 955b92ac58e5f..4e8aa6d46597d 100644 --- a/packages/@aws-cdk/aws-rds/lib/serverless-cluster.ts +++ b/packages/@aws-cdk/aws-rds/lib/serverless-cluster.ts @@ -10,7 +10,7 @@ import { DatabaseSecret } from './database-secret'; import { Endpoint } from './endpoint'; import { IParameterGroup } from './parameter-group'; import { DATA_API_ACTIONS } from './perms'; -import { defaultDeletionProtection, DEFAULT_PASSWORD_EXCLUDE_CHARS, renderCredentials } from './private/util'; +import { applyDefaultRotationOptions, defaultDeletionProtection, renderCredentials } from './private/util'; import { Credentials, RotationMultiUserOptions, RotationSingleUserOptions, SnapshotCredentials } from './props'; import { CfnDBCluster, CfnDBClusterProps } from './rds.generated'; import { ISubnetGroup, SubnetGroup } from './subnet-group'; @@ -558,13 +558,11 @@ export class ServerlessCluster extends ServerlessClusterNew { } return new secretsmanager.SecretRotation(this, id, { + ...applyDefaultRotationOptions(options, this.vpcSubnets), secret: this.secret, application: this.singleUserRotationApplication, vpc: this.vpc, - vpcSubnets: this.vpcSubnets, target: this, - ...options, - excludeCharacters: options.excludeCharacters ?? DEFAULT_PASSWORD_EXCLUDE_CHARS, }); } @@ -581,12 +579,11 @@ export class ServerlessCluster extends ServerlessClusterNew { } return new secretsmanager.SecretRotation(this, id, { - ...options, - excludeCharacters: options.excludeCharacters ?? DEFAULT_PASSWORD_EXCLUDE_CHARS, + ...applyDefaultRotationOptions(options, this.vpcSubnets), + secret: options.secret, masterSecret: this.secret, application: this.multiUserRotationApplication, vpc: this.vpc, - vpcSubnets: this.vpcSubnets, target: this, }); } diff --git a/packages/@aws-cdk/aws-rds/test/cluster.test.ts b/packages/@aws-cdk/aws-rds/test/cluster.test.ts index bf597d08540e2..a7c749e04a399 100644 --- a/packages/@aws-cdk/aws-rds/test/cluster.test.ts +++ b/packages/@aws-cdk/aws-rds/test/cluster.test.ts @@ -889,15 +889,18 @@ describe('cluster', () => { }); }); - test('addRotationSingleUser() with options', () => { + test('addRotationSingleUser() with custom automaticallyAfter, excludeCharacters and vpcSubnets', () => { // GIVEN const stack = new cdk.Stack(); - const vpcWithIsolated = new ec2.Vpc(stack, 'Vpc', { - subnetConfiguration: [ - { name: 'public', subnetType: ec2.SubnetType.PUBLIC }, - { name: 'private', subnetType: ec2.SubnetType.PRIVATE_WITH_NAT }, - { name: 'isolated', subnetType: ec2.SubnetType.PRIVATE_ISOLATED }, - ], + const vpcWithIsolated = ec2.Vpc.fromVpcAttributes(stack, 'Vpc', { + vpcId: 'vpc-id', + availabilityZones: ['az1'], + publicSubnetIds: ['public-subnet-id-1', 'public-subnet-id-2'], + publicSubnetNames: ['public-subnet-name-1', 'public-subnet-name-2'], + privateSubnetIds: ['private-subnet-id-1', 'private-subnet-id-2'], + privateSubnetNames: ['private-subnet-name-1', 'private-subnet-name-2'], + isolatedSubnetIds: ['isolated-subnet-id-1', 'isolated-subnet-id-2'], + isolatedSubnetNames: ['isolated-subnet-name-1', 'isolated-subnet-name-2'], }); // WHEN @@ -935,20 +938,64 @@ describe('cluster', () => { { Ref: 'AWS::URLSuffix' }, ]], }, - functionName: 'DatabaseRotationSingleUser458A45BE', - vpcSubnetIds: { + vpcSubnetIds: 'private-subnet-id-1,private-subnet-id-2', + excludeCharacters: '°_@', + }, + }); + }); + + test('addRotationMultiUser() with custom automaticallyAfter, excludeCharacters and vpcSubnets', () => { + // GIVEN + const stack = new cdk.Stack(); + const vpcWithIsolated = ec2.Vpc.fromVpcAttributes(stack, 'Vpc', { + vpcId: 'vpc-id', + availabilityZones: ['az1'], + publicSubnetIds: ['public-subnet-id-1', 'public-subnet-id-2'], + publicSubnetNames: ['public-subnet-name-1', 'public-subnet-name-2'], + privateSubnetIds: ['private-subnet-id-1', 'private-subnet-id-2'], + privateSubnetNames: ['private-subnet-name-1', 'private-subnet-name-2'], + isolatedSubnetIds: ['isolated-subnet-id-1', 'isolated-subnet-id-2'], + isolatedSubnetNames: ['isolated-subnet-name-1', 'isolated-subnet-name-2'], + }); + const userSecret = new DatabaseSecret(stack, 'UserSecret', { username: 'user' }); + + // WHEN + // DB in isolated subnet (no internet connectivity) + const cluster = new DatabaseCluster(stack, 'Database', { + engine: DatabaseClusterEngine.AURORA_MYSQL, + instanceProps: { + instanceType: ec2.InstanceType.of(ec2.InstanceClass.BURSTABLE2, ec2.InstanceSize.SMALL), + vpc: vpcWithIsolated, + vpcSubnets: { subnetType: ec2.SubnetType.PRIVATE_ISOLATED }, + }, + }); + + // Rotation in private subnet (internet via NAT) + cluster.addRotationMultiUser('user', { + secret: userSecret.attach(cluster), + automaticallyAfter: cdk.Duration.days(15), + excludeCharacters: '°_@', + vpcSubnets: { subnetType: ec2.SubnetType.PRIVATE_WITH_NAT }, + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::SecretsManager::RotationSchedule', { + RotationRules: { + AutomaticallyAfterDays: 15, + }, + }); + + Template.fromStack(stack).hasResourceProperties('AWS::Serverless::Application', { + Parameters: { + endpoint: { 'Fn::Join': ['', [ - { Ref: 'VpcprivateSubnet1SubnetCEAD3716' }, - ',', - { Ref: 'VpcprivateSubnet2Subnet2DE7549C' }, + 'https://secretsmanager.', + { Ref: 'AWS::Region' }, + '.', + { Ref: 'AWS::URLSuffix' }, ]], }, - vpcSecurityGroupIds: { - 'Fn::GetAtt': [ - 'DatabaseRotationSingleUserSecurityGroupAC6E0E73', - 'GroupId', - ], - }, + vpcSubnetIds: 'private-subnet-id-1,private-subnet-id-2', excludeCharacters: '°_@', }, }); @@ -1974,6 +2021,27 @@ describe('cluster', () => { }); }); + test('create a cluster from a snapshot with encrypted storage', () => { + const stack = testStack(); + const vpc = new ec2.Vpc(stack, 'VPC'); + + // WHEN + new DatabaseClusterFromSnapshot(stack, 'Database', { + engine: DatabaseClusterEngine.aurora({ version: AuroraEngineVersion.VER_1_22_2 }), + instanceProps: { + vpc, + }, + snapshotIdentifier: 'mySnapshot', + storageEncryptionKey: kms.Key.fromKeyArn(stack, 'Key', 'arn:aws:kms:us-east-1:456:key/my-key'), + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::RDS::DBCluster', { + KmsKeyId: 'arn:aws:kms:us-east-1:456:key/my-key', + StorageEncrypted: true, + }); + }); + test('reuse an existing subnet group', () => { // GIVEN const stack = testStack(); diff --git a/packages/@aws-cdk/aws-rds/test/instance.test.ts b/packages/@aws-cdk/aws-rds/test/instance.test.ts index 6ba08c6d9f2fb..d8ec0d85fa6d1 100644 --- a/packages/@aws-cdk/aws-rds/test/instance.test.ts +++ b/packages/@aws-cdk/aws-rds/test/instance.test.ts @@ -797,14 +797,17 @@ describe('instance', () => { }); }); - test('addRotationSingleUser() with options', () => { + test('addRotationSingleUser() with custom automaticallyAfter, excludeCharacters and vpcSubnets', () => { // GIVEN - const vpcWithIsolated = new ec2.Vpc(stack, 'Vpc', { - subnetConfiguration: [ - { name: 'public', subnetType: ec2.SubnetType.PUBLIC }, - { name: 'private', subnetType: ec2.SubnetType.PRIVATE_WITH_NAT }, - { name: 'isolated', subnetType: ec2.SubnetType.PRIVATE_ISOLATED }, - ], + const vpcWithIsolated = ec2.Vpc.fromVpcAttributes(stack, 'Vpc', { + vpcId: 'vpc-id', + availabilityZones: ['az1'], + publicSubnetIds: ['public-subnet-id-1', 'public-subnet-id-2'], + publicSubnetNames: ['public-subnet-name-1', 'public-subnet-name-2'], + privateSubnetIds: ['private-subnet-id-1', 'private-subnet-id-2'], + privateSubnetNames: ['private-subnet-name-1', 'private-subnet-name-2'], + isolatedSubnetIds: ['isolated-subnet-id-1', 'isolated-subnet-id-2'], + isolatedSubnetNames: ['isolated-subnet-name-1', 'isolated-subnet-name-2'], }); // WHEN @@ -839,26 +842,65 @@ describe('instance', () => { { Ref: 'AWS::URLSuffix' }, ]], }, - functionName: 'DatabaseRotationSingleUser458A45BE', - vpcSubnetIds: { + vpcSubnetIds: 'private-subnet-id-1,private-subnet-id-2', + excludeCharacters: '°_@', + }, + }); + }); + + test('addRotationMultiUser() with custom automaticallyAfter, excludeCharacters and vpcSubnets', () => { + // GIVEN + const vpcWithIsolated = ec2.Vpc.fromVpcAttributes(stack, 'Vpc', { + vpcId: 'vpc-id', + availabilityZones: ['az1'], + publicSubnetIds: ['public-subnet-id-1', 'public-subnet-id-2'], + publicSubnetNames: ['public-subnet-name-1', 'public-subnet-name-2'], + privateSubnetIds: ['private-subnet-id-1', 'private-subnet-id-2'], + privateSubnetNames: ['private-subnet-name-1', 'private-subnet-name-2'], + isolatedSubnetIds: ['isolated-subnet-id-1', 'isolated-subnet-id-2'], + isolatedSubnetNames: ['isolated-subnet-name-1', 'isolated-subnet-name-2'], + }); + const userSecret = new rds.DatabaseSecret(stack, 'UserSecret', { username: 'user' }); + + // WHEN + // DB in isolated subnet (no internet connectivity) + const instance = new rds.DatabaseInstance(stack, 'Database', { + engine: rds.DatabaseInstanceEngine.postgres({ version: rds.PostgresEngineVersion.VER_10 }), + vpc: vpcWithIsolated, + vpcSubnets: { subnetType: ec2.SubnetType.PRIVATE_ISOLATED }, + }); + + // Rotation in private subnet (internet via NAT) + instance.addRotationMultiUser('user', { + secret: userSecret.attach(instance), + automaticallyAfter: cdk.Duration.days(15), + excludeCharacters: '°_@', + vpcSubnets: { subnetType: ec2.SubnetType.PRIVATE_WITH_NAT }, + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::SecretsManager::RotationSchedule', { + RotationRules: { + AutomaticallyAfterDays: 15, + }, + }); + + Template.fromStack(stack).hasResourceProperties('AWS::Serverless::Application', { + Parameters: { + endpoint: { 'Fn::Join': ['', [ - { Ref: 'VpcprivateSubnet1SubnetCEAD3716' }, - ',', - { Ref: 'VpcprivateSubnet2Subnet2DE7549C' }, + 'https://secretsmanager.', + { Ref: 'AWS::Region' }, + '.', + { Ref: 'AWS::URLSuffix' }, ]], }, - vpcSecurityGroupIds: { - 'Fn::GetAtt': [ - 'DatabaseRotationSingleUserSecurityGroupAC6E0E73', - 'GroupId', - ], - }, + vpcSubnetIds: 'private-subnet-id-1,private-subnet-id-2', excludeCharacters: '°_@', }, }); }); - test('addRotationSingleUser() with VPC interface endpoint', () => { // GIVEN const vpcIsolatedOnly = new ec2.Vpc(stack, 'Vpc', { natGateways: 0 }); @@ -1617,6 +1659,31 @@ describe('instance', () => { }, }); }); + + test('engine is specified for read replica using domain', () => { + // GIVEN + const instanceType = ec2.InstanceType.of(ec2.InstanceClass.T3, ec2.InstanceSize.SMALL); + const engine = rds.DatabaseInstanceEngine.postgres({ version: rds.PostgresEngineVersion.VER_13 }); + const source = new rds.DatabaseInstance(stack, 'Source', { + engine, + instanceType, + vpc, + }); + + // WHEN + new rds.DatabaseInstanceReadReplica(stack, 'Replica', { + sourceDatabaseInstance: source, + instanceType, + vpc, + domain: 'my-domain', + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::RDS::DBInstance', { + SourceDBInstanceIdentifier: Match.anyValue(), + Engine: 'postgres', + }); + }); }); test.each([ diff --git a/packages/@aws-cdk/aws-route53-targets/lib/elastic-beanstalk-environment-target.ts b/packages/@aws-cdk/aws-route53-targets/lib/elastic-beanstalk-environment-target.ts index ef48c2845c233..255114b773854 100644 --- a/packages/@aws-cdk/aws-route53-targets/lib/elastic-beanstalk-environment-target.ts +++ b/packages/@aws-cdk/aws-route53-targets/lib/elastic-beanstalk-environment-target.ts @@ -5,6 +5,7 @@ import { RegionInfo } from '@aws-cdk/region-info'; /** * Use an Elastic Beanstalk environment URL as an alias record target. * E.g. mysampleenvironment.xyz.us-east-1.elasticbeanstalk.com + * or mycustomcnameprefix.us-east-1.elasticbeanstalk.com * * Only supports Elastic Beanstalk environments created after 2016 that have a regional endpoint. */ @@ -18,7 +19,9 @@ export class ElasticBeanstalkEnvironmentEndpointTarget implements route53.IAlias } const dnsName = this.environmentEndpoint; - const region = cdk.Fn.select(2, cdk.Fn.split('.', dnsName)); + const subDomains = cdk.Fn.split('.', dnsName); + const regionSubdomainIndex = subDomains.length - 3; + const region = cdk.Fn.select(regionSubdomainIndex, subDomains); const { ebsEnvEndpointHostedZoneId: hostedZoneId } = RegionInfo.get(region); if (!hostedZoneId || !dnsName) { diff --git a/packages/@aws-cdk/aws-route53-targets/test/elastic-beanstalk-environment-target.test.ts b/packages/@aws-cdk/aws-route53-targets/test/elastic-beanstalk-environment-target.test.ts index 44cadae6e3b9f..a60fd9be58d5b 100644 --- a/packages/@aws-cdk/aws-route53-targets/test/elastic-beanstalk-environment-target.test.ts +++ b/packages/@aws-cdk/aws-route53-targets/test/elastic-beanstalk-environment-target.test.ts @@ -23,3 +23,25 @@ test('use EBS environment as record target', () => { }, }); }); + + +test('support 4-levels subdomain URLs for EBS environments', () => { + // GIVEN + const stack = new Stack(); + const zone = new route53.PublicHostedZone(stack, 'HostedZone', { zoneName: 'test.public' }); + + // WHEN + new route53.ARecord(stack, 'Alias', { + zone, + recordName: '_foo', + target: route53.RecordTarget.fromAlias(new targets.ElasticBeanstalkEnvironmentEndpointTarget('mycustomcnameprefix.us-east-1.elasticbeanstalk.com')), + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::Route53::RecordSet', { + AliasTarget: { + DNSName: 'mycustomcnameprefix.us-east-1.elasticbeanstalk.com', + HostedZoneId: 'Z117KPS5GTRQ2G', + }, + }); +}); diff --git a/packages/@aws-cdk/aws-s3/lib/bucket.ts b/packages/@aws-cdk/aws-s3/lib/bucket.ts index 31537274d13d4..f21fb65db79f5 100644 --- a/packages/@aws-cdk/aws-s3/lib/bucket.ts +++ b/packages/@aws-cdk/aws-s3/lib/bucket.ts @@ -2293,6 +2293,16 @@ export enum EventType { */ OBJECT_RESTORE_COMPLETED = 's3:ObjectRestore:Completed', + /** + * Using restore object event types you can receive notifications for + * initiation and completion when restoring objects from the S3 Glacier + * storage class. + * + * You use s3:ObjectRestore:Delete to request notification of + * restoration completion. + */ + OBJECT_RESTORE_DELETE = 's3:ObjectRestore:Delete', + /** * You can use this event type to request Amazon S3 to send a notification * message when Amazon S3 detects that an object of the RRS storage class is diff --git a/packages/@aws-cdk/aws-s3objectlambda/README.md b/packages/@aws-cdk/aws-s3objectlambda/README.md index 60a5c42835925..35deed15685a9 100644 --- a/packages/@aws-cdk/aws-s3objectlambda/README.md +++ b/packages/@aws-cdk/aws-s3objectlambda/README.md @@ -9,23 +9,92 @@ > > [CFN Resources]: https://docs.aws.amazon.com/cdk/latest/guide/constructs.html#constructs_lib +![cdk-constructs: Experimental](https://img.shields.io/badge/cdk--constructs-experimental-important.svg?style=for-the-badge) + +> The APIs of higher level constructs in this module are experimental and under active development. +> They are subject to non-backward compatible changes or removal in any future version. These are +> not subject to the [Semantic Versioning](https://semver.org/) model and breaking changes will be +> announced in the release notes. This means that while you may use them, you may need to update +> your source code when upgrading to a newer version of this package. + --- -This module is part of the [AWS Cloud Development Kit](https://github.com/aws/aws-cdk) project. +This construct library allows you to define S3 object lambda access points. -```ts nofixture +```ts +import * as lambda from '@aws-cdk/aws-lambda'; +import * as s3 from '@aws-cdk/aws-s3'; import * as s3objectlambda from '@aws-cdk/aws-s3objectlambda'; +import * as cdk from '@aws-cdk/core'; + +const stack = new cdk.Stack(); +const bucket = new s3.Bucket(stack, 'MyBucket'); +const handler = new lambda.Function(stack, 'MyFunction', { + runtime: lambda.Runtime.NODEJS_14_X, + handler: 'index.handler', + code: lambda.Code.fromAsset('lambda.zip'), +}); +new s3objectlambda.AccessPoint(stack, 'MyObjectLambda', { + bucket, + handler, + accessPointName: 'my-access-point', + payload: { + prop: "value", + }, +}); ``` - +## Handling range and part number requests + +Lambdas are currently limited to only transforming `GetObject` requests. However, they can additionally support `GetObject-Range` and `GetObject-PartNumber` requests, which needs to be specified in the access point configuration: + +```ts +import * as lambda from '@aws-cdk/aws-lambda'; +import * as s3 from '@aws-cdk/aws-s3'; +import * as s3objectlambda from '@aws-cdk/aws-s3objectlambda'; +import * as cdk from '@aws-cdk/core'; -There are no hand-written ([L2](https://docs.aws.amazon.com/cdk/latest/guide/constructs.html#constructs_lib)) constructs for this service yet. -However, you can still use the automatically generated [L1](https://docs.aws.amazon.com/cdk/latest/guide/constructs.html#constructs_l1_using) constructs, and use this service exactly as you would using CloudFormation directly. +const stack = new cdk.Stack(); +const bucket = new s3.Bucket(stack, 'MyBucket'); +const handler = new lambda.Function(stack, 'MyFunction', { + runtime: lambda.Runtime.NODEJS_14_X, + handler: 'index.handler', + code: lambda.Code.fromAsset('lambda.zip'), +}); +new s3objectlambda.AccessPoint(stack, 'MyObjectLambda', { + bucket, + handler, + accessPointName: 'my-access-point', + supportsGetObjectRange: true, + supportsGetObjectPartNumber: true, +}); +``` -For more information on the resources and properties available for this service, see the [CloudFormation documentation for AWS::S3ObjectLambda](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/AWS_S3ObjectLambda.html). +## Pass additional data to Lambda function -(Read the [CDK Contributing Guide](https://github.com/aws/aws-cdk/blob/master/CONTRIBUTING.md) if you are interested in contributing to this construct library.) +You can specify an additional object that provides supplemental data to the Lambda function used to transform objects. The data is delivered as a JSON payload to the Lambda: - +```ts +import * as lambda from '@aws-cdk/aws-lambda'; +import * as s3 from '@aws-cdk/aws-s3'; +import * as s3objectlambda from '@aws-cdk/aws-s3objectlambda'; +import * as cdk from '@aws-cdk/core'; + +const stack = new cdk.Stack(); +const bucket = new s3.Bucket(stack, 'MyBucket'); +const handler = new lambda.Function(stack, 'MyFunction', { + runtime: lambda.Runtime.NODEJS_14_X, + handler: 'index.handler', + code: lambda.Code.fromAsset('lambda.zip'), +}); +new s3objectlambda.AccessPoint(stack, 'MyObjectLambda', { + bucket, + handler, + accessPointName: 'my-access-point', + payload: { + prop: "value", + }, +}); +``` diff --git a/packages/@aws-cdk/aws-s3objectlambda/lib/access-point.ts b/packages/@aws-cdk/aws-s3objectlambda/lib/access-point.ts new file mode 100644 index 0000000000000..a99fd64669f81 --- /dev/null +++ b/packages/@aws-cdk/aws-s3objectlambda/lib/access-point.ts @@ -0,0 +1,255 @@ +import * as iam from '@aws-cdk/aws-iam'; +import * as lambda from '@aws-cdk/aws-lambda'; +import * as s3 from '@aws-cdk/aws-s3'; +import * as core from '@aws-cdk/core'; +import { Construct } from 'constructs'; +import { CfnAccessPoint } from './s3objectlambda.generated'; + +/** + * The interface that represents the AccessPoint resource. + */ +export interface IAccessPoint extends core.IResource { + /** + * The ARN of the access point. + * @attribute + */ + readonly accessPointArn: string; + + /** + * The creation data of the access point. + * @attribute + */ + readonly accessPointCreationDate: string; + + /** + * The IPv4 DNS name of the access point. + */ + readonly domainName: string; + + /** + * The regional domain name of the access point. + */ + readonly regionalDomainName: string; + + /** + * The virtual hosted-style URL of an S3 object through this access point. + * Specify `regional: false` at the options for non-regional URL. + * @param key The S3 key of the object. If not specified, the URL of the + * bucket is returned. + * @param options Options for generating URL. + * @returns an ObjectS3Url token + */ + virtualHostedUrlForObject(key?: string, options?: s3.VirtualHostedStyleUrlOptions): string; +} + +/** + * The S3 object lambda access point configuration. + */ +export interface AccessPointProps { + /** + * The bucket to which this access point belongs. + */ + readonly bucket: s3.IBucket; + + /** + * The Lambda function used to transform objects. + */ + readonly handler: lambda.IFunction; + + /** + * The name of the S3 object lambda access point. + * + * @default a unique name will be generated + */ + readonly accessPointName?: string; + + /** + * Whether CloudWatch metrics are enabled for the access point. + * + * @default false + */ + readonly cloudWatchMetricsEnabled?: boolean; + + /** + * Whether the Lambda function can process `GetObject-Range` requests. + * + * @default false + */ + readonly supportsGetObjectRange?: boolean; + + /** + * Whether the Lambda function can process `GetObject-PartNumber` requests. + * + * @default false + */ + readonly supportsGetObjectPartNumber?: boolean; + + /** + * Additional JSON that provides supplemental data passed to the + * Lambda function on every request. + * + * @default - No data. + */ + readonly payload?: { [key: string]: any }; +} + +abstract class AccessPointBase extends core.Resource implements IAccessPoint { + public abstract readonly accessPointArn: string; + public abstract readonly accessPointCreationDate: string; + public abstract readonly accessPointName: string; + + /** Implement the {@link IAccessPoint.domainName} field. */ + get domainName(): string { + const urlSuffix = this.stack.urlSuffix; + return `${this.accessPointName}-${this.stack.account}.s3-object-lambda.${urlSuffix}`; + } + + /** Implement the {@link IAccessPoint.regionalDomainName} field. */ + get regionalDomainName(): string { + const urlSuffix = this.stack.urlSuffix; + const region = this.stack.region; + return `${this.accessPointName}-${this.stack.account}.s3-object-lambda.${region}.${urlSuffix}`; + } + + /** Implement the {@link IAccessPoint.virtualHostedUrlForObject} method. */ + public virtualHostedUrlForObject(key?: string, options?: s3.VirtualHostedStyleUrlOptions): string { + const domainName = options?.regional ?? true ? this.regionalDomainName : this.domainName; + const prefix = `https://${domainName}`; + if (!key) { + return prefix; + } + if (key.startsWith('/')) { + key = key.slice(1); + } + if (key.endsWith('/')) { + key = key.slice(0, -1); + } + return `${prefix}/${key}`; + } +} + +/** + * The access point resource attributes. + */ +export interface AccessPointAttributes { + /** + * The ARN of the access point. + */ + readonly accessPointArn: string + + /** + * The creation data of the access point. + */ + readonly accessPointCreationDate: string; +} + +/** + * Checks the access point name against the rules in https://docs.aws.amazon.com/AmazonS3/latest/userguide/creating-access-points.html#access-points-names + * @param name The name of the access point + */ +function validateAccessPointName(name: string): void { + if (name.length < 3 || name.length > 50) { + throw new Error('Access point name must be between 3 and 50 characters long'); + } + if (name.endsWith('-s3alias')) { + throw new Error('Access point name cannot end with the suffix -s3alias'); + } + if (name[0] === '-' || name[name.length - 1] === '-') { + throw new Error('Access point name cannot begin or end with a dash'); + } + if (!/^[0-9a-z](.(?![\.A-Z_]))+[0-9a-z]$/.test(name)) { + throw new Error('Access point name must begin with a number or lowercase letter and not contain underscores, uppercase letters, or periods'); + } +} + +/** + * An S3 object lambda access point for intercepting and + * transforming `GetObject` requests. + */ +export class AccessPoint extends AccessPointBase { + /** + * Reference an existing AccessPoint defined outside of the CDK code. + */ + public static fromAccessPointAttributes(scope: Construct, id: string, attrs: AccessPointAttributes): IAccessPoint { + const arn = core.Arn.split(attrs.accessPointArn, core.ArnFormat.SLASH_RESOURCE_NAME); + if (!arn.resourceName) { + throw new Error('Unable to parse acess point name'); + } + const name = arn.resourceName; + class Import extends AccessPointBase { + public readonly accessPointArn: string = attrs.accessPointArn; + public readonly accessPointCreationDate: string = attrs.accessPointCreationDate; + public readonly accessPointName: string = name; + } + return new Import(scope, id); + } + + /** + * The ARN of the access point. + */ + public readonly accessPointName: string + + /** + * The ARN of the access point. + * @attribute + */ + public readonly accessPointArn: string + + /** + * The creation data of the access point. + * @attribute + */ + public readonly accessPointCreationDate: string + + constructor(scope: Construct, id: string, props: AccessPointProps) { + super(scope, id, { + physicalName: props.accessPointName, + }); + + if (props.accessPointName) { + validateAccessPointName(props.accessPointName); + } + + const supporting = new s3.CfnAccessPoint(this, 'SupportingAccessPoint', { + bucket: props.bucket.bucketName, + }); + + const allowedFeatures = []; + if (props.supportsGetObjectPartNumber) { + allowedFeatures.push('GetObject-PartNumber'); + } + if (props.supportsGetObjectRange) { + allowedFeatures.push('GetObject-Range'); + } + + const accessPoint = new CfnAccessPoint(this, id, { + name: this.physicalName, + objectLambdaConfiguration: { + allowedFeatures, + cloudWatchMetricsEnabled: props.cloudWatchMetricsEnabled, + supportingAccessPoint: supporting.attrArn, + transformationConfigurations: [ + { + actions: ['GetObject'], + contentTransformation: { + AwsLambda: { + FunctionArn: props.handler.functionArn, + FunctionPayload: props.payload ? JSON.stringify(props.payload) : undefined, + }, + }, + }, + ], + }, + }); + this.accessPointName = accessPoint.ref; + this.accessPointArn = accessPoint.attrArn; + this.accessPointCreationDate = accessPoint.attrCreationDate; + + props.handler.addToRolePolicy( + new iam.PolicyStatement({ + actions: ['s3-object-lambda:WriteGetObjectResponse'], + resources: ['*'], + }), + ); + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3objectlambda/lib/index.ts b/packages/@aws-cdk/aws-s3objectlambda/lib/index.ts index 791ddcf126933..e3c96c8d8be85 100644 --- a/packages/@aws-cdk/aws-s3objectlambda/lib/index.ts +++ b/packages/@aws-cdk/aws-s3objectlambda/lib/index.ts @@ -1,2 +1,4 @@ +export * from './access-point'; + // AWS::S3ObjectLambda CloudFormation Resources: export * from './s3objectlambda.generated'; diff --git a/packages/@aws-cdk/aws-s3objectlambda/package.json b/packages/@aws-cdk/aws-s3objectlambda/package.json index 1fc4d83279d41..1f89f37447d83 100644 --- a/packages/@aws-cdk/aws-s3objectlambda/package.json +++ b/packages/@aws-cdk/aws-s3objectlambda/package.json @@ -85,15 +85,23 @@ "devDependencies": { "@aws-cdk/assertions": "0.0.0", "@aws-cdk/cdk-build-tools": "0.0.0", + "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.4.1" + "@types/jest": "^27.4.1", + "jest": "^27.5.1" }, "dependencies": { + "@aws-cdk/aws-iam": "0.0.0", + "@aws-cdk/aws-lambda": "0.0.0", + "@aws-cdk/aws-s3": "0.0.0", "@aws-cdk/core": "0.0.0", "constructs": "^10.0.0" }, "peerDependencies": { + "@aws-cdk/aws-iam": "0.0.0", + "@aws-cdk/aws-lambda": "0.0.0", + "@aws-cdk/aws-s3": "0.0.0", "@aws-cdk/core": "0.0.0", "constructs": "^10.0.0" }, @@ -101,12 +109,17 @@ "node": ">= 14.15.0" }, "stability": "experimental", - "maturity": "cfn-only", + "maturity": "experimental", "awscdkio": { "announce": false }, "publishConfig": { "tag": "next" }, + "awslint": { + "exclude": [ + "attribute-tag:@aws-cdk/aws-s3objectlambda.AccessPoint.accessPointName" + ] + }, "private": true } diff --git a/packages/@aws-cdk/aws-s3objectlambda/test/integ.s3objectlambda.expected.json b/packages/@aws-cdk/aws-s3objectlambda/test/integ.s3objectlambda.expected.json new file mode 100644 index 0000000000000..c53bfb57cd719 --- /dev/null +++ b/packages/@aws-cdk/aws-s3objectlambda/test/integ.s3objectlambda.expected.json @@ -0,0 +1,239 @@ +{ + "Resources": { + "MyBucketF68F3FF0": { + "Type": "AWS::S3::Bucket", + "UpdateReplacePolicy": "Retain", + "DeletionPolicy": "Retain" + }, + "MyFunction1ServiceRole9852B06B": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ] + ] + } + ] + } + }, + "MyFunction1ServiceRoleDefaultPolicy39556460": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": "s3-object-lambda:WriteGetObjectResponse", + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "MyFunction1ServiceRoleDefaultPolicy39556460", + "Roles": [ + { + "Ref": "MyFunction1ServiceRole9852B06B" + } + ] + } + }, + "MyFunction12A744C2E": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "ZipFile": "foo" + }, + "Role": { + "Fn::GetAtt": [ + "MyFunction1ServiceRole9852B06B", + "Arn" + ] + }, + "Handler": "index.handler", + "Runtime": "nodejs14.x" + }, + "DependsOn": [ + "MyFunction1ServiceRoleDefaultPolicy39556460", + "MyFunction1ServiceRole9852B06B" + ] + }, + "MyFunction2ServiceRole07E5BE0E": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ] + ] + } + ] + } + }, + "MyFunction2ServiceRoleDefaultPolicyA79C693E": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": "s3-object-lambda:WriteGetObjectResponse", + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "MyFunction2ServiceRoleDefaultPolicyA79C693E", + "Roles": [ + { + "Ref": "MyFunction2ServiceRole07E5BE0E" + } + ] + } + }, + "MyFunction2F2A964CA": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "ZipFile": "foo" + }, + "Role": { + "Fn::GetAtt": [ + "MyFunction2ServiceRole07E5BE0E", + "Arn" + ] + }, + "Handler": "index.handler", + "Runtime": "nodejs14.x" + }, + "DependsOn": [ + "MyFunction2ServiceRoleDefaultPolicyA79C693E", + "MyFunction2ServiceRole07E5BE0E" + ] + }, + "MyObjectLambda1SupportingAccessPoint223B719B": { + "Type": "AWS::S3::AccessPoint", + "Properties": { + "Bucket": { + "Ref": "MyBucketF68F3FF0" + } + } + }, + "MyObjectLambda17554FEF4": { + "Type": "AWS::S3ObjectLambda::AccessPoint", + "Properties": { + "Name": "obj-lambda-1", + "ObjectLambdaConfiguration": { + "AllowedFeatures": [ + "GetObject-PartNumber" + ], + "CloudWatchMetricsEnabled": true, + "SupportingAccessPoint": { + "Fn::GetAtt": [ + "MyObjectLambda1SupportingAccessPoint223B719B", + "Arn" + ] + }, + "TransformationConfigurations": [ + { + "Actions": [ + "GetObject" + ], + "ContentTransformation": { + "AwsLambda": { + "FunctionArn": { + "Fn::GetAtt": [ + "MyFunction12A744C2E", + "Arn" + ] + } + } + } + } + ] + } + } + }, + "MyObjectLambda2SupportingAccessPoint6C54778F": { + "Type": "AWS::S3::AccessPoint", + "Properties": { + "Bucket": { + "Ref": "MyBucketF68F3FF0" + } + } + }, + "MyObjectLambda2CCBCAAF7": { + "Type": "AWS::S3ObjectLambda::AccessPoint", + "Properties": { + "Name": "obj-lambda-1", + "ObjectLambdaConfiguration": { + "AllowedFeatures": [ + "GetObject-Range" + ], + "SupportingAccessPoint": { + "Fn::GetAtt": [ + "MyObjectLambda2SupportingAccessPoint6C54778F", + "Arn" + ] + }, + "TransformationConfigurations": [ + { + "Actions": [ + "GetObject" + ], + "ContentTransformation": { + "AwsLambda": { + "FunctionArn": { + "Fn::GetAtt": [ + "MyFunction2F2A964CA", + "Arn" + ] + }, + "FunctionPayload": "{\"foo\":10}" + } + } + } + ] + } + } + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3objectlambda/test/integ.s3objectlambda.ts b/packages/@aws-cdk/aws-s3objectlambda/test/integ.s3objectlambda.ts new file mode 100644 index 0000000000000..e840de6367479 --- /dev/null +++ b/packages/@aws-cdk/aws-s3objectlambda/test/integ.s3objectlambda.ts @@ -0,0 +1,45 @@ +import * as lambda from '@aws-cdk/aws-lambda'; +import * as s3 from '@aws-cdk/aws-s3'; +import * as cdk from '@aws-cdk/core'; +import { AccessPoint } from '../lib'; + +class TestStack extends cdk.Stack { + constructor(scope: cdk.App, id: string) { + super(scope, id); + + const bucket = new s3.Bucket(this, 'MyBucket'); + const handler1 = new lambda.Function(this, 'MyFunction1', { + runtime: lambda.Runtime.NODEJS_14_X, + handler: 'index.handler', + code: lambda.Code.fromInline('foo'), + }); + + const handler2 = new lambda.Function(this, 'MyFunction2', { + runtime: lambda.Runtime.NODEJS_14_X, + handler: 'index.handler', + code: lambda.Code.fromInline('foo'), + }); + + new AccessPoint(this, 'MyObjectLambda1', { + bucket, + handler: handler1, + accessPointName: 'obj-lambda-1', + cloudWatchMetricsEnabled: true, + supportsGetObjectPartNumber: true, + }); + + new AccessPoint(this, 'MyObjectLambda2', { + bucket, + handler: handler2, + accessPointName: 'obj-lambda-1', + supportsGetObjectRange: true, + payload: { foo: 10 }, + }); + } +} + +const app = new cdk.App(); + +new TestStack(app, 'aws-s3-object-lambda'); + +app.synth(); diff --git a/packages/@aws-cdk/aws-s3objectlambda/test/s3objectlambda.test.ts b/packages/@aws-cdk/aws-s3objectlambda/test/s3objectlambda.test.ts index 465c7bdea0693..3e62fd370f039 100644 --- a/packages/@aws-cdk/aws-s3objectlambda/test/s3objectlambda.test.ts +++ b/packages/@aws-cdk/aws-s3objectlambda/test/s3objectlambda.test.ts @@ -1,6 +1,338 @@ -import '@aws-cdk/assertions'; -import {} from '../lib'; +import { Template } from '@aws-cdk/assertions'; +import * as lambda from '@aws-cdk/aws-lambda'; +import * as s3 from '@aws-cdk/aws-s3'; +import * as cdk from '@aws-cdk/core'; +import { AccessPoint } from '../lib'; -test('No tests are specified for this package', () => { - expect(true).toBe(true); +let stack: cdk.Stack; +let bucket: s3.Bucket; +let handler: lambda.Function; + +beforeEach(() => { + stack = new cdk.Stack(); + bucket = new s3.Bucket(stack, 'MyBucket'); + handler = new lambda.Function(stack, 'MyFunction', { + runtime: lambda.Runtime.NODEJS_14_X, + handler: 'index.hello', + code: new lambda.InlineCode('def hello(): pass'), + }); +}); + +test('Can create a valid access point', () => { + const accessPoint = new AccessPoint(stack, 'MyObjectLambda', { + bucket, + handler, + accessPointName: 'obj-lambda', + supportsGetObjectRange: true, + supportsGetObjectPartNumber: true, + payload: { foo: 10 }, + }); + new cdk.CfnOutput(stack, 'AccessPointName', { + value: accessPoint.accessPointName, + }); + new cdk.CfnOutput(stack, 'DomainName', { + value: accessPoint.domainName, + }); + new cdk.CfnOutput(stack, 'RegionalDomainName', { + value: accessPoint.regionalDomainName, + }); + new cdk.CfnOutput(stack, 'VirtualHostedUrl', { + value: accessPoint.virtualHostedUrlForObject('key', { + regional: true, + }), + }); + new cdk.CfnOutput(stack, 'VirtualHostedRegionalUrl', { + value: accessPoint.virtualHostedUrlForObject('key', { + regional: false, + }), + }); + + expect(Template.fromStack(stack).findOutputs('*')).toEqual( + { + AccessPointName: { + Value: { + Ref: 'MyObjectLambda3F9602DC', + }, + }, + DomainName: { + Value: { + 'Fn::Join': [ + '', + [ + { + Ref: 'MyObjectLambda3F9602DC', + }, + '-', + { + Ref: 'AWS::AccountId', + }, + '.s3-object-lambda.', + { + Ref: 'AWS::URLSuffix', + }, + ], + ], + }, + }, + RegionalDomainName: { + Value: { + 'Fn::Join': [ + '', + [ + { + Ref: 'MyObjectLambda3F9602DC', + }, + '-', + { + Ref: 'AWS::AccountId', + }, + '.s3-object-lambda.', + { + Ref: 'AWS::Region', + }, + '.', + { + Ref: 'AWS::URLSuffix', + }, + ], + ], + }, + }, + VirtualHostedRegionalUrl: { + Value: { + 'Fn::Join': [ + '', + [ + 'https://', + { + Ref: 'MyObjectLambda3F9602DC', + }, + '-', + { + Ref: 'AWS::AccountId', + }, + '.s3-object-lambda.', + { + Ref: 'AWS::URLSuffix', + }, + '/key', + ], + ], + }, + }, + VirtualHostedUrl: { + Value: { + 'Fn::Join': [ + '', + [ + 'https://', + { + Ref: 'MyObjectLambda3F9602DC', + }, + '-', + { + Ref: 'AWS::AccountId', + }, + '.s3-object-lambda.', + { + Ref: 'AWS::Region', + }, + '.', + { + Ref: 'AWS::URLSuffix', + }, + '/key', + ], + ], + }, + }, + }, + ); + + Template.fromStack(stack).hasResourceProperties('AWS::S3ObjectLambda::AccessPoint', { + ObjectLambdaConfiguration: { + AllowedFeatures: [ + 'GetObject-PartNumber', + 'GetObject-Range', + ], + TransformationConfigurations: [ + { + Actions: [ + 'GetObject', + ], + ContentTransformation: { + AwsLambda: { + FunctionArn: { + 'Fn::GetAtt': [ + 'MyFunction3BAA72D1', + 'Arn', + ], + }, + FunctionPayload: '{"foo":10}', + }, + }, + }, + ], + }, + }); +}); + +test('Can create an access point without specifying the name', () => { + new AccessPoint(stack, 'MyObjectLambda', { + bucket, + handler, + }); + Template.fromStack(stack).hasResourceProperties('AWS::S3ObjectLambda::AccessPoint', { + ObjectLambdaConfiguration: { + AllowedFeatures: [], + }, + }); +}); + +test('Slashes are removed from the virtual hosted url', () => { + const accessPoint = new AccessPoint(stack, 'MyObjectLambda', { + bucket, + handler, + }); + new cdk.CfnOutput(stack, 'VirtualHostedUrlNoKey', { + value: accessPoint.virtualHostedUrlForObject(), + }); + new cdk.CfnOutput(stack, 'VirtualHostedUrlKeyBeginsSlash', { + value: accessPoint.virtualHostedUrlForObject('/key1/key2'), + }); + new cdk.CfnOutput(stack, 'VirtualHostedUrlKeyEndsSlash', { + value: accessPoint.virtualHostedUrlForObject('key1/key2/'), + }); + expect(Template.fromStack(stack).findOutputs('*')).toEqual( { + VirtualHostedUrlKeyBeginsSlash: { + Value: { + 'Fn::Join': [ + '', + [ + 'https://', + { + Ref: 'MyObjectLambda3F9602DC', + }, + '-', + { + Ref: 'AWS::AccountId', + }, + '.s3-object-lambda.', + { + Ref: 'AWS::Region', + }, + '.', + { + Ref: 'AWS::URLSuffix', + }, + '/key1/key2', + ], + ], + }, + }, + VirtualHostedUrlKeyEndsSlash: { + Value: { + 'Fn::Join': [ + '', + [ + 'https://', + { + Ref: 'MyObjectLambda3F9602DC', + }, + '-', + { + Ref: 'AWS::AccountId', + }, + '.s3-object-lambda.', + { + Ref: 'AWS::Region', + }, + '.', + { + Ref: 'AWS::URLSuffix', + }, + '/key1/key2', + ], + ], + }, + }, + VirtualHostedUrlNoKey: { + Value: { + 'Fn::Join': [ + '', + [ + 'https://', + { + Ref: 'MyObjectLambda3F9602DC', + }, + '-', + { + Ref: 'AWS::AccountId', + }, + '.s3-object-lambda.', + { + Ref: 'AWS::Region', + }, + '.', + { + Ref: 'AWS::URLSuffix', + }, + ], + ], + }, + }, + }); +}); + +test('Validates the access point name', () => { + expect(() => new AccessPoint(stack, 'MyObjectLambda1', { + bucket, + handler, + accessPointName: 'aa', + })).toThrowError(/name must be between 3 and 50 characters long/); + expect(() => new AccessPoint(stack, 'MyObjectLambda2', { + bucket, + handler, + accessPointName: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', + })).toThrowError(/name must be between 3 and 50 characters long/); + expect(() => new AccessPoint(stack, 'MyObjectLambda3', { + bucket, + handler, + accessPointName: 'aaaa-s3alias', + })).toThrowError(/name cannot end with the suffix -s3alias/); + expect(() => new AccessPoint(stack, 'MyObjectLambda4', { + bucket, + handler, + accessPointName: '-aaaaa', + })).toThrowError(/name cannot begin or end with a dash/); + expect(() => new AccessPoint(stack, 'MyObjectLambda5', { + bucket, + handler, + accessPointName: 'aaaaa-', + })).toThrowError(/name cannot begin or end with a dash/); + expect(() => new AccessPoint(stack, 'MyObjectLambda6', { + bucket, + handler, + accessPointName: 'Aaaaa', + })).toThrowError(/name must begin with a number or lowercase letter and not contain underscores, uppercase letters, or periods/); + expect(() => new AccessPoint(stack, 'MyObjectLambda7', { + bucket, + handler, + accessPointName: '$aaaaa', + })).toThrowError(/name must begin with a number or lowercase letter and not contain underscores, uppercase letters, or periods/); + expect(() => new AccessPoint(stack, 'MyObjectLambda8', { + bucket, + handler, + accessPointName: 'aaaAaaa', + })).toThrowError(/name must begin with a number or lowercase letter and not contain underscores, uppercase letters, or periods/); + expect(() => new AccessPoint(stack, 'MyObjectLambda9', { + bucket, + handler, + accessPointName: 'aaa_aaa', + })).toThrowError(/name must begin with a number or lowercase letter and not contain underscores, uppercase letters, or periods/); + expect(() => new AccessPoint(stack, 'MyObjectLambda10', { + bucket, + handler, + accessPointName: 'aaa.aaa', + })).toThrowError(/name must begin with a number or lowercase letter and not contain underscores, uppercase letters, or periods/); }); diff --git a/packages/@aws-cdk/aws-secretsmanager/README.md b/packages/@aws-cdk/aws-secretsmanager/README.md index 8ff23ea3ba01d..5b88885e863a5 100644 --- a/packages/@aws-cdk/aws-secretsmanager/README.md +++ b/packages/@aws-cdk/aws-secretsmanager/README.md @@ -63,7 +63,7 @@ A secret can set `RemovalPolicy`. If it set to `RETAIN`, that removing a secret ## Grant permission to use the secret to a role You must grant permission to a resource for that resource to be allowed to -use a secret. This can be achieved with the `Secret.grantRead` and/or `Secret.grantUpdate` +use a secret. This can be achieved with the `Secret.grantRead` and/or `Secret.grantWrite` method, depending on your need: ```ts diff --git a/packages/@aws-cdk/aws-servicecatalog/README.md b/packages/@aws-cdk/aws-servicecatalog/README.md index 121aeba2db78f..fff8c5b498bba 100644 --- a/packages/@aws-cdk/aws-servicecatalog/README.md +++ b/packages/@aws-cdk/aws-servicecatalog/README.md @@ -9,13 +9,13 @@ > > [CFN Resources]: https://docs.aws.amazon.com/cdk/latest/guide/constructs.html#constructs_lib -![cdk-constructs: Experimental](https://img.shields.io/badge/cdk--constructs-experimental-important.svg?style=for-the-badge) +![cdk-constructs: Developer Preview](https://img.shields.io/badge/cdk--constructs-developer--preview-informational.svg?style=for-the-badge) -> The APIs of higher level constructs in this module are experimental and under active development. -> They are subject to non-backward compatible changes or removal in any future version. These are -> not subject to the [Semantic Versioning](https://semver.org/) model and breaking changes will be -> announced in the release notes. This means that while you may use them, you may need to update -> your source code when upgrading to a newer version of this package. +> The APIs of higher level constructs in this module are in **developer preview** before they +> become stable. We will only make breaking changes to address unforeseen API issues. Therefore, +> these APIs are not subject to [Semantic Versioning](https://semver.org/), and breaking changes +> will be announced in release notes. This means that while you may use them, you may need to +> update your source code when upgrading to a newer version of this package. --- @@ -37,7 +37,7 @@ enables organizations to create and manage catalogs of products for their end us - [Constraints](#constraints) - [Tag update constraint](#tag-update-constraint) - [Notify on stack events](#notify-on-stack-events) - - [CloudFormation parameters constraint](#cloudformation-parameters-constraint) + - [CloudFormation template parameters constraint](#cloudformation-template-parameters-constraint) - [Set launch role](#set-launch-role) - [Deploy with StackSets](#deploy-with-stacksets) @@ -50,23 +50,23 @@ import * as servicecatalog from '@aws-cdk/aws-servicecatalog'; ## Portfolio -AWS Service Catalog portfolios allow admins to manage products that their end users have access to. +AWS Service Catalog portfolios allow administrators to organize, manage, and distribute cloud resources for their end users. Using the CDK, a new portfolio can be created with the `Portfolio` construct: ```ts -new servicecatalog.Portfolio(this, 'MyFirstPortfolio', { - displayName: 'MyFirstPortfolio', +new servicecatalog.Portfolio(this, 'Portfolio', { + displayName: 'MyPortfolio', providerName: 'MyTeam', }); ``` -You can also specify properties such as `description` and `acceptLanguage` +You can also specify optional metadata properties such as `description` and `messageLanguage` to help better catalog and manage your portfolios. ```ts -new servicecatalog.Portfolio(this, 'MyFirstPortfolio', { +new servicecatalog.Portfolio(this, 'Portfolio', { displayName: 'MyFirstPortfolio', - providerName: 'MyTeam', + providerName: 'SCAdmin', description: 'Portfolio for a project', messageLanguage: servicecatalog.MessageLanguage.EN, }); @@ -74,37 +74,39 @@ new servicecatalog.Portfolio(this, 'MyFirstPortfolio', { Read more at [Creating and Managing Portfolios](https://docs.aws.amazon.com/servicecatalog/latest/adminguide/catalogs_portfolios.html). -A portfolio that has been created outside the stack can be imported into your CDK app. -Portfolios can be imported by their ARN via the `Portfolio.fromPortfolioArn()` API: +To import an existing portfolio into your CDK application, use the `Portfolio.fromPortfolioArn()` factory method: ```ts -const portfolio = servicecatalog.Portfolio.fromPortfolioArn(this, 'MyImportedPortfolio', +const portfolio = servicecatalog.Portfolio.fromPortfolioArn(this, 'ImportedPortfolio', 'arn:aws:catalog:region:account-id:portfolio/port-abcdefghi'); ``` ### Granting access to a portfolio -You can manage end user access to a portfolio by granting permissions to `IAM` entities like a user, group, or role. +You can grant access to and manage the `IAM` users, groups, or roles that have access to the products within a portfolio. +Entities with granted access will be able to utilize the portfolios resources and products via the console or AWS CLI. Once resources are deployed end users will be able to access them via the console or service catalog CLI. ```ts fixture=basic-portfolio import * as iam from '@aws-cdk/aws-iam'; -const user = new iam.User(this, 'MyUser'); +const user = new iam.User(this, 'User'); portfolio.giveAccessToUser(user); -const role = new iam.Role(this, 'MyRole', { +const role = new iam.Role(this, 'Role', { assumedBy: new iam.AccountRootPrincipal(), }); portfolio.giveAccessToRole(role); -const group = new iam.Group(this, 'MyGroup'); +const group = new iam.Group(this, 'Group'); portfolio.giveAccessToGroup(group); ``` ### Sharing a portfolio with another AWS account -A portfolio can be programatically shared with other accounts so that specified users can also access it: +You can use account-to-account sharing to distribute a reference to your portfolio to other AWS accounts by passing the recipient account number. +After the share is initiated, the recipient account can accept the share via CLI or console by importing the portfolio ID. +Changes made to the shared portfolio will automatically propagate to recipients. ```ts fixture=basic-portfolio portfolio.shareWithAccount('012345678901'); @@ -112,10 +114,10 @@ portfolio.shareWithAccount('012345678901'); ## Product -Products are the resources you are allowing end users to provision and utilize. +Products are version friendly infrastructure-as-code templates that admins create and add to portfolios for end users to provision and create AWS resources. The CDK currently only supports adding products of type Cloudformation product. Using the CDK, a new Product can be created with the `CloudFormationProduct` construct. -`CloudFormationTemplate.fromUrl` can be utilized to create a Product using a Cloudformation template directly from an URL: +You can use `CloudFormationTemplate.fromUrl` to create a Product from a CloudFormation template directly from a URL that points to the template in S3, GitHub, or CodeCommit: ```ts const product = new servicecatalog.CloudFormationProduct(this, 'MyFirstProduct', { @@ -133,14 +135,14 @@ const product = new servicecatalog.CloudFormationProduct(this, 'MyFirstProduct', ### Creating a product from a local asset -A `CloudFormationProduct` can also be created using a Cloudformation template from an Asset. +A `CloudFormationProduct` can also be created by using a CloudFormation template held locally on disk using Assets. Assets are files that are uploaded to an S3 Bucket before deployment. `CloudFormationTemplate.fromAsset` can be utilized to create a Product by passing the path to a local template file on your disk: ```ts import * as path from 'path'; -const product = new servicecatalog.CloudFormationProduct(this, 'MyFirstProduct', { +const product = new servicecatalog.CloudFormationProduct(this, 'Product', { productName: "My Product", owner: "Product Owner", productVersions: [ @@ -159,10 +161,10 @@ const product = new servicecatalog.CloudFormationProduct(this, 'MyFirstProduct', ### Creating a product from a stack -You can define a service catalog `CloudFormationProduct` entirely within CDK using a service catalog `ProductStack`. +You can create a Service Catalog `CloudFormationProduct` entirely defined with CDK code using a service catalog `ProductStack`. A separate child stack for your product is created and you can add resources like you would for any other CDK stack, such as an S3 Bucket, IAM roles, and EC2 instances. This stack is passed in as a product version to your -product. This will not create a separate stack during deployment. +product. This will not create a separate CloudFormation stack during deployment. ```ts import * as s3 from '@aws-cdk/aws-s3'; @@ -176,7 +178,7 @@ class S3BucketProduct extends servicecatalog.ProductStack { } } -const product = new servicecatalog.CloudFormationProduct(this, 'MyFirstProduct', { +const product = new servicecatalog.CloudFormationProduct(this, 'Product', { productName: "My Product", owner: "Product Owner", productVersions: [ @@ -190,9 +192,9 @@ const product = new servicecatalog.CloudFormationProduct(this, 'MyFirstProduct', ### Adding a product to a portfolio -You add products to a portfolio to manage your resources at scale. After adding a product to a portfolio, -it creates a portfolio-product association, and will become visible from the portfolio side in both the console and service catalog CLI. -A product can be added to multiple portfolios depending on your resource and organizational needs. +You add products to a portfolio to organize and distribute your catalog at scale. Adding a product to a portfolio creates an association, +and the product will become visible within the portfolio side in both the Service Catalog console and AWS CLI. +You can add a product to multiple portfolios depending on your organizational structure and how you would like to group access to products. ```ts fixture=portfolio-product portfolio.addProduct(product); @@ -200,11 +202,11 @@ portfolio.addProduct(product); ## Tag Options -TagOptions allow administrators to easily manage tags on provisioned products by creating a selection of tags for end users to choose from. -TagOptions are created by specifying a tag key with a selection of allowed values and can be associated with both portfolios and products. +TagOptions allow administrators to easily manage tags on provisioned products by providing a template for a selection of tags that end users choose from. +TagOptions are created by specifying a tag key with a set of allowed values and can be associated with both portfolios and products. When launching a product, both the TagOptions associated with the product and the containing portfolio are made available. -At the moment, TagOptions can only be disabled in the console. +At the moment, TagOptions can only be deactivated in the console. ```ts fixture=portfolio-product const tagOptionsForPortfolio = new servicecatalog.TagOptions(this, 'OrgTagOptions', { @@ -225,12 +227,11 @@ product.associateTagOptions(tagOptionsForProduct); ## Constraints -Constraints define governance mechanisms that allow you to manage permissions, notifications, and options related to actions end users can perform on products, -Constraints are applied on a portfolio-product association. +Constraints are governance gestures that you place on product-portfolio associations that allow you to manage minimal launch permissions, notifications, and other optional actions that end users can perform on products. Using the CDK, if you do not explicitly associate a product to a portfolio and add a constraint, it will automatically add an association for you. -There are rules around plurariliites of constraints for a portfolio and product. -For example, you can only have a single "tag update" constraint applied to a portfolio-product association. +There are rules around how constraints are applied to portfolio-product associations. +For example, you can only have a single "launch role" constraint applied to a portfolio-product association. If a misconfigured constraint is added, `synth` will fail with an error message. Read more at [Service Catalog Constraints](https://docs.aws.amazon.com/servicecatalog/latest/adminguide/constraints.html). @@ -238,7 +239,7 @@ Read more at [Service Catalog Constraints](https://docs.aws.amazon.com/serviceca ### Tag update constraint Tag update constraints allow or disallow end users to update tags on resources associated with an AWS Service Catalog product upon provisioning. -By default, tag updating is not permitted. +By default, if a Tag Update constraint is not configured, tag updating is not permitted. If tag updating is allowed, then new tags associated with the product or portfolio will be applied to provisioned resources during a provisioned product update. ```ts fixture=portfolio-product @@ -258,30 +259,30 @@ portfolio.constrainTagUpdates(product, { ### Notify on stack events -Allows users to subscribe an AWS `SNS` topic to the stack events of the product. -When an end user provisions a product it creates a product stack that notifies the subscribed topic on creation, edit, and delete events. -An individual `SNS` topic may only be subscribed once to a portfolio-product association. +Allows users to subscribe an AWS `SNS` topic to a provisioned product's CloudFormation stack events. +When an end user provisions a product it creates a CloudFormation stack that notifies the subscribed topic on creation, edit, and delete events. +An individual `SNS` topic may only have a single subscription to any given portfolio-product association. ```ts fixture=portfolio-product import * as sns from '@aws-cdk/aws-sns'; -const topic1 = new sns.Topic(this, 'MyTopic1'); +const topic1 = new sns.Topic(this, 'Topic1'); portfolio.notifyOnStackEvents(product, topic1); -const topic2 = new sns.Topic(this, 'MyTopic2'); +const topic2 = new sns.Topic(this, 'Topic2'); portfolio.notifyOnStackEvents(product, topic2, { - description: 'description for this topic2', // description is an optional field. + description: 'description for topic2', // description is an optional field. }); ``` -### CloudFormation parameters constraint +### CloudFormation template parameters constraint -CloudFormation parameters constraints allow you to configure the that are available to end users when they launch a product via defined rules. -A rule consists of one or more assertions that narrow the allowable values for parameters in a product. -You can configure multiple parameter constraints to govern the different parameters and parameter options in your products. -For example, a rule might define the various instance types that users can choose from when launching a stack that includes EC2 instances. -A parameter rule has an optional `condition` field that allows ability to configure when rules are applied. -If a `condition` is specified, all the assertions will be applied if the condition evalutates to true. +CloudFormation template parameter constraints allow you to configure the provisioning parameters that are available to end users when they launch a product. +Template constraint rules consist of one or more assertions that define the default and/or allowable values for a product’s provisioning parameters. +You can configure multiple parameter constraints to govern the different provisioning parameters within your products. +For example, a rule might define the `EC2` instance types that users can choose from when launching a product that includes one or more `EC2` instances. +Parameter rules have an optional `condition` field that allow for rule application to consider conditional evaluations. +If a `condition` is specified, all assertions will be applied if the condition evaluates to true. For information on rule-specific intrinsic functions to define rule conditions and assertions, see [AWS Rule Functions](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-rules.html). @@ -302,10 +303,12 @@ portfolio.constrainCloudFormationParameters(product, { ### Set launch role -Allows you to configure a specific AWS `IAM` role that a user must assume when launching a product. -By setting this launch role, you can control what policies and privileges end users can have. -The launch role must be assumed by the service catalog principal. -You can only have one launch role set for a portfolio-product association, and you cannot set a launch role if a StackSets deployment has been configured. +Allows you to configure a specific `IAM` role that Service Catalog assumes on behalf of the end user when launching a product. +By setting a launch role constraint, you can maintain least permissions for an end user when launching a product. +For example, a launch role can grant permissions for specific resource creation like an `S3` bucket that the user. +The launch role must be assumed by the Service Catalog principal. +You can only have one launch role set for a portfolio-product association, +and you cannot set a launch role on a product that already has a StackSets deployment configured. ```ts fixture=portfolio-product import * as iam from '@aws-cdk/aws-iam'; @@ -346,16 +349,16 @@ const launchRole: iam.IRole = portfolio.setLocalLaunchRoleName(product, roleName ``` See [Launch Constraint](https://docs.aws.amazon.com/servicecatalog/latest/adminguide/constraints-launch.html) documentation -to understand the permissions roles need. +to understand the permissions that launch roles need. ### Deploy with StackSets A StackSets deployment constraint allows you to configure product deployment options using [AWS CloudFormation StackSets](https://docs.aws.amazon.com/servicecatalog/latest/adminguide/using-stacksets.html). -You can specify multiple accounts and regions for the product launch following StackSets conventions. -There is an additional field `allowStackSetInstanceOperations` that configures ability for end users to create, edit, or delete the stacks. +You can specify one or more accounts and regions into which stack instances will launch when the product is provisioned. +There is an additional field `allowStackSetInstanceOperations` that sets ability for end users to create, edit, or delete the stacks created by the StackSet. By default, this field is set to `false`. -End users can manage those accounts and determine where products deploy and the order of deployment. +When launching a StackSets product, end users can select from the list of accounts and regions configured in the constraint to determine where the Stack Instances will deploy and the order of deployment. You can only define one StackSets deployment configuration per portfolio-product association, and you cannot both set a launch role and StackSets deployment configuration for an assocation. diff --git a/packages/@aws-cdk/aws-servicecatalog/package.json b/packages/@aws-cdk/aws-servicecatalog/package.json index 491fbc1542620..c01c45433260e 100644 --- a/packages/@aws-cdk/aws-servicecatalog/package.json +++ b/packages/@aws-cdk/aws-servicecatalog/package.json @@ -122,7 +122,7 @@ "ref-via-interface:@aws-cdk/aws-servicecatalog.PortfolioProps.tagOptions" ] }, - "maturity": "experimental", + "maturity": "developer-preview", "stability": "experimental", "awscdkio": { "announce": false diff --git a/packages/@aws-cdk/cfnspec/CHANGELOG.md b/packages/@aws-cdk/cfnspec/CHANGELOG.md index ccf8f50ff2d31..247a718165fd2 100644 --- a/packages/@aws-cdk/cfnspec/CHANGELOG.md +++ b/packages/@aws-cdk/cfnspec/CHANGELOG.md @@ -1,3 +1,45 @@ +# CloudFormation Resource Specification v59.0.0 + +## New Resource Types + +* AWS::EKS::IdentityProviderConfig +* AWS::MSK::BatchScramSecret +* AWS::MSK::Configuration + +## Attribute Changes + +* AWS::ImageBuilder::Image ImageUri (__added__) +* AWS::MSK::Cluster Arn (__added__) + +## Property Changes + +* AWS::AmplifyUIBuilder::Component SchemaVersion (__added__) +* AWS::ApiGateway::BasePathMapping Id (__added__) +* AWS::EC2::TransitGatewayVpcAttachment SubnetIds.Required (__changed__) + * Old: false + * New: true +* AWS::EC2::TransitGatewayVpcAttachment TransitGatewayId.Required (__changed__) + * Old: false + * New: true +* AWS::EC2::TransitGatewayVpcAttachment VpcId.Required (__changed__) + * Old: false + * New: true +* AWS::ImageBuilder::Image ContainerRecipeArn.UpdateType (__changed__) + * Old: Mutable + * New: Immutable +* AWS::MSK::Cluster CurrentVersion (__added__) +* AWS::MSK::Cluster Tags.PrimitiveType (__deleted__) +* AWS::MSK::Cluster Tags.PrimitiveItemType (__added__) +* AWS::MSK::Cluster Tags.Type (__added__) + +## Property Type Changes + +* AWS::DataBrew::Job.Output MaxOutputFiles (__added__) +* AWS::MSK::Cluster.BrokerNodeGroupInfo ClientSubnets.DuplicatesAllowed (__added__) +* AWS::MSK::Cluster.BrokerNodeGroupInfo SecurityGroups.DuplicatesAllowed (__added__) +* AWS::MSK::Cluster.Tls CertificateAuthorityArnList.DuplicatesAllowed (__added__) + + # CloudFormation Resource Specification v58.0.0 ## New Resource Types diff --git a/packages/@aws-cdk/cfnspec/cfn.version b/packages/@aws-cdk/cfnspec/cfn.version index 7218a42ede4f9..1a985d6cc8839 100644 --- a/packages/@aws-cdk/cfnspec/cfn.version +++ b/packages/@aws-cdk/cfnspec/cfn.version @@ -1 +1 @@ -58.0.0 +59.0.0 diff --git a/packages/@aws-cdk/cfnspec/spec-source/cfn-docs/cfn-docs.json b/packages/@aws-cdk/cfnspec/spec-source/cfn-docs/cfn-docs.json index b818011fd0df4..ac2b4d0caddc7 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/cfn-docs/cfn-docs.json +++ b/packages/@aws-cdk/cfnspec/spec-source/cfn-docs/cfn-docs.json @@ -649,10 +649,11 @@ "Children": "A list of the component's `ComponentChild` instances.", "CollectionProperties": "The data binding configuration for the component's properties. Use this for a collection component. You can't specify `tags` as a valid property for `collectionProperties` .", "ComponentType": "The type of the component. This can be an Amplify custom UI component or another custom component.", - "Events": "", + "Events": "Describes the events that can be raised on the component. Use for the workflow feature in Amplify Studio that allows you to bind events and actions to components.", "Name": "The name of the component.", "Overrides": "Describes the component's properties that can be overriden in a customized instance of the component. You can't specify `tags` as a valid property for `overrides` .", "Properties": "Describes the component's properties. You can't specify `tags` as a valid property for `properties` .", + "SchemaVersion": "The schema version of the component when it was imported.", "SourceId": "The unique ID of the component in its original source system, such as Figma.", "Tags": "One or more key-value pairs to use when tagging the component.", "Variants": "A list of the component's variants. A variant is a unique style configuration of a main component." @@ -660,17 +661,17 @@ }, "AWS::AmplifyUIBuilder::Component.ActionParameters": { "attributes": {}, - "description": "", + "description": "The `ActionParameters` property specifies the event action configuration for an element of a `Component` or `ComponentChild` . Use for the workflow feature in Amplify Studio that allows you to bind events and actions to components. `ActionParameters` defines the action that is performed when an event occurs on the component.", "properties": { - "Anchor": "", - "Fields": "", - "Global": "", - "Id": "", - "Model": "", - "State": "", - "Target": "", - "Type": "", - "Url": "" + "Anchor": "The HTML anchor link to the location to open. Specify this value for a navigation action.", + "Fields": "A dictionary of key-value pairs mapping Amplify Studio properties to fields in a data model. Use when the action performs an operation on an Amplify DataStore model.", + "Global": "Specifies whether the user should be signed out globally. Specify this value for an auth sign out action.", + "Id": "The unique ID of the component that the `ActionParameters` apply to.", + "Model": "The name of the data model. Use when the action performs an operation on an Amplify DataStore model.", + "State": "A key-value pair that specifies the state property name and its initial value.", + "Target": "The element within the same component to modify when the action occurs.", + "Type": "The type of navigation action. Valid values are `url` and `anchor` . This value is required for a navigation action.", + "Url": "The URL to the location to open. Specify this value for a navigation action." } }, "AWS::AmplifyUIBuilder::Component.ComponentBindingPropertiesValue": { @@ -701,7 +702,7 @@ "properties": { "Children": "The list of `ComponentChild` instances for this component.", "ComponentType": "The type of the child component.", - "Events": "", + "Events": "Describes the events that can be raised on the child component. Use for the workflow feature in Amplify Studio that allows you to bind events and actions to components.", "Name": "The name of the child component.", "Properties": "Describes the properties of the child component. You can't specify `tags` as a valid property for `properties` ." } @@ -713,7 +714,7 @@ "Else": "The value to assign to the property if the condition is not met.", "Field": "The name of a field. Specify this when the property is a data model.", "Operand": "The value of the property to evaluate.", - "OperandType": "", + "OperandType": "The type of the property to evaluate.", "Operator": "The operator to use to perform the evaluation, such as `eq` to represent equals.", "Property": "The name of the conditional property.", "Then": "The value to assign to the property if the condition is met." @@ -731,15 +732,15 @@ }, "AWS::AmplifyUIBuilder::Component.ComponentEvent": { "attributes": {}, - "description": "", + "description": "The `ComponentEvent` property specifies the configuration of an event. You can bind an event and a corresponding action to a `Component` or a `ComponentChild` . A button click is an example of an event.", "properties": { - "Action": "", - "Parameters": "" + "Action": "The action to perform when a specific event is raised.", + "Parameters": "Describes information about the action." } }, "AWS::AmplifyUIBuilder::Component.ComponentEvents": { "attributes": {}, - "description": "", + "description": "The `ComponentEvents` property specifies the events that can be raised on the component. Use for the workflow feature in Amplify Studio that allows you to bind events and actions to components.", "properties": {} }, "AWS::AmplifyUIBuilder::Component.ComponentOverrides": { @@ -764,7 +765,7 @@ "BindingProperties": "The information to bind the component property to data at runtime.", "Bindings": "The information to bind the component property to form data.", "CollectionBindingProperties": "The information to bind the component property to data at runtime. Use this for collection components.", - "ComponentName": "", + "ComponentName": "The name of the component that is affected by an event.", "Concat": "A list of component properties to concatenate to create the value to assign to this component property.", "Condition": "The conditional expression to use to assign a value to the component property.", "Configured": "Specifies whether the user configured the property in Amplify Studio after importing it.", @@ -772,7 +773,7 @@ "Event": "An event that occurs in your app. Use this for workflow data binding.", "ImportedValue": "The default value assigned to the property when the component is imported into an app.", "Model": "The data model to use to assign a value to the component property.", - "Property": "", + "Property": "The name of the component's property that is affected by an event.", "Type": "The component type.", "UserAttribute": "An authenticated user attribute to use to assign a value to the component property.", "Value": "The value to assign to the component property." @@ -806,11 +807,11 @@ }, "AWS::AmplifyUIBuilder::Component.MutationActionSetStateParameter": { "attributes": {}, - "description": "", + "description": "The `MutationActionSetStateParameter` property specifies the state configuration when an action modifies a property of another element within the same component.", "properties": { - "ComponentName": "", - "Property": "", - "Set": "" + "ComponentName": "The name of the component that is being modified.", + "Property": "The name of the component property to apply the state configuration to.", + "Set": "The state configuration to assign to the property." } }, "AWS::AmplifyUIBuilder::Component.Predicate": { @@ -925,6 +926,7 @@ "properties": { "BasePath": "The base path name that callers of the API must provide in the URL after the domain name.", "DomainName": "The `DomainName` of an [AWS::ApiGateway::DomainName](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-apigateway-domainname.html) resource.", + "Id": "", "RestApiId": "The ID of the API.", "Stage": "The name of the API's stage." } @@ -5134,7 +5136,7 @@ "MixedInstancesPolicy": "An embedded object that specifies a mixed instances policy.\n\nThe policy includes properties that not only define the distribution of On-Demand Instances and Spot Instances, the maximum price to pay for Spot Instances (optional), and how the Auto Scaling group allocates instance types to fulfill On-Demand and Spot capacities, but also the properties that specify the instance configuration information\u2014the launch template and instance types. The policy can also include a weight for each instance type and different launch templates for individual instance types.\n\nFor more information, see [Auto Scaling groups with multiple instance types and purchase options](https://docs.aws.amazon.com/autoscaling/ec2/userguide/ec2-auto-scaling-mixed-instances-groups.html) in the *Amazon EC2 Auto Scaling User Guide* .\n\nIf you specify `LaunchTemplate` , `InstanceId` , or `LaunchConfigurationName` , don't specify `MixedInstancesPolicy` .", "NewInstancesProtectedFromScaleIn": "Indicates whether newly launched instances are protected from termination by Amazon EC2 Auto Scaling when scaling in. For more information about preventing instances from terminating on scale in, see [Instance Protection](https://docs.aws.amazon.com/autoscaling/ec2/userguide/as-instance-termination.html#instance-protection) in the *Amazon EC2 Auto Scaling User Guide* .", "NotificationConfigurations": "Configures an Auto Scaling group to send notifications when specified events take place.", - "PlacementGroup": "The name of the placement group into which you want to launch your instances. A placement group is a logical grouping of instances within a single Availability Zone. For more information, see [Placement Groups](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/placement-groups.html) in the *Amazon EC2 User Guide for Linux Instances* .", + "PlacementGroup": "The name of the placement group into which you want to launch your instances. For more information, see [Placement groups](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/placement-groups.html) in the *Amazon EC2 User Guide for Linux Instances* .\n\n> A *cluster* placement group is a logical grouping of instances within a single Availability Zone. You cannot specify multiple Availability Zones and a cluster placement group.", "ServiceLinkedRoleARN": "The Amazon Resource Name (ARN) of the service-linked role that the Auto Scaling group uses to call other AWS services on your behalf. By default, Amazon EC2 Auto Scaling uses a service-linked role named `AWSServiceRoleForAutoScaling` , which it creates if it does not exist. For more information, see [Service-linked roles for Amazon EC2 Auto Scaling](https://docs.aws.amazon.com/autoscaling/ec2/userguide/autoscaling-service-linked-role.html) in the *Amazon EC2 Auto Scaling User Guide* .", "Tags": "One or more tags. You can tag your Auto Scaling group and propagate the tags to the Amazon EC2 instances it launches. For more information, see [Tagging Auto Scaling groups and instances](https://docs.aws.amazon.com/autoscaling/ec2/userguide/autoscaling-tagging.html) in the *Amazon EC2 Auto Scaling User Guide* .", "TargetGroupARNs": "One or more Amazon Resource Names (ARN) of load balancer target groups to associate with the Auto Scaling group. Instances are registered as targets in a target group, and traffic is routed to the target group. For more information, see [Elastic Load Balancing and Amazon EC2 Auto Scaling](https://docs.aws.amazon.com/autoscaling/ec2/userguide/autoscaling-load-balancer.html) in the *Amazon EC2 Auto Scaling User Guide* .", @@ -8677,7 +8679,7 @@ "AllowedOAuthFlows": "The allowed OAuth flows.\n\nSet to `code` to initiate a code grant flow, which provides an authorization code as the response. This code can be exchanged for access tokens with the token endpoint.\n\nSet to `implicit` to specify that the client should get the access token (and, optionally, ID token, based on scopes) directly.\n\nSet to `client_credentials` to specify that the client should get the access token (and, optionally, ID token, based on scopes) from the token endpoint using a combination of client and client_secret.", "AllowedOAuthFlowsUserPoolClient": "Set to true if the client is allowed to follow the OAuth protocol when interacting with Amazon Cognito user pools.", "AllowedOAuthScopes": "The allowed OAuth scopes. Possible values provided by OAuth are: `phone` , `email` , `openid` , and `profile` . Possible values provided by AWS are: `aws.cognito.signin.user.admin` . Custom scopes created in Resource Servers are also supported.", - "AnalyticsConfiguration": "The Amazon Pinpoint analytics configuration for collecting metrics for this user pool.\n\n> In AWS Regions where isn't available, User Pools only supports sending events to Amazon Pinpoint projects in AWS Region us-east-1. In Regions where is available, User Pools will support sending events to Amazon Pinpoint projects within that same Region.", + "AnalyticsConfiguration": "The Amazon Pinpoint analytics configuration for collecting metrics for this user pool.\n\n> In AWS Regions where Amazon Pinpoint isn't available, User Pools only supports sending events to Amazon Pinpoint projects in AWS Region us-east-1. In Regions where is available, User Pools will support sending events to Amazon Pinpoint projects within that same Region.", "CallbackURLs": "A list of allowed redirect (callback) URLs for the identity providers.\n\nA redirect URI must:\n\n- Be an absolute URI.\n- Be registered with the authorization server.\n- Not include a fragment component.\n\nSee [OAuth 2.0 - Redirection Endpoint](https://docs.aws.amazon.com/https://tools.ietf.org/html/rfc6749#section-3.1.2) .\n\nAmazon Cognito requires HTTPS over HTTP except for http://localhost for testing purposes only.\n\nApp callback URLs such as myapp://example are also supported.", "ClientName": "The client name for the user pool client you would like to create.", "DefaultRedirectURI": "The default redirect URI. Must be in the `CallbackURLs` list.\n\nA redirect URI must:\n\n- Be an absolute URI.\n- Be registered with the authorization server.\n- Not include a fragment component.\n\nSee [OAuth 2.0 - Redirection Endpoint](https://docs.aws.amazon.com/https://tools.ietf.org/html/rfc6749#section-3.1.2) .\n\nAmazon Cognito requires HTTPS over HTTP except for http://localhost for testing purposes only.\n\nApp callback URLs such as myapp://example are also supported.", @@ -10818,7 +10820,7 @@ "GlobalSecondaryIndexes": "Global secondary indexes to be created on the global table. You can create up to 20 global secondary indexes. Each replica in your global table will have the same global secondary index settings. You can only create or delete one global secondary index in a single stack operation.\n\nSince the backfilling of an index could take a long time, CloudFormation does not wait for the index to become active. If a stack operation rolls back, CloudFormation might not delete an index that has been added. In that case, you will need to delete the index manually.", "KeySchema": "Specifies the attributes that make up the primary key for the table. The attributes in the `KeySchema` property must also be defined in the `AttributeDefinitions` property.", "LocalSecondaryIndexes": "Local secondary indexes to be created on the table. You can create up to five local secondary indexes. Each index is scoped to a given hash key value. The size of each hash key can be up to 10 gigabytes. Each replica in your global table will have the same local secondary index settings.", - "Replicas": "Specifies the list of replicas for your global table. The list must contain at least one element, the region where the stack defining the global table is deployed. For example, if you define your table in a stack deployed to us-east-1, you must have an entry in `Replicas` with the region us-east-1. You cannot remove the replica in the stack region.\n\n> Adding a replica might take a few minutes for an empty table, or up to several hours for large tables. If you want to add or remove a replica, we recommend submitting an `UpdateStack` operation containing only that change.\n> \n> If you add or delete a replica during an update, we recommend that you don't update any other resources. If your stack fails to update and is rolled back while adding a new replica, you might need to manually delete the replica. \n\nYou can create a new global table with up to two replicas. You can add or remove replicas after table creation, but you can only add or remove a single replica in each update.", + "Replicas": "Specifies the list of replicas for your global table. The list must contain at least one element, the region where the stack defining the global table is deployed. For example, if you define your table in a stack deployed to us-east-1, you must have an entry in `Replicas` with the region us-east-1. You cannot remove the replica in the stack region.\n\n> Adding a replica might take a few minutes for an empty table, or up to several hours for large tables. If you want to add or remove a replica, we recommend submitting an `UpdateStack` operation containing only that change.\n> \n> If you add or delete a replica during an update, we recommend that you don't update any other resources. If your stack fails to update and is rolled back while adding a new replica, you might need to manually delete the replica. \n\nYou can create a new global table with as many replicas as needed. You can add or remove replicas after table creation, but you can only add or remove a single replica in each update.", "SSESpecification": "Specifies the settings to enable server-side encryption. These settings will be applied to all replicas. If you plan to use customer-managed KMS keys, you must provide a key for each replica using the `ReplicaSpecification.ReplicaSSESpecification` property.", "StreamSpecification": "Specifies the streams settings on your global table. You must provide a value for this property if your global table contains more than one replica. You can only change the streams settings if your global table has only one replica.", "TableName": "A name for the global table. If you don't specify a name, AWS CloudFormation generates a unique ID and uses that ID as the table name. For more information, see [Name type](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-name.html) .\n\n> If you specify a name, you cannot perform updates that require replacement of this resource. You can perform updates that require no or some interruption. If you must replace the resource, specify a new name.", @@ -10927,7 +10929,7 @@ "ReadProvisionedThroughputSettings": "Defines read capacity settings for the replica table.", "Region": "The region in which this replica exists.", "SSESpecification": "Allows you to specify a customer-managed key for the replica. When using customer-managed keys for server-side encryption, this property must have a value in all replicas.", - "TableClass": "", + "TableClass": "The table class of the specified table. Valid values are `STANDARD` and `STANDARD_INFREQUENT_ACCESS` .", "Tags": "An array of key-value pairs to apply to this replica.\n\nFor more information, see [Tag](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-resource-tags.html) ." } }, @@ -13880,7 +13882,7 @@ "InstanceWarmupPeriod": "The period of time, in seconds, after a newly launched Amazon EC2 instance can contribute to CloudWatch metrics for Auto Scaling group. If this parameter is omitted, the default value of `300` seconds is used.", "MaximumScalingStepSize": "The maximum number of container instances that Amazon ECS scales in or scales out at one time. If this parameter is omitted, the default value of `10000` is used.", "MinimumScalingStepSize": "The minimum number of container instances that Amazon ECS scales in or scales out at one time. If this parameter is omitted, the default value of `1` is used.", - "Status": "Determines whether to enable managed scaling for the capacity provider.", + "Status": "Determines whether to use managed scaling for the capacity provider.", "TargetCapacity": "The target capacity value for the capacity provider. The specified value must be greater than `0` and less than or equal to `100` . A value of `100` results in the Amazon EC2 instances in your Auto Scaling group being completely used." } }, @@ -13917,7 +13919,7 @@ }, "AWS::ECS::Cluster.ClusterSettings": { "attributes": {}, - "description": "The settings to use when creating a cluster. This parameter is used to enable CloudWatch Container Insights for a cluster.", + "description": "The settings to use when creating a cluster. This parameter is used to turn on CloudWatch Container Insights for a cluster.", "properties": { "Name": "The name of the cluster setting. The only supported value is `containerInsights` .", "Value": "The value to set for the cluster setting. The supported values are `enabled` and `disabled` . If `enabled` is specified, CloudWatch Container Insights will be enabled for the cluster, otherwise it will be disabled unless the `containerInsights` account setting is enabled. If a cluster value is specified, it will override the `containerInsights` value set with [PutAccountSetting](https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_PutAccountSetting.html) or [PutAccountSettingDefault](https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_PutAccountSettingDefault.html) ." @@ -13936,7 +13938,7 @@ "attributes": {}, "description": "The log configuration for the results of the execute command actions. The logs can be sent to CloudWatch Logs or an Amazon S3 bucket.", "properties": { - "CloudWatchEncryptionEnabled": "Determines whether to enable encryption on the CloudWatch logs. If not specified, encryption will be disabled.", + "CloudWatchEncryptionEnabled": "Determines whether to use encryption on the CloudWatch logs. If not specified, encryption will be disabled.", "CloudWatchLogGroupName": "The name of the CloudWatch log group to send logs to.\n\n> The CloudWatch log group must already be created.", "S3BucketName": "The name of the S3 bucket to send logs to.\n\n> The S3 bucket must already be created.", "S3EncryptionEnabled": "Determines whether to use encryption on the S3 logs. If not specified, encryption is not used.", @@ -13987,7 +13989,7 @@ "DeploymentConfiguration": "Optional deployment parameters that control how many tasks run during the deployment and the ordering of stopping and starting tasks.", "DeploymentController": "The deployment controller to use for the service. If no deployment controller is specified, the default value of `ECS` is used.", "DesiredCount": "The number of instantiations of the specified task definition to place and keep running on your cluster.\n\nFor new services, if a desired count is not specified, a default value of `1` is used. When using the `DAEMON` scheduling strategy, the desired count is not required.\n\nFor existing services, if a desired count is not specified, it is omitted from the operation.", - "EnableECSManagedTags": "Specifies whether to enable Amazon ECS managed tags for the tasks within the service. For more information, see [Tagging Your Amazon ECS Resources](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-using-tags.html) in the *Amazon Elastic Container Service Developer Guide* .", + "EnableECSManagedTags": "Specifies whether to turn on Amazon ECS managed tags for the tasks within the service. For more information, see [Tagging Your Amazon ECS Resources](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-using-tags.html) in the *Amazon Elastic Container Service Developer Guide* .", "EnableExecuteCommand": "Determines whether the execute command functionality is enabled for the service. If `true` , the execute command functionality is enabled for all containers in tasks as part of the service.", "HealthCheckGracePeriodSeconds": "The period of time, in seconds, that the Amazon ECS service scheduler ignores unhealthy Elastic Load Balancing target health checks after a task has first started. This is only used when your service is configured to use a load balancer. If your service has a load balancer defined and you don't specify a health check grace period value, the default value of `0` is used.\n\nIf you do not use an Elastic Load Balancing, we recomend that you use the `startPeriod` in the task definition healtch check parameters. For more information, see [Health check](https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_HealthCheck.html) .\n\nIf your service's tasks take a while to start and respond to Elastic Load Balancing health checks, you can specify a health check grace period of up to 2,147,483,647 seconds (about 69 years). During that time, the Amazon ECS service scheduler ignores health check status. This grace period can prevent the service scheduler from marking tasks as unhealthy and stopping them before they have time to come up.", "LaunchType": "The launch type on which to run your service. For more information, see [Amazon ECS Launch Types](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/launch_types.html) in the *Amazon Elastic Container Service Developer Guide* .", @@ -14027,8 +14029,8 @@ "attributes": {}, "description": "> The deployment circuit breaker can only be used for services using the rolling update ( `ECS` ) deployment type. \n\nThe `DeploymentCircuitBreaker` property determines whether a service deployment will fail if the service can't reach a steady state. If deployment circuit breaker is enabled, a service deployment will transition to a failed state and stop launching new tasks. If rollback is enabled, when a service deployment fails, the service is rolled back to the last deployment that completed successfully.", "properties": { - "Enable": "Determines whether to enable the deployment circuit breaker logic for the service.", - "Rollback": "Determines whether to enable Amazon ECS to roll back the service if a service deployment fails. If rollback is enabled, when a service deployment fails, the service is rolled back to the last deployment that completed successfully." + "Enable": "Determines whether to use the deployment circuit breaker logic for the service.", + "Rollback": "Determines whether to configure Amazon ECS to roll back the service if a service deployment fails. If rollback is enabled, when a service deployment fails, the service is rolled back to the last deployment that completed successfully." } }, "AWS::ECS::Service.DeploymentConfiguration": { @@ -14129,7 +14131,7 @@ "properties": { "Command": "The command that's passed to the container. This parameter maps to `Cmd` in the [Create a container](https://docs.aws.amazon.com/https://docs.docker.com/engine/api/v1.35/#operation/ContainerCreate) section of the [Docker Remote API](https://docs.aws.amazon.com/https://docs.docker.com/engine/api/v1.35/) and the `COMMAND` parameter to [docker run](https://docs.aws.amazon.com/https://docs.docker.com/engine/reference/run/#security-configuration) . For more information, see [https://docs.docker.com/engine/reference/builder/#cmd](https://docs.aws.amazon.com/https://docs.docker.com/engine/reference/builder/#cmd) . If there are multiple arguments, each argument is a separated string in the array.", "Cpu": "The number of `cpu` units reserved for the container. This parameter maps to `CpuShares` in the [Create a container](https://docs.aws.amazon.com/https://docs.docker.com/engine/api/v1.35/#operation/ContainerCreate) section of the [Docker Remote API](https://docs.aws.amazon.com/https://docs.docker.com/engine/api/v1.35/) and the `--cpu-shares` option to [docker run](https://docs.aws.amazon.com/https://docs.docker.com/engine/reference/run/#security-configuration) .\n\nThis field is optional for tasks using the Fargate launch type, and the only requirement is that the total amount of CPU reserved for all containers within a task be lower than the task-level `cpu` value.\n\n> You can determine the number of CPU units that are available per EC2 instance type by multiplying the vCPUs listed for that instance type on the [Amazon EC2 Instances](https://docs.aws.amazon.com/ec2/instance-types/) detail page by 1,024. \n\nLinux containers share unallocated CPU units with other containers on the container instance with the same ratio as their allocated amount. For example, if you run a single-container task on a single-core instance type with 512 CPU units specified for that container, and that's the only task running on the container instance, that container could use the full 1,024 CPU unit share at any given time. However, if you launched another copy of the same task on that container instance, each task is guaranteed a minimum of 512 CPU units when needed. Moreover, each container could float to higher CPU usage if the other container was not using it. If both tasks were 100% active all of the time, they would be limited to 512 CPU units.\n\nOn Linux container instances, the Docker daemon on the container instance uses the CPU value to calculate the relative CPU share ratios for running containers. For more information, see [CPU share constraint](https://docs.aws.amazon.com/https://docs.docker.com/engine/reference/run/#cpu-share-constraint) in the Docker documentation. The minimum valid CPU share value that the Linux kernel allows is 2. However, the CPU parameter isn't required, and you can use CPU values below 2 in your container definitions. For CPU values below 2 (including null), the behavior varies based on your Amazon ECS container agent version:\n\n- *Agent versions less than or equal to 1.1.0:* Null and zero CPU values are passed to Docker as 0, which Docker then converts to 1,024 CPU shares. CPU values of 1 are passed to Docker as 1, which the Linux kernel converts to two CPU shares.\n- *Agent versions greater than or equal to 1.2.0:* Null, zero, and CPU values of 1 are passed to Docker as 2.\n\nOn Windows container instances, the CPU limit is enforced as an absolute limit, or a quota. Windows containers only have access to the specified amount of CPU that's described in the task definition. A null or zero CPU value is passed to Docker as `0` , which Windows interprets as 1% of one CPU.", - "DependsOn": "The dependencies defined for container startup and shutdown. A container can contain multiple dependencies. When a dependency is defined for container startup, for container shutdown it is reversed.\n\nFor tasks using the EC2 launch type, the container instances require at least version 1.26.0 of the container agent to enable container dependencies. However, we recommend using the latest container agent version. For information about checking your agent version and updating to the latest version, see [Updating the Amazon ECS Container Agent](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-agent-update.html) in the *Amazon Elastic Container Service Developer Guide* . If you're using an Amazon ECS-optimized Linux AMI, your instance needs at least version 1.26.0-1 of the `ecs-init` package. If your container instances are launched from version `20190301` or later, then they contain the required versions of the container agent and `ecs-init` . For more information, see [Amazon ECS-optimized Linux AMI](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-optimized_AMI.html) in the *Amazon Elastic Container Service Developer Guide* .\n\nFor tasks using the Fargate launch type, the task or service requires the following platforms:\n\n- Linux platform version `1.3.0` or later.\n- Windows platform version `1.0.0` or later.", + "DependsOn": "The dependencies defined for container startup and shutdown. A container can contain multiple dependencies. When a dependency is defined for container startup, for container shutdown it is reversed.\n\nFor tasks using the EC2 launch type, the container instances require at least version 1.26.0 of the container agent to turn on container dependencies. However, we recommend using the latest container agent version. For information about checking your agent version and updating to the latest version, see [Updating the Amazon ECS Container Agent](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-agent-update.html) in the *Amazon Elastic Container Service Developer Guide* . If you're using an Amazon ECS-optimized Linux AMI, your instance needs at least version 1.26.0-1 of the `ecs-init` package. If your container instances are launched from version `20190301` or later, then they contain the required versions of the container agent and `ecs-init` . For more information, see [Amazon ECS-optimized Linux AMI](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-optimized_AMI.html) in the *Amazon Elastic Container Service Developer Guide* .\n\nFor tasks using the Fargate launch type, the task or service requires the following platforms:\n\n- Linux platform version `1.3.0` or later.\n- Windows platform version `1.0.0` or later.", "DisableNetworking": "When this parameter is true, networking is disabled within the container. This parameter maps to `NetworkDisabled` in the [Create a container](https://docs.aws.amazon.com/https://docs.docker.com/engine/api/v1.35/#operation/ContainerCreate) section of the [Docker Remote API](https://docs.aws.amazon.com/https://docs.docker.com/engine/api/v1.35/) .\n\n> This parameter is not supported for Windows containers.", "DnsSearchDomains": "A list of DNS search domains that are presented to the container. This parameter maps to `DnsSearch` in the [Create a container](https://docs.aws.amazon.com/https://docs.docker.com/engine/api/v1.35/#operation/ContainerCreate) section of the [Docker Remote API](https://docs.aws.amazon.com/https://docs.docker.com/engine/api/v1.35/) and the `--dns-search` option to [docker run](https://docs.aws.amazon.com/https://docs.docker.com/engine/reference/run/#security-configuration) .\n\n> This parameter is not supported for Windows containers.", "DnsServers": "A list of DNS servers that are presented to the container. This parameter maps to `Dns` in the [Create a container](https://docs.aws.amazon.com/https://docs.docker.com/engine/api/v1.35/#operation/ContainerCreate) section of the [Docker Remote API](https://docs.aws.amazon.com/https://docs.docker.com/engine/api/v1.35/) and the `--dns` option to [docker run](https://docs.aws.amazon.com/https://docs.docker.com/engine/reference/run/#security-configuration) .\n\n> This parameter is not supported for Windows containers.", @@ -14159,8 +14161,8 @@ "RepositoryCredentials": "The private repository authentication credentials to use.", "ResourceRequirements": "The type and amount of a resource to assign to a container. The only supported resource is a GPU.", "Secrets": "The secrets to pass to the container. For more information, see [Specifying Sensitive Data](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/specifying-sensitive-data.html) in the *Amazon Elastic Container Service Developer Guide* .", - "StartTimeout": "Time duration (in seconds) to wait before giving up on resolving dependencies for a container. For example, you specify two containers in a task definition with containerA having a dependency on containerB reaching a `COMPLETE` , `SUCCESS` , or `HEALTHY` status. If a `startTimeout` value is specified for containerB and it doesn't reach the desired status within that time then containerA gives up and not start. This results in the task transitioning to a `STOPPED` state.\n\n> When the `ECS_CONTAINER_START_TIMEOUT` container agent configuration variable is used, it's enforced independently from this start timeout value. \n\nFor tasks using the Fargate launch type, the task or service requires the following platforms:\n\n- Linux platform version `1.3.0` or later.\n- Windows platform version `1.0.0` or later.\n\nFor tasks using the EC2 launch type, your container instances require at least version `1.26.0` of the container agent to enable a container start timeout value. However, we recommend using the latest container agent version. For information about checking your agent version and updating to the latest version, see [Updating the Amazon ECS Container Agent](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-agent-update.html) in the *Amazon Elastic Container Service Developer Guide* . If you're using an Amazon ECS-optimized Linux AMI, your instance needs at least version `1.26.0-1` of the `ecs-init` package. If your container instances are launched from version `20190301` or later, then they contain the required versions of the container agent and `ecs-init` . For more information, see [Amazon ECS-optimized Linux AMI](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-optimized_AMI.html) in the *Amazon Elastic Container Service Developer Guide* .", - "StopTimeout": "Time duration (in seconds) to wait before the container is forcefully killed if it doesn't exit normally on its own.\n\nFor tasks using the Fargate launch type, the task or service requires the following platforms:\n\n- Linux platform version `1.3.0` or later.\n- Windows platform version `1.0.0` or later.\n\nThe max stop timeout value is 120 seconds and if the parameter is not specified, the default value of 30 seconds is used.\n\nFor tasks that use the EC2 launch type, if the `stopTimeout` parameter isn't specified, the value set for the Amazon ECS container agent configuration variable `ECS_CONTAINER_STOP_TIMEOUT` is used. If neither the `stopTimeout` parameter or the `ECS_CONTAINER_STOP_TIMEOUT` agent configuration variable are set, then the default values of 30 seconds for Linux containers and 30 seconds on Windows containers are used. Your container instances require at least version 1.26.0 of the container agent to enable a container stop timeout value. However, we recommend using the latest container agent version. For information about checking your agent version and updating to the latest version, see [Updating the Amazon ECS Container Agent](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-agent-update.html) in the *Amazon Elastic Container Service Developer Guide* . If you're using an Amazon ECS-optimized Linux AMI, your instance needs at least version 1.26.0-1 of the `ecs-init` package. If your container instances are launched from version `20190301` or later, then they contain the required versions of the container agent and `ecs-init` . For more information, see [Amazon ECS-optimized Linux AMI](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-optimized_AMI.html) in the *Amazon Elastic Container Service Developer Guide* .", + "StartTimeout": "Time duration (in seconds) to wait before giving up on resolving dependencies for a container. For example, you specify two containers in a task definition with containerA having a dependency on containerB reaching a `COMPLETE` , `SUCCESS` , or `HEALTHY` status. If a `startTimeout` value is specified for containerB and it doesn't reach the desired status within that time then containerA gives up and not start. This results in the task transitioning to a `STOPPED` state.\n\n> When the `ECS_CONTAINER_START_TIMEOUT` container agent configuration variable is used, it's enforced independently from this start timeout value. \n\nFor tasks using the Fargate launch type, the task or service requires the following platforms:\n\n- Linux platform version `1.3.0` or later.\n- Windows platform version `1.0.0` or later.\n\nFor tasks using the EC2 launch type, your container instances require at least version `1.26.0` of the container agent to use a container start timeout value. However, we recommend using the latest container agent version. For information about checking your agent version and updating to the latest version, see [Updating the Amazon ECS Container Agent](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-agent-update.html) in the *Amazon Elastic Container Service Developer Guide* . If you're using an Amazon ECS-optimized Linux AMI, your instance needs at least version `1.26.0-1` of the `ecs-init` package. If your container instances are launched from version `20190301` or later, then they contain the required versions of the container agent and `ecs-init` . For more information, see [Amazon ECS-optimized Linux AMI](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-optimized_AMI.html) in the *Amazon Elastic Container Service Developer Guide* .", + "StopTimeout": "Time duration (in seconds) to wait before the container is forcefully killed if it doesn't exit normally on its own.\n\nFor tasks using the Fargate launch type, the task or service requires the following platforms:\n\n- Linux platform version `1.3.0` or later.\n- Windows platform version `1.0.0` or later.\n\nThe max stop timeout value is 120 seconds and if the parameter is not specified, the default value of 30 seconds is used.\n\nFor tasks that use the EC2 launch type, if the `stopTimeout` parameter isn't specified, the value set for the Amazon ECS container agent configuration variable `ECS_CONTAINER_STOP_TIMEOUT` is used. If neither the `stopTimeout` parameter or the `ECS_CONTAINER_STOP_TIMEOUT` agent configuration variable are set, then the default values of 30 seconds for Linux containers and 30 seconds on Windows containers are used. Your container instances require at least version 1.26.0 of the container agent to use a container stop timeout value. However, we recommend using the latest container agent version. For information about checking your agent version and updating to the latest version, see [Updating the Amazon ECS Container Agent](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-agent-update.html) in the *Amazon Elastic Container Service Developer Guide* . If you're using an Amazon ECS-optimized Linux AMI, your instance needs at least version 1.26.0-1 of the `ecs-init` package. If your container instances are launched from version `20190301` or later, then they contain the required versions of the container agent and `ecs-init` . For more information, see [Amazon ECS-optimized Linux AMI](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-optimized_AMI.html) in the *Amazon Elastic Container Service Developer Guide* .", "SystemControls": "A list of namespaced kernel parameters to set in the container. This parameter maps to `Sysctls` in the [Create a container](https://docs.aws.amazon.com/https://docs.docker.com/engine/api/v1.35/#operation/ContainerCreate) section of the [Docker Remote API](https://docs.aws.amazon.com/https://docs.docker.com/engine/api/v1.35/) and the `--sysctl` option to [docker run](https://docs.aws.amazon.com/https://docs.docker.com/engine/reference/run/#security-configuration) .\n\n> We don't recommended that you specify network-related `systemControls` parameters for multiple containers in a single task that also uses either the `awsvpc` or `host` network modes. For tasks that use the `awsvpc` network mode, the container that's started last determines which `systemControls` parameters take effect. For tasks that use the `host` network mode, it changes the container instance's namespaced kernel parameters as well as the containers.", "Ulimits": "A list of `ulimits` to set in the container. This parameter maps to `Ulimits` in the [Create a container](https://docs.aws.amazon.com/https://docs.docker.com/engine/api/v1.35/#operation/ContainerCreate) section of the [Docker Remote API](https://docs.aws.amazon.com/https://docs.docker.com/engine/api/v1.35/) and the `--ulimit` option to [docker run](https://docs.aws.amazon.com/https://docs.docker.com/engine/reference/run/) . Valid naming values are displayed in the [Ulimit](https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_Ulimit.html) data type. This parameter requires version 1.18 of the Docker Remote API or greater on your container instance. To check the Docker Remote API version on your container instance, log in to your container instance and run the following command: `sudo docker version --format '{{.Server.APIVersion}}'`\n\n> This parameter is not supported for Windows containers.", "User": "The user to use inside the container. This parameter maps to `User` in the [Create a container](https://docs.aws.amazon.com/https://docs.docker.com/engine/api/v1.35/#operation/ContainerCreate) section of the [Docker Remote API](https://docs.aws.amazon.com/https://docs.docker.com/engine/api/v1.35/) and the `--user` option to [docker run](https://docs.aws.amazon.com/https://docs.docker.com/engine/reference/run/#security-configuration) .\n\n> When running tasks using the `host` network mode, don't run containers using the root user (UID 0). We recommend using a non-root user for better security. \n\nYou can specify the `user` using the following formats. If specifying a UID or GID, you must specify it as a positive integer.\n\n- `user`\n- `user:group`\n- `uid`\n- `uid:gid`\n- `user:gid`\n- `uid:group`\n\n> This parameter is not supported for Windows containers.", @@ -14203,7 +14205,7 @@ "AuthorizationConfig": "The authorization configuration details for the Amazon EFS file system.", "FilesystemId": "The Amazon EFS file system ID to use.", "RootDirectory": "The directory within the Amazon EFS file system to mount as the root directory inside the host. If this parameter is omitted, the root of the Amazon EFS volume will be used. Specifying `/` will have the same effect as omitting this parameter.\n\n> If an EFS access point is specified in the `authorizationConfig` , the root directory parameter must either be omitted or set to `/` which will enforce the path set on the EFS access point.", - "TransitEncryption": "Determines whether to enable encryption for Amazon EFS data in transit between the Amazon ECS host and the Amazon EFS server. Transit encryption must be enabled if Amazon EFS IAM authorization is used. If this parameter is omitted, the default value of `DISABLED` is used. For more information, see [Encrypting Data in Transit](https://docs.aws.amazon.com/efs/latest/ug/encryption-in-transit.html) in the *Amazon Elastic File System User Guide* .", + "TransitEncryption": "Determines whether to use encryption for Amazon EFS data in transit between the Amazon ECS host and the Amazon EFS server. Transit encryption must be enabled if Amazon EFS IAM authorization is used. If this parameter is omitted, the default value of `DISABLED` is used. For more information, see [Encrypting Data in Transit](https://docs.aws.amazon.com/efs/latest/ug/encryption-in-transit.html) in the *Amazon Elastic File System User Guide* .", "TransitEncryptionPort": "The port to use when sending encrypted data between the Amazon ECS host and the Amazon EFS server. If you do not specify a transit encryption port, it will use the port selection strategy that the Amazon EFS mount helper uses. For more information, see [EFS Mount Helper](https://docs.aws.amazon.com/efs/latest/ug/efs-mount-helper.html) in the *Amazon Elastic File System User Guide* ." } }, @@ -14467,7 +14469,7 @@ }, "AWS::ECS::TaskSet.ServiceRegistry": { "attributes": {}, - "description": "The details for the service registry.", + "description": "The details for the service registry.\n\nEach service may be associated with one service registry. Multiple service registries for each service are not supported.\n\nWhen you add, update, or remove the service registries configuration, Amazon ECS starts a new deployment. New tasks are registered and deregistered to the updated service registry configuration.", "properties": { "ContainerName": "The container name value to be used for your service discovery service. It's already specified in the task definition. If the task definition that your service task specifies uses the `bridge` or `host` network mode, you must specify a `containerName` and `containerPort` combination from the task definition. If the task definition that your service task specifies uses the `awsvpc` network mode and a type SRV DNS record is used, you must specify either a `containerName` and `containerPort` combination or a `port` value. However, you can't specify both.", "ContainerPort": "The port value to be used for your service discovery service. It's already specified in the task definition. If the task definition your service task specifies uses the `bridge` or `host` network mode, you must specify a `containerName` and `containerPort` combination from the task definition. If the task definition your service task specifies uses the `awsvpc` network mode and a type SRV DNS record is used, you must specify either a `containerName` and `containerPort` combination or a `port` value. However, you can't specify both.", @@ -14585,7 +14587,7 @@ "AWS::EKS::Addon": { "attributes": { "Arn": "The ARN of the add-on, such as `arn:aws:eks:us-west-2:111122223333:addon/1-19/vpc-cni/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx` .", - "Ref": "`Ref` returns the resource name. For example:\n\n`{ \"Ref\": \"vpc-cni\" }`\n\nFor the add-on `vpc-cni` , `Ref` returns the name of the add-on. For example, `|` ." + "Ref": "`Ref` returns the resource name. For example:\n\n`{ \"Ref\": \"vpc-cni\" }`\n\nFor the add-on `vpc-cni` , `Ref` returns the name of the add-on. For example, `cluster-name|vpc-cni` ." }, "description": "Creates an Amazon EKS add-on.\n\nAmazon EKS add-ons help to automate the provisioning and lifecycle management of common operational software for Amazon EKS clusters. Amazon EKS add-ons require clusters running version 1.18 or later because Amazon EKS add-ons rely on the Server-side Apply Kubernetes feature, which is only available in Kubernetes 1.18 and later. For more information, see [Amazon EKS add-ons](https://docs.aws.amazon.com/eks/latest/userguide/eks-add-ons.html) in the *Amazon EKS User Guide* .", "properties": { @@ -14605,7 +14607,7 @@ "EncryptionConfigKeyArn": "Amazon Resource Name (ARN) or alias of the customer master key (CMK).", "Endpoint": "The endpoint for your Kubernetes API server, such as `https://5E1D0CEXAMPLEA591B746AFC5AB30262.yl4.us-west-2.eks.amazonaws.com` .", "KubernetesNetworkConfig.ServiceIpv6Cidr": "The CIDR block that Kubernetes Service IP addresses are assigned from if you created a 1.21 or later cluster with version 1.10.1 or later of the Amazon VPC CNI add-on and specified `ipv6` for *ipFamily* when you created the cluster. Kubernetes assigns Service addresses from the unique local address range ( `fc00::/7` ) because you can't specify a custom IPv6 CIDR block when you create the cluster.", - "OpenIdConnectIssuerUrl": "The issuer URL for the OIDC identity provider of the cluster, such as `https://oidc.eks.us-west-2.amazonaws.com/id/EXAMPLED539D4633E53DE1B716D3041E` . If you need to remove `https://` from this output value, you can include the following code in your template.\n\n`!Select [1, !Split [\"//\", !GetAtt EKSCluster.OpenIdConnectIssuerUrl]]`", + "OpenIdConnectIssuerUrl": "", "Ref": "`Ref` returns the resource name. For example:\n\n`{ \"Ref\": \"myCluster\" }`\n\nFor the Amazon EKS cluster `myCluster` , `Ref` returns the name of the cluster." }, "description": "Creates an Amazon EKS control plane.\n\nThe Amazon EKS control plane consists of control plane instances that run the Kubernetes software, such as `etcd` and the API server. The control plane runs in an account managed by AWS , and the Kubernetes API is exposed by the Amazon EKS API server endpoint. Each Amazon EKS cluster control plane is single tenant and unique. It runs on its own set of Amazon EC2 instances.\n\nThe cluster control plane is provisioned across multiple Availability Zones and fronted by an Elastic Load Balancing Network Load Balancer. Amazon EKS also provisions elastic network interfaces in your VPC subnets to provide connectivity from the control plane instances to the nodes (for example, to support `kubectl exec` , `logs` , and `proxy` data flows).\n\nAmazon EKS nodes run in your AWS account and connect to your cluster's control plane over the Kubernetes API server endpoint and a certificate file that is created for your cluster.\n\nIn most cases, it takes several minutes to create a cluster. After you create an Amazon EKS cluster, you must configure your Kubernetes tooling to communicate with the API server and launch nodes into your cluster. For more information, see [Managing Cluster Authentication](https://docs.aws.amazon.com/eks/latest/userguide/managing-auth.html) and [Launching Amazon EKS nodes](https://docs.aws.amazon.com/eks/latest/userguide/launch-workers.html) in the *Amazon EKS User Guide* .", @@ -14672,7 +14674,7 @@ "AWS::EKS::FargateProfile": { "attributes": { "Arn": "The ARN of the cluster, such as `arn:aws:eks:us-west-2:666666666666:fargateprofile/myCluster/myFargateProfile/1cb1a11a-1dc1-1d11-cf11-1111f11fa111` .", - "Ref": "`Ref` returns the resource name. For example:\n\n`{ \"Ref\": \"myFargateProfile\" }`\n\nFor the Fargate profile `myFargateProfile` , Ref returns the physical resource ID of the Fargate profile. For example, `/` ." + "Ref": "`Ref` returns the resource name. For example:\n\n`{ \"Ref\": \"myFargateProfile\" }`\n\nFor the Fargate profile `myFargateProfile` , Ref returns the physical resource ID of the Fargate profile. For example, `/` ." }, "description": "Creates an AWS Fargate profile for your Amazon EKS cluster. You must have at least one Fargate profile in a cluster to be able to run pods on Fargate.\n\nThe Fargate profile allows an administrator to declare which pods run on Fargate and specify which pods run on which Fargate profile. This declaration is done through the profile\u2019s selectors. Each profile can have up to five selectors that contain a namespace and labels. A namespace is required for every selector. The label field consists of multiple optional key-value pairs. Pods that match the selectors are scheduled on Fargate. If a to-be-scheduled pod matches any of the selectors in the Fargate profile, then that pod is run on Fargate.\n\nWhen you create a Fargate profile, you must specify a pod execution role to use with the pods that are scheduled with the profile. This role is added to the cluster's Kubernetes [Role Based Access Control](https://docs.aws.amazon.com/https://kubernetes.io/docs/admin/authorization/rbac/) (RBAC) for authorization so that the `kubelet` that is running on the Fargate infrastructure can register with your Amazon EKS cluster so that it can appear in your cluster as a node. The pod execution role also provides IAM permissions to the Fargate infrastructure to allow read access to Amazon ECR image repositories. For more information, see [Pod Execution Role](https://docs.aws.amazon.com/eks/latest/userguide/pod-execution-role.html) in the *Amazon EKS User Guide* .\n\nFargate profiles are immutable. However, you can create a new updated profile to replace an existing profile and then delete the original after the updated profile has finished creating.\n\nIf any Fargate profiles in a cluster are in the `DELETING` status, you must wait for that Fargate profile to finish deleting before you can create any other profiles in that cluster.\n\nFor more information, see [AWS Fargate Profile](https://docs.aws.amazon.com/eks/latest/userguide/fargate-profile.html) in the *Amazon EKS User Guide* .", "properties": { @@ -14700,13 +14702,48 @@ "Namespace": "The Kubernetes namespace that the selector should match." } }, + "AWS::EKS::IdentityProviderConfig": { + "attributes": { + "IdentityProviderConfigArn": "The Amazon Resource Name (ARN) associated with the identity provider config.", + "Ref": "`Ref` returns the resource name. For example:\n\n`{ \"Ref\": \"myIdentityProviderConfig\" }`\n\nFor the IdentityProviderConfig, Ref returns the physical resource ID of the config. For example, `cluster-name/oidc/identity-provider-config-name` ." + }, + "description": "Associate an identity provider configuration to a cluster.\n\nIf you want to authenticate identities using an identity provider, you can create an identity provider configuration and associate it to your cluster. After configuring authentication to your cluster you can create Kubernetes `roles` and `clusterroles` to assign permissions to the roles, and then bind the roles to the identities using Kubernetes `rolebindings` and `clusterrolebindings` . For more information see [Using RBAC Authorization](https://docs.aws.amazon.com/https://kubernetes.io/docs/reference/access-authn-authz/rbac/) in the Kubernetes documentation.\n\nThis resource isn't available in all AWS Regions .", + "properties": { + "ClusterName": "The cluster that the configuration is associated to.", + "IdentityProviderConfigName": "The name of the configuration.", + "Oidc": "An object that represents an OpenID Connect (OIDC) identity provider configuration.", + "Tags": "The metadata to apply to the provider configuration to assist with categorization and organization. Each tag consists of a key and an optional value. You define both.", + "Type": "The type of the identity provider configuration. The only type available is `oidc` ." + } + }, + "AWS::EKS::IdentityProviderConfig.OidcIdentityProviderConfig": { + "attributes": {}, + "description": "An object that represents the configuration for an OpenID Connect (OIDC) identity provider.\n\nThis resource isn't available in all AWS Regions .", + "properties": { + "ClientId": "This is also known as *audience* . The ID of the client application that makes authentication requests to the OIDC identity provider.", + "GroupsClaim": "The JSON web token (JWT) claim that the provider uses to return your groups.", + "GroupsPrefix": "The prefix that is prepended to group claims to prevent clashes with existing names (such as `system:` groups). For example, the value `oidc:` creates group names like `oidc:engineering` and `oidc:infra` . The prefix can't contain `system:`", + "IssuerUrl": "The URL of the OIDC identity provider that allows the API server to discover public signing keys for verifying tokens.", + "RequiredClaims": "The key-value pairs that describe required claims in the identity token. If set, each claim is verified to be present in the token with a matching value.", + "UsernameClaim": "The JSON Web token (JWT) claim that is used as the username.", + "UsernamePrefix": "The prefix that is prepended to username claims to prevent clashes with existing names. The prefix can't contain `system:`" + } + }, + "AWS::EKS::IdentityProviderConfig.RequiredClaim": { + "attributes": {}, + "description": "A key-value pair that describes a required claim in the identity token. If set, each claim is verified to be present in the token with a matching value.\n\nThis resource isn't available in all AWS Regions .", + "properties": { + "Key": "The key to match from the token.", + "Value": "The value for the key from the token." + } + }, "AWS::EKS::Nodegroup": { "attributes": { "Arn": "The Amazon Resource Name (ARN) associated with the managed node group.", "ClusterName": "The name of the cluster that the managed node group resides in.", "Id": "", "NodegroupName": "The name associated with an Amazon EKS managed node group.", - "Ref": "`Ref` returns the resource name. For example:\n\n`{ \"Ref\": \"myNodegroup\" }`\n\nFor the Amazon EKS node group `myNodegroup` , Ref returns the physical resource ID of the node group. For example, `/` ." + "Ref": "`Ref` returns the resource name. For example:\n\n`{ \"Ref\": \"myNodegroup\" }`\n\nFor the Amazon EKS node group `myNodegroup` , Ref returns the physical resource ID of the node group. For example, `cluster-name/nodegroup_name` ." }, "description": "Creates a managed node group for an Amazon EKS cluster. You can only create a node group for your cluster that is equal to the current Kubernetes version for the cluster. All node groups are created with the latest AMI release version for the respective minor Kubernetes version of the cluster, unless you deploy a custom AMI using a launch template. For more information about using launch templates, see [Launch template support](https://docs.aws.amazon.com/eks/latest/userguide/launch-templates.html) .\n\nAn Amazon EKS managed node group is an Amazon EC2 Auto Scaling group and associated Amazon EC2 instances that are managed by AWS for an Amazon EKS cluster. Each node group uses a version of the Amazon EKS optimized Amazon Linux 2 AMI. For more information, see [Managed Node Groups](https://docs.aws.amazon.com/eks/latest/userguide/managed-node-groups.html) in the *Amazon EKS User Guide* .", "properties": { @@ -15551,7 +15588,7 @@ "description": "The `AWS::ElastiCache::ReplicationGroup` resource creates an Amazon ElastiCache Redis replication group. A Redis (cluster mode disabled) replication group is a collection of cache clusters, where one of the clusters is a primary read-write cluster and the others are read-only replicas.\n\nA Redis (cluster mode enabled) cluster is comprised of from 1 to 90 shards (API/CLI: node groups). Each shard has a primary node and up to 5 read-only replica nodes. The configuration can range from 90 shards and 0 replicas to 15 shards and 5 replicas, which is the maximum number or replicas allowed.\n\nThe node or shard limit can be increased to a maximum of 500 per cluster if the Redis engine version is 5.0.6 or higher. For example, you can choose to configure a 500 node cluster that ranges between 83 shards (one primary and 5 replicas per shard) and 500 shards (single primary and no replicas). Make sure there are enough available IP addresses to accommodate the increase. Common pitfalls include the subnets in the subnet group have too small a CIDR range or the subnets are shared and heavily used by other clusters. For more information, see [Creating a Subnet Group](https://docs.aws.amazon.com/AmazonElastiCache/latest/red-ug/SubnetGroups.Creating.html) . For versions below 5.0.6, the limit is 250 per cluster.\n\nTo request a limit increase, see [Amazon Service Limits](https://docs.aws.amazon.com/general/latest/gr/aws_service_limits.html) and choose the limit type *Nodes per cluster per instance type* .", "properties": { "AtRestEncryptionEnabled": "A flag that enables encryption at rest when set to `true` .\n\nYou cannot modify the value of `AtRestEncryptionEnabled` after the replication group is created. To enable encryption at rest on a replication group you must set `AtRestEncryptionEnabled` to `true` when you create the replication group.\n\n*Required:* Only available when creating a replication group in an Amazon VPC using redis version `3.2.6` or `4.x` onward.\n\nDefault: `false`", - "AuthToken": "*Reserved parameter.* The password used to access a password protected server.\n\n`AuthToken` can be specified only on replication groups where `TransitEncryptionEnabled` is `true` . For more information, see [Authenticating Users with the Redis AUTH Command](https://docs.aws.amazon.com/AmazonElastiCache/latest/red-ug/auth.html) .\n\n> For HIPAA compliance, you must specify `TransitEncryptionEnabled` as `true` , an `AuthToken` , and a `CacheSubnetGroup` . \n\nPassword constraints:\n\n- Must be only printable ASCII characters.\n- Must be at least 16 characters and no more than 128 characters in length.\n- Cannot contain any of the following characters: '/', '\"', or '@'.\n\nFor more information, see [AUTH password](https://docs.aws.amazon.com/http://redis.io/commands/AUTH) at http://redis.io/commands/AUTH.", + "AuthToken": "*Reserved parameter.* The password used to access a password protected server.\n\n`AuthToken` can be specified only on replication groups where `TransitEncryptionEnabled` is `true` . For more information, see [Authenticating Users with the Redis AUTH Command](https://docs.aws.amazon.com/AmazonElastiCache/latest/red-ug/auth.html) .\n\n> For HIPAA compliance, you must specify `TransitEncryptionEnabled` as `true` , an `AuthToken` , and a `CacheSubnetGroup` . \n\nPassword constraints:\n\n- Must be only printable ASCII characters.\n- Must be at least 16 characters and no more than 128 characters in length.\n- Nonalphanumeric characters are restricted to (!, &, #, $, ^, <, >, -, ).\n\nFor more information, see [AUTH password](https://docs.aws.amazon.com/http://redis.io/commands/AUTH) at http://redis.io/commands/AUTH.", "AutoMinorVersionUpgrade": "If you are running Redis engine version 6.0 or later, set this parameter to yes if you want to opt-in to the next minor version upgrade campaign. This parameter is disabled for previous versions.", "AutomaticFailoverEnabled": "Specifies whether a read-only replica is automatically promoted to read/write primary if the existing primary fails.\n\n`AutomaticFailoverEnabled` must be enabled for Redis (cluster mode enabled) replication groups.\n\nDefault: false", "CacheNodeType": "The compute and memory capacity of the nodes in the node group (shard).\n\nThe following node types are supported by ElastiCache. Generally speaking, the current generation types provide more memory and computational power at lower cost when compared to their equivalent previous generation counterparts.\n\n- General purpose:\n\n- Current generation:\n\n*M6g node types:* `cache.m6g.large` , `cache.m6g.xlarge` , `cache.m6g.2xlarge` , `cache.m6g.4xlarge` , `cache.m6g.12xlarge` , `cache.m6g.24xlarge`\n\n*M5 node types:* `cache.m5.large` , `cache.m5.xlarge` , `cache.m5.2xlarge` , `cache.m5.4xlarge` , `cache.m5.12xlarge` , `cache.m5.24xlarge`\n\n*M4 node types:* `cache.m4.large` , `cache.m4.xlarge` , `cache.m4.2xlarge` , `cache.m4.4xlarge` , `cache.m4.10xlarge`\n\n*T4g node types:* `cache.t4g.micro` , `cache.t4g.small` , `cache.t4g.medium`\n\n*T3 node types:* `cache.t3.micro` , `cache.t3.small` , `cache.t3.medium`\n\n*T2 node types:* `cache.t2.micro` , `cache.t2.small` , `cache.t2.medium`\n- Previous generation: (not recommended)\n\n*T1 node types:* `cache.t1.micro`\n\n*M1 node types:* `cache.m1.small` , `cache.m1.medium` , `cache.m1.large` , `cache.m1.xlarge`\n\n*M3 node types:* `cache.m3.medium` , `cache.m3.large` , `cache.m3.xlarge` , `cache.m3.2xlarge`\n- Compute optimized:\n\n- Previous generation: (not recommended)\n\n*C1 node types:* `cache.c1.xlarge`\n- Memory optimized:\n\n- Current generation:\n\n*R6gd node types:* `cache.r6gd.xlarge` , `cache.r6gd.2xlarge` , `cache.r6gd.4xlarge` , `cache.r6gd.8xlarge` , `cache.r6gd.12xlarge` , `cache.r6gd.16xlarge`\n\n> The `r6gd` family is available in the following regions: `us-east-2` , `us-east-1` , `us-west-2` , `us-west-1` , `eu-west-1` , `eu-central-1` , `ap-northeast-1` , `ap-southeast-1` , `ap-southeast-2` . \n\n*R6g node types:* `cache.r6g.large` , `cache.r6g.xlarge` , `cache.r6g.2xlarge` , `cache.r6g.4xlarge` , `cache.r6g.12xlarge` , `cache.r6g.24xlarge`\n\n*R5 node types:* `cache.r5.large` , `cache.r5.xlarge` , `cache.r5.2xlarge` , `cache.r5.4xlarge` , `cache.r5.12xlarge` , `cache.r5.24xlarge`\n\n*R4 node types:* `cache.r4.large` , `cache.r4.xlarge` , `cache.r4.2xlarge` , `cache.r4.4xlarge` , `cache.r4.8xlarge` , `cache.r4.16xlarge`\n- Previous generation: (not recommended)\n\n*M2 node types:* `cache.m2.xlarge` , `cache.m2.2xlarge` , `cache.m2.4xlarge`\n\n*R3 node types:* `cache.r3.large` , `cache.r3.xlarge` , `cache.r3.2xlarge` , `cache.r3.4xlarge` , `cache.r3.8xlarge`\n\nFor region availability, see [Supported Node Types by Amazon Region](https://docs.aws.amazon.com/AmazonElastiCache/latest/red-ug/CacheNodes.SupportedTypes.html#CacheNodes.SupportedTypesByRegion)", @@ -17221,7 +17258,7 @@ "KmsKeyId": "The ID of the AWS Key Management Service ( AWS KMS ) key used to encrypt the file system's data for Amazon FSx for Windows File Server file systems, Amazon FSx for NetApp ONTAP file systems, and `PERSISTENT` Amazon FSx for Lustre file systems at rest. If this ID isn't specified, the Amazon FSx-managed key for your account is used. The scratch Amazon FSx for Lustre file systems are always encrypted at rest using the Amazon FSx-managed key for your account. For more information, see [Encrypt](https://docs.aws.amazon.com//kms/latest/APIReference/API_Encrypt.html) in the *AWS Key Management Service API Reference* .", "LustreConfiguration": "The Lustre configuration for the file system being created.\n\n> The following parameters are not supported for file systems with the `Persistent_2` deployment type. Instead, use `CreateDataRepositoryAssociation` to create a data repository association to link your Lustre file system to a data repository.\n> \n> - `AutoImportPolicy`\n> - `ExportPath`\n> - `ImportedChunkSize`\n> - `ImportPath`", "OntapConfiguration": "The ONTAP configuration properties of the FSx for ONTAP file system that you are creating.", - "OpenZFSConfiguration": "The OpenZFS configuration properties for the file system that you are creating.", + "OpenZFSConfiguration": "The Amazon FSx for OpenZFS configuration properties for the file system that you are creating.", "SecurityGroupIds": "A list of IDs specifying the security groups to apply to all network interfaces created for file system access. This list isn't returned in later requests to describe the file system.", "StorageCapacity": "Sets the storage capacity of the file system that you're creating. `StorageCapacity` is required if you are creating a new file system. Do not include `StorageCapacity` if you are creating a file system from a backup.\n\nFor Lustre file systems:", "StorageType": "Sets the storage type for the file system that you're creating. Valid values are `SSD` and `HDD` .\n\n- Set to `SSD` to use solid state drive storage. SSD is supported on all Windows, Lustre, ONTAP, and OpenZFS deployment types.\n- Set to `HDD` to use hard disk drive storage. HDD is supported on `SINGLE_AZ_2` and `MULTI_AZ_1` Windows file system deployment types, and on `PERSISTENT` Lustre file system deployment types.\n\nDefault value is `SSD` . For more information, see [Storage type options](https://docs.aws.amazon.com/fsx/latest/WindowsGuide/optimize-fsx-costs.html#storage-type-options) in the *FSx for Windows File Server User Guide* and [Multiple storage options](https://docs.aws.amazon.com/fsx/latest/LustreGuide/what-is.html#storage-options) in the *FSx for Lustre User Guide* .", @@ -17243,8 +17280,8 @@ "attributes": {}, "description": "Specifies who can mount the file system and the options that can be used while mounting the file system.", "properties": { - "Clients": "A value that specifies who can mount the file system. You can provide a wildcard character ( `*` ), an IP address ( `0.0.0.0` ), or a CIDR address ( `192.0.2.0/24` . By default, Amazon FSx uses the wildcard character when specifying the client.", - "Options": "The options to use when mounting the file system. For a list of options that you can use with Network File System (NFS), see the [exports(5) - Linux man page](https://docs.aws.amazon.com/https://linux.die.net/man/5/exports) . When choosing your options, consider the following:\n\n- `crossmount` is used by default. If you don't specify `crossmount` when changing the client configuration, you won't be able to see or access snapshots in your file system's snapshot directory.\n- `sync` is used by default. If you instead specify `async` , the system acknowledges writes before writing to disk. If the system crashes before the writes are finished, you lose the unwritten data." + "Clients": "A value that specifies who can mount the file system. You can provide a wildcard character ( `*` ), an IP address ( `0.0.0.0` ), or a CIDR address ( `192.0.2.0/24` ). By default, Amazon FSx uses the wildcard character when specifying the client.", + "Options": "The options to use when mounting the file system. For a list of options that you can use with Network File System (NFS), see the [exports(5) - Linux man page](https://docs.aws.amazon.com/https://linux.die.net/man/5/exports) . When choosing your options, consider the following:\n\n- `crossmnt` is used by default. If you don't specify `crossmnt` when changing the client configuration, you won't be able to see or access snapshots in your file system's snapshot directory.\n- `sync` is used by default. If you instead specify `async` , the system acknowledges writes before writing to disk. If the system crashes before the writes are finished, you lose the unwritten data." } }, "AWS::FSx::FileSystem.DiskIopsConfiguration": { @@ -17288,7 +17325,7 @@ "DailyAutomaticBackupStartTime": "A recurring daily time, in the format `HH:MM` . `HH` is the zero-padded hour of the day (0-23), and `MM` is the zero-padded minute of the hour. For example, `05:00` specifies 5 AM daily.", "DeploymentType": "Specifies the FSx for ONTAP file system deployment type to use in creating the file system. `MULTI_AZ_1` is the supported ONTAP deployment type.", "DiskIopsConfiguration": "The SSD IOPS configuration for the FSx for ONTAP file system.", - "EndpointIpAddressRange": "Specifies the IP address range in which the endpoints to access your file system will be created. By default, Amazon FSx selects an unused IP address range for you from the 198.19.* range.", + "EndpointIpAddressRange": "Specifies the IP address range in which the endpoints to access your file system will be created. By default, Amazon FSx selects an unused IP address range for you from the 198.19.* range.\n\n> The Endpoint IP address range you select for your file system must exist outside the VPC's CIDR range and must be at least /30 or larger.", "FsxAdminPassword": "The ONTAP administrative password for the `fsxadmin` user with which you administer your file system using the NetApp ONTAP CLI and REST API.", "PreferredSubnetId": "Required when `DeploymentType` is set to `MULTI_AZ_1` . This specifies the subnet in which you want the preferred file server to be located.", "RouteTableIds": "Specifies the virtual private cloud (VPC) route tables in which your file system's endpoints will be created. You should specify all VPC route tables associated with the subnets in which your clients are located. By default, Amazon FSx selects your VPC's default route table.", @@ -17304,7 +17341,7 @@ "CopyTagsToBackups": "A Boolean value indicating whether tags for the file system should be copied to backups. This value defaults to `false` . If it's set to `true` , all tags for the file system are copied to all automatic and user-initiated backups where the user doesn't specify tags. If this value is `true` , and you specify one or more tags, only the specified tags are copied to backups. If you specify one or more tags when creating a user-initiated backup, no tags are copied from the file system, regardless of this value.", "CopyTagsToVolumes": "A Boolean value indicating whether tags for the volume should be copied to snapshots. This value defaults to `false` . If it's set to `true` , all tags for the volume are copied to snapshots where the user doesn't specify tags. If this value is `true` , and you specify one or more tags, only the specified tags are copied to snapshots. If you specify one or more tags when creating the snapshot, no tags are copied from the volume, regardless of this value.", "DailyAutomaticBackupStartTime": "A recurring daily time, in the format `HH:MM` . `HH` is the zero-padded hour of the day (0-23), and `MM` is the zero-padded minute of the hour. For example, `05:00` specifies 5 AM daily.", - "DeploymentType": "Specifies the file system deployment type. Amazon FSx for OpenZFS supports `SINGLE_AZ_1` . `SINGLE_AZ_1` is a file system configured for a single Availability Zone (AZ) of redundancy.", + "DeploymentType": "Specifies the file system deployment type. Amazon FSx for OpenZFS supports `SINGLE_AZ_1` . `SINGLE_AZ_1` deployment type is configured for redundancy within a single Availability Zone.", "DiskIopsConfiguration": "The SSD IOPS (input/output operations per second) configuration for an Amazon FSx for NetApp ONTAP or Amazon FSx for OpenZFS file system. The default is 3 IOPS per GB of storage capacity, but you can provision additional IOPS per GB of storage. The configuration consists of the total number of provisioned SSD IOPS and how the amount was provisioned (by the customer or by the system).", "RootVolumeConfiguration": "The configuration Amazon FSx uses when creating the root value of the Amazon FSx for OpenZFS file system. All volumes are children of the root volume.", "ThroughputCapacity": "Specifies the throughput of an Amazon FSx for OpenZFS file system, measured in megabytes per second (MB/s). Valid values are 64, 128, 256, 512, 1024, 2048, 3072, or 4096 MB/s. You pay for additional throughput capacity that you provision.", @@ -17315,8 +17352,8 @@ "attributes": {}, "description": "The configuration of an Amazon FSx for OpenZFS root volume.", "properties": { - "CopyTagsToSnapshots": "A Boolean value indicating whether tags for the volume should be copied to snapshots. This value defaults to `false` . If it's set to `true` , all tags for the volume are copied to snapshots where the user doesn't specify tags. If this value is `true` and you specify one or more tags, only the specified tags are copied to snapshots. If you specify one or more tags when creating the snapshot, no tags are copied from the volume, regardless of this value.", - "DataCompressionType": "Specifies the method used to compress the data on the volume. Unless the compression type is specified, volumes inherit the `DataCompressionType` value of their parent volume.\n\n- `NONE` - Doesn't compress the data on the volume.\n- `ZSTD` - Compresses the data in the volume using the ZStandard (ZSTD) compression algorithm. This algorithm reduces the amount of space used on your volume and has very little impact on compute resources.", + "CopyTagsToSnapshots": "A Boolean value indicating whether tags for the volume should be copied to snapshots of the volume. This value defaults to `false` . If it's set to `true` , all tags for the volume are copied to snapshots where the user doesn't specify tags. If this value is `true` and you specify one or more tags, only the specified tags are copied to snapshots. If you specify one or more tags when creating the snapshot, no tags are copied from the volume, regardless of this value.", + "DataCompressionType": "Specifies the method used to compress the data on the volume. The compression type is `NONE` by default.\n\n- `NONE` - Doesn't compress the data on the volume. `NONE` is the default.\n- `ZSTD` - Compresses the data in the volume using the Zstandard (ZSTD) compression algorithm. Compared to LZ4, Z-Standard provides a better compression ratio to minimize on-disk storage utilization.\n- `LZ4` - Compresses the data in the volume using the LZ4 compression algorithm. Compared to Z-Standard, LZ4 is less compute-intensive and delivers higher write throughput speeds.", "NfsExports": "The configuration object for mounting a file system.", "ReadOnly": "A Boolean value indicating whether the volume is read-only. Setting this value to `true` can be useful after you have completed changes to a volume and no longer want changes to occur.", "UserAndGroupQuotas": "An object specifying how much storage users or groups can use on the volume." @@ -17416,12 +17453,12 @@ "UUID": "Returns the volume's universally unique identifier (UUID).\n\nExample: `abcd0123-cd45-ef67-11aa-1111aaaa23bc`", "VolumeId": "Returns the volume's ID.\n\nExample: `fsvol-0123456789abcdefa`" }, - "description": "Creates an Amazon FSx for NetApp ONTAP or Amazon FSx for OpenZFS storage volume.", + "description": "Creates an FSx for ONTAP or Amazon FSx for OpenZFS storage volume.", "properties": { "BackupId": "The ID of the source backup. Specifies the backup that you are copying.", "Name": "The name of the volume.", "OntapConfiguration": "The configuration of an Amazon FSx for NetApp ONTAP volume.", - "OpenZFSConfiguration": "Specifies the configuration of the OpenZFS volume that you are creating.", + "OpenZFSConfiguration": "Specifies the configuration of the Amazon FSx for OpenZFS volume that you are creating.", "Options": "To delete the volume's child volumes, snapshots, and clones, use the string `DELETE_CHILD_VOLUMES_AND_SNAPSHOTS` .", "SnapshotId": "A unique ID that represents the snapshot.", "Tags": "An array of key-value pairs to apply to this resource.\n\nFor more information, see [Tag](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-resource-tags.html) .", @@ -17432,8 +17469,8 @@ "attributes": {}, "description": "Specifies who can mount the file system and the options that can be used while mounting the file system.", "properties": { - "Clients": "A value that specifies who can mount the file system. You can provide a wildcard character ( `*` ), an IP address ( `0.0.0.0` ), or a CIDR address ( `192.0.2.0/24` . By default, Amazon FSx uses the wildcard character when specifying the client.", - "Options": "The options to use when mounting the file system. For a list of options that you can use with Network File System (NFS), see the [exports(5) - Linux man page](https://docs.aws.amazon.com/https://linux.die.net/man/5/exports) . When choosing your options, consider the following:\n\n- `crossmount` is used by default. If you don't specify `crossmount` when changing the client configuration, you won't be able to see or access snapshots in your file system's snapshot directory.\n- `sync` is used by default. If you instead specify `async` , the system acknowledges writes before writing to disk. If the system crashes before the writes are finished, you lose the unwritten data." + "Clients": "A value that specifies who can mount the file system. You can provide a wildcard character ( `*` ), an IP address ( `0.0.0.0` ), or a CIDR address ( `192.0.2.0/24` ). By default, Amazon FSx uses the wildcard character when specifying the client.", + "Options": "The options to use when mounting the file system. For a list of options that you can use with Network File System (NFS), see the [exports(5) - Linux man page](https://docs.aws.amazon.com/https://linux.die.net/man/5/exports) . When choosing your options, consider the following:\n\n- `crossmnt` is used by default. If you don't specify `crossmnt` when changing the client configuration, you won't be able to see or access snapshots in your file system's snapshot directory.\n- `sync` is used by default. If you instead specify `async` , the system acknowledges writes before writing to disk. If the system crashes before the writes are finished, you lose the unwritten data." } }, "AWS::FSx::Volume.NfsExports": { @@ -17457,16 +17494,16 @@ }, "AWS::FSx::Volume.OpenZFSConfiguration": { "attributes": {}, - "description": "Specifies the configuration of the OpenZFS volume that you are creating.", + "description": "Specifies the configuration of the Amazon FSx for OpenZFS volume that you are creating.", "properties": { "CopyTagsToSnapshots": "A Boolean value indicating whether tags for the volume should be copied to snapshots. This value defaults to `false` . If it's set to `true` , all tags for the volume are copied to snapshots where the user doesn't specify tags. If this value is `true` , and you specify one or more tags, only the specified tags are copied to snapshots. If you specify one or more tags when creating the snapshot, no tags are copied from the volume, regardless of this value.", - "DataCompressionType": "The method used to compress the data on the volume. Unless a compression type is specified, volumes inherit the `DataCompressionType` value of their parent volume.\n\n- `NONE` - Doesn't compress the data on the volume.\n- `ZSTD` - Compresses the data in the volume using the Zstandard (ZSTD) compression algorithm. This algorithm reduces the amount of space used on your volume and has very little impact on compute resources.", + "DataCompressionType": "Specifies the method used to compress the data on the volume. The compression type is `NONE` by default.\n\n- `NONE` - Doesn't compress the data on the volume. `NONE` is the default.\n- `ZSTD` - Compresses the data in the volume using the Zstandard (ZSTD) compression algorithm. Compared to LZ4, Z-Standard provides a better compression ratio to minimize on-disk storage utilization.\n- `LZ4` - Compresses the data in the volume using the LZ4 compression algorithm. Compared to Z-Standard, LZ4 is less compute-intensive and delivers higher write throughput speeds.", "NfsExports": "The configuration object for mounting a Network File System (NFS) file system.", "OriginSnapshot": "The configuration object that specifies the snapshot to use as the origin of the data for the volume.", - "ParentVolumeId": "The ID of the volume to use as the parent volume.", + "ParentVolumeId": "The ID of the volume to use as the parent volume of the volume that you are creating.", "ReadOnly": "A Boolean value indicating whether the volume is read-only.", - "StorageCapacityQuotaGiB": "The maximum amount of storage in gibibytes (GiB) that the volume can use from its parent. You can specify a quota larger than the storage on the parent volume.", - "StorageCapacityReservationGiB": "The amount of storage in gibibytes (GiB) to reserve from the parent volume. You can't reserve more storage than the parent volume has reserved.", + "StorageCapacityQuotaGiB": "Sets the maximum storage size in gibibytes (GiB) for the volume. You can specify a quota that is larger than the storage on the parent volume. A volume quota limits the amount of storage that the volume can consume to the configured amount, but does not guarantee the space will be available on the parent volume. To guarantee quota space, you must also set `StorageCapacityReservationGiB` . To *not* specify a storage capacity quota, set this to `-1` .\n\nFor more information, see [Volume properties](https://docs.aws.amazon.com/fsx/latest/OpenZFSGuide/managing-volumes.html#volume-properties) in the *Amazon FSx for OpenZFS User Guide* .", + "StorageCapacityReservationGiB": "Specifies the amount of storage in gibibytes (GiB) to reserve from the parent volume. Setting `StorageCapacityReservationGiB` guarantees that the specified amount of storage space on the parent volume will always be available for the volume. You can't reserve more storage than the parent volume has. To *not* specify a storage capacity reservation, set this to `0` or `-1` . For more information, see [Volume properties](https://docs.aws.amazon.com/fsx/latest/OpenZFSGuide/managing-volumes.html#volume-properties) in the *Amazon FSx for OpenZFS User Guide* .", "UserAndGroupQuotas": "An object specifying how much storage users or groups can use on the volume." } }, @@ -17859,10 +17896,10 @@ "attributes": {}, "description": "A range of IP addresses and port settings that allow inbound traffic to connect to server processes on an instance in a fleet. New game sessions are assigned an IP address/port number combination, which must fall into the fleet's allowed ranges. Fleets with custom game builds must have permissions explicitly set. For Realtime Servers fleets, GameLift automatically opens two port ranges, one for TCP messaging and one for UDP.", "properties": { - "FromPort": "A starting value for a range of allowed port numbers.\n\nFor fleets using Linux builds, only port 22, 443, 1026-60000 are valid. For fleets using Windows builds, only port 443, 1026-60000 are valid.", + "FromPort": "A starting value for a range of allowed port numbers.\n\nFor fleets using Windows and Linux builds, only ports 1026-60000 are valid.", "IpRange": "A range of allowed IP addresses. This value must be expressed in CIDR notation. Example: \" `000.000.000.000/[subnet mask]` \" or optionally the shortened version \" `0.0.0.0/[subnet mask]` \".", "Protocol": "The network communication protocol used by the fleet.", - "ToPort": "An ending value for a range of allowed port numbers. Port numbers are end-inclusive. This value must be higher than `FromPort` .\n\nFor fleets using Linux builds, only port 22, 443, 1026-60000 are valid. For fleets using Windows builds, only port 443, 1026-60000 are valid." + "ToPort": "An ending value for a range of allowed port numbers. Port numbers are end-inclusive. This value must be higher than `FromPort` .\n\nFor fleets using Windows and Linux builds, only ports 1026-60000 are valid." } }, "AWS::GameLift::Fleet.LocationCapacity": { @@ -17918,7 +17955,7 @@ "properties": { "AutoScalingPolicy": "Configuration settings to define a scaling policy for the Auto Scaling group that is optimized for game hosting. The scaling policy uses the metric `\"PercentUtilizedGameServers\"` to maintain a buffer of idle game servers that can immediately accommodate new games and players. After the Auto Scaling group is created, update this value directly in the Auto Scaling group using the AWS console or APIs.", "BalancingStrategy": "Indicates how GameLift FleetIQ balances the use of Spot Instances and On-Demand Instances in the game server group. Method options include the following:\n\n- `SPOT_ONLY` - Only Spot Instances are used in the game server group. If Spot Instances are unavailable or not viable for game hosting, the game server group provides no hosting capacity until Spot Instances can again be used. Until then, no new instances are started, and the existing nonviable Spot Instances are terminated (after current gameplay ends) and are not replaced.\n- `SPOT_PREFERRED` - (default value) Spot Instances are used whenever available in the game server group. If Spot Instances are unavailable, the game server group continues to provide hosting capacity by falling back to On-Demand Instances. Existing nonviable Spot Instances are terminated (after current gameplay ends) and are replaced with new On-Demand Instances.\n- `ON_DEMAND_ONLY` - Only On-Demand Instances are used in the game server group. No Spot Instances are used, even when available, while this balancing strategy is in force.", - "DeleteOption": "The type of delete to perform. Options include the following:\n\n- `SAFE_DELETE` \u2013 (default) Terminates the game server group and Amazon EC2 Auto Scaling group only when it has no game servers that are in `UTILIZED` status.\n- `FORCE_DELETE` \u2013 Terminates the game server group, including all active game servers regardless of their utilization status, and the Amazon EC2 Auto Scaling group.\n- `RETAIN` \u2013 Does a safe delete of the game server group but retains the Amazon EC2 Auto Scaling group as is.", + "DeleteOption": "The type of delete to perform. To delete a game server group, specify the `DeleteOption` . Options include the following:\n\n- `SAFE_DELETE` \u2013 (default) Terminates the game server group and Amazon EC2 Auto Scaling group only when it has no game servers that are in `UTILIZED` status.\n- `FORCE_DELETE` \u2013 Terminates the game server group, including all active game servers regardless of their utilization status, and the Amazon EC2 Auto Scaling group.\n- `RETAIN` \u2013 Does a safe delete of the game server group but retains the Amazon EC2 Auto Scaling group as is.", "GameServerGroupName": "A developer-defined identifier for the game server group. The name is unique for each Region in each AWS account.", "GameServerProtectionPolicy": "A flag that indicates whether instances in the game server group are protected from early termination. Unprotected instances that have active game servers running might be terminated during a scale-down event, causing players to be dropped from the game. Protected instances cannot be terminated while there are active game servers running except in the event of a forced game server group deletion (see ). An exception to this is with Spot Instances, which can be terminated by AWS regardless of protection status.", "InstanceDefinitions": "The set of Amazon EC2 instance types that GameLift FleetIQ can use when balancing and automatically scaling instances in the corresponding Auto Scaling group.", @@ -17952,7 +17989,7 @@ "properties": { "LaunchTemplateId": "A unique identifier for an existing Amazon EC2 launch template.", "LaunchTemplateName": "A readable identifier for an existing Amazon EC2 launch template.", - "Version": "The version of the Amazon EC2 launch template to use. If no version is specified, the default version will be used. With Amazon Elastic Compute Cloud, you can specify a default version for a launch template. If none is set, the default is the first version created." + "Version": "The version of the Amazon EC2 launch template to use. If no version is specified, the default version will be used. With Amazon EC2, you can specify a default version for a launch template. If none is set, the default is the first version created." } }, "AWS::GameLift::GameServerGroup.TargetTrackingConfiguration": { @@ -20508,6 +20545,7 @@ "attributes": { "Arn": "Returns the Amazon Resource Name (ARN) of the image. For example, `arn:aws:imagebuilder:us-west-2:123456789012:image/mybasicrecipe/2019.12.03/1` .", "ImageId": "Returns the AMI ID of the Amazon EC2 AMI in the Region in which you are using Image Builder.", + "ImageUri": "", "Name": "Returns the name of the image.", "Ref": "`Ref` returns the resource ARN, such as `arn:aws:imagebuilder:us-west-2:123456789012:image/my-example-image` ." }, @@ -27015,29 +27053,17 @@ }, "AWS::MSK::Configuration": { "attributes": { - "CreationTime": "The time the configuration was created.", - "LatestRevision": "The latest revision of the configuration.", - "Ref": "The ARN of the configuration.", - "State": "The state of the configuration." + "Arn": "The ARN of the configuration.", + "Ref": "The ARN of the configuration." }, "description": "Creates a new MSK configuration.", "properties": { - "Arn": "The Amazon Resource Name (ARN) that uniquely identifies an MSK configuration and all of its revisions.", "Description": "The description of the configuration.", "KafkaVersionsList": "A list of the versions of Apache Kafka with which you can use this MSK configuration. You can use this configuration for an MSK cluster only if the Apache Kafka version specified for the cluster appears in this list.", "Name": "The name of the configuration. Configuration names are strings that match the regex \"^[0-9A-Za-z][0-9A-Za-z-]{0,}$\".", "ServerProperties": "Contents of the server.properties file. When using the API, you must ensure that the contents of the file are base64 encoded. When using the console, the SDK, or the CLI, the contents of server.properties can be in plaintext." } }, - "AWS::MSK::Configuration.ConfigurationRevision": { - "attributes": {}, - "description": "Describes a configuration revision.", - "properties": { - "CreationTime": "The time when the configuration revision was created.", - "Description": "The description of the configuration revision.", - "Revision": "The revision number." - } - }, "AWS::MWAA::Environment": { "attributes": { "Arn": "The ARN for the Amazon MWAA environment.", @@ -30400,7 +30426,7 @@ "ClusterConfig": "`ClusterConfig` is a property of the AWS::OpenSearchService::Domain resource that configures an Amazon OpenSearch Service cluster.", "CognitoOptions": "Configures OpenSearch Service to use Amazon Cognito authentication for OpenSearch Dashboards.", "DomainEndpointOptions": "Specifies additional options for the domain endpoint, such as whether to require HTTPS for all traffic or whether to use a custom endpoint rather than the default endpoint.", - "DomainName": "A name for the OpenSearch Service domain. For valid values, see the [DomainName](https://docs.aws.amazon.com/opensearch-service/latest/developerguide/configuration-api.html#configuration-api-datatypes-domainname) data type in the *Amazon OpenSearch Service Developer Guide* . If you don't specify a name, AWS CloudFormation generates a unique physical ID and uses that ID for the domain name. For more information, see [Name Type](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-name.html) .\n\n> If you specify a name, you can't perform updates that require replacement of this resource. You can perform updates that require no or some interruption. If you must replace the resource, specify a new name.", + "DomainName": "A name for the OpenSearch Service domain. For valid values, see the [DomainName](https://docs.aws.amazon.com/opensearch-service/latest/developerguide/configuration-api.html#configuration-api-datatypes-domainname) data type in the *Amazon OpenSearch Service Developer Guide* . If you don't specify a name, AWS CloudFormation generates a unique physical ID and uses that ID for the domain name. For more information, see [Name Type](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-name.html) .\n\nRequired when creating a new domain.\n\n> If you specify a name, you can't perform updates that require replacement of this resource. You can perform updates that require no or some interruption. If you must replace the resource, specify a new name.", "EBSOptions": "The configurations of Amazon Elastic Block Store (Amazon EBS) volumes that are attached to data nodes in the OpenSearch Service domain. For more information, see [EBS volume size limits](https://docs.aws.amazon.com/opensearch-service/latest/developerguide/limits.html#ebsresource) in the *Amazon OpenSearch Service Developer Guide* .", "EncryptionAtRestOptions": "Whether the domain should encrypt data at rest, and if so, the AWS KMS key to use. See [Encryption of data at rest for Amazon OpenSearch Service](https://docs.aws.amazon.com/opensearch-service/latest/developerguide/encryption-at-rest.html) .", "EngineVersion": "The version of OpenSearch to use. The value must be in the format `OpenSearch_X.Y` or `Elasticsearch_X.Y` . If not specified, the latest version of OpenSearch is used. For information about the versions that OpenSearch Service supports, see [Supported versions of OpenSearch and Elasticsearch](https://docs.aws.amazon.com/opensearch-service/latest/developerguide/what-is.html#choosing-version) in the *Amazon OpenSearch Service Developer Guide* .\n\nIf you set the [EnableVersionUpgrade](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-updatepolicy.html#cfn-attributes-updatepolicy-upgradeopensearchdomain) update policy to `true` , you can update `EngineVersion` without interruption. When `EnableVersionUpgrade` is set to `false` , or is not specified, updating `EngineVersion` results in [replacement](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-update-behaviors.html#update-replacement) .", @@ -30441,17 +30467,17 @@ "description": "Configures OpenSearch Service to use Amazon Cognito authentication for OpenSearch Dashboards.", "properties": { "Enabled": "Whether to enable or disable Amazon Cognito authentication for OpenSearch Dashboards. See [Amazon Cognito authentication for OpenSearch Dashboards](https://docs.aws.amazon.com/opensearch-service/latest/developerguide/cognito-auth.html) .", - "IdentityPoolId": "The Amazon Cognito identity pool ID that you want OpenSearch Service to use for OpenSearch Dashboards authentication.", - "RoleArn": "The `AmazonESCognitoAccess` role that allows OpenSearch Service to configure your user pool and identity pool.", - "UserPoolId": "The Amazon Cognito user pool ID that you want OpenSearch Service to use for OpenSearch Dashboards authentication." + "IdentityPoolId": "The Amazon Cognito identity pool ID that you want OpenSearch Service to use for OpenSearch Dashboards authentication.\n\nRequired if you enabled Cognito Authentication for OpenSearch Dashboards.", + "RoleArn": "The `AmazonOpenSearchServiceCognitoAccess` role that allows OpenSearch Service to configure your user pool and identity pool.\n\nRequired if you enabled Cognito Authentication for OpenSearch Dashboards.", + "UserPoolId": "The Amazon Cognito user pool ID that you want OpenSearch Service to use for OpenSearch Dashboards authentication.\n\nRequired if you enabled Cognito Authentication for OpenSearch Dashboards." } }, "AWS::OpenSearchService::Domain.DomainEndpointOptions": { "attributes": {}, "description": "Specifies additional options for the domain endpoint, such as whether to require HTTPS for all traffic or whether to use a custom endpoint rather than the default endpoint.", "properties": { - "CustomEndpoint": "The fully qualified URL for your custom endpoint.", - "CustomEndpointCertificateArn": "The AWS Certificate Manager ARN for your domain's SSL/TLS certificate.", + "CustomEndpoint": "The fully qualified URL for your custom endpoint. Required if you enabled a custom endpoint for the domain.", + "CustomEndpointCertificateArn": "The AWS Certificate Manager ARN for your domain's SSL/TLS certificate. Required if you enabled a custom endpoint for the domain.", "CustomEndpointEnabled": "True to enable a custom endpoint for the domain. If enabled, you must also provide values for `CustomEndpoint` and `CustomEndpointCertificateArn` .", "EnforceHTTPS": "True to require that all traffic to the domain arrive over HTTPS.", "TLSSecurityPolicy": "The minimum TLS version required for traffic to the domain. Valid values are TLS 1.0 (default) or 1.2:\n\n- `Policy-Min-TLS-1-0-2019-07`\n- `Policy-Min-TLS-1-2-2019-07`" @@ -30472,20 +30498,20 @@ "description": "Whether the domain should encrypt data at rest, and if so, the AWS Key Management Service key to use.", "properties": { "Enabled": "Specify `true` to enable encryption at rest.", - "KmsKeyId": "The KMS key ID. Takes the form `1a2a3a4-1a2a-3a4a-5a6a-1a2a3a4a5a6a` ." + "KmsKeyId": "The KMS key ID. Takes the form `1a2a3a4-1a2a-3a4a-5a6a-1a2a3a4a5a6a` . Required if you enable encryption at rest." } }, "AWS::OpenSearchService::Domain.LogPublishingOption": { "attributes": {}, "description": "Specifies whether the OpenSearch Service domain publishes application, search slow logs, or index slow logs to Amazon CloudWatch. Each option must be an object of name `SEARCH_SLOW_LOGS` , `ES_APPLICATION_LOGS` , `INDEX_SLOW_LOGS` , or `AUDIT_LOGS` depending on the type of logs you want to publish. For the full syntax, see the [examples](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-opensearchservice-domain.html#aws-resource-opensearchservice-domain--examples) .\n\nBefore you enable log publishing, you need to create a CloudWatch log group and provide OpenSearch Service the correct permissions to write to it. To learn more, see [Enabling log publishing ( AWS CloudFormation)](https://docs.aws.amazon.com/opensearch-service/latest/developerguide/createdomain-configure-slow-logs.html#createdomain-configure-slow-logs-cfn) .", "properties": { - "CloudWatchLogsLogGroupArn": "Specifies the CloudWatch log group to publish to.", + "CloudWatchLogsLogGroupArn": "Specifies the CloudWatch log group to publish to. Required if you enable log publishing.", "Enabled": "If `true` , enables the publishing of logs to CloudWatch.\n\nDefault: `false` ." } }, "AWS::OpenSearchService::Domain.MasterUserOptions": { "attributes": {}, - "description": "Specifies information about the master user.", + "description": "Specifies information about the master user.\n\nRequired if if `InternalUserDatabaseEnabled` is true in `AdvancedSecurityOptions` .", "properties": { "MasterUserARN": "ARN for the master user. Only specify if `InternalUserDatabaseEnabled` is false in `AdvancedSecurityOptions` .", "MasterUserName": "Username for the master user. Only specify if `InternalUserDatabaseEnabled` is true in `AdvancedSecurityOptions` . If you don't want to specify this value directly within the template, you can use a [dynamic reference](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/dynamic-references.html) instead.", @@ -34640,7 +34666,6 @@ "attributes": {}, "description": "Specifies a metrics configuration for the CloudWatch request metrics (specified by the metrics configuration ID) from an Amazon S3 bucket. If you're updating an existing metrics configuration, note that this is a full replacement of the existing metrics configuration. If you don't include the elements you want to keep, they are erased. For examples, see [AWS::S3::Bucket](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-s3-bucket.html#aws-properties-s3-bucket--examples) . For more information, see [PUT Bucket metrics](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTBucketPUTMetricConfiguration.html) in the *Amazon S3 API Reference* .", "properties": { - "AccessPointArn": "The access point that was used while performing operations on the object. The metrics configuration only includes objects that meet the filter's criteria.", "Id": "The ID used to identify the metrics configuration. This can be any value you choose that helps you identify your metrics configuration.", "Prefix": "The prefix that an object must have to be included in the metrics results.", "TagFilters": "Specifies a list of tag filters to use as a metrics configuration filter. The metrics configuration includes only objects that meet the filter's criteria." @@ -34667,7 +34692,6 @@ "attributes": {}, "description": "Describes the notification configuration for an Amazon S3 bucket.\n\n> If you create the target resource and related permissions in the same template, you might have a circular dependency.\n> \n> For example, you might use the `AWS::Lambda::Permission` resource to grant the bucket permission to invoke an AWS Lambda function. However, AWS CloudFormation can't create the bucket until the bucket has permission to invoke the function ( AWS CloudFormation checks whether the bucket can invoke the function). If you're using Refs to pass the bucket name, this leads to a circular dependency.\n> \n> To avoid this dependency, you can create all resources without specifying the notification configuration. Then, update the stack with a notification configuration.\n> \n> For more information on permissions, see [AWS::Lambda::Permission](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-permission.html) and [Granting Permissions to Publish Event Notification Messages to a Destination](https://docs.aws.amazon.com/AmazonS3/latest/dev/NotificationHowTo.html#grant-destinations-permissions-to-s3) .", "properties": { - "EventBridgeConfiguration": "Enables delivery of events to Amazon EventBridge.", "LambdaConfigurations": "Describes the AWS Lambda functions to invoke and the events for which to invoke them.", "QueueConfigurations": "The Amazon Simple Queue Service queues to publish messages to and the events for which to publish messages.", "TopicConfigurations": "The topic to which notifications are sent and the events for which notifications are generated." @@ -34948,12 +34972,7 @@ "AWS::S3::Bucket.WebsiteConfiguration": { "attributes": {}, "description": "Specifies website configuration parameters for an Amazon S3 bucket.", - "properties": { - "ErrorDocument": "The name of the error document for the website.", - "IndexDocument": "The name of the index document for the website.", - "RedirectAllRequestsTo": "The redirect behavior for every request to this bucket's website endpoint.\n\n> If you specify this property, you can't specify any other property.", - "RoutingRules": "Rules that define when a redirect is applied and the redirect behavior." - } + "properties": {} }, "AWS::S3::BucketPolicy": { "attributes": {}, @@ -37578,11 +37597,11 @@ "description": "Specifies that you want to create a hosted Lambda rotation function.\n\nTo use these values, you must specify `Transform: AWS::SecretsManager-2020-07-23` at the beginning of the CloudFormation template.", "properties": { "KmsKeyArn": "The ARN of the KMS key that Secrets Manager uses to encrypt the secret. If you don't specify this value, then Secrets Manager uses the key `aws/secretsmanager` . If `aws/secretsmanager` doesn't yet exist, then Secrets Manager creates it for you automatically the first time it encrypts the secret value.", - "MasterSecretArn": "The ARN of the secret that contains elevated credentials. The Lambda rotation function uses this secret for the [Alternating users rotation strategy](https://docs.aws.amazon.com/secretsmanager/latest/userguide/rotating-secrets_strategies.html#rotating-secrets-two-users) .", + "MasterSecretArn": "The ARN of the secret that contains elevated credentials. You must create the elevated secret before you can set this property. The Lambda rotation function uses this secret for the [Alternating users rotation strategy](https://docs.aws.amazon.com/secretsmanager/latest/userguide/rotating-secrets_strategies.html#rotating-secrets-two-users) .", "MasterSecretKmsKeyArn": "The ARN of the KMS key that Secrets Manager uses to encrypt the elevated secret if you use the [alternating users strategy](https://docs.aws.amazon.com/secretsmanager/latest/userguide/rotating-secrets_strategies.html#rotating-secrets-two-users) . If you don't specify this value and you use the alternating users strategy, then Secrets Manager uses the key `aws/secretsmanager` . If `aws/secretsmanager` doesn't yet exist, then Secrets Manager creates it for you automatically the first time it encrypts the secret value.", "RotationLambdaName": "The name of the Lambda rotation function.", "RotationType": "The type of rotation template to use. For more information, see [Secrets Manager rotation function templates](https://docs.aws.amazon.com/secretsmanager/latest/userguide/reference_available-rotation-templates.html) .\n\nYou can specify one of the following `RotationTypes` :\n\n- MySQLSingleUser\n- MySQLMultiUser\n- PostgreSQLSingleUser\n- PostgreSQLMultiUser\n- OracleSingleUser\n- OracleMultiUser\n- MariaDBSingleUser\n- MariaDBMultiUser\n- SQLServerSingleUser\n- SQLServerMultiUser\n- RedshiftSingleUser\n- RedshiftMultiUser\n- MongoDBSingleUser\n- MongoDBMultiUser", - "SuperuserSecretArn": "The ARN of the secret that contains elevated credentials. The Lambda rotation function uses this secret for the [Alternating users rotation strategy](https://docs.aws.amazon.com/secretsmanager/latest/userguide/rotating-secrets_strategies.html#rotating-secrets-two-users) .", + "SuperuserSecretArn": "The ARN of the secret that contains elevated credentials. You must create the superuser secret before you can set this property. The Lambda rotation function uses this secret for the [Alternating users rotation strategy](https://docs.aws.amazon.com/secretsmanager/latest/userguide/rotating-secrets_strategies.html#rotating-secrets-two-users) .", "SuperuserSecretKmsKeyArn": "The ARN of the KMS key that Secrets Manager uses to encrypt the elevated secret if you use the [alternating users strategy](https://docs.aws.amazon.com/secretsmanager/latest/userguide/rotating-secrets_strategies.html#rotating-secrets-two-users) . If you don't specify this value and you use the alternating users strategy, then Secrets Manager uses the key `aws/secretsmanager` . If `aws/secretsmanager` doesn't yet exist, then Secrets Manager creates it for you automatically the first time it encrypts the secret value.", "VpcSecurityGroupIds": "A comma-separated list of security group IDs applied to the target database.\n\nThe templates applies the same security groups as on the Lambda rotation function that is created as part of this stack.", "VpcSubnetIds": "A comma separated list of VPC subnet IDs of the target database network. The Lambda rotation function is in the same subnet group." @@ -38282,7 +38301,7 @@ "attributes": {}, "description": "Use this structure to input your script code for the canary. This structure contains the Lambda handler with the location where the canary should start running the script. If the script is stored in an S3 bucket, the bucket name, key, and version are also included. If the script is passed into the canary directly, the script code is contained in the value of `Script` .", "properties": { - "Handler": "The entry point to use for the source code when running the canary. This value must end with the string `.handler` . The string is limited to 29 characters or fewer.", + "Handler": "The entry point to use for the source code when running the canary. For canaries that use the `syn-python-selenium-1.0` runtime or a `syn-nodejs.puppeteer` runtime earlier than `syn-nodejs.puppeteer-3.4` , the handler must be specified as `*fileName* .handler` . For `syn-python-selenium-1.1` , `syn-nodejs.puppeteer-3.4` , and later runtimes, the handler can be specified as `*fileName* . *functionName*` , or you can specify a folder where canary scripts reside as `*folder* / *fileName* . *functionName*` .", "S3Bucket": "If your canary script is located in S3, specify the bucket name here. The bucket must already exist.", "S3Key": "The S3 key of your script. For more information, see [Working with Amazon S3 Objects](https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingObjects.html) .", "S3ObjectVersion": "The S3 version ID of your script.", @@ -39050,21 +39069,21 @@ }, "description": "Defines an association between logging destinations and a web ACL resource, for logging from AWS WAF . As part of the association, you can specify parts of the standard logging fields to keep out of the logs and you can specify filters so that you log only a subset of the logging records.\n\n> You can define one logging destination per web ACL. \n\nYou can access information about the traffic that AWS WAF inspects using the following steps:\n\n- Create your logging destination. You can use an Amazon CloudWatch Logs log group, an Amazon Simple Storage Service (Amazon S3) bucket, or an Amazon Kinesis Data Firehose. For information about configuring logging destinations and the permissions that are required for each, see [Logging web ACL traffic information](https://docs.aws.amazon.com/waf/latest/developerguide/logging.html) in the *AWS WAF Developer Guide* .\n- Associate your logging destination to your web ACL using a `PutLoggingConfiguration` request.\n\nWhen you successfully enable logging using a `PutLoggingConfiguration` request, AWS WAF creates an additional role or policy that is required to write logs to the logging destination. For an Amazon CloudWatch Logs log group, AWS WAF creates a resource policy on the log group. For an Amazon S3 bucket, AWS WAF creates a bucket policy. For an Amazon Kinesis Data Firehose, AWS WAF creates a service-linked role.\n\nFor additional information about web ACL logging, see [Logging web ACL traffic information](https://docs.aws.amazon.com/waf/latest/developerguide/logging.html) in the *AWS WAF Developer Guide* .", "properties": { - "LogDestinationConfigs": "The Amazon Resource Names (ARNs) of the logging destinations that you want to associate with the web ACL.", + "LogDestinationConfigs": "The logging destination configuration that you want to associate with the web ACL.\n\n> You can associate one logging destination to a web ACL.", "LoggingFilter": "Filtering that specifies which web requests are kept in the logs and which are dropped. You can filter on the rule action and on the web request labels that were applied by matching rules during web ACL evaluation.", - "RedactedFields": "The parts of the request that you want to keep out of the logs. For example, if you redact the `SingleHeader` field, the `HEADER` field in the firehose will be `xxx` .\n\n> You can specify only the following fields for redaction: `UriPath` , `QueryString` , `SingleHeader` , `Method` , and `JsonBody` .", + "RedactedFields": "The parts of the request that you want to keep out of the logs. For example, if you redact the `SingleHeader` field, the `HEADER` field in the logs will be `xxx` .\n\n> You can specify only the following fields for redaction: `UriPath` , `QueryString` , `SingleHeader` , `Method` , and `JsonBody` .", "ResourceArn": "The Amazon Resource Name (ARN) of the web ACL that you want to associate with `LogDestinationConfigs` ." } }, "AWS::WAFv2::LoggingConfiguration.FieldToMatch": { "attributes": {}, - "description": "The parts of the request that you want to keep out of the logs. For example, if you redact the `SingleHeader` field, the `HEADER` field in the firehose will be `xxx` .\n\nJSON specification for a `QueryString` field to match:\n\n`\"FieldToMatch\": { \"QueryString\": {} }`\n\nExample JSON for a `Method` field to match specification:\n\n`\"FieldToMatch\": { \"Method\": { \"Name\": \"DELETE\" } }`", + "description": "The part of a web request that you want AWS WAF to inspect. Include the single `FieldToMatch` type that you want to inspect, with additional specifications as needed, according to the type. You specify a single request component in `FieldToMatch` for each rule statement that requires it. To inspect more than one component of a web request, create a separate rule statement for each component.\n\nJSON specification for a `QueryString` field to match:\n\n`\"FieldToMatch\": { \"QueryString\": {} }`\n\nExample JSON for a `Method` field to match specification:\n\n`\"FieldToMatch\": { \"Method\": { \"Name\": \"DELETE\" } }`", "properties": { - "JsonBody": "Redact the JSON body from the logs.", - "Method": "Redact the method from the logs.", - "QueryString": "Redact the query string from the logs.", - "SingleHeader": "Redact the header from the logs.", - "UriPath": "Redact the URI path from the logs." + "JsonBody": "Inspect the request body as JSON. The request body immediately follows the request headers. This is the part of a request that contains any additional data that you want to send to your web server as the HTTP request body, such as data from a form.\n\nNote that only the first 8 KB (8192 bytes) of the request body are forwarded to AWS WAF for inspection by the underlying host service. If you don't need to inspect more than 8 KB, you can guarantee that you don't allow additional bytes in by combining a statement that inspects the body of the web request, such as `ByteMatchStatement` or `RegexPatternSetReferenceStatement` , with a `SizeConstraintStatement` that enforces an 8 KB size limit on the body of the request. AWS WAF doesn't support inspecting the entire contents of web requests whose bodies exceed the 8 KB limit.", + "Method": "Inspect the HTTP method. The method indicates the type of operation that the request is asking the origin to perform.", + "QueryString": "Inspect the query string. This is the part of a URL that appears after a `?` character, if any.", + "SingleHeader": "Inspect a single header. Provide the name of the header to inspect, for example, `User-Agent` or `Referer` . This setting isn't case sensitive.\n\nExample JSON: `\"SingleHeader\": { \"Name\": \"haystack\" }`", + "UriPath": "Inspect the request URI path. This is the part of a web request that identifies a resource, for example, `/images/daily-ad.jpg` ." } }, "AWS::WAFv2::RegexPatternSet": { @@ -39572,7 +39591,7 @@ }, "AWS::WAFv2::WebACL.ManagedRuleGroupConfig": { "attributes": {}, - "description": "Additional information that's used by a managed rule group. Most managed rule groups don't require this.\n\nUse this for the account takeover prevention managed rule group `AWSManagedRulesATPRuleSet` , to provide information about the sign-in page of your application.", + "description": "Additional information that's used by a managed rule group. Most managed rule groups don't require this.\n\nUse this for the account takeover prevention managed rule group `AWSManagedRulesATPRuleSet` , to provide information about the sign-in page of your application.\n\nYou can provide multiple individual `ManagedRuleGroupConfig` objects for any rule group configuration, for example `UsernameField` and `PasswordField` . The configuration that you provide depends on the needs of the managed rule group. For the ATP managed rule group, you provide the following individual configuration objects: `LoginPath` , `PasswordField` , `PayloadType` and `UsernameField` .", "properties": { "LoginPath": "The path of the login endpoint for your application. For example, for the URL `https://example.com/web/login` , you would provide the path `/web/login` .", "PasswordField": "Details about your login page password field.", @@ -39585,7 +39604,7 @@ "description": "A rule statement used to run the rules that are defined in a managed rule group. To use this, provide the vendor name and the name of the rule group in this statement.\n\nYou can't nest a `ManagedRuleGroupStatement` , for example for use inside a `NotStatement` or `OrStatement` . It can only be referenced as a top-level statement within a rule.", "properties": { "ExcludedRules": "The rules whose actions are set to `COUNT` by the web ACL, regardless of the action that is configured in the rule. This effectively excludes the rule from acting on web requests.", - "ManagedRuleGroupConfigs": "Additional information that's used by a managed rule group. Most managed rule groups don't require this.\n\nUse this for the account takeover prevention managed rule group `AWSManagedRulesATPRuleSet` , to provide information about the sign-in page of your application.", + "ManagedRuleGroupConfigs": "Additional information that's used by a managed rule group. Most managed rule groups don't require this.\n\nUse this for the account takeover prevention managed rule group `AWSManagedRulesATPRuleSet` , to provide information about the sign-in page of your application.\n\nYou can provide multiple individual `ManagedRuleGroupConfig` objects for any rule group configuration, for example `UsernameField` and `PasswordField` . The configuration that you provide depends on the needs of the managed rule group. For the ATP managed rule group, you provide the following individual configuration objects: `LoginPath` , `PasswordField` , `PayloadType` and `UsernameField` .", "Name": "The name of the managed rule group. You use this, along with the vendor name, to identify the rule group.", "ScopeDownStatement": "Statement nested inside a managed rule group statement to narrow the scope of the requests that AWS WAF evaluates using the rule group. Requests that match the scope-down statement are evaluated using the rule group. Requests that don't match the scope-down statement are not a match for the managed rule group statement, without any further evaluation.", "VendorName": "The name of the managed rule group vendor. You use this, along with the rule group name, to identify the rule group.", @@ -39668,10 +39687,10 @@ }, "AWS::WAFv2::WebACL.RuleGroupReferenceStatement": { "attributes": {}, - "description": "A rule statement used to run the rules that are defined in a `RuleGroup` . To use this, create a rule group with your rules, then provide the ARN of the rule group in this statement.\n\nYou cannot nest a `RuleGroupReferenceStatement` , for example for use inside a `NotStatement` or `OrStatement` . It can only be referenced as a top-level statement within a rule.", + "description": "A rule statement used to run the rules that are defined in a `RuleGroup` . To use this, create a rule group with your rules, then provide the ARN of the rule group in this statement.\n\nYou cannot nest a `RuleGroupReferenceStatement` , for example for use inside a `NotStatement` or `OrStatement` . You can only use a rule group reference statement at the top level inside a web ACL.", "properties": { "Arn": "The Amazon Resource Name (ARN) of the entity.", - "ExcludedRules": "The names of rules that are in the referenced rule group, but that you want AWS WAF to exclude from processing for this rule statement." + "ExcludedRules": "The rules in the referenced rule group whose actions are set to `Count` . When you exclude a rule, AWS WAF evaluates it exactly as it would if the rule action setting were `Count` . This is a useful option for testing the rules in a rule group without modifying how they handle your web traffic." } }, "AWS::WAFv2::WebACL.SizeConstraintStatement": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ACMPCA.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ACMPCA.json index 2ff728ca24165..dac153e3007d0 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ACMPCA.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ACMPCA.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::ACMPCA::Certificate.ApiPassthrough": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-acmpca-certificate-apipassthrough.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_APS.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_APS.json index b159729345a78..a70041a096054 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_APS.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_APS.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::APS::RuleGroupsNamespace": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AccessAnalyzer.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AccessAnalyzer.json index 505d0473b5596..b299f8945cdd4 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AccessAnalyzer.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AccessAnalyzer.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::AccessAnalyzer::Analyzer.ArchiveRule": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-accessanalyzer-analyzer-archiverule.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AmazonMQ.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AmazonMQ.json index a3b995a91ec2d..6698f6c945cdc 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AmazonMQ.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AmazonMQ.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::AmazonMQ::Broker.ConfigurationId": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-amazonmq-broker-configurationid.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Amplify.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Amplify.json index de7b02919ac8d..ea80361cefe44 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Amplify.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Amplify.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::Amplify::App.AutoBranchCreationConfig": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-amplify-app-autobranchcreationconfig.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AmplifyUIBuilder.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AmplifyUIBuilder.json index ebc86a904b5a1..6c2c648f4a595 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AmplifyUIBuilder.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AmplifyUIBuilder.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::AmplifyUIBuilder::Component.ActionParameters": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-amplifyuibuilder-component-actionparameters.html", @@ -610,6 +610,12 @@ "Type": "Map", "UpdateType": "Mutable" }, + "SchemaVersion": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-amplifyuibuilder-component.html#cfn-amplifyuibuilder-component-schemaversion", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, "SourceId": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-amplifyuibuilder-component.html#cfn-amplifyuibuilder-component-sourceid", "PrimitiveType": "String", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ApiGateway.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ApiGateway.json index a4adc6e4a68db..30342b35d19d3 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ApiGateway.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ApiGateway.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::ApiGateway::ApiKey.StageKey": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-apigateway-apikey-stagekey.html", @@ -892,6 +892,12 @@ "Required": true, "UpdateType": "Immutable" }, + "Id": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-apigateway-basepathmapping.html#cfn-apigateway-basepathmapping-id", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, "RestApiId": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-apigateway-basepathmapping.html#cfn-apigateway-basepathmapping-restapiid", "PrimitiveType": "String", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ApiGatewayV2.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ApiGatewayV2.json index 4a5b455d3b4d8..a4c11dfddee1e 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ApiGatewayV2.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ApiGatewayV2.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::ApiGatewayV2::Api.BodyS3Location": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-apigatewayv2-api-bodys3location.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppConfig.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppConfig.json index 5b4ac582b1fea..8bb66bdfa0514 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppConfig.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppConfig.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::AppConfig::Application.Tags": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appconfig-application-tags.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppFlow.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppFlow.json index c434dd570708a..760499dc8e26d 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppFlow.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppFlow.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::AppFlow::ConnectorProfile.AmplitudeConnectorProfileCredentials": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appflow-connectorprofile-amplitudeconnectorprofilecredentials.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppIntegrations.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppIntegrations.json index cb070c672e010..fe801de427892 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppIntegrations.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppIntegrations.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::AppIntegrations::DataIntegration.ScheduleConfig": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appintegrations-dataintegration-scheduleconfig.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppMesh.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppMesh.json index 50ec207ee83c4..0fa21840770c8 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppMesh.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppMesh.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::AppMesh::GatewayRoute.GatewayRouteHostnameMatch": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appmesh-gatewayroute-gatewayroutehostnamematch.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppRunner.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppRunner.json index 48a96380d9a09..f6ec168d966ee 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppRunner.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppRunner.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::AppRunner::Service.AuthenticationConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-apprunner-service-authenticationconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppStream.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppStream.json index 6e7197f97f6a0..eb23b562ec809 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppStream.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppStream.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::AppStream::AppBlock.S3Location": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appstream-appblock-s3location.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppSync.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppSync.json index b4b716a9f04c6..d4853b9eeec5b 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppSync.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppSync.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::AppSync::DataSource.AuthorizationConfig": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appsync-datasource-authorizationconfig.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ApplicationAutoScaling.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ApplicationAutoScaling.json index 2bf7147ee321d..4b86fc0650394 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ApplicationAutoScaling.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ApplicationAutoScaling.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::ApplicationAutoScaling::ScalableTarget.ScalableTargetAction": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-applicationautoscaling-scalabletarget-scalabletargetaction.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ApplicationInsights.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ApplicationInsights.json index d67b7a63678cc..9c30a33fc0088 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ApplicationInsights.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ApplicationInsights.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::ApplicationInsights::Application.Alarm": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-applicationinsights-application-alarm.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Athena.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Athena.json index 9ba92b53965af..128a384482631 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Athena.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Athena.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::Athena::WorkGroup.EncryptionConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-athena-workgroup-encryptionconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AuditManager.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AuditManager.json index 06283583e3d9a..37fcdfb3dcae4 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AuditManager.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AuditManager.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::AuditManager::Assessment.AWSAccount": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-auditmanager-assessment-awsaccount.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AutoScaling.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AutoScaling.json index 0ca1e3c8da9b8..015d7ef11d4f2 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AutoScaling.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AutoScaling.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::AutoScaling::AutoScalingGroup.AcceleratorCountRequest": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-autoscaling-autoscalinggroup-acceleratorcountrequest.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AutoScalingPlans.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AutoScalingPlans.json index 7db9290dc6839..11a5c2b5b0099 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AutoScalingPlans.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AutoScalingPlans.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::AutoScalingPlans::ScalingPlan.ApplicationSource": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-autoscalingplans-scalingplan-applicationsource.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Backup.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Backup.json index c83a50f12e1b9..1d33a8b543e37 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Backup.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Backup.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::Backup::BackupPlan.AdvancedBackupSettingResourceType": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-backup-backupplan-advancedbackupsettingresourcetype.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Batch.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Batch.json index e9844eb09d16c..891e31a407d0f 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Batch.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Batch.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::Batch::ComputeEnvironment.ComputeResources": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-batch-computeenvironment-computeresources.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Budgets.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Budgets.json index d0338ec0af09c..dcd3c55f3218a 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Budgets.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Budgets.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::Budgets::Budget.BudgetData": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-budgets-budget-budgetdata.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CE.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CE.json index 8df832d0ba302..fe5d15b420a56 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CE.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CE.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::CE::AnomalySubscription.Subscriber": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ce-anomalysubscription-subscriber.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CUR.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CUR.json index 925515125628c..1566d46908c7b 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CUR.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CUR.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::CUR::ReportDefinition": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Cassandra.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Cassandra.json index b9527679bd2cb..97eb91f8f45c0 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Cassandra.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Cassandra.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::Cassandra::Table.BillingMode": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cassandra-table-billingmode.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CertificateManager.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CertificateManager.json index 1b354ccb5843a..5e511759a4f1f 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CertificateManager.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CertificateManager.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::CertificateManager::Account.ExpiryEventsConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-certificatemanager-account-expiryeventsconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Chatbot.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Chatbot.json index 5c1f8b5f7b81a..3575f5459a09e 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Chatbot.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Chatbot.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::Chatbot::SlackChannelConfiguration": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Cloud9.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Cloud9.json index d989f711e6be3..3297e6643bf99 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Cloud9.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Cloud9.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::Cloud9::EnvironmentEC2.Repository": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cloud9-environmentec2-repository.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CloudFormation.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CloudFormation.json index ee7c50e075372..dddebf6f4b44d 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CloudFormation.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CloudFormation.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::CloudFormation::HookVersion.LoggingConfig": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cloudformation-hookversion-loggingconfig.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CloudFront.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CloudFront.json index ab73bb9de3206..22c0717588cb8 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CloudFront.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CloudFront.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::CloudFront::CachePolicy.CachePolicyConfig": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cloudfront-cachepolicy-cachepolicyconfig.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CloudTrail.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CloudTrail.json index a31d77ff522b5..2cfb35e3d8823 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CloudTrail.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CloudTrail.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::CloudTrail::Trail.DataResource": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cloudtrail-trail-dataresource.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CloudWatch.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CloudWatch.json index 0b71b44c52a15..a59c52f28a48d 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CloudWatch.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CloudWatch.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::CloudWatch::Alarm.Dimension": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cw-dimension.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeArtifact.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeArtifact.json index 6287219485fa7..297826596c615 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeArtifact.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeArtifact.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::CodeArtifact::Domain": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeBuild.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeBuild.json index 08324d3568d7c..aa6eab1214a2e 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeBuild.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeBuild.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::CodeBuild::Project.Artifacts": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-codebuild-project-artifacts.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeCommit.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeCommit.json index cad407be30584..c6668b46ef1c0 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeCommit.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeCommit.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::CodeCommit::Repository.Code": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-codecommit-repository-code.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeDeploy.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeDeploy.json index 3bfee7899e089..e500317a11195 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeDeploy.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeDeploy.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::CodeDeploy::DeploymentConfig.MinimumHealthyHosts": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-codedeploy-deploymentconfig-minimumhealthyhosts.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeGuruProfiler.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeGuruProfiler.json index 95dc02232f853..07562c3c95b26 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeGuruProfiler.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeGuruProfiler.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::CodeGuruProfiler::ProfilingGroup.Channel": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-codeguruprofiler-profilinggroup-channel.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeGuruReviewer.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeGuruReviewer.json index 2e0b75cdbdf59..ba975800ca1fc 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeGuruReviewer.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeGuruReviewer.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::CodeGuruReviewer::RepositoryAssociation": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodePipeline.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodePipeline.json index 7e99e6618a4d7..dd554b9cc6538 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodePipeline.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodePipeline.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::CodePipeline::CustomActionType.ArtifactDetails": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-codepipeline-customactiontype-artifactdetails.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeStar.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeStar.json index 1e64b76b944c0..686431702961f 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeStar.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeStar.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::CodeStar::GitHubRepository.Code": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-codestar-githubrepository-code.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeStarConnections.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeStarConnections.json index f2e30c565fc48..1613ba7e671bd 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeStarConnections.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeStarConnections.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::CodeStarConnections::Connection": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeStarNotifications.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeStarNotifications.json index 63eff810949d8..2566cb083c272 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeStarNotifications.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeStarNotifications.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::CodeStarNotifications::NotificationRule.Target": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-codestarnotifications-notificationrule-target.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Cognito.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Cognito.json index 5b910c4b4f48f..a17a8d2ae7d53 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Cognito.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Cognito.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::Cognito::IdentityPool.CognitoIdentityProvider": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cognito-identitypool-cognitoidentityprovider.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Config.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Config.json index de6cff6ed6287..059dba0e6bd65 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Config.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Config.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::Config::ConfigRule.Scope": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-config-configrule-scope.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Connect.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Connect.json index e3c593c3f7145..353bb7c024107 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Connect.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Connect.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::Connect::HoursOfOperation.HoursOfOperationConfig": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-connect-hoursofoperation-hoursofoperationconfig.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CustomerProfiles.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CustomerProfiles.json index f60d94f1a7a2a..d263c81b4218c 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CustomerProfiles.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CustomerProfiles.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::CustomerProfiles::Integration.ConnectorOperator": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-customerprofiles-integration-connectoroperator.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DAX.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DAX.json index 52852e97bc58b..6f03d49c5ad07 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DAX.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DAX.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::DAX::Cluster.SSESpecification": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dax-cluster-ssespecification.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DLM.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DLM.json index 5c3bfda5dd1b2..bff6ea72ec99e 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DLM.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DLM.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::DLM::LifecyclePolicy.Action": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dlm-lifecyclepolicy-action.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DMS.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DMS.json index 4f456afa803ec..db28a5e1805ee 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DMS.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DMS.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::DMS::Endpoint.DocDbSettings": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dms-endpoint-docdbsettings.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DataBrew.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DataBrew.json index cc2ebcaffebfb..ae8b721fd145b 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DataBrew.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DataBrew.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::DataBrew::Dataset.CsvOptions": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-databrew-dataset-csvoptions.html", @@ -550,6 +550,12 @@ "Type": "S3Location", "UpdateType": "Mutable" }, + "MaxOutputFiles": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-databrew-job-output.html#cfn-databrew-job-output-maxoutputfiles", + "PrimitiveType": "Integer", + "Required": false, + "UpdateType": "Mutable" + }, "Overwrite": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-databrew-job-output.html#cfn-databrew-job-output-overwrite", "PrimitiveType": "Boolean", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DataPipeline.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DataPipeline.json index e56e2f9238abc..21d5aa48047be 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DataPipeline.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DataPipeline.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::DataPipeline::Pipeline.Field": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-datapipeline-pipeline-pipelineobjects-fields.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DataSync.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DataSync.json index ceb993b76f11c..a6ccf78781300 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DataSync.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DataSync.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::DataSync::LocationEFS.Ec2Config": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-datasync-locationefs-ec2config.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Detective.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Detective.json index 304e933e560b9..a6b15557080a0 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Detective.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Detective.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::Detective::Graph": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DevOpsGuru.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DevOpsGuru.json index 5a693509166bc..ef9a76da445f4 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DevOpsGuru.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DevOpsGuru.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::DevOpsGuru::NotificationChannel.NotificationChannelConfig": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-devopsguru-notificationchannel-notificationchannelconfig.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DirectoryService.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DirectoryService.json index a08912ffb8dd5..cb12cac9d1e62 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DirectoryService.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DirectoryService.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::DirectoryService::MicrosoftAD.VpcSettings": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-directoryservice-microsoftad-vpcsettings.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DocDB.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DocDB.json index aff4483803d48..39675ffbc909e 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DocDB.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DocDB.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::DocDB::DBCluster": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DynamoDB.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DynamoDB.json index 9825b82f92992..84cf6ddc6f718 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DynamoDB.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DynamoDB.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::DynamoDB::GlobalTable.AttributeDefinition": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-globaltable-attributedefinition.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EC2.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EC2.json index 0947d48f9c80d..121bd07541944 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EC2.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EC2.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::EC2::CapacityReservation.TagSpecification": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-capacityreservation-tagspecification.html", @@ -7391,7 +7391,7 @@ "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-transitgatewayvpcattachment.html#cfn-ec2-transitgatewayvpcattachment-subnetids", "DuplicatesAllowed": true, "PrimitiveItemType": "String", - "Required": false, + "Required": true, "Type": "List", "UpdateType": "Immutable" }, @@ -7406,13 +7406,13 @@ "TransitGatewayId": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-transitgatewayvpcattachment.html#cfn-ec2-transitgatewayvpcattachment-transitgatewayid", "PrimitiveType": "String", - "Required": false, + "Required": true, "UpdateType": "Immutable" }, "VpcId": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-transitgatewayvpcattachment.html#cfn-ec2-transitgatewayvpcattachment-vpcid", "PrimitiveType": "String", - "Required": false, + "Required": true, "UpdateType": "Immutable" } } diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ECR.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ECR.json index e79749ff66fe9..2d218f537b90e 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ECR.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ECR.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::ECR::ReplicationConfiguration.ReplicationConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ecr-replicationconfiguration-replicationconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ECS.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ECS.json index c613e88847e4f..0ee480e4895bc 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ECS.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ECS.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::ECS::CapacityProvider.AutoScalingGroupProvider": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ecs-capacityprovider-autoscalinggroupprovider.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EFS.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EFS.json index e03a609e14cdb..bbc443d07d1e6 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EFS.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EFS.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::EFS::AccessPoint.AccessPointTag": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-efs-accesspoint-accesspointtag.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EKS.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EKS.json index 212042083c563..2b97e822693e9 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EKS.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EKS.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::EKS::Cluster.ClusterLogging": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-eks-cluster-clusterlogging.html", @@ -149,6 +149,72 @@ } } }, + "AWS::EKS::IdentityProviderConfig.OidcIdentityProviderConfig": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-eks-identityproviderconfig-oidcidentityproviderconfig.html", + "Properties": { + "ClientId": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-eks-identityproviderconfig-oidcidentityproviderconfig.html#cfn-eks-identityproviderconfig-oidcidentityproviderconfig-clientid", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + }, + "GroupsClaim": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-eks-identityproviderconfig-oidcidentityproviderconfig.html#cfn-eks-identityproviderconfig-oidcidentityproviderconfig-groupsclaim", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Immutable" + }, + "GroupsPrefix": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-eks-identityproviderconfig-oidcidentityproviderconfig.html#cfn-eks-identityproviderconfig-oidcidentityproviderconfig-groupsprefix", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Immutable" + }, + "IssuerUrl": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-eks-identityproviderconfig-oidcidentityproviderconfig.html#cfn-eks-identityproviderconfig-oidcidentityproviderconfig-issuerurl", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + }, + "RequiredClaims": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-eks-identityproviderconfig-oidcidentityproviderconfig.html#cfn-eks-identityproviderconfig-oidcidentityproviderconfig-requiredclaims", + "DuplicatesAllowed": false, + "ItemType": "RequiredClaim", + "Required": false, + "Type": "List", + "UpdateType": "Immutable" + }, + "UsernameClaim": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-eks-identityproviderconfig-oidcidentityproviderconfig.html#cfn-eks-identityproviderconfig-oidcidentityproviderconfig-usernameclaim", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Immutable" + }, + "UsernamePrefix": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-eks-identityproviderconfig-oidcidentityproviderconfig.html#cfn-eks-identityproviderconfig-oidcidentityproviderconfig-usernameprefix", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Immutable" + } + } + }, + "AWS::EKS::IdentityProviderConfig.RequiredClaim": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-eks-identityproviderconfig-requiredclaim.html", + "Properties": { + "Key": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-eks-identityproviderconfig-requiredclaim.html#cfn-eks-identityproviderconfig-requiredclaim-key", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + }, + "Value": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-eks-identityproviderconfig-requiredclaim.html#cfn-eks-identityproviderconfig-requiredclaim-value", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + } + } + }, "AWS::EKS::Nodegroup.LaunchTemplateSpecification": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-eks-nodegroup-launchtemplatespecification.html", "Properties": { @@ -433,6 +499,48 @@ } } }, + "AWS::EKS::IdentityProviderConfig": { + "Attributes": { + "IdentityProviderConfigArn": { + "PrimitiveType": "String" + } + }, + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-eks-identityproviderconfig.html", + "Properties": { + "ClusterName": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-eks-identityproviderconfig.html#cfn-eks-identityproviderconfig-clustername", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + }, + "IdentityProviderConfigName": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-eks-identityproviderconfig.html#cfn-eks-identityproviderconfig-identityproviderconfigname", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Immutable" + }, + "Oidc": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-eks-identityproviderconfig.html#cfn-eks-identityproviderconfig-oidc", + "Required": false, + "Type": "OidcIdentityProviderConfig", + "UpdateType": "Immutable" + }, + "Tags": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-eks-identityproviderconfig.html#cfn-eks-identityproviderconfig-tags", + "DuplicatesAllowed": false, + "ItemType": "Tag", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "Type": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-eks-identityproviderconfig.html#cfn-eks-identityproviderconfig-type", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + } + } + }, "AWS::EKS::Nodegroup": { "Attributes": { "Arn": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EMR.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EMR.json index 9cbf0d9c7fdbd..1ffa7905a01a5 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EMR.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EMR.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::EMR::Cluster.Application": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-elasticmapreduce-cluster-application.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EMRContainers.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EMRContainers.json index 534a9bed8f874..a18345b5e07df 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EMRContainers.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EMRContainers.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::EMRContainers::VirtualCluster.ContainerInfo": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-emrcontainers-virtualcluster-containerinfo.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ElastiCache.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ElastiCache.json index 1ed242f9c57db..512eace7ec712 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ElastiCache.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ElastiCache.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::ElastiCache::CacheCluster.CloudWatchLogsDestinationDetails": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-elasticache-cachecluster-cloudwatchlogsdestinationdetails.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ElasticBeanstalk.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ElasticBeanstalk.json index e4ad1811f5f27..8fbfbc0e692b4 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ElasticBeanstalk.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ElasticBeanstalk.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::ElasticBeanstalk::Application.ApplicationResourceLifecycleConfig": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-elasticbeanstalk-application-applicationresourcelifecycleconfig.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ElasticLoadBalancing.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ElasticLoadBalancing.json index fc2bbc4a0642d..c8ced355143b0 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ElasticLoadBalancing.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ElasticLoadBalancing.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::ElasticLoadBalancing::LoadBalancer.AccessLoggingPolicy": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-elb-accessloggingpolicy.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ElasticLoadBalancingV2.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ElasticLoadBalancingV2.json index 40d0d351aaf26..7b8aec57a7721 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ElasticLoadBalancingV2.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ElasticLoadBalancingV2.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::ElasticLoadBalancingV2::Listener.Action": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-elasticloadbalancingv2-listener-action.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Elasticsearch.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Elasticsearch.json index 799a4e7887bfe..ff7e2e746acda 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Elasticsearch.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Elasticsearch.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::Elasticsearch::Domain.AdvancedSecurityOptionsInput": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-elasticsearch-domain-advancedsecurityoptionsinput.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EventSchemas.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EventSchemas.json index f3f34975898af..f50e452150aef 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EventSchemas.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EventSchemas.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::EventSchemas::Discoverer.TagsEntry": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-eventschemas-discoverer-tagsentry.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Events.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Events.json index 66932fa38a03d..235368cfa05f3 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Events.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Events.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::Events::Connection.ApiKeyAuthParameters": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-events-connection-apikeyauthparameters.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Evidently.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Evidently.json index 6c4ae0fc07b0e..d17ba0b979f20 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Evidently.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Evidently.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::Evidently::Experiment.MetricGoalObject": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-evidently-experiment-metricgoalobject.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_FIS.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_FIS.json index 3fd699ab3b922..0f5b0f810c8ff 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_FIS.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_FIS.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::FIS::ExperimentTemplate.ExperimentTemplateAction": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-fis-experimenttemplate-experimenttemplateaction.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_FMS.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_FMS.json index 644093a4b4d53..d13e5954f1495 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_FMS.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_FMS.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::FMS::Policy.IEMap": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-fms-policy-iemap.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_FSx.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_FSx.json index 09dc836f49ec6..73f32fa8a75e6 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_FSx.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_FSx.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::FSx::FileSystem.AuditLogConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-fsx-filesystem-windowsconfiguration-auditlogconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_FinSpace.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_FinSpace.json index c5e4cda9f483b..2bd367e897afb 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_FinSpace.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_FinSpace.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::FinSpace::Environment.FederationParameters": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-finspace-environment-federationparameters.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Forecast.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Forecast.json index 1fdb461a48f33..e9013d59a0666 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Forecast.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Forecast.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::Forecast::Dataset": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_FraudDetector.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_FraudDetector.json index 4de76991aa6c8..7bf297b2a4257 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_FraudDetector.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_FraudDetector.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::FraudDetector::Detector.EntityType": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-frauddetector-detector-entitytype.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_GameLift.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_GameLift.json index 9dd908cd09c2e..0669af13996bb 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_GameLift.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_GameLift.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::GameLift::Alias.RoutingStrategy": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-gamelift-alias-routingstrategy.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_GlobalAccelerator.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_GlobalAccelerator.json index 20e904240395c..8e9cc088d59ac 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_GlobalAccelerator.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_GlobalAccelerator.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::GlobalAccelerator::EndpointGroup.EndpointConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-globalaccelerator-endpointgroup-endpointconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Glue.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Glue.json index 82cde304b845c..90d0fde049366 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Glue.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Glue.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::Glue::Classifier.CsvClassifier": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-glue-classifier-csvclassifier.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Greengrass.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Greengrass.json index e019dde079ea0..948e51373320f 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Greengrass.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Greengrass.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::Greengrass::ConnectorDefinition.Connector": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-greengrass-connectordefinition-connector.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_GreengrassV2.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_GreengrassV2.json index 6c6e6bfceba0e..41857626f318b 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_GreengrassV2.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_GreengrassV2.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::GreengrassV2::ComponentVersion.ComponentDependencyRequirement": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-greengrassv2-componentversion-componentdependencyrequirement.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_GroundStation.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_GroundStation.json index 0becc7747cf08..e8ec3aed62033 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_GroundStation.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_GroundStation.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::GroundStation::Config.AntennaDownlinkConfig": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-groundstation-config-antennadownlinkconfig.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_GuardDuty.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_GuardDuty.json index 6bcd40e47295a..c604431104c74 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_GuardDuty.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_GuardDuty.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::GuardDuty::Detector.CFNDataSourceConfigurations": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-guardduty-detector-cfndatasourceconfigurations.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_HealthLake.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_HealthLake.json index 58a248c2ec07e..57fe856c570e9 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_HealthLake.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_HealthLake.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::HealthLake::FHIRDatastore.KmsEncryptionConfig": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-healthlake-fhirdatastore-kmsencryptionconfig.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IAM.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IAM.json index f70c59615f0e1..c6a876338538a 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IAM.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IAM.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::IAM::Group.Policy": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iam-policy.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IVS.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IVS.json index bcf2872bf3889..cf6cd0025b11d 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IVS.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IVS.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::IVS::RecordingConfiguration.DestinationConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ivs-recordingconfiguration-destinationconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ImageBuilder.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ImageBuilder.json index 91fd1e98ebc7c..feb22b933215e 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ImageBuilder.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ImageBuilder.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::ImageBuilder::ContainerRecipe.ComponentConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-imagebuilder-containerrecipe-componentconfiguration.html", @@ -666,6 +666,9 @@ "ImageId": { "PrimitiveType": "String" }, + "ImageUri": { + "PrimitiveType": "String" + }, "Name": { "PrimitiveType": "String" } @@ -676,7 +679,7 @@ "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-imagebuilder-image.html#cfn-imagebuilder-image-containerrecipearn", "PrimitiveType": "String", "Required": false, - "UpdateType": "Mutable" + "UpdateType": "Immutable" }, "DistributionConfigurationArn": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-imagebuilder-image.html#cfn-imagebuilder-image-distributionconfigurationarn", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Inspector.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Inspector.json index 3421ea3d2fa5a..54630811777d3 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Inspector.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Inspector.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::Inspector::AssessmentTarget": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_InspectorV2.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_InspectorV2.json index f1cfe40792246..08afea929e819 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_InspectorV2.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_InspectorV2.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::InspectorV2::Filter.DateFilter": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-inspectorv2-filter-datefilter.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoT.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoT.json index 8c75df1e60ab3..524e8388050d7 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoT.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoT.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::IoT::AccountAuditConfiguration.AuditCheckConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iot-accountauditconfiguration-auditcheckconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoT1Click.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoT1Click.json index 5aaf952177f5c..5eb1ce6e4c870 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoT1Click.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoT1Click.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::IoT1Click::Project.DeviceTemplate": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iot1click-project-devicetemplate.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTAnalytics.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTAnalytics.json index 7a3d99844dcb2..de00da04e8560 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTAnalytics.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTAnalytics.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::IoTAnalytics::Channel.ChannelStorage": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotanalytics-channel-channelstorage.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTCoreDeviceAdvisor.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTCoreDeviceAdvisor.json index 2404567bebddf..e1e638619aaee 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTCoreDeviceAdvisor.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTCoreDeviceAdvisor.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::IoTCoreDeviceAdvisor::SuiteDefinition": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTEvents.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTEvents.json index 2175b31ca4190..63aa8505f8b3a 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTEvents.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTEvents.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::IoTEvents::DetectorModel.Action": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotevents-detectormodel-action.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTFleetHub.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTFleetHub.json index cda3088454b72..ce086ffbf239f 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTFleetHub.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTFleetHub.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::IoTFleetHub::Application": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTSiteWise.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTSiteWise.json index 07bfb378cea37..56e976fbfced8 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTSiteWise.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTSiteWise.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::IoTSiteWise::AccessPolicy.AccessPolicyIdentity": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotsitewise-accesspolicy-accesspolicyidentity.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTThingsGraph.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTThingsGraph.json index 7bb78b1d32849..1e6c7cb361196 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTThingsGraph.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTThingsGraph.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::IoTThingsGraph::FlowTemplate.DefinitionDocument": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotthingsgraph-flowtemplate-definitiondocument.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTWireless.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTWireless.json index 36e79d2a8fcd2..1f5b18019a032 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTWireless.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTWireless.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::IoTWireless::DeviceProfile.LoRaWANDeviceProfile": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotwireless-deviceprofile-lorawandeviceprofile.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KMS.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KMS.json index 2722f7ac55c72..72371ab85a1ad 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KMS.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KMS.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::KMS::Alias": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KafkaConnect.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KafkaConnect.json index 7e71100a6770d..6878e90f81da3 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KafkaConnect.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KafkaConnect.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::KafkaConnect::Connector.ApacheKafkaCluster": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-kafkaconnect-connector-apachekafkacluster.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Kendra.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Kendra.json index 0fdc08cff566e..4e6247329ab19 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Kendra.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Kendra.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::Kendra::DataSource.AccessControlListConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-kendra-datasource-accesscontrollistconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Kinesis.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Kinesis.json index 7af96c931bf7c..208bc9e757d84 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Kinesis.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Kinesis.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::Kinesis::Stream.StreamEncryption": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-kinesis-stream-streamencryption.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KinesisAnalytics.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KinesisAnalytics.json index fc08ae3b18cf8..37318b1b1d591 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KinesisAnalytics.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KinesisAnalytics.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::KinesisAnalytics::Application.CSVMappingParameters": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-kinesisanalytics-application-csvmappingparameters.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KinesisAnalyticsV2.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KinesisAnalyticsV2.json index fd35a866d7f78..c9a22253a2f7e 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KinesisAnalyticsV2.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KinesisAnalyticsV2.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::KinesisAnalyticsV2::Application.ApplicationCodeConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-kinesisanalyticsv2-application-applicationcodeconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KinesisFirehose.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KinesisFirehose.json index e3160d0a44469..c3432dd2c6e72 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KinesisFirehose.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KinesisFirehose.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::KinesisFirehose::DeliveryStream.AmazonopensearchserviceBufferingHints": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-kinesisfirehose-deliverystream-amazonopensearchservicebufferinghints.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KinesisVideo.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KinesisVideo.json index 7958736c68273..cbe9e5a0fee8b 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KinesisVideo.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KinesisVideo.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::KinesisVideo::SignalingChannel": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_LakeFormation.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_LakeFormation.json index ae487635e6ded..1da453a20b485 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_LakeFormation.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_LakeFormation.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::LakeFormation::DataLakeSettings.Admins": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-lakeformation-datalakesettings-admins.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Lambda.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Lambda.json index a903d9b9be120..eb93de4c0bf80 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Lambda.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Lambda.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::Lambda::Alias.AliasRoutingConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-lambda-alias-aliasroutingconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Lex.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Lex.json index 02db824a58cd9..1547db8f8abdc 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Lex.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Lex.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::Lex::Bot.BotLocale": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-lex-bot-botlocale.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_LicenseManager.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_LicenseManager.json index a9fe91377d947..cace32e328e32 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_LicenseManager.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_LicenseManager.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::LicenseManager::License.BorrowConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-licensemanager-license-borrowconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Lightsail.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Lightsail.json index 9b0667e794955..f026f3bcb0c96 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Lightsail.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Lightsail.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::Lightsail::Bucket.AccessRules": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-lightsail-bucket-accessrules.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Location.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Location.json index 15cb3e1cb1afc..7619d660ec8ea 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Location.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Location.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::Location::Map.MapConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-location-map-mapconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Logs.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Logs.json index 923c82c3eb423..1b7e74fc4d1ec 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Logs.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Logs.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::Logs::MetricFilter.MetricTransformation": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-logs-metricfilter-metrictransformation.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_LookoutEquipment.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_LookoutEquipment.json index bb6cb001d235f..9230be162663c 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_LookoutEquipment.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_LookoutEquipment.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::LookoutEquipment::InferenceScheduler": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_LookoutMetrics.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_LookoutMetrics.json index 46f568e26cc50..2b149f8160c28 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_LookoutMetrics.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_LookoutMetrics.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::LookoutMetrics::Alert.Action": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-lookoutmetrics-alert-action.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_LookoutVision.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_LookoutVision.json index 8899a2555d600..7fcd7edfc5ac2 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_LookoutVision.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_LookoutVision.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::LookoutVision::Project": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MSK.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MSK.json index 4ae5188c169ec..54d2aa068ca9d 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MSK.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MSK.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::MSK::Cluster.BrokerLogs": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-msk-cluster-brokerlogs.html", @@ -35,6 +35,7 @@ }, "ClientSubnets": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-msk-cluster-brokernodegroupinfo.html#cfn-msk-cluster-brokernodegroupinfo-clientsubnets", + "DuplicatesAllowed": true, "PrimitiveItemType": "String", "Required": true, "Type": "List", @@ -54,6 +55,7 @@ }, "SecurityGroups": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-msk-cluster-brokernodegroupinfo.html#cfn-msk-cluster-brokernodegroupinfo-securitygroups", + "DuplicatesAllowed": true, "PrimitiveItemType": "String", "Required": false, "Type": "List", @@ -381,6 +383,7 @@ "Properties": { "CertificateAuthorityArnList": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-msk-cluster-tls.html#cfn-msk-cluster-tls-certificateauthorityarnlist", + "DuplicatesAllowed": true, "PrimitiveItemType": "String", "Required": false, "Type": "List", @@ -407,7 +410,30 @@ } }, "ResourceTypes": { + "AWS::MSK::BatchScramSecret": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-msk-batchscramsecret.html", + "Properties": { + "ClusterArn": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-msk-batchscramsecret.html#cfn-msk-batchscramsecret-clusterarn", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + }, + "SecretArnList": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-msk-batchscramsecret.html#cfn-msk-batchscramsecret-secretarnlist", + "PrimitiveItemType": "String", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + } + } + }, "AWS::MSK::Cluster": { + "Attributes": { + "Arn": { + "PrimitiveType": "String" + } + }, "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-msk-cluster.html", "Properties": { "BrokerNodeGroupInfo": { @@ -434,6 +460,12 @@ "Type": "ConfigurationInfo", "UpdateType": "Mutable" }, + "CurrentVersion": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-msk-cluster.html#cfn-msk-cluster-currentversion", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, "EncryptionInfo": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-msk-cluster.html#cfn-msk-cluster-encryptioninfo", "Required": false, @@ -472,11 +504,47 @@ }, "Tags": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-msk-cluster.html#cfn-msk-cluster-tags", - "PrimitiveType": "Json", + "PrimitiveItemType": "String", "Required": false, + "Type": "Map", "UpdateType": "Immutable" } } + }, + "AWS::MSK::Configuration": { + "Attributes": { + "Arn": { + "PrimitiveType": "String" + } + }, + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-msk-configuration.html", + "Properties": { + "Description": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-msk-configuration.html#cfn-msk-configuration-description", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "KafkaVersionsList": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-msk-configuration.html#cfn-msk-configuration-kafkaversionslist", + "PrimitiveItemType": "String", + "Required": false, + "Type": "List", + "UpdateType": "Immutable" + }, + "Name": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-msk-configuration.html#cfn-msk-configuration-name", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Immutable" + }, + "ServerProperties": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-msk-configuration.html#cfn-msk-configuration-serverproperties", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + } + } } } } diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MWAA.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MWAA.json index 9a95f9ceb1b4a..2d8db8368ece4 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MWAA.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MWAA.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::MWAA::Environment.LoggingConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-mwaa-environment-loggingconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Macie.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Macie.json index faa5d9e45e4f0..3d3c12b1f7fcd 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Macie.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Macie.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::Macie::FindingsFilter.Criterion": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-macie-findingsfilter-criterion.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ManagedBlockchain.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ManagedBlockchain.json index d8f7ad0f7b8a0..038ec243aec4e 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ManagedBlockchain.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ManagedBlockchain.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::ManagedBlockchain::Member.ApprovalThresholdPolicy": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-managedblockchain-member-approvalthresholdpolicy.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaConnect.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaConnect.json index 1379fd8225b39..987a145eb053c 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaConnect.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaConnect.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::MediaConnect::Flow.Encryption": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-mediaconnect-flow-encryption.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaConvert.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaConvert.json index 661959cadffeb..9009c2c6476f1 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaConvert.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaConvert.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::MediaConvert::JobTemplate.AccelerationSettings": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-mediaconvert-jobtemplate-accelerationsettings.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaLive.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaLive.json index 8728b842e06b4..e04e80c6654d7 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaLive.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaLive.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::MediaLive::Channel.AacSettings": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-medialive-channel-aacsettings.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaPackage.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaPackage.json index 4487f1e307855..852f2ae5d2672 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaPackage.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaPackage.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::MediaPackage::Asset.EgressEndpoint": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-mediapackage-asset-egressendpoint.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaStore.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaStore.json index 6cbaf66d50415..b5b8781af9bbb 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaStore.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaStore.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::MediaStore::Container.CorsRule": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-mediastore-container-corsrule.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MemoryDB.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MemoryDB.json index bf8cdd2cd9660..c75483b4a4218 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MemoryDB.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MemoryDB.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::MemoryDB::Cluster.Endpoint": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-memorydb-cluster-endpoint.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Neptune.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Neptune.json index 2f9803eb5d597..231715f6b5b5a 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Neptune.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Neptune.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::Neptune::DBCluster.DBClusterRole": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-neptune-dbcluster-dbclusterrole.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_NetworkFirewall.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_NetworkFirewall.json index ebb6c77c06490..cea445244c7ac 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_NetworkFirewall.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_NetworkFirewall.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::NetworkFirewall::Firewall.SubnetMapping": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-networkfirewall-firewall-subnetmapping.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_NetworkManager.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_NetworkManager.json index a082c6582695a..46aeea5c8a6b4 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_NetworkManager.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_NetworkManager.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::NetworkManager::Device.Location": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-networkmanager-device-location.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_NimbleStudio.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_NimbleStudio.json index 06f183e5e9949..6f1f1dede2f01 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_NimbleStudio.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_NimbleStudio.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::NimbleStudio::LaunchProfile.StreamConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-nimblestudio-launchprofile-streamconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_OpenSearchService.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_OpenSearchService.json index 087b62ea4a94f..4109049a69869 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_OpenSearchService.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_OpenSearchService.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::OpenSearchService::Domain.AdvancedSecurityOptionsInput": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-opensearchservice-domain-advancedsecurityoptionsinput.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_OpsWorks.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_OpsWorks.json index 71cc0074262aa..12c75fee328b0 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_OpsWorks.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_OpsWorks.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::OpsWorks::App.DataSource": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-opsworks-app-datasource.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_OpsWorksCM.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_OpsWorksCM.json index e1ba8f64bf9ee..c094689aea531 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_OpsWorksCM.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_OpsWorksCM.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::OpsWorksCM::Server.EngineAttribute": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-opsworkscm-server-engineattribute.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Panorama.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Panorama.json index ae5d724ec9246..bb8f2ea1c04e6 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Panorama.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Panorama.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::Panorama::ApplicationInstance.ManifestOverridesPayload": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-panorama-applicationinstance-manifestoverridespayload.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Pinpoint.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Pinpoint.json index 49c7d6fbf4bb0..d7018ddd4331b 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Pinpoint.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Pinpoint.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::Pinpoint::ApplicationSettings.CampaignHook": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-pinpoint-applicationsettings-campaignhook.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_PinpointEmail.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_PinpointEmail.json index 48abd830c9ee3..f2adfa3b5c18d 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_PinpointEmail.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_PinpointEmail.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::PinpointEmail::ConfigurationSet.DeliveryOptions": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-pinpointemail-configurationset-deliveryoptions.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_QLDB.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_QLDB.json index 43660641354c0..3e84501937b3b 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_QLDB.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_QLDB.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::QLDB::Stream.KinesisConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-qldb-stream-kinesisconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_QuickSight.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_QuickSight.json index ee3ecfd2e3675..1e6c845a8dc67 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_QuickSight.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_QuickSight.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::QuickSight::Analysis.AnalysisError": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-quicksight-analysis-analysiserror.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RAM.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RAM.json index f6e1c12950e6a..a0d89a1609f3a 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RAM.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RAM.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::RAM::ResourceShare": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RDS.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RDS.json index 793e0f162c65a..fce9fdd1d7e7e 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RDS.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RDS.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::RDS::DBCluster.DBClusterRole": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-rds-dbcluster-dbclusterrole.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RUM.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RUM.json index 39458c6bf2f32..dc594c5704bef 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RUM.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RUM.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::RUM::AppMonitor.AppMonitorConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-rum-appmonitor-appmonitorconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Redshift.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Redshift.json index c60c929d76672..822aa9e95ff78 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Redshift.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Redshift.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::Redshift::Cluster.Endpoint": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-redshift-cluster-endpoint.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RefactorSpaces.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RefactorSpaces.json index b4cae6627f43d..1b41ea853b3d8 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RefactorSpaces.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RefactorSpaces.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::RefactorSpaces::Application.ApiGatewayProxyInput": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-refactorspaces-application-apigatewayproxyinput.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Rekognition.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Rekognition.json index b9f896185eaa3..b7af4136804a9 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Rekognition.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Rekognition.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::Rekognition::Collection": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ResilienceHub.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ResilienceHub.json index f36f6dd25a32d..0a9c707c4346d 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ResilienceHub.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ResilienceHub.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::ResilienceHub::App.PhysicalResourceId": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-resiliencehub-app-physicalresourceid.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ResourceGroups.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ResourceGroups.json index 9c5341689fead..14d578d05832e 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ResourceGroups.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ResourceGroups.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::ResourceGroups::Group.ConfigurationItem": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-resourcegroups-group-configurationitem.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RoboMaker.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RoboMaker.json index 00517673585ea..5e3103240d1ad 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RoboMaker.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RoboMaker.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::RoboMaker::RobotApplication.RobotSoftwareSuite": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-robomaker-robotapplication-robotsoftwaresuite.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Route53.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Route53.json index d4551a4448ef9..124eb8d672efc 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Route53.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Route53.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::Route53::HealthCheck.HealthCheckTag": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-route53-healthcheck-healthchecktag.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Route53RecoveryControl.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Route53RecoveryControl.json index e5a84bfbd9ed2..a3aadf8cebf78 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Route53RecoveryControl.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Route53RecoveryControl.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::Route53RecoveryControl::Cluster.ClusterEndpoint": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-route53recoverycontrol-cluster-clusterendpoint.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Route53RecoveryReadiness.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Route53RecoveryReadiness.json index b70f136443f2d..da2e930f5fbfb 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Route53RecoveryReadiness.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Route53RecoveryReadiness.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::Route53RecoveryReadiness::ResourceSet.DNSTargetResource": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-route53recoveryreadiness-resourceset-dnstargetresource.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Route53Resolver.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Route53Resolver.json index 5a149c5f4c50c..11a7b617a656b 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Route53Resolver.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Route53Resolver.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::Route53Resolver::FirewallRuleGroup.FirewallRule": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-route53resolver-firewallrulegroup-firewallrule.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_S3.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_S3.json index 784346f06e828..3cbb45a36e0bf 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_S3.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_S3.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::S3::AccessPoint.PublicAccessBlockConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-s3-accesspoint-publicaccessblockconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_S3ObjectLambda.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_S3ObjectLambda.json index 345b6e977a03c..a8854f9f8929b 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_S3ObjectLambda.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_S3ObjectLambda.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::S3ObjectLambda::AccessPoint.ObjectLambdaConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-s3objectlambda-accesspoint-objectlambdaconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_S3Outposts.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_S3Outposts.json index a774b29257927..e3b4d3c74ab97 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_S3Outposts.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_S3Outposts.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::S3Outposts::AccessPoint.VpcConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-s3outposts-accesspoint-vpcconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SDB.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SDB.json index a6ee34e7f0c4f..3ae21ad8babc4 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SDB.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SDB.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::SDB::Domain": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SES.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SES.json index 8db59e67a3307..458ac20410732 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SES.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SES.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::SES::ConfigurationSetEventDestination.CloudWatchDestination": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ses-configurationseteventdestination-cloudwatchdestination.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SNS.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SNS.json index acab0a31e8539..8d7fe41bf4807 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SNS.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SNS.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::SNS::Topic.Subscription": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sns-subscription.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SQS.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SQS.json index 3b5f657277657..822ddd7bf2ba9 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SQS.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SQS.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::SQS::Queue": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SSM.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SSM.json index db171e7996356..dcf958b637e95 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SSM.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SSM.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::SSM::Association.InstanceAssociationOutputLocation": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ssm-association-instanceassociationoutputlocation.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SSMContacts.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SSMContacts.json index a54e05e780f70..59e2f2305f919 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SSMContacts.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SSMContacts.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::SSMContacts::Contact.ChannelTargetInfo": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ssmcontacts-contact-channeltargetinfo.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SSMIncidents.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SSMIncidents.json index 143751b426c4b..54bff1c699a44 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SSMIncidents.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SSMIncidents.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::SSMIncidents::ReplicationSet.RegionConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ssmincidents-replicationset-regionconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SSO.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SSO.json index 7402e84813c1f..065fb33419e4c 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SSO.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SSO.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::SSO::InstanceAccessControlAttributeConfiguration.AccessControlAttribute": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sso-instanceaccesscontrolattributeconfiguration-accesscontrolattribute.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SageMaker.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SageMaker.json index ecbc09c59afc1..0972225ee2065 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SageMaker.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SageMaker.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::SageMaker::App.ResourceSpec": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sagemaker-app-resourcespec.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SecretsManager.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SecretsManager.json index ceb828a9e5314..85e8bb7215378 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SecretsManager.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SecretsManager.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::SecretsManager::RotationSchedule.HostedRotationLambda": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-secretsmanager-rotationschedule-hostedrotationlambda.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SecurityHub.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SecurityHub.json index 1944ad7dc36be..d77633b0a98a8 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SecurityHub.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SecurityHub.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::SecurityHub::Hub": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ServiceCatalog.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ServiceCatalog.json index 2b1fa34018936..89e18fda9794d 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ServiceCatalog.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ServiceCatalog.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::ServiceCatalog::CloudFormationProduct.ProvisioningArtifactProperties": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-servicecatalog-cloudformationproduct-provisioningartifactproperties.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ServiceCatalogAppRegistry.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ServiceCatalogAppRegistry.json index 6edef3804ffa4..6d78e56d74e49 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ServiceCatalogAppRegistry.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ServiceCatalogAppRegistry.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::ServiceCatalogAppRegistry::Application": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ServiceDiscovery.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ServiceDiscovery.json index e4421cdf782ae..069c3c401ab09 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ServiceDiscovery.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ServiceDiscovery.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::ServiceDiscovery::PrivateDnsNamespace.PrivateDnsPropertiesMutable": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-servicediscovery-privatednsnamespace-privatednspropertiesmutable.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Signer.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Signer.json index 98366919b3562..377cadb96a98b 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Signer.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Signer.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::Signer::SigningProfile.SignatureValidityPeriod": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-signer-signingprofile-signaturevalidityperiod.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_StepFunctions.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_StepFunctions.json index 4c6f1bfd17166..c4c85447bfe6d 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_StepFunctions.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_StepFunctions.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::StepFunctions::Activity.TagsEntry": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-stepfunctions-activity-tagsentry.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Synthetics.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Synthetics.json index c6de2dca2e115..fa0af32bb32a1 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Synthetics.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Synthetics.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::Synthetics::Canary.ArtifactConfig": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-synthetics-canary-artifactconfig.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Timestream.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Timestream.json index a3c124bc24f27..f5292aa0bca38 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Timestream.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Timestream.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::Timestream::ScheduledQuery.DimensionMapping": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-timestream-scheduledquery-dimensionmapping.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Transfer.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Transfer.json index 70a2015341992..ea367242272af 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Transfer.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Transfer.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::Transfer::Server.EndpointDetails": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-transfer-server-endpointdetails.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_WAF.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_WAF.json index d9fb583709813..b1e04253166a0 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_WAF.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_WAF.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::WAF::ByteMatchSet.ByteMatchTuple": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-waf-bytematchset-bytematchtuples.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_WAFRegional.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_WAFRegional.json index 200b02ac40492..aace044f4e39e 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_WAFRegional.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_WAFRegional.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::WAFRegional::ByteMatchSet.ByteMatchTuple": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-wafregional-bytematchset-bytematchtuple.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_WAFv2.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_WAFv2.json index 232aceb58e101..8d3c7ab99387c 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_WAFv2.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_WAFv2.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::WAFv2::LoggingConfiguration.FieldToMatch": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-wafv2-loggingconfiguration-fieldtomatch.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Wisdom.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Wisdom.json index a8b61664c5b41..4e5aaf71b1512 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Wisdom.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Wisdom.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::Wisdom::Assistant.ServerSideEncryptionConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-wisdom-assistant-serversideencryptionconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_WorkSpaces.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_WorkSpaces.json index a13dfdce3e0a0..bcc704cf09e7a 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_WorkSpaces.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_WorkSpaces.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::WorkSpaces::ConnectionAlias.ConnectionAliasAssociation": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-workspaces-connectionalias-connectionaliasassociation.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_XRay.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_XRay.json index 1c86fc70f1e90..fa8f39f841c3d 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_XRay.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_XRay.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "AWS::XRay::Group.InsightsConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-xray-group-insightsconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_Alexa_ASK.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_Alexa_ASK.json index 911baf91989c0..37b81dd9b80a9 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_Alexa_ASK.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_Alexa_ASK.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "Alexa::ASK::Skill.AuthenticationConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ask-skill-authenticationconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_Tag.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_Tag.json index 8391e097f9f8d..d66f999a231e5 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_Tag.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_Tag.json @@ -1,5 +1,5 @@ { - "$version": "58.0.0", + "$version": "59.0.0", "PropertyTypes": { "Tag": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-resource-tags.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/001_Version.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/001_Version.json index 86492b0d7be4e..c3a7ac47632f6 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/001_Version.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/001_Version.json @@ -1,3 +1,3 @@ { - "ResourceSpecificationVersion": "58.0.0" + "ResourceSpecificationVersion": "59.0.0" } diff --git a/packages/@aws-cdk/core/lib/asset-staging.ts b/packages/@aws-cdk/core/lib/asset-staging.ts index a80dcb562432d..b6a84d9af0961 100644 --- a/packages/@aws-cdk/core/lib/asset-staging.ts +++ b/packages/@aws-cdk/core/lib/asset-staging.ts @@ -4,7 +4,6 @@ import * as path from 'path'; import * as cxapi from '@aws-cdk/cx-api'; import { Construct } from 'constructs'; import * as fs from 'fs-extra'; -import * as minimatch from 'minimatch'; import { AssetHashType, AssetOptions, FileAssetPackaging } from './assets'; import { BundlingOptions, BundlingOutput } from './bundling'; import { FileSystem, FingerprintOptions } from './fs'; @@ -184,9 +183,7 @@ export class AssetStaging extends Construct { let skip = false; if (props.bundling) { // Check if we actually have to bundle for this stack - const bundlingStacks: string[] = this.node.tryGetContext(cxapi.BUNDLING_STACKS) ?? ['*']; - // bundlingStacks is of the form `Stage/Stack`, convert it to `Stage-Stack` before comparing to stack name - skip = !bundlingStacks.find(pattern => minimatch(Stack.of(this).stackName, pattern.replace('/', '-'))); + skip = !Stack.of(this).bundlingRequired; const bundling = props.bundling; stageThisAsset = () => this.stageByBundling(bundling, skip); } else { diff --git a/packages/@aws-cdk/core/lib/stack.ts b/packages/@aws-cdk/core/lib/stack.ts index e3d92c1d750a0..4a83831793e11 100644 --- a/packages/@aws-cdk/core/lib/stack.ts +++ b/packages/@aws-cdk/core/lib/stack.ts @@ -3,6 +3,7 @@ import * as path from 'path'; import * as cxschema from '@aws-cdk/cloud-assembly-schema'; import * as cxapi from '@aws-cdk/cx-api'; import { IConstruct, Construct, Node } from 'constructs'; +import * as minimatch from 'minimatch'; import { Annotations } from './annotations'; import { App } from './app'; import { Arn, ArnComponents, ArnFormat } from './arn'; @@ -1148,6 +1149,19 @@ export class Stack extends Construct implements ITaggable { return makeStackName(ids); } + + /** + * Indicates whether the stack requires bundling or not + */ + public get bundlingRequired() { + const bundlingStacks: string[] = this.node.tryGetContext(cxapi.BUNDLING_STACKS) ?? ['*']; + + // bundlingStacks is of the form `Stage/Stack`, convert it to `Stage-Stack` before comparing to stack name + return bundlingStacks.some(pattern => minimatch( + this.stackName, + pattern.replace('/', '-'), + )); + } } function merge(template: any, fragment: any): void { diff --git a/packages/@aws-cdk/core/test/stack.test.ts b/packages/@aws-cdk/core/test/stack.test.ts index 4ee11b649f24a..e6e6b2f650b1e 100644 --- a/packages/@aws-cdk/core/test/stack.test.ts +++ b/packages/@aws-cdk/core/test/stack.test.ts @@ -1171,6 +1171,38 @@ describe('stack', () => { expect(new Stack(app, 'Stack', { analyticsReporting: true })._versionReportingEnabled).toBeDefined(); }); + + test('requires bundling when wildcard is specified in BUNDLING_STACKS', () => { + const app = new App(); + const stack = new Stack(app, 'Stack'); + stack.node.setContext(cxapi.BUNDLING_STACKS, ['*']); + expect(stack.bundlingRequired).toBe(true); + + }); + + test('requires bundling when stackName has an exact match in BUNDLING_STACKS', () => { + const app = new App(); + const stack = new Stack(app, 'Stack'); + stack.node.setContext(cxapi.BUNDLING_STACKS, ['Stack']); + expect(stack.bundlingRequired).toBe(true); + + }); + + test('does not require bundling when no item from BUILDING_STACKS matches stackName', () => { + const app = new App(); + const stack = new Stack(app, 'Stack'); + stack.node.setContext(cxapi.BUNDLING_STACKS, ['Stac']); + expect(stack.bundlingRequired).toBe(false); + + }); + + test('does not require bundling when BUNDLING_STACKS is empty', () => { + const app = new App(); + const stack = new Stack(app, 'Stack'); + stack.node.setContext(cxapi.BUNDLING_STACKS, []); + expect(stack.bundlingRequired).toBe(false); + + }); }); describe('regionalFact', () => { diff --git a/packages/@aws-cdk/lambda-layer-awscli/layer/requirements.txt b/packages/@aws-cdk/lambda-layer-awscli/layer/requirements.txt index 2550f9594c2c7..96070a4e696a9 100644 --- a/packages/@aws-cdk/lambda-layer-awscli/layer/requirements.txt +++ b/packages/@aws-cdk/lambda-layer-awscli/layer/requirements.txt @@ -1 +1 @@ -awscli==1.22.63 +awscli==1.22.68 diff --git a/packages/@aws-cdk/pipelines/lib/codepipeline/codepipeline-source.ts b/packages/@aws-cdk/pipelines/lib/codepipeline/codepipeline-source.ts index 062df5b4b446f..0f95d41f5c940 100644 --- a/packages/@aws-cdk/pipelines/lib/codepipeline/codepipeline-source.ts +++ b/packages/@aws-cdk/pipelines/lib/codepipeline/codepipeline-source.ts @@ -139,21 +139,27 @@ export abstract class CodePipelineSource extends Step implements ICodePipelineAc * What attributes are available depends on the type of source. These attributes * are supported: * - * - GitHub, CodeCommit, and CodeStar connection + * - GitHub, CodeCommit, and CodeStarSourceConnection * - `AuthorDate` * - `BranchName` * - `CommitId` * - `CommitMessage` + * - GitHub, CodeCommit and ECR + * - `RepositoryName` * - GitHub and CodeCommit * - `CommitterDate` - * - `RepositoryName` * - GitHub * - `CommitUrl` - * - CodeStar Connection + * - CodeStarSourceConnection * - `FullRepositoryName` * - S3 * - `ETag` * - `VersionId` + * - ECR + * - `ImageDigest` + * - `ImageTag` + * - `ImageURI` + * - `RegistryId` * * @see https://docs.aws.amazon.com/codepipeline/latest/userguide/reference-variables.html#reference-variables-list */ diff --git a/packages/aws-cdk/lib/api/logs/logs-monitor.ts b/packages/aws-cdk/lib/api/logs/logs-monitor.ts index f6f2086bc20bf..9ad1ed393f5ce 100644 --- a/packages/aws-cdk/lib/api/logs/logs-monitor.ts +++ b/packages/aws-cdk/lib/api/logs/logs-monitor.ts @@ -198,10 +198,11 @@ export class CloudWatchLogEventMonitor { } } - // if we have > 100 events let the user know some - // messages have been supressed. We are essentially - // showing them a sampling (10000 events printed out is not very useful) - if (filteredEvents.length > 0 && response.nextToken) { + // As long as there are _any_ events in the log group `filterLogEvents` will return a nextToken. + // This is true even if these events are before `startTime`. So if we have 100 events and a nextToken + // then assume that we have hit the limit and let the user know some messages have been supressed. + // We are essentially showing them a sampling (10000 events printed out is not very useful) + if (filteredEvents.length === 100 && response.nextToken) { events.push({ message: '>>> `watch` shows only the first 100 log messages - the rest have been truncated...', logGroupName, diff --git a/packages/aws-cdk/lib/cdk-toolkit.ts b/packages/aws-cdk/lib/cdk-toolkit.ts index 6d95bb76ac81b..3d9901a0610fe 100644 --- a/packages/aws-cdk/lib/cdk-toolkit.ts +++ b/packages/aws-cdk/lib/cdk-toolkit.ts @@ -450,7 +450,7 @@ export class CdkToolkit { // not outputting template to stdout, let's explain things to the user a little bit... success(`Successfully synthesized to ${chalk.blue(path.resolve(stacks.assembly.directory))}`); - print(`Supply a stack id (${stacks.stackArtifacts.map(s => chalk.green(s.id)).join(', ')}) to display its template.`); + print(`Supply a stack id (${stacks.stackArtifacts.map(s => chalk.green(s.hierarchicalId)).join(', ')}) to display its template.`); return undefined; } diff --git a/packages/aws-cdk/lib/cli.ts b/packages/aws-cdk/lib/cli.ts index f63c60ca5ced0..00b9c16d4017b 100644 --- a/packages/aws-cdk/lib/cli.ts +++ b/packages/aws-cdk/lib/cli.ts @@ -235,10 +235,6 @@ if (!process.stdout.isTTY) { } async function initCommandLine() { - void refreshNotices() - .then(_ => debug('Notices refreshed')) - .catch(e => debug(`Notices refresh failed: ${e}`)); - const argv = await parseCommandLineArguments(); if (argv.verbose) { setLogLevel(argv.verbose); @@ -254,6 +250,12 @@ async function initCommandLine() { }); await configuration.load(); + if (shouldDisplayNotices()) { + void refreshNotices() + .then(_ => debug('Notices refreshed')) + .catch(e => debug(`Notices refresh failed: ${e}`)); + } + const sdkProvider = await SdkProvider.withAwsCliCompatibleDefaults({ profile: configuration.settings.get(['profile']), ec2creds: argv.ec2creds, @@ -326,10 +328,10 @@ async function initCommandLine() { }); } } + } - function shouldDisplayNotices(): boolean { - return configuration.settings.get(['notices']) ?? true; - } + function shouldDisplayNotices(): boolean { + return configuration.settings.get(['notices']) ?? true; } async function main(command: string, args: any): Promise { diff --git a/packages/aws-cdk/lib/notices.ts b/packages/aws-cdk/lib/notices.ts index 83b38412aa87b..fd92f4bf853c0 100644 --- a/packages/aws-cdk/lib/notices.ts +++ b/packages/aws-cdk/lib/notices.ts @@ -43,13 +43,14 @@ export async function displayNotices(props: DisplayNoticesProps) { export async function generateMessage(dataSource: NoticeDataSource, props: DisplayNoticesProps) { const data = await dataSource.fetch(); - const individualMessages = formatNotices(filterNotices(data, { + const filteredNotices = filterNotices(data, { outdir: props.outdir, acknowledgedIssueNumbers: new Set(props.acknowledgedIssueNumbers), - })); + }); - if (individualMessages.length > 0) { - return finalMessage(individualMessages, data[0].issueNumber); + if (filteredNotices.length > 0) { + const individualMessages = formatNotices(filteredNotices); + return finalMessage(individualMessages, filteredNotices[0].issueNumber); } return ''; } @@ -108,18 +109,15 @@ export class WebsiteNoticeDataSource implements NoticeDataSource { const timeout = 3000; return new Promise((resolve) => { + setTimeout(() => resolve([]), timeout); try { const req = https.get('https://cli.cdk.dev-tools.aws.dev/notices.json', { timeout }, res => { - const startTime = Date.now(); if (res.statusCode === 200) { res.setEncoding('utf8'); let rawData = ''; res.on('data', (chunk) => { - if (Date.now() - startTime > timeout) { - resolve([]); - } rawData += chunk; }); res.on('end', () => { diff --git a/packages/aws-cdk/test/api/logs/logs-monitor.test.ts b/packages/aws-cdk/test/api/logs/logs-monitor.test.ts index 930e6427dbab7..eed3cf2683540 100644 --- a/packages/aws-cdk/test/api/logs/logs-monitor.test.ts +++ b/packages/aws-cdk/test/api/logs/logs-monitor.test.ts @@ -12,18 +12,55 @@ beforeEach(() => { sdk = new MockSdk(); }); -afterAll(() => { +afterEach(() => { stderrMock.mockRestore(); monitor.deactivate(); }); -test('continue to the next page if it exists', async () => { +test('process events', async () => { // GIVEN const eventDate = new Date(T0 + 102 * 1000); sdk.stubCloudWatchLogs({ filterLogEvents() { return { events: [event(102, 'message', eventDate)], + }; + }, + }); + monitor.addLogGroups( + { + name: 'name', + account: '11111111111', + region: 'us-east-1', + }, + sdk, + ['loggroup'], + ); + // WHEN + monitor.activate(); + // need time for the log processing to occur + await sleep(1000); + + // THEN + const expectedLocaleTimeString = eventDate.toLocaleTimeString(); + expect(stderrMock).toHaveBeenCalledTimes(1); + expect(stderrMock.mock.calls[0][0]).toContain( + `[${blue('loggroup')}] ${yellow(expectedLocaleTimeString)} message`, + ); +}); + +test('process truncated events', async () => { + // GIVEN + const eventDate = new Date(T0 + 102 * 1000); + const events: AWS.CloudWatchLogs.FilteredLogEvents = []; + for (let i = 0; i < 100; i++) { + events.push(event(102+i, 'message' + i, eventDate)); + } + + sdk.stubCloudWatchLogs({ + filterLogEvents() { + return { + events, nextToken: 'some-token', }; }, @@ -44,11 +81,11 @@ test('continue to the next page if it exists', async () => { // THEN const expectedLocaleTimeString = eventDate.toLocaleTimeString(); - expect(stderrMock).toHaveBeenCalledTimes(2); + expect(stderrMock).toHaveBeenCalledTimes(101); expect(stderrMock.mock.calls[0][0]).toContain( `[${blue('loggroup')}] ${yellow(expectedLocaleTimeString)} message`, ); - expect(stderrMock.mock.calls[1][0]).toContain( + expect(stderrMock.mock.calls[100][0]).toContain( `[${blue('loggroup')}] ${yellow(expectedLocaleTimeString)} >>> \`watch\` shows only the first 100 log messages - the rest have been truncated...`, ); }); diff --git a/packages/aws-cdk/test/cdk-toolkit.test.ts b/packages/aws-cdk/test/cdk-toolkit.test.ts index f87ab3e76499c..52922d51ed50f 100644 --- a/packages/aws-cdk/test/cdk-toolkit.test.ts +++ b/packages/aws-cdk/test/cdk-toolkit.test.ts @@ -66,6 +66,7 @@ import { instanceMockFrom, MockCloudExecutable, TestStackArtifact } from './util let cloudExecutable: MockCloudExecutable; let bootstrapper: jest.Mocked; +let stderrMock: jest.SpyInstance; beforeEach(() => { jest.resetAllMocks(); @@ -86,6 +87,7 @@ beforeEach(() => { }], }); + stderrMock = jest.spyOn(process.stderr, 'write').mockImplementation(() => { return true; }); }); function defaultToolkitSetup() { @@ -105,9 +107,7 @@ describe('readCurrentTemplate', () => { let template: any; let mockForEnvironment = jest.fn(); let mockCloudExecutable: MockCloudExecutable; - let stderrMock: jest.SpyInstance; beforeEach(() => { - stderrMock = jest.spyOn(process.stderr, 'write').mockImplementation(() => { return true; }); template = { Resources: { @@ -409,7 +409,7 @@ describe('deploy', () => { // WHEN await cdkToolkit.deploy({ - selector: { patterns: ['Test-Stack-A'] }, + selector: { patterns: ['Test-Stack-A-Display-Name'] }, requireApproval: RequireApproval.Never, hotswap: true, }); @@ -444,7 +444,7 @@ describe('deploy', () => { const toolkit = defaultToolkitSetup(); // WHEN - await toolkit.deploy({ selector: { patterns: ['Test-Stack-A'] } }); + await toolkit.deploy({ selector: { patterns: ['Test-Stack-A-Display-Name'] } }); }); test('with stacks all stacks specified as wildcard', async () => { @@ -677,12 +677,19 @@ describe('watch', () => { }); describe('synth', () => { + test('successful synth outputs hierarchical stack ids', async () => { + const toolkit = defaultToolkitSetup(); + await toolkit.synth([], false, false); + + expect(stderrMock.mock.calls[1][0]).toMatch('Test-Stack-A-Display-Name, Test-Stack-B'); + }); + test('with no stdout option', async () => { // GIVE const toolkit = defaultToolkitSetup(); // THEN - await toolkit.synth(['Test-Stack-A'], false, true); + await toolkit.synth(['Test-Stack-A-Display-Name'], false, true); expect(mockData.mock.calls.length).toEqual(0); }); @@ -787,6 +794,7 @@ class MockStack { }, ], }, + displayName: 'Test-Stack-A-Display-Name', }; public static readonly MOCK_STACK_B: TestStackArtifact = { stackName: 'Test-Stack-B', diff --git a/packages/aws-cdk/test/integ/cli/cli.integtest.ts b/packages/aws-cdk/test/integ/cli/cli.integtest.ts index a0deaf1b3c3bc..42a4f55729a97 100644 --- a/packages/aws-cdk/test/integ/cli/cli.integtest.ts +++ b/packages/aws-cdk/test/integ/cli/cli.integtest.ts @@ -757,6 +757,20 @@ integTest('templates on disk contain metadata resource, also in nested assemblie expect(JSON.parse(nestedTemplateContents).Resources.CDKMetadata).toBeTruthy(); })); +integTest('skips notice refresh', withDefaultFixture(async (fixture) => { + const output = await fixture.cdkSynth({ + options: ['--no-notices'], + modEnv: { + INTEG_STACK_SET: 'stage-using-context', + }, + allowErrExit: true, + }); + + // Neither succeeds nor fails, but skips the refresh + await expect(output).not.toContain('Notices refreshed'); + await expect(output).not.toContain('Notices refresh failed'); +})); + async function listChildren(parent: string, pred: (x: string) => Promise) { const ret = new Array(); for (const child of await fs.readdir(parent, { encoding: 'utf-8' })) { diff --git a/packages/aws-cdk/test/integ/run-against-release b/packages/aws-cdk/test/integ/run-against-release index 1e4c0a8b3aba1..5bfcbbfae7e4f 100755 --- a/packages/aws-cdk/test/integ/run-against-release +++ b/packages/aws-cdk/test/integ/run-against-release @@ -5,6 +5,16 @@ # - Run the script set -eu scriptdir=$(cd $(dirname $0) && pwd) +CLI_INSTALLER="${CLI_INSTALLER:=npm}" + +if [ ${CLI_INSTALLER} = "npm" ]; then + install_command="install" +elif [ ${CLI_INSTALLER} = "yarn" ]; then + install_command="add" +else + echo "CLI_INSTALLER can only be set to either npm or yarn (got ${CLI_INSTALLER})" + exit 1 +fi # NPM Workspace. Will have CDK CLI installed into it. npmws=/tmp/cdk-runrelease @@ -12,7 +22,7 @@ rm -rf $npmws mkdir -p $npmws # Install the CLI and put it on the PATH -(cd $npmws && npm install aws-cdk@${RELEASE_TAG:-latest}) +(cd $npmws && ${CLI_INSTALLER} ${install_command} aws-cdk@${RELEASE_TAG:-latest}) # FRAMEWORK_VERSION is the version that will be 'npm install'ed by the tests if [[ "${FRAMEWORK_VERSION:-}" = "" ]]; then diff --git a/tools/@aws-cdk/pkglint/lib/rules.ts b/tools/@aws-cdk/pkglint/lib/rules.ts index 0fcab212fdec2..1952ffb80269e 100644 --- a/tools/@aws-cdk/pkglint/lib/rules.ts +++ b/tools/@aws-cdk/pkglint/lib/rules.ts @@ -1690,6 +1690,7 @@ export class NoExperimentalDependents extends ValidationRule { ['@aws-cdk/aws-events-targets', ['@aws-cdk/aws-kinesisfirehose']], ['@aws-cdk/aws-kinesisfirehose-destinations', ['@aws-cdk/aws-kinesisfirehose']], ['@aws-cdk/aws-iot-actions', ['@aws-cdk/aws-iot', '@aws-cdk/aws-kinesisfirehose']], + ['@aws-cdk/aws-iotevents-actions', ['@aws-cdk/aws-iotevents']], ]); private readonly excludedModules = ['@aws-cdk/cloudformation-include']; diff --git a/version.v1.json b/version.v1.json index d726bab6ab46f..e4f7b428d4641 100644 --- a/version.v1.json +++ b/version.v1.json @@ -1,3 +1,3 @@ { - "version": "1.146.0" + "version": "1.147.0" } \ No newline at end of file diff --git a/version.v2.json b/version.v2.json index af85e9d5c4b76..e85d253f9ffab 100644 --- a/version.v2.json +++ b/version.v2.json @@ -1,4 +1,4 @@ { - "version": "2.15.0", - "alphaVersion": "2.15.0-alpha.0" + "version": "2.16.0", + "alphaVersion": "2.16.0-alpha.0" } \ No newline at end of file