Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@ jobs:
- name: apisix-runtime
script_url: "https://raw.githubusercontent.com/api7/apisix-build-tools/master/build-apisix-runtime.sh"
script_name: "build-apisix-runtime.sh"
exclude_tests: ""
# These assert stream-lua internal buffer-allocation debug logs that
# changed in OpenResty 1.29.2.4 (stream-lua 0.0.19); they still run on
# api7ee-runtime (OR 1.21, stream-lua 0.0.16) for functional coverage.
exclude_tests: "t/stream/xrpc/downstream.t t/stream/xrpc/upstream.t"
- name: api7ee-runtime
script_url: "https://raw.githubusercontent.com/api7/apisix-build-tools/release/api7ee-runtime/build-api7ee-runtime.sh"
script_name: "build-api7ee-runtime.sh"
Expand Down
17 changes: 17 additions & 0 deletions lib/resty/apisix/stream/upstream.lua
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ ffi.cdef([[
typedef intptr_t ngx_int_t;
ngx_int_t
ngx_stream_apisix_upstream_enable_tls(ngx_stream_lua_request_t *r);
ngx_int_t
ngx_stream_apisix_upstream_set_cert_and_key(ngx_stream_lua_request_t *r, void *cert, void *key);
]])
local _M = {}

Expand All @@ -30,4 +32,19 @@ function _M.set_tls()
end


function _M.set_cert_and_key(cert, key)
if not cert or not key then
return nil, "both client certificate and private key should be given"
end

local r = get_request()
local ret = C.ngx_stream_apisix_upstream_set_cert_and_key(r, cert, key)
if ret == NGX_ERROR then
return nil, "error while setting upstream client cert and key"
end

return true
end


return _M
15 changes: 15 additions & 0 deletions patch/1.19.9/nginx-stream_upstream_mtls.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
diff --git src/stream/ngx_stream_proxy_module.c src/stream/ngx_stream_proxy_module.c
--- src/stream/ngx_stream_proxy_module.c
+++ src/stream/ngx_stream_proxy_module.c
@@ -1219,7 +1219,11 @@ ngx_stream_proxy_ssl_init_connection(ngx_stream_session_t *s)
}

s->connection->log->action = "SSL handshaking to upstream";

+#if (NGX_STREAM_APISIX)
+ ngx_stream_apisix_set_upstream_ssl(s, pc);
+#endif
+
rc = ngx_ssl_handshake(pc);

if (rc == NGX_AGAIN) {
15 changes: 15 additions & 0 deletions patch/1.21.4.1/nginx-stream_upstream_mtls.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
diff --git src/stream/ngx_stream_proxy_module.c src/stream/ngx_stream_proxy_module.c
--- src/stream/ngx_stream_proxy_module.c
+++ src/stream/ngx_stream_proxy_module.c
@@ -1219,7 +1219,11 @@ ngx_stream_proxy_ssl_init_connection(ngx_stream_session_t *s)
}

s->connection->log->action = "SSL handshaking to upstream";

+#if (NGX_STREAM_APISIX)
+ ngx_stream_apisix_set_upstream_ssl(s, pc);
+#endif
+
rc = ngx_ssl_handshake(pc);

if (rc == NGX_AGAIN) {
15 changes: 15 additions & 0 deletions patch/1.21.4/nginx-stream_upstream_mtls.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
diff --git src/stream/ngx_stream_proxy_module.c src/stream/ngx_stream_proxy_module.c
--- src/stream/ngx_stream_proxy_module.c
+++ src/stream/ngx_stream_proxy_module.c
@@ -1219,7 +1219,11 @@ ngx_stream_proxy_ssl_init_connection(ngx_stream_session_t *s)
}

s->connection->log->action = "SSL handshaking to upstream";

+#if (NGX_STREAM_APISIX)
+ ngx_stream_apisix_set_upstream_ssl(s, pc);
+#endif
+
rc = ngx_ssl_handshake(pc);

if (rc == NGX_AGAIN) {
15 changes: 15 additions & 0 deletions patch/1.25.3.1/nginx-stream_upstream_mtls.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
diff --git src/stream/ngx_stream_proxy_module.c src/stream/ngx_stream_proxy_module.c
--- src/stream/ngx_stream_proxy_module.c
+++ src/stream/ngx_stream_proxy_module.c
@@ -1219,7 +1219,11 @@ ngx_stream_proxy_ssl_init_connection(ngx_stream_session_t *s)
}

s->connection->log->action = "SSL handshaking to upstream";

+#if (NGX_STREAM_APISIX)
+ ngx_stream_apisix_set_upstream_ssl(s, pc);
+#endif
+
rc = ngx_ssl_handshake(pc);

if (rc == NGX_AGAIN) {
15 changes: 15 additions & 0 deletions patch/1.27.1.1/nginx-stream_upstream_mtls.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
diff --git src/stream/ngx_stream_proxy_module.c src/stream/ngx_stream_proxy_module.c
--- src/stream/ngx_stream_proxy_module.c
+++ src/stream/ngx_stream_proxy_module.c
@@ -1219,7 +1219,11 @@ ngx_stream_proxy_ssl_init_connection(ngx_stream_session_t *s)
}

s->connection->log->action = "SSL handshaking to upstream";

+#if (NGX_STREAM_APISIX)
+ ngx_stream_apisix_set_upstream_ssl(s, pc);
+#endif
+
rc = ngx_ssl_handshake(pc);

if (rc == NGX_AGAIN) {
15 changes: 15 additions & 0 deletions patch/1.29.2.4/nginx-stream_upstream_mtls.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
diff --git src/stream/ngx_stream_proxy_module.c src/stream/ngx_stream_proxy_module.c
--- src/stream/ngx_stream_proxy_module.c
+++ src/stream/ngx_stream_proxy_module.c
@@ -1219,7 +1219,11 @@ ngx_stream_proxy_ssl_init_connection(ngx_stream_session_t *s)
}

s->connection->log->action = "SSL handshaking to upstream";

+#if (NGX_STREAM_APISIX)
+ ngx_stream_apisix_set_upstream_ssl(s, pc);
+#endif
+
rc = ngx_ssl_handshake(pc);

if (rc == NGX_AGAIN) {
207 changes: 203 additions & 4 deletions src/stream/ngx_stream_apisix_module.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@


typedef struct {
#if (NGX_STREAM_SSL)
STACK_OF(X509) *upstream_cert;
EVP_PKEY *upstream_pkey;
#endif
unsigned proxy_ssl_enabled:1;
} ngx_stream_apisix_ctx_t;

Expand Down Expand Up @@ -36,21 +40,89 @@ ngx_module_t ngx_stream_apisix_module = {
};


ngx_int_t
ngx_stream_apisix_upstream_enable_tls(ngx_stream_lua_request_t *r)
#if (NGX_STREAM_SSL)

static X509 *
ngx_stream_apisix_x509_copy(const X509 *in)
{
ngx_stream_apisix_ctx_t *ctx;
return X509_up_ref((X509 *) in) == 0 ? NULL : (X509 *) in;
}


static void
ngx_stream_apisix_flush_ssl_error(void)
{
ERR_clear_error();
}


static void
ngx_stream_apisix_cleanup_cert_and_key(ngx_stream_apisix_ctx_t *ctx)
{
if (ctx->upstream_cert != NULL) {
sk_X509_pop_free(ctx->upstream_cert, X509_free);
EVP_PKEY_free(ctx->upstream_pkey);

ctx->upstream_cert = NULL;
ctx->upstream_pkey = NULL;
}
}


static void
ngx_stream_apisix_cleanup(void *data)
{
ngx_stream_apisix_ctx_t *ctx = data;

ngx_stream_apisix_cleanup_cert_and_key(ctx);
}

#endif


static ngx_stream_apisix_ctx_t *
ngx_stream_apisix_get_module_ctx(ngx_stream_lua_request_t *r)
{
ngx_stream_apisix_ctx_t *ctx;
#if (NGX_STREAM_SSL)
ngx_pool_cleanup_t *cln;
#endif

ctx = ngx_stream_lua_get_module_ctx(r, ngx_stream_apisix_module);

if (ctx == NULL) {
ctx = ngx_pcalloc(r->pool, sizeof(ngx_stream_apisix_ctx_t));
if (ctx == NULL) {
return NGX_ERROR;
return NULL;
}

#if (NGX_STREAM_SSL)
cln = ngx_pool_cleanup_add(r->pool, 0);
if (cln == NULL) {
return NULL;
}

cln->data = ctx;
cln->handler = ngx_stream_apisix_cleanup;
#endif

ngx_stream_lua_set_ctx(r, ctx, ngx_stream_apisix_module);
}

return ctx;
}


ngx_int_t
ngx_stream_apisix_upstream_enable_tls(ngx_stream_lua_request_t *r)
{
ngx_stream_apisix_ctx_t *ctx;

ctx = ngx_stream_apisix_get_module_ctx(r);
if (ctx == NULL) {
return NGX_ERROR;
}

ctx->proxy_ssl_enabled = 1;

return NGX_OK;
Expand All @@ -66,3 +138,130 @@ ngx_stream_apisix_is_proxy_ssl_enabled(ngx_stream_session_t *s)

return ctx != NULL && ctx->proxy_ssl_enabled;
}


#if (NGX_STREAM_SSL)

ngx_int_t
ngx_stream_apisix_upstream_set_cert_and_key(ngx_stream_lua_request_t *r,
void *data_cert, void *data_key)
{
STACK_OF(X509) *cert = data_cert;
EVP_PKEY *key = data_key;
STACK_OF(X509) *new_chain;
ngx_stream_apisix_ctx_t *ctx;

if (cert == NULL || key == NULL) {
return NGX_ERROR;
}

ctx = ngx_stream_apisix_get_module_ctx(r);

if (ctx == NULL) {
return NGX_ERROR;
}

if (ctx->upstream_cert != NULL) {
ngx_stream_apisix_cleanup_cert_and_key(ctx);
}

if (EVP_PKEY_up_ref(key) == 0) {
goto failed;
}

new_chain = sk_X509_deep_copy(cert, ngx_stream_apisix_x509_copy,
X509_free);
if (new_chain == NULL) {
EVP_PKEY_free(key);
goto failed;
}

ctx->upstream_cert = new_chain;
ctx->upstream_pkey = key;

return NGX_OK;

failed:

ngx_stream_apisix_flush_ssl_error();

return NGX_ERROR;
}


void
ngx_stream_apisix_set_upstream_ssl(ngx_stream_session_t *s, ngx_connection_t *c)
{
ngx_ssl_conn_t *sc = c->ssl->connection;
ngx_stream_apisix_ctx_t *ctx;
STACK_OF(X509) *cert;
EVP_PKEY *pkey;
X509 *x509;
#ifdef OPENSSL_IS_BORINGSSL
size_t i;
#else
int i;
#endif

ctx = ngx_stream_get_module_ctx(s, ngx_stream_apisix_module);

if (ctx == NULL) {
ngx_log_debug0(NGX_LOG_DEBUG_STREAM, c->log, 0,
"skip overriding upstream SSL configuration, "
"module ctx not set");
return;
}

if (ctx->upstream_cert != NULL) {
cert = ctx->upstream_cert;
pkey = ctx->upstream_pkey;

if (sk_X509_num(cert) < 1) {
ngx_ssl_error(NGX_LOG_ERR, c->log, 0,
"invalid client certificate provided while "
"handshaking with upstream");
goto failed;
}

x509 = sk_X509_value(cert, 0);
if (x509 == NULL) {
ngx_ssl_error(NGX_LOG_ERR, c->log, 0, "sk_X509_value() failed");
goto failed;
}

if (SSL_use_certificate(sc, x509) == 0) {
ngx_ssl_error(NGX_LOG_ERR, c->log, 0,
"SSL_use_certificate() failed");
goto failed;
}

for (i = 1; i < sk_X509_num(cert); i++) {
x509 = sk_X509_value(cert, i);
if (x509 == NULL) {
ngx_ssl_error(NGX_LOG_ERR, c->log, 0,
"sk_X509_value() failed");
goto failed;
}

if (SSL_add1_chain_cert(sc, x509) == 0) {
ngx_ssl_error(NGX_LOG_ERR, c->log, 0,
"SSL_add1_chain_cert() failed");
goto failed;
}
}

if (SSL_use_PrivateKey(sc, pkey) == 0) {
ngx_ssl_error(NGX_LOG_ERR, c->log, 0,
"SSL_use_PrivateKey() failed");
goto failed;
}
}

return;

failed:

ngx_stream_apisix_flush_ssl_error();
}

#endif
5 changes: 5 additions & 0 deletions src/stream/ngx_stream_apisix_module.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,10 @@

ngx_int_t ngx_stream_apisix_is_proxy_ssl_enabled(ngx_stream_session_t *s);

#if (NGX_STREAM_SSL)
void ngx_stream_apisix_set_upstream_ssl(ngx_stream_session_t *s,
ngx_connection_t *c);
#endif


#endif /* _NGX_STREAM_APISIX_H_INCLUDED_ */
Loading
Loading