7. Certificate Management (证书管理)
在本节中, 我们描述 ACME 启用的证书管理功能:
- 账户创建 (Account Creation)
- 订购证书 (Ordering a Certificate)
- 标识符授权 (Identifier Authorization)
- 证书颁发 (Certificate Issuance)
- 证书吊销 (Certificate Revocation)
7.1. Resources (资源)
ACME 被构建为基于 HTTP 的应用程序, 具有以下类型的资源:
- 账户资源 (Account Resources), 表示有关账户的信息 (第 7.1.2 节, 第 7.3 节)
- 订单资源 (Order Resources), 表示账户颁发证书的请求 (第 7.1.3 节)
- 授权资源 (Authorization Resources), 表示账户对标识符采取行动的授权 (第 7.1.4 节)
- 挑战资源 (Challenge Resources), 表示证明对标识符控制的挑战 (第 7.5 节, 第 8 节)
- 证书资源 (Certificate Resources), 表示已颁发的证书 (第 7.4.2 节)
- "directory" 资源 (第 7.1.1 节)
- "newNonce" 资源 (第 7.2 节)
- "newAccount" 资源 (第 7.3 节)
- "newOrder" 资源 (第 7.4 节)
- "revokeCert" 资源 (第 7.6 节)
- "keyChange" 资源 (第 7.3.5 节)
服务器必须 (MUST) 提供 "directory" 和 "newNonce" 资源。
ACME 对不同的管理功能使用不同的 URL。每个功能都与其相应的 URL 一起列在目录中, 因此客户端只需要配置目录 URL。这些 URL 通过几个不同的链接关系 [RFC8288] 连接。
"up" 链接关系与挑战资源一起使用, 以指示挑战所属的授权资源。对于某些媒体类型, 它也从证书资源使用, 以指示客户端可以从中获取可用于验证原始资源中证书的 CA 证书链的资源。
"index" 链接关系出现在除目录之外的所有资源上, 并指示目录的 URL。
下图说明了 ACME 服务器上资源之间的关系。在大多数情况下, 这些关系由资源的 JSON 表示中作为字符串提供的 URL 表示。带有引号标签的线表示 HTTP 链接关系。
directory
|
+--> newNonce
|
+----------+----------+-----+-----+------------+
| | | | |
| | | | |
V V V V V
newAccount newAuthz newOrder revokeCert keyChange
| | |
| | |
V | V
account | order --+--> finalize
| | |
| | +--> cert
| V
+---> authorization
| ^
| | "up"
V |
challenge
ACME Resources and Relationships
下表说明了建立与服务器的新账户、证明对标识符的控制、颁发证书以及在颁发后某个时间获取更新证书所需的典型请求序列。"->" 是指向创建资源的 Location 头字段的助记符。
| 操作 | 请求 | 响应 |
|---|---|---|
| 获取目录 | GET directory | 200 |
| 获取 nonce | HEAD newNonce | 200 |
| 创建账户 | POST newAccount | 201 -> account |
| 提交订单 | POST newOrder | 201 -> order |
| 获取挑战 | POST-as-GET order's authorization urls | 200 |
| 响应挑战 | POST authorization challenge urls | 200 |
| 轮询状态 | POST-as-GET order | 200 |
| 完成订单 | POST order's finalize url | 200 |
| 轮询状态 | POST-as-GET order | 200 |
| 下载证书 | POST-as-GET order's certificate url | 200 |
本节的其余部分提供了这些资源如何构建以及 ACME 协议如何使用它们的详细信息。
7.1.1. Directory (目录)
为了帮助客户端为每个 ACME 操作配置正确的 URL, ACME 服务器提供目录对象。这应该是配置客户端所需的唯一 URL。它是一个 JSON 对象, 其字段名称来自资源注册表 (第 9.7.5 节), 其值是相应的 URL。
| 字段 | 值中的 URL |
|---|---|
| newNonce | 新 nonce |
| newAccount | 新账户 |
| newOrder | 新订单 |
| newAuthz | 新授权 |
| revokeCert | 吊销证书 |
| keyChange | 密钥更改 |
目录的 URL 没有约束, 除了它应该与其他 ACME 服务器资源的 URL 不同, 并且不应与其他服务冲突。例如:
- 同时充当 ACME 和 Web 服务器的主机可能希望将根路径 "/" 保留用于 HTML "首页", 并将 ACME 目录放在路径 "/acme" 下。
- 仅充当 ACME 服务器的主机可以将目录放在路径 "/" 下。
如果 ACME 服务器不实现预授权 (Pre-authorization) (第 7.4.1 节), 它必须 (MUST) 省略目录的 "newAuthz" 字段。
该对象可以 (MAY) 另外包含 "meta" 字段。如果存在, 它必须 (MUST) 是 JSON 对象; 对象中的每个字段都是与 ACME 服务器提供的服务相关的元数据项。
定义了以下元数据项 (第 9.7.6 节), 所有这些都是可选的 (OPTIONAL):
termsOfService (可选, 字符串): 标识当前服务条款的 URL。
website (可选, 字符串): 定位提供有关 ACME 服务器更多信息的网站的 HTTP 或 HTTPS URL。
caaIdentities (可选, 字符串数组): ACME 服务器识别为引用自身的主机名, 用于 [RFC6844] 中定义的 CAA 记录验证。每个字符串必须 (MUST) 表示服务器期望在 CAA issue 或 issuewild 属性标签中看到的 "颁发者域名" (Issuer Domain Name) 的相同 ASCII 代码点序列。这允许客户端在配置 CAA 记录时确定要使用的正确颁发者域名。
externalAccountRequired (可选, 布尔值): 如果此字段存在并设置为 "true", 则 CA 要求所有 newAccount 请求包含 "externalAccountBinding" 字段, 将新账户与外部账户关联。
客户端通过向目录 URL 发送 GET 请求来访问目录。
HTTP/1.1 200 OK
Content-Type: application/json
{
"newNonce": "https://example.com/acme/new-nonce",
"newAccount": "https://example.com/acme/new-account",
"newOrder": "https://example.com/acme/new-order",
"newAuthz": "https://example.com/acme/new-authz",
"revokeCert": "https://example.com/acme/revoke-cert",
"keyChange": "https://example.com/acme/key-change",
"meta": {
"termsOfService": "https://example.com/acme/terms/2017-5-30",
"website": "https://www.example.com/",
"caaIdentities": ["example.com"],
"externalAccountRequired": false
}
}
7.1.2. Account Objects (账户对象)
ACME 账户资源表示与账户关联的一组元数据。账户资源具有以下结构:
status (必需, 字符串): 此账户的状态。可能的值为 "valid", "deactivated" 和 "revoked"。值 "deactivated" 应该用于指示客户端发起的停用, 而 "revoked" 应该用于指示服务器发起的停用。参见第 7.1.6 节。
contact (可选, 字符串数组): 服务器可以用来联系客户端以解决与此账户相关问题的 URL 数组。例如, 服务器可能希望通知客户端有关服务器发起的吊销或证书过期的信息。有关支持的 URL 方案的信息, 请参见第 7.3 节。
termsOfServiceAgreed (可选, 布尔值): 在 newAccount 请求中包含此字段, 值为 true, 表示客户端同意服务条款。此字段不能由客户端更新。
externalAccountBinding (可选, 对象): 在 newAccount 请求中包含此字段表示现有非 ACME 账户的持有者批准将该账户绑定到此 ACME 账户。此字段不可由客户端更新 (参见第 7.3.4 节)。
orders (必需, 字符串): 一个 URL, 可以通过 POST-as-GET 请求从中获取此账户提交的订单列表, 如第 7.1.2.1 节所述。
{
"status": "valid",
"contact": [
"mailto:[email protected]",
"mailto:[email protected]"
],
"termsOfServiceAgreed": true,
"orders": "https://example.com/acme/orders/rzGoeA"
}
7.1.2.1. Orders List (订单列表)
每个账户对象都包含一个 "orders" URL, 可以通过 POST-as-GET 请求从中获取账户创建的订单列表。请求的结果必须 (MUST) 是一个 JSON 对象, 其 "orders" 字段是一个 URL 数组, 每个 URL 标识属于该账户的订单。服务器应该 (SHOULD) 包括待处理的订单, 并且不应该 (SHOULD NOT) 在 URL 数组中包括无效的订单。服务器可以 (MAY) 返回不完整的列表, 以及带有 "next" 链接关系的 Link 头字段, 指示可以获取更多条目的位置。
HTTP/1.1 200 OK
Content-Type: application/json
Link: `https://example.com/acme/directory`;rel="index"
Link: `https://example.com/acme/orders/rzGoeA?cursor=2`;rel="next"
{
"orders": [
"https://example.com/acme/order/TOlocE8rfgo",
"https://example.com/acme/order/4E16bbL5iSw",
/* 为简洁起见未显示更多 URL */
"https://example.com/acme/order/neBHYLfw0mg"
]
}
7.1.3. Order Objects (订单对象)
ACME 订单对象表示客户端对证书的请求, 并用于跟踪该订单直至颁发的进度。因此, 该对象包含有关所请求证书、服务器要求客户端完成的授权以及此订单产生的任何证书的信息。
status (必需, 字符串): 此订单的状态。可能的值为 "pending", "ready", "processing", "valid" 和 "invalid"。参见第 7.1.6 节。
expires (可选, 字符串): 服务器将在此时间戳之后将此订单视为无效的时间戳, 以 [RFC3339] 中指定的格式编码。对于状态字段中具有 "pending" 或 "valid" 的对象, 此字段是必需的 (REQUIRED)。
identifiers (必需, 对象数组): 订单涉及的标识符对象数组。
-
type (必需, 字符串): 标识符的类型。本文档定义了 "dns" 标识符类型。有关任何其他类型, 请参见第 9.7.7 节中定义的注册表。
-
value (必需, 字符串): 标识符本身。
notBefore (可选, 字符串): 证书中 notBefore 字段的请求值, 采用 [RFC3339] 中定义的日期格式。
notAfter (可选, 字符串): 证书中 notAfter 字段的请求值, 采用 [RFC3339] 中定义的日期格式。
error (可选, 对象): 处理订单时发生的错误 (如果有)。此字段被构建为问题文档 [RFC7807]。
authorizations (必需, 字符串数组): 对于待处理的订单, 客户端在颁发所请求的证书之前需要完成的授权 (参见第 7.5 节), 包括客户端过去为订单中指定的标识符完成的未过期授权。所需的授权由服务器策略决定; 订单标识符和所需授权之间可能没有 1:1 的关系。对于最终订单 (处于 "valid" 或 "invalid" 状态), 已完成的授权。每个条目都是一个 URL, 可以使用 POST-as-GET 请求从中获取授权。
finalize (必需, 字符串): 一旦订单的所有授权都满足, 必须将 CSR POST 到此 URL 以完成订单。成功完成的结果将是填充订单的证书 URL。
certificate (可选, 字符串): 响应此订单已颁发的证书的 URL。
{
"status": "valid",
"expires": "2016-01-20T14:09:07.99Z",
"identifiers": [
{ "type": "dns", "value": "www.example.org" },
{ "type": "dns", "value": "example.org" }
],
"notBefore": "2016-01-01T00:00:00Z",
"notAfter": "2016-01-08T00:00:00Z",
"authorizations": [
"https://example.com/acme/authz/PAniVnsZcis",
"https://example.com/acme/authz/r4HqLzrSrpI"
],
"finalize": "https://example.com/acme/order/TOlocE8rfgo/finalize",
"certificate": "https://example.com/acme/cert/mAt3xBGaobw"
}
newOrder 请求中类型为 "dns" 的任何标识符可以 (MAY) 将通配符域名作为其值。通配符域名由单个星号字符后跟单个句点字符 (".") 后跟 [RFC5280] 为在主体备用名称扩展中使用而定义的域名组成。服务器为通配符域名标识符返回的授权禁止 (MUST NOT) 在授权标识符值中包含星号和句点 (".") 前缀。返回的授权必须 (MUST) 包含可选的 "wildcard" 字段, 值为 true。
"authorizations" 和 "identifiers" 数组的元素一旦设置就是不可变的。服务器禁止 (MUST NOT) 在创建后更改任一数组的内容。如果客户端观察到任一数组内容的更改, 则它应该 (SHOULD) 将订单视为无效。
订单的 "authorizations" 数组应该 (SHOULD) 反映 CA 在决定颁发时考虑的所有授权, 即使某些授权在较早的订单或预授权事务中已完成。例如, 如果 CA 允许基于单个授权事务完成多个订单, 则它应该 (SHOULD) 在所有订单中反映该授权。
请注意, 仅仅因为授权 URL 列在订单对象的 "authorizations" 数组中并不意味着客户端需要采取行动。引用的授权可能已经有效的原因有几个:
- 客户端作为先前订单的一部分完成了授权
- 客户端先前预授权了标识符 (参见第 7.4.1 节)
- 服务器基于外部账户授予客户端授权
客户端应该 (SHOULD) 检查订单的 "status" 字段以确定是否需要采取任何行动。
注意: 由于第7章内容非常长,本文件仅包含7.1-7.1.3节。7.1.4-7.6节将在Part 2中继续。