Skip to content

Commit

Permalink
chore: improve HTTPS doc (apache#3149)
Browse files Browse the repository at this point in the history
  • Loading branch information
spacewander authored Dec 30, 2020
1 parent 81c1c7c commit 13ab490
Show file tree
Hide file tree
Showing 9 changed files with 293 additions and 75 deletions.
3 changes: 2 additions & 1 deletion apisix/schema_def.lua
Original file line number Diff line number Diff line change
Expand Up @@ -621,7 +621,8 @@ _M.ssl = {
items = {
type = "string",
pattern = [[^\*?[0-9a-zA-Z-.]+$]],
}
},
minItems = 1,
},
certs = {
type = "array",
Expand Down
5 changes: 3 additions & 2 deletions doc/admin-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -667,10 +667,11 @@ Return response from etcd currently.
|key|True|Private key|https private key||
|certs|False|An array of certificate|when you need to configure multiple certificate for the same domain, you can pass extra https certificates (excluding the one given as cert) in this field||
|keys|False|An array of private key|https private keys. The keys should be paired with certs above||
|sni|True|Match Rules|https SNI||
|snis|True|Match Rules|a non-empty arrays of https SNI||
|labels|False |Match Rules|Key/value pairs to specify attributes|{"version":"v2","build":"16","env":"production"}|
|create_time|False| Auxiliary|epoch timestamp in second, will be created automatically if missing | 1602883670|
|update_time|False| Auxiliary|epoch timestamp in second, will be created automatically if missing | 1602883670|
|status|False|Auxiliary|enable this SSL, default `1`.|`1` to enable, `0` to disable|

Config Example:

Expand All @@ -679,7 +680,7 @@ Config Example:
"id": "1", # id
"cert": "cert", # Certificate
"key": "key", # Private key
"sni": "sni" # https SNI
"snis": ["t.com"] # https SNI
}
```

Expand Down
75 changes: 63 additions & 12 deletions doc/https.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,53 @@ It is most common for an SSL certificate to contain only one domain. We can crea

* `cert`: PEM-encoded public certificate of the SSL key pair.
* `key`: PEM-encoded private key of the SSL key pair.
* `sni`: Hostname to associate with this certificate as SNIs. To set this attribute this certificate must have a valid private key associated with it.
* `snis`: Hostname(s) to associate with this certificate as SNIs. To set this attribute this certificate must have a valid private key associated with it.

We will use the python script below to simplify the example:
```python
#!/usr/bin/env python
# coding: utf-8
# save this file as ssl.py
import sys
# sudo pip install requests
import requests

if len(sys.argv) <= 3:
print("bad argument")
sys.exit(1)
with open(sys.argv[1]) as f:
cert = f.read()
with open(sys.argv[2]) as f:
key = f.read()
sni = sys.argv[3]
api_key = "edd1c9f034335f136f87ad84b625c8f1"
resp = requests.put("http://127.0.0.1:9080/apisix/admin/ssl/1", json={
"cert": cert,
"key": key,
"snis": [sni],
}, headers={
"X-API-KEY": api_key,
})
print(resp.status_code)
print(resp.text)
```

```shell
curl http://127.0.0.1:9080/apisix/admin/ssl/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
# create SSL object
./ssl.py t.crt t.key test.com

# create Router object
curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -i -d '
{
"cert": "...",
"key": "....",
"sni": "test.com"
"uri": "/hello",
"hosts": ["test.com"],
"methods": ["GET"],
"upstream": {
"type": "roundrobin",
"nodes": {
"127.0.0.1:1980": 1
}
}
}'

# make a test
Expand Down Expand Up @@ -66,14 +105,22 @@ curl --resolve 'test.com:9443:127.0.0.1' https://test.com:9443/hello -vvv
Sometimes, one SSL certificate may contain a wildcard domain like `*.test.com`,
that means it can accept more than one domain, eg: `www.test.com` or `mail.test.com`.
Here is an example, please pay attention on the field `sni`.
Here is an example, note that the value we pass as `sni` is `*.test.com`.
```shell
curl http://127.0.0.1:9080/apisix/admin/ssl/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
./ssl.py t.crt t.key '*.test.com'

curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -i -d '
{
"cert": "...",
"key": "....",
"sni": "*.test.com"
"uri": "/hello",
"hosts": ["*.test.com"],
"methods": ["GET"],
"upstream": {
"type": "roundrobin",
"nodes": {
"127.0.0.1:1980": 1
}
}
}'

# make a test
Expand Down Expand Up @@ -101,8 +148,12 @@ curl --resolve 'www.test.com:9443:127.0.0.1' https://www.test.com:9443/hello -v
### multiple domain
If your SSL certificate may contain more than one domain, like `www.test.com`
and `mail.test.com`, then you can more ssl object for each domain, that is a
most simple way.
and `mail.test.com`, then you can add them into the `snis` array. For example:
```json
{
"snis": ["www.test.com", "mail.test.com"]
}
```
### multiple certificates for a single domain
Expand Down
3 changes: 2 additions & 1 deletion doc/stand-alone.md
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,7 @@ ssl:
IeVtU6fH57Ddn59VPbF20m8RCSkmBvSdcbyBmqlZSBE+fKwCliKl6u/GH0BNAWKz
r8yiEiskqRmy7P7MY9hDmEbG
-----END PRIVATE KEY-----
sni: "yourdomain.com"
snis:
- "yourdomain.com"
#END
```
5 changes: 3 additions & 2 deletions doc/zh-cn/admin-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -675,10 +675,11 @@ HTTP/1.1 200 OK
|key|必需|私钥|https 证书私钥||
|certs|可选|证书字符串数组|当你想给同一个域名配置多个证书时,除了第一个证书需要通过cert传递外,剩下的证书可以通过该参数传递上来||
|keys|可选|私钥字符串数组|certs 对应的证书私钥,注意要跟 certs 一一对应||
|sni|必需|匹配规则|https 证书SNI||
|snis|必需|匹配规则|非空数组形式,可以匹配多个 SNI||
|labels|可选|匹配规则|标识附加属性的键值对|{"version":"v2","build":"16","env":"production"}|
|create_time|可选|辅助|单位为秒的 epoch 时间戳,如果不指定则自动创建|1602883670|
|update_time|可选|辅助|单位为秒的 epoch 时间戳,如果不指定则自动创建|1602883670|
|status|可选 |辅助| 是否启用此SSL, 缺省 `1`|`1` 表示启用,`0` 表示禁用|

ssl 对象 json 配置内容:

Expand All @@ -687,7 +688,7 @@ ssl 对象 json 配置内容:
"id": "1", # id
"cert": "cert", # 证书
"key": "key", # 私钥
"sni": "sni" # host 域名
"snis": ["t.com"] # HTTPS 握手时客户端发送的 SNI
}
```

Expand Down
77 changes: 65 additions & 12 deletions doc/zh-cn/https.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,53 @@ SNI(Server Name Indication)是用来改善 SSL 和 TLS 的一项特性,它允

* `cert`: SSL 密钥对的公钥,pem 格式
* `key`: SSL 密钥对的私钥,pem 格式
* `sni`: SSL 证书所指定的域名,注意在设置这个参数之前,你需要确保这个证书对应的私钥是有效的。
* `snis`: SSL 证书所指定的一个或多个域名,注意在设置这个参数之前,你需要确保这个证书对应的私钥是有效的。

为了简化示例,我们会使用下面的 python 脚本:
```python
#!/usr/bin/env python
# coding: utf-8
# save this file as ssl.py
import sys
# sudo pip install requests
import requests

if len(sys.argv) <= 3:
print("bad argument")
sys.exit(1)
with open(sys.argv[1]) as f:
cert = f.read()
with open(sys.argv[2]) as f:
key = f.read()
sni = sys.argv[3]
api_key = "edd1c9f034335f136f87ad84b625c8f1"
resp = requests.put("http://127.0.0.1:9080/apisix/admin/ssl/1", json={
"cert": cert,
"key": key,
"snis": [sni],
}, headers={
"X-API-KEY": api_key,
})
print(resp.status_code)
print(resp.text)
```

```shell
curl http://127.0.0.1:9080/apisix/admin/ssl/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
# 创建 SSL 对象
./ssl.py t.crt t.key test.com

# 创建 Router 对象
curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -i -d '
{
"cert": "...",
"key": "....",
"sni": "test.com"
"uri": "/hello",
"hosts": ["test.com"],
"methods": ["GET"],
"upstream": {
"type": "roundrobin",
"nodes": {
"127.0.0.1:1980": 1
}
}
}'

# 测试一下
Expand Down Expand Up @@ -68,14 +107,22 @@ curl --resolve 'test.com:9443:127.0.0.1' https://test.com:9443/hello -vvv
一个 SSL 证书的域名也可能包含泛域名,如`*.test.com`,它代表所有以`test.com`结尾的域名都可以使用该证书。
比如`*.test.com`,可以匹配 `www.test.com``mail.test.com`甚至`a.b.test.com`
看下面这个例子,请注意 `sni` 这个属性:
看下面这个例子,请注意我们把 `*.test.com` 作为 sni 传递进来:
```shell
curl http://127.0.0.1:9080/apisix/admin/ssl/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
./ssl.py t.crt t.key '*.test.com'

curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -i -d '
{
"cert": "...",
"key": "....",
"sni": "*.test.com"
"uri": "/hello",
"hosts": ["*.test.com"],
"methods": ["GET"],
"upstream": {
"type": "roundrobin",
"nodes": {
"127.0.0.1:1980": 1
}
}
}'

# 测试一下
Expand All @@ -102,8 +149,14 @@ curl --resolve 'www.test.com:9443:127.0.0.1' https://www.test.com:9443/hello -v
### 多域名的情况
如果一个 SSL 证书包含多个独立域名,比如`www.test.com``mail.test.com`,通配符方式又会导致匹配不严谨。
所以针对不同域名,设置不同 SSL 证书对象即可。
如果一个 SSL 证书包含多个独立域名,比如`www.test.com``mail.test.com`
你可以把它们都放入 `snis` 数组中,就像这样:
```json
{
"snis": ["www.test.com", "mail.test.com"]
}
```
### 单域名多证书的情况
Expand Down
3 changes: 2 additions & 1 deletion doc/zh-cn/stand-alone.md
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@ ssl:
IeVtU6fH57Ddn59VPbF20m8RCSkmBvSdcbyBmqlZSBE+fKwCliKl6u/GH0BNAWKz
r8yiEiskqRmy7P7MY9hDmEbG
-----END PRIVATE KEY-----
sni: "yourdomain.com"
snis:
- "yourdomain.com"
#END
```
29 changes: 29 additions & 0 deletions t/admin/ssl2.t
Original file line number Diff line number Diff line change
Expand Up @@ -336,3 +336,32 @@ wzarryret/7GFW1/3cz+hTj9/d45i25zArr3Pocfpur5mfz3fJO8jg==
--- error_code: 400
--- response_body
{"error_msg":"failed to handle cert-key pair[1]: failed to parse key: PEM_read_bio_PrivateKey() failed"}
=== TEST 10: empty snis
--- config
location /t {
content_by_lua_block {
local json = require("toolkit.json")
local t = require("lib.test_admin")
local ssl_cert = t.read_file("t/certs/apisix.crt")
local ssl_key = t.read_file("t/certs/apisix.key")
local data = {cert = ssl_cert, key = ssl_key, snis = {}}
local code, message, res = t.test('/apisix/admin/ssl/1',
ngx.HTTP_PUT,
json.encode(data)
)
if code >= 300 then
ngx.status = code
ngx.print(message)
return
end
ngx.say(res)
}
}
--- error_code: 400
--- response_body
{"error_msg":"invalid configuration: property \"snis\" validation failed: expect array to have at least 1 items"}
Loading

0 comments on commit 13ab490

Please sign in to comment.