nyaundi brian
5 years ago
commit
8025444796
5 changed files with 250 additions and 0 deletions
@ -0,0 +1,10 @@ |
|||
# [acme-dns-01-namecheap](https://git.rootprojects.org/root/acme-dns-01-namecheap) | a [Root](https://rootrpojects.org) project |
|||
|
|||
NameCheap DNS for Let's Encrypt / ACME dns-01 challenges with ACME.js and Greenlock.js (Node.js). |
|||
|
|||
# Tests |
|||
|
|||
``` |
|||
# node ./test.js domain-zone api-user api-key username [username is optional if similar to api-user] |
|||
node ./test.js example.com demo d41474b94e7d4536baabb074a09c96bd |
|||
``` |
@ -0,0 +1,3 @@ |
|||
'use strict'; |
|||
|
|||
module.exports = require('./lib/index.js'); |
@ -0,0 +1,155 @@ |
|||
'use strict'; |
|||
var util = require('util'); |
|||
|
|||
var request = require('@root/request'); |
|||
request = util.promisify(request); |
|||
var parseString = require('xml2js').parseString; |
|||
parseString = util.promisify(parseString); |
|||
|
|||
|
|||
const SANDBOX_URL = 'https://api.sandbox.namecheap.com/xml.response'; |
|||
const PRODUCTION_URL = 'https://api.namecheap.com/xml.response'; |
|||
|
|||
|
|||
var defaults = { |
|||
baseUrl: SANDBOX_URL |
|||
}; |
|||
|
|||
function extend(obj) { |
|||
var newObj = {}; |
|||
for (var i in obj) { |
|||
if (obj.hasOwnProperty(i)) { |
|||
newObj[i] = obj[i]; |
|||
} |
|||
} |
|||
return newObj; |
|||
} |
|||
|
|||
function requestUrl(baseUrl, params) { |
|||
var queryString = Object.keys(params).map(function (key) { |
|||
return encodeURIComponent(key) + '=' + encodeURIComponent(params[key]); |
|||
}).join('&'); |
|||
console.debug(queryString); |
|||
return baseUrl + '?' + queryString; |
|||
} |
|||
|
|||
module.exports.create = function (config) { |
|||
// config = { baseUrl, token }
|
|||
var baseUrl = config.baseUrl || defaults.baseUrl; |
|||
|
|||
var globalParams = { |
|||
apiUser: config.apiUser, |
|||
apiKey: config.apiKey, |
|||
username: config.username, |
|||
ClientIp: '122.178.155.204' |
|||
}; |
|||
|
|||
return { |
|||
set: function (data) { |
|||
var ch = data.challenge; |
|||
var domainname = ch.identifier.value; |
|||
var zone = domainname; |
|||
|
|||
var dnsPrefix = ch.dnsHost.replace(new RegExp('.' + zone + '$'), ''); |
|||
var txt = ch.dnsAuthorization; |
|||
|
|||
var params = extend(globalParams); |
|||
params['Command'] = 'namecheap.domains.dns.setHosts'; |
|||
// the domain is the first part
|
|||
params['SLD'] = zone.split('.')[0]; |
|||
// the rest of the components are the TLD
|
|||
params['TLD'] = zone.split('.').splice(1).join('.'); |
|||
|
|||
params['HostName1'] = dnsPrefix; |
|||
params['RecordType1'] = 'TXT'; |
|||
params['Address1'] = txt; |
|||
params['TTL1'] = 100; |
|||
|
|||
var url = requestUrl(baseUrl, params); |
|||
console.debug(url); |
|||
|
|||
console.log('adding txt', data); |
|||
return request({ |
|||
method: 'POST', |
|||
url: url, |
|||
}).then(function (resp) { |
|||
resp = resp.body; |
|||
console.log(resp); |
|||
return parseString(resp, function (err, result) { |
|||
console.dir(result); |
|||
if (result['ApiResponse']['$']['Status'] === 'ERROR') { |
|||
for (let i = 0; i < result['ApiResponse']['Errors'].length; i++) { |
|||
console.log(result['ApiResponse']['Errors'][i]) |
|||
} |
|||
throw new Error('record did not set. check subdomain, api key, etc'); |
|||
|
|||
} else { |
|||
return true |
|||
} |
|||
}); |
|||
|
|||
}); |
|||
}, |
|||
remove: function (data) { |
|||
var domainname = data.challenge.altname; |
|||
var zone = domainname; |
|||
|
|||
throw new Error('not supported'); |
|||
|
|||
}, |
|||
get: function (data) { |
|||
var ch = data.challenge; |
|||
var domainname = data.challenge.altname; |
|||
var zone = domainname; |
|||
|
|||
|
|||
var params = extend(globalParams); |
|||
params['Command'] = 'namecheap.domains.dns.getHosts'; |
|||
// the domain is the first part
|
|||
params['SLD'] = zone.split('.')[0]; |
|||
// the rest of the components are the TLD
|
|||
params['TLD'] = zone.split('.').splice(1).join('.'); |
|||
|
|||
|
|||
var url = requestUrl(baseUrl, params); |
|||
console.debug(url); |
|||
|
|||
console.log('getting txt', data); |
|||
return request({ |
|||
method: 'POST', |
|||
url: url, |
|||
}).then(function (resp) { |
|||
resp = resp.body; |
|||
|
|||
return parseString(resp, function (err, result) { |
|||
console.dir(result); |
|||
if (result['ApiResponse']['$']['Status'] === 'ERROR') { |
|||
for (let i = 0; i < result['ApiResponse']['Errors'].length; i++) { |
|||
console.log(result['ApiResponse']['Errors'][i]) |
|||
} |
|||
throw new Error('record did not set. check subdomain, api key, etc'); |
|||
|
|||
} else { // Status="OK"
|
|||
|
|||
var entries = result['ApiResponse']['CommandResponse']['DomainDNSGetHostsResult'].filter(function (x) { |
|||
|
|||
return x['$']['Type'] === 'TXT'; |
|||
}); |
|||
|
|||
var entry = entries.filter(function (x) { |
|||
console.log('data', x.data); |
|||
console.log('dnsAuth', ch.dnsAuthorization, ch); |
|||
return x['$']['Address'] === ch.dnsAuthorization; |
|||
})[0]; |
|||
|
|||
if (entry) { |
|||
return {dnsAuthorization: entry['$']['Address']}; |
|||
} else { |
|||
return null; |
|||
} |
|||
} |
|||
}); |
|||
}); |
|||
} |
|||
}; |
|||
}; |
@ -0,0 +1,34 @@ |
|||
{ |
|||
"name": "acme-dns-01-namecheap", |
|||
"version": "3.0.0", |
|||
"description": "Namecheap DNS 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.coolaj86.com/coolaj86/acme-dns-01-namecheap.js.git" |
|||
}, |
|||
"keywords": [ |
|||
"namecheap", |
|||
"name-cheap", |
|||
"dns", |
|||
"dns-01", |
|||
"letsencrypt", |
|||
"acme", |
|||
"greenlock" |
|||
], |
|||
"author": "AJ ONeal <coolaj86@gmail.com> (https://coolaj86.com/)", |
|||
"contributors": [ |
|||
"Nyaundi Brian <danleyb2@gmail.com> (https://git.coolaj86.com/danleyb2/)" |
|||
], |
|||
"license": "MPL-2.0", |
|||
"dependencies": { |
|||
"@root/request": "^1.3.11", |
|||
"xml2js": "^0.4.19" |
|||
}, |
|||
"devDependencies": { |
|||
"acme-challenge-test": "^3.1.1" |
|||
} |
|||
} |
@ -0,0 +1,48 @@ |
|||
#!/usr/bin/env node
|
|||
'use strict'; |
|||
|
|||
// 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({ |
|||
apiUser:process.argv[3], |
|||
apiKey : process.argv[4], |
|||
username: process.argv[5]||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
|
|||
var domain = zone; |
|||
|
|||
tester |
|||
.test('dns-01', domain, challenger) |
|||
.then(function() { |
|||
console.info('PASS', domain); |
|||
///*
|
|||
domain = 'foo.' + zone; |
|||
|
|||
return tester |
|||
.test('dns-01', domain, challenger) |
|||
.then(function() { |
|||
console.info('PASS', domain); |
|||
}) |
|||
.then(function() { |
|||
domain = '*.foo.' + zone; |
|||
|
|||
return tester.test('dns-01', domain, challenger).then(function() { |
|||
console.info('PASS', domain); |
|||
}); |
|||
}); |
|||
//*/
|
|||
}) |
|||
.catch(function(e) { |
|||
console.info('ERROR', domain); |
|||
|
|||
console.error(e.message); |
|||
console.error(e.stack); |
|||
}); |
|||
|
Loading…
Reference in new issue