diff --git a/.gitignore b/.gitignore index 340662c..fbfbd7d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ src/layer/* src/*.zip .idea/* +__pycache__ diff --git a/README.MD b/README.MD index 8045817..4f66a92 100644 --- a/README.MD +++ b/README.MD @@ -3,24 +3,46 @@ A [layer](https://aws.amazon.com/about-aws/whats-new/2018/11/aws-lambda-now-supports-custom-runtimes-and-layers/) for AWS Lambda that allows your functions to use `openssl` binaries. -## Getting Started +This repository contains the code needed to create an AWS Lambda Layer that +adds the OpenSSL binary and related files to a Lambda container. -You can add this layer to any Lambda function you want. -`PATH` already includes `/opt/bin` in Lambda, which is where it will be mounted. +This is useful because Lambda Runtimes based on Amazon Linux 2 and newer do not +include this binary. -Click on Layers and choose "Add a layer", and "Provide a layer version -ARN" and enter the following ARN (replace `us-east-1` with the region of your Lambda): +## How to build +To build the zip, just run ``` -arn:aws:lambda:us-east-1:034541671702:layer:openssl-lambda:1 +cd src +./build.sh ``` +Then, log in to AWS Console, navigate to Lambda, and find the Layers subsection +in the sidebar. + +There you can create a new layer, fill in the required details, and upload the +zip you just created. After finishing this process, the new layer is available +to be used in you lambda functions! + +## Using a Lambda Layer + +You can add this layer to any Lambda function you want. +`PATH` already includes `/opt/bin` in Lambda, which is where it will be mounted. + +In some Runtimes, you may still need to alter the `LD_LIBRARY_PATH` environment +variable, prepending /opt/lib64 to override the .so files already present in +the image. + +In AWS Lambda console, find your function, then scroll down to Layers and +choose "Add a layer", then select your layer. + ![Provide layer ARN](https://raw.githubusercontent.com/alexandredavi/openssl-lambda-layer/master/img/provide.PNG "Provide layer ARN screenshot") Then click Add, save your lambda and test it out! ![Referenced layers](https://raw.githubusercontent.com/alexandredavi/openssl-lambda-layer/master/img/referenced.PNG "Referenced layer ARN screenshot") + ## Simple example on Node.js ```js @@ -30,3 +52,13 @@ exports.handler = async(event) => { execSync(' openssl genrsa -out testCert.key 2048', { encoding: 'utf8', stdio: 'inherit' }) } ``` + +## Simple example on Python + +```python +import os +import subprocess + +def handler(event, context): + subprocess.run("openssl genrsa 2048", env={'PATH': os.environ['PATH']}) +``` diff --git a/src/Dockerfile b/src/Dockerfile index c544433..36682aa 100644 --- a/src/Dockerfile +++ b/src/Dockerfile @@ -1,15 +1,12 @@ -FROM amazonlinux:2 +FROM amazonlinux:2023 + +RUN dnf -y install zip +RUN dnf -y install openssl -RUN yum install openssl11 -y -RUN yum install zip -y RUN mkdir -p /tmp/layer -CMD cd /tmp/layer && \ - mkdir -p bin && \ - mkdir -p lib && \ - cp /bin/openssl11 ./bin/openssl && \ - cp /usr/lib64/libbz2.so.1 ./lib && \ - cp /usr/lib64/libssl.so.1.1 ./lib && \ - cp /usr/lib64/libcrypto.so.1.1 ./lib && \ - zip -r layer.zip ./* && \ - rm -rf lib bin +COPY build-layer.sh build-layer.sh + +ENTRYPOINT ["/bin/bash"] + +CMD ["build-layer.sh"] diff --git a/src/build-layer.sh b/src/build-layer.sh new file mode 100755 index 0000000..b319302 --- /dev/null +++ b/src/build-layer.sh @@ -0,0 +1,10 @@ +ts=$(date +%s) +cd /tmp/layer && \ + mkdir -p bin && \ + mkdir -p lib && \ + cp /bin/openssl ./bin/openssl && \ + cp /usr/lib64/libbz2.so.1 ./lib && \ + cp /usr/lib64/libssl.so.3 ./lib && \ + cp /usr/lib64/libcrypto.so.3 ./lib && \ + zip -r layer-${ts}.zip ./* && \ + rm -rf lib bin diff --git a/src/build.sh b/src/build.sh old mode 100644 new mode 100755 index f8a11ab..9ed74af --- a/src/build.sh +++ b/src/build.sh @@ -1,7 +1,10 @@ #!/bin/sh -rm layer/layer.zip +DOCKER_ARGS=$@ -docker image build -t openssl-layer . +rm -rf layer >/dev/null 2>&1 +mkdir layer -docker run --rm -v "$PWD"/layer/:/tmp/layer openssl-layer +docker image build $DOCKER_ARGS -t openssl-layer . + +docker run --rm $DOCKER_ARGS -v "$PWD"/layer/:/tmp/layer openssl-layer diff --git a/src/check.sh b/src/check.sh old mode 100644 new mode 100755 diff --git a/src/publish.sh b/src/publish.sh old mode 100644 new mode 100755 index 8027acc..01d5a51 --- a/src/publish.sh +++ b/src/publish.sh @@ -2,6 +2,8 @@ LAYER_NAME=openssl-lambda +LAYER_ZIP=$(ls layer/layer-*.zip | tail -n 1) + REGIONS="$(aws ssm get-parameters-by-path --path /aws/service/global-infrastructure/services/lambda/regions \ --query 'Parameters[].Value' --output text | tr '[:blank:]' '\n' | grep -v -e ^cn- -e ^us-gov- | sort -r)" @@ -9,6 +11,6 @@ for region in $REGIONS; do aws lambda add-layer-version-permission --region $region --layer-name $LAYER_NAME \ --statement-id sid1 --action lambda:GetLayerVersion --principal '*' \ --version-number $(aws lambda publish-layer-version --region $region --layer-name $LAYER_NAME \ - --zip-file fileb://layer/layer.zip --cli-read-timeout 0 --cli-connect-timeout 0 \ + --zip-file fileb://$LAYER_ZIP --cli-read-timeout 0 --cli-connect-timeout 0 \ --description "OpenSSL binaries for Amazon Linux 2 Lambdas" --query Version --output text) done diff --git a/src/test.sh b/src/test.sh old mode 100644 new mode 100755 index 3df67c5..b8072d6 --- a/src/test.sh +++ b/src/test.sh @@ -1,6 +1,32 @@ #!/bin/sh -rm -rf layer/files && unzip layer/layer.zip -d layer/files +DOCKER_ARGS=$@ -docker run --rm -v "$PWD"/test/:/var/task -v "$PWD"/layer/files:/opt lambci/lambda:nodejs10.x index.handler +LAMBDA_RUNTIMES="public.ecr.aws/lambda/python:3.12 public.ecr.aws/lambda/nodejs:latest" + +LAYER_ZIP=$(ls layer/layer-*.zip | tail -n 1) + +rm -rf layer/files && unzip $LAYER_ZIP -d layer/files + +# Overriding LD_LIBRARY_PATH required for nodejs image to bypass the .so files already present there +for runtime in $LAMBDA_RUNTIMES +do + docker pull $DOCKER_ARGS $runtime + docker run \ + $DOCKER_ARGS \ + --rm \ + --name lambda-openssl-layer-test \ + -p 9000:8080 \ + -e LD_LIBRARY_PATH=/opt/lib:/var/lang/lib:/lib64:/usr/lib64:/var/runtime:/var/runtime/lib:/var/task:/var/task/lib \ + -v "$PWD"/test/:/var/task \ + -v "$PWD"/layer/files:/opt \ + $runtime \ + index.handler & + + sleep 2 + + curl -v -XPOST "http://localhost:9000/2015-03-31/functions/function/invocations" -d '{}' + + docker kill lambda-openssl-layer-test +done diff --git a/src/test/index.js b/src/test/index.js index ee17206..9cb58a7 100644 --- a/src/test/index.js +++ b/src/test/index.js @@ -1,5 +1,5 @@ const { execSync } = require('child_process') exports.handler = async(event, context) => { - execSync(' openssl genrsa 2048', { encoding: 'utf8', stdio: 'inherit' }) + execSync('openssl genrsa 2048', { encoding: 'utf8', stdio: 'inherit' }) } diff --git a/src/test/index.py b/src/test/index.py new file mode 100644 index 0000000..e8d9aa2 --- /dev/null +++ b/src/test/index.py @@ -0,0 +1,6 @@ +import os +import subprocess + +def handler(event, context): + subprocess.run(["openssl","genrsa", "2048"], env={'PATH': os.environ['PATH']}) +