Commit dd1fc29
Changed files (21)
lib
spec
xml-kit
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"