# Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/ require 'keycloak/admin' module ZammadSpecSupportSAML def saml_configure_keycloak(zammad_saml_metadata:, saml_client_json:) # Setup Keycloak SAML authentication. if !Keycloak::Admin.configured? Keycloak::Admin.configure do |config| config.username = ENV['KEYCLOAK_ADMIN_USER'] config.password = ENV['KEYCLOAK_ADMIN_PASSWORD'] config.realm = 'zammad' config.base_url = ENV['KEYCLOAK_BASE_URL'] end end # Force create Zammad client in Keycloak. client = Keycloak::Admin.clients.lookup(clientId: zammad_saml_metadata) if client.count.positive? Keycloak::Admin.clients.delete(client.first['id']) end Keycloak::Admin.clients.create(JSON.parse(saml_client_json)) end def saml_configure_zammad(saml_base_url:, saml_realm_zammad_descriptor:, name_identifier_format: nil, uid_attribute: nil, idp_slo_service_url: true, security: nil) # Setup Zammad SAML authentication. response = UserAgent.get(saml_realm_zammad_descriptor) raise 'No Zammad realm descriptor found' if !response.success? match = response.body.match(%r{(?.+)}) raise 'No X509Certificate found' if !match[:cert] auth_saml_credentials = { display_name: 'SAML', idp_sso_target_url: "#{saml_base_url}/realms/zammad/protocol/saml", idp_cert: "-----BEGIN CERTIFICATE-----\n#{match[:cert]}\n-----END CERTIFICATE-----", name_identifier_format: name_identifier_format || 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress', } auth_saml_credentials[:idp_slo_service_url] = "#{saml_base_url}/realms/zammad/protocol/saml" if idp_slo_service_url auth_saml_credentials[:uid_attribute] = uid_attribute if uid_attribute if security.present? auth_saml_credentials[:security] = 'on' auth_saml_credentials[:certificate] = "-----BEGIN CERTIFICATE-----\n#{security[:cert]}\n-----END CERTIFICATE-----" auth_saml_credentials[:private_key] = "-----BEGIN RSA PRIVATE KEY-----\n#{security[:key]}\n-----END RSA PRIVATE KEY-----" # gitleaks:allow auth_saml_credentials[:private_key_secret] = '' end # Disable setting validation. We have an explicit test for this. setting = Setting.find_by(name: 'auth_saml_credentials') setting.state_current = { value: auth_saml_credentials } setting.save!(validate: false) Setting.set('auth_saml', true) end def saml_login_keycloak find_by_id('kc-form') expect(page).to have_current_path(%r{/realms/zammad/protocol/saml\?SAMLRequest=.+}) expect(page).to have_css('#kc-form-login') within '#kc-form-login' do fill_in 'username', with: 'john.doe' fill_in 'password', with: 'test' click_on 'Sign In' end end end RSpec.configure do |config| config.include ZammadSpecSupportSAML, integration_standalone: :saml end