Skip to content

Commit ce88c76

Browse files
feat(appconfig): deletion protection check for configuration profile (#34418)
### Issue # (if applicable) None ### Reason for this change Cloudformation now supports for configuring deletion protection check for configuration profile in addition to environment. https://docs.aws.amazon.com/appconfig/latest/userguide/deletion-protection.html https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-appconfig-configurationprofile.html#cfn-appconfig-configurationprofile-deletionprotectioncheck ### Description of changes - Add `deletionProtectionCheck` to both `HostedConfigurationProfileProps` and `SourcedConfigurationProfileProps` ### Describe any new or updated permissions being added None ### Description of how you validated changes Add both unit and integ tests. ### Checklist - [x] My code adheres to the [CONTRIBUTING GUIDE](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) and [DESIGN GUIDELINES](https://github.com/aws/aws-cdk/blob/main/docs/DESIGN_GUIDELINES.md) ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
1 parent d604089 commit ce88c76

File tree

9 files changed

+115
-23
lines changed

9 files changed

+115
-23
lines changed

packages/@aws-cdk-testing/framework-integ/test/aws-appconfig/test/integ.configuration.js.snapshot/aws-appconfig-configuration.assets.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/@aws-cdk-testing/framework-integ/test/aws-appconfig/test/integ.configuration.js.snapshot/aws-appconfig-configuration.template.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@
105105
"ApplicationId": {
106106
"Ref": "MyAppConfigB4B63E75"
107107
},
108+
"DeletionProtectionCheck": "BYPASS",
108109
"LocationUri": "hosted",
109110
"Name": "awsappconfigconfiguration-MyHostedConfigFromFile-8ED1123C"
110111
}
@@ -399,6 +400,7 @@
399400
"ApplicationId": {
400401
"Ref": "MyAppConfigB4B63E75"
401402
},
403+
"DeletionProtectionCheck": "BYPASS",
402404
"Description": "This is a configuration profile used for integ testing",
403405
"LocationUri": {
404406
"Fn::Join": [

packages/@aws-cdk-testing/framework-integ/test/aws-appconfig/test/integ.configuration.js.snapshot/manifest.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/@aws-cdk-testing/framework-integ/test/aws-appconfig/test/integ.configuration.js.snapshot/tree.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/@aws-cdk-testing/framework-integ/test/aws-appconfig/test/integ.configuration.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
Application,
1414
ConfigurationContent,
1515
ConfigurationSource,
16+
DeletionProtectionCheck,
1617
DeploymentStrategy,
1718
HostedConfiguration,
1819
JsonSchemaValidator,
@@ -57,6 +58,7 @@ const deploymentStrategy = new DeploymentStrategy(stack, 'MyDeployStrategy', {
5758
new HostedConfiguration(stack, 'MyHostedConfigFromFile', {
5859
application: appConfigApp,
5960
content: ConfigurationContent.fromFile('config.json'),
61+
deletionProtectionCheck: DeletionProtectionCheck.BYPASS,
6062
});
6163

6264
// create basic config profile and add config version
@@ -110,6 +112,7 @@ new SourcedConfiguration(stack, 'MyConfigFromParameter', {
110112
LambdaValidator.fromFunction(func),
111113
],
112114
deploymentStrategy,
115+
deletionProtectionCheck: DeletionProtectionCheck.BYPASS,
113116
});
114117

115118
// ssm document as configuration source

packages/aws-cdk-lib/aws-appconfig/README.md

Lines changed: 34 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -96,25 +96,6 @@ const user = new iam.User(this, 'MyUser');
9696
env.grantReadConfig(user);
9797
```
9898

99-
### Deletion Protection Check
100-
101-
You can enable [deletion protection](https://docs.aws.amazon.com/appconfig/latest/userguide/deletion-protection.html) on the environment by setting the `deletionProtectionCheck` property.
102-
103-
- ACCOUNT_DEFAULT: The default setting, which uses account-level deletion protection. To configure account-level deletion protection, use the UpdateAccountSettings API.
104-
- APPLY: Instructs the deletion protection check to run, even if deletion protection is disabled at the account level. APPLY also forces the deletion protection check to run against resources created in the past hour, which are normally excluded from deletion protection checks.
105-
- BYPASS: Instructs AWS AppConfig to bypass the deletion protection check and delete an environment even if deletion protection would have otherwise prevented it.
106-
107-
```ts
108-
declare const application: appconfig.Application;
109-
declare const alarm: cloudwatch.Alarm;
110-
declare const compositeAlarm: cloudwatch.CompositeAlarm;
111-
112-
new appconfig.Environment(this, 'MyEnvironment', {
113-
application,
114-
deletionProtectionCheck: appconfig.DeletionProtectionCheck.APPLY,
115-
});
116-
```
117-
11899
## Deployment Strategy
119100

120101
[AWS AppConfig Deployment Strategy Documentation](https://docs.aws.amazon.com/appconfig/latest/userguide/appconfig-creating-deployment-strategy.html)
@@ -551,6 +532,40 @@ new appconfig.SourcedConfiguration(this, 'MySourcedConfiguration', {
551532
});
552533
```
553534

535+
## Deletion Protection Check
536+
537+
You can enable [deletion protection](https://docs.aws.amazon.com/appconfig/latest/userguide/deletion-protection.html) on the environment and configuration profile by setting the `deletionProtectionCheck` property.
538+
539+
- ACCOUNT_DEFAULT: The default setting, which uses account-level deletion protection. To configure account-level deletion protection, use the UpdateAccountSettings API.
540+
- APPLY: Instructs the deletion protection check to run, even if deletion protection is disabled at the account level. APPLY also forces the deletion protection check to run against resources created in the past hour, which are normally excluded from deletion protection checks.
541+
- BYPASS: Instructs AWS AppConfig to bypass the deletion protection check and delete an environment even if deletion protection would have otherwise prevented it.
542+
543+
```ts
544+
declare const application: appconfig.Application;
545+
declare const alarm: cloudwatch.Alarm;
546+
declare const compositeAlarm: cloudwatch.CompositeAlarm;
547+
declare const bucket: s3.Bucket;
548+
549+
// Environment deletion protection check
550+
new appconfig.Environment(this, 'MyEnvironment', {
551+
application,
552+
deletionProtectionCheck: appconfig.DeletionProtectionCheck.APPLY,
553+
});
554+
555+
// configuration profile with deletion protection check
556+
new appconfig.HostedConfiguration(this, 'MyHostedConfigFromFile', {
557+
application,
558+
content: appconfig.ConfigurationContent.fromFile('config.json'),
559+
deletionProtectionCheck: appconfig.DeletionProtectionCheck.BYPASS,
560+
});
561+
562+
new appconfig.SourcedConfiguration(this, 'MySourcedConfiguration', {
563+
application,
564+
location: appconfig.ConfigurationSource.fromBucket(bucket, 'path/to/file.json'),
565+
deletionProtectionCheck: appconfig.DeletionProtectionCheck.ACCOUNT_DEFAULT,
566+
});
567+
```
568+
554569
## Extension
555570

556571
An extension augments your ability to inject logic or behavior at different points during the AWS AppConfig workflow of

packages/aws-cdk-lib/aws-appconfig/lib/configuration.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import * as sm from '../../aws-secretsmanager';
1616
import * as ssm from '../../aws-ssm';
1717
import { PhysicalName, Stack, ArnFormat, Names, RemovalPolicy } from '../../core';
1818
import * as mimeTypes from 'mime-types';
19+
import { DeletionProtectionCheck } from './util';
1920

2021
/**
2122
* Options for the Configuration construct
@@ -76,6 +77,17 @@ export interface ConfigurationOptions {
7677
* @default - None.
7778
*/
7879
readonly deploymentKey?: kms.IKey;
80+
81+
/**
82+
* A parameter to configure deletion protection.
83+
* Deletion protection prevents a user from deleting a configuration profile if your application has called
84+
* either `GetLatestConfiguration` or `GetConfiguration` for the configuration profile during the specified interval.
85+
*
86+
* @see https://docs.aws.amazon.com/appconfig/latest/userguide/deletion-protection.html
87+
*
88+
* @default DeletionProtectionCheck.ACCOUNT_DEFAULT
89+
*/
90+
readonly deletionProtectionCheck?: DeletionProtectionCheck;
7991
}
8092

8193
/**
@@ -186,6 +198,7 @@ abstract class ConfigurationBase extends Construct implements IConfiguration, IE
186198

187199
protected applicationId: string;
188200
protected extensible!: ExtensibleBase;
201+
protected deletionProtectionCheck?: DeletionProtectionCheck;
189202

190203
constructor(scope: Construct, id: string, props: ConfigurationProps) {
191204
super(scope, id);
@@ -201,6 +214,7 @@ abstract class ConfigurationBase extends Construct implements IConfiguration, IE
201214
this.description = props.description;
202215
this.deployTo = props.deployTo;
203216
this.deploymentKey = props.deploymentKey;
217+
this.deletionProtectionCheck = props.deletionProtectionCheck;
204218
this.deploymentStrategy = props.deploymentStrategy || new DeploymentStrategy(this, 'DeploymentStrategy', {
205219
rolloutStrategy: RolloutStrategy.CANARY_10_PERCENT_20_MINUTES,
206220
});
@@ -442,6 +456,7 @@ export class HostedConfiguration extends ConfigurationBase {
442456
description: this.description,
443457
type: this.type,
444458
validators: this.validators,
459+
deletionProtectionCheck: this.deletionProtectionCheck,
445460
});
446461
this.configurationProfileId = this._cfnConfigurationProfile.ref;
447462
this.configurationProfileArn = Stack.of(this).formatArn({
@@ -584,6 +599,7 @@ export class SourcedConfiguration extends ConfigurationBase {
584599
retrievalRoleArn: this.retrievalRole?.roleArn,
585600
type: this.type,
586601
validators: this.validators,
602+
deletionProtectionCheck: this.deletionProtectionCheck,
587603
});
588604

589605
this.configurationProfileId = this._cfnConfigurationProfile.ref;

packages/aws-cdk-lib/aws-appconfig/test/configuration.test.ts

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import {
1818
JsonSchemaValidator,
1919
ConfigurationContent,
2020
RolloutStrategy,
21+
DeletionProtectionCheck,
2122
} from '../lib';
2223

2324
describe('configuration', () => {
@@ -789,6 +790,61 @@ describe('configuration', () => {
789790
Template.fromStack(stack).resourceCountIs('AWS::AppConfig::Deployment', 0);
790791
});
791792

793+
test.each([
794+
DeletionProtectionCheck.ACCOUNT_DEFAULT,
795+
DeletionProtectionCheck.APPLY,
796+
DeletionProtectionCheck.BYPASS,
797+
])('hosted configuration profile with deletion protection check', (deletionProtectionCheck) => {
798+
const stack = new cdk.Stack();
799+
const app = new Application(stack, 'MyAppConfig');
800+
new HostedConfiguration(stack, 'MyConfigurationProfile', {
801+
name: 'TestConfigProfile',
802+
application: app,
803+
content: ConfigurationContent.fromInlineText('This is my content'),
804+
deletionProtectionCheck,
805+
deploymentStrategy: new DeploymentStrategy(stack, 'MyDeploymentStrategy', {
806+
rolloutStrategy: RolloutStrategy.linear({
807+
growthFactor: 15,
808+
deploymentDuration: cdk.Duration.minutes(30),
809+
}),
810+
}),
811+
});
812+
813+
Template.fromStack(stack).hasResourceProperties('AWS::AppConfig::ConfigurationProfile', {
814+
Name: 'TestConfigProfile',
815+
ApplicationId: {
816+
Ref: 'MyAppConfigB4B63E75',
817+
},
818+
DeletionProtectionCheck: deletionProtectionCheck,
819+
});
820+
});
821+
822+
test.each([
823+
DeletionProtectionCheck.ACCOUNT_DEFAULT,
824+
DeletionProtectionCheck.APPLY,
825+
DeletionProtectionCheck.BYPASS,
826+
])('sourced configuration profile with deletion protection check', (deletionProtectionCheck) => {
827+
const stack = new cdk.Stack();
828+
const app = new Application(stack, 'MyAppConfig');
829+
const bucket = new Bucket(stack, 'MyBucket');
830+
831+
new SourcedConfiguration(stack, 'MySourcedConfig', {
832+
name: 'TestConfigProfile',
833+
versionNumber: '1',
834+
location: ConfigurationSource.fromBucket(bucket, 'path/to/object'),
835+
application: app,
836+
deletionProtectionCheck,
837+
});
838+
839+
Template.fromStack(stack).hasResourceProperties('AWS::AppConfig::ConfigurationProfile', {
840+
Name: 'TestConfigProfile',
841+
ApplicationId: {
842+
Ref: 'MyAppConfigB4B63E75',
843+
},
844+
DeletionProtectionCheck: deletionProtectionCheck,
845+
});
846+
});
847+
792848
test('configuration profile with inline json schema validator', () => {
793849
const stack = new cdk.Stack();
794850
const app = new Application(stack, 'MyAppConfig');

0 commit comments

Comments
 (0)