Amazon Linux 2
blueleader07 opened this issue · 6 comments
First, awesome job getting this to work on MacOS. I was pulling my hair out (and I don't have much left).
Given your experience, do you have any advice to get this working on Amazon Linux 2? That would be what Lamba runs on. I've been attempting to run Powershell within a lambda (Lambda supports Powershell after all) but when I try to connect to Microsoft I get the same error you helped me fix on MacOS.
This parameter set requires WSMan, and no supported WSMan client library was found. WSMan is either not installed or unavailable for this system.
I thought maybe I could include the PSWSMan module with my deployment, but it turns out Amazon Linux 2 uses glibc-2 which is not one of your pre-built packages. Looking at your notes it sounds like I might be able to build this myself?
So if I can build it myself and get it to run on Lambda that would install WSMan ... and then somehow I need to "restart" powershell. Right? That part is going to be interesting as well ... since a lambda invocation doesn't really have a "restart powershell" concept (that I know of). My next thought was ... maybe a Lamba layer ... if I could somehow get the files needed in a lamba layer it might work.
Sorry for the long explanation. Been working on this 2+ days. Powershell works great on my mac (thanks to you) but when I go to deploy to lambda I'm stuck again. Would love to hear your thoughts (or others who might read this).
Thanks!
SUCCESS!!! I got it working. At least locally in a docker container running Amazon Linux 2. I'm going to try running it in AWS tomorrow.
I followed these instructions for setting up a docker container locally. I chose Node 12.x because that's what I've been using in my existing project. My plan is to create a Node lambda and throw all the powershell files in a layer. Then use node-powershell to run my powershell commands.
Dockerfile:
FROM public.ecr.aws/lambda/nodejs:12
# my lambda code (typescript)
COPY .npmrc tsconfig.json package.json powershell-7.1.3-1.rhel.7.x86_64.rpm /var/task/
COPY src/*.ts /var/task/src/
RUN npm install
RUN npm run build
# install powershell (I downloaded the rpm file locally)
RUN yum -y install powershell-7.1.3-1.rhel.7.x86_64.rpm
# copy the libmi.* files from PSWSMan glibc-1.0 (overwriting what came with powershell)
COPY libmi.* /opt/microsoft/powershell/7/
# This just points to my lambda handler
CMD [ "build/app.handler" ]
Given your experience, do you have any advice to get this working on Amazon Linux 2?
Unfortunately not but IIRC Amazon Linux is based on RHEL so it should be possible.
but it turns out Amazon Linux 2 uses glibc-2 which is not one of your pre-built packages
It's slightly confusing but the number in the packages provided here actually refer to the OpenSSL major version it is compiled with. The glibc
version shouldn't matter except for the requirement that the version is the same or newer than CentOS 7. Therefore pretty much any modern glibc based distribution should work as I provide a version for OpenSSL 1.0.x, 1.1.x, and experimental support for OpenSSL 3.x which is still not a final release yet.
Therefore to install it you should just install the module and run Install-WSMan
as you normally would (with superuser access). The only tricky part is the restart of PowerShell as you said. As long as the files are in place when PowerShell starts up you should be good. If lambda runs with a brand new instance then you need to use a workaround which will be a bit more tricky.
Have a read through #24 (comment) which is a way to override where PowerShell looks for the libpsrpclient
and libmi
library that it will load the first time. This allows you to have the files in a local directory and tell PowerShell to use those instead of the builtin ones. Otherwise what you have done by creating a new container will also work, you just need to make sure you use the correct glibc
version based on what OpenSSL version is installed.
Success from Lambda! NodeJS Lamba + custom Powershell Layer.
It took a bunch of trial and error but the result is pretty simple. All I did was copy the files from my docker container to a folder in my "layer" stack. The layer gets unpacked to /opt on the Amazon Linux OS. My pwsh
executable ends up at /opt/pwsh
and then I used the NPS
environment variable to tell node-powershell
where pwsh
is.
NPS=/opt/pwsh
Lambda layer (CDK)
const layer = new LayerVersion(this, 'lambda-powershell-layer', {
layerVersionName: 'lambda-powershell-layer',
code: new AssetCode('layer/microsoft/powershell/7'),
compatibleRuntimes: [Runtime.NODEJS_12_X],
description:
'A layer that contains Powershell + libmi.so which fixes WSMan on Linux. AWS Powershell runtime does not work with WSMan',
});
I think I can simplify it even more by using a slightly different folder structure. If I drop the contents of the "7" folder into /layer/bin
it might be added to the path automatically without needing the NPS environment variable. Will try that next ...
Just for awareness ... the Powershell layer ends up being ~174MB. AWS limits you to 250MB max layer + lambda total unpacked. When I first tried I was over the limit. I used webpack to bring my lambda code down from ~140MB to ~11MB. :)
My layer now looks like this ... and it works without needing the NPS environment variable.
/layer/bin
All the stuff that was in the "7" folder is in bin.
Updated CDK:
const layer = new LayerVersion(this, 'lambda-powershell-layer', {
layerVersionName: 'lambda-powershell-layer',
code: new AssetCode('layer'),
compatibleRuntimes: [Runtime.NODEJS_12_X],
description:
'A layer that contains Powershell + libmi.so which fixes WSMan on Linux. AWS Powershell runtime does not work with WSMan',
});
I'm closing this issue. I'm set. Thanks!
Nice work, glad to know you got it working.