add .prettierrc, and make prettier
This commit is contained in:
parent
466de61232
commit
f2b6772f5c
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"bracketSpacing": true,
|
||||||
|
"printWidth": 80,
|
||||||
|
"singleQuote": true,
|
||||||
|
"tabWidth": 2,
|
||||||
|
"trailingComma": "none",
|
||||||
|
"useTabs": true
|
||||||
|
}
|
118
README.md
118
README.md
|
@ -8,21 +8,21 @@
|
||||||
|
|
||||||
# [acme-v2.js](https://git.coolaj86.com/coolaj86/acme-v2.js)
|
# [acme-v2.js](https://git.coolaj86.com/coolaj86/acme-v2.js)
|
||||||
|
|
||||||
A lightweight, **Low Dependency*** framework for building
|
A lightweight, **Low Dependency**\* framework for building
|
||||||
Let's Encrypt v2 (ACME draft 12) clients, successor to `le-acme-core.js`.
|
Let's Encrypt v2 (ACME draft 12) clients, successor to `le-acme-core.js`.
|
||||||
Built [by request](https://git.coolaj86.com/coolaj86/greenlock.js/issues/5#issuecomment-8).
|
Built [by request](https://git.coolaj86.com/coolaj86/greenlock.js/issues/5#issuecomment-8).
|
||||||
|
|
||||||
* <small>although `node-forge` and `ursa` are included as `optionalDependencies`
|
\* <small>although `node-forge` and `ursa` are included as `optionalDependencies`
|
||||||
for backwards compatibility with older versions of node, there are no other
|
for backwards compatibility with older versions of node, there are no other
|
||||||
dependencies except those that I wrote for this (and related) projects.</small>
|
dependencies except those that I wrote for this (and related) projects.</small>
|
||||||
|
|
||||||
## Looking for Quick 'n' Easy™?
|
## Looking for Quick 'n' Easy™?
|
||||||
|
|
||||||
If you're looking to *build a webserver*, try [greenlock.js](https://git.coolaj86.com/coolaj86/greenlock.js).
|
If you're looking to _build a webserver_, try [greenlock.js](https://git.coolaj86.com/coolaj86/greenlock.js).
|
||||||
If you're looking for an *ACME-enabled webserver*, try [goldilocks.js](https://git.coolaj86.com/coolaj86/goldilocks.js).
|
If you're looking for an _ACME-enabled webserver_, try [goldilocks.js](https://git.coolaj86.com/coolaj86/goldilocks.js).
|
||||||
|
|
||||||
* [greenlock.js](https://git.coolaj86.com/coolaj86/greenlock.js)
|
- [greenlock.js](https://git.coolaj86.com/coolaj86/greenlock.js)
|
||||||
* [goldilocks.js](https://git.coolaj86.com/coolaj86/goldilocks.js)
|
- [goldilocks.js](https://git.coolaj86.com/coolaj86/goldilocks.js)
|
||||||
|
|
||||||
## How to build ACME clients
|
## How to build ACME clients
|
||||||
|
|
||||||
|
@ -77,20 +77,20 @@ https://acme-staging-v02.api.letsencrypt.org/directory
|
||||||
|
|
||||||
## Two API versions, Two Implementations
|
## Two API versions, Two Implementations
|
||||||
|
|
||||||
This library (acme-v2.js) supports ACME [*draft 11*](https://tools.ietf.org/html/draft-ietf-acme-acme-11),
|
This library (acme-v2.js) supports ACME [_draft 11_](https://tools.ietf.org/html/draft-ietf-acme-acme-11),
|
||||||
otherwise known as Let's Encrypt v2 (or v02).
|
otherwise known as Let's Encrypt v2 (or v02).
|
||||||
|
|
||||||
* ACME draft 11
|
- ACME draft 11
|
||||||
* Let's Encrypt v2
|
- Let's Encrypt v2
|
||||||
* Let's Encrypt v02
|
- Let's Encrypt v02
|
||||||
|
|
||||||
The predecessor (le-acme-core) supports Let's Encrypt v1 (or v01), which was a
|
The predecessor (le-acme-core) supports Let's Encrypt v1 (or v01), which was a
|
||||||
[hodge-podge of various drafts](https://github.com/letsencrypt/boulder/blob/master/docs/acme-divergences.md)
|
[hodge-podge of various drafts](https://github.com/letsencrypt/boulder/blob/master/docs/acme-divergences.md)
|
||||||
of the ACME spec early on.
|
of the ACME spec early on.
|
||||||
|
|
||||||
* ACME early draft
|
- ACME early draft
|
||||||
* Let's Encrypt v1
|
- Let's Encrypt v1
|
||||||
* Let's Encrypt v01
|
- Let's Encrypt v01
|
||||||
|
|
||||||
This library maintains compatibility with le-acme-core so that it can be used as a **drop-in replacement**
|
This library maintains compatibility with le-acme-core so that it can be used as a **drop-in replacement**
|
||||||
and requires **no changes to existing code**,
|
and requires **no changes to existing code**,
|
||||||
|
@ -102,7 +102,7 @@ Status: Stable, Locked, Bugfix-only
|
||||||
|
|
||||||
See Full Documentation at <https://git.coolaj86.com/coolaj86/le-acme-core.js>
|
See Full Documentation at <https://git.coolaj86.com/coolaj86/le-acme-core.js>
|
||||||
|
|
||||||
```
|
```js
|
||||||
var RSA = require('rsa-compat').RSA;
|
var RSA = require('rsa-compat').RSA;
|
||||||
var acme = require('acme-v2/compat.js').ACME.create({ RSA: RSA });
|
var acme = require('acme-v2/compat.js').ACME.create({ RSA: RSA });
|
||||||
|
|
||||||
|
@ -118,7 +118,7 @@ Status: Almost stable, but **not semver locked**
|
||||||
This API is a simple evolution of le-acme-core,
|
This API is a simple evolution of le-acme-core,
|
||||||
but tries to provide a better mapping to the new draft 11 APIs.
|
but tries to provide a better mapping to the new draft 11 APIs.
|
||||||
|
|
||||||
```
|
```js
|
||||||
// Create Instance (Dependency Injection)
|
// Create Instance (Dependency Injection)
|
||||||
var ACME = require('acme-v2').ACME.create({
|
var ACME = require('acme-v2').ACME.create({
|
||||||
RSA: require('rsa-compat').RSA
|
RSA: require('rsa-compat').RSA
|
||||||
|
@ -187,54 +187,54 @@ Helpers & Stuff
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
// Constants
|
// Constants
|
||||||
ACME.challengePrefixes['http-01'] // '/.well-known/acme-challenge'
|
ACME.challengePrefixes['http-01']; // '/.well-known/acme-challenge'
|
||||||
ACME.challengePrefixes['dns-01'] // '_acme-challenge'
|
ACME.challengePrefixes['dns-01']; // '_acme-challenge'
|
||||||
```
|
```
|
||||||
|
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
* v1.5
|
- v1.5
|
||||||
* perform full test challenge first (even before nonce)
|
- perform full test challenge first (even before nonce)
|
||||||
* v1.3
|
- v1.3
|
||||||
* Use node RSA keygen by default
|
- Use node RSA keygen by default
|
||||||
* No non-optional external deps!
|
- No non-optional external deps!
|
||||||
* v1.2
|
- v1.2
|
||||||
* fix some API out-of-specness
|
- fix some API out-of-specness
|
||||||
* doc some magic numbers (status)
|
- doc some magic numbers (status)
|
||||||
* updated deps
|
- updated deps
|
||||||
* v1.1.0
|
- v1.1.0
|
||||||
* reduce dependencies (use lightweight @coolaj86/request instead of request)
|
- reduce dependencies (use lightweight @coolaj86/request instead of request)
|
||||||
* v1.0.5 - cleanup logging
|
- v1.0.5 - cleanup logging
|
||||||
* v1.0.4 - v6- compat use `promisify` from node's util or bluebird
|
- v1.0.4 - v6- compat use `promisify` from node's util or bluebird
|
||||||
* v1.0.3 - documentation cleanup
|
- v1.0.3 - documentation cleanup
|
||||||
* v1.0.2
|
- v1.0.2
|
||||||
* use `options.contact` to provide raw contact array
|
- use `options.contact` to provide raw contact array
|
||||||
* made `options.email` optional
|
- made `options.email` optional
|
||||||
* file cleanup
|
- file cleanup
|
||||||
* v1.0.1
|
- v1.0.1
|
||||||
* Compat API is ready for use
|
- Compat API is ready for use
|
||||||
* Eliminate debug logging
|
- Eliminate debug logging
|
||||||
* Apr 10, 2018 - tested backwards-compatibility using greenlock.js
|
- Apr 10, 2018 - tested backwards-compatibility using greenlock.js
|
||||||
* Apr 5, 2018 - export http and dns challenge tests
|
- Apr 5, 2018 - export http and dns challenge tests
|
||||||
* Apr 5, 2018 - test http and dns challenges (success and failure)
|
- Apr 5, 2018 - test http and dns challenges (success and failure)
|
||||||
* Apr 5, 2018 - test subdomains and its wildcard
|
- Apr 5, 2018 - test subdomains and its wildcard
|
||||||
* Apr 5, 2018 - test two subdomains
|
- Apr 5, 2018 - test two subdomains
|
||||||
* Apr 5, 2018 - test wildcard
|
- Apr 5, 2018 - test wildcard
|
||||||
* Apr 5, 2018 - completely match api for acme v1 (le-acme-core.js)
|
- Apr 5, 2018 - completely match api for acme v1 (le-acme-core.js)
|
||||||
* Mar 21, 2018 - *mostly* matches le-acme-core.js API
|
- Mar 21, 2018 - _mostly_ matches le-acme-core.js API
|
||||||
* Mar 21, 2018 - can now accept values (not hard coded)
|
- Mar 21, 2018 - can now accept values (not hard coded)
|
||||||
* Mar 20, 2018 - SUCCESS - got a test certificate (hard-coded)
|
- Mar 20, 2018 - SUCCESS - got a test certificate (hard-coded)
|
||||||
* Mar 20, 2018 - download certificate
|
- Mar 20, 2018 - download certificate
|
||||||
* Mar 20, 2018 - poll for status
|
- Mar 20, 2018 - poll for status
|
||||||
* Mar 20, 2018 - finalize order (submit csr)
|
- Mar 20, 2018 - finalize order (submit csr)
|
||||||
* Mar 20, 2018 - generate domain keypair
|
- Mar 20, 2018 - generate domain keypair
|
||||||
* Mar 20, 2018 - respond to challenges
|
- Mar 20, 2018 - respond to challenges
|
||||||
* Mar 16, 2018 - get challenges
|
- Mar 16, 2018 - get challenges
|
||||||
* Mar 16, 2018 - new order
|
- Mar 16, 2018 - new order
|
||||||
* Mar 15, 2018 - create account
|
- Mar 15, 2018 - create account
|
||||||
* Mar 15, 2018 - generate account keypair
|
- Mar 15, 2018 - generate account keypair
|
||||||
* Mar 15, 2018 - get nonce
|
- Mar 15, 2018 - get nonce
|
||||||
* Mar 15, 2018 - get directory
|
- Mar 15, 2018 - get directory
|
||||||
|
|
||||||
# Legal
|
# Legal
|
||||||
|
|
||||||
|
|
123
compat.js
123
compat.js
|
@ -8,74 +8,87 @@
|
||||||
var ACME2 = require('./').ACME;
|
var ACME2 = require('./').ACME;
|
||||||
|
|
||||||
function resolveFn(cb) {
|
function resolveFn(cb) {
|
||||||
return function (val) {
|
return function(val) {
|
||||||
// nextTick to get out of Promise chain
|
// nextTick to get out of Promise chain
|
||||||
process.nextTick(function () { cb(null, val); });
|
process.nextTick(function() {
|
||||||
};
|
cb(null, val);
|
||||||
|
});
|
||||||
|
};
|
||||||
}
|
}
|
||||||
function rejectFn(cb) {
|
function rejectFn(cb) {
|
||||||
return function (err) {
|
return function(err) {
|
||||||
console.error('[acme-v2] handled(?) rejection as errback:');
|
console.error('[acme-v2] handled(?) rejection as errback:');
|
||||||
console.error(err.stack);
|
console.error(err.stack);
|
||||||
|
|
||||||
// nextTick to get out of Promise chain
|
// nextTick to get out of Promise chain
|
||||||
process.nextTick(function () { cb(err); });
|
process.nextTick(function() {
|
||||||
|
cb(err);
|
||||||
|
});
|
||||||
|
|
||||||
// do not resolve promise further
|
// do not resolve promise further
|
||||||
return new Promise(function () {});
|
return new Promise(function() {});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function create(deps) {
|
function create(deps) {
|
||||||
deps.LeCore = {};
|
deps.LeCore = {};
|
||||||
var acme2 = ACME2.create(deps);
|
var acme2 = ACME2.create(deps);
|
||||||
acme2.registerNewAccount = function (options, cb) {
|
acme2.registerNewAccount = function(options, cb) {
|
||||||
acme2.accounts.create(options).then(resolveFn(cb), rejectFn(cb));
|
acme2.accounts.create(options).then(resolveFn(cb), rejectFn(cb));
|
||||||
};
|
};
|
||||||
acme2.getCertificate = function (options, cb) {
|
acme2.getCertificate = function(options, cb) {
|
||||||
options.agreeToTerms = options.agreeToTerms || function (tos) {
|
options.agreeToTerms =
|
||||||
return Promise.resolve(tos);
|
options.agreeToTerms ||
|
||||||
};
|
function(tos) {
|
||||||
acme2.certificates.create(options).then(function (certs) {
|
return Promise.resolve(tos);
|
||||||
var privkeyPem = acme2.RSA.exportPrivatePem(options.domainKeypair);
|
};
|
||||||
certs.privkey = privkeyPem;
|
acme2.certificates.create(options).then(function(certs) {
|
||||||
resolveFn(cb)(certs);
|
var privkeyPem = acme2.RSA.exportPrivatePem(options.domainKeypair);
|
||||||
}, rejectFn(cb));
|
certs.privkey = privkeyPem;
|
||||||
};
|
resolveFn(cb)(certs);
|
||||||
acme2.getAcmeUrls = function (options, cb) {
|
}, rejectFn(cb));
|
||||||
acme2.init(options).then(resolveFn(cb), rejectFn(cb));
|
};
|
||||||
};
|
acme2.getAcmeUrls = function(options, cb) {
|
||||||
acme2.getOptions = function () {
|
acme2.init(options).then(resolveFn(cb), rejectFn(cb));
|
||||||
var defs = {};
|
};
|
||||||
|
acme2.getOptions = function() {
|
||||||
|
var defs = {};
|
||||||
|
|
||||||
Object.keys(module.exports.defaults).forEach(function (key) {
|
Object.keys(module.exports.defaults).forEach(function(key) {
|
||||||
defs[key] = defs[deps] || module.exports.defaults[key];
|
defs[key] = defs[deps] || module.exports.defaults[key];
|
||||||
});
|
});
|
||||||
|
|
||||||
return defs;
|
return defs;
|
||||||
};
|
};
|
||||||
acme2.stagingServerUrl = module.exports.defaults.stagingServerUrl;
|
acme2.stagingServerUrl = module.exports.defaults.stagingServerUrl;
|
||||||
acme2.productionServerUrl = module.exports.defaults.productionServerUrl;
|
acme2.productionServerUrl = module.exports.defaults.productionServerUrl;
|
||||||
acme2.acmeChallengePrefix = module.exports.defaults.acmeChallengePrefix;
|
acme2.acmeChallengePrefix = module.exports.defaults.acmeChallengePrefix;
|
||||||
return acme2;
|
return acme2;
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports.ACME = { };
|
module.exports.ACME = {};
|
||||||
module.exports.defaults = {
|
module.exports.defaults = {
|
||||||
productionServerUrl: 'https://acme-v02.api.letsencrypt.org/directory'
|
productionServerUrl: 'https://acme-v02.api.letsencrypt.org/directory',
|
||||||
, stagingServerUrl: 'https://acme-staging-v02.api.letsencrypt.org/directory'
|
stagingServerUrl: 'https://acme-staging-v02.api.letsencrypt.org/directory',
|
||||||
, knownEndpoints: [ 'keyChange', 'meta', 'newAccount', 'newNonce', 'newOrder', 'revokeCert' ]
|
knownEndpoints: [
|
||||||
, challengeTypes: [ 'http-01', 'dns-01' ]
|
'keyChange',
|
||||||
, challengeType: 'http-01'
|
'meta',
|
||||||
//, keyType: 'rsa' // ecdsa
|
'newAccount',
|
||||||
//, keySize: 2048 // 256
|
'newNonce',
|
||||||
, rsaKeySize: 2048 // 256
|
'newOrder',
|
||||||
, acmeChallengePrefix: '/.well-known/acme-challenge/'
|
'revokeCert'
|
||||||
|
],
|
||||||
|
challengeTypes: ['http-01', 'dns-01'],
|
||||||
|
challengeType: 'http-01',
|
||||||
|
//, keyType: 'rsa' // ecdsa
|
||||||
|
//, keySize: 2048 // 256
|
||||||
|
rsaKeySize: 2048, // 256
|
||||||
|
acmeChallengePrefix: '/.well-known/acme-challenge/'
|
||||||
};
|
};
|
||||||
Object.keys(module.exports.defaults).forEach(function (key) {
|
Object.keys(module.exports.defaults).forEach(function(key) {
|
||||||
module.exports.ACME[key] = module.exports.defaults[key];
|
module.exports.ACME[key] = module.exports.defaults[key];
|
||||||
});
|
});
|
||||||
Object.keys(ACME2).forEach(function (key) {
|
Object.keys(ACME2).forEach(function(key) {
|
||||||
module.exports.ACME[key] = ACME2[key];
|
module.exports.ACME[key] = ACME2[key];
|
||||||
});
|
});
|
||||||
module.exports.ACME.create = create;
|
module.exports.ACME.create = create;
|
||||||
|
|
139
examples/cli.js
139
examples/cli.js
|
@ -7,66 +7,125 @@
|
||||||
var RSA = require('rsa-compat').RSA;
|
var RSA = require('rsa-compat').RSA;
|
||||||
var readline = require('readline');
|
var readline = require('readline');
|
||||||
var rl = readline.createInterface({
|
var rl = readline.createInterface({
|
||||||
input: process.stdin,
|
input: process.stdin,
|
||||||
output: process.stdout
|
output: process.stdout
|
||||||
});
|
});
|
||||||
|
|
||||||
require('./genkeypair.js');
|
require('./genkeypair.js');
|
||||||
|
|
||||||
function getWeb() {
|
function getWeb() {
|
||||||
rl.question('What web address(es) would you like to get certificates for? (ex: example.com,*.example.com) ', function (web) {
|
rl.question(
|
||||||
web = (web||'').trim().split(/,/g);
|
'What web address(es) would you like to get certificates for? (ex: example.com,*.example.com) ',
|
||||||
if (!web[0]) { getWeb(); return; }
|
function(web) {
|
||||||
|
web = (web || '').trim().split(/,/g);
|
||||||
|
if (!web[0]) {
|
||||||
|
getWeb();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (web.some(function (w) { return '*' === w[0]; })) {
|
if (
|
||||||
console.log('Wildcard domains must use dns-01');
|
web.some(function(w) {
|
||||||
getEmail(web, 'dns-01');
|
return '*' === w[0];
|
||||||
} else {
|
})
|
||||||
getChallengeType(web);
|
) {
|
||||||
}
|
console.log('Wildcard domains must use dns-01');
|
||||||
});
|
getEmail(web, 'dns-01');
|
||||||
|
} else {
|
||||||
|
getChallengeType(web);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getChallengeType(web) {
|
function getChallengeType(web) {
|
||||||
rl.question('What challenge will you be testing today? http-01 or dns-01? [http-01] ', function (chType) {
|
rl.question(
|
||||||
chType = (chType||'').trim();
|
'What challenge will you be testing today? http-01 or dns-01? [http-01] ',
|
||||||
if (!chType) { chType = 'http-01'; }
|
function(chType) {
|
||||||
|
chType = (chType || '').trim();
|
||||||
|
if (!chType) {
|
||||||
|
chType = 'http-01';
|
||||||
|
}
|
||||||
|
|
||||||
getEmail(web, chType);
|
getEmail(web, chType);
|
||||||
});
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getEmail(web, chType) {
|
function getEmail(web, chType) {
|
||||||
rl.question('What email should we use? (optional) ', function (email) {
|
rl.question('What email should we use? (optional) ', function(email) {
|
||||||
email = (email||'').trim();
|
email = (email || '').trim();
|
||||||
if (!email) { email = null; }
|
if (!email) {
|
||||||
|
email = null;
|
||||||
|
}
|
||||||
|
|
||||||
getApiStyle(web, chType, email);
|
getApiStyle(web, chType, email);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function getApiStyle(web, chType, email) {
|
function getApiStyle(web, chType, email) {
|
||||||
var defaultStyle = 'compat';
|
var defaultStyle = 'compat';
|
||||||
rl.question('What API style would you like to test? v1-compat or promise? [v1-compat] ', function (apiStyle) {
|
rl.question(
|
||||||
apiStyle = (apiStyle||'').trim();
|
'What API style would you like to test? v1-compat or promise? [v1-compat] ',
|
||||||
if (!apiStyle) { apiStyle = 'v1-compat'; }
|
function(apiStyle) {
|
||||||
|
apiStyle = (apiStyle || '').trim();
|
||||||
|
if (!apiStyle) {
|
||||||
|
apiStyle = 'v1-compat';
|
||||||
|
}
|
||||||
|
|
||||||
rl.close();
|
rl.close();
|
||||||
|
|
||||||
var RSA = require('rsa-compat').RSA;
|
var RSA = require('rsa-compat').RSA;
|
||||||
var accountKeypair = RSA.import({ privateKeyPem: require('fs').readFileSync(__dirname + '/../tests/account.privkey.pem') });
|
var accountKeypair = RSA.import({
|
||||||
var domainKeypair = RSA.import({ privateKeyPem: require('fs').readFileSync(__dirname + '/../tests/privkey.pem') });
|
privateKeyPem: require('fs').readFileSync(
|
||||||
var directoryUrl = 'https://acme-staging-v02.api.letsencrypt.org/directory';
|
__dirname + '/../tests/account.privkey.pem'
|
||||||
|
)
|
||||||
|
});
|
||||||
|
var domainKeypair = RSA.import({
|
||||||
|
privateKeyPem: require('fs').readFileSync(
|
||||||
|
__dirname + '/../tests/privkey.pem'
|
||||||
|
)
|
||||||
|
});
|
||||||
|
var directoryUrl =
|
||||||
|
'https://acme-staging-v02.api.letsencrypt.org/directory';
|
||||||
|
|
||||||
if ('promise' === apiStyle) {
|
if ('promise' === apiStyle) {
|
||||||
require('../tests/promise.js').run(directoryUrl, RSA, web, chType, email, accountKeypair, domainKeypair);
|
require('../tests/promise.js').run(
|
||||||
} else if ('cb' === apiStyle) {
|
directoryUrl,
|
||||||
require('../tests/cb.js').run(directoryUrl, RSA, web, chType, email, accountKeypair, domainKeypair);
|
RSA,
|
||||||
} else {
|
web,
|
||||||
if ('v1-compat' !== apiStyle) { console.warn("Didn't understand '" + apiStyle + "', using 'v1-compat' instead..."); }
|
chType,
|
||||||
require('../tests/compat.js').run(directoryUrl, RSA, web, chType, email, accountKeypair, domainKeypair);
|
email,
|
||||||
}
|
accountKeypair,
|
||||||
});
|
domainKeypair
|
||||||
|
);
|
||||||
|
} else if ('cb' === apiStyle) {
|
||||||
|
require('../tests/cb.js').run(
|
||||||
|
directoryUrl,
|
||||||
|
RSA,
|
||||||
|
web,
|
||||||
|
chType,
|
||||||
|
email,
|
||||||
|
accountKeypair,
|
||||||
|
domainKeypair
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
if ('v1-compat' !== apiStyle) {
|
||||||
|
console.warn(
|
||||||
|
"Didn't understand '" + apiStyle + "', using 'v1-compat' instead..."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
require('../tests/compat.js').run(
|
||||||
|
directoryUrl,
|
||||||
|
RSA,
|
||||||
|
web,
|
||||||
|
chType,
|
||||||
|
email,
|
||||||
|
accountKeypair,
|
||||||
|
domainKeypair
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
getWeb();
|
getWeb();
|
||||||
|
|
|
@ -6,21 +6,21 @@ var RSA = require('rsa-compat').RSA;
|
||||||
var fs = require('fs');
|
var fs = require('fs');
|
||||||
|
|
||||||
if (!fs.existsSync(__dirname + '/../tests/account.privkey.pem')) {
|
if (!fs.existsSync(__dirname + '/../tests/account.privkey.pem')) {
|
||||||
RSA.generateKeypair(2048, 65537, {}, function (err, keypair) {
|
RSA.generateKeypair(2048, 65537, {}, function(err, keypair) {
|
||||||
console.log(keypair);
|
console.log(keypair);
|
||||||
var privkeyPem = RSA.exportPrivatePem(keypair)
|
var privkeyPem = RSA.exportPrivatePem(keypair);
|
||||||
console.log(privkeyPem);
|
console.log(privkeyPem);
|
||||||
|
|
||||||
fs.writeFileSync(__dirname + '/../tests/account.privkey.pem', privkeyPem);
|
fs.writeFileSync(__dirname + '/../tests/account.privkey.pem', privkeyPem);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!fs.existsSync(__dirname + '/../tests/privkey.pem')) {
|
if (!fs.existsSync(__dirname + '/../tests/privkey.pem')) {
|
||||||
RSA.generateKeypair(2048, 65537, {}, function (err, keypair) {
|
RSA.generateKeypair(2048, 65537, {}, function(err, keypair) {
|
||||||
console.log(keypair);
|
console.log(keypair);
|
||||||
var privkeyPem = RSA.exportPrivatePem(keypair)
|
var privkeyPem = RSA.exportPrivatePem(keypair);
|
||||||
console.log(privkeyPem);
|
console.log(privkeyPem);
|
||||||
|
|
||||||
fs.writeFileSync(__dirname + '/../tests/privkey.pem', privkeyPem);
|
fs.writeFileSync(__dirname + '/../tests/privkey.pem', privkeyPem);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
|
|
||||||
var http = require('http');
|
var http = require('http');
|
||||||
var express = require('express');
|
var express = require('express');
|
||||||
var server = http.createServer(express.static('../tests')).listen(80, function () {
|
var server = http
|
||||||
console.log('Listening on', this.address());
|
.createServer(express.static('../tests'))
|
||||||
});
|
.listen(80, function() {
|
||||||
|
console.log('Listening on', this.address());
|
||||||
|
});
|
||||||
|
|
|
@ -5,11 +5,16 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var https = require('https');
|
var https = require('https');
|
||||||
var server = https.createServer({
|
var server = https
|
||||||
key: require('fs').readFileSync('../tests/privkey.pem')
|
.createServer(
|
||||||
, cert: require('fs').readFileSync('../tests/fullchain.pem')
|
{
|
||||||
}, function (req, res) {
|
key: require('fs').readFileSync('../tests/privkey.pem'),
|
||||||
res.end("Hello, World!");
|
cert: require('fs').readFileSync('../tests/fullchain.pem')
|
||||||
}).listen(443, function () {
|
},
|
||||||
console.log('Listening on', this.address());
|
function(req, res) {
|
||||||
});
|
res.end('Hello, World!');
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.listen(443, function() {
|
||||||
|
console.log('Listening on', this.address());
|
||||||
|
});
|
||||||
|
|
|
@ -1,40 +1,40 @@
|
||||||
{
|
{
|
||||||
"name": "acme-v2",
|
"name": "acme-v2",
|
||||||
"version": "1.7.6",
|
"version": "1.7.6",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@coolaj86/urequest": {
|
"@coolaj86/urequest": {
|
||||||
"version": "1.3.7",
|
"version": "1.3.7",
|
||||||
"resolved": "https://registry.npmjs.org/@coolaj86/urequest/-/urequest-1.3.7.tgz",
|
"resolved": "https://registry.npmjs.org/@coolaj86/urequest/-/urequest-1.3.7.tgz",
|
||||||
"integrity": "sha512-PPrVYra9aWvZjSCKl/x1pJ9ZpXda1652oJrPBYy5rQumJJMkmTBN3ux+sK2xAUwVvv2wnewDlaQaHLxLwSHnIA=="
|
"integrity": "sha512-PPrVYra9aWvZjSCKl/x1pJ9ZpXda1652oJrPBYy5rQumJJMkmTBN3ux+sK2xAUwVvv2wnewDlaQaHLxLwSHnIA=="
|
||||||
},
|
},
|
||||||
"eckles": {
|
"eckles": {
|
||||||
"version": "1.4.1",
|
"version": "1.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/eckles/-/eckles-1.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/eckles/-/eckles-1.4.1.tgz",
|
||||||
"integrity": "sha512-auWyk/k8oSkVHaD4RxkPadKsLUcIwKgr/h8F7UZEueFDBO7BsE4y+H6IMUDbfqKIFPg/9MxV6KcBdJCmVVcxSA=="
|
"integrity": "sha512-auWyk/k8oSkVHaD4RxkPadKsLUcIwKgr/h8F7UZEueFDBO7BsE4y+H6IMUDbfqKIFPg/9MxV6KcBdJCmVVcxSA=="
|
||||||
},
|
},
|
||||||
"keypairs": {
|
"keypairs": {
|
||||||
"version": "1.2.14",
|
"version": "1.2.14",
|
||||||
"resolved": "https://registry.npmjs.org/keypairs/-/keypairs-1.2.14.tgz",
|
"resolved": "https://registry.npmjs.org/keypairs/-/keypairs-1.2.14.tgz",
|
||||||
"integrity": "sha512-ZoZfZMygyB0QcjSlz7Rh6wT2CJasYEHBPETtmHZEfxuJd7bnsOG5AdtPZqHZBT+hoHvuWCp/4y8VmvTvH0Y9uA==",
|
"integrity": "sha512-ZoZfZMygyB0QcjSlz7Rh6wT2CJasYEHBPETtmHZEfxuJd7bnsOG5AdtPZqHZBT+hoHvuWCp/4y8VmvTvH0Y9uA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"eckles": "^1.4.1",
|
"eckles": "^1.4.1",
|
||||||
"rasha": "^1.2.4"
|
"rasha": "^1.2.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"rasha": {
|
"rasha": {
|
||||||
"version": "1.2.5",
|
"version": "1.2.5",
|
||||||
"resolved": "https://registry.npmjs.org/rasha/-/rasha-1.2.5.tgz",
|
"resolved": "https://registry.npmjs.org/rasha/-/rasha-1.2.5.tgz",
|
||||||
"integrity": "sha512-KxtX+/fBk+wM7O3CNgwjSh5elwFilLvqWajhr6wFr2Hd63JnKTTi43Tw+Jb1hxJQWOwoya+NZWR2xztn3hCrTw=="
|
"integrity": "sha512-KxtX+/fBk+wM7O3CNgwjSh5elwFilLvqWajhr6wFr2Hd63JnKTTi43Tw+Jb1hxJQWOwoya+NZWR2xztn3hCrTw=="
|
||||||
},
|
},
|
||||||
"rsa-compat": {
|
"rsa-compat": {
|
||||||
"version": "2.0.6",
|
"version": "2.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/rsa-compat/-/rsa-compat-2.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/rsa-compat/-/rsa-compat-2.0.6.tgz",
|
||||||
"integrity": "sha512-bQmpscAQec9442RaghDybrHMy1twQ3nUZOgTlqntio1yru+rMnDV64uGRzKp7dJ4VVhNv3mLh3X4MNON+YM0dA==",
|
"integrity": "sha512-bQmpscAQec9442RaghDybrHMy1twQ3nUZOgTlqntio1yru+rMnDV64uGRzKp7dJ4VVhNv3mLh3X4MNON+YM0dA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"keypairs": "^1.2.14"
|
"keypairs": "^1.2.14"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
60
package.json
60
package.json
|
@ -1,32 +1,32 @@
|
||||||
{
|
{
|
||||||
"name": "acme-v2",
|
"name": "acme-v2",
|
||||||
"version": "1.7.7",
|
"version": "1.7.7",
|
||||||
"description": "Free SSL. A framework for building Let's Encrypt v2 clients, and other ACME v2 (draft 11) clients. Successor to le-acme-core.js",
|
"description": "Free SSL. A framework for building Let's Encrypt v2 clients, and other ACME v2 (draft 11) clients. Successor to le-acme-core.js",
|
||||||
"homepage": "https://git.coolaj86.com/coolaj86/acme-v2.js",
|
"homepage": "https://git.coolaj86.com/coolaj86/acme-v2.js",
|
||||||
"main": "node.js",
|
"main": "node.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "echo \"Error: no test specified\" && exit 1"
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "ssh://gitea@git.coolaj86.com:22042/coolaj86/acme-v2.js.git"
|
"url": "ssh://gitea@git.coolaj86.com:22042/coolaj86/acme-v2.js.git"
|
||||||
},
|
},
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"Let's Encrypt",
|
"Let's Encrypt",
|
||||||
"ACME",
|
"ACME",
|
||||||
"v02",
|
"v02",
|
||||||
"v2",
|
"v2",
|
||||||
"draft-11",
|
"draft-11",
|
||||||
"draft-12",
|
"draft-12",
|
||||||
"free ssl",
|
"free ssl",
|
||||||
"tls",
|
"tls",
|
||||||
"automated https",
|
"automated https",
|
||||||
"letsencrypt"
|
"letsencrypt"
|
||||||
],
|
],
|
||||||
"author": "AJ ONeal <coolaj86@gmail.com> (https://coolaj86.com/)",
|
"author": "AJ ONeal <coolaj86@gmail.com> (https://coolaj86.com/)",
|
||||||
"license": "MPL-2.0",
|
"license": "MPL-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@coolaj86/urequest": "^1.3.6",
|
"@coolaj86/urequest": "^1.3.6",
|
||||||
"rsa-compat": "^2.0.6"
|
"rsa-compat": "^2.0.6"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
175
tests/cb.js
175
tests/cb.js
|
@ -4,80 +4,115 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
module.exports.run = function run(directoryUrl, RSA, web, chType, email, accountKeypair, domainKeypair) {
|
module.exports.run = function run(
|
||||||
// [ 'test.ppl.family' ] 'coolaj86@gmail.com''http-01'
|
directoryUrl,
|
||||||
var acme2 = require('../').ACME.create({ RSA: RSA });
|
RSA,
|
||||||
acme2.init(directoryUrl).then(function () {
|
web,
|
||||||
var options = {
|
chType,
|
||||||
agreeToTerms: function (tosUrl, agree) {
|
email,
|
||||||
agree(null, tosUrl);
|
accountKeypair,
|
||||||
}
|
domainKeypair
|
||||||
, setChallenge: function (opts, cb) {
|
) {
|
||||||
var pathname;
|
// [ 'test.ppl.family' ] 'coolaj86@gmail.com''http-01'
|
||||||
|
var acme2 = require('../').ACME.create({ RSA: RSA });
|
||||||
|
acme2.init(directoryUrl).then(function() {
|
||||||
|
var options = {
|
||||||
|
agreeToTerms: function(tosUrl, agree) {
|
||||||
|
agree(null, tosUrl);
|
||||||
|
},
|
||||||
|
setChallenge: function(opts, cb) {
|
||||||
|
var pathname;
|
||||||
|
|
||||||
console.log("");
|
console.log('');
|
||||||
console.log('identifier:');
|
console.log('identifier:');
|
||||||
console.log(opts.identifier);
|
console.log(opts.identifier);
|
||||||
console.log('hostname:');
|
console.log('hostname:');
|
||||||
console.log(opts.hostname);
|
console.log(opts.hostname);
|
||||||
console.log('type:');
|
console.log('type:');
|
||||||
console.log(opts.type);
|
console.log(opts.type);
|
||||||
console.log('token:');
|
console.log('token:');
|
||||||
console.log(opts.token);
|
console.log(opts.token);
|
||||||
console.log('thumbprint:');
|
console.log('thumbprint:');
|
||||||
console.log(opts.thumbprint);
|
console.log(opts.thumbprint);
|
||||||
console.log('keyAuthorization:');
|
console.log('keyAuthorization:');
|
||||||
console.log(opts.keyAuthorization);
|
console.log(opts.keyAuthorization);
|
||||||
console.log('dnsAuthorization:');
|
console.log('dnsAuthorization:');
|
||||||
console.log(opts.dnsAuthorization);
|
console.log(opts.dnsAuthorization);
|
||||||
console.log("");
|
console.log('');
|
||||||
|
|
||||||
if ('http-01' === opts.type) {
|
if ('http-01' === opts.type) {
|
||||||
pathname = opts.hostname + acme2.challengePrefixes['http-01'] + "/" + opts.token;
|
pathname =
|
||||||
console.log("Put the string '" + opts.keyAuthorization + "' into a file at '" + pathname + "'");
|
opts.hostname +
|
||||||
console.log("echo '" + opts.keyAuthorization + "' > '" + pathname + "'");
|
acme2.challengePrefixes['http-01'] +
|
||||||
} else if ('dns-01' === opts.type) {
|
'/' +
|
||||||
pathname = acme2.challengePrefixes['dns-01'] + "." + opts.hostname.replace(/^\*\./, '');
|
opts.token;
|
||||||
console.log("Put the string '" + opts.dnsAuthorization + "' into the TXT record '" + pathname + "'");
|
console.log(
|
||||||
console.log("ddig TXT " + pathname + " '" + opts.dnsAuthorization + "'");
|
"Put the string '" +
|
||||||
} else {
|
opts.keyAuthorization +
|
||||||
cb(new Error("[acme-v2] unrecognized challenge type"));
|
"' into a file at '" +
|
||||||
return;
|
pathname +
|
||||||
}
|
"'"
|
||||||
console.log("\nThen hit the 'any' key to continue...");
|
);
|
||||||
|
console.log(
|
||||||
|
"echo '" + opts.keyAuthorization + "' > '" + pathname + "'"
|
||||||
|
);
|
||||||
|
} else if ('dns-01' === opts.type) {
|
||||||
|
pathname =
|
||||||
|
acme2.challengePrefixes['dns-01'] +
|
||||||
|
'.' +
|
||||||
|
opts.hostname.replace(/^\*\./, '');
|
||||||
|
console.log(
|
||||||
|
"Put the string '" +
|
||||||
|
opts.dnsAuthorization +
|
||||||
|
"' into the TXT record '" +
|
||||||
|
pathname +
|
||||||
|
"'"
|
||||||
|
);
|
||||||
|
console.log(
|
||||||
|
'ddig TXT ' + pathname + " '" + opts.dnsAuthorization + "'"
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
cb(new Error('[acme-v2] unrecognized challenge type'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.log("\nThen hit the 'any' key to continue...");
|
||||||
|
|
||||||
function onAny() {
|
function onAny() {
|
||||||
console.log("'any' key was hit");
|
console.log("'any' key was hit");
|
||||||
process.stdin.pause();
|
process.stdin.pause();
|
||||||
process.stdin.removeListener('data', onAny);
|
process.stdin.removeListener('data', onAny);
|
||||||
process.stdin.setRawMode(false);
|
process.stdin.setRawMode(false);
|
||||||
cb();
|
cb();
|
||||||
}
|
}
|
||||||
|
|
||||||
process.stdin.setRawMode(true);
|
process.stdin.setRawMode(true);
|
||||||
process.stdin.resume();
|
process.stdin.resume();
|
||||||
process.stdin.on('data', onAny);
|
process.stdin.on('data', onAny);
|
||||||
}
|
},
|
||||||
, removeChallenge: function (opts, cb) {
|
removeChallenge: function(opts, cb) {
|
||||||
// hostname, key
|
// hostname, key
|
||||||
console.log('[acme-v2] remove challenge', opts.hostname, opts.keyAuthorization);
|
console.log(
|
||||||
setTimeout(cb, 1 * 1000);
|
'[acme-v2] remove challenge',
|
||||||
}
|
opts.hostname,
|
||||||
, challengeType: chType
|
opts.keyAuthorization
|
||||||
, email: email
|
);
|
||||||
, accountKeypair: accountKeypair
|
setTimeout(cb, 1 * 1000);
|
||||||
, domainKeypair: domainKeypair
|
},
|
||||||
, domains: web
|
challengeType: chType,
|
||||||
};
|
email: email,
|
||||||
|
accountKeypair: accountKeypair,
|
||||||
|
domainKeypair: domainKeypair,
|
||||||
|
domains: web
|
||||||
|
};
|
||||||
|
|
||||||
acme2.accounts.create(options).then(function (account) {
|
acme2.accounts.create(options).then(function(account) {
|
||||||
console.log('[acme-v2] account:');
|
console.log('[acme-v2] account:');
|
||||||
console.log(account);
|
console.log(account);
|
||||||
|
|
||||||
acme2.certificates.create(options).then(function (fullchainPem) {
|
acme2.certificates.create(options).then(function(fullchainPem) {
|
||||||
console.log('[acme-v2] fullchain.pem:');
|
console.log('[acme-v2] fullchain.pem:');
|
||||||
console.log(fullchainPem);
|
console.log(fullchainPem);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
150
tests/compat.js
150
tests/compat.js
|
@ -4,69 +4,103 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
module.exports.run = function (directoryUrl, RSA, web, chType, email, accountKeypair, domainKeypair) {
|
module.exports.run = function(
|
||||||
console.log('[DEBUG] run', web, chType, email);
|
directoryUrl,
|
||||||
|
RSA,
|
||||||
|
web,
|
||||||
|
chType,
|
||||||
|
email,
|
||||||
|
accountKeypair,
|
||||||
|
domainKeypair
|
||||||
|
) {
|
||||||
|
console.log('[DEBUG] run', web, chType, email);
|
||||||
|
|
||||||
var acme2 = require('../compat.js').ACME.create({ RSA: RSA });
|
var acme2 = require('../compat.js').ACME.create({ RSA: RSA });
|
||||||
acme2.getAcmeUrls(acme2.stagingServerUrl, function (err/*, directoryUrls*/) {
|
acme2.getAcmeUrls(acme2.stagingServerUrl, function(err /*, directoryUrls*/) {
|
||||||
if (err) { console.log('err 1'); throw err; }
|
if (err) {
|
||||||
|
console.log('err 1');
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
|
||||||
var options = {
|
var options = {
|
||||||
agreeToTerms: function (tosUrl, agree) {
|
agreeToTerms: function(tosUrl, agree) {
|
||||||
agree(null, tosUrl);
|
agree(null, tosUrl);
|
||||||
}
|
},
|
||||||
, setChallenge: function (hostname, token, val, cb) {
|
setChallenge: function(hostname, token, val, cb) {
|
||||||
var pathname;
|
var pathname;
|
||||||
|
|
||||||
if ('http-01' === cb.type) {
|
if ('http-01' === cb.type) {
|
||||||
pathname = hostname + acme2.acmeChallengePrefix + token;
|
pathname = hostname + acme2.acmeChallengePrefix + token;
|
||||||
console.log("Put the string '" + val /*keyAuthorization*/ + "' into a file at '" + pathname + "'");
|
console.log(
|
||||||
console.log("echo '" + val /*keyAuthorization*/ + "' > '" + pathname + "'");
|
"Put the string '" +
|
||||||
console.log("\nThen hit the 'any' key to continue...");
|
val /*keyAuthorization*/ +
|
||||||
} else if ('dns-01' === cb.type) {
|
"' into a file at '" +
|
||||||
// forwards-backwards compat
|
pathname +
|
||||||
pathname = acme2.challengePrefixes['dns-01'] + "." + hostname.replace(/^\*\./, '');
|
"'"
|
||||||
console.log("Put the string '" + cb.dnsAuthorization + "' into the TXT record '" + pathname + "'");
|
);
|
||||||
console.log("dig TXT " + pathname + " '" + cb.dnsAuthorization + "'");
|
console.log(
|
||||||
console.log("\nThen hit the 'any' key to continue...");
|
"echo '" + val /*keyAuthorization*/ + "' > '" + pathname + "'"
|
||||||
} else {
|
);
|
||||||
cb(new Error("[acme-v2] unrecognized challenge type: " + cb.type));
|
console.log("\nThen hit the 'any' key to continue...");
|
||||||
return;
|
} else if ('dns-01' === cb.type) {
|
||||||
}
|
// forwards-backwards compat
|
||||||
|
pathname =
|
||||||
|
acme2.challengePrefixes['dns-01'] +
|
||||||
|
'.' +
|
||||||
|
hostname.replace(/^\*\./, '');
|
||||||
|
console.log(
|
||||||
|
"Put the string '" +
|
||||||
|
cb.dnsAuthorization +
|
||||||
|
"' into the TXT record '" +
|
||||||
|
pathname +
|
||||||
|
"'"
|
||||||
|
);
|
||||||
|
console.log('dig TXT ' + pathname + " '" + cb.dnsAuthorization + "'");
|
||||||
|
console.log("\nThen hit the 'any' key to continue...");
|
||||||
|
} else {
|
||||||
|
cb(new Error('[acme-v2] unrecognized challenge type: ' + cb.type));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
function onAny() {
|
function onAny() {
|
||||||
console.log("'any' key was hit");
|
console.log("'any' key was hit");
|
||||||
process.stdin.pause();
|
process.stdin.pause();
|
||||||
process.stdin.removeListener('data', onAny);
|
process.stdin.removeListener('data', onAny);
|
||||||
process.stdin.setRawMode(false);
|
process.stdin.setRawMode(false);
|
||||||
cb();
|
cb();
|
||||||
}
|
}
|
||||||
|
|
||||||
process.stdin.setRawMode(true);
|
process.stdin.setRawMode(true);
|
||||||
process.stdin.resume();
|
process.stdin.resume();
|
||||||
process.stdin.on('data', onAny);
|
process.stdin.on('data', onAny);
|
||||||
}
|
},
|
||||||
, removeChallenge: function (hostname, key, cb) {
|
removeChallenge: function(hostname, key, cb) {
|
||||||
console.log('[DEBUG] remove challenge', hostname, key);
|
console.log('[DEBUG] remove challenge', hostname, key);
|
||||||
setTimeout(cb, 1 * 1000);
|
setTimeout(cb, 1 * 1000);
|
||||||
}
|
},
|
||||||
, challengeType: chType
|
challengeType: chType,
|
||||||
, email: email
|
email: email,
|
||||||
, accountKeypair: accountKeypair
|
accountKeypair: accountKeypair,
|
||||||
, domainKeypair: domainKeypair
|
domainKeypair: domainKeypair,
|
||||||
, domains: web
|
domains: web
|
||||||
};
|
};
|
||||||
|
|
||||||
acme2.registerNewAccount(options, function (err, account) {
|
acme2.registerNewAccount(options, function(err, account) {
|
||||||
if (err) { console.log('err 2'); throw err; }
|
if (err) {
|
||||||
if (options.debug) console.debug('account:');
|
console.log('err 2');
|
||||||
if (options.debug) console.log(account);
|
throw err;
|
||||||
|
}
|
||||||
|
if (options.debug) console.debug('account:');
|
||||||
|
if (options.debug) console.log(account);
|
||||||
|
|
||||||
acme2.getCertificate(options, function (err, fullchainPem) {
|
acme2.getCertificate(options, function(err, fullchainPem) {
|
||||||
if (err) { console.log('err 3'); throw err; }
|
if (err) {
|
||||||
console.log('[acme-v2] A fullchain.pem:');
|
console.log('err 3');
|
||||||
console.log(fullchainPem);
|
throw err;
|
||||||
});
|
}
|
||||||
});
|
console.log('[acme-v2] A fullchain.pem:');
|
||||||
});
|
console.log(fullchainPem);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -23,59 +23,67 @@ Rules
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// https://github.com/certbot/certbot/issues/5721#issuecomment-402362709
|
// https://github.com/certbot/certbot/issues/5721#issuecomment-402362709
|
||||||
var expected = "----\nxxxx\nyyyy\n----\n\n----\nxxxx\nyyyy\n----\n";
|
var expected = '----\nxxxx\nyyyy\n----\n\n----\nxxxx\nyyyy\n----\n';
|
||||||
var tests = [
|
var tests = [
|
||||||
"----\r\nxxxx\r\nyyyy\r\n----\r\n\r\n----\r\nxxxx\r\nyyyy\r\n----\r\n"
|
'----\r\nxxxx\r\nyyyy\r\n----\r\n\r\n----\r\nxxxx\r\nyyyy\r\n----\r\n',
|
||||||
, "----\r\nxxxx\r\nyyyy\r\n----\r\n----\r\nxxxx\r\nyyyy\r\n----\r\n"
|
'----\r\nxxxx\r\nyyyy\r\n----\r\n----\r\nxxxx\r\nyyyy\r\n----\r\n',
|
||||||
, "----\nxxxx\nyyyy\n----\n\n----\r\nxxxx\r\nyyyy\r\n----"
|
'----\nxxxx\nyyyy\n----\n\n----\r\nxxxx\r\nyyyy\r\n----',
|
||||||
, "----\nxxxx\nyyyy\n----\n----\r\nxxxx\r\nyyyy\r\n----"
|
'----\nxxxx\nyyyy\n----\n----\r\nxxxx\r\nyyyy\r\n----',
|
||||||
, "----\nxxxx\nyyyy\n----\n----\nxxxx\nyyyy\n----"
|
'----\nxxxx\nyyyy\n----\n----\nxxxx\nyyyy\n----',
|
||||||
, "----\nxxxx\nyyyy\n----\n----\nxxxx\nyyyy\n----\n"
|
'----\nxxxx\nyyyy\n----\n----\nxxxx\nyyyy\n----\n',
|
||||||
, "----\nxxxx\nyyyy\n----\n\n----\nxxxx\nyyyy\n----\n"
|
'----\nxxxx\nyyyy\n----\n\n----\nxxxx\nyyyy\n----\n',
|
||||||
, "----\nxxxx\nyyyy\n----\r\n----\nxxxx\ryyyy\n----\n"
|
'----\nxxxx\nyyyy\n----\r\n----\nxxxx\ryyyy\n----\n'
|
||||||
];
|
];
|
||||||
|
|
||||||
function formatPemChain(str) {
|
function formatPemChain(str) {
|
||||||
return str.trim().replace(/[\r\n]+/g, '\n').replace(/\-\n\-/g, '-\n\n-') + '\n';
|
return (
|
||||||
|
str
|
||||||
|
.trim()
|
||||||
|
.replace(/[\r\n]+/g, '\n')
|
||||||
|
.replace(/\-\n\-/g, '-\n\n-') + '\n'
|
||||||
|
);
|
||||||
}
|
}
|
||||||
function splitPemChain(str) {
|
function splitPemChain(str) {
|
||||||
return str.trim().split(/[\r\n]{2,}/g).map(function (str) {
|
return str
|
||||||
return str + '\n';
|
.trim()
|
||||||
});
|
.split(/[\r\n]{2,}/g)
|
||||||
|
.map(function(str) {
|
||||||
|
return str + '\n';
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
tests.forEach(function (str) {
|
tests.forEach(function(str) {
|
||||||
var actual = formatPemChain(str);
|
var actual = formatPemChain(str);
|
||||||
if (expected !== actual) {
|
if (expected !== actual) {
|
||||||
console.error('input: ', JSON.stringify(str));
|
console.error('input: ', JSON.stringify(str));
|
||||||
console.error('expected:', JSON.stringify(expected));
|
console.error('expected:', JSON.stringify(expected));
|
||||||
console.error('actual: ', JSON.stringify(actual));
|
console.error('actual: ', JSON.stringify(actual));
|
||||||
throw new Error("did not pass");
|
throw new Error('did not pass');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (
|
if (
|
||||||
"----\nxxxx\nyyyy\n----\n"
|
'----\nxxxx\nyyyy\n----\n' !==
|
||||||
!==
|
formatPemChain('\n\n----\r\nxxxx\r\nyyyy\r\n----\n\n')
|
||||||
formatPemChain("\n\n----\r\nxxxx\r\nyyyy\r\n----\n\n")
|
|
||||||
) {
|
) {
|
||||||
throw new Error("Not proper for single cert in chain");
|
throw new Error('Not proper for single cert in chain');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
"--B--\nxxxx\nyyyy\n--E--\n\n--B--\nxxxx\nyyyy\n--E--\n\n--B--\nxxxx\nyyyy\n--E--\n"
|
'--B--\nxxxx\nyyyy\n--E--\n\n--B--\nxxxx\nyyyy\n--E--\n\n--B--\nxxxx\nyyyy\n--E--\n' !==
|
||||||
!==
|
formatPemChain(
|
||||||
formatPemChain("\n\n\n--B--\nxxxx\nyyyy\n--E--\n\n\n\n--B--\nxxxx\nyyyy\n--E--\n\n\n--B--\nxxxx\nyyyy\n--E--\n\n\n")
|
'\n\n\n--B--\nxxxx\nyyyy\n--E--\n\n\n\n--B--\nxxxx\nyyyy\n--E--\n\n\n--B--\nxxxx\nyyyy\n--E--\n\n\n'
|
||||||
|
)
|
||||||
) {
|
) {
|
||||||
throw new Error("Not proper for three certs in chain");
|
throw new Error('Not proper for three certs in chain');
|
||||||
}
|
}
|
||||||
|
|
||||||
splitPemChain(
|
splitPemChain(
|
||||||
"--B--\nxxxx\nyyyy\n--E--\n\n--B--\nxxxx\nyyyy\n--E--\n\n--B--\nxxxx\nyyyy\n--E--\n"
|
'--B--\nxxxx\nyyyy\n--E--\n\n--B--\nxxxx\nyyyy\n--E--\n\n--B--\nxxxx\nyyyy\n--E--\n'
|
||||||
).forEach(function (str) {
|
).forEach(function(str) {
|
||||||
if ("--B--\nxxxx\nyyyy\n--E--\n" !== str) {
|
if ('--B--\nxxxx\nyyyy\n--E--\n' !== str) {
|
||||||
throw new Error("bad thingy");
|
throw new Error('bad thingy');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
console.info('PASS');
|
console.info('PASS');
|
||||||
|
|
185
tests/promise.js
185
tests/promise.js
|
@ -5,85 +5,120 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
/* global Promise */
|
/* global Promise */
|
||||||
module.exports.run = function run(directoryUrl, RSA, web, chType, email, accountKeypair, domainKeypair) {
|
module.exports.run = function run(
|
||||||
var acme2 = require('../').ACME.create({ RSA: RSA });
|
directoryUrl,
|
||||||
// [ 'test.ppl.family' ] 'coolaj86@gmail.com''http-01'
|
RSA,
|
||||||
acme2.init(directoryUrl).then(function () {
|
web,
|
||||||
var options = {
|
chType,
|
||||||
agreeToTerms: function (tosUrl) {
|
email,
|
||||||
return Promise.resolve(tosUrl);
|
accountKeypair,
|
||||||
}
|
domainKeypair
|
||||||
, setChallenge: function (opts) {
|
) {
|
||||||
return new Promise(function (resolve, reject) {
|
var acme2 = require('../').ACME.create({ RSA: RSA });
|
||||||
var pathname;
|
// [ 'test.ppl.family' ] 'coolaj86@gmail.com''http-01'
|
||||||
|
acme2.init(directoryUrl).then(function() {
|
||||||
|
var options = {
|
||||||
|
agreeToTerms: function(tosUrl) {
|
||||||
|
return Promise.resolve(tosUrl);
|
||||||
|
},
|
||||||
|
setChallenge: function(opts) {
|
||||||
|
return new Promise(function(resolve, reject) {
|
||||||
|
var pathname;
|
||||||
|
|
||||||
console.log("");
|
console.log('');
|
||||||
console.log('identifier:');
|
console.log('identifier:');
|
||||||
console.log(opts.identifier);
|
console.log(opts.identifier);
|
||||||
console.log('hostname:');
|
console.log('hostname:');
|
||||||
console.log(opts.hostname);
|
console.log(opts.hostname);
|
||||||
console.log('type:');
|
console.log('type:');
|
||||||
console.log(opts.type);
|
console.log(opts.type);
|
||||||
console.log('token:');
|
console.log('token:');
|
||||||
console.log(opts.token);
|
console.log(opts.token);
|
||||||
console.log('thumbprint:');
|
console.log('thumbprint:');
|
||||||
console.log(opts.thumbprint);
|
console.log(opts.thumbprint);
|
||||||
console.log('keyAuthorization:');
|
console.log('keyAuthorization:');
|
||||||
console.log(opts.keyAuthorization);
|
console.log(opts.keyAuthorization);
|
||||||
console.log('dnsAuthorization:');
|
console.log('dnsAuthorization:');
|
||||||
console.log(opts.dnsAuthorization);
|
console.log(opts.dnsAuthorization);
|
||||||
console.log("");
|
console.log('');
|
||||||
|
|
||||||
if ('http-01' === opts.type) {
|
if ('http-01' === opts.type) {
|
||||||
pathname = opts.hostname + acme2.challengePrefixes['http-01'] + "/" + opts.token;
|
pathname =
|
||||||
console.log("Put the string '" + opts.keyAuthorization + "' into a file at '" + pathname + "'");
|
opts.hostname +
|
||||||
console.log("echo '" + opts.keyAuthorization + "' > '" + pathname + "'");
|
acme2.challengePrefixes['http-01'] +
|
||||||
} else if ('dns-01' === opts.type) {
|
'/' +
|
||||||
pathname = acme2.challengePrefixes['dns-01'] + "." + opts.hostname.replace(/^\*\./, '');
|
opts.token;
|
||||||
console.log("Put the string '" + opts.dnsAuthorization + "' into the TXT record '" + pathname + "'");
|
console.log(
|
||||||
console.log("dig TXT " + pathname + " '" + opts.dnsAuthorization + "'");
|
"Put the string '" +
|
||||||
} else {
|
opts.keyAuthorization +
|
||||||
reject(new Error("[acme-v2] unrecognized challenge type"));
|
"' into a file at '" +
|
||||||
return;
|
pathname +
|
||||||
}
|
"'"
|
||||||
console.log("\nThen hit the 'any' key to continue...");
|
);
|
||||||
|
console.log(
|
||||||
|
"echo '" + opts.keyAuthorization + "' > '" + pathname + "'"
|
||||||
|
);
|
||||||
|
} else if ('dns-01' === opts.type) {
|
||||||
|
pathname =
|
||||||
|
acme2.challengePrefixes['dns-01'] +
|
||||||
|
'.' +
|
||||||
|
opts.hostname.replace(/^\*\./, '');
|
||||||
|
console.log(
|
||||||
|
"Put the string '" +
|
||||||
|
opts.dnsAuthorization +
|
||||||
|
"' into the TXT record '" +
|
||||||
|
pathname +
|
||||||
|
"'"
|
||||||
|
);
|
||||||
|
console.log(
|
||||||
|
'dig TXT ' + pathname + " '" + opts.dnsAuthorization + "'"
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
reject(new Error('[acme-v2] unrecognized challenge type'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.log("\nThen hit the 'any' key to continue...");
|
||||||
|
|
||||||
function onAny() {
|
function onAny() {
|
||||||
console.log("'any' key was hit");
|
console.log("'any' key was hit");
|
||||||
process.stdin.pause();
|
process.stdin.pause();
|
||||||
process.stdin.removeListener('data', onAny);
|
process.stdin.removeListener('data', onAny);
|
||||||
process.stdin.setRawMode(false);
|
process.stdin.setRawMode(false);
|
||||||
resolve();
|
resolve();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
process.stdin.setRawMode(true);
|
process.stdin.setRawMode(true);
|
||||||
process.stdin.resume();
|
process.stdin.resume();
|
||||||
process.stdin.on('data', onAny);
|
process.stdin.on('data', onAny);
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
, removeChallenge: function (opts) {
|
removeChallenge: function(opts) {
|
||||||
console.log('[acme-v2] remove challenge', opts.hostname, opts.keyAuthorization);
|
console.log(
|
||||||
return new Promise(function (resolve) {
|
'[acme-v2] remove challenge',
|
||||||
// hostname, key
|
opts.hostname,
|
||||||
setTimeout(resolve, 1 * 1000);
|
opts.keyAuthorization
|
||||||
});
|
);
|
||||||
}
|
return new Promise(function(resolve) {
|
||||||
, challengeType: chType
|
// hostname, key
|
||||||
, email: email
|
setTimeout(resolve, 1 * 1000);
|
||||||
, accountKeypair: accountKeypair
|
});
|
||||||
, domainKeypair: domainKeypair
|
},
|
||||||
, domains: web
|
challengeType: chType,
|
||||||
};
|
email: email,
|
||||||
|
accountKeypair: accountKeypair,
|
||||||
|
domainKeypair: domainKeypair,
|
||||||
|
domains: web
|
||||||
|
};
|
||||||
|
|
||||||
acme2.accounts.create(options).then(function (account) {
|
acme2.accounts.create(options).then(function(account) {
|
||||||
console.log('[acme-v2] account:');
|
console.log('[acme-v2] account:');
|
||||||
console.log(account);
|
console.log(account);
|
||||||
|
|
||||||
acme2.certificates.create(options).then(function (fullchainPem) {
|
acme2.certificates.create(options).then(function(fullchainPem) {
|
||||||
console.log('[acme-v2] fullchain.pem:');
|
console.log('[acme-v2] fullchain.pem:');
|
||||||
console.log(fullchainPem);
|
console.log(fullchainPem);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue