ssl-test 2.0.0 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +5 -1
- data/README.md +9 -1
- data/lib/ssl-test/crl.rb +17 -8
- data/lib/ssl-test.rb +42 -14
- data/spec/memory_store_spec.rb +2 -1
- data/spec/ssl-test_spec.rb +64 -12
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 073a878a42dbba9b30e7c69ec4b435cd8f2c607e59a6b894099af73ea60526f8
|
|
4
|
+
data.tar.gz: 709b2f097b7d8a61922f2cfcee0cb6651046c57854dea0b3dc17c8367b7b856a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 150c1d97a77c0a37c71a180d7cd643f3a4264280f65261e2cb830b184fed00cb60458bf4d27ce1eb52225db506398d2e1480bf69d5a7d6ffc4ee7e5ad288a5b1
|
|
7
|
+
data.tar.gz: '08f66249c1b7d951b71283589d957b6bfe4451934ff155af255e4e31a5f77d0aa27bcd1dcc9cee1dcb0b1ddc450618d97c9a445c5067990009b14ad616933128'
|
data/.github/workflows/ruby.yml
CHANGED
|
@@ -3,6 +3,10 @@ on: [push]
|
|
|
3
3
|
jobs:
|
|
4
4
|
specs:
|
|
5
5
|
runs-on: ubuntu-22.04
|
|
6
|
+
strategy:
|
|
7
|
+
fail-fast: false
|
|
8
|
+
matrix:
|
|
9
|
+
ruby-version: ['3.2', '3.3', '3.4']
|
|
6
10
|
services:
|
|
7
11
|
redis:
|
|
8
12
|
image: redis
|
|
@@ -16,7 +20,7 @@ jobs:
|
|
|
16
20
|
- name: Set up Ruby
|
|
17
21
|
uses: ruby/setup-ruby@v1
|
|
18
22
|
with:
|
|
19
|
-
ruby-version:
|
|
23
|
+
ruby-version: ${{ matrix.ruby-version }}
|
|
20
24
|
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
|
|
21
25
|
- name: Run specs
|
|
22
26
|
run: |
|
data/README.md
CHANGED
|
@@ -70,6 +70,13 @@ cert # => #<OpenSSL::X509::Certificate...>
|
|
|
70
70
|
|
|
71
71
|
If the CRL is missing, invalid or unreachable the certificate revocation will be tested using [OCSP](https://en.wikipedia.org/wiki/Online_Certificate_Status_Protocol).
|
|
72
72
|
|
|
73
|
+
You can swap the order if you'd rather check OCSP first and only fall back to CRL on error (the default is CRL first, since 1.6, to reduce the revocation propagation delay):
|
|
74
|
+
|
|
75
|
+
```ruby
|
|
76
|
+
SSLTest.revocation_order = %i[ocsp crl] # OCSP first, CRL fallback
|
|
77
|
+
SSLTest.revocation_order = %i[crl ocsp] # the default: CRL first, OCSP fallback
|
|
78
|
+
```
|
|
79
|
+
|
|
73
80
|
If both CRL and OCSP tests are impossible, the certificate will still be considered valid but with an error message:
|
|
74
81
|
|
|
75
82
|
```ruby
|
|
@@ -195,7 +202,8 @@ But also **revoked certs** like most browsers (not handled by `curl`)
|
|
|
195
202
|
|
|
196
203
|
See also github releases: https://github.com/jarthod/ssl-test/releases
|
|
197
204
|
|
|
198
|
-
* 2.0.
|
|
205
|
+
* 2.0.1 - 2026-06-19: Speed up and shrink the memory use of CRL checks with a fast path that scans the raw CRL for the certificate's serial before parsing, avoiding instantiating the entire revocation list (>1M Ruby objects for busy CAs) when the cert isn't revoked. Send both `If-None-Match` and `If-Modified-Since` on CRL revalidation so CDN-backed CAs that don't honor their own ETag (e.g. DigiCert) still return a `304` instead of re-downloading the whole list.
|
|
206
|
+
* 2.0.0 - 2026-06-16: Make the revocation check order configurable via `SSLTest.revocation_order` (`%i[crl ocsp]` by default, set `%i[ocsp crl]` to check OCSP first). Make the cache backend configurable. The default stays an in-process `SSLTest::MemoryStore`, but you can now assign any object responding to the `Rails.cache`-style API (`read`/`write`/`delete`) with `SSLTest.cache = Rails.cache` to share responses across processes and get compression (e.g. memcache via Dalli — see the memcached note in the Caching section about raising the max value size for large CRLs). **Breaking:** the module-level `SSLTest.cache_size` and `SSLTest.flush_cache` were removed — use `SSLTest.cache.size` and `SSLTest.cache.clear` instead (these only work with the built-in `MemoryStore`; shared backends like `Rails.cache` can't be enumerated and shouldn't be wholesale-cleared)
|
|
199
207
|
* 1.6.0 - 2026-06-16: Check revocation with CRL first and fall back to OCSP (was OCSP first) to reduce revocation detection delay
|
|
200
208
|
* 1.5.0 - 2025-11-28: Add support for local certificates testing and HTTP proxies (#8), changed `#test` method into `#test_url` and `#test_cert` (`#test` remains as an alias for `#test_url` for backward-compatibility)
|
|
201
209
|
* 1.4.1 - 2022-10-24: Add support for "tcps://" scheme
|
data/lib/ssl-test/crl.rb
CHANGED
|
@@ -47,11 +47,19 @@ module SSLTest
|
|
|
47
47
|
response = OpenSSL::X509::CRL.new http_response
|
|
48
48
|
return [false, "Signature verification failed (URI: #{crl_uri})", nil] unless response.verify(issuer.public_key)
|
|
49
49
|
|
|
50
|
+
# Fast path: scan the raw response for the cert's serial encoded as DER.
|
|
51
|
+
# In most case (not revoked) this lets us skip response.revoked, which
|
|
52
|
+
# instantiate the *entire* revocation list as Ruby objects (>1M objects for busy CAs)
|
|
53
|
+
serial_der = OpenSSL::ASN1::Integer.new(cert.serial).to_der
|
|
54
|
+
return :crl_ok unless response.to_der.include?(serial_der)
|
|
55
|
+
|
|
56
|
+
# The serial's bytes appear (a real hit, or a rare collision):
|
|
57
|
+
# confirm authoritatively and pull the reason/date. The costly revoked-list
|
|
58
|
+
# materialisation only happens here, i.e. for actually-revoked certs.
|
|
50
59
|
revoked = response.revoked.find { |r| r.serial == cert.serial }
|
|
51
60
|
if revoked
|
|
52
61
|
reason = revoked.extensions.find {|e| e.oid == "CRLReason"}&.value
|
|
53
62
|
return [true, reason || "Unknown reason", revoked.time]
|
|
54
|
-
else
|
|
55
63
|
end
|
|
56
64
|
|
|
57
65
|
:crl_ok
|
|
@@ -77,12 +85,13 @@ module SSLTest
|
|
|
77
85
|
http.read_timeout = read_timeout
|
|
78
86
|
|
|
79
87
|
req = Net::HTTP::Get.new(path)
|
|
80
|
-
# Include conditional caching headers from cache to save bandwidth if
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
88
|
+
# Include conditional caching headers from cache to save bandwidth if the
|
|
89
|
+
# list didn't change (304). Send both validators when present: some
|
|
90
|
+
# CDN-backed CAs (e.g. DigiCert) serve per-node ETags they won't honor via
|
|
91
|
+
# If-None-Match but will revalidate via If-Modified-Since, so sending only
|
|
92
|
+
# the ETag defeats the 304 and re-downloads the whole list every time.
|
|
93
|
+
req["If-None-Match"] = cache_entry[:etag] if cache_entry&.[](:etag)
|
|
94
|
+
req["If-Modified-Since"] = cache_entry[:last_mod] if cache_entry&.[](:last_mod)
|
|
86
95
|
http_response = http.request(req)
|
|
87
96
|
case http_response
|
|
88
97
|
when Net::HTTPNotModified
|
|
@@ -93,7 +102,7 @@ module SSLTest
|
|
|
93
102
|
when Net::HTTPSuccess
|
|
94
103
|
# Success, update (or add to) cache and return frech body
|
|
95
104
|
@logger&.debug { "SSLTest + CRL: 200 OK (#{http_response.body.bytesize} bytes)" }
|
|
96
|
-
@logger&.warn { "SSLTest + CRL: Warning: massive file size" } if http_response.body.bytesize > 1024**2 # 1MB
|
|
105
|
+
@logger&.warn { "SSLTest + CRL: Warning: massive file size (#{http_response.body.bytesize} bytes)" } if http_response.body.bytesize > 1024**2 # 1MB
|
|
97
106
|
@logger&.warn { "SSLTest + CRL: Warning: no caching headers on #{uri}" } unless http_response["Etag"] or http_response["Last-Modified"]
|
|
98
107
|
cache.write(cache_key, {
|
|
99
108
|
body: http_response.body,
|
data/lib/ssl-test.rb
CHANGED
|
@@ -11,7 +11,7 @@ module SSLTest
|
|
|
11
11
|
extend OCSP
|
|
12
12
|
extend CRL
|
|
13
13
|
|
|
14
|
-
VERSION = -"2.0.
|
|
14
|
+
VERSION = -"2.0.1"
|
|
15
15
|
|
|
16
16
|
# Prefix for all cache keys so SSLTest entries coexist cleanly inside a shared
|
|
17
17
|
# cache (e.g. Rails.cache).
|
|
@@ -114,6 +114,23 @@ module SSLTest
|
|
|
114
114
|
@logger = logger
|
|
115
115
|
end
|
|
116
116
|
|
|
117
|
+
# The order in which revocation check methods are tried for each certificate.
|
|
118
|
+
# The first method to return a conclusive answer (ok or revoked) wins; the
|
|
119
|
+
# next is only tried when the previous one errors out (missing endpoint,
|
|
120
|
+
# network error, etc.). Defaults to CRL first (since 1.6) to reduce the
|
|
121
|
+
# revocation propagation delay. Set to %i[ocsp crl] to check OCSP first.
|
|
122
|
+
def revocation_order
|
|
123
|
+
@revocation_order ||= %i[crl ocsp]
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def revocation_order= order
|
|
127
|
+
order = Array(order).map { |m| m.to_sym }
|
|
128
|
+
unless order.sort == %i[crl ocsp]
|
|
129
|
+
raise ArgumentError, "SSLTest.revocation_order must be %i[crl ocsp] or %i[ocsp crl], got #{order.inspect}"
|
|
130
|
+
end
|
|
131
|
+
@revocation_order = order
|
|
132
|
+
end
|
|
133
|
+
|
|
117
134
|
private
|
|
118
135
|
|
|
119
136
|
def revocation_message(revoked, revocation_date, message)
|
|
@@ -147,26 +164,37 @@ module SSLTest
|
|
|
147
164
|
chain[0..-2].each_with_index do |cert, i|
|
|
148
165
|
@logger&.debug { "SSLTest + test_chain_revocation: #{cert_field_to_hash(cert.subject)['CN']}" }
|
|
149
166
|
|
|
150
|
-
# Try
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
167
|
+
# Try each revocation method in the configured order, falling back to the
|
|
168
|
+
# next one only when the current method errors out.
|
|
169
|
+
errors = {}
|
|
170
|
+
passed = false
|
|
171
|
+
revocation_order.each do |method|
|
|
172
|
+
result = test_revocation(method, cert, issuer: chain[i + 1], chain: chain, **options)
|
|
173
|
+
@logger&.debug { "SSLTest + #{method.to_s.upcase}: #{result}" }
|
|
174
|
+
if result == :"#{method}_ok" # passed, go to next cert
|
|
175
|
+
passed = true
|
|
176
|
+
break
|
|
177
|
+
end
|
|
178
|
+
return result if result[0] == true # revoked
|
|
179
|
+
errors[method] = result[1] # errored, try the next method
|
|
180
|
+
end
|
|
181
|
+
next if passed
|
|
161
182
|
|
|
162
|
-
# If
|
|
163
|
-
return [false, "
|
|
183
|
+
# If all methods failed, return a soft fail with a combination of the error messages
|
|
184
|
+
return [false, errors.map { |method, message| "#{method.to_s.upcase}: #{message}" }.join(", "), nil]
|
|
164
185
|
end
|
|
165
186
|
|
|
166
187
|
# If all test passed, the certificate is not revoked
|
|
167
188
|
[false, nil, nil]
|
|
168
189
|
end
|
|
169
190
|
|
|
191
|
+
def test_revocation method, cert, **options
|
|
192
|
+
case method
|
|
193
|
+
when :crl then test_crl_revocation(cert, **options)
|
|
194
|
+
when :ocsp then test_ocsp_revocation(cert, **options)
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
|
|
170
198
|
def cert_field_to_hash field
|
|
171
199
|
field.to_a.each.with_object({}) do |v, h|
|
|
172
200
|
v = v.to_a
|
data/spec/memory_store_spec.rb
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
require "ssl-test"
|
|
2
|
+
require "rspec/retry" # the cache.size examples below hit live CRL/OCSP endpoints
|
|
2
3
|
|
|
3
4
|
describe SSLTest::MemoryStore do
|
|
4
5
|
subject(:store) { described_class.new }
|
|
@@ -51,7 +52,7 @@ describe SSLTest::MemoryStore do
|
|
|
51
52
|
end
|
|
52
53
|
|
|
53
54
|
# #size as reported through the default store after real CRL/OCSP fetches.
|
|
54
|
-
describe "SSLTest.cache.size" do
|
|
55
|
+
describe "SSLTest.cache.size", retry: 5 do # examples hit live CRL/OCSP endpoints
|
|
55
56
|
before { SSLTest.cache.clear }
|
|
56
57
|
|
|
57
58
|
it "returns 0 by default" do
|
data/spec/ssl-test_spec.rb
CHANGED
|
@@ -12,8 +12,8 @@ RSpec.configure do |config|
|
|
|
12
12
|
# The error/revocation examples below hit several public TLS test endpoints
|
|
13
13
|
# (badssl.com, testserver.host, ssl.com) which intermittently reset connections
|
|
14
14
|
# under load. They're spread across a few providers to avoid hammering a single
|
|
15
|
-
# one, and
|
|
16
|
-
# transient network blips don't fail the suite.
|
|
15
|
+
# one, and the network-hitting describe blocks are tagged `retry: 5` (via
|
|
16
|
+
# rspec-retry) so transient network blips don't fail the suite.
|
|
17
17
|
config.verbose_retry = true
|
|
18
18
|
config.default_sleep_interval = 1
|
|
19
19
|
end
|
|
@@ -26,7 +26,7 @@ describe SSLTest do
|
|
|
26
26
|
|
|
27
27
|
after(:each) { proxy_thread&.kill }
|
|
28
28
|
|
|
29
|
-
describe '.test_url' do
|
|
29
|
+
describe '.test_url', retry: 5 do # examples hit live TLS/CRL/OCSP endpoints
|
|
30
30
|
it "returns no error on valid SNI website" do
|
|
31
31
|
valid, error, cert = SSLTest.test("https://www.mycs.com")
|
|
32
32
|
expect(error).to be_nil
|
|
@@ -59,35 +59,35 @@ describe SSLTest do
|
|
|
59
59
|
expect(cert).to be_a OpenSSL::X509::Certificate
|
|
60
60
|
end
|
|
61
61
|
|
|
62
|
-
it "returns error on self signed certificate"
|
|
62
|
+
it "returns error on self signed certificate" do
|
|
63
63
|
valid, error, cert = SSLTest.test("https://self-signed.testserver.host/")
|
|
64
64
|
expect(error).to eq ("error code 18: self-signed certificate")
|
|
65
65
|
expect(valid).to eq(false)
|
|
66
66
|
expect(cert).to be_a OpenSSL::X509::Certificate
|
|
67
67
|
end
|
|
68
68
|
|
|
69
|
-
it "returns error on incomplete chain"
|
|
69
|
+
it "returns error on incomplete chain" do
|
|
70
70
|
valid, error, cert = SSLTest.test("https://incomplete-chain.badssl.com/")
|
|
71
71
|
expect(error).to eq ("error code 20: unable to get local issuer certificate")
|
|
72
72
|
expect(valid).to eq(false)
|
|
73
73
|
expect(cert).to be_a OpenSSL::X509::Certificate
|
|
74
74
|
end
|
|
75
75
|
|
|
76
|
-
it "returns error on untrusted root"
|
|
76
|
+
it "returns error on untrusted root" do
|
|
77
77
|
valid, error, cert = SSLTest.test("https://untrusted-root.testserver.host/")
|
|
78
78
|
expect(error).to eq ("error code 19: self-signed certificate in certificate chain")
|
|
79
79
|
expect(valid).to eq(false)
|
|
80
80
|
expect(cert).to be_a OpenSSL::X509::Certificate
|
|
81
81
|
end
|
|
82
82
|
|
|
83
|
-
it "returns error on invalid host"
|
|
83
|
+
it "returns error on invalid host" do
|
|
84
84
|
valid, error, cert = SSLTest.test("https://wrong.host.badssl.com/")
|
|
85
85
|
expect(error).to include('error code 62: hostname mismatch')
|
|
86
86
|
expect(valid).to eq(false)
|
|
87
87
|
expect(cert).to be_a OpenSSL::X509::Certificate
|
|
88
88
|
end
|
|
89
89
|
|
|
90
|
-
it "returns error on expired cert"
|
|
90
|
+
it "returns error on expired cert" do
|
|
91
91
|
valid, error, cert = SSLTest.test("https://expired-rsa-dv.ssl.com/")
|
|
92
92
|
expect(error).to eq ("error code 10: certificate has expired")
|
|
93
93
|
expect(valid).to eq(false)
|
|
@@ -128,10 +128,12 @@ describe SSLTest do
|
|
|
128
128
|
expect(cert).to be_a OpenSSL::X509::Certificate
|
|
129
129
|
end
|
|
130
130
|
|
|
131
|
-
it "returns error on revoked cert (CRL)"
|
|
131
|
+
it "returns error on revoked cert (CRL)" do
|
|
132
132
|
# CRL is tried first and detects the revocation, so OCSP is never used
|
|
133
133
|
expect(SSLTest).to receive(:follow_crl_redirects).once.and_call_original
|
|
134
134
|
expect(SSLTest).not_to receive(:test_ocsp_revocation)
|
|
135
|
+
# On a serial byte-match we fall back to #revoked to extract the reason/date
|
|
136
|
+
expect_any_instance_of(OpenSSL::X509::CRL).to receive(:revoked).and_call_original
|
|
135
137
|
valid, error, cert = SSLTest.test("https://revoked.badssl.com/")
|
|
136
138
|
expect(error).to eq ("SSL certificate revoked: Key Compromise (revocation date: 2026-05-12 21:01:31 UTC)")
|
|
137
139
|
expect(valid).to eq(false)
|
|
@@ -161,6 +163,9 @@ describe SSLTest do
|
|
|
161
163
|
# CRL is tried first and succeeds for both certs, so OCSP is never used
|
|
162
164
|
expect(SSLTest).to receive(:follow_crl_redirects).twice.and_call_original
|
|
163
165
|
expect(SSLTest).not_to receive(:test_ocsp_revocation)
|
|
166
|
+
# Both certs are absent from their CRL, so the serial byte-search short-circuits
|
|
167
|
+
# and we never materialise the (potentially huge) revoked list.
|
|
168
|
+
expect_any_instance_of(OpenSSL::X509::CRL).not_to receive(:revoked)
|
|
164
169
|
valid, error, cert = SSLTest.test("https://www.demarches-simplifiees.fr")
|
|
165
170
|
expect(error).to be_nil
|
|
166
171
|
expect(valid).to eq(true)
|
|
@@ -236,7 +241,7 @@ describe SSLTest do
|
|
|
236
241
|
end
|
|
237
242
|
end
|
|
238
243
|
|
|
239
|
-
describe '.follow_crl_redirects' do
|
|
244
|
+
describe '.follow_crl_redirects', retry: 5 do # fetches a live CRL
|
|
240
245
|
before { SSLTest.cache.clear }
|
|
241
246
|
# 19MB: http://crl3.digicert.com/ssca-sha2-g6.crl
|
|
242
247
|
it "fetch CRL list and updates cache" do
|
|
@@ -267,7 +272,7 @@ describe SSLTest do
|
|
|
267
272
|
end
|
|
268
273
|
end
|
|
269
274
|
|
|
270
|
-
describe '.cache' do
|
|
275
|
+
describe '.cache', retry: 5 do # some examples hit live CRL/OCSP endpoints
|
|
271
276
|
# Restore the default in-process store after tests that swap the backend so
|
|
272
277
|
# global state doesn't leak between examples.
|
|
273
278
|
after { SSLTest.cache = SSLTest::MemoryStore.new }
|
|
@@ -294,7 +299,7 @@ describe SSLTest do
|
|
|
294
299
|
end
|
|
295
300
|
end
|
|
296
301
|
|
|
297
|
-
describe '.test_cert' do
|
|
302
|
+
describe '.test_cert', retry: 5 do # revocation checks hit live CRL/OCSP endpoints
|
|
298
303
|
it "returns no error on valid SNI website" do
|
|
299
304
|
cert = OpenSSL::X509::Certificate.new(File.read(File.join(__dir__, 'fixtures/www_mycs_com_client.pem')))
|
|
300
305
|
ca_bundle = OpenSSL::X509::Certificate.load(File.read(File.join(__dir__, 'fixtures/www_mycs_com_ca_bundle.pem')))
|
|
@@ -488,4 +493,51 @@ describe SSLTest do
|
|
|
488
493
|
end
|
|
489
494
|
end
|
|
490
495
|
end
|
|
496
|
+
|
|
497
|
+
describe '.revocation_order' do # no network: dispatch logic is stubbed
|
|
498
|
+
after { SSLTest.revocation_order = %i[crl ocsp] } # reset to the default
|
|
499
|
+
|
|
500
|
+
let(:cert) { OpenSSL::X509::Certificate.new }
|
|
501
|
+
let(:issuer) { OpenSSL::X509::Certificate.new }
|
|
502
|
+
let(:chain) { [cert, issuer] }
|
|
503
|
+
|
|
504
|
+
it "defaults to CRL first" do
|
|
505
|
+
expect(SSLTest.revocation_order).to eq(%i[crl ocsp])
|
|
506
|
+
end
|
|
507
|
+
|
|
508
|
+
it "validates the value" do
|
|
509
|
+
expect { SSLTest.revocation_order = %i[crl] }.to raise_error(ArgumentError)
|
|
510
|
+
expect { SSLTest.revocation_order = %i[ocsp bogus] }.to raise_error(ArgumentError)
|
|
511
|
+
end
|
|
512
|
+
|
|
513
|
+
it "checks CRL first by default, falling back to OCSP on error" do
|
|
514
|
+
expect(SSLTest).to receive(:test_crl_revocation).ordered.and_return([false, "CRL boom", nil])
|
|
515
|
+
expect(SSLTest).to receive(:test_ocsp_revocation).ordered.and_return(:ocsp_ok)
|
|
516
|
+
result = SSLTest.send(:test_chain_revocation, chain)
|
|
517
|
+
expect(result).to eq([false, nil, nil])
|
|
518
|
+
end
|
|
519
|
+
|
|
520
|
+
it "checks OCSP first when configured, falling back to CRL on error" do
|
|
521
|
+
SSLTest.revocation_order = %i[ocsp crl]
|
|
522
|
+
expect(SSLTest).to receive(:test_ocsp_revocation).ordered.and_return([false, "OCSP boom", nil])
|
|
523
|
+
expect(SSLTest).to receive(:test_crl_revocation).ordered.and_return(:crl_ok)
|
|
524
|
+
result = SSLTest.send(:test_chain_revocation, chain)
|
|
525
|
+
expect(result).to eq([false, nil, nil])
|
|
526
|
+
end
|
|
527
|
+
|
|
528
|
+
it "does not try the second method when the first one passes" do
|
|
529
|
+
SSLTest.revocation_order = %i[ocsp crl]
|
|
530
|
+
expect(SSLTest).to receive(:test_ocsp_revocation).and_return(:ocsp_ok)
|
|
531
|
+
expect(SSLTest).not_to receive(:test_crl_revocation)
|
|
532
|
+
expect(SSLTest.send(:test_chain_revocation, chain)).to eq([false, nil, nil])
|
|
533
|
+
end
|
|
534
|
+
|
|
535
|
+
it "combines error messages in the configured order when all methods fail" do
|
|
536
|
+
SSLTest.revocation_order = %i[ocsp crl]
|
|
537
|
+
allow(SSLTest).to receive(:test_ocsp_revocation).and_return([false, "OCSP boom", nil])
|
|
538
|
+
allow(SSLTest).to receive(:test_crl_revocation).and_return([false, "CRL boom", nil])
|
|
539
|
+
_revoked, message, _date = SSLTest.send(:test_chain_revocation, chain)
|
|
540
|
+
expect(message).to eq("OCSP: OCSP boom, CRL: CRL boom")
|
|
541
|
+
end
|
|
542
|
+
end
|
|
491
543
|
end
|
metadata
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ssl-test
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.0.
|
|
4
|
+
version: 2.0.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Adrien Rey-Jarthon
|
|
8
8
|
bindir: bin
|
|
9
9
|
cert_chain: []
|
|
10
|
-
date: 2026-06-
|
|
10
|
+
date: 2026-06-19 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
13
|
name: bundler
|