feat: add openidc_metadata_dir to federation::oidc

Add optional keystone::federation::openidc::openidc_metadata_dir param
to set OIDCMetadataDir, to be configured when using multiple OIDC
providers. OIDCProviderMetadataURL is now optional and mutually
exclusive with OIDCMetadataDir.

References
https://github.com/OpenIDC/mod_auth_openidc/wiki/Multiple-Providers

Change-Id: Ife36d000c6747a14a6d9ae3bff4babc6ac8b3022
This commit is contained in:
Francesco Di Nucci 2024-07-01 10:43:50 +02:00 committed by Takashi Kajinami
parent 7558e5bfa1
commit e4acfc9f29
4 changed files with 79 additions and 31 deletions

View File

@ -17,8 +17,13 @@
# (Required) String value.
#
# [*openidc_provider_metadata_url*]
# The url that points to your OpenID Connect metadata provider
# (Required) String value.
# (Optional) The url that points to your OpenID Connect metadata provider.
# Defaults to undef
#
# [*openidc_metadata_dir*]
# (Optional) Path of OIDCMetadataDir, directory that holds metadata in case of
# usage of multiple OIDC provider.
# Defaults to undef
#
# [*openidc_client_id*]
# The client ID to use when handshaking with your OpenID Connect provider
@ -154,36 +159,36 @@ class keystone::federation::openidc (
$keystone_url,
$methods,
$idp_name,
$openidc_provider_metadata_url,
$openidc_client_id,
$openidc_client_secret,
$openidc_crypto_passphrase = 'openstack',
$openidc_response_type = 'id_token',
$openidc_response_mode = undef,
$openidc_cache_type = undef,
$openidc_cache_shm_max = undef,
$openidc_cache_shm_entry_size = undef,
$openidc_cache_dir = undef,
$openidc_cache_clean_interval = undef,
$openidc_claim_delimiter = undef,
Boolean $openidc_enable_oauth = false,
$openidc_introspection_endpoint = undef,
$openidc_verify_jwks_uri = undef,
$openidc_verify_method = 'introspection',
$openidc_pass_userinfo_as = undef,
$openidc_pass_claim_as = undef,
$openidc_redirect_uri = undef,
$memcached_servers = undef,
$redis_server = undef,
$redis_password = undef,
$redis_username = undef,
$redis_database = undef,
$redis_connect_timeout = undef,
$redis_timeout = undef,
$remote_id_attribute = $facts['os_service_default'],
$template_order = 331,
Optional[Stdlib::HTTPUrl] $openidc_provider_metadata_url = undef,
Optional[Stdlib::Unixpath] $openidc_metadata_dir = undef,
$openidc_crypto_passphrase = 'openstack',
$openidc_response_type = 'id_token',
$openidc_response_mode = undef,
$openidc_cache_type = undef,
$openidc_cache_shm_max = undef,
$openidc_cache_shm_entry_size = undef,
$openidc_cache_dir = undef,
$openidc_cache_clean_interval = undef,
$openidc_claim_delimiter = undef,
Boolean $openidc_enable_oauth = false,
$openidc_introspection_endpoint = undef,
$openidc_verify_jwks_uri = undef,
$openidc_verify_method = 'introspection',
$openidc_pass_userinfo_as = undef,
$openidc_pass_claim_as = undef,
$openidc_redirect_uri = undef,
$memcached_servers = undef,
$redis_server = undef,
$redis_password = undef,
$redis_username = undef,
$redis_database = undef,
$redis_connect_timeout = undef,
$redis_timeout = undef,
$remote_id_attribute = $facts['os_service_default'],
$template_order = 331,
) {
include apache
include apache::mod::auth_openidc
@ -193,6 +198,15 @@ class keystone::federation::openidc (
if ! defined(Class['keystone::wsgi::apache']) {
fail('The keystone::wsgi::apache class should be included in the catalog')
}
# With a single provider, OIDCProviderMetadataURL should be set, with multiple
# providers OIDCMetadataDir should be used instead
if !$openidc_provider_metadata_url and !$openidc_metadata_dir {
fail('Set one openidc_provider_metadata_url or openidc_metadata_dir')
}
if $openidc_provider_metadata_url and $openidc_metadata_dir {
fail("openidc_provider_metadata_url and openidc_metadata_dir are mutually \
exclusive, set only one of the two.")
}
if !($openidc_verify_method in ['introspection', 'jwks']) {
fail('Unsupported token verification method. Must be one of "introspection" or "jwks"')

View File

@ -0,0 +1,5 @@
---
features: >
Add ``keystone::federation::openidc:openidc_metadata_dir`` parameter
to specify OIDCMetadataDir path instead of OIDCProviderMetadataURL . This may
be required when multiple OIDC providers are used for the federation.

View File

@ -50,6 +50,18 @@ describe 'keystone::federation::openidc' do
params.merge!(:openidc_enable_oauth => true)
it_raises 'a Puppet:Error', /You must set openidc_introspection_endpoint when enabling oauth support/
end
before do
params.merge!({
:openidc_metadata_dir => '/CUSTOM_METADATA_DIR',
})
it_raises 'a Puppet:Error', /openidc_provider_metadata_url and openidc_metadata_dir are mutually/
end
before do
params.delete(:openidc_provider_metadata_url)
it_raises 'a Puppet:Error', /Set openidc_provider_metadata_url or openidc_metadata_dir/
end
end
on_supported_os({
@ -76,10 +88,23 @@ describe 'keystone::federation::openidc' do
it 'should contain expected config' do
content = get_param('concat::fragment', 'keystone_wsgi-configure_openidc_keystone', 'content')
expect(content).to match('OIDCProviderMetadataURL "https://accounts.google.com/.well-known/openid-configuration"')
expect(content).to match('OIDCClientID "openid_client_id"')
expect(content).to match('OIDCClientSecret "openid_client_secret"')
expect(content).to match('OIDCRedirectURI "http://localhost:5000/v3/OS-FEDERATION/identity_providers/myidp/protocols/openid/auth"')
expect(content).to match('OIDCProviderMetadataURL "https://accounts.google.com/.well-known/openid-configuration"')
end
end
context 'with openidc_metadata_dir' do
before do
params.delete(:openidc_provider_metadata_url)
params.merge!({
:openidc_metadata_dir => '/CUSTOM_METADATA_DIR'
})
end
it 'should contain the expected OIDCMetadataDir' do
content = get_param('concat::fragment', 'keystone_wsgi-configure_openidc_keystone', 'content')
expect(content).to match('OIDCMetadataDir "/CUSTOM_METADATA_DIR"')
end
end

View File

@ -1,11 +1,15 @@
OIDCClaimPrefix "OIDC-"
OIDCResponseType "<%= scope['keystone::federation::openidc::openidc_response_type']-%>"
OIDCScope "openid email profile"
<%- if scope['::keystone::federation::openidc::openidc_provider_metadata_url'] != nil -%>
OIDCProviderMetadataURL "<%= scope['keystone::federation::openidc::openidc_provider_metadata_url']-%>"
<%- end -%>
<%- if scope['::keystone::federation::openidc::openidc_metadata_dir'] != nil -%>
OIDCMetadataDir "<%= scope['::keystone::federation::openidc::openidc_metadata_dir'] %>"
<%- end -%>
OIDCClientID "<%= scope['keystone::federation::openidc::openidc_client_id']-%>"
OIDCClientSecret "<%= scope['keystone::federation::openidc::openidc_client_secret']-%>"
OIDCCryptoPassphrase "<%= scope['keystone::federation::openidc::openidc_crypto_passphrase']-%>"
<%- if scope['::keystone::federation::openidc::openidc_response_mode'] != nil -%>
OIDCResponseMode "<%= scope['::keystone::federation::openidc::openidc_response_mode'] %>"
<%- end -%>