added dns support

This commit is contained in:
peterbakker
2020-03-18 21:05:04 +01:00
parent 505ce369e5
commit 98d07ff83c
5 changed files with 167 additions and 110 deletions

View File

@@ -267,6 +267,8 @@ class Client
{
if ($type == self::VALIDATION_HTTP) {
return $this->selfHttpTest($authorization, $maxAttempts);
} elseif ($type == self::VALIDATION_DNS) {
return $this->selfDNSTest($authorization, $maxAttempts);
}
}
@@ -394,21 +396,17 @@ class Client
*/
protected function selfHttpTest(Authorization $authorization, $maxAttempts)
{
$file = $authorization->getFile();
$authorization->getDomain();
do {
$maxAttempts--;
try {
$response = $this->getSelfTestClient()->request(
'GET',
'http://' . $authorization->getDomain() . '/.well-known/acme-challenge/' . $file->getFilename()
'http://' . $authorization->getDomain() . '/.well-known/acme-challenge/' .
$authorization->getFile()->getFilename()
);
$contents = (string)$response->getBody();
if ($contents == $file->getContents()) {
{
return true;
}
if ($contents == $authorization->getFile()->getContents()) {
return true;
}
} catch (RequestException $e) {
}
@@ -417,6 +415,54 @@ class Client
return false;
}
/**
* Self DNS test client that uses Cloudflare's DNS API
* @param Authorization $authorization
* @param $maxAttempts
* @return bool
*/
protected function selfDNSTest(Authorization $authorization, $maxAttempts)
{
do {
$response = $this->getSelfTestDNSClient()->get(
'/dns-query',
[
'query' => [
'name' => $authorization->getTxtRecord()->getName(),
'type' => 'TXT'
]
]
);
$data = json_decode((string)$response->getBody(), true);
if (isset($data['Answer'])) {
foreach ($data['Answer'] as $result) {
if (trim($result['data'], "\"") == $authorization->getTxtRecord()->getValue()) {
return true;
}
}
}
sleep(ceil(30 / $maxAttempts));
$maxAttempts--;
} while ($maxAttempts > 0);
return false;
}
/**
* Return the preconfigured client to call Cloudflare's DNS API
* @return HttpClient
*/
protected function getSelfTestDNSClient()
{
return new HttpClient([
'base_uri' => 'https://cloudflare-dns.com',
'connect_timeout' => 10,
'headers' => [
'Accept' => 'application/dns-json',
],
]);
}
/**
* Initialize the client
*/

View File

@@ -122,13 +122,20 @@ class Authorization
}
/**
* Returns the DNS record object
*
* @param Challenge $challenge
* @return string containing TXT record for DNS challenge
* @return Record|bool
*/
public function getTxtRecord(Challenge $challenge)
public function getTxtRecord()
{
$raw=$challenge->getToken() . '.' . $this->digest;
$hash=hash('sha256', $raw, true);
return Helper::toSafeString($hash);
$challenge = $this->getDnsChallenge();
if ($challenge !== false) {
$hash = hash('sha256', $challenge->getToken() . '.' . $this->digest, true);
$value = Helper::toSafeString($hash);
return new Record('_acme-challenge.' . $this->getDomain(), $value);
}
return false;
}
}

46
src/Data/Record.php Normal file
View File

@@ -0,0 +1,46 @@
<?php
namespace Afosto\Acme\Data;
class Record
{
/**
* @var string
*/
protected $name;
/**
* @var string
*/
protected $value;
/**
* Record constructor.
* @param string $name
* @param string $value
*/
public function __construct(string $name, string $value)
{
$this->name = $name;
$this->value = $value;
}
/**
* Return the DNS TXT record name for validation
* @return string
*/
public function getName(): string
{
return $this->name;
}
/**
* Return the record value for DNS validation
* @return string
*/
public function getValue(): string
{
return $this->value;
}
}

View File

@@ -92,11 +92,11 @@ class Helper
file_put_contents($fn, implode("\n", $config));
$csr = openssl_csr_new([
'countryName' => 'NL',
'commonName' => $primaryDomain,
'commonName' => $primaryDomain,
], $key, [
'config' => $fn,
'config' => $fn,
'req_extensions' => 'SAN',
'digest_alg' => 'sha512',
'digest_alg' => 'sha512',
]);
unlink($fn);
@@ -140,37 +140,4 @@ class Helper
return $accountDetails;
}
/**
* Wait until a set of DNS records return specific TXT record values
*
* @param array mapping domain to desired TXT record value
* @param $txtRecord
* @param int $maxSeconds to wait
* @return bool true if record found, false otherwise
*/
public static function waitForDNS(array $records, $maxSeconds=60)
{
$waitUntil = time() + $maxSeconds;
do {
//validate all remaining records..
foreach($records as $domain=>$txtRecord) {
$record=dns_get_record($domain, DNS_TXT);
if (isset($record[0]['txt']) && ($record[0]['txt']===$txtRecord)) {
unset($records[$domain]);
}
}
//did we find them all?
if (empty($records)) {
return true;
}
//otherwise still domains to check...have a short sleep
sleep(1);
} while(time() < $waitUntil);
return false;
}
}