sso_login_box_for_ntu/ruby-saml-custom/test/test_helper.rb

358 lines
12 KiB
Ruby

require 'simplecov'
require 'simplecov-lcov'
SimpleCov::Formatter::LcovFormatter.config.report_with_single_file = true
SimpleCov::Formatter::LcovFormatter.config.output_directory = 'coverage'
SimpleCov::Formatter::LcovFormatter.config.lcov_file_name = 'lcov.info'
SimpleCov.formatter = SimpleCov::Formatter::LcovFormatter
SimpleCov.start do
add_filter "test/"
add_filter "vendor/"
add_filter "lib/onelogin/ruby-saml/logging.rb"
end
require 'stringio'
require 'rubygems'
require 'bundler'
require 'minitest/autorun'
require 'mocha/setup'
require 'timecop'
Bundler.require :default, :test
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
$LOAD_PATH.unshift(File.dirname(__FILE__))
require 'onelogin/ruby-saml/logging'
TEST_LOGGER = Logger.new(StringIO.new)
OneLogin::RubySaml::Logging.logger = TEST_LOGGER
class Minitest::Test
def fixture(document, base64 = true)
response = Dir.glob(File.join(File.dirname(__FILE__), "responses", "#{document}*")).first
if base64 && response =~ /\.xml$/
Base64.encode64(File.read(response))
else
File.read(response)
end
end
def read_response(response)
File.read(File.join(File.dirname(__FILE__), "responses", response))
end
def read_invalid_response(response)
File.read(File.join(File.dirname(__FILE__), "responses", "invalids", response))
end
def read_logout_request(request)
File.read(File.join(File.dirname(__FILE__), "logout_requests", request))
end
def read_certificate(certificate)
File.read(File.join(File.dirname(__FILE__), "certificates", certificate))
end
def response_document_valid_signed
@response_document_valid_signed ||= read_response("valid_response.xml.base64")
end
def response_document_valid_signed_without_x509certificate
@response_document_valid_signed_without_x509certificate ||= read_response("valid_response_without_x509certificate.xml.base64")
end
def response_document_without_recipient
@response_document_without_recipient ||= read_response("response_with_undefined_recipient.xml.base64")
end
def response_document_without_recipient_with_time_updated
doc = Base64.decode64(response_document_without_recipient)
doc.gsub!(/NotBefore=\"(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})Z\"/, "NotBefore=\"#{(Time.now-300).getutc.strftime("%Y-%m-%dT%XZ")}\"")
doc.gsub!(/NotOnOrAfter=\"(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})Z\"/, "NotOnOrAfter=\"#{(Time.now+300).getutc.strftime("%Y-%m-%dT%XZ")}\"")
Base64.encode64(doc)
end
def response_document_without_attributes
@response_document_without_attributes ||= read_response("response_without_attributes.xml.base64")
end
def response_document_without_reference_uri
@response_document_without_reference_uri ||= read_response("response_without_reference_uri.xml.base64")
end
def response_document_with_signed_assertion
@response_document_with_signed_assertion ||= read_response("response_with_signed_assertion.xml.base64")
end
def response_document_with_signed_assertion_2
@response_document_with_signed_assertion_2 ||= read_response("response_with_signed_assertion_2.xml.base64")
end
def response_document_with_ds_namespace_at_the_root
@response_document_with_ds_namespace_at_the_root ||= read_response("response_with_ds_namespace_at_the_root.xml.base64")
end
def response_document_unsigned
@response_document_unsigned ||= read_response("response_unsigned_xml_base64")
end
def response_document_with_saml2_namespace
@response_document_with_saml2_namespace ||= read_response("response_with_saml2_namespace.xml.base64")
end
def ampersands_document
@ampersands_response ||= read_response("response_with_ampersands.xml.base64")
end
def response_document_no_cert_and_encrypted_attrs
@response_document_no_cert_and_encrypted_attrs ||= Base64.encode64(read_response("response_no_cert_and_encrypted_attrs.xml"))
end
def response_document_wrapped
@response_document_wrapped ||= read_response("response_wrapped.xml.base64")
end
def response_document_assertion_wrapped
@response_document_assertion_wrapped ||= read_response("response_assertion_wrapped.xml.base64")
end
def response_document_encrypted_nameid
@response_document_encrypted_nameid ||= File.read(File.join(File.dirname(__FILE__), 'responses', 'response_encrypted_nameid.xml.base64'))
end
def signed_message_encrypted_unsigned_assertion
@signed_message_encrypted_unsigned_assertion ||= File.read(File.join(File.dirname(__FILE__), 'responses', 'signed_message_encrypted_unsigned_assertion.xml.base64'))
end
def signed_message_encrypted_signed_assertion
@signed_message_encrypted_signed_assertion ||= File.read(File.join(File.dirname(__FILE__), 'responses', 'signed_message_encrypted_signed_assertion.xml.base64'))
end
def unsigned_message_encrypted_signed_assertion
@unsigned_message_encrypted_signed_assertion ||= File.read(File.join(File.dirname(__FILE__), 'responses', 'unsigned_message_encrypted_signed_assertion.xml.base64'))
end
def unsigned_message_encrypted_unsigned_assertion
@unsigned_message_encrypted_unsigned_assertion ||= File.read(File.join(File.dirname(__FILE__), 'responses', 'unsigned_message_encrypted_unsigned_assertion.xml.base64'))
end
def response_document_encrypted_attrs
@response_document_encrypted_attrs ||= File.read(File.join(File.dirname(__FILE__), 'responses', 'response_encrypted_attrs.xml.base64'))
end
def response_document_double_status_code
@response_document_double_status_code ||= File.read(File.join(File.dirname(__FILE__), 'responses', 'response_double_status_code.xml.base64'))
end
def signature_fingerprint_1
@signature_fingerprint1 ||= "C5:19:85:D9:47:F1:BE:57:08:20:25:05:08:46:EB:27:F6:CA:B7:83"
end
# certificate used on response_with_undefined_recipient
def signature_1
@signature1 ||= read_certificate("certificate1")
end
# certificate used on response_document_with_signed_assertion_2
def certificate_without_head_foot
@certificate_without_head_foot ||= read_certificate("certificate_without_head_foot")
end
def idp_metadata_descriptor
@idp_metadata_descriptor ||= File.read(File.join(File.dirname(__FILE__), 'metadata', 'idp_descriptor.xml'))
end
def idp_metadata_descriptor2
@idp_metadata_descriptor2 ||= File.read(File.join(File.dirname(__FILE__), 'metadata', 'idp_descriptor_2.xml'))
end
def idp_metadata_descriptor3
@idp_metadata_descriptor3 ||= File.read(File.join(File.dirname(__FILE__), 'metadata', 'idp_descriptor_3.xml'))
end
def idp_metadata_descriptor4
@idp_metadata_descriptor4 ||= File.read(File.join(File.dirname(__FILE__), 'metadata', 'idp_descriptor_4.xml'))
end
def idp_metadata_descriptor5
@idp_metadata_descriptor5 ||= File.read(File.join(File.dirname(__FILE__), 'metadata', 'idp_descriptor_5.xml'))
end
def idp_metadata_descriptor6
@idp_metadata_descriptor6 ||= File.read(File.join(File.dirname(__FILE__), 'metadata', 'idp_descriptor_6.xml'))
end
def no_idp_metadata_descriptor
@no_idp_metadata_descriptor ||= File.read(File.join(File.dirname(__FILE__), 'metadata', 'no_idp_descriptor.xml'))
end
def idp_metadata_multiple_descriptors
@idp_metadata_multiple_descriptors ||= File.read(File.join(File.dirname(__FILE__), 'metadata', 'idp_multiple_descriptors.xml'))
end
def idp_metadata_multiple_descriptors2
@idp_metadata_multiple_descriptors2 ||= File.read(File.join(File.dirname(__FILE__), 'metadata', 'idp_multiple_descriptors_2.xml'))
end
def idp_metadata_multiple_certs
@idp_metadata_multiple_descriptors ||= File.read(File.join(File.dirname(__FILE__), 'metadata', 'idp_metadata_multi_certs.xml'))
end
def idp_metadata_multiple_signing_certs
@idp_metadata_multiple_signing_certs ||= File.read(File.join(File.dirname(__FILE__), 'metadata', 'idp_metadata_multi_signing_certs.xml'))
end
def idp_metadata_same_sign_and_encrypt_cert
@idp_metadata_same_sign_and_encrypt_cert ||= File.read(File.join(File.dirname(__FILE__), 'metadata', 'idp_metadata_same_sign_and_encrypt_cert.xml'))
end
def idp_metadata_different_sign_and_encrypt_cert
@idp_metadata_different_sign_and_encrypt_cert ||= File.read(File.join(File.dirname(__FILE__), 'metadata', 'idp_metadata_different_sign_and_encrypt_cert.xml'))
end
def idp_different_slo_response_location
@idp_different_slo_response_location ||= File.read(File.join(File.dirname(__FILE__), 'metadata', 'idp_different_slo_response_location.xml'))
end
def idp_without_slo_response_location
@idp_without_slo_response_location ||= File.read(File.join(File.dirname(__FILE__), 'metadata', 'idp_without_slo_response_location.xml'))
end
def logout_request_document
unless @logout_request_document
xml = read_logout_request("slo_request.xml")
deflated = Zlib::Deflate.deflate(xml, 9)[2..-5]
@logout_request_document = Base64.encode64(deflated)
end
@logout_request_document
end
def logout_request_document_with_name_id_format
unless @logout_request_document_with_name_id_format
xml = read_logout_request("slo_request_with_name_id_format.xml")
deflated = Zlib::Deflate.deflate(xml, 9)[2..-5]
@logout_request_document_with_name_id_format = Base64.encode64(deflated)
end
@logout_request_document_with_name_id_format
end
def logout_request_xml_with_session_index
@logout_request_xml_with_session_index ||= File.read(File.join(File.dirname(__FILE__), 'logout_requests', 'slo_request_with_session_index.xml'))
end
def invalid_logout_request_document
unless @invalid_logout_request_document
xml = File.read(File.join(File.dirname(__FILE__), 'logout_requests', 'invalid_slo_request.xml'))
deflated = Zlib::Deflate.deflate(xml, 9)[2..-5]
@invalid_logout_request_document = Base64.encode64(deflated)
end
@invalid_logout_request_document
end
def logout_request_base64
@logout_request_base64 ||= File.read(File.join(File.dirname(__FILE__), 'logout_requests', 'slo_request.xml.base64'))
end
def logout_request_deflated_base64
@logout_request_deflated_base64 ||= File.read(File.join(File.dirname(__FILE__), 'logout_requests', 'slo_request_deflated.xml.base64'))
end
def ruby_saml_cert
@ruby_saml_cert ||= OpenSSL::X509::Certificate.new(ruby_saml_cert_text)
end
def ruby_saml_cert2
@ruby_saml_cert2 ||= OpenSSL::X509::Certificate.new(ruby_saml_cert_text2)
end
def ruby_saml_cert_fingerprint
@ruby_saml_cert_fingerprint ||= Digest::SHA1.hexdigest(ruby_saml_cert.to_der).scan(/../).join(":")
end
def ruby_saml_cert_text
read_certificate("ruby-saml.crt")
end
def ruby_saml_cert_text2
read_certificate("ruby-saml-2.crt")
end
def ruby_saml_key
@ruby_saml_key ||= OpenSSL::PKey::RSA.new(ruby_saml_key_text)
end
def ruby_saml_key_text
read_certificate("ruby-saml.key")
end
#
# logoutresponse fixtures
#
def random_id
"_#{OneLogin::RubySaml::Utils.uuid}"
end
#
# decodes a base64 encoded SAML response for use in SloLogoutresponse tests
#
def decode_saml_response_payload(unauth_url)
payload = CGI.unescape(unauth_url.split("SAMLResponse=").last)
decoded = Base64.decode64(payload)
zstream = Zlib::Inflate.new(-Zlib::MAX_WBITS)
inflated = zstream.inflate(decoded)
zstream.finish
zstream.close
inflated
end
#
# decodes a base64 encoded SAML request for use in Logoutrequest tests
#
def decode_saml_request_payload(unauth_url)
payload = CGI.unescape(unauth_url.split("SAMLRequest=").last)
decoded = Base64.decode64(payload)
zstream = Zlib::Inflate.new(-Zlib::MAX_WBITS)
inflated = zstream.inflate(decoded)
zstream.finish
zstream.close
inflated
end
SCHEMA_DIR = File.expand_path(File.join(__FILE__, '../../lib/schemas'))
#
# validate an xml document against the given schema
#
def validate_xml!(document, schema)
Dir.chdir(SCHEMA_DIR) do
xsd = if schema.is_a? Nokogiri::XML::Schema
schema
else
Nokogiri::XML::Schema(File.read(schema))
end
xml = if document.is_a? Nokogiri::XML::Document
document
else
Nokogiri::XML(document) { |c| c.strict }
end
result = xsd.validate(xml)
if result.length != 0
raise "Schema validation failed! XSD validation errors: #{result.join(", ")}"
else
true
end
end
end
# Allows to emulate Azure AD request behavior
def downcased_escape(str)
CGI.escape(str).gsub(/%[A-Fa-f0-9]{2}/) { |match| match.downcase }
end
end