From 79a83291794d21aaaf252a7d5496ffb2e0476ece Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Sat, 15 Jun 2019 11:30:02 -0600 Subject: [PATCH] v3.0.0: initial release --- .gitignore | 1 + README.md | 77 +++++++++++++++++++++++++++++++++++++++++----------- lib/index.js | 41 ++++++++++++++++++---------- package.json | 1 - 4 files changed, 89 insertions(+), 31 deletions(-) diff --git a/.gitignore b/.gitignore index c2658d7..8e688ed 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ +*secret* node_modules/ diff --git a/README.md b/README.md index e94c19f..f6e58df 100644 --- a/README.md +++ b/README.md @@ -5,24 +5,39 @@ Digital Ocean DNS + Let's Encrypt for Node.js This handles ACME dns-01 challenges, compatible with ACME.js and Greenlock.js. Passes [acme-dns-01-test](https://git.rootprojects.org/root/acme-dns-01-test.js). +## Features + +- Compatible + - [x] Let's Encrypt v2.1 / ACME draft 18 (2019) + - [x] Digital Ocean v2 API + - [x] ACME.js, Greenlock.js, and others +- Quality + - [x] node v6 compatible VanillaJS + - [x] < 150 lines of code + - [x] **Zero Dependencies** + # Install ```bash npm install --save acme-dns-01-digitalocean@3.x ``` +Generate Digital Ocean API Token: + +- + # Usage First you create an instance with your credentials: ```js var dns01 = require('acme-dns-01-digitalocean').create({ - baseUrl: 'https://api.digitalocean.com', // default + baseUrl: 'https://api.digitalocean.com/v2/domains', // default token: 'xxxx' }); ``` -Then you can use it with any compatible ACME module, +Then you can use it with any compatible ACME library, such as Greenlock.js or ACME.js. ### Greenlock.js @@ -37,8 +52,9 @@ var greenlock = Greenlock.create({ }); ``` -See [Greenlockā„¢ Express](https://git.rootprojects.org/root/greenlock-express.js) -and/or [Greenlock.js](https://git.rootprojects.org/root/greenlock.js) documentation for more details. +See [Greenlock Express](https://git.rootprojects.org/root/greenlock-express.js) +and/or [Greenlock.js](https://git.rootprojects.org/root/greenlock.js) +documentation for more details. ### ACME.js @@ -50,20 +66,29 @@ See the [ACME.js](https://git.rootprojects.org/root/acme-v2.js) for more details ### Build your own +There are only 5 methods: + +- `init(config)` +- `zones(opts)` +- `set(opts)` +- `get(opts)` +- `remove(opts)` + ```js dns01 - .set({ - identifier: { value: 'foo.example.com' }, - wildcard: false, - dnsHost: '_acme-challenge.foo.example.com' - dnsAuthorization: 'xxx_secret_xxx' - }) - .then(function () { - console.log("TXT record set"); - }) - .catch(function () { - console.log("Failed to set TXT record"); - }); + .set({ + identifier: { value: 'foo.example.co.uk' }, + wildcard: false, + dnsZone: 'example.co.uk', + dnsPrefix: '_acme-challenge.foo', + dnsAuthorization: 'xxx_secret_xxx' + }) + .then(function() { + console.log('TXT record set'); + }) + .catch(function() { + console.log('Failed to set TXT record'); + }); ``` See [acme-dns-01-test](https://git.rootprojects.org/root/acme-dns-01-test.js) @@ -75,3 +100,23 @@ for more implementation details. # node ./test.js domain-zone api-token node ./test.js example.com xxxxxx ``` + +# Authors + +- Aneem Patrabansha +- AJ ONeal + +See AUTHORS for contact info. + + + +# Legal + +[acme-dns-01-digitalocean.js](https://git.coolaj86.com/coolaj86/acme-dns-01-digitalocean.js) | +MPL-2.0 | +[Terms of Use](https://therootcompany.com/legal/#terms) | +[Privacy Policy](https://therootcompany.com/legal/#privacy) + +Copyright 2019 The Root Group LLC + + diff --git a/lib/index.js b/lib/index.js index d3a9022..de3f103 100644 --- a/lib/index.js +++ b/lib/index.js @@ -1,19 +1,17 @@ 'use strict'; -var request = require('@root/request'); -request = require('util').promisify(request); - var defaults = { - baseUrl: 'https://api.digitalocean.com' + baseUrl: 'https://api.digitalocean.com/v2/domains' }; module.exports.create = function(config) { // config = { baseUrl, token } - var baseUrl = config.baseUrl || defaults.baseUrl; + var baseUrl = (config.baseUrl || defaults.baseUrl).replace(/\/$/, ''); var authtoken = config.token; + var request; function api(method, path, form) { - return request({ + var req = { method: method, url: baseUrl + path, headers: { @@ -22,13 +20,27 @@ module.exports.create = function(config) { }, json: true, form: form + }; + return request(req).then(function(resp) { + if (2 !== Math.floor(resp.statusCode / 100)) { + console.error(resp.statusCode, req.url); + console.error(); + console.error('Request:'); + console.error(req); + console.error(); + console.error('Response:'); + console.error(resp.body); + console.error(); + throw new Error('Error response. Check token, baseUrl, domains, etc.'); + } + return resp; }); } var helpers = { getZonenames: function(/*opts*/) { // { dnsHosts: [ xxxx.foo.example.com ] } - return api('GET', '/v2/domains/').then(function(resp) { + return api('GET', '/').then(function(resp) { return resp.body.domains.map(function(x) { return x.name; }); @@ -42,9 +54,7 @@ module.exports.create = function(config) { // Digital ocean provides the api to fetch records by ID. Since we do not have id, we fetch all the records, // filter the required TXT record - return api('GET', '/v2/domains/' + data.zone + '/records').then(function( - resp - ) { + return api('GET', '/' + data.zone + '/records').then(function(resp) { resp = resp.body; var entries = resp && @@ -58,6 +68,10 @@ module.exports.create = function(config) { }; return { + init: function(opts) { + request = opts.request; + return null; + }, zones: function(data) { //console.info('Get zones'); return helpers.getZonenames(data); @@ -67,7 +81,7 @@ module.exports.create = function(config) { var txt = ch.dnsAuthorization; // console.info('Adding TXT', data); - return api('POST', '/v2/domains/' + ch.dnsZone + '/records', { + return api('POST', '/' + ch.dnsZone + '/records', { type: 'TXT', name: ch.dnsPrefix, data: txt, @@ -93,12 +107,11 @@ module.exports.create = function(config) { return helpers.getTXTRecord(payload).then(function(txtRecord) { if (txtRecord) { - var url = - baseUrl + '/v2/domains/' + ch.dnsZone + '/records/' + txtRecord.id; + var url = baseUrl + '/' + ch.dnsZone + '/records/' + txtRecord.id; return api( 'DELETE', - '/v2/domains/' + ch.dnsZone + '/records/' + txtRecord.id + '/' + ch.dnsZone + '/records/' + txtRecord.id ).then(function(resp) { resp = resp.body; return true; diff --git a/package.json b/package.json index 5046272..04d99ab 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,6 @@ "author": "AJ ONeal (https://coolaj86.com/)", "license": "MPL-2.0", "dependencies": { - "@root/request": "^1.3.11" }, "devDependencies": { "acme-dns-01-test": "^3.2.0"