qf/acme

另一个ACME客户端:从afosto/yaac分叉的解耦Let’s Encrypt客户端

安装: 2

依赖: 0

建议者: 0

安全: 0

星标: 0

关注者: 0

分支: 84

类型:package

v1.0.1 2024-05-31 01:52 UTC

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以列出您的项目或公司。