From f12a0acadc3c935e51e6b41132fe5a085cf3146d Mon Sep 17 00:00:00 2001 From: Calvin Combs Date: Thu, 17 Feb 2022 09:49:34 -0800 Subject: [PATCH 01/13] rewrite Construct imports --- .../lib/cloudformation/private/singleton-policy.ts | 5 +---- .../lib/cloudformation/stackinstances-action.ts | 7 ++----- .../lib/cloudformation/stackset-action.ts | 6 ++---- 3 files changed, 5 insertions(+), 13 deletions(-) diff --git a/packages/@aws-cdk/aws-codepipeline-actions/lib/cloudformation/private/singleton-policy.ts b/packages/@aws-cdk/aws-codepipeline-actions/lib/cloudformation/private/singleton-policy.ts index 7a9a3efdde784..e2bc7cbf7cee3 100644 --- a/packages/@aws-cdk/aws-codepipeline-actions/lib/cloudformation/private/singleton-policy.ts +++ b/packages/@aws-cdk/aws-codepipeline-actions/lib/cloudformation/private/singleton-policy.ts @@ -1,9 +1,6 @@ import * as iam from '@aws-cdk/aws-iam'; import * as cdk from '@aws-cdk/core'; - -// keep this import separate from other imports to reduce chance for merge conflicts with v2-main -// eslint-disable-next-line no-duplicate-imports, import/order -import { Construct } from '@aws-cdk/core'; +import { Construct } from 'constructs'; /** * Manages a bunch of singleton-y statements on the policy of an IAM Role. diff --git a/packages/@aws-cdk/aws-codepipeline-actions/lib/cloudformation/stackinstances-action.ts b/packages/@aws-cdk/aws-codepipeline-actions/lib/cloudformation/stackinstances-action.ts index e0ddf6c9c1cb6..e5170318699c0 100644 --- a/packages/@aws-cdk/aws-codepipeline-actions/lib/cloudformation/stackinstances-action.ts +++ b/packages/@aws-cdk/aws-codepipeline-actions/lib/cloudformation/stackinstances-action.ts @@ -1,13 +1,10 @@ import * as codepipeline from '@aws-cdk/aws-codepipeline'; +import { Construct } from 'constructs'; import { Action } from '../action'; import { validatePercentage } from '../common'; import { SingletonPolicy } from './private/singleton-policy'; import { CommonCloudFormationStackSetOptions, StackInstances, StackSetParameters } from './stackset-types'; -// keep this import separate from other imports to reduce chance for merge conflicts with v2-main -// eslint-disable-next-line no-duplicate-imports, import/order -import { Construct as CoreConstruct } from '@aws-cdk/core'; - /** * Properties for the CloudFormationDeployStackInstancesAction */ @@ -74,7 +71,7 @@ export class CloudFormationDeployStackInstancesAction extends Action { validatePercentage('maxAccountConcurrencyPercentage', props.maxAccountConcurrencyPercentage); } - protected bound(scope: CoreConstruct, _stage: codepipeline.IStage, options: codepipeline.ActionBindOptions): codepipeline.ActionConfig { + protected bound(scope: Construct, _stage: codepipeline.IStage, options: codepipeline.ActionBindOptions): codepipeline.ActionConfig { const singletonPolicy = SingletonPolicy.forRole(options.role); singletonPolicy.grantCreateUpdateStackSet(this.props); diff --git a/packages/@aws-cdk/aws-codepipeline-actions/lib/cloudformation/stackset-action.ts b/packages/@aws-cdk/aws-codepipeline-actions/lib/cloudformation/stackset-action.ts index 574e69f86a96c..47731d8332fb7 100644 --- a/packages/@aws-cdk/aws-codepipeline-actions/lib/cloudformation/stackset-action.ts +++ b/packages/@aws-cdk/aws-codepipeline-actions/lib/cloudformation/stackset-action.ts @@ -1,13 +1,11 @@ import * as codepipeline from '@aws-cdk/aws-codepipeline'; import * as cdk from '@aws-cdk/core'; +import { Construct } from 'constructs'; import { Action } from '../action'; import { validatePercentage } from '../common'; import { parseCapabilities, SingletonPolicy } from './private/singleton-policy'; import { CommonCloudFormationStackSetOptions, StackInstances, StackSetDeploymentModel, StackSetParameters, StackSetTemplate } from './stackset-types'; -// keep this import separate from other imports to reduce chance for merge conflicts with v2-main -// eslint-disable-next-line no-duplicate-imports, import/order -import { Construct as CoreConstruct } from '@aws-cdk/core'; /** * Properties for the CloudFormationDeployStackSetAction @@ -142,7 +140,7 @@ export class CloudFormationDeployStackSetAction extends Action { validatePercentage('maxAccountConcurrencyPercentage', props.maxAccountConcurrencyPercentage); } - protected bound(scope: CoreConstruct, _stage: codepipeline.IStage, options: codepipeline.ActionBindOptions): codepipeline.ActionConfig { + protected bound(scope: Construct, _stage: codepipeline.IStage, options: codepipeline.ActionBindOptions): codepipeline.ActionConfig { const singletonPolicy = SingletonPolicy.forRole(options.role); singletonPolicy.grantCreateUpdateStackSet(this.props); From 03c3a267e676bc5c2950343a0de29c393559eef5 Mon Sep 17 00:00:00 2001 From: Calvin Combs Date: Thu, 17 Feb 2022 09:51:05 -0800 Subject: [PATCH 02/13] undo --- .../lib/cloudformation/private/singleton-policy.ts | 5 ++++- .../lib/cloudformation/stackinstances-action.ts | 7 +++++-- .../lib/cloudformation/stackset-action.ts | 6 ++++-- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/packages/@aws-cdk/aws-codepipeline-actions/lib/cloudformation/private/singleton-policy.ts b/packages/@aws-cdk/aws-codepipeline-actions/lib/cloudformation/private/singleton-policy.ts index e2bc7cbf7cee3..7a9a3efdde784 100644 --- a/packages/@aws-cdk/aws-codepipeline-actions/lib/cloudformation/private/singleton-policy.ts +++ b/packages/@aws-cdk/aws-codepipeline-actions/lib/cloudformation/private/singleton-policy.ts @@ -1,6 +1,9 @@ import * as iam from '@aws-cdk/aws-iam'; import * as cdk from '@aws-cdk/core'; -import { Construct } from 'constructs'; + +// keep this import separate from other imports to reduce chance for merge conflicts with v2-main +// eslint-disable-next-line no-duplicate-imports, import/order +import { Construct } from '@aws-cdk/core'; /** * Manages a bunch of singleton-y statements on the policy of an IAM Role. diff --git a/packages/@aws-cdk/aws-codepipeline-actions/lib/cloudformation/stackinstances-action.ts b/packages/@aws-cdk/aws-codepipeline-actions/lib/cloudformation/stackinstances-action.ts index e5170318699c0..e0ddf6c9c1cb6 100644 --- a/packages/@aws-cdk/aws-codepipeline-actions/lib/cloudformation/stackinstances-action.ts +++ b/packages/@aws-cdk/aws-codepipeline-actions/lib/cloudformation/stackinstances-action.ts @@ -1,10 +1,13 @@ import * as codepipeline from '@aws-cdk/aws-codepipeline'; -import { Construct } from 'constructs'; import { Action } from '../action'; import { validatePercentage } from '../common'; import { SingletonPolicy } from './private/singleton-policy'; import { CommonCloudFormationStackSetOptions, StackInstances, StackSetParameters } from './stackset-types'; +// keep this import separate from other imports to reduce chance for merge conflicts with v2-main +// eslint-disable-next-line no-duplicate-imports, import/order +import { Construct as CoreConstruct } from '@aws-cdk/core'; + /** * Properties for the CloudFormationDeployStackInstancesAction */ @@ -71,7 +74,7 @@ export class CloudFormationDeployStackInstancesAction extends Action { validatePercentage('maxAccountConcurrencyPercentage', props.maxAccountConcurrencyPercentage); } - protected bound(scope: Construct, _stage: codepipeline.IStage, options: codepipeline.ActionBindOptions): codepipeline.ActionConfig { + protected bound(scope: CoreConstruct, _stage: codepipeline.IStage, options: codepipeline.ActionBindOptions): codepipeline.ActionConfig { const singletonPolicy = SingletonPolicy.forRole(options.role); singletonPolicy.grantCreateUpdateStackSet(this.props); diff --git a/packages/@aws-cdk/aws-codepipeline-actions/lib/cloudformation/stackset-action.ts b/packages/@aws-cdk/aws-codepipeline-actions/lib/cloudformation/stackset-action.ts index 47731d8332fb7..574e69f86a96c 100644 --- a/packages/@aws-cdk/aws-codepipeline-actions/lib/cloudformation/stackset-action.ts +++ b/packages/@aws-cdk/aws-codepipeline-actions/lib/cloudformation/stackset-action.ts @@ -1,11 +1,13 @@ import * as codepipeline from '@aws-cdk/aws-codepipeline'; import * as cdk from '@aws-cdk/core'; -import { Construct } from 'constructs'; import { Action } from '../action'; import { validatePercentage } from '../common'; import { parseCapabilities, SingletonPolicy } from './private/singleton-policy'; import { CommonCloudFormationStackSetOptions, StackInstances, StackSetDeploymentModel, StackSetParameters, StackSetTemplate } from './stackset-types'; +// keep this import separate from other imports to reduce chance for merge conflicts with v2-main +// eslint-disable-next-line no-duplicate-imports, import/order +import { Construct as CoreConstruct } from '@aws-cdk/core'; /** * Properties for the CloudFormationDeployStackSetAction @@ -140,7 +142,7 @@ export class CloudFormationDeployStackSetAction extends Action { validatePercentage('maxAccountConcurrencyPercentage', props.maxAccountConcurrencyPercentage); } - protected bound(scope: Construct, _stage: codepipeline.IStage, options: codepipeline.ActionBindOptions): codepipeline.ActionConfig { + protected bound(scope: CoreConstruct, _stage: codepipeline.IStage, options: codepipeline.ActionBindOptions): codepipeline.ActionConfig { const singletonPolicy = SingletonPolicy.forRole(options.role); singletonPolicy.grantCreateUpdateStackSet(this.props); From 14809d3d556fcd38c8ed4aaec21d2bfe2080f073 Mon Sep 17 00:00:00 2001 From: Calvin Combs Date: Wed, 23 Feb 2022 17:51:38 -0800 Subject: [PATCH 03/13] successful investigation code --- .../@aws-cdk/aws-iam/lib/policy-statement.ts | 7 ++++++- packages/@aws-cdk/aws-logs/lib/log-group.ts | 19 ++++++++++++++++++- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/packages/@aws-cdk/aws-iam/lib/policy-statement.ts b/packages/@aws-cdk/aws-iam/lib/policy-statement.ts index 08a8353e84b36..48b3d0f970b68 100644 --- a/packages/@aws-cdk/aws-iam/lib/policy-statement.ts +++ b/packages/@aws-cdk/aws-iam/lib/policy-statement.ts @@ -62,7 +62,7 @@ export class PolicyStatement { private readonly action = new Array(); private readonly notAction = new Array(); - private readonly principal: { [key: string]: any[] } = {}; + private principal: { [key: string]: any[] } = {}; private readonly notPrincipal: { [key: string]: any[] } = {}; private readonly resource = new Array(); private readonly notResource = new Array(); @@ -466,8 +466,13 @@ export class PolicyStatement { } return errors; } + + public clearPrincipals(): void { + this.principal = {}; + } } + /** * The Effect element of an IAM policy * diff --git a/packages/@aws-cdk/aws-logs/lib/log-group.ts b/packages/@aws-cdk/aws-logs/lib/log-group.ts index 9baf950f92f85..1255f3114b001 100644 --- a/packages/@aws-cdk/aws-logs/lib/log-group.ts +++ b/packages/@aws-cdk/aws-logs/lib/log-group.ts @@ -1,7 +1,7 @@ import * as cloudwatch from '@aws-cdk/aws-cloudwatch'; import * as iam from '@aws-cdk/aws-iam'; import * as kms from '@aws-cdk/aws-kms'; -import { ArnFormat, RemovalPolicy, Resource, Stack, Token } from '@aws-cdk/core'; +import { ArnFormat, Fn, RemovalPolicy, Resource, Stack, Token } from '@aws-cdk/core'; import { Construct } from 'constructs'; import { LogStream } from './log-stream'; import { CfnLogGroup } from './logs.generated'; @@ -200,6 +200,23 @@ abstract class LogGroupBase extends Resource implements ILogGroup { if (!this.policy) { this.policy = new ResourcePolicy(this, 'Policy'); } + console.log(statement.hasPrincipal); + if (statement.hasPrincipal) { + console.log(statement.toJSON()); + for (const principal in statement.toJSON().Principal) { + const token = statement.toJSON().Principal[principal]; + console.log(token) + console.log(Token.isUnresolved(token)); + if (Token.isUnresolved(token)) { + console.log(Fn.split(':', token)) + statement.clearPrincipals(); + // 4, to get the 5th element, because the 4th is a `:` because the arn has `::` immediately preceeding the account id + statement.addArnPrincipal(Fn.select(4, Fn.split(':', token))); + console.log(statement.toJSON()) + + } + } + } this.policy.document.addStatements(statement); return { statementAdded: true, policyDependable: this.policy }; } From a4cb4237bac32a9601695360e8c3807ae28e4611 Mon Sep 17 00:00:00 2001 From: Calvin Combs Date: Thu, 24 Feb 2022 18:41:56 -0800 Subject: [PATCH 04/13] temp --- .../@aws-cdk/aws-iam/lib/policy-statement.ts | 48 +++++++++++++++++-- packages/@aws-cdk/aws-logs/lib/log-group.ts | 17 +++---- .../@aws-cdk/aws-logs/test/loggroup.test.ts | 48 ++++++++++++++++++- 3 files changed, 97 insertions(+), 16 deletions(-) diff --git a/packages/@aws-cdk/aws-iam/lib/policy-statement.ts b/packages/@aws-cdk/aws-iam/lib/policy-statement.ts index 48b3d0f970b68..3d4aba592f3fc 100644 --- a/packages/@aws-cdk/aws-iam/lib/policy-statement.ts +++ b/packages/@aws-cdk/aws-iam/lib/policy-statement.ts @@ -62,7 +62,7 @@ export class PolicyStatement { private readonly action = new Array(); private readonly notAction = new Array(); - private principal: { [key: string]: any[] } = {}; + private readonly principal: { [key: string]: any[] } = {}; private readonly notPrincipal: { [key: string]: any[] } = {}; private readonly resource = new Array(); private readonly notResource = new Array(); @@ -318,6 +318,48 @@ export class PolicyStatement { this.addCondition('StringEquals', { 'sts:ExternalId': accountId }); } + public copy(overrides: PolicyStatementProps = {}) { + /* + for (const action of [...props.actions || [], ...props.notActions || []]) { + + if (!/^(\*|[a-zA-Z0-9-]+:[a-zA-Z0-9*]+)$/.test(action) && !cdk.Token.isUnresolved(action)) { + throw new Error(`Action '${action}' is invalid. An action string consists of a service namespace, a colon, and the name of an action. Action names can include wildcards.`); + } + } + + this.sid = props.sid; + this.effect = props.effect || Effect.ALLOW; + + this.addActions(...props.actions || []); + this.addNotActions(...props.notActions || []); + this.addPrincipals(...props.principals || []); + this.addNotPrincipals(...props.notPrincipals || []); + this.addResources(...props.resources || []); + this.addNotResources(...props.notResources || []); + if (props.conditions !== undefined) { + this.addConditions(props.conditions); + } + */ + + + + + const props:PolicyStatementProps = { + sid: overrides.sid ?? this.sid, + effect: overrides.effect ?? this.effect, + actions: overrides.actions ?? this.action, + notActions: overrides.notActions ?? this.notAction, + + principals: overrides.principals, + notPrincipals: overrides.notPrincipals, + + resources: overrides.resources ?? this.resource, + notResources: overrides.notResources ?? this.notResource, + + }; + return new PolicyStatement(); + } + /** * JSON-ify the policy statement * @@ -466,10 +508,6 @@ export class PolicyStatement { } return errors; } - - public clearPrincipals(): void { - this.principal = {}; - } } diff --git a/packages/@aws-cdk/aws-logs/lib/log-group.ts b/packages/@aws-cdk/aws-logs/lib/log-group.ts index 1255f3114b001..fce1c244bf349 100644 --- a/packages/@aws-cdk/aws-logs/lib/log-group.ts +++ b/packages/@aws-cdk/aws-logs/lib/log-group.ts @@ -200,24 +200,21 @@ abstract class LogGroupBase extends Resource implements ILogGroup { if (!this.policy) { this.policy = new ResourcePolicy(this, 'Policy'); } - console.log(statement.hasPrincipal); + statement.copy({ + + }); if (statement.hasPrincipal) { - console.log(statement.toJSON()); for (const principal in statement.toJSON().Principal) { const token = statement.toJSON().Principal[principal]; - console.log(token) - console.log(Token.isUnresolved(token)); if (Token.isUnresolved(token)) { - console.log(Fn.split(':', token)) - statement.clearPrincipals(); // 4, to get the 5th element, because the 4th is a `:` because the arn has `::` immediately preceeding the account id - statement.addArnPrincipal(Fn.select(4, Fn.split(':', token))); - console.log(statement.toJSON()) - + fixedStatement.addArnPrincipal(Fn.select(4, Fn.split(':', token))); + } else { + fixedStatement.addPrincipals(token); } } } - this.policy.document.addStatements(statement); + this.policy.document.addStatements(fixedStatement); return { statementAdded: true, policyDependable: this.policy }; } } diff --git a/packages/@aws-cdk/aws-logs/test/loggroup.test.ts b/packages/@aws-cdk/aws-logs/test/loggroup.test.ts index 4fefc67272d5f..be3c85b69fbf5 100644 --- a/packages/@aws-cdk/aws-logs/test/loggroup.test.ts +++ b/packages/@aws-cdk/aws-logs/test/loggroup.test.ts @@ -1,7 +1,7 @@ import { Template } from '@aws-cdk/assertions'; import * as iam from '@aws-cdk/aws-iam'; import * as kms from '@aws-cdk/aws-kms'; -import { CfnParameter, RemovalPolicy, Stack } from '@aws-cdk/core'; +import { CfnParameter, Fn/*, Intrinsic*/, RemovalPolicy, Stack, Token } from '@aws-cdk/core'; import { LogGroup, RetentionDays } from '../lib'; describe('log group', () => { @@ -383,6 +383,52 @@ describe('log group', () => { }); }); + test('policies with token statements correctly extract the account id from the role ARN', () => { + // GIVEN + const stack = new Stack(); + const lg = new LogGroup(stack, 'LogGroup'); + //const tokenizedRole = new Intrinsic('arn:aws:iam::123456789012:role/my-role'); + const tokenizedRole = Fn.importValue('roleExport'); + + // WHEN + lg.addToResourcePolicy(new iam.PolicyStatement({ + resources: ['*'], + actions: ['logs:PutLogEvents'], + principals: [new iam.ArnPrincipal(Token.asString(tokenizedRole))], + })); + + const document = { + Statement: [{ + Action: 'logs:PutLogEvents', + Effect: 'Allow', + Principal: { + AWS: { + 'Fn::Select': [ + 4, + { + 'Fn::Split': [ + ':', + { + 'Fn::ImportValue': 'roleExport', + }, + ], + }, + ], + }, + }, + Resource: '*', + }], + Version: '2012-10-17', + }; + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::Logs::ResourcePolicy', { + PolicyDocument: document, //`{"Statement":[{"Action":"logs:PutLogEvents","Effect":"Allow","Principal":{"AWS":"arn:aws:iam::123456789012:user/user-name"},"Resource":"*"}],"Version":"2012-10-17"}`, + PolicyName: 'LogGroupPolicy643B329C', + }); + }); + + test('correctly returns physical name of the log group', () => { // GIVEN const stack = new Stack(); From c11d76ee1e5abdeea67b67a9d98cde81ef327cd8 Mon Sep 17 00:00:00 2001 From: Calvin Combs Date: Tue, 8 Mar 2022 16:07:06 -0800 Subject: [PATCH 05/13] improved role handling logic --- .../@aws-cdk/aws-iam/lib/policy-statement.ts | 39 ++++------------ packages/@aws-cdk/aws-logs/lib/log-group.ts | 20 ++------ .../@aws-cdk/aws-logs/test/loggroup.test.ts | 46 +++++++------------ 3 files changed, 31 insertions(+), 74 deletions(-) diff --git a/packages/@aws-cdk/aws-iam/lib/policy-statement.ts b/packages/@aws-cdk/aws-iam/lib/policy-statement.ts index 3d4aba592f3fc..5f1aec513fffd 100644 --- a/packages/@aws-cdk/aws-iam/lib/policy-statement.ts +++ b/packages/@aws-cdk/aws-iam/lib/policy-statement.ts @@ -69,6 +69,9 @@ export class PolicyStatement { private readonly condition: { [key: string]: any } = { }; private principalConditionsJson?: string; + // Hold on to those principals + private readonly _principals = new Array(); + constructor(props: PolicyStatementProps = {}) { // Validate actions for (const action of [...props.actions || [], ...props.notActions || []]) { @@ -144,6 +147,7 @@ export class PolicyStatement { * @param principals IAM principals that will be added */ public addPrincipals(...principals: IPrincipal[]) { + this._principals.push(...principals); if (Object.keys(principals).length > 0 && Object.keys(this.notPrincipal).length > 0) { throw new Error('Cannot add \'Principals\' to policy statement if \'NotPrincipals\' have been added'); } @@ -155,6 +159,10 @@ export class PolicyStatement { } } + public get principals(): IPrincipal[] { + return [...this._principals]; + } + /** * Specify principals that is not allowed or denied access to the "NotPrincipal" section of * a policy statement. @@ -319,32 +327,7 @@ export class PolicyStatement { } public copy(overrides: PolicyStatementProps = {}) { - /* - for (const action of [...props.actions || [], ...props.notActions || []]) { - - if (!/^(\*|[a-zA-Z0-9-]+:[a-zA-Z0-9*]+)$/.test(action) && !cdk.Token.isUnresolved(action)) { - throw new Error(`Action '${action}' is invalid. An action string consists of a service namespace, a colon, and the name of an action. Action names can include wildcards.`); - } - } - - this.sid = props.sid; - this.effect = props.effect || Effect.ALLOW; - - this.addActions(...props.actions || []); - this.addNotActions(...props.notActions || []); - this.addPrincipals(...props.principals || []); - this.addNotPrincipals(...props.notPrincipals || []); - this.addResources(...props.resources || []); - this.addNotResources(...props.notResources || []); - if (props.conditions !== undefined) { - this.addConditions(props.conditions); - } - */ - - - - - const props:PolicyStatementProps = { + return new PolicyStatement({ sid: overrides.sid ?? this.sid, effect: overrides.effect ?? this.effect, actions: overrides.actions ?? this.action, @@ -355,9 +338,7 @@ export class PolicyStatement { resources: overrides.resources ?? this.resource, notResources: overrides.notResources ?? this.notResource, - - }; - return new PolicyStatement(); + }); } /** diff --git a/packages/@aws-cdk/aws-logs/lib/log-group.ts b/packages/@aws-cdk/aws-logs/lib/log-group.ts index fce1c244bf349..46473485e7620 100644 --- a/packages/@aws-cdk/aws-logs/lib/log-group.ts +++ b/packages/@aws-cdk/aws-logs/lib/log-group.ts @@ -1,7 +1,7 @@ import * as cloudwatch from '@aws-cdk/aws-cloudwatch'; import * as iam from '@aws-cdk/aws-iam'; import * as kms from '@aws-cdk/aws-kms'; -import { ArnFormat, Fn, RemovalPolicy, Resource, Stack, Token } from '@aws-cdk/core'; +import { ArnFormat, RemovalPolicy, Resource, Stack, Token } from '@aws-cdk/core'; import { Construct } from 'constructs'; import { LogStream } from './log-stream'; import { CfnLogGroup } from './logs.generated'; @@ -200,21 +200,9 @@ abstract class LogGroupBase extends Resource implements ILogGroup { if (!this.policy) { this.policy = new ResourcePolicy(this, 'Policy'); } - statement.copy({ - - }); - if (statement.hasPrincipal) { - for (const principal in statement.toJSON().Principal) { - const token = statement.toJSON().Principal[principal]; - if (Token.isUnresolved(token)) { - // 4, to get the 5th element, because the 4th is a `:` because the arn has `::` immediately preceeding the account id - fixedStatement.addArnPrincipal(Fn.select(4, Fn.split(':', token))); - } else { - fixedStatement.addPrincipals(token); - } - } - } - this.policy.document.addStatements(fixedStatement); + this.policy.document.addStatements(statement.copy({ + principals: statement.principals.map(p => p.principalAccount !== undefined ? new iam.ArnPrincipal(p.principalAccount) : p), + })); return { statementAdded: true, policyDependable: this.policy }; } } diff --git a/packages/@aws-cdk/aws-logs/test/loggroup.test.ts b/packages/@aws-cdk/aws-logs/test/loggroup.test.ts index be3c85b69fbf5..db68d983d6afe 100644 --- a/packages/@aws-cdk/aws-logs/test/loggroup.test.ts +++ b/packages/@aws-cdk/aws-logs/test/loggroup.test.ts @@ -1,7 +1,7 @@ import { Template } from '@aws-cdk/assertions'; import * as iam from '@aws-cdk/aws-iam'; import * as kms from '@aws-cdk/aws-kms'; -import { CfnParameter, Fn/*, Intrinsic*/, RemovalPolicy, Stack, Token } from '@aws-cdk/core'; +import { CfnParameter, Fn/*, Intrinsic*/, RemovalPolicy, Stack } from '@aws-cdk/core'; import { LogGroup, RetentionDays } from '../lib'; describe('log group', () => { @@ -388,43 +388,31 @@ describe('log group', () => { const stack = new Stack(); const lg = new LogGroup(stack, 'LogGroup'); //const tokenizedRole = new Intrinsic('arn:aws:iam::123456789012:role/my-role'); - const tokenizedRole = Fn.importValue('roleExport'); // WHEN lg.addToResourcePolicy(new iam.PolicyStatement({ resources: ['*'], actions: ['logs:PutLogEvents'], - principals: [new iam.ArnPrincipal(Token.asString(tokenizedRole))], + principals: [iam.Role.fromRoleArn(stack, 'Role', Fn.importValue('SomeRole'))], })); - const document = { - Statement: [{ - Action: 'logs:PutLogEvents', - Effect: 'Allow', - Principal: { - AWS: { - 'Fn::Select': [ - 4, - { - 'Fn::Split': [ - ':', - { - 'Fn::ImportValue': 'roleExport', - }, - ], - }, - ], - }, - }, - Resource: '*', - }], - Version: '2012-10-17', - }; - // THEN Template.fromStack(stack).hasResourceProperties('AWS::Logs::ResourcePolicy', { - PolicyDocument: document, //`{"Statement":[{"Action":"logs:PutLogEvents","Effect":"Allow","Principal":{"AWS":"arn:aws:iam::123456789012:user/user-name"},"Resource":"*"}],"Version":"2012-10-17"}`, - PolicyName: 'LogGroupPolicy643B329C', + PolicyDocument: { + 'Fn::Join': [ + '', + [ + '{\"Statement\":[{\"Action\":\"logs:PutLogEvents\",\"Effect\":\"Allow\",\"Principal\":{\"AWS\":\"', + { + 'Fn::Select': [ + 4, + { 'Fn::Split': [':', { 'Fn::ImportValue': 'SomeRole' }] }, + ], + }, + '\"},\"Resource\":\"*\"}],\"Version\":\"2012-10-17\"}', + ], + ], + }, }); }); From 7b2a91e3e35b589dd43c8101a5ed78128b7ffdc6 Mon Sep 17 00:00:00 2001 From: Calvin Combs Date: Wed, 16 Mar 2022 16:38:01 -0700 Subject: [PATCH 06/13] fixed arn principal handling --- .../@aws-cdk/aws-iam/lib/policy-statement.ts | 8 ++++++ packages/@aws-cdk/aws-iam/lib/principals.ts | 1 + packages/@aws-cdk/aws-logs/lib/log-group.ts | 28 +++++++++++++++++-- 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/packages/@aws-cdk/aws-iam/lib/policy-statement.ts b/packages/@aws-cdk/aws-iam/lib/policy-statement.ts index 5f1aec513fffd..9d302dfc852d8 100644 --- a/packages/@aws-cdk/aws-iam/lib/policy-statement.ts +++ b/packages/@aws-cdk/aws-iam/lib/policy-statement.ts @@ -159,6 +159,9 @@ export class PolicyStatement { } } + /** + * aaaaaaaaaaaa + */ public get principals(): IPrincipal[] { return [...this._principals]; } @@ -326,6 +329,11 @@ export class PolicyStatement { this.addCondition('StringEquals', { 'sts:ExternalId': accountId }); } + /** + * aaaaaaaaaaaaaaaaaaaaaaa + * @param overrides + * @returns + */ public copy(overrides: PolicyStatementProps = {}) { return new PolicyStatement({ sid: overrides.sid ?? this.sid, diff --git a/packages/@aws-cdk/aws-iam/lib/principals.ts b/packages/@aws-cdk/aws-iam/lib/principals.ts index aecd493192142..998423f171ca6 100644 --- a/packages/@aws-cdk/aws-iam/lib/principals.ts +++ b/packages/@aws-cdk/aws-iam/lib/principals.ts @@ -359,6 +359,7 @@ export class ArnPrincipal extends PrincipalBase { */ constructor(public readonly arn: string) { super(); + console.log('yay') } public get policyFragment(): PrincipalPolicyFragment { diff --git a/packages/@aws-cdk/aws-logs/lib/log-group.ts b/packages/@aws-cdk/aws-logs/lib/log-group.ts index 46473485e7620..b76a7f627eda4 100644 --- a/packages/@aws-cdk/aws-logs/lib/log-group.ts +++ b/packages/@aws-cdk/aws-logs/lib/log-group.ts @@ -1,7 +1,7 @@ import * as cloudwatch from '@aws-cdk/aws-cloudwatch'; import * as iam from '@aws-cdk/aws-iam'; import * as kms from '@aws-cdk/aws-kms'; -import { ArnFormat, RemovalPolicy, Resource, Stack, Token } from '@aws-cdk/core'; +import { Arn, ArnFormat, RemovalPolicy, Resource, Stack, Token } from '@aws-cdk/core'; import { Construct } from 'constructs'; import { LogStream } from './log-stream'; import { CfnLogGroup } from './logs.generated'; @@ -201,10 +201,34 @@ abstract class LogGroupBase extends Resource implements ILogGroup { this.policy = new ResourcePolicy(this, 'Policy'); } this.policy.document.addStatements(statement.copy({ - principals: statement.principals.map(p => p.principalAccount !== undefined ? new iam.ArnPrincipal(p.principalAccount) : p), + //principals: statement.principals.map(p => p.principalAccount !== undefined ? new iam.ArnPrincipal(p.principalAccount) : p), + principals: statement.principals.map(p => this.mutatePrincipal(p)), })); return { statementAdded: true, policyDependable: this.policy }; } + + private mutatePrincipal(p: iam.IPrincipal) { + if (p.principalAccount) { + console.log('oiadjk;adfsjk;;jkadsf') + console.log(p) + return new iam.ArnPrincipal(p.principalAccount); + } + + if (p instanceof iam.ArnPrincipal) { + console.log('ayayaya 1') + const parsedArn = Arn.split(p.arn, ArnFormat.SLASH_RESOURCE_NAME); + console.log('ayayaya 2') + if (parsedArn.account) { + console.log('ayayaya 3') + return new iam.ArnPrincipal(parsedArn.account); + } + } + + console.log('ffffffffffffffffff') + console.log(p) + + return p; + } } /** From 92e77d6485e15c0339483717b06732478bd3d36c Mon Sep 17 00:00:00 2001 From: Calvin Combs Date: Wed, 30 Mar 2022 12:15:56 -0700 Subject: [PATCH 07/13] updated docs --- packages/@aws-cdk/aws-iam/lib/policy-statement.ts | 9 +++++---- packages/@aws-cdk/aws-iam/lib/principals.ts | 1 - 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/@aws-cdk/aws-iam/lib/policy-statement.ts b/packages/@aws-cdk/aws-iam/lib/policy-statement.ts index 9d302dfc852d8..d8cfed7aaf908 100644 --- a/packages/@aws-cdk/aws-iam/lib/policy-statement.ts +++ b/packages/@aws-cdk/aws-iam/lib/policy-statement.ts @@ -160,7 +160,9 @@ export class PolicyStatement { } /** - * aaaaaaaaaaaa + * Expose principals to allow their ARNs to be replaced by account ID strings + * in policy statements for resources that don't allow full account ARNs, such + * as cloudwatch logs. */ public get principals(): IPrincipal[] { return [...this._principals]; @@ -330,9 +332,8 @@ export class PolicyStatement { } /** - * aaaaaaaaaaaaaaaaaaaaaaa - * @param overrides - * @returns + * Create a new `PolicyStatement` with the same exact properties + * as this one, except for the overrides; effectively a copy constructor. */ public copy(overrides: PolicyStatementProps = {}) { return new PolicyStatement({ diff --git a/packages/@aws-cdk/aws-iam/lib/principals.ts b/packages/@aws-cdk/aws-iam/lib/principals.ts index 998423f171ca6..aecd493192142 100644 --- a/packages/@aws-cdk/aws-iam/lib/principals.ts +++ b/packages/@aws-cdk/aws-iam/lib/principals.ts @@ -359,7 +359,6 @@ export class ArnPrincipal extends PrincipalBase { */ constructor(public readonly arn: string) { super(); - console.log('yay') } public get policyFragment(): PrincipalPolicyFragment { From 505bbeb5b77d0bf3d70f8086d94f0b9e3f7b1b2e Mon Sep 17 00:00:00 2001 From: Calvin Combs Date: Wed, 30 Mar 2022 17:38:14 -0700 Subject: [PATCH 08/13] finalized testing --- packages/@aws-cdk/aws-logs/lib/log-group.ts | 26 +++++++------------ .../@aws-cdk/aws-logs/test/loggroup.test.ts | 8 +++--- 2 files changed, 13 insertions(+), 21 deletions(-) diff --git a/packages/@aws-cdk/aws-logs/lib/log-group.ts b/packages/@aws-cdk/aws-logs/lib/log-group.ts index b76a7f627eda4..8e298eb801f5b 100644 --- a/packages/@aws-cdk/aws-logs/lib/log-group.ts +++ b/packages/@aws-cdk/aws-logs/lib/log-group.ts @@ -201,33 +201,27 @@ abstract class LogGroupBase extends Resource implements ILogGroup { this.policy = new ResourcePolicy(this, 'Policy'); } this.policy.document.addStatements(statement.copy({ - //principals: statement.principals.map(p => p.principalAccount !== undefined ? new iam.ArnPrincipal(p.principalAccount) : p), - principals: statement.principals.map(p => this.mutatePrincipal(p)), + principals: statement.principals.map(p => this.convertArnPrincpalToAccountId(p)), })); return { statementAdded: true, policyDependable: this.policy }; } - private mutatePrincipal(p: iam.IPrincipal) { - if (p.principalAccount) { - console.log('oiadjk;adfsjk;;jkadsf') - console.log(p) - return new iam.ArnPrincipal(p.principalAccount); + private convertArnPrincpalToAccountId(principal: iam.IPrincipal) { + if (principal.principalAccount) { + // we use ArnPrincipal here because the constructor inserts the argument + // into the template without mutating it, which means that there is no + // ARN created by this call. + return new iam.ArnPrincipal(principal.principalAccount); } - if (p instanceof iam.ArnPrincipal) { - console.log('ayayaya 1') - const parsedArn = Arn.split(p.arn, ArnFormat.SLASH_RESOURCE_NAME); - console.log('ayayaya 2') + if (principal instanceof iam.ArnPrincipal) { + const parsedArn = Arn.split(principal.arn, ArnFormat.SLASH_RESOURCE_NAME); if (parsedArn.account) { - console.log('ayayaya 3') return new iam.ArnPrincipal(parsedArn.account); } } - console.log('ffffffffffffffffff') - console.log(p) - - return p; + return principal; } } diff --git a/packages/@aws-cdk/aws-logs/test/loggroup.test.ts b/packages/@aws-cdk/aws-logs/test/loggroup.test.ts index db68d983d6afe..f0aa176e23df6 100644 --- a/packages/@aws-cdk/aws-logs/test/loggroup.test.ts +++ b/packages/@aws-cdk/aws-logs/test/loggroup.test.ts @@ -364,7 +364,7 @@ describe('log group', () => { }); }); - test('can add a policy to the log group', () => { + test('when added to log groups, IAM users are converted into account IDs in the resource policy', () => { // GIVEN const stack = new Stack(); const lg = new LogGroup(stack, 'LogGroup'); @@ -378,16 +378,15 @@ describe('log group', () => { // THEN Template.fromStack(stack).hasResourceProperties('AWS::Logs::ResourcePolicy', { - PolicyDocument: '{"Statement":[{"Action":"logs:PutLogEvents","Effect":"Allow","Principal":{"AWS":"arn:aws:iam::123456789012:user/user-name"},"Resource":"*"}],"Version":"2012-10-17"}', + PolicyDocument: '{"Statement":[{"Action":"logs:PutLogEvents","Effect":"Allow","Principal":{"AWS":"123456789012"},"Resource":"*"}],"Version":"2012-10-17"}', PolicyName: 'LogGroupPolicy643B329C', }); }); - test('policies with token statements correctly extract the account id from the role ARN', () => { + test('imported values are treated as if they are ARNs and converted to account IDs via CFN pseudo parameters', () => { // GIVEN const stack = new Stack(); const lg = new LogGroup(stack, 'LogGroup'); - //const tokenizedRole = new Intrinsic('arn:aws:iam::123456789012:role/my-role'); // WHEN lg.addToResourcePolicy(new iam.PolicyStatement({ @@ -416,7 +415,6 @@ describe('log group', () => { }); }); - test('correctly returns physical name of the log group', () => { // GIVEN const stack = new Stack(); From 6ddc637ab94beee062586626a0f71b73b3ada6f2 Mon Sep 17 00:00:00 2001 From: Calvin Combs Date: Wed, 30 Mar 2022 17:48:41 -0700 Subject: [PATCH 09/13] fixed docs --- packages/@aws-cdk/aws-iam/lib/policy-statement.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/@aws-cdk/aws-iam/lib/policy-statement.ts b/packages/@aws-cdk/aws-iam/lib/policy-statement.ts index d8cfed7aaf908..97a080fbd5ee9 100644 --- a/packages/@aws-cdk/aws-iam/lib/policy-statement.ts +++ b/packages/@aws-cdk/aws-iam/lib/policy-statement.ts @@ -161,8 +161,8 @@ export class PolicyStatement { /** * Expose principals to allow their ARNs to be replaced by account ID strings - * in policy statements for resources that don't allow full account ARNs, such - * as cloudwatch logs. + * in policy statements for resources policies that don't allow full account ARNs, + * such as AWS::Logs::ResourcePolicy. */ public get principals(): IPrincipal[] { return [...this._principals]; @@ -333,7 +333,7 @@ export class PolicyStatement { /** * Create a new `PolicyStatement` with the same exact properties - * as this one, except for the overrides; effectively a copy constructor. + * as this one, except for the overrides */ public copy(overrides: PolicyStatementProps = {}) { return new PolicyStatement({ @@ -500,7 +500,6 @@ export class PolicyStatement { } } - /** * The Effect element of an IAM policy * From 69b7baa9b87d5118aef292c65ea8c470ee8992ce Mon Sep 17 00:00:00 2001 From: Calvin Combs Date: Wed, 30 Mar 2022 17:57:32 -0700 Subject: [PATCH 10/13] updated README --- packages/@aws-cdk/aws-logs/README.md | 4 ++++ packages/@aws-cdk/aws-logs/lib/log-group.ts | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/packages/@aws-cdk/aws-logs/README.md b/packages/@aws-cdk/aws-logs/README.md index 804b5c56c4eb3..4e04059638138 100644 --- a/packages/@aws-cdk/aws-logs/README.md +++ b/packages/@aws-cdk/aws-logs/README.md @@ -69,6 +69,10 @@ const logGroup = new logs.LogGroup(this, 'LogGroup'); logGroup.grantWrite(new iam.ServicePrincipal('es.amazonaws.com')); ``` +Be aware that any ARNs or tokenized values passed to the resource policy will be converted into AWS Account IDs. +This is because CloudWatch Logs Resource Policies do not accept ARNs as principals, but they do accept +Account ID strings. Non-ARN principals, like Service principals or Any princpals, are accepted by CloudWatch. + ## Encrypting Log Groups By default, log group data is always encrypted in CloudWatch Logs. You have the diff --git a/packages/@aws-cdk/aws-logs/lib/log-group.ts b/packages/@aws-cdk/aws-logs/lib/log-group.ts index 8e298eb801f5b..026f00092087a 100644 --- a/packages/@aws-cdk/aws-logs/lib/log-group.ts +++ b/packages/@aws-cdk/aws-logs/lib/log-group.ts @@ -194,6 +194,10 @@ abstract class LogGroupBase extends Resource implements ILogGroup { /** * Adds a statement to the resource policy associated with this log group. * A resource policy will be automatically created upon the first call to `addToResourcePolicy`. + * + * Any ARN Principals inside of the statement will be converted into AWS Account ID strings + * because CloudWatch Logs Resource Policies do not accept ARN principals. + * * @param statement The policy statement to add */ public addToResourcePolicy(statement: iam.PolicyStatement): iam.AddToResourcePolicyResult { From 5f05136bb988be6ec68dd879e673bc91b46bf2b4 Mon Sep 17 00:00:00 2001 From: Calvin Combs Date: Thu, 31 Mar 2022 16:15:57 -0700 Subject: [PATCH 11/13] debug logic --- .../@aws-cdk/aws-lambda/test/singleton-lambda.test.ts | 10 ++++++++-- packages/@aws-cdk/aws-logs/test/loggroup.test.ts | 2 +- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/packages/@aws-cdk/aws-lambda/test/singleton-lambda.test.ts b/packages/@aws-cdk/aws-lambda/test/singleton-lambda.test.ts index 0f0a864a4c173..c68d8fa7f0167 100644 --- a/packages/@aws-cdk/aws-lambda/test/singleton-lambda.test.ts +++ b/packages/@aws-cdk/aws-lambda/test/singleton-lambda.test.ts @@ -1,11 +1,12 @@ import { Template } from '@aws-cdk/assertions'; -import * as ec2 from '@aws-cdk/aws-ec2'; +//import * as ec2 from '@aws-cdk/aws-ec2'; import * as iam from '@aws-cdk/aws-iam'; -import * as s3 from '@aws-cdk/aws-s3'; +//import * as s3 from '@aws-cdk/aws-s3'; import * as cdk from '@aws-cdk/core'; import * as lambda from '../lib'; describe('singleton lambda', () => { + /* test('can add same singleton Lambda multiple times, only instantiated once in template', () => { // GIVEN const stack = new cdk.Stack(); @@ -160,6 +161,7 @@ describe('singleton lambda', () => { }); }); + */ test('grantInvoke works correctly', () => { // GIVEN const stack = new cdk.Stack(); @@ -174,6 +176,8 @@ describe('singleton lambda', () => { const invokeResult = singleton.grantInvoke(new iam.ServicePrincipal('events.amazonaws.com')); const statement = stack.resolve(invokeResult.resourceStatement); + console.log('WUTWUT') + // THEN Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Permission', { Action: 'lambda:InvokeFunction', @@ -187,6 +191,7 @@ describe('singleton lambda', () => { { 'Fn::Join': ['', [{ 'Fn::GetAtt': ['SingletonLambda84c0de93353f42179b0b45b6c993251a840BCC38', 'Arn'] }, ':*']] }, ]); }); + /* test('check edge compatibility', () => { // GIVEN @@ -285,4 +290,5 @@ describe('singleton lambda', () => { expect(singleton.isBoundToVpc).toBeTruthy(); expect(singleton.connections).toEqual(new ec2.Connections({ securityGroups: [securityGroup] })); }); +*/ }); diff --git a/packages/@aws-cdk/aws-logs/test/loggroup.test.ts b/packages/@aws-cdk/aws-logs/test/loggroup.test.ts index f0aa176e23df6..2ba10fdd38f86 100644 --- a/packages/@aws-cdk/aws-logs/test/loggroup.test.ts +++ b/packages/@aws-cdk/aws-logs/test/loggroup.test.ts @@ -1,7 +1,7 @@ import { Template } from '@aws-cdk/assertions'; import * as iam from '@aws-cdk/aws-iam'; import * as kms from '@aws-cdk/aws-kms'; -import { CfnParameter, Fn/*, Intrinsic*/, RemovalPolicy, Stack } from '@aws-cdk/core'; +import { CfnParameter, Fn, RemovalPolicy, Stack } from '@aws-cdk/core'; import { LogGroup, RetentionDays } from '../lib'; describe('log group', () => { From a69977b63581cd9b04c39a0b0a569b974aeb069b Mon Sep 17 00:00:00 2001 From: Calvin Combs Date: Mon, 4 Apr 2022 09:59:40 -0700 Subject: [PATCH 12/13] fixed failing lambda test --- .../aws-lambda/test/singleton-lambda.test.ts | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/packages/@aws-cdk/aws-lambda/test/singleton-lambda.test.ts b/packages/@aws-cdk/aws-lambda/test/singleton-lambda.test.ts index c68d8fa7f0167..90803c220560a 100644 --- a/packages/@aws-cdk/aws-lambda/test/singleton-lambda.test.ts +++ b/packages/@aws-cdk/aws-lambda/test/singleton-lambda.test.ts @@ -174,19 +174,17 @@ describe('singleton lambda', () => { // WHEN const invokeResult = singleton.grantInvoke(new iam.ServicePrincipal('events.amazonaws.com')); - const statement = stack.resolve(invokeResult.resourceStatement); - - console.log('WUTWUT') + const statement = stack.resolve(invokeResult.resourceStatement?.toJSON()); // THEN Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Permission', { Action: 'lambda:InvokeFunction', Principal: 'events.amazonaws.com', }); - expect(statement.action).toEqual(['lambda:InvokeFunction']); - expect(statement.principal).toEqual({ Service: ['events.amazonaws.com'] }); - expect(statement.effect).toEqual('Allow'); - expect(statement.resource).toEqual([ + expect(statement.Action).toEqual('lambda:InvokeFunction'); + expect(statement.Principal).toEqual({ Service: 'events.amazonaws.com' }); + expect(statement.Effect).toEqual('Allow'); + expect(statement.Resource).toEqual([ { 'Fn::GetAtt': ['SingletonLambda84c0de93353f42179b0b45b6c993251a840BCC38', 'Arn'] }, { 'Fn::Join': ['', [{ 'Fn::GetAtt': ['SingletonLambda84c0de93353f42179b0b45b6c993251a840BCC38', 'Arn'] }, ':*']] }, ]); From 1c581b3fe9a4924735dc4fb94de0bd587f433772 Mon Sep 17 00:00:00 2001 From: Calvin Combs Date: Mon, 4 Apr 2022 10:03:31 -0700 Subject: [PATCH 13/13] removed unneeded comments --- .../@aws-cdk/aws-lambda/test/singleton-lambda.test.ts | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/packages/@aws-cdk/aws-lambda/test/singleton-lambda.test.ts b/packages/@aws-cdk/aws-lambda/test/singleton-lambda.test.ts index 90803c220560a..0f259e1866abd 100644 --- a/packages/@aws-cdk/aws-lambda/test/singleton-lambda.test.ts +++ b/packages/@aws-cdk/aws-lambda/test/singleton-lambda.test.ts @@ -1,12 +1,11 @@ import { Template } from '@aws-cdk/assertions'; -//import * as ec2 from '@aws-cdk/aws-ec2'; +import * as ec2 from '@aws-cdk/aws-ec2'; import * as iam from '@aws-cdk/aws-iam'; -//import * as s3 from '@aws-cdk/aws-s3'; +import * as s3 from '@aws-cdk/aws-s3'; import * as cdk from '@aws-cdk/core'; import * as lambda from '../lib'; describe('singleton lambda', () => { - /* test('can add same singleton Lambda multiple times, only instantiated once in template', () => { // GIVEN const stack = new cdk.Stack(); @@ -161,7 +160,6 @@ describe('singleton lambda', () => { }); }); - */ test('grantInvoke works correctly', () => { // GIVEN const stack = new cdk.Stack(); @@ -189,7 +187,6 @@ describe('singleton lambda', () => { { 'Fn::Join': ['', [{ 'Fn::GetAtt': ['SingletonLambda84c0de93353f42179b0b45b6c993251a840BCC38', 'Arn'] }, ':*']] }, ]); }); - /* test('check edge compatibility', () => { // GIVEN @@ -288,5 +285,4 @@ describe('singleton lambda', () => { expect(singleton.isBoundToVpc).toBeTruthy(); expect(singleton.connections).toEqual(new ec2.Connections({ securityGroups: [securityGroup] })); }); -*/ });