qf/acme
另一个ACME客户端:从afosto/yaac分叉的解耦Let’s Encrypt客户端
Requires
- ext-json: *
- ext-openssl: *
- guzzlehttp/guzzle: ^6.3|^7.0
- league/flysystem: ^1.0|^2.0|^3.0
This package is auto-updated.
Last update: 2024-10-01 00:11:33 UTC
README
使用PHP编写的此客户端旨在成为一个简化和解耦的Let’s Encrypt客户端,基于ACME V2。
解耦于文件系统或Web服务器
例如,不将证书写入nginx配置下的磁盘,此客户端仅返回数据(证书和私钥)。
为什么
为什么我需要这个包?在Afosto,我们像其他SaaS一样运行我们的软件,因此我们无法使用已经存在的许多客户端。
几乎所有客户端都耦合到某种类型的Web服务器或固定(一组)域名。此包在您需要动态获取和安装证书时可能非常有用。
要求
- PHP7+
- openssl
- Flysystem(任何适配器均可) - 用于存储Let’s Encrypt账户信息
入门
入门非常简单。首先安装客户端,然后您需要构建一个flysystem文件系统,实例化客户端,然后您可以开始请求证书。
安装
使用composer轻松安装此包。
composer require afosto/yaac
实例化客户端
要启动客户端,您需要三样东西;Let’s Encrypt账户的用户名,初始化的Flysystem,以及您需要决定是否要颁发Fake LE Intermediate X1
(预览:MODE_STAGING
)或Let's Encrypt Authority X3
(实时:MODE_LIVE
,用于生产)证书。
use League\Flysystem\Filesystem; use League\Flysystem\Adapter\Local; use Afosto\Acme\Client; //Prepare flysystem $adapter = new Local('data'); $filesystem = new Filesystem($adapter); //Construct the client $client = new Client([ 'username' => 'example@example.org', 'fs' => $filesystem, 'mode' => Client::MODE_STAGING, ]);
在实例化客户端时,如果需要,将创建一个新的Let’s Encrypt账户,并同意TOS。
创建订单
要开始检索证书,我们首先需要创建一个订单。操作如下
$order = $client->createOrder(['example.org', 'www.example.org']);
在上面的例子中,主域后跟一个或多个次要域名。确保对于每个域名您都能证明所有权。因此,证书将适用于所有提供的域名。
证明所有权
在您可以为特定域名获取证书之前,您需要证明您拥有给定的域名(s)。我们请求授权以证明所有权。获取订单的授权。对于在创建订单请求中提供的每个域名,都会返回一个授权。
$authorizations = $client->authorize($order);
现在您有一个Authorization
对象的数组。这些对象具有您可以使用(DNS和HTTP)来提供所有权证明的挑战。
HTTP验证
HTTP验证(在特定域上的特定URL上提供特定内容,例如:example.org/.well-known/acme-challenge/*
)如下所示
使用以下示例启动HTTP验证。首先获取挑战,下一步是从以下位置使挑战可访问
foreach ($authorizations as $authorization) { $file = $authorization->getFile(); file_put_contents($file->getFilename(), $file->getContents()); }
如果您需要通配符证书,您需要使用DNS验证,见下文
DNS验证
您还可以使用DNS验证 - 要这样做,您将需要访问DNS提供商的API,为目标域名创建TXT记录。
foreach ($authorizations as $authorization) { $txtRecord = $authorization->getTxtRecord(); //To get the name of the TXT record call: $txtRecord->getName(); //To get the value of the TXT record call: $txtRecord->getValue(); }
自检
在暴露挑战(通过HTTP或DNS使其可访问)之后,我们应该进行自检,以确保在请求Let’s Encrypt验证所有权之前它正常工作。
对于HTTP挑战测试调用
if (!$client->selfTest($authorization, Client::VALIDATION_HTTP)) { throw new \Exception('Could not verify ownership via HTTP'); }
对于DNS测试调用
if (!$client->selfTest($authorization, Client::VALIDATION_DNS)) { throw new \Exception('Could not verify ownership via DNS'); } sleep(30); // this further sleep is recommended, depending on your DNS provider, see below
使用DNS验证后,在selfTest
确认DNS已更新后,建议您在继续之前等待一些额外的时间,例如sleep(30);
。这是因为Let’s Encrypt将执行多视角验证,而您的DNS提供商可能尚未完成在整个网络中传播更改。
如果您太早继续,Let's Encrypt将无法验证。
请求验证
下一步是请求验证所有权。对于每个授权(域名),我们请求Let’s Encrypt验证挑战。
对于HTTP验证
foreach ($authorizations as $authorization) { $client->validate($authorization->getHttpChallenge(), 15); }
对于DNS验证
foreach ($authorizations as $authorization) { $client->validate($authorization->getDnsChallenge(), 15); }
上面的代码首先执行自我测试,如果成功,将尝试15次请求Let’s Encrypt验证挑战(间隔1秒)并检索更新状态(Let’s Encrypt验证挑战可能需要几秒钟)。
获取证书
现在要了解我们是否可以请求订单的证书,按照以下方式测试订单是否就绪
if ($client->isReady($order)) { //The validation was successful. }
我们现在知道验证已完成,可以获取证书。这是通过以下方式完成的
$certificate = $client->getCertificate($order);
我们现在有了证书,将其存储在文件系统中
//Store the certificate and private key where you need it file_put_contents('certificate.cert', $certificate->getCertificate()); file_put_contents('private.key', $certificate->getPrivateKey());
获取单独的中间证书和域名证书
$domainCertificate = $certificate->getCertificate(false); $intermediateCertificate = $certificate->getIntermediate();
谁在使用它?
您是否在使用此包?我们很乐意了解。请发送PR以列出您的项目或公司。