diff --git a/apisix/cli/file.lua b/apisix/cli/file.lua index 36873631a84c..90ed7d89b4f3 100644 --- a/apisix/cli/file.lua +++ b/apisix/cli/file.lua @@ -328,7 +328,7 @@ function _M.read_yaml_conf(apisix_home) -- Therefore we need to check the absolute version instead local cert_path = pl_path.abspath(apisix_ssl.ssl_trusted_certificate) if not pl_path.exists(cert_path) then - util.die("certificate path", cert_path, "doesn't exist\n") + util.die("certificate path ", cert_path, " doesn't exist\n") end apisix_ssl.ssl_trusted_certificate = cert_path end diff --git a/apisix/init.lua b/apisix/init.lua index 5fc874254449..84c1ebc5a714 100644 --- a/apisix/init.lua +++ b/apisix/init.lua @@ -552,9 +552,22 @@ function _M.handle_upstream(api_ctx, route, enable_websocket) return ngx_exit(1) end + local new_upstream_ssl = apisix_secret.fetch_secrets(upstream_ssl, true) + + if not new_upstream_ssl then + core.log.error("failed to get ssl cert: error fetching secrets") + + if is_http then + return core.response.exit(502) + end + + return ngx_exit(1) + end + core.log.info("matched ssl: ", core.json.delay_encode(upstream_ssl, true)) - api_ctx.upstream_ssl = upstream_ssl + + api_ctx.upstream_ssl = new_upstream_ssl end if enable_websocket then diff --git a/t/node/upstream-mtls.t b/t/node/upstream-mtls.t index 998543e25aff..62d4c15a200a 100644 --- a/t/node/upstream-mtls.t +++ b/t/node/upstream-mtls.t @@ -14,6 +14,22 @@ # See the License for the specific language governing permissions and # limitations under the License. # + +BEGIN { + sub set_env_from_file { + my ($env_name, $file_path) = @_; + + open my $fh, '<', $file_path or die $!; + my $content = do { local $/; <$fh> }; + close $fh; + + $ENV{$env_name} = $content; + } + # set env + set_env_from_file('MTLS_CERT_VAR', 't/certs/mtls_client.crt'); + set_env_from_file('MTLS_KEY_VAR', 't/certs/mtls_client.key'); +} + use t::APISIX; my $nginx_binary = $ENV{'TEST_NGINX_BINARY'} || 'nginx'; @@ -38,7 +54,17 @@ run_tests(); __DATA__ -=== TEST 1: tls without key +=== TEST 1: store cert and key in vault +--- exec +VAULT_TOKEN='root' VAULT_ADDR='http://0.0.0.0:8200' vault kv put kv/apisix/ssl \ + mtls_client.crt=@t/certs/mtls_client.crt \ + mtls_client.key=@t/certs/mtls_client.key +--- response_body +Success! Data written to: kv/apisix/ssl + + + +=== TEST 2: tls without key --- config location /t { content_by_lua_block { @@ -77,7 +103,7 @@ GET /t -=== TEST 2: tls with bad key +=== TEST 3: tls with bad key --- config location /t { content_by_lua_block { @@ -119,7 +145,7 @@ decrypt ssl key failed -=== TEST 3: encrypt key by default +=== TEST 4: encrypt key by default --- config location /t { content_by_lua_block { @@ -248,7 +274,7 @@ false -=== TEST 4: hit +=== TEST 5: hit --- upstream_server_config ssl_client_certificate ../../certs/mtls_ca.crt; ssl_verify_client on; @@ -259,7 +285,7 @@ hello world -=== TEST 5: wrong cert +=== TEST 6: wrong cert --- config location /t { content_by_lua_block { @@ -300,7 +326,7 @@ passed -=== TEST 6: hit +=== TEST 7: hit --- upstream_server_config ssl_client_certificate ../../certs/mtls_ca.crt; ssl_verify_client on; @@ -312,7 +338,7 @@ client SSL certificate verify error -=== TEST 7: clean old data +=== TEST 8: clean old data --- config location /t { content_by_lua_block { @@ -333,7 +359,7 @@ GET /t -=== TEST 8: don't encrypt key +=== TEST 9: don't encrypt key --- yaml_config apisix: node_listen: 1984 @@ -467,7 +493,7 @@ true -=== TEST 9: bind upstream +=== TEST 10: bind upstream --- config location /t { content_by_lua_block { @@ -494,7 +520,7 @@ GET /t -=== TEST 10: hit +=== TEST 11: hit --- upstream_server_config ssl_client_certificate ../../certs/mtls_ca.crt; ssl_verify_client on; @@ -505,7 +531,7 @@ GET /server_port -=== TEST 11: bind service +=== TEST 12: bind service --- config location /t { content_by_lua_block { @@ -532,7 +558,7 @@ GET /t -=== TEST 12: hit +=== TEST 13: hit --- upstream_server_config ssl_client_certificate ../../certs/mtls_ca.crt; ssl_verify_client on; @@ -543,7 +569,7 @@ hello world -=== TEST 13: get cert by tls.client_cert_id +=== TEST 14: get cert by tls.client_cert_id --- config location /t { content_by_lua_block { @@ -598,7 +624,7 @@ GET /t -=== TEST 14: hit +=== TEST 15: hit --- upstream_server_config ssl_client_certificate ../../certs/mtls_ca.crt; ssl_verify_client on; @@ -609,7 +635,7 @@ hello world -=== TEST 15: change ssl object type +=== TEST 16: change ssl object type --- config location /t { content_by_lua_block { @@ -640,7 +666,7 @@ GET /t -=== TEST 16: hit, ssl object type mismatch +=== TEST 17: hit, ssl object type mismatch --- upstream_server_config ssl_client_certificate ../../certs/mtls_ca.crt; ssl_verify_client on; @@ -652,7 +678,7 @@ failed to get ssl cert: ssl type should be 'client' -=== TEST 17: delete ssl object +=== TEST 18: delete ssl object --- config location /t { content_by_lua_block { @@ -673,7 +699,7 @@ GET /t -=== TEST 18: hit, ssl object not exits +=== TEST 19: hit, ssl object not exits --- upstream_server_config ssl_client_certificate ../../certs/mtls_ca.crt; ssl_verify_client on; @@ -685,7 +711,7 @@ failed to get ssl cert: ssl id [1] not exits -=== TEST 19: `tls.verify` only +=== TEST 20: `tls.verify` only --- config location /t { content_by_lua_block { @@ -723,7 +749,7 @@ passed -=== TEST 20: hit +=== TEST 21: hit When only `tls.verify` is present, the matching logic related to `client_cert`, `client_key` or `client_cert_id` should not be entered --- request @@ -733,7 +759,7 @@ hello world -=== TEST 21: set `verify` with `client_cert`, `client_key` +=== TEST 22: set `verify` with `client_cert`, `client_key` --- config location /t { content_by_lua_block { @@ -774,7 +800,7 @@ passed -=== TEST 22: hit +=== TEST 23: hit `tls.verify` does not affect the parsing of `client_cert`, `client_key` --- upstream_server_config ssl_client_certificate ../../certs/mtls_ca.crt; @@ -783,3 +809,125 @@ passed GET /hello --- response_body hello world + +=== TEST 24: get cert by tls.client_cert_id with secrets using secrets +--- config + location /t { + content_by_lua_block { + local t = require("lib.test_admin") + local json = require("toolkit.json") + + local data = { + type = "client", + cert = "$secret://vault/test/ssl/mtls_client.crt", + key = "$secret://vault/test/ssl/mtls_client.key" + } + local code, body = t.test('/apisix/admin/ssls/1', + ngx.HTTP_PUT, + json.encode(data) + ) + + if code >= 300 then + ngx.status = code + ngx.say(body) + return + end + + local data = { + upstream = { + scheme = "https", + type = "roundrobin", + nodes = { + ["127.0.0.1:1983"] = 1, + }, + tls = { + client_cert_id = 1 + } + }, + uri = "/hello" + } + local code, body = t.test('/apisix/admin/routes/1', + ngx.HTTP_PUT, + json.encode(data) + ) + + if code >= 300 then + ngx.status = code + ngx.say(body) + return + end + } + } +--- request +GET /t + + +=== TEST 25: hit +--- upstream_server_config + ssl_client_certificate ../../certs/mtls_ca.crt; + ssl_verify_client on; +--- request +GET /hello +--- response_body +hello world + +=== TEST 26: get cert by tls.client_cert_id with secrets using env +--- config + location /t { + content_by_lua_block { + local t = require("lib.test_admin") + local json = require("toolkit.json") + + local data = { + type = "client", + cert = "$env://MTLS_CERT_VAR", + key = "$env://MTLS_KEY_VAR" + } + local code, body = t.test('/apisix/admin/ssls/1', + ngx.HTTP_PUT, + json.encode(data) + ) + + if code >= 300 then + ngx.status = code + ngx.say(body) + return + end + + local data = { + upstream = { + scheme = "https", + type = "roundrobin", + nodes = { + ["127.0.0.1:1983"] = 1, + }, + tls = { + client_cert_id = 1 + } + }, + uri = "/hello" + } + local code, body = t.test('/apisix/admin/routes/1', + ngx.HTTP_PUT, + json.encode(data) + ) + + if code >= 300 then + ngx.status = code + ngx.say(body) + return + end + } + } +--- request +GET /t + + +=== TEST 27: hit +--- upstream_server_config + ssl_client_certificate ../../certs/mtls_ca.crt; + ssl_verify_client on; +--- request +GET /hello +--- response_body +hello world