mbretter/acme2-library 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

mbretter/acme2-library

Composer 安装命令:

composer require mbretter/acme2-library

包简介

ACME2 low level library

README 文档

README

Coverage Status Build Status Latest Stable Version Total Downloads License

ACME2 low level php library

This library has been built to be integrated into applications, not as a standalone acme client.

The ACME2 specs: https://ietf-wg-acme.github.io/acme/draft-ietf-acme-acme.html

Benefits:

  • no dependencies to other packages, like http clients
  • it comes up with a builtin http client (based on PHP streams), though any other PSR-7 compliant http client could be used
  • the PSR-7 implementation is heavily based on slim, with some modifications
  • it uses standardclasses and arrays, no fancy data objects or sophisticated data models
  • it does not take care about data storage, it is up to you to store credentials/orders/states

namespaces

use Karl\Acme2;
use Karl\Acme2\Resources;

acme

The Acme class is the manager for all requests, it carries the directory, the private key, fetches nonces and is the interface between the resource objects and the http client.

$acme = new Acme2\Acme(); // without any args letsencrypt staging urls are used

$acme = new Acme2\Acme(true); // for letsencrypt production use

$acme = new Acme2\Acme('https://someca.example.com/acme'); // for any other acme compatible CA

$acme = new Acme2\Acme(true, $myHttpClient); // use your own http client

resources

You can create the objects yourself, this is useful, if you have your own DI/Container system:

$acme = new Acme2\Acme();

$key = new Acme2\Key\RSA($pemKey);
$acme->setKey($key);

$account = new Resources\Account($acme)
$accountData = $account->lookup();

The other way ist to use the acme object to retrieve the resource objects, which is more fluent:

$acme = new Acme2\Acme();

$key = new Acme2\Key\RSA($pemKey);
$acme->setKey($key);

$accountData = $acme->account()->lookup();
...

account management

Before you can send any other requests you must subscribe for an account, this is done by generating your private key and submitting the create call.

$acme = new Acme2\Acme();

$key = new Acme2\Key\RSA(); // we use an RSA key
$key->generate();
$pem = $key->getPem(); // get the PEM, store your key somewhere

$acme->setKey($key); // acme needs a key to operate

$accountData = $acme->account()->create([
    'termsOfServiceAgreed' => true, 
    'contact' => ['mailto:example@example.com']
]);
$kid = $accountData->url; // acme uses the account url as keyId

You have to store the private key PEM and the kid somewhere in your system.

account lookup

If you have the PEM only, the key id can be retrieved using the lookup method:

$acme = new Acme2\Acme();

$key = new Acme2\Key\RSA($pemKey);

$info = $acme->account()->lookup();
if ($info !== null)
{
    $key->setKid($info->url); // account location is used as kid
}

account deactivation

$acme = new Acme2\Acme();
$key = new Acme2\Key\RSA($pemKey);
$acme->setKey($key);

$account = new Resources\Account($acme);
$account->deactivate($kid);

orders

create new order

$acme = new Acme2\Acme();
$key = new Acme2\Key\RSA($pemKey);
$key->setKid($kid);
$acme->setKey($key);

$newOrder = $acme->order()->addIdentifier(null, 'acme01.example.com'); // create a new order object 
$acme->order()->addIdentifier($newOrder, 'acme02.example.com'); // add another identifier

$orderData = $acme->order()->create($newOrder);

$orderUrl = $orderData->url; // store the orderUrl somewhere

create an order for a wildcard domain:

...
$newOrder = $acme->order()->addIdentifier(null, '*.example.com');

$orderData = $acme->order()->create($newOrder);

$orderUrl = $orderData->url; // store the orderUrl somewhere

Note: When using wildcard domains, Lets encrypt supports DNS validation only.

get an existing order

$order = new Acme2\Resources\Order($acme);

$orderData = $order->get($orderUrl);

print_r($orderData);

example output:

stdClass Object
(
    [status] => valid
    [expires] => 2018-05-23T14:02:32Z
    [identifiers] => Array
        (
            [0] => stdClass Object
                (
                    [type] => dns
                    [value] => acme01.example.com
                )

        )

    [authorizations] => Array
        (
            [0] => https://acme-staging-v02.api.letsencrypt.org/acme/authz/AAAAA8
        )

    [finalize] => https://acme-staging-v02.api.letsencrypt.org/acme/finalize/999999/111111
    [certificate] => https://acme-staging-v02.api.letsencrypt.org/acme/cert/a83732947234cdef
    [url] => https://acme-staging-v02.api.letsencrypt.org/acme/order/999999/111111
)

authorization

Basically there are two possibilities to validate your orders, the first one is to put the key authorization into a wellknown path and the other one is to provision a DNS TXT record with the authentication key.

Once you have done one of these steps, you have to tell the CA to verify the order, the verification is done by either querying the DNS record or by fetching the key authorization from the well known path.

The authentication must be done for each identifier added to the order, each authentication usually offers the DNS and the HTTP method, they are called challenges, for wildcard domains the DNS challenge is supported only.

$orderData = $acme->order()->get($orderUrl);

foreach ($orderData->authorizations as $a)
{
    $authData = $acme->authorization()->get($a);

    printf("authorization for: %s\n", $authData->identifier->value);

    $challengeData = $acme->authorization()->getChallenge($authData, 'dns-01');
    if ($challengeData === null)
        continue;

    // you have to add the $authKey to the DNS TXT record
    $authKey = $acme->challenge()->buildKeyAuthorization($challengeData);
    printf("DNS auth key is: %s\n", $authKey);

    // tell the CA to validate the challenge
    $acme->challenge()->validate($challengeData->url);

    $challengeData = $acme->authorization()->getChallenge($authData, 'http-01');
    if ($challengeData === null)
        continue;

    // you have to put the $authKey to the well known path
    $authKey = $acme->challenge()->buildKeyAuthorization($challengeData);
    printf("HTTP auth key is: %s\n", $authKey);

    // tell the CA to validate the challenge
    $acme->challenge()->validate($challengeData->url);
}

practically, only one challenge type needs to succeed for successfully validating the identifier.

DNS challenge

The DNS TXT record, where you have to put the auth key, is called _acme-challenge, e.g.

_acme-challenge.example.org 300 IN TXT "w2toDKxcQx2N8zcu4HnDboT1FceHs7lupLMTXsPbXCQ".

You can put multiple TXT records with the same name there, this is needed if you are using wildcard domains and an alternative subject name with the domainname.

HTTP challenge

When using HTTP challenges, you have to put the auth key under the path:

/.well-known/acme-challenge/<token>

/.well-known/acme-challenge/LoqXcYV8q5ONbJQxbmR7SCTNo3tiAXDfowyjxAjEuX0

The token can be found inside the challenge data.

The Content-Type of the response must be application/octet-stream.

Important: the well known path must be available using HTTP not HTTPS, even if you have a valid certificate, otherwise you will have problems when renewing your certificate.

finalize

ToDo

download the certificate

ToDo

renew

ToDo

ToDos

  • EC keys

mbretter/acme2-library 适用场景与选型建议

mbretter/acme2-library 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 38 次下载、GitHub Stars 达 0, 最近一次更新时间为 2018 年 06 月 04 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「letsencrypt」 「acme2」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 mbretter/acme2-library 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 mbretter/acme2-library 我们能提供哪些服务?
定制开发 / 二次开发

基于 mbretter/acme2-library 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 38
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 2
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 1
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2018-06-04