v3.0.0: Name.com DNS + Let's Encrypt for Node.js
This commit is contained in:
parent
c19b850d6e
commit
18fcf2ce31
30
README.md
30
README.md
@ -8,7 +8,7 @@ Handles ACME dns-01 challenges. Compatible with ACME.js and Greenlock.js. Passes
|
||||
|
||||
- Compatible
|
||||
- Let’s Encrypt v2.1 / ACME draft 18 (2019)
|
||||
- Name.com API
|
||||
- Name.com v4 API
|
||||
- ACME.js, Greenlock.js, and others
|
||||
- Quality
|
||||
- node v6 compatible VanillaJS
|
||||
@ -21,10 +21,22 @@ Handles ACME dns-01 challenges. Compatible with ACME.js and Greenlock.js. Passes
|
||||
npm install --save acme-dns-01-namedotcom
|
||||
```
|
||||
|
||||
Name.com Token:
|
||||
## Name.com API Token
|
||||
|
||||
- Login to your account at: {{ Service URL }}
|
||||
- {{ Instructions to generate token }}
|
||||
- Login to your account at: <https://www.name.com/>
|
||||
- Generate a token at <https://www.name.com/account/settings/api>
|
||||
- **Important** Enable API Access, _again_ at <https://www.name.com/account/settings/security>
|
||||
|
||||
The following error is what you may get if you have Two-Factor Auth and don't _Enable API Access_ the second time:
|
||||
|
||||
```json
|
||||
{
|
||||
"message": "Permission Denied",
|
||||
"details": "Authentication Error - Account Has Namesafe Enabled"
|
||||
}
|
||||
```
|
||||
|
||||
If you're using the Whitelist IPs feature, don't forget to add your test environment!
|
||||
|
||||
# Usage
|
||||
|
||||
@ -32,7 +44,8 @@ First you create an instance with your credentials:
|
||||
|
||||
```js
|
||||
var dns01 = require('acme-dns-01-namedotcom').create({
|
||||
baseUrl: '{{ api url }}', // default
|
||||
baseUrl: 'http://api.name.com/v4/', // default
|
||||
username: 'johndoe',
|
||||
token: 'xxxx'
|
||||
});
|
||||
```
|
||||
@ -51,7 +64,8 @@ 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
|
||||
|
||||
@ -93,8 +107,8 @@ See acme-dns-01-test for more implementation details.
|
||||
# Tests
|
||||
|
||||
```bash
|
||||
# node ./test.js domain-zone api-token
|
||||
node ./test.js example.com xxxxxx
|
||||
# node ./test.js domain-zone username api-token
|
||||
node ./test.js example.com me xxxxxx
|
||||
```
|
||||
|
||||
# Authors
|
||||
|
@ -1,2 +1,4 @@
|
||||
ZONE=example.co.uk
|
||||
TOKEN=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
# Used for HTTP Basic Auth
|
||||
USERNAME=johndoe
|
||||
TOKEN=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
|
132
lib/index.js
132
lib/index.js
@ -1,29 +1,137 @@
|
||||
'use strict';
|
||||
|
||||
var request;
|
||||
var defaults = {};
|
||||
var defaults = {
|
||||
baseUrl: 'https://api.name.com/v4/'
|
||||
};
|
||||
|
||||
module.exports.create = function(config) {
|
||||
return {
|
||||
var baseUrl = (config.baseUrl || defaults.baseUrl).replace(/\/$/, '');
|
||||
var token = config.token;
|
||||
var username = config.username;
|
||||
|
||||
var plugin = {
|
||||
init: function(opts) {
|
||||
request = opts.request;
|
||||
return null;
|
||||
},
|
||||
|
||||
// We must list all zones (domains) in the account
|
||||
zones: function(data) {
|
||||
//console.info('List Zones', data);
|
||||
throw Error('listing zones not implemented');
|
||||
return api({
|
||||
url: baseUrl + '/domains'
|
||||
}).then(function(resp) {
|
||||
return resp.body.domains.map(function(d) {
|
||||
//#console.log("Domain Name:", d.domainName);
|
||||
return d.domainName;
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
// We must set each record as required
|
||||
set: function(data) {
|
||||
// console.info('Add TXT', data);
|
||||
throw Error('setting TXT not implemented');
|
||||
},
|
||||
remove: function(data) {
|
||||
// console.info('Remove TXT', data);
|
||||
throw Error('removing TXT not implemented');
|
||||
// console.log('Add TXT', data);
|
||||
var ch = data.challenge;
|
||||
if (!ch.dnsZone) {
|
||||
throw new Error(
|
||||
'[Name.com Plugin] Unknown domain: ',
|
||||
data.domain || data.dnsHost
|
||||
);
|
||||
}
|
||||
return api({
|
||||
method: 'POST',
|
||||
url: baseUrl + '/domains/' + ch.dnsZone + '/records',
|
||||
json: {
|
||||
host: ch.dnsPrefix,
|
||||
type: 'TXT',
|
||||
answer: ch.dnsAuthorization,
|
||||
ttl: 300 // minimum allowed value
|
||||
}
|
||||
}).then(function(resp) {
|
||||
if (!resp.body.id) {
|
||||
throw Error('[Name.com API] [set] ' + resp.body);
|
||||
}
|
||||
return null;
|
||||
});
|
||||
},
|
||||
|
||||
// We must be able to confirm that the appropriate records were set
|
||||
get: function(data) {
|
||||
// console.info('List TXT', data);
|
||||
throw Error('listing TXTs not implemented');
|
||||
// console.log('List TXT', data);
|
||||
var ch = data.challenge;
|
||||
if (!ch.dnsZone) {
|
||||
throw new Error(
|
||||
'[Name.com Plugin] Unknown domain: ',
|
||||
data.domain || data.dnsHost
|
||||
);
|
||||
}
|
||||
return api({
|
||||
url: baseUrl + '/domains/' + ch.dnsZone + '/records'
|
||||
}).then(function(resp) {
|
||||
var value = resp.body.records.filter(function(r) {
|
||||
return (
|
||||
r.host === ch.dnsPrefix &&
|
||||
'TXT' === r.type &&
|
||||
ch.dnsAuthorization === r.answer
|
||||
);
|
||||
})[0];
|
||||
if (!value) {
|
||||
return null;
|
||||
}
|
||||
// adding id to make re-usable for remove
|
||||
return { id: value.id, dnsAuthorization: value.answer };
|
||||
});
|
||||
},
|
||||
|
||||
// We must delete junk records once we're done
|
||||
remove: function(data) {
|
||||
// console.log('Remove TXT', data);
|
||||
var ch = data.challenge;
|
||||
return plugin.get(data).then(function(r) {
|
||||
if (!r.id) {
|
||||
throw new Error(
|
||||
'[Name.com Plugin] [del] Did not find TXT record for ' +
|
||||
ch.dnsHost
|
||||
);
|
||||
}
|
||||
return api({
|
||||
method: 'DELETE',
|
||||
url: baseUrl + '/domains/' + ch.dnsZone + '/records/' + r.id
|
||||
}).then(function(resp) {
|
||||
return null;
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// Authentication and Error handling here
|
||||
function api(opts) {
|
||||
opts.auth = {
|
||||
user: username,
|
||||
pass: token,
|
||||
sendImmediately: true
|
||||
};
|
||||
if (!opts.json) {
|
||||
opts.json = true;
|
||||
}
|
||||
return request(opts).then(function(resp) {
|
||||
if (!resp.body.message) {
|
||||
return resp;
|
||||
}
|
||||
|
||||
console.error(opts.method + ' ' + opts.url);
|
||||
console.error(resp.headers);
|
||||
console.error(resp.body);
|
||||
throw new Error(
|
||||
'[Name.com API] ' +
|
||||
(opts.method || 'GET') +
|
||||
' ' +
|
||||
opts.url +
|
||||
' : ' +
|
||||
resp.body.message
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
return plugin;
|
||||
};
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "acme-dns-01-namedotcom",
|
||||
"version": "0.0.1",
|
||||
"version": "3.0.0",
|
||||
"description": "Name.com + Let's Encrypt for Node.js - ACME dns-01 challenges w/ ACME.js and Greenlock.js",
|
||||
"main": "index.js",
|
||||
"files": [
|
||||
@ -26,9 +26,9 @@
|
||||
"author": "AJ ONeal <coolaj86@gmail.com> (https://coolaj86.com/)",
|
||||
"license": "MPL-2.0",
|
||||
"devDependencies": {
|
||||
"acme-challenge-test": "^3.3.2",
|
||||
"dotenv": "^8.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"acme-challenge-test": "^3.3.2"
|
||||
}
|
||||
}
|
||||
|
6
test.js
6
test.js
@ -5,10 +5,12 @@
|
||||
var tester = require('acme-challenge-test');
|
||||
require('dotenv').config();
|
||||
|
||||
// Usage: node ./test.js example.com xxxxxxxxx
|
||||
// Usage: node ./test.js example.com username xxxxxxxxx
|
||||
var zone = process.argv[2] || process.env.ZONE;
|
||||
var challenger = require('./index.js').create({
|
||||
token: process.argv[3] || process.env.TOKEN
|
||||
//baseUrl: 'http://api.dev.name.com/v4/', // sandbox url
|
||||
username: process.argv[3] || process.env.USERNAME,
|
||||
token: process.argv[4] || process.env.TOKEN
|
||||
});
|
||||
|
||||
// The dry-run tests can pass on, literally, 'example.com'
|
||||
|
9
token-test.sh
Normal file
9
token-test.sh
Normal file
@ -0,0 +1,9 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# Before assuming there's something wrong with this plugin,
|
||||
# you should test that you can use your token with curl first.
|
||||
|
||||
echo "USERNAME: '$USERNAME'"
|
||||
echo "TOKEN: '$TOKEN'"
|
||||
curl -f -u "$USERNAME:$TOKEN" https://api.name.com/v4/domains
|
Loading…
x
Reference in New Issue
Block a user