diff --git a/CHANGELOG.md b/CHANGELOG.md index b024e6087..cb1358a6c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -47,6 +47,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Add `enable_extended_context` to allow JWT Claim Check access full request context [PR #1535](https://github.com/3scale/APIcast/pull/1535) [THREESCALE-9510](https://issues.redhat.com/browse/THREESCALE-9510) - JWT signature verification, support for ES256/ES512 [PR #1533](https://github.com/3scale/APIcast/pull/1533) [THREESCALE-11474](https://issues.redhat.com/browse/THREESCALE-11474) - JWT Parser policy [PR #1536](https://github.com/3scale/APIcast/pull/1536) [THREESCALE-10708](https://issues.redhat.com/browse/THREESCALE-10708) +- TLS Validation Policy - add support to validate client certificate with CRL and OCSP [PR #1503](https://github.com/3scale/APIcast/pull/1503) [THREESCALE-11404](https://issues.redhat.com/browse/THREESCALE-11404) ## [3.15.0] 2024-04-04 diff --git a/gateway/http.d/shdict.conf b/gateway/http.d/shdict.conf index ba0901d57..c5a28e07e 100644 --- a/gateway/http.d/shdict.conf +++ b/gateway/http.d/shdict.conf @@ -8,3 +8,4 @@ lua_shared_dict limiter 1m; lua_shared_dict cached_auths 20m; lua_shared_dict batched_reports {{env.APICAST_POLICY_BATCHER_SHARED_MEMORY_SIZE | default: "20m"}}; lua_shared_dict batched_reports_locks 1m; +lua_shared_dict ocsp_cache 10m; diff --git a/gateway/src/apicast/policy/tls_validation/README.md b/gateway/src/apicast/policy/tls_validation/README.md index 97adb15d2..867f73b66 100644 --- a/gateway/src/apicast/policy/tls_validation/README.md +++ b/gateway/src/apicast/policy/tls_validation/README.md @@ -1,10 +1,11 @@ # TLS Validation policy -This policy can validate TLS Client Certificate against a whitelist. +This policy can validate TLS Client Certificate against a whitelist and Certificate Revocation List (CRL) -Whitelist expects PEM formatted CA or Client certificates. -It is not necessary to have the full certificate chain, just partial matches are allowed. -For example you can add to the whitelist just leaf client certificates without the whole bundle with a CA certificate. +* Whitelist expects PEM formatted CA or Client certificates. +* Revocation List expects PEM formatted certificates. + +It is not necessary to have the full certificate chain, just partial matches are allowed. For example you can add to the whitelist just leaf client certificates without the whole bundle with a CA certificate. However, you can change this behaviour with `allow_partial_chain` ## Configuration @@ -18,13 +19,77 @@ NOTE: This policy is not compatible with `APICAST_PATH_ROUTING` or `APICAST_PATH ## Example +* Allow certificate verification with only an intermediate certificate. +``` +{ + "name": "apicast.policy.tls_validation", + "configuration": { + "whitelist": [ + { "pem_certificate": ""-----BEGIN CERTIFICATE----- XXXXXX -----END CERTIFICATE-----"} + ] + } +} +``` + +* Use full certificate chain to verify client certificate +``` +{ + "name": "apicast.policy.tls_validation", + "configuration": { + "whitelist": [ + { "pem_certificate": ""-----BEGIN CERTIFICATE----- XXXXXX -----END CERTIFICATE-----"} + ], + "allow_partial_chain": false + } +} +``` + +With Certificate Revocation List (CRL) + ``` { "name": "apicast.policy.tls_validation", "configuration": { "whitelist": [ { "pem_certificate": ""-----BEGIN CERTIFICATE----- XXXXXX -----END CERTIFICATE-----"} + ], + "revocation_check_type": "crl", + "revoke_list": [ + { "pem_certificate": ""-----BEGIN X509 CRL ----- XXXXXX -----END X509 CRL-----"} ] } } ``` + +Checking certificate status with Online Certificate Status Protocol (OCSP). The responder url is +extracted from the certificate. + +NOTE: When validating a client certificate with OCSP, APIcast requires the client to send the certificate chain +(i.e. if the certificate is signed with an intermediate certificate, the client needs to send both the client certificate + the intermediate certificate) + +``` +{ + "name": "apicast.policy.tls_validation", + "configuration": { + "whitelist": [ + { "pem_certificate": ""-----BEGIN CERTIFICATE----- XXXXXX -----END CERTIFICATE-----"} + ], + "revocation_check_type": "ocsp", + } +} +``` + +Overwrite OCSP responder URL + +``` +{ + "name": "apicast.policy.tls_validation", + "configuration": { + "whitelist": [ + { "pem_certificate": ""-----BEGIN CERTIFICATE----- XXXXXX -----END CERTIFICATE-----"} + ], + "revocation_check_type": "ocsp", + "ocsp_responder_url": "http://:" + } +} +``` diff --git a/gateway/src/apicast/policy/tls_validation/apicast-policy.json b/gateway/src/apicast/policy/tls_validation/apicast-policy.json index d742a5488..5c499c38c 100644 --- a/gateway/src/apicast/policy/tls_validation/apicast-policy.json +++ b/gateway/src/apicast/policy/tls_validation/apicast-policy.json @@ -31,6 +31,85 @@ "$ref": "#/definitions/store", "title": "Certificate Whitelist", "description": "Individual certificates and CA certificates to be whitelisted." + }, + "allow_partial_chain": { + "description": "Allow certificate verification with only an intermediate certificate", + "type": "boolean", + "default": true + }, + "revocation_check_type": { + "title": "Certificate Revocation Check type", + "type": "string", + "oneOf": [ + { + "enum": [ + "ocsp" + ], + "title": "Enables OCSP validation of the client certificate." + }, + { + "enum": [ + "crl" + ], + "title": "Use certificates revocation list (CRL) in the PEM format to verify client certificates." + }, + { + "enum": [ + "none" + ], + "title": "Do not check for certificate recovation status" + } + ], + "default": "none" + } + }, + "dependencies": { + "revocation_check_type": { + "oneOf": [ + { + "properties": { + "revocation_check_type": { + "enum": [ + "none" + ] + } + } + }, + { + "properties": { + "revocation_check_type": { + "enum": [ + "crl" + ] + }, + "revoke_list": { + "title": "Certificate RevokeList", + "description": "Individual certificates and CA certificates to be revoked.", + "$ref": "#/definitions/store" + } + } + }, + { + "properties": { + "revocation_check_type": { + "enum": [ + "ocsp" + ] + }, + "ocsp_responder_url": { + "title": "OCSP Responder URL ", + "description": "Overrides the URL of the OCSP responder specified in the “Authority Information Access” certificate extension for validation of client certificates. ", + "type": "string" + }, + "cache_ttl": { + "title": "Max TTL for cached OCSP response", + "type": "integer", + "minimum": 1, + "maximum": 3600 + } + } + } + ] } } } diff --git a/gateway/src/apicast/policy/tls_validation/ocsp_validation.lua b/gateway/src/apicast/policy/tls_validation/ocsp_validation.lua new file mode 100644 index 000000000..fd7dbf8ae --- /dev/null +++ b/gateway/src/apicast/policy/tls_validation/ocsp_validation.lua @@ -0,0 +1,116 @@ +local user_agent = require "apicast.user_agent" +local http_ng = require "resty.http_ng" +local resty_env = require "resty.env" +local tls = require "resty.tls" +local ngx_ssl = require "ngx.ssl" +local ocsp = require "ngx.ocsp" + +local _M = {} +local ocsp_shm = ngx.shared.ocsp_cache + +local function do_ocsp_request(ocsp_url, ocsp_request) + -- TODO: set default timeout + local http_client = http_ng.new{ + options = { + headers = { + ['User-Agent'] = user_agent() + }, + ssl = { verify = resty_env.enabled('OPENSSL_VERIFY') } + } + } + local res, err = http_client.post{ + ocsp_url, + ocsp_request, + headers= { + ["Content-Type"] = "application/ocsp-request" + }} + if err then + return nil, err + end + + ngx.log(ngx.INFO, "fetching OCSP response from ", ocsp_url) + + if not res then + return nil, "failed to send request to OCSP responder: " .. tostring(err) + end + + if res.status ~= 200 then + return nil, "unexpected OCSP responder status code: " .. res.status + end + + return res.body +end + +function _M.check_revocation_status(ocsp_responder_url, digest, ttl) + -- Nginx supports leaf mode, that is only verify the client ceritificate, however + -- until we have a way to detect which CA certificate is being used to verify the + -- client certificate we need to get the full certificate chain here to construct + -- the OCSP request. + local cert_chain, err = tls.get_full_client_certificate_chain() + if not cert_chain then + return nil, err or "no client certificate" + end + + local der_cert + der_cert, err = ngx_ssl.cert_pem_to_der(cert_chain) + if not der_cert then + return nil, "failed to convert certificate chain from PEM to DER " .. err + end + + local ocsp_resp + ocsp_resp = ocsp_shm:get(digest) + + if ocsp_resp == nil then + ngx.log(ngx.INFO, "no ocsp resp cache found, fetch from ocsp responder") + + + -- TODO: check response cache + local ocsp_url + if ocsp_responder_url and ocsp_responder_url ~= "" then + ocsp_url = ocsp_responder_url + else + ocsp_url, err = ocsp.get_ocsp_responder_from_der_chain(der_cert) + if not ocsp_url then + return nil, err or ("could not extract OCSP responder URL, the client " .. + "certificate may be missing the required extensions") + end + end + + if not ocsp_url or ocsp_url == "" then + return nil, " invalid OCSP responder URL" + end + + local ocsp_req + ocsp_req, err = ocsp.create_ocsp_request(der_cert) + if not ocsp_req then + return nil, "failed to create OCSP request: " .. err + end + + ocsp_resp, err = do_ocsp_request(ocsp_url, ocsp_req) + if not ocsp_resp or #ocsp_resp == 0 then + return nil, "unexpected response from OCSP responder: empty body" + end + + -- Use ttl, normally this should be (nextUpdate - thisUpdate), but current version + -- of openresty API does not expose those attributes. Support for this was added + -- in openrest-core v0.1.31, we either need to backport or upgrade the openresty + -- version. + local ok + ok, err = ocsp_shm:set(digest, ocsp_resp, ttl) + if not ok then + ngx.log(ngx.ERR, "could not save ocsp response to cache: ", err) + end + else + ngx.log(ngx.INFO, "using ocsp from cache") + end + + local ok + ok, err = ocsp.validate_ocsp_response(ocsp_resp, der_cert) + if not ok then + return false, "failed to validate OCSP response: " .. err + end + + return true +end + +return _M diff --git a/gateway/src/apicast/policy/tls_validation/tls_validation.lua b/gateway/src/apicast/policy/tls_validation/tls_validation.lua index 151bd97c3..44c4ede18 100644 --- a/gateway/src/apicast/policy/tls_validation/tls_validation.lua +++ b/gateway/src/apicast/policy/tls_validation/tls_validation.lua @@ -2,9 +2,12 @@ local policy = require('apicast.policy') local _M = policy.new('tls_validation') -local X509_STORE = require('resty.openssl.x509.store') local X509 = require('resty.openssl.x509') +local X509_STORE = require('resty.openssl.x509.store') +local X509_CRL = require('resty.openssl.x509.crl') +local tls = require('resty.tls') local ngx_ssl = require "ngx.ssl" +local ocsp = require ("ocsp_validation") local ipairs = ipairs local tostring = tostring @@ -13,23 +16,56 @@ local debug = ngx.config.debug local function init_trusted_store(store, certificates) for _,certificate in ipairs(certificates) do - local cert, err = X509.new(certificate.pem_certificate) -- TODO: handle errors - - if cert then - store:add(cert) - - if debug then - ngx.log(ngx.DEBUG, 'adding certificate to the tls validation ', tostring(cert:subject_name()), ' SHA1: ', cert:hexdigest('SHA1')) + local normalized_cert = tls.normalize_pem_cert(certificate.pem_certificate) + if normalized_cert then + local cert, err = X509.new(normalized_cert) -- TODO: handle errors + + if cert then + store:add(cert) + + if debug then + ngx.log(ngx.DEBUG, 'adding certificate to the tls validation ', tostring(cert:subject_name()), ' SHA1: ', cert:hexdigest('SHA1')) + end + else + ngx.log(ngx.WARN, 'error whitelisting certificate, err: ', err) + + if debug then + ngx.log(ngx.DEBUG, 'certificate: ', certificate.pem_certificate) + end end else - ngx.log(ngx.WARN, 'error whitelisting certificate, err: ', err) + ngx.log(ngx.WARN, "invalid cert") + end + end - if debug then - ngx.log(ngx.DEBUG, 'certificate: ', certificate.pem_certificate) + return store +end + +local function init_crl_list(store, crl_certificates) + local ok, err + local crl + for _, certificate in ipairs(crl_certificates) do + local normalized_cert = tls.normalize_pem_cert(certificate.pem_certificate) + if normalized_cert then + crl, err = X509_CRL.new(normalized_cert) + if crl then + -- add crl to store, but skip setting the flag + ok, err = store:add(crl, true) + + if debug then + ngx.log(ngx.DEBUG, 'adding crl certificate to the tls validation ', tostring(crl:subject_name()), ' SHA1: ', crl:hexdigest('SHA1')) + end + else + ngx.log(ngx.WARN, 'failed to add crl certificate, err: ', err) + + if debug then + ngx.log(ngx.DEBUG, 'certificate: ', certificate.pem_certificate) + end end + else + ngx.log(ngx.WARN, "invalid CRL cert") end end - return store end @@ -42,6 +78,14 @@ function _M.new(config) self.x509_store = init_trusted_store(store, config and config.whitelist or {}) self.error_status = config and config.error_status or 400 + self.allow_partial_chain = config and config.allow_partial_chain ~= false and true or false + self.revocation_type = config and config.revocation_check_type or "none" + if self.revocation_type == "crl" then + init_crl_list(store, config and config.revoke_list or {}) + elseif self.revocation_type == "ocsp" then + self.ocsp_responder_url = config and config.ocsp_responder_url + self.cache_ttl = config and config.cache_ttl + end return self end @@ -49,13 +93,11 @@ end function _M:ssl_certificate() -- Request client certificate -- - -- We don't validate the certificate during the handshake, thus set `depth` to 0 (default is 1) - -- value here in order to save CPU cycles - -- -- TODO: -- provide ca_certs: See https://github.com/openresty/lua-resty-core/blob/master/lib/ngx/ssl.md#verify_client -- handle verify_depth -- + -- TODO: OCSP stapling return ngx_ssl.verify_client() end @@ -70,26 +112,48 @@ function _M:access() local cert, err = X509.new(client_cert) if not cert then ngx.status = self.error_status - ngx.log(ngx.WARN, "Invalid TLS certificate, err: ", err) + ngx.log(ngx.WARN, "Unable to load client certificate, err: ", err) ngx.say("Invalid TLS certificate") return ngx.exit(ngx.status) end local store = self.x509_store - store:set_flags(store.verify_flags.X509_V_FLAG_PARTIAL_CHAIN) + + if self.allow_partial_chain then + store:set_flags(store.verify_flags.X509_V_FLAG_PARTIAL_CHAIN) + end -- err is printed inside validate_cert method -- so no need capture the err here - local ok, err = store:verify(cert) + local chain, ok + chain, err = store:verify(cert, nil, true) - if not ok then + if not chain then ngx.status = self.error_status - ngx.log(ngx.INFO, "TLS certificate validation failed, err: ", err) + ngx.log(ngx.WARN, "TLS certificate validation failed, err: ", err) ngx.say("TLS certificate validation failed") return ngx.exit(ngx.status) end - return ok, nil + if self.revocation_type == "crl" then + ok, err = store:check_revocation(chain) + if not ok then + ngx.status = self.error_status + ngx.log(ngx.WARN, "TLS certificate validation failed, err: ", err) + ngx.say("TLS certificate validation failed") + return ngx.exit(ngx.status) + end + elseif self.revocation_type == "ocsp" then + ok, err = ocsp.check_revocation_status(self.ocsp_responder_url, cert:digest("SHA256"), self.cache_ttl) + if not ok then + ngx.status = self.error_status + ngx.log(ngx.WARN, "TLS certificate validation failed, err: ", err) + ngx.say("TLS certificate validation failed") + return ngx.exit(ngx.status) + end + end + + return true, nil end return _M diff --git a/gateway/src/apicast/policy/upstream_mtls/upstream_mtls.lua b/gateway/src/apicast/policy/upstream_mtls/upstream_mtls.lua index da9bbd37c..d2d88ae7c 100644 --- a/gateway/src/apicast/policy/upstream_mtls/upstream_mtls.lua +++ b/gateway/src/apicast/policy/upstream_mtls/upstream_mtls.lua @@ -2,6 +2,7 @@ local ssl = require('ngx.ssl') local data_url = require('resty.data_url') +local tls = require 'resty.tls' local util = require 'apicast.util' local pairs = pairs @@ -58,12 +59,18 @@ local function read_ca_certificates(ca_certificates) local valid = false local store = X509_STORE.new() for _,certificate in pairs(ca_certificates) do - local cert, err = X509.new(certificate) - if cert then - valid = true - store:add(cert) + local normalized_cert = tls.normalize_pem_cert(certificate) + + if normalized_cert then + local cert, err = X509.new(normalized_cert) + if cert then + valid = true + store:add(cert) + else + ngx.log(ngx.INFO, "cannot load certificate, err: ", err) + end else - ngx.log(ngx.INFO, "cannot load certificate, err: ", err) + ngx.log(ngx.WARN, "invalid cert") end end diff --git a/gateway/src/resty/http_ng/backend/resty.lua b/gateway/src/resty/http_ng/backend/resty.lua index 595286b9f..0dfb748ef 100644 --- a/gateway/src/resty/http_ng/backend/resty.lua +++ b/gateway/src/resty/http_ng/backend/resty.lua @@ -36,6 +36,10 @@ backend.send = function(_, request) local res local httpc, err = http_proxy.new(request) + if err then + return nil, err + end + if httpc then res, err = send(httpc, request) end diff --git a/gateway/src/resty/tls.lua b/gateway/src/resty/tls.lua index 0b5a65e7f..201698b89 100644 --- a/gateway/src/resty/tls.lua +++ b/gateway/src/resty/tls.lua @@ -2,20 +2,32 @@ local base = require "resty.core.base" local type = type local tostring = tostring +local re_gsub = ngx.re.gsub local get_request = base.get_request +local get_size_ptr = base.get_size_ptr local ffi = require "ffi" +local ffi_new = ffi.new +local ffi_str = ffi.string local C = ffi.C + local _M = {} local NGX_OK = ngx.OK +local NGX_ERROR = ngx.ERROR +local NGX_DECLINED = ngx.DECLINED +local ngx_http_apicast_ffi_get_full_client_certificate_chain; local ngx_http_apicast_ffi_set_proxy_cert_key; local ngx_http_apicast_ffi_set_proxy_ca_cert; local ngx_http_apicast_ffi_set_ssl_verify +local value_ptr = ffi_new("unsigned char *[1]") + ffi.cdef([[ + int ngx_http_apicast_ffi_get_full_client_certificate_chain( + ngx_http_request_t *r, char **value, size_t *value_len); int ngx_http_apicast_ffi_set_proxy_cert_key( ngx_http_request_t *r, void *cdata_chain, void *cdata_key); int ngx_http_apicast_ffi_set_proxy_ca_cert( @@ -24,6 +36,7 @@ ffi.cdef([[ ngx_http_request_t *r, int verify, int verify_deph); ]]) +ngx_http_apicast_ffi_get_full_client_certificate_chain = C.ngx_http_apicast_ffi_get_full_client_certificate_chain ngx_http_apicast_ffi_set_proxy_cert_key = C.ngx_http_apicast_ffi_set_proxy_cert_key ngx_http_apicast_ffi_set_proxy_ca_cert = C.ngx_http_apicast_ffi_set_proxy_ca_cert ngx_http_apicast_ffi_set_ssl_verify = C.ngx_http_apicast_ffi_set_ssl_verify @@ -88,4 +101,37 @@ function _M.set_upstream_ssl_verify(verify, verify_deph) end end +-- Retrieve the full client certificate chain +function _M.get_full_client_certificate_chain() + local r = get_request() + if not r then + error("no request found") + end + + local size_ptr = get_size_ptr() + + local rc = ngx_http_apicast_ffi_get_full_client_certificate_chain(r, value_ptr, size_ptr) + + if rc == NGX_OK then + return ffi_str(value_ptr[0], size_ptr[0]) + end + + if rc == NGX_ERROR then + return nil, "error while obtaining client certificate chain" + end + + + if rc == NGX_DECLINED then + return nil + end +end + +function _M.normalize_pem_cert(str) + if not str then return end + if #(str) == 0 then return end + + -- using also jit compiler (j) will result in a segfault with some certificates + return re_gsub(str, [[\s(?!(CERTIFICATE|X509|CRL))]], '\n', 'o') +end + return _M diff --git a/spec/policy/tls_validation/tls_validation_spec.lua b/spec/policy/tls_validation/tls_validation_spec.lua index bf06d401f..c059ab2d0 100644 --- a/spec/policy/tls_validation/tls_validation_spec.lua +++ b/spec/policy/tls_validation/tls_validation_spec.lua @@ -3,7 +3,9 @@ local _M = require('apicast.policy.tls_validation') local server = assert(fixture('CA', 'server.crt')) local CA = assert(fixture('CA', 'intermediate-ca.crt')) local client = assert(fixture('CA', 'client.crt')) +local revoked_client = assert(fixture('CA', 'revoked_client.crt')) local ssl_helper = require 'ssl_helper' +local crl = assert(fixture('CA', 'crl.pem')) describe('tls_validation policy', function() describe('.new', function() @@ -74,5 +76,29 @@ describe('tls_validation policy', function() assert.is_true(policy:access()) end) + + it('accepts CRL', function() + ngx.var = { ssl_client_raw_cert = client } + + local policy = _M.new({ + whitelist = { { pem_certificate = CA }}, + revocation_check_type = "crl", + revoke_list = { { pem_certificate = crl }}}) + + assert.is_true(policy:access()) + end) + + it('reject revoked certificate', function() + ngx.var = { ssl_client_raw_cert = revoked_client } + + local policy = _M.new({ + whitelist = { { pem_certificate = CA }}, + revocation_check_type = "crl", + revoke_list = { { pem_certificate = crl }}}) + + policy:access() + assert.stub(ngx.exit).was_called_with(400) + assert.stub(ngx.say).was_called_with([[TLS certificate validation failed]]) + end) end) end) diff --git a/spec/resty/http_ng/backend/resty_spec.lua b/spec/resty/http_ng/backend/resty_spec.lua index 5cc2fd50f..9f4e5ff7c 100755 --- a/spec/resty/http_ng/backend/resty_spec.lua +++ b/spec/resty/http_ng/backend/resty_spec.lua @@ -37,10 +37,8 @@ describe('resty backend', function() local req = { method = method, url = 'http://0.0.0.0:0/' } local response, err = backend:send(req) - assert.falsy(err) - assert.truthy(response.error) - assert.falsy(response.ok) - assert.same(req, response.request) + assert.falsy(response) + assert.equal("connection refused", err) end) context('http proxy is set', function() diff --git a/spec/resty/http_ng_spec.lua b/spec/resty/http_ng_spec.lua index 280b0f48b..1fdcb8b85 100755 --- a/spec/resty/http_ng_spec.lua +++ b/spec/resty/http_ng_spec.lua @@ -224,18 +224,18 @@ describe('http_ng', function() end) describe('when there is error #network', function() - local response + local response, err before_each(function() http = http_ng.new{ backend = resty_backend } - response = http.get('http://127.0.0.1:1') + response, err = http.get('http://127.0.0.1:1') end) it('is not ok', function() - assert.equal(false, response.ok) + assert.falsy(response) end) it('has error', function() - assert.equal('string', type(response.error)) -- depending on the openresty version it can be "timeout" or "connection refused" + assert.equal("connection refused", err) end) end) diff --git a/t/apicast-policy-tls_validation.t b/t/apicast-policy-tls_validation.t index 15b2c66ab..c1f015536 100644 --- a/t/apicast-policy-tls_validation.t +++ b/t/apicast-policy-tls_validation.t @@ -8,6 +8,24 @@ env_to_apicast( 'APICAST_HTTPS_SESSION_REUSE' => 'on', ); +add_block_preprocessor(sub { + my $block = shift; + my $custom_config = $block->custom_config; + my $sites_d = $block->sites_d || ''; + + + if (defined $custom_config) { + + $sites_d .= <<_EOC_; + $custom_config +_EOC_ + + $block->set_value('sites_d', $sites_d) + } +}); + +$ENV{TEST_NGINX_HTML_DIR} ||= "$Test::Nginx::Util::ServRoot/html"; + run_tests(); __DATA__ @@ -353,3 +371,497 @@ No required TLS certificate was sent --- no_error_log [error] --- user_files fixture=CA/files.pl eval + + + +=== TEST 9: TLS Client Certificate is whitelisted but allow_partial_chain set to false +--- configuration eval +use JSON qw(to_json); +use File::Slurp qw(read_file); + +to_json({ + services => [{ + proxy => { + hosts => ['test'], + policy_chain => [ + { name => 'apicast.policy.tls_validation', + configuration => { + whitelist => [ + { pem_certificate => CORE::join('', read_file('t/fixtures/CA/client.crt')) } + ], + allow_partial_chain => JSON::false + } + }, + { name => 'apicast.policy.echo' }, + ] + } + }] +}); +--- test env +proxy_ssl_verify on; +proxy_ssl_trusted_certificate $TEST_NGINX_SERVER_ROOT/html/ca.crt; +proxy_ssl_certificate $TEST_NGINX_SERVER_ROOT/html/client.crt; +proxy_ssl_certificate_key $TEST_NGINX_SERVER_ROOT/html/client.key; +proxy_pass https://$server_addr:$apicast_port/t; +proxy_set_header Host test; +log_by_lua_block { collectgarbage() } +--- error_code: 400 +--- error_log +unable to get local issuer certificate +--- user_files fixture=CA/files.pl eval + + + +=== TEST 10: TLS Client Certificate with Certificate Revoke List (CRL) +--- configuration eval +use JSON qw(to_json); +use File::Slurp qw(read_file); + +to_json({ + services => [{ + proxy => { + hosts => ['test'], + policy_chain => [ + { name => 'apicast.policy.tls_validation', + configuration => { + whitelist => [ + { pem_certificate => CORE::join('', read_file('t/fixtures/CA/intermediate-ca.crt')) } + ], + revoke_list => [ + { pem_certificate => CORE::join('', read_file('t/fixtures/CA/crl.pem')) } + ], + revocation_check_type => 'crl' + } + }, + { name => 'apicast.policy.echo' }, + ] + } + }] +}); +--- test env +proxy_ssl_verify on; +proxy_ssl_trusted_certificate $TEST_NGINX_SERVER_ROOT/html/ca.crt; +proxy_ssl_certificate $TEST_NGINX_SERVER_ROOT/html/client.crt; +proxy_ssl_certificate_key $TEST_NGINX_SERVER_ROOT/html/client.key; +proxy_pass https://$server_addr:$apicast_port/t; +proxy_set_header Host test; +log_by_lua_block { collectgarbage() } +--- error_code: 200 +--- no_error_log +[error] +--- user_files fixture=CA/files.pl eval + + + +=== TEST 11: TLS Client Certificate with Certificate Revoke List (CRL) and +revoked certificate +--- configuration eval +use JSON qw(to_json); +use File::Slurp qw(read_file); + +to_json({ + services => [{ + proxy => { + hosts => ['test'], + policy_chain => [ + { name => 'apicast.policy.tls_validation', + configuration => { + whitelist => [ + { pem_certificate => CORE::join('', read_file('t/fixtures/CA/intermediate-ca.crt')) } + ], + revoke_list => [ + { pem_certificate => CORE::join('', read_file('t/fixtures/CA/crl.pem')) } + ], + revocation_check_type => 'crl' + } + }, + { name => 'apicast.policy.echo' }, + ] + } + }] +}); +--- test env +proxy_ssl_verify on; +proxy_ssl_trusted_certificate $TEST_NGINX_SERVER_ROOT/html/ca.crt; +proxy_ssl_certificate $TEST_NGINX_SERVER_ROOT/html/revoked_client.crt; +proxy_ssl_certificate_key $TEST_NGINX_SERVER_ROOT/html/revoked_client.key; +proxy_pass https://$server_addr:$apicast_port/t; +proxy_set_header Host test; +log_by_lua_block { collectgarbage() } +--- error_code: 400 +--- error_log +TLS certificate validation failed, err: certificate revoked +--- user_files fixture=CA/files.pl eval + + + +=== TEST 12: TLS Client Certificate with OCSP and cert without no responder URL +--- configuration eval +use JSON qw(to_json); +use File::Slurp qw(read_file); + +to_json({ + services => [{ + proxy => { + hosts => ['test'], + policy_chain => [ + { name => 'apicast.policy.tls_validation', + configuration => { + whitelist => [ + { pem_certificate => CORE::join('', read_file('t/fixtures/CA/intermediate-ca.crt')) } + ], + revocation_check_type => 'ocsp' + } + }, + { name => 'apicast.policy.echo' }, + ] + } + }] +}); +--- test env +proxy_ssl_verify on; +proxy_ssl_trusted_certificate $TEST_NGINX_SERVER_ROOT/html/ca.crt; +proxy_ssl_certificate $TEST_NGINX_SERVER_ROOT/html/client.crt; +proxy_ssl_certificate_key $TEST_NGINX_SERVER_ROOT/html/client.key; +proxy_pass https://$server_addr:$apicast_port/t; +proxy_set_header Host test; +log_by_lua_block { collectgarbage() } +--- error_code: 400 +--- error_log +TLS certificate validation failed, err: could not extract OCSP responder URL, the client certificate may be missing the required extensions +--- user_files fixture=CA/files.pl eval + + + +=== TEST 13: TLS Client Certificate with OCSP and cert with ocsp supported (no issuer) +--- env eval +( + 'APICAST_HTTPS_CERTIFICATE' => "$Test::Nginx::Util::ServRoot/html/server.pem", + 'APICAST_HTTPS_CERTIFICATE_KEY' => "$Test::Nginx::Util::ServRoot/html/server-key.pem", + 'APICAST_HTTPS_SESSION_REUSE' => 'on', +) +--- configuration eval +use JSON qw(to_json); +use File::Slurp qw(read_file); +to_json({ + services => [{ + proxy => { + hosts => ['test.com'], + policy_chain => [ + { name => 'apicast.policy.tls_validation', + configuration => { + whitelist => [ + { pem_certificate => CORE::join('', read_file('t/fixtures/ocsp/intermediate_ca.pem')) } + ], + revocation_check_type => 'ocsp' + } + }, + { name => 'apicast.policy.echo' }, + ] + } + }] +}); +--- test env +proxy_ssl_verify on; +proxy_ssl_trusted_certificate $TEST_NGINX_SERVER_ROOT/html/ca.pem; +proxy_ssl_certificate $TEST_NGINX_SERVER_ROOT/html/client.pem; +proxy_ssl_certificate_key $TEST_NGINX_SERVER_ROOT/html/client-key.pem; +proxy_pass https://$server_addr:$apicast_port/t; +proxy_set_header Host test.com; +log_by_lua_block { collectgarbage() } +--- error_code: 400 +--- error_log +no issuer certificate in chain +--- user_files fixture=ocsp/files.pl eval + + + +=== TEST 14: TLS Client Certificate with OCSP and cert with ocsp supported (issuer +cert not next to the leaf cert) +--- env eval +( + 'APICAST_HTTPS_CERTIFICATE' => "$Test::Nginx::Util::ServRoot/html/server.pem", + 'APICAST_HTTPS_CERTIFICATE_KEY' => "$Test::Nginx::Util::ServRoot/html/server-key.pem", + 'APICAST_HTTPS_SESSION_REUSE' => 'on', + 'APICAST_HTTPS_VERIFY_DEPTH' => 2 +) +--- configuration eval +use JSON qw(to_json); +use File::Slurp qw(read_file); +to_json({ + services => [{ + proxy => { + hosts => ['test'], + policy_chain => [ + { name => 'apicast.policy.tls_validation', + configuration => { + whitelist => [ + { pem_certificate => CORE::join('', read_file('t/fixtures/ocsp/intermediate_ca.pem')) } + ], + revocation_check_type => 'ocsp' + } + }, + { name => 'apicast.policy.echo' }, + ] + } + }] +}); +--- test env +proxy_ssl_verify on; +proxy_ssl_trusted_certificate $TEST_NGINX_SERVER_ROOT/html/ca.pem; +proxy_ssl_certificate $TEST_NGINX_SERVER_ROOT/html/wrong-issuer-order-chain.pem; +proxy_ssl_certificate_key $TEST_NGINX_SERVER_ROOT/html/client-key.pem; +proxy_pass https://$server_addr:$apicast_port/t; +proxy_set_header Host test; +log_by_lua_block { collectgarbage() } +--- error_code: 400 +--- error_log +issuer certificate not next to leaf +--- user_files fixture=ocsp/files.pl eval + + + +=== TEST 15: TLS Client Certificate with OCSP and unreachable OCSP responder URL +--- env eval +( + 'APICAST_HTTPS_CERTIFICATE' => "$Test::Nginx::Util::ServRoot/html/server.pem", + 'APICAST_HTTPS_CERTIFICATE_KEY' => "$Test::Nginx::Util::ServRoot/html/server-key.pem", + 'APICAST_HTTPS_SESSION_REUSE' => 'on', + 'APICAST_HTTPS_VERIFY_DEPTH' => 2 +) +--- configuration eval +use JSON qw(to_json); +use File::Slurp qw(read_file); +to_json({ + services => [{ + proxy => { + hosts => ['test'], + policy_chain => [ + { name => 'apicast.policy.tls_validation', + configuration => { + whitelist => [ + { pem_certificate => CORE::join('', read_file('t/fixtures/ocsp/intermediate_ca.pem')) } + ], + revocation_check_type => 'ocsp' + } + }, + { name => 'apicast.policy.echo' }, + ] + } + }] +}); +--- test env +proxy_ssl_verify on; +proxy_ssl_trusted_certificate $TEST_NGINX_SERVER_ROOT/html/ca.pem; +proxy_ssl_certificate $TEST_NGINX_SERVER_ROOT/html/chain.pem; +proxy_ssl_certificate_key $TEST_NGINX_SERVER_ROOT/html/client-key.pem; +proxy_pass https://$server_addr:$apicast_port/t; +proxy_set_header Host test; +log_by_lua_block { collectgarbage() } +--- error_code: 400 +--- error_log +ocsp-responder.test could not be resolved (3: Host not found) +--- user_files fixture=ocsp/files.pl eval + + + +=== TEST 15: TLS Client Certificate with OCSP and invalid OCSP respond +--- init eval +$Test::Nginx::Util::ENDPOINT_SSL_PORT = Test::APIcast::get_random_port(); +--- env eval +( + 'APICAST_HTTPS_CERTIFICATE' => "$Test::Nginx::Util::ServRoot/html/server.pem", + 'APICAST_HTTPS_CERTIFICATE_KEY' => "$Test::Nginx::Util::ServRoot/html/server-key.pem", + 'APICAST_HTTPS_SESSION_REUSE' => 'on', + 'APICAST_HTTPS_VERIFY_DEPTH' => 2 +) +--- configuration env eval +use JSON qw(to_json); +use File::Slurp qw(read_file); +to_json({ + services => [{ + proxy => { + hosts => ['test'], + policy_chain => [ + { name => 'apicast.policy.tls_validation', + configuration => { + whitelist => [ + { pem_certificate => CORE::join('', read_file('t/fixtures/ocsp/intermediate_ca.pem')) } + ], + revocation_check_type => 'ocsp', + ocsp_responder_url => "https://127.0.0.1:$Test::Nginx::Util::ENDPOINT_SSL_PORT/ocsp", + } + }, + { name => 'apicast.policy.echo' }, + ] + } + }] +}); +--- custom_config eval +< "$Test::Nginx::Util::ServRoot/html/server.pem", + 'APICAST_HTTPS_CERTIFICATE_KEY' => "$Test::Nginx::Util::ServRoot/html/server-key.pem", + 'APICAST_HTTPS_SESSION_REUSE' => 'on', + 'APICAST_HTTPS_VERIFY_DEPTH' => 2 +) +--- backend + location /ocsp { + content_by_lua_block { + } + } +--- configuration env eval +use JSON qw(to_json); +use File::Slurp qw(read_file); +to_json({ + services => [{ + proxy => { + hosts => ['test'], + policy_chain => [ + { name => 'apicast.policy.tls_validation', + configuration => { + whitelist => [ + { pem_certificate => CORE::join('', read_file('t/fixtures/ocsp/intermediate_ca.pem')) } + ], + revocation_check_type => 'ocsp', + ocsp_responder_url => "https://127.0.0.1:$Test::Nginx::Util::ENDPOINT_SSL_PORT/ocsp", + } + }, + { name => 'apicast.policy.echo' }, + ] + } + }] +}); +--- custom_config eval +< "$Test::Nginx::Util::ServRoot/html/server.pem", + 'APICAST_HTTPS_CERTIFICATE_KEY' => "$Test::Nginx::Util::ServRoot/html/server-key.pem", + 'APICAST_HTTPS_SESSION_REUSE' => 'on', + 'APICAST_HTTPS_VERIFY_DEPTH' => 2 +) +--- backend + location /ocsp { + content_by_lua_block { + } + } +--- configuration env eval +use JSON qw(to_json); +use File::Slurp qw(read_file); +to_json({ + services => [{ + proxy => { + hosts => ['test'], + policy_chain => [ + { name => 'apicast.policy.tls_validation', + configuration => { + whitelist => [ + { pem_certificate => CORE::join('', read_file('t/fixtures/ocsp/intermediate_ca.pem')) } + ], + revocation_check_type => 'ocsp', + ocsp_responder_url => "https://127.0.0.1:$Test::Nginx::Util::ENDPOINT_SSL_PORT/ocsp", + } + }, + { name => 'apicast.policy.echo' }, + ] + } + }] +}); +--- custom_config eval +< CORE::join('', read_file('t/fixtures/CA/client.key')) ], + [ "revoked_client.crt" => CORE::join('',read_file('t/fixtures/CA/revoked_client.crt')) ], + [ "revoked_client.key" => CORE::join('', read_file('t/fixtures/CA/revoked_client.key')) ], ] diff --git a/t/fixtures/CA/revoked_client.crt b/t/fixtures/CA/revoked_client.crt new file mode 100644 index 000000000..f58f87b8c --- /dev/null +++ b/t/fixtures/CA/revoked_client.crt @@ -0,0 +1,12 @@ +-----BEGIN CERTIFICATE----- +MIIBrzCCAVWgAwIBAgIQDMdcmy80L5ESidMVEKybXjAKBggqhkjOPQQDAjAaMRgw +FgYDVQQDEw9pbnRlcm1lZGlhdGUtY2EwHhcNMjQxMDMwMDU0NDIwWhcNMzQxMDI4 +MDU0NDIwWjARMQ8wDQYDVQQDEwZjbGllbnQwWTATBgcqhkjOPQIBBggqhkjOPQMB +BwNCAAQcDPD//JMA0j46aYVdsTh5Eb5KIfNhoJcHkhVRjMbhhsZGcMD+pysHvUlQ +7lwprlYOMSXgnPJUM7IUPq9eCMvso4GFMIGCMA4GA1UdDwEB/wQEAwIHgDAdBgNV +HSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwHQYDVR0OBBYEFNPTMaJOoyQXFMEz +6Cf7WfWFLlXxMB8GA1UdIwQYMBaAFNoSN4pwJIkS5RyfBSV121eEqExxMBEGA1Ud +EQQKMAiCBmNsaWVudDAKBggqhkjOPQQDAgNIADBFAiAmcpvUCOettopMTnaCoIaX +k3/Xw2GpM5OB90YWvbs69wIhAJhhK6+73p3yMu6MvTn4bSLL8eLAWrDcAuSX17vM +OAOb +-----END CERTIFICATE----- diff --git a/t/fixtures/CA/revoked_client.key b/t/fixtures/CA/revoked_client.key new file mode 100644 index 000000000..86eb16452 --- /dev/null +++ b/t/fixtures/CA/revoked_client.key @@ -0,0 +1,5 @@ +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEINyI8SLVOG+ufV0+tAzwhRT9/Xe19z//O0xci/SqZJCAoAoGCCqGSM49 +AwEHoUQDQgAEHAzw//yTANI+OmmFXbE4eRG+SiHzYaCXB5IVUYzG4YbGRnDA/qcr +B71JUO5cKa5WDjEl4JzyVDOyFD6vXgjL7A== +-----END EC PRIVATE KEY----- diff --git a/t/fixtures/ocsp/README.md b/t/fixtures/ocsp/README.md new file mode 100644 index 000000000..280278b1a --- /dev/null +++ b/t/fixtures/ocsp/README.md @@ -0,0 +1,58 @@ + +## Requirements +* cfssl - following steps require https://github.com/cloudflare/cfssl + +## Steps +Initiate CA by creating root certificate pair: + +``` +cfssl gencert -initca cfssl/ca_csr.json | cfssljson -bare ca +``` + +Continue with intermediate certificate pair for signing: + +``` +cfssl gencert -ca ca.pem -ca-key ca-key.pem -config=cfssl/cfssl_config.json -profile=intermediate cfssl/intermediate_ca_csr.json | cfssljson -bare intermediate_ca +``` + +Also create OCSP certificate pair to sign OCSP responses: + +``` +cfssl gencert -ca intermediate_ca.pem -ca-key intermediate_ca-key.pem -config=cfssl/cfssl_config.json -profile=ocsp cfssl/ocsp_csr.json | cfssljson -bare ocsp +``` + +Create a server certificate: + +``` +cfssl gencert -ca intermediate_ca.pem -ca-key intermediate_ca-key.pem -config cfssl/cfssl_config.json -profile server cfssl/leaf_csr.json | cfssljson -bare server +``` + +Create a client certificate: + +``` +cfssl gencert -ca intermediate_ca.pem -ca-key intermediate_ca-key.pem -config cfssl/cfssl_config.json -profile client cfssl/leaf_csr.json | cfssljson -bare client +``` + +Create an OCSP response for the certificate (NexUpdate in 10years): + +``` +cfssl ocspsign -ca intermediate_ca.pem -responder ocsp.pem -responder-key ocsp-key.pem -cert client.pem -status good -interval 87600h | cfssljson -bare ocsp-response-good +``` + +Bundle certificate to be installed at Nginx: + +``` +cat leaf.pem intermediate_ca.pem ca.pem > leaf-bundle.pem +``` + +Inspect OCSP response to see what is the Next Update: + +``` +openssl ocsp -text -no_cert_verify -respin t/cert/ocsp/cfssl/ocsp-response-good-response.der | grep "Next Update" +``` + +Create an OCSP response with revoked status for the certificate: + +``` +cfssl ocspsign -ca intermediate_ca.pem -responder ocsp.pem -responder-key ocsp-key.pem -cert client.pem -status revoked -reason 1 | cfssljson -bare ocsp-response-good +``` diff --git a/t/fixtures/ocsp/ca-key.pem b/t/fixtures/ocsp/ca-key.pem new file mode 100644 index 000000000..cdf00d3c2 --- /dev/null +++ b/t/fixtures/ocsp/ca-key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEogIBAAKCAQEAt2e0klGfWpwv2iCIlJU3Gq6T2e/d4KBph6k8PX8wyIlUWL6C +4xknOMAyUlOjUoqPdXBV9iepQioRFBonFAYtoy+WKN+V1HOkmVPSABG4FHoKKCwM +izTTC8teOJwa+oIHATcJbPIR005hFg32DwdpCqxIxVSRtP93rSXoqLM4AQQ+WFdW +hG6KfzjTMZ9D0CLzshUKRRKyQ7+gAf6ZrvirExZ7UT4rHyPUKnh1CGxrnUTdoXhU +UaBKod1MkiRlCBahT6MZhnl3gnK+VVEL0F2k56UOEbhsXnpPxVozwSTFjlcQveF8 +P4WGPI/9Q1f+pgnHBcq16OicoOVGKB4VkhO8KQIDAQABAoIBAH1/pCsfWSiaiY/8 +BRmPBVbnsNpHbY8glTW0UzlNiGcguavEKTIW6yTFN2noO3DmyYW16cx3lTVmLauQ +vb7Q/3eTv2+WlyL6Qt58Yc2UUl8Ip1yXz7mN2wBOF9oqz7ctNHfbXkLDXfk2v+5k +fUQJcRJRk7YbyVyOFylPMGYHxMHEKc4wyeF3krD+JvQIwRPf+p7kp0jWTe9//DOc +I5HilERUcdJoOeDqQLo/11ySJ5CxMBVPQbLJh6Fa5tiAzcVUWdaquPjZcH4HpON1 +wo0xDaNwURcM5RereKKsKQ2dD2ZRDMn9iX6G/pqMveRmThcQF86NUKyFm6v6s41W +DMdiAbUCgYEA4bzhZ/kaetmXck3gKp1HQA7s1w2E5K6sVA8H2OnsFo4Yog7FqP4H +y8jbIjVx7D1t/LFyhZgWLYTc3KV8QaNAv4X8XZ/S1J3t3k1/WLlzZHl2h5UAi3FI +Dh9O5N6Bxq8sBgMhI7YgQwp+NG8fI1UiKZhydcwiH1Od48CGMOpHc+sCgYEAz/4B +BqZmxGNPL+Los6PTDOiMcmngjMBdIIg6qTF5/UiKKIYTq7uCCQGiJ7pZT2OgJAEo +ZrtZCma8bKPEK+BD3KrCVj7ba9wKg0WNrSiaNopWKZnq6BN95Jwcyg9c0IiFa0oX +WlK3XLQ49DxrTlu+homxVMLbvE88GHYp8KtjzzsCgYBA7zhX1ExNsnHiK4ykNYHd +Z22xnu3val+f/oLfXsrO4ikr1Nv+9LQBZtHCUWVn83PEELdEvq8CgQmXXvMTXoat +kTk7JVJcXuGh5OERAKe060uxTKdPdVKo3VCwfWEPaixbvmK2BxnYrxgGtUBbxY2C +MZwbTpEyObddYHA5eer76QKBgDXMxgcqU7rI1VrVnsuYvKbCIFIYAPVnbK9VjZbm +LV/Ou63vwHbTcbdSrNcJ5MAcTPgDNKgeHdIK8QJI+h0/TU5u/QXCDI/BwxZhj1wS +/JDPB6qLHbAaGp5fozLA9okaRyiRaaj7bGKWW4URe9Aw+v9h7nS2UpBLDohlSEPw +kUixAoGAAiLrCo9BZeCTTVZcDLrIh7H+ptUTI4LttzaPEI57LbkPLH1w5PN4ZE2R +CeMU5pgMMTFlmBttbhx5EvT5SFGva9i43JwfkTfjclq9OKr2xpuWO5Jl7aFHUyCs +R0E2U2ZbznMO/fnH+JdifchH/Ge/O5gyDe1DxWzNaAbQ9Ci+zq0= +-----END RSA PRIVATE KEY----- diff --git a/t/fixtures/ocsp/ca.csr b/t/fixtures/ocsp/ca.csr new file mode 100644 index 000000000..a0f11263e --- /dev/null +++ b/t/fixtures/ocsp/ca.csr @@ -0,0 +1,17 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIICvTCCAaUCAQAweDELMAkGA1UEBhMCQ0ExEDAOBgNVBAgTB09udGFyaW8xDzAN +BgNVBAcTBk90dGF3YTESMBAGA1UEChMJTHVhIE5naW54MRgwFgYDVQQLEw9BUElj +YXN0IFJvb3QgQ0ExGDAWBgNVBAMTD0FQSWNhc3QgUm9vdCBDQTCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBALdntJJRn1qcL9ogiJSVNxquk9nv3eCgaYep +PD1/MMiJVFi+guMZJzjAMlJTo1KKj3VwVfYnqUIqERQaJxQGLaMvlijfldRzpJlT +0gARuBR6CigsDIs00wvLXjicGvqCBwE3CWzyEdNOYRYN9g8HaQqsSMVUkbT/d60l +6KizOAEEPlhXVoRuin840zGfQ9Ai87IVCkUSskO/oAH+ma74qxMWe1E+Kx8j1Cp4 +dQhsa51E3aF4VFGgSqHdTJIkZQgWoU+jGYZ5d4JyvlVRC9BdpOelDhG4bF56T8Va +M8EkxY5XEL3hfD+FhjyP/UNX/qYJxwXKtejonKDlRigeFZITvCkCAwEAAaAAMA0G +CSqGSIb3DQEBCwUAA4IBAQAXv+NudAib4JeSu5d8bM0p84HC4iarRTv1UYMULBE9 +eQRt04khs4wjtHoki0EkyE9M027W8x7otTdLsNSCh7QP4UxiZH3z/jF/Pa6WdKZy +qDtLVJ/i1fpMba0Jct8HwJo1uO0boexakR7OkgxfAn4RKZ/IR9PzsoQ10WMHbXGz +5PYWAZEGUSt4zkhqaSwYaA6oZ6HvJzo+QtkyIDnlfV6FX9v7jgGP/KadBkYbtVuj +xBgE88dNUVsBsxFxDms03SiSqtPc7YSEZO3koKC4ziZ8QUKMHRlnsvILf1nSYr6+ +osOP1tycj9Pd1WyOkhORssBZOGBMrTeCdaCHJ19Rkw5v +-----END CERTIFICATE REQUEST----- diff --git a/t/fixtures/ocsp/ca.pem b/t/fixtures/ocsp/ca.pem new file mode 100644 index 000000000..c980d667c --- /dev/null +++ b/t/fixtures/ocsp/ca.pem @@ -0,0 +1,23 @@ +-----BEGIN CERTIFICATE----- +MIIDwDCCAqigAwIBAgIUcSXJIwYu13xp3Iewm41m+UYc7zIwDQYJKoZIhvcNAQEL +BQAweDELMAkGA1UEBhMCQ0ExEDAOBgNVBAgTB09udGFyaW8xDzANBgNVBAcTBk90 +dGF3YTESMBAGA1UEChMJTHVhIE5naW54MRgwFgYDVQQLEw9BUEljYXN0IFJvb3Qg +Q0ExGDAWBgNVBAMTD0FQSWNhc3QgUm9vdCBDQTAeFw0yNTAyMDQwNTI1MDBaFw0z +MDAyMDMwNTI1MDBaMHgxCzAJBgNVBAYTAkNBMRAwDgYDVQQIEwdPbnRhcmlvMQ8w +DQYDVQQHEwZPdHRhd2ExEjAQBgNVBAoTCUx1YSBOZ2lueDEYMBYGA1UECxMPQVBJ +Y2FzdCBSb290IENBMRgwFgYDVQQDEw9BUEljYXN0IFJvb3QgQ0EwggEiMA0GCSqG +SIb3DQEBAQUAA4IBDwAwggEKAoIBAQC3Z7SSUZ9anC/aIIiUlTcarpPZ793goGmH +qTw9fzDIiVRYvoLjGSc4wDJSU6NSio91cFX2J6lCKhEUGicUBi2jL5Yo35XUc6SZ +U9IAEbgUegooLAyLNNMLy144nBr6ggcBNwls8hHTTmEWDfYPB2kKrEjFVJG0/3et +JeioszgBBD5YV1aEbop/ONMxn0PQIvOyFQpFErJDv6AB/pmu+KsTFntRPisfI9Qq +eHUIbGudRN2heFRRoEqh3UySJGUIFqFPoxmGeXeCcr5VUQvQXaTnpQ4RuGxeek/F +WjPBJMWOVxC94Xw/hYY8j/1DV/6mCccFyrXo6Jyg5UYoHhWSE7wpAgMBAAGjQjBA +MA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBQaaSka +5maUzsFM/Vnn+cUUp54uSTANBgkqhkiG9w0BAQsFAAOCAQEAIhIQpkC8EVxA6Lhm +uDutU9LGKQjp0PrzJLWCCcDCnxQ8cbaH2CUr2mw0et/cBM8R5TR35JMZe6MOGSbt +lFfWKfLE+QzNPaLhQkOI21YZMqY1kcGNmsc2UyHxhPo6PZ+J1IF/9N/P7+BjDQeN +yCd+dwXpUZlRZRyEVVXNl2yKUKLynViiNpa9rRb/mT5pqD/b523/Icva0mi6xyJZ +UbaYQBE4IozQ2YEChP3EpfUjJepZCeHWbCEzKgC61H21uSK62K33pPPN3+zKKJrk +eu2xwIugYpLwf3dvFGdW47vfUvxZdYltRkrAASDOPTpaU5dHwfR8MsoGy2h2A2jz +qOUrUg== +-----END CERTIFICATE----- diff --git a/t/fixtures/ocsp/cfssl/ca_csr.json b/t/fixtures/ocsp/cfssl/ca_csr.json new file mode 100644 index 000000000..eaefaafcc --- /dev/null +++ b/t/fixtures/ocsp/cfssl/ca_csr.json @@ -0,0 +1,16 @@ +{ + "CN": "APIcast Root CA", + "key": { + "algo": "rsa", + "size": 2048 + }, + "names": [ + { + "C": "CA", + "L": "Ottawa", + "O": "Lua Nginx", + "OU": "APIcast Root CA", + "ST": "Ontario" + } + ] +} diff --git a/t/fixtures/ocsp/cfssl/cfssl_config.json b/t/fixtures/ocsp/cfssl/cfssl_config.json new file mode 100644 index 000000000..cbdfe1c15 --- /dev/null +++ b/t/fixtures/ocsp/cfssl/cfssl_config.json @@ -0,0 +1,32 @@ +{ + "signing": { + "default": { + "ocsp_url": "https://ocsp-responder.test", + "expiry": "2190000h", + "usages": [ + "signing", + "key encipherment", + "client auth" + ] + }, + "profiles": { + "ocsp": { + "usages": ["digital signature", "ocsp signing"], + "expiry": "876000h" + }, + "intermediate": { + "usages": ["cert sign", "crl sign"], + "expiry": "2190000h", + "ca_constraint": {"is_ca": true} + }, + "server": { + "usages": ["signing", "key encipherment", "server auth"], + "expiry": "876000h" + }, + "client": { + "usages": ["signing", "key encipherment", "client auth"], + "expiry": "876000h" + } + } + } +} diff --git a/t/fixtures/ocsp/cfssl/intermediate_ca_csr.json b/t/fixtures/ocsp/cfssl/intermediate_ca_csr.json new file mode 100644 index 000000000..a6288d58c --- /dev/null +++ b/t/fixtures/ocsp/cfssl/intermediate_ca_csr.json @@ -0,0 +1,16 @@ +{ + "CN": "APIcast Intermediate CA", + "key": { + "algo": "rsa", + "size": 2048 + }, + "names": [ + { + "C": "CA", + "L": "Ottawa", + "O": "Lua Nginx", + "OU": "APIcast Intermediate CA", + "ST": "Ontario" + } + ] +} diff --git a/t/fixtures/ocsp/cfssl/leaf_csr.json b/t/fixtures/ocsp/cfssl/leaf_csr.json new file mode 100644 index 000000000..77e6b396c --- /dev/null +++ b/t/fixtures/ocsp/cfssl/leaf_csr.json @@ -0,0 +1,20 @@ +{ + "CN": "test.com", + "hosts": [ + "localhost", + "test" + ], + "key": { + "algo": "rsa", + "size": 2048 + }, + "names": [ + { + "C": "US", + "L": "San Francisco", + "O": "Customer", + "OU": "Website", + "ST": "California" + } + ] +} diff --git a/t/fixtures/ocsp/cfssl/ocsp_csr.json b/t/fixtures/ocsp/cfssl/ocsp_csr.json new file mode 100644 index 000000000..572acef4d --- /dev/null +++ b/t/fixtures/ocsp/cfssl/ocsp_csr.json @@ -0,0 +1,16 @@ +{ + "CN": "APIcast OCSP Responder", + "key": { + "algo": "rsa", + "size": 2048 + }, + "names": [ + { + "C": "CA", + "L": "Ottawa", + "O": "Lua Nginx", + "OU": "APIcast OCSP Responder", + "ST": "Ontario" + } + ] +} diff --git a/t/fixtures/ocsp/chain.pem b/t/fixtures/ocsp/chain.pem new file mode 100644 index 000000000..34d78d166 --- /dev/null +++ b/t/fixtures/ocsp/chain.pem @@ -0,0 +1,74 @@ +-----BEGIN CERTIFICATE----- +MIIEVzCCAz+gAwIBAgIUTKcAbc6mgr6a9FcHhywQ6lrsoBkwDQYJKoZIhvcNAQEL +BQAwgYgxCzAJBgNVBAYTAkNBMRAwDgYDVQQIEwdPbnRhcmlvMQ8wDQYDVQQHEwZP +dHRhd2ExEjAQBgNVBAoTCUx1YSBOZ2lueDEgMB4GA1UECxMXQVBJY2FzdCBJbnRl +cm1lZGlhdGUgQ0ExIDAeBgNVBAMTF0FQSWNhc3QgSW50ZXJtZWRpYXRlIENBMCAX +DTI1MDIwNDA4MDAwMFoYDzIxMjUwMTExMDgwMDAwWjByMQswCQYDVQQGEwJVUzET +MBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzERMA8G +A1UEChMIQ3VzdG9tZXIxEDAOBgNVBAsTB1dlYnNpdGUxETAPBgNVBAMTCHRlc3Qu +Y29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv+EK5duP98xw5Fmj +WwnC5xOdz6AnqwaxkWcfBOtCX7W2tuN7gOF3L7NXtJ5Tnyr9uCYhhL4zqRF6j6rp ++yP/jIR4ZN1UHmq+ScHG7//8NCFCu6R9h3YkkDRh5OLSdksGzIIeBRkqiyUOiJaH +vciXFOX/pcjDSQCVqeTFTzOaOmHNT4A9dC4zCNjR1Zn02LqK0IxylFp6MzXCt+lW +cGJvLniSo1KUOW6JPj1TVrgUQygns0ijb1nok5jbsCSHQW9lRK16JrCqVangABvg +V2WAoieB1RPLkCIj1ZJneHSZKsBN9HcF3x0AMoOOTHkpmpv1eqbkVXLbKWU6i305 +4Jn8lwIDAQABo4HLMIHIMA4GA1UdDwEB/wQEAwIFoDATBgNVHSUEDDAKBggrBgEF +BQcDAjAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBR1FdZ2snwxIUD+KrVkBO9pZ9Ib +iTAfBgNVHSMEGDAWgBTYX0fMoRXzpdBMwUvIwgfO2UunvTA3BggrBgEFBQcBAQQr +MCkwJwYIKwYBBQUHMAGGG2h0dHBzOi8vb2NzcC1yZXNwb25kZXIudGVzdDAaBgNV +HREEEzARgglsb2NhbGhvc3SCBHRlc3QwDQYJKoZIhvcNAQELBQADggEBAB5talFl +dl0faUMOCAq7np0BHYCXm/txxqfIuIKetkFNortrpMYxsktkaAcFmEQV5+O6kVyC +Frxui/ogZt1d2uG/jCy8eAhKkdO2/Y3siYenT8wAS/Z3iFiBRb5KfIPcTIZp3CFj +f3y9ND6HWtMSXqNaPRBqX3hWrWIkEIer7YeSjBeceaJhrddfMyW1Wo2cOPHvz6eA +53Swz2yjYkaaU2UMBIb3xxGl4q4a8HqNyDqeI7pzobBxmhroAFS3dD0t8JpycmzM +lDvTDoUu/vtp194CcxJnGJ0kAWNemfAEriIqh6koBeXslUqFbxhXJhwYwyheArp/ +yk9pbkJR+3rrWrk= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIELzCCAxegAwIBAgIUfUh/NyK/i7Zpk5xEAE/Hycg8oGMwDQYJKoZIhvcNAQEL +BQAweDELMAkGA1UEBhMCQ0ExEDAOBgNVBAgTB09udGFyaW8xDzANBgNVBAcTBk90 +dGF3YTESMBAGA1UEChMJTHVhIE5naW54MRgwFgYDVQQLEw9BUEljYXN0IFJvb3Qg +Q0ExGDAWBgNVBAMTD0FQSWNhc3QgUm9vdCBDQTAgFw0yNTAyMDQwNTI2MDBaGA8y +Mjc0MTIwNjA1MjYwMFowgYgxCzAJBgNVBAYTAkNBMRAwDgYDVQQIEwdPbnRhcmlv +MQ8wDQYDVQQHEwZPdHRhd2ExEjAQBgNVBAoTCUx1YSBOZ2lueDEgMB4GA1UECxMX +QVBJY2FzdCBJbnRlcm1lZGlhdGUgQ0ExIDAeBgNVBAMTF0FQSWNhc3QgSW50ZXJt +ZWRpYXRlIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzdmEqwQL +fSnEfXUmMO9TMsY2y7pPr++n4vt03wuo0ZsJLWW7LZ7irtWOHwxnWeu0tfc5UmoU +bjwfxltxn+lw1I+Z+Q5pg/uSe8IwyoA051TCu7MqljPNt93pX97m6wLJnOlGbaIR +S6r8uBuYIm9//f+jZBI+7gL3CRpkRHgRn6QsYqAOyn1s8DYT6O3cGJ+ldVb75KdD +A11leT4Pxdap+iGY7rKu5F+K60QhUgStwiV8jK0f9dpx/cm1eutzC2c5WlqmQ15f +Qfq3rQOGoiVLt1USqzvELdaWff2RkULDeS63Vn4JMaY4dhRkyMNSwmx7ZixDpsx2 +sV3pqHbdAkP2QwIDAQABo4GdMIGaMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E +BTADAQH/MB0GA1UdDgQWBBTYX0fMoRXzpdBMwUvIwgfO2UunvTAfBgNVHSMEGDAW +gBQaaSka5maUzsFM/Vnn+cUUp54uSTA3BggrBgEFBQcBAQQrMCkwJwYIKwYBBQUH +MAGGG2h0dHBzOi8vb2NzcC1yZXNwb25kZXIudGVzdDANBgkqhkiG9w0BAQsFAAOC +AQEAs/V67Aah67xA0dRXMChK+IE6y3bTjDDo3MndJAnImCVjtbyJJyX4udBfDOKj +sCslF/bFWmLgb1w5ek0kwEOAPc5lDteQ/lPRIW7o9EnIyZico1qnR/bXG5XzQ/UZ +G2UYvHuwPqY2NEsbbPP2yxqaoIL1vhNwm3/Ga5KriiP0Zd3KgIvpfbZ4OcyJBWtm +9P1qsBDpNNkBiNm7i/D9vPDC4skvHsmm2lOBF3CNQ1+WcZRAf5oL9IfptOru79+N +qfOjWbnIMugxez+7TiFGlE81RyKocyflFMwIcGeeQD0KFD9XXnaVPQEovFIspcto +SXPTXb7wJL19OSGBOMBEJ6oS5Q== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDwDCCAqigAwIBAgIUcSXJIwYu13xp3Iewm41m+UYc7zIwDQYJKoZIhvcNAQEL +BQAweDELMAkGA1UEBhMCQ0ExEDAOBgNVBAgTB09udGFyaW8xDzANBgNVBAcTBk90 +dGF3YTESMBAGA1UEChMJTHVhIE5naW54MRgwFgYDVQQLEw9BUEljYXN0IFJvb3Qg +Q0ExGDAWBgNVBAMTD0FQSWNhc3QgUm9vdCBDQTAeFw0yNTAyMDQwNTI1MDBaFw0z +MDAyMDMwNTI1MDBaMHgxCzAJBgNVBAYTAkNBMRAwDgYDVQQIEwdPbnRhcmlvMQ8w +DQYDVQQHEwZPdHRhd2ExEjAQBgNVBAoTCUx1YSBOZ2lueDEYMBYGA1UECxMPQVBJ +Y2FzdCBSb290IENBMRgwFgYDVQQDEw9BUEljYXN0IFJvb3QgQ0EwggEiMA0GCSqG +SIb3DQEBAQUAA4IBDwAwggEKAoIBAQC3Z7SSUZ9anC/aIIiUlTcarpPZ793goGmH +qTw9fzDIiVRYvoLjGSc4wDJSU6NSio91cFX2J6lCKhEUGicUBi2jL5Yo35XUc6SZ +U9IAEbgUegooLAyLNNMLy144nBr6ggcBNwls8hHTTmEWDfYPB2kKrEjFVJG0/3et +JeioszgBBD5YV1aEbop/ONMxn0PQIvOyFQpFErJDv6AB/pmu+KsTFntRPisfI9Qq +eHUIbGudRN2heFRRoEqh3UySJGUIFqFPoxmGeXeCcr5VUQvQXaTnpQ4RuGxeek/F +WjPBJMWOVxC94Xw/hYY8j/1DV/6mCccFyrXo6Jyg5UYoHhWSE7wpAgMBAAGjQjBA +MA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBQaaSka +5maUzsFM/Vnn+cUUp54uSTANBgkqhkiG9w0BAQsFAAOCAQEAIhIQpkC8EVxA6Lhm +uDutU9LGKQjp0PrzJLWCCcDCnxQ8cbaH2CUr2mw0et/cBM8R5TR35JMZe6MOGSbt +lFfWKfLE+QzNPaLhQkOI21YZMqY1kcGNmsc2UyHxhPo6PZ+J1IF/9N/P7+BjDQeN +yCd+dwXpUZlRZRyEVVXNl2yKUKLynViiNpa9rRb/mT5pqD/b523/Icva0mi6xyJZ +UbaYQBE4IozQ2YEChP3EpfUjJepZCeHWbCEzKgC61H21uSK62K33pPPN3+zKKJrk +eu2xwIugYpLwf3dvFGdW47vfUvxZdYltRkrAASDOPTpaU5dHwfR8MsoGy2h2A2jz +qOUrUg== +-----END CERTIFICATE----- diff --git a/t/fixtures/ocsp/client-key.pem b/t/fixtures/ocsp/client-key.pem new file mode 100644 index 000000000..6ea4407e1 --- /dev/null +++ b/t/fixtures/ocsp/client-key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEAv+EK5duP98xw5FmjWwnC5xOdz6AnqwaxkWcfBOtCX7W2tuN7 +gOF3L7NXtJ5Tnyr9uCYhhL4zqRF6j6rp+yP/jIR4ZN1UHmq+ScHG7//8NCFCu6R9 +h3YkkDRh5OLSdksGzIIeBRkqiyUOiJaHvciXFOX/pcjDSQCVqeTFTzOaOmHNT4A9 +dC4zCNjR1Zn02LqK0IxylFp6MzXCt+lWcGJvLniSo1KUOW6JPj1TVrgUQygns0ij +b1nok5jbsCSHQW9lRK16JrCqVangABvgV2WAoieB1RPLkCIj1ZJneHSZKsBN9HcF +3x0AMoOOTHkpmpv1eqbkVXLbKWU6i3054Jn8lwIDAQABAoIBADWzoD8wshxiRX5D +cCq8kqXloZdIdZGyL+RH/jB8P3lV/Cs3g4tQjvD0uqk8Xp7/gz8UvPDP4tmAoNKw +vQeizZTgRmnEYBSbP2KZLzpgZI+ad3jY0qEk+Zq6bmOG7+xXlzGJgSlgH74NwwGL +T7ZX+6DHtkMJ6031Me34rxg5kwKffKPymjAG440UVQiOXeIOAp8WlZVjFfwZIpnr +2QLosS2FdEilNYMcY4U++MrqxzkKjoiQ0b09fPlzWNo7StIGchlfdYM9mZaIc//1 +2dAr9XyYWGHlr20AawSiKkzQtvRpYN91kE/gt494k+6CV6Ck7w2WEhHzzb53yW2i +jzwvuYECgYEA4xz/mUf+sTYWq1u/o1O4kREK5H15tdbhxmnyiuKESnzp3Ylr5+g0 +zLKdIrytKKf02cbcJzguS9wC2lteqC1wvk11OcJPXxN9Gvik4guRWg0ecDu9U8xh +yclxkdYoYN+J2YjuUTOo0YUwkLu0vTaFX0bImgOfqf+dxsCGMjFlCfcCgYEA2EjJ +26gxWveicDZrt3vad7ykWsF6v/YswauU4y/UUP2AuaZYB6zz29eZ2lIkWR2eOKMo +icDFBmMAdxtEli0SYr8I7MBz/B7HfWx86g7lPSgsQTeNxmq8Tc5r8DHKMwe9X5zE +sj+/OSRnWSLr6392z48MRQQAlaZsCQBrq7ma+mECgYAXRviXgD6FcTK/m2a32bPY +AnQoWQfpcD2xtVgrje3bKJRbpWMO4MjQlhnu3oGs4hIBZBVaW7K7CbCtKqI4AHhG +uO+j3Nt/tiKjagqUNHVQUnnlLOpJtW/sW54tQVLgIukhB5zNa8sItmr02pg6sGTZ +EAstZeOua8mC/maCrHdbnwKBgGWc3OlL/dQlH7Xke3r6v0sd34GcANWLDL/4oryR +zgg28XFHS3hfszoH8wp1KQqNNbaaQQNnA6nafW936iM8DbVC1yiTymoa89JjU9SL +JvwykYgaV4tuvgU4A9IXMk4DRt9Swb6U4HwyNDPWikxb2C/vnu4V0Uh9pagdAHjv +fHZBAoGBAJkJ2LTZiSb6Li5SvznVTSkVZbT9xClXy3B6tHq/0TUfl5yzwTNfgTUZ +hn8Bs7smgLbU/VQZpPcpk7c8kzgcpimGk+q2lpWdvsBtdaat708zzFmfjFj13BKA +d/qyWACDg4yEOYEFc9Fy7agJIfz6aB430EBVlHuB4C32IjCnoQrK +-----END RSA PRIVATE KEY----- diff --git a/t/fixtures/ocsp/client.csr b/t/fixtures/ocsp/client.csr new file mode 100644 index 000000000..fe557063f --- /dev/null +++ b/t/fixtures/ocsp/client.csr @@ -0,0 +1,18 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIC5DCCAcwCAQAwcjELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWEx +FjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xETAPBgNVBAoTCEN1c3RvbWVyMRAwDgYD +VQQLEwdXZWJzaXRlMREwDwYDVQQDEwh0ZXN0LmNvbTCCASIwDQYJKoZIhvcNAQEB +BQADggEPADCCAQoCggEBAL/hCuXbj/fMcORZo1sJwucTnc+gJ6sGsZFnHwTrQl+1 +trbje4Dhdy+zV7SeU58q/bgmIYS+M6kReo+q6fsj/4yEeGTdVB5qvknBxu///DQh +QrukfYd2JJA0YeTi0nZLBsyCHgUZKoslDoiWh73IlxTl/6XIw0kAlankxU8zmjph +zU+APXQuMwjY0dWZ9Ni6itCMcpRaejM1wrfpVnBiby54kqNSlDluiT49U1a4FEMo +J7NIo29Z6JOY27Akh0FvZUSteiawqlWp4AAb4FdlgKIngdUTy5AiI9WSZ3h0mSrA +TfR3Bd8dADKDjkx5KZqb9Xqm5FVy2yllOot9OeCZ/JcCAwEAAaAtMCsGCSqGSIb3 +DQEJDjEeMBwwGgYDVR0RBBMwEYIJbG9jYWxob3N0ggR0ZXN0MA0GCSqGSIb3DQEB +CwUAA4IBAQADIG7CyC6epszpaxeCaqS4s+hF15/1WCekSek43gyoXQ8/8isoflK5 +IX3aVMK9fDwlamCPkOYprcQaPTfcTWdjmxOlCK4gIzV35JzcnhdV9jfGOsSQ3Ced +dXeGdazFI0kCJ15bo8vs6X+U4nAWvUJVq/HGqc2PG4HWOSCUXqKsksnbrXYtOZdC +pkagIiLKOoUplRz1PNyrbe5T0BYxYcRjhPoI4zbC3Xg3Woun6eWMcokFMXD2PnFT +iLqkRI21gJvdrn3VWXG6Brm2GoWUCx8KrCU+JPdVMBetnei78bfTHa/emtRNEFZB +PtEw25RkjzwLPc4AJAagH9l4jzYJZRK9 +-----END CERTIFICATE REQUEST----- diff --git a/t/fixtures/ocsp/client.pem b/t/fixtures/ocsp/client.pem new file mode 100644 index 000000000..f2f116007 --- /dev/null +++ b/t/fixtures/ocsp/client.pem @@ -0,0 +1,26 @@ +-----BEGIN CERTIFICATE----- +MIIEVzCCAz+gAwIBAgIUTKcAbc6mgr6a9FcHhywQ6lrsoBkwDQYJKoZIhvcNAQEL +BQAwgYgxCzAJBgNVBAYTAkNBMRAwDgYDVQQIEwdPbnRhcmlvMQ8wDQYDVQQHEwZP +dHRhd2ExEjAQBgNVBAoTCUx1YSBOZ2lueDEgMB4GA1UECxMXQVBJY2FzdCBJbnRl +cm1lZGlhdGUgQ0ExIDAeBgNVBAMTF0FQSWNhc3QgSW50ZXJtZWRpYXRlIENBMCAX +DTI1MDIwNDA4MDAwMFoYDzIxMjUwMTExMDgwMDAwWjByMQswCQYDVQQGEwJVUzET +MBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzERMA8G +A1UEChMIQ3VzdG9tZXIxEDAOBgNVBAsTB1dlYnNpdGUxETAPBgNVBAMTCHRlc3Qu +Y29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv+EK5duP98xw5Fmj +WwnC5xOdz6AnqwaxkWcfBOtCX7W2tuN7gOF3L7NXtJ5Tnyr9uCYhhL4zqRF6j6rp ++yP/jIR4ZN1UHmq+ScHG7//8NCFCu6R9h3YkkDRh5OLSdksGzIIeBRkqiyUOiJaH +vciXFOX/pcjDSQCVqeTFTzOaOmHNT4A9dC4zCNjR1Zn02LqK0IxylFp6MzXCt+lW +cGJvLniSo1KUOW6JPj1TVrgUQygns0ijb1nok5jbsCSHQW9lRK16JrCqVangABvg +V2WAoieB1RPLkCIj1ZJneHSZKsBN9HcF3x0AMoOOTHkpmpv1eqbkVXLbKWU6i305 +4Jn8lwIDAQABo4HLMIHIMA4GA1UdDwEB/wQEAwIFoDATBgNVHSUEDDAKBggrBgEF +BQcDAjAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBR1FdZ2snwxIUD+KrVkBO9pZ9Ib +iTAfBgNVHSMEGDAWgBTYX0fMoRXzpdBMwUvIwgfO2UunvTA3BggrBgEFBQcBAQQr +MCkwJwYIKwYBBQUHMAGGG2h0dHBzOi8vb2NzcC1yZXNwb25kZXIudGVzdDAaBgNV +HREEEzARgglsb2NhbGhvc3SCBHRlc3QwDQYJKoZIhvcNAQELBQADggEBAB5talFl +dl0faUMOCAq7np0BHYCXm/txxqfIuIKetkFNortrpMYxsktkaAcFmEQV5+O6kVyC +Frxui/ogZt1d2uG/jCy8eAhKkdO2/Y3siYenT8wAS/Z3iFiBRb5KfIPcTIZp3CFj +f3y9ND6HWtMSXqNaPRBqX3hWrWIkEIer7YeSjBeceaJhrddfMyW1Wo2cOPHvz6eA +53Swz2yjYkaaU2UMBIb3xxGl4q4a8HqNyDqeI7pzobBxmhroAFS3dD0t8JpycmzM +lDvTDoUu/vtp194CcxJnGJ0kAWNemfAEriIqh6koBeXslUqFbxhXJhwYwyheArp/ +yk9pbkJR+3rrWrk= +-----END CERTIFICATE----- diff --git a/t/fixtures/ocsp/files.pl b/t/fixtures/ocsp/files.pl new file mode 100644 index 000000000..39892b791 --- /dev/null +++ b/t/fixtures/ocsp/files.pl @@ -0,0 +1,15 @@ +use File::Slurp qw(read_file); + +[ + [ "ca.pem" => CORE::join('', + read_file('t/fixtures/ocsp/intermediate_ca.pem'), + read_file('t/fixtures/ocsp/ca.pem'), + ) ], + [ "intermediate_ca.pem" => CORE::join('', read_file('t/fixtures/ocsp/intermediate_ca.pem')) ], + [ "server.pem" => CORE::join('', read_file('t/fixtures/ocsp/server.pem')) ], + [ "server-key.pem" => CORE::join('', read_file('t/fixtures/ocsp/server-key.pem')) ], + [ "client.pem" => CORE::join('', read_file('t/fixtures/ocsp/client.pem')) ], + [ "client-key.pem" => CORE::join('', read_file('t/fixtures/ocsp/client-key.pem')) ], + [ "chain.pem" => CORE::join('', read_file('t/fixtures/ocsp/chain.pem')) ], + [ "wrong-issuer-order-chain.pem" => CORE::join('', read_file('t/fixtures/ocsp/wrong-issuer-order-chain.pem')) ], +] diff --git a/t/fixtures/ocsp/intermediate_ca-key.pem b/t/fixtures/ocsp/intermediate_ca-key.pem new file mode 100644 index 000000000..c2311d5b3 --- /dev/null +++ b/t/fixtures/ocsp/intermediate_ca-key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpQIBAAKCAQEAzdmEqwQLfSnEfXUmMO9TMsY2y7pPr++n4vt03wuo0ZsJLWW7 +LZ7irtWOHwxnWeu0tfc5UmoUbjwfxltxn+lw1I+Z+Q5pg/uSe8IwyoA051TCu7Mq +ljPNt93pX97m6wLJnOlGbaIRS6r8uBuYIm9//f+jZBI+7gL3CRpkRHgRn6QsYqAO +yn1s8DYT6O3cGJ+ldVb75KdDA11leT4Pxdap+iGY7rKu5F+K60QhUgStwiV8jK0f +9dpx/cm1eutzC2c5WlqmQ15fQfq3rQOGoiVLt1USqzvELdaWff2RkULDeS63Vn4J +MaY4dhRkyMNSwmx7ZixDpsx2sV3pqHbdAkP2QwIDAQABAoIBAQDBBZ9mcROI2Pp7 +nbcjGbcNHFpTbK++TN5DdADiCV/StCrF2+fJXnw27t8mdA4RfnjkTB7/DaN8vnoZ +GLQR++amGsWJiZ8deG+iBrSTneZ9qLg1I0rir07Og5KLKEulwOZmcUNuGBNZvcrd +pFpip+T/uo9ujcFek38rlQjCP0hfRPcmtDmG8OjhaLYuDM4KZhqMSgRzm0uc5oUT +i4WH2MdPUwy4+1VnCykw6JdoMtSfXWG7EF9FU0GqABb7LKSJY11rGyMMxiHhxz9W +J77wikJ3UVFYVzLvlt0Zf3Y+JXZhoRm8YF42/JIUVZ+wj3YKytRKVC1F9Yr9N3Zj +WaLcjWp5AoGBAOPPxTrhC5nxAGogoak3eyh5Qxz9ovf8R1vqs7cQyLC0Kg7kNI5j +8YeihZ9Frrar+pmXek/IC6JEwLhbC+LR+KH3sQ0wpp6R6ZL/8wDBKHJ6vHDVx+Qm +x5WwEQIgZxj2xHA7tFfKG8zST/R7qN7vyi6T6vWDpibQ20Z88uGUEDdlAoGBAOdS +E0Tf8vB1zpuJUtN9jw/NTlWcuJZcZYqbv2Svvv+Ec8VlHFvJnbbZnDn37kigecpQ +uXqpKbNYKjtX9GS80j7+aitGoHrZR05rcMopyLFjeOPptFTGS0IjmXQ4FXSu1Tl0 +nlD9c5iJ+EkzSp+BEHSiEDee5BJ0GAc7oPM8T8CHAoGAHvNzkHRS5y9fJwwX6q2n +BfCztZSgN6EG8O4KTKzzF07jB/LpUQ8zGYJzNRh6jEcBXSy/aWd8bSd6J5H3I3Hz +nc3ROEGL4a9hVJ+BnHCh1ivmvk3NQqoiI6wwI2HToAim17jE38iNzl4kjsrePqvF +hF6EZablRBDMOd9wAEXljiECgYEAmrwlVZo0yTMUzKg0dnJ0A08DinM2aqZN6kU6 +5yBEtGmmg7GaIbAhRtIUFhbKF1z5eyM6n1mPIn/kaCPywHwqa6cF4ALzkJnNgCCQ +pzsCG979W//V+CtY5lon6T0m5RGaYj+nM2gHLk+EfXrI/R95oXtTO9GWoN11wUja +5jo+4vsCgYEAuXpNId5WvzaU2kB7kEL1UWPhIuMkz5Ez1ol6cpL/KKoE/AVVLhSn +HsTzuhmf8sFwZp4oxhLAKrrG8IaeZ4y5Cd0RaAApjd20n5fO0p++2eDvc7gyA6JK +t6UQhpqjrA0WUYMyGg3ktoOTvHKDjv53BcvOyldQcA1D/9sY3iO3y4c= +-----END RSA PRIVATE KEY----- diff --git a/t/fixtures/ocsp/intermediate_ca.csr b/t/fixtures/ocsp/intermediate_ca.csr new file mode 100644 index 000000000..58580694e --- /dev/null +++ b/t/fixtures/ocsp/intermediate_ca.csr @@ -0,0 +1,18 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIICzjCCAbYCAQAwgYgxCzAJBgNVBAYTAkNBMRAwDgYDVQQIEwdPbnRhcmlvMQ8w +DQYDVQQHEwZPdHRhd2ExEjAQBgNVBAoTCUx1YSBOZ2lueDEgMB4GA1UECxMXQVBJ +Y2FzdCBJbnRlcm1lZGlhdGUgQ0ExIDAeBgNVBAMTF0FQSWNhc3QgSW50ZXJtZWRp +YXRlIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzdmEqwQLfSnE +fXUmMO9TMsY2y7pPr++n4vt03wuo0ZsJLWW7LZ7irtWOHwxnWeu0tfc5UmoUbjwf +xltxn+lw1I+Z+Q5pg/uSe8IwyoA051TCu7MqljPNt93pX97m6wLJnOlGbaIRS6r8 +uBuYIm9//f+jZBI+7gL3CRpkRHgRn6QsYqAOyn1s8DYT6O3cGJ+ldVb75KdDA11l +eT4Pxdap+iGY7rKu5F+K60QhUgStwiV8jK0f9dpx/cm1eutzC2c5WlqmQ15fQfq3 +rQOGoiVLt1USqzvELdaWff2RkULDeS63Vn4JMaY4dhRkyMNSwmx7ZixDpsx2sV3p +qHbdAkP2QwIDAQABoAAwDQYJKoZIhvcNAQELBQADggEBAFwpVkYRmQz+JUfWmvwz +ZU9r3XYNHs7FH4E635TkN54PMJtAFBcOGLQOJxI13a4hHYPvDjrVN3C1CeB5LkQn +8Lq/x/dSIZOpIggOaWQJi73PZW9BO/pOIynAkOxBm0Giqw0pzCsGyRUdkoOgwHXw +dIgzzptUtH2cabitafMG3Cu76z0jRtb5K57b79BlmFnCNRxITSewtRefMQKrp+ha +LzH8nb7WYv0e4ISlW/A9tyg6JW/dWPSywWA0aaRFPptt1VgF/1hoM5O4kmckmSmf +vXIC5QTO0eUI/pBqMTLt+xg4EMnH5wpTzt0aVz+HD0gvgBzezOUv1Ov0j01bYYxd +iYY= +-----END CERTIFICATE REQUEST----- diff --git a/t/fixtures/ocsp/intermediate_ca.pem b/t/fixtures/ocsp/intermediate_ca.pem new file mode 100644 index 000000000..e251d7b08 --- /dev/null +++ b/t/fixtures/ocsp/intermediate_ca.pem @@ -0,0 +1,25 @@ +-----BEGIN CERTIFICATE----- +MIIELzCCAxegAwIBAgIUfUh/NyK/i7Zpk5xEAE/Hycg8oGMwDQYJKoZIhvcNAQEL +BQAweDELMAkGA1UEBhMCQ0ExEDAOBgNVBAgTB09udGFyaW8xDzANBgNVBAcTBk90 +dGF3YTESMBAGA1UEChMJTHVhIE5naW54MRgwFgYDVQQLEw9BUEljYXN0IFJvb3Qg +Q0ExGDAWBgNVBAMTD0FQSWNhc3QgUm9vdCBDQTAgFw0yNTAyMDQwNTI2MDBaGA8y +Mjc0MTIwNjA1MjYwMFowgYgxCzAJBgNVBAYTAkNBMRAwDgYDVQQIEwdPbnRhcmlv +MQ8wDQYDVQQHEwZPdHRhd2ExEjAQBgNVBAoTCUx1YSBOZ2lueDEgMB4GA1UECxMX +QVBJY2FzdCBJbnRlcm1lZGlhdGUgQ0ExIDAeBgNVBAMTF0FQSWNhc3QgSW50ZXJt +ZWRpYXRlIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzdmEqwQL +fSnEfXUmMO9TMsY2y7pPr++n4vt03wuo0ZsJLWW7LZ7irtWOHwxnWeu0tfc5UmoU +bjwfxltxn+lw1I+Z+Q5pg/uSe8IwyoA051TCu7MqljPNt93pX97m6wLJnOlGbaIR +S6r8uBuYIm9//f+jZBI+7gL3CRpkRHgRn6QsYqAOyn1s8DYT6O3cGJ+ldVb75KdD +A11leT4Pxdap+iGY7rKu5F+K60QhUgStwiV8jK0f9dpx/cm1eutzC2c5WlqmQ15f +Qfq3rQOGoiVLt1USqzvELdaWff2RkULDeS63Vn4JMaY4dhRkyMNSwmx7ZixDpsx2 +sV3pqHbdAkP2QwIDAQABo4GdMIGaMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E +BTADAQH/MB0GA1UdDgQWBBTYX0fMoRXzpdBMwUvIwgfO2UunvTAfBgNVHSMEGDAW +gBQaaSka5maUzsFM/Vnn+cUUp54uSTA3BggrBgEFBQcBAQQrMCkwJwYIKwYBBQUH +MAGGG2h0dHBzOi8vb2NzcC1yZXNwb25kZXIudGVzdDANBgkqhkiG9w0BAQsFAAOC +AQEAs/V67Aah67xA0dRXMChK+IE6y3bTjDDo3MndJAnImCVjtbyJJyX4udBfDOKj +sCslF/bFWmLgb1w5ek0kwEOAPc5lDteQ/lPRIW7o9EnIyZico1qnR/bXG5XzQ/UZ +G2UYvHuwPqY2NEsbbPP2yxqaoIL1vhNwm3/Ga5KriiP0Zd3KgIvpfbZ4OcyJBWtm +9P1qsBDpNNkBiNm7i/D9vPDC4skvHsmm2lOBF3CNQ1+WcZRAf5oL9IfptOru79+N +qfOjWbnIMugxez+7TiFGlE81RyKocyflFMwIcGeeQD0KFD9XXnaVPQEovFIspcto +SXPTXb7wJL19OSGBOMBEJ6oS5Q== +-----END CERTIFICATE----- diff --git a/t/fixtures/ocsp/ocsp-key.pem b/t/fixtures/ocsp/ocsp-key.pem new file mode 100644 index 000000000..c71a0bddd --- /dev/null +++ b/t/fixtures/ocsp/ocsp-key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEAuEYwCfh0srnGHBPV3fSl72SmPhGMl3TBkbpyGYeNfLigiFYX +rZCptZqtHDRcXiWMpHohZ4W5ym+jPVJIdIkAPRcRkV7O+Bwd8v8rg5rRTtP44xs5 +g7oHHkzF6KugRIh3arzAsUsyzh9oNXb2N9a3sKyjHv2sNJEuWy+LjLn4hDTLCqx4 +z6Zjyk6maKnqF3ohZKM6HTOgz24ZfpyffWjEmflQx8eupqEN8esoPlT5Z8e0Lvt+ +LFRKIizk6Lt/duhHGDWbQp3ceHXq7ipIlv3MmmUewSO8Ote1mBCgh9KJI6imgr/A +Ao/MxeizPVblg4mRvcFb4KuEXsTzhvSW7wGbwwIDAQABAoIBABbbVeAWulrk4ibf +avqx+tcb0+cFBDxRFiV+S+LQxoL+36KpkxxLQlGtUuWZtQ9UdwJ7x6Lwml/6wvO7 +PhN+XtI1B0/Rw7hQvIJElmAnlujBMDDzUon9TB69BRtcFnAJwU4zBW+4VR/uE132 +WIoKjxRSBZW1f2Ox0l8rIZMeCi5TrCscHRtWdBtrQ9jlxb6wSnQmuAwTUqn8QZC1 +ZhM5f+mSOzKiZ7h9owbeDkbPcEzSM77o5ObUn4XG+1k29yfXotI00xdvqJrHRR72 +7QqxfruQszsmWFi8q+M/hdv3qdftyNSoEXTtCCuCTsDfoMo76e9lH4bNwqLZh73e +Z/0hmnkCgYEA3bf+z8ApcShs+fmT3Ll8Sw+oBoRYQAi8gYOkiyjGADgOvzYJHZVj +SXMz0cwijkEwX66n8Ql6vvNL2MmE9hgTfrMrebJiuaYy/LJYDcEwKTjBw1fJEk4q +0Utya3065/zgp89IQcwT1KxNQGCwccTVl0RNDtOYh0oHVkywzwzOjDUCgYEA1MQS +piYlEhDJCc2bLlMwSII652yJKP5n6oXBmtBp2z5baZQWWw+/+LFyjeBlpyKbeB2L +9bLo9rdhwIDEFRNp+M2a1A2L2WY3N/sigNKjHD8b6mQLmk1C5qHau1cSA5vhgtwg +Wb68Tf5iB7hDxCYZ6c4qnJpGr1bOWXGflcM5VxcCgYBUI0y5Pez8GiEww3tPGbyH +J4vV3Uc4FZijdXdtr61jy+Icwb630Ub6SpNxnAvI/AgFZ1wn5jcEW4N+4wpn8T8E +p61p4z3/wYg7yNoNbjB+lCFDpf6RycQJ5J2pGL7P5nDCfbCn92/XFwPB2G9c3RtI +6gxsAfQx8u/R2gyGpg+DuQKBgB/iRh0p6DI927KhYhjeFIU5JtSZWjCPd0kYxDuL +8eEOBirbK0J4KL9+7/i84N7b+8pTOy8VoX2fW4G6iifSYfYL8aDHauaoP6we8Tu2 +1QSdnHRSi76Sx2zCYoHieWubB39Rt3NbduKFNXGMtnMFdqqn35DaOa965a9XrJ+H +wub/AoGBALOHGYpo4M1i8UHe5YecxSiYfSydK4lvlX2zauJaS5OvahWvSCXUXoIf +Xr90+I+VoQtMTZw6wOLZuUV4Ds81KI4MapFexzjP73+X6rN67GFNnq60nqpqMQgp +SBrVQqzL42Xf/Qv28Nj2zgmC0jofm0tBnRYDRYBLHkA3LF6u9VDY +-----END RSA PRIVATE KEY----- diff --git a/t/fixtures/ocsp/ocsp-response-good-response.der b/t/fixtures/ocsp/ocsp-response-good-response.der new file mode 100644 index 000000000..3cf85c55b Binary files /dev/null and b/t/fixtures/ocsp/ocsp-response-good-response.der differ diff --git a/t/fixtures/ocsp/ocsp-response-revoked-response.der b/t/fixtures/ocsp/ocsp-response-revoked-response.der new file mode 100644 index 000000000..454cf9508 Binary files /dev/null and b/t/fixtures/ocsp/ocsp-response-revoked-response.der differ diff --git a/t/fixtures/ocsp/ocsp.csr b/t/fixtures/ocsp/ocsp.csr new file mode 100644 index 000000000..eeb2b0336 --- /dev/null +++ b/t/fixtures/ocsp/ocsp.csr @@ -0,0 +1,17 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIICzDCCAbQCAQAwgYYxCzAJBgNVBAYTAkNBMRAwDgYDVQQIEwdPbnRhcmlvMQ8w +DQYDVQQHEwZPdHRhd2ExEjAQBgNVBAoTCUx1YSBOZ2lueDEfMB0GA1UECxMWQVBJ +Y2FzdCBPQ1NQIFJlc3BvbmRlcjEfMB0GA1UEAxMWQVBJY2FzdCBPQ1NQIFJlc3Bv +bmRlcjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALhGMAn4dLK5xhwT +1d30pe9kpj4RjJd0wZG6chmHjXy4oIhWF62QqbWarRw0XF4ljKR6IWeFucpvoz1S +SHSJAD0XEZFezvgcHfL/K4Oa0U7T+OMbOYO6Bx5MxeiroESId2q8wLFLMs4faDV2 +9jfWt7Csox79rDSRLlsvi4y5+IQ0ywqseM+mY8pOpmip6hd6IWSjOh0zoM9uGX6c +n31oxJn5UMfHrqahDfHrKD5U+WfHtC77fixUSiIs5Oi7f3boRxg1m0Kd3Hh16u4q +SJb9zJplHsEjvDrXtZgQoIfSiSOopoK/wAKPzMXosz1W5YOJkb3BW+CrhF7E84b0 +lu8Bm8MCAwEAAaAAMA0GCSqGSIb3DQEBCwUAA4IBAQBAy7WnzrIQYPXuhyqj051I +ruzccP4WKdt23GjxCKipdznAyzfYsfxlE1lnpg/QVarMOcpJr6rE1rwh5gCzn/GI +h5Dt31banivXGdDU2l0T7r3teIR9EVImax7qhzxOLa47UYSbTvp4ub7HPSd5gthc +21DEqYTo+GuEPG8wyo4TuL/HViZdXF108mMmWPlz25vqhK44vCq5gmfnwNNrb50r +SFst5XQk4IRQc+PcZIsjog/FnGxsBnRcNF4U4CSJkQL+QnURHp1k4MNIFMGWvZ7q +Ag9VxlEG3CkByMg0f0SzV4nbt0rbGGsRGyAx+KLr4JYXMMpo+ccJ4CM8/21JG7uX +-----END CERTIFICATE REQUEST----- diff --git a/t/fixtures/ocsp/ocsp.pem b/t/fixtures/ocsp/ocsp.pem new file mode 100644 index 000000000..f4409882e --- /dev/null +++ b/t/fixtures/ocsp/ocsp.pem @@ -0,0 +1,26 @@ +-----BEGIN CERTIFICATE----- +MIIEUDCCAzigAwIBAgIUASs9WlttwA1SNLh2Ry/JdkAryaQwDQYJKoZIhvcNAQEL +BQAwgYgxCzAJBgNVBAYTAkNBMRAwDgYDVQQIEwdPbnRhcmlvMQ8wDQYDVQQHEwZP +dHRhd2ExEjAQBgNVBAoTCUx1YSBOZ2lueDEgMB4GA1UECxMXQVBJY2FzdCBJbnRl +cm1lZGlhdGUgQ0ExIDAeBgNVBAMTF0FQSWNhc3QgSW50ZXJtZWRpYXRlIENBMCAX +DTI1MDIwNDA1MjYwMFoYDzIxMjUwMTExMDUyNjAwWjCBhjELMAkGA1UEBhMCQ0Ex +EDAOBgNVBAgTB09udGFyaW8xDzANBgNVBAcTBk90dGF3YTESMBAGA1UEChMJTHVh +IE5naW54MR8wHQYDVQQLExZBUEljYXN0IE9DU1AgUmVzcG9uZGVyMR8wHQYDVQQD +ExZBUEljYXN0IE9DU1AgUmVzcG9uZGVyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEAuEYwCfh0srnGHBPV3fSl72SmPhGMl3TBkbpyGYeNfLigiFYXrZCp +tZqtHDRcXiWMpHohZ4W5ym+jPVJIdIkAPRcRkV7O+Bwd8v8rg5rRTtP44xs5g7oH +HkzF6KugRIh3arzAsUsyzh9oNXb2N9a3sKyjHv2sNJEuWy+LjLn4hDTLCqx4z6Zj +yk6maKnqF3ohZKM6HTOgz24ZfpyffWjEmflQx8eupqEN8esoPlT5Z8e0Lvt+LFRK +Iizk6Lt/duhHGDWbQp3ceHXq7ipIlv3MmmUewSO8Ote1mBCgh9KJI6imgr/AAo/M +xeizPVblg4mRvcFb4KuEXsTzhvSW7wGbwwIDAQABo4GvMIGsMA4GA1UdDwEB/wQE +AwIHgDATBgNVHSUEDDAKBggrBgEFBQcDCTAMBgNVHRMBAf8EAjAAMB0GA1UdDgQW +BBSmJ2jPnfwCaWKsmvFZKoKxlYUD2DAfBgNVHSMEGDAWgBTYX0fMoRXzpdBMwUvI +wgfO2UunvTA3BggrBgEFBQcBAQQrMCkwJwYIKwYBBQUHMAGGG2h0dHBzOi8vb2Nz +cC1yZXNwb25kZXIudGVzdDANBgkqhkiG9w0BAQsFAAOCAQEAzJzqawaIJWw1r3ZN +MrlAQXqd0MgpdZyeWGkDKj8WcrlLzC6q/Ynb7CoM9nZoCCo88/qhiuPaARieIKgL +fX/24fbeXQxPN/CnwWuq7XkM5FfTX+D77qjFjz2adI3Lu/DiJS3aHlkjtNu9HASw +db3KYWc++JofMcVy3WXc9BwQnn4xRpD6bY6vLBchtlUsQOd6wgchM6I8NRCgwu2w +IjtQZgkajpe216eMbMpbTyEHzE9rQu11acMN1mdc7KKSDM9yvyaJZDtUoOX6J7dp +FG+45i6sM/QVNiT7IyH6B7gWZbOlfz1x3leS2sN79+gfxFDNPZkvCV1aoM1zyHTo +n4skYQ== +-----END CERTIFICATE----- diff --git a/t/fixtures/ocsp/server-key.pem b/t/fixtures/ocsp/server-key.pem new file mode 100644 index 000000000..79b76e5b1 --- /dev/null +++ b/t/fixtures/ocsp/server-key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAv99Rhg42S4hQqWAVAtcj774UubfFnCZO/zxaUhqh3d0pk5wg +Z94v3+PuyzTGDeXf+6N71KLoRUncXIoYNRWbbO7TupfobB1Edn2yQL4te5vhhoef +OvQthzlRkucjcbYonc9wbEbPTJxxQxqddUA9pwwpUDSPLKsytVz2a/ZRGURjOlcc +CO6AmGnAL4nY9zrvIQ/V2UexC+O4W4vjVh+Hom6nVvWD+M+z8rovVWgre++b5X25 +zLgmPQgYqcvL4xFlwQlTTKrC+uRC05xPYjD+tPwSOuBfDZaS78UsWPMUWSxDBpuK +Fvv6RimYwYGtpRzP5OWDpyCgRC9T7NYMpa9ORQIDAQABAoIBAA2YoYpCT46ipjSa +XmLJI/7FFWrjntklzctAV5Yh1P6HwX54PcOedv4ChNVZc/9gHrMSLqAuuw7N4ROd +pYF9enoJom9CfHHM0SEkXxE/aLGtphmGWr4ut1sxsJocTuKr6czk+i5yBhaDr3L1 +29qHJtdDgVnxn4Omzf0UDVIxLiYAFv/L7rY/V7QifMl2i93wdmlhgupzMhVBzijr +XvQ2GxihiXugxQqPTlk7dyiYTgk8Yz9/U7PEh0d56SOkfgknT4AptHzMwiysflf4 +hNy7Hybzye2WSgj2ZBzjUPLQHBFycQUMY5RR+TEJMvl+lRQNeug9U2Q3I/JPaWWb +X6LRgQECgYEA9vqHaHY1bggEI35nZopgz/0fff13pPUFWbbV1QjxlBpSUIY8BKX2 +MrGYxopDiBkMdyPdFgm9yoKQ8UgOdxlZvFWFWJeAO3sq8730w+Zb13vtYi6TKsH/ +0CGiMBk6uffBBFSEobewcjfzmO+fBccG8v5efW+je3KDRQB5T0H19dECgYEAxuF/ +FLF6yLm65QS9mvho/Gua/laDuZj4M0Z5NHiPOtKayhKHoKfxfUF4tKRdYdAfF8DS +9S0GidACQVCr0bhxujT8VhOxFy+JEtzUCjO665Lb7JwOKYgz6vnTuYppQWDW7ucm ++DWI967Sxh75ciQQL+8dNG/MEuDsBPHVEGWlSjUCgYEAtDcYyTvAPvqwcmnQ73y3 +qezMpvVl8UMs1UrZeyqchHI0cDeS4d1r6Y+3p9/J6SxF8UWFFIilKXjeZIEstPEV +jpxkwcFCu6RjMhoA2VVk3La7/7F2h3Opw2hXXXt7Y6mJ+Svm384WfTGgmY733ZJd +2r+LmUH166Uibh4rZo7995ECgYB5pXfrmls155TPfETVQ1hD/TWCmDxeC5jVFCgS +1iMVobgYHZljxRXKvX8tTtPnfjtmdgUS/gVfyiF2/fb6gkzdzocBx22sduDq7rOr +wdR1PxDR+uoWsT7AXSsJ9AVJfgg5fJ2zeFtc1EwL7uo4zKIyD5nXdwJmEbmLlLf0 +HZgqeQKBgQCch/Q5cBjNcOM7PI7H+NC/jw/Rxjfa/nEhYmyCsRlBdL/JLc+DciKP +BwFteyHqyT+qwDt76UbeI8vG/c5jSnSeK6ggIw5bOtLFqmk2TyC1/HhJr1/kb2it +qWF5SPP80BwBydacjrlDvAJ5MAlGksUGCgwlL+4MmadwmfiayTPWlA== +-----END RSA PRIVATE KEY----- diff --git a/t/fixtures/ocsp/server.csr b/t/fixtures/ocsp/server.csr new file mode 100644 index 000000000..7c4c61619 --- /dev/null +++ b/t/fixtures/ocsp/server.csr @@ -0,0 +1,18 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIC5DCCAcwCAQAwcjELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWEx +FjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xETAPBgNVBAoTCEN1c3RvbWVyMRAwDgYD +VQQLEwdXZWJzaXRlMREwDwYDVQQDEwh0ZXN0LmNvbTCCASIwDQYJKoZIhvcNAQEB +BQADggEPADCCAQoCggEBAL/fUYYONkuIUKlgFQLXI+++FLm3xZwmTv88WlIaod3d +KZOcIGfeL9/j7ss0xg3l3/uje9Si6EVJ3FyKGDUVm2zu07qX6GwdRHZ9skC+LXub +4YaHnzr0LYc5UZLnI3G2KJ3PcGxGz0yccUManXVAPacMKVA0jyyrMrVc9mv2URlE +YzpXHAjugJhpwC+J2Pc67yEP1dlHsQvjuFuL41Yfh6Jup1b1g/jPs/K6L1VoK3vv +m+V9ucy4Jj0IGKnLy+MRZcEJU0yqwvrkQtOcT2Iw/rT8EjrgXw2Wku/FLFjzFFks +Qwabihb7+kYpmMGBraUcz+Tlg6cgoEQvU+zWDKWvTkUCAwEAAaAtMCsGCSqGSIb3 +DQEJDjEeMBwwGgYDVR0RBBMwEYIJbG9jYWxob3N0ggR0ZXN0MA0GCSqGSIb3DQEB +CwUAA4IBAQCH0FK5sVjhqBZ+bg6Ja5BuEjCrfVLbVzhnlFR8ov0RpwU+7zrVqYBR +DwyQ6YBkRZkL1VRN+mqMDsPmJYxbWsc9kaJXSz+ivIUMB9qnNlQgoKoYdWjs08xc +5MINRdJxx6KSvNsKKq6xlxeUc9I1KM9P2MlJdSALPNi3Xc0TscGaIJtfzKy8sSZP +weAohkGIl85oejLCuyaJHcDoov7/hoGPaEua5OI2J0RszuAEU0GG9HkGXOtUHd/m +3sRPTJ4Ue3BaPykin6vKSaNAQM0qD0fZK+sV+nyIg9IvzD6zA+DV3BTGky/uYq9K +PFFy79CP6yKYJTMjhQUWUkYr3xqOlsTe +-----END CERTIFICATE REQUEST----- diff --git a/t/fixtures/ocsp/server.pem b/t/fixtures/ocsp/server.pem new file mode 100644 index 000000000..b4b007ee2 --- /dev/null +++ b/t/fixtures/ocsp/server.pem @@ -0,0 +1,26 @@ +-----BEGIN CERTIFICATE----- +MIIEVzCCAz+gAwIBAgIUFvw4BaVypD2JMbj8lS48BZPh8O8wDQYJKoZIhvcNAQEL +BQAwgYgxCzAJBgNVBAYTAkNBMRAwDgYDVQQIEwdPbnRhcmlvMQ8wDQYDVQQHEwZP +dHRhd2ExEjAQBgNVBAoTCUx1YSBOZ2lueDEgMB4GA1UECxMXQVBJY2FzdCBJbnRl +cm1lZGlhdGUgQ0ExIDAeBgNVBAMTF0FQSWNhc3QgSW50ZXJtZWRpYXRlIENBMCAX +DTI1MDIyNzA3MTQwMFoYDzIxMjUwMjAzMDcxNDAwWjByMQswCQYDVQQGEwJVUzET +MBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzERMA8G +A1UEChMIQ3VzdG9tZXIxEDAOBgNVBAsTB1dlYnNpdGUxETAPBgNVBAMTCHRlc3Qu +Y29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv99Rhg42S4hQqWAV +Atcj774UubfFnCZO/zxaUhqh3d0pk5wgZ94v3+PuyzTGDeXf+6N71KLoRUncXIoY +NRWbbO7TupfobB1Edn2yQL4te5vhhoefOvQthzlRkucjcbYonc9wbEbPTJxxQxqd +dUA9pwwpUDSPLKsytVz2a/ZRGURjOlccCO6AmGnAL4nY9zrvIQ/V2UexC+O4W4vj +Vh+Hom6nVvWD+M+z8rovVWgre++b5X25zLgmPQgYqcvL4xFlwQlTTKrC+uRC05xP +YjD+tPwSOuBfDZaS78UsWPMUWSxDBpuKFvv6RimYwYGtpRzP5OWDpyCgRC9T7NYM +pa9ORQIDAQABo4HLMIHIMA4GA1UdDwEB/wQEAwIFoDATBgNVHSUEDDAKBggrBgEF +BQcDATAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBQADYPYAN8jLcvdV4jMKBYkx/72 +/TAfBgNVHSMEGDAWgBTYX0fMoRXzpdBMwUvIwgfO2UunvTA3BggrBgEFBQcBAQQr +MCkwJwYIKwYBBQUHMAGGG2h0dHBzOi8vb2NzcC1yZXNwb25kZXIudGVzdDAaBgNV +HREEEzARgglsb2NhbGhvc3SCBHRlc3QwDQYJKoZIhvcNAQELBQADggEBAGMg6g+z +UOvaFdYq0vbS1XnsArXD/LgzuU6qZ2a+23qC3vXbBB3XPAmx/aBYhXjt84rtmxXn +5emNIGd0/2IuSWwLqre+GOPf3AOP5rJrSDtr8526BteMqBSy5fWWl+y79yqPUq8E +1u6zp+feyCDfmVBLi8t9VEgnejfBQTcGjk6W1nx832oJJNZ5YIL1YW33InPYsbKy +erwjsNkZU0gtw1qzbKuazj5INbsYMBP+JhOR8eqBfqWBOgVShR64haAQS93J130o +q0HmXSONDajWkyct0An6wAqWSgD8QGa+u8jLY8KRBkmQY4vI7Jb7x7jB4VX5yZfA +mbtuCaqpHQga6Gw= +-----END CERTIFICATE----- diff --git a/t/fixtures/ocsp/wrong-issuer-order-chain.pem b/t/fixtures/ocsp/wrong-issuer-order-chain.pem new file mode 100644 index 000000000..bab52cfa0 --- /dev/null +++ b/t/fixtures/ocsp/wrong-issuer-order-chain.pem @@ -0,0 +1,74 @@ +-----BEGIN CERTIFICATE----- +MIIEVzCCAz+gAwIBAgIUTKcAbc6mgr6a9FcHhywQ6lrsoBkwDQYJKoZIhvcNAQEL +BQAwgYgxCzAJBgNVBAYTAkNBMRAwDgYDVQQIEwdPbnRhcmlvMQ8wDQYDVQQHEwZP +dHRhd2ExEjAQBgNVBAoTCUx1YSBOZ2lueDEgMB4GA1UECxMXQVBJY2FzdCBJbnRl +cm1lZGlhdGUgQ0ExIDAeBgNVBAMTF0FQSWNhc3QgSW50ZXJtZWRpYXRlIENBMCAX +DTI1MDIwNDA4MDAwMFoYDzIxMjUwMTExMDgwMDAwWjByMQswCQYDVQQGEwJVUzET +MBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzERMA8G +A1UEChMIQ3VzdG9tZXIxEDAOBgNVBAsTB1dlYnNpdGUxETAPBgNVBAMTCHRlc3Qu +Y29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv+EK5duP98xw5Fmj +WwnC5xOdz6AnqwaxkWcfBOtCX7W2tuN7gOF3L7NXtJ5Tnyr9uCYhhL4zqRF6j6rp ++yP/jIR4ZN1UHmq+ScHG7//8NCFCu6R9h3YkkDRh5OLSdksGzIIeBRkqiyUOiJaH +vciXFOX/pcjDSQCVqeTFTzOaOmHNT4A9dC4zCNjR1Zn02LqK0IxylFp6MzXCt+lW +cGJvLniSo1KUOW6JPj1TVrgUQygns0ijb1nok5jbsCSHQW9lRK16JrCqVangABvg +V2WAoieB1RPLkCIj1ZJneHSZKsBN9HcF3x0AMoOOTHkpmpv1eqbkVXLbKWU6i305 +4Jn8lwIDAQABo4HLMIHIMA4GA1UdDwEB/wQEAwIFoDATBgNVHSUEDDAKBggrBgEF +BQcDAjAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBR1FdZ2snwxIUD+KrVkBO9pZ9Ib +iTAfBgNVHSMEGDAWgBTYX0fMoRXzpdBMwUvIwgfO2UunvTA3BggrBgEFBQcBAQQr +MCkwJwYIKwYBBQUHMAGGG2h0dHBzOi8vb2NzcC1yZXNwb25kZXIudGVzdDAaBgNV +HREEEzARgglsb2NhbGhvc3SCBHRlc3QwDQYJKoZIhvcNAQELBQADggEBAB5talFl +dl0faUMOCAq7np0BHYCXm/txxqfIuIKetkFNortrpMYxsktkaAcFmEQV5+O6kVyC +Frxui/ogZt1d2uG/jCy8eAhKkdO2/Y3siYenT8wAS/Z3iFiBRb5KfIPcTIZp3CFj +f3y9ND6HWtMSXqNaPRBqX3hWrWIkEIer7YeSjBeceaJhrddfMyW1Wo2cOPHvz6eA +53Swz2yjYkaaU2UMBIb3xxGl4q4a8HqNyDqeI7pzobBxmhroAFS3dD0t8JpycmzM +lDvTDoUu/vtp194CcxJnGJ0kAWNemfAEriIqh6koBeXslUqFbxhXJhwYwyheArp/ +yk9pbkJR+3rrWrk= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDwDCCAqigAwIBAgIUcSXJIwYu13xp3Iewm41m+UYc7zIwDQYJKoZIhvcNAQEL +BQAweDELMAkGA1UEBhMCQ0ExEDAOBgNVBAgTB09udGFyaW8xDzANBgNVBAcTBk90 +dGF3YTESMBAGA1UEChMJTHVhIE5naW54MRgwFgYDVQQLEw9BUEljYXN0IFJvb3Qg +Q0ExGDAWBgNVBAMTD0FQSWNhc3QgUm9vdCBDQTAeFw0yNTAyMDQwNTI1MDBaFw0z +MDAyMDMwNTI1MDBaMHgxCzAJBgNVBAYTAkNBMRAwDgYDVQQIEwdPbnRhcmlvMQ8w +DQYDVQQHEwZPdHRhd2ExEjAQBgNVBAoTCUx1YSBOZ2lueDEYMBYGA1UECxMPQVBJ +Y2FzdCBSb290IENBMRgwFgYDVQQDEw9BUEljYXN0IFJvb3QgQ0EwggEiMA0GCSqG +SIb3DQEBAQUAA4IBDwAwggEKAoIBAQC3Z7SSUZ9anC/aIIiUlTcarpPZ793goGmH +qTw9fzDIiVRYvoLjGSc4wDJSU6NSio91cFX2J6lCKhEUGicUBi2jL5Yo35XUc6SZ +U9IAEbgUegooLAyLNNMLy144nBr6ggcBNwls8hHTTmEWDfYPB2kKrEjFVJG0/3et +JeioszgBBD5YV1aEbop/ONMxn0PQIvOyFQpFErJDv6AB/pmu+KsTFntRPisfI9Qq +eHUIbGudRN2heFRRoEqh3UySJGUIFqFPoxmGeXeCcr5VUQvQXaTnpQ4RuGxeek/F +WjPBJMWOVxC94Xw/hYY8j/1DV/6mCccFyrXo6Jyg5UYoHhWSE7wpAgMBAAGjQjBA +MA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBQaaSka +5maUzsFM/Vnn+cUUp54uSTANBgkqhkiG9w0BAQsFAAOCAQEAIhIQpkC8EVxA6Lhm +uDutU9LGKQjp0PrzJLWCCcDCnxQ8cbaH2CUr2mw0et/cBM8R5TR35JMZe6MOGSbt +lFfWKfLE+QzNPaLhQkOI21YZMqY1kcGNmsc2UyHxhPo6PZ+J1IF/9N/P7+BjDQeN +yCd+dwXpUZlRZRyEVVXNl2yKUKLynViiNpa9rRb/mT5pqD/b523/Icva0mi6xyJZ +UbaYQBE4IozQ2YEChP3EpfUjJepZCeHWbCEzKgC61H21uSK62K33pPPN3+zKKJrk +eu2xwIugYpLwf3dvFGdW47vfUvxZdYltRkrAASDOPTpaU5dHwfR8MsoGy2h2A2jz +qOUrUg== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIELzCCAxegAwIBAgIUfUh/NyK/i7Zpk5xEAE/Hycg8oGMwDQYJKoZIhvcNAQEL +BQAweDELMAkGA1UEBhMCQ0ExEDAOBgNVBAgTB09udGFyaW8xDzANBgNVBAcTBk90 +dGF3YTESMBAGA1UEChMJTHVhIE5naW54MRgwFgYDVQQLEw9BUEljYXN0IFJvb3Qg +Q0ExGDAWBgNVBAMTD0FQSWNhc3QgUm9vdCBDQTAgFw0yNTAyMDQwNTI2MDBaGA8y +Mjc0MTIwNjA1MjYwMFowgYgxCzAJBgNVBAYTAkNBMRAwDgYDVQQIEwdPbnRhcmlv +MQ8wDQYDVQQHEwZPdHRhd2ExEjAQBgNVBAoTCUx1YSBOZ2lueDEgMB4GA1UECxMX +QVBJY2FzdCBJbnRlcm1lZGlhdGUgQ0ExIDAeBgNVBAMTF0FQSWNhc3QgSW50ZXJt +ZWRpYXRlIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzdmEqwQL +fSnEfXUmMO9TMsY2y7pPr++n4vt03wuo0ZsJLWW7LZ7irtWOHwxnWeu0tfc5UmoU +bjwfxltxn+lw1I+Z+Q5pg/uSe8IwyoA051TCu7MqljPNt93pX97m6wLJnOlGbaIR +S6r8uBuYIm9//f+jZBI+7gL3CRpkRHgRn6QsYqAOyn1s8DYT6O3cGJ+ldVb75KdD +A11leT4Pxdap+iGY7rKu5F+K60QhUgStwiV8jK0f9dpx/cm1eutzC2c5WlqmQ15f +Qfq3rQOGoiVLt1USqzvELdaWff2RkULDeS63Vn4JMaY4dhRkyMNSwmx7ZixDpsx2 +sV3pqHbdAkP2QwIDAQABo4GdMIGaMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E +BTADAQH/MB0GA1UdDgQWBBTYX0fMoRXzpdBMwUvIwgfO2UunvTAfBgNVHSMEGDAW +gBQaaSka5maUzsFM/Vnn+cUUp54uSTA3BggrBgEFBQcBAQQrMCkwJwYIKwYBBQUH +MAGGG2h0dHBzOi8vb2NzcC1yZXNwb25kZXIudGVzdDANBgkqhkiG9w0BAQsFAAOC +AQEAs/V67Aah67xA0dRXMChK+IE6y3bTjDDo3MndJAnImCVjtbyJJyX4udBfDOKj +sCslF/bFWmLgb1w5ek0kwEOAPc5lDteQ/lPRIW7o9EnIyZico1qnR/bXG5XzQ/UZ +G2UYvHuwPqY2NEsbbPP2yxqaoIL1vhNwm3/Ga5KriiP0Zd3KgIvpfbZ4OcyJBWtm +9P1qsBDpNNkBiNm7i/D9vPDC4skvHsmm2lOBF3CNQ1+WcZRAf5oL9IfptOru79+N +qfOjWbnIMugxez+7TiFGlE81RyKocyflFMwIcGeeQD0KFD9XXnaVPQEovFIspcto +SXPTXb7wJL19OSGBOMBEJ6oS5Q== +-----END CERTIFICATE----- diff --git a/t/prometheus-metrics.t b/t/prometheus-metrics.t index aca2dc2bb..9d6bbb8d5 100644 --- a/t/prometheus-metrics.t +++ b/t/prometheus-metrics.t @@ -37,6 +37,7 @@ openresty_shdict_capacity{dict="batched_reports"} 20971520 openresty_shdict_capacity{dict="batched_reports_locks"} 1048576 openresty_shdict_capacity{dict="cached_auths"} 20971520 openresty_shdict_capacity{dict="limiter"} 1048576 +openresty_shdict_capacity{dict="ocsp_cache"} 10485760 openresty_shdict_capacity{dict="prometheus_metrics"} 16777216 openresty_shdict_capacity{dict="rate_limit_headers"} 20971520 # HELP openresty_shdict_free_space OpenResty shared dictionary free space @@ -46,6 +47,7 @@ openresty_shdict_free_space{dict="batched_reports"} 20840448 openresty_shdict_free_space{dict="batched_reports_locks"} 1032192 openresty_shdict_free_space{dict="cached_auths"} 20840448 openresty_shdict_free_space{dict="limiter"} 1032192 +openresty_shdict_free_space{dict="ocsp_cache"} 10412032 openresty_shdict_free_space{dict="prometheus_metrics"} 16662528 openresty_shdict_free_space{dict="rate_limit_headers"} 20840448 # HELP worker_process Number of times that a nginx worker has been started