From 759c626987749f030087ddcd9689f19a6608279d Mon Sep 17 00:00:00 2001 From: Iury Gregory Melo Ferreira Date: Fri, 11 Dec 2015 19:49:47 +0000 Subject: [PATCH] Federation support for mellon This patch aim to configure Keystone to use Mellon according to [1] [1] http://docs.openstack.org/developer/keystone/federation/mellon.html Change-Id: I092ea274bd3aa6aa2fd59d01bd2af48744f37240 --- manifests/federation/mellon.pp | 106 +++++++++++++++++++ manifests/params.pp | 2 + spec/classes/keystone_federation_mellon.rb | 116 +++++++++++++++++++++ templates/mellon.conf.erb | 16 +++ 4 files changed, 240 insertions(+) create mode 100644 manifests/federation/mellon.pp create mode 100644 spec/classes/keystone_federation_mellon.rb create mode 100644 templates/mellon.conf.erb diff --git a/manifests/federation/mellon.pp b/manifests/federation/mellon.pp new file mode 100644 index 000000000..0de7e2274 --- /dev/null +++ b/manifests/federation/mellon.pp @@ -0,0 +1,106 @@ +# == class: keystone::federation::mellon +# +# == Parameters +# +# [*methods*] +# A list of methods used for authentication separated by comma or an array. +# The allowed values are: 'external', 'password', 'token', 'oauth1', 'saml2' +# (Required) (string or array value). +# Note: The external value should be dropped to avoid problems. +# +# [*idp_name*] +# The name name associated with the IdP in Keystone. +# (Required) String value. +# +# [*protocol_name*] +# The name for your protocol associated with the IdP. +# (Required) String value. +# +# [*admin_port*] +# A boolean value to ensure that you want to configure K2K Federation +# using Keystone VirtualHost on port 35357. +# (Optional) Defaults to false. +# +# [*main_port*] +# A boolean value to ensure that you want to configure K2K Federation +# using Keystone VirtualHost on port 5000. +# (Optional) Defaults to true. +# +# [*module_plugin*] +# The plugin for authentication acording to the choice made with protocol and +# module. +# (Optional) Defaults to 'keystone.auth.plugins.mapped.Mapped' (string value) +# +# [*template_order*] +# This number indicates the order for the concat::fragment that will apply +# the shibboleth configuration to Keystone VirtualHost. The value should +# The value should be greater than 330 an less then 999, according to: +# https://github.com/puppetlabs/puppetlabs-apache/blob/master/manifests/vhost.pp +# The value 330 corresponds to the order for concat::fragment "${name}-filters" +# and "${name}-limits". +# The value 999 corresponds to the order for concat::fragment "${name}-file_footer". +# (Optional) Defaults to 331. +# +class keystone::federation::mellon ( + $methods, + $idp_name, + $protocol_name, + $admin_port = false, + $main_port = true, + $module_plugin = 'keystone.auth.plugins.mapped.Mapped', + $template_order = 331, +) { + + include ::apache + include ::keystone::params + + # Note: if puppet-apache modify these values, this needs to be updated + if $template_order <= 330 or $template_order >= 999 { + fail('The template order should be greater than 330 and less than 999.') + } + + if ('external' in $methods ) { + fail('The external method should be dropped to avoid any interference with some Apache + Mellon SP setups, where a REMOTE_USER env variable is always set, even as an empty value.') + } + + if !('saml2' in $methods ) { + fail('Methods should contain saml2 as one of the auth methods.') + }else{ + if ($module_plugin != 'keystone.auth.plugins.mapped.Mapped') { + fail('The plugin for saml and mellon should be keystone.auth.plugins.mapped.Mapped') + } + } + + validate_bool($admin_port) + validate_bool($main_port) + + if( !$admin_port and !$main_port){ + fail('No VirtualHost port to configure, please choose at least one.') + } + + keystone_config { + 'auth/methods': value => join(any2array($methods),','); + 'auth/saml2': value => $module_plugin; + } + + ensure_packages([$::keystone::params::mellon_package_name], { + ensure => present + }) + + if $admin_port { + concat::fragment { 'configure_mellon_on_port_35357': + target => "${keystone::wsgi::apache::priority}-keystone_wsgi_admin.conf", + content => template('keystone/mellon.conf.erb'), + order => $template_order, + } + } + + if $main_port { + concat::fragment { 'configure_mellon_on_port_5000': + target => "${keystone::wsgi::apache::priority}-keystone_wsgi_main.conf", + content => template('keystone/mellon.conf.erb'), + order => $template_order, + } + } + +} diff --git a/manifests/params.pp b/manifests/params.pp index d8c473702..e233bbc55 100644 --- a/manifests/params.pp +++ b/manifests/params.pp @@ -14,6 +14,7 @@ class keystone::params { $sqlite_package_name = 'python-pysqlite2' $paste_config = undef $pymysql_package_name = 'python-pymysql' + $mellon_package_name = 'libapache2-mod-auth-mellon' case $::operatingsystem { 'Debian': { $service_provider = undef @@ -33,6 +34,7 @@ class keystone::params { $keystone_wsgi_script_source = '/usr/share/keystone/keystone.wsgi' $paste_config = '/usr/share/keystone/keystone-dist-paste.ini' $pymysql_package_name = undef + $mellon_package_name = 'mod_auth_mellon' } } } diff --git a/spec/classes/keystone_federation_mellon.rb b/spec/classes/keystone_federation_mellon.rb new file mode 100644 index 000000000..a0b9e5305 --- /dev/null +++ b/spec/classes/keystone_federation_mellon.rb @@ -0,0 +1,116 @@ +require 'spec_helper' + +describe 'keystone::federation::mellon' do + + describe 'with invalid params' do + before do + params.merge!(:methods => 'external, password, token, oauth1') + end + + it_raises 'a Puppet::Error', /The external method should be dropped to avoid any interference with some Apache + Mellon SP setups, where a REMOTE_USER env variable is always set, even as an empty value./ + + before do + params.merge!(:methods => 'password, token, oauth1') + end + + it_raises 'a Puppet::Error', /Methods should contain saml2 as one of the auth methods./ + + before do + params.merge!(:methods => 'password, token, oauth1, saml2', + :module_plugin => 'keystone.auth.plugins') + end + + it_raises 'a Puppet:Error', /The plugin for saml and mellon should be keystone.auth.plugins.mapped.Mapped/ + + before do + params.merge!(:admin_port => false, + :main_port => false) + end + + it_raises 'a Puppet:Error', /No VirtualHost port to configure, please choose at least one./ + + befode do + params.merge!(:template_port => 330) + end + + it_raises 'a Puppet:Error', /The template order should be greater than 330 and less than 999./ + + befode do + params.merge!(:template_port => 999) + end + + it_raises 'a Puppet:Error', /The template order should be greater than 330 and less than 999./ + end + + context 'on a RedHat osfamily' do + let :facts do + { :osfamily => 'RedHat', + :operatingsystemrelease => '7.0', + :concat_basedir => '/var/lib/puppet/concat' } + end + + context 'with only required parameters' do + let :params do + { :methods => 'password, token, saml2' } + end + + it 'should have basic params for mellon in Keystone configuration' do + is_expected.to contain_keystone_config('auth/methods').with_value('password, token, saml2') + is_expected.to contain_keystone_config('auth/saml2').with_value('keystone.auth.plugins.mapped.Mapped') + end + end + + it { is_expected.to contain_package('mod_auth_mellon') } + + end + + context 'on a Debian osfamily' do + let :facts do + { :osfamily => 'Debian', + :operatingsystemrelease => '7.8', + :concat_basedir => '/var/lib/puppet/concat' } + end + + context 'with only required parameters' do + let :params do + { :methods => 'password, token, saml2' } + end + + it 'should have basic params for mellon in Keystone configuration' do + is_expected.to contain_keystone_config('auth/methods').with_value('password, token, saml2') + is_expected.to contain_keystone_config('auth/saml2').with_value('keystone.auth.plugins.mapped.Mapped') + end + + it { is_expected.to contain_concat__fragment('configure_mellon_on_port_5000').with({ + :target => "${keystone::wsgi::apache::priority}-keystone_wsgi_main.conf", + :order => params[:template_order], + })} + end + + context 'with override default parameters' do + let :params do + { :methods => 'password, token, saml2', + :admin_port => true } + end + + it 'should have basic params for mellon in Keystone configuration' do + is_expected.to contain_keystone_config('auth/methods').with_value('password, token, saml2') + is_expected.to contain_keystone_config('auth/saml2').with_value('keystone.auth.plugins.mapped.Mapped') + end + + it { is_expected.to contain_concat__fragment('configure_mellon_on_port_5000').with({ + :target => "${keystone::wsgi::apache::priority}-keystone_wsgi_main.conf", + :order => params[:template_order], + })} + + it { is_expected.to contain_concat__fragment('configure_mellon_on_port_35357').with({ + :target => "${keystone::wsgi::apache::priority}-keystone_wsgi_admin.conf", + :order => params[:template_order], + })} + end + + it { is_expected.to contain_package('libapache2-mod-auth-mellon') } + + end + +end diff --git a/templates/mellon.conf.erb b/templates/mellon.conf.erb new file mode 100644 index 000000000..259bcd824 --- /dev/null +++ b/templates/mellon.conf.erb @@ -0,0 +1,16 @@ + WSGIScriptAliasMatch ^(/v3/OS-FEDERATION/identity_providers/.*?/protocols/.*?/auth)$ <%= scope['keystone::params::keystone_wsgi_script_path'] -%>/$1 + + + MellonEnable "info" + MellonSPPrivateKeyFile <%= scope['apache::mod_dir']-%>/mellon/http_keystone.fqdn.key + MellonSPCertFile <%= scope['apache::mod_dir']-%>/mellon/http_keystone.fqdn.cert + MellonSPMetadataFile <%= scope['apache::mod_dir']-%>/mellon/http_keystone.fqdn.xml + MellonIdPMetadataFile <%= scope['apache::mod_dir']-%>/mellon/idp-metadata.xml + MellonEndpointPath /v3/OS-FEDERATION/identity_providers/<%= scope['keystone::federation::mellon::idp_name']-%>/protocols/<%= scope['keystone::federation::mellon::protocol_name']-%>/auth/mellon + MellonIdP "IDP" + + + /protocols/<%= scope['keystone::federation::mellon::protocol_name']-%>/auth> + AuthType "Mellon" + MellonEnable "auth" +