initial commit

This commit is contained in:
AJ ONeal 2019-06-06 23:32:22 -06:00
commit ed4a83d788
6 changed files with 161 additions and 0 deletions

8
.prettierrc Normal file
View File

@ -0,0 +1,8 @@
{
"bracketSpacing": true,
"printWidth": 80,
"singleQuote": true,
"tabWidth": 2,
"trailingComma": "none",
"useTabs": true
}

10
README.md Normal file
View File

@ -0,0 +1,10 @@
# [acme-dns-01-duckdns](https://git.rootprojects.org/root/acme-dns-01-duckdns) | a [Root](https://rootrpojects.org) project
DuckDNS for Let's Encrypt / ACME dns-01 challenges with ACME.js and Greenlock.js (Node.js).
# Tests
```
# node ./test.js domain-zone api-token
node ./test.js example.com xxxxxx
```

3
index.js Normal file
View File

@ -0,0 +1,3 @@
'use strict';
module.exports = require('./lib/index.js');

87
lib/index.js Normal file
View File

@ -0,0 +1,87 @@
'use strict';
var request = require('@root/request');
request = require('util').promisify(request);
var dns = require('dns');
module.exports.create = function(config) {
// config = { baseUrl, token, apiTimeout }
var baseUrl = config.baseUrl || 'https://www.duckdns.org';
var authtoken = config.token;
var apiTimeout = config.apiTimeout || 5000;
// return object containing get/set/remove functions
return {
set: function(data) {
var domain_name = data.challenge.identifier.value;
var txt = data.challenge.dnsAuthorization;
var url =
baseUrl +
'/update?domains=' +
domain_name +
'&token=' +
authtoken +
'&txt=' +
txt;
// console.log("adding txt", data);
return request({
method: 'GET',
url: url
}).then(function(resp) {
if (resp === 'OK') {
return true;
}
throw new Error('record did not set. check subdomain, api key, etc');
});
},
remove: function(data) {
var domain_name = data.challenge.identifier.value;
var txt = data.challenge.dnsAuthorization;
var url =
baseUrl +
'/update?domains=' +
domain_name +
'&token=' +
authtoken +
'&txt=' +
txt +
'&clear=true';
// console.log("removing txt");
return request({
method: 'GET',
url: url
}).then(function(resp) {
if (resp === 'OK') {
return true;
}
throw new Error('Couldnt remove record. check subdomain, api key, etc');
});
},
get: function(data) {
// the duckdns doesnt provide an API to fetch DNS records so we are using Node DNS library to get TXT record.
// We need to add manual delay as the DNS records do not get updated instantly.
var domain_name = data.challenge.identifier.value;
return delay(apiTimeout).then(function() {
console.log('fetching txt', data);
return new Promise(function(resolve, reject) {
dns.resolveTxt(domain_name, (err, txt) => {
if (err) {
console.error(err);
reject(null);
}
// console.log(txt);
if (txt && txt[0] && txt[0][0])
resolve({ dnsAuthorization: txt[0][0] });
else resolve(null);
});
});
});
}
};
};
function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}

30
package.json Normal file
View File

@ -0,0 +1,30 @@
{
"name": "acme-dns-01-duckdns",
"version": "3.0.0",
"description": "DuckDNS for Let's Encrypt / ACME dns-01 challenges with ACME.js and Greenlock.js",
"main": "index.js",
"scripts": {
"test": "node ./test.js"
},
"repository": {
"type": "git",
"url": "https://git.rootprojects.org/root/acme-dns-01-duckdns.git"
},
"keywords": [
"duckdns",
"duck",
"dns",
"dns-01",
"letsencrypt",
"acme",
"greenlock"
],
"author": "AJ ONeal <coolaj86@gmail.com> (https://coolaj86.com/)",
"license": "MPL-2.0",
"dependencies": {
"@root/request": "^1.3.11"
},
"devDependencies": {
"acme-challenge-test": "^3.1.0"
}
}

23
test.js Executable file
View File

@ -0,0 +1,23 @@
#!/usr/bin/env node
'use strict';
// See https://git.coolaj86.com/coolaj86/acme-challenge-test.js
var tester = require('acme-challenge-test');
// Usage: node ./test.js example.com xxxxxxxxx
var zone = process.argv[2];
var challenger = require('./index.js').create({
token: process.argv[3]
});
// The dry-run tests can pass on, literally, 'example.com'
// but the integration tests require that you have control over the domain
tester
.testZone('dns-01', zone, challenger)
.then(function() {
console.info('PASS', zone);
})
.catch(function(e) {
console.error(e.message);
console.error(e.stack);
});