我们正在编写一个插件来接收“让我们加密”通配符证书

亲爱的读者,您好! ISPmanager面板中有关“让我们加密冒险”的第二章宣布为开放状态。 在上一篇文章中,我们讨论了ACME v01的插件。 在本文中,我们将从与用户合作的逻辑的角度来讨论其发展,当然,还涉及支持通配符证书的ACME v02协议。



过度照顾


尝试谨慎地包围用户,您可以走得更远。 到目前为止,他将完全无法使用功能。 而我们故事的第一部分就是关于这一点的。

在开发模块时,我们希望节省客户端的证书准备工作。 为此引入了两个限制:它们仅允许为面板中注册的Web域和面板知道的那些域别名订购SSL。

两种限制似乎合乎逻辑。 第一个不允许订购不存在的域的证书并产生“无效”实体-不会发行的证书,因为没有地方放置验证令牌。 第二个也消除了不必要的实体,并且仍然不允许为“ *。”(别名)订购证书,而LE根本不支持此类证书。

直到一天,一切都很好, LE中出现了一种通过DNS记录检查域的功能以及为邮件域订购证书的功能。 然后,在订购邮件域时,我们决定将以下内容添加到别名:“ mail”,“ pop”,“ smtp”-毕竟,最常见的是证书与它们连接。 最后,结果很糟糕:有些用户最初将其邮件服务器配置为完全不同的别名。 由于我们在订购方面的限制,他们无法添加所需的名称。

幸运的是,我们迅速意识到并纠正了该错误,使用户可以在订购证书时指定必要的数据。 尽管如此,有时还是有太多担心:)。

通配符


现在让我们谈谈切换到ACME v02的问题 ,因为只有在此LE协议版本中才出现对通配符证书的支持。 让我们从一个新的,或者说一个修改后的目录开始:

curl -o- 'https://acme-v02.api.letsencrypt.org/directory' { "keyChange": "https://acme-v02.api.letsencrypt.org/acme/key-change", "mIU2Y2m2FsA": "https://community.letsencrypt.org/t/adding-random-entries-to-the-directory/33417", "meta": { "caaIdentities": [ "letsencrypt.org" ], "termsOfService": "https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf", "website": "https://letsencrypt.org" }, "newAccount": "https://acme-v02.api.letsencrypt.org/acme/new-acct", "newNonce": "https://acme-v02.api.letsencrypt.org/acme/new-nonce", "newOrder": "https://acme-v02.api.letsencrypt.org/acme/new-order", "revokeCert": "https://acme-v02.api.letsencrypt.org/acme/revoke-cert" } 

第一个也是最明显的区别是键是不同的:)。 我认为它们已经变得更加直观。 第二个区别是用于获取Replay-Nonce的单独URL。 现在这样完成:

 curl -LD - 'https://acme-v02.api.letsencrypt.org/acme/new-nonce' HTTP/1.1 204 No Content Server: nginx Replay-Nonce: QQgdAERh1MLQ6LHC0SVmB9OJXBcEWnwGB53CP0V4JlQ X-Frame-Options: DENY Strict-Transport-Security: max-age=604800 Expires: Sat, 02 Jun 2018 09:49:47 GMT Cache-Control: max-age=0, no-cache, no-store Pragma: no-cache Date: Sat, 02 Jun 2018 09:49:47 GMT Connection: keep-alive 

当然,Nonce会多次为我们派上用场。

现在,我们来谈谈过渡到ACME v02带来的显而易见的变化。

为了以防万一,让我提醒您,我们的旧POST请求是如何与ACME的第一个版本进行通信的:

 { "header": jws, // JSON Web Signature "protected": Base64Url(jws + Replay-Nonce), // Nonce —    "payload": Base64Url(payload), //  "signature": Base64Url(sign(protected.payload, private.pem)) //  } 

现在,一般的数据结构将有所不同:

 { "protected": Base64Url(protected), "payload": Base64Url(payload), // "signature": Base64Url(sign(protected.payload, private.pem)) } 

如您所见,标头字段已被取消。 像我这样的“密码爱好者”非常高兴的准备阶段根本没有改变:我们将需要所有相同的rsa密钥, JWKJWS在第一部分中对此有更多了解)。

报名


要注册用户,您只需要接受用户协议并从目录发送对“ newAccount”的请求。

 payload = {"termsOfServiceAgreed": true} 

并编译正确的保护:

 { "alg" : "RS256", "jwk" : jwk, \\ JSON Web Key “url” : url, \\       “nonce” : Replay-Nonce \\    } 

我们形成请求的正文,发送并...花点时间! 仔细仔细地处理ACME的响应头。 我们找到一个名为Location的标头并保存其内容。 这就是所谓的KID-新注册用户的标识密钥。 所有后续请求都需要将此值包含在protected而不是JWK中请注意 :如果您继续按照旧的方案发送请求,则只有错误消息才是答案。

这是我们随后的保护:

 { "alg" : "RS256", "kid" : kid, \\    “url” : url, \\        “nonce” : Replay-Nonce \\    } 

证书订单


我们准备将请求发送到目录[“ newOrder”]。 我们将要为其颁发证书的Web域的所有别名添加到有效负载中:

 payload ={ "identifiers":[ { "type":"dns", "value":"name1" }, ... { "type":"dns", "value":"nameN" } ] } 

请记住,如果要颁发通配符证书,则名称应仅包含主名和“ *”(别名)。 任何其他名称的存在将导致发布错误。

在响应中,我们得到一个JSON,其中包含用于确认域所有权和URL的方法,这些方法将用于完成证书的颁发。

 { "status":"pending", "expires":"2018-06-08T08:05:49.437251947Z", "identifiers":[ { "type":"dns", "value":"name1" }, { "type":"dns", "value":"www.name1" } ], "authorizations":[ //    "https://acme-v02.api.letsencrypt.org/acme/authz/Xp0a_...", "https://acme-v02.api.letsencrypt.org/acme/authz/o3Bvy..." ], "finalize":"https://acme-v02.api.letsencrypt.org/acme/finalize/..." //   } 

此外,我们还会收到有关支票的详细说明:

 curl -o- 'https://acme-v02.api.letsencrypt.org/acme/authz/Xp0a_...' { "identifier":{ "type":"dns", "value":"name1" }, "status":"pending", "expires":"2018-06-08T08:05:49Z", "challenges":[ { "type":"http-01", "status":"pending", "url":"https://acme-v02.api.letsencrypt.org/acme/challenge/Xp0a_.../4906756205", "token":"Me_cKM2Stu3iyCJQWEssho8Kj2nvRKuSJvIPF5tRyko" }, { "type":"dns-01", "status":"pending", "url":"https://acme-v02.api.letsencrypt.org/acme/challenge/Xp0a_.../4906756206", "token":"p-0xyySPQClTXVlgTxwJUvVOQtdHmNPpFht95bWrq8s" } ] } 

确认过程与为ACME v01实施的过程没有什么不同。 请注意:对于通配符证书,必须选择“ dns-01”确认。

取得证书


确认过程之后,仍然需要调用“ 完成 URL”。 可能会有一些延迟,因此,应该执行对此地址的GET请求,直到我们在响应中得到以下信息为止:

 { "status": "valid", ///<    "expires": "2018-06-11T10:39:24Z", "identifiers": [ { "type": "dns", "value": "name1" }, { "type": "dns", "value": "name2" } ], "authorizations": [ "https://acme-v02.api.letsencrypt.org/acme/authz/Xp0a_...", "https://acme-v02.api.letsencrypt.org/acme/authz/o3Bvy..." ], "finalize": "https://acme-v02.api.letsencrypt.org/acme/finalize/...", "certificate": "https://acme-v02.api.letsencrypt.org/acme/cert/..." ///<  } 

该证书将已经包含一个链,因此已完全可以使用。

与第一个版本相比, ACME的第二个版本变得更加方便和易于理解。 鉴于“密码学”本身没有改变,编写集成变得更加容易。 我将饶有兴趣地观察这个惊人工具的开发,如果发生任何重要和有用的变化,我一定会在这里提供新的信息。

Source: https://habr.com/ru/post/zh-CN413429/


All Articles