Keeping credentials secure in a serverless applications
In my previous post, I provided an overview of how to create a serverless web application that uses OCLC APIs. In this post, I’ll discuss keeping credentials for this serverless application secure. You can see the full application code in the Developer Network GitHub repository.
Securely storing API credentials in AWS
The biggest challenge with deploying a serverless application that uses APIs is keeping credentials secure within the infrastructure. Typically, I like to store my configuration in a yml file. I use the following code to load the yml data so I can use it in my application:
Yaml::parse(‘config.yml’)
However, if I stored my credentials this way and then uploaded this file to Lambda, then it would be readily accessible to anyone who might gain access to my account. Lambda offers environment variables that could be used to store API credentials, but if one reads the documentation at any length, these values are shown in the clear in various logs and throughout the AWS console.
Therefore, I needed a way to secure my credentials within the Lambda infrastructure. My solution is to use AWS KMS (Key Management System) to create a key and then to use the key to encrypt my configuration file, which is uploaded to Lambda. I can then add code to my application to decrypt the configuration file.
Creating a KMS key
In order to encrypt and decrypt the configuration file, you’ll need to create a KMS key. This can be done via the AWS console.
Encrypting the config file
The next step to encrypting the configuration file is to install the AWS command line tools. These will allow you to interact with AWS from your command prompt. You’ll need to use the following command to encrypt the yml file that contains your configuration:
aws kms encrypt --key-id {kms_key_id} --plaintext fileb://prod_config.yml --output text --query CiphertextBlob --output text | base64 -D > prod_config_encrypted.txt
Make sure to exclude your encrypted config file from version control by adding it to your .gitignore file.
Decrypting and using the file
Now that I have an encrypted yml file with my configuration information, my application needs code to decrypt the file before loading the data.
const kms = new aws.KMS({'region': 'us-east-1'}); let environment = 'prod'; const params = { CiphertextBlob: fs.readFileSync(environment + "_config_encrypted.txt") } exports.handler = async (event) => { try { let data = await kms.decrypt(params).promise(); let config = yaml.load(data['Plaintext'].toString()); //the core application code } catch (Error){ console.log(Error, Error.stack); return Error; } }
Once I updated the code, I wanted to make sure that my original configuration file was not uploaded during the deploy. To do this, I needed to exclude my original config file via the serverless.yml file.
package: exclude: - config.yml
These two pieces of my application allow me to deploy it to Lambda and keep my API credentials secure. If the application needed other credentials, such as database username/password, they could be secured using the same techniques.
Using KMS keys for encryption is just one option to keeping application credentials secure in Lambda. Another option is AWS Parameter Store. This allows you to store your credentials securely in Amazon's infrastructure and either reference them in via your serverless.yml file or call them directly from a Lambda. For more details check out this blog post. A third option is to use the serverless framework's serverless-secrets-plugin. A good example of doing this in available in the serverless framework examples repository. It is important to recognize that each of these options offers different levels of security and scaleability. As an application developer, you should review and understand each before choosing the appropriate one for your project.
Next steps
In this post, we’ve looked at how to keep credentials secure in a serverless application. In our next post, we’ll talk about storing data in a serverless application.
-
Karen Coombs
Senior Product Analyst