AWS Contact Center

Getting AWS account security event alerts on your phone with Amazon Connect

It’s critical to stay up-to-date with security-related events in your AWS account. In an earlier post, Receive Phone Call Alerts for AWS Account Security Events with Amazon Polly, I showed you how to get phone notices for critical alerts in your AWS account using Twilio. In this post, I use Amazon Connect to create the same solution with a simpler architecture.

Overview

Amazon Connect is a self-service, cloud-based contact center service that makes it easy for businesses to deliver better customer service at a lower cost. The self-service graphical interface in Amazon Connect makes it easy for non-technical users to design contact flows, manage agents, and track performance metrics—no specialized skills required.

There are various ways to get a security alert using email or SMS. The following steps outline how to get a voice alert on your phone using Amazon Connect:

  1. The root user performs an activity in the AWS account that generates an event.
  2. An Amazon CloudWatch event rule triggers an AWS Lambda function, which uses the Amazon Connect API to initiate an outbound call to the concerned party.

Walkthrough

To implement this solution, you must create the following resources:

  1. A contact flow.
  2. An AWS Lambda function.
  3. An Amazon CloudWatch event rule.

Prerequisites

To follow this walkthrough, you must create at least one Amazon Connect virtual contact center instance with a claimed phone number. For details, see Amazon Connect—Customer Contact Center in the Cloud.

Step 1: Create a contact flow

Create a contact flow IVR to enable the outbound call and play the alert message based on the event.

  1. In the Amazon Connect console, choose Overview. As the administrator, choose Login.
  2. On the Routing menu, choose Contact Flows, Create Contact flow.
  3. On the left pane, enter a name for the contact flow, for example, “SampleAlert.”
  4. On the left pane, for Set, drag and drop the Set logging behavior IVR to the grid on the right.
  5. On the left pane, for Interact, drag and drop the Play prompt IVR block to the grid on the right.
  6. On the left pane, for Terminate/Transfer, drag and drop the Disconnect / hang up IVR block to the grid on the right.
  7. Connect these three IVR blocks to make a contact flow, as shown in the following screenshot.
  8. Double-click the Play prompt IVR block. On the Play prompt page, configure the following fields:
      1. Choose Text to speech (Ad hoc).
      2. Choose Enter text, and enter the following:
        <speak>
        <prosody rate="slow">
        $.Attributes.Message
        </prosody>
        </speak>
      3. For Interpret as, choose SSML.
      4. Choose Save.
  9. Choose Save & Publish.
  10. On the left pane, for Show additional flow information, note the contact flow ID for the contact flow you just published for future use. The Lambda function only needs the last 36-digit number, as underlined in the following screenshot.

Step 2: Create a Lambda function

Before you create the Lambda function to trigger the contact flow, create an IAM role for it to use. For more information, see the Creating an IAM Role section in the IAM Roles for Amazon EC2 topic.

To create an IAM role

      1. In the IAM console, choose Policies, Create Policy.
      2. On the JSON tab, copy the following IAM policy, and choose Review policy.
        {
        "Version": "2012-10-17",
        "Statement": [
          {
              "Sid": "VisualEditor0",
              "Effect": "Allow",
              "Action": [
                  "logs:CreateLogStream",
                  "logs:PutLogEvents"
              ],
              "Resource": "arn:aws:logs:*:*:*"
          },
          {
              "Sid": "VisualEditor1",
              "Effect": "Allow",
              "Action": [
                  "iam:ListAccountAliases"
              ],
              "Resource": "*"
          },
          {
              "Sid": "VisualEditor2",
              "Effect": "Allow",
              "Action": [
                  "connect:ListInstances",
                  "connect:StartOutboundVoiceContact"
              ],
              "Resource": "*"
          },
          {
              "Sid": "VisualEditor3",
              "Effect": "Allow",
              "Action": "logs:CreateLogGroup",
              "Resource": "arn:aws:logs:*:*:*"
          }
        ]
        }
        
      3. Enter a name for this policy and choose Create policy. Note the name of this policy for future use.
      4. In the navigation pane, choose Roles, Create role.
      5. On the Select role type page, choose EC2 and the EC2 use case. Choose Next: Permissions.
      6. Filter policies by the policy name that you just created, and select the check box.
      7. Choose Next: Tags, and give it an appropriate tag.
      8. Choose Next: Review, give this IAM role an appropriate name, and remember it for future use.
      9. Choose Create role.

To create a Lambda function.

For more information, see Create a Lambda Function with the Console.

    1. In the Lambda console, choose Author from scratch.
    2. For Runtime, choose Python 2.7.
    3. For Execution role, select Use an existing role, then select the IAM role created in the previous step.
    4. Choose Create Function, remove the default function, and copy the following code into the Function Code window:
      # Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
      #
      # Licensed under the Apache License, Version 2.0 (the "License").
      # You may not use this file except in compliance with the License.
      # A copy of the License is located at
      #
      #     http://aws.amazon.com/apache2.0/
      #
      # or in the "license" file accompanying this file.
      # This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
      # either express or implied. See the License for the specific language governing permissions
      # and limitations under the License.
      #
      # Description: This Lambda function triggers Amazon Connect to place an outbound phone call alert 
      #to a given phone number when an API call event by an IAM root user is detected.
      #
      # Author: Sudhanshu Malhotra  
      import json
      import boto3
      import logging
      import os
      import botocore.session
      from botocore.exceptions import ClientError
      session = botocore.session.get_session()
      logging.basicConfig(level=logging.DEBUG)
      logger=logging.getLogger(__name__)
      def lambda_handler(event, context):
      logger.setLevel(logging.DEBUG)
      eventname = event['detail']['eventName']
      DestPhoneNumber = os.environ['DestPhoneNumber']          #Getting the destination phone number passed in by the environment variables.
      ContactFlowId = os.environ['ContactFlowId']              #Getting the Amazon Connect ContactFlowID passed in by the environment variables.
      InstanceId = os.environ['InstanceId']                    #Getting the Amazon Connect InstanceId passed in by the environment variables.
      SourcePhoneNumber = os.environ['SourcePhoneNumber']      #Getting the Source Phone Number passed in by the environment variables. This phone number is your Amazon Connect phone number.
      
      user = event['detail']['userIdentity']['type']
      
      logger.debug("Event is --- %s" %event)
      logger.debug("Event Name is--- %s" %eventname)
      logger.debug("DestPhoneNumber is-- %s" %DestPhoneNumber)
      logger.debug("User Name is -- %s" %user)
      
      client = boto3.client('iam')
      connectclient = boto3.client('connect')
      response = client.list_account_aliases()
      logger.debug("List account alias response --- %s" %response)
      
      try:
        if not response['AccountAliases']:
            accntAliase = (boto3.client('sts').get_caller_identity()['Account'])
            logger.info("Account alias is not defined. Account ID is %s" %accntAliase)
        else:
            accntAliase = response['AccountAliases'][0]
            logger.info("Account alias is : %s" %accntAliase)
      
      except ClientError as e:
        logger.error("Client error occurred")
      
      try: 
        #Making the outbound phone alert...
        OutboundResponse = connectclient.start_outbound_voice_contact(
                        DestinationPhoneNumber=DestPhoneNumber,
                        ContactFlowId=ContactFlowId,
                        InstanceId=InstanceId,
                        SourcePhoneNumber=SourcePhoneNumber,
                        Attributes={'Message': 'This is a critical alert message! Root API call-%s detected in account-%s' %(eventname,accntAliase)
                                    }
                        )
      
        logger.debug("outbound Call response is-- %s" %OutboundResponse)
      except ClientError as e:
        logger.error("An error occurred: %s" %e)
    5. In the Environment variables section, enter the following key-value pairs:
      • Key= ContactFlowId
        Value= Enter the value of the contact flow from an earlier step.
      • Key= DestPhoneNumber
        Value= Enter the phone number where you want to receive the alert call (prepend the number with “+country code”).
      • Key= InstanceId
        Value= Enter the ID of your Amazon Connect instance. To find the Amazon Connect instance ID, see How do I find my Amazon Connect instance ID.
      •  Key= SourcePhoneNumber
        Value= Enter the phone number assigned to your Amazon Connect instance. The format should be “+country code” followed by the number. For example, for a US number, use +14567891234.
    6. Choose Save.

 

In the next step, you add a trigger to this Lambda function.

Step 3: Create a CloudWatch Events rule

This rule catches a console login event and all other API events performed by a root user, and triggers the Lambda function (set as a target) when these events are detected.

  1. In the CloudWatch console, choose Rules, Create rule.
    1. On the Step 1: Create rule page:
    2. Under Event Source, select Event Pattern, and copy the following event into the preview pane (note placement in the screenshot after the following code):
      {
      "detail-type": [
      "AWS API Call via CloudTrail",
      "AWS Console Sign In via CloudTrail"
      ],
      "detail": {
      "userIdentity": {
      "type": [
        "Root"
      ]
      }
      }
      }
    3. For Targets, select Lambda function, and select the Lambda function created in Step 2.
    4. Choose Configure details.
  2. On the Step 2: Configure rule details page, add a name and description for the rule.
  3. For State, select Enabled, and choose Create rule.

To add a trigger to the Lambda function created earlier:

  1. In the Lambda console, select the Lambda function that you created in Step 2, and open the designer section on the left panel.
  2. Under Add triggers, choose CloudWatch Events, and select the CloudWatch event rule created earlier.
  3. Select Enable trigger and choose Add.
  4. On the top-right corner, choose Save. You should see the following screenshot.

 

Solution validation

In the following sample audio, I demonstrate that after deploying the solution, I received a phone call alert each time a root API was detected for the AWS account.

Phone call sample for a console login alert by root:

Root console login sample phone call:

 

Then I created an EBS volume using the AWS account root users and got another phone call alert:

Create EBS volume sample phone call :

 

For troubleshooting purposes, Lambda automatically integrates with CloudWatch Logs. It pushes all logs from your code to a CloudWatch Logs group associated with the Lambda function. The group is named /aws/lambda/<function name>. For more information, see Accessing Amazon CloudWatch Logs for AWS Lambda.

 

Conclusion

In this post, I showed you how to create a phone-call audio alert system using Amazon Connect that you can integrate with your previously existing alert and monitoring system. This framework makes sure that you get near-real-time phone call alerts on critical events in your AWS account.

For further reading, I recommend the following posts:

 

About the authors:

Sudhanshu Malhotra is a solutions architect at AWS. Sudhanshu enjoys working with customers and helping them deliver complex solutions in AWS in the area of DevOps, infrastructure as code, and config management. In his spare time, Sudhanshu enjoys spending time with his family, hiking, and tinkering with cars.

 

 

 

 

Pawan Matta is a solutions architect at AWS. Pawan enjoys working with customers and helping them in area of Storage and Migration. During his free time, Pawan loves spending time in watching cricket and playing Pubg mobile with friends