Lambda Rust Extension for any Runtime to preload SSM Parameters as Secure Environment Variables!
Tags: serverless, rust, aws, security
Published: 2022-06-29 12:24:04

---
canonical_url: https://dev.to/aws-heroes/lambda-extension-for-any-runtime-to-preload-ssm-parameters-as-secure-environment-variables-342n
---

ℹ️ [Crypteia Hits v1.0.0 Miletstone!](https://github.com/customink/crypteia) 🎉 - 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](https://github.com/customink/crypteia) is a new super fast Lambda Extension written in Rust which turns your serverless environment variables from SSM Parameter Store paths like these...

```yaml
Environment:
  Variables:
    SECRET: x-crypteia-ssm:/myapp/SECRET
```

... 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
```

It works by using a shared object library via the `LD_PRELOAD` environment variable in coordination with our [Lambda Extension](https://docs.aws.amazon.com/lambda/latest/dg/runtimes-extensions-api.html) binary that loads all Parameter Store values within a few milliseconds of your function starting up.

## Installation

When building your own Lambda Containers, [download](https://github.com/customink/crypteia/releases) both the `crypteia` binary and `libcrypteia.so` shared object files that match your platform from our [Releases](https://github.com/customink/crypteia/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](https://www.gnu.org/software/libc/) is installed since this is used by [redhook](https://github.com/geofft/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](https://github.com/customink/crypteia/issues/5) which tracks this topic.

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

```dockerfile
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
```

#### Lambda Layer

Our Amazon Linux 2 files can be used within a [Lambda Layer](https://docs.aws.amazon.com/lambda/latest/dg/configuration-layers.html) 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:

```shell
aws configure
./amzn/setup
S3_BUCKET_NAME=my-bucket ./layer/deploy
```

## Usage

First, you will need your secret environment variables setup in [AWS Systems Manager Parameter Store](https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-parameter-store.html). These can be whatever [hierarchy](https://docs.aws.amazon.com/systems-manager/latest/userguide/sysman-paramstore-hierarchies.html) 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](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-getting-started.html) template that demonstrates all of Crypteia's features.

```yaml
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
```

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
```

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](#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 `LD_PRELOAD` to `/opt/lib/libcrypteia.so` and `SECRET` to `x-crypteia-ssm:/myapp/SECRET`.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k38z2bip4d7rb58a5fxv.png)

![Screenshot of Code source in the AWS Lambda Console showing the `body` results of `1A2B3C4D5E6F` which is resolved from SSM Parameter Store.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qma1xry8evggassqzp0e.png)
 
## Thank You 💞

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