Refactor challenge solving so it can run in parallel
This commit is contained in:
@@ -2,11 +2,13 @@
|
|||||||
|
|
||||||
namespace Kelunik\AcmeClient\Commands;
|
namespace Kelunik\AcmeClient\Commands;
|
||||||
|
|
||||||
|
use Amp\CombinatorException;
|
||||||
use Amp\Dns\Record;
|
use Amp\Dns\Record;
|
||||||
use Exception;
|
use Exception;
|
||||||
use Kelunik\Acme\AcmeClient;
|
use Kelunik\Acme\AcmeClient;
|
||||||
use Kelunik\Acme\AcmeException;
|
use Kelunik\Acme\AcmeException;
|
||||||
use Kelunik\Acme\AcmeService;
|
use Kelunik\Acme\AcmeService;
|
||||||
|
use Kelunik\Acme\KeyPair;
|
||||||
use Kelunik\Acme\OpenSSLKeyGenerator;
|
use Kelunik\Acme\OpenSSLKeyGenerator;
|
||||||
use Kelunik\AcmeClient\Stores\CertificateStore;
|
use Kelunik\AcmeClient\Stores\CertificateStore;
|
||||||
use Kelunik\AcmeClient\Stores\ChallengeStore;
|
use Kelunik\AcmeClient\Stores\ChallengeStore;
|
||||||
@@ -77,7 +79,45 @@ class Issue implements Command {
|
|||||||
|
|
||||||
$acme = new AcmeService(new AcmeClient($server, $keyPair));
|
$acme = new AcmeService(new AcmeClient($server, $keyPair));
|
||||||
|
|
||||||
|
$promises = [];
|
||||||
|
|
||||||
foreach ($domains as $i => $domain) {
|
foreach ($domains as $i => $domain) {
|
||||||
|
$promises[] = \Amp\resolve($this->solveChallenge($acme, $keyPair, $domain, $docRoots[$i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
list($errors) = (yield \Amp\any($promises));
|
||||||
|
|
||||||
|
if (!empty($errors)) {
|
||||||
|
foreach ($errors as $error) {
|
||||||
|
$this->logger->error($error->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new AcmeException("Issuance failed, not all challenges could be solved.");
|
||||||
|
}
|
||||||
|
|
||||||
|
$path = "certs/" . $keyFile . "/" . reset($domains) . "/key.pem";
|
||||||
|
$bits = $args->get("bits");
|
||||||
|
|
||||||
|
try {
|
||||||
|
$keyPair = (yield $keyStore->get($path));
|
||||||
|
} catch (KeyStoreException $e) {
|
||||||
|
$keyPair = (new OpenSSLKeyGenerator)->generate($bits);
|
||||||
|
$keyPair = (yield $keyStore->put($path, $keyPair));
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->logger->info("Requesting certificate ...");
|
||||||
|
|
||||||
|
$location = (yield $acme->requestCertificate($keyPair, $domains));
|
||||||
|
$certificates = (yield $acme->pollForCertificate($location));
|
||||||
|
|
||||||
|
$path = dirname(dirname(__DIR__)) . "/data/certs/" . $keyFile;
|
||||||
|
$certificateStore = new CertificateStore($path);
|
||||||
|
yield $certificateStore->put($certificates);
|
||||||
|
|
||||||
|
$this->logger->info("Successfully issued certificate, see {$path}/" . reset($domains));
|
||||||
|
}
|
||||||
|
|
||||||
|
private function solveChallenge(AcmeService $acme, KeyPair $keyPair, $domain, $path) {
|
||||||
list($location, $challenges) = (yield $acme->requestChallenges($domain));
|
list($location, $challenges) = (yield $acme->requestChallenges($domain));
|
||||||
$goodChallenges = $this->findSuitableCombination($challenges);
|
$goodChallenges = $this->findSuitableCombination($challenges);
|
||||||
|
|
||||||
@@ -98,7 +138,7 @@ class Issue implements Command {
|
|||||||
$this->logger->info("Providing payload at http://{$domain}/.well-known/acme-challenge/{$token}");
|
$this->logger->info("Providing payload at http://{$domain}/.well-known/acme-challenge/{$token}");
|
||||||
|
|
||||||
|
|
||||||
$challengeStore = new ChallengeStore($docRoots[$i]);
|
$challengeStore = new ChallengeStore($path);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$challengeStore->put($token, $payload, isset($user) ? $user : null);
|
$challengeStore->put($token, $payload, isset($user) ? $user : null);
|
||||||
@@ -124,28 +164,6 @@ class Issue implements Command {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$path = "certs/" . $keyFile . "/" . reset($domains) . "/key.pem";
|
|
||||||
$bits = $args->get("bits");
|
|
||||||
|
|
||||||
try {
|
|
||||||
$keyPair = (yield $keyStore->get($path));
|
|
||||||
} catch (KeyStoreException $e) {
|
|
||||||
$keyPair = (new OpenSSLKeyGenerator)->generate($bits);
|
|
||||||
$keyPair = (yield $keyStore->put($path, $keyPair));
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->logger->info("Requesting certificate ...");
|
|
||||||
|
|
||||||
$location = (yield $acme->requestCertificate($keyPair, $domains));
|
|
||||||
$certificates = (yield $acme->pollForCertificate($location));
|
|
||||||
|
|
||||||
$path = dirname(dirname(__DIR__)) . "/data/certs/" . $keyFile;
|
|
||||||
$certificateStore = new CertificateStore($path);
|
|
||||||
yield $certificateStore->put($certificates);
|
|
||||||
|
|
||||||
$this->logger->info("Successfully issued certificate, see {$path}/" . reset($domains));
|
|
||||||
}
|
|
||||||
|
|
||||||
private function checkDnsRecords($domains) {
|
private function checkDnsRecords($domains) {
|
||||||
$promises = [];
|
$promises = [];
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user