Collecting Information from AWS CloudFormation Resources Created in External Accounts with Custom Resources
By Erin McGill. Erin is a Partner Solutions Architect (SA) at AWS.
Throughout this series, we’ve talked about easing cross-account role creation with AWS CloudFormation and a custom stack URL. We’ve also discussed how to dynamically generate CloudFormation templates to populate a unique external ID. But once your cross-account role is created, how does the Amazon Resource Name (ARN) for the generated cross-account role in the customer account get back to your company’s onboarding portal? Asking the customer to cut and paste the output ARN is possible, but it’s a manual step that’s prone to human error.
In this post, we’ll describe how to use a custom resource to send the cross-account role ARN to the onboarding portal. A custom resource enables you to add custom provisioning logic to a CloudFormation template. AWS CloudFormation runs this code anytime a stack is created, updated, or deleted. By adding a custom resource to the template that is launched in your customer’s account, you can post a custom resource request that includes the cross-account role ARN back to an Amazon SNS topic.
Every time the CloudFormation stack is updated or deleted, it will trigger the custom resource.
Even if no action is taking place within the custom resource during these stages, you need a mechanism to signal back to the ResponseURL, a success or failure. The ResponseURL is provided in the custom resource request. If the ResponseURL does not receive a success or failure, the CloudFormation stack will remain in an
DELETE_IN_PROGRESS state, and will ultimately fail upon reaching the timeout waiting for a response.
The SNS topic runs in your company’s AWS account, which is associated with your onboarding portal, as shown in the following illustration.
The onboarding portal then takes the message that arrives in the SNS topic and uses it to associate the new cross-account role ARN with the customer’s account ID and unique external ID. You can use an Amazon DynamoDB table as a tracking mechanism. This table stores the cross-account role ARN in an item that also contains the customer’s account ID and unique external ID from earlier in the onboarding process.
The SNS topic in your company’s AWS account that receives the cross-account role ARN from a customer’s AWS account should not be publicly accessible—it should be restricted to only those authorized to send messages to the topic. In a previous post in this series, we explained how the user-provided AWS account ID is associated with our generated unique external ID for the customer in a DynamoDB table. With the AWS account ID, you can also whitelist this account in the SNS topic policy to keep your AWS resource secure.
When your customer launches the CloudFormation stack, the template creates the custom resource. As demonstrated in our previous blog post, the Service Token for the custom resource is prepopulated with the SNS topic associated with the onboarding portal in your company’s AWS account. Once the cross-account role is created, the custom resource is triggered, and it sends the cross-account role ARN, your customer’s AWS account ID, and any other additional information you want to include to the SNS topic in your company’s AWS account.
Since the stack remains in the customer’s account, it will continue to provide a mechanism for capturing changes to the CloudFormation stack, including deletion, back to your company. For example, if a customer deletes the CloudFormation stack, thereby deleting the cross-account role, a notification will be sent to the same SNS topic. This will allow you or your support staff to proactively reach out for troubleshooting or assistance. We recommend removing the customer’s AWS account ID from the SNS topic policy during the stack deletion phase, as they will need to restart the workflow to re-onboard, which will, in turn, re-whitelist their account ID.
Here’s the Resources section from an example CloudFormation template that demonstrates how to create the cross-account role and send it back to your company’s SNS topic:
This CloudFormation YAML script has one section, Resources, with two resources defined within it:
CrossAccountRole resource creates the IAM role that your company can assume in the customer’s account. It consists of three properties:
AssumeRolePolicyDocument– Identifies your company by your account ARN, provided in the Principal, and sets the condition that your company account is allowed to assume the role only as long as the external ID is provided when assuming the role.
Path– A friendly name or path for the role. We’ve chosen to set this to a forward slash for simplicity.
PolicyDocument– Defines the permissions that this role will be granted. In this example, we are granting the ability to describe EC2 instances in the account and naming the policy
PhoneHomeCustomResource creates a custom resource with three properties:
ServiceToken– Identifies the endpoint that gives the template the ability to access the custom resource in your company’s account. In this case, the service token is the SNS topic ARN in your company’s account. This service token must be from the same region as the stack being created. This SNS topic will, in turn, trigger a Lambda function. This function can perform any onboarding required by your workflow, but, most importantly, sends back the
SUCCESSstatus to CloudFormation so it can proceed with launching the stack.
RoleArn– The ARN of the CrossAccountRole
AccountID– The account ID of the customer’s account that is launching your CloudFormation stack.
CloudFormation is able to identify dependencies and will wait till the
RoleArn resource has been created. Once created, the custom resource will be invoked and the
RoleArn and the
AccountID values will be sent to the
ServiceToken, which is the SNS topic in your company’s account.
In this blog series, we showed you how to create a URL to launch a stack in your customer’s account, dynamically generate a CloudFormation template to include unique data for each customer, and automatically acquire and send information back about created resources, such as IAM cross-account role ARNs. In the next, and final, post in this series, we’ll provide a walkthrough of the entire process.
Do you have any questions or comments? Let us know in the comments section, and check back soon for the final post in this series.