6.2 KiB
layout | title | category | tags | summary |
---|---|---|---|---|
post | Workflow - Using Chef Vaults in Workflow | chef_automate_1 | [chef workflow] | Secrets are hard. Shared key encryption is bad. Use Chef Vault. |
What is Chef Vault
Chef Vault is a solution for securing data used during a Chef Client run. Chef Vault solves the shared key encryption problem present in encrypted data bags.
Currently, encrypted data bags use shared key encryption; this means that both the key to encrypt and decrypt the data are the same. This leads to security issues due to the fact that this single key must be shared with anyone who wants to use the data.
Chef Vault solves the shared key encryption problem by using the already present trust relationship between Chef clients and the Chef Server. By using each client's public key to encrypt the data and allowing the clients to decrypt the data using their secret private key at no point do sensitive keys need to be transmitted.
For more info on how Chef Vaults work see here.
Using Chef Vaults in Chef Automate Workflow
The method demonstrated in this post uses a data bag called workflow-vaults
to hold all of the Chef Vaults used by Workflow projects.
The vaults inside of workflow-vaults
are created with a specific naming and scoping scheme to enable the following:
- Using the
*-slug
helper methods in delivery-sugar to load vaults - Sharing data within the Enterprise, Organization, and Project
- Reducing variable duplication through merging down to a single Ruby hash
Naming Scheme and Scope
Vaults should be named and data be scoped as follows:
Vault Name |
Enterprise Scope |
Organization Scope |
Project Scope |
---|---|---|---|
#{ent_name} |
Y | Y | Y |
#{ent_name}-#{org_name} |
Y | Y | |
#{ent_name}-#{org_name}-#{project_name} |
Y |
Creating the Chef Vaults
There are a few options for creating Chef Vaults. You can set your EDITOR
environment variable and type the JSON at creation, pass the JSON in as a string, or create JSON files on disk and reference them.
I personally prefer creating the files on disk and referencing them. To use this method do the following:
Create your directory structure
workflow-vaults
├── my_ent.json
├── my_ent-my_org.json
├── my_ent-my_org-project1.json
└── my_ent-my_org-project2.json
Populate your JSON files (EXAMPLE)
{
"id":"my_ent-my_org-project1",
"secret_data": "something secret",
"other_data": "something else"
}
NOTE: Keys with the same name in multiple vaults will be merged in such a way that Project level data will overwrite Organization data and Organization data will overwrite Enterprise data
Create your vaults using knife vault create
(EXAMPLE)
knife vault create \
workflow-vaults \
my_ent-my_org-project1 \
-J '/path/to/my_ent-my_org-project1.json' \
-A 'delivery,jerry' \
-S 'tags:delivery-job-runner' \
-M client
Argument | Purpose |
---|---|
workflow-vaults |
Selects the data bag that will contain our vaults |
my_ent-my_org-my_project |
Sets the Chef Vault name in workflow-vaults |
-A 'delivery,jerry' |
Comma separated list of Admins to grant access |
-S 'tags:delivery-job-runner' |
SOLR search that gives access to all Workflow runners |
-M client |
Enables creating vaults on Chef Server instead of locally |
NOTE: After creating your vaults it is recommended that you delete the JSON files from disk
Using Chef Vaults in your build_cookbook
There are two methods of accessing your Chef Vaults in your build_cookbook.
You can add the code snippet below or use the built-in get_workflow_vault_data
method included when you generate a cookbook with ChefDK.
Using the built-in method
By default, when you generate a cookbook with the ChefDK via chef generate cookbook
it creates a .delivery/build_cookbook
. This default build_cookbook exposes the get_workflow_vault_data
method to you.
To use this method just assign the output to a Ruby Hash:
vault_data = get_workflow_vault_data
Using a code snippet.
Note: This is functionally equivalent to using the
get_workflow_vault_data
method above
From any recipe in your build_cookbook you can now use the below code to access your vault data:
# Load the `chef-vault` gem
require 'chef-vault'
# Load a Chef config that has rights to view workflow-vaults
Chef::Config.from_file(automate_knife_rb)
# Compile list of Vault items using `delivery-sugar` helper methods
vault_items = [
workflow_change_enterprise,
workflow_organization_slug,
workflow_project_slug
]
# Populate a list of hashes with empty hashes for non-existent vaults
vault_data_list = []
vault_items.each do |item|
vault_data_list.push(
begin
ChefVault::Item.load('workflow-vaults', item)
rescue ChefVault::Exceptions::KeysNotFound
{}
end
)
end
# Merge each of the hashes above into a single hash
vault_data = vault_data_list.inject(&:merge)
# Raise an error if no data is found
if vault_data.empty?
raise 'No Chef Vaults found in \'workflow-vaults\' that match naming standard'
end
NOTE: The above code only works if you added
-A 'delivery'
when creating your Chef Vaults