rogierw/rw-acme-client

PHP编写的ACME v2协议Let's Encrypt客户端库。

4.2.0 2024-04-06 07:45 UTC

README

Latest Version on Packagist Scrutinizer Code Quality StyleCI

此库允许您请求、续订和吊销由Let's Encrypt提供的SSL证书。

如果您正在寻找一个易于使用的CLI工具来管理您的LE证书,请查看RW ACME CLI项目。

要求

  • PHP ^8.2
  • OpenSSL >= 1.0.1
  • cURL扩展
  • JSON扩展

注意

  • 建议在您的系统上安装dig,因为它将被用来获取DNS信息。
  • 本包的v4版本仅支持php:^8.2。如果您需要旧版本,请查看v1v3

安装

您可以通过composer安装此包

composer require rogierw/rw-acme-client

用法

创建一个Rogierw\RwAcme\Api客户端实例,并向其提供一个本地账户,用于存储账户密钥。

$localAccount = new \Rogierw\RwAcme\Support\LocalFileAccount(__DIR__.'/__account', 'test@example.com');
$client = new Api(localAccount: $localAccount);

您也可以先创建一个客户端,然后稍后传递本地账户数据

$client = new Api();

// Do some stuff.

$localAccount = new \Rogierw\RwAcme\Support\LocalFileAccount(__DIR__.'/__account', 'test@example.com');
$client->setLocalAccount($localAccount);

请注意,在执行以下详细操作之前,必须先设置本地账户。

创建账户

if (!$client->account()->exists()) {
    $account = $client->account()->create();
}

// Or get an existing account.
$account = $client->account()->get();

accountlocalAccount之间的区别

  • account是在ACME(Let's Encrypt)服务器上创建的账户,数据来自localAccount
  • localAccount处理用于对ACME服务器发送请求的私钥/公钥对和联系电子邮件地址。根据实现方式,这些数据可能存储在本地,例如数据库中。

创建订单

$order = $client->order()->new($account, ['example.com']);

续订

简单地创建一个新订单来续订现有证书,如上所述。请确保您使用与初始请求相同的账户。

获取订单

$order = $client->order()->get($order->id);

域名验证

获取DCV状态

$validationStatus = $client->domainValidation()->status($order);

http-01

获取验证文件的名称和内容

// Get the data for the HTTP challenge; filename and content.
$validationData = $client->domainValidation()->getValidationData($validationStatus, \Rogierw\RwAcme\Enums\AuthorizationChallengeEnum::HTTP);

这返回一个数组

Array
(
    [0] => Array
        (
            [type] => http-01
            [identifier] => example.com
            [filename] => sqQnDYNNywpkwuHeU4b4FTPI2mwSrDF13ti08YFMm9M
            [content] => sqQnDYNNywpkwuHeU4b4FTPI2mwSrDF13ti08YFMm9M.kB7_eWSDdG3aWIaPSp6Uy4vLBbBI5M0COvM-AZOBcoQ
        )
)

Let's Encrypt验证服务器将对以下URL发出请求

http://example.com/.well-known/acme-challenge/sqQnDYNNywpkwuHeU4b4FTPI2mwSrDF13ti08YFMm9M

dns-01

获取TXT记录的名称和值

// Get the data for the DNS challenge.
$validationData = $client->domainValidation()->getValidationData($validationStatus, \Rogierw\RwAcme\Enums\AuthorizationChallengeEnum::DNS);

这返回一个数组

Array
(
    [0] => Array
        (
            [type] => dns-01
            [identifier] => example.com
            [name] => _acme-challenge
            [value] => 8hSNdxGNkx4MI7ZN5F8uZj3cTSMX92SGMCMHQMh0cMA
        )
)

开始域名验证

http-01
try {
    $client->domainValidation()->start($account, $validationStatus[0], \Rogierw\RwAcme\Enums\AuthorizationChallengeEnum::HTTP);
} catch (DomainValidationException $exception) {
    // The local HTTP challenge test has been failed...
}
dns-01
try {
    $client->domainValidation()->start($account, $validationStatus[0], \Rogierw\RwAcme\Enums\AuthorizationChallengeEnum::DNS);
} catch (DomainValidationException $exception) {
    // The local DNS challenge test has been failed...
}

生成CSR

$privateKey = \Rogierw\RwAcme\Support\OpenSsl::generatePrivateKey();
$csr = \Rogierw\RwAcme\Support\OpenSsl::generateCsr(['example.com'], $privateKey);

最终化订单

if ($order->isReady() && $client->domainValidation()->allChallengesPassed($order)) {
    $client->order()->finalize($order, $csr);
}

获取实际证书

if ($order->isFinalized()) {
    $certificateBundle = $client->certificate()->getBundle($order);
}

吊销证书

if ($order->isValid()) {
    $client->certificate()->revoke($certificateBundle->fullchain);
}