AWS PowerShell Python Lambda - PSPy
AWS PowerShell Python Lambda, or PSPy for short, is a simple Python 2.7 AWS Lambda function designed to execute the PowerShell binary and marshal input/output to PowerShell.
Setup
Setup is very easy depending on your level of trust with a random GitHub repository you found on the internet.
Quickstart
If you prefer to get started right away, head over to the releases page and grab the latest zip file and upload the zip file as the code for a new Lambda function in your AWS account.
Build from scratch
Alternatively, if you want to ensure you are getting the latest PowerShell release, and that nothing else is packaged with it [nothing is, I promise :) ] then follow the steps below.
Create a new Amazon Linux EC2 instance and run the following commands on it (note you can replace the rpm with the latest release if you desire)
wget https://github.com/PowerShell/PowerShell/releases/download/v6.0.0-alpha.18/powershell-6.0.0_alpha.18-1.el7.centos.x86_64.rpm
yum install libunwind uuid
rpm -i powershell-6.0.0_alpha.18-1.el7.centos.x86_64.rpm
mkdir pspy
cd pspy
cp -R /opt/microsoft/powershell/6.0.0-alpha.18/* .
cp /usr/lib64/libunwind* .
cp /usr/bin/uuid .
Create lambda_function.py within the pspy folder containing the code below
import boto3,subprocess,os
def lambda_handler(event, context):
#get lambda variables
executionArg = event['executionArg']
executionPayload = event['executionPayload']
#environment variables required for powershell to start
os.environ["HOME"] = "/tmp"
os.environ["PSHOME"] = "/tmp"
#need to make powershell binary executable
process = subprocess.Popen(["/bin/chmod +x /var/task/pwsh"],stdout=subprocess.PIPE,stderr=subprocess.STDOUT,shell=True)
if executionArg == "-c":
process = subprocess.Popen(["/var/task/pwsh -c '{}'".format(executionPayload)],stdout=subprocess.PIPE,stderr=subprocess.STDOUT,shell=True)
elif executionArg == "-enc":
process = subprocess.Popen(["/var/task/pwsh -enc {}".format(executionPayload)],stdout=subprocess.PIPE,stderr=subprocess.STDOUT,shell=True)
elif executionArg == "-f":
s3_client = boto3.client('s3')
bucket = executionPayload['bucket']
key = executionPayload['key']
localPath = os.path.join('/tmp',key.split("/")[-1])
s3_client.download_file(bucket, key, localPath)
process = subprocess.Popen(["/var/task/pwsh -f {}".format(localPath)],stdout=subprocess.PIPE,stderr=subprocess.STDOUT,shell=True)
else:
return "Unrecognized executionArg"
returncode = process.wait()
output = process.stdout.read()
print output
return output
Run the following commands
zip -rq lambda.zip .
aws s3 cp lambda.zip s3://yourbucket/lambda.zip
Create python 2.7 lambda function referencing your uploaded zip file from s3
Make sure that your Lambda can read from a S3 bucket if you desire to execute ps1 files (more on this later)
Usage
The Python portion of this Lambda function was designed to be very easy to use. It accepts PowerShell code in three ways.
Literal commands that you might traditionally use with -command
Base64 encoded commands that you might traditionally use with -encodedcommand
PS1 script files that you might traditionally use with -file
-Command
Simply pass your Lambda function an event that looks like this
{
"executionArg": "-c",
"executionPayload": "Get-Host"
}
-EncodedCommand
Simply pass your Lambda function an event that looks like this
{
"executionArg": "-enc",
"executionPayload": "RwBlAHQALQBIAG8AcwB0ADsARQB4AGkAdAA7AA=="
}
-File
Simply pass your Lambda function an event that looks like this
{
"executionArg": "-f",
"executionPayload": {
"bucket": "",
"key": ""
}
}
I found an issue
Great! I threw this silly thing together rather hastily so it's likely to have issues. Open an issue with the repository explaining what is wrong and we'll see if we can't figure out how to fix the problem. Or you can bring up an issue and the solution in a pull request.
I have a suggestion
Awesome! Create an issue describing your suggestion, including a pull request if you have decided to take care of implementing your suggestion for me.
Why on earth did you do this?
In short: I like PowerShell and wanted to run it in AWS Lambda.
I attempted to get it running in native C# code using dotnetcore in Lambda but kept running into issues. I was seeking help on the PowerShell slack team when a gentleman from AWS (who will remain nameless until he consents to being credited) sent me a private message, interested in what I was trying to do. He asked if I had tried to just use the PowerShell binary in Lambda, so I decided I would give his suggestion a shot and it totally worked!
License
PSPy is licensed under the MIT license, just like PowerShell