11 November 2018

saml-kit 1.0.27

by mo


saml-kit has been updated to evict expired x509 certificates.

A common scenario in publishing SAML metadata is to rotate certificates. When a certificate is near expiration, it’s useful to be able to publish a new certificate before the old one expires. This allows other parties to sync up and get a copy of the new certificate before the old one expires.

E.g.

  • Week 1: Certificate A active
  • Week 2: Certificate A, B active
  • Week 3: Certificate B active

In the above example Certificate A expires in week 3. Certificate B becomes active in week 2.

By default saml-kit generates metadata using the signing certificates configured in the saml-kit configuration.

private_key = OpenSSL::PKey::RSA.new(2048)

certificate_a = OpenSSL::X509::Certificate.new
certificate_a.not_before = start_of_week_1
certificate_a.not_after = end_of_week_2
certificate_a.public_key = private_key.public_key
certificate_a.sign(private_key, OpenSSL::Digest::SHA256.new)

certificate_b = OpenSSL::X509::Certificate.new
certificate_b.not_before = start_of_week_2
certificate_b.not_after = end_of_week_3
certificate_b.public_key = private_key.public_key
certificate_b.sign(private_key, OpenSSL::Digest::SHA256.new)

configuration = Saml::Kit::Configuration
configuration.entity_id = "https://www.example.org/metadata"
configuration.add_key_pair(certificate_a.to_pem, private_key.export, use: :signing)
configuration.add_key_pair(certificate_b.to_pem, private_key.export, use: :signing)

When saml-kit chooses a key pair to use for signing a message, it chooses the oldest active key pair and evicts key pairs that are associated with an expired certificate.

This means if you read in key pairs from external configuration (e.g. environment variables), a process restart is not necessary to evict stale certificates.

Saml::Kit::Metadata.build(configuration: configuration) do |builder|
  builder.build_identity_provider do |x|
    x.add_single_sign_on_service('https://www.example.org/login', binding: :http_post)
  end
end

Week 1

In week 1, saml-kit will only supply certificate a in the metadata because certificate b is not active yet. During this time, messages signed by saml-kit will only be signed with certificate a. saml-kit will generate something like the following. Some attributes removed for brevity.

<EntityDescriptor entityID="https://www.example.org/metadata">
 <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">...</Signature>
 <IDPSSODescriptor>
   <KeyDescriptor use="signing">
     <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
       <X509Data>
         <X509Certificate><!-- certificate a --><X509Certificate>
       </X509Data>
     </KeyInfo>
   </KeyDescriptor>
   <NameIDFormat>...</NameIDFormat>
   <SingleSignOnService Location="https://www.example.org/login"/>
 </IDPSSODescriptor>
</EntityDescriptor>

Week 2

In week 2, saml-kit will supply both certificate a and certificate b in the metadata because both certificates are now considered active. During this time, messages signed by saml-kit will continue to be signed with certificate a. saml-kit will generate something like the following. Some attributes removed for brevity.

<EntityDescriptor entityID="https://www.example.org/metadata">
 <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">...</Signature>
 <IDPSSODescriptor>
   <KeyDescriptor use="signing">
     <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
       <X509Data>
         <X509Certificate><!-- certificate a --><X509Certificate>
       </X509Data>
     </KeyInfo>
   </KeyDescriptor>
   <KeyDescriptor use="signing">
     <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
       <X509Data>
         <X509Certificate><!-- certificate b --><X509Certificate>
       </X509Data>
     </KeyInfo>
   </KeyDescriptor>
   <NameIDFormat>...</NameIDFormat>
   <SingleSignOnService Location="https://www.example.org/login"/>
 </IDPSSODescriptor>
</EntityDescriptor>

Week 3

In week 3, saml-kit will only supply certificate b in the metadata because certificate a is now expired. During this time, messages signed by saml-kit will convert to being signed with certificate b. saml-kit will generate something like the following. Some attributes removed for brevity.

<EntityDescriptor entityID="https://www.example.org/metadata">
 <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">...</Signature>
 <IDPSSODescriptor>
   <KeyDescriptor use="signing">
     <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
       <X509Data>
         <X509Certificate><!-- certificate b --><X509Certificate>
       </X509Data>
     </KeyInfo>
   </KeyDescriptor>
   <NameIDFormat>...</NameIDFormat>
   <SingleSignOnService Location="https://www.example.org/login"/>
 </IDPSSODescriptor>
</EntityDescriptor>

You can download the latest version from RubyGems.

πŸ’Ž