diff --git a/Gemfile b/Gemfile index 5c716436cce..6e26c4bc037 100644 --- a/Gemfile +++ b/Gemfile @@ -290,7 +290,7 @@ end group :appliance, :optional => true do gem "irb", "=1.4.1", :require => false # Locked to same version as the installed RPM rubygem-irb-1.4.1-142.module_el9+787+b20bfeee.noarch so that we don't bundle our own - gem "manageiq-appliance_console", "~>9.1", ">=9.1.1", :require => false + gem "manageiq-appliance_console", "~>10.0", :require => false gem "rdoc", :require => false # Needed for rails console end diff --git a/app/models/authenticator/httpd.rb b/app/models/authenticator/httpd.rb index b81bed98f46..9dbd83d6910 100644 --- a/app/models/authenticator/httpd.rb +++ b/app/models/authenticator/httpd.rb @@ -151,7 +151,7 @@ def user_details_from_headers(username, request) user_headers.each { |k, v| log_auth_debug(" %-24{key} = \"%{val}\"" % {:key => k, :val => v}) } end - delimiter = self.class.group_delimiter || /[;:,]/ + delimiter = self.class.group_delimiter || user_headers['X-REMOTE-USER-GROUP-DELIMITER'].presence || /[;:,]/ groups = CGI.unescape(user_headers['X-REMOTE-USER-GROUPS'] || '').split(delimiter) user_attrs = {:username => username, :fullname => user_headers['X-REMOTE-USER-FULLNAME'], @@ -172,6 +172,7 @@ def user_details_from_headers(username, request) X-REMOTE-USER-EMAIL X-REMOTE-USER-DOMAIN X-REMOTE-USER-GROUPS + X-REMOTE-USER-GROUP-DELIMITER ].each_with_object({}) do |k, h| h[k] = request.headers[k]&.force_encoding("UTF-8") end.delete_nils diff --git a/spec/models/authenticator/httpd_spec.rb b/spec/models/authenticator/httpd_spec.rb index 4ccb3ad5f91..af496e4e08f 100644 --- a/spec/models/authenticator/httpd_spec.rb +++ b/spec/models/authenticator/httpd_spec.rb @@ -738,6 +738,50 @@ def authenticate end end + context "using custom delimiter in settings (despite a header)" do + let(:config) { {:httpd_role => true, :group_delimiter => "|"} } + let(:headers) do + super().merge('X-Remote-User-Groups' => 'wibble,wobble@fqdn|bubble@fqdn', 'X-Remote-User-Group-Delimiter' => ",") + end + let(:user_attrs) do + { + :username => "testuser", + :fullname => "Test User", + :firstname => "Alice", + :lastname => "Aardvark", + :email => "testuser@example.com", + :domain => "example.com" + } + end + + it "parses group names that contain characters from header" do + expect(subject).to receive(:find_external_identity).with(username, user_attrs, ["wibble,wobble@fqdn", "bubble@fqdn"]) + authenticate + end + end + + context "using header delimiter" do + let(:config) { {:httpd_role => true} } + let(:headers) do + super().merge('X-Remote-User-Groups' => 'wibble:wobble@fqdn,bubble@fqdn', 'X-Remote-User-Group-Delimiter' => ",") + end + let(:user_attrs) do + { + :username => "testuser", + :fullname => "Test User", + :firstname => "Alice", + :lastname => "Aardvark", + :email => "testuser@example.com", + :domain => "example.com" + } + end + + it "parses group names that contain characters from default delimiter" do + expect(subject).to receive(:find_external_identity).with(username, user_attrs, ["wibble:wobble@fqdn", "bubble@fqdn"]) + authenticate + end + end + context "when group names have escaped special characters" do let(:config) { {:httpd_role => true} } let(:headers) do @@ -769,6 +813,27 @@ def authenticate authenticate end end + + context "when there are no group names (but a group header)" do + let(:config) { {:httpd_role => true} } + let(:headers) do + { + 'X-Remote-User' => 'testuser', + 'X-Remote-User-FullName' => 'Test User', + 'X-Remote-User-FirstName' => 'Alice', + 'X-Remote-User-LastName' => 'Aardvark', + 'X-Remote-User-Email' => 'testuser@example.com', + 'X-Remote-User-Domain' => 'example.com', + 'X-Remote-User-Groups' => nil, + 'X-Remote-User-Group-Delimiter' => nil + } + end + + it "handles nil group names" do + expect(subject).to receive(:find_external_identity).with(username, user_attrs, []) + authenticate + end + end end end end