Today, I discovered yet again that there are countless ways to tackle a single task as a developer.
I was tasked with automating a workflow that involved an AWS Lambda Function triggered by an SNS event source. The goal was to publish a message to an SNS topic in a different AWS account when the status of a CloudFormation stack updated.
We use AWS CDK for infrastructure as code (IAC). While exploring the documentation and blog posts, I found that there is no direct equivalent of the Notification Policy in CloudFormation to publish notifications to an SNS topic on a CloudFormation stack status change. Instead, there are several common patterns to achieve this. Let's start with solution diagram. Here's a simplified version of the architecture diagram of what I implemented:
If this is what you are looking for, you can simply achieve it in 3 different ways:
Using AWS Event Bridge
- Create SNS Topic as a Stack B CDK resource:
import { Topic } from "aws-cdk-lib/aws-sns";
const SNSTopic = new Topic(this, "SNS_TOPIC_ID", {
displayName: "YOUR DISPLAY NAME",
});
_Note: you need to add an event source to your function or any other resources that is going to subscribe to this topic. in my case I needed to configure a lambda event source as _bellow:
MyFunction.addEventSource(new SnsEventSource(SNSTopic));
- Add Event Rule
new Rule(this, "Trigger", {
eventPattern: {
source: ["aws.cloudformation"],
detailType: ["CloudFormation Stack Status Change"],
detail: {
eventName: ["CREATE_COMPLETE", "UPDATE_COMPLETE", "DELETE_COMPLETE"],
requestParameters: {
stackName: [this.stackName],
},
},
},
targets: [new SnsTopic(SNSTopic)],
});
Using AWS Custom Resources
Second approach to achieve this is by using AWS Custom Resources.
- Create an AWS Custom Resource within the Stack B CDK:
import { AwsCustomResource, AwsCustomResourcePolicy, PhysicalResourceId } from "aws-cdk-lib/custom-resources";
const Trigger = new AwsCustomResource(this, "TriggerOnSuccess", {
onUpdate: {
service: "SNS",
action: "publish",
parameters: {
TopicArn: "YOUR_TOPIC_ARN",
Message: "Stack updated successfully",
},
physicalResourceId: PhysicalResourceId.of("TriggerOnSuccess"),
},
onDelete: {
service: "SNS",
action: "publish",
parameters: {
TopicArn: "YOUR_TOPIC_ARN",
Message: "Stack deleted successfully",
},
physicalResourceId: PhysicalResourceId.of("TriggerOnSuccess"),
},
policy: AwsCustomResourcePolicy.fromStatements( [new PolicyStatement({
actions: ["sns:Publish"],
effect: Effect.ALLOW,
resources: [SNSTopic.topicArn],
})]),
});
- Add Dependency order so that CDK doesn't return Dependency Cycle error
Trigger.node.addDependency(YOUR_FUNCTION);
Trigger.node.addDependency(SNSS_TOPIC);
Using AWS Custom Resource with Lambda Invoke Action
There is also a 3rd solution for this as well which I am not a big fan of it and that is. I personally prefer to use fan out approach, to populate events to Lambda via an "Event Service" such as SNS or EventBridge. If you look for a simplified Custom Resource, here is what you should update your AWS Custom Resource to:
import { AwsCustomResource, AwsCustomResourcePolicy, PhysicalResourceId } from "aws-cdk-lib/custom-resources";
const Trigger = new AwsCustomResource(this, "TriggerOnSuccess", {
onUpdate: {
service: "Lambda",
action: "invoke",
parameters: {
FunctionName: "YOUR_FUNCTION_ARN",
InvokationType: "Event"
},
physicalResourceId: PhysicalResourceId.of("TriggerOnSuccess"),
},
onDelete: {
service: "Lambda",
action: "invoke",
parameters: {
FunctionName: "YOUR_FUNCTION_ARN",
InvokationType: "Event"
},
physicalResourceId: PhysicalResourceId.of("TriggerOnSuccess"),
},
policy: AwsCustomResourcePolicy.fromStatements( [new PolicyStatement({
actions: ["lambda:InvokeFunction"],
effect: Effect.ALLOW,
resources: [YOUR_FUNCTION_ARN],
})]),
});
This concludes our brief discussion. While I'm still hopeful about discovering if CDK offers an API for configuring Stack Notification Options, I wanted to share these workarounds in the meantime.
Top comments (1)
Heyo!
Just a reminder that you likely want to add tags to your post to help with discoverability. Depending on what tags folks are following, posts will appear in their "relevant" feed on the DEV homepage.
You can add popular, established tags, more niche tags, or create a brand new tag if there's one that has yet to be created. Some tags are centered around a technology (#python, #javascript) and others are more functional (#discuss, #help, #tutorial)... you can use a combination of 4 tags on your post, so choose wisely.
Always make sure that the tags you choose fit the subject matter of your post. Different tags have submission guidelines set up for them which you can view on a tag's landing page. For example, view the landing page for #career - dev.to/t/career and you'll see that the submission guidelines read:
Note that we recruit Tag Moderators to help us create submission guidelines and ensure that posts are properly tagged.
Those are some of the basics of tags! Feel free to visit DEV Help for other helpful information!