Skip to content

Commit

Permalink
feat: add ACME.js propagationDelay support
Browse files Browse the repository at this point in the history
fix: wait 10 seconds before attempting first propagation check, to prevent poluting the DNS cache with an invalid result

Work towards implementing suggestions in #9
  • Loading branch information
Cherry committed Apr 26, 2020
1 parent d4dea6f commit a8e4d40
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 41 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [1.2.0] - 2020-04-26
- Add ACME.js propagationDelay support
- Wait 10 seconds before attempting first propagation check, to prevent poluting the DNS cache with an invalid result

## [1.1.1] - 2020-02-04
- Simplify promise handlers

Expand Down
43 changes: 24 additions & 19 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,21 +38,26 @@ function delay(ms){
}

class Challenge {
constructor(options){
constructor(options = {}){
this.options = options;
this.client = new cloudflare({
email: options.email,
key: options.key,
token: options.token
});
this.propagationDelay = options.propagationDelay || 15000; // set propagationDelay for ACME.js
if(this.options.verifyPropagation){
// if our own propagation is set, like is required for greenlock.js at time of writing, disable use native ACME.js propagation delay to prevent double verification
this.propagationDelay = 0;
}
}

static create(config){
return new Challenge(Object.assign(config, this.options));
}

async init(){
return Promise.resolve(null);
return null;
}

async set(args){
Expand All @@ -72,7 +77,10 @@ class Challenge {
content: args.challenge.dnsAuthorization,
ttl: 120
});
// verify propagation
if(this.options.verifyPropagation){
// wait for one "tick" before attempting to query. This can help prevent the DNS cache from getting polluted with a bad value
await delay(this.options.waitFor || 10000);
await Challenge.verifyPropagation(args.challenge, this.options.verbose, this.options.waitFor, this.options.retries);
}
return null;
Expand Down Expand Up @@ -100,8 +108,12 @@ class Challenge {
await this.client.dnsRecords.del(zone.id, record.id);
}
}
// allow time for deletion to propagate
await Challenge.verifyPropagation(Object.assign({}, args.challenge, {removed: true}), this.options.verbose);
if(this.options.verifyPropagation){
// wait for one "tick" before attempting to query. This can help prevent the DNS cache from getting polluted with a bad value
await delay(this.options.waitFor || 10000);
// allow time for deletion to propagate
await Challenge.verifyPropagation(Object.assign({}, args.challenge, {removed: true}), this.options.verbose);
}
return null;
}catch(err){
throw new Error(err);
Expand Down Expand Up @@ -146,9 +158,7 @@ class Challenge {
async zones(args){ // eslint-disable-line no-unused-vars
try{
const zones = [];
for await(const zone of consumePages((pagination) => {
this.client.zones.browse(pagination);
})){
for await(const zone of consumePages(pagination => this.client.zones.browse(pagination))){
zones.push(zone.name);
}
return zones;
Expand Down Expand Up @@ -181,8 +191,7 @@ class Challenge {
return;
}
if(verbose){
console.error(err);
console.log(`Waiting for ${waitFor} ms before attempting propagation verification retry ${i + 1} / ${retries}.`);
console.log(`DNS not propagated yet for ${fullRecordName}. Checking again in ${waitFor}ms. (Attempt ${i + 1} / ${retries})`);
}
await delay(waitFor);
}
Expand All @@ -191,9 +200,7 @@ class Challenge {
}

async getZoneForDomain(domain){
for await(const zone of consumePages((pagination) => {
this.client.zones.browse(pagination);
})){
for await(const zone of consumePages(pagination => this.client.zones.browse(pagination))){
if(domain.endsWith(zone.name)){
return zone;
}
Expand All @@ -204,13 +211,11 @@ class Challenge {
async getTxtRecords(zone, name){
const records = [];

for await(const txtRecord of consumePages((pagination) => {
this.client.dnsRecords.browse(zone.id, {
...pagination,
type: 'TXT',
name
});
})){
for await(const txtRecord of consumePages(pagination => this.client.dnsRecords.browse(zone.id, {
...pagination,
type: 'TXT',
name
}))){
if(txtRecord.name === name){
records.push(txtRecord);
}
Expand Down
40 changes: 20 additions & 20 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "acme-dns-01-cloudflare",
"version": "1.1.1",
"version": "1.2.0",
"description": "Cloudflare DNS for Let's Encrypt / ACME dns-01 challenges with Greenlock.js and ACME.js",
"keywords": [
"acme",
Expand Down
3 changes: 2 additions & 1 deletion test.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ const challenger = require("./index.js").create({
token: process.env.CLOUDFLARE_TOKEN,
email: process.env.CLOUDFLARE_EMAIL,
key: process.env.CLOUDFLARE_APIKEY,
verifyPropagation: true
verifyPropagation: true,
verbose: true
});

const domain = process.env.DOMAIN;
Expand Down

0 comments on commit a8e4d40

Please sign in to comment.