From 06f26d390707b0e2a4e05e36405a4751c907a234 Mon Sep 17 00:00:00 2001 From: Jonathan Goldwasser Date: Mon, 14 Dec 2020 12:41:00 +0100 Subject: [PATCH] feat(core): expose custom resource provider's role (#11923) The role ARN can then be used in resource-based IAM policies. See https://github.com/aws/aws-cdk/pull/9751#issuecomment-723554595 ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- packages/@aws-cdk/core/README.md | 14 +++++++++++ .../custom-resource-provider.ts | 23 ++++++++++++++++++- .../custom-resource-provider.test.ts | 20 ++++++++++++++++ 3 files changed, 56 insertions(+), 1 deletion(-) diff --git a/packages/@aws-cdk/core/README.md b/packages/@aws-cdk/core/README.md index ffa333cd0634f..3b013f3ff990e 100644 --- a/packages/@aws-cdk/core/README.md +++ b/packages/@aws-cdk/core/README.md @@ -486,6 +486,20 @@ const sum = new Sum(this, 'MySum', { lhs: 40, rhs: 2 }); new CfnOutput(this, 'Result', { value: Token.asString(sum.result) }); ``` +To access the ARN of the provider's AWS Lambda function role, use the `getOrCreateProvider()` +built-in singleton method: + +```ts +const provider = CustomResourceProvider.getOrCreateProvider(this, 'Custom::MyCustomResourceType', { + codeDirectory: `${__dirname}/my-handler`, + runtime: CustomResourceProviderRuntime.NODEJS_12, // currently the only supported runtime +}); + +const roleArn = provider.roleArn; +``` + +This role ARN can then be used in resource-based IAM policies. + #### The Custom Resource Provider Framework The [`@aws-cdk/custom-resources`] module includes an advanced framework for diff --git a/packages/@aws-cdk/core/lib/custom-resource-provider/custom-resource-provider.ts b/packages/@aws-cdk/core/lib/custom-resource-provider/custom-resource-provider.ts index ea5b0882dbb44..f7905fc51447b 100644 --- a/packages/@aws-cdk/core/lib/custom-resource-provider/custom-resource-provider.ts +++ b/packages/@aws-cdk/core/lib/custom-resource-provider/custom-resource-provider.ts @@ -100,12 +100,27 @@ export class CustomResourceProvider extends CoreConstruct { * used when defining a `CustomResource`. */ public static getOrCreate(scope: Construct, uniqueid: string, props: CustomResourceProviderProps) { + return this.getOrCreateProvider(scope, uniqueid, props).serviceToken; + } + + /** + * Returns a stack-level singleton for the custom resource provider. + * + * @param scope Construct scope + * @param uniqueid A globally unique id that will be used for the stack-level + * construct. + * @param props Provider properties which will only be applied when the + * provider is first created. + * @returns the service token of the custom resource provider, which should be + * used when defining a `CustomResource`. + */ + public static getOrCreateProvider(scope: Construct, uniqueid: string, props: CustomResourceProviderProps) { const id = `${uniqueid}CustomResourceProvider`; const stack = Stack.of(scope); const provider = stack.node.tryFindChild(id) as CustomResourceProvider ?? new CustomResourceProvider(stack, id, props); - return provider.serviceToken; + return provider; } /** @@ -121,6 +136,11 @@ export class CustomResourceProvider extends CoreConstruct { */ public readonly serviceToken: string; + /** + * The ARN of the provider's AWS Lambda function role. + */ + public readonly roleArn: string; + protected constructor(scope: Construct, id: string, props: CustomResourceProviderProps) { super(scope, id); @@ -167,6 +187,7 @@ export class CustomResourceProvider extends CoreConstruct { Policies: policies, }, }); + this.roleArn = Token.asString(role.getAtt('Arn')); const timeout = props.timeout ?? Duration.minutes(15); const memory = props.memorySize ?? Size.mebibytes(128); diff --git a/packages/@aws-cdk/core/test/custom-resource-provider/custom-resource-provider.test.ts b/packages/@aws-cdk/core/test/custom-resource-provider/custom-resource-provider.test.ts index c56a991298574..b6c1e608e2f59 100644 --- a/packages/@aws-cdk/core/test/custom-resource-provider/custom-resource-provider.test.ts +++ b/packages/@aws-cdk/core/test/custom-resource-provider/custom-resource-provider.test.ts @@ -232,5 +232,25 @@ nodeunitShim({ }); test.done(); }, + + 'roleArn'(test: Test) { + // GIVEN + const stack = new Stack(); + + // WHEN + const cr = CustomResourceProvider.getOrCreateProvider(stack, 'Custom:MyResourceType', { + codeDirectory: TEST_HANDLER, + runtime: CustomResourceProviderRuntime.NODEJS_12, + }); + + // THEN + test.deepEqual(stack.resolve(cr.roleArn), { + 'Fn::GetAtt': [ + 'CustomMyResourceTypeCustomResourceProviderRoleBD5E655F', + 'Arn', + ], + }); + test.done(); + }, });