Commit dd1fc29

mo <mo.khan@gmail.com>
2017-12-26 22:56:48
move fingerprint, certificate, xml to xml-kit.
1 parent a2d1b3a
lib/saml/kit/document.rb
@@ -2,6 +2,13 @@ module Saml
   module Kit
     class Document
       PROTOCOL_XSD = File.expand_path("./xsd/saml-schema-protocol-2.0.xsd", File.dirname(__FILE__)).freeze
+      NAMESPACES = {
+        "NameFormat": ::Saml::Kit::Namespaces::ATTR_SPLAT,
+        "ds": ::Xml::Kit::Namespaces::XMLDSIG,
+        "md": ::Saml::Kit::Namespaces::METADATA,
+        "saml": ::Saml::Kit::Namespaces::ASSERTION,
+        "samlp": ::Saml::Kit::Namespaces::PROTOCOL,
+      }.freeze
       include ActiveModel::Validations
       include XsdValidatable
       include Translatable
@@ -84,7 +91,7 @@ module Saml
             "LogoutRequest" => Saml::Kit::LogoutRequest,
             "LogoutResponse" => Saml::Kit::LogoutResponse,
             "Response" => Saml::Kit::Response,
-          }[Saml::Kit::Xml.new(xml).find_by(XPATH).name] || InvalidDocument
+          }[::Xml::Kit::Xml.new(xml, namespaces: { "samlp": ::Saml::Kit::Namespaces::PROTOCOL }).find_by(XPATH).name] || InvalidDocument
           constructor.new(xml, configuration: configuration)
         rescue => error
           Saml::Kit.logger.error(error)
lib/saml/kit/key_pair.rb
@@ -5,7 +5,7 @@ module Saml
 
       def initialize(certificate, private_key, passphrase, use)
         @use = use
-        @certificate = Saml::Kit::Certificate.new(certificate, use: use)
+        @certificate = Xml::Kit::Certificate.new(certificate, use: use)
         @private_key = OpenSSL::PKey::RSA.new(private_key, passphrase)
       end
 
lib/saml/kit/metadata.rb
@@ -24,6 +24,13 @@ module Saml
     # {include:file:spec/examples/metadata_spec.rb}
     class Metadata
       METADATA_XSD = File.expand_path("./xsd/saml-schema-metadata-2.0.xsd", File.dirname(__FILE__)).freeze
+      NAMESPACES = {
+        "NameFormat": Namespaces::ATTR_SPLAT,
+        "ds": ::Xml::Kit::Namespaces::XMLDSIG,
+        "md": Namespaces::METADATA,
+        "saml": Namespaces::ASSERTION,
+        "samlp": Namespaces::PROTOCOL,
+      }.freeze
       include ActiveModel::Validations
       include XsdValidatable
       include Translatable
@@ -69,8 +76,8 @@ module Saml
       # Returns each of the X509 certificates.
       def certificates
         @certificates ||= document.find_all("/md:EntityDescriptor/md:#{name}/md:KeyDescriptor").map do |item|
-          cert = item.at_xpath("./ds:KeyInfo/ds:X509Data/ds:X509Certificate", Xml::NAMESPACES).text
-          Certificate.new(cert, use: item.attribute('use').value.to_sym)
+          cert = item.at_xpath("./ds:KeyInfo/ds:X509Data/ds:X509Certificate", NAMESPACES).text
+          ::Xml::Kit::Certificate.new(cert, use: item.attribute('use').value.to_sym)
         end
       end
 
@@ -134,7 +141,7 @@ module Saml
       #
       # @param fingerprint [Saml::Kit::Fingerprint] the fingerprint to search for.
       # @param use [Symbol] the type of certificates to look at. Can be `:signing` or `:encryption`.
-      # @return [Saml::Kit::Certificate] returns the matching `{Saml::Kit::Certificate}`
+      # @return [Xml::Kit::Certificate] returns the matching `{Xml::Kit::Certificate}`
       def matches?(fingerprint, use: :signing)
         certificates.find do |certificate|
           certificate.for?(use) && certificate.fingerprint == fingerprint
@@ -163,7 +170,7 @@ module Saml
       # @param algorithm [OpenSSL::Digest] the digest algorithm to use. E.g. `OpenSSL::Digest::SHA256`
       # @param signature [String] the signature to verify
       # @param data [String] the data that is used to produce the signature.
-      # @return [Saml::Kit::Certificate] the certificate that was used to produce the signature.
+      # @return [Xml::Kit::Certificate] the certificate that was used to produce the signature.
       def verify(algorithm, signature, data)
         signing_certificates.find do |certificate|
           certificate.public_key.verify(algorithm, signature, data)
@@ -196,7 +203,7 @@ module Saml
       attr_reader :xml
 
       def document
-        @document ||= Xml.new(xml)
+        @document ||= ::Xml::Kit::Xml.new(xml, namespaces: NAMESPACES)
       end
 
       def metadata
@@ -220,7 +227,7 @@ module Saml
       end
 
       def valid_signature?
-        xml = Saml::Kit::Xml.new(to_xml)
+        xml = ::Xml::Kit::Xml.new(to_xml)
         result = xml.valid?
         xml.errors.each do |error|
           errors[:base] << error
lib/saml/kit/signature.rb
@@ -9,7 +9,7 @@ module Saml
       def certificate
         value = to_h.fetch('KeyInfo', {}).fetch('X509Data', {}).fetch('X509Certificate', nil)
         return if value.nil?
-        Saml::Kit::Certificate.new(value, use: :signing)
+        Xml::Kit::Certificate.new(value, use: :signing)
       end
 
       # Returns true when the fingerprint of the certificate matches one of the certificates registered in the metadata.
lib/saml/kit/trustable.rb
@@ -44,7 +44,13 @@ module Saml
       def must_have_valid_signature
         return if to_xml.blank?
 
-        xml = Saml::Kit::Xml.new(to_xml)
+        xml = ::Xml::Kit::Xml.new(to_xml, namespaces: {
+          "NameFormat": Namespaces::ATTR_SPLAT,
+          "ds": ::Xml::Kit::Namespaces::XMLDSIG,
+          "md": Namespaces::METADATA,
+          "saml": Namespaces::ASSERTION,
+          "samlp": Namespaces::PROTOCOL,
+        })
         xml.valid?
         xml.errors.each do |error|
           errors[:base] << error
lib/saml/kit.rb
@@ -31,10 +31,8 @@ require "saml/kit/document"
 require "saml/kit/assertion"
 require "saml/kit/authentication_request"
 require "saml/kit/bindings"
-require "saml/kit/certificate"
 require "saml/kit/configuration"
 require "saml/kit/default_registry"
-require "saml/kit/fingerprint"
 require "saml/kit/key_pair"
 require "saml/kit/logout_response"
 require "saml/kit/logout_request"
@@ -48,7 +46,6 @@ require "saml/kit/service_provider_metadata"
 require "saml/kit/signature"
 require "saml/kit/signatures"
 require "saml/kit/template"
-require "saml/kit/xml"
 
 I18n.load_path += Dir[File.expand_path("kit/locales/*.yml", File.dirname(__FILE__))]
 
@@ -61,8 +58,6 @@ module Saml
 
       def configure
         yield configuration
-      ensure
-        Xml::Kit.logger = configuration.logger
       end
 
       def logger
spec/saml/certificate_spec.rb
@@ -1,13 +0,0 @@
-RSpec.describe Saml::Kit::Certificate do
-  subject { described_class.new(certificate, use: :signing) }
-  let(:certificate) do
-    cert, _ = Saml::Kit::SelfSignedCertificate.new('password').create
-    cert
-  end
-
-  describe "#fingerprint" do
-    it 'returns a fingerprint' do
-      expect(subject.fingerprint).to be_instance_of(Saml::Kit::Fingerprint)
-    end
-  end
-end
spec/saml/identity_provider_metadata_spec.rb
@@ -19,7 +19,7 @@ RSpec.describe Saml::Kit::IdentityProviderMetadata do
     it { expect(subject.single_logout_services).to be_empty }
     it do
       fingerprint = "9F:74:13:3B:BC:5A:7B:8B:2D:4F:8B:EF:1E:88:EB:D1:AE:BC:19:BF:CA:19:C6:2F:0F:4B:31:1D:68:98:B0:1B"
-      expect(subject.certificates).to match_array([Saml::Kit::Certificate.new(certificate, use: :signing)])
+      expect(subject.certificates).to match_array([::Xml::Kit::Certificate.new(certificate, use: :signing)])
       expect(subject.certificates.first.fingerprint.to_s).to eql(fingerprint)
     end
     it { expect(subject.attributes).to be_empty }
@@ -59,8 +59,8 @@ RSpec.describe Saml::Kit::IdentityProviderMetadata do
     end
     it do
       expect(subject.certificates).to match_array([
-        Saml::Kit::Certificate.new(signing_certificate, use: :signing),
-        Saml::Kit::Certificate.new(encryption_certificate, use: :encryption),
+        ::Xml::Kit::Certificate.new(signing_certificate, use: :signing),
+        ::Xml::Kit::Certificate.new(encryption_certificate, use: :encryption),
       ])
     end
     it { expect(subject.attributes).to be_present }
spec/saml/response_spec.rb
@@ -320,7 +320,7 @@ RSpec.describe Saml::Kit::Response do
     let(:id) { Xml::Kit::Id.generate }
     let(:url) { FFaker::Internet.uri("https") }
     let(:certificate) do
-      Saml::Kit::Certificate.new(
+      ::Xml::Kit::Certificate.new(
         Saml::Kit::SelfSignedCertificate.new("password").create[0],
         use: :signing
       )
spec/saml/service_provider_metadata_spec.rb
@@ -18,7 +18,7 @@ RSpec.describe Saml::Kit::ServiceProviderMetadata do
 
     it 'returns each of the certificates' do
       expected_certificates = Saml::Kit.configuration.certificates.map do |x|
-        Saml::Kit::Certificate.new(x.stripped, use: x.use)
+        ::Xml::Kit::Certificate.new(x.stripped, use: x.use)
       end
       expect(subject.certificates).to match_array(expected_certificates)
     end
@@ -125,13 +125,13 @@ RSpec.describe Saml::Kit::ServiceProviderMetadata do
 
     it 'returns true when the fingerprint matches one of the signing certificates' do
       certificate = Hash.from_xml(subject.to_xml)['EntityDescriptor']['Signature']['KeyInfo']['X509Data']['X509Certificate']
-      fingerprint = Saml::Kit::Fingerprint.new(certificate)
+      fingerprint = ::Xml::Kit::Fingerprint.new(certificate)
       expect(subject.matches?(fingerprint)).to be_truthy
     end
 
     it 'returns false when the fingerprint does not match one of the signing certificates' do
       certificate, _ = Saml::Kit::SelfSignedCertificate.new('password').create
-      fingerprint = Saml::Kit::Fingerprint.new(certificate)
+      fingerprint = ::Xml::Kit::Fingerprint.new(certificate)
       expect(subject.matches?(fingerprint)).to be_falsey
     end
   end
spec/support/matchers/have_xml.rb
@@ -1,6 +1,13 @@
 RSpec::Matchers.define :have_xpath do |xpath|
   match do |actual|
-    xml_document(actual).xpath(xpath, Saml::Kit::Xml::NAMESPACES).any?
+    namespaces = {
+      "NameFormat": Saml::Kit::Namespaces::ATTR_SPLAT,
+      "ds": ::Xml::Kit::Namespaces::XMLDSIG,
+      "md": Saml::Kit::Namespaces::METADATA,
+      "saml": Saml::Kit::Namespaces::ASSERTION,
+      "samlp": Saml::Kit::Namespaces::PROTOCOL,
+    }
+    xml_document(actual).xpath(xpath, namespaces).any?
   end
 
   failure_message do |actual|
spec/spec_helper.rb
@@ -8,7 +8,7 @@ require "active_support/testing/time_helpers"
 require "ffaker"
 require "webmock/rspec"
 
-Saml::Kit.configuration.logger.level = Logger::FATAL
+Saml::Kit.configuration.logger.level = Xml::Kit.logger.level = Logger::FATAL
 
 Dir[File.join(Dir.pwd, 'spec/support/**/*.rb')].each { |f| require f }
 RSpec.configure do |config|
lib/saml/kit/certificate.rb → xml-kit/lib/xml/kit/certificate.rb
@@ -1,6 +1,6 @@
-module Saml
+module Xml
   module Kit
-    # {include:file:spec/saml/certificate_spec.rb}
+    # {include:file:spec/xml/certificate_spec.rb}
     class Certificate
       BEGIN_CERT=/-----BEGIN CERTIFICATE-----/
       END_CERT=/-----END CERTIFICATE-----/
@@ -12,7 +12,7 @@ module Saml
         @use = use.downcase.to_sym
       end
 
-      # @return [Saml::Kit::Fingerprint] the certificate fingerprint.
+      # @return [Xml::Kit::Fingerprint] the certificate fingerprint.
       def fingerprint
         Fingerprint.new(value)
       end
@@ -84,7 +84,7 @@ module Saml
       def self.to_x509(value)
         OpenSSL::X509::Certificate.new(Base64.decode64(value))
       rescue OpenSSL::X509::CertificateError => error
-        Saml::Kit.logger.warn(error)
+        ::Xml::Kit.logger.warn(error)
         OpenSSL::X509::Certificate.new(value)
       end
 
lib/saml/kit/fingerprint.rb → xml-kit/lib/xml/kit/fingerprint.rb
@@ -1,4 +1,4 @@
-module Saml
+module Xml
   module Kit
     # This generates a fingerprint for an X509 Certificate.
     #
lib/saml/kit/xml.rb → xml-kit/lib/xml/kit/xml.rb
@@ -1,14 +1,14 @@
-module Saml
+module Xml
   module Kit
     # {include:file:spec/saml/xml_spec.rb}
     class Xml # :nodoc:
       include ActiveModel::Validations
       NAMESPACES = {
-        "NameFormat": Namespaces::ATTR_SPLAT,
+        #"NameFormat": Namespaces::ATTR_SPLAT,
         "ds": ::Xml::Kit::Namespaces::XMLDSIG,
-        "md": Namespaces::METADATA,
-        "saml": Namespaces::ASSERTION,
-        "samlp": Namespaces::PROTOCOL,
+        #"md": Namespaces::METADATA,
+        #"saml": Namespaces::ASSERTION,
+        #"samlp": Namespaces::PROTOCOL,
       }.freeze
 
       validate :validate_signatures
xml-kit/lib/xml/kit/xml_decryption.rb
@@ -30,7 +30,7 @@ module Xml
             attempts -= 1
             return to_plaintext(cipher_text, private_key, encrypted_key["EncryptionMethod"]['Algorithm'])
           rescue OpenSSL::PKey::RSAError => error
-            Xml::Kit.logger.error(error)
+            ::Xml::Kit.logger.error(error)
             raise if attempts.zero?
           end
         end
xml-kit/lib/xml/kit.rb
@@ -1,11 +1,15 @@
+require "active_model"
 require "base64"
 require "logger"
 require "openssl"
 
+require "xml/kit/certificate"
 require "xml/kit/crypto"
+require "xml/kit/fingerprint"
 require "xml/kit/id"
 require "xml/kit/namespaces"
 require "xml/kit/version"
+require "xml/kit/xml"
 require "xml/kit/xml_decryption"
 
 module Xml
xml-kit/spec/xml/certificate_spec.rb
@@ -0,0 +1,13 @@
+RSpec.describe Xml::Kit::Certificate do
+  subject { described_class.new(certificate, use: :signing) }
+  let(:certificate) do
+    cert, _ = generate_key_pair('password')
+    cert
+  end
+
+  describe "#fingerprint" do
+    it 'returns a fingerprint' do
+      expect(subject.fingerprint).to be_instance_of(Xml::Kit::Fingerprint)
+    end
+  end
+end
spec/saml/fingerprint_spec.rb → xml-kit/spec/xml/fingerprint_spec.rb
@@ -1,7 +1,7 @@
-RSpec.describe Saml::Kit::Fingerprint do
+RSpec.describe Xml::Kit::Fingerprint do
   describe "#sha" do
     it 'returns the SHA256' do
-      certificate, _ = Saml::Kit::SelfSignedCertificate.new("password").create
+      certificate, _ = generate_key_pair("password")
       x509 = OpenSSL::X509::Certificate.new(certificate)
       sha256 = OpenSSL::Digest::SHA256.new.hexdigest(x509.to_der).upcase.scan(/../).join(":")
 
@@ -9,7 +9,7 @@ RSpec.describe Saml::Kit::Fingerprint do
     end
 
     it 'returns the SHA1' do
-      certificate, _ = Saml::Kit::SelfSignedCertificate.new("password").create
+      certificate, _ = generate_key_pair("password")
       x509 = OpenSSL::X509::Certificate.new(certificate)
       sha1 = OpenSSL::Digest::SHA1.new.hexdigest(x509.to_der).upcase.scan(/../).join(":")
 
@@ -18,7 +18,7 @@ RSpec.describe Saml::Kit::Fingerprint do
   end
 
   it 'produces correct hash keys' do
-    certificate, _ = Saml::Kit::SelfSignedCertificate.new("password").create
+    certificate, _ = generate_key_pair("password")
     items = { }
     items[described_class.new(certificate)] = "HI"
     items[described_class.new(certificate)] = "BYE"
spec/saml/xml_spec.rb → xml-kit/spec/xml/xml_spec.rb
@@ -1,4 +1,4 @@
-RSpec.describe Saml::Kit::Xml do
+RSpec.describe Xml::Kit::Xml do
   describe "#valid_signature?" do
     let(:login_url) { "https://#{FFaker::Internet.domain_name}/login" }
     let(:logout_url) { "https://#{FFaker::Internet.domain_name}/logout" }
xml-kit/xml-kit.gemspec
@@ -21,6 +21,7 @@ Gem::Specification.new do |spec|
   spec.executables   = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
   spec.require_paths = ["lib"]
 
+  spec.add_dependency "activemodel", ">= 4.2.0"
   spec.add_development_dependency "bundler", "~> 1.16"
   spec.add_development_dependency "ffaker", "~> 2.7"
   spec.add_development_dependency "rake", "~> 10.0"