|
1 |
| -# vault-lambda-extension |
| 1 | +# vault-lambda-extension |
| 2 | + |
| 3 | +This repository contains the source code for Hashicorp's Vault AWS Lambda extension. |
| 4 | +The extension utilises the AWS Lambda Extensions API to read secrets from your |
| 5 | +Vault deployment and write the result to disk before the Lambda function itself |
| 6 | +starts to execute. To use it, include the following ARN as a layer in your |
| 7 | +Lambda function: |
| 8 | + |
| 9 | +```text |
| 10 | +TBD |
| 11 | +``` |
| 12 | + |
| 13 | +The extension authenticates with Vault using [AWS IAM auth][vault-aws-iam-auth], |
| 14 | +and writes the result as JSON to disk. It also writes a vault token to |
| 15 | +`/tmp/vault/token`. All configuration is supplied via environment variables. |
| 16 | + |
| 17 | +## Getting Started |
| 18 | + |
| 19 | +### Quickstart |
| 20 | + |
| 21 | +The [quick-start](./quick-start) directory has a fully worked example, for which |
| 22 | +you will need an AWS account and some comand line tools. Follow the readme in |
| 23 | +that directory if you'd like to try out the extension from scratch. **Please |
| 24 | +note it will create real infrastructure with an associated cost as per AWS' |
| 25 | +pricing.** |
| 26 | + |
| 27 | +### Adding the extension to your existing Lambda and Vault infrastructure |
| 28 | + |
| 29 | +Requirements: |
| 30 | + |
| 31 | +* ARN of the role your Lambda runs as |
| 32 | +* An instance of Vault accessible from AWS Lambda |
| 33 | +* An authenticated `vault` client |
| 34 | +* A secret in Vault that you want your Lambda to access, and a policy giving read access to it |
| 35 | + |
| 36 | +First, set up AWS IAM auth on Vault, and attach a policy to your ARN: |
| 37 | + |
| 38 | +```bash |
| 39 | +vault auth enable aws |
| 40 | +vault write -force auth/aws/config/client |
| 41 | +vault write auth/aws/role/vault-lambda-role \ |
| 42 | + auth_type=iam \ |
| 43 | + bound_iam_principal_arn="${YOUR_ARN}" \ |
| 44 | + policies="${YOUR_POLICY}" \ |
| 45 | + ttl=1h |
| 46 | +``` |
| 47 | + |
| 48 | +Add the extension to your Lambda layers using the console or [cli][lambda-add-layer-cli]: |
| 49 | + |
| 50 | +```text |
| 51 | +TBD |
| 52 | +``` |
| 53 | + |
| 54 | +Configure the extension using [Lambda environment variables][lambda-env-vars]: |
| 55 | + |
| 56 | +```bash |
| 57 | +VAULT_ADDR=http://vault.example.com:8200 # Your Vault address |
| 58 | +VAULT_AUTH_PROVIDER=aws # The AWS IAM auth mount point, i.e. the path segment after auth/ from above |
| 59 | +VAULT_AUTH_ROLE=vault-lambda-role # The Vault role to authenticate as. Must be configured for the ARN of your Lambda's role |
| 60 | +VAULT_SECRET_PATH=secret/lambda-app/token # The path to a secret in Vault. Can be static or dynamic. |
| 61 | + # Unless VAULT_SECRET_FILE is specified, JSON response will be written to /tmp/vault/secret.json |
| 62 | +``` |
| 63 | + |
| 64 | +If everything is correctly set up, your Lambda function can then read secret |
| 65 | +material from `/tmp/vault/secret.json`. The exact contents of the JSON object |
| 66 | +will depend on the secret read, but its schema is the [Secret struct][vault-api-secret-struct] |
| 67 | +from the Vault API module. |
| 68 | + |
| 69 | +## Configuration |
| 70 | + |
| 71 | +The extension is configured via [Lambda environment variables][lambda-env-vars]. |
| 72 | +Most of the [Vault CLI client's environment variables][vault-env-vars] are available, |
| 73 | +as well as some additional variables to configure auth, which secret(s) to read and |
| 74 | +where to write secrets. At least one valid secret to read must be specified. |
| 75 | + |
| 76 | +Environment variable | Description | Required | Example value |
| 77 | +------------------------|-------------|----------|-------------- |
| 78 | +`VAULT_ADDR` | Vault address to connect to | Yes | `https://x.x.x.x:8200` |
| 79 | +`VAULT_AUTH_PROVIDER` | Name of the configured AWS IAM auth route on Vault | Yes | `aws` |
| 80 | +`VAULT_AUTH_ROLE` | Vault role to authenticate as | Yes | `lambda-app` |
| 81 | +`VAULT_SECRET_PATH` | Secret path to read, written to `/tmp/vault/secret.json` unless `VAULT_SECRET_FILE` is specified | No | `database/creds/lambda-app` |
| 82 | +`VAULT_SECRET_FILE` | Path to write the JSON response for `VAULT_SECRET_PATH` | No | `/tmp/db.json` |
| 83 | +`VAULT_SECRET_PATH_FOO` | Additional secret path to read, where FOO can be any name, as long as a matching `VAULT_SECRET_FILE_FOO` is specified | No | `secret/lambda-app/token` |
| 84 | +`VAULT_SECRET_FILE_FOO` | Must exist for any correspondingly named `VAULT_SECRET_PATH_FOO`. Name has no further effect beyond matching to the correct path variable | No | `/tmp/token` |
| 85 | + |
| 86 | +The remaining environment variables are not required, and function exactly as |
| 87 | +described in the [Vault Commands (CLI)][vault-env-vars] documentation. However, |
| 88 | +note that `VAULT_CLIENT_TIMEOUT` cannot extend the timeout beyond the 10s |
| 89 | +timeout imposed by the Extensions API. |
| 90 | + |
| 91 | +Environment variable | Description | Required | Example value |
| 92 | +------------------------|-------------|----------|-------------- |
| 93 | +`VAULT_CACERT` | Path to a PEM-encoded CA certificate _file_ on the local disk | No | `/tmp/ca.crt` |
| 94 | +`VAULT_CAPATH` | Path to a _directory_ of PEM-encoded CA certificate files on the local disk | No | `/tmp/certs` |
| 95 | +`VAULT_CLIENT_CERT` | Path to a PEM-encoded client certificate on the local disk | No | `/tmp/client.crt` |
| 96 | +`VAULT_CLIENT_KEY` | Path to an unencrypted, PEM-encoded private key on disk which corresponds to the matching client certificate | No | `/tmp/client.key` |
| 97 | +`VAULT_CLIENT_TIMEOUT` | Timeout for Vault requests. Default value is 60s. **Any value over 10s will exceed the Extensions API timeout and therefore have no effect** | No | `5s` |
| 98 | +`VAULT_MAX_RETRIES` | Maximum number of retries on `5xx` error codes. Defaults to 2 | No | `2` |
| 99 | +`VAULT_SKIP_VERIFY` | Do not verify Vault's presented certificate before communicating with it. Setting this variable is not recommended and voids Vault's [security model][vault-security-model] | No | `true` |
| 100 | +`VAULT_TLS_SERVER_NAME` | Name to use as the SNI host when connecting via TLS | No | `vault.example.com` |
| 101 | +`VAULT_RATE_LIMIT` | Only applies to a single invocation of the extension. See [Vault Commands (CLI)][vault-env-vars] documentation for details | No | `10` |
| 102 | +`VAULT_NAMESPACE` | The namespace to use for the command | No | `education` |
| 103 | +`VAULT_SRV_LOOKUP` | The Vault client will lookup DNS SRV records for the host. See [Vault Commands (CLI)][vault-env-vars] documentation for details | No | `true` |
| 104 | +`VAULT_MFA` | MFA credentials. See [Vault Commands (CLI)][vault-env-vars] documentation for details | No | `true` |
| 105 | + |
| 106 | +## Limitations |
| 107 | + |
| 108 | +For this early release, the extension does not support automatic secret renewal. |
| 109 | +This means once a secret is written to disk, it will not be refreshed once it |
| 110 | +expires. This may cause problems if you use [provisioned concurrency][lambda-provisioned-concurrency] |
| 111 | +or if your Lambda is invoked often enough that execution contexts live beyond |
| 112 | +the lifetime of the secret. |
| 113 | + |
| 114 | +[vault-aws-iam-auth]: https://www.vaultproject.io/docs/auth/aws |
| 115 | +[vault-env-vars]: https://www.vaultproject.io/docs/commands#environment-variables |
| 116 | +[vault-api-secret-struct]: https://github.com/hashicorp/vault/blob/api/v1.0.4/api/secret.go#L15 |
| 117 | +[vault-security-model]: https://www.vaultproject.io/docs/internals/security |
| 118 | +[lambda-env-vars]: https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html |
| 119 | +[lambda-add-layer-cli]: https://docs.aws.amazon.com/lambda/latest/dg/configuration-layers.html#configuration-layers-using |
| 120 | +[lambda-provisioned-concurrency]: https://docs.aws.amazon.com/lambda/latest/dg/configuration-concurrency.html#configuration-concurrency-provisioned |
0 commit comments