Your serverless function has a secret... maybe it's a password for a remote API, a private key, or signing certificate. These secrets have to be stored somewhere, and in the old days that usually meant just a plaintext config file on your server. Sure, you could encrypt it, but then you have to put the key on the server, and you haven't gained anything except a bit of obfuscation. Or you could use more complex schemes, like Hiera-Eyaml, which is a small improvement, but you've really just moved the threat to a different part of your infrastructure.
Using AWS KMS (Key Management Service) with AWS Lambdas offers a significant reduction in attack surface area. You get HSM-like functionality, without the high cost (starting at $1/month). In this model, there are only three ways the secret can be accessed:
I believe (3) is important to acknowledge here - the risk doesn't go away, but is outsourced to an extremely mature, security-focused organization with a stellar track record and a lot at stake.
Here's a short example using the Serverless framework, and Node.js. Many other language and framework combinations are possible.
Here are the steps. Refer to the quickstart docs for Serverless, KMS, and aws-cli if any of these are unfamiliar.
aws kms encrypt --key-id 'arn:aws:kms...' --plaintext 'secret'
awsKmsKeyArn
property in your serverless.yml
filekms.decrypt()
to access the secret'use strict'; const aws = require('aws-sdk'); var kms = new aws.KMS(); exports.hello = (event, context, callback) => { kms.decrypt({CiphertextBlob: new Buffer(process.env.password, 'base64')}, (err, data) => { var password = data.Plaintext.toString('ascii'); /* * Do stuff with plaintext password */ callback(null, { statusCode: 200, body: JSON.stringify("hello"), headers: { 'Content-Type': 'application/json', }, }); }); };
service: example provider: name: aws region: us-west-2 functions: hello: handler: index.hello events: - http: path: hello method: get awsKmsKeyArn: 'arn:aws:kms:us-west-2:123456789:key/80abc534-be62-992a-7ba1-e3a44d4271ac' environment: # password value below is KMS ciphertext password: 'AQICAHiNrBUmBQhi496ozpFzP9BrHUALq+NAyE7Xsz6gRsiz0AGsJnI1cyYl57qLnxn1FDSkAAAAbTBrBgkqhkiG9w0BBwagXjBcAgEAMFcGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQM8TW0l6r7UEi1soz9AgEQgCp4Vy6sWq1W7SXXmeaz3jRL/X5ax4E2Uw3N0KGztPwv9kGK8O2Nk56tM4Q=' runtime: nodejs6.10