diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index f449c2fb..803251ac 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -67,17 +67,17 @@ jobs: - "puppet6" - "puppet7" keycloak_version: - - "18.0.0" + - "19.0.3" keycloak_full: - "no" include: - set: "el7" puppet: "puppet6" - keycloak_version: "18.0.0" + keycloak_version: "19.0.3" keycloak_full: "yes" - set: "el7" puppet: "puppet7" - keycloak_version: "18.0.0" + keycloak_version: "19.0.3" keycloak_full: "yes" env: BUNDLE_WITHOUT: development:release diff --git a/.sync.yml b/.sync.yml index 95084526..38f37c7e 100644 --- a/.sync.yml +++ b/.sync.yml @@ -26,16 +26,16 @@ Rakefile: - puppet6 - puppet7 keycloak_version: - - '18.0.0' + - '19.0.3' keycloak_full: ['no'] acceptance_includes: - set: el7 puppet: puppet6 - keycloak_version: 18.0.0 + keycloak_version: 19.0.3 keycloak_full: 'yes' - set: el7 puppet: puppet7 - keycloak_version: 18.0.0 + keycloak_version: 19.0.3 keycloak_full: 'yes' .gitignore: paths: diff --git a/README.md b/README.md index 86125b50..d1ee9f3b 100644 --- a/README.md +++ b/README.md @@ -172,6 +172,7 @@ This module may work on earlier versions but this is the only version tested. | 8.x - 12.x | 6.x | | 12.x - 16.x | 7.x | | 18.x | 8.x | +| 19.x | 9.x | ## Usage diff --git a/lib/puppet/provider/keycloak_client_protocol_mapper/kcadm.rb b/lib/puppet/provider/keycloak_client_protocol_mapper/kcadm.rb index 24bc57bd..8cf5a31a 100644 --- a/lib/puppet/provider/keycloak_client_protocol_mapper/kcadm.rb +++ b/lib/puppet/provider/keycloak_client_protocol_mapper/kcadm.rb @@ -49,12 +49,9 @@ def self.instances if protocol_mapper[:type] == 'oidc-group-membership-mapper' protocol_mapper[:full_path] = d['config']['full.path'] end - if ['saml-user-property-mapper', 'saml-javascript-mapper'].include?(protocol_mapper[:type]) + if ['saml-user-property-mapper'].include?(protocol_mapper[:type]) || protocol_mapper[:type] =~ /script-.+/ protocol_mapper[:friendly_name] = d['config']['friendly.name'] end - if protocol_mapper[:type] == 'saml-javascript-mapper' - protocol_mapper[:script] = d['config']['Script'] - end if protocol_mapper[:protocol] == 'openid-connect' protocol_mapper[:id_token_claim] = d['config']['id.token.claim'] protocol_mapper[:access_token_claim] = d['config']['access.token.claim'] @@ -69,7 +66,7 @@ def self.instances protocol_mapper[:attribute_name] = d['config']['attribute.name'] protocol_mapper[:attribute_nameformat] = get_attribute_nameformat_reverse(d['config']['attribute.nameformat']) end - if ['saml-role-list-mapper', 'saml-javascript-mapper'].include?(protocol_mapper[:type]) + if ['saml-role-list-mapper'].include?(protocol_mapper[:type]) || protocol_mapper[:type] =~ /script-.+/ protocol_mapper[:single] = d['config']['single'].to_s.to_sym end protocol_mappers << new(protocol_mapper) @@ -112,12 +109,9 @@ def create if resource[:type] == 'oidc-group-membership-mapper' data[:config][:'full.path'] = resource[:full_path] if resource[:full_path] end - if ['saml-user-property-mapper', 'saml-javascript-mapper'].include?(resource[:type]) + if ['saml-user-property-mapper'].include?(resource[:type]) || (resource[:protocol] == 'saml' && resource[:type] =~ /script-.+/) data[:config][:'friendly.name'] = resource[:friendly_name] if resource[:friendly_name] end - if resource[:type] == 'saml-javascript-mapper' - data[:config][:Script] = resource[:script] - end if resource[:protocol] == 'openid-connect' data[:config][:'id.token.claim'] = resource[:id_token_claim] if resource[:id_token_claim] data[:config][:'access.token.claim'] = resource[:access_token_claim] if resource[:access_token_claim] @@ -132,7 +126,7 @@ def create data[:config][:'attribute.name'] = resource[:attribute_name] if resource[:attribute_name] data[:config][:'attribute.nameformat'] = self.class.get_attribute_nameformat(resource[:attribute_nameformat]) if resource[:attribute_nameformat] end - if ['saml-role-list-mapper', 'saml-javascript-mapper'].include?(resource[:type]) + if ['saml-role-list-mapper'].include?(resource[:type]) || (resource[:protocol] == 'saml' && resource[:type] =~ /script-.+/) data[:config][:single] = resource[:single].to_s if resource[:single] end @@ -196,12 +190,9 @@ def flush if resource[:type] == 'oidc-group-membership-mapper' config[:'full.path'] = resource[:full_path] if resource[:full_path] end - if ['saml-user-property-mapper', 'saml-javascript-mapper'].include?(resource[:type]) + if ['saml-user-property-mapper'].include?(resource[:type]) || (resource[:protocol] == 'saml' && resource[:type] =~ /script-.+/) config[:'friendly.name'] = resource[:friendly_name] if resource[:friendly_name] end - if resource[:type] == 'saml-javascript-mapper' - config[:Script] = resource[:script] - end if resource[:protocol] == 'openid-connect' config[:'id.token.claim'] = resource[:id_token_claim] if resource[:id_token_claim] config[:'access.token.claim'] = resource[:access_token_claim] if resource[:access_token_claim] @@ -216,7 +207,7 @@ def flush config[:'attribute.name'] = resource[:attribute_name] if resource[:attribute_name] config[:'attribute.nameformat'] = self.class.get_attribute_nameformat(resource[:attribute_nameformat]) if resource[:attribute_nameformat] end - if ['saml-role-list-mapper', 'saml-javascript-mapper'].include?(resource[:type]) + if ['saml-role-list-mapper'].include?(resource[:type]) || (resource[:protocol] == 'saml' && resource[:type] =~ /script-.+/) config[:single] = resource[:single].to_s if resource[:single] end data[:config] = config unless config.empty? diff --git a/lib/puppet/provider/keycloak_protocol_mapper/kcadm.rb b/lib/puppet/provider/keycloak_protocol_mapper/kcadm.rb index d26bab62..193de182 100644 --- a/lib/puppet/provider/keycloak_protocol_mapper/kcadm.rb +++ b/lib/puppet/provider/keycloak_protocol_mapper/kcadm.rb @@ -49,12 +49,9 @@ def self.instances if ['oidc-group-membership-mapper', 'saml-group-membership-mapper'].include?(protocol_mapper[:type]) protocol_mapper[:full_path] = d['config']['full.path'] end - if ['saml-group-membership-mapper', 'saml-user-property-mapper', 'saml-user-attribute-mapper', 'saml-javascript-mapper'].include?(protocol_mapper[:type]) + if ['saml-group-membership-mapper', 'saml-user-property-mapper', 'saml-user-attribute-mapper'].include?(protocol_mapper[:type]) || protocol_mapper[:type] =~ /script-.+/ protocol_mapper[:friendly_name] = d['config']['friendly.name'] end - if protocol_mapper[:type] == 'saml-javascript-mapper' - protocol_mapper[:script] = d['config']['Script'] - end if protocol_mapper[:protocol] == 'openid-connect' protocol_mapper[:id_token_claim] = d['config']['id.token.claim'] protocol_mapper[:access_token_claim] = d['config']['access.token.claim'] @@ -69,7 +66,7 @@ def self.instances protocol_mapper[:attribute_name] = d['config']['attribute.name'] protocol_mapper[:attribute_nameformat] = get_attribute_nameformat_reverse(d['config']['attribute.nameformat']) end - if ['saml-group-membership-mapper', 'saml-role-list-mapper', 'saml-javascript-mapper'].include?(protocol_mapper[:type]) + if ['saml-group-membership-mapper', 'saml-role-list-mapper'].include?(protocol_mapper[:type]) || protocol_mapper[:type] =~ /script-.+/ protocol_mapper[:single] = d['config']['single'].to_s.to_sym end protocol_mappers << new(protocol_mapper) @@ -112,12 +109,9 @@ def create if ['oidc-group-membership-mapper', 'saml-group-membership-mapper'].include?(resource[:type]) data[:config][:'full.path'] = resource[:full_path] if resource[:full_path] end - if ['saml-group-membership-mapper', 'saml-user-property-mapper', 'saml-user-attribute-mapper', 'saml-javascript-mapper'].include?(resource[:type]) + if ['saml-group-membership-mapper', 'saml-user-property-mapper', 'saml-user-attribute-mapper'].include?(resource[:type]) || (resource[:protocol] == 'saml' && resource[:type] =~ /script-.+/) data[:config][:'friendly.name'] = resource[:friendly_name] if resource[:friendly_name] end - if resource[:type] == 'saml-javascript-mapper' - data[:config][:Script] = resource[:script] - end if resource[:protocol] == 'openid-connect' data[:config][:'id.token.claim'] = resource[:id_token_claim] if resource[:id_token_claim] data[:config][:'access.token.claim'] = resource[:access_token_claim] if resource[:access_token_claim] @@ -132,7 +126,7 @@ def create data[:config][:'attribute.name'] = resource[:attribute_name] if resource[:attribute_name] data[:config][:'attribute.nameformat'] = self.class.get_attribute_nameformat(resource[:attribute_nameformat]) if resource[:attribute_nameformat] end - if ['saml-group-membership-mapper', 'saml-role-list-mapper', 'saml-javascript-mapper'].include?(resource[:type]) + if ['saml-group-membership-mapper', 'saml-role-list-mapper'].include?(resource[:type]) || (resource[:protocol] == 'saml' && resource[:type] =~ /script-.+/) data[:config][:single] = resource[:single].to_s if resource[:single] end @@ -196,12 +190,9 @@ def flush if ['oidc-group-membership-mapper', 'saml-group-membership-mapper'].include?(resource[:type]) config[:'full.path'] = resource[:full_path] if resource[:full_path] end - if ['saml-group-membership-mapper', 'saml-user-property-mapper', 'saml-user-attribute-mapper', 'saml-javascript-mapper'].include?(resource[:type]) + if ['saml-group-membership-mapper', 'saml-user-property-mapper', 'saml-user-attribute-mapper'].include?(resource[:type]) || (resource[:protocol] == 'saml' && resource[:type] =~ /script-.+/) config[:'friendly.name'] = resource[:friendly_name] if resource[:friendly_name] end - if resource[:type] == 'saml-javascript-mapper' - config[:Script] = resource[:script] - end if resource[:protocol] == 'openid-connect' config[:'id.token.claim'] = resource[:id_token_claim] if resource[:id_token_claim] config[:'access.token.claim'] = resource[:access_token_claim] if resource[:access_token_claim] @@ -216,7 +207,7 @@ def flush config[:'attribute.name'] = resource[:attribute_name] if resource[:attribute_name] config[:'attribute.nameformat'] = self.class.get_attribute_nameformat(resource[:attribute_nameformat]) if resource[:attribute_nameformat] end - if ['saml-group-membership-mapper', 'saml-role-list-mapper', 'saml-javascript-mapper'].include?(resource[:type]) + if ['saml-group-membership-mapper', 'saml-role-list-mapper'].include?(resource[:type]) || (resource[:protocol] == 'saml' && resource[:type] =~ /script-.+/) config[:single] = resource[:single].to_s if resource[:single] end data[:config] = config unless config.empty? diff --git a/lib/puppet/type/keycloak_client_protocol_mapper.rb b/lib/puppet/type/keycloak_client_protocol_mapper.rb index 33d2b695..2af4c944 100644 --- a/lib/puppet/type/keycloak_client_protocol_mapper.rb +++ b/lib/puppet/type/keycloak_client_protocol_mapper.rb @@ -62,7 +62,7 @@ 'oidc-audience-mapper', 'saml-user-property-mapper', 'saml-role-list-mapper', - 'saml-javascript-mapper', + /script-.+/ ) defaultto do if @resource[:protocol] == 'openid-connect' @@ -188,7 +188,7 @@ desc 'single. Default to `false` for `type` `saml-role-list-mapper`.' newvalues(:true, :false) defaultto do - if ['saml-role-list-mapper', 'saml-javascript-mapper'].include?(@resource['type']) + if ['saml-role-list-mapper'].include?(@resource['type']) :false else nil @@ -196,14 +196,6 @@ end end - newproperty(:script) do - desc <<-EOS - Script, only valid for `type` of `saml-javascript-mapper`' - - Array values will be joined with newlines. Strings will be kept unchanged. - EOS - end - newproperty(:included_client_audience) do desc 'included.client.audience Required for `type` of `oidc-audience-mapper`' end @@ -247,13 +239,13 @@ def self.title_patterns 'oidc-group-membership-mapper', 'oidc-audience-mapper', ] - if self[:protocol] == 'openid-connect' && !oidc_types.include?(self[:type]) + if self[:protocol] == 'openid-connect' && !oidc_types.include?(self[:type]) && self[:type] !~ /script-.+/ raise Puppet::Error, "type #{self[:type]} is not valid for protocol openid-connect" end - if self[:protocol] == 'saml' && !['saml-user-property-mapper', 'saml-role-list-mapper', 'saml-javascript-mapper'].include?(self[:type]) + if self[:protocol] == 'saml' && !['saml-user-property-mapper', 'saml-role-list-mapper'].include?(self[:type]) && self[:type] !~ /script-.+/ raise Puppet::Error, "type #{self[:type]} is not valid for protocol saml" end - if self[:friendly_name] && !['saml-user-property-mapper', 'saml-javascript-mapper'].include?(self[:type]) + if self[:friendly_name] && self[:type] !~ /(saml-user-property-mapper|script.+)/ raise Puppet::Error, "friendly_name is not valid for type #{self[:type]}" end if self[:attribute_name] && self[:protocol] != 'saml' @@ -262,12 +254,9 @@ def self.title_patterns if self[:attribute_nameformat] && self[:protocol] != 'saml' raise Puppet::Error, "attribute_nameformat is not valid for protocol #{self[:protocol]}" end - if self[:single] && !['saml-role-list-mapper', 'saml-javascript-mapper'].include?(self[:type]) + if self[:single] && self[:type] !~ /(saml-role-list-mapper|script-.+)/ raise Puppet::Error, "single is not valid for type #{self[:type]}" end - if self[:type] == 'saml-javascript-mapper' && self[:script].nil? - raise Puppet::Error, 'script is required for saml-javascript-mapper' - end if self[:type] == 'oidc-audience-mapper' && self[:included_client_audience].nil? raise Puppet::Error, 'included_client_audience is required for oidc-audience-mapper' end diff --git a/lib/puppet/type/keycloak_protocol_mapper.rb b/lib/puppet/type/keycloak_protocol_mapper.rb index ce782d41..f6c02128 100644 --- a/lib/puppet/type/keycloak_protocol_mapper.rb +++ b/lib/puppet/type/keycloak_protocol_mapper.rb @@ -64,7 +64,7 @@ 'saml-user-property-mapper', 'saml-user-attribute-mapper', 'saml-role-list-mapper', - 'saml-javascript-mapper', + /script-.+/ ) defaultto do if @resource[:protocol] == 'openid-connect' @@ -187,10 +187,10 @@ end newproperty(:single, boolean: true) do - desc 'single. Default to `false` for `type` `saml-role-list-mapper` or `saml-javascript-mapper`.' + desc 'single. Default to `false` for `type` `saml-role-list-mapper`.' newvalues(:true, :false) defaultto do - if ['saml-role-list-mapper', 'saml-javascript-mapper'].include?(@resource['type']) + if ['saml-role-list-mapper'].include?(@resource['type']) :false else nil @@ -198,14 +198,6 @@ end end - newproperty(:script) do - desc <<-EOS - Script, only valid for `type` of `saml-javascript-mapper`' - - Array values will be joined with newlines. Strings will be kept unchanged. - EOS - end - newproperty(:included_client_audience) do desc 'included.client.audience Required for `type` of `oidc-audience-mapper`' end @@ -249,14 +241,14 @@ def self.title_patterns 'oidc-audience-mapper', 'oidc-usermodel-attribute-mapper', ] - if self[:protocol] == 'openid-connect' && !openid_connect_types.include?(self[:type]) + if self[:protocol] == 'openid-connect' && !openid_connect_types.include?(self[:type]) && self[:type] !~ /script-.+/ raise Puppet::Error, "type #{self[:type]} is not valid for protocol openid-connect" end - saml_mapper = ['saml-group-membership-mapper', 'saml-user-property-mapper', 'saml-user-attribute-mapper', 'saml-role-list-mapper', 'saml-javascript-mapper'] - if self[:protocol] == 'saml' && !saml_mapper.include?(self[:type]) + saml_mapper = ['saml-group-membership-mapper', 'saml-user-property-mapper', 'saml-user-attribute-mapper', 'saml-role-list-mapper'] + if self[:protocol] == 'saml' && !saml_mapper.include?(self[:type]) && self[:type] !~ /script-.+/ raise Puppet::Error, "type #{self[:type]} is not valid for protocol saml" end - if self[:friendly_name] && !['saml-group-membership-mapper', 'saml-user-property-mapper', 'saml-user-attribute-mapper', 'saml-javascript-mapper'].include?(self[:type]) + if self[:friendly_name] && self[:type] !~ /(saml-group-membership-mapper|saml-user-property-mapper|saml-user-attribute-mapper|script-.+)/ raise Puppet::Error, "friendly_name is not valid for type #{self[:type]}" end if self[:attribute_name] && self[:protocol] != 'saml' @@ -265,12 +257,9 @@ def self.title_patterns if self[:attribute_nameformat] && self[:protocol] != 'saml' raise Puppet::Error, "attribute_nameformat is not valid for protocol #{self[:protocol]}" end - if self[:single] && !['saml-group-membership-mapper', 'saml-role-list-mapper', 'saml-javascript-mapper'].include?(self[:type]) + if self[:single] && self[:type] !~ /(saml-group-membership-mapper|saml-role-list-mapper|script-.+)/ raise Puppet::Error, "single is not valid for type #{self[:type]}" end - if self[:type] == 'saml-javascript-mapper' && self[:script].nil? - raise Puppet::Error, 'script is required for saml-javascript-mapper' - end if self[:type] == 'oidc-audience-mapper' && self[:included_client_audience].nil? raise Puppet::Error, 'included_client_audience is required for oidc-audience-mapper' end diff --git a/lib/puppet/type/keycloak_required_action.rb b/lib/puppet/type/keycloak_required_action.rb index de6ad142..976640e3 100644 --- a/lib/puppet/type/keycloak_required_action.rb +++ b/lib/puppet/type/keycloak_required_action.rb @@ -6,29 +6,29 @@ Manage Keycloak required actions @example Enable Webauthn Register and make it default keycloak_required_action { 'webauthn-register on master': - ensure => present, - provider_id => 'webauthn-register', + ensure => present, + alias => 'webauthn-register', + provider_id => 'webauthn-register', display_name => 'Webauthn Register', - default => true, - enabled => true, - priority => 1, - config => { + default => true, + enabled => true, + priority => 1, + config => { 'something' => 'true', # keep in mind that keycloak only supports strings for both keys and values 'smth else' => '1', }, - alias => 'webauthn', } @example Minimal example to enable email verification without making it default keycloak_required_action { 'VERIFY_EMAIL on master': ensure => present, - provider_id => 'webauthn-register', } DESC extend PuppetX::Keycloak::Type ensurable + add_autorequires newparam(:name, namevar: true) do desc 'The required action name' @@ -38,33 +38,33 @@ desc 'realm' end - newparam(:provider_id, namevar: true) do - desc 'providerId of the required action' + newparam(:alias, namevar: true) do + desc 'Alias.' + end + + newparam(:provider_id) do + desc 'providerId of the required action. Default to `alias`' munge { |v| v.to_s } + defaultto do + @resource[:alias] + end end newproperty(:display_name) do - desc 'Displayed name. Default to `provider_id`' + desc 'Displayed name.' munge { |v| v.to_s } end newproperty(:enabled, boolean: true) do desc 'If the required action is enabled. Default to true.' - defaultto true + defaultto :true newvalues(:true, :false) munge { |v| v.to_s == 'true' } end - newproperty(:alias) do - desc 'Alias. Default to `provider_id`.' - defaultto do - @resource[:provider_id] - end - end - newproperty(:default, boolean: true) do desc 'If the required action is a default one. Default to false' - defaultto false + defaultto :false newvalues(:true, :false) munge { |v| v.to_s == 'true' } end diff --git a/manifests/init.pp b/manifests/init.pp index fd6b5806..831e42d5 100644 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -206,7 +206,7 @@ # Only necessary to set if the URL path to Keycloak is modified class keycloak ( Boolean $manage_install = true, - String $version = '18.0.0', + String $version = '19.0.3', Optional[Variant[Stdlib::HTTPUrl, Stdlib::HTTPSUrl]] $package_url = undef, Optional[Stdlib::Absolutepath] $install_dir = undef, @@ -359,15 +359,9 @@ } $wrapper_server = "${wrapper_protocol}://${wrapper_address}:${wrapper_port}${config['http-relative-path']}" - if versioncmp($version, '19.0') < 0 { - $auto_build_arg = '--auto-build' - } else { - $auto_build_arg = undef - } $service_start = [ "${install_base}/bin/kc.sh", $start_command, - $auto_build_arg, $service_extra_opts, ].filter |$s| { $s =~ NotUndef } $service_start_cmd = join($service_start, ' ') diff --git a/metadata.json b/metadata.json index 2f75bacf..a072ff65 100644 --- a/metadata.json +++ b/metadata.json @@ -89,5 +89,5 @@ ], "pdk-version": "2.1.0", "template-url": "https://github.com/treydock/pdk-templates.git#master", - "template-ref": "heads/master-0-gd5daad3" + "template-ref": "heads/master-0-gde1d67f" } diff --git a/spec/acceptance/10_required_action_spec.rb b/spec/acceptance/10_required_action_spec.rb index b03a8f13..b21388fb 100644 --- a/spec/acceptance/10_required_action_spec.rb +++ b/spec/acceptance/10_required_action_spec.rb @@ -5,15 +5,13 @@ it 'runs successfully' do pp = <<-EOS class { 'keycloak': } - - -> keycloak_realm { 'test': ensure => 'present' } - - -> keycloak_required_action { 'custom-alias on test': - ensure => 'present', - provider_id => 'webauthn-register', - default => true, - enabled => true, - priority => 200, + keycloak_realm { 'test': ensure => 'present' } + keycloak_required_action { 'webauthn-register on test': + ensure => 'present', + display_name => 'Webauthn Register', + default => true, + enabled => true, + priority => 200, } EOS @@ -22,9 +20,9 @@ class { 'keycloak': } end it 'has configured a required action' do - on hosts, '/opt/keycloak/bin/kcadm-wrapper.sh get authentication/required-actions/custom-alias -r test' do + on hosts, '/opt/keycloak/bin/kcadm-wrapper.sh get authentication/required-actions/webauthn-register -r test' do data = JSON.parse(stdout) - expect(data['alias']).to eq('custom-alias') + expect(data['alias']).to eq('webauthn-register') expect(data['defaultAction']).to eq(true) expect(data['enabled']).to eq(true) expect(data['priority']).to eq(200) @@ -34,7 +32,7 @@ class { 'keycloak': } it 'has the configured required action in list' do on hosts, '/opt/keycloak/bin/kcadm-wrapper.sh get authentication/required-actions -r test' do data = JSON.parse(stdout) - webauthn = data.find { |d| d['alias'] == 'custom-alias' } + webauthn = data.find { |d| d['alias'] == 'webauthn-register' } expect(webauthn['priority']).to eq(200) end end @@ -44,13 +42,10 @@ class { 'keycloak': } it 'runs successfully' do pp = <<-EOS class { 'keycloak': } - - -> keycloak_realm { 'test': ensure => 'present' } - - -> keycloak_required_action { 'custom-alias on test': + keycloak_realm { 'test': ensure => 'present' } + keycloak_required_action { 'webauthn-register on test': ensure => 'present', - provider_id => 'webauthn-register', - display_name => 'updated name', + display_name => 'Webauthn Register', default => true, enabled => true, priority => 100, @@ -62,9 +57,8 @@ class { 'keycloak': } end it 'has updated a required action' do - on hosts, '/opt/keycloak/bin/kcadm-wrapper.sh get authentication/required-actions/custom-alias -r test' do + on hosts, '/opt/keycloak/bin/kcadm-wrapper.sh get authentication/required-actions/webauthn-register -r test' do data = JSON.parse(stdout) - expect(data['name']).to eq('updated name') expect(data['priority']).to eq(100) end end @@ -74,8 +68,8 @@ class { 'keycloak': } it 'runs successfully' do pp = <<-EOS class { 'keycloak': } - -> keycloak_required_action { 'custom-alias on test': - ensure => 'absent' + keycloak_required_action { 'webauthn-register on test': + ensure => 'absent', } EOS @@ -86,7 +80,7 @@ class { 'keycloak': } it 'has deleted a flow' do on hosts, '/opt/keycloak/bin/kcadm-wrapper.sh get authentication/required-actions -r test' do data = JSON.parse(stdout) - d = data.select { |o| o['alias'] == 'custom-alias' }[0] + d = data.select { |o| o['alias'] == 'webauthn-register' }[0] expect(d).to be_nil end end diff --git a/spec/acceptance/6_protocol_mapper_spec.rb b/spec/acceptance/6_protocol_mapper_spec.rb index 0f22c25b..a22495d7 100644 --- a/spec/acceptance/6_protocol_mapper_spec.rb +++ b/spec/acceptance/6_protocol_mapper_spec.rb @@ -163,7 +163,13 @@ class { 'keycloak': } context 'creates saml protocol_mapper' do it 'runs successfully' do pp = <<-EOS - class { 'keycloak': } + class { 'keycloak': + features => ['scripts'], + } + keycloak::spi_deployment { 'mappers': + deployed_name => 'mappers.jar', + source => 'file:///tmp/mappers.jar', + } keycloak_realm { 'test': ensure => 'present' } keycloak_client_scope { 'saml on test': ensure => 'present', @@ -183,12 +189,12 @@ class { 'keycloak': } friendly_name => 'firstName', attribute_name => 'firstName', } - keycloak_protocol_mapper { "displayName for saml on test": - protocol => 'saml', - type => 'saml-javascript-mapper', - script => "var foo = 'bar';\\nfoo;", - friendly_name => 'displayName', - attribute_name => 'displayName', + keycloak_protocol_mapper { 'x500 displayName for saml on test': + protocol => 'saml', + type => 'script-x500-displayName.js', + attribute_nameformat => 'uri', + friendly_name => 'displayName', + attribute_name => 'urn:oid:2.16.840.1.113730.3.1.241', } EOS @@ -226,14 +232,13 @@ class { 'keycloak': } end end - it 'has created protocol mapper displayName' do + it 'has created protocol mapper from script' do on hosts, '/opt/keycloak/bin/kcadm-wrapper.sh get client-scopes/saml/protocol-mappers/models -r test' do data = JSON.parse(stdout) - mapper = data.select { |d| d['name'] == 'displayName' }[0] - expect(mapper['protocolMapper']).to eq('saml-javascript-mapper') - expect(mapper['config']['attribute.name']).to eq('displayName') - expect(mapper['config']['Script']).to match(%r{^var foo = 'bar';$}) - expect(mapper['config']['Script']).to match(%r{^foo;$}) + mapper = data.select { |d| d['name'] == 'x500 displayName' }[0] + expect(mapper['protocolMapper']).to eq('script-x500-displayName.js') + expect(mapper['config']['attribute.name']).to eq('urn:oid:2.16.840.1.113730.3.1.241') + expect(mapper['config']['attribute.nameformat']).to eq('URI Reference') expect(mapper['config']['friendly.name']).to eq('displayName') end end diff --git a/spec/acceptance/nodesets/el8.yml b/spec/acceptance/nodesets/el8.yml index 8ced0b7d..cc813a28 100644 --- a/spec/acceptance/nodesets/el8.yml +++ b/spec/acceptance/nodesets/el8.yml @@ -11,7 +11,7 @@ HOSTS: docker_image_commands: - 'dnf install -y dnf-utils' - 'dnf config-manager --set-enabled powertools' - - 'dnf install -y wget which cronie iproute initscripts langpacks-en glibc-all-langpacks cpio' + - 'dnf install -y wget which cronie iproute initscripts langpacks-en glibc-all-langpacks glibc-langpack-en cpio' docker_env: - LANG=en_US.UTF-8 - LANGUAGE=en_US.UTF-8 diff --git a/spec/acceptance/nodesets/el9.yml b/spec/acceptance/nodesets/el9.yml index fbcb8bab..c3cc916f 100644 --- a/spec/acceptance/nodesets/el9.yml +++ b/spec/acceptance/nodesets/el9.yml @@ -11,7 +11,7 @@ HOSTS: docker_image_commands: - 'dnf install -y dnf-utils' - 'dnf config-manager --set-enabled crb' - - 'dnf install -y wget which cronie iproute initscripts langpacks-en glibc-all-langpacks cpio' + - 'dnf install -y wget which cronie iproute initscripts langpacks-en glibc-all-langpacks glibc-langpack-en cpio' docker_env: - LANG=en_US.UTF-8 - LANGUAGE=en_US.UTF-8 diff --git a/spec/classes/init_spec.rb b/spec/classes/init_spec.rb index f036510e..cdccc23e 100644 --- a/spec/classes/init_spec.rb +++ b/spec/classes/init_spec.rb @@ -6,7 +6,7 @@ let(:facts) do facts.merge(concat_basedir: '/dne') end - let(:version) { '18.0.0' } + let(:version) { '19.0.3' } case facts[:osfamily] when %r{RedHat} @@ -149,7 +149,7 @@ context 'keycloak::service' do it do is_expected.to contain_systemd__unit_file('keycloak.service').with( - content: %r{ExecStart=/opt/keycloak-18.0.0/bin/kc.sh start --auto-build$} + content: %r{ExecStart=/opt/keycloak-#{version}/bin/kc.sh start$} ) end @@ -170,16 +170,6 @@ ) end end - - context 'with newer version' do - let(:params) { { version: '19.0.0' } } - - it do - is_expected.to contain_systemd__unit_file('keycloak.service').with( - content: %r{ExecStart=/opt/keycloak-19.0.0/bin/kc.sh start$} - ) - end - end end end # end context end # end on_supported_os loop diff --git a/spec/defines/spi_deployment_spec.rb b/spec/defines/spi_deployment_spec.rb index f46ab636..1426aa88 100644 --- a/spec/defines/spi_deployment_spec.rb +++ b/spec/defines/spi_deployment_spec.rb @@ -6,7 +6,7 @@ let(:facts) do facts.merge(concat_basedir: '/dne') end - let(:version) { '18.0.0' } + let(:version) { '19.0.3' } let(:title) { 'duo-spi' } let(:params) { { deployed_name: 'keycloak-duo-spi-jar-with-dependencies.jar', source: 'https://example.com/files/keycloak-duo-spi-jar-with-dependencies.jar' } } diff --git a/spec/fixtures/mappers.jar b/spec/fixtures/mappers.jar new file mode 100644 index 00000000..7c6dfabc Binary files /dev/null and b/spec/fixtures/mappers.jar differ diff --git a/spec/fixtures/mappers/META-INF/keycloak-scripts.json b/spec/fixtures/mappers/META-INF/keycloak-scripts.json new file mode 100644 index 00000000..e0bb8cd1 --- /dev/null +++ b/spec/fixtures/mappers/META-INF/keycloak-scripts.json @@ -0,0 +1,12 @@ +{ + "authenticators": [], + "policies": [], + "mappers": [], + "saml-mappers": [ + { + "name": "X500 displayName", + "fileName": "x500-displayName.js", + "description": "X500 displayName" + } + ] +} diff --git a/spec/fixtures/mappers/x500-displayName.js b/spec/fixtures/mappers/x500-displayName.js new file mode 100644 index 00000000..e4c52424 --- /dev/null +++ b/spec/fixtures/mappers/x500-displayName.js @@ -0,0 +1 @@ +user.getFirstName() + ' ' + user.getLastName(); diff --git a/spec/spec_helper_acceptance_setup.rb b/spec/spec_helper_acceptance_setup.rb index cbf9fbf7..5e546853 100644 --- a/spec/spec_helper_acceptance_setup.rb +++ b/spec/spec_helper_acceptance_setup.rb @@ -1,7 +1,7 @@ RSpec.configure do |c| c.add_setting :keycloak_version keycloak_version = if ENV['BEAKER_keycloak_version'].nil? || ENV['BEAKER_keycloak_version'].empty? - '18.0.0' + '19.0.3' else ENV['BEAKER_keycloak_version'] end @@ -12,6 +12,7 @@ proj_root = File.expand_path(File.join(File.dirname(__FILE__), '..')) scp_to(hosts, File.join(proj_root, 'spec/fixtures/keycloak-duo-spi-jar-with-dependencies.jar'), '/tmp/keycloak-duo-spi-jar-with-dependencies.jar') +scp_to(hosts, File.join(proj_root, 'spec/fixtures/mappers.jar'), '/tmp/mappers.jar') hiera_yaml = <<-EOS --- diff --git a/spec/unit/puppet/type/keycloak_client_protocol_mapper_spec.rb b/spec/unit/puppet/type/keycloak_client_protocol_mapper_spec.rb index ebb22e23..dc66a8cb 100644 --- a/spec/unit/puppet/type/keycloak_client_protocol_mapper_spec.rb +++ b/spec/unit/puppet/type/keycloak_client_protocol_mapper_spec.rb @@ -330,18 +330,14 @@ }.to raise_error(%r{foo}) end - it 'accepts value for script' do + it 'accepts script' do config[:protocol] = 'saml' - config[:type] = 'saml-javascript-mapper' - config[:script] = 'foobar' - expect(resource[:script]).to eq('foobar') - end - - it 'accepts value with newline for script' do - config[:protocol] = 'saml' - config[:type] = 'saml-javascript-mapper' - config[:script] = 'foobar\nbaz' - expect(resource[:script]).to eq('foobar\nbaz') + config[:type] = 'script-foo.js' + config[:single] = true + config[:attribute_name] = 'foo' + config[:attribute_nameformat] = 'uri' + config[:friendly_name] = 'foo' + expect(resource[:type]).to eq('script-foo.js') end it 'accepts value for included_client_audience' do diff --git a/spec/unit/puppet/type/keycloak_protocol_mapper_spec.rb b/spec/unit/puppet/type/keycloak_protocol_mapper_spec.rb index e4e963ed..af2d40d0 100644 --- a/spec/unit/puppet/type/keycloak_protocol_mapper_spec.rb +++ b/spec/unit/puppet/type/keycloak_protocol_mapper_spec.rb @@ -330,26 +330,22 @@ }.to raise_error(%r{foo}) end - it 'accepts value for script' do - config[:protocol] = 'saml' - config[:type] = 'saml-javascript-mapper' - config[:script] = 'foobar' - expect(resource[:script]).to eq('foobar') - end - - it 'accepts value with newline for script' do - config[:protocol] = 'saml' - config[:type] = 'saml-javascript-mapper' - config[:script] = 'foobar\nbaz' - expect(resource[:script]).to eq('foobar\nbaz') - end - it 'accepts value for included_client_audience' do config[:type] = 'oidc-audience-mapper' config[:included_client_audience] = 'foo' expect(resource[:included_client_audience]).to eq('foo') end + it 'accepts script' do + config[:protocol] = 'saml' + config[:type] = 'script-foo.js' + config[:single] = true + config[:attribute_name] = 'foo' + config[:attribute_nameformat] = 'uri' + config[:friendly_name] = 'foo' + expect(resource[:type]).to eq('script-foo.js') + end + it 'requires included_client_audience for oidc-audience-mapper' do config[:type] = 'oidc-audience-mapper' expect { resource }.to raise_error(%r{included_client_audience}) diff --git a/spec/unit/puppet/type/keycloak_required_action_spec.rb b/spec/unit/puppet/type/keycloak_required_action_spec.rb index 31a1c6af..d1a7a606 100644 --- a/spec/unit/puppet/type/keycloak_required_action_spec.rb +++ b/spec/unit/puppet/type/keycloak_required_action_spec.rb @@ -24,14 +24,15 @@ end it 'has alias default to provider_id' do - config.delete(:alias) - expect(resource[:alias]).to eq('some-provider') + config.delete(:provider_id) + expect(resource[:provider_id]).to eq('something') end it 'handles componsite name' do - component = described_class.new(name: 'foo on test', provider_id: 'provider') + component = described_class.new(name: 'foo on test') expect(component[:name]).to eq('foo on test') expect(component[:alias]).to eq('foo') + expect(component[:provider_id]).to eq('foo') expect(component[:realm]).to eq('test') end @@ -149,11 +150,6 @@ config.delete(:alias) expect { resource }.to raise_error(%r{must have a alias defined}) end - it 'requires provider_id when present' do - config.delete(:provider_id) - config[:ensure] = 'present' - expect { resource }.to raise_error(%r{provider_id is required}) - end it 'does not require provider_id for absent' do config.delete(:provider_id) config[:ensure] = 'absent'