Skip to content

Commit

Permalink
Allow SP certificates to be OpenSSL::X509::Certificate
Browse files Browse the repository at this point in the history
This allows settings to accept instances of OpenSSL::X509::Certificate
as service provider (SP) certificates.
  • Loading branch information
tobiasamft committed Oct 3, 2024
1 parent 791fc2c commit c0b1dd7
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 8 deletions.
27 changes: 19 additions & 8 deletions lib/onelogin/ruby-saml/settings.rb
Original file line number Diff line number Diff line change
Expand Up @@ -312,28 +312,33 @@ def get_all_sp_certs

# Validate certificate, certificate_new, private_key, and sp_cert_multi params.
def validate_sp_certs_params!
multi = sp_cert_multi && !sp_cert_multi.empty?
cert = certificate && !certificate.empty?
cert_new = certificate_new && !certificate_new.empty?
pk = private_key && !private_key.empty?
if multi && (cert || cert_new || pk)
has_multi = sp_cert_multi && !sp_cert_multi.empty?
has_pk = private_key && !private_key.empty?
if has_multi && (has_cert?(certificate) || has_cert?(certificate_new) || has_pk)
raise ArgumentError.new("Cannot specify both sp_cert_multi and certificate, certificate_new, private_key parameters")
end
end

# Check if a certificate is present.
def has_cert?(cert)
return true if cert.is_a?(OpenSSL::X509::Certificate)

cert && !cert.empty?
end

# Get certs from certificate, certificate_new, and private_key parameters.
def get_sp_certs_single
certs = { :signing => [], :encryption => [] }

sp_key = OneLogin::RubySaml::Utils.build_private_key_object(private_key)
cert = OneLogin::RubySaml::Utils.build_cert_object(certificate)
cert = build_cert_object(certificate)
if cert || sp_key
ary = [cert, sp_key].freeze
certs[:signing] << ary
certs[:encryption] << ary
end

cert_new = OneLogin::RubySaml::Utils.build_cert_object(certificate_new)
cert_new = build_cert_object(certificate_new)
if cert_new
ary = [cert_new, sp_key].freeze
certs[:signing] << ary
Expand Down Expand Up @@ -368,7 +373,7 @@ def get_sp_certs_multi
end

certs[type] << [
OneLogin::RubySaml::Utils.build_cert_object(cert),
build_cert_object(cert),
OneLogin::RubySaml::Utils.build_private_key_object(key)
].freeze
end
Expand All @@ -377,6 +382,12 @@ def get_sp_certs_multi
certs.each { |_, ary| ary.freeze }
certs
end

def build_cert_object(cert)
return cert if cert.is_a?(OpenSSL::X509::Certificate)

OneLogin::RubySaml::Utils.build_cert_object(cert)
end
end
end
end
Expand Down
41 changes: 41 additions & 0 deletions test/settings_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,47 @@ class SettingsTest < Minitest::Test
assert_equal expected_encryption, actual[:encryption].map {|ary| ary.map(&:to_pem) }
end

it "handles OpenSSL::X509::Certificate objects for single case" do
@settings.certificate = OpenSSL::X509::Certificate.new(cert_text1)
@settings.private_key = key_text1

actual = @settings.get_sp_certs
expected = [[cert_text1, key_text1]]
assert_equal [:signing, :encryption], actual.keys
assert_equal expected, actual[:signing].map {|ary| ary.map(&:to_pem) }
assert_equal expected, actual[:encryption].map {|ary| ary.map(&:to_pem) }
end

it "handles OpenSSL::X509::Certificate objects for single case with new cert" do
@settings.certificate = cert_text1
@settings.certificate_new = OpenSSL::X509::Certificate.new(cert_text2)
@settings.private_key = key_text1

actual = @settings.get_sp_certs
expected = [[cert_text1, key_text1], [cert_text2, key_text1]]
assert_equal [:signing, :encryption], actual.keys
assert_equal expected, actual[:signing].map {|ary| ary.map(&:to_pem) }
assert_equal expected, actual[:encryption].map {|ary| ary.map(&:to_pem) }
end

it "handles OpenSSL::X509::Certificate objects for multi case" do
x509_certificate1 = OpenSSL::X509::Certificate.new(cert_text1)
x509_certificate2 = OpenSSL::X509::Certificate.new(cert_text2)
@settings.sp_cert_multi = {
signing: [{ certificate: x509_certificate1, private_key: key_text1 },
{ certificate: cert_text2, private_key: key_text1 }],
encryption: [{ certificate: x509_certificate2, private_key: key_text1 },
{ certificate: cert_text3, private_key: key_text2 }]
}

actual = @settings.get_sp_certs
expected_signing = [[cert_text1, key_text1], [cert_text2, key_text1]]
expected_encryption = [[cert_text2, key_text1], [cert_text3, key_text2]]
assert_equal [:signing, :encryption], actual.keys
assert_equal expected_signing, actual[:signing].map {|ary| ary.map(&:to_pem) }
assert_equal expected_encryption, actual[:encryption].map {|ary| ary.map(&:to_pem) }
end

it "sp_cert_multi allows sending only signing" do
@settings.sp_cert_multi = {
signing: [{ certificate: cert_text1, private_key: key_text1 },
Expand Down

0 comments on commit c0b1dd7

Please sign in to comment.