Skip to content

Instantly share code, notes, and snippets.

@nikgraf
Last active April 17, 2019 22:24
Show Gist options
  • Star 9 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nikgraf/ef25181cf5f2bf85e9dd94184ec5446a to your computer and use it in GitHub Desktop.
Save nikgraf/ef25181cf5f2bf85e9dd94184ec5446a to your computer and use it in GitHub Desktop.
Providing sensitive information to a Lambda

I’m struggling with providing sensitive information like a password or api key to a Lambda:

In the AWS docs it says: When you create or update Lambda functions that use environment variables, AWS Lambda encrypts them using the AWS Key Management Service.

But they also mention

Storing Sensitive Information

For sensitive information, such as database passwords, we recommend you use client-side encryption using
AWS Key Management Service and store the resulting values as Ciphertext in your environment variable.
You will need to include logic in your Lambda function code to decrypt these values.

So in the end the Lambda function needs a password/key to decrypt the Ciphertext. How do I safely provide the Lambda function with this password/key? How is this safer than just passing in the environment variable as plaintext and then Lambda storing it in KMS?

any ideas?

Resource: http://docs.aws.amazon.com/lambda/latest/dg/env_variables.html

@ryansb
Copy link

ryansb commented Nov 26, 2016

Using KMS to decrypt the ciphertext as part of your Lambda is safer for a couple reasons:

  1. The plaintext doesn't show up in the GetFunctionConfiguration API call. This is important, because people with "production" access don't need to be able to see the DB passwords in plaintext all the time. And you can't lock down that API call without totally crippling their ability to use Lambda.
  2. Your audit log shows use of the specific KMS key, so you can have different keys per stage or per "class" of secret. For example, one key for your external services API keys like TwitFacedIn, then a separate more locked-down key for things like payment secrets and other super-regulated stuff.
  3. Using KMS directly also means you can lock down that key differently than other env vars. That means that functions that don't do DB access also don't have the permissions to decrypt the DB password (even if it somehow gets into its environment).

All of these answers basically come down to "security is like a good parfait: more layers are good." KMS is good at controlling who (or what services) can access secrets, and it would be a major pain to reinvent that in Lambda (with env vars) so they're encouraging you to leverage that if you need it (or are required by $REGULATIONS).

@nikgraf
Copy link
Author

nikgraf commented Nov 26, 2016

just wow, thx so much for clarifying!

@benkehoe
Copy link

To add some extra info: You don't want to use KMS as the direct Encrypt/Decrypt API from Lambda, as you run the risk of throttling by the API, and it is slower. You want to use data keys. You use GenerateDataKey to create it, both the plaintext version of the key, and an version encrypted by KMS. You use the plaintext version to do encryption and decryption on your data, and you use the KMS-encrypted version to store it (outside KMS). So in your Lambda, on container start you retrieve the encrypted data key, use KMS.Decrypt to decrypt it, and then use it during the calls.

@dror-g
Copy link

dror-g commented Apr 17, 2019

Thanks Ryan, that's a very clear and concise explanation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment