diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 489ffe35943a0..cf357ce6d7680 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -977,6 +977,7 @@ Adding a new flag looks as follows: your description, be sure to cover the following: - Consciously pick the type of feature flag. Can the flag be removed in a future major version, or not? - Motivate why the feature flag exists. What is the change to existing infrastructure and why is it not safe? + - In case of a "default change flag", describe what the user needs to do to restore the old behavior. 4. Add an entry for your feature flag in the [README](https://github.com/aws/aws-cdk/blob/main/packages/%40aws-cdk/cx-api/README.md) file. 5. In your tests, ensure that you test your feature with and without the feature flag enabled. You can do this by passing the feature flag to the `context` property when instantiating an `App`. ```ts diff --git a/packages/@aws-cdk/cx-api/FEATURE_FLAGS.md b/packages/@aws-cdk/cx-api/FEATURE_FLAGS.md index 5bd7e9a7717c8..30a52f8b5889f 100644 --- a/packages/@aws-cdk/cx-api/FEATURE_FLAGS.md +++ b/packages/@aws-cdk/cx-api/FEATURE_FLAGS.md @@ -5,7 +5,7 @@ Feature flags are [context values](https://docs.aws.amazon.com/cdk/v2/guide/context.html) and can be configured using any of the context management methods, at any level of the construct tree. Commonly, they are specified in the `cdk.json` file. `cdk init` will create new CDK projects with a `cdk.json` file containing all recommended feature flags enabled. -## Feature flag table +## Current list of feature flags Flags come in three types: @@ -15,59 +15,318 @@ Flags come in three types: -| Flag | Summary | Since | Type | Recommended | -| ----- | ----- | ----- | ----- | ----- | -| @aws-cdk/core:newStyleStackSynthesis | Switch to new stack synthesis method which enables CI/CD | 2.0.0 | (fix) | `true` | -| @aws-cdk/core:stackRelativeExports | Name exports based on the construct paths relative to the stack, rather than the global construct path | 2.0.0 | (fix) | `true` | -| @aws-cdk/aws-rds:lowercaseDbIdentifier | Force lowercasing of RDS Cluster names in CDK | 2.0.0 | (fix) | `true` | -| @aws-cdk/aws-apigateway:usagePlanKeyOrderInsensitiveId | Allow adding/removing multiple UsagePlanKeys independently | 2.0.0 | (fix) | `true` | -| @aws-cdk/aws-lambda:recognizeVersionProps | Enable this feature flag to opt in to the updated logical id calculation for Lambda Version created using the `fn.currentVersion`. | 2.0.0 | (fix) | `true` | -| @aws-cdk/aws-cloudfront:defaultSecurityPolicyTLSv1.2_2021 | Enable this feature flag to have cloudfront distributions use the security policy TLSv1.2_2021 by default. | 2.0.0 | (fix) | `true` | -| @aws-cdk/core:target-partitions | What regions to include in lookup tables of environment agnostic stacks | 2.4.0 | (config) | `["aws","aws-cn"]` | -| @aws-cdk-containers/ecs-service-extensions:enableDefaultLogDriver | ECS extensions will automatically add an `awslogs` driver if no logging is specified | 2.8.0 | (default) | `true` | -| @aws-cdk/aws-ec2:uniqueImdsv2TemplateName | Enable this feature flag to have Launch Templates generated by the `InstanceRequireImdsv2Aspect` use unique names. | 2.8.0 | (fix) | `true` | -| @aws-cdk/aws-iam:minimizePolicies | Minimize IAM policies by combining Statements | 2.18.0 | (config) | `true` | -| @aws-cdk/core:checkSecretUsage | Enable this flag to make it impossible to accidentally use SecretValues in unsafe locations | 2.21.0 | (config) | `true` | -| @aws-cdk/aws-lambda:recognizeLayerVersion | Enable this feature flag to opt in to the updated logical id calculation for Lambda Version created using the `fn.currentVersion`. | 2.27.0 | (fix) | `true` | -| @aws-cdk/core:validateSnapshotRemovalPolicy | Error on snapshot removal policies on resources that do not support it. | 2.28.0 | (default) | `true` | -| @aws-cdk/aws-codepipeline:crossAccountKeyAliasStackSafeResourceName | Generate key aliases that include the stack name | 2.29.0 | (fix) | `true` | -| @aws-cdk/aws-s3:createDefaultLoggingPolicy | Enable this feature flag to create an S3 bucket policy by default in cases where an AWS service would automatically create the Policy if one does not exist. | 2.31.0 | (fix) | `true` | -| @aws-cdk/aws-sns-subscriptions:restrictSqsDescryption | Restrict KMS key policy for encrypted Queues a bit more | 2.32.0 | (fix) | `true` | -| @aws-cdk/aws-ecs:arnFormatIncludesClusterName | ARN format used by ECS. In the new ARN format, the cluster name is part of the resource ID. | 2.35.0 | (fix) | `true` | -| @aws-cdk/aws-apigateway:disableCloudWatchRole | Make default CloudWatch Role behavior safe for multiple API Gateways in one environment | 2.38.0 | (fix) | `true` | -| @aws-cdk/core:enablePartitionLiterals | Make ARNs concrete if AWS partition is known | 2.38.0 | (fix) | `true` | -| @aws-cdk/aws-events:eventsTargetQueueSameAccount | Event Rules may only push to encrypted SQS queues in the same account | 2.51.0 | (fix) | `true` | +| Flag | Summary | Since | Type | +| ----- | ----- | ----- | ----- | +| [@aws-cdk/core:newStyleStackSynthesis](#aws-cdkcorenewstylestacksynthesis) | Switch to new stack synthesis method which enables CI/CD | 2.0.0 | (fix) | +| [@aws-cdk/core:stackRelativeExports](#aws-cdkcorestackrelativeexports) | Name exports based on the construct paths relative to the stack, rather than the global construct path | 2.0.0 | (fix) | +| [@aws-cdk/aws-rds:lowercaseDbIdentifier](#aws-cdkaws-rdslowercasedbidentifier) | Force lowercasing of RDS Cluster names in CDK | 2.0.0 | (fix) | +| [@aws-cdk/aws-apigateway:usagePlanKeyOrderInsensitiveId](#aws-cdkaws-apigatewayusageplankeyorderinsensitiveid) | Allow adding/removing multiple UsagePlanKeys independently | 2.0.0 | (fix) | +| [@aws-cdk/aws-lambda:recognizeVersionProps](#aws-cdkaws-lambdarecognizeversionprops) | Enable this feature flag to opt in to the updated logical id calculation for Lambda Version created using the `fn.currentVersion`. | 2.0.0 | (fix) | +| [@aws-cdk/aws-cloudfront:defaultSecurityPolicyTLSv1.2\_2021](#aws-cdkaws-cloudfrontdefaultsecuritypolicytlsv12_2021) | Enable this feature flag to have cloudfront distributions use the security policy TLSv1.2_2021 by default. | 2.0.0 | (fix) | +| [@aws-cdk/core:target-partitions](#aws-cdkcoretarget-partitions) | What regions to include in lookup tables of environment agnostic stacks | 2.4.0 | (config) | +| [@aws-cdk-containers/ecs-service-extensions:enableDefaultLogDriver](#aws-cdk-containersecs-service-extensionsenabledefaultlogdriver) | ECS extensions will automatically add an `awslogs` driver if no logging is specified | 2.8.0 | (default) | +| [@aws-cdk/aws-ec2:uniqueImdsv2TemplateName](#aws-cdkaws-ec2uniqueimdsv2templatename) | Enable this feature flag to have Launch Templates generated by the `InstanceRequireImdsv2Aspect` use unique names. | 2.8.0 | (fix) | +| [@aws-cdk/aws-iam:minimizePolicies](#aws-cdkaws-iamminimizepolicies) | Minimize IAM policies by combining Statements | 2.18.0 | (config) | +| [@aws-cdk/core:checkSecretUsage](#aws-cdkcorechecksecretusage) | Enable this flag to make it impossible to accidentally use SecretValues in unsafe locations | 2.21.0 | (config) | +| [@aws-cdk/aws-lambda:recognizeLayerVersion](#aws-cdkaws-lambdarecognizelayerversion) | Enable this feature flag to opt in to the updated logical id calculation for Lambda Version created using the `fn.currentVersion`. | 2.27.0 | (fix) | +| [@aws-cdk/core:validateSnapshotRemovalPolicy](#aws-cdkcorevalidatesnapshotremovalpolicy) | Error on snapshot removal policies on resources that do not support it. | 2.28.0 | (default) | +| [@aws-cdk/aws-codepipeline:crossAccountKeyAliasStackSafeResourceName](#aws-cdkaws-codepipelinecrossaccountkeyaliasstacksaferesourcename) | Generate key aliases that include the stack name | 2.29.0 | (fix) | +| [@aws-cdk/aws-s3:createDefaultLoggingPolicy](#aws-cdkaws-s3createdefaultloggingpolicy) | Enable this feature flag to create an S3 bucket policy by default in cases where an AWS service would automatically create the Policy if one does not exist. | 2.31.0 | (fix) | +| [@aws-cdk/aws-sns-subscriptions:restrictSqsDescryption](#aws-cdkaws-sns-subscriptionsrestrictsqsdescryption) | Restrict KMS key policy for encrypted Queues a bit more | 2.32.0 | (fix) | +| [@aws-cdk/aws-ecs:arnFormatIncludesClusterName](#aws-cdkaws-ecsarnformatincludesclustername) | ARN format used by ECS. In the new ARN format, the cluster name is part of the resource ID. | 2.35.0 | (fix) | +| [@aws-cdk/aws-apigateway:disableCloudWatchRole](#aws-cdkaws-apigatewaydisablecloudwatchrole) | Make default CloudWatch Role behavior safe for multiple API Gateways in one environment | 2.38.0 | (fix) | +| [@aws-cdk/core:enablePartitionLiterals](#aws-cdkcoreenablepartitionliterals) | Make ARNs concrete if AWS partition is known | 2.38.0 | (fix) | +| [@aws-cdk/aws-events:eventsTargetQueueSameAccount](#aws-cdkaws-eventseventstargetqueuesameaccount) | Event Rules may only push to encrypted SQS queues in the same account | 2.51.0 | (fix) | +## Currently recommended cdk.json + +The following json shows the current recommended set of flags, as `cdk init` would generate it for new projects. + + +```json +{ + "context": { + "@aws-cdk/aws-lambda:recognizeLayerVersion": true, + "@aws-cdk/core:checkSecretUsage": true, + "@aws-cdk/core:target-partitions": [ + "aws", + "aws-cn" + ], + "@aws-cdk-containers/ecs-service-extensions:enableDefaultLogDriver": true, + "@aws-cdk/aws-ec2:uniqueImdsv2TemplateName": true, + "@aws-cdk/aws-ecs:arnFormatIncludesClusterName": true, + "@aws-cdk/aws-iam:minimizePolicies": true, + "@aws-cdk/core:validateSnapshotRemovalPolicy": true, + "@aws-cdk/aws-codepipeline:crossAccountKeyAliasStackSafeResourceName": true, + "@aws-cdk/aws-s3:createDefaultLoggingPolicy": true, + "@aws-cdk/aws-sns-subscriptions:restrictSqsDescryption": true, + "@aws-cdk/aws-apigateway:disableCloudWatchRole": true, + "@aws-cdk/core:enablePartitionLiterals": true, + "@aws-cdk/aws-events:eventsTargetQueueSameAccount": true + } +} +``` + + +## Flags removed in v2 + +These **default change** flags have been removed in v2. These used to be configurable in v1, but in v2 their +behavior has become the default. Remove these from your `cdk.json` file. If the old behavior is important +for your infrastructure, see the flag's description on how to achieve it. + + + +| Flag | Summary | Type | Since | +| ----- | ----- | ----- | ----- | +| [@aws-cdk/core:enableStackNameDuplicates](#aws-cdkcoreenablestacknameduplicates) | Allow multiple stacks with the same name | (default) | 1.16.0 | +| [aws-cdk:enableDiffNoFail](#aws-cdkenablediffnofail) | Make `cdk diff` not fail when there are differences | (default) | 1.19.0 | +| [@aws-cdk/aws-ecr-assets:dockerIgnoreSupport](#aws-cdkaws-ecr-assetsdockerignoresupport) | DockerImageAsset properly supports `.dockerignore` files by default | (default) | 1.73.0 | +| [@aws-cdk/aws-secretsmanager:parseOwnedSecretName](#aws-cdkaws-secretsmanagerparseownedsecretname) | Fix the referencing of SecretsManager names from ARNs | (default) | 1.77.0 | +| [@aws-cdk/aws-kms:defaultKeyPolicies](#aws-cdkaws-kmsdefaultkeypolicies) | Tighten default KMS key policies | (default) | 1.78.0 | +| [@aws-cdk/aws-s3:grantWriteWithoutAcl](#aws-cdkaws-s3grantwritewithoutacl) | Remove `PutObjectAcl` from Bucket.grantWrite | (default) | 1.85.0 | +| [@aws-cdk/aws-ecs-patterns:removeDefaultDesiredCount](#aws-cdkaws-ecs-patternsremovedefaultdesiredcount) | Do not specify a default DesiredCount for ECS services | (default) | 1.92.0 | +| [@aws-cdk/aws-efs:defaultEncryptionAtRest](#aws-cdkaws-efsdefaultencryptionatrest) | Enable this feature flag to have elastic file systems encrypted at rest by default. | (default) | 1.98.0 | + + + +## Flags with a different default in v2 + +These **fix/deprecation** flags are still configurable in v2, but their default has changed compared to v1. If you +are migrating a v1 CDK project to v2, explicitly set any of these flags which does not currently appear in your +`cdk.json` to `false`, to avoid unexpected infrastructure changes. + + + +| Flag | Summary | Type | Since | v1 default | v2 default | +| ----- | ----- | ----- | ----- | ----- | ----- | +| [@aws-cdk/core:newStyleStackSynthesis](#aws-cdkcorenewstylestacksynthesis) | Switch to new stack synthesis method which enables CI/CD | (fix) | 1.39.0 | `false` | `true` | +| [@aws-cdk/core:stackRelativeExports](#aws-cdkcorestackrelativeexports) | Name exports based on the construct paths relative to the stack, rather than the global construct path | (fix) | 1.58.0 | `false` | `true` | +| [@aws-cdk/aws-rds:lowercaseDbIdentifier](#aws-cdkaws-rdslowercasedbidentifier) | Force lowercasing of RDS Cluster names in CDK | (fix) | 1.97.0 | `false` | `true` | +| [@aws-cdk/aws-apigateway:usagePlanKeyOrderInsensitiveId](#aws-cdkaws-apigatewayusageplankeyorderinsensitiveid) | Allow adding/removing multiple UsagePlanKeys independently | (fix) | 1.98.0 | `false` | `true` | +| [@aws-cdk/aws-lambda:recognizeVersionProps](#aws-cdkaws-lambdarecognizeversionprops) | Enable this feature flag to opt in to the updated logical id calculation for Lambda Version created using the `fn.currentVersion`. | (fix) | 1.106.0 | `false` | `true` | +| [@aws-cdk/aws-cloudfront:defaultSecurityPolicyTLSv1.2\_2021](#aws-cdkaws-cloudfrontdefaultsecuritypolicytlsv12_2021) | Enable this feature flag to have cloudfront distributions use the security policy TLSv1.2_2021 by default. | (fix) | 1.117.0 | `false` | `true` | + + + +Here is an example of a `cdk.json` file that restores v1 behavior for these flags: + + +```json +{ + "context": { + "@aws-cdk/core:newStyleStackSynthesis": false, + "@aws-cdk/core:stackRelativeExports": false, + "@aws-cdk/aws-rds:lowercaseDbIdentifier": false, + "@aws-cdk/aws-apigateway:usagePlanKeyOrderInsensitiveId": false, + "@aws-cdk/aws-lambda:recognizeVersionProps": false, + "@aws-cdk/aws-cloudfront:defaultSecurityPolicyTLSv1.2_2021": false + } +} +``` + ## Feature flag details Here are more details about each of the flags: +### @aws-cdk/core:enableStackNameDuplicates + +*Allow multiple stacks with the same name* (default) + +If this is set, multiple stacks can use the same stack name (e.g. deployed to +different environments). This means that the name of the synthesized template +file will be based on the construct path and not on the defined `stackName` +of the stack. + + +| Since | Default | Recommended | +| ----- | ----- | ----- | +| 1.16.0 | `false` | `true` | +| (default in v2) | `true` | | + +**Compatibility with old behavior:** Pass stack identifiers to the CLI instead of stack names. + + +### aws-cdk:enableDiffNoFail + +*Make `cdk diff` not fail when there are differences* (default) + +Determines what status code `cdk diff` should return when the specified stack +differs from the deployed stack or the local CloudFormation template: + +* `aws-cdk:enableDiffNoFail=true` => status code == 0 +* `aws-cdk:enableDiffNoFail=false` => status code == 1 + +You can override this behavior with the --fail flag: + +* `--fail` => status code == 1 +* `--no-fail` => status code == 0 + + +| Since | Default | Recommended | +| ----- | ----- | ----- | +| 1.19.0 | `false` | `true` | +| (default in v2) | `true` | | + +**Compatibility with old behavior:** Specify `--fail` to the CLI. + + +### @aws-cdk/aws-ecr-assets:dockerIgnoreSupport + +*DockerImageAsset properly supports `.dockerignore` files by default* (default) + +If this flag is not set, the default behavior for `DockerImageAsset` is to use +glob semantics for `.dockerignore` files. If this flag is set, the default behavior +is standard Docker ignore semantics. + +This is a feature flag as the old behavior was technically incorrect but +users may have come to depend on it. + + +| Since | Default | Recommended | +| ----- | ----- | ----- | +| 1.73.0 | `false` | `true` | +| (default in v2) | `true` | | + +**Compatibility with old behavior:** Update your `.dockerignore` file to match standard Docker ignore rules, if necessary. + + +### @aws-cdk/aws-secretsmanager:parseOwnedSecretName + +*Fix the referencing of SecretsManager names from ARNs* (default) + +Secret.secretName for an "owned" secret will attempt to parse the secretName from the ARN, +rather than the default full resource name, which includes the SecretsManager suffix. + +If this flag is not set, Secret.secretName will include the SecretsManager suffix, which cannot be directly +used by SecretsManager.DescribeSecret, and must be parsed by the user first (e.g., Fn:Join, Fn:Select, Fn:Split). + + +| Since | Default | Recommended | +| ----- | ----- | ----- | +| 1.77.0 | `false` | `true` | +| (default in v2) | `true` | | + +**Compatibility with old behavior:** Use `parseArn(secret.secretName).resourceName` to emulate the incorrect old parsing. + + +### @aws-cdk/aws-kms:defaultKeyPolicies + +*Tighten default KMS key policies* (default) + +KMS Keys start with a default key policy that grants the account access to administer the key, +mirroring the behavior of the KMS SDK/CLI/Console experience. Users may override the default key +policy by specifying their own. + +If this flag is not set, the default key policy depends on the setting of the `trustAccountIdentities` +flag. If false (the default, for backwards-compatibility reasons), the default key policy somewhat +resembles the default admin key policy, but with the addition of 'GenerateDataKey' permissions. If +true, the policy matches what happens when this feature flag is set. + +Additionally, if this flag is not set and the user supplies a custom key policy, this will be appended +to the key's default policy (rather than replacing it). + + +| Since | Default | Recommended | +| ----- | ----- | ----- | +| 1.78.0 | `false` | `true` | +| (default in v2) | `true` | | + +**Compatibility with old behavior:** Pass `trustAccountIdentities: false` to `Key` construct to restore the old behavior. + + +### @aws-cdk/aws-s3:grantWriteWithoutAcl + +*Remove `PutObjectAcl` from Bucket.grantWrite* (default) + +Change the old 's3:PutObject*' permission to 's3:PutObject' on Bucket, +as the former includes 's3:PutObjectAcl', +which could be used to grant read/write object access to IAM principals in other accounts. +Use a feature flag to make sure existing customers who might be relying +on the overly-broad permissions are not broken. + + +| Since | Default | Recommended | +| ----- | ----- | ----- | +| 1.85.0 | `false` | `true` | +| (default in v2) | `true` | | + +**Compatibility with old behavior:** Call `bucket.grantPutAcl()` in addition to `bucket.grantWrite()` to grant ACL permissions. + + +### @aws-cdk/aws-ecs-patterns:removeDefaultDesiredCount + +*Do not specify a default DesiredCount for ECS services* (default) + +ApplicationLoadBalancedServiceBase, ApplicationMultipleTargetGroupServiceBase, +NetworkLoadBalancedServiceBase, NetworkMultipleTargetGroupServiceBase, and +QueueProcessingServiceBase currently determine a default value for the desired count of +a CfnService if a desiredCount is not provided. The result of this is that on every +deployment, the service count is reset to the fixed value, even if it was autoscaled. + +If this flag is not set, the default behaviour for CfnService.desiredCount is to set a +desiredCount of 1, if one is not provided. If true, a default will not be defined for +CfnService.desiredCount and as such desiredCount will be undefined, if one is not provided. + + +| Since | Default | Recommended | +| ----- | ----- | ----- | +| 1.92.0 | `false` | `true` | +| (default in v2) | `true` | | + +**Compatibility with old behavior:** You can pass `desiredCount: 1` explicitly, but you should never need this. + + +### @aws-cdk/aws-efs:defaultEncryptionAtRest + +*Enable this feature flag to have elastic file systems encrypted at rest by default.* (default) + +Encryption can also be configured explicitly using the `encrypted` property. + + +| Since | Default | Recommended | +| ----- | ----- | ----- | +| 1.98.0 | `false` | `true` | +| (default in v2) | `true` | | + +**Compatibility with old behavior:** Pass the `encrypted: false` property to the `FileSystem` construct to disable encryption. + + ### @aws-cdk/core:newStyleStackSynthesis -Switch to new stack synthesis method which enables CI/CD (fix) +*Switch to new stack synthesis method which enables CI/CD* (fix) If this flag is specified, all `Stack`s will use the `DefaultStackSynthesizer` by default. If it is not set, they will use the `LegacyStackSynthesizer`. -Introduced in **2.0.0**, recommended value `true`. + +| Since | Default | Recommended | +| ----- | ----- | ----- | +| 1.39.0 | `false` | `true` | +| 2.0.0 | `true` | `true` | + ### @aws-cdk/core:stackRelativeExports -Name exports based on the construct paths relative to the stack, rather than the global construct path (fix) +*Name exports based on the construct paths relative to the stack, rather than the global construct path* (fix) Combined with the stack name this relative construct path is good enough to ensure uniqueness, and makes the export names robust against refactoring the location of the stack in the construct tree (specifically, moving the Stack into a Stage). -Introduced in **2.0.0**, recommended value `true`. + +| Since | Default | Recommended | +| ----- | ----- | ----- | +| 1.58.0 | `false` | `true` | +| 2.0.0 | `true` | `true` | + ### @aws-cdk/aws-rds:lowercaseDbIdentifier -Force lowercasing of RDS Cluster names in CDK (fix) +*Force lowercasing of RDS Cluster names in CDK* (fix) Cluster names must be lowercase, and the service will lowercase the name when the cluster is created. However, CDK did not use to know about this, and would use the user-provided name @@ -79,11 +338,16 @@ Must be behind a permanent flag because changing a name from mixed case to lower would lead CloudFormation to think the name was changed and would trigger a cluster replacement (losing data!). -Introduced in **2.0.0**, recommended value `true`. + +| Since | Default | Recommended | +| ----- | ----- | ----- | +| 1.97.0 | `false` | `true` | +| 2.0.0 | `true` | `true` | + ### @aws-cdk/aws-apigateway:usagePlanKeyOrderInsensitiveId -Allow adding/removing multiple UsagePlanKeys independently (fix) +*Allow adding/removing multiple UsagePlanKeys independently* (fix) The UsagePlanKey resource connects an ApiKey with a UsagePlan. API Gateway does not allow more than one UsagePlanKey for any given UsagePlan and ApiKey combination. For this reason, CloudFormation cannot replace this resource without @@ -98,52 +362,79 @@ which again is disallowed. In effect, there is no way to get out of this mess in a backwards compatible way, while supporting existing stacks. This flag changes the logical id layout of UsagePlanKey to not be sensitive to order. -Introduced in **2.0.0**, recommended value `true`. + +| Since | Default | Recommended | +| ----- | ----- | ----- | +| 1.98.0 | `false` | `true` | +| 2.0.0 | `true` | `true` | + ### @aws-cdk/aws-lambda:recognizeVersionProps -Enable this feature flag to opt in to the updated logical id calculation for Lambda Version created using the `fn.currentVersion`. (fix) +*Enable this feature flag to opt in to the updated logical id calculation for Lambda Version created using the `fn.currentVersion`.* (fix) The previous calculation incorrectly considered properties of the `AWS::Lambda::Function` resource that did not constitute creating a new Version. See 'currentVersion' section in the aws-lambda module's README for more details. -Introduced in **2.0.0**, recommended value `true`. + +| Since | Default | Recommended | +| ----- | ----- | ----- | +| 1.106.0 | `false` | `true` | +| 2.0.0 | `true` | `true` | + ### @aws-cdk/aws-cloudfront:defaultSecurityPolicyTLSv1.2_2021 -Enable this feature flag to have cloudfront distributions use the security policy TLSv1.2_2021 by default. (fix) +*Enable this feature flag to have cloudfront distributions use the security policy TLSv1.2_2021 by default.* (fix) The security policy can also be configured explicitly using the `minimumProtocolVersion` property. -Introduced in **2.0.0**, recommended value `true`. + +| Since | Default | Recommended | +| ----- | ----- | ----- | +| 1.117.0 | `false` | `true` | +| 2.0.0 | `true` | `true` | + ### @aws-cdk/core:target-partitions -What regions to include in lookup tables of environment agnostic stacks (config) +*What regions to include in lookup tables of environment agnostic stacks* (config) Has no effect on stacks that have a defined region, but will limit the amount of unnecessary regions included in stacks without a known region. The type of this value should be a list of strings. -Introduced in **2.4.0**, recommended value `["aws","aws-cn"]`. + +| Since | Default | Recommended | +| ----- | ----- | ----- | +| 1.137.0 | `false` | `["aws","aws-cn"]` | +| 2.4.0 | `false` | `["aws","aws-cn"]` | + ### @aws-cdk-containers/ecs-service-extensions:enableDefaultLogDriver -ECS extensions will automatically add an `awslogs` driver if no logging is specified (default) +*ECS extensions will automatically add an `awslogs` driver if no logging is specified* (default) Enable this feature flag to configure default logging behavior for the ECS Service Extensions. This will enable the `awslogs` log driver for the application container of the service to send the container logs to CloudWatch Logs. This is a feature flag as the new behavior provides a better default experience for the users. -Introduced in **2.8.0**, recommended value `true`. + +| Since | Default | Recommended | +| ----- | ----- | ----- | +| 1.140.0 | `false` | `true` | +| 2.8.0 | `false` | `true` | + +**Compatibility with old behavior:** Specify a log driver explicitly. + ### @aws-cdk/aws-ec2:uniqueImdsv2TemplateName -Enable this feature flag to have Launch Templates generated by the `InstanceRequireImdsv2Aspect` use unique names. (fix) +*Enable this feature flag to have Launch Templates generated by the `InstanceRequireImdsv2Aspect` use unique names.* (fix) Previously, the generated Launch Template names were only unique within a stack because they were based only on the `Instance` construct ID. If another stack that has an `Instance` with the same construct ID is deployed in the same @@ -151,52 +442,79 @@ account and region, the deployments would always fail as the generated Launch Te The new implementation addresses this issue by generating the Launch Template name with the `Names.uniqueId` method. -Introduced in **2.8.0**, recommended value `true`. + +| Since | Default | Recommended | +| ----- | ----- | ----- | +| 1.140.0 | `false` | `true` | +| 2.8.0 | `false` | `true` | + ### @aws-cdk/aws-iam:minimizePolicies -Minimize IAM policies by combining Statements (config) +*Minimize IAM policies by combining Statements* (config) Minimize IAM policies by combining Principals, Actions and Resources of two Statements in the policies, as long as it doesn't change the meaning of the policy. -Introduced in **2.18.0**, recommended value `true`. + +| Since | Default | Recommended | +| ----- | ----- | ----- | +| 1.150.0 | `false` | `true` | +| 2.18.0 | `false` | `true` | + ### @aws-cdk/core:checkSecretUsage -Enable this flag to make it impossible to accidentally use SecretValues in unsafe locations (config) +*Enable this flag to make it impossible to accidentally use SecretValues in unsafe locations* (config) With this flag enabled, `SecretValue` instances can only be passed to constructs that accept `SecretValue`s; otherwise, `unsafeUnwrap()` must be called to use it as a regular string. -Introduced in **2.21.0**, recommended value `true`. + +| Since | Default | Recommended | +| ----- | ----- | ----- | +| 1.153.0 | `false` | `true` | +| 2.21.0 | `false` | `true` | + ### @aws-cdk/aws-lambda:recognizeLayerVersion -Enable this feature flag to opt in to the updated logical id calculation for Lambda Version created using the `fn.currentVersion`. (fix) +*Enable this feature flag to opt in to the updated logical id calculation for Lambda Version created using the `fn.currentVersion`.* (fix) This flag correct incorporates Lambda Layer properties into the Lambda Function Version. See 'currentVersion' section in the aws-lambda module's README for more details. -Introduced in **2.27.0**, recommended value `true`. + +| Since | Default | Recommended | +| ----- | ----- | ----- | +| 1.159.0 | `false` | `true` | +| 2.27.0 | `false` | `true` | + ### @aws-cdk/core:validateSnapshotRemovalPolicy -Error on snapshot removal policies on resources that do not support it. (default) +*Error on snapshot removal policies on resources that do not support it.* (default) Makes sure we do not allow snapshot removal policy on resources that do not support it. If supplied on an unsupported resource, CloudFormation ignores the policy altogether. This flag will reduce confusion and unexpected loss of data when erroneously supplying the snapshot removal policy. -Introduced in **2.28.0**, recommended value `true`. + +| Since | Default | Recommended | +| ----- | ----- | ----- | +| (not in v1) | | | +| 2.28.0 | `false` | `true` | + +**Compatibility with old behavior:** The old behavior was incorrect. Update your source to not specify SNAPSHOT policies on resources that do not support it. + ### @aws-cdk/aws-codepipeline:crossAccountKeyAliasStackSafeResourceName -Generate key aliases that include the stack name (fix) +*Generate key aliases that include the stack name* (fix) Enable this feature flag to have CodePipeline generate a unique cross account key alias name using the stack name. @@ -205,11 +523,16 @@ the KMS key alias name created for these pipelines may be the same due to how th This new implementation creates a stack safe resource name for the alias using the stack name instead of the stack ID. -Introduced in **2.29.0**, recommended value `true`. + +| Since | Default | Recommended | +| ----- | ----- | ----- | +| (not in v1) | | | +| 2.29.0 | `false` | `true` | + ### @aws-cdk/aws-s3:createDefaultLoggingPolicy -Enable this feature flag to create an S3 bucket policy by default in cases where an AWS service would automatically create the Policy if one does not exist. (fix) +*Enable this feature flag to create an S3 bucket policy by default in cases where an AWS service would automatically create the Policy if one does not exist.* (fix) For example, in order to send VPC flow logs to an S3 bucket, there is a specific Bucket Policy that needs to be attached to the bucket. If you create the bucket without a policy and then add the @@ -222,11 +545,16 @@ remain in control of it. @see https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/AWS-logs-and-resource-policy.html#AWS-logs-infrastructure-S3 -Introduced in **2.31.0**, recommended value `true`. + +| Since | Default | Recommended | +| ----- | ----- | ----- | +| (not in v1) | | | +| 2.31.0 | `false` | `true` | + ### @aws-cdk/aws-sns-subscriptions:restrictSqsDescryption -Restrict KMS key policy for encrypted Queues a bit more (fix) +*Restrict KMS key policy for encrypted Queues a bit more* (fix) Enable this feature flag to restrict the decryption of a SQS queue, which is subscribed to a SNS topic, to only the topic which it is subscribed to and not the whole SNS service of an account. @@ -235,11 +563,16 @@ Previously the decryption was only restricted to the SNS service principal. To m secure, it is a good practice to restrict the decryption further and only allow the connected SNS topic to decryption the subscribed queue. -Introduced in **2.32.0**, recommended value `true`. + +| Since | Default | Recommended | +| ----- | ----- | ----- | +| (not in v1) | | | +| 2.32.0 | `false` | `true` | + ### @aws-cdk/aws-ecs:arnFormatIncludesClusterName -ARN format used by ECS. In the new ARN format, the cluster name is part of the resource ID. (fix) +*ARN format used by ECS. In the new ARN format, the cluster name is part of the resource ID.* (fix) If this flag is not set, the old ARN format (without cluster name) for ECS is used. If this flag is set, the new ARN format (with cluster name) for ECS is used. @@ -248,11 +581,16 @@ This is a feature flag as the old format is still valid for existing ECS cluster See https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-account-settings.html#ecs-resource-ids -Introduced in **2.35.0**, recommended value `true`. + +| Since | Default | Recommended | +| ----- | ----- | ----- | +| (not in v1) | | | +| 2.35.0 | `false` | `true` | + ### @aws-cdk/aws-apigateway:disableCloudWatchRole -Make default CloudWatch Role behavior safe for multiple API Gateways in one environment (fix) +*Make default CloudWatch Role behavior safe for multiple API Gateways in one environment* (fix) Enable this feature flag to change the default behavior for aws-apigateway.RestApi and aws-apigateway.SpecRestApi to _not_ create a CloudWatch role and Account. There is only a single ApiGateway account per AWS @@ -263,11 +601,16 @@ role will also be deleted, breaking any existing ApiGateways that were depending When this flag is enabled you should either create the ApiGateway account and CloudWatch role separately _or_ only enable the cloudWatchRole on a single RestApi. -Introduced in **2.38.0**, recommended value `true`. + +| Since | Default | Recommended | +| ----- | ----- | ----- | +| (not in v1) | | | +| 2.38.0 | `false` | `true` | + ### @aws-cdk/core:enablePartitionLiterals -Make ARNs concrete if AWS partition is known (fix) +*Make ARNs concrete if AWS partition is known* (fix) Enable this feature flag to get partition names as string literals in Stacks with known regions defined in their environment, such as "aws" or "aws-cn". Previously the CloudFormation intrinsic function @@ -285,7 +628,7 @@ Principal: becomes: -``` +```yaml Principal: AWS: "arn:aws:iam::123456789876:root" ``` @@ -293,102 +636,26 @@ Principal: The intrinsic function will still be used in Stacks where no region is defined or the region's partition is unknown. -Introduced in **2.38.0**, recommended value `true`. + +| Since | Default | Recommended | +| ----- | ----- | ----- | +| (not in v1) | | | +| 2.38.0 | `false` | `true` | + ### @aws-cdk/aws-events:eventsTargetQueueSameAccount -Event Rules may only push to encrypted SQS queues in the same account (fix) +*Event Rules may only push to encrypted SQS queues in the same account* (fix) This flag applies to SQS Queues that are used as the target of event Rules. When enabled, only principals -from the same account as the Queue can send messages. If a queue is unencrypted, this restriction will +from the same account as the Rule can send messages. If a queue is unencrypted, this restriction will always apply, regardless of the value of this flag. -Introduced in **2.51.0**, recommended value `true`. - - - -## Currently recommended cdk.json - -The following json shows the current recommended set of flags, as `cdk init` would generate it for new projects. - - -```json -{ - "context": { - "@aws-cdk/aws-lambda:recognizeLayerVersion": true, - "@aws-cdk/core:checkSecretUsage": true, - "@aws-cdk/core:target-partitions": [ - "aws", - "aws-cn" - ], - "@aws-cdk-containers/ecs-service-extensions:enableDefaultLogDriver": true, - "@aws-cdk/aws-ec2:uniqueImdsv2TemplateName": true, - "@aws-cdk/aws-ecs:arnFormatIncludesClusterName": true, - "@aws-cdk/aws-iam:minimizePolicies": true, - "@aws-cdk/core:validateSnapshotRemovalPolicy": true, - "@aws-cdk/aws-codepipeline:crossAccountKeyAliasStackSafeResourceName": true, - "@aws-cdk/aws-s3:createDefaultLoggingPolicy": true, - "@aws-cdk/aws-sns-subscriptions:restrictSqsDescryption": true, - "@aws-cdk/aws-apigateway:disableCloudWatchRole": true, - "@aws-cdk/core:enablePartitionLiterals": true, - "@aws-cdk/aws-events:eventsTargetQueueSameAccount": true - } -} -``` - - -## Flags removed in v2 - -These **default change** flags have been removed in v2. These used to be configurable in v1, but in v2 their -behavior has become the default. Remove these from your `cdk.json` file. - - - -| Flag | Summary | Type | Since | Value in v2 | -| ----- | ----- | ----- | ----- | ----- | -| @aws-cdk/core:enableStackNameDuplicates | Allow multiple stacks with the same name | (default) | 1.16.0 | `true` | -| aws-cdk:enableDiffNoFail | Make `cdk diff` not fail when there are differences | (default) | 1.19.0 | `true` | -| @aws-cdk/aws-ecr-assets:dockerIgnoreSupport | DockerImageAsset properly supports `.dockerignore` files by default | (default) | 1.73.0 | `true` | -| @aws-cdk/aws-secretsmanager:parseOwnedSecretName | Fix the referencing of SecretsManager names from ARNs | (default) | 1.77.0 | `true` | -| @aws-cdk/aws-kms:defaultKeyPolicies | Tighten default KMS key policies | (default) | 1.78.0 | `true` | -| @aws-cdk/aws-s3:grantWriteWithoutAcl | Remove `PutObjectAcl` from Bucket.grantWrite | (default) | 1.85.0 | `true` | -| @aws-cdk/aws-ecs-patterns:removeDefaultDesiredCount | Do not specify a default DesiredCount for ECS services | (default) | 1.92.0 | `true` | -| @aws-cdk/aws-efs:defaultEncryptionAtRest | Enable this feature flag to have elastic file systems encrypted at rest by default. | (default) | 1.98.0 | `true` | - - - -## Flags with a different default in v2 -These **fix/deprecation** flags are still configurable in v2, but their default has changed compared to v1. If you -are migrating a v1 CDK project to v2, explicitly set any of these flags which does not currently appear in your -`cdk.json` to `false`, to avoid unexpected infrastructure changes. - - - -| Flag | Summary | Type | Since | v1 default | v2 default | -| ----- | ----- | ----- | ----- | ----- | ----- | -| @aws-cdk/core:newStyleStackSynthesis | Switch to new stack synthesis method which enables CI/CD | (fix) | 1.39.0 | `false` | `true` | -| @aws-cdk/core:stackRelativeExports | Name exports based on the construct paths relative to the stack, rather than the global construct path | (fix) | 1.58.0 | `false` | `true` | -| @aws-cdk/aws-rds:lowercaseDbIdentifier | Force lowercasing of RDS Cluster names in CDK | (fix) | 1.97.0 | `false` | `true` | -| @aws-cdk/aws-apigateway:usagePlanKeyOrderInsensitiveId | Allow adding/removing multiple UsagePlanKeys independently | (fix) | 1.98.0 | `false` | `true` | -| @aws-cdk/aws-lambda:recognizeVersionProps | Enable this feature flag to opt in to the updated logical id calculation for Lambda Version created using the `fn.currentVersion`. | (fix) | 1.106.0 | `false` | `true` | -| @aws-cdk/aws-cloudfront:defaultSecurityPolicyTLSv1.2_2021 | Enable this feature flag to have cloudfront distributions use the security policy TLSv1.2_2021 by default. | (fix) | 1.117.0 | `false` | `true` | - - +| Since | Default | Recommended | +| ----- | ----- | ----- | +| (not in v1) | | | +| 2.51.0 | `false` | `true` | -Here is an example of a `cdk.json` file that restores v1 behavior for these flags: - -```json -{ - "context": { - "@aws-cdk/core:newStyleStackSynthesis": false, - "@aws-cdk/core:stackRelativeExports": false, - "@aws-cdk/aws-rds:lowercaseDbIdentifier": false, - "@aws-cdk/aws-apigateway:usagePlanKeyOrderInsensitiveId": false, - "@aws-cdk/aws-lambda:recognizeVersionProps": false, - "@aws-cdk/aws-cloudfront:defaultSecurityPolicyTLSv1.2_2021": false - } -} -``` - \ No newline at end of file + diff --git a/packages/@aws-cdk/cx-api/build-tools/flag-report.ts b/packages/@aws-cdk/cx-api/build-tools/flag-report.ts index 002086e36ed6b..7366b4a885308 100644 --- a/packages/@aws-cdk/cx-api/build-tools/flag-report.ts +++ b/packages/@aws-cdk/cx-api/build-tools/flag-report.ts @@ -16,9 +16,14 @@ async function main() { function flagsTable() { return renderTable([ - ['Flag', 'Summary', 'Since', 'Type', 'Recommended'], + ['Flag', 'Summary', 'Since', 'Type'], ...v2flags().map(([name, flag]) => - [name, flag.summary, flag.introducedIn.v2 ?? '', renderType(flag.type), '`' + JSON.stringify(flag.recommendedValue) + '`'], + [ + renderLink(mdEsc(name), githubHeadingLink(flagDetailsHeading(name, flag))), + flag.summary, + flag.introducedIn.v2 ?? '', + renderType(flag.type), + ], ), ]); } @@ -27,10 +32,13 @@ function removedFlags() { const removedInV2 = flags(flag => flag.introducedIn.v2 === undefined && flag.introducedIn.v1 !== undefined); return renderTable([ - ['Flag', 'Summary', 'Type', 'Since', 'Value in v2'], - ...removedInV2.map(([name, flag]) => - [name, flag.summary, renderType(flag.type), flag.introducedIn.v1 ?? '', renderValue(flag.defaults?.v2)], - ), + ['Flag', 'Summary', 'Type', 'Since'], + ...removedInV2.map(([name, flag]) => [ + renderLink(mdEsc(name), githubHeadingLink(flagDetailsHeading(name, flag))), + flag.summary, + renderType(flag.type), + flag.introducedIn.v1 ?? '', + ]), ]); } @@ -39,9 +47,14 @@ function changedFlags() { return renderTable([ ['Flag', 'Summary', 'Type', 'Since', 'v1 default', 'v2 default'], - ...changedInV2.map(([name, flag]) => - [name, flag.summary, renderType(flag.type), flag.introducedIn.v1 ?? '', renderValue(false), renderValue(flag.defaults?.v2)], - ), + ...changedInV2.map(([name, flag]) => [ + renderLink(mdEsc(name), githubHeadingLink(flagDetailsHeading(name, flag))), + flag.summary, + renderType(flag.type), + flag.introducedIn.v1 ?? '', + renderValue(false), + renderValue(flag.defaults?.v2), + ]), ]); } @@ -58,18 +71,46 @@ function migrateJson() { } function flagsDetails() { - return v2flags().flatMap(([name, flag]) => [ - `### ${name}`, + const allFlags = flags(_ => true); + + return allFlags.flatMap(([name, flag]) => [ + `### ${flagDetailsHeading(name, flag)}`, '', - `${flag.summary} ${renderType(flag.type)}`, + `*${flag.summary}* ${renderType(flag.type)}`, '', - dedent(flag.details), + dedent(flag.detailsMd), '', - `Introduced in **${flag.introducedIn.v2}**, recommended value ${renderValue(flag.recommendedValue)}.`, + renderTable([ + ['Since', 'Default', 'Recommended'], + + // V1 + flag.introducedIn.v1 + ? [flag.introducedIn.v1, renderValue(false), renderValue(flag.recommendedValue)] + : ['(not in v1)', '', ''], + + // V2 + flag.introducedIn.v2 + ? [flag.introducedIn.v2, renderValue(flag.defaults?.v2 ?? false), renderValue(flag.recommendedValue)] + : flag.defaults?.v2 !== undefined + ? ['(default in v2)', renderValue(flag.defaults?.v2), ''] + : ['(not in v2)', '', ''], + ]), + ...oldBehavior(flag) ? [ + `**Compatibility with old behavior:** ${oldBehavior(flag)}`, + '', + ] : [], '', ]).join('\n'); } +function oldBehavior(flag: FlagInfo): string | undefined { + switch (flag.type) { + case FlagType.ApiDefault: return flag.compatibilityWithOldBehaviorMd; + case FlagType.BugFix: return flag.compatibilityWithOldBehaviorMd; + case FlagType.VisibleContext: return undefined; + } +} + function recommendedJson() { return [ '```json', @@ -114,6 +155,20 @@ function renderTable(rows: string[][]) { ].join('\n'); } +/** + * Return the heading that will be used to caption this flag's details + */ +function flagDetailsHeading(name: string, _: FlagInfo) { + return name; +} + +/** + * Return a link that is valid on GitHub to refer to a heading + */ +function githubHeadingLink(heading: string) { + return `#${heading.toLowerCase().replace(/ /g, '-').replace(/[^a-z0-9_-]/g, '')}`; +} + /** * Remove shared leading whitespace from all non-empty lines */ @@ -129,6 +184,14 @@ function renderValue(x: any) { return `\`${JSON.stringify(x)}\``; } +function renderLink(caption: string, link: string) { + return `[${caption}](${link})`; +} + +function mdEsc(x: string) { + return x.replace(/_/g, '\\_'); +} + async function updateMarkdownFile(filename: string, sections: Record) { let contents = await fs.readFile(filename, { encoding: 'utf-8' }); diff --git a/packages/@aws-cdk/cx-api/lib/features.ts b/packages/@aws-cdk/cx-api/lib/features.ts index c4d03eacd0e13..9cdfe6f1071ba 100644 --- a/packages/@aws-cdk/cx-api/lib/features.ts +++ b/packages/@aws-cdk/cx-api/lib/features.ts @@ -65,7 +65,7 @@ export const FLAGS: Record = { [ENABLE_STACK_NAME_DUPLICATES_CONTEXT]: { type: FlagType.ApiDefault, summary: 'Allow multiple stacks with the same name', - details: ` + detailsMd: ` If this is set, multiple stacks can use the same stack name (e.g. deployed to different environments). This means that the name of the synthesized template file will be based on the construct path and not on the defined \`stackName\` @@ -73,33 +73,35 @@ export const FLAGS: Record = { recommendedValue: true, introducedIn: { v1: '1.16.0' }, defaults: { v2: true }, + compatibilityWithOldBehaviorMd: 'Pass stack identifiers to the CLI instead of stack names.', }, ////////////////////////////////////////////////////////////////////// [ENABLE_DIFF_NO_FAIL_CONTEXT]: { type: FlagType.ApiDefault, summary: 'Make `cdk diff` not fail when there are differences', - details: ` + detailsMd: ` Determines what status code \`cdk diff\` should return when the specified stack differs from the deployed stack or the local CloudFormation template: - * \`aws-cdk:enableDiffNoFail=true\` => status code == 0 - * \`aws-cdk:enableDiffNoFail=false\` => status code == 1 + * \`aws-cdk:enableDiffNoFail=true\` => status code == 0 + * \`aws-cdk:enableDiffNoFail=false\` => status code == 1 You can override this behavior with the --fail flag: - * \`--fail\` => status code == 1 - * \`--no-fail\` => status code == 0`, + * \`--fail\` => status code == 1 + * \`--no-fail\` => status code == 0`, introducedIn: { v1: '1.19.0' }, defaults: { v2: true }, recommendedValue: true, + compatibilityWithOldBehaviorMd: 'Specify `--fail` to the CLI.', }, ////////////////////////////////////////////////////////////////////// [NEW_STYLE_STACK_SYNTHESIS_CONTEXT]: { type: FlagType.BugFix, summary: 'Switch to new stack synthesis method which enables CI/CD', - details: ` + detailsMd: ` If this flag is specified, all \`Stack\`s will use the \`DefaultStackSynthesizer\` by default. If it is not set, they will use the \`LegacyStackSynthesizer\`.`, introducedIn: { v1: '1.39.0', v2: '2.0.0' }, @@ -111,7 +113,7 @@ export const FLAGS: Record = { [STACK_RELATIVE_EXPORTS_CONTEXT]: { type: FlagType.BugFix, summary: 'Name exports based on the construct paths relative to the stack, rather than the global construct path', - details: ` + detailsMd: ` Combined with the stack name this relative construct path is good enough to ensure uniqueness, and makes the export names robust against refactoring the location of the stack in the construct tree (specifically, moving the Stack @@ -125,7 +127,7 @@ export const FLAGS: Record = { [DOCKER_IGNORE_SUPPORT]: { type: FlagType.ApiDefault, summary: 'DockerImageAsset properly supports `.dockerignore` files by default', - details: ` + detailsMd: ` If this flag is not set, the default behavior for \`DockerImageAsset\` is to use glob semantics for \`.dockerignore\` files. If this flag is set, the default behavior is standard Docker ignore semantics. @@ -135,13 +137,14 @@ export const FLAGS: Record = { introducedIn: { v1: '1.73.0' }, defaults: { v2: true }, recommendedValue: true, + compatibilityWithOldBehaviorMd: 'Update your `.dockerignore` file to match standard Docker ignore rules, if necessary.', }, ////////////////////////////////////////////////////////////////////// [SECRETS_MANAGER_PARSE_OWNED_SECRET_NAME]: { type: FlagType.ApiDefault, summary: 'Fix the referencing of SecretsManager names from ARNs', - details: ` + detailsMd: ` Secret.secretName for an "owned" secret will attempt to parse the secretName from the ARN, rather than the default full resource name, which includes the SecretsManager suffix. @@ -150,13 +153,14 @@ export const FLAGS: Record = { introducedIn: { v1: '1.77.0' }, defaults: { v2: true }, recommendedValue: true, + compatibilityWithOldBehaviorMd: 'Use `parseArn(secret.secretName).resourceName` to emulate the incorrect old parsing.', }, ////////////////////////////////////////////////////////////////////// [KMS_DEFAULT_KEY_POLICIES]: { type: FlagType.ApiDefault, summary: 'Tighten default KMS key policies', - details: ` + detailsMd: ` KMS Keys start with a default key policy that grants the account access to administer the key, mirroring the behavior of the KMS SDK/CLI/Console experience. Users may override the default key policy by specifying their own. @@ -171,13 +175,14 @@ export const FLAGS: Record = { introducedIn: { v1: '1.78.0' }, defaults: { v2: true }, recommendedValue: true, + compatibilityWithOldBehaviorMd: 'Pass `trustAccountIdentities: false` to `Key` construct to restore the old behavior.', }, ////////////////////////////////////////////////////////////////////// [S3_GRANT_WRITE_WITHOUT_ACL]: { type: FlagType.ApiDefault, summary: 'Remove `PutObjectAcl` from Bucket.grantWrite', - details: ` + detailsMd: ` Change the old 's3:PutObject*' permission to 's3:PutObject' on Bucket, as the former includes 's3:PutObjectAcl', which could be used to grant read/write object access to IAM principals in other accounts. @@ -186,13 +191,14 @@ export const FLAGS: Record = { introducedIn: { v1: '1.85.0' }, defaults: { v2: true }, recommendedValue: true, + compatibilityWithOldBehaviorMd: 'Call `bucket.grantPutAcl()` in addition to `bucket.grantWrite()` to grant ACL permissions.', }, ////////////////////////////////////////////////////////////////////// [ECS_REMOVE_DEFAULT_DESIRED_COUNT]: { type: FlagType.ApiDefault, summary: 'Do not specify a default DesiredCount for ECS services', - details: ` + detailsMd: ` ApplicationLoadBalancedServiceBase, ApplicationMultipleTargetGroupServiceBase, NetworkLoadBalancedServiceBase, NetworkMultipleTargetGroupServiceBase, and QueueProcessingServiceBase currently determine a default value for the desired count of @@ -205,13 +211,14 @@ export const FLAGS: Record = { introducedIn: { v1: '1.92.0' }, defaults: { v2: true }, recommendedValue: true, + compatibilityWithOldBehaviorMd: 'You can pass `desiredCount: 1` explicitly, but you should never need this.', }, ////////////////////////////////////////////////////////////////////// [RDS_LOWERCASE_DB_IDENTIFIER]: { type: FlagType.BugFix, summary: 'Force lowercasing of RDS Cluster names in CDK', - details: ` + detailsMd: ` Cluster names must be lowercase, and the service will lowercase the name when the cluster is created. However, CDK did not use to know about this, and would use the user-provided name referencing the cluster, which would fail if it happened to be mixed-case. @@ -230,7 +237,7 @@ export const FLAGS: Record = { [APIGATEWAY_USAGEPLANKEY_ORDERINSENSITIVE_ID]: { type: FlagType.BugFix, summary: 'Allow adding/removing multiple UsagePlanKeys independently', - details: ` + detailsMd: ` The UsagePlanKey resource connects an ApiKey with a UsagePlan. API Gateway does not allow more than one UsagePlanKey for any given UsagePlan and ApiKey combination. For this reason, CloudFormation cannot replace this resource without either the UsagePlan or ApiKey changing. @@ -252,19 +259,20 @@ export const FLAGS: Record = { [EFS_DEFAULT_ENCRYPTION_AT_REST]: { type: FlagType.ApiDefault, summary: 'Enable this feature flag to have elastic file systems encrypted at rest by default.', - details: ` + detailsMd: ` Encryption can also be configured explicitly using the \`encrypted\` property. `, introducedIn: { v1: '1.98.0' }, defaults: { v2: true }, recommendedValue: true, + compatibilityWithOldBehaviorMd: 'Pass the `encrypted: false` property to the `FileSystem` construct to disable encryption.', }, ////////////////////////////////////////////////////////////////////// [LAMBDA_RECOGNIZE_VERSION_PROPS]: { type: FlagType.BugFix, summary: 'Enable this feature flag to opt in to the updated logical id calculation for Lambda Version created using the `fn.currentVersion`.', - details: ` + detailsMd: ` The previous calculation incorrectly considered properties of the \`AWS::Lambda::Function\` resource that did not constitute creating a new Version. @@ -278,7 +286,7 @@ export const FLAGS: Record = { [LAMBDA_RECOGNIZE_LAYER_VERSION]: { type: FlagType.BugFix, summary: 'Enable this feature flag to opt in to the updated logical id calculation for Lambda Version created using the `fn.currentVersion`.', - details: ` + detailsMd: ` This flag correct incorporates Lambda Layer properties into the Lambda Function Version. See 'currentVersion' section in the aws-lambda module's README for more details.`, @@ -290,7 +298,7 @@ export const FLAGS: Record = { [CLOUDFRONT_DEFAULT_SECURITY_POLICY_TLS_V1_2_2021]: { type: FlagType.BugFix, summary: 'Enable this feature flag to have cloudfront distributions use the security policy TLSv1.2_2021 by default.', - details: ` + detailsMd: ` The security policy can also be configured explicitly using the \`minimumProtocolVersion\` property.`, introducedIn: { v1: '1.117.0', v2: '2.0.0' }, defaults: { v2: true }, @@ -301,7 +309,7 @@ export const FLAGS: Record = { [CHECK_SECRET_USAGE]: { type: FlagType.VisibleContext, summary: 'Enable this flag to make it impossible to accidentally use SecretValues in unsafe locations', - details: ` + detailsMd: ` With this flag enabled, \`SecretValue\` instances can only be passed to constructs that accept \`SecretValue\`s; otherwise, \`unsafeUnwrap()\` must be called to use it as a regular string.`, @@ -313,7 +321,7 @@ export const FLAGS: Record = { [TARGET_PARTITIONS]: { type: FlagType.VisibleContext, summary: 'What regions to include in lookup tables of environment agnostic stacks', - details: ` + detailsMd: ` Has no effect on stacks that have a defined region, but will limit the amount of unnecessary regions included in stacks without a known region. @@ -326,20 +334,21 @@ export const FLAGS: Record = { [ECS_SERVICE_EXTENSIONS_ENABLE_DEFAULT_LOG_DRIVER]: { type: FlagType.ApiDefault, summary: 'ECS extensions will automatically add an `awslogs` driver if no logging is specified', - details: ` + detailsMd: ` Enable this feature flag to configure default logging behavior for the ECS Service Extensions. This will enable the \`awslogs\` log driver for the application container of the service to send the container logs to CloudWatch Logs. This is a feature flag as the new behavior provides a better default experience for the users.`, introducedIn: { v1: '1.140.0', v2: '2.8.0' }, recommendedValue: true, + compatibilityWithOldBehaviorMd: 'Specify a log driver explicitly.', }, ////////////////////////////////////////////////////////////////////// [EC2_UNIQUE_IMDSV2_LAUNCH_TEMPLATE_NAME]: { type: FlagType.BugFix, summary: 'Enable this feature flag to have Launch Templates generated by the `InstanceRequireImdsv2Aspect` use unique names.', - details: ` + detailsMd: ` Previously, the generated Launch Template names were only unique within a stack because they were based only on the \`Instance\` construct ID. If another stack that has an \`Instance\` with the same construct ID is deployed in the same account and region, the deployments would always fail as the generated Launch Template names were the same. @@ -353,7 +362,7 @@ export const FLAGS: Record = { [ECS_ARN_FORMAT_INCLUDES_CLUSTER_NAME]: { type: FlagType.BugFix, summary: 'ARN format used by ECS. In the new ARN format, the cluster name is part of the resource ID.', - details: ` + detailsMd: ` If this flag is not set, the old ARN format (without cluster name) for ECS is used. If this flag is set, the new ARN format (with cluster name) for ECS is used. @@ -369,7 +378,7 @@ export const FLAGS: Record = { [IAM_MINIMIZE_POLICIES]: { type: FlagType.VisibleContext, summary: 'Minimize IAM policies by combining Statements', - details: ` + detailsMd: ` Minimize IAM policies by combining Principals, Actions and Resources of two Statements in the policies, as long as it doesn't change the meaning of the policy.`, @@ -381,20 +390,21 @@ export const FLAGS: Record = { [VALIDATE_SNAPSHOT_REMOVAL_POLICY]: { type: FlagType.ApiDefault, summary: 'Error on snapshot removal policies on resources that do not support it.', - details: ` + detailsMd: ` Makes sure we do not allow snapshot removal policy on resources that do not support it. If supplied on an unsupported resource, CloudFormation ignores the policy altogether. This flag will reduce confusion and unexpected loss of data when erroneously supplying the snapshot removal policy.`, introducedIn: { v2: '2.28.0' }, recommendedValue: true, + compatibilityWithOldBehaviorMd: 'The old behavior was incorrect. Update your source to not specify SNAPSHOT policies on resources that do not support it.', }, ////////////////////////////////////////////////////////////////////// [CODEPIPELINE_CROSS_ACCOUNT_KEY_ALIAS_STACK_SAFE_RESOURCE_NAME]: { type: FlagType.BugFix, summary: 'Generate key aliases that include the stack name', - details: ` + detailsMd: ` Enable this feature flag to have CodePipeline generate a unique cross account key alias name using the stack name. Previously, when creating multiple pipelines with similar naming conventions and when crossAccountKeys is true, @@ -410,7 +420,7 @@ export const FLAGS: Record = { [S3_CREATE_DEFAULT_LOGGING_POLICY]: { type: FlagType.BugFix, summary: 'Enable this feature flag to create an S3 bucket policy by default in cases where an AWS service would automatically create the Policy if one does not exist.', - details: ` + detailsMd: ` For example, in order to send VPC flow logs to an S3 bucket, there is a specific Bucket Policy that needs to be attached to the bucket. If you create the bucket without a policy and then add the bucket as the flow log destination, the service will automatically create the bucket policy with the @@ -430,7 +440,7 @@ export const FLAGS: Record = { [SNS_SUBSCRIPTIONS_SQS_DECRYPTION_POLICY]: { type: FlagType.BugFix, summary: 'Restrict KMS key policy for encrypted Queues a bit more', - details: ` + detailsMd: ` Enable this feature flag to restrict the decryption of a SQS queue, which is subscribed to a SNS topic, to only the topic which it is subscribed to and not the whole SNS service of an account. @@ -445,7 +455,7 @@ export const FLAGS: Record = { [APIGATEWAY_DISABLE_CLOUDWATCH_ROLE]: { type: FlagType.BugFix, summary: 'Make default CloudWatch Role behavior safe for multiple API Gateways in one environment', - details: ` + detailsMd: ` Enable this feature flag to change the default behavior for aws-apigateway.RestApi and aws-apigateway.SpecRestApi to _not_ create a CloudWatch role and Account. There is only a single ApiGateway account per AWS environment which means that each time you create a RestApi in your account the ApiGateway account @@ -463,7 +473,7 @@ export const FLAGS: Record = { [ENABLE_PARTITION_LITERALS]: { type: FlagType.BugFix, summary: 'Make ARNs concrete if AWS partition is known', - details: ` + detailsMd: ` Enable this feature flag to get partition names as string literals in Stacks with known regions defined in their environment, such as "aws" or "aws-cn". Previously the CloudFormation intrinsic function "Ref: AWS::Partition" was used. For example: @@ -480,7 +490,7 @@ export const FLAGS: Record = { becomes: - \`\`\` + \`\`\`yaml Principal: AWS: "arn:aws:iam::123456789876:root" \`\`\` @@ -496,7 +506,7 @@ export const FLAGS: Record = { [EVENTS_TARGET_QUEUE_SAME_ACCOUNT]: { type: FlagType.BugFix, summary: 'Event Rules may only push to encrypted SQS queues in the same account', - details: ` + detailsMd: ` This flag applies to SQS Queues that are used as the target of event Rules. When enabled, only principals from the same account as the Rule can send messages. If a queue is unencrypted, this restriction will always apply, regardless of the value of this flag. diff --git a/packages/@aws-cdk/cx-api/lib/private/flag-modeling.ts b/packages/@aws-cdk/cx-api/lib/private/flag-modeling.ts index cb4d11da7e59c..ac023ed513b7b 100644 --- a/packages/@aws-cdk/cx-api/lib/private/flag-modeling.ts +++ b/packages/@aws-cdk/cx-api/lib/private/flag-modeling.ts @@ -22,13 +22,11 @@ export enum FlagType { VisibleContext, }; -export interface FlagInfo { - /** Flag type */ - readonly type: FlagType; +export interface FlagInfoBase { /** Single-line description for the flag */ readonly summary: string; - /** Detailed description for the flag */ - readonly details: string; + /** Detailed description for the flag (Markdown) */ + readonly detailsMd: string; /** Version number the flag was introduced in each version line. `undefined` means flag does not exist in that line. */ readonly introducedIn: { v1?: string; v2?: string }; /** Default value, if flag is unset by user. Adding a flag with a default may not change behavior after GA! */ @@ -37,3 +35,14 @@ export interface FlagInfo { readonly recommendedValue: any; }; +/** Flag information, adding required fields if present */ +export type FlagInfo = FlagInfoBase & ( + | { readonly type: FlagType.ApiDefault; + + /** Describe restoring old behavior or dealing with the change (Markdown) */ + readonly compatibilityWithOldBehaviorMd: string } + | { readonly type: FlagType.BugFix; + /** Describe restoring old behavior or dealing with the change (Markdown) */ + readonly compatibilityWithOldBehaviorMd?: string } + | { readonly type: FlagType.VisibleContext } +); \ No newline at end of file