saml.rb 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. # Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
  2. require 'keycloak/admin'
  3. module ZammadSpecSupportSAML
  4. def saml_configure_keycloak(zammad_saml_metadata:, saml_client_json:)
  5. # Setup Keycloak SAML authentication.
  6. if !Keycloak::Admin.configured?
  7. Keycloak::Admin.configure do |config|
  8. config.username = ENV['KEYCLOAK_ADMIN_USER']
  9. config.password = ENV['KEYCLOAK_ADMIN_PASSWORD']
  10. config.realm = 'zammad'
  11. config.base_url = ENV['KEYCLOAK_BASE_URL']
  12. end
  13. end
  14. # Force create Zammad client in Keycloak.
  15. client = Keycloak::Admin.clients.lookup(clientId: zammad_saml_metadata)
  16. if client.count.positive?
  17. Keycloak::Admin.clients.delete(client.first['id'])
  18. end
  19. Keycloak::Admin.clients.create(JSON.parse(saml_client_json))
  20. end
  21. 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)
  22. # Setup Zammad SAML authentication.
  23. response = UserAgent.get(saml_realm_zammad_descriptor)
  24. raise 'No Zammad realm descriptor found' if !response.success?
  25. match = response.body.match(%r{<ds:X509Certificate>(?<cert>.+)</ds:X509Certificate>})
  26. raise 'No X509Certificate found' if !match[:cert]
  27. auth_saml_credentials =
  28. {
  29. display_name: 'SAML',
  30. idp_sso_target_url: "#{saml_base_url}/realms/zammad/protocol/saml",
  31. idp_cert: "-----BEGIN CERTIFICATE-----\n#{match[:cert]}\n-----END CERTIFICATE-----",
  32. name_identifier_format: name_identifier_format || 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress',
  33. }
  34. auth_saml_credentials[:idp_slo_service_url] = "#{saml_base_url}/realms/zammad/protocol/saml" if idp_slo_service_url
  35. auth_saml_credentials[:uid_attribute] = uid_attribute if uid_attribute
  36. if security.present?
  37. auth_saml_credentials[:security] = 'on'
  38. auth_saml_credentials[:certificate] = "-----BEGIN CERTIFICATE-----\n#{security[:cert]}\n-----END CERTIFICATE-----"
  39. auth_saml_credentials[:private_key] = "-----BEGIN RSA PRIVATE KEY-----\n#{security[:key]}\n-----END RSA PRIVATE KEY-----" # gitleaks:allow
  40. auth_saml_credentials[:private_key_secret] = ''
  41. end
  42. # Disable setting validation. We have an explicit test for this.
  43. setting = Setting.find_by(name: 'auth_saml_credentials')
  44. setting.state_current = { value: auth_saml_credentials }
  45. setting.save!(validate: false)
  46. Setting.set('auth_saml', true)
  47. end
  48. def saml_login_keycloak
  49. find_by_id('kc-form')
  50. expect(page).to have_current_path(%r{/realms/zammad/protocol/saml\?SAMLRequest=.+})
  51. expect(page).to have_css('#kc-form-login')
  52. within '#kc-form-login' do
  53. fill_in 'username', with: 'john.doe'
  54. fill_in 'password', with: 'test'
  55. click_on 'Sign In'
  56. end
  57. expect(page).to have_no_text('Sign In')
  58. end
  59. end
  60. RSpec.configure do |config|
  61. config.include ZammadSpecSupportSAML, integration_standalone: :saml
  62. end