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 'strainer'
gem 'rubocop', '~> 0.18.1' gem 'rubocop', '~> 0.18.1'
gem 'rake', '~> 10.0' 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 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. 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 default['openstack']['use_databags'] = true
# Set databag type # Set databag type
# acceptable values 'encrypted', 'standard' # acceptable values 'encrypted', 'standard', 'vault'
# Set this to 'standard' in order to use regular databags. # Set this to 'standard' in order to use regular databags.
# this is not recommended for anything other than dev/CI # this is not recommended for anything other than dev/CI
# type environments. Storing real secrets in plaintext = craycray. # 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']['databag_type'] = 'encrypted'
default['openstack']['vault_gem_version'] = '~> 2.3'
# Default attributes when not using data bags (use_databags = false) # Default attributes when not using data bags (use_databags = false)
%w{block-storage object-storage compute database dashboard image identity %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' # nova_password = secret 'passwords', 'nova'
# #
# The nova_password will == 'nova_password' # The nova_password will == 'nova_password'
def secret(bag_name, index) def secret(bag_name, index)
if node['openstack']['developer_mode'] if node['openstack']['developer_mode']
::Chef::Log.warn( dev_secret(index)
"Developer mode for reading passwords is DEPRECATED and will "\ else
"be removed. Please use attributes (and the get_password method) "\
"instead.")
return (node['openstack']['secret'][index] || index)
end
case node['openstack']['databag_type'] case node['openstack']['databag_type']
when 'encrypted' when 'encrypted'
encrypted_secret(bag_name, index) encrypted_secret(bag_name, index)
when 'standard' when 'standard'
standard_secret(bag_name, index) 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 else
::Chef::Log.error("Unsupported value for node['openstack']['databag_type']") ::Chef::Log.error("Unsupported value for node['openstack']['databag_type']")
end end
end end
end
def encrypted_secret(bag_name, index) def encrypted_secret(bag_name, index)
key_path = node['openstack']['secret']['key_path'] key_path = node['openstack']['secret']['key_path']
@ -78,6 +77,16 @@ module ::Openstack # rubocop:disable Documentation
::Chef::DataBagItem.load(bag_name, index)[index] ::Chef::DataBagItem.load(bag_name, index)[index]
end 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 # Ease-of-use/standarization routine that returns a secret from the
# attribute-specified openstack secrets databag. # attribute-specified openstack secrets databag.
def get_secret(key) def get_secret(key)
@ -115,4 +124,14 @@ module ::Openstack # rubocop:disable Documentation
node['openstack']['secret'][key][type] node['openstack']['secret'][key][type]
end end
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 end

View File

@ -103,3 +103,9 @@ when 'suse'
not_if { Mixlib::ShellOut.new('zypper repos --export -').run_command.stdout.include? repo_uri } not_if { Mixlib::ShellOut.new('zypper repos --export -').run_command.stdout.include? repo_uri }
end end
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', uri: 'http://ubuntu-cloud.archive.canonical.com/ubuntu',
components: ['precise-updates/juno', 'main']) components: ['precise-updates/juno', 'main'])
end 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
end end

View File

@ -1,6 +1,7 @@
# encoding: UTF-8 # encoding: UTF-8
require_relative 'spec_helper' require_relative 'spec_helper'
require ::File.join ::File.dirname(__FILE__), '..', 'libraries', 'passwords' require ::File.join ::File.dirname(__FILE__), '..', 'libraries', 'passwords'
require 'chef-vault'
describe 'openstack-common::default' do describe 'openstack-common::default' do
describe 'Passwords' do describe 'Passwords' do
@ -21,6 +22,17 @@ describe 'openstack-common::default' do
end end
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 describe '#get_secret' do
it 'returns databag value' do it 'returns databag value' do
value = { 'nova' => 'this' } value = { 'nova' => 'this' }