-
Notifications
You must be signed in to change notification settings - Fork 2.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add ocsp-stapling plugin (#10817)
- Loading branch information
Showing
20 changed files
with
1,276 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,220 @@ | ||
-- | ||
-- Licensed to the Apache Software Foundation (ASF) under one | ||
-- or more contributor license agreements. See the NOTICE file | ||
-- distributed with this work for additional information | ||
-- regarding copyright ownership. The ASF licenses this file | ||
-- to you under the Apache License, Version 2.0 (the | ||
-- "License"); you may not use this file except in compliance | ||
-- with the License. You may obtain a copy of the License at | ||
-- | ||
-- http://www.apache.org/licenses/LICENSE-2.0 | ||
-- | ||
-- Unless required by applicable law or agreed to in writing, | ||
-- software distributed under the License is distributed on an | ||
-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
-- KIND, either express or implied. See the License for the | ||
-- specific language governing permissions and limitations | ||
-- under the License. | ||
-- | ||
|
||
local require = require | ||
local http = require("resty.http") | ||
local ngx = ngx | ||
local ngx_ocsp = require("ngx.ocsp") | ||
local ngx_ssl = require("ngx.ssl") | ||
local radixtree_sni = require("apisix.ssl.router.radixtree_sni") | ||
local core = require("apisix.core") | ||
|
||
local plugin_name = "ocsp-stapling" | ||
local ocsp_resp_cache = ngx.shared[plugin_name] | ||
|
||
local plugin_schema = { | ||
type = "object", | ||
properties = {}, | ||
} | ||
|
||
local _M = { | ||
name = plugin_name, | ||
schema = plugin_schema, | ||
version = 0.1, | ||
priority = -44, | ||
} | ||
|
||
|
||
function _M.check_schema(conf) | ||
return core.schema.check(plugin_schema, conf) | ||
end | ||
|
||
|
||
local function fetch_ocsp_resp(der_cert_chain) | ||
core.log.info("fetch ocsp response from remote") | ||
local ocsp_url, err = ngx_ocsp.get_ocsp_responder_from_der_chain(der_cert_chain) | ||
|
||
if not ocsp_url then | ||
-- if cert not support ocsp, the report error is nil | ||
if not err then | ||
err = "cert not contains authority_information_access extension" | ||
end | ||
return nil, "failed to get ocsp url: " .. err | ||
end | ||
|
||
local ocsp_req, err = ngx_ocsp.create_ocsp_request(der_cert_chain) | ||
if not ocsp_req then | ||
return nil, "failed to create ocsp request: " .. err | ||
end | ||
|
||
local httpc = http.new() | ||
local res, err = httpc:request_uri(ocsp_url, { | ||
method = "POST", | ||
headers = { | ||
["Content-Type"] = "application/ocsp-request", | ||
}, | ||
body = ocsp_req | ||
}) | ||
|
||
if not res then | ||
return nil, "ocsp responder query failed: " .. err | ||
end | ||
|
||
local http_status = res.status | ||
if http_status ~= 200 then | ||
return nil, "ocsp responder returns bad http status code: " | ||
.. http_status | ||
end | ||
|
||
if res.body and #res.body > 0 then | ||
return res.body, nil | ||
end | ||
|
||
return nil, "ocsp responder returns empty body" | ||
end | ||
|
||
|
||
local function set_ocsp_resp(full_chain_pem_cert, skip_verify, cache_ttl) | ||
local der_cert_chain, err = ngx_ssl.cert_pem_to_der(full_chain_pem_cert) | ||
if not der_cert_chain then | ||
return false, "failed to convert certificate chain from PEM to DER: ", err | ||
end | ||
|
||
local ocsp_resp = ocsp_resp_cache:get(der_cert_chain) | ||
if ocsp_resp == nil then | ||
core.log.info("not ocsp resp cache found, fetch from ocsp responder") | ||
ocsp_resp, err = fetch_ocsp_resp(der_cert_chain) | ||
if ocsp_resp == nil then | ||
return false, err | ||
end | ||
core.log.info("fetch ocsp resp ok, cache it") | ||
ocsp_resp_cache:set(der_cert_chain, ocsp_resp, cache_ttl) | ||
end | ||
|
||
if not skip_verify then | ||
local ok, err = ngx_ocsp.validate_ocsp_response(ocsp_resp, der_cert_chain) | ||
if not ok then | ||
return false, "failed to validate ocsp response: " .. err | ||
end | ||
end | ||
|
||
-- set the OCSP stapling | ||
local ok, err = ngx_ocsp.set_ocsp_status_resp(ocsp_resp) | ||
if not ok then | ||
return false, "failed to set ocsp status response: " .. err | ||
end | ||
|
||
return true | ||
end | ||
|
||
|
||
local original_set_cert_and_key | ||
local function set_cert_and_key(sni, value) | ||
if value.gm then | ||
-- should not run with gm plugin | ||
core.log.warn("gm plugin enabled, no need to run ocsp-stapling plugin") | ||
return original_set_cert_and_key(sni, value) | ||
end | ||
|
||
if not value.ocsp_stapling then | ||
core.log.info("no 'ocsp_stapling' field found, no need to run ocsp-stapling plugin") | ||
return original_set_cert_and_key(sni, value) | ||
end | ||
|
||
if not value.ocsp_stapling.enabled then | ||
return original_set_cert_and_key(sni, value) | ||
end | ||
|
||
if not ngx.ctx.tls_ext_status_req then | ||
core.log.info("no status request required, no need to send ocsp response") | ||
return original_set_cert_and_key(sni, value) | ||
end | ||
|
||
local ok, err = radixtree_sni.set_pem_ssl_key(sni, value.cert, value.key) | ||
if not ok then | ||
return false, err | ||
end | ||
local fin_pem_cert = value.cert | ||
|
||
-- multiple certificates support. | ||
if value.certs then | ||
for i = 1, #value.certs do | ||
local cert = value.certs[i] | ||
local key = value.keys[i] | ||
ok, err = radixtree_sni.set_pem_ssl_key(sni, cert, key) | ||
if not ok then | ||
return false, err | ||
end | ||
fin_pem_cert = cert | ||
end | ||
end | ||
|
||
local ok, err = set_ocsp_resp(fin_pem_cert, | ||
value.ocsp_stapling.skip_verify, | ||
value.ocsp_stapling.cache_ttl) | ||
if not ok then | ||
core.log.error("no ocsp response send: ", err) | ||
end | ||
|
||
return true | ||
end | ||
|
||
|
||
function _M.init() | ||
if core.schema.ssl.properties.gm ~= nil then | ||
core.log.error("ocsp-stapling plugin should not run with gm plugin") | ||
end | ||
|
||
original_set_cert_and_key = radixtree_sni.set_cert_and_key | ||
radixtree_sni.set_cert_and_key = set_cert_and_key | ||
|
||
if core.schema.ssl.properties.ocsp_stapling ~= nil then | ||
core.log.error("Field 'ocsp_stapling' is occupied") | ||
end | ||
|
||
core.schema.ssl.properties.ocsp_stapling = { | ||
type = "object", | ||
properties = { | ||
enabled = { | ||
type = "boolean", | ||
default = false, | ||
}, | ||
skip_verify = { | ||
type = "boolean", | ||
default = false, | ||
}, | ||
cache_ttl = { | ||
type = "integer", | ||
minimum = 60, | ||
default = 3600, | ||
}, | ||
} | ||
} | ||
|
||
end | ||
|
||
|
||
function _M.destroy() | ||
radixtree_sni.set_cert_and_key = original_set_cert_and_key | ||
core.schema.ssl.properties.ocsp_stapling = nil | ||
ocsp_resp_cache:flush_all() | ||
end | ||
|
||
|
||
return _M |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
-----BEGIN CERTIFICATE----- | ||
MIIC+jCCAWKgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJDTjES | ||
MBAGA1UECAwJR3VhbmdEb25nMQ8wDQYDVQQHDAZaaHVIYWkxDzANBgNVBAoMBmly | ||
ZXN0eTERMA8GA1UEAwwIdGVzdC5jb20wHhcNMjQwMTEyMTQ1OTUwWhcNMzQwMTA5 | ||
MTQ1OTUwWjA9MQswCQYDVQQGEwJDTjEWMBQGA1UECwwNQXBhY2hlIEFQSVNJWDEW | ||
MBQGA1UEAwwNb2NzcC50ZXN0LmNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IA | ||
BIuZCmq/vmX5LqFrpa9ot5SboEhNyS/r5UGT7akjIOAXBVwZkn1vm/EsQp9VMF8y | ||
rWZkGKFmElo0ZAXAyhjn9D6jNzA1MDMGCCsGAQUFBwEBBCcwJTAjBggrBgEFBQcw | ||
AYYXaHR0cDovLzEyNy4wLjAuMToxMTQ1MS8wDQYJKoZIhvcNAQELBQADggGBAIEm | ||
LKKS+eGBazPpSRvq2agnqmjM+PHVWRB/O/+LNOO69Lji3wRtq6T2zNHPZQXw1OMA | ||
3C9HcIwaawTyb+hm+vX8yBr5mgS1UOtmDYzbnlpERjJBjxmPXTZLDbzogHshbabp | ||
227p/IAjWm/2F2VPXjiX+aV1pYrhCcO7zUtBEu9KaoG3Amxg8T2WVamTV+J6r0SL | ||
fkvYItZwbawSfwQlZ+22H4Mttu/bd2USTusT4zLAflv9UFh20bA1PizvcKK1brWS | ||
IH2rxxSLCvu2wmrGsrLVn+9yD6xNsn4m6DyCWx9S/Tas7KLub8BjnCzP8YEvrVpV | ||
fotefEMY5h0waj9Zc32l+6gk8Ntyp2ozWi+iu4eo0Y5SUqHlPjuGUXOivp5o/6b0 | ||
gF5M9jtkXvbH2ffrOiz9YUo4fVwk6ws5OQTr9WsildEHZH4ADOW6HqPYkOnuxhdM | ||
p6JP0LmnO/S60/k/ZH8nMTcSUfE+qcDg3LlH5ay2fv6IKz5BaVkyHPNreRi9qg== | ||
-----END CERTIFICATE----- | ||
-----BEGIN CERTIFICATE----- | ||
MIIEojCCAwqgAwIBAgIJAK253pMhgCkxMA0GCSqGSIb3DQEBCwUAMFYxCzAJBgNV | ||
BAYTAkNOMRIwEAYDVQQIDAlHdWFuZ0RvbmcxDzANBgNVBAcMBlpodUhhaTEPMA0G | ||
A1UECgwGaXJlc3R5MREwDwYDVQQDDAh0ZXN0LmNvbTAgFw0xOTA2MjQyMjE4MDVa | ||
GA8yMTE5MDUzMTIyMTgwNVowVjELMAkGA1UEBhMCQ04xEjAQBgNVBAgMCUd1YW5n | ||
RG9uZzEPMA0GA1UEBwwGWmh1SGFpMQ8wDQYDVQQKDAZpcmVzdHkxETAPBgNVBAMM | ||
CHRlc3QuY29tMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAyCM0rqJe | ||
cvgnCfOw4fATotPwk5Ba0gC2YvIrO+gSbQkyxXF5jhZB3W6BkWUWR4oNFLLSqcVb | ||
VDPitz/Mt46Mo8amuS6zTbQetGnBARzPLtmVhJfoeLj0efMiOepOSZflj9Ob4yKR | ||
2bGdEFOdHPjm+4ggXU9jMKeLqdVvxll/JiVFBW5smPtW1Oc/BV5terhscJdOgmRr | ||
abf9xiIis9/qVYfyGn52u9452V0owUuwP7nZ01jt6iMWEGeQU6mwPENgvj1olji2 | ||
WjdG2UwpUVp3jp3l7j1ekQ6mI0F7yI+LeHzfUwiyVt1TmtMWn1ztk6FfLRqwJWR/ | ||
Evm95vnfS3Le4S2ky3XAgn2UnCMyej3wDN6qHR1onpRVeXhrBajbCRDRBMwaNw/1 | ||
/3Uvza8QKK10PzQR6OcQ0xo9psMkd9j9ts/dTuo2fzaqpIfyUbPST4GdqNG9NyIh | ||
/B9g26/0EWcjyO7mYVkaycrtLMaXm1u9jyRmcQQI1cGrGwyXbrieNp63AgMBAAGj | ||
cTBvMB0GA1UdDgQWBBSZtSvV8mBwl0bpkvFtgyiOUUcbszAfBgNVHSMEGDAWgBSZ | ||
tSvV8mBwl0bpkvFtgyiOUUcbszAMBgNVHRMEBTADAQH/MB8GA1UdEQQYMBaCCHRl | ||
c3QuY29tggoqLnRlc3QuY29tMA0GCSqGSIb3DQEBCwUAA4IBgQAHGEul/x7ViVgC | ||
tC8CbXEslYEkj1XVr2Y4hXZXAXKd3W7V3TC8rqWWBbr6L/tsSVFt126V5WyRmOaY | ||
1A5pju8VhnkhYxYfZALQxJN2tZPFVeME9iGJ9BE1wPtpMgITX8Rt9kbNlENfAgOl | ||
PYzrUZN1YUQjX+X8t8/1VkSmyZysr6ngJ46/M8F16gfYXc9zFj846Z9VST0zCKob | ||
rJs3GtHOkS9zGGldqKKCj+Awl0jvTstI4qtS1ED92tcnJh5j/SSXCAB5FgnpKZWy | ||
hme45nBQj86rJ8FhN+/aQ9H9/2Ib6Q4wbpaIvf4lQdLUEcWAeZGW6Rk0JURwEog1 | ||
7/mMgkapDglgeFx9f/XztSTrkHTaX4Obr+nYrZ2V4KOB4llZnK5GeNjDrOOJDk2y | ||
IJFgBOZJWyS93dQfuKEj42hA79MuX64lMSCVQSjX+ipR289GQZqFrIhiJxLyA+Ve | ||
U/OOcSRr39Kuis/JJ+DkgHYa/PWHZhnJQBxcqXXk1bJGw9BNbhM= | ||
-----END CERTIFICATE----- |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
-----BEGIN EC PARAMETERS----- | ||
BggqhkjOPQMBBw== | ||
-----END EC PARAMETERS----- | ||
-----BEGIN EC PRIVATE KEY----- | ||
MHcCAQEEIHMwGqSAcIFnsy8Sa6NxlSmGuOXV13SbZbZVIobN+3xboAoGCCqGSM49 | ||
AwEHoUQDQgAEi5kKar++ZfkuoWulr2i3lJugSE3JL+vlQZPtqSMg4BcFXBmSfW+b | ||
8SxCn1UwXzKtZmQYoWYSWjRkBcDKGOf0Pg== | ||
-----END EC PRIVATE KEY----- |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
V 340109124821Z 1 unknown /C=CN/OU=Apache APISIX/CN=ocsp.test.com1 | ||
V 340109125024Z 2 unknown /C=CN/OU=Apache APISIX/CN=ocsp.test.com2 | ||
R 340109125151Z 240109125151Z 3 unknown /C=CN/OU=Apache APISIX/CN=ocsp-revoked.test.com | ||
V 340109125746Z 5 unknown /C=CN/OU=Apache APISIX/CN=ocsp test CA signer |
Oops, something went wrong.