Added chef-vault as option to store secrets

*Added gem chef-vault to gemfile
*Added method to decrypt chef-vault items
*Added case for ['openstack']['databag_type'] = 'vault'
*Added version for ['openstack']['vault_gem_version'] = '~> 2.3'
*Moved ::Chef.log.warn for developer_mode from method 'secret' to private method
'dev_secret' to refactore and shrink the method 'secret'
*Added link to opscode chef-vault documentation

Change-Id: Icda0e288bbb920498aba856fefaf04c0f1852787
This commit is contained in:
Jan Klare 2014-09-19 17:08:14 +02:00
parent 0655583c91
commit 794cc3d461
7 changed files with 68 additions and 15 deletions

View File

@ -10,3 +10,4 @@ gem 'foodcritic', '~> 4.0'
gem 'strainer'
gem 'rubocop', '~> 0.18.1'
gem 'rake', '~> 10.0'
gem 'chef-vault', '~> 2.3'

View File

@ -102,7 +102,7 @@ the entries to `/etc/sysctl.d/60-openstack.conf`.
Data Bags
=========
This cookbook containes Libraries to work with passwords and secrets in databags. Databags can be unencrypted ( for dev ) or encrypted ( for prod ).
This cookbook containes Libraries to work with passwords and secrets in databags. Databags can be unencrypted ( for dev ) or encrypted ( for prod ). In addition to traditionally encrypted data bags they can also be created as chef-vault items. To read more about chef-vault and how to use it, go to https://docs.getchef.com/chef_vault.html.
Documentation for Attributes for selecting databag format can be found in the attributes section of this cookbook.

View File

@ -45,11 +45,15 @@ default['openstack']['developer_mode'] = false
default['openstack']['use_databags'] = true
# Set databag type
# acceptable values 'encrypted', 'standard'
# acceptable values 'encrypted', 'standard', 'vault'
# Set this to 'standard' in order to use regular databags.
# this is not recommended for anything other than dev/CI
# type environments. Storing real secrets in plaintext = craycray.
# In addition to the encrypted data_bags which are an included
# feature of the official chef project, you can use 'vault' to
# encrypt your secrets with the method provided in the chef-vault gem.
default['openstack']['databag_type'] = 'encrypted'
default['openstack']['vault_gem_version'] = '~> 2.3'
# Default attributes when not using data bags (use_databags = false)
%w{block-storage object-storage compute database dashboard image identity

View File

@ -47,24 +47,23 @@ module ::Openstack # rubocop:disable Documentation
# nova_password = secret 'passwords', 'nova'
#
# The nova_password will == 'nova_password'
def secret(bag_name, index)
if node['openstack']['developer_mode']
::Chef::Log.warn(
"Developer mode for reading passwords is DEPRECATED and will "\
"be removed. Please use attributes (and the get_password method) "\
"instead.")
return (node['openstack']['secret'][index] || index)
end
dev_secret(index)
else
case node['openstack']['databag_type']
when 'encrypted'
encrypted_secret(bag_name, index)
when 'standard'
standard_secret(bag_name, index)
when 'vault' # chef-vault, by convention use "vault_<bag_name>" as bag_name
vault_secret('vault_' + bag_name, index)
else
::Chef::Log.error("Unsupported value for node['openstack']['databag_type']")
end
end
end
def encrypted_secret(bag_name, index)
key_path = node['openstack']['secret']['key_path']
@ -78,6 +77,16 @@ module ::Openstack # rubocop:disable Documentation
::Chef::DataBagItem.load(bag_name, index)[index]
end
def vault_secret(bag_name, index)
begin
require 'chef-vault'
rescue LoadError
Chef::Log.warn("Missing gem 'chef-vault'")
end
::Chef::Log.info "Loading vault secret #{index} from #{bag_name}"
::ChefVault::Item.load(bag_name, index)[index]
end
# Ease-of-use/standarization routine that returns a secret from the
# attribute-specified openstack secrets databag.
def get_secret(key)
@ -115,4 +124,14 @@ module ::Openstack # rubocop:disable Documentation
node['openstack']['secret'][key][type]
end
end
private
def dev_secret(index)
::Chef::Log.warn(
'Developer mode for reading passwords is DEPRECATED and will '\
'be removed. Please use attributes (and the get_password method) '\
'instead.')
(node['openstack']['secret'][index] || index)
end
end

View File

@ -103,3 +103,9 @@ when 'suse'
not_if { Mixlib::ShellOut.new('zypper repos --export -').run_command.stdout.include? repo_uri }
end
end
if node['openstack']['databag_type'] == 'vault'
chef_gem 'chef-vault' do
version node['openstack']['vault_gem_version']
end
end

View File

@ -30,5 +30,16 @@ describe 'openstack-common::default' do
uri: 'http://ubuntu-cloud.archive.canonical.com/ubuntu',
components: ['precise-updates/juno', 'main'])
end
it 'does not install the gem chef-vault by default' do
expect(chef_run).to_not install_chef_gem('chef-vault')
end
it 'installs the gem chef-vault if databag_type is vault' do
node.set['openstack']['databag_type'] = 'vault'
expect(chef_run).to install_chef_gem('chef-vault')
.with(version: '~> 2.3')
end
end
end

View File

@ -1,6 +1,7 @@
# encoding: UTF-8
require_relative 'spec_helper'
require ::File.join ::File.dirname(__FILE__), '..', 'libraries', 'passwords'
require 'chef-vault'
describe 'openstack-common::default' do
describe 'Passwords' do
@ -21,6 +22,17 @@ describe 'openstack-common::default' do
end
end
context 'using chef-vault' do
before do
node.set['openstack']['databag_type'] = 'vault'
end
it 'returns the data from a chef vault item' do
allow(ChefVault::Item).to receive(:load).with('vault_passwords', 'nova')
.and_return('nova' => 'novapassword')
expect(subject.secret('passwords', 'nova')).to eq('novapassword')
end
end
describe '#get_secret' do
it 'returns databag value' do
value = { 'nova' => 'this' }