Secrets are values you don’t want to be exposed publicly, such as API credentials or private keys.
In Laravel, these are typically values added to your .env
file. Sometimes they are private keys, perhaps generated for Laravel Passport, or downloaded for a GitHub app.
How you manage these secrets depends a lot on your deployment process. Forge allows you to load and edit the .env
file directly from the server. For more custom hosting solutions, you might save the .env
file in an S3 bucket, and download them during deployments.
A more secure solution (but still easy to use!) for managing secrets is AWS Parameter Store.
There is also an AWS service appropriately named Secrets Manager.
Secrets Manager has a lot more features, but you may not necessarily need or want them for this use case. It’s also more expensive. Parameter Store pricing is here. Secrets Manager pricing is here.
Using Parameter Store
Parameter store is a key-value store. It’s part of the larger AWS Systems Manager (SSM) service.
It’s got a bunch of features! We’ll cover what we need to manage secrets for Laravel apps, including:
Storing Encrypted Values
The following are the types of values you can store:
We’ll be using SecureString
, which is appropriate for storing secrets. Using this type will encrypt the parameter value. Values requiring encryption use the KMS service (Key Management Service) to provide a the key pair used for encryption.
You can create and manage your own keys within KMS, or you can use the default key, which is managed for you.
Creating your own key gives you more fine-grained control over who has access to data encrypted with the key. KMS is used EVERYTHING in AWS where things are encrypted – such as encrypted EBS drives, Parameter Store, and Secrets Manager.
I’m using the default KMS key in this example. Whether or not you should depends on your team size and who should be able to access these secrets within your organization.
Storing Large Values
Parameters are priced on the number of parameters and how often you access them via API calls. There are two tiers – “standard” and “advanced”.
Standard tiers are limited to 10,000 parameters, each no larger than 4 KB. These parameters are free (altho there’s still a charge for API usage).
Advanced parameters are limitd to 100,000 parameters, but have a limit of 8 KB along with extra security features. Each parameter has a cost per month.
Since we’ll be saving our entire .env
file into a parameter, it’s possible to go over the 4 KB limit. You may then need to use an Advanced Parameter or save individual secrets (key/values) into separate parameters.
Create a Parameter
To store a secret into Parameter Store, we’ll use the AWS CLI command .
Here we store the entire .env
file:
There’s a few things to note:
This will encrypt and store our secret into Parameter Store!
Generating Your .env File
I like to grab a fresh copy of the secrets (rebuilding the .env
file) on every deployment.
If you’d like to see how to create a fully automated, auto-scaled infrastructure on AWS, checkout the Simple Auto Scaling course on CloudCasts! Within it, we use Parameter Store during deployments to retrieve secrets.
If your secrets change dynamically (outside of deployments), you may need something more dynamic. In any case, one thing I would avoid is saving parameters into a “build artifact” (e.g. a .zip
archive of your application). If these build artifacts are stored somewhere publicly (for example, an S3 bucket with pulic access enabled), you can leak important secrets.
To build a new .env
file (perhaps during a deployment), we can use the command:
Things to note:
The --output
and --query
flags are available on all AWS CLI commands. You can find more info on those flags, and other tricks, here.
Handling large .env Files
If you have a large .env
file and have separated individual secrets into their own parameters, you may want to append to your .env
file rather than overwrite it.
For example, perhaps your base .env
file is in one parameter, but then a few longer secrets are in others. You can do the following:
Nothing fancy there! Just keep appending to the .env file for each secret.
IAM Permissions
The IAM User or Role used to call get-parameter
can be locked down using a variety of methods. Using the hierarchical name (e.g. /cloudcasts/staging/env
) helps us lock down secrets related to specific apps and environments.
For example, I may have an IAM Role for automations related to deploying the cloudcasts
app within the staging
environment. I can set the Role’s IAM Policy like so:
So, within us-east-2
, on account ID 012345678910
, this Role with the above IAM Policy can run GetParameter
on parameters that start with /cloudcasts/staging
(note the use of the wildcard).
This content was originally published here.