letsencrypt:challenges throws TypeError because challenges are already arrays

Environment

ApisCP:

3.2.0
revision: 097c6710d91a8ad731adf8622b31d6b06a8e6a21

AcmePHP:

acmephp/core dev-master ca7f26e
acmephp/ssl  2.1.0

Steps to reproduce

Run:

env DEBUG=1 cpcmd letsencrypt:challenges \
    '[eric.domainhostingshop.com.au]'

Actual result

ApisCP throws:

TypeError: Letsencrypt_Module::{closure}():
Argument #1 ($c) must be of type
AcmePhp\Core\Protocol\AuthorizationChallenge,
array given

The relevant code in lib/modules/letsencrypt.php is:

foreach (array_get($challenges->toArray(), 'authorizationsChallenges', []) as $domain => $challengeTypes) {
    $sans[$domain] = array_map(static function (AuthorizationChallenge $c) {
        return $c->toArray();
    }, $challengeTypes);
}

However, $challenges->toArray() has already converted the contained AuthorizationChallenge objects to arrays.

The runtime value passed to the closure is already similar to:

[
  domain: "eric.domainhostingshop.com.au",
  status: "valid",
  type: "http-01",
  url: "...",
  token: "...",
  payload: "..."
]

Expected result

letsencrypt:challenges should return the challenge data without throwing a TypeError.

Proposed fix

Replace:

foreach (array_get($challenges->toArray(), 'authorizationsChallenges', []) as $domain => $challengeTypes) {
    $sans[$domain] = array_map(static function (AuthorizationChallenge $c) {
        return $c->toArray();
    }, $challengeTypes);
}

with:

foreach (array_get($challenges->toArray(), 'authorizationsChallenges', []) as $domain => $challengeTypes) {
    $sans[$domain] = $challengeTypes;
}

This fixes the command because the challenge objects have already been serialised by CertificateOrder::toArray().

Related observation

I originally found this while troubleshooting certificate issuance. HTTP-01 validation succeeds, but issuance subsequently fails with:

ACME server reported the request was malformed:
No such challenge

It is not yet clear whether that issuance error is directly related to this bug, but the letsencrypt:challenges TypeError is independently reproducible and fixed by the change above.

The patch resolved the issue.

AI was used to help diaignose the problem, create the patch and generate this report.

Thanks for the bug report. This is fixed in edge, due to an API change in acmephp circa 2022.

I’ve seen “No such challenge” before when issuing certificates but can’t reliably reproduce it. Running the order again fixes it, from what I’ve surveyed.