Skip to content

Commit

Permalink
[policy] introduce ssl_certificate phase
Browse files Browse the repository at this point in the history
* allows policies to serve ssl certificate
* service is detected by host from SNI
* policy should clear certificates before setting them
  • Loading branch information
mikz committed Jun 5, 2018
1 parent 59acd42 commit 7c64dbb
Show file tree
Hide file tree
Showing 10 changed files with 128 additions and 9 deletions.
9 changes: 7 additions & 2 deletions gateway/conf/nginx.conf.liquid
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@ http {
{% include tracer_conf %}
{% endif %}

ssl_session_fetch_by_lua_block { require('apicast.executor'):ssl_session_fetch() }
ssl_session_store_by_lua_block { require('apicast.executor'):ssl_session_store() }

server {
listen {{ port.management | default: 8090 }};
server_name {{ server_name.management | default: 'management _' }};
Expand Down Expand Up @@ -131,8 +134,10 @@ http {

{% if https_port -%}
listen {{ https_port }} ssl;
ssl_certificate {{ env.APICAST_HTTPS_CERTIFICATE }};
ssl_certificate_key {{ env.APICAST_HTTPS_CERTIFICATE_KEY }};
ssl_certificate {{ env.APICAST_HTTPS_CERTIFICATE | default: "conf/server.crt" | filesystem | first }};
ssl_certificate_key {{ env.APICAST_HTTPS_CERTIFICATE_KEY | default: "conf/server.key" | filesystem | first }};

ssl_certificate_by_lua_block { require('apicast.executor'):ssl_certificate() }
{%- endif %}

server_name _;
Expand Down
10 changes: 10 additions & 0 deletions gateway/conf/server.crt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
-----BEGIN CERTIFICATE-----
MIIBTzCB9gIJAJ/Hbl7Rg8UpMAoGCCqGSM49BAMCMDAxEDAOBgNVBAoMB0FQSWNh
c3QxHDAaBgNVBAsME0RlZmF1bHQgY2VydGlmaWNhdGUwHhcNMTgwNjA1MTAxNjAx
WhcNMjgwNjAyMTAxNjAxWjAwMRAwDgYDVQQKDAdBUEljYXN0MRwwGgYDVQQLDBNE
ZWZhdWx0IGNlcnRpZmljYXRlMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEVUiV
WRQcAve1ssYN0qaFWP33pYRLSV4SM6G0BB3SLiYnQKan8K0I7DtvOAoT8HOm0UyM
+6vNyedReg5PXHOuPjAKBggqhkjOPQQDAgNIADBFAiEAoSKLhFHcwFGSu1N4NxSq
p0bGI5J8WYfrdvWVZgWsV9MCIBeJzCEsegLdVBf/mn+4m7GNitMNzLj4CxTCnpqq
S1m1
-----END CERTIFICATE-----
8 changes: 8 additions & 0 deletions gateway/conf/server.key
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-----
MHcCAQEEIK9vyuYjAXWiI6QwoBwMs2BPKyY/46Qdd8ZFgTCA2YNRoAoGCCqGSM49
AwEHoUQDQgAEVUiVWRQcAve1ssYN0qaFWP33pYRLSV4SM6G0BB3SLiYnQKan8K0I
7DtvOAoT8HOm0UyM+6vNyedReg5PXHOuPg==
-----END EC PRIVATE KEY-----
2 changes: 1 addition & 1 deletion gateway/src/apicast/executor.lua
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ end
-- @tparam string phase Nginx phase
-- @treturn linked_list The context. Note: The list returned is 'read-write'.
function _M:context(phase)
if phase == 'init' then
if phase == 'init' or phase == 'ssl_certificate' then
return build_context(self)
end

Expand Down
2 changes: 2 additions & 0 deletions gateway/src/apicast/policy.lua
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ local PHASES = {
'content', 'balancer',
'header_filter', 'body_filter',
'post_action', 'log', 'metrics',

'ssl_certificate',
}

local setmetatable = setmetatable
Expand Down
11 changes: 7 additions & 4 deletions gateway/src/apicast/policy/find_service/find_service.lua
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
local policy = require('apicast.policy')
local _M = policy.new('Find Service Policy')
local Policy = require('apicast.policy')
local _M = Policy.new('Find Service Policy')
local configuration_store = require 'apicast.configuration_store'
local mapping_rules_matcher = require 'apicast.mapping_rules_matcher'
local new = _M.new
Expand Down Expand Up @@ -70,8 +70,11 @@ function _M.new(...)
return self
end

function _M:rewrite(context)
context.service = self.find_service(context.configuration, context.host)
local function find_service(policy, context)
context.service = policy.find_service(context.configuration, context.host)
end

_M.rewrite = find_service
_M.ssl_certificate = find_service

return _M
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
local _M = require('apicast.policy').new('Load Configuration')
local ssl = require('ngx.ssl')

local configuration_loader = require('apicast.configuration_loader').new()
local configuration_store = require('apicast.configuration_store')
Expand Down Expand Up @@ -30,4 +31,8 @@ function _M:rewrite(context)
context.configuration = configuration_loader.rewrite(self.configuration, context.host)
end

function _M.ssl_certificate(_, context)
context.host = ssl.server_name()
end

return _M
3 changes: 2 additions & 1 deletion spec/policy_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ describe('policy', function()
'rewrite', 'access',
'content', 'balancer',
'header_filter', 'body_filter',
'post_action', 'log', 'metrics'
'post_action', 'log', 'metrics',
'ssl_certificate',
}

describe('.new', function()
Expand Down
23 changes: 23 additions & 0 deletions t/fixtures/policies/https/builtin/init.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
local _M = require('apicast.policy').new('HTTPS', '1.0.0')
local ssl = require('ngx.ssl')
local new = _M.new

function _M.new(configuration)
local policy = new(configuration)

if configuration then
policy.certificate_chain = assert(ssl.parse_pem_cert(configuration.certificate))
policy.priv_key = assert(ssl.parse_pem_priv_key(configuration.key))
end

return policy
end

function _M:ssl_certificate()
assert(ssl.clear_certs())

assert(ssl.set_cert(self.certificate_chain))
assert(ssl.set_priv_key(self.priv_key))
end

return _M
64 changes: 63 additions & 1 deletion t/listen-https.t
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ run_tests();

__DATA__
=== TEST 1: Listen on HTTPS
--- ssl random_port
--- env eval
(
'APICAST_HTTPS_PORT' => "$Test::Nginx::Util::ServerPortForClient",
Expand Down Expand Up @@ -63,3 +62,66 @@ MHcCAQEEIH22v43xtXcHWJyH3BEB9N30ahrCOLripkoSWW/WujUxoAoGCCqGSM49
AwEHoUQDQgAEjchlS+kmxpBuIvL/J+2EkN3/4EhorMBuAwCKa2Hh486Ldr9ggLCw
fKrqwHFuC8x5PDE0kgel7e13i0FVnlavXQ==
-----END EC PRIVATE KEY-----



=== TEST 2: Listen on HTTPS with policy serving the certificate
--- env eval
(
'APICAST_HTTPS_PORT' => "$Test::Nginx::Util::ServerPortForClient",
'APICAST_POLICY_LOAD_PATH' => 't/fixtures/policies',
)
--- configuration
{
"services": [{
"proxy": {
"policy_chain": [
{ "name": "https", "configuration": {
"certificate": "-----BEGIN CERTIFICATE-----\nMIIBRzCB7gIJAPHi8uNGM8wDMAoGCCqGSM49BAMCMCwxFjAUBgNVBAoMDVRlc3Q6\nOkFQSWNhc3QxEjAQBgNVBAMMCWxvY2FsaG9zdDAeFw0xODA2MDUwOTQ0MjRaFw0y\nODA2MDIwOTQ0MjRaMCwxFjAUBgNVBAoMDVRlc3Q6OkFQSWNhc3QxEjAQBgNVBAMM\nCWxvY2FsaG9zdDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABI3IZUvpJsaQbiLy\n/yfthJDd/+BIaKzAbgMAimth4ePOi3a/YICwsHyq6sBxbgvMeTwxNJIHpe3td4tB\nVZ5Wr10wCgYIKoZIzj0EAwIDSAAwRQIhAPRkfbxowt0H7p5xZYpwoMKanUXz9eKQ\n0sGkOw+TqqGXAiAMKJRqtjnCF2LIjGygHG6BlgjM4NgIMDHteZPEr4qEmw==\n-----END CERTIFICATE-----",
"key": "-----BEGIN EC PARAMETERS-----\nBggqhkjOPQMBBw==\n-----END EC PARAMETERS-----\n-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIH22v43xtXcHWJyH3BEB9N30ahrCOLripkoSWW/WujUxoAoGCCqGSM49\nAwEHoUQDQgAEjchlS+kmxpBuIvL/J+2EkN3/4EhorMBuAwCKa2Hh486Ldr9ggLCw\nfKrqwHFuC8x5PDE0kgel7e13i0FVnlavXQ==\n-----END EC PRIVATE KEY-----" } },
{ "name": "apicast.policy.upstream",
"configuration": { "rules": [ { "regex": "/", "url": "http://echo" } ] } }
]
}
}]
}
--- test env
lua_ssl_trusted_certificate $TEST_NGINX_HTML_DIR/server.crt;

content_by_lua_block {
local sock = ngx.socket.tcp()
sock:settimeout(2000)

local ok, err = sock:connect(ngx.var.server_addr, ngx.var.apicast_port)
if not ok then
ngx.say("failed to connect: ", err)
return
end

ngx.say("connected: ", ok)

local sess, err = sock:sslhandshake(nil, "localhost", true)
if not sess then
ngx.say("failed to do SSL handshake: ", err)
return
end

ngx.say("ssl handshake: ", type(sess))
}
--- response_body
connected: 1
ssl handshake: userdata
--- error_code: 200
--- no_error_log
[error]
--- user_files
>>> server.crt
-----BEGIN CERTIFICATE-----
MIIBRzCB7gIJAPHi8uNGM8wDMAoGCCqGSM49BAMCMCwxFjAUBgNVBAoMDVRlc3Q6
OkFQSWNhc3QxEjAQBgNVBAMMCWxvY2FsaG9zdDAeFw0xODA2MDUwOTQ0MjRaFw0y
ODA2MDIwOTQ0MjRaMCwxFjAUBgNVBAoMDVRlc3Q6OkFQSWNhc3QxEjAQBgNVBAMM
CWxvY2FsaG9zdDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABI3IZUvpJsaQbiLy
/yfthJDd/+BIaKzAbgMAimth4ePOi3a/YICwsHyq6sBxbgvMeTwxNJIHpe3td4tB
VZ5Wr10wCgYIKoZIzj0EAwIDSAAwRQIhAPRkfbxowt0H7p5xZYpwoMKanUXz9eKQ
0sGkOw+TqqGXAiAMKJRqtjnCF2LIjGygHG6BlgjM4NgIMDHteZPEr4qEmw==
-----END CERTIFICATE-----

0 comments on commit 7c64dbb

Please sign in to comment.