From c85beff334d527245ca428e47e7411fcdb42937d Mon Sep 17 00:00:00 2001 From: Thiago da Silva Date: Mon, 4 Dec 2017 16:20:27 -0500 Subject: [PATCH] Adding barbican configuration to swift Adding barbican configuration to Swift will allow enabling data-at-rest encryption in Swift. Change-Id: I78c6003f5f599a422193dc47422ee607ce05c715 Signed-off-by: Thiago da Silva --- .../swift_keymaster_config/ini_setting.rb | 10 ++ lib/puppet/type/swift_keymaster_config.rb | 53 ++++++++++ manifests/keymaster.pp | 98 +++++++++++++++++++ manifests/proxy/encryption.pp | 27 +++++ manifests/proxy/kms_keymaster.pp | 24 +++++ spec/classes/swift_keymaster.rb | 32 ++++++ spec/classes/swift_proxy_encryption_spec.rb | 24 +++++ .../classes/swift_proxy_kms_keymaster_spec.rb | 24 +++++ .../ini_setting_spec.rb | 72 ++++++++++++++ spec/unit/type/swift_keymaster_config_spec.rb | 19 ++++ 10 files changed, 383 insertions(+) create mode 100644 lib/puppet/provider/swift_keymaster_config/ini_setting.rb create mode 100644 lib/puppet/type/swift_keymaster_config.rb create mode 100644 manifests/keymaster.pp create mode 100644 manifests/proxy/encryption.pp create mode 100644 manifests/proxy/kms_keymaster.pp create mode 100644 spec/classes/swift_keymaster.rb create mode 100644 spec/classes/swift_proxy_encryption_spec.rb create mode 100644 spec/classes/swift_proxy_kms_keymaster_spec.rb create mode 100644 spec/unit/provider/swift_keymaster_config/ini_setting_spec.rb create mode 100644 spec/unit/type/swift_keymaster_config_spec.rb diff --git a/lib/puppet/provider/swift_keymaster_config/ini_setting.rb b/lib/puppet/provider/swift_keymaster_config/ini_setting.rb new file mode 100644 index 00000000..8abdc16a --- /dev/null +++ b/lib/puppet/provider/swift_keymaster_config/ini_setting.rb @@ -0,0 +1,10 @@ +Puppet::Type.type(:swift_keymaster_config).provide( + :ini_setting, + :parent => Puppet::Type.type(:openstack_config).provider(:ini_setting) +) do + + def self.file_path + '/etc/swift/keymaster.conf' + end + +end diff --git a/lib/puppet/type/swift_keymaster_config.rb b/lib/puppet/type/swift_keymaster_config.rb new file mode 100644 index 00000000..d792b26e --- /dev/null +++ b/lib/puppet/type/swift_keymaster_config.rb @@ -0,0 +1,53 @@ +Puppet::Type.newtype(:swift_keymaster_config) do + + ensurable + + newparam(:name, :namevar => true) do + desc 'Section/setting name to manage from /etc/swift/keymaster.conf' + newvalues(/\S+\/\S+/) + end + + newproperty(:value) do + desc 'The value of the setting to be defined.' + munge do |value| + value = value.to_s.strip + value.capitalize! if value =~ /^(true|false)$/i + value + end + newvalues(/^[\S ]*$/) + + def is_to_s( currentvalue ) + if resource.secret? + return '[old secret redacted]' + else + return currentvalue + end + end + + def should_to_s( newvalue ) + if resource.secret? + return '[new secret redacted]' + else + return newvalue + end + end + end + + newparam(:secret, :boolean => true) do + desc 'Whether to hide the value from Puppet logs. Defaults to `false`.' + + newvalues(:true, :false) + + defaultto false + end + + newparam(:ensure_absent_val) do + desc 'A value that is specified as the value property will behave as if ensure => absent was specified' + defaultto('') + end + + autorequire(:package) do + 'swift-proxy' + end + +end diff --git a/manifests/keymaster.pp b/manifests/keymaster.pp new file mode 100644 index 00000000..a7f89a9c --- /dev/null +++ b/manifests/keymaster.pp @@ -0,0 +1,98 @@ +# Configure keymaster configuration file +# +# == Parameters +# +# [*api_class*] +# (Required) String. The api_class tells Castellan which key manager to +# use to access the external key management system. The default value that +# accesses Barbican is +# castellan.key_manager.barbican_key_manager.BarbicanKeyManager. +# +# [*key_id*] +# (Required) String. The key_id is the identifier of the root secret stored +# in the KMS. The key_id is the final part of the secret href returned in the +# output of an 'openstack secret order get' command after an order to store +# or create a key has been successfully completed. +# +# [*username*] +# (Required) String. The Keystone username of the user used to access the key +# from the KMS. The username shall be set to match an existing user. +# Defaults to swift. +# +# [*password*] +# (Required) String. The password to go with the Keystone username. +# +# [*project_name*] +# (Optional) String. The Keystone project name. For security reasons, +# it is recommended to set the project_name to a project separate from the +# service project used by other OpenStack services. Thereby, if another +# service is compromised, it will not have access to the Swift root +# encryption secret. It is recommended that the swift user is the only one +# that has a role in this project. +# Defaults to service. +# +# [*project_id*] +# (Optional) String. Instead of the project name, the project id may also +# be used. +# +# [*auth_endpoint*] +# (Required) String. The Keystone URL to authenticate to. The value of +# auth_url may be set according to the value of auth_uri in +# [filter:authtoken] in proxy-server.conf. +# +# [*project_domain_name*] +# (Optional) String. The project domain name may optionally be specififed. +# +# [*user_domain_name*] +# (Optional) String. The user domain name may optionally be specififed. +# +# [*project_domain_id*] +# (Optional) String. Instead of the project domain name, the project domain +# id may also be specified. +# Defaults to 'default' (note the capitalization). +# +# [*user_domain_id*] +# (Optional) String. Instead of the user domain name, the user domain +# id may also be specified. +# Defaults to 'default' (note the capitalization). +# +# == Dependencies +# +# None +# +# == Authors +# +# Thiago da Silva thiago@redhat.com +# +class swift::keymaster( + + $api_class = 'castellan.key_manager.barbican_key_manager.BarbicanKeyManager', + $key_id = undef, + $username = 'swift', + $password = undef, + $project_name = 'service', + $project_id = undef, + $auth_endpoint = undef, + $project_domain_name = undef, + $user_domain_name = undef, + $project_domain_id = 'default', + $user_domain_id = 'default', +) { + + include ::swift::deps + + swift_keymaster_config { + 'kms_keymaster/api_class': value => $api_class; + 'kms_keymaster/key_id': value => $key_id; + 'kms_keymaster/username': value => $username; + 'kms_keymaster/password': value => $password; + 'kms_keymaster/project_name': value => $project_name; + 'kms_keymaster/project_id': value => $project_id; + 'kms_keymaster/auth_endpoint': value => $auth_endpoint; + 'kms_keymaster/project_domain_name': value => $project_domain_name; + 'kms_keymaster/user_domain_name': value => $user_domain_name; + 'kms_keymaster/project_domain_id': value => $project_domain_id; + 'kms_keymaster/user_domain_id': value => $user_domain_id; + } +} + diff --git a/manifests/proxy/encryption.pp b/manifests/proxy/encryption.pp new file mode 100644 index 00000000..61aa614b --- /dev/null +++ b/manifests/proxy/encryption.pp @@ -0,0 +1,27 @@ +# +# Configure Swift encryption. +# +# == Examples +# +# include ::swift::proxy::encryption +# +# == Parameters +# +# [*disable_encryption*] +# By default all PUT or POST'ed object data and/or metadata will be encrypted. +# Encryption of new data and/or metadata may be disabled by setting +# disable_encryption to True. However, all encryption middleware should remain +# in the pipeline in order for existing encrypted data to be read. +# +class swift::proxy::encryption ( + $disable_encryption = false +) { + + include ::swift::deps + + swift_proxy_config { + 'filter:encryption/use': value => 'egg:swift#encryption'; + 'filter:encryption/disable_encryption': value => $disable_encryption; + } +} + diff --git a/manifests/proxy/kms_keymaster.pp b/manifests/proxy/kms_keymaster.pp new file mode 100644 index 00000000..06356adc --- /dev/null +++ b/manifests/proxy/kms_keymaster.pp @@ -0,0 +1,24 @@ +# +# Configure Swift KMS Keymaster middleware. +# +# == Examples +# +# include ::swift::proxy::kms_keymaster +# +# == Parameters +# +# [*keymaster_config_path*] +# Sets the path from which the keymaster config options should be read +# +class swift::proxy::kms_keymaster ( + $keymaster_config_path = '/etc/swift/keymaster.conf' +) { + + include ::swift::deps + + swift_proxy_config { + 'filter:kms_keymaster/use': value => 'egg:swift#kms_keymaster'; + 'filter:kms_keymaster/keymaster_config_path': value => $keymaster_config_path; + } +} + diff --git a/spec/classes/swift_keymaster.rb b/spec/classes/swift_keymaster.rb new file mode 100644 index 00000000..54a19726 --- /dev/null +++ b/spec/classes/swift_keymaster.rb @@ -0,0 +1,32 @@ +require 'spec_helper' + +describe 'swift::keymaster' do + + let :facts do + {} + end + + describe "when using default parameters" do + it { is_expected.to contain_swift_keymaster_config('kms_keymaster/api_class').with_value('castellan.key_manager.barbican_key_manager.BarbicanKeyManager') } + it { is_expected.to contain_swift_keymaster_config('kms_keymaster/username').with_value('swift') } + it { is_expected.to contain_swift_keymaster_config('kms_keymaster/project_name').with_value('service') } + it { is_expected.to contain_swift_keymaster_config('kms_keymaster/project_domain_id').with_value('default') } + it { is_expected.to contain_swift_keymaster_config('kms_keymaster/user_domain_id').with_value('default') } + end + + describe "when overriding default parameters" do + let :params do + { + :key_id => 'dummy_key_id', + :password => 'fake_password', + :auth_endpoint => 'http://127.0.0.1:5000', + :project_name => 'barbican_swift_service', + } + end + it { is_expected.to contain_swift_keymaster_config('kms_keymaster/key_id').with_value('dummy_key_id') } + it { is_expected.to contain_swift_keymaster_config('kms_keymaster/password').with_value('fake_password') } + it { is_expected.to contain_swift_keymaster_config('kms_keymaster/auth_endpoint').with_value('http://127.0.0.1:5000') } + it { is_expected.to contain_swift_keymaster_config('kms_keymaster/project_name').with_value('barbican_swift_service') } + end + +end diff --git a/spec/classes/swift_proxy_encryption_spec.rb b/spec/classes/swift_proxy_encryption_spec.rb new file mode 100644 index 00000000..767dd3f4 --- /dev/null +++ b/spec/classes/swift_proxy_encryption_spec.rb @@ -0,0 +1,24 @@ +require 'spec_helper' + +describe 'swift::proxy::encryption' do + + let :facts do + {} + end + + describe "when using default parameters" do + it { is_expected.to contain_swift_proxy_config('filter:encryption/use').with_value('egg:swift#encryption') } + it { is_expected.to contain_swift_proxy_config('filter:encryption/disable_encryption').with_value('false') } + + end + + describe "when overriding default parameters" do + let :params do + { + :disable_encryption => true, + } + end + it { is_expected.to contain_swift_proxy_config('filter:encryption/disable_encryption').with_value('true') } + end + +end diff --git a/spec/classes/swift_proxy_kms_keymaster_spec.rb b/spec/classes/swift_proxy_kms_keymaster_spec.rb new file mode 100644 index 00000000..12793416 --- /dev/null +++ b/spec/classes/swift_proxy_kms_keymaster_spec.rb @@ -0,0 +1,24 @@ +require 'spec_helper' + +describe 'swift::proxy::kms_keymaster' do + + let :facts do + {} + end + + describe "when using default parameters" do + it { is_expected.to contain_swift_proxy_config('filter:kms_keymaster/use').with_value('egg:swift#kms_keymaster') } + it { is_expected.to contain_swift_proxy_config('filter:kms_keymaster/keymaster_config_path').with_value('/etc/swift/keymaster.conf') } + + end + + describe "when overriding default parameters" do + let :params do + { + :keymaster_config_path => '/tmp/keymaster.conf', + } + end + it { is_expected.to contain_swift_proxy_config('filter:kms_keymaster/keymaster_config_path').with_value('/tmp/keymaster.conf') } + end + +end diff --git a/spec/unit/provider/swift_keymaster_config/ini_setting_spec.rb b/spec/unit/provider/swift_keymaster_config/ini_setting_spec.rb new file mode 100644 index 00000000..6d7c6421 --- /dev/null +++ b/spec/unit/provider/swift_keymaster_config/ini_setting_spec.rb @@ -0,0 +1,72 @@ +$LOAD_PATH.push( + File.join( + File.dirname(__FILE__), + '..', + '..', + '..', + 'fixtures', + 'modules', + 'inifile', + 'lib') +) +$LOAD_PATH.push( + File.join( + File.dirname(__FILE__), + '..', + '..', + '..', + 'fixtures', + 'modules', + 'openstacklib', + 'lib') +) + +require 'spec_helper' + +provider_class = Puppet::Type.type(:swift_keymaster_config).provider(:ini_setting) + +describe provider_class do + + it 'should default to the default setting when no other one is specified' do + resource = Puppet::Type::Swift_keymaster_config.new( + { + :name => 'DEFAULT/foo', + :value => 'bar' + } + ) + provider = provider_class.new(resource) + expect(provider.section).to eq('DEFAULT') + expect(provider.setting).to eq('foo') + end + + it 'should allow setting to be set explicitly' do + resource = Puppet::Type::Swift_keymaster_config.new( + { + :name => 'dude/foo', + :value => 'bar' + } + ) + provider = provider_class.new(resource) + expect(provider.section).to eq('dude') + expect(provider.setting).to eq('foo') + end + + it 'should ensure absent when is specified as a value' do + resource = Puppet::Type::Swift_keymaster_config.new( + {:name => 'dude/foo', :value => ''} + ) + provider = provider_class.new(resource) + provider.exists? + expect(resource[:ensure]).to eq :absent + end + + it 'should ensure absent when value matches ensure_absent_val' do + resource = Puppet::Type::Swift_keymaster_config.new( + {:name => 'dude/foo', :value => 'foo', :ensure_absent_val => 'foo' } + ) + provider = provider_class.new(resource) + provider.exists? + expect(resource[:ensure]).to eq :absent + end + +end diff --git a/spec/unit/type/swift_keymaster_config_spec.rb b/spec/unit/type/swift_keymaster_config_spec.rb new file mode 100644 index 00000000..13abceb0 --- /dev/null +++ b/spec/unit/type/swift_keymaster_config_spec.rb @@ -0,0 +1,19 @@ +require 'puppet' +require 'puppet/type/swift_keymaster_config' + +describe 'Puppet::Type.type(:swift_keymaster_config)' do + before :each do + @swift_keymaster_config = Puppet::Type.type(:swift_keymaster_config).new(:name => 'DEFAULT/foo', :value => 'bar') + end + + it 'should autorequire the package that install the file' do + catalog = Puppet::Resource::Catalog.new + package = Puppet::Type.type(:package).new(:name => 'swift-proxy') + catalog.add_resource package, @swift_keymaster_config + dependency = @swift_keymaster_config.autorequire + expect(dependency.size).to eq(1) + expect(dependency[0].target).to eq(@swift_keymaster_config) + expect(dependency[0].source).to eq(package) + end + +end