#!/usr/bin/env python from aws_cdk import ( App, Environment, Stack, aws_events as events, aws_events_targets as targets, aws_kms as kms, aws_sns as sns, aws_sns_subscriptions as subscriptions, aws_stepfunctions as sfn, aws_stepfunctions_tasks as tasks, ) import os from constructs import Construct class support_notifications(Stack): def __init__( self, scope: Construct, id: str, notification_email: str, **kwargs ) -> None: super().__init__(scope, id, **kwargs) # Create SNS Topic for notifications of new case creation which match the severity level sns_key = kms.Alias.from_alias_name(self, "SnsKey", "alias/aws/sns") support_notifications_topic = sns.Topic( self, "SupportCasesCreatedNotification", master_key=sns_key, ) # Subscribe to notifications support_notifications_topic.add_subscription( subscriptions.EmailSubscription(notification_email) ) # AWS Step Function Definition # Step to call AWS Support API to retrieve information about the newly created case get_support_case = tasks.CallAwsService( self, "Get Support Case Details", service="support", action="describeCases", parameters={"CaseIdList": sfn.JsonPath.array(sfn.JsonPath.entire_payload)}, input_path="$.detail.case-id", result_path="$.CaseDetails", iam_resources=["*"], ) # Choice step depending on whether the case matches either the urgent or critical severity level we want to notify on. # This is refers to "Production system down" or "Business-critical system down" in AWS console. # https://docs.aws.amazon.com/awssupport/latest/APIReference/API_SeverityLevel.html#API_SeverityLevel_Contents determine_severity = sfn.Choice(self, "Determine Severity") match_severity = sfn.Condition.or_( sfn.Condition.string_equals( "$.CaseDetails.Cases[0].SeverityCode", "critical" ), sfn.Condition.string_equals( "$.CaseDetails.Cases[0].SeverityCode", "urgent" ), ) # Step to notify of a new case being created via SNS Topic. notify_new_case_created = tasks.SnsPublish( self, "Notify that a new case has been created", topic=support_notifications_topic, integration_pattern=sfn.IntegrationPattern.REQUEST_RESPONSE, subject=sfn.JsonPath.format( "AWS Support Case Created - Case ID: {} - {}", sfn.JsonPath.string_at("$.CaseDetails.Cases[0].DisplayId"), sfn.JsonPath.string_at("$.CaseDetails.Cases[0].Subject"), ), message=sfn.TaskInput.from_text( sfn.JsonPath.format( "A new AWS Support case (Case ID: {}) has been opened in account {}, with a {} severity by {}. The subject is {}. You can access this case by logging into AWS account {} and clicking the following link: https://console.aws.amazon.com/support/home#/case/?displayId={}&language=en", sfn.JsonPath.string_at("$.CaseDetails.Cases[0].DisplayId"), sfn.JsonPath.string_at("$.account"), sfn.JsonPath.string_at("$.CaseDetails.Cases[0].SeverityCode"), sfn.JsonPath.string_at("$.CaseDetails.Cases[0].SubmittedBy"), sfn.JsonPath.string_at("$.CaseDetails.Cases[0].Subject"), sfn.JsonPath.string_at("$.account"), sfn.JsonPath.string_at("$.CaseDetails.Cases[0].DisplayId"), ) ), ) finished = sfn.Succeed(self, "Notification not required") support_notifications_state_machine = sfn.StateMachine( self, "SupportNotificationsStateMachine", state_machine_name="support-notifications-python", definition=sfn.Chain.start( get_support_case.next( determine_severity.when( match_severity, notify_new_case_created ).otherwise(finished) ) ), ) # EventBridge rule that triggers the state machine whenever a support case is created. events.Rule( self, "SupportCaseCreatedTrigger", event_pattern=events.EventPattern( source=["aws.support"], detail={"event-name": ["CreateCase"]}, ), targets=[targets.SfnStateMachine(support_notifications_state_machine)], ) app = App() # Note that the AWS Support API is only available from the us-east-1 region. support_env = Environment(account=os.environ["CDK_DEFAULT_ACCOUNT"], region="us-east-1") support_notifications( app, "SupportNotificationsPython", notification_email="admin@example.com", env=support_env, ) app.synth()