From fad7b9bc171dccd3598806f6d6bb6d6e20777856 Mon Sep 17 00:00:00 2001 From: Trey Dockendorf Date: Mon, 24 Jun 2024 09:41:33 -0400 Subject: [PATCH] BREAKING: Support Keycloak 25 See README for details on breaking changes --- .github/workflows/ci.yaml | 10 +- .sync.yml | 6 +- README.md | 28 +++- lib/puppet/provider/keycloak_flow/kcadm.rb | 37 +---- .../provider/keycloak_flow_execution/kcadm.rb | 39 +---- lib/puppet/type/keycloak_client.rb | 1 - lib/puppet/type/keycloak_flow.rb | 18 +-- lib/puppet/type/keycloak_flow_execution.rb | 22 +-- manifests/init.pp | 4 +- metadata.json | 2 +- spec/acceptance/9_flow_spec.rb | 140 +++++++----------- spec/acceptance/nodesets/el8.yml | 4 + spec/classes/init_spec.rb | 2 +- spec/defines/partial_import_spec.rb | 2 +- spec/defines/spi_deployment_spec.rb | 2 +- spec/spec_helper_acceptance_setup.rb | 5 +- .../provider/keycloak_flow/kcadm_spec.rb | 36 ----- .../keycloak_flow_execution/kcadm_spec.rb | 34 +---- spec/unit/puppet/type/keycloak_client_spec.rb | 1 - .../type/keycloak_flow_execution_spec.rb | 26 ++-- spec/unit/puppet/type/keycloak_flow_spec.rb | 30 ++-- types/configs.pp | 11 +- 22 files changed, 160 insertions(+), 300 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 25096d87..940c827c 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -16,11 +16,11 @@ jobs: fail-fast: false matrix: include: - - ruby: 2.7.7 + - ruby: 2.7.8 puppet: 7 fixtures: .fixtures.yml allow_failure: false - - ruby: 3.2.2 + - ruby: 3.2.3 puppet: 8 fixtures: .fixtures.yml allow_failure: false @@ -65,17 +65,17 @@ jobs: - "puppet7" - "puppet8" keycloak_version: - - "24.0.5" + - "25.0.1" keycloak_full: - "no" include: - set: "el8" puppet: "puppet7" - keycloak_version: "24.0.5" + keycloak_version: "25.0.1" keycloak_full: "yes" - set: "el8" puppet: "puppet8" - keycloak_version: "24.0.5" + keycloak_version: "25.0.1" keycloak_full: "yes" env: BUNDLE_WITHOUT: development:release diff --git a/.sync.yml b/.sync.yml index 20823fdc..18fca20c 100644 --- a/.sync.yml +++ b/.sync.yml @@ -25,16 +25,16 @@ Rakefile: - puppet7 - puppet8 keycloak_version: - - '24.0.5' + - '25.0.1' keycloak_full: ['no'] acceptance_includes: - set: el8 puppet: puppet7 - keycloak_version: '24.0.5' + keycloak_version: '25.0.1' keycloak_full: 'yes' - set: el8 puppet: puppet8 - keycloak_version: '24.0.5' + keycloak_version: '25.0.1' keycloak_full: 'yes' .gitignore: paths: diff --git a/README.md b/README.md index de09ee6d..ff65abd3 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,7 @@ #### Table of Contents 1. [Overview](#overview) + * [Upgrade to 12.x](#upgrade-to-12x) * [Upgrade to 8.x](#upgrade-to-8x) * [Changes to LDAP user provider IDs](#changes-to-ldap-user-provider-ids) * [Supported Versions of Keycloak](#supported-versions-of-keycloak) @@ -35,6 +36,23 @@ The keycloak module allows easy installation and management of Keycloak. +### Upgrade to 12.x + +Version 12.x of this module had some major breaking changes to support Keycloak 25.x. + +The `keycloak_flow` and `keycloak_flow_execution` types had their `index` property replaced by `priority`. If you had executions with `index` 0,1,2 you'd need to set `priority` to something like 10,20,30. + +The configuration options switched to using Hostname v2 options. + +* `hostname` now accepts a URL +* `hostname-url` is removed +* `hostname-path` is removed +* `hostname-port` is removed +* `hostname-admin` now requires a URL +* `hostname-admin-url` is removed +* `hostname-strict-backchannel` is renamed to `hostname-backchannel-dynamic` +* `hostname-strict-https` is removed + ### Upgrade to 8.x This module underwent major changes in the 8.0.0 release to support Keycloak that uses Quarkus. @@ -523,19 +541,19 @@ keycloak_flow_execution { 'auth-cookie under browser-with-duo on test': ensure => 'present', configurable => false, display_name => 'Cookie', - index => 0, + priority => 10, requirement => 'ALTERNATIVE', } keycloak_flow_execution { 'identity-provider-redirector under browser-with-duo on test': ensure => 'present', configurable => true, display_name => 'Identity Provider Redirector', - index => 1, + priority => 15, requirement => 'ALTERNATIVE', } keycloak_flow { 'form-browser-with-duo under browser-with-duo on test': ensure => 'present', - index => 2, + priority => 20, requirement => 'ALTERNATIVE', top_level => false, } @@ -543,7 +561,7 @@ keycloak_flow_execution { 'auth-username-password-form under form-browser-with-d ensure => 'present', configurable => false, display_name => 'Username Password Form', - index => 0, + priority => 10, requirement => 'REQUIRED', } keycloak_flow_execution { 'duo-universal under form-browser-with-duo on test': @@ -558,7 +576,7 @@ keycloak_flow_execution { 'duo-universal under form-browser-with-duo on test': "duoGroups" => "duo" }, requirement => 'REQUIRED', - index => 1, + priority => 15, } ``` diff --git a/lib/puppet/provider/keycloak_flow/kcadm.rb b/lib/puppet/provider/keycloak_flow/kcadm.rb index 43df134f..8686a28f 100644 --- a/lib/puppet/provider/keycloak_flow/kcadm.rb +++ b/lib/puppet/provider/keycloak_flow/kcadm.rb @@ -63,6 +63,7 @@ def self.instances flow[:realm] = realm flow[:description] = e['description'] flow[:index] = e['index'] + flow[:priority] = e['priority'] flow[:display_name] = e['displayName'] flow[:alias] = e['displayName'] if e['level'] != 0 @@ -105,6 +106,7 @@ def create data[:provider] = resource[:type] data[:description] = resource[:description] data[:type] = resource[:provider_id] + data[:priority] = resource[:priority] url = "authentication/flows/#{resource[:flow_alias]}/executions/flow" end t = Tempfile.new('keycloak_flow') @@ -134,7 +136,8 @@ def create unless execution_id.nil? update_data = { id: execution_id, - requirement: resource[:requirement] + requirement: resource[:requirement], + priority: resource[:priority] } t = Tempfile.new('keycloak_flow_execution') t.write(JSON.pretty_generate(update_data)) @@ -181,19 +184,6 @@ def initialize(value = {}) end end - def current_priority - data = {} - begin - output = kcadm('get', "authentication/executions/#{id}", resource[:realm]) - data = JSON.parse(output) - rescue Puppet::ExecutionFailure => e - Puppet.debug("kcadm get execution failed\nError message: #{e.message}") - rescue JSON::ParserError - Puppet.debug('Unable to parse output from kcadm get execution') - end - data['priority'] || resource[:index] - end - def flush unless @property_flush.empty? data = {} @@ -204,10 +194,11 @@ def flush data[:providerId] = resource[:provider_id] data[:topLevel] = true url = "authentication/flows/#{id}" - elsif @property_flush[:requirement] + elsif @property_flush[:requirement] || @property_flush[:priority] data[:id] = id data[:description] = resource[:description] data[:requirement] = resource[:requirement] + data[:priority] = resource[:priority] url = "authentication/flows/#{resource[:flow_alias]}/executions" end unless data.empty? @@ -221,22 +212,6 @@ def flush raise Puppet::Error, "kcadm update flow failed\nError message: #{e.message}" end end - if resource[:top_level] == :false && @property_flush[:index] - index_difference = current_priority - @property_flush[:index] - if index_difference.zero? - Puppet.notice("Index difference for Keycloak_flow[#{resource[:name]}] is unchanged, skipping.") - elsif index_difference.negative? - incrementer = 1 - action = 'lower-priority' - else - incrementer = -1 - action = 'raise-priority' - end - while index_difference != 0 - kcadm('create', "authentication/executions/#{id}/#{action}", resource[:realm]) - index_difference += incrementer - end - end end # Collect the resources again once they've been changed (that way `puppet # resource` will show the correct values after changes have been made). diff --git a/lib/puppet/provider/keycloak_flow_execution/kcadm.rb b/lib/puppet/provider/keycloak_flow_execution/kcadm.rb index 87e8cb28..19dbbceb 100644 --- a/lib/puppet/provider/keycloak_flow_execution/kcadm.rb +++ b/lib/puppet/provider/keycloak_flow_execution/kcadm.rb @@ -49,6 +49,7 @@ def self.instances execution[:flow_alias] = f['alias'] execution[:realm] = realm execution[:index] = e['index'] + execution[:priority] = e['priority'] execution[:display_name] = e['displayName'] if e.key?('displayName') if e['level'] != 0 parent_level = levels.find { |k, _v| k == (e['level'] - 1) } @@ -104,6 +105,7 @@ def create data[:displayName] = resource[:display_name] if resource[:display_name] data[:configurable] = convert_property_value(resource[:configurable]) if resource[:configurable] data[:alias] = resource[:alias] if resource[:alias] + data[:priority] = resource[:priority] t = Tempfile.new('keycloak_flow_execution') t.write(JSON.pretty_generate(data)) t.close @@ -117,7 +119,8 @@ def create if resource[:requirement] != 'DISABLED' update_data = { id: new_id.strip, - requirement: resource[:requirement] + requirement: resource[:requirement], + priority: resource[:priority] } tu = Tempfile.new('keycloak_flow_execution_update') tu.write(JSON.pretty_generate(update_data)) @@ -173,25 +176,13 @@ def initialize(value = {}) end end - def current_priority - data = {} - begin - output = kcadm('get', "authentication/executions/#{id}", resource[:realm]) - data = JSON.parse(output) - rescue Puppet::ExecutionFailure => e - Puppet.debug("kcadm get execution failed\nError message: #{e.message}") - rescue JSON::ParserError - Puppet.debug('Unable to parse output from kcadm get execution') - end - data['priority'] || resource[:index] - end - def flush unless @property_flush.empty? - if @property_flush[:requirement] + if @property_flush[:requirement] || @property_flush[:priority] data = {} data[:id] = id - data[:requirement] = resource[:requirement] if @property_flush[:requirement] + data[:requirement] = resource[:requirement] + data[:priority] = resource[:priority] t = Tempfile.new('keycloak_flow_execution') t.write(JSON.pretty_generate(data)) t.close @@ -225,22 +216,6 @@ def flush raise Puppet::Error, "kcadm update flow execution config failed\nError message: #{e.message}" end end - if @property_flush[:index] - index_difference = current_priority - @property_flush[:index] - if index_difference.zero? - Puppet.notice("Index difference for Keycloak_flow_execution[#{resource[:name]}] is unchanged, skipping.") - elsif index_difference.negative? - incrementer = 1 - action = 'lower-priority' - else - incrementer = -1 - action = 'raise-priority' - end - while index_difference != 0 - kcadm('create', "authentication/executions/#{id}/#{action}", resource[:realm]) - index_difference += incrementer - end - end end # Collect the resources again once they've been changed (that way `puppet # resource` will show the correct values after changes have been made). diff --git a/lib/puppet/type/keycloak_client.rb b/lib/puppet/type/keycloak_client.rb index 481bc938..a3b0aa59 100644 --- a/lib/puppet/type/keycloak_client.rb +++ b/lib/puppet/type/keycloak_client.rb @@ -215,7 +215,6 @@ def insync?(is) newproperty(:web_origins, array_matching: :all, parent: PuppetX::Keycloak::ArrayProperty) do desc 'webOrigins' - defaultto [] end newproperty(:login_theme) do diff --git a/lib/puppet/type/keycloak_flow.rb b/lib/puppet/type/keycloak_flow.rb index ad270e90..519799ba 100644 --- a/lib/puppet/type/keycloak_flow.rb +++ b/lib/puppet/type/keycloak_flow.rb @@ -16,7 +16,7 @@ @example Add a flow execution to existing browser-with-duo flow keycloak_flow { 'form-browser-with-duo under browser-with-duo on test': ensure => 'present', - index => 2, + priority => 20, requirement => 'ALTERNATIVE', top_level => false, } @@ -24,8 +24,8 @@ **Autorequires** * `keycloak_realm` defined for `realm` parameter * `keycloak_flow` of `flow_alias` if `top_level=false` -* `keycloak_flow` of `flow_alias` if other `index` is lower and if `top_level=false` -* `keycloak_flow_execution` if `flow_alias` is the same and other `index` is lower and if `top_level=false` +* `keycloak_flow` of `flow_alias` if other `priority` is lower and if `top_level=false` +* `keycloak_flow_execution` if `flow_alias` is the same and other `priority` is lower and if `top_level=false` DESC extend PuppetX::Keycloak::Type @@ -88,8 +88,8 @@ defaultto(:true) end - newproperty(:index, parent: PuppetX::Keycloak::IntegerProperty) do - desc 'execution index, only applied to top_level=false, required for top_level=false' + newproperty(:priority, parent: PuppetX::Keycloak::IntegerProperty) do + desc 'execution priority, only applied to top_level=false, required for top_level=false' end newproperty(:description) do @@ -148,7 +148,7 @@ def self.title_patterns if self[:flow_alias] == resource[:alias] requires << resource.name end - if !resource[:index].nil? && !self[:index].nil? && self[:index] > resource[:index] && self[:flow_alias] == resource[:flow_alias] + if !resource[:priority].nil? && !self[:priority].nil? && self[:priority] > resource[:priority] && self[:flow_alias] == resource[:flow_alias] requires << resource.name end end @@ -162,7 +162,7 @@ def self.title_patterns next if self[:realm] != resource[:realm] next if self[:top_level] == :true - if self[:flow_alias] == resource[:flow_alias] && !self[:index].nil? && !resource[:index].nil? && self[:index] > resource[:index] + if self[:flow_alias] == resource[:flow_alias] && !self[:priority].nil? && !resource[:priority].nil? && self[:priority] > resource[:priority] requires << resource.name end end @@ -187,8 +187,8 @@ def self.title_patterns end if self[:ensure] == :present - if self[:top_level] == :false && self[:index].nil? - raise "Keycloak_flow[#{self[:name]}] index is required when top_level is false" + if self[:top_level] == :false && self[:priority].nil? + raise "Keycloak_flow[#{self[:name]}] priority is required when top_level is false" end if self[:top_level] == :false && self[:flow_alias].nil? raise "Keycloak_flow[#{self[:name]}] flow_alias is required when top_level is false" diff --git a/lib/puppet/type/keycloak_flow_execution.rb b/lib/puppet/type/keycloak_flow_execution.rb index fc70229f..2028f6c1 100644 --- a/lib/puppet/type/keycloak_flow_execution.rb +++ b/lib/puppet/type/keycloak_flow_execution.rb @@ -12,7 +12,7 @@ ensure => 'present', configurable => false, display_name => 'Cookie', - index => 0, + priority => 10, requirement => 'ALTERNATIVE', } @@ -21,7 +21,7 @@ ensure => 'present', configurable => false, display_name => 'Username Password Form', - index => 0, + priority => 10, requirement => 'REQUIRED', } @@ -39,14 +39,14 @@ "duomfa.groups" => "duo" }, requirement => 'REQUIRED', - index => 1, + priority => 20, } **Autorequires** * `keycloak_realm` defined for `realm` parameter * `keycloak_flow` of value defined for `flow_alias` -* `keycloak_flow` if they share same `flow_alias` value and the other resource `index` is lower -* `keycloak_flow_execution` if `flow_alias` is the same and other `index` is lower +* `keycloak_flow` if they share same `flow_alias` value and the other resource `priority` is lower +* `keycloak_flow_execution` if `flow_alias` is the same and other `priority` is lower DESC extend PuppetX::Keycloak::Type @@ -79,8 +79,8 @@ desc 'displayName' end - newproperty(:index, parent: PuppetX::Keycloak::IntegerProperty) do - desc 'execution index' + newproperty(:priority, parent: PuppetX::Keycloak::IntegerProperty) do + desc 'execution priority' munge { |v| v.to_i } end @@ -156,7 +156,7 @@ def self.title_patterns if self[:flow_alias] == resource[:alias] requires << resource.name end - if !resource[:index].nil? && !self[:index].nil? && self[:index] > resource[:index] && self[:flow_alias] == resource[:flow_alias] + if !resource[:priority].nil? && !self[:priority].nil? && self[:priority] > resource[:priority] && self[:flow_alias] == resource[:flow_alias] requires << resource.name end end @@ -169,7 +169,7 @@ def self.title_patterns next unless resource.instance_of?(Puppet::Type::Keycloak_flow_execution) next if self[:realm] != resource[:realm] - if self[:flow_alias] == resource[:flow_alias] && !resource[:index].nil? && !self[:index].nil? && self[:index] > resource[:index] + if self[:flow_alias] == resource[:flow_alias] && !resource[:priority].nil? && !self[:priority].nil? && self[:priority] > resource[:priority] requires << resource.name end end @@ -194,8 +194,8 @@ def self.title_patterns end if self[:ensure] == :present - if self[:index].nil? - raise "Keycloak_flow_execution[#{self[:name]}] index is required" + if self[:priority].nil? + raise "Keycloak_flow_execution[#{self[:name]}] priority is required" end if self[:flow_alias].nil? raise "Keycloak_flow_execution[#{self[:name]}] flow_alias is required" diff --git a/manifests/init.pp b/manifests/init.pp index ed5c6d87..d8ebf6f9 100644 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -222,7 +222,7 @@ # Only necessary to set if the URL path to Keycloak is modified class keycloak ( Boolean $manage_install = true, - String $version = '24.0.5', + String $version = '25.0.1', Optional[Variant[Stdlib::HTTPUrl, Stdlib::HTTPSUrl, Stdlib::Absolutepath]] $package_url= undef, Optional[Stdlib::Absolutepath] $install_dir = undef, Array[String[1]] $java_package_dependencies = [], @@ -243,7 +243,7 @@ Array $conf_dir_purge_ignore = ['cache-ispn.xml', 'README.md', 'truststore.jks'], Keycloak::Configs $configs = {}, Hash[String, Variant[String[1],Boolean,Array]] $extra_configs = {}, - Variant[Stdlib::Host, Enum['unset','UNSET']] $hostname = $facts['networking']['fqdn'], + Variant[Stdlib::Host, Stdlib::HTTPUrl, Stdlib::HTTPSUrl, Enum['unset','UNSET']] $hostname = $facts['networking']['fqdn'], Boolean $http_enabled = true, Stdlib::IP::Address $http_host = '0.0.0.0', Stdlib::Port $http_port = 8080, diff --git a/metadata.json b/metadata.json index eb6f5e8f..2bf599ed 100644 --- a/metadata.json +++ b/metadata.json @@ -81,5 +81,5 @@ ], "pdk-version": "2.7.1", "template-url": "https://github.com/treydock/pdk-templates.git#master", - "template-ref": "heads/master-0-g15e3149" + "template-ref": "heads/master-0-g50afcd2" } diff --git a/spec/acceptance/9_flow_spec.rb b/spec/acceptance/9_flow_spec.rb index 652b9276..192653b1 100644 --- a/spec/acceptance/9_flow_spec.rb +++ b/spec/acceptance/9_flow_spec.rb @@ -16,9 +16,7 @@ class { 'keycloak': } test_realm => 'test', test_before => [ 'Keycloak_flow[form-browser-with-duo]', - 'Keycloak_flow[form-browser-with-duo2]', 'Keycloak_flow_execution[duo-universal under form-browser-with-duo on test]', - 'Keycloak_flow_execution[duo-universal under form-browser-with-duo2 on test]', ], } keycloak_realm { 'test': ensure => 'present' } @@ -26,61 +24,47 @@ class { 'keycloak': } ensure => 'present', description => 'Browser with DUO', } - keycloak_flow_execution { 'duo-universal under form-browser-with-duo on test': + keycloak_flow_execution { 'auth-cookie under browser-with-duo on test': ensure => 'present', - configurable => true, - display_name => 'Duo Universal MFA', - alias => 'Duo Universal', - config => { - "duoApiHostname" => "api-foo.duosecurity.com", - "duoSecretKey" => "secret", - "duoIntegrationKey" => "foo-ikey", - "duoGroups" => "duo" - }, - requirement => 'REQUIRED', - index => 1, + configurable => false, + display_name => 'Cookie', + priority => 10, + requirement => 'ALTERNATIVE', } - keycloak_flow_execution { 'duo-universal under form-browser-with-duo2 on test': + keycloak_flow_execution { 'identity-provider-redirector under browser-with-duo on test': ensure => 'present', configurable => true, - display_name => 'Duo Universal MFA', - alias => 'Duo2 Universal', - requirement => 'REQUIRED', - index => 0, - } - keycloak_flow_execution { 'auth-username-password-form under form-browser-with-duo on test': - ensure => 'present', - configurable => false, - display_name => 'Username Password Form', - index => 0, - requirement => 'REQUIRED', + display_name => 'Identity Provider Redirector', + priority => 20, + requirement => 'ALTERNATIVE', } keycloak_flow { 'form-browser-with-duo under browser-with-duo on test': ensure => 'present', - index => 2, + priority => 30, requirement => 'ALTERNATIVE', top_level => false, description => 'Form Browser with DUO', } - keycloak_flow { 'form-browser-with-duo2 under browser-with-duo on test': - ensure => 'present', - index => 3, - requirement => 'REQUIRED', - top_level => false, - } - keycloak_flow_execution { 'auth-cookie under browser-with-duo on test': + keycloak_flow_execution { 'auth-username-password-form under form-browser-with-duo on test': ensure => 'present', configurable => false, - display_name => 'Cookie', - index => 0, - requirement => 'ALTERNATIVE', + display_name => 'Username Password Form', + priority => 10, + requirement => 'REQUIRED', } - keycloak_flow_execution { 'identity-provider-redirector under browser-with-duo on test': + keycloak_flow_execution { 'duo-universal under form-browser-with-duo on test': ensure => 'present', configurable => true, - display_name => 'Identity Provider Redirector', - index => 1, - requirement => 'ALTERNATIVE', + display_name => 'Duo Universal MFA', + alias => 'Duo Universal', + config => { + "duoApiHostname" => "api-foo.duosecurity.com", + "duoSecretKey" => "secret", + "duoIntegrationKey" => "foo-ikey", + "duoGroups" => "duo" + }, + requirement => 'REQUIRED', + priority => 20, } PUPPET_PP @@ -100,12 +84,12 @@ class { 'keycloak': } it 'has executions' do on hosts, '/opt/keycloak/bin/kcadm-wrapper.sh get authentication/flows/browser-with-duo/executions -r test' do data = JSON.parse(stdout) + form = data.find { |d| d['displayName'] == 'form-browser-with-duo' } + expect(form['index']).to eq(2) cookie = data.find { |d| d['providerId'] == 'auth-cookie' } expect(cookie['index']).to eq(0) idp = data.find { |d| d['providerId'] == 'identity-provider-redirector' } expect(idp['index']).to eq(1) - form = data.find { |d| d['displayName'] == 'form-browser-with-duo' } - expect(form['index']).to eq(2) expect(form['description']).to eq('Form Browser with DUO') auth_form = data.find { |d| d['providerId'] == 'auth-username-password-form' } expect(auth_form['index']).to eq(0) @@ -128,9 +112,7 @@ class { 'keycloak': } test_realm => 'test', test_before => [ 'Keycloak_flow[form-browser-with-duo]', - 'Keycloak_flow[form-browser-with-duo2]', 'Keycloak_flow_execution[duo-universal under form-browser-with-duo on test]', - 'Keycloak_flow_execution[duo-universal under form-browser-with-duo2 on test]', ], } keycloak_realm { 'test': ensure => 'present' } @@ -138,67 +120,47 @@ class { 'keycloak': } ensure => 'present', description => 'browser with Duo', } - keycloak_flow_execution { 'duo-universal under form-browser-with-duo on test': + keycloak_flow_execution { 'auth-cookie under browser-with-duo on test': + ensure => 'present', + configurable => false, + display_name => 'Cookie', + priority => 25, + requirement => 'ALTERNATIVE', + } + keycloak_flow_execution { 'identity-provider-redirector under browser-with-duo on test': ensure => 'present', configurable => true, - display_name => 'Duo Universal MFA', - alias => 'Duo Universal', - config => { - "duoApiHostname" => "api-foo.duosecurity.com", - "duoSecretKey" => "secret2", - "duoIntegrationKey" => "foo-ikey2", - "duoGroups" => "duo,duo2" - }, - requirement => 'REQUIRED', - index => 0, + display_name => 'Identity Provider Redirector', + priority => 15, + requirement => 'ALTERNATIVE', } - keycloak_flow_execution { 'duo-universal under form-browser-with-duo2 on test': + keycloak_flow { 'form-browser-with-duo under browser-with-duo on test': + ensure => 'present', + priority => 30, + requirement => 'REQUIRED', + top_level => false, + } + keycloak_flow_execution { 'duo-universal under form-browser-with-duo on test': ensure => 'present', configurable => true, display_name => 'Duo Universal MFA', - alias => 'Duo2 Universal', + alias => 'Duo Universal', config => { "duoApiHostname" => "api-foo.duosecurity.com", "duoSecretKey" => "secret2", "duoIntegrationKey" => "foo-ikey2", - "duoGroups" => "duo,duo2" + "duoGroups" => "duo" }, requirement => 'REQUIRED', - index => 0, + priority => 15, } keycloak_flow_execution { 'auth-username-password-form under form-browser-with-duo on test': ensure => 'present', configurable => false, display_name => 'Username Password Form', - index => 1, + priority => 25, requirement => 'REQUIRED', } - keycloak_flow { 'form-browser-with-duo under browser-with-duo on test': - ensure => 'present', - index => 2, - requirement => 'REQUIRED', - top_level => false, - } - keycloak_flow { 'form-browser-with-duo2 under browser-with-duo on test': - ensure => 'present', - index => 3, - requirement => 'REQUIRED', - top_level => false, - } - keycloak_flow_execution { 'auth-cookie under browser-with-duo on test': - ensure => 'present', - configurable => false, - display_name => 'Cookie', - index => 1, - requirement => 'ALTERNATIVE', - } - keycloak_flow_execution { 'identity-provider-redirector under browser-with-duo on test': - ensure => 'present', - configurable => true, - display_name => 'Identity Provider Redirector', - index => 0, - requirement => 'ALTERNATIVE', - } PUPPET_PP apply_manifest(pp, catch_failures: true) @@ -215,12 +177,12 @@ class { 'keycloak': } it 'has executions' do on hosts, '/opt/keycloak/bin/kcadm-wrapper.sh get authentication/flows/browser-with-duo/executions -r test' do data = JSON.parse(stdout) + form = data.find { |d| d['displayName'] == 'form-browser-with-duo' } + expect(form['index']).to eq(2) cookie = data.find { |d| d['providerId'] == 'auth-cookie' } expect(cookie['index']).to eq(1) idp = data.find { |d| d['providerId'] == 'identity-provider-redirector' } expect(idp['index']).to eq(0) - form = data.find { |d| d['displayName'] == 'form-browser-with-duo' } - expect(form['index']).to eq(2) auth_form = data.find { |d| d['providerId'] == 'auth-username-password-form' } expect(auth_form['index']).to eq(1) duo = data.find { |d| d['providerId'] == 'duo-universal' } diff --git a/spec/acceptance/nodesets/el8.yml b/spec/acceptance/nodesets/el8.yml index 8f40f510..56bbc198 100644 --- a/spec/acceptance/nodesets/el8.yml +++ b/spec/acceptance/nodesets/el8.yml @@ -17,6 +17,10 @@ HOSTS: - LANGUAGE=en_US.UTF-8 - LC_ALL=en_US.UTF-8 docker_container_name: 'keycloak-el8' + docker_port_bindings: + 8080/tcp: + - HostPort: '8080' + HostIp: '0.0.0.0' CONFIG: log_level: debug type: foss diff --git a/spec/classes/init_spec.rb b/spec/classes/init_spec.rb index 32d1b8ca..ede1c65e 100644 --- a/spec/classes/init_spec.rb +++ b/spec/classes/init_spec.rb @@ -8,7 +8,7 @@ let(:facts) do facts.merge(concat_basedir: '/dne') end - let(:version) { '24.0.5' } + let(:version) { '25.0.1' } case facts[:osfamily] when %r{RedHat} diff --git a/spec/defines/partial_import_spec.rb b/spec/defines/partial_import_spec.rb index 6655c583..f187895e 100644 --- a/spec/defines/partial_import_spec.rb +++ b/spec/defines/partial_import_spec.rb @@ -8,7 +8,7 @@ let(:facts) do facts.merge(concat_basedir: '/dne') end - let(:version) { '24.0.5' } + let(:version) { '25.0.1' } let(:title) { 'test' } let(:params) do { diff --git a/spec/defines/spi_deployment_spec.rb b/spec/defines/spi_deployment_spec.rb index a0d9419d..d03856cc 100644 --- a/spec/defines/spi_deployment_spec.rb +++ b/spec/defines/spi_deployment_spec.rb @@ -8,7 +8,7 @@ let(:facts) do facts.merge(concat_basedir: '/dne') end - let(:version) { '24.0.5' } + let(:version) { '25.0.1' } 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/spec_helper_acceptance_setup.rb b/spec/spec_helper_acceptance_setup.rb index 396509c3..af4310d2 100644 --- a/spec/spec_helper_acceptance_setup.rb +++ b/spec/spec_helper_acceptance_setup.rb @@ -3,7 +3,7 @@ RSpec.configure do |c| c.add_setting :keycloak_version keycloak_version = if ENV['BEAKER_keycloak_version'].nil? || ENV['BEAKER_keycloak_version'].empty? - '24.0.5' + '25.0.1' else ENV['BEAKER_keycloak_version'] end @@ -31,7 +31,8 @@ common_yaml = <<-COMMON_YAML --- keycloak::version: '#{RSpec.configuration.keycloak_version}' -keycloak::http_host: '127.0.0.1' +keycloak::http_host: '0.0.0.0' +keycloak::hostname: localhost keycloak::db: mariadb keycloak::proxy: edge # Force only listen on IPv4 for testing diff --git a/spec/unit/puppet/provider/keycloak_flow/kcadm_spec.rb b/spec/unit/puppet/provider/keycloak_flow/kcadm_spec.rb index a2798e06..c71cb1a5 100644 --- a/spec/unit/puppet/provider/keycloak_flow/kcadm_spec.rb +++ b/spec/unit/puppet/provider/keycloak_flow/kcadm_spec.rb @@ -121,41 +121,5 @@ resource.provider.requirement = 'ALTERNATIVE' resource.provider.flush end - - it 'lowers priority twice' do - resource[:top_level] = false - allow(resource.provider).to receive(:id).and_return('uuid') - allow(resource.provider).to receive(:current_priority).and_return(0) - expect(resource.provider).to receive(:kcadm).with('create', 'authentication/executions/uuid/lower-priority', 'test').twice - resource.provider.index = 2 - resource.provider.flush - end - - it 'lowers priority once' do - resource[:top_level] = false - allow(resource.provider).to receive(:id).and_return('uuid') - allow(resource.provider).to receive(:current_priority).and_return(0) - expect(resource.provider).to receive(:kcadm).with('create', 'authentication/executions/uuid/lower-priority', 'test').once - resource.provider.index = 1 - resource.provider.flush - end - - it 'raise priority twice' do - resource[:top_level] = false - allow(resource.provider).to receive(:id).and_return('uuid') - allow(resource.provider).to receive(:current_priority).and_return(2) - expect(resource.provider).to receive(:kcadm).with('create', 'authentication/executions/uuid/raise-priority', 'test').twice - resource.provider.index = 0 - resource.provider.flush - end - - it 'raise priority once' do - resource[:top_level] = false - allow(resource.provider).to receive(:id).and_return('uuid') - allow(resource.provider).to receive(:current_priority).and_return(1) - expect(resource.provider).to receive(:kcadm).with('create', 'authentication/executions/uuid/raise-priority', 'test').once - resource.provider.index = 0 - resource.provider.flush - end end end diff --git a/spec/unit/puppet/provider/keycloak_flow_execution/kcadm_spec.rb b/spec/unit/puppet/provider/keycloak_flow_execution/kcadm_spec.rb index ebbf295d..9690937a 100644 --- a/spec/unit/puppet/provider/keycloak_flow_execution/kcadm_spec.rb +++ b/spec/unit/puppet/provider/keycloak_flow_execution/kcadm_spec.rb @@ -11,7 +11,7 @@ realm: 'test', flow_alias: 'browser-with-duo', provider_id: 'auth-username-password-form', - index: 0) + priority: 0) end describe 'self.instances' do @@ -119,37 +119,5 @@ resource.provider.config = { 'foo' => 'bar' } resource.provider.flush end - - it 'lowers priority twice' do - allow(resource.provider).to receive(:id).and_return('uuid') - allow(resource.provider).to receive(:current_priority).and_return(0) - expect(resource.provider).to receive(:kcadm).with('create', 'authentication/executions/uuid/lower-priority', 'test').twice - resource.provider.index = 2 - resource.provider.flush - end - - it 'lowers priority once' do - allow(resource.provider).to receive(:id).and_return('uuid') - allow(resource.provider).to receive(:current_priority).and_return(0) - expect(resource.provider).to receive(:kcadm).with('create', 'authentication/executions/uuid/lower-priority', 'test').once - resource.provider.index = 1 - resource.provider.flush - end - - it 'raise priority twice' do - allow(resource.provider).to receive(:id).and_return('uuid') - allow(resource.provider).to receive(:current_priority).and_return(2) - expect(resource.provider).to receive(:kcadm).with('create', 'authentication/executions/uuid/raise-priority', 'test').twice - resource.provider.index = 0 - resource.provider.flush - end - - it 'raise priority once' do - allow(resource.provider).to receive(:id).and_return('uuid') - allow(resource.provider).to receive(:current_priority).and_return(1) - expect(resource.provider).to receive(:kcadm).with('create', 'authentication/executions/uuid/raise-priority', 'test').once - resource.provider.index = 0 - resource.provider.flush - end end end diff --git a/spec/unit/puppet/type/keycloak_client_spec.rb b/spec/unit/puppet/type/keycloak_client_spec.rb index 4465f29b..81326fb4 100644 --- a/spec/unit/puppet/type/keycloak_client_spec.rb +++ b/spec/unit/puppet/type/keycloak_client_spec.rb @@ -73,7 +73,6 @@ default_client_scopes: [], optional_client_scopes: [], redirect_uris: [], - web_origins: [], login_theme: :absent, browser_flow: :absent, direct_grant_flow: :absent diff --git a/spec/unit/puppet/type/keycloak_flow_execution_spec.rb b/spec/unit/puppet/type/keycloak_flow_execution_spec.rb index 4818fde3..160a3134 100644 --- a/spec/unit/puppet/type/keycloak_flow_execution_spec.rb +++ b/spec/unit/puppet/type/keycloak_flow_execution_spec.rb @@ -7,7 +7,7 @@ { name: 'foo', realm: 'test', - index: 0, + priority: 10, flow_alias: 'bar', provider_id: 'auth-username-password-form' } @@ -106,7 +106,7 @@ describe 'integer properties' do # Integer properties [ - :index + :priority ].each do |p| it "accepts integer for #{p}" do config[p] = 1 @@ -207,9 +207,9 @@ expect(rel.target.ref).to eq(resource.ref) end - it 'autorequires keycloak_flow of lower index' do - config[:index] = 1 - keycloak_flow = Puppet::Type.type(:keycloak_flow).new(name: 'baz under bar on test', index: 0) + it 'autorequires keycloak_flow of lower priority' do + config[:priority] = 1 + keycloak_flow = Puppet::Type.type(:keycloak_flow).new(name: 'baz under bar on test', priority: 0) catalog = Puppet::Resource::Catalog.new catalog.add_resource resource catalog.add_resource keycloak_flow @@ -218,9 +218,9 @@ expect(rel.target.ref).to eq(resource.ref) end - it 'autorequires keycloak_flow_execution of lower index' do - config[:index] = 1 - keycloak_flow_execution = Puppet::Type.type(:keycloak_flow_execution).new(name: 'baz under bar on test', index: 0) + it 'autorequires keycloak_flow_execution of lower priority' do + config[:priority] = 1 + keycloak_flow_execution = Puppet::Type.type(:keycloak_flow_execution).new(name: 'baz under bar on test', priority: 0) catalog = Puppet::Resource::Catalog.new catalog.add_resource resource catalog.add_resource keycloak_flow_execution @@ -251,14 +251,14 @@ expect { resource }.to raise_error(%r{must have a realm defined}) end - it 'requires index when present' do - config.delete(:index) + it 'requires priority when present' do + config.delete(:priority) config[:ensure] = 'present' - expect { resource }.to raise_error(%r{index is required}) + expect { resource }.to raise_error(%r{priority is required}) end - it 'does not require index for absent' do - config.delete(:index) + it 'does not require priority for absent' do + config.delete(:priority) config[:ensure] = 'absent' expect { resource }.not_to raise_error end diff --git a/spec/unit/puppet/type/keycloak_flow_spec.rb b/spec/unit/puppet/type/keycloak_flow_spec.rb index dee524e2..f281b600 100644 --- a/spec/unit/puppet/type/keycloak_flow_spec.rb +++ b/spec/unit/puppet/type/keycloak_flow_spec.rb @@ -7,7 +7,7 @@ { name: 'foo', realm: 'test', - index: 0, + priority: 10, flow_alias: 'bar' } end @@ -113,7 +113,7 @@ describe 'integer properties' do # Integer properties [ - :index + :priority ].each do |p| it "accepts integer for #{p}" do config[p] = 1 @@ -233,10 +233,10 @@ expect(rel.target.ref).to eq(resource.ref) end - it 'autorequires keycloak_flow of lower index' do + it 'autorequires keycloak_flow of lower priority' do config[:top_level] = false - config[:index] = 1 - keycloak_flow = Puppet::Type.type(:keycloak_flow).new(name: 'baz under bar on test', index: 0) + config[:priority] = 1 + keycloak_flow = Puppet::Type.type(:keycloak_flow).new(name: 'baz under bar on test', priority: 0) catalog = Puppet::Resource::Catalog.new catalog.add_resource resource catalog.add_resource keycloak_flow @@ -245,10 +245,10 @@ expect(rel.target.ref).to eq(resource.ref) end - it 'autorequires keycloak_flow_execution of lower index' do + it 'autorequires keycloak_flow_execution of lower priority' do config[:top_level] = false - config[:index] = 1 - keycloak_flow_execution = Puppet::Type.type(:keycloak_flow_execution).new(name: 'baz under bar on test', index: 0) + config[:priority] = 1 + keycloak_flow_execution = Puppet::Type.type(:keycloak_flow_execution).new(name: 'baz under bar on test', priority: 0) catalog = Puppet::Resource::Catalog.new catalog.add_resource resource catalog.add_resource keycloak_flow_execution @@ -294,21 +294,21 @@ expect { resource }.to raise_error(%r{must have a realm defined}) end - it 'requires index when present' do - config.delete(:index) + it 'requires priority when present' do + config.delete(:priority) config[:top_level] = false config[:ensure] = 'present' - expect { resource }.to raise_error(%r{index is required}) + expect { resource }.to raise_error(%r{priority is required}) end - it 'does not require index for absent' do - config.delete(:index) + it 'does not require priority for absent' do + config.delete(:priority) config[:ensure] = 'absent' expect { resource }.not_to raise_error end - it 'does not require index for top level' do - config.delete(:index) + it 'does not require priority for top level' do + config.delete(:priority) config[:ensure] = 'present' config[:top_level] = true expect { resource }.not_to raise_error diff --git a/types/configs.pp b/types/configs.pp index eb1462e2..9f321b28 100644 --- a/types/configs.pp +++ b/types/configs.pp @@ -28,16 +28,11 @@ Optional['transaction-xa-enabled'] => Boolean, Optional['features'] => Array[String[1]], Optional['features-disabled'] => Array[String[1]], - Optional['hostname'] => Stdlib::Host, - Optional['hostname-admin'] => Stdlib::Host, - Optional['hostname-admin-url'] => String[1], + Optional['hostname'] => Variant[Stdlib::Host, Stdlib::HTTPUrl, Stdlib::HTTPSUrl], + Optional['hostname-admin'] => Variant[Stdlib::HTTPUrl, Stdlib::HTTPSUrl], + Optional['hostname-backchannel-dynamic'] => Boolean, Optional['hostname-debug'] => Boolean, - Optional['hostname-path'] => String[1], - Optional['hostname-port'] => Stdlib::Port, Optional['hostname-strict'] => Boolean, - Optional['hostname-strict-backchannel'] => Boolean, - Optional['hostname-strict-https'] => Boolean, - Optional['hostname-url'] => String[1], Optional['http-enabled'] => Boolean, Optional['http-host'] => Stdlib::Host, Optional['http-max-queued-requests'] => Integer,