diff --git a/README.md b/README.md index 50f99ebe..d8c48dd7 100644 --- a/README.md +++ b/README.md @@ -78,11 +78,6 @@ 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" diff --git a/lib/saml_idp/algorithmable.rb b/lib/saml_idp/algorithmable.rb index 354dbb92..182d6114 100644 --- a/lib/saml_idp/algorithmable.rb +++ b/lib/saml_idp/algorithmable.rb @@ -1,10 +1,9 @@ module SamlIdp module Algorithmable def algorithm - algorithm_check = raw_algorithm || SamlIdp.config.algorithm - return algorithm_check if algorithm_check.respond_to?(:digest) + return raw_algorithm if raw_algorithm.respond_to?(:digest) begin - OpenSSL::Digest.const_get(algorithm_check.to_s.upcase) + OpenSSL::Digest.const_get(raw_algorithm.to_s.upcase) rescue NameError OpenSSL::Digest::SHA1 end diff --git a/lib/saml_idp/assertion_builder.rb b/lib/saml_idp/assertion_builder.rb index 8e0170fa..482ab16a 100644 --- a/lib/saml_idp/assertion_builder.rb +++ b/lib/saml_idp/assertion_builder.rb @@ -18,23 +18,29 @@ class AssertionBuilder attr_accessor :session_expiry attr_accessor :name_id_formats_opts attr_accessor :asserted_attributes_opts + attr_accessor :public_cert + attr_accessor :private_key + attr_accessor :pv_key_password delegate :config, to: :SamlIdp def initialize( - reference_id, - issuer_uri, - principal, - audience_uri, - saml_request_id, - saml_acs_url, - raw_algorithm, - authn_context_classref, - expiry=60*60, - encryption_opts=nil, - session_expiry=nil, - name_id_formats_opts = nil, - asserted_attributes_opts = nil + reference_id:, + issuer_uri:, + principal:, + audience_uri:, + saml_request_id:, + saml_acs_url:, + raw_algorithm:, + authn_context_classref:, + public_cert:, + private_key:, + pv_key_password:, + expiry: 60*60, + encryption_opts: nil, + session_expiry: nil, + name_id_formats_opts: nil, + asserted_attributes_opts: nil ) self.reference_id = reference_id self.issuer_uri = issuer_uri @@ -49,6 +55,17 @@ def initialize( self.session_expiry = session_expiry.nil? ? config.session_expiry : session_expiry self.name_id_formats_opts = name_id_formats_opts self.asserted_attributes_opts = asserted_attributes_opts + self.public_cert = public_cert + self.private_key = private_key + self.pv_key_password = pv_key_password + end + + def encrypt(opts = {}) + raise "Must set encryption_opts to encrypt" unless encryption_opts + raw_xml = opts[:sign] ? signed : raw + require 'saml_idp/encryptor' + encryptor = Encryptor.new encryption_opts + encryptor.encrypt(raw_xml) end def fresh @@ -105,15 +122,8 @@ def fresh end end alias_method :raw, :fresh - private :fresh - def encrypt(opts = {}) - raise "Must set encryption_opts to encrypt" unless encryption_opts - raw_xml = opts[:sign] ? signed : raw - require 'saml_idp/encryptor' - encryptor = Encryptor.new encryption_opts - encryptor.encrypt(raw_xml) - end + private def asserted_attributes if asserted_attributes_opts.present? && !asserted_attributes_opts.empty? @@ -124,7 +134,6 @@ def asserted_attributes config.attributes end end - private :asserted_attributes def get_values_for(friendly_name, getter) result = nil @@ -141,12 +150,10 @@ def get_values_for(friendly_name, getter) end Array(result) end - private :get_values_for def name_id name_id_getter.call principal end - private :name_id def name_id_getter getter = name_id_format[:getter] @@ -156,56 +163,45 @@ def name_id_getter ->(principal) { principal.public_send getter.to_s } end end - private :name_id_getter def name_id_format @name_id_format ||= NameIdFormatter.new(name_id_formats).chosen end - private :name_id_format def name_id_formats @name_id_formats ||= (name_id_formats_opts || config.name_id.formats) end - private :name_id_formats def reference_string "_#{reference_id}" end - private :reference_string def now @now ||= Time.now.utc end - private :now def now_iso iso { now } end - private :now_iso def not_before iso { now - 5 } end - private :not_before def not_on_or_after_condition iso { now + expiry } end - private :not_on_or_after_condition def not_on_or_after_subject iso { now + 3 * 60 } end - private :not_on_or_after_subject def session_not_on_or_after iso { now + session_expiry } end - private :session_not_on_or_after def iso yield.iso8601 end - private :iso end end diff --git a/lib/saml_idp/configurator.rb b/lib/saml_idp/configurator.rb index 99a662a0..e645f912 100644 --- a/lib/saml_idp/configurator.rb +++ b/lib/saml_idp/configurator.rb @@ -25,8 +25,8 @@ 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.algorithm = :sha1 self.reference_id_generator = ->() { SecureRandom.uuid } self.service_provider = OpenStruct.new diff --git a/lib/saml_idp/controller.rb b/lib/saml_idp/controller.rb index 26ebbf29..283aff38 100644 --- a/lib/saml_idp/controller.rb +++ b/lib/saml_idp/controller.rb @@ -34,10 +34,7 @@ def acs_url def validate_saml_request(raw_saml_request = params[:SAMLRequest]) decode_request(raw_saml_request, params[:Signature], params[:SigAlg], params[:RelayState]) - return true if valid_saml_request? - - head :forbidden if defined?(::Rails) - false + valid_saml_request? end def decode_request(raw_saml_request, signature, sig_algorithm, relay_state) @@ -60,6 +57,9 @@ def encode_authn_response(principal, opts = {}) audience_uri = opts[:audience_uri] || saml_request.issuer || saml_acs_url[/^(.*?\/\/.*?\/)/, 1] opt_issuer_uri = opts[:issuer_uri] || issuer_uri my_authn_context_classref = opts[:authn_context_classref] || authn_context_classref + public_cert = opts[:public_cert] || SamlIdp.config.x509_certificate + private_key = opts[:private_key] || SamlIdp.config.secret_key + pv_key_password = opts[:pv_key_password] || SamlIdp.config.password acs_url = opts[:acs_url] || saml_acs_url expiry = opts[:expiry] || 60*60 session_expiry = opts[:session_expiry] @@ -73,33 +73,39 @@ def encode_authn_response(principal, opts = {}) compress_opts = opts[:compress] || false SamlResponse.new( - reference_id, - response_id, - opt_issuer_uri, - principal, - audience_uri, - saml_request_id, - acs_url, - (opts[:algorithm] || algorithm || default_algorithm), - my_authn_context_classref, - expiry, - encryption_opts, - session_expiry, - name_id_formats_opts, - asserted_attributes_opts, - signed_message_opts, - signed_assertion_opts, - compress_opts + reference_id: reference_id, + response_id: response_id, + issuer_uri: opt_issuer_uri, + principal: principal, + audience_uri: audience_uri, + saml_request_id: saml_request_id, + saml_acs_url: acs_url, + algorithm: (opts[:algorithm] || algorithm || default_algorithm), + authn_context_classref: my_authn_context_classref, + public_cert: public_cert, + private_key: private_key, + pv_key_password: pv_key_password, + expiry: expiry, + encryption_opts: encryption_opts, + session_expiry: session_expiry, + name_id_formats_opts: name_id_formats_opts, + asserted_attributes_opts: asserted_attributes_opts, + signed_message_opts: signed_message_opts, + signed_assertion_opts: signed_assertion_opts, + compression_opts: compress_opts ).build end def encode_logout_response(_principal, opts = {}) SamlIdp::LogoutResponseBuilder.new( - get_saml_response_id, - (opts[:issuer_uri] || issuer_uri), - saml_logout_url, - saml_request_id, - (opts[:algorithm] || algorithm || default_algorithm) + response_id: get_saml_response_id, + issuer_uri: (opts[:issuer_uri] || issuer_uri), + saml_slo_url: saml_logout_url, + saml_request_id: saml_request_id, + algorithm: (opts[:algorithm] || algorithm || default_algorithm), + public_cert: opts[:public_cert] || SamlIdp.config.x509_certificate, + private_key: opts[:private_key] || SamlIdp.config.secret_key, + pv_key_password: opts[:pv_key_password] || SamlIdp.config.password ).signed end diff --git a/lib/saml_idp/logout_builder.rb b/lib/saml_idp/logout_builder.rb index 7d049dd6..230e898c 100644 --- a/lib/saml_idp/logout_builder.rb +++ b/lib/saml_idp/logout_builder.rb @@ -7,12 +7,26 @@ class LogoutBuilder attr_accessor :issuer_uri attr_accessor :saml_slo_url attr_accessor :algorithm + attr_accessor :public_cert + attr_accessor :private_key + attr_accessor :pv_key_password - def initialize(response_id, issuer_uri, saml_slo_url, algorithm) + def initialize( + response_id:, + issuer_uri:, + saml_slo_url:, + algorithm:, + public_cert:, + private_key:, + pv_key_password: + ) self.response_id = response_id self.issuer_uri = issuer_uri self.saml_slo_url = saml_slo_url self.algorithm = algorithm + self.public_cert = public_cert + self.private_key = private_key + self.pv_key_password = pv_key_password end # this is an abstract base class. diff --git a/lib/saml_idp/logout_request_builder.rb b/lib/saml_idp/logout_request_builder.rb index b75f9315..87f76c89 100644 --- a/lib/saml_idp/logout_request_builder.rb +++ b/lib/saml_idp/logout_request_builder.rb @@ -3,8 +3,25 @@ module SamlIdp class LogoutRequestBuilder < LogoutBuilder attr_accessor :name_id - def initialize(response_id, issuer_uri, saml_slo_url, name_id, algorithm) - super(response_id, issuer_uri, saml_slo_url, algorithm) + def initialize( + response_id:, + issuer_uri:, + saml_slo_url:, + name_id:, + algorithm:, + public_cert:, + private_key:, + pv_key_password: nil + ) + super( + response_id: response_id, + issuer_uri: issuer_uri, + saml_slo_url: saml_slo_url, + algorithm: algorithm, + public_cert: public_cert, + private_key: private_key, + pv_key_password: pv_key_password + ) self.name_id = name_id end diff --git a/lib/saml_idp/logout_response_builder.rb b/lib/saml_idp/logout_response_builder.rb index fd14116b..ee9370cb 100644 --- a/lib/saml_idp/logout_response_builder.rb +++ b/lib/saml_idp/logout_response_builder.rb @@ -3,8 +3,25 @@ module SamlIdp class LogoutResponseBuilder < LogoutBuilder attr_accessor :saml_request_id - def initialize(response_id, issuer_uri, saml_slo_url, saml_request_id, algorithm) - super(response_id, issuer_uri, saml_slo_url, algorithm) + def initialize( + response_id:, + issuer_uri:, + saml_slo_url:, + saml_request_id:, + algorithm:, + public_cert:, + private_key:, + pv_key_password: nil + ) + super( + response_id: response_id, + issuer_uri: issuer_uri, + saml_slo_url: saml_slo_url, + algorithm: algorithm, + public_cert: public_cert, + private_key: private_key, + pv_key_password: pv_key_password + ) self.saml_request_id = saml_request_id end diff --git a/lib/saml_idp/metadata_builder.rb b/lib/saml_idp/metadata_builder.rb index 92258e38..5d77caad 100644 --- a/lib/saml_idp/metadata_builder.rb +++ b/lib/saml_idp/metadata_builder.rb @@ -160,6 +160,16 @@ def x509_certificate .gsub(/\n/, "") end + alias_method :public_cert, :x509_certificate + + def private_key + SamlIdp.config.secret_key + end + + def pv_key_password + nil + end + %w[ support_email organization_name diff --git a/lib/saml_idp/response_builder.rb b/lib/saml_idp/response_builder.rb index 0686cd9b..fc278b98 100644 --- a/lib/saml_idp/response_builder.rb +++ b/lib/saml_idp/response_builder.rb @@ -11,16 +11,32 @@ class ResponseBuilder attr_accessor :saml_request_id attr_accessor :assertion_and_signature attr_accessor :raw_algorithm + attr_accessor :public_cert + attr_accessor :private_key + attr_accessor :pv_key_password alias_method :reference_id, :response_id - def initialize(response_id, issuer_uri, saml_acs_url, saml_request_id, assertion_and_signature, raw_algorithm) + def initialize( + response_id:, + issuer_uri:, + saml_acs_url:, + saml_request_id:, + assertion_and_signature:, + raw_algorithm:, + public_cert:, + private_key:, + pv_key_password: + ) self.response_id = response_id self.issuer_uri = issuer_uri self.saml_acs_url = saml_acs_url self.saml_request_id = saml_request_id self.assertion_and_signature = assertion_and_signature self.raw_algorithm = raw_algorithm + self.public_cert = public_cert + self.private_key = private_key + self.pv_key_password = pv_key_password end def encoded(signed_message: false, compress: false) @@ -31,15 +47,15 @@ def raw build end + private + def encode_raw_message(compress) Base64.strict_encode64(compress ? deflate(raw) : raw) end - private :encode_raw_message def encode_signed_message(compress) Base64.strict_encode64(compress ? deflate(signed) : signed) end - private :encode_signed_message def build resp_options = {} @@ -61,22 +77,17 @@ def build response << assertion_and_signature end end - private :build def response_id_string "_#{response_id}" end - alias_method :reference_id, :response_id - private :response_id_string def now_iso Time.now.utc.iso8601 end - private :now_iso def deflate(inflated) Zlib::Deflate.deflate(inflated, 9)[2..-5] end - private :deflate end end diff --git a/lib/saml_idp/saml_response.rb b/lib/saml_idp/saml_response.rb index 85cf48b1..ecda5cfe 100644 --- a/lib/saml_idp/saml_response.rb +++ b/lib/saml_idp/saml_response.rb @@ -12,8 +12,9 @@ class SamlResponse attr_accessor :saml_request_id attr_accessor :saml_acs_url attr_accessor :algorithm - attr_accessor :secret_key - attr_accessor :x509_certificate + attr_accessor :private_key + attr_accessor :pv_key_password + attr_accessor :public_cert attr_accessor :authn_context_classref attr_accessor :expiry attr_accessor :encryption_opts @@ -25,23 +26,26 @@ class SamlResponse attr_accessor :compression_opts def initialize( - reference_id, - response_id, - issuer_uri, - principal, - audience_uri, - saml_request_id, - saml_acs_url, - algorithm, - authn_context_classref, - expiry = 60 * 60, - encryption_opts = nil, - session_expiry = 0, - name_id_formats_opts = nil, - asserted_attributes_opts = nil, - signed_message_opts = false, - signed_assertion_opts = true, - compression_opts = false + reference_id:, + response_id:, + issuer_uri:, + principal:, + audience_uri:, + saml_request_id:, + saml_acs_url:, + algorithm:, + authn_context_classref:, + public_cert:, + private_key:, + pv_key_password:, + expiry: 60 * 60, + encryption_opts: nil, + session_expiry: 0, + name_id_formats_opts: nil, + asserted_attributes_opts: nil, + signed_message_opts: false, + signed_assertion_opts: true, + compression_opts: false ) self.reference_id = reference_id @@ -52,8 +56,9 @@ def initialize( self.saml_request_id = saml_request_id self.saml_acs_url = saml_acs_url self.algorithm = algorithm - self.secret_key = secret_key - self.x509_certificate = x509_certificate + self.private_key = private_key + self.pv_key_password = pv_key_password + self.public_cert = public_cert self.authn_context_classref = authn_context_classref self.expiry = expiry self.encryption_opts = encryption_opts @@ -80,7 +85,8 @@ def signed_assertion assertion_builder.raw end end - private :signed_assertion + + private def encoded_message if signed_message_opts @@ -89,29 +95,41 @@ def encoded_message response_builder.encoded(signed_message: false, compress: compression_opts) end end - private :encoded_message def response_builder - ResponseBuilder.new(response_id, issuer_uri, saml_acs_url, saml_request_id, signed_assertion, algorithm) + ResponseBuilder.new( + response_id: response_id, + issuer_uri: issuer_uri, + saml_acs_url: saml_acs_url, + saml_request_id: saml_request_id, + assertion_and_signature: signed_assertion, + raw_algorithm: algorithm, + public_cert: public_cert, + private_key: private_key, + pv_key_password: pv_key_password, + ) end - private :response_builder def assertion_builder @assertion_builder ||= - AssertionBuilder.new(reference_id || SecureRandom.uuid, - issuer_uri, - principal, - audience_uri, - saml_request_id, - saml_acs_url, - algorithm, - authn_context_classref, - expiry, - encryption_opts, - session_expiry, - name_id_formats_opts, - asserted_attributes_opts) + AssertionBuilder.new( + reference_id: (reference_id || SecureRandom.uuid), + issuer_uri: issuer_uri, + principal: principal, + audience_uri: audience_uri, + saml_request_id: saml_request_id, + saml_acs_url: saml_acs_url, + raw_algorithm: algorithm, + authn_context_classref: authn_context_classref, + public_cert: public_cert, + private_key: private_key, + pv_key_password: pv_key_password, + expiry: expiry, + encryption_opts: encryption_opts, + session_expiry: session_expiry, + name_id_formats_opts: name_id_formats_opts, + asserted_attributes_opts: asserted_attributes_opts + ) end - private :assertion_builder end end diff --git a/lib/saml_idp/signable.rb b/lib/saml_idp/signable.rb index 0a330a18..14c923a8 100644 --- a/lib/saml_idp/signable.rb +++ b/lib/saml_idp/signable.rb @@ -5,6 +5,7 @@ # * algorithm require 'saml_idp/signed_info_builder' require 'saml_idp/signature_builder' + module SamlIdp module Signable def self.included(base) @@ -24,6 +25,8 @@ def sign(el) el << signature if sign? end + private + def generated_reference_id if reference_id fin = yield reference_id if block_given? @@ -34,12 +37,10 @@ def generated_reference_id end block_given? ? fin : ref end - private :generated_reference_id def reference_id_generator SamlIdp.config.reference_id_generator end - private :reference_id_generator def with_signature original = @sign @@ -48,7 +49,6 @@ def with_signature @sign = original end end - private :with_signature def without_signature original = @sign @@ -57,49 +57,52 @@ def without_signature @sign = original end end - private :without_signature def sign? !!@sign end - private :sign? def signature - SignatureBuilder.new(signed_info_builder).raw + SignatureBuilder.new(signed_info_builder, get_public_cert).raw end - private :signature def signed_info_builder - SignedInfoBuilder.new(get_reference_id, get_digest, get_algorithm) + SignedInfoBuilder.new(get_reference_id, get_digest, get_algorithm, get_private_key, pv_key_password) end - private :signed_info_builder def get_reference_id send(self.class.reference_id_method) end - private :get_reference_id def get_digest without_signature do send(self.class.digest_method) end end - private :get_digest def get_algorithm send(self.class.algorithm_method) end - private :get_algorithm def get_raw send(self.class.raw_method) end - private :get_raw + + def get_public_cert + send(self.class.public_cert_method) + end + + def get_private_key + send(self.class.private_key_method) + end + + def pv_key_password + send(self.class.pv_key_password_method) + end def noko_raw Nokogiri::XML::Document.parse(get_raw) end - private :noko_raw def digest # Make it check for inclusive at some point (https://github.com/onelogin/ruby-saml/blob/master/lib/xml_security.rb#L159) @@ -111,7 +114,6 @@ def digest hash = digest_algorithm.digest(canon_hashed_element) Base64.strict_encode64(hash).gsub(/\n/, '') end - private :digest module ClassMethods def self.module_method(name, default = nil) @@ -125,6 +127,9 @@ def self.module_method(name, default = nil) module_method :digest module_method :algorithm module_method :reference_id + module_method :public_cert + module_method :private_key + module_method :pv_key_password end end end diff --git a/lib/saml_idp/signature_builder.rb b/lib/saml_idp/signature_builder.rb index 0406715c..fe6e4c39 100644 --- a/lib/saml_idp/signature_builder.rb +++ b/lib/saml_idp/signature_builder.rb @@ -1,10 +1,12 @@ require 'builder' + module SamlIdp class SignatureBuilder - attr_accessor :signed_info_builder + attr_accessor :signed_info_builder, :x509_certificate - def initialize(signed_info_builder) + def initialize(signed_info_builder, x509_certificate) self.signed_info_builder = signed_info_builder + self.x509_certificate = x509_certificate end def raw @@ -14,30 +16,31 @@ def raw signature.tag! "ds:SignatureValue", signature_value signature.KeyInfo xmlns: "http://www.w3.org/2000/09/xmldsig#" do |key_info| key_info.tag! "ds:X509Data" do |x509| - x509.tag! "ds:X509Certificate", x509_certificate + x509.tag! "ds:X509Certificate", der_certificate end end end end - def 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-----/,"") - .gsub(/\n/, "") + private + + def der_certificate + certificate_formatter(x509_certificate) end - private :x509_certificate def signed_info signed_info_builder.raw end - private :signed_info def signature_value signed_info_builder.signed end - private :signature_value + + def certificate_formatter(pem_certificate) + pem_certificate + .gsub(/-----BEGIN CERTIFICATE-----/,"") + .gsub(/-----END CERTIFICATE-----/,"") + .gsub(/\n/, "") + end end end diff --git a/lib/saml_idp/signed_info_builder.rb b/lib/saml_idp/signed_info_builder.rb index 4b0ff224..a858197e 100644 --- a/lib/saml_idp/signed_info_builder.rb +++ b/lib/saml_idp/signed_info_builder.rb @@ -22,11 +22,15 @@ class SignedInfoBuilder attr_accessor :reference_id attr_accessor :digest_value attr_accessor :raw_algorithm + attr_accessor :private_key + attr_accessor :pv_key_password - def initialize(reference_id, digest_value, raw_algorithm) + def initialize(reference_id, digest_value, raw_algorithm, private_key, pv_key_password) self.reference_id = reference_id self.digest_value = digest_value self.raw_algorithm = raw_algorithm + self.private_key = private_key + self.pv_key_password = pv_key_password end def raw @@ -49,40 +53,27 @@ def signed encoded.gsub(/\n/, "") end + private + def digest_method DIGEST_METHODS.fetch(clean_algorithm_name, DIGEST_METHODS["sha1"]) end - private :digest_method def signature_method SIGNATURE_METHODS.fetch(clean_algorithm_name, SIGNATURE_METHODS["sha1"]) end - private :signature_method def clean_algorithm_name algorithm_name.to_s.downcase end - private :clean_algorithm_name - - def 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.is_a?(Proc) ? SamlIdp.config.password.call : SamlIdp.config.password - end - private :password def encoded - key = OpenSSL::PKey::RSA.new(secret_key, password) + key = OpenSSL::PKey::RSA.new(private_key, pv_key_password) Base64.strict_encode64(key.sign(algorithm.new, raw)) end - private :encoded def reference_string "#_#{reference_id}" end - private :reference_string end end diff --git a/spec/lib/saml_idp/assertion_builder_spec.rb b/spec/lib/saml_idp/assertion_builder_spec.rb index 9e267464..8592cd3f 100644 --- a/spec/lib/saml_idp/assertion_builder_spec.rb +++ b/spec/lib/saml_idp/assertion_builder_spec.rb @@ -1,4 +1,6 @@ require 'spec_helper' +require 'debug' + module SamlIdp describe AssertionBuilder do let(:reference_id) { "abc" } @@ -22,16 +24,21 @@ module SamlIdp let(:session_expiry) { nil } let(:name_id_formats_opt) { nil } let(:asserted_attributes_opt) { nil } + let(:principal) { Struct.new(:email, :asserted_attributes).new('foo@example.com', { emailAddress: { getter: :email } })} + subject { described_class.new( - reference_id, - issuer_uri, - name_id, - audience_uri, - saml_request_id, - saml_acs_url, - algorithm, - authn_context_classref, - expiry + reference_id: reference_id, + issuer_uri: issuer_uri, + principal: name_id, + audience_uri: audience_uri, + saml_request_id: saml_request_id, + saml_acs_url: saml_acs_url, + raw_algorithm: algorithm, + authn_context_classref: authn_context_classref, + public_cert: sp_encrypted_pv_key[:sp_public_cert], + private_key: sp_encrypted_pv_key[:sp_encrypted_pv_key], + pv_key_password: sp_encrypted_pv_key[:pv_key_password], + expiry: expiry ) } context "No Request ID" do @@ -70,18 +77,19 @@ module SamlIdp describe "with principal.asserted_attributes" do it "delegates attributes to principal" do - Principal = Struct.new(:email, :asserted_attributes) - principal = Principal.new('foo@example.com', { emailAddress: { getter: :email } }) builder = described_class.new( - reference_id, - issuer_uri, - principal, - audience_uri, - saml_request_id, - saml_acs_url, - algorithm, - authn_context_classref, - expiry + reference_id: reference_id, + issuer_uri: issuer_uri, + principal: principal, + audience_uri: audience_uri, + saml_request_id: saml_request_id, + saml_acs_url: saml_acs_url, + raw_algorithm: algorithm, + authn_context_classref: authn_context_classref, + public_cert: sp_encrypted_pv_key[:sp_public_cert], + private_key: sp_encrypted_pv_key[:sp_encrypted_pv_key], + pv_key_password: sp_encrypted_pv_key[:pv_key_password], + expiry: expiry ) Timecop.travel(Time.zone.local(2010, 6, 1, 13, 0, 0)) do expect(builder.raw).to eq("http://sportngin.comfoo@example.comhttp://example.comurn:oasis:names:tc:SAML:2.0:ac:classes:Passwordfoo@example.com") @@ -91,16 +99,19 @@ module SamlIdp it "builds encrypted XML" do builder = described_class.new( - reference_id, - issuer_uri, - name_id, - audience_uri, - saml_request_id, - saml_acs_url, - algorithm, - authn_context_classref, - expiry, - encryption_opts + reference_id: reference_id, + issuer_uri: issuer_uri, + principal: name_id, + audience_uri: audience_uri, + saml_request_id: saml_request_id, + saml_acs_url: saml_acs_url, + raw_algorithm: algorithm, + authn_context_classref: authn_context_classref, + public_cert: sp_encrypted_pv_key[:sp_public_cert], + private_key: sp_encrypted_pv_key[:sp_encrypted_pv_key], + pv_key_password: sp_encrypted_pv_key[:pv_key_password], + expiry: expiry, + encryption_opts: encryption_opts ) encrypted_xml = builder.encrypt expect(encrypted_xml).to_not match(audience_uri) @@ -118,19 +129,22 @@ module SamlIdp UserWithUniqueId = Struct.new(:unique_identifier, :email, :asserted_attributes) principal = UserWithUniqueId.new('unique_identifier_123456', 'foo@example.com', { emailAddress: { getter: :email } }) builder = described_class.new( - reference_id, - issuer_uri, - principal, - audience_uri, - saml_request_id, - saml_acs_url, - algorithm, - authn_context_classref, - expiry, - encryption_opts, - session_expiry, - name_id_formats_opt, - asserted_attributes_opt + reference_id: reference_id, + issuer_uri: issuer_uri, + principal: principal, + audience_uri: audience_uri, + saml_request_id: saml_request_id, + saml_acs_url: saml_acs_url, + raw_algorithm: algorithm, + authn_context_classref: authn_context_classref, + public_cert: sp_encrypted_pv_key[:sp_public_cert], + private_key: sp_encrypted_pv_key[:sp_encrypted_pv_key], + pv_key_password: sp_encrypted_pv_key[:pv_key_password], + expiry: expiry, + encryption_opts: encryption_opts, + session_expiry: session_expiry, + name_id_formats_opts: name_id_formats_opt, + asserted_attributes_opts: asserted_attributes_opt ) Timecop.travel(Time.zone.local(2010, 6, 1, 13, 0, 0)) do expect(builder.raw).to eq("http://sportngin.comunique_identifier_123456http://example.comurn:oasis:names:tc:SAML:2.0:ac:classes:Passwordfoo@example.com") @@ -156,19 +170,22 @@ module SamlIdp UserWithName = Struct.new(:email, :first_name, :last_name) principal = UserWithName.new('foo@example.com', 'George', 'Washington') builder = described_class.new( - reference_id, - issuer_uri, - principal, - audience_uri, - saml_request_id, - saml_acs_url, - algorithm, - authn_context_classref, - expiry, - encryption_opts, - session_expiry, - name_id_formats_opt, - asserted_attributes_opt + reference_id: reference_id, + issuer_uri: issuer_uri, + principal: principal, + audience_uri: audience_uri, + saml_request_id: saml_request_id, + saml_acs_url: saml_acs_url, + raw_algorithm: algorithm, + authn_context_classref: authn_context_classref, + public_cert: sp_encrypted_pv_key[:sp_public_cert], + private_key: sp_encrypted_pv_key[:sp_encrypted_pv_key], + pv_key_password: sp_encrypted_pv_key[:pv_key_password], + expiry: expiry, + encryption_opts: encryption_opts, + session_expiry: session_expiry, + name_id_formats_opts: name_id_formats_opt, + asserted_attributes_opts: asserted_attributes_opt ) Timecop.travel(Time.zone.local(2010, 6, 1, 13, 0, 0)) do expect(builder.raw).to eq("http://sportngin.comfoo@example.comhttp://example.comurn:oasis:names:tc:SAML:2.0:ac:classes:PasswordGeorgeWashington") @@ -185,16 +202,19 @@ module SamlIdp it "sets default session_expiry from config" do builder = described_class.new( - reference_id, - issuer_uri, - name_id, - audience_uri, - saml_request_id, - saml_acs_url, - algorithm, - authn_context_classref, - expiry, - encryption_opts + reference_id: reference_id, + issuer_uri: issuer_uri, + principal: name_id, + audience_uri: audience_uri, + saml_request_id: saml_request_id, + saml_acs_url: saml_acs_url, + raw_algorithm: algorithm, + authn_context_classref: authn_context_classref, + public_cert: sp_encrypted_pv_key[:sp_public_cert], + private_key: sp_encrypted_pv_key[:sp_encrypted_pv_key], + pv_key_password: sp_encrypted_pv_key[:pv_key_password], + expiry: expiry, + encryption_opts: encryption_opts ) expect(builder.session_expiry).to eq(8) end @@ -212,19 +232,22 @@ module SamlIdp UserWithUniqueId = Struct.new(:unique_identifier, :email, :asserted_attributes) principal = UserWithUniqueId.new('unique_identifier_123456', 'foo@example.com', { emailAddress: { getter: :email } }) builder = described_class.new( - reference_id, - issuer_uri, - principal, - audience_uri, - saml_request_id, - saml_acs_url, - algorithm, - authn_context_classref, - expiry, - encryption_opts, - session_expiry, - name_id_formats_opt, - asserted_attributes_opt + reference_id: reference_id, + issuer_uri: issuer_uri, + principal: principal, + audience_uri: audience_uri, + saml_request_id: saml_request_id, + saml_acs_url: saml_acs_url, + raw_algorithm: algorithm, + authn_context_classref: authn_context_classref, + public_cert: sp_encrypted_pv_key[:sp_public_cert], + private_key: sp_encrypted_pv_key[:sp_encrypted_pv_key], + pv_key_password: sp_encrypted_pv_key[:pv_key_password], + expiry: expiry, + encryption_opts: encryption_opts, + session_expiry: session_expiry, + name_id_formats_opts: name_id_formats_opt, + asserted_attributes_opts: asserted_attributes_opt ) Timecop.travel(Time.zone.local(2010, 6, 1, 13, 0, 0)) do expect(builder.raw).to eq("http://sportngin.comunique_identifier_123456http://example.comurn:oasis:names:tc:SAML:2.0:ac:classes:Passwordfoo@example.com") @@ -250,19 +273,22 @@ module SamlIdp UserWithName = Struct.new(:email, :first_name, :last_name) principal = UserWithName.new('foo@example.com', 'George', 'Washington') builder = described_class.new( - reference_id, - issuer_uri, - principal, - audience_uri, - saml_request_id, - saml_acs_url, - algorithm, - authn_context_classref, - expiry, - encryption_opts, - session_expiry, - name_id_formats_opt, - asserted_attributes_opt + reference_id: reference_id, + issuer_uri: issuer_uri, + principal: principal, + audience_uri: audience_uri, + saml_request_id: saml_request_id, + saml_acs_url: saml_acs_url, + raw_algorithm: algorithm, + authn_context_classref: authn_context_classref, + public_cert: sp_encrypted_pv_key[:sp_public_cert], + private_key: sp_encrypted_pv_key[:sp_encrypted_pv_key], + pv_key_password: sp_encrypted_pv_key[:pv_key_password], + expiry: expiry, + encryption_opts: encryption_opts, + session_expiry: session_expiry, + name_id_formats_opts: name_id_formats_opt, + asserted_attributes_opts: asserted_attributes_opt ) Timecop.travel(Time.zone.local(2010, 6, 1, 13, 0, 0)) do expect(builder.raw).to eq("http://sportngin.comfoo@example.comhttp://example.comurn:oasis:names:tc:SAML:2.0:ac:classes:PasswordGeorgeWashington") diff --git a/spec/lib/saml_idp/configurator_spec.rb b/spec/lib/saml_idp/configurator_spec.rb index 80da3b14..59c399a8 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.call).to eq(Default::X509_CERTIFICATE) + expect(subject.x509_certificate).to eq(Default::X509_CERTIFICATE) end it "has a valid secret_key" do - expect(subject.secret_key.call).to eq(Default::SECRET_KEY) + expect(subject.secret_key).to eq(Default::SECRET_KEY) end it "has a valid algorithm" do diff --git a/spec/lib/saml_idp/logout_request_builder_spec.rb b/spec/lib/saml_idp/logout_request_builder_spec.rb index 73f0a626..26890159 100644 --- a/spec/lib/saml_idp/logout_request_builder_spec.rb +++ b/spec/lib/saml_idp/logout_request_builder_spec.rb @@ -19,11 +19,13 @@ module SamlIdp subject do described_class.new( - response_id, - issuer_uri, - saml_slo_url, - name_id, - algorithm + response_id: response_id, + issuer_uri: issuer_uri, + saml_slo_url: saml_slo_url, + name_id: name_id, + algorithm: algorithm, + public_cert: SamlIdp::Default::X509_CERTIFICATE, + private_key: SamlIdp::Default::SECRET_KEY ) end diff --git a/spec/lib/saml_idp/logout_response_builder_spec.rb b/spec/lib/saml_idp/logout_response_builder_spec.rb index a4ca7bfd..44f730dd 100644 --- a/spec/lib/saml_idp/logout_response_builder_spec.rb +++ b/spec/lib/saml_idp/logout_response_builder_spec.rb @@ -19,11 +19,13 @@ module SamlIdp subject do described_class.new( - response_id, - issuer_uri, - saml_slo_url, - request_id, - algorithm + response_id: response_id, + issuer_uri: issuer_uri, + saml_slo_url: saml_slo_url, + saml_request_id: request_id, + algorithm: algorithm, + public_cert: SamlIdp::Default::X509_CERTIFICATE, + private_key: SamlIdp::Default::SECRET_KEY ) end diff --git a/spec/lib/saml_idp/response_builder_spec.rb b/spec/lib/saml_idp/response_builder_spec.rb index 9105eede..ce5224e8 100644 --- a/spec/lib/saml_idp/response_builder_spec.rb +++ b/spec/lib/saml_idp/response_builder_spec.rb @@ -8,12 +8,15 @@ module SamlIdp let(:assertion_and_signature) { "http://sportngin.comstuffjon.phenow@sportngin.comhttp://example.comjon.phenow@sportngin.comurn:federation:authentication:windows" } let(:algorithm) { :sha256 } subject { described_class.new( - response_id, - issuer_uri, - saml_acs_url, - saml_request_id, - assertion_and_signature, - algorithm + response_id: response_id, + issuer_uri: issuer_uri, + saml_acs_url: saml_acs_url, + saml_request_id: saml_request_id, + assertion_and_signature: assertion_and_signature, + raw_algorithm: algorithm, + public_cert: sp_encrypted_pv_key[:sp_public_cert], + private_key: sp_encrypted_pv_key[:sp_encrypted_pv_key], + pv_key_password: sp_encrypted_pv_key[:pv_key_password], ) } before do diff --git a/spec/lib/saml_idp/saml_response_spec.rb b/spec/lib/saml_idp/saml_response_spec.rb index b79f8a2b..f702054c 100644 --- a/spec/lib/saml_idp/saml_response_spec.rb +++ b/spec/lib/saml_idp/saml_response_spec.rb @@ -28,43 +28,50 @@ module SamlIdp let(:unsigned_response_opts) { false } let(:signed_assertion_opts) { true } let(:compress_opts) { false } - let(:subject_encrypted) { described_class.new(reference_id, - response_id, - issuer_uri, - name_id, - audience_uri, - saml_request_id, - saml_acs_url, - algorithm, - authn_context_classref, - expiry, - encryption_opts, - session_expiry, - nil, - nil, - unsigned_response_opts, - signed_assertion_opts, - compress_opts + let(:subject_encrypted) { described_class.new( + reference_id: reference_id, + response_id: response_id, + issuer_uri: issuer_uri, + principal: name_id, + audience_uri: audience_uri, + saml_request_id: saml_request_id, + saml_acs_url: saml_acs_url, + algorithm: algorithm, + authn_context_classref: authn_context_classref, + public_cert: x509_certificate, + private_key: secret_key, + pv_key_password: nil, + expiry: expiry, + encryption_opts: encryption_opts, + session_expiry: session_expiry, + name_id_formats_opts: nil, + asserted_attributes_opts: nil, + signed_message_opts: unsigned_response_opts, + signed_assertion_opts: signed_assertion_opts, + compression_opts: compress_opts ) } - subject { described_class.new(reference_id, - response_id, - issuer_uri, - name_id, - audience_uri, - saml_request_id, - saml_acs_url, - algorithm, - authn_context_classref, - expiry, - nil, - session_expiry, - nil, - nil, - signed_response_opts, - signed_assertion_opts, - compress_opts + subject { described_class.new(reference_id: reference_id, + response_id: response_id, + issuer_uri: issuer_uri, + principal: name_id, + audience_uri: audience_uri, + saml_request_id: saml_request_id, + saml_acs_url: saml_acs_url, + algorithm: algorithm, + authn_context_classref: authn_context_classref, + public_cert: x509_certificate, + private_key: secret_key, + pv_key_password: nil, + expiry: expiry, + encryption_opts: nil, + session_expiry: session_expiry, + name_id_formats_opts: nil, + asserted_attributes_opts: nil, + signed_message_opts: signed_response_opts, + signed_assertion_opts: signed_assertion_opts, + compression_opts: compress_opts ) } diff --git a/spec/lib/saml_idp/signable_spec.rb b/spec/lib/saml_idp/signable_spec.rb index cd9a90ae..0d033780 100644 --- a/spec/lib/saml_idp/signable_spec.rb +++ b/spec/lib/saml_idp/signable_spec.rb @@ -1,7 +1,9 @@ # encoding: utf-8 require 'spec_helper' + class MockSignable include SamlIdp::Signable + include SecurityHelpers def raw builder = Builder::XmlMarkup.new @@ -21,6 +23,18 @@ def digest def algorithm OpenSSL::Digest::SHA1 end + + def private_key + sp_encrypted_pv_key[:sp_encrypted_pv_key] + end + + def pv_key_password + sp_encrypted_pv_key[:pv_key_password] + end + + def public_cert + sp_encrypted_pv_key[:sp_public_cert] + end end module SamlIdp @@ -72,6 +86,5 @@ module SamlIdp it "has a valid signed" do expect(subject.signed).to match all_regex end - end end diff --git a/spec/lib/saml_idp/signature_builder_spec.rb b/spec/lib/saml_idp/signature_builder_spec.rb index ff28575a..8fe612b2 100644 --- a/spec/lib/saml_idp/signature_builder_spec.rb +++ b/spec/lib/saml_idp/signature_builder_spec.rb @@ -5,7 +5,8 @@ module SamlIdp let(:raw_info) { "em8csGAWynywpe8S4nN64o56/4DosXi2XWMY6RJ6YfA=" } let(:signed_info) { double raw: raw_info, signed: signed } subject { described_class.new( - signed_info + signed_info, + SamlIdp::Default::X509_CERTIFICATE ) } before do diff --git a/spec/lib/saml_idp/signed_info_builder_spec.rb b/spec/lib/saml_idp/signed_info_builder_spec.rb index 4685d39a..0ac39966 100644 --- a/spec/lib/saml_idp/signed_info_builder_spec.rb +++ b/spec/lib/saml_idp/signed_info_builder_spec.rb @@ -1,4 +1,5 @@ require 'spec_helper' + module SamlIdp describe SignedInfoBuilder do let(:reference_id) { "abc" } @@ -7,7 +8,9 @@ module SamlIdp subject { described_class.new( reference_id, digest, - algorithm + algorithm, + sp_encrypted_pv_key[:sp_encrypted_pv_key], + sp_encrypted_pv_key[:pv_key_password] ) } before do @@ -19,7 +22,7 @@ module SamlIdp end it "builds a legit digest of the XML file" do - expect(subject.signed).to eq("hKLeWLRgatHcV6N5Fc8aKveqNp6Y/J4m2WSYp0awGFtsCTa/2nab32wI3du+3kuuIy59EDKeUhHVxEfyhoHUo6xTZuO2N7XcTpSonuZ/CB3WjozC2Q/9elss3z1rOC3154v5pW4puirLPRoG+Pwi8SmptxNRHczr6NvmfYmmGfo=") + expect(subject.signed).to eq("YP2e6cTEfRj1vI1/gaaSApLAMxPBQzyuBvbvulbS99x17LCLDSKvqA6MyU4WLavmVba5qiF88e97f0XKLsse7gEGOfnF/6jaRV3fePXk6+LFaeYUHZ11u7PkZ1/ucO459ASsuPN/9P9xCY2t+jtVKvIrcSZQbomymfsWGt9P/oY83elKU712aAwqcfvINsa1N+RefZRwdAW4ATBwwcDjE3VTR6mKOyGMsPJ4HQcPrNiEmuwd1QaPH0H1LLzxtewGQGmIL2UqNE/QMe/kKiSTFZ0loBKuSEc9WBw5XuH31QxbzpLJjqM/C1qy4aykPqDUuJtQ4csx78GgfFS4uiqowg==") end end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index ffc9f9a8..61819b77 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -17,6 +17,7 @@ require 'ruby-saml' require 'saml_idp' require 'timecop' +require 'debug' Dir[File.dirname(__FILE__) + "/support/**/*.rb"].each {|f| require f} diff --git a/spec/support/certificates/sp_encrypted_pv_key.pem b/spec/support/certificates/sp_encrypted_pv_key.pem new file mode 100644 index 00000000..2fecdc96 --- /dev/null +++ b/spec/support/certificates/sp_encrypted_pv_key.pem @@ -0,0 +1,30 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-128-CBC,89BFDC1035C5C7A2277D87B8F0763A70 + +9Tpy80djhnb8S7Xq7O94TkH6ec38gO54JWbMbC3xTtVnR8lqvX6kIeF5gLjbySUI +Q30F+1bZ1/AiT1PeJ9Mg+TUEFDxiNrRw+liS3F6mhM5XyGe96FVOGEKp+WbCEznV +ZgLzzMXXwcAzKblsVNAiBAozqyfdhyGg/BhTcPXpAXt3wxy4VfbwHs1CW5+Ar+iN +qlYXDFyg+UPh0EbKQc7FUB6NKcgZ76yuaWQlkUfAbBjx4f7zpHSwYO29Gv2Hq/E4 +REhS4GXuJDTZLSDW3n6TcOszyudVYNSNFEjDWtc88/l3gQW5ZtJVnLarNMOfQF48 +MFFQBT/ksT/9GbCIKOonr12D+XlGgHJpNJrHQ+Hzee3sU8U4tn2/4sM2ZMrjOiMh +giuJq1OiM95ohK3XcdcE5apbMtCTzBjcwumG6MaI/okQURHuHvMvdhivhp5CC1Ix +dRx9cnCmXidEdhsgKBq5vBvcqt4VJqqkaGEA0YBAge//LZbzc1fp8Ghzjdev78Sb +SeW/QnzGTPW4FX/UMLrZPuwNpx9fJ1pJdI8UOOWBxIBkvl+1dM9WOVP+07b80RO1 +rJm+QKZVEbrHZKX8Gq3+DyvI2a+FUWv0WTDxp4fcPMAGy+Kr8Xratxh/fQhvksbV +ZK6/m/8f97zfxsUU5tM0B+WwIv6/KQm3wwloeL226OgmBX8x+WKthFe+MozchVLI +UNvXCw5NeGmIbLWlcoZuzsvHHcfNJ/iDaBLl6itJxd1sNiuamTHfpTQlxoDCwaQO +OqRRMfq8pjEgHYXHMm0us3sQ235yN5W32K2N79YlTQOQUA9QYHLlpmMvVRtOSRQY +GNhIPNWqLWP7+CAtfXVA0o97p5Wd0ySWwOcv3iJuAxywBg0a6s6iYV2lkRHHkJY2 +dvDH39hbaqRakPUKFOPkCHdHvN+cM7trvdxpzURj67u9IKLPMwK64FJ3LEerqSgh +FIcwTcN8jQBLdcsi9XHNPRJEaa+4Sf7KpeUYe79yZlFNDKU6yG8DMpt2uJ6p17C7 +R2L11AdsPC0MAgxaj2yNV1/CSP3wc6Y36AMSnRJtMsUX7BjZT6TSUjOj21zPfu9R +h2aJYe1224EpT6bb31Sgfky2TcIOXAY60g8slRLniCDzmexB6u/EUvF7A4fYXFRK +pgcbWVAfYr1/GqXs9srLLAeYRbFcg6aaTD63uTe0rf/Vse5h7c9tmMZ6/Wk/rkwQ +oguzl8rXvXd2mpJdhvT/NDI2AI6jzIDcCb/F21qlyfEk8K5Rlykm8BDoRNx6+wW/ +SuUZfnXJmywovvpRSsEaGTYo/3eERZVdIZqV5nLHVJtcTRzvh3QuCm2JC8S1HNHE +PboWwv1BHZOR9/llB/voip+DJuIGkBVwbN9mDUC+uf7L/y6Xj8kOvI7g3zaJR/ac +t2YjhgL3sxORZp8lIsYlwZYHT39jGkYP4Pi1HoVWH1sKyn+P55nF8f9BrQCmhyFU +t1K+p2AwzuWxYw6YThQYy2SdiGSaZ9axGrwlu1kdh9Vq2YDctXX+yR1Bs3DytK/6 +PzdLSUAJt4HoLCND+lXG8Ii79WWTCqX9UrYWTJN4PhApCnN+/RYft2Bjd8ZGl0E2 +-----END RSA PRIVATE KEY----- diff --git a/spec/support/certificates/sp_public_cert.pem b/spec/support/certificates/sp_public_cert.pem new file mode 100644 index 00000000..02bea35a --- /dev/null +++ b/spec/support/certificates/sp_public_cert.pem @@ -0,0 +1,16 @@ +-----BEGIN CERTIFICATE----- +MIICjTCCAXWgAwIBAgIVAOTwdQ89937l4RyuaJ7Ni1K2YifEMA0GCSqGSIb3DQEB +CwUAMAAwHhcNMjQxMTAxMjIyMzQ4WhcNMzQxMTAxMjIyMzQ4WjAAMIIBIjANBgkq +hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1Ddn+u21iDGHHcLLsThAgdAXLnvL8Pqi +aXKu+MoMu2LYu/pHPk6ZuCmecdM6Tsqdc69S1fCJGu45zSbSuQNzZnW+iLItzBYj +WWv5cgQdOTkT6WVUBsA7NU9sKKmCqsU/3DOCXbZ8OYPxnftZGRIZdydsENOG49f6 +195VJ7h3FybXUnqpaw+bO+pepl4UNl6Y6nIKv4eZnAXJ8P7sJX2iHiu5zl2y/eht +rrL9faNdiSdb2wERkcIZKDrnoGlTvxkFd7fr7sIHIIJvxCBvBpBrgSNfQrHtqjsG +STQ4IK1f5Vtwy8jVkuK+SBEzA+Ft6IlWDkTW3oTnFgVjwwOv0NQdNwIDAQABMA0G +CSqGSIb3DQEBCwUAA4IBAQC2nUkoFXCBVvmkJ9iwXnmJwTGPuDFlZh0zVAuDnVCi +DAcb5z+96GV1dPucFGP/0dtSVazHw3bpw1b9sm1844ne11XjU6PFGEkVAbAyA72Z +Vi0t+ksEVlXP044XjSvZLuWnETJU31w8MjUcoi4BUhdlPtgqYd5jWMSKTncpZCmp +zggCKpz6tSpJcBl7kBAudcxP3kCrWNku5V1OW/4Z4A27ISJLE+Gzi2Q+O/lKHydr +ebXtjQpuuCuMnNwWaLRnxQaQWmYdbVvCuXIweoC6pSPffwjbMpU4ZTpHn1UoPqUQ +9JfW50G2IUKQjq9ssjZAKcGsQIRAIwzwWLvNtl62OeoK +-----END CERTIFICATE----- diff --git a/spec/support/security_helpers.rb b/spec/support/security_helpers.rb index f6952ce7..93b57391 100644 --- a/spec/support/security_helpers.rb +++ b/spec/support/security_helpers.rb @@ -68,4 +68,12 @@ def sp_pv_key def sp_x509_cert @sp_x509_cert ||= File.read(File.join(File.dirname(__FILE__), 'certificates', 'sp_x509_cert.crt')) end + + def sp_encrypted_pv_key + @sp_encrypted_pv_key ||= { + sp_encrypted_pv_key: File.read(File.join(File.dirname(__FILE__), 'certificates', 'sp_encrypted_pv_key.pem')), + sp_public_cert: File.read(File.join(File.dirname(__FILE__), 'certificates', 'sp_public_cert.pem')), + pv_key_password: 'dccf0b7614b554fbe16b0f31' + } + end end