DEV Community

Ken Collins for Custom Ink Technology

Posted on • Edited on • Originally published at dev.to

Lambda Rust Extension for any Runtime to preload SSM Parameters as Secure Environment Variables!

ℹ️ Crypteia Hits v1.0.0 Miletstone! 🎉 - It now has support for Python among other popular languages like Ruby, Node, & PHP. Crypteia is easy to install as a Lambda Layer or in a Container. It can even be used with K8s containers!

Crypteia is a new super fast Lambda Extension written in Rust which turns your serverless environment variables from SSM Parameter Store paths like these...

Environment:
  Variables:
    SECRET: x-crypteia-ssm:/myapp/SECRET
Enter fullscreen mode Exit fullscreen mode

... into real environment variables when using your Runtime's language of choice. For example, assuming the SSM Parameter path above returns 1A2B3C4D5E6F as the value. Your code's environment variable methods would return that same value.

process.env.SECRET   // 1A2B3C4D5E6F
ENV['SECRET']        # 1A2B3C4D5E6F
Enter fullscreen mode Exit fullscreen mode

It works by using a shared object library via the LD_PRELOAD environment variable in coordination with our Lambda Extension binary that loads all Parameter Store values within a few milliseconds of your function starting up.

Installation

When building your own Lambda Containers, download both the crypteia binary and libcrypteia.so shared object files that match your platform from our Releases page. Target platforms include the following using these naming conventions.

  • Amazon Linux 2: crypteia-amzn.zip & libcrypteia-amzn.zip
  • Debian, Ubuntu, Etc: crypteia-debian.zip & libcrypteia-debian.zip

⚠️ When building your own Lambda Containers, please make sure glibc is installed since this is used by redhook.

⚠️ For now our project supports the x86_64 architecture, but we plan to release arm64 variants soon. Follow or contribute in our GitHub Issue which tracks this topic.

Once these files are downloaded, they can be incorporated into your Dockerfile file like so:

RUN mkdir -p /opt/lib
RUN mkdir -p /opt/extensions
COPY crypteia /opt/extensions/crypteia
COPY libcrypteia.so /opt/lib/libcrypteia.so
ENV LD_PRELOAD=/opt/lib/libcrypteia.so
Enter fullscreen mode Exit fullscreen mode

Lambda Layer

Our Amazon Linux 2 files can be used within a Lambda Layer that you can deploy to your own AWS account. You can use this project to build, publish, and deploy that layer since it has the SAM CLI installed. All you need to do is supply your own S3 bucket. For example:

aws configure
./amzn/setup
S3_BUCKET_NAME=my-bucket ./layer/deploy
Enter fullscreen mode Exit fullscreen mode

Usage

First, you will need your secret environment variables setup in AWS Systems Manager Parameter Store. These can be whatever hierarchy you choose. Parameters can be any string type. However, we recommend using SecureString to ensure your secrets are encrypted within AWS. For example, let's assume the following paramter paths and values exists.

  • /myapp/SECRET -> 1A2B3C4D5E6F
  • /myapp/access-key -> G7H8I9J0K1L2
  • /myapp/envs/DB_URL -> mysql2://u:p@host:3306
  • /myapp/envs/NR_KEY -> z6y5x4w3v2u1

Crypteia supports two methods to fetch SSM parameters:

  1. x-crypteia-ssm: - Single path for a single environment variable.
  2. x-crypteia-ssm-path: - Path prefix to fetch many environment variables.

Using whatever serverless framework you prefer, setup your function's environment variables using either of the two SSM interfaces from above. For example, here is a environment variables section for an AWS SAM template that demonstrates all of Crypteia's features.

Environment:
  Variables:
    SECRET: x-crypteia-ssm:/myapp/SECRET
    ACCESS_KEY: x-crypteia-ssm:/myapp/access-key
    X_CRYPTEIA_SSM: x-crypteia-ssm-path:/myapp/envs
    DB_URL: x-crypteia
    NR_KEY: x-crypteia
Enter fullscreen mode Exit fullscreen mode

When your function initializes, each of the four environmet variables (SECRET, ACCESS_KEY, DB_URL, and NR_KEY) will return values from their respective SSM paths.

process.env.SECRET;       // 1A2B3C4D5E6F
process.env.ACCESS_KEY;   // G7H8I9J0K1L2
process.env.DB_URL;       // mysql2://u:p@host:3306
process.env.NR_KEY;       // z6y5x4w3v2u1
Enter fullscreen mode Exit fullscreen mode

Here are a few details about the internal implementation on how Crypteia works:

  1. When accessing a single parameter path via x-crypteia-ssm: the environment variable name available to your runtime is used as is. No part of the parameter path effects the resulting name.
  2. When using x-crypteia-ssm-path: the environment variable name can be anything and the value is left unchanged.
  3. The parameter path hierarchy passed with x-crypteia-ssm-path: must be one level deep and end with valid environment variable names. These names must match environement placeholders using x-crypteia values.

For security, the usage of DB_URL: x-crypteia placeholders ensures that your application's configuration is in full control on which dynamic values can be used with x-crypteia-ssm-path:.

Lambda Layer

Shown below is a simple Node.js 16 function which has the appropriate IAM Permissions and Crypteia Lambda Layer added. Also configured are the needed LD_PRELOAD and SECRET environment variables. The code of this function log the value of the process.env.SECRET which does correctly resolve to the value within SSM Parameter Store.

Screenshot of the Environment variables in the AWS Lambda Console showing  raw `LD_PRELOAD` endraw  to  raw `/opt/lib/libcrypteia.so` endraw  and  raw `SECRET` endraw  to  raw `x-crypteia-ssm:/myapp/SECRET` endraw .

Screenshot of Code source in the AWS Lambda Console showing the  raw `body` endraw  results of  raw `1A2B3C4D5E6F` endraw  which is resolved from SSM Parameter Store.

Thank You 💞

Let me know if you find Crypteia useful or have any questions.

Top comments (0)