Blessed are the Geeks, for they shall internet the earth

Managing AWS Parameter Store Secrets with Chef

by Joe Ritchey


Posted on Mon 18 March 2019 in workflows



Working with Chef for the past few year, encrypted data bags are the go to for secrets management. I have found the need where sometimes I can't just run chef-client to get to secrets. This is where AWS system manager parameter store comes into play. I can assign permissions in a IAM Role to be able to decrypt the SecretString from parameter store to get our secrets. The code to get encrypted data bag secrets into parameter store is pretty easy thanks to the AWS cookbook https://github.com/chef-cookbooks/aws. Data Bag show in JSON format:

{ 
  "id": "awesome_app", 
  "db_name": "myawesome_db", 
  "db_hostname": "example-db.example.net" 
}

I'm organizing my data bag in Chef to make it easier to sync to Parameter Store. I'm following the guide from AWS on Organizing Parameters into Hierarchies. https://docs.aws.amazon.com/systems-manager/latest/userguide/sysman-paramstore-su-organize.html I'm going to keep my hierarchy simple for this case. I'm going to use /application_name/key. Something to keep in mind, if a user or role has access to a path, like /application_name then the role can access all levels of that path. A role that has access to /application_name, will then inherit permissions to /application_name/foo and /application_name/bar and so forth. For me starting the hierarchy with the application name made more sense then say the environment name. We have to tell Chef how to talk to AWS. Following the instruction on setting up the permission to AWS for the Chef recipe was pretty straight forward. https://github.com/chef-cookbooks/aws#aws_ssm_parameter_store. I am going to chose to run this recipe from inside AWS on a EC2 instance. I apply a IAM role on the EC2 instance with permissions to use the KMS Key and permissions to update SSM parameters. In my chef recipe I decrypt the data bag for this app into a hash I call secrets. I can then loop through each item in this hash as a key, value. I'm setting the option overwrite to true, because in this case I want Chef to still be my source of truth for the secrets. The key_id is optional. If you don't include a key_id the aws_ssm_parameter_store resource will use the default key_id for your account. You will need to make sure the IAM role you are using has access to the key you want to encrypt the parameters with. sensitive true Is a built in Chef property for resources, it ensures that sensitive resource data is not logged by the chef-client.

secrets = Chef::EncryptedDataBagItem.load(bag, app_name)
secrets.each do |key, value| 
  aws_ssm_parameter_store "#{app_name} #{key.upcase}" do 
    path "/#{app_name}/#{key.upcase}" 
    type "SecureString" 
    action :create 
    sensitive true 
    key_id key_id 
    value value 
    overwrite true 
  end
end

That is it for now, next I will be about a couple of ways to use encrypted system parameters on EC2 instances.