forked from 3scale-demos/apicast-example-policy
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Extracted from 3scale/APIcast#966
- Loading branch information
Showing
21 changed files
with
668 additions
and
139 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
#!/bin/sh | ||
|
||
echo "---> Copying policy source..." | ||
cp -Rf /tmp/src/. ./ | ||
cp -Rfv /tmp/src/. ./ |
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 was deleted.
Oops, something went wrong.
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 @@ | ||
ssl_verify_client optional_no_ca; |
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 was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
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,39 @@ | ||
{ | ||
"$schema": "http://apicast.io/policy-v1/schema#manifest#", | ||
"name": "TLS validation", | ||
"summary": "Validate client TLS certificates", | ||
"description": [ | ||
"Validate client certificates against individual certificates and CA certificates." | ||
], | ||
"version": "0.1", | ||
"configuration": { | ||
"type": "object", | ||
"definitions": { | ||
"certificate": { | ||
"$id": "#/definitions/certificate", | ||
"type": "object", | ||
"properties": { | ||
"pem_certificate": { | ||
"type": "string", | ||
"title": "PEM formatted certificate", | ||
"description": "Certificate including the -----BEGIN CERTIFICATE----- and -----END CERTIFICATE-----" | ||
} | ||
} | ||
}, | ||
"store": { | ||
"$id": "#/definitions/store", | ||
"type": "array", | ||
"items": { | ||
"$ref": "#/definitions/certificate" | ||
} | ||
} | ||
}, | ||
"properties": { | ||
"whitelist": { | ||
"$ref": "#/definitions/store", | ||
"title": "Certificate Whitelist", | ||
"description": "Individual certificates and CA certificates to be whitelisted." | ||
} | ||
} | ||
} | ||
} |
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 @@ | ||
return require('tls_validation') |
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,61 @@ | ||
-- This is a tls_validation description. | ||
|
||
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 ipairs = ipairs | ||
local tostring = tostring | ||
|
||
local debug = ngx.config.debug | ||
|
||
local function init_trusted_store(store, certificates) | ||
for _,certificate in ipairs(certificates) do | ||
local cert, err = X509.parse_pem_cert(certificate.pem_certificate) -- TODO: handle errors | ||
|
||
if cert then | ||
store:add_cert(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 | ||
end | ||
|
||
return store | ||
end | ||
|
||
local new = _M.new | ||
--- Initialize a tls_validation | ||
-- @tparam[opt] table config Policy configuration. | ||
function _M.new(config) | ||
local self = new(config) | ||
local store = X509_STORE.new() | ||
|
||
self.x509_store = init_trusted_store(store, config and config.whitelist or {}) | ||
self.error_status = config and config.error_status or 400 | ||
|
||
return self | ||
end | ||
|
||
function _M:access() | ||
local cert = X509.parse_pem_cert(ngx.var.ssl_client_raw_cert) | ||
local store = self.x509_store | ||
|
||
local ok, err = store:validate_cert(cert) | ||
if not ok then | ||
ngx.var.cached_key = nil | ||
ngx.status = self.error_status | ||
ngx.say(err) | ||
return ngx.exit(ngx.status) | ||
end | ||
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
local ffi = require('ffi') | ||
|
||
ffi.cdef([[ | ||
// https://github.com/openssl/openssl/blob/4ace4ccda2934d2628c3d63d41e79abe041621a7/include/openssl/ossl_typ.h | ||
typedef struct x509_store_st X509_STORE; | ||
typedef struct x509_st X509; | ||
typedef struct X509_crl_st X509_CRL; | ||
typedef struct X509_name_st X509_NAME; | ||
typedef struct bio_st BIO; | ||
typedef struct bio_method_st BIO_METHOD; | ||
typedef struct X509_VERIFY_PARAM_st X509_VERIFY_PARAM; | ||
typedef struct stack_st OPENSSL_STACK; | ||
typedef struct evp_md_st { | ||
int type; | ||
int pkey_type; | ||
int md_size; | ||
} EVP_MD; | ||
unsigned long ERR_get_error(void); | ||
const char *ERR_reason_error_string(unsigned long e); | ||
void ERR_clear_error(void); | ||
]]) | ||
|
||
local C = ffi.C | ||
local _M = { } | ||
|
||
local error = error | ||
|
||
local function openssl_error() | ||
local code, reason | ||
|
||
while true do | ||
--[[ | ||
https://www.openssl.org/docs/man1.1.0/crypto/ERR_get_error.html | ||
ERR_get_error() returns the earliest error code | ||
from the thread's error queue and removes the entry. | ||
This function can be called repeatedly | ||
until there are no more error codes to return. | ||
]]-- | ||
code = C.ERR_get_error() | ||
|
||
if code == 0 then | ||
break | ||
else | ||
reason = C.ERR_reason_error_string(code) | ||
end | ||
end | ||
|
||
C.ERR_clear_error() | ||
|
||
if reason then | ||
return ffi.string(reason) | ||
end | ||
end | ||
|
||
local function ffi_value(ret, expected) | ||
if ret == nil or ret == -1 or (expected and ret ~= expected) then | ||
return nil, openssl_error() or 'expected value, got nil' | ||
end | ||
|
||
return ret | ||
end | ||
|
||
local function ffi_assert(ret, expected) | ||
local value, err = ffi_value(ret, expected) | ||
|
||
if not value then | ||
error(err, 2) | ||
end | ||
|
||
return value | ||
end | ||
|
||
local function tocdata(obj) | ||
return obj and obj.cdata or obj | ||
end | ||
|
||
_M.ffi_assert = ffi_assert | ||
_M.ffi_value = ffi_value | ||
_M.openssl_error = openssl_error | ||
_M.tocdata = tocdata | ||
|
||
return _M |
Oops, something went wrong.