Skip to content

Commit

Permalink
feat(secret): support store ssl.keys ssl.certs in secrets mamager (#1…
Browse files Browse the repository at this point in the history
  • Loading branch information
AlinsRan committed Jun 11, 2024
1 parent 3ad9c28 commit 5e383e0
Show file tree
Hide file tree
Showing 8 changed files with 391 additions and 11 deletions.
1 change: 1 addition & 0 deletions apisix/core/env.lua
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ end


function _M.fetch_by_uri(env_uri)
log.info("fetching data from env uri: ", env_uri)
local opts, err = parse_env_uri(env_uri)
if not opts then
return nil, err
Expand Down
25 changes: 20 additions & 5 deletions apisix/schema_def.lua
Original file line number Diff line number Diff line change
Expand Up @@ -714,6 +714,12 @@ _M.consumer = {
_M.upstream = upstream_schema


local secret_uri_schema = {
type = "string",
pattern = "^\\$(secret|env|ENV)://"
}


_M.ssl = {
type = "object",
properties = {
Expand All @@ -729,14 +735,13 @@ _M.ssl = {
cert = {
oneOf = {
certificate_scheme,
-- TODO: uniformly define the schema of secret_uri
{ type = "string", pattern = "^\\$(secret|env)://"}
secret_uri_schema
}
},
key = {
oneOf = {
private_key_schema,
{ type = "string", pattern = "^\\$(secret|env)://"}
secret_uri_schema
}
},
sni = {
Expand All @@ -753,11 +758,21 @@ _M.ssl = {
},
certs = {
type = "array",
items = certificate_scheme,
items = {
oneOf = {
certificate_scheme,
secret_uri_schema
}
}
},
keys = {
type = "array",
items = private_key_schema,
items = {
oneOf = {
private_key_schema,
secret_uri_schema
}
}
},
client = {
type = "object",
Expand Down
1 change: 1 addition & 0 deletions apisix/secret.lua
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ end


local function fetch_by_uri(secret_uri)
core.log.info("fetching data from secret uri: ", secret_uri)
local opts, err = parse_secret_uri(secret_uri)
if not opts then
return nil, err
Expand Down
4 changes: 2 additions & 2 deletions apisix/ssl.lua
Original file line number Diff line number Diff line change
Expand Up @@ -278,8 +278,8 @@ function _M.check_ssl_conf(in_dp, conf)
end

for i = 1, numcerts do
if not secret.check_secret_uri(conf.cert[i]) and
not secret.check_secret_uri(conf.key[i]) then
if not secret.check_secret_uri(conf.certs[i]) and
not secret.check_secret_uri(conf.keys[i]) then

local ok, err = validate(conf.certs[i], conf.keys[i])
if not ok then
Expand Down
4 changes: 2 additions & 2 deletions docs/en/latest/admin-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -1204,8 +1204,8 @@ For notes on ID syntax please refer to: [ID Syntax](#quick-note-on-id-syntax)
| ------------ | -------- | ------------------------ | -------------------------------------------------------------------------------------------------------------- | ------------------------------------------------ |
| cert | True | Certificate | HTTPS certificate. This field supports saving the value in Secret Manager using the [APISIX Secret](./terminology/secret.md) resource. | |
| key | True | Private key | HTTPS private key. This field supports saving the value in Secret Manager using the [APISIX Secret](./terminology/secret.md) resource. | |
| certs | False | An array of certificates | Used for configuring multiple certificates for the same domain excluding the one provided in the `cert` field. | |
| keys | False | An array of private keys | Private keys to pair with the `certs`. | |
| certs | False | An array of certificates | Used for configuring multiple certificates for the same domain excluding the one provided in the `cert` field. This field supports saving the value in Secret Manager using the [APISIX Secret](./terminology/secret.md) resource. | |
| keys | False | An array of private keys | Private keys to pair with the `certs`. This field supports saving the value in Secret Manager using the [APISIX Secret](./terminology/secret.md) resource. | |
| client.ca | False | Certificate | Sets the CA certificate that verifies the client. Requires OpenResty 1.19+. | |
| client.depth | False | Certificate | Sets the verification depth in client certificate chains. Defaults to 1. Requires OpenResty 1.19+. | |
| client.skip_mtls_uri_regex | False | An array of regular expressions, in PCRE format | Used to match URI, if matched, this request bypasses the client certificate checking, i.e. skip the MTLS. | ["/hello[0-9]+", "/foobar"] |
Expand Down
4 changes: 2 additions & 2 deletions docs/zh/latest/admin-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -1205,8 +1205,8 @@ SSL 资源请求地址:/apisix/admin/ssls/{id}
| ----------- | ------ | -------------- | ------------------------------------------------------------------------------------------------------ | ------------------------------------------------ |
| cert || 证书 | HTTP 证书。该字段支持使用 [APISIX Secret](./terminology/secret.md) 资源,将值保存在 Secret Manager 中。 | |
| key || 私钥 | HTTPS 证书私钥。该字段支持使用 [APISIX Secret](./terminology/secret.md) 资源,将值保存在 Secret Manager 中。 | |
| certs || 证书字符串数组 | 当你想给同一个域名配置多个证书时,除了第一个证书需要通过 `cert` 传递外,剩下的证书可以通过该参数传递上来。 | |
| keys || 私钥字符串数组 | `certs` 对应的证书私钥,需要与 `certs` 一一对应。 | |
| certs || 证书字符串数组 | 当你想给同一个域名配置多个证书时,除了第一个证书需要通过 `cert` 传递外,剩下的证书可以通过该参数传递上来。该字段支持使用 [APISIX Secret](./terminology/secret.md) 资源,将值保存在 Secret Manager 中。 | |
| keys || 私钥字符串数组 | `certs` 对应的证书私钥,需要与 `certs` 一一对应。该字段支持使用 [APISIX Secret](./terminology/secret.md) 资源,将值保存在 Secret Manager 中。 | |
| client.ca || 证书 | 设置将用于客户端证书校验的 `CA` 证书。该特性需要 OpenResty 为 1.19 及以上版本。 | |
| client.depth || 辅助 | 设置客户端证书校验的深度,默认为 1。该特性需要 OpenResty 为 1.19 及以上版本。 | |
| client.skip_mtls_uri_regex || PCRE 正则表达式数组 | 用来匹配请求的 URI,如果匹配,则该请求将绕过客户端证书的检查,也就是跳过 MTLS。 | ["/hello[0-9]+", "/foobar"] |
Expand Down
120 changes: 120 additions & 0 deletions t/admin/ssl.t
Original file line number Diff line number Diff line change
Expand Up @@ -680,3 +680,123 @@ GET /t
GET /t
--- response_body chomp
passed
=== TEST 21: set ssl with sercret
--- config
location /t {
content_by_lua_block {
local core = require("apisix.core")
local t = require("lib.test_admin")
local data = {
sni = "test.com",
cert = "$secret://vault/test/ssl/test.com.crt",
key = "$secret://vault/test/ssl/test.com.key",
certs = {"$secret://vault/test/ssl/test.com.2.crt"},
keys = {"$secret://vault/test/ssl/test.com.2.key"}
}
local code, body = t.test('/apisix/admin/ssls/1',
ngx.HTTP_PUT,
core.json.encode(data),
[[{
"value": {
"sni": "test.com",
"cert": "$secret://vault/test/ssl/test.com.crt",
"key": "$secret://vault/test/ssl/test.com.key",
"certs": ["$secret://vault/test/ssl/test.com.2.crt"],
"keys": ["$secret://vault/test/ssl/test.com.2.key"]
},
"key": "/apisix/ssls/1"
}]]
)
ngx.status = code
ngx.say(body)
}
}
--- request
GET /t
--- response_body
passed
=== TEST 22: set ssl with env, and prefix is all uppercase or lowercase
--- config
location /t {
content_by_lua_block {
local core = require("apisix.core")
local t = require("lib.test_admin")
local data = {
sni = "test.com",
cert = "$ENV://APISIX_TEST_SSL_CERT",
key = "$env://APISIX_TEST_SSL_KEY",
certs = {"$env://APISIX_TEST_SSL_CERTS"},
keys = {"$ENV://APISIX_TEST_SSL_KEYS"},
}
local code, body = t.test('/apisix/admin/ssls/1',
ngx.HTTP_PUT,
core.json.encode(data),
[[{
"value": {
"sni": "test.com",
"cert": "$ENV://APISIX_TEST_SSL_CERT",
"key": "$env://APISIX_TEST_SSL_KEY",
"certs": ["$env://APISIX_TEST_SSL_CERTS"],
"keys": ["$ENV://APISIX_TEST_SSL_KEYS"]
},
"key": "/apisix/ssls/1"
}]]
)
ngx.status = code
ngx.say(body)
}
}
--- request
GET /t
--- response_body
passed
=== TEST 23: set ssl with invalid prefix
--- config
location /t {
content_by_lua_block {
local core = require("apisix.core")
local t = require("lib.test_admin")
local data = {
sni = "test.com",
cert = "$ENV://APISIX_TEST_SSL_CERT",
key = "$env://APISIX_TEST_SSL_KEY",
certs = {"https://APISIX_TEST_SSL_CERTS"},
keys = {"$ENV://APISIX_TEST_SSL_KEYS"},
}
local code, body = t.test('/apisix/admin/ssls/1',
ngx.HTTP_PUT,
core.json.encode(data),
[[{
"value": {
"sni": "test.com"
},
"key": "/apisix/ssls/1"
}]]
)
ngx.status = code
ngx.print(body)
}
}
--- request
GET /t
--- error_code: 400
--- response_body
{"error_msg":"invalid configuration: property \"certs\" validation failed: failed to validate item 1: value should match only one schema, but matches none"}
Loading

0 comments on commit 5e383e0

Please sign in to comment.