从 openresty 发出 https tls 请求 lua
Making an https tls request from openresty lua
我正在尝试找到一种方法,从我的 nginx/lua 模块中向服务器发出安全的 GET 请求,以检查入口调用的身份验证。关于如何做到这一点似乎很少。我目前的尝试主要围绕使用 resty.http 和以下内容。
-- Create http client
local httpc = http.new();
httpc:set_timeout(500)
ngx.log(ngx.DEBUG, '**** Connect with TLS ****');
ok, err = httpc:connect(my_server, port);
my_server 但是在输入时需要证书、ca 和密钥,但再次不确定如何使用 ["ca"] = myca.pem;等等...不起作用。如果我设置
lua_ssl_trusted_certificate=myca.pem
请求失败并显示以下内容:
2018/02/23 19:22:17 [crit] 19#0: *4 SSL_shutdown() failed (SSL: error:140E0197:SSL routines:SSL_shutdown:shutdown while in init), client: 127.0.0.1, server: my_server
我查看了 https://github.com/brunoos/luasec/archive/luasec-0.6,但坦率地说无法在我的高山 linux 容器上进行干净编译。
不确定此时要使用哪个模块或如何进行,有什么想法吗?
更新
基于评论和我收到的答案的附加信息。尝试使用 openresty pintsized lua-resty-http 与 https 失败,目前没有办法获得 cert/key/ca 相互 TLS 流工作。使用下面的答案,我能够配置对我的后端应用程序微服务的上游代理调用,以正确地为请求提供服务。
我的 proxy.conf 文件片段让这个工作看起来像 followwing。 注意: 上游服务器必须与证书中的 CN 相匹配,否则它将无法工作,或者至少我在证书失败时一无所获。
http {
# Upstream backend for services
upstream apimy {
server apimy:3003;
}
...
location /api/analytics/token-info {
internal; # Specifies that a given location can only be used for internal requests
set $bearerToken $arg_token;
set $args "";
proxy_pass_request_headers on;
proxy_ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
proxy_ssl_ciphers HIGH:!aNULL:!MD5;
proxy_ssl_certificate /etc/certs/analytics_proxy_client_public.cert.pem;
proxy_ssl_certificate_key /etc/certs/analytics_proxy_client_private.key.pem;
proxy_ssl_trusted_certificate /etc/certs/analytics_proxy_client_ca.cert.pem;
proxy_ssl_verify on;
proxy_ssl_verify_depth 2;
proxy_ssl_session_reuse off;
proxy_set_header Host apimy;
proxy_set_header Content-Type "application/json";
proxy_set_header Accept "application/json";
proxy_set_header Authorization "Bearer $bearerToken";
proxy_pass https://apimy/api/analytics/token-info; # trailing slash
}
另一个注意事项,无论我无法让 bearerToken 工作,从 lua 端将其作为 vars 传递,我必须将其作为 arg 传递,然后清除 args所以任何其他人都没有被传递到电话中。
我的 lua 调用路径的代码。
-- Connect --
ngx.log(ngx.DEBUG, '**** Connect with TLS ****');
res = ngx.location.capture('/api/analytics/token-info',
{
method = ngx.HTTP_POST,
body = json.encode(query),
args = {
token = accessToken;
}
})
忘记 luasec,你最后的代码片段没有意义。
LuaSec 与 LuaSocket 兼容,但显然与 nginx cosocket 不兼容 API。
使用通用 resty-http request_uri()
接口:
local http = require "resty.http"
local httpc = http.new()
local res, err = httpc:request_uri("https://example.com:443/helloworld", {
method = "POST",
body = "a=1&b=2",
headers = {
["Content-Type"] = "application/x-www-form-urlencoded",
},
ssl_verify = true
})
顺便说一句,request_uri() source 是如何使用泛型 resty-http API (connect/ssl_handshake/request)
的完美示例
更新:
如果您确实需要通过证书对客户端进行身份验证,您可以使用下一种方法:
创建上游,配置客户端证书:
location /my_upstream/ {
internal; # Specifies that a given location can only be used for internal requests
proxy_pass_request_headers off;
proxy_set_header Host backend.example.com;
proxy_set_header Content-Type "application/json";
proxy_set_header Accept "application/json";
proxy_set_header Authorization "Bearer $bearerToken"
proxy_pass https://backend.example.com/; # trailing slash
proxy_ssl_certificate /etc/nginx/client.pem;
proxy_ssl_certificate_key /etc/nginx/client.key
proxy_ssl_verify on;
proxy_ssl_verify_depth 2; #just example
proxy_ssl_trusted_certificate /etc/nginx/ca.pem;
}
使用ngx.location.captureAPI发出一个同步但仍然non-blocking的Nginx子请求:
local res = ngx.location.capture('/my_upstream/login',
{
method = ngx.HTTP_POST,
body = "some text",
vars = {
bearerToken = "12345"
}
})
请不要泛滥,RTFM 关于 ngx.location.capture API 和 proxy_pass
的所有细节
PS:查看您的上次更新 - 不敢相信有人会同时需要客户端证书和令牌授权。
通常没有客户端证书的 HTTPS 用于安全传输和授权 header 使用令牌进行身份验证。
我正在尝试找到一种方法,从我的 nginx/lua 模块中向服务器发出安全的 GET 请求,以检查入口调用的身份验证。关于如何做到这一点似乎很少。我目前的尝试主要围绕使用 resty.http 和以下内容。
-- Create http client
local httpc = http.new();
httpc:set_timeout(500)
ngx.log(ngx.DEBUG, '**** Connect with TLS ****');
ok, err = httpc:connect(my_server, port);
my_server 但是在输入时需要证书、ca 和密钥,但再次不确定如何使用 ["ca"] = myca.pem;等等...不起作用。如果我设置
lua_ssl_trusted_certificate=myca.pem
请求失败并显示以下内容:
2018/02/23 19:22:17 [crit] 19#0: *4 SSL_shutdown() failed (SSL: error:140E0197:SSL routines:SSL_shutdown:shutdown while in init), client: 127.0.0.1, server: my_server
我查看了 https://github.com/brunoos/luasec/archive/luasec-0.6,但坦率地说无法在我的高山 linux 容器上进行干净编译。 不确定此时要使用哪个模块或如何进行,有什么想法吗?
更新 基于评论和我收到的答案的附加信息。尝试使用 openresty pintsized lua-resty-http 与 https 失败,目前没有办法获得 cert/key/ca 相互 TLS 流工作。使用下面的答案,我能够配置对我的后端应用程序微服务的上游代理调用,以正确地为请求提供服务。 我的 proxy.conf 文件片段让这个工作看起来像 followwing。 注意: 上游服务器必须与证书中的 CN 相匹配,否则它将无法工作,或者至少我在证书失败时一无所获。
http {
# Upstream backend for services
upstream apimy {
server apimy:3003;
}
...
location /api/analytics/token-info {
internal; # Specifies that a given location can only be used for internal requests
set $bearerToken $arg_token;
set $args "";
proxy_pass_request_headers on;
proxy_ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
proxy_ssl_ciphers HIGH:!aNULL:!MD5;
proxy_ssl_certificate /etc/certs/analytics_proxy_client_public.cert.pem;
proxy_ssl_certificate_key /etc/certs/analytics_proxy_client_private.key.pem;
proxy_ssl_trusted_certificate /etc/certs/analytics_proxy_client_ca.cert.pem;
proxy_ssl_verify on;
proxy_ssl_verify_depth 2;
proxy_ssl_session_reuse off;
proxy_set_header Host apimy;
proxy_set_header Content-Type "application/json";
proxy_set_header Accept "application/json";
proxy_set_header Authorization "Bearer $bearerToken";
proxy_pass https://apimy/api/analytics/token-info; # trailing slash
}
另一个注意事项,无论我无法让 bearerToken 工作,从 lua 端将其作为 vars 传递,我必须将其作为 arg 传递,然后清除 args所以任何其他人都没有被传递到电话中。 我的 lua 调用路径的代码。
-- Connect --
ngx.log(ngx.DEBUG, '**** Connect with TLS ****');
res = ngx.location.capture('/api/analytics/token-info',
{
method = ngx.HTTP_POST,
body = json.encode(query),
args = {
token = accessToken;
}
})
忘记 luasec,你最后的代码片段没有意义。
LuaSec 与 LuaSocket 兼容,但显然与 nginx cosocket 不兼容 API。
使用通用 resty-http request_uri()
接口:
local http = require "resty.http"
local httpc = http.new()
local res, err = httpc:request_uri("https://example.com:443/helloworld", {
method = "POST",
body = "a=1&b=2",
headers = {
["Content-Type"] = "application/x-www-form-urlencoded",
},
ssl_verify = true
})
顺便说一句,request_uri() source 是如何使用泛型 resty-http API (connect/ssl_handshake/request)
的完美示例更新:
如果您确实需要通过证书对客户端进行身份验证,您可以使用下一种方法:
创建上游,配置客户端证书:
location /my_upstream/ {
internal; # Specifies that a given location can only be used for internal requests
proxy_pass_request_headers off;
proxy_set_header Host backend.example.com;
proxy_set_header Content-Type "application/json";
proxy_set_header Accept "application/json";
proxy_set_header Authorization "Bearer $bearerToken"
proxy_pass https://backend.example.com/; # trailing slash
proxy_ssl_certificate /etc/nginx/client.pem;
proxy_ssl_certificate_key /etc/nginx/client.key
proxy_ssl_verify on;
proxy_ssl_verify_depth 2; #just example
proxy_ssl_trusted_certificate /etc/nginx/ca.pem;
}
使用ngx.location.captureAPI发出一个同步但仍然non-blocking的Nginx子请求:
local res = ngx.location.capture('/my_upstream/login',
{
method = ngx.HTTP_POST,
body = "some text",
vars = {
bearerToken = "12345"
}
})
请不要泛滥,RTFM 关于 ngx.location.capture API 和 proxy_pass
的所有细节PS:查看您的上次更新 - 不敢相信有人会同时需要客户端证书和令牌授权。 通常没有客户端证书的 HTTPS 用于安全传输和授权 header 使用令牌进行身份验证。