From a5f7655099271fd23f87e1442228f361997d539f Mon Sep 17 00:00:00 2001 From: Pahud Hsieh Date: Fri, 26 May 2023 03:29:13 -0400 Subject: [PATCH] chore(iam): support addSourceAccountCondition and addSourceArnCondition (#25744) The [addAccountCondition](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.PolicyStatement.html#addwbraccountwbrconditionaccountid) method essentially create a `StringEquals` condition with `sts:ExternalId` which is used for [Cross-account confused deputy prevention](https://docs.aws.amazon.com/IAM/latest/UserGuide/confused-deputy.html#mitigate-confused-deputy). This PR adds `addSourceArnCondition` and `addSourceAccountCondition` methods used for [Cross-service confused deputy prevention](https://docs.aws.amazon.com/IAM/latest/UserGuide/confused-deputy.html#cross-service-confused-deputy-prevention) and improves the doc on the methods. Closes https://github.com/aws/aws-cdk/issues/25732 ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- packages/aws-cdk-lib/aws-iam/README.md | 7 +++++ .../aws-iam/lib/policy-statement.ts | 26 ++++++++++++++++++- .../aws-iam/test/policy-document.test.ts | 23 ++++++++++++++++ 3 files changed, 55 insertions(+), 1 deletion(-) diff --git a/packages/aws-cdk-lib/aws-iam/README.md b/packages/aws-cdk-lib/aws-iam/README.md index 77f09f481767d..0e88c3bbee339 100644 --- a/packages/aws-cdk-lib/aws-iam/README.md +++ b/packages/aws-cdk-lib/aws-iam/README.md @@ -257,6 +257,13 @@ an `ExternalId` works like this: [supplying an external ID](test/example.external-id.lit.ts) +## SourceArn and SourceAccount + +If you need to create resource policies using `aws:SourceArn` and `aws:SourceAccount` for cross-service resource access, +use `addSourceArnCondition` and `addSourceAccountCondition` to create the conditions. + +See [Cross-service confused deputy prevention for more details](https://docs.aws.amazon.com/IAM/latest/UserGuide/confused-deputy.html#cross-service-confused-deputy-prevention). + ## Principals vs Identities When we say *Principal*, we mean an entity you grant permissions to. This diff --git a/packages/aws-cdk-lib/aws-iam/lib/policy-statement.ts b/packages/aws-cdk-lib/aws-iam/lib/policy-statement.ts index 5a9e6905d2101..0c7cdfd0e031a 100644 --- a/packages/aws-cdk-lib/aws-iam/lib/policy-statement.ts +++ b/packages/aws-cdk-lib/aws-iam/lib/policy-statement.ts @@ -402,14 +402,38 @@ export class PolicyStatement { } /** - * Add a condition that limits to a given account + * Add a `StringEquals` condition that limits to a given account from `sts:ExternalId`. * * This method can only be called once: subsequent calls will overwrite earlier calls. + * + * @see https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_create_for-user_externalid.html */ public addAccountCondition(accountId: string) { this.addCondition('StringEquals', { 'sts:ExternalId': accountId }); } + /** + * Add an `StringEquals` condition that limits to a given account from `aws:SourceAccount`. + * + * This method can only be called once: subsequent calls will overwrite earlier calls. + * + * @see https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_condition-keys.html#condition-keys-sourceaccount + */ + public addSourceAccountCondition(accountId: string) { + this.addCondition('StringEquals', { 'aws:SourceAccount': accountId }); + } + + /** + * Add an `ArnEquals` condition that limits to a given resource arn from `aws:SourceArn`. + * + * This method can only be called once: subsequent calls will overwrite earlier calls. + * + * @see https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_condition-keys.html#condition-keys-sourcearn + */ + public addSourceArnCondition(arn: string) { + this.addCondition('ArnEquals', { 'aws:SourceArn': arn }); + } + /** * Create a new `PolicyStatement` with the same exact properties * as this one, except for the overrides diff --git a/packages/aws-cdk-lib/aws-iam/test/policy-document.test.ts b/packages/aws-cdk-lib/aws-iam/test/policy-document.test.ts index 12db0c13718d4..09af35f469636 100644 --- a/packages/aws-cdk-lib/aws-iam/test/policy-document.test.ts +++ b/packages/aws-cdk-lib/aws-iam/test/policy-document.test.ts @@ -44,6 +44,29 @@ describe('IAM policy document', () => { }); }); + test('addSourceAccountCondition and addSourceArnCondition for cross-service resource access', () => { + const stack = new Stack(); + + const p = new PolicyStatement(); + p.addActions('sns:Publish'); + p.addResources('myTopic'); + p.addAllResources(); + p.addServicePrincipal('s3.amazonaws.com'); + p.addSourceAccountCondition('12221121221'); + p.addSourceArnCondition('bucketArn'); + + expect(stack.resolve(p.toStatementJson())).toEqual({ + Action: 'sns:Publish', + Resource: ['myTopic', '*'], + Effect: 'Allow', + Principal: { Service: 's3.amazonaws.com' }, + Condition: { + StringEquals: { 'aws:SourceAccount': '12221121221' }, + ArnEquals: { 'aws:SourceArn': 'bucketArn' }, + }, + }); + }); + test('the PolicyDocument class is a dom for iam policy documents', () => { const stack = new Stack(); const doc = new PolicyDocument();