1-888-317-7920 info@2ndwatch.com

Creating a simple Alexa Skill

Why do it?

Alexa gets a lot of use in our house, and it is very apparent to me that the future is not a touch screen or a mouse, but voice.  Creating an Alexa skill is easy to learn by watching videos and such, but actually creating the skill is a great way to understand the ins and outs of the process and what the backend systems (like AWS Lambda) are capable of.

First you need a problem

To get started, you need a problem to solve.  Once you have the problem, you’ll need to think about the solution before you write a line of code.  What will your skill do?  You need to define the requirements.  For my skill, I wanted to ask Alexa to “park my cloud” and have her stop all EC2 instances or RDS databases in my environment.

Building a solution one word at a time

Now that I’ve defined the problem and have an idea for the requirements of the solution, it’s time to start building the skill.  The first thing you’ll notice is that the Alexa Skill port is not in the standard AWS portal.  You need to go to developer.amazon.com/Alexa and create a developer account and sign in there.  Once inside, there is a lot of good information and videos on creating Alexa skills that are worth reviewing.  Click the “Create Skill” button to get started.  In my example, I’m building a custom skill.

Build

The process for building a skill is broken into major sections; Build, Test, Launch, Measure.  In each one you’ll have a number of things to complete before moving on to the next section.  The major areas of each section are broken down on the left-hand side of the console.  On the initial dashboard you’re also presented with the “Skill builder checklist” on the right as a visual reminder of what you need to do before moving on.

Interaction model

This is the first area you’ll work on in the Build phase of your Alexa skill.  This is setting up how your users will interact with your skill.

Invocation

Invocation will setup how your users will launch your skill.  For simplicity’s sake, this is often just the name of the skill.  The common patterns will be “Alexa, ask [my skill] [some request],” or “Alexa, launch [my skill].”  You’ll want to make sure the invocation for your skill sounds natural to a native speaker.

Intents

I think of intents as the “functions” or “methods” for my Alexa skill.  There are a number of built-in intents that should always be included (Cancel, Help, Stop) as well as your custom intents that will compose the main functionality of your skill.  Here my intent is called “park” since that will have the logic for parking my AWS systems.  The name here will only be exposed to your own code, so it isn’t necessarily important what it is.

Utterances

Utterances is your defined pattern of how people will use your skill.  You’ll want to focus on natural language and normal patterns of speech for native users in your target audience.  I would recommend doing some research and speaking to a diversity of people to get a good cross section of utterances for your skill.  More is better.

Slots

Amazon also provides the option to use slots (variables) in your utterances.  This allows your skill to do things that are dynamic in nature.  When you create a variable in an utterance you also need to create a slot and give it a slot type.  This is like providing a type to a variable in a programming language (Number, String, etc.) and will allow Amazon to understand what to expect when hearing the utterance.  In our simple example, we don’t need any slots.

Interfaces

Interfaces allow you to interface your skill with other services to provide audio, display, or video options.  These aren’t needed for a simple skill, so you can skip it.

Endpoint

Here’s where you’ll connect your Alexa skill to the endpoint you want to handle the logic for your skill.  The easiest setup is to use AWS Lambda.  There are lots of example Lambda blueprints using different programming languages and doing different things.  Use those to get started because the json response formatting can be difficult otherwise.  If you don’t have an Alexa skill id here, you’ll need to Save and Build your skill first.  Then a skill id will be generated, and you can use it when configuring your Lambda triggers.

AWS Account Lambda

Assuming you already have an AWS account, you’ll want to deploy a new Lambda from a blueprint that looks somewhat similar to what you’re trying to accomplish with your skill (deployed in US-East-1).  Even if nothing matches well, pick any one of them as they have the json return formatting set up so you can use it in your code.  This will save you a lot of time and effort.  Take a look at the information here and here for more information about how to setup and deploy Lambda for Alexa skills.  You’ll want to configure your Alexa skill as the trigger for the Lambda in the configuration, and here’s where you’ll copy in your skill id from the developer console “Endpoints” area of the Build phase.

While the actual coding of the Lambda isn’t the purpose of the article, I will include a couple of highlights that are worth mentioning.  Below, see the part of the code from the AWS template that would block the Lambda from being run by any Alexa skill other than my own.  While the chances of this are rare, there’s no reason for my Lambda to be open to everyone.  Here’s what that code looks like in Python:

if (event[‘session’][‘application’][‘applicationId’] != “amzn1.ask.skill.000000000000000000000000”):

raise ValueError(“Invalid Application ID”)

Quite simply, if the Alexa application id passed in the session doesn’t match my known Alexa skill id, then raise an error.  The other piece of advice I’d give about the Lambda is to create different methods for each intent to keep the logic separated and easy to follow.  Make sure you remove any response language from your code that is from the original blueprint.  If your responses are inconsistent, Amazon will fail your skill (I had this happen multiple times because I borrowed from the “Color Picker” Lambda blueprint and had some generic responses left in the code).  Also, you’ll want to handle your Cancel, Help, and Stop requests correctly.  Lastly, as best practice in all code, add copious logging to CloudWatch so you can diagnose issues.  Note the ARN of your Lambda function as you’ll need it for configuring the endpoints in the developer portal.

Test

Once your Lambda is deployed in AWS, you can go back into the developer portal and begin testing the skill.  First, put your Lambda function ARN into the endpoint configuration for your skill.  Next, click over to the Test phase at the top and choose “Alexa Simulator.”  You can try recording your voice on your computer microphone or typing in the request.  I recommend you do both to get a sense of how Alexa will interpret what you say and respond.  Note that I’ve found the actual Alexa is better at natural language processing than the test options using a microphone on my laptop.  When you do a test, the console will show you the JSON input and output.  You can take this INPUT pane and copy that information to build a Lambda test script on your Lambda function.  If you need to do a lot of work on your Lambda, it’s a lot easier to test from there than to flip back and forth.  Pay special attention to your utterances.  You’ll learn quickly that your proposed utterances weren’t as natural as you thought.  Make updates to the utterances and Lambda as needed and keep testing.

Launch

Once you have your skill in a place where it’s viable, it’s time to launch.  Under “Skill Preview,” you’ll pick names, icons, and a category for your skill.  You’ll also create “cards” that people will see in the Alexa app that explain how to use your skill and the kinds of things you can say.  Lastly, you’ll need a URL to your “Privacy Policy” and “Terms of Use.”  Under “Privacy and Compliance,” you answer more questions about what kind of information your skill collects, whether it targets children or contains advertising, if it’s ok to export, etc.  Note that if you categorize your skill as a “Game,” it will automatically be considered to be directed at children, so you may want to avoid that with your first skill if you collect any identifiable information. Under “Availability,” you’ll decide if the skill should be public and what countries you want to be able to access the skill.  The last section is “Submission,” where you hopefully get the green checkmark and be allowed to submit.

Skill Certification

Now you wait.  Amazon seems to have a number of automated processes that catch glaring issues, but you will likely end up with some back and forth between yourself and an Amazon employee regarding some part of your skill that needs to be updated.  It took about a week to get my final approval and my skill posted.

Conclusion

Creating your own simple Alexa skill is a fun and easy way to get some experience creating applications that respond to voice and understand what’s possible on the platform.  Good luck!

-Coin Graham, Senior Cloud Consultant

Facebooktwittergoogle_pluslinkedinmailrss

AWS re:Invent Keynote Recap – Thursday

Thursday’s General Session Keynote kicked off with Amazon CTO, Werner Vogels, taking the stage to deliver additional product and services announcements with the inclusion of deeper, technical content.  Revisiting his vision for 21st Architectures from the 1st Re:Invent in 2012, Werner focused on what he sees as key guiding principles for next-gen workloads.

  1. Voice represents the next major disruption in computing. Stressing this point, Werner announced the general availability of Alexa for Business to help improve productivity by introducing voice automation into your business.
  2. Use automation to make experimentation easier
  3. Encryption is the ‘key’ to controlling access to your data. As such, encrypting data (at rest and in transit) should be a default behavior.
  4. All the code you should ever write is business logic.

 

Werner also highlighted the fact that AWS now has over 3,951 new services released since 2012. These services were not built for today but built for the workloads of the future.  The goal for AWS, Werner says, is to be your partner for the future.

One of the highlights of the keynote was when Abby Fuller, evangelist for containers at AWS, came on stage to talk about the future of containers at AWS.  She demoed the use of Fargate which is AWS’s fully managed container service. Think of Fargate as Elastic Beanstalk but for containers.  Per AWS documentation “It’s a technology that allows you to use containers as a fundamental compute primitive without having to manage the underlying instances. All you need to do is build your container image, specify the CPU and memory requirements, define your networking and IAM policies, and launch. With Fargate, you have flexible options to closely match your application needs and you’re billed with per-second granularity.”

The Cloud9 acquisition was also a highlight of the keynote.  Cloud9 is a browser-based IDE for developers.  Cloud9 is completely integrated with AWS and you can create cloud environments, develop code, and push that code to your cloud environment all from within the tool.  It’s really going to be useful for writing and debugging lambda functions for developers that have gone all in on serverless technologies.

New Announcements

AWS Lambda Function Execution Activity Logging – Log all execution activity for your Lambda functions. Previously you could only log events but this allows you to log data events and get additional details.

AWS Lambda Doubles Maximum Memory Capacity for Lambda Functions – You can now allocate 3008MB of memory to your AWS Lambda functions.

AWS Cloud9 –  Cloud9 is a cloud based IDE for writing, running, and debugging your code.

API Gateway now supports endpoint integrations with Private VPCs –  You can now provide access to HTTP(S) resources within your Amazon Virtual Private Cloud (VPC) without exposing them directly to the public Internet.

AWS Serverless Application Repository –   The Serverless Application Repository is a collection of serverless applications published by developers, companies, and partners in the serverless community.

We expect AWS to announce many more awesome features and services before the day ends so stay tuned for our AWS  re:Invent 2017 Products & Services Review and 2017 Conference Recap blog posts for a summary of all of the announcements that are being delivered at AWS re:Invent 2017.

 

— Brent Clements, Sr. Cloud Consultant, 2nd Watch

Facebooktwittergoogle_pluslinkedinmailrss

A Step-by-Step Guide on Using AWS Lambda-Backed Custom Resources with Amazon CFTs

Amazon CloudFormation Template (CFT) custom resources allow for additional flexibility in building Amazon environments. These can be utilized in a number of ways to enhance automation and make deployment easier. Generally speaking you’ll want to engage custom resources when you need information that is normally not available to the CloudFormation Template in order to complete the processing of the template. This could be a Security Group in another account, or the most updated AMI, or a Spot Price analysis. Additionally it’s useful for creating functionality in CFT that doesn’t exist yet, like verifying that the database size you’ve chosen is valid, or checking if you have a valid password (our example). You won’t want to use it for anything “one-off” as it takes time to develop and process. You will also want to avoid using it for long running processes since AWS CloudFormation will timeout if the internal processes take too long.

To give you an easy example of how this is setup, we’re going to build an AWS Lambda-backed custom resource that will verify that a password is correct by having you type it in twice. If the passwords you type don’t match, the CFT will quit processing and rollback. This is a bit of functionality that’s missing from AWS CFT and can be very frustrating once your environment is deployed and you realize you fat fingered the password parameter. The basic areas we’ll be focusing on are AWS CloudFormation and AWS Lambda. This guide assumes you’re familiar with both of these already, but if you’re not, learn more about AWS Lambda here or AWS CFTs here.

You want to start with the CFT that you’re looking to add the custom resource to and make sure it is functional. It’s always best to start from a place of known good. Adding a Lambda-backed custom resource to a CFT consists of four basic parts:

1. IAM Role for Lambda Execution: This is the role that will be assigned to your Lambda function. You will utilize this role to give the lambda permissions to other parts of AWS as necessary. If you don’t need to add any permissions, just create a role that allows Lambda to write its logs out.

"LambdaExecutionRole": {
  "Type": "AWS::IAM::Role",
  "Properties": {
    "AssumeRolePolicyDocument": {
      "Version": "2012-10-17",
      "Statement": [{
        "Effect": "Allow",
        "Principal": {
          "Service": ["lambda.amazonaws.com"]
        },
        "Action": ["sts:AssumeRole"]
      }]
    },
    "Policies": [{
      "PolicyName": "lambdalogtocloudwatch",
      "PolicyDocument": {
        "Version": "2012-10-17",
        "Statement": [{
          "Effect": "Allow",
          "Action": ["logs:CreateLogGroup",
          "logs:CreateLogStream",
          "logs:PutLogEvents"],
          "Resource": "arn:aws:logs:*:*:*"
        }]
      }
    }]
  }
}

2. The Lambda Function: There are two ways of introducing your Lambda function into your CFT. If it is small, you can embed your function directly into the CFT by using the “ZipFile”
option under the “Code” property of the “AWS::Lambda::Function” resource. Or you can use the “S3Bucket” option and reference an S3 bucket that has your code already present in zip
format. Note that if you use the S3 bucket option the user that deploys the CFT will need permissions to read from the bucket, not the Lambda function. Next you’ll set your “Handler,”
“Runtime,” “Timeout,” and “Role” (which should reference the ARN of the role you created previously). If you are using the ZipFile option, your handler is the default for the runtime.

"CheckPasswordsFunction": {
  "Type": "AWS::Lambda::Function",
  "Properties": {
    "Code": {
      "ZipFile": {
        "Fn::Join": ["\n", [
          "var response = require('cfn-response');",
          "exports.handler = function(event, context) {",
          " if (event.RequestType == 'Delete') {",
          " response.send(event, context, response.SUCCESS);",
          " return;", " }",
          " var password = event.ResourceProperties.Password;",
          " var confpassword = event.ResourceProperties.ConfirmPassword;",
          " var responseData = {};",
          " if (password == confpassword) {",
          " responseData = {'passwordcheck': 'Password Valid!'};",
          " response.send(event, context, response.SUCCESS, responseData);",
          " } else {",
          " responseData = {Error: 'Passwords do not match'};",
          " console.log(responseData.Error);",
          " responseData = {'passwordcheck': 'Password Invalid!'};",
          " response.send(event, context, response.FAILED, responseData);",
          " }", "};"
        ]]
      }
    },
    "Handler": "index.handler",
    "Runtime": "nodejs",
    "Timeout": "30",
    "Role": {
      "Fn::GetAtt": [
        "LambdaExecutionRole", "Arn"
      ]
    }
  }
}


3. The Lambda Callout: The Lambda callout is where you pass the variables from the CFT to your Lambda function. It’s important to name these appropriately and consider what effect case and naming conventions will have on the runtime you’re using. The “Service Token” property is the ARN of the Lambda function you just created and the rest of the properties are the variables you’re passing through.

"TestPasswords": {
  "Type": "Custom::LambdaCallout",
  "Properties": {
    "ServiceToken": {
      "Fn::GetAtt": [
        "CheckPasswordsFunction",
        "Arn"
      ]
    },
    "Password": {
      "Ref": "Password"
    },
    "ConfirmPassword": {
      "Ref": "ConfirmPassword"
    }
  }
}

4. The Response: There are two key parts of the response from the custom resources and this applies to non-Lambda custom resources too. The first is the “Status” of the response. If you return a status of “FAILED,” the CFT will short circuit and rollback. If you return a status of “SUCCESS,” then the CFT will continue to process. This is important because sometimes you’ll want to send SUCCESS even if your lambda didn’t produce the desired result. In the case of our PassCheck, we wanted to stop the CFT from moving forward to save time. Knowing at the end that the password were mismatched would not be very valuable. The second important piece of the response is the “Data.” This is how you pass information back to CloudFormation to process the result. You’ll set the “Data” variable in your code as a json and reference the json key/value pair back inside the CFT. You’ll use the “Fn::GetAtt” option to reference the Lambda callout you created previously and the key of the json data you’re interested in.

"Outputs": {
  "Results": {
    "Description": "Test Passwords Result",
    "Value": {
      "Fn::GetAtt": ["TestPasswords",
        "passwordcheck"
      ]
    }
  }
}

As far as your Lambda function is concerned, you may or may not need to reference variables sent from the CloudFormation Template. These variables will be in the “event”->”ResourceProperties” dictionary/hash. For example:

NodeJs

var password = event.ResourceProperties.Password

Python

password = event['ResourceProperties']['Password']

And similarly, once you’re function is completed processing you might need to send a response back to the CFT. Thankfully AWS has created some wrappers to make the response easier. For nodejs it is called “cfn-response” but is only available when using the “ZipFile” option. There is a similar package for Python, but you’ll need to bundle it with your Lambda and deploy from S3. Sending information back from your Lambda is as easy as setting the “Data” variable to a properly formatted json file and sending it back.

...
if (password == confpassword) {
responseData = {'passwordcheck': 'Password Valid!'};
response.send(event, context, response.SUCCESS, responseData);
...

That’s it. Creating a Lambda-backed custom resource can add all kinds of additional functionality and options to your CloudFormation Templates. Feel free to download the whole CFT here and it out or use it to learn more, or Contact Us for help in getting started.

-Coin Graham, Sr Cloud Engineer

Facebooktwittergoogle_pluslinkedinmailrss

AWS Lambda Scheduled Event Function Deep Dive: Part 4

Registering the Lambda Function

Now that we’ve created the Lambda function IAM role, for the sake of simplicity, let’s assume the function itself is already written and packaged sitting in an S3 bucket that your Lambda function Role will have access to.  For this example, let’s assume our S3 URL for this backup function is: s3://my-awesome-lambda-functions/ec2_backup_manager.zip

The IAM policy rights required for creating the Lambda function and the Scheduled Event are:

  • lambda:CreateFunction
  • lambda:AddPermission
  • events:PutRule
  • events:PutTargets

Registering the Lambda Function and Scheduled Event via the AWS Lambda API using Python and boto3

Note: Like the previous boto3 example, you must either have your AWS credentials defined in a supported location (e.g. ENV variables, ~/.boto, ~/.aws/configuration, EC2 meta-data) or you must specify credentials when creating your boto3 client (or alternatively ‘session’).  The User/Role associated with the AWS credentials must also have the necessary rights, defined by policy, to perform the required operations against the AWS Lambda API.

A few notes on the creation_function function arguments
  • The Runtime is the language and version being used by our function (i.e. python2.7)
  • The Role is the ARN of the role we created in the previous exercise
  • The Handler is the function within your code that Lambda calls to begin execution. For our python example the value is: {lambda_function_name}.{handler_function_name}
  • The Code is either a base64 encoded zip file or the s3 bucket and key
An important Warning about IAM role replication delay

In the previous step we created an IAM role that we reference in the code below when creating our Lambda function.  Since IAM is an AWS region independent service it takes some time – usually less than a minute – for create/update/delete actions against the IAM API to replicate to all AWS regions.  This means that when we perform the create_function operation in the script below, we may very well receive an error from the Lambda API stating that the role we specified does not exist.  This is especially true when scripting an operation where the create_function operation happens only milliseconds after the create_role function.  Since there is really no way of querying the Lambda API to see if the role is available in the region yet prior to creating the function, the best option is to use exception handling to catch the specific error where the role does not yet exist and wrap that exception handler in a retry loop with an exponential back-off algorithm (though sleeping for 10-15 seconds will work just fine too).

Let’s pick up in the python script where we previously left off in the last example:

Img_6

Registering the Lambda Function and Scheduled Event using AWS CloudFormation Template

Note: The S3Bucket MUST exist in the same region you are launching your CFT stack in.  To support multi-region templates I generally will have a Lambda S3 bucket for each Lambda region and append a .{REGION_NAME} suffix to the bucket name (e.g. my-awesome-lambda-functions.us-west-2).  Since CloudFormation provides us with a psuedo-parameter of the region you are launching the stack in (AWS::Region), you can utilize that to ensure you are referencing the appropriate bucket (see my example below).

The following block of JSON can be used in conjunction with our previous CloudFormation snippet by being added to the template’s “Resource” section to create the Lambda function, CloudWatch Event, and Input:

Img_7

If you implement your Lambda functions using either of the two examples provided you should be able to reliably create, , manage, automate and scale them to whatever extent and whatever schedule you need.  And the best part is you will only be charged for the ACTUAL compute time you use, in 100ms increments.

Now go have fun, automate everything you possibly can, and save your organization thousands of dollars in wasted compute costs!  Oh, and conserve a bunch of energy while you’re at it.

-Ryan Kennedy, Sr Cloud Consultant

Facebooktwittergoogle_pluslinkedinmailrss

AWS Lambda Scheduled Event Function Deep Dive: Part 3

Creating the Lambda Function IAM Role

In our last article, we looked at how to set up scheduled events using either the API (python and boto3) or CloudFormation, including the required Trusted Entity Policy Document and IAM Role. This role and policy can be created manually using the AWS web console (not recommended), scripted using the IAM API (e.g. Python and boto3), or using a templating tool (e.g. CloudFormation. Hashicorp’s Terraform).  For this exercise we will cover both the scripted and the template tool approaches.

The IAM policy rights required for creating the Lambda function role and policy are:

  • iam:CreateRole
  • iam:PutRolePolicy

Creating the Lambda IAM role via the IAM API using Python and boto3

Note: For the following example you must either have your AWS credentials defined in a supported location (e.g. ENV variables, ~/.boto, ~/.aws/configuration, EC2 meta-data) or you must specify credentials when creating your boto3 client (or alternatively ‘session’).  The User/Role associated with the AWS credentials must also have the necessary rights, defined by policy, to perform the required operations against AWS IAM API.

The following python script will produce our desired IAM role and policy:

Img_4

That will create the necessary lambda function role and its inline policy.

Creating the Lambda IAM role using AWS CloudFormation Template

The following block of JSON can be added to a CloudFormation template’s “Resource” section to create the Lambda function role and its inline policy:

Img_5

Visit us next week for the final segment of this blog series – Registering the Lambda Function.

-Ryan Kennedy, Sr Cloud Consultant

Facebooktwittergoogle_pluslinkedinmailrss