Writing PowerShell Core AWS Lambda Functions ‚Äď Part III

Overview

In this third blog, we’ll be setting up the initial configuration of the Lex ‘bot that is going to be the intermediary between the Facebook page we setup earlier and our forthcoming PowerShell Lambda function. After a brief overview of what’s going to be needed, we’ll setup a Slot Type (with a bit of help from PowerShell), Slot, Intent, and Facebook Channel. With this done, we’ll do a basic test of the ‘bot which to give some insight into the event data format that our function will be receiving and processing.

The Story So Far…

At this point, we have a Facebook app and page setup, our development environment in place with all the prerequisites for writing & publishing PowerShell Lambda packages and taken a trip through the (currently) four cmdlets offered by the AWSLambdaPSCore module.

About Lex

Lex is an AWS service geared towards allowing the use of natural language, written or spoken, as a mechanism for driving other applications and services. It allows you to connect social media services like Facebook, a device such as an Alexa Dot, or your own application to Lex and process the input before providing a response back to the source.

Your Lex bot consists of one or more :

  • Intents – An objective, performed via a combination of the items below.
  • Utterances – Sequence of words which activate a specific Intent
  • Slots – Sets of values, akin to parameters, that are utilized in order for the objective to be achieved. The value of a slot can be filtered from an Utterance, or prompted for separately. Also akin to typical parameter behavior, the values provided to Slots can be restricted to a given format or list of values, using what are known as Slot types.
  • Prompts – Requests for additional information or confirmation of details already given.
  • Fulfilments – The steps that will be taken with all the previous provided that allows the Intent to be completed. In our case this will involve the invoking of a Lambda function and receipt of its output.
  • Channels – Communications services (currently Facebook, Kik, Slack, and Twilio SMS) that Lex can by interact with.

What’s Required

For our ‘bot, with the above in mind, we’re going to go for the following:

Intent Name GetPowerShellHelp
Utterances I want help with {command}

What does {command} do

I want help with an AWS cmdlet

Slot Type PSCommand (custom)
Slot Type Values Every command in the AWSLambdaPSCore module(!)
Slot Name command
Fulfillment Our Lambda function
Channel Facebook

Let’s set about getting these setup. ūüôā

Creating the ‘bot

    • Login to the AWS console
    • Click Services, Amazon Lex
  • With¬†Bot¬†selected on the left hand side, click Create

  • In the Create your bot window, click Custom bot
    • Bot name : MyPowerShellHelpBot
    • Language : Leave as default English (US)
    • Output voice: None. This is a text based application
    • Session timeout¬†: 1 min
    • IAM Role : This is created for you automatically
    • COPPA : No
  • Click Create

A few more seconds should see our bot created. Before we start creating the Intent though, we’re going to create a file that will be used by the Intent, the Slot type¬†PSCommand, mentioned above.

About Slot Types and Slots

Initially, Lex receives a set of words, the Utterance, which acts as a trigger to a specific Intent. In the simplest of Intents, no specifics are required other than the a fixed set of words.

e.g. “play a song for me”.

More often though, additional details will be required. After all, if we want to hear a song, sometimes you might want to hear music by a specific artist. However, creating an Utterance for every single artist would be an impossible task.

This is where Slots come into play. In the example above, the artist is your slot. Defining a Slot tells Lex that it needs specific information to process the request. Each Slot has an associated Slot type.

A Slot type really is just an enumeration that consist of a specific input value (or values), and the underlying value. A Slot type can have more than input value, known as a synonym.

e.g. In the Amazon.Number Slot type, an input value of “four” has an underlying value of 4.

Slot types help not only to translate input data into a more suitable format for processing, but also to restrict the input values that can be given. They can be used to prevent invalid data from being given BEFORE any processing is done. Whilst it also is possible to do pre-processing of input data, In our case, we don’t want our Lambda to run if it’s being provided with an invalid cmdlet name.

Creating the Slot Type File

We’re going to create a Slot type, called PScommand. This will consist of a list of commands from the current revision of the AWSPowerShell.NetCore module we have installed. Our Slot, command, is the parameter that we will be using within our PowerShell Lambda function.¬†Slot types can be imported as a zip compressed JSON file.

We’ll write a PowerShell script to make this JSON and zip file for us. Jump to your development environment of choice, paste the code below, and save it as a .ps1 file.

$json = @"
{
"metadata": {
"schemaVersion": "1.0",
"importType": "LEX",
"importFormat": "JSON"
},
"resource": {
"name": "PScommand",
"version": "1",
"enumerationValues": [

],
"valueSelectionStrategy": "ORIGINAL_VALUE"
}
}
"@

$slot = $json | ConvertFrom-Json
$command = Get-Command -Module 'AWSPowerShell.NetCore'

ForEach ($obj in $command) {
$slot.resource.enumerationValues += [PSCustomObject]@{
value = $obj.name
synonyms = @()
}
}

$slot | ConvertTo-Json -Depth 4 | Out-File psCommand.json -force
Compress-Archive -Path ./psCommand.json -DestinationPath ./psCommand.zip -Force

The here-string that you see is the core template format for slot type we’ll be using. The changes to be made here will involve filling the¬†enumerationValues array with a list of the¬†AWSPowerShell.NetCore modules cmdlets.

The script itself, after converting the JSON to a PSObject, enumerates through each command in the above module and appends an array consisting of a value element, set to the name of the command, and an empty array value for the synonyms attribute. Note that if we wanted to get really detailed, we could use the PowerShell aliases that exist for the commands in this module, placing them in the appropriate entries synonym value, but I’m going to keep it simple. Once this is complete, the PSObject is converted to a JSON file, before being zipped up.

Run the script to create both of these files.

Should you so want, you can take a look at psCommand.json.

Import the Slot Type File

Let’s import our new file:

    • Go back to the main Amazon Lex screen
    • Click Slot types
    • Click Actions, Import
    • On the Import slot type popup, click¬†Browse
    • Navigate to the directory containing your script and the¬†psCommand.zip, select the file and click Open
    • Click Import


Soon after, our Slot type, PScommand should be visible.

Create the Intent

Follow the steps below to create the intent. Similar to Slot types, it is possible to create a zipped JSON file with the Intent, but we’ll do this through the console for now to make it a bit clearer what is happening.

  • On the main Amazon Lex screen, click Bots
  • Click¬†MyPowerShellHelpBot
  • Click +Create Intent
  • In the Add intent window, click Create intent

  • In the Create intent window, call the type¬†getAWSPowerShellHelp¬†for the Intents name.
  • Click Add

Next, we configure the intent. Set to the following.

  • Sample utterances :
    • What does {command} do
    • I want help with {command}
    • I want help with an AWS cmdlet
  • Lambda initialization and validation
    • Do not set
  • Slots
    • Required : Checked
    • Name: command
    • Slot type:¬†PScommand
    • Prompt: What cmdlet?
    • Click the blue + button to add the slot
  • Confirmation prompt
    • Leave unchecked
  • Fullfillment
    • Return parameters to client


Now, scroll down to the bottom of the screen and click Save Intent

Build and Publish the ‘Bot
Before we begin configuration of the Channel, we need to build and publish the ‘bot.

Click Build and wait for the build to finish. On completion, you should find the Test bot window has expanded.

  • Click Publish
  • Next, we are prompted to create an alias by providing it with a name. An alias is simply a reference to a version of a build.
  • Enter Prod for the alias name
  • Click Publish

Once the bot is published, a confirmation screen will appear.

  • Click Close

Create the Facebook Channel

The next step involves us setting up a Channel, in our case for Facebook. Successful configuration of a Channel allows the creation of an endpoint through which Facebook will communicate with Lex.

At this point, grab the Page Access Token and App Secret Key you recorded in Part I of this series.

  • Click the¬†Channels¬†tab
  • Click Facebook¬†on the left hand side
  • Configure as follows:
    • Channel Name: MyFBChannel
    • Channel Description: AWS PowerShell Help Channel
    • KMS Key : Select aws/lex from the drop down list
    • Alias: Select Prod from the drop down list
    • Verify Token: MyVerifyToken
    • Page Access Token : Use the one you have from Part I
    • App Secret Key: Use the one you have from Part I
  • Click Activate

Activation results in a Callback URL, an endpoint that will be used by the Facebook app to communicate with Lex, being created.

Click Copy to copy into the clipboard.

Configure the Facebook Page and App

With the above configured in AWS, we now move on to configuring Facebook to use the Lex ‘bot.

Making the Application Live
In order to allow our application talk to Lex, the Facebook application (AWS PowerShell Help in my case) needs to go live. This requires, however, that the application is configured to provide a link to a privacy policy for users the app.

  • Click Settings, Basic.
  • Configure Privacy Policy URL with any valid web address. There does not need to be any policy a the address given.

    • At the top of the screen, click the slider to make the app live.
    • Set the category to Messaging
  • Click¬†Confirm when prompted if you wish to make the application public.

Shortly afterwards, the slider will go green and indicate ‘ON’

Configure a Webhook and Subscription
Now we’re going to setup the app to use the Callback URL from earlier.

  • Click Messenger on the left side of the screen
  • Click Settings directly below
  • Scroll down to Webhooks
  • Click Setup Webhooks
  • On the New Page Subscription window that opens, use the following settings:
    • Callback URL : Paste the text that was copied into your clipboard from the AWS console
    • Verify Token : MyVerifyToken
    • Subscription Fields: messages, messaging_postbacks, messaging_options
  • Click Verify and Save

Your subscription will be created.

  • Go to the App Review for Messenger section further down the screen
  • Click pages_messaging
  • Click¬†Add to Submission

  • Click the¬†Page Settings¬†hyperlink in the text Looking for pages_messaging_subscripts? It’s moved to Page Settings.
  • This will take you to the Messenger Platform Settings

Because we are using Messenger as our communication method with our Lex ‘bot, some additional configuration needs to be carried out.

We don’t want the app to require manual intervention, so we need to tell Facebook this.

  • Go to the General Settings section
  • Set Response Method to¬†Responses are all automated

Additionally, we want our app to be the one first notified if a message is received by our Facebook page.

  • Go to the Subscribed Apps section
  • Set Primary Receiver¬†to¬†AWS PowerShell Help¬†
  • Ensure Secondary Receiver is now set to¬†Page Inbox

Testing Interaction With Lex ‘bot

Now let’s perform some basic checks of our apps interoperability with Lex.

  • Scroll to the Your Messenger Link section
  • Click Copy link to place the address in your clipboard

  • Paste the URL into the address bar of a new tab in your browser
  • Enter the following text into the message bar:
    • What does Get-EC2Host do?
    • Press return
    • I want help with Get-EC2Host
    • Press return

For each of the text entries above, you should receive a message back.

Remember that at this point we have set Fulfillment to Return parameters to client¬†in the bot’s Intent configuration. This is why you should be seeing the name of¬†Intent being invoked and the Slot provided. Our Lambda still needs to be created.

We’ve verified connectivity between Facebook and Lex, that the messages we have sent are triggering the right Intent and the parameter (slot) is properly parsed.

Let’s jump back to Lex so we can take a look at how this information is natively output.

Viewing the JSON Output

Note that the response that you saw in the Messenger window was a modified version of the actual event data that is raised. This was handled by the Channel.

Let’s take a look at the pre-formatted data.

  • Go back to the Amazon Lex screen
  • Click Bots
  • Click MyPowerShellHelpBot
  • Expand the Test bot window on the right hand side of the screen
  • In Chat with your bot…¬†type I want help with Get-EC2Host
  • In the¬†Indirect response section below, click Detail

You Test bot window should resemble the below:

The text in the Indirect response window is the exact JSON data that our Lambda will receive once it’s up and running.

Conclusion

In this slightly longer than usual blog, we’ve covered the basics of a Lex ‘bot and components that are used with it, created a Slot type consisting of the AWS PowerShell commands, configured an Intent and Channel and setup interoperability between Lex (via the Channel) to the Facebook app. We then performed testing both from Facebook Messenger and also using the Test ‘bot in the AWS console. Lastly, we’ve had an introduction to the format of the¬†event data that is going to be passed to our forthcoming PowerShell Lambda function.

This leads us nicely up to the next blog, in which we’ll create our PowerShell Lambda function, upload it to AWS, and configure it to be activated by our Lex ‘bot.

Thanks for reading! Feedback welcome!

 

Recommended Further Reading

Create and Edit Custom Slot Types –¬†https://developer.amazon.com/docs/custom-skills/create-and-edit-custom-slot-types.html

 

Share

Writing PowerShell Core AWS Lambda Functions ‚Äď Part II

Overview

In this second blog, we’ll be setting up our development environment to allow us to create and publish Lambda compatible PowerShell packages. This will involve installing the .NET Core SDK, PowerShell Core and two AWS specific PowerShell modules, namely AWSPowerShell.NetCore and¬†AWSLambdaPSCore. We’ll also spend a bit of time looking at the cmdlets provided with the latter module.

The Story So Far

In the previous blog, we provided a brief overview on the use of PowerShell Lambda functions and how they process incoming and outgoing data. Then, we set about getting the Facebook app and page setup that is going to be used by our PowerShell driven ‘bot.

Now, let’s carry out the installation of the following

      • PowerShell Core 6.0
      • .Net Core 2.1 SDK
      • AWSPowerShell.NetCore Module
      • AWSLambdaPSCore Module

PowerShell Core 6.0

Various installations of PowerShell Core exist, dependent on your distribution platform. A link to installation instructions for each of these is listed below. Note that as part of the installation process, other prerequisites are installed, such as .Net Core.

Installing PowerShell Core on Windows
Installing PowerShell Core on Linux
Installing PowerShell Core on macOS
Installing PowerShell Core on ARM

.Net Core 2.1 SDK

PowerShell Core is built on top of .NET Core. As such, the Lambda support for PowerShell uses the same .NET Core 2.1 Lambda runtime for both .NET Core and PowerShell based Lambda functions. From a functionality point of view, the cmdlets in the AWSLambdaPSCore module ALSO need the .NET Core 2.1 SDK for packaging your functions for Lambda.

You can find the 2.1 SDK and installation instructions for your distribution here:

AWS Modules

We can now install our two AWS modules, AWSPowerShell.Netcore and AWSLambdaPSCore.

A couple of things worthwhile pointing out regards the installation of these modules:

  1. By default the PSGallery is not a trusted source for installing modules. If you have not configured this to be so, you will be prompted to confirm if you trust this source for the installation of a module.
  2. In the Scope parameter for the installation of the modules, I’ve set the value to CurrentUser. You can also set this to Global, but bear in mind if you choose this other option some platforms might require your PowerShell session to be running in an elevated context.

AWSPowerShell.Netcore Module

This module houses, as of version 3.3.253.0,¬† 4488 cmdlets, split across 125 different AWS services. These are the cmdlets that our solution will offer interactive help on. Suffice to say, I’ll skip giving an overview on the main ones in these!

Launch PowerShell Core from a terminal session via:

pwsh

Next, to install the module, we use the command below.

Install-Module -Name AWSPowerShell.NetCore -Scope CurrentUser

AWSLambdaPSCore Module

Lastly, we can install the AWS Lambda PowerShell Core module. These cmdlets in this module provide options for reporting available template information, creating your PowerShell script, creating an entire deployment package and the creation of the Lambda function itself.

Use the following command for installation:

Install-Module AWSLambdaPSCore -Scope CurrentUser

Once complete, we can see the current list of commands available in the module via Get-Command.

NB. If you wish to see more extensive information about the cmdlets in the module, such as Scriptblock and ParameterSets, you can use the following to return all properties:

Get-Command -Module AWSLambdaPSCore | Format-List -Property *

 

Let’s take a look at these commands in a bit more detail:

Get-AWSPowerShellLambdaTemplate

It’s important to be aware that the source of the input event data dictates its format and properties.

Whilst on a technical level PowerShell does not need to know the schema of JSON data being received before being able to cast it to a PSObject, it is still the case that in order to make effective use of the data therein, you will need to have an idea of how it is organized. Given the growing number of services whose events can be processed by Lambda, this can involve quite a bit of work.

Fortunately, AWS make things a bit simpler for starting out with a PowerShell Lambda function by providing a group of starter templates both offline (as part of the default install of the module) and online that cover some of the event sources/destinations formats that the Lambda function may need to use.

Should you so wish to, you can view them on your browser directly via either of the two URLs below:

As of the date of this blog, these comprise a set of blueprints for the CloudFormation, Code Commit, Amazon Rekognition, Kinesis, S3, SNS, and SQS services. There is additionally a generic template provided, Basic, which ultimately just contains details of the predefined variables for the Lambda context and event source data and details of logging to CloudWatch. You can see the Basic templates content in the HelloWorld example for one of the cmdlets below.

The list of blueprints is actively updated, which is where Get-AWSPowerShellLambdaTemplate assists. It provides a quick point of reference for the templates that are currently available for you to use when creating your solution.

When you execute this cmdlet without any parameters, it queries by default the URLs listed above and then casts the JSON data to a PSObject. If content is not available in either of these two locations, then the locally installed blueprints are returned.

There is also a parameter documented in the help for this cmdlet, InstalledOnly, which is intended to only parse locally installed templates and skip an online check. However, as far as I can see at the moment, this switch is not processed at all.

New-AWSPowerShellLambda

The New-AWSPowerShellLambda cmdlet is capable of either creating a basic, new Lambda function in a single PowerShell script file, or alternatively an entire project, consisting additionally of project, bootstrap, and parameter default files. The latter option is typically only used for advanced cases where additional manual intervention (e.g. adding additional files, or setting default values for parameters in your function) is required before creating the deployment package and needs to be invoked with the WithProject switch parameter. We’ll being doing all our work in a simple PowerShell script, so for the purposes of this blog will not explore this switch further.

An example of the use of the command and what it does is below:

Creating a ‘HelloWorld’ Lambda based on the Basic template

The ‘HelloWorld’ folder and file structure

‘HelloWorld.ps1’ contents

Subsequent to your work being complete, the script or project can be either directly turned into a Lambda function (using Publish-AWSPowerShellLambda), or put into a state which allows its later deployment via a deployment service, such as Cloudformation, using NewAWSPowerShellLambdaPackage. Details of both are below.

Publish-AWSPowerShellLambda

This penultimate cmdlet handles the heavy lifting of taking your script/project, putting it into a state suitable for deployment, and then creating the function itself with the appropriate parameters and with the package uploaded. This step extensively uses the .NET Core SDK, and behind the scenes installs the .NET Amazon.Lambda.Tools package. Once this step is complete, your Lambda function should be accessible to be used as an event handler for another service (Lex in our case).

New-AWSPowerShellLambdaPackage

This cmdlet is used to bundle up a script/project into a package and subsequent zip file that is available for use at a later date by another service or even in a separately defined Lambda project which you configure manually. We’ll not be using this cmdlet during this series of blogs.

Conclusion

At this point, we’ve put in place all the prerequisites for starting scripting of our Lambda function and learnt a bit about the cmdlets provided in the AWSLambdaPSCore module.

In the next blog, we’re going to start on the first stage of our Lex work. It’ll involve setting up a Slot, Intent, and a Channel which will link the ‘bot to the Facebook page created in the first blog. We’ll also cover the event data format, which will link us nicely into the third blog, which involves writing the Lambda function itself.

Thanks for reading! Feedback welcome!

Share

Writing PowerShell Core AWS Lambda Functions – Part I

Writing PowerShell Core AWS Lambda Functions – Part I

Overview

AWS Lambda support for PowerShell Core is here! In this series of blogs, we’re going to be a taking a dive into writing one of these Lambda functions in PowerShell Core. To make it a bit more fun, we’ll be connecting this function with Lex¬†, which will in turn be connected to a custom Facebook page to drive an interactive AWS PowerShell help facility.

Our Goal

By the end of this series of blogs, we’ll have in place a Facebook page which, by sending a message containing an AWS PowerShell command to, will provide an overview of what the command does. It will do this by forwarding the request to a Lex ‘bot, which will parse it, and then provide the input criteria to our PowerShell Lambda function. Our function will then lookup the documentation page for the command, extract a summary, and provide a JSON formatted response back to Lex, which in turn will feed the result back to the Facebook chat channel. Phew!

How PowerShell Processes Lambda Input & Output

First though, let’s take a look at how a Lamda function written in PowerShell works.

As covered in a previous blog, when a Lambda function is invoked, up to two parameters are passed: context, and input object. The context object simply contains details of the Lambda environment, whilst the input one contains event details, such as S3 information relating to when the CreateObject action occurred. For languages such as Go, you need to write an event handler for processing of the above information, an example of which is in the blog previous to this one.

This months announcement from AWS of support for PowerShell Core 6.0 with Lambda and new tools for this was quite a step in the evolution of PowerShell, and introduces another way for processing of events. In a packaged PowerShell script for Lambda, the value of the parameters passed into the Lambda function are made available via predefined $LambdaInput and $LambdaContext. There is no need to write method or function handlers. Particularly of note though is that $LambdaInput is automatically cast into PSObject, making parsing and processing of the information a lot simpler. The handler does not need to know in advance the JSON schema and neither do you need to go through reflection hell and mappings to identify it. PowerShell does it all for you. There is no need to even use the ConvertFrom-JSON cmdlet.

For returning output (if so desired), strings are processed as is. Non returned string types are dynamically cast to JSON prior to them being handed over to the recipient. The choice is yours.

Prerequisites

In order to develop this solution, we need to have the following already in place

  • AWS account
  • Facebook developer account
  • Facebook app
  • .Net Core 2.1 SDK
  • PowerShell Core 6.0
  • AWSLambdaPSCore Module

AWS Account

I’m going to assume that you already have the first in the list. If for whatever reason that’s not the case, you can sign up for a Free Tier account via the following link:

Creating a Facebook Developer Account

You have the option of either converting an existing Facebook account to a developer one, or alternatively creating a new, developer specific, Facebook account. This is necessary in order to allow our application to access both Lex, and internal Facebook API’s.

Full instructions for doing this are at: https://developers.facebook.com/docs/apps/

Creating Our FaceBook App & Page

Once you have carried out the previous step, we need to register an application and page which will connect to our forthcoming Lex ‘bot. You can find full instructions https://developers.facebook.com/docs/messenger-platform/getting-started/quick-start

In your browser, go to https://developers.facebook.com/

  • Click Log In
  • Enter the Facebook credentials that are associated with your development account
  • Click Log In

  • Click My Apps
  • Click Add New App

  • On the Create a New App ID, enter AWS PowerShell Help for Display Name, and your own email address for Contact Email
  • Click Create App ID

  • Follow any instructions if prompted for a Security Check
  • You’ll be taken to an Add a Product screen. Locate Messenger, and click Set Up

  • Scroll down to Token Generation
  • Click Create a new page
  • In the Community or Public Figure page, select Get Started

  • Page Name : AWS PowerShell Help
  • Category: Computers & Internet Website
  • Click Continue

  • On Add a Profile Picture, select Skip

  • On Add a Cover Photo, select Skip

  • After a couple of seconds, our AWS PowerShell Help page will be created.
    Go back to Token Generation for our Messenger settings
  • Select our AWS PowerShell Help page
  • Select Continue as … when prompted to allow the application to receive your name and profile picture

  • The next dialog is to do with allowing your application to act on your behalf. Click OK to authorize.

  • When the screen returns to Token Generation, it will now have a Page Access Token. Record this information for later use

  • Now go to Settings, Basic
  • Click Show in the App Secret dialog, and enter your password when prompted
  • The App Secret will be displayed. Also record this information for later use

Conclusion

At this point, with the exception of one setting which needs to be carried out after we have created our Lex ‘bot, our pre-requisites for our Facebook app are in place. In the next blog, we’ll get our development environment setup for generating our PowerShell function.

Thanks for reading! Feedback welcome!

Share