Commit ae7b4c8

mo <mo@mokhan.ca>
2018-11-03 15:42:07
rescue asn1 errors when checking validity.
1 parent 9e3fd13
Changed files (2)
lib/saml/kit/configuration.rb
@@ -90,7 +90,7 @@ module Saml
       # @param use [Symbol] the type of key pair to return
       # `nil`, `:signing` or `:encryption`
       def key_pairs(use: nil)
-        use.present? ? @key_pairs.find_all { |xxx| xxx.for?(use) } : @key_pairs
+        use.present? ? active_key_pairs.find_all { |xxx| xxx.for?(use) } : active_key_pairs
       end
 
       # Return each certificate for a specific use.
@@ -122,6 +122,15 @@ module Saml
         error_message = 'Use must be either :signing or :encryption'
         raise ArgumentError, error_message
       end
+
+      def active_key_pairs
+        @key_pairs.find_all do |x|
+          x.certificate.active?
+        rescue OpenSSL::X509::CertificateError => error
+          Saml::Kit.logger.error(error)
+          false
+        end
+      end
     end
   end
 end
spec/saml/kit/configuration_spec.rb
@@ -24,27 +24,96 @@ RSpec.describe Saml::Kit::Configuration do
   describe '#add_key_pair' do
     subject { described_class.new }
 
-    let(:certificate) do
+    let(:active_certificate) do
       certificate = OpenSSL::X509::Certificate.new
+      certificate.not_before = 1.minute.ago
+      certificate.not_after = 1.minute.from_now
+      certificate.public_key = private_key.public_key
+      certificate.sign(private_key, OpenSSL::Digest::SHA256.new)
+      certificate
+    end
+    let(:expired_certificate) do
+      certificate = OpenSSL::X509::Certificate.new
+      certificate.not_before = 2.minutes.ago
+      certificate.not_after = 1.minute.ago
+      certificate.public_key = private_key.public_key
+      certificate.sign(private_key, OpenSSL::Digest::SHA256.new)
+      certificate
+    end
+    let(:unsigned_certificate) do
+      certificate = OpenSSL::X509::Certificate.new
+      certificate.not_before = 1.minute.ago
+      certificate.not_after = 1.minute.from_now
       certificate.public_key = private_key.public_key
       certificate
     end
     let(:private_key) { OpenSSL::PKey::RSA.new(2048) }
 
-    it 'raises an error when the use is not known' do
-      expect do
-        subject.add_key_pair(certificate, private_key.export, use: :blah)
-      end.to raise_error(/:signing or :encryption/)
+    context 'when the use is not known' do
+      specify { expect { subject.add_key_pair(active_certificate, private_key.export, use: :blah) }.to raise_error(/:signing or :encryption/) }
     end
 
-    it 'adds a signing key pair' do
-      subject.add_key_pair(certificate.to_pem, private_key.export, use: :signing)
-      expect(subject.key_pairs(use: :signing).count).to be(1)
+    context "when adding a signing key pair" do
+      before do
+        subject.add_key_pair(active_certificate.to_pem, private_key.export, use: :signing)
+        subject.add_key_pair(expired_certificate.to_pem, private_key.export, use: :signing)
+        subject.add_key_pair(unsigned_certificate.to_pem, private_key.export, use: :signing)
+      end
+
+      specify { expect(subject.key_pairs(use: :signing).count).to eql(1) }
     end
 
-    it 'adds an encryption key pair' do
-      subject.add_key_pair(certificate.to_pem, private_key.export, use: :encryption)
-      expect(subject.key_pairs(use: :encryption).count).to be(1)
+    context "when adding an encryption key pair" do
+      before do
+        subject.add_key_pair(active_certificate.to_pem, private_key.export, use: :encryption)
+        subject.add_key_pair(expired_certificate.to_pem, private_key.export, use: :encryption)
+        subject.add_key_pair(unsigned_certificate.to_pem, private_key.export, use: :encryption)
+      end
+
+      specify { expect(subject.key_pairs(use: :encryption).count).to be(1) }
+    end
+  end
+
+  describe "#key_pairs" do
+    context "when a certificate expires" do
+      let(:active_certificate) do
+        certificate = OpenSSL::X509::Certificate.new
+        certificate.not_before = 1.minute.ago
+        certificate.not_after = 1.minute.from_now
+        certificate.public_key = private_key.public_key
+        certificate.sign(private_key, OpenSSL::Digest::SHA256.new)
+        certificate
+      end
+      let(:expired_certificate) do
+        certificate = OpenSSL::X509::Certificate.new
+        certificate.not_before = 2.minutes.ago
+        certificate.not_after = 1.minute.ago
+        certificate.public_key = private_key.public_key
+        certificate.sign(private_key, OpenSSL::Digest::SHA256.new)
+        certificate
+      end
+      let(:unsigned_certificate) do
+        certificate = OpenSSL::X509::Certificate.new
+        certificate.not_before = 1.minute.ago
+        certificate.not_after = 1.minute.from_now
+        certificate.public_key = private_key.public_key
+        certificate
+      end
+      let(:private_key) { OpenSSL::PKey::RSA.new(2048) }
+
+      before do
+        subject.add_key_pair(active_certificate.to_pem, private_key.export, use: :signing)
+        subject.add_key_pair(expired_certificate.to_pem, private_key.export, use: :signing)
+        subject.add_key_pair(unsigned_certificate.to_pem, private_key.export, use: :signing)
+      end
+
+      specify { expect(subject.key_pairs.count).to eql(1) }
+      specify { expect(subject.key_pairs.map(&:certificate).map(&:fingerprint)).to match_array([Xml::Kit::Fingerprint.new(active_certificate)]) }
+    end
+
+    context "when there is more than one key pair" do
+      it 'returns them sorted from newest to oldest' do
+      end
     end
   end
 end