From c17879dd8dab526695e69c6faf8345292634ba24 Mon Sep 17 00:00:00 2001 From: Jane Chen <125300057+chenjane-dev@users.noreply.github.com> Date: Tue, 20 Feb 2024 15:05:06 -0500 Subject: [PATCH] fix(appconfig): scope generated alarm role policy to '*' for composite alarm support (#29171) ### Reason for this change Customers could create an alarm of type `IAlarm` where the alarm would be a composite alarm (for ex, when importing composite alarms, they return a type `IAlarm` instead of `CompositeAlarm`. This caused the logic that differentiates a composite alarm to mistakenly categorize the alarm incorrectly. ### Description of changes Add one policy scoped to `*` for any alarm passed to an environment. ### Description of how you validated changes Unit and integration 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* --- .../aws-appconfig-alpha/lib/environment.ts | 24 +- .../test/environment.test.ts | 80 +++--- ...efaultTestDeployAssert75BD28E7.assets.json | 2 +- .../aws-appconfig-environment.assets.json | 6 +- .../aws-appconfig-environment.template.json | 171 ++++++----- .../integ.environment.js.snapshot/cdk.out | 2 +- .../integ.environment.js.snapshot/integ.json | 2 +- .../manifest.json | 47 +++- .../integ.environment.js.snapshot/tree.json | 265 +++++++++++------- .../test/integ.environment.ts | 56 +++- 10 files changed, 397 insertions(+), 258 deletions(-) diff --git a/packages/@aws-cdk/aws-appconfig-alpha/lib/environment.ts b/packages/@aws-cdk/aws-appconfig-alpha/lib/environment.ts index d85ecab12e231..aaad287952b5c 100644 --- a/packages/@aws-cdk/aws-appconfig-alpha/lib/environment.ts +++ b/packages/@aws-cdk/aws-appconfig-alpha/lib/environment.ts @@ -5,6 +5,7 @@ import * as iam from 'aws-cdk-lib/aws-iam'; import { Construct } from 'constructs'; import { IApplication } from './application'; import { ActionPoint, IEventDestination, ExtensionOptions, IExtension, IExtensible, ExtensibleBase } from './extension'; +import { getHash } from './private/hash'; /** * Attributes of an existing AWS AppConfig environment to import it. @@ -252,11 +253,11 @@ export class Environment extends EnvironmentBase { applicationId: this.applicationId, name: this.name, description: this.description, - monitors: this.monitors?.map((monitor, index) => { + monitors: this.monitors?.map((monitor) => { return { alarmArn: monitor.alarmArn, ...(monitor.monitorType === MonitorType.CLOUDWATCH - ? { alarmRoleArn: monitor.alarmRoleArn || this.createAlarmRole(monitor, index).roleArn } + ? { alarmRoleArn: monitor.alarmRoleArn || this.createOrGetAlarmRole().roleArn } : { alarmRoleArn: monitor.alarmRoleArn }), }; }), @@ -274,24 +275,20 @@ export class Environment extends EnvironmentBase { this.application.addExistingEnvironment(this); } - private createAlarmRole(monitor: Monitor, index: number): iam.IRole { - const logicalId = monitor.isCompositeAlarm ? 'RoleCompositeAlarm' : `Role${index}`; + private createOrGetAlarmRole(): iam.IRole { + // the name is guaranteed to be set in line 243 + const logicalId = `Role${getHash(this.name!)}`; const existingRole = this.node.tryFindChild(logicalId) as iam.IRole; if (existingRole) { return existingRole; } - const alarmArn = monitor.isCompositeAlarm - ? this.stack.formatArn({ - service: 'cloudwatch', - resource: 'alarm', - resourceName: '*', - arnFormat: ArnFormat.COLON_RESOURCE_NAME, - }) - : monitor.alarmArn; + // this scope is fine for cloudwatch:DescribeAlarms since it is readonly + // and it is required for composite alarms + // https://docs.aws.amazon.com/AmazonCloudWatch/latest/APIReference/API_DescribeAlarms.html const policy = new iam.PolicyStatement({ effect: iam.Effect.ALLOW, actions: ['cloudwatch:DescribeAlarms'], - resources: [alarmArn], + resources: ['*'], }); const document = new iam.PolicyDocument({ statements: [policy], @@ -338,7 +335,6 @@ export abstract class Monitor { alarmArn: alarm.alarmArn, alarmRoleArn: alarmRole?.roleArn, monitorType: MonitorType.CLOUDWATCH, - isCompositeAlarm: alarm instanceof cloudwatch.CompositeAlarm, }; } diff --git a/packages/@aws-cdk/aws-appconfig-alpha/test/environment.test.ts b/packages/@aws-cdk/aws-appconfig-alpha/test/environment.test.ts index 261d113728dae..8c0f8eae3aca1 100644 --- a/packages/@aws-cdk/aws-appconfig-alpha/test/environment.test.ts +++ b/packages/@aws-cdk/aws-appconfig-alpha/test/environment.test.ts @@ -140,7 +140,7 @@ describe('environment', () => { }, AlarmRoleArn: { 'Fn::GetAtt': [ - 'MyEnvironmentRole01C8C013F', + 'MyEnvironmentRole1E6113D2F07A1', 'Arn', ], }, @@ -154,12 +154,7 @@ describe('environment', () => { Statement: [ { Effect: iam.Effect.ALLOW, - Resource: { - 'Fn::GetAtt': [ - 'Alarm7103F465', - 'Arn', - ], - }, + Resource: '*', Action: 'cloudwatch:DescribeAlarms', }, ], @@ -272,7 +267,7 @@ describe('environment', () => { }, AlarmRoleArn: { 'Fn::GetAtt': [ - 'MyEnvironmentRoleCompositeAlarm8C2A0542', + 'MyEnvironmentRole1E6113D2F07A1', 'Arn', ], }, @@ -286,20 +281,7 @@ describe('environment', () => { Statement: [ { Effect: iam.Effect.ALLOW, - Resource: { - 'Fn::Join': [ - '', - [ - 'arn:', - { Ref: 'AWS::Partition' }, - ':cloudwatch:', - { Ref: 'AWS::Region' }, - ':', - { Ref: 'AWS::AccountId' }, - ':alarm:*', - ], - ], - }, + Resource: '*', Action: 'cloudwatch:DescribeAlarms', }, ], @@ -357,7 +339,7 @@ describe('environment', () => { }, AlarmRoleArn: { 'Fn::GetAtt': [ - 'MyEnvironmentRoleCompositeAlarm8C2A0542', + 'MyEnvironmentRole1E6113D2F07A1', 'Arn', ], }, @@ -371,7 +353,7 @@ describe('environment', () => { }, AlarmRoleArn: { 'Fn::GetAtt': [ - 'MyEnvironmentRoleCompositeAlarm8C2A0542', + 'MyEnvironmentRole1E6113D2F07A1', 'Arn', ], }, @@ -385,20 +367,7 @@ describe('environment', () => { Statement: [ { Effect: iam.Effect.ALLOW, - Resource: { - 'Fn::Join': [ - '', - [ - 'arn:', - { Ref: 'AWS::Partition' }, - ':cloudwatch:', - { Ref: 'AWS::Region' }, - ':', - { Ref: 'AWS::AccountId' }, - ':alarm:*', - ], - ], - }, + Resource: '*', Action: 'cloudwatch:DescribeAlarms', }, ], @@ -409,7 +378,7 @@ describe('environment', () => { }); }); - test('environment with monitors with two alarms', () => { + test('environment with monitors with multiple alarms', () => { const stack = new cdk.Stack(); const app = new Application(stack, 'MyAppConfig'); const alarm1 = new Alarm(stack, 'Alarm1', { @@ -432,17 +401,28 @@ describe('environment', () => { }, ), }); + const alarm3 = new Alarm(stack, 'Alarm3', { + threshold: 5, + evaluationPeriods: 5, + metric: new Metric( + { + namespace: 'aws', + metricName: 'myMetric', + }, + ), + }); new Environment(stack, 'MyEnvironment', { environmentName: 'TestEnv', application: app, monitors: [ Monitor.fromCloudWatchAlarm(alarm1), Monitor.fromCloudWatchAlarm(alarm2), + Monitor.fromCloudWatchAlarm(alarm3), ], }); - Template.fromStack(stack).resourceCountIs('AWS::CloudWatch::Alarm', 2); - Template.fromStack(stack).resourceCountIs('AWS::IAM::Role', 2); + Template.fromStack(stack).resourceCountIs('AWS::CloudWatch::Alarm', 3); + Template.fromStack(stack).resourceCountIs('AWS::IAM::Role', 1); Template.fromStack(stack).hasResourceProperties('AWS::AppConfig::Environment', { Name: 'TestEnv', ApplicationId: { @@ -458,7 +438,7 @@ describe('environment', () => { }, AlarmRoleArn: { 'Fn::GetAtt': [ - 'MyEnvironmentRole01C8C013F', + 'MyEnvironmentRole1E6113D2F07A1', 'Arn', ], }, @@ -472,7 +452,21 @@ describe('environment', () => { }, AlarmRoleArn: { 'Fn::GetAtt': [ - 'MyEnvironmentRole135A2CEE4', + 'MyEnvironmentRole1E6113D2F07A1', + 'Arn', + ], + }, + }, + { + AlarmArn: { + 'Fn::GetAtt': [ + 'Alarm32341D8D9', + 'Arn', + ], + }, + AlarmRoleArn: { + 'Fn::GetAtt': [ + 'MyEnvironmentRole1E6113D2F07A1', 'Arn', ], }, diff --git a/packages/@aws-cdk/aws-appconfig-alpha/test/integ.environment.js.snapshot/appconfigenvironmentDefaultTestDeployAssert75BD28E7.assets.json b/packages/@aws-cdk/aws-appconfig-alpha/test/integ.environment.js.snapshot/appconfigenvironmentDefaultTestDeployAssert75BD28E7.assets.json index 87b95745076b2..947e7fb4d76ea 100644 --- a/packages/@aws-cdk/aws-appconfig-alpha/test/integ.environment.js.snapshot/appconfigenvironmentDefaultTestDeployAssert75BD28E7.assets.json +++ b/packages/@aws-cdk/aws-appconfig-alpha/test/integ.environment.js.snapshot/appconfigenvironmentDefaultTestDeployAssert75BD28E7.assets.json @@ -1,5 +1,5 @@ { - "version": "35.0.0", + "version": "36.0.0", "files": { "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { "source": { diff --git a/packages/@aws-cdk/aws-appconfig-alpha/test/integ.environment.js.snapshot/aws-appconfig-environment.assets.json b/packages/@aws-cdk/aws-appconfig-alpha/test/integ.environment.js.snapshot/aws-appconfig-environment.assets.json index fa54d57aa0d8a..8ffcd1a6d5b6d 100644 --- a/packages/@aws-cdk/aws-appconfig-alpha/test/integ.environment.js.snapshot/aws-appconfig-environment.assets.json +++ b/packages/@aws-cdk/aws-appconfig-alpha/test/integ.environment.js.snapshot/aws-appconfig-environment.assets.json @@ -1,7 +1,7 @@ { - "version": "35.0.0", + "version": "36.0.0", "files": { - "6452c0ef7699cda5c609159e92012f180afda9cac21a0cba23acff97b8734de7": { + "6ec3a45c455c20f3072a3622b3e548aa72a4c1b8e5a1fac757962194d9f1c82d": { "source": { "path": "aws-appconfig-environment.template.json", "packaging": "file" @@ -9,7 +9,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "6452c0ef7699cda5c609159e92012f180afda9cac21a0cba23acff97b8734de7.json", + "objectKey": "6ec3a45c455c20f3072a3622b3e548aa72a4c1b8e5a1fac757962194d9f1c82d.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-appconfig-alpha/test/integ.environment.js.snapshot/aws-appconfig-environment.template.json b/packages/@aws-cdk/aws-appconfig-alpha/test/integ.environment.js.snapshot/aws-appconfig-environment.template.json index bb9c67d5ebfcb..ea327d13d23c1 100644 --- a/packages/@aws-cdk/aws-appconfig-alpha/test/integ.environment.js.snapshot/aws-appconfig-environment.template.json +++ b/packages/@aws-cdk/aws-appconfig-alpha/test/integ.environment.js.snapshot/aws-appconfig-environment.template.json @@ -6,16 +6,33 @@ "Name": "AppForEnvTest" } }, - "MyAlarm696658B6": { + "StartDeploymentCallCountAlarm6846E07B": { "Type": "AWS::CloudWatch::Alarm", "Properties": { + "ActionsEnabled": false, + "AlarmName": "AppConfigStartDeploymentCallCountAlarm", "ComparisonOperator": "GreaterThanOrEqualToThreshold", - "EvaluationPeriods": 5, - "MetricName": "dummy name", - "Namespace": "aws", + "Dimensions": [ + { + "Name": "Resource", + "Value": "StartDeployment" + }, + { + "Name": "Service", + "Value": "AWS AppConfig" + }, + { + "Name": "Type", + "Value": "API" + } + ], + "EvaluationPeriods": 3, + "MetricName": "CallCount", + "Namespace": "AWS/AppConfig", "Period": 300, - "Statistic": "Average", - "Threshold": 10 + "Statistic": "Sum", + "Threshold": 300, + "TreatMissingData": "notBreaching" } }, "MyRoleF48FFE04": { @@ -32,7 +49,22 @@ } ], "Version": "2012-10-17" - } + }, + "Policies": [ + { + "PolicyDocument": { + "Statement": [ + { + "Action": "cloudwatch:DescribeAlarms", + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "AllowAppConfigMonitorAlarmPolicy" + } + ] } }, "MyCompositeAlarm0F045229": { @@ -46,7 +78,7 @@ "ALARM(\"", { "Fn::GetAtt": [ - "MyAlarm696658B6", + "StartDeploymentCallCountAlarm6846E07B", "Arn" ] }, @@ -56,44 +88,7 @@ } } }, - "MyEnvironmentRole01C8C013F": { - "Type": "AWS::IAM::Role", - "Properties": { - "AssumeRolePolicyDocument": { - "Statement": [ - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": { - "Service": "appconfig.amazonaws.com" - } - } - ], - "Version": "2012-10-17" - }, - "Policies": [ - { - "PolicyDocument": { - "Statement": [ - { - "Action": "cloudwatch:DescribeAlarms", - "Effect": "Allow", - "Resource": { - "Fn::GetAtt": [ - "MyAlarm696658B6", - "Arn" - ] - } - } - ], - "Version": "2012-10-17" - }, - "PolicyName": "AllowAppConfigMonitorAlarmPolicy" - } - ] - } - }, - "MyEnvironmentRoleCompositeAlarm8C2A0542": { + "MyEnvironmentRole1963C404EAE3E": { "Type": "AWS::IAM::Role", "Properties": { "AssumeRolePolicyDocument": { @@ -115,26 +110,7 @@ { "Action": "cloudwatch:DescribeAlarms", "Effect": "Allow", - "Resource": { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":cloudwatch:", - { - "Ref": "AWS::Region" - }, - ":", - { - "Ref": "AWS::AccountId" - }, - ":alarm:*" - ] - ] - } + "Resource": "*" } ], "Version": "2012-10-17" @@ -155,13 +131,13 @@ { "AlarmArn": { "Fn::GetAtt": [ - "MyAlarm696658B6", + "StartDeploymentCallCountAlarm6846E07B", "Arn" ] }, "AlarmRoleArn": { "Fn::GetAtt": [ - "MyEnvironmentRole01C8C013F", + "MyEnvironmentRole1963C404EAE3E", "Arn" ] } @@ -169,7 +145,7 @@ { "AlarmArn": { "Fn::GetAtt": [ - "MyAlarm696658B6", + "StartDeploymentCallCountAlarm6846E07B", "Arn" ] }, @@ -189,7 +165,7 @@ }, "AlarmRoleArn": { "Fn::GetAtt": [ - "MyEnvironmentRoleCompositeAlarm8C2A0542", + "MyEnvironmentRole1963C404EAE3E", "Arn" ] } @@ -197,6 +173,61 @@ ], "Name": "awsappconfigenvironment-MyEnvironment-C8813182" } + }, + "MyDeploymentStrategy60D31FB0": { + "Type": "AWS::AppConfig::DeploymentStrategy", + "Properties": { + "DeploymentDurationInMinutes": 1, + "GrowthFactor": 50, + "GrowthType": "LINEAR", + "Name": "awsappconfigenvironment-MyDeploymentStrategy-28486041", + "ReplicateTo": "NONE" + } + }, + "MyConfigConfigurationProfileCF3951C3": { + "Type": "AWS::AppConfig::ConfigurationProfile", + "Properties": { + "ApplicationId": { + "Ref": "MyApplicationForEnv1F597ED9" + }, + "LocationUri": "hosted", + "Name": "awsappconfigenvironment-MyConfig-24828868" + } + }, + "MyConfigFA92D419": { + "Type": "AWS::AppConfig::HostedConfigurationVersion", + "Properties": { + "ApplicationId": { + "Ref": "MyApplicationForEnv1F597ED9" + }, + "ConfigurationProfileId": { + "Ref": "MyConfigConfigurationProfileCF3951C3" + }, + "Content": "config content", + "ContentType": "application/octet-stream" + }, + "UpdateReplacePolicy": "Retain", + "DeletionPolicy": "Retain" + }, + "MyConfigDeployment1963CC374E8A4": { + "Type": "AWS::AppConfig::Deployment", + "Properties": { + "ApplicationId": { + "Ref": "MyApplicationForEnv1F597ED9" + }, + "ConfigurationProfileId": { + "Ref": "MyConfigConfigurationProfileCF3951C3" + }, + "ConfigurationVersion": { + "Ref": "MyConfigFA92D419" + }, + "DeploymentStrategyId": { + "Ref": "MyDeploymentStrategy60D31FB0" + }, + "EnvironmentId": { + "Ref": "MyEnvironment465E4DEA" + } + } } }, "Parameters": { diff --git a/packages/@aws-cdk/aws-appconfig-alpha/test/integ.environment.js.snapshot/cdk.out b/packages/@aws-cdk/aws-appconfig-alpha/test/integ.environment.js.snapshot/cdk.out index c5cb2e5de6344..1f0068d32659a 100644 --- a/packages/@aws-cdk/aws-appconfig-alpha/test/integ.environment.js.snapshot/cdk.out +++ b/packages/@aws-cdk/aws-appconfig-alpha/test/integ.environment.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"35.0.0"} \ No newline at end of file +{"version":"36.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-appconfig-alpha/test/integ.environment.js.snapshot/integ.json b/packages/@aws-cdk/aws-appconfig-alpha/test/integ.environment.js.snapshot/integ.json index 8c6291ddb72a5..c314a395d9c88 100644 --- a/packages/@aws-cdk/aws-appconfig-alpha/test/integ.environment.js.snapshot/integ.json +++ b/packages/@aws-cdk/aws-appconfig-alpha/test/integ.environment.js.snapshot/integ.json @@ -1,5 +1,5 @@ { - "version": "35.0.0", + "version": "36.0.0", "testCases": { "appconfig-environment/DefaultTest": { "stacks": [ diff --git a/packages/@aws-cdk/aws-appconfig-alpha/test/integ.environment.js.snapshot/manifest.json b/packages/@aws-cdk/aws-appconfig-alpha/test/integ.environment.js.snapshot/manifest.json index cb504329bc8a0..e21ade66747e8 100644 --- a/packages/@aws-cdk/aws-appconfig-alpha/test/integ.environment.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-appconfig-alpha/test/integ.environment.js.snapshot/manifest.json @@ -1,5 +1,5 @@ { - "version": "35.0.0", + "version": "36.0.0", "artifacts": { "aws-appconfig-environment.assets": { "type": "cdk:asset-manifest", @@ -18,7 +18,7 @@ "validateOnSynth": false, "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", - "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/6452c0ef7699cda5c609159e92012f180afda9cac21a0cba23acff97b8734de7.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/6ec3a45c455c20f3072a3622b3e548aa72a4c1b8e5a1fac757962194d9f1c82d.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ @@ -40,10 +40,10 @@ "data": "MyApplicationForEnv1F597ED9" } ], - "/aws-appconfig-environment/MyAlarm/Resource": [ + "/aws-appconfig-environment/StartDeploymentCallCountAlarm/Resource": [ { "type": "aws:cdk:logicalId", - "data": "MyAlarm696658B6" + "data": "StartDeploymentCallCountAlarm6846E07B" } ], "/aws-appconfig-environment/MyRole/Resource": [ @@ -58,22 +58,40 @@ "data": "MyCompositeAlarm0F045229" } ], - "/aws-appconfig-environment/MyEnvironment/Role0/Resource": [ + "/aws-appconfig-environment/MyEnvironment/Role1963C/Resource": [ { "type": "aws:cdk:logicalId", - "data": "MyEnvironmentRole01C8C013F" + "data": "MyEnvironmentRole1963C404EAE3E" } ], - "/aws-appconfig-environment/MyEnvironment/RoleCompositeAlarm/Resource": [ + "/aws-appconfig-environment/MyEnvironment/Resource": [ { "type": "aws:cdk:logicalId", - "data": "MyEnvironmentRoleCompositeAlarm8C2A0542" + "data": "MyEnvironment465E4DEA" } ], - "/aws-appconfig-environment/MyEnvironment/Resource": [ + "/aws-appconfig-environment/MyDeploymentStrategy/Resource": [ { "type": "aws:cdk:logicalId", - "data": "MyEnvironment465E4DEA" + "data": "MyDeploymentStrategy60D31FB0" + } + ], + "/aws-appconfig-environment/MyConfig/ConfigurationProfile": [ + { + "type": "aws:cdk:logicalId", + "data": "MyConfigConfigurationProfileCF3951C3" + } + ], + "/aws-appconfig-environment/MyConfig/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyConfigFA92D419" + } + ], + "/aws-appconfig-environment/MyConfig/Deployment1963C": [ + { + "type": "aws:cdk:logicalId", + "data": "MyConfigDeployment1963CC374E8A4" } ], "/aws-appconfig-environment/BootstrapVersion": [ @@ -87,6 +105,15 @@ "type": "aws:cdk:logicalId", "data": "CheckBootstrapVersion" } + ], + "MyConfigDeployment36077E0B58611": [ + { + "type": "aws:cdk:logicalId", + "data": "MyConfigDeployment36077E0B58611", + "trace": [ + "!!DESTRUCTIVE_CHANGES: WILL_DESTROY" + ] + } ] }, "displayName": "aws-appconfig-environment" diff --git a/packages/@aws-cdk/aws-appconfig-alpha/test/integ.environment.js.snapshot/tree.json b/packages/@aws-cdk/aws-appconfig-alpha/test/integ.environment.js.snapshot/tree.json index 744719477b065..fd96c532cfa58 100644 --- a/packages/@aws-cdk/aws-appconfig-alpha/test/integ.environment.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-appconfig-alpha/test/integ.environment.js.snapshot/tree.json @@ -32,23 +32,40 @@ "version": "0.0.0" } }, - "MyAlarm": { - "id": "MyAlarm", - "path": "aws-appconfig-environment/MyAlarm", + "StartDeploymentCallCountAlarm": { + "id": "StartDeploymentCallCountAlarm", + "path": "aws-appconfig-environment/StartDeploymentCallCountAlarm", "children": { "Resource": { "id": "Resource", - "path": "aws-appconfig-environment/MyAlarm/Resource", + "path": "aws-appconfig-environment/StartDeploymentCallCountAlarm/Resource", "attributes": { "aws:cdk:cloudformation:type": "AWS::CloudWatch::Alarm", "aws:cdk:cloudformation:props": { + "actionsEnabled": false, + "alarmName": "AppConfigStartDeploymentCallCountAlarm", "comparisonOperator": "GreaterThanOrEqualToThreshold", - "evaluationPeriods": 5, - "metricName": "dummy name", - "namespace": "aws", + "dimensions": [ + { + "name": "Resource", + "value": "StartDeployment" + }, + { + "name": "Service", + "value": "AWS AppConfig" + }, + { + "name": "Type", + "value": "API" + } + ], + "evaluationPeriods": 3, + "metricName": "CallCount", + "namespace": "AWS/AppConfig", "period": 300, - "statistic": "Average", - "threshold": 10 + "statistic": "Sum", + "threshold": 300, + "treatMissingData": "notBreaching" } }, "constructInfo": { @@ -91,7 +108,22 @@ } ], "Version": "2012-10-17" - } + }, + "policies": [ + { + "policyName": "AllowAppConfigMonitorAlarmPolicy", + "policyDocument": { + "Statement": [ + { + "Action": "cloudwatch:DescribeAlarms", + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + } + } + ] } }, "constructInfo": { @@ -123,7 +155,7 @@ "ALARM(\"", { "Fn::GetAtt": [ - "MyAlarm696658B6", + "StartDeploymentCallCountAlarm6846E07B", "Arn" ] }, @@ -148,76 +180,13 @@ "id": "MyEnvironment", "path": "aws-appconfig-environment/MyEnvironment", "children": { - "Role0": { - "id": "Role0", - "path": "aws-appconfig-environment/MyEnvironment/Role0", - "children": { - "ImportRole0": { - "id": "ImportRole0", - "path": "aws-appconfig-environment/MyEnvironment/Role0/ImportRole0", - "constructInfo": { - "fqn": "aws-cdk-lib.Resource", - "version": "0.0.0" - } - }, - "Resource": { - "id": "Resource", - "path": "aws-appconfig-environment/MyEnvironment/Role0/Resource", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::IAM::Role", - "aws:cdk:cloudformation:props": { - "assumeRolePolicyDocument": { - "Statement": [ - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": { - "Service": "appconfig.amazonaws.com" - } - } - ], - "Version": "2012-10-17" - }, - "policies": [ - { - "policyName": "AllowAppConfigMonitorAlarmPolicy", - "policyDocument": { - "Statement": [ - { - "Action": "cloudwatch:DescribeAlarms", - "Effect": "Allow", - "Resource": { - "Fn::GetAtt": [ - "MyAlarm696658B6", - "Arn" - ] - } - } - ], - "Version": "2012-10-17" - } - } - ] - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_iam.CfnRole", - "version": "0.0.0" - } - } - }, - "constructInfo": { - "fqn": "aws-cdk-lib.aws_iam.Role", - "version": "0.0.0" - } - }, - "RoleCompositeAlarm": { - "id": "RoleCompositeAlarm", - "path": "aws-appconfig-environment/MyEnvironment/RoleCompositeAlarm", + "Role1963C": { + "id": "Role1963C", + "path": "aws-appconfig-environment/MyEnvironment/Role1963C", "children": { - "ImportRoleCompositeAlarm": { - "id": "ImportRoleCompositeAlarm", - "path": "aws-appconfig-environment/MyEnvironment/RoleCompositeAlarm/ImportRoleCompositeAlarm", + "ImportRole1963C": { + "id": "ImportRole1963C", + "path": "aws-appconfig-environment/MyEnvironment/Role1963C/ImportRole1963C", "constructInfo": { "fqn": "aws-cdk-lib.Resource", "version": "0.0.0" @@ -225,7 +194,7 @@ }, "Resource": { "id": "Resource", - "path": "aws-appconfig-environment/MyEnvironment/RoleCompositeAlarm/Resource", + "path": "aws-appconfig-environment/MyEnvironment/Role1963C/Resource", "attributes": { "aws:cdk:cloudformation:type": "AWS::IAM::Role", "aws:cdk:cloudformation:props": { @@ -249,26 +218,7 @@ { "Action": "cloudwatch:DescribeAlarms", "Effect": "Allow", - "Resource": { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":cloudwatch:", - { - "Ref": "AWS::Region" - }, - ":", - { - "Ref": "AWS::AccountId" - }, - ":alarm:*" - ] - ] - } + "Resource": "*" } ], "Version": "2012-10-17" @@ -302,13 +252,13 @@ { "alarmArn": { "Fn::GetAtt": [ - "MyAlarm696658B6", + "StartDeploymentCallCountAlarm6846E07B", "Arn" ] }, "alarmRoleArn": { "Fn::GetAtt": [ - "MyEnvironmentRole01C8C013F", + "MyEnvironmentRole1963C404EAE3E", "Arn" ] } @@ -316,7 +266,7 @@ { "alarmArn": { "Fn::GetAtt": [ - "MyAlarm696658B6", + "StartDeploymentCallCountAlarm6846E07B", "Arn" ] }, @@ -336,7 +286,7 @@ }, "alarmRoleArn": { "Fn::GetAtt": [ - "MyEnvironmentRoleCompositeAlarm8C2A0542", + "MyEnvironmentRole1963C404EAE3E", "Arn" ] } @@ -356,6 +306,111 @@ "version": "0.0.0" } }, + "MyDeploymentStrategy": { + "id": "MyDeploymentStrategy", + "path": "aws-appconfig-environment/MyDeploymentStrategy", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-appconfig-environment/MyDeploymentStrategy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::AppConfig::DeploymentStrategy", + "aws:cdk:cloudformation:props": { + "deploymentDurationInMinutes": 1, + "growthFactor": 50, + "growthType": "LINEAR", + "name": "awsappconfigenvironment-MyDeploymentStrategy-28486041", + "replicateTo": "NONE" + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_appconfig.CfnDeploymentStrategy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-appconfig-alpha.DeploymentStrategy", + "version": "0.0.0" + } + }, + "MyConfig": { + "id": "MyConfig", + "path": "aws-appconfig-environment/MyConfig", + "children": { + "ConfigurationProfile": { + "id": "ConfigurationProfile", + "path": "aws-appconfig-environment/MyConfig/ConfigurationProfile", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::AppConfig::ConfigurationProfile", + "aws:cdk:cloudformation:props": { + "applicationId": { + "Ref": "MyApplicationForEnv1F597ED9" + }, + "locationUri": "hosted", + "name": "awsappconfigenvironment-MyConfig-24828868" + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_appconfig.CfnConfigurationProfile", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "aws-appconfig-environment/MyConfig/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::AppConfig::HostedConfigurationVersion", + "aws:cdk:cloudformation:props": { + "applicationId": { + "Ref": "MyApplicationForEnv1F597ED9" + }, + "configurationProfileId": { + "Ref": "MyConfigConfigurationProfileCF3951C3" + }, + "content": "config content", + "contentType": "application/octet-stream" + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_appconfig.CfnHostedConfigurationVersion", + "version": "0.0.0" + } + }, + "Deployment1963C": { + "id": "Deployment1963C", + "path": "aws-appconfig-environment/MyConfig/Deployment1963C", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::AppConfig::Deployment", + "aws:cdk:cloudformation:props": { + "applicationId": { + "Ref": "MyApplicationForEnv1F597ED9" + }, + "configurationProfileId": { + "Ref": "MyConfigConfigurationProfileCF3951C3" + }, + "configurationVersion": { + "Ref": "MyConfigFA92D419" + }, + "deploymentStrategyId": { + "Ref": "MyDeploymentStrategy60D31FB0" + }, + "environmentId": { + "Ref": "MyEnvironment465E4DEA" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_appconfig.CfnDeployment", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-appconfig-alpha.HostedConfiguration", + "version": "0.0.0" + } + }, "BootstrapVersion": { "id": "BootstrapVersion", "path": "aws-appconfig-environment/BootstrapVersion", diff --git a/packages/@aws-cdk/aws-appconfig-alpha/test/integ.environment.ts b/packages/@aws-cdk/aws-appconfig-alpha/test/integ.environment.ts index 31f41061aaca1..30694cc43e900 100644 --- a/packages/@aws-cdk/aws-appconfig-alpha/test/integ.environment.ts +++ b/packages/@aws-cdk/aws-appconfig-alpha/test/integ.environment.ts @@ -1,8 +1,8 @@ import { IntegTest } from '@aws-cdk/integ-tests-alpha'; -import { App, Stack } from 'aws-cdk-lib'; -import { Alarm, CompositeAlarm, Metric } from 'aws-cdk-lib/aws-cloudwatch'; -import { Role, ServicePrincipal } from 'aws-cdk-lib/aws-iam'; -import { Application, Environment, Monitor } from '../lib'; +import { App, Duration, PhysicalName, Stack } from 'aws-cdk-lib'; +import { Alarm, ComparisonOperator, CompositeAlarm, Metric, TreatMissingData } from 'aws-cdk-lib/aws-cloudwatch'; +import { Role, ServicePrincipal, Effect, PolicyStatement, PolicyDocument } from 'aws-cdk-lib/aws-iam'; +import { Application, ConfigurationContent, DeploymentStrategy, Environment, HostedConfiguration, Monitor, RolloutStrategy } from '../lib'; const app = new App(); @@ -12,23 +12,46 @@ const stack = new Stack(app, 'aws-appconfig-environment'); const appForEnv = new Application(stack, 'MyApplicationForEnv', { applicationName: 'AppForEnvTest', }); -const alarm = new Alarm(stack, 'MyAlarm', { +const alarm = new Alarm(stack, 'StartDeploymentCallCountAlarm', { + alarmName: 'AppConfigStartDeploymentCallCountAlarm', metric: new Metric({ - namespace: 'aws', - metricName: 'dummy name', + namespace: 'AWS/AppConfig', + metricName: 'CallCount', + dimensionsMap: { + Type: 'API', + Resource: 'StartDeployment', + Service: 'AWS AppConfig', + }, + statistic: 'SUM', + period: Duration.minutes(5), }), - evaluationPeriods: 5, - threshold: 10, + threshold: 300, + comparisonOperator: ComparisonOperator.GREATER_THAN_OR_EQUAL_TO_THRESHOLD, + evaluationPeriods: 3, + treatMissingData: TreatMissingData.NOT_BREACHING, + actionsEnabled: false, +}); +const policy = new PolicyStatement({ + effect: Effect.ALLOW, + actions: ['cloudwatch:DescribeAlarms'], + resources: ['*'], +}); +const document = new PolicyDocument({ + statements: [policy], }); const role = new Role(stack, 'MyRole', { + roleName: PhysicalName.GENERATE_IF_NEEDED, assumedBy: new ServicePrincipal('appconfig.amazonaws.com'), + inlinePolicies: { + ['AllowAppConfigMonitorAlarmPolicy']: document, + }, }); const compositeAlarm = new CompositeAlarm(stack, 'MyCompositeAlarm', { alarmRule: alarm, }); // create environment with all props defined -new Environment(stack, 'MyEnvironment', { +const env = new Environment(stack, 'MyEnvironment', { application: appForEnv, description: 'This is the environment for integ testing', monitors: [ @@ -41,6 +64,19 @@ new Environment(stack, 'MyEnvironment', { ], }); +// ensure the service can track the monitors in the environment +new HostedConfiguration(stack, 'MyConfig', { + application: appForEnv, + content: ConfigurationContent.fromInline('config content'), + deploymentStrategy: new DeploymentStrategy(stack, 'MyDeploymentStrategy', { + rolloutStrategy: RolloutStrategy.linear({ + deploymentDuration: Duration.minutes(1), + growthFactor: 50, + }), + }), + deployTo: [env], +}); + /* resource deployment alone is sufficient because we already have the corresponding resource handler tests to assert that resources can be used after created */