Security of your AWS account is paramount. Staying up to date with any security-related events in your AWS account is important. There are various ways to get alerts- via email or SMS, however in this blog post I’m going to show you how to get a voice alert on your phone using Amazon AI services like Amazon Polly and any cloud-based communications platform like Twilio.

Amazon Polly is a service that turns text into lifelike speech, allowing you to create applications that can talk and build entirely new categories of speech-enabled products. It uses deep learning technologies to synthesize speech that sounds like a human voice. It has varied voices available across different languages.

For enterprise IT security personnel on the move, phone call alerts on AWS account security events are tremendously helpful. These security events can be custom-defined based on their severity and priority. The higher severity and priority security events can be sent to the system that alerts via a phone call.

For phone call alerts, I use Twilio, which provide API capabilities like voice, video, and messaging. Using Twilio’s platform I can programmatically issue API calls to make phone calls when a security event occurs in a given AWS account. Amazon Polly converts this textual alert into a voice message to be played back on the phone call.

Solution overview

The solution consists of two systems as shown in the architectural diagram that follows:

Event Detection and notification system

Text to audio converting system

The event detection and notification system is decoupled from the text to audio conversion system because the latter system will be common to any other user defined event detection. In this blog post I will focus on the text to audio converting system and use the event detection and notification system from my previous blog post, as an example in my solution.

As seen in the architecture diagram. The alert message from step 3 gets published to the Amazon SNS topic and that SNS triggers the Lambda function in our text to audio converting system.

This Lambda function parses the subject for the SNS alert message and uses Amazon Polly to convert the text to an audio file. This audio file is stored in an Amazon S3 bucket. Using the location of the audio file, Twilio places an outbound call to the concerned party and plays back the audio file. Please note, you can add an Amazon S3 object lifecycle policy for these files based on your requirements after the audio file is used to make the outbound call.

Walkthrough

Prerequisites

Have at least one event detection and notification system. For example, you can set up the Monitor and Notify on AWS Account Root User Activity

You will need a Twilio account auth token to make API calls. You can sign-up for a free (trial) Twilio account here.

Your Twilio account will be assigned a phone number. This is where you’ll receive phone call alerts from.



If you are using a trial account, you’ll need to need to make sure the “call to” phone number is verified.



Deployment steps

The following deployment steps will deploy the “Text to Audio Converting” system as shown in the diagram below.

In the AWS CloudFormation console, choose Create Stack. Use the CloudFormation JSON template . Choose Next. (Note: Amazon Polly is not supported in China and the AWS GovCloud (US) Regions.) Create the stack in the Region where the event detection and notification system is deployed. Enter the following parameter details and choose Next and then Next: ToPhoneNo: The phone number that Twilio will call to. Prepend the number with “+country code”, for example- +14561237890. FromPhoneNo: The virtual phone number that Twilio uses to call. This information can be found in your Twilio account. Refer to the Prerequisites section. TwilioAccntSid: Enter the Twilio account SID. This will be provided when you sign up at https://www.twilio.com/ TwilioAuthToken: Enter the Twilio auth token ID. BucketName: Enter the name of the bucket you want to create. This bucket will store the audio file of the event alerts. PollyVoiceId: Enter the Amazon Polly voice you want the alert call in. The default voice is “Amy.” LambdaS3Bucket: Name of the Amazon S3 bucket where the Lambda function zip file is stored. LambdaS3Key: Name of the Lambda function zip file. This is the full path to the S3 object, with the prefix. For example, “dir1/dir2/lambdafunction.zip”. The Lambda function zip file can be downloaded from the link in the Lambda function section of this blog post. Select Capabilities Acknowledgement and choose Create. This field gives permission to the stack to create IAM roles and policies. These roles and policies are used by the Lambda function to perform certain actions such as publishing messages to the SNS topic, listing the account alias, and so on. After the CloudFormation stack is completed, check for the Lambda function name available in the output Now we will add a trigger to this Lambda function. Go to the Lambda console and select the Lambda function we just created, and choose triggers and add trigger. In the trigger box select SNS and choose the SNS topic of the “Event Detection & notification” system you want the phone calls for. Choose Submit.

Now the Lambda function is ready to get triggered by the SNS topic of your “event detection and notification” system. You can add as many triggers for various event detection and notification system as you would like. More information on triggering AWS Lambda can be found here.

SNS trigger Lambda Function

The Text-Audio converting Lambda function parses the subject of the SNS message when it is triggered. It then passes this subject field text to the Amazon Polly service to convert it into an audio file. After the text gets converted into an audio file it gets stored in the S3 bucket created by the CloudFormation stack in the previous section.

It then calls the Twilio API to make a phone call and play back the audio file of the event notification from the S3 bucket.

import boto3 import os from contextlib import closing import botocore.session from botocore.exceptions import ClientError session = botocore.session.get_session() import logging import uuid import twilio from twilio.rest import Client import urllib from urllib import request, parse from urllib.parse import quote logging.basicConfig(level=logging.DEBUG) logger=logging.getLogger(__name__) def lambda_handler(event, context): logger.setLevel(logging.DEBUG) logger.debug("Event is --- %s" %event) speak = event["Records"][0]["Sns"]["Subject"] # Converting the Subject text of the SNS message into an mp3 audio file. polly = boto3.client('polly') response = polly.synthesize_speech( OutputFormat='mp3', Text = 'ALERT !' + speak, SampleRate='22050', VoiceId = os.environ['VoiceId'] ) logger.debug("Polly Response is-- %s" %response) id = str(uuid.uuid4()) logger.debug("ID= %s" %id) #Save the audio stream returned by Amazon Polly on Lambda's temp # directory. If there are multiple text blocks, the audio stream # will be combined into a single file. if "AudioStream" in response: with closing(response["AudioStream"]) as stream: filename=id + ".mp3" output = os.path.join("/tmp/",filename) with open(output, "wb") as file: file.write(stream.read()) # Upload the Audio MP3 file to an S3 location s3 = boto3.client('s3') s3upload_response = s3.upload_file('/tmp/' + filename, os.environ['BUCKET_NAME'],filename,ExtraArgs={"ContentType": "audio/mp3"}) logger.debug("S3 UPLOAD RESPONSE IS--- %s" %s3upload_response) s3.put_object_acl(ACL='public-read', Bucket=os.environ['BUCKET_NAME'], Key= filename) location = s3.get_bucket_location(Bucket=os.environ['BUCKET_NAME']) logger.debug("Location response is -- %s" %location) region = location['LocationConstraint'] if region is None: url_begining = "https://s3.amazonaws.com/" else: url = url_begining + str(os.environ['BUCKET_NAME']) + "/" + filename url = '{}/{}/{}'.format(s3.meta.endpoint_url, os.environ['BUCKET_NAME'], filename) #Encode URL encode_url = quote(url, safe='') logger.debug("ENCODED URL-- %s" %encode_url) # Get these credentials from http://twilio.com/user/account account_sid = os.environ['account_sid'] auth_token = os.environ['auth_token'] client = Client(account_sid, auth_token) # Make the phone call using Twilio call_response = client.api.account.calls.create(to=os.environ['ToPhoneNo'], # Any phone number from_=os.environ['FromPhoneNo'], # Must be a valid Twilio number url="http://twimlets.com/message?Message%5B0%5D=" + encode_url + "&" ) logger.debug("Call_response is-- %s" %call_response)

This AWS Lambda code zip file can be downloaded from here and used for the CloudFormation stack deployment.

Solution validation

In the sample audio that follows, I demonstrate that after deploying an event detection system (notify on root API activity) and integrating it to the text to audio converting system, I receive a phone call alert every time a root API is detected for the AWS account.

Phone call sample for console login alert by root:

Listen now



Voiced by Amazon Polly

Then I create an Amazon EBS volume using the root credentials and get another phone call alert.

Listen now



Voiced by Amazon Polly

Conclusion

In this post, I showed you how to create a phone call audio alert system that can be integrated with your previously existing alert and monitoring system. This framework will be useful to get near real-time phone call alerts on critical events in the AWS account.

For further reading, I recommend the following:

About the Author

Sudhanshu Malhotra is a Solutions Architect at AWS Professional Services. Sudhanshu enjoys working with our 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.