Commit 9c9fdae
Changed files (5)
lib
spec
lib/saml/kit/configuration.rb
@@ -18,6 +18,10 @@ module Saml
signing_certificate_pem.to_s.gsub(BEGIN_CERT, '').gsub(END_CERT, '').gsub(/\n/, '')
end
+ def signing_x509
+ OpenSSL::X509::Certificate.new(signing_certificate_pem)
+ end
+
def signing_private_key
OpenSSL::PKey::RSA.new(signing_private_key_pem, signing_private_key_password)
end
lib/saml/kit/metadata.rb
@@ -0,0 +1,58 @@
+module Saml
+ module Kit
+ class Metadata
+ NAMESPACES = {
+ "NameFormat": Namespaces::Formats::Attr::SPLAT,
+ "ds": Namespaces::SIGNATURE,
+ "md": Namespaces::METADATA,
+ "saml": Namespaces::ASSERTION,
+ }.freeze
+
+ attr_reader :xml, :descriptor_name
+
+ def initialize(descriptor_name, xml)
+ @descriptor_name = descriptor_name
+ @xml = xml
+ end
+
+ def certificates
+ xpath = "/md:EntityDescriptor/md:#{descriptor_name}/md:KeyDescriptor"
+ find_all(xpath).map do |item|
+ cert = item.at_xpath("./ds:KeyInfo/ds:X509Data/ds:X509Certificate", NAMESPACES).text
+ {
+ fingerprint: fingerprint_for(cert, OpenSSL::Digest::SHA256),
+ text: cert,
+ use: item.attribute('use').value,
+ }
+ end
+ end
+
+ def to_xml
+ @xml
+ end
+
+ private
+
+ def document
+ @document ||= Nokogiri::XML(@xml)
+ end
+
+ def find_by(xpath)
+ document.at_xpath(xpath, NAMESPACES)
+ end
+
+ def find_all(xpath)
+ document.search(xpath, NAMESPACES)
+ end
+
+ def fingerprint_for(value, algorithm)
+ x509 = OpenSSL::X509::Certificate.new(Base64.decode64(value))
+ pretty_fingerprint(algorithm.new.hexdigest(x509.to_der))
+ end
+
+ def pretty_fingerprint(fingerprint)
+ fingerprint.upcase.scan(/../).join(":")
+ end
+ end
+ end
+end
lib/saml/kit/service_provider_metadata.rb
@@ -1,13 +1,11 @@
module Saml
module Kit
- class ServiceProviderMetadata
+ class ServiceProviderMetadata < Metadata
def initialize(xml)
- @xml = xml
+ super("SPSSODescriptor", xml)
end
- def to_xml
- @xml
- end
+ private
class Builder
attr_accessor :id, :entity_id, :acs_urls
lib/saml/kit.rb
@@ -12,6 +12,7 @@ require "xmldsig"
require "saml/kit/authentication_request"
require "saml/kit/configuration"
require "saml/kit/namespaces"
+require "saml/kit/metadata"
require "saml/kit/request"
require "saml/kit/response"
require "saml/kit/service_provider_registry"
spec/saml/service_provider_metadata_spec.rb
@@ -42,10 +42,24 @@ RSpec.describe Saml::Kit::ServiceProviderMetadata do
end
describe described_class do
+ let(:entity_id) { FFaker::Movie.title }
+ let(:acs_url) { "https://#{FFaker::Internet.domain_name}/acs" }
let(:builder) { described_class::Builder.new }
+ subject do
+ builder.entity_id = entity_id
+ builder.add_acs_url(acs_url)
+ builder.build
+ end
it 'returns each of the certificates' do
-
+ expected_sha256 = OpenSSL::Digest::SHA256.new.hexdigest(Saml::Kit.configuration.signing_x509.to_der)
+ expect(subject.certificates).to match_array([
+ {
+ fingerprint: expected_sha256.upcase.scan(/../).join(":"),
+ use: "signing",
+ text: Saml::Kit.configuration.stripped_signing_certificate
+ }
+ ])
end
end
end