allow for attribute storage of secrets as an alternative
In addition to storing secrets in data bags (the default) we would like to be able to store them in attributes. This commit doesn't change the existing passwords API, get_password will now read from attributes when the node['openstack']['use_databags'] attribute is falsy. This commit deprecates the development_mode which was only used as a hack for getting passwords easier without data bags. The attribute storage of passwords should now be sufficient for all those use cases. Increased rubocop's methodlength maximum to 15 because there are some temporary deprecation warnings which add up, but should go away soon. Change-Id: I1f23878dd3fa83fb40f7b4b56960d57a7b9b89cc
This commit is contained in:
parent
17cee2d238
commit
dbe0bd6818
@ -22,3 +22,6 @@ LineLength:
|
|||||||
|
|
||||||
WordArray:
|
WordArray:
|
||||||
MinSize: 3
|
MinSize: 3
|
||||||
|
|
||||||
|
MethodLength:
|
||||||
|
Max: 15
|
@ -2,6 +2,9 @@
|
|||||||
|
|
||||||
This file is used to list changes made in each version of cookbook-openstack-common.
|
This file is used to list changes made in each version of cookbook-openstack-common.
|
||||||
|
|
||||||
|
## 9.6.0
|
||||||
|
* Add an option to store passwords in attributes instead of data bags. Deprecates the get_secret method and the development_mode.
|
||||||
|
|
||||||
## 9.5.2
|
## 9.5.2
|
||||||
* Adds new python_packages attributes for database client packages
|
* Adds new python_packages attributes for database client packages
|
||||||
|
|
||||||
|
@ -34,8 +34,24 @@ default['openstack']['common']['custom_template_banner'] = '
|
|||||||
# pass = secret "passwords", "nova"
|
# pass = secret "passwords", "nova"
|
||||||
#
|
#
|
||||||
# The value of pass will be "nova"
|
# The value of pass will be "nova"
|
||||||
|
#
|
||||||
|
# This attribute is now DEPRECATED and will be removed. Use the default
|
||||||
|
# attributes below instead.
|
||||||
default['openstack']['developer_mode'] = false
|
default['openstack']['developer_mode'] = false
|
||||||
|
|
||||||
|
# Use data bags for storing passwords
|
||||||
|
# Set this to false in order to get the passwords from attributes like:
|
||||||
|
# node['openstack']['secret'][key][type]
|
||||||
|
default['openstack']['use_databags'] = true
|
||||||
|
|
||||||
|
# Default attributes when not using data bags (use_databags = false)
|
||||||
|
%w{block-storage object-storage compute database dashboard image identity
|
||||||
|
telemetry network object-storage orchestration}.each do |service|
|
||||||
|
%w{user service db token}.each do |type|
|
||||||
|
default['openstack']['secret'][service][type] = "#{service}-#{type}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# The type of token signing to use (uuid or pki)
|
# The type of token signing to use (uuid or pki)
|
||||||
default['openstack']['auth']['strategy'] = 'pki'
|
default['openstack']['auth']['strategy'] = 'pki'
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
# library:: passwords
|
# library:: passwords
|
||||||
#
|
#
|
||||||
# Copyright 2012-2013, AT&T Services, Inc.
|
# Copyright 2012-2013, AT&T Services, Inc.
|
||||||
|
# Copyright 2014, SUSE Linux, GmbH.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# you may not use this file except in compliance with the License.
|
# you may not use this file except in compliance with the License.
|
||||||
@ -47,7 +48,14 @@ module ::Openstack # rubocop:disable Documentation
|
|||||||
#
|
#
|
||||||
# The nova_password will == 'nova_password'
|
# The nova_password will == 'nova_password'
|
||||||
def secret(bag_name, index)
|
def secret(bag_name, index)
|
||||||
return (node['openstack']['secret'][index] || index) if node['openstack']['developer_mode']
|
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
|
||||||
key_path = node['openstack']['secret']['key_path']
|
key_path = node['openstack']['secret']['key_path']
|
||||||
::Chef::Log.info "Loading encrypted databag #{bag_name}.#{index} using key at #{key_path}"
|
::Chef::Log.info "Loading encrypted databag #{bag_name}.#{index} using key at #{key_path}"
|
||||||
secret = ::Chef::EncryptedDataBagItem.load_secret key_path
|
secret = ::Chef::EncryptedDataBagItem.load_secret key_path
|
||||||
@ -57,17 +65,38 @@ module ::Openstack # rubocop:disable Documentation
|
|||||||
# 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)
|
||||||
secret node['openstack']['secret']['secrets_data_bag'], key
|
::Chef::Log.warn(
|
||||||
|
"The get_secret method is DEPRECATED. "\
|
||||||
|
"Use get_password(key, 'token') instead")
|
||||||
|
|
||||||
|
if node['openstack']['use_databags']
|
||||||
|
secret node['openstack']['secret']['secrets_data_bag'], key
|
||||||
|
else
|
||||||
|
node['openstack']['secret'][key]['token']
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Ease-of-use/standarization routine that returns a service/database/user
|
# Return a password using either data bags or attributes for
|
||||||
# password for a named OpenStack service/database/user. Accepts 'user',
|
# storage. The storage mechanism used is determined by the
|
||||||
# 'service' or 'db' as the type.
|
# node['openstack']['use_databags'] attribute.
|
||||||
|
# @param [String] type of password, one of 'user', 'service', 'db' or 'token'
|
||||||
|
# @param [String] the identifier of the password (usually the
|
||||||
|
# component name, but can also be a token name
|
||||||
|
# e.g. openstack_identity_bootstrap_token
|
||||||
def get_password(type, key)
|
def get_password(type, key)
|
||||||
if ['db', 'user', 'service'].include?(type)
|
unless %w{db user service token}.include?(type)
|
||||||
secret node['openstack']['secret']["#{type}_passwords_data_bag"], key
|
|
||||||
else
|
|
||||||
::Chef::Log.error("Unsupported type for get_password: #{type}")
|
::Chef::Log.error("Unsupported type for get_password: #{type}")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if node['openstack']['use_databags']
|
||||||
|
if type == 'token'
|
||||||
|
secret node['openstack']['secret']['secrets_data_bag'], key
|
||||||
|
else
|
||||||
|
secret node['openstack']['secret']["#{type}_passwords_data_bag"], key
|
||||||
|
end
|
||||||
|
else
|
||||||
|
node['openstack']['secret'][key][type]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -4,7 +4,7 @@ maintainer_email 'cookbooks@lists.tfoundry.com'
|
|||||||
license 'Apache 2.0'
|
license 'Apache 2.0'
|
||||||
description 'Common OpenStack attributes, libraries and recipes.'
|
description 'Common OpenStack attributes, libraries and recipes.'
|
||||||
long_description IO.read(File.join(File.dirname(__FILE__), 'README.md'))
|
long_description IO.read(File.join(File.dirname(__FILE__), 'README.md'))
|
||||||
version '9.5.2'
|
version '9.6.0'
|
||||||
|
|
||||||
recipe 'openstack-common', 'Installs/Configures common recipes'
|
recipe 'openstack-common', 'Installs/Configures common recipes'
|
||||||
recipe 'openstack-common::set_endpoints_by_interface', 'Set endpoints by interface'
|
recipe 'openstack-common::set_endpoints_by_interface', 'Set endpoints by interface'
|
||||||
|
@ -11,39 +11,66 @@ describe 'openstack-common::default' do
|
|||||||
|
|
||||||
include_context 'library-stubs'
|
include_context 'library-stubs'
|
||||||
|
|
||||||
describe '#secret' do
|
context 'stored in data bags by default' do
|
||||||
it 'returns databag' do
|
describe '#secret' do
|
||||||
value = { 'nova' => 'this' }
|
it 'returns databag' do
|
||||||
::Chef::EncryptedDataBagItem.stub(:load_secret).with('/etc/chef/openstack_data_bag_secret').and_return('secret')
|
|
||||||
::Chef::EncryptedDataBagItem.stub(:load).with('passwords', 'nova', 'secret').and_return(value)
|
|
||||||
expect(subject.secret('passwords', 'nova')).to eq('this')
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
describe '#get_secret' do
|
|
||||||
it 'returns databag' do
|
|
||||||
value = { 'nova' => 'this' }
|
|
||||||
::Chef::EncryptedDataBagItem.stub(:load_secret).with('/etc/chef/openstack_data_bag_secret').and_return('secret')
|
|
||||||
::Chef::EncryptedDataBagItem.stub(:load).with('secrets', 'nova', 'secret').and_return(value)
|
|
||||||
expect(subject.get_secret('nova')).to eq('this')
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'returns secret from an alternate databag when secrets_data_bag set' do
|
|
||||||
node.set['openstack']['secret']['secrets_data_bag'] = 'myothersecrets'
|
|
||||||
value = { 'nova' => 'this' }
|
|
||||||
::Chef::EncryptedDataBagItem.stub(:load_secret).with('/etc/chef/openstack_data_bag_secret').and_return('secret')
|
|
||||||
::Chef::EncryptedDataBagItem.stub(:load).with('myothersecrets', 'nova', 'secret').and_return(value)
|
|
||||||
expect(subject.get_secret('nova')).to eq('this')
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
describe '#get_password' do
|
|
||||||
['service', 'db', 'user'].each do |type|
|
|
||||||
it "returns databag for #{type}" do
|
|
||||||
value = { 'nova' => 'this' }
|
value = { 'nova' => 'this' }
|
||||||
::Chef::EncryptedDataBagItem.stub(:load_secret).with('/etc/chef/openstack_data_bag_secret').and_return('secret')
|
::Chef::EncryptedDataBagItem.stub(:load_secret).with('/etc/chef/openstack_data_bag_secret').and_return('secret')
|
||||||
::Chef::EncryptedDataBagItem.stub(:load).with("#{type}_passwords", 'nova', 'secret').and_return(value)
|
::Chef::EncryptedDataBagItem.stub(:load).with('passwords', 'nova', 'secret').and_return(value)
|
||||||
expect(subject.get_password(type, 'nova')).to eq('this')
|
expect(subject.secret('passwords', 'nova')).to eq('this')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#get_secret' do
|
||||||
|
it 'returns databag value' do
|
||||||
|
value = { 'nova' => 'this' }
|
||||||
|
::Chef::EncryptedDataBagItem.stub(:load_secret).with('/etc/chef/openstack_data_bag_secret').and_return('secret')
|
||||||
|
::Chef::EncryptedDataBagItem.stub(:load).with('secrets', 'nova', 'secret').and_return(value)
|
||||||
|
expect(subject.get_secret('nova')).to eq('this')
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns secret from an alternate databag when secrets_data_bag set' do
|
||||||
|
node.set['openstack']['secret']['secrets_data_bag'] = 'myothersecrets'
|
||||||
|
value = { 'nova' => 'this' }
|
||||||
|
::Chef::EncryptedDataBagItem.stub(:load_secret).with('/etc/chef/openstack_data_bag_secret').and_return('secret')
|
||||||
|
::Chef::EncryptedDataBagItem.stub(:load).with('myothersecrets', 'nova', 'secret').and_return(value)
|
||||||
|
expect(subject.get_secret('nova')).to eq('this')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#get_password' do
|
||||||
|
['service', 'db', 'user'].each do |type|
|
||||||
|
it "returns databag value for #{type}" do
|
||||||
|
value = { 'nova' => 'this' }
|
||||||
|
::Chef::EncryptedDataBagItem.stub(:load_secret).with('/etc/chef/openstack_data_bag_secret').and_return('secret')
|
||||||
|
::Chef::EncryptedDataBagItem.stub(:load).with("#{type}_passwords", 'nova', 'secret').and_return(value)
|
||||||
|
expect(subject.get_password(type, 'nova')).to eq('this')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns nil for an invalid type' do
|
||||||
|
expect(subject.get_password('invalid_type', 'nova')).to be_nil
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns tokens from the secrets_data_bag' do
|
||||||
|
bag_content = { 'nova' => 'mysecret' }
|
||||||
|
::Chef::EncryptedDataBagItem.stub(:load_secret).with(
|
||||||
|
'/etc/chef/openstack_data_bag_secret').and_return('secret')
|
||||||
|
::Chef::EncryptedDataBagItem.stub(:load).with(
|
||||||
|
'secrets', 'nova', 'secret').and_return(bag_content)
|
||||||
|
expect(subject.get_password('token', 'nova')).to eq('mysecret')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'stored in attributes as an alternative' do
|
||||||
|
before { node.set['openstack']['use_databags'] = false }
|
||||||
|
|
||||||
|
describe '#get_password' do
|
||||||
|
%w{service db user token}.each do |type|
|
||||||
|
it "returns the set attribute for #{type}" do
|
||||||
|
expect(subject.get_password(type, 'compute')).to eq("compute-#{type}")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
Loading…
Reference in New Issue
Block a user