How to create AWS Lambda function with PowerCLI to access VMConAWS?

AWS Lambda in a nutshell

Lambda is an AWS offering to build serverless applications. It helps you to run code without provisioning or managing servers. The Lambda functions can be invoked directly through API calls or in response to events. AWS will charge the customer only for the compute time consumed by Lambda function, so no need to pay for idle time. You can learn more about lambda here.

AWS Lambda, PowerShell and PowerCLI

The code you run on AWS Lambda is uploaded as a ‘Lambda Function’. AWS Lambda natively supports PowerShell as scripting language. It helps us to write Lambda functions in PowerShell which includes commands from PowerCLI modules.

Let us see the steps to create a PowerShell based Lambda Function to get the list of VMs from a VMware Cloud on AWS SDDC. As of now the AWS Code Editor doesn’t support writing or editing PowerShell based Lambda functions. The steps discuss how to create the Lambda functions offline and deploy them in AWS Lambda.

Step 1 : Install PowerShell Core.

The Lambda functions in PowerShell require PowerShell Core 6.0, Windows PowerShell isn’t supported. If you have PowerShell Core 6.0 or above already installed, skip to step 2. The environment variable $PSVersionTable will help you to find the PowerShell version and Edition.

I’ve used Powershell Core v6.2.1 which can be downloaded from PowerShell GitHub repo.

1.1 Goto https://github.com/PowerShell/PowerShell/releases/tag/v6.2.1 > Assets > and download the Package suitable for your OS, mine is Windows 10 and the bundle ‘PowerShell-6.2.1-win-x64.msi’ worked fine.

1.2 Once downloaded, double-click the installer and follow the prompts.

Step 2 : Install .NET Core 2.1 SDK.

Because PowerShell Core is built on top of .NET Core, the Lambda support for PowerShell uses the same .NET Core 2.1 runtime for both .NET Core and PowerShell Lambda functions. The .NET Core 2.1 SDK is used by the Lambda PowerShell publishing cmdlets to create the Lambda deployment package. The .NET Core 2.1 SDK is available at .NET downloads on the Microsoft website. Be sure to install the SDK and not the runtime installation.

Step 3 : Install Powershell module ‘AWSLambdaPSCore’

Open PowerShell Core and run the following command to install ‘AWSLambdaPSCore’ module.

Install-Module AWSLambdaPSCore -Scope CurrentUser

The following are the commands available in module ‘AWSLambdaPSCore’

Step 4 : Install PowerCLI

If you already have PowerCLI modules installed in Powershell Core, skip this step.

Open PowerShell Core and run the following command

Install-Module VMware.PowerCLI

Step 5 : Create script from PowerShell Lambda Templates.

AWSLambdaPSCore module provides some Script Templates. Get-AWSPowerShellLambdaTemplate will list out the available templates.

We will use the template ‘Basic’ to create script ‘VMC-GetVM.ps1’ for getting the VM list from VMC SDDC.

Step 6 : Modify the script to get the VMs from vCenter located VMConAWS SDDC.

If you are new to Powershell Lambda its good to go through this articleto understand Input Object, Returning Data, Additional Modules and Logging.

Open the script VMC-GetVM.ps1 in the editor, I use VSCode. Replace the content of the script with the following script.

Note: Please ensure the version of modules marked with #Requiresstatement are same as the version of modules loaded in Powershell Core. If it’s different, then update the script with version details of corresponding modules which are loaded. The following command will help to find the versions of required modules.

Get-InstalledModule VMware.*.Sdk,VMware.*.common,VMware.vim,VMware.*.Cis.Core,VMware.*.core | select Name,Version

The values for the properties (venter, vCenterUser, etc) in the object $LamdaInput will be passed when we execute the function.

# PowerShell script file to be executed as a AWS Lambda function. 
# 
# When executing in Lambda the following variables will be predefined.
#   $LambdaInput - A PSObject that contains the Lambda function input data.
#   $LambdaContext - An Amazon.Lambda.Core.ILambdaContext object that contains information about the currently running Lambda environment.
#
# The last item in the PowerShell pipeline will be returned as the result of the Lambda function.
#
# To include PowerShell modules with your Lambda function, like the AWSPowerShell.NetCore module, add a "#Requires" statement 
# indicating the module and version.
#Requires -Modules @{ModuleName='VMware.VimAutomation.Sdk';ModuleVersion='11.3.0.13964823'}
#Requires -Modules @{ModuleName='VMware.VimAutomation.Common';ModuleVersion='11.3.0.13964816'}
#Requires -Modules @{ModuleName='VMware.Vim';ModuleVersion='6.7.0.13964812'}
#Requires -Modules @{ModuleName='VMware.VimAutomation.Cis.Core';ModuleVersion='11.3.0.13964830'}
#Requires -Modules @{ModuleName='VMware.VimAutomation.Core';ModuleVersion='11.3.0.13964826'}

# Uncomment to send the input event to CloudWatch Logs
#Write-Host (ConvertTo-Json -InputObject $LambdaInput -Compress -Depth 5)

$vCenter = $lambdainput.vCenter
$vCenterUser = $lambdainput.vCenterUser
$vCenterPassword = $lambdainput.vCenterpassword
Connect-VIServer $vCenter -User $vCenterUser -Password $vCenterPassword
$vmlist = get-vm
Write-Host $vmlist.Name

Save the script.

Step 7 : Reduce the size of package

In next step we will publish the Lambda Function. While publishing, a deployment package that contains our PowerShell script ‘VMC-GetVM.ps1’ and all modules declared with the #Requires statement will be created. But the deployment may fail since the package with listed PowerCLI modules will exceed Lambda’s hard limit on Package size, ie 69905067 bytes. In that situation the following error will be thrown.

To avoid that, as a workaround, we’ve to reduce the package size by cutting down the size of PowerCLI modules. When I checked ‘VMware.VimAutomation.Core’ is the largest module which is due to  Remote Console files included in the module.

Browse to the following path and move the folder ‘VMware Remote Console’ to Documents.

C:\Users\<user>\Documents\PowerShell\Modules\VMware.VimAutomation.Core\11.3.0.13964826\net45

Step 8 : Create IAM role to access CloudWatch Log and to execute Lambda.

Login to AWS Console and navigated to IAM. Create new role ‘lambda_basic_excution’ with the policy ‘CloudWatchLogsFullAccess’.

Step 9 : Publish to Lambda

To publish our new PowerShell based Lambda function, let’s execute the following command from Powershell Core.

Publish-AWSPowerShellLambda -ScriptPath <path>\VMC-GetVM.ps1 -Name RDPLockDown -Region <aws region> -IAMRoleArn lambda_basic_excution

It will take a while to create the package and deploy to AWS Lambda.

Step 10 : Configure environment variable.

Once the function is deployed, login to AWS Console and navigate to Lambda. Select the newly created function ‘VMC-GetVM’

Set the environment variable HOME to /tmp.

Step 11 : Install AWSPowerShell module.

To execute the newly created function from PowerShell Core we need the module ‘AWSPowerShell’. Run the following command to install it.

Install-Module AWSPowerShell

Step 12 : Execute the function

From the editor (VSCode) create new file LambdaExecute.ps1 and copy the following code.

$payload = @{    vCenter =  '<FQDN of vCenter in VMConAWS>'    vCenterUser = '<vCenter User>'    vCenterpassword = '<vCenter Password>'} | convertto-json Invoke-LMFunction -FunctionName VMC-GetVM  -Payload $payload

Once the execution completed you can see the list of VMs in CloudWatch Logs.

From AWS Console go to CloudWatch > Log Groups and select ‘ /aws/lambda/VMC-GetVM’ and click on latest log stream.

You can see the VMs list in the Message!