Skip to content

Commit

Permalink
feat(core): expose custom resource provider's role (#11923)
Browse files Browse the repository at this point in the history
The role ARN can then be used in resource-based IAM policies.

See #9751 (comment)


----

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
  • Loading branch information
jogold authored Dec 14, 2020
1 parent 9417b02 commit 06f26d3
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 1 deletion.
14 changes: 14 additions & 0 deletions packages/@aws-cdk/core/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

/**
Expand All @@ -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);

Expand Down Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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();
},
});

0 comments on commit 06f26d3

Please sign in to comment.