From ab16df82cf9cbe2a90b266d0b1a2e4fa3c85d852 Mon Sep 17 00:00:00 2001 From: Chris Born Date: Wed, 31 Jul 2024 10:40:47 -0700 Subject: [PATCH 01/10] Free up the `Saml` module by extracting `XML` into the `SamlIdp` namespace. --- lib/saml_idp.rb | 69 +-------------------------------------------- lib/saml_idp/xml.rb | 66 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 68 deletions(-) create mode 100644 lib/saml_idp/xml.rb diff --git a/lib/saml_idp.rb b/lib/saml_idp.rb index 1e8532f2..0b2197cb 100644 --- a/lib/saml_idp.rb +++ b/lib/saml_idp.rb @@ -2,6 +2,7 @@ module SamlIdp require 'active_support/all' require 'saml_idp/saml_response' + require 'saml_idp/xml' require 'saml_idp/xml_security' require 'saml_idp/configurator' require 'saml_idp/controller' @@ -23,71 +24,3 @@ def self.metadata @metadata ||= MetadataBuilder.new(config) end end - -# TODO Needs extraction out -module Saml - module XML - module Namespaces - METADATA = "urn:oasis:names:tc:SAML:2.0:metadata" - ASSERTION = "urn:oasis:names:tc:SAML:2.0:assertion" - SIGNATURE = "http://www.w3.org/2000/09/xmldsig#" - PROTOCOL = "urn:oasis:names:tc:SAML:2.0:protocol" - - module Statuses - SUCCESS = "urn:oasis:names:tc:SAML:2.0:status:Success" - end - - module Consents - UNSPECIFIED = "urn:oasis:names:tc:SAML:2.0:consent:unspecified" - end - - module AuthnContext - module ClassRef - PASSWORD = "urn:oasis:names:tc:SAML:2.0:ac:classes:Password" - PASSWORD_PROTECTED = "urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport" - end - end - - module Methods - BEARER = "urn:oasis:names:tc:SAML:2.0:cm:bearer" - end - - module Formats - module Attr - URI = "urn:oasis:names:tc:SAML:2.0:attrname-format:uri" - end - - module NameId - EMAIL_ADDRESS = "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress" - TRANSIENT = "urn:oasis:names:tc:SAML:2.0:nameid-format:transient" - PERSISTENT = "urn:oasis:names:tc:SAML:2.0:nameid-format:persistent" - end - end - end - - class Document < Nokogiri::XML::Document - def signed? - !!xpath("//ds:Signature", ds: signature_namespace).first - end - - def valid_signature?(fingerprint) - signed? && - signed_document.validate(fingerprint, :soft) - end - - def signed_document - SamlIdp::XMLSecurity::SignedDocument.new(to_xml) - end - - def signature_namespace - Namespaces::SIGNATURE - end - - def to_xml - super( - save_with: Nokogiri::XML::Node::SaveOptions::AS_XML | Nokogiri::XML::Node::SaveOptions::NO_DECLARATION - ).strip - end - end - end -end diff --git a/lib/saml_idp/xml.rb b/lib/saml_idp/xml.rb new file mode 100644 index 00000000..debe5c16 --- /dev/null +++ b/lib/saml_idp/xml.rb @@ -0,0 +1,66 @@ +module SamlIdp + module XML + module Namespaces + METADATA = "urn:oasis:names:tc:SAML:2.0:metadata" + ASSERTION = "urn:oasis:names:tc:SAML:2.0:assertion" + SIGNATURE = "http://www.w3.org/2000/09/xmldsig#" + PROTOCOL = "urn:oasis:names:tc:SAML:2.0:protocol" + + module Statuses + SUCCESS = "urn:oasis:names:tc:SAML:2.0:status:Success" + end + + module Consents + UNSPECIFIED = "urn:oasis:names:tc:SAML:2.0:consent:unspecified" + end + + module AuthnContext + module ClassRef + PASSWORD = "urn:oasis:names:tc:SAML:2.0:ac:classes:Password" + PASSWORD_PROTECTED = "urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport" + end + end + + module Methods + BEARER = "urn:oasis:names:tc:SAML:2.0:cm:bearer" + end + + module Formats + module Attr + URI = "urn:oasis:names:tc:SAML:2.0:attrname-format:uri" + end + + module NameId + EMAIL_ADDRESS = "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress" + TRANSIENT = "urn:oasis:names:tc:SAML:2.0:nameid-format:transient" + PERSISTENT = "urn:oasis:names:tc:SAML:2.0:nameid-format:persistent" + end + end + end + + class Document < Nokogiri::XML::Document + def signed? + !!xpath("//ds:Signature", ds: signature_namespace).first + end + + def valid_signature?(fingerprint) + signed? && + signed_document.validate(fingerprint, :soft) + end + + def signed_document + SamlIdp::XMLSecurity::SignedDocument.new(to_xml) + end + + def signature_namespace + Namespaces::SIGNATURE + end + + def to_xml + super( + save_with: Nokogiri::XML::Node::SaveOptions::AS_XML | Nokogiri::XML::Node::SaveOptions::NO_DECLARATION + ).strip + end + end + end +end \ No newline at end of file From 45e90b9321b5b269930c06cad67b19400d16b111 Mon Sep 17 00:00:00 2001 From: Chris Born Date: Wed, 31 Jul 2024 10:41:35 -0700 Subject: [PATCH 02/10] Refactor the references from `Saml::XML` to `SamlIdp::XML` --- lib/saml_idp/assertion_builder.rb | 6 +++--- lib/saml_idp/attribute_decorator.rb | 2 +- lib/saml_idp/controller.rb | 2 +- lib/saml_idp/encryptor.rb | 2 +- lib/saml_idp/incoming_metadata.rb | 8 ++++---- lib/saml_idp/logout_request_builder.rb | 8 ++++---- lib/saml_idp/logout_response_builder.rb | 8 ++++---- lib/saml_idp/metadata_builder.rb | 10 +++++----- lib/saml_idp/request.rb | 8 ++++---- lib/saml_idp/response_builder.rb | 8 ++++---- spec/lib/saml_idp/assertion_builder_spec.rb | 2 +- spec/lib/saml_idp/attribute_decorator_spec.rb | 2 +- spec/lib/saml_idp/metadata_builder_spec.rb | 2 +- spec/lib/saml_idp/saml_response_spec.rb | 2 +- 14 files changed, 35 insertions(+), 35 deletions(-) diff --git a/lib/saml_idp/assertion_builder.rb b/lib/saml_idp/assertion_builder.rb index 8e0170fa..cf62808b 100644 --- a/lib/saml_idp/assertion_builder.rb +++ b/lib/saml_idp/assertion_builder.rb @@ -53,7 +53,7 @@ def initialize( def fresh builder = Builder::XmlMarkup.new - builder.Assertion xmlns: Saml::XML::Namespaces::ASSERTION, + builder.Assertion xmlns: SamlIdp::XML::Namespaces::ASSERTION, ID: reference_string, IssueInstant: now_iso, Version: "2.0" do |assertion| @@ -61,7 +61,7 @@ def fresh sign assertion assertion.Subject do |subject| subject.NameID name_id, Format: name_id_format[:name] - subject.SubjectConfirmation Method: Saml::XML::Namespaces::Methods::BEARER do |confirmation| + subject.SubjectConfirmation Method: SamlIdp::XML::Namespaces::Methods::BEARER do |confirmation| confirmation_hash = {} confirmation_hash[:InResponseTo] = saml_request_id unless saml_request_id.nil? confirmation_hash[:NotOnOrAfter] = not_on_or_after_subject @@ -92,7 +92,7 @@ def fresh asserted_attributes.each do |friendly_name, attrs| attrs = (attrs || {}).with_indifferent_access attr_statement.Attribute Name: attrs[:name] || friendly_name, - NameFormat: attrs[:name_format] || Saml::XML::Namespaces::Formats::Attr::URI, + NameFormat: attrs[:name_format] || SamlIdp::XML::Namespaces::Formats::Attr::URI, FriendlyName: friendly_name.to_s do |attr| values = get_values_for friendly_name, attrs[:getter] values.each do |val| diff --git a/lib/saml_idp/attribute_decorator.rb b/lib/saml_idp/attribute_decorator.rb index 3f0b7540..6d26332f 100644 --- a/lib/saml_idp/attribute_decorator.rb +++ b/lib/saml_idp/attribute_decorator.rb @@ -17,7 +17,7 @@ def friendly_name end def name_format - source[:name_format] || Saml::XML::Namespaces::Formats::Attr::URI + source[:name_format] || SamlIdp::XML::Namespaces::Formats::Attr::URI end def values diff --git a/lib/saml_idp/controller.rb b/lib/saml_idp/controller.rb index e2bf25e7..5f4a44dc 100644 --- a/lib/saml_idp/controller.rb +++ b/lib/saml_idp/controller.rb @@ -45,7 +45,7 @@ def decode_request(raw_saml_request) end def authn_context_classref - Saml::XML::Namespaces::AuthnContext::ClassRef::PASSWORD + SamlIdp::XML::Namespaces::AuthnContext::ClassRef::PASSWORD end def encode_authn_response(principal, opts = {}) diff --git a/lib/saml_idp/encryptor.rb b/lib/saml_idp/encryptor.rb index 879e1b76..32fdee0b 100644 --- a/lib/saml_idp/encryptor.rb +++ b/lib/saml_idp/encryptor.rb @@ -23,7 +23,7 @@ def encrypt(raw_xml) encrypted_key = Xmlenc::EncryptedKey.new(encrypted_key_node) encrypted_key.encrypt(openssl_cert.public_key, encryption_key) xml = Builder::XmlMarkup.new - xml.EncryptedAssertion xmlns: Saml::XML::Namespaces::ASSERTION do |enc_assert| + xml.EncryptedAssertion xmlns: SamlIdp::XML::Namespaces::ASSERTION do |enc_assert| enc_assert << encrypted_data.node.to_s end end diff --git a/lib/saml_idp/incoming_metadata.rb b/lib/saml_idp/incoming_metadata.rb index fe0f5c61..6cca7b3d 100644 --- a/lib/saml_idp/incoming_metadata.rb +++ b/lib/saml_idp/incoming_metadata.rb @@ -13,7 +13,7 @@ def initialize(raw = "") end def document - @document ||= Saml::XML::Document.parse raw + @document ||= SamlIdp::XML::Document.parse raw end def entity_id @@ -149,16 +149,16 @@ def idp_descriptor_document end def contact_person_document - @contact_person_document ||= (xpath("//md:ContactPerson", md: metadata_namespace).first || Saml::XML::Document.new) + @contact_person_document ||= (xpath("//md:ContactPerson", md: metadata_namespace).first || SamlIdp::XML::Document.new) end def metadata_namespace - Saml::XML::Namespaces::METADATA + SamlIdp::XML::Namespaces::METADATA end private :metadata_namespace def signature_namespace - Saml::XML::Namespaces::SIGNATURE + SamlIdp::XML::Namespaces::SIGNATURE end private :signature_namespace end diff --git a/lib/saml_idp/logout_request_builder.rb b/lib/saml_idp/logout_request_builder.rb index b75f9315..b44905c2 100644 --- a/lib/saml_idp/logout_request_builder.rb +++ b/lib/saml_idp/logout_request_builder.rb @@ -14,11 +14,11 @@ def build Version: "2.0", IssueInstant: now_iso, Destination: saml_slo_url, - "xmlns" => Saml::XML::Namespaces::PROTOCOL do |request| - request.Issuer issuer_uri, xmlns: Saml::XML::Namespaces::ASSERTION + "xmlns" => SamlIdp::XML::Namespaces::PROTOCOL do |request| + request.Issuer issuer_uri, xmlns: SamlIdp::XML::Namespaces::ASSERTION sign request - request.NameID name_id, xmlns: Saml::XML::Namespaces::ASSERTION, - Format: Saml::XML::Namespaces::Formats::NameId::PERSISTENT + request.NameID name_id, xmlns: SamlIdp::XML::Namespaces::ASSERTION, + Format: SamlIdp::XML::Namespaces::Formats::NameId::PERSISTENT request.SessionIndex response_id_string end end diff --git a/lib/saml_idp/logout_response_builder.rb b/lib/saml_idp/logout_response_builder.rb index fd14116b..cbdbdad9 100644 --- a/lib/saml_idp/logout_response_builder.rb +++ b/lib/saml_idp/logout_response_builder.rb @@ -15,11 +15,11 @@ def build IssueInstant: now_iso, Destination: saml_slo_url, InResponseTo: saml_request_id, - xmlns: Saml::XML::Namespaces::PROTOCOL do |response| - response.Issuer issuer_uri, xmlns: Saml::XML::Namespaces::ASSERTION + xmlns: SamlIdp::XML::Namespaces::PROTOCOL do |response| + response.Issuer issuer_uri, xmlns: SamlIdp::XML::Namespaces::ASSERTION sign response - response.Status xmlns: Saml::XML::Namespaces::PROTOCOL do |status| - status.StatusCode Value: Saml::XML::Namespaces::Statuses::SUCCESS + response.Status xmlns: SamlIdp::XML::Namespaces::PROTOCOL do |status| + status.StatusCode Value: SamlIdp::XML::Namespaces::Statuses::SUCCESS end end end diff --git a/lib/saml_idp/metadata_builder.rb b/lib/saml_idp/metadata_builder.rb index 9a4afb92..2e6e0b08 100644 --- a/lib/saml_idp/metadata_builder.rb +++ b/lib/saml_idp/metadata_builder.rb @@ -16,9 +16,9 @@ def fresh builder = Builder::XmlMarkup.new generated_reference_id do builder.EntityDescriptor ID: reference_string, - xmlns: Saml::XML::Namespaces::METADATA, - "xmlns:saml" => Saml::XML::Namespaces::ASSERTION, - "xmlns:ds" => Saml::XML::Namespaces::SIGNATURE, + xmlns: SamlIdp::XML::Namespaces::METADATA, + "xmlns:saml" => SamlIdp::XML::Namespaces::ASSERTION, + "xmlns:ds" => SamlIdp::XML::Namespaces::SIGNATURE, entityID: entity_id do |entity| sign entity @@ -56,7 +56,7 @@ def fresh def build_key_descriptor(el) el.KeyDescriptor use: "signing" do |key_descriptor| - key_descriptor.KeyInfo xmlns: Saml::XML::Namespaces::SIGNATURE do |key_info| + key_descriptor.KeyInfo xmlns: SamlIdp::XML::Namespaces::SIGNATURE do |key_info| key_info.X509Data do |x509| x509.X509Certificate x509_certificate end @@ -128,7 +128,7 @@ def entity_id private :entity_id def protocol_enumeration - Saml::XML::Namespaces::PROTOCOL + SamlIdp::XML::Namespaces::PROTOCOL end private :protocol_enumeration diff --git a/lib/saml_idp/request.rb b/lib/saml_idp/request.rb index 4b8b891f..b5315ffa 100644 --- a/lib/saml_idp/request.rb +++ b/lib/saml_idp/request.rb @@ -157,7 +157,7 @@ def response_host private :response_host def document - @_document ||= Saml::XML::Document.parse(raw_xml) + @_document ||= SamlIdp::XML::Document.parse(raw_xml) end private :document @@ -179,17 +179,17 @@ def logout_request private :logout_request def samlp - Saml::XML::Namespaces::PROTOCOL + SamlIdp::XML::Namespaces::PROTOCOL end private :samlp def assertion - Saml::XML::Namespaces::ASSERTION + SamlIdp::XML::Namespaces::ASSERTION end private :assertion def signature_namespace - Saml::XML::Namespaces::SIGNATURE + SamlIdp::XML::Namespaces::SIGNATURE end private :signature_namespace diff --git a/lib/saml_idp/response_builder.rb b/lib/saml_idp/response_builder.rb index 0686cd9b..71d0665d 100644 --- a/lib/saml_idp/response_builder.rb +++ b/lib/saml_idp/response_builder.rb @@ -47,16 +47,16 @@ def build resp_options[:Version] = "2.0" resp_options[:IssueInstant] = now_iso resp_options[:Destination] = saml_acs_url - resp_options[:Consent] = Saml::XML::Namespaces::Consents::UNSPECIFIED + resp_options[:Consent] = SamlIdp::XML::Namespaces::Consents::UNSPECIFIED resp_options[:InResponseTo] = saml_request_id unless saml_request_id.nil? - resp_options["xmlns:samlp"] = Saml::XML::Namespaces::PROTOCOL + resp_options["xmlns:samlp"] = SamlIdp::XML::Namespaces::PROTOCOL builder = Builder::XmlMarkup.new builder.tag! "samlp:Response", resp_options do |response| - response.Issuer issuer_uri, xmlns: Saml::XML::Namespaces::ASSERTION + response.Issuer issuer_uri, xmlns: SamlIdp::XML::Namespaces::ASSERTION sign response response.tag! "samlp:Status" do |status| - status.tag! "samlp:StatusCode", Value: Saml::XML::Namespaces::Statuses::SUCCESS + status.tag! "samlp:StatusCode", Value: SamlIdp::XML::Namespaces::Statuses::SUCCESS end response << assertion_and_signature end diff --git a/spec/lib/saml_idp/assertion_builder_spec.rb b/spec/lib/saml_idp/assertion_builder_spec.rb index 9e267464..7b077e93 100644 --- a/spec/lib/saml_idp/assertion_builder_spec.rb +++ b/spec/lib/saml_idp/assertion_builder_spec.rb @@ -9,7 +9,7 @@ module SamlIdp let(:saml_acs_url) { "http://saml.acs.url" } let(:algorithm) { :sha256 } let(:authn_context_classref) { - Saml::XML::Namespaces::AuthnContext::ClassRef::PASSWORD + SamlIdp::XML::Namespaces::AuthnContext::ClassRef::PASSWORD } let(:expiry) { 3*60*60 } let (:encryption_opts) do diff --git a/spec/lib/saml_idp/attribute_decorator_spec.rb b/spec/lib/saml_idp/attribute_decorator_spec.rb index 2b808c72..5ed25cf3 100644 --- a/spec/lib/saml_idp/attribute_decorator_spec.rb +++ b/spec/lib/saml_idp/attribute_decorator_spec.rb @@ -20,7 +20,7 @@ module SamlIdp end it "has a valid name_format" do - expect(subject.name_format).to eq(Saml::XML::Namespaces::Formats::Attr::URI) + expect(subject.name_format).to eq(SamlIdp::XML::Namespaces::Formats::Attr::URI) end it "has a valid values" do diff --git a/spec/lib/saml_idp/metadata_builder_spec.rb b/spec/lib/saml_idp/metadata_builder_spec.rb index c8e14765..2562f2ae 100644 --- a/spec/lib/saml_idp/metadata_builder_spec.rb +++ b/spec/lib/saml_idp/metadata_builder_spec.rb @@ -6,7 +6,7 @@ module SamlIdp end it "signs valid xml" do - expect(Saml::XML::Document.parse(subject.signed).valid_signature?(Default::FINGERPRINT)).to be_truthy + expect(SamlIdp::XML::Document.parse(subject.signed).valid_signature?(Default::FINGERPRINT)).to be_truthy end it "includes logout element" do diff --git a/spec/lib/saml_idp/saml_response_spec.rb b/spec/lib/saml_idp/saml_response_spec.rb index a9e82151..5dd7f3f4 100644 --- a/spec/lib/saml_idp/saml_response_spec.rb +++ b/spec/lib/saml_idp/saml_response_spec.rb @@ -13,7 +13,7 @@ module SamlIdp let(:x509_certificate) { Default::X509_CERTIFICATE } let(:xauthn) { Default::X509_CERTIFICATE } let(:authn_context_classref) { - Saml::XML::Namespaces::AuthnContext::ClassRef::PASSWORD + SamlIdp::XML::Namespaces::AuthnContext::ClassRef::PASSWORD } let(:expiry) { 3 * 60 * 60 } let(:session_expiry) { 24 * 60 * 60 } From f2aab36e834eaf1404e56499973e0ed4bbb791ff Mon Sep 17 00:00:00 2001 From: Chris Born Date: Wed, 31 Jul 2024 11:30:53 -0700 Subject: [PATCH 03/10] Update missed references in the readme --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 7d70b75c..0f26dea8 100644 --- a/README.md +++ b/README.md @@ -121,8 +121,8 @@ CERT # phone: { getter: :phone }, # email: { # getter: :email, - # name_format: Saml::XML::Namespaces::Formats::NameId::EMAIL_ADDRESS, - # name_id_format: Saml::XML::Namespaces::Formats::NameId::EMAIL_ADDRESS + # name_format: SamlIdp::XML::Namespaces::Formats::NameId::EMAIL_ADDRESS, + # name_id_format: SamlIdp::XML::Namespaces::Formats::NameId::EMAIL_ADDRESS # } # } # end From 852a664caa8d5cbeb4360b92924a7ef001edd9a0 Mon Sep 17 00:00:00 2001 From: Chris Born Date: Wed, 31 Jul 2024 11:42:31 -0700 Subject: [PATCH 04/10] Adds support for multiple multiple x509 certificates, secret keys, and passwords by providing procs in the idp configuration. --- lib/saml_idp/configurator.rb | 5 +++-- lib/saml_idp/signature_builder.rb | 3 ++- lib/saml_idp/signed_info_builder.rb | 4 ++-- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/lib/saml_idp/configurator.rb b/lib/saml_idp/configurator.rb index 4998869a..0b0c23a3 100644 --- a/lib/saml_idp/configurator.rb +++ b/lib/saml_idp/configurator.rb @@ -25,8 +25,9 @@ class Configurator attr_accessor :logger def initialize - self.x509_certificate = Default::X509_CERTIFICATE - self.secret_key = Default::SECRET_KEY + self.x509_certificate = -> { Default::X509_CERTIFICATE } + self.secret_key = -> { Default::SECRET_KEY } + self.password = nil self.algorithm = :sha1 self.reference_id_generator = ->() { SecureRandom.uuid } self.service_provider = OpenStruct.new diff --git a/lib/saml_idp/signature_builder.rb b/lib/saml_idp/signature_builder.rb index 83183f23..0406715c 100644 --- a/lib/saml_idp/signature_builder.rb +++ b/lib/saml_idp/signature_builder.rb @@ -21,7 +21,8 @@ def raw end def x509_certificate - SamlIdp.config.x509_certificate + certificate = SamlIdp.config.x509_certificate.is_a?(Proc) ? SamlIdp.config.x509_certificate.call : SamlIdp.config.x509_certificate + certificate .to_s .gsub(/-----BEGIN CERTIFICATE-----/,"") .gsub(/-----END CERTIFICATE-----/,"") diff --git a/lib/saml_idp/signed_info_builder.rb b/lib/saml_idp/signed_info_builder.rb index 81380666..4b0ff224 100644 --- a/lib/saml_idp/signed_info_builder.rb +++ b/lib/saml_idp/signed_info_builder.rb @@ -65,12 +65,12 @@ def clean_algorithm_name private :clean_algorithm_name def secret_key - SamlIdp.config.secret_key + SamlIdp.config.secret_key.is_a?(Proc) ? SamlIdp.config.secret_key.call : SamlIdp.config.secret_key end private :secret_key def password - SamlIdp.config.password + SamlIdp.config.password.is_a?(Proc) ? SamlIdp.config.password.call : SamlIdp.config.password end private :password From 1e03a446888f9f3b0c85dcd20ab25dce9dc2cb44 Mon Sep 17 00:00:00 2001 From: Chris Born Date: Wed, 31 Jul 2024 11:42:43 -0700 Subject: [PATCH 05/10] Call the proc in the tests --- spec/lib/saml_idp/configurator_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/lib/saml_idp/configurator_spec.rb b/spec/lib/saml_idp/configurator_spec.rb index 5148a289..3de7f08a 100644 --- a/spec/lib/saml_idp/configurator_spec.rb +++ b/spec/lib/saml_idp/configurator_spec.rb @@ -20,11 +20,11 @@ module SamlIdp it { should respond_to :logger } it "has a valid x509_certificate" do - expect(subject.x509_certificate).to eq(Default::X509_CERTIFICATE) + expect(subject.x509_certificate.call).to eq(Default::X509_CERTIFICATE) end it "has a valid secret_key" do - expect(subject.secret_key).to eq(Default::SECRET_KEY) + expect(subject.secret_key.call).to eq(Default::SECRET_KEY) end it "has a valid algorithm" do From 5fa7c381ec830a44bedd908ce3b1bd1d5672e80f Mon Sep 17 00:00:00 2001 From: Chris Born Date: Wed, 31 Jul 2024 11:43:25 -0700 Subject: [PATCH 06/10] Add documentation in the form of a comment in the README.md --- README.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 7d70b75c..7cb21aef 100644 --- a/README.md +++ b/README.md @@ -61,7 +61,7 @@ Be sure to load a file like this during your app initialization: ```ruby SamlIdp.configure do |config| base = "http://example.com" - + config.x509_certificate = <<-CERT -----BEGIN CERTIFICATE----- CERTIFICATE DATA @@ -74,6 +74,11 @@ KEY DATA -----END RSA PRIVATE KEY----- CERT + # x509_certificate, secret_key, and password may also be set from within a proc, for example: + # config.x509_certificate = -> { File.read("cert.pem") } + # config.secret_key = -> { SecretKeyFinder.key_for(id: 1) } + # config.password = -> { "password" } + # config.password = "secret_key_password" # config.algorithm = :sha256 # Default: sha1 only for development. # config.organization_name = "Your Organization" From 2ef7a38acdaea20faccba14e33ea05aec4de19ea Mon Sep 17 00:00:00 2001 From: Chris Born Date: Wed, 31 Jul 2024 11:45:25 -0700 Subject: [PATCH 07/10] fix extra space --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7cb21aef..dd30500e 100644 --- a/README.md +++ b/README.md @@ -61,7 +61,7 @@ Be sure to load a file like this during your app initialization: ```ruby SamlIdp.configure do |config| base = "http://example.com" - + config.x509_certificate = <<-CERT -----BEGIN CERTIFICATE----- CERTIFICATE DATA From f27ce73ebed8a682a51cfd01f8f8050c773fe754 Mon Sep 17 00:00:00 2001 From: Chris Born Date: Wed, 31 Jul 2024 12:23:55 -0700 Subject: [PATCH 08/10] remove additional change --- lib/saml_idp/configurator.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/saml_idp/configurator.rb b/lib/saml_idp/configurator.rb index 0b0c23a3..6702f1db 100644 --- a/lib/saml_idp/configurator.rb +++ b/lib/saml_idp/configurator.rb @@ -27,7 +27,6 @@ class Configurator def initialize self.x509_certificate = -> { Default::X509_CERTIFICATE } self.secret_key = -> { Default::SECRET_KEY } - self.password = nil self.algorithm = :sha1 self.reference_id_generator = ->() { SecureRandom.uuid } self.service_provider = OpenStruct.new From ef8eb05e972ce69d16b49bc05bb3260476ad6633 Mon Sep 17 00:00:00 2001 From: Chris Born Date: Tue, 6 Aug 2024 05:59:19 -0700 Subject: [PATCH 09/10] require nokogiri - fixes test failures --- lib/saml_idp/xml.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/saml_idp/xml.rb b/lib/saml_idp/xml.rb index debe5c16..d354a352 100644 --- a/lib/saml_idp/xml.rb +++ b/lib/saml_idp/xml.rb @@ -1,3 +1,5 @@ +require 'nokogiri' + module SamlIdp module XML module Namespaces From 2b45b55a500778a7441991fa43b90c885344a967 Mon Sep 17 00:00:00 2001 From: Chris Born Date: Tue, 24 Sep 2024 07:51:08 -0700 Subject: [PATCH 10/10] fix x509 cert lookup in metadata builder --- lib/saml_idp/metadata_builder.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/saml_idp/metadata_builder.rb b/lib/saml_idp/metadata_builder.rb index 2e6e0b08..3e5c4615 100644 --- a/lib/saml_idp/metadata_builder.rb +++ b/lib/saml_idp/metadata_builder.rb @@ -152,7 +152,8 @@ def raw_algorithm private :raw_algorithm def x509_certificate - SamlIdp.config.x509_certificate + certificate = SamlIdp.config.x509_certificate.is_a?(Proc) ? SamlIdp.config.x509_certificate.call : SamlIdp.config.x509_certificate + certificate .to_s .gsub(/-----BEGIN CERTIFICATE-----/,"") .gsub(/-----END CERTIFICATE-----/,"")