This is an automated email from the ASF dual-hosted git repository. membphis pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/apisix.git
The following commit(s) were added to refs/heads/master by this push: new 12c9e6f feat: upstream grpcs support mTLS (#4070) 12c9e6f is described below commit 12c9e6f2670904c0daa19f47844dd61dae6496a5 Author: 罗泽轩 <spacewander...@gmail.com> AuthorDate: Tue Apr 20 18:08:13 2021 +0800 feat: upstream grpcs support mTLS (#4070) --- apisix/init.lua | 62 ++++++++++++++++++++++--------------- apisix/upstream.lua | 24 ++++++++++++-- ci/centos7-ci.sh | 7 +++-- ci/common.sh | 2 ++ ci/linux_openresty_common_runner.sh | 10 +++--- t/grpc-proxy-test.sh | 35 +++++++++++++++++++-- 6 files changed, 102 insertions(+), 38 deletions(-) diff --git a/apisix/init.lua b/apisix/init.lua index 70be796..24747fc 100644 --- a/apisix/init.lua +++ b/apisix/init.lua @@ -14,32 +14,33 @@ -- See the License for the specific language governing permissions and -- limitations under the License. -- -local require = require +local require = require require("apisix.patch").patch() -local core = require("apisix.core") -local plugin = require("apisix.plugin") -local plugin_config = require("apisix.plugin_config") -local script = require("apisix.script") -local service_fetch = require("apisix.http.service").get -local admin_init = require("apisix.admin.init") -local get_var = require("resty.ngxvar").fetch -local router = require("apisix.router") -local set_upstream = require("apisix.upstream").set_by_route -local upstream_util = require("apisix.utils.upstream") -local ctxdump = require("resty.ctxdump") -local ipmatcher = require("resty.ipmatcher") -local ngx = ngx -local get_method = ngx.req.get_method -local ngx_exit = ngx.exit -local math = math -local error = error -local ipairs = ipairs -local tostring = tostring -local ngx_now = ngx.now -local ngx_var = ngx.var -local str_byte = string.byte -local str_sub = string.sub -local tonumber = tonumber +local core = require("apisix.core") +local plugin = require("apisix.plugin") +local plugin_config = require("apisix.plugin_config") +local script = require("apisix.script") +local service_fetch = require("apisix.http.service").get +local admin_init = require("apisix.admin.init") +local get_var = require("resty.ngxvar").fetch +local router = require("apisix.router") +local apisix_upstream = require("apisix.upstream") +local set_upstream = apisix_upstream.set_by_route +local upstream_util = require("apisix.utils.upstream") +local ctxdump = require("resty.ctxdump") +local ipmatcher = require("resty.ipmatcher") +local ngx = ngx +local get_method = ngx.req.get_method +local ngx_exit = ngx.exit +local math = math +local error = error +local ipairs = ipairs +local tostring = tostring +local ngx_now = ngx.now +local ngx_var = ngx.var +local str_byte = string.byte +local str_sub = string.sub +local tonumber = tonumber local control_api_router if ngx.config.subsystem == "http" then control_api_router = require("apisix.control.router") @@ -488,6 +489,17 @@ end function _M.grpc_access_phase() ngx.ctx = ctxdump.apply_ngx_ctx(ngx_var.ctx_ref) + + local api_ctx = ngx.ctx.api_ctx + if not api_ctx then + return + end + + local code, err = apisix_upstream.set_grpcs_upstream_param(api_ctx) + if code then + core.log.error("failed to set grpcs upstream param: ", err) + core.response.exit(code) + end end diff --git a/apisix/upstream.lua b/apisix/upstream.lua index 5bcc679..488dfaf 100644 --- a/apisix/upstream.lua +++ b/apisix/upstream.lua @@ -291,7 +291,8 @@ function _M.set_by_route(route, api_ctx) api_ctx.up_checker = checker end - if up_conf.scheme == "https" and up_conf.tls then + local scheme = up_conf.scheme + if (scheme == "https" or scheme == "grpcs") and up_conf.tls then -- the sni here is just for logging local sni = api_ctx.var.upstream_host local cert, err = apisix_ssl.fetch_cert(sni, up_conf.tls.client_cert) @@ -304,13 +305,30 @@ function _M.set_by_route(route, api_ctx) return 503, err end + if scheme == "grpcs" then + api_ctx.upstream_grpcs_cert = cert + api_ctx.upstream_grpcs_key = key + else + local ok, err = set_upstream_tls_client_param(cert, key) + if not ok then + return 503, err + end + end + end + + return +end + + +function _M.set_grpcs_upstream_param(ctx) + if ctx.upstream_grpcs_cert then + local cert = ctx.upstream_grpcs_cert + local key = ctx.upstream_grpcs_key local ok, err = set_upstream_tls_client_param(cert, key) if not ok then return 503, err end end - - return end diff --git a/ci/centos7-ci.sh b/ci/centos7-ci.sh index 8a7fabc..b03d4d2 100755 --- a/ci/centos7-ci.sh +++ b/ci/centos7-ci.sh @@ -44,12 +44,15 @@ install_dependencies() { # install and start grpc_server_example mkdir build-cache - wget https://github.com/iresty/grpc_server_example/releases/download/20200901/grpc_server_example-amd64.tar.gz + wget https://github.com/api7/grpc_server_example/releases/download/"$GRPC_SERVER_EXAMPLE_VER"/grpc_server_example-amd64.tar.gz tar -xvf grpc_server_example-amd64.tar.gz mv grpc_server_example build-cache/ git clone https://github.com/iresty/grpc_server_example.git grpc_server_example cd grpc_server_example/ && mv proto/ ../build-cache/ && cd .. - ./build-cache/grpc_server_example > grpc_server_example.log 2>&1 || (cat grpc_server_example.log && exit 1)& + ./build-cache/grpc_server_example \ + -grpc-address :50051 -grpcs-address :50052 -grpcs-mtls-address :50053 \ + -crt ./t/certs/apisix.crt -key ./t/certs/apisix.key -ca ./t/certs/mtls_ca.crt \ + > grpc_server_example.log 2>&1 || (cat grpc_server_example.log && exit 1)& # wait for grpc_server_example to fully start sleep 3 diff --git a/ci/common.sh b/ci/common.sh index aec7082..26e7b6f 100644 --- a/ci/common.sh +++ b/ci/common.sh @@ -36,3 +36,5 @@ create_lua_deps() { # maybe reopen this feature later # luarocks install luacov-coveralls --tree=deps --local > build.log 2>&1 || (cat build.log && exit 1) } + +GRPC_SERVER_EXAMPLE_VER=20210417 diff --git a/ci/linux_openresty_common_runner.sh b/ci/linux_openresty_common_runner.sh index 5b501e0..34c3ecd 100755 --- a/ci/linux_openresty_common_runner.sh +++ b/ci/linux_openresty_common_runner.sh @@ -75,8 +75,8 @@ do_install() { cp ci/ASF* ci/openwhisk-utilities/scancode/ mkdir -p build-cache - if [ ! -f "build-cache/grpc_server_example_20210122" ]; then - wget https://github.com/api7/grpc_server_example/releases/download/20210122/grpc_server_example-amd64.tar.gz + if [ ! -f "build-cache/grpc_server_example_$GRPC_SERVER_EXAMPLE_VER" ]; then + wget https://github.com/api7/grpc_server_example/releases/download/"$GRPC_SERVER_EXAMPLE_VER"/grpc_server_example-amd64.tar.gz tar -xvf grpc_server_example-amd64.tar.gz mv grpc_server_example build-cache/ @@ -85,7 +85,7 @@ do_install() { mv proto/ ../build-cache/ popd || exit 1 - touch build-cache/grpc_server_example_20210122 + touch build-cache/grpc_server_example_"$GRPC_SERVER_EXAMPLE_VER" fi if [ ! -f "build-cache/grpcurl" ]; then @@ -102,8 +102,8 @@ script() { ./utils/set-dns.sh ./build-cache/grpc_server_example \ - -grpc-address :50051 -grpcs-address :50052 \ - -crt ./t/certs/apisix.crt -key ./t/certs/apisix.key \ + -grpc-address :50051 -grpcs-address :50052 -grpcs-mtls-address :50053 \ + -crt ./t/certs/apisix.crt -key ./t/certs/apisix.key -ca ./t/certs/mtls_ca.crt \ & # listen 9081 for http2 with plaintext diff --git a/t/grpc-proxy-test.sh b/t/grpc-proxy-test.sh index c6e294c..b6574cd 100755 --- a/t/grpc-proxy-test.sh +++ b/t/grpc-proxy-test.sh @@ -16,6 +16,12 @@ # limitations under the License. # +clean_up() { + #delete test data + curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X DELETE + curl http://127.0.0.1:9080/apisix/admin/ssl/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X DELETE +} + set -ex # ensure grpc server example is already started @@ -88,6 +94,29 @@ curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f1 ./build-cache/grpcurl -insecure -import-path ./build-cache/proto -proto helloworld.proto -d '{"name":"apisix"}' test.com:9443 helloworld.Greeter.SayHello | grep 'Hello apisix' -#delete test data -curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X DELETE -curl http://127.0.0.1:9080/apisix/admin/ssl/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X DELETE +if ! openresty -V 2>&1 | grep "apisix-nginx-module"; then + echo "skip vanilla OpenResty" + clean_up + exit 0 +fi + +#test grpcs with mTLS proxy +curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d ' +{ + "methods": ["POST"], + "uri": "/helloworld.Greeter/SayHello", + "upstream": { + "scheme": "grpcs", + "tls": { + "client_cert": "-----BEGIN CERTIFICATE-----\nMIIDOjCCAiICAwD6zzANBgkqhkiG9w0BAQsFADBnMQswCQYDVQQGEwJjbjESMBAG\nA1UECAwJR3VhbmdEb25nMQ8wDQYDVQQHDAZaaHVIYWkxDTALBgNVBAoMBGFwaTcx\nDDAKBgNVBAsMA29wczEWMBQGA1UEAwwNY2EuYXBpc2l4LmRldjAeFw0yMDA2MjAx\nMzE1MDBaFw0zMDA3MDgxMzE1MDBaMF0xCzAJBgNVBAYTAmNuMRIwEAYDVQQIDAlH\ndWFuZ0RvbmcxDTALBgNVBAoMBGFwaTcxDzANBgNVBAcMBlpodUhhaTEaMBgGA1UE\nAwwRY2xpZW50LmFwaXNpeC5kZXYwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK\nAoIBAQCfKI8uiEH/ifZikSnRa3/E2B4ohVWRwjo [...] + "client_key": "-----BEGIN RSA PRIVATE KEY-----\nMIIEpAIBAAKCAQEAnyiPLohB/4n2YpEp0Wt/xNgeKIVVkcI6PyMcgxFqJoEeLS5N\naUiYT/+Egi1rjEExVk20qrdSBWMuGW1Uhx8hqDT5iRqx0SQhhPrIKX859Bo1eJV0\nDyQ9JOhkdQl9jKNU1nRakifx3OQEMHEBZz36CwMLAcuMqq5Zn/emQFMrZf+2ZI3+\nD+5iZCR7TP1oEkdKRoY2UwBkX+QyVqDudZIt4tySPteZjoZp5wqZ5LJxlT35fdqv\ndh8/+L94qhPlE4T2EaXBm53XczLz2gl4mr4PAf7ti1W5+JdGnWpqkBnqTgIw/9ca\n2jlT9lttltD87Q1yeKy3vnGqTUuKBrklH5CBDQIDAQABAoIBAHDe5bPdQ9jCcW3z\nfpGax/DER5b6//UvpfkSoGy/E+Wcmdb2yEVL [...] + }, + "type": "roundrobin", + "nodes": { + "127.0.0.1:50053": 1 + } + } +}' + +./build-cache/grpcurl -insecure -import-path ./build-cache/proto -proto helloworld.proto -d '{"name":"apisix"}' test.com:9443 helloworld.Greeter.SayHello | grep 'Hello apisix' +clean_up