Skip to content

Commit 5bb14c4

Browse files
authored
Merge pull request #733 from johnnyshields/v2.x-time-arg-to-utils
[READY] v2.x - Allow `RubySaml::Utils.is_cert_expired` and `is_cert_active` to accept an optional time argument
2 parents d1a57ea + 7e1a3bb commit 5bb14c4

File tree

3 files changed

+156
-53
lines changed

3 files changed

+156
-53
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
* [#715](https://github.com/SAML-Toolkits/ruby-saml/pull/715) Fix typo in error when SPNameQualifier value does not match the SP entityID.
1515
* [#718](https://github.com/SAML-Toolkits/ruby-saml/pull/718) Add support to retrieve from SAMLResponse the AuthnInstant and AuthnContextClassRef values
1616
* [#711](https://github.com/SAML-Toolkits/ruby-saml/pull/711) Standardize how RubySaml reads and formats certificate and private_key PEM values, including the `RubySaml::Util#format_cert` and `#format_private_key` methods.
17+
* [#733](https://github.com/SAML-Toolkits/ruby-saml/pull/733) Allow `RubySaml::Utils.is_cert_expired` and `is_cert_active` to accept an optional time argument.
1718
* [#731](https://github.com/SAML-Toolkits/ruby-saml/pull/731) Add CI coverage for Ruby 3.4. Remove CI coverage for Ruby 1.x and 2.x.
1819

1920
### 1.18.0 (???)

lib/ruby_saml/utils.rb

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ module RubySaml
88

99
# SAML2 Auxiliary class
1010
#
11-
module Utils
11+
module Utils # rubocop:disable Metrics/ModuleLength
1212
extend self
1313

1414
BINDINGS = { post: "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST",
@@ -35,32 +35,32 @@ module Utils
3535
# Checks if the x509 cert provided is expired.
3636
#
3737
# @param cert [OpenSSL::X509::Certificate|String] The x509 certificate.
38+
# @param now [Time|Integer] The time to compare.
3839
# @return [true|false] Whether the certificate is expired.
39-
def is_cert_expired(cert)
40+
def is_cert_expired(cert, now = Time.now)
41+
now = Time.at(now) if now.is_a?(Integer)
4042
cert = build_cert_object(cert) if cert.is_a?(String)
41-
cert.not_after < Time.now
43+
cert.not_after < now
4244
end
4345

4446
# Checks if the x509 cert provided has both started and has not expired.
4547
#
4648
# @param cert [OpenSSL::X509::Certificate|String] The x509 certificate.
49+
# @param now [Time|Integer] The time to compare.
4750
# @return [true|false] Whether the certificate is currently active.
48-
def is_cert_active(cert)
51+
def is_cert_active(cert, now = Time.now)
52+
now = Time.at(now) if now.is_a?(Integer)
4953
cert = build_cert_object(cert) if cert.is_a?(String)
50-
now = Time.now
5154
cert.not_before <= now && cert.not_after >= now
5255
end
5356

5457
# Interprets a ISO8601 duration value relative to a given timestamp.
5558
#
5659
# @param duration [String] The duration, as a string.
57-
# @param timestamp [Integer] The unix timestamp we should apply the
58-
# duration to. Optional, default to the
59-
# current time.
60-
#
60+
# @param timestamp [Time|Integer] The unix timestamp we should apply the
61+
# duration to. Optional, default to the current time.
6162
# @return [Integer] The new timestamp, after the duration is applied.
62-
#
63-
def parse_duration(duration, timestamp=Time.now.utc)
63+
def parse_duration(duration, timestamp = Time.now)
6464
matches = duration.match(DURATION_FORMAT)
6565

6666
if matches.nil?

test/utils_test.rb

Lines changed: 144 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -408,66 +408,168 @@ def result(duration, reference = 0)
408408
end
409409

410410
describe '.is_cert_expired' do
411-
it 'returns true for expired certificate' do
412-
expired_cert = CertificateHelper.generate_cert(not_after: Time.now - 60)
413-
assert RubySaml::Utils.is_cert_expired(expired_cert)
414-
end
415411

416-
it 'returns false for not-started certificate' do
417-
not_started_cert = CertificateHelper.generate_cert(not_before: Time.now + 60)
418-
refute RubySaml::Utils.is_cert_active(not_started_cert)
419-
end
412+
describe 'time argument not specified' do
413+
it 'returns true for expired certificate' do
414+
expired_cert = CertificateHelper.generate_cert(not_after: Time.now - 60)
415+
assert RubySaml::Utils.is_cert_expired(expired_cert)
416+
end
420417

421-
it 'returns false for active certificate' do
422-
valid_cert = CertificateHelper.generate_cert
423-
refute RubySaml::Utils.is_cert_expired(valid_cert)
424-
end
418+
it 'returns false for not-started certificate' do
419+
not_started_cert = CertificateHelper.generate_cert(not_before: Time.now + 60)
420+
refute RubySaml::Utils.is_cert_active(not_started_cert)
421+
end
422+
423+
it 'returns false for active certificate' do
424+
valid_cert = CertificateHelper.generate_cert
425+
refute RubySaml::Utils.is_cert_expired(valid_cert)
426+
end
425427

426-
it 'returns true for expired certificate string' do
427-
expired_cert_string = CertificateHelper.generate_cert(not_after: Time.now - 60).to_pem
428-
assert RubySaml::Utils.is_cert_expired(expired_cert_string)
428+
it 'returns true for expired certificate string' do
429+
expired_cert_string = CertificateHelper.generate_cert(not_after: Time.now - 60).to_pem
430+
assert RubySaml::Utils.is_cert_expired(expired_cert_string)
431+
end
432+
433+
it 'returns false for not-started certificate string' do
434+
not_started_cert_string = CertificateHelper.generate_cert(not_before: Time.now + 60).to_pem
435+
refute RubySaml::Utils.is_cert_active(not_started_cert_string)
436+
end
437+
438+
it 'returns false for active certificate string' do
439+
valid_cert_string = CertificateHelper.generate_cert.to_pem
440+
refute RubySaml::Utils.is_cert_expired(valid_cert_string)
441+
end
429442
end
430443

431-
it 'returns false for not-started certificate string' do
432-
not_started_cert_string = CertificateHelper.generate_cert(not_before: Time.now + 60).to_pem
433-
refute RubySaml::Utils.is_cert_active(not_started_cert_string)
444+
describe 'time argument specified as Time' do
445+
let(:now) { Time.at(10000) }
446+
447+
it 'returns true for expired certificate' do
448+
expired_cert = CertificateHelper.generate_cert(not_after: now - 60)
449+
assert RubySaml::Utils.is_cert_expired(expired_cert, now)
450+
end
451+
452+
it 'returns false for not-started certificate' do
453+
not_started_cert = CertificateHelper.generate_cert(not_before: now + 60)
454+
refute RubySaml::Utils.is_cert_active(not_started_cert, now)
455+
end
456+
457+
it 'returns false for active certificate' do
458+
valid_cert = CertificateHelper.generate_cert(not_before: now - 60, not_after: now + 60)
459+
refute RubySaml::Utils.is_cert_expired(valid_cert, now)
460+
end
461+
462+
it 'returns true for expired certificate string' do
463+
expired_cert_string = CertificateHelper.generate_cert(not_after: now - 60).to_pem
464+
assert RubySaml::Utils.is_cert_expired(expired_cert_string, now)
465+
end
466+
467+
it 'returns false for not-started certificate string' do
468+
not_started_cert_string = CertificateHelper.generate_cert(not_before: now + 60).to_pem
469+
refute RubySaml::Utils.is_cert_active(not_started_cert_string, now)
470+
end
471+
472+
it 'returns false for active certificate string' do
473+
valid_cert_string = CertificateHelper.generate_cert(not_before: now - 60, not_after: now + 60).to_pem
474+
refute RubySaml::Utils.is_cert_expired(valid_cert_string, now)
475+
end
434476
end
435477

436-
it 'returns false for active certificate string' do
437-
valid_cert_string = CertificateHelper.generate_cert.to_pem
438-
refute RubySaml::Utils.is_cert_expired(valid_cert_string)
478+
describe 'time argument specified as Integer' do
479+
let(:int) { 10000 }
480+
481+
it 'returns true for expired certificate' do
482+
expired_cert = CertificateHelper.generate_cert(not_after: Time.at(int) - 60)
483+
assert RubySaml::Utils.is_cert_expired(expired_cert, int)
484+
end
485+
486+
it 'returns false for not-started certificate' do
487+
not_started_cert = CertificateHelper.generate_cert(not_before: Time.at(int) + 60)
488+
refute RubySaml::Utils.is_cert_active(not_started_cert, int)
489+
end
439490
end
440491
end
441492

442493
describe '.is_cert_active' do
443-
it 'returns true for active certificate' do
444-
valid_cert = CertificateHelper.generate_cert
445-
assert RubySaml::Utils.is_cert_active(valid_cert)
446-
end
447494

448-
it 'returns false for not-started certificate' do
449-
not_started_cert = CertificateHelper.generate_cert(not_before: Time.now + 60)
450-
refute RubySaml::Utils.is_cert_active(not_started_cert)
451-
end
495+
describe 'time argument not specified' do
496+
it 'returns true for active certificate' do
497+
valid_cert = CertificateHelper.generate_cert
498+
assert RubySaml::Utils.is_cert_active(valid_cert)
499+
end
452500

453-
it 'returns false for expired certificate' do
454-
expired_cert = CertificateHelper.generate_cert(not_after: Time.now - 60)
455-
refute RubySaml::Utils.is_cert_active(expired_cert)
456-
end
501+
it 'returns false for not-started certificate' do
502+
not_started_cert = CertificateHelper.generate_cert(not_before: Time.now + 60)
503+
refute RubySaml::Utils.is_cert_active(not_started_cert)
504+
end
505+
506+
it 'returns false for expired certificate' do
507+
expired_cert = CertificateHelper.generate_cert(not_after: Time.now - 60)
508+
refute RubySaml::Utils.is_cert_active(expired_cert)
509+
end
457510

458-
it 'returns true for active certificate string' do
459-
valid_cert_string = CertificateHelper.generate_cert.to_pem
460-
assert RubySaml::Utils.is_cert_active(valid_cert_string)
511+
it 'returns true for active certificate string' do
512+
valid_cert_string = CertificateHelper.generate_cert.to_pem
513+
assert RubySaml::Utils.is_cert_active(valid_cert_string)
514+
end
515+
516+
it 'returns false for not-started certificate string' do
517+
not_started_cert_string = CertificateHelper.generate_cert(not_before: Time.now + 60).to_pem
518+
refute RubySaml::Utils.is_cert_active(not_started_cert_string)
519+
end
520+
521+
it 'returns false for expired certificate string' do
522+
expired_cert_string = CertificateHelper.generate_cert(not_after: Time.now - 60).to_pem
523+
refute RubySaml::Utils.is_cert_active(expired_cert_string)
524+
end
461525
end
462526

463-
it 'returns false for not-started certificate string' do
464-
not_started_cert_string = CertificateHelper.generate_cert(not_before: Time.now + 60).to_pem
465-
refute RubySaml::Utils.is_cert_active(not_started_cert_string)
527+
describe 'time argument specified as Time' do
528+
let(:now) { Time.at(10000) }
529+
530+
it 'returns true for active certificate' do
531+
valid_cert = CertificateHelper.generate_cert(not_before: now - 60, not_after: now + 60)
532+
assert RubySaml::Utils.is_cert_active(valid_cert, now)
533+
end
534+
535+
it 'returns false for not-started certificate' do
536+
not_started_cert = CertificateHelper.generate_cert(not_before: now + 60)
537+
refute RubySaml::Utils.is_cert_active(not_started_cert, now)
538+
end
539+
540+
it 'returns false for expired certificate' do
541+
expired_cert = CertificateHelper.generate_cert(not_after: now - 60)
542+
refute RubySaml::Utils.is_cert_active(expired_cert, now)
543+
end
544+
545+
it 'returns true for active certificate string' do
546+
valid_cert_string = CertificateHelper.generate_cert(not_before: now - 60, not_after: now + 60).to_pem
547+
assert RubySaml::Utils.is_cert_active(valid_cert_string, now)
548+
end
549+
550+
it 'returns false for not-started certificate string' do
551+
not_started_cert_string = CertificateHelper.generate_cert(not_before: now + 60).to_pem
552+
refute RubySaml::Utils.is_cert_active(not_started_cert_string, now)
553+
end
554+
555+
it 'returns false for expired certificate string' do
556+
expired_cert_string = CertificateHelper.generate_cert(not_after: now - 60).to_pem
557+
refute RubySaml::Utils.is_cert_active(expired_cert_string, now)
558+
end
466559
end
467560

468-
it 'returns false for expired certificate string' do
469-
expired_cert_string = CertificateHelper.generate_cert(not_after: Time.now - 60).to_pem
470-
refute RubySaml::Utils.is_cert_active(expired_cert_string)
561+
describe 'time argument specified as Integer' do
562+
let(:int) { 10000 }
563+
564+
it 'returns true for active certificate' do
565+
valid_cert = CertificateHelper.generate_cert(not_before: Time.at(int) - 60, not_after: Time.at(int) + 60)
566+
assert RubySaml::Utils.is_cert_active(valid_cert, int)
567+
end
568+
569+
it 'returns false for expired certificate' do
570+
expired_cert = CertificateHelper.generate_cert(not_after: Time.at(int) - 60)
571+
refute RubySaml::Utils.is_cert_active(expired_cert, int)
572+
end
471573
end
472574
end
473575
end

0 commit comments

Comments
 (0)