deliciousbrains / leclient
PHP LetsEncrypt客户端库,用于ACME v2
Requires
- php: >=5.2
This package is auto-updated.
Last update: 2022-06-07 09:05:08 UTC
README
PHP LetsEncrypt客户端库,用于ACME v2。此客户端的目的是提供一个易于使用且集成的解决方案,以便使用PHP创建由Let's Encrypt签发的SSL/TLS证书。用户必须能够访问Web服务器或DNS管理,才能验证域名是否可访问/由用户拥有。
当前版本
当前版本是1.1.7
以下示例代码需要更新。
此客户端是使用Let's Encrypt的2.0版本测试服务器开发的。虽然目前Let's Encrypt仍在开发和实施2.0版本,但该项目可能会发生变化。
入门
以下说明将指导您开始使用此客户端库。如果您有任何问题或遇到任何问题,请随时打开一个问题,我会尽力查看。
还可以查看Let's Encrypt文档以获取更多有关Let's Encrypt和ACME的信息和文档。
先决条件
最低要求的PHP版本是5.2.0。需要7.1.0版本进行EC密钥。当尝试使用低于7.1.0的PHP版本生成EC密钥时,生成EC密钥的函数将抛出异常。将保留1.0.0版本,但不再维护。
此客户端还依赖于cURL和OpenSSL。
安装
使用composer
composer require yourivw/leclient
尽管可以将此添加到自己的自动加载器中,但并不推荐这样做,因为您将无法控制依赖项。如果您以前没有使用过composer,我强烈建议您在https://getcomposer.org.cn上查看它。
建议设置较高的最大执行时间以减少脚本执行时间。有多种方法可以实现这一点。一种方法是将以下内容添加到页面的顶部
ini_set('max_execution_time', 120); // Maximum execution time in seconds.
用法
以下显示了基本函数及其必要的参数。每个类中都包含扩展说明。
从版本1.1.6开始,还可以使用PSR-3日志记录器(\Psr\Log\LoggerInterface)启动LEClient。
启动客户端
use LEClient\LEClient; $client = new LEClient($email); // Initiating a basic LEClient with an array of string e-mail address(es). $client = new LEClient($email, true); // Initiating a LECLient and use the LetsEncrypt staging URL. $client = new LEClient($email, true, $logger); // Initiating a LEClient and use a PSR-3 logger (\Psr\Log\LoggerInterface). $client = new LEClient($email, true, LEClient::LOG_STATUS); // Initiating a LEClient and log status messages (LOG_DEBUG for full debugging). $client = new LEClient($email, true, LEClient::LOG_STATUS, 'keys/'); // Initiating a LEClient and select custom certificate keys directory (string or array) $client = new LEClient($email, true, LEClient::LOG_STATUS, 'keys/', '__account/'); // Initiating a LEClient and select custom account keys directory (string or array)
如果没有找到现有账户,客户端将自动创建新账户。它将转发在启动过程中提供的电子邮件地址,如上所示。
使用账户功能
$acct = $client->getAccount(); // Retrieves the LetsEncrypt Account instance created by the client. $acct->updateAccount($email); // Updates the account with new contact information. Supply an array of string e-mail address(es). $acct->changeAccountKeys(); // Generates a new RSA keypair for the account and updates the keys with LetsEncrypt. $acct->deactivateAccount(); // Deactivates the account with LetsEncrypt.
创建证书订单实例。如果找到已存储在本地的订单,则使用此订单。否则,将创建新的订单。如果提供的域名与订单不匹配,也将创建新的订单。构建Let's Encrypt订单实例
$order = $client->getOrCreateOrder($basename, $domains); // Get or create order. The basename is preferably the top domain name. This will be the directory in which the keys are stored. Supply an array of string domain names to create a certificate for. $order = $client->getOrCreateOrder($basename, $domains, $keyType); // Get or create order. keyType can be set to "ec" to get ECDSA certificate. "rsa-4096" is default value. Accepts ALGO-SIZE format. $order = $client->getOrCreateOrder($basename, $domains, $keyType, $notBefore); // Get or create order. Supply a notBefore date as a string similar to 0000-00-00T00:00:00Z (yyyy-mm-dd hh:mm:ss). $order = $client->getOrCreateOrder($basename, $domains, $keyType, $notBefore, $notAfter); // Get or create order. Supply a notBefore and notAfter date as a string similar to 0000-00-00T00:00:00Z (yyyy-mm-dd hh:mm:ss).
使用订单功能
$valid = $order->allAuthorizationsValid(); // Check whether all authorizations in this order instance are valid. $pending = $order->getPendingAuthorizations($type); // Get an array of pending authorizations. Performing authorizations is described further on. Type is LEOrder::CHALLENGE_TYPE_HTTP or LEOrder::CHALLENGE_TYPE_DNS. $verify = $order->verifyPendingOrderAuthorization($identifier, $type); // Verify a pending order. The identifier is a string domain name. Type is LEOrder::CHALLENGE_TYPE_HTTP or LEOrder::CHALLENGE_TYPE_DNS. $deactivate = $order->deactivateOrderAuthorization($identifier); // Deactivate an authorization. The identifier is a string domain name. $finalize = $order->finalizeOrder(); // Finalize the order and generate a Certificate Signing Request automatically. $finalize = $order->finalizeOrder($csr); // Finalize the order with a custom Certificate Signing Request string. $finalized = $order->isFinalized(); // Check whether the order is finalized. $cert = $order->getCertificate(); // Retrieves the certificate and stores it in the keys directory, under the specific order (basename). $revoke = $order->revokeCertificate(); // Revoke the certificate without a reason. $revoke = $order->revokeCertificate($reason); // Revoke the certificate with a reason integer as found in section 5.3.1 of RFC5280.
辅助函数
use LEClient\LEFunctions; LEFunctions::RSAGenerateKeys($directory, $privateKeyFile, $publicKeyFile); // Generate a RSA keypair in the given directory. Variables privateKeyFile and publicKeyFile are optional and have default values private.pem and public.pem. LEFunctions::ECGenerateKeys($directory, $privateKeyFile, $publicKeyFile); // Generate a EC keypair in the given directory (PHP 7.1+ required). Variables privateKeyFile and publicKeyFile are optional and have default values private.pem and public.pem. LEFunctions::Base64UrlSafeEncode($input); // Encode the input string as a base64 URL safe string. LEFunctions::Base64UrlSafeDecode($input); // Decode a base64 URL safe encoded string. LEFunctions::log($data, $function); // Print the data. The function variable is optional and defaults to the calling function's name. LEFunctions::checkHTTPChallenge($domain, $token, $keyAuthorization); // Checks whether the HTTP challenge is valid. Performing authorizations is described further on. LEFunctions::checkDNSChallenge($domain, $DNSDigest); // Checks whether the DNS challenge is valid. Performing authorizations is described further on. LEFunctions::createhtaccess($directory); // Created a simple .htaccess file in the directory supplied, denying all visitors.
授权挑战
Let's Encrypt (ACME) 对您想要包含在证书中的域进行授权,以验证您确实可以访问该特定域。因此,在创建订单时,为每个域添加一个授权。如果某个域在最近(过去30天内)已被您的账户验证,例如在其他订单中,则无需再次验证。此时,可以通过向文件(http-01)或DNS TXT记录(dns-01)发起HTTP请求来验证域。客户端通过调用getPendingAuthorizations()来提供所选验证所需的数据。由于创建文件或DNS记录的方式因服务器而异,因此客户端中未实现此功能。用户完成挑战要求后,必须调用verifyPendingOrderAuthorization()来验证授权。此客户端将首先通过checkHTTPChallenge()或checkDNSChallenge()自行验证挑战,然后再通过Let's Encrypt进行验证。请注意,通配符域名只能通过DNS挑战进行验证。以下展示了两种挑战的示例。
HTTP挑战
对于此示例,我们假设还有一个待验证的域。
use LEClient\LEOrder; $pending = $order->getPendingAuthorizations(LEOrder::CHALLENGE_TYPE_HTTP);
这将返回一个数组
Array
(
[0] => Array
(
[type] => http-01
[identifier] => test.example.org
[filename] => A8Q1DAVcd_k_oKAC0D_y4ln2IWrRX51jmXnR9UMMtOb
[content] => A8Q1DAVcd_k_oKAC0D_y4ln2IWrRX51jmXnR9UMMtOb.C4kIiiwfcynb3i48AQVtZRtNrD51z4JiIrdQsgVqcL8
)
)
对于成功的验证,将向以下URL发起请求
http://test.example.org/.well-known/acme-challenge/A8Q1DAVcd_k_oKAC0D_y4ln2IWrRX51jmXnR9UMMtOb
此文件的应设置为上面数组的相应内容。用户应在验证授权之前创建此文件。
DNS挑战
对于此示例,我们假设还有两个待验证的域。其中一个是一个通配符域名。此示例中的第二个域名是为了演示目的而添加的。将子域名添加到证书中,而这些子域名已经由通配符域名覆盖,并不会提供太多额外的价值。
$pending = $order->getPendingAuthorizations(LEOrder::CHALLENGE_TYPE_DNS);
这将返回一个数组
Array
(
[0] => Array
(
[type] => dns-01
[identifier] => example.org
[DNSDigest] => FV5HgbpjIYe1x9MkPI81Nffo2oA-Jo2S88gCL7-Ky5P
)
[1] => Array
(
[type] => dns-01
[identifier] => test.example.org
[DNSDigest] => WM5YIsgaZQv1b9DbRZ81EwCf2fi-Af2JlgxTC7-Up5D
)
)
为了成功验证,应创建以下DNS记录
名称 | TTL | 类型 | 值 |
---|---|---|---|
_acme-challenge.example.org | 60 | TXT | FV5HgbpjIYe1x9MkPI81Nffo2oA-Jo2S88gCL7-Ky5P |
_acme-challenge.test.example.org | 60 | TXT | WM5YIsgaZQv1b9DbRZ81EwCf2fi-Af2JlgxTC7-Up5D |
如果需要,可以将TTL值设置得更高,但我更倾向于尽可能将其保持得较低。为了确保验证成功,建议运行使用DNS挑战的脚本,分为两个部分,中间有一定的时间间隔,以便允许DNS记录更新。用户自己应确保在记录可以验证之前设置此DNS记录。DNS记录的名称也取决于您的提供商,因此getPendingAuthorizations()不会提供现成的记录名称。一些提供商仅接受如_acme-challenge
之类的名称,不包含顶级域名名称,用于_acme-challenge.example.org
。一些提供商接受(或要求)如上所示的全名。
通配符域名,如*.example.org
,将像上面所示那样被验证为example.org
。这意味着DNS记录名称应该是_acme-challenge.example.org
完整示例
对于HTTP和DNS授权,完整示例可在项目的主代码目录中找到。HTTP授权示例包含在一个文件中。如上所述,DNS授权示例分为两部分,以便在同时允许DNS记录更新。虽然记录的TTL可能很低,但有时在修改后,您的提供商更新DNS记录可能需要一些时间。
如果您无法获取这些示例或客户端库,请尝试查看上面提到的Let's Encrypt文档。
安全
安全是关于SSL/TLS证书的一个重要主题,当然。由于这个客户端是PHP脚本,因此很可能这段代码是在Web服务器上运行的。显然,您存储在Web服务器上的私钥绝对不应该从Web上访问。当客户端第一次创建密钥目录时,它将在这个目录中存储一个.htaccess文件,拒绝所有访问者。始终确保您自己的密钥不被Web访问!如果您的私钥公开了,我概不负责。如果发生这种情况,最简单的解决方案是更改您账户的密钥(如上所述)或停用账户并创建一个新的账户。接下来,创建一个新的证书。
许可证
本项目采用MIT许可证 - 有关详细信息,请参阅LICENSE文件。