Compare commits
No commits in common. "master" and "v1.x" have entirely different histories.
|
@ -29,5 +29,3 @@ build/Release
|
||||||
# Dependency directory
|
# Dependency directory
|
||||||
# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git
|
# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git
|
||||||
node_modules
|
node_modules
|
||||||
.idea
|
|
||||||
.DS_Store
|
|
||||||
|
|
2
AUTHORS
2
AUTHORS
|
@ -1,3 +1,3 @@
|
||||||
ISRG
|
ISRG
|
||||||
Anatol Sommer <anatol@anatol.at>
|
Anatol Sommer <anatol@anatol.at>
|
||||||
AJ ONeal <coolaj86@gmail.com> (https://coolaj86.com/)
|
AJ ONeal <aj@daplie.com> (https://daplie.com/)
|
||||||
|
|
102
README.md
102
README.md
|
@ -1,8 +1,4 @@
|
||||||
# le-acme-core
|
# letiny-core
|
||||||
|
|
||||||
Looking for **letiny-core**? Check the [v1.x branch](https://git.coolaj86.com/coolaj86/le-acme-core.js/tree/v1.x).
|
|
||||||
|
|
||||||
<!-- rename to le-acme-core -->
|
|
||||||
|
|
||||||
A framework for building letsencrypt clients, forked from `letiny`.
|
A framework for building letsencrypt clients, forked from `letiny`.
|
||||||
|
|
||||||
|
@ -13,44 +9,19 @@ Supports all of:
|
||||||
* browser WebCrypto (not implemented, but... Let's Encrypt over WebRTC anyone?)
|
* browser WebCrypto (not implemented, but... Let's Encrypt over WebRTC anyone?)
|
||||||
* any javascript implementation
|
* any javascript implementation
|
||||||
|
|
||||||
# NEW: Let's Encrypt v2 Support
|
|
||||||
Let's Encrypt v2 (aka ACME v2 or ACME draft 11) is available in [acme-v2.js](https://git.coolaj86.com/coolaj86/acme-v2.js)
|
|
||||||
|
|
||||||
### These aren't the droids you're looking for
|
### These aren't the droids you're looking for
|
||||||
|
|
||||||
This is a library / framework for building letsencrypt clients.
|
This is a library / framework for building letsencrypt clients.
|
||||||
You probably want one of these pre-built clients instead:
|
You probably want one of these pre-built clients instead:
|
||||||
|
|
||||||
* [`letsencrypt`](https://git.coolaj86.com/coolaj86/greenlock.js) (compatible with the official client)
|
* [`letsencrypt`](https://github.com/Daplie/node-letsencrypt) (compatible with the official client)
|
||||||
* `letiny` (lightweight client cli)
|
* `letiny` (lightweight client cli)
|
||||||
* [`letsencrypt-express`](https://git.coolaj86.com/coolaj86/greenlock-express.js) (automatic https for express)
|
* [`letsencrypt-express`](https://github.com/Daplie/letsencrypt-express) (automatic https for express)
|
||||||
|
|
||||||
## Install & Usage:
|
## Install & Usage:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm install --save le-acme-core
|
npm install --save letiny-core
|
||||||
```
|
|
||||||
|
|
||||||
To use the default dependencies:
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
var ACME = require('le-acme-core').ACME.create();
|
|
||||||
```
|
|
||||||
|
|
||||||
For **testing** and **development**, you can also inject the dependencies you want to use:
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
var ACME = require('le-acme-core').ACME.create({
|
|
||||||
, RSA: require('rsa-compat').RSA
|
|
||||||
});
|
|
||||||
|
|
||||||
ACME.getAcmeUrls(discoveryUrl, function (err, urls) {
|
|
||||||
console.log(urls);
|
|
||||||
});
|
|
||||||
```
|
```
|
||||||
|
|
||||||
You will follow these steps to obtain certificates:
|
You will follow these steps to obtain certificates:
|
||||||
|
@ -78,12 +49,12 @@ Note: use **YOUR EMAIL** and accept the terms of service (run `ddns --help` to s
|
||||||
|
|
||||||
<!-- TODO tutorial on ddns -->
|
<!-- TODO tutorial on ddns -->
|
||||||
|
|
||||||
Install le-acme-core and its dependencies. **Note**: it's okay if you're on windows
|
Install letiny-core and its dependencies. **Note**: it's okay if you're on windows
|
||||||
and `ursa` fails to compile. It'll still work.
|
and `ursa` fails to compile. It'll still work.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git clone https://git.coolaj86.com/coolaj86/le-acme-core.js.git ~/le-acme-core
|
git clone https://github.com/Daplie/letiny-core.git ~/letiny-core
|
||||||
pushd ~/le-acme-core
|
pushd ~/letiny-core
|
||||||
|
|
||||||
npm install
|
npm install
|
||||||
```
|
```
|
||||||
|
@ -102,7 +73,7 @@ The Goodies
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
// Accounts
|
// Accounts
|
||||||
ACME.registerNewAccount(options, cb) // returns "regr" registration data
|
LeCore.registerNewAccount(options, cb) // returns "regr" registration data
|
||||||
|
|
||||||
{ newRegUrl: '<url>' // no defaults, specify acmeUrls.newAuthz
|
{ newRegUrl: '<url>' // no defaults, specify acmeUrls.newAuthz
|
||||||
, email: '<email>' // valid email (server checks MX records)
|
, email: '<email>' // valid email (server checks MX records)
|
||||||
|
@ -113,7 +84,7 @@ ACME.registerNewAccount(options, cb) // returns "regr" registration data
|
||||||
}
|
}
|
||||||
|
|
||||||
// Registration
|
// Registration
|
||||||
ACME.getCertificate(options, cb) // returns (err, pems={ privkey (key), cert, chain (ca) })
|
LeCore.getCertificate(options, cb) // returns (err, pems={ privkey (key), cert, chain (ca) })
|
||||||
|
|
||||||
{ newAuthzUrl: '<url>' // specify acmeUrls.newAuthz
|
{ newAuthzUrl: '<url>' // specify acmeUrls.newAuthz
|
||||||
, newCertUrl: '<url>' // specify acmeUrls.newCert
|
, newCertUrl: '<url>' // specify acmeUrls.newCert
|
||||||
|
@ -131,32 +102,49 @@ ACME.getCertificate(options, cb) // returns (err, pems={ privkey (key
|
||||||
}
|
}
|
||||||
|
|
||||||
// Discovery URLs
|
// Discovery URLs
|
||||||
ACME.getAcmeUrls(acmeDiscoveryUrl, cb) // returns (err, acmeUrls={newReg,newAuthz,newCert,revokeCert})
|
LeCore.getAcmeUrls(acmeDiscoveryUrl, cb) // returns (err, acmeUrls={newReg,newAuthz,newCert,revokeCert})
|
||||||
```
|
```
|
||||||
|
|
||||||
Helpers & Stuff
|
Helpers & Stuff
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
// Constants
|
// Constants
|
||||||
ACME.productionServerUrl // https://acme-v01.api.letsencrypt.org/directory
|
LeCore.productionServerUrl // https://acme-v01.api.letsencrypt.org/directory
|
||||||
ACME.stagingServerUrl // https://acme-staging.api.letsencrypt.org/directory
|
LeCore.stagingServerUrl // https://acme-staging.api.letsencrypt.org/directory
|
||||||
ACME.acmeChallengePrefix // /.well-known/acme-challenge/
|
LeCore.acmeChallengePrefix // /.well-known/acme-challenge/
|
||||||
ACME.knownEndpoints // new-authz, new-cert, new-reg, revoke-cert
|
LeCore.configDir // /etc/letsencrypt/
|
||||||
|
LeCore.logsDir // /var/log/letsencrypt/
|
||||||
|
LeCore.workDir // /var/lib/letsencrypt/
|
||||||
|
LeCore.knownEndpoints // new-authz, new-cert, new-reg, revoke-cert
|
||||||
|
|
||||||
|
|
||||||
// HTTP Client Helpers
|
// HTTP Client Helpers
|
||||||
ACME.Acme // Signs requests with JWK
|
LeCore.Acme // Signs requests with JWK
|
||||||
acme = new Acme(keypair) // 'keypair' is an object with `privateKeyPem` and/or `privateKeyJwk`
|
acme = new Acme(keypair) // 'keypair' is an object with `privateKeyPem` and/or `privateKeyJwk`
|
||||||
acme.post(url, body, cb) // POST with signature
|
acme.post(url, body, cb) // POST with signature
|
||||||
acme.parseLinks(link) // (internal) parses 'link' header
|
acme.parseLinks(link) // (internal) parses 'link' header
|
||||||
acme.getNonce(url, cb) // (internal) HEAD request to get 'replay-nonce' strings
|
acme.getNonce(url, cb) // (internal) HEAD request to get 'replay-nonce' strings
|
||||||
```
|
```
|
||||||
|
|
||||||
|
For testing and development, you can also inject the dependencies you want to use:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
LeCore = LeCore.create({
|
||||||
|
request: require('request')
|
||||||
|
, RSA: rquire('rsa-compat').RSA
|
||||||
|
});
|
||||||
|
|
||||||
|
// now uses node `request` (could also use jQuery or Angular in the browser)
|
||||||
|
LeCore.getAcmeUrls(discoveryUrl, function (err, urls) {
|
||||||
|
console.log(urls);
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
## Example
|
## Example
|
||||||
|
|
||||||
Below you'll find a stripped-down example. You can see the full example in the example folder.
|
Below you'll find a stripped-down example. You can see the full example in the example folder.
|
||||||
|
|
||||||
* [example/](https://git.coolaj86.com/coolaj86/le-acme-core.js/blob/master/example/)
|
* [example/](https://github.com/Daplie/letiny-core/blob/master/example/)
|
||||||
|
|
||||||
#### Register Account & Domain
|
#### Register Account & Domain
|
||||||
|
|
||||||
|
@ -165,12 +153,12 @@ This is how you **register an ACME account** and **get an HTTPS certificate**
|
||||||
```javascript
|
```javascript
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var ACME = require('le-acme-core').ACME.create();
|
var LeCore = require('letiny-core');
|
||||||
var RSA = require('rsa-compat').RSA;
|
var RSA = require('rsa-compat').RSA;
|
||||||
|
|
||||||
var email = 'user@example.com'; // CHANGE TO YOUR EMAIL
|
var email = 'user@example.com'; // CHANGE TO YOUR EMAIL
|
||||||
var domains = 'example.com'; // CHANGE TO YOUR DOMAIN
|
var domains = 'example.com'; // CHANGE TO YOUR DOMAIN
|
||||||
var acmeDiscoveryUrl = ACME.stagingServerUrl; // CHANGE to production, when ready
|
var acmeDiscoveryUrl = LeCore.stagingServerUrl; // CHANGE to production, when ready
|
||||||
|
|
||||||
var accountKeypair = null; // { privateKeyPem: null, privateKeyJwk: null };
|
var accountKeypair = null; // { privateKeyPem: null, privateKeyJwk: null };
|
||||||
var domainKeypair = null; // same as above
|
var domainKeypair = null; // same as above
|
||||||
|
@ -179,14 +167,14 @@ var acmeUrls = null;
|
||||||
RSA.generateKeypair(2048, 65537, function (err, keypair) {
|
RSA.generateKeypair(2048, 65537, function (err, keypair) {
|
||||||
accountKeypair = keypair;
|
accountKeypair = keypair;
|
||||||
// ...
|
// ...
|
||||||
ACME.getAcmeUrls(acmeDiscoveryUrl, function (err, urls) {
|
LeCore.getAcmeUrls(acmeDiscoveryUrl, function (err, urls) {
|
||||||
// ...
|
// ...
|
||||||
runDemo();
|
runDemo();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
function runDemo() {
|
function runDemo() {
|
||||||
ACME.registerNewAccount(
|
LeCore.registerNewAccount(
|
||||||
{ newRegUrl: acmeUrls.newReg
|
{ newRegUrl: acmeUrls.newReg
|
||||||
, email: email
|
, email: email
|
||||||
, accountKeypair: accountKeypair
|
, accountKeypair: accountKeypair
|
||||||
|
@ -198,7 +186,7 @@ function runDemo() {
|
||||||
}
|
}
|
||||||
, function (err, regr) {
|
, function (err, regr) {
|
||||||
|
|
||||||
ACME.getCertificate(
|
LeCore.getCertificate(
|
||||||
{ newAuthzUrl: acmeUrls.newAuthz
|
{ newAuthzUrl: acmeUrls.newAuthz
|
||||||
, newCertUrl: acmeUrls.newCert
|
, newCertUrl: acmeUrls.newCert
|
||||||
|
|
||||||
|
@ -226,7 +214,7 @@ function runDemo() {
|
||||||
```
|
```
|
||||||
|
|
||||||
**But wait**, there's more!
|
**But wait**, there's more!
|
||||||
See [example/letsencrypt.js](https://git.coolaj86.com/coolaj86/le-acme-core.js/blob/master/example/letsencrypt.js)
|
See [example/letsencrypt.js](https://github.com/Daplie/letiny-core/blob/master/example/letsencrypt.js)
|
||||||
|
|
||||||
#### Run a Server on 80, 443, and 5001 (https/tls)
|
#### Run a Server on 80, 443, and 5001 (https/tls)
|
||||||
|
|
||||||
|
@ -239,7 +227,7 @@ var http = require('http');
|
||||||
|
|
||||||
|
|
||||||
var LeCore = deps.LeCore;
|
var LeCore = deps.LeCore;
|
||||||
var tlsOptions = deps.tlsOptions;
|
var httpsOptions = deps.httpsOptions;
|
||||||
var challengeStore = deps.challengeStore;
|
var challengeStore = deps.challengeStore;
|
||||||
var certStore = deps.certStore;
|
var certStore = deps.certStore;
|
||||||
|
|
||||||
|
@ -264,7 +252,7 @@ function acmeResponder(req, res) {
|
||||||
//
|
//
|
||||||
// Server
|
// Server
|
||||||
//
|
//
|
||||||
https.createServer(tlsOptions, acmeResponder).listen(5001, function () {
|
https.createServer(httpsOptions, acmeResponder).listen(5001, function () {
|
||||||
console.log('Listening https on', this.address());
|
console.log('Listening https on', this.address());
|
||||||
});
|
});
|
||||||
http.createServer(acmeResponder).listen(80, function () {
|
http.createServer(acmeResponder).listen(80, function () {
|
||||||
|
@ -273,7 +261,7 @@ http.createServer(acmeResponder).listen(80, function () {
|
||||||
```
|
```
|
||||||
|
|
||||||
**But wait**, there's more!
|
**But wait**, there's more!
|
||||||
See [example/serve.js](https://git.coolaj86.com/coolaj86/le-acme-core.js/blob/master/example/serve.js)
|
See [example/serve.js](https://github.com/Daplie/letiny-core/blob/master/example/serve.js)
|
||||||
|
|
||||||
#### Put some storage in place
|
#### Put some storage in place
|
||||||
|
|
||||||
|
@ -314,14 +302,14 @@ var certStore = {
|
||||||
**But wait**, there's more!
|
**But wait**, there's more!
|
||||||
See
|
See
|
||||||
|
|
||||||
* [example/challenge-store.js](https://git.coolaj86.com/coolaj86/le-acme-core.js/blob/master/challenge-store.js)
|
* [example/challenge-store.js](https://github.com/Daplie/letiny-core/blob/master/challenge-store.js)
|
||||||
* [example/cert-store.js](https://git.coolaj86.com/coolaj86/le-acme-core.js/blob/master/cert-store.js)
|
* [example/cert-store.js](https://github.com/Daplie/letiny-core/blob/master/cert-store.js)
|
||||||
|
|
||||||
## Authors
|
## Authors
|
||||||
|
|
||||||
* ISRG
|
* ISRG
|
||||||
* Anatol Sommer (https://github.com/anatolsommer)
|
* Anatol Sommer (https://github.com/anatolsommer)
|
||||||
* AJ ONeal <coolaj86@gmail.com> (https://coolaj86.com)
|
* AJ ONeal <aj@daplie.com> (https://daplie.com)
|
||||||
|
|
||||||
## Licence
|
## Licence
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*!
|
/*!
|
||||||
* letiny-core
|
* letiny-core
|
||||||
* Copyright(c) 2015 AJ ONeal <coolaj86@gmail.com> https://coolaj86.com
|
* Copyright(c) 2015 AJ ONeal <aj@daplie.com> https://daplie.com
|
||||||
* Apache-2.0 OR MIT (and hence also MPL 2.0)
|
* Apache-2.0 OR MIT (and hence also MPL 2.0)
|
||||||
*/
|
*/
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*!
|
/*!
|
||||||
* letiny-core
|
* letiny-core
|
||||||
* Copyright(c) 2015 AJ ONeal <coolaj86@gmail.com> https://coolaj86.com
|
* Copyright(c) 2015 AJ ONeal <aj@daplie.com> https://daplie.com
|
||||||
* Apache-2.0 OR MIT (and hence also MPL 2.0)
|
* Apache-2.0 OR MIT (and hence also MPL 2.0)
|
||||||
*/
|
*/
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
/*!
|
/*!
|
||||||
* letiny-core
|
* letiny-core
|
||||||
* Copyright(c) 2015 AJ ONeal <coolaj86@gmail.com> https://coolaj86.com
|
* Copyright(c) 2015 AJ ONeal <aj@daplie.com> https://daplie.com
|
||||||
* Apache-2.0 OR MIT (and hence also MPL 2.0)
|
* Apache-2.0 OR MIT (and hence also MPL 2.0)
|
||||||
*/
|
*/
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
//var LeCore = require('letiny-core');
|
//var LeCore = require('letiny-core');
|
||||||
var LeCore = require('../').ACME.create();
|
var LeCore = require('../');
|
||||||
|
|
||||||
var email = process.argv[2] || 'user@example.com'; // CHANGE TO YOUR EMAIL
|
var email = process.argv[2] || 'user@example.com'; // CHANGE TO YOUR EMAIL
|
||||||
var domains = [process.argv[3] || 'example.com']; // CHANGE TO YOUR DOMAIN
|
var domains = [process.argv[3] || 'example.com']; // CHANGE TO YOUR DOMAIN
|
||||||
|
@ -17,8 +17,8 @@ var certStore = require('./cert-store');
|
||||||
var serve = require('./serve');
|
var serve = require('./serve');
|
||||||
var closer;
|
var closer;
|
||||||
|
|
||||||
var accountKeypair = null;
|
var accountPrivateKeyPem = null;
|
||||||
var domainKeypair = null;
|
var domainPrivateKeyPem = null;
|
||||||
var acmeUrls = null;
|
var acmeUrls = null;
|
||||||
|
|
||||||
|
|
||||||
|
@ -44,14 +44,14 @@ function init() {
|
||||||
|
|
||||||
function getPrivateKeys(cb) {
|
function getPrivateKeys(cb) {
|
||||||
console.log('Generating Account Keypair');
|
console.log('Generating Account Keypair');
|
||||||
const RSA = require('rsa-compat').RSA;
|
console.log("(Note: if you're using forge and not ursa, this will take a long time");
|
||||||
RSA.generateKeypair(2048, 65537, {}, function (err, pems) {
|
LeCore.leCrypto.generateRsaKeypair(2048, 65537, function (err, pems) {
|
||||||
|
|
||||||
accountKeypair = pems;
|
accountPrivateKeyPem = pems.privateKeyPem;
|
||||||
console.log('Generating Domain Keypair');
|
console.log('Generating Domain Keypair');
|
||||||
RSA.generateKeypair(2048, 65537, {}, function (err, pems2) {
|
LeCore.leCrypto.generateRsaKeypair(2048, 65537, function (err, pems) {
|
||||||
|
|
||||||
domainKeypair = pems2;
|
domainPrivateKeyPem = pems.privateKeyPem;
|
||||||
cb();
|
cb();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -62,7 +62,7 @@ function runDemo() {
|
||||||
LeCore.registerNewAccount(
|
LeCore.registerNewAccount(
|
||||||
{ newRegUrl: acmeUrls.newReg
|
{ newRegUrl: acmeUrls.newReg
|
||||||
, email: email
|
, email: email
|
||||||
, accountKeypair: accountKeypair
|
, accountPrivateKeyPem: accountPrivateKeyPem
|
||||||
, agreeToTerms: function (tosUrl, done) {
|
, agreeToTerms: function (tosUrl, done) {
|
||||||
|
|
||||||
// agree to the exact version of these terms
|
// agree to the exact version of these terms
|
||||||
|
@ -82,8 +82,8 @@ function runDemo() {
|
||||||
{ newAuthzUrl: acmeUrls.newAuthz
|
{ newAuthzUrl: acmeUrls.newAuthz
|
||||||
, newCertUrl: acmeUrls.newCert
|
, newCertUrl: acmeUrls.newCert
|
||||||
|
|
||||||
, domainKeypair: domainKeypair
|
, domainPrivateKeyPem: domainPrivateKeyPem
|
||||||
, accountKeypair: accountKeypair
|
, accountPrivateKeyPem: accountPrivateKeyPem
|
||||||
, domains: domains
|
, domains: domains
|
||||||
|
|
||||||
, setChallenge: challengeStore.set
|
, setChallenge: challengeStore.set
|
||||||
|
@ -99,7 +99,7 @@ function runDemo() {
|
||||||
closer();
|
closer();
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -111,7 +111,8 @@ function runDemo() {
|
||||||
//
|
//
|
||||||
closer = serve.init({
|
closer = serve.init({
|
||||||
LeCore: LeCore
|
LeCore: LeCore
|
||||||
, tlsOptions: {}
|
// needs a default key and cert chain, anything will do
|
||||||
|
, httpsOptions: require('localhost.daplie.com-certificates')
|
||||||
, challengeStore: challengeStore
|
, challengeStore: challengeStore
|
||||||
, certStore: certStore
|
, certStore: certStore
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*!
|
/*!
|
||||||
* letiny-core
|
* letiny-core
|
||||||
* Copyright(c) 2015 AJ ONeal <coolaj86@gmail.com> https://coolaj86.com
|
* Copyright(c) 2015 AJ ONeal <aj@daplie.com> https://daplie.com
|
||||||
* Apache-2.0 OR MIT (and hence also MPL 2.0)
|
* Apache-2.0 OR MIT (and hence also MPL 2.0)
|
||||||
*/
|
*/
|
||||||
'use strict';
|
'use strict';
|
||||||
|
@ -15,7 +15,7 @@ module.exports.init = function (deps) {
|
||||||
|
|
||||||
|
|
||||||
var LeCore = deps.LeCore;
|
var LeCore = deps.LeCore;
|
||||||
var tlsOptions = deps.tlsOptions || deps.httpsOptions;
|
var httpsOptions = deps.httpsOptions;
|
||||||
var challengeStore = deps.challengeStore;
|
var challengeStore = deps.challengeStore;
|
||||||
var certStore = deps.certStore;
|
var certStore = deps.certStore;
|
||||||
|
|
||||||
|
@ -63,11 +63,11 @@ module.exports.init = function (deps) {
|
||||||
//
|
//
|
||||||
// Server
|
// Server
|
||||||
//
|
//
|
||||||
tlsOptions.SNICallback = certGetter;
|
httpsOptions.SNICallback = certGetter;
|
||||||
https.createServer(tlsOptions, acmeResponder).listen(443, function () {
|
https.createServer(httpsOptions, acmeResponder).listen(443, function () {
|
||||||
console.log('Listening https on', this.address());
|
console.log('Listening https on', this.address());
|
||||||
});
|
});
|
||||||
https.createServer(tlsOptions, acmeResponder).listen(5001, function () {
|
https.createServer(httpsOptions, acmeResponder).listen(5001, function () {
|
||||||
console.log('Listening https on', this.address());
|
console.log('Listening https on', this.address());
|
||||||
});
|
});
|
||||||
http.createServer(acmeResponder).listen(80, function () {
|
http.createServer(acmeResponder).listen(80, function () {
|
||||||
|
@ -77,6 +77,6 @@ module.exports.init = function (deps) {
|
||||||
return function () {
|
return function () {
|
||||||
// Note: we should just keep a handle on
|
// Note: we should just keep a handle on
|
||||||
// the servers and close them each with server.close()
|
// the servers and close them each with server.close()
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -8,10 +8,10 @@
|
||||||
|
|
||||||
module.exports.create = function (deps) {
|
module.exports.create = function (deps) {
|
||||||
|
|
||||||
var NOOP = function () {
|
var NOOP=function () {
|
||||||
};
|
};
|
||||||
var log = NOOP;
|
var log=NOOP;
|
||||||
var acmeRequest = deps.acmeRequest;
|
var request=require('request');
|
||||||
var RSA = deps.RSA;
|
var RSA = deps.RSA;
|
||||||
var generateSignature = RSA.signJws;
|
var generateSignature = RSA.signJws;
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ module.exports.create = function (deps) {
|
||||||
Acme.prototype.getNonce=function(url, cb) {
|
Acme.prototype.getNonce=function(url, cb) {
|
||||||
var self=this;
|
var self=this;
|
||||||
|
|
||||||
acmeRequest.create().head({
|
request.head({
|
||||||
url:url,
|
url:url,
|
||||||
}, function(err, res/*, body*/) {
|
}, function(err, res/*, body*/) {
|
||||||
if (err) {
|
if (err) {
|
||||||
|
@ -73,10 +73,10 @@ module.exports.create = function (deps) {
|
||||||
|
|
||||||
//process.exit(1);
|
//process.exit(1);
|
||||||
//return;
|
//return;
|
||||||
return acmeRequest.create().post({
|
return request.post({
|
||||||
url: url
|
url:url,
|
||||||
, body: signed
|
body:signed,
|
||||||
, encoding: null
|
encoding:null
|
||||||
}, function(err, res, body) {
|
}, function(err, res, body) {
|
||||||
var parsed;
|
var parsed;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
/*!
|
||||||
|
* letiny
|
||||||
|
* Copyright(c) 2015 Anatol Sommer <anatol@anatol.at>
|
||||||
|
* Some code used from https://github.com/letsencrypt/boulder/tree/master/test/js
|
||||||
|
* MPL 2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
exports.Acme = require('./acme-client');
|
||||||
|
exports.registerNewAccount = require('./register-new-account');
|
||||||
|
exports.getCertificate = require('./get-certificate');
|
||||||
|
exports.getCert=function (options, cb) {
|
||||||
|
exports.registerNewAccount(options, function () {
|
||||||
|
exports.getCertificate(options, cb);
|
||||||
|
});
|
||||||
|
};
|
|
@ -1,12 +1,12 @@
|
||||||
/*!
|
/*!
|
||||||
* letiny-core
|
* letiny-core
|
||||||
* Copyright(c) 2015 AJ ONeal <coolaj86@gmail.com> https://coolaj86.com
|
* Copyright(c) 2015 AJ ONeal <aj@daplie.com> https://daplie.com
|
||||||
* Apache-2.0 OR MIT (and hence also MPL 2.0)
|
* Apache-2.0 OR MIT (and hence also MPL 2.0)
|
||||||
*/
|
*/
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
module.exports.create = function (deps) {
|
module.exports.create = function (deps) {
|
||||||
var acmeRequest = deps.acmeRequest;
|
var request = deps.request;
|
||||||
var knownUrls = deps.LeCore.knownEndpoints;
|
var knownUrls = deps.LeCore.knownEndpoints;
|
||||||
|
|
||||||
function getAcmeUrls(acmeDiscoveryUrl, cb) {
|
function getAcmeUrls(acmeDiscoveryUrl, cb) {
|
||||||
|
@ -15,7 +15,7 @@ module.exports.create = function (deps) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO check response header on request for cache time
|
// TODO check response header on request for cache time
|
||||||
return acmeRequest.create()({
|
return request({
|
||||||
url: acmeDiscoveryUrl
|
url: acmeDiscoveryUrl
|
||||||
, encoding: 'utf8'
|
, encoding: 'utf8'
|
||||||
}, function (err, resp) {
|
}, function (err, resp) {
|
||||||
|
@ -30,15 +30,18 @@ module.exports.create = function (deps) {
|
||||||
try {
|
try {
|
||||||
data = JSON.parse(data);
|
data = JSON.parse(data);
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
e.raw = data;
|
err.raw = data;
|
||||||
e.url = acmeDiscoveryUrl;
|
err.stack += '\n' + data;
|
||||||
e.stack += '\n\nresponse data:\n'
|
|
||||||
+ data + '\n\nacmeDiscoveryUrl:' + acmeDiscoveryUrl;
|
|
||||||
cb(e);
|
cb(e);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (4 !== Object.keys(data).length) {
|
||||||
|
console.warn("This Let's Encrypt / ACME server has been updated with urls that this client doesn't understand");
|
||||||
|
console.warn(data);
|
||||||
|
}
|
||||||
|
|
||||||
if (!knownUrls.every(function (url) {
|
if (!knownUrls.every(function (url) {
|
||||||
return data[url];
|
return data[url];
|
||||||
})) {
|
})) {
|
||||||
|
@ -51,7 +54,6 @@ module.exports.create = function (deps) {
|
||||||
, newCert: data['new-cert']
|
, newCert: data['new-cert']
|
||||||
, newReg: data['new-reg']
|
, newReg: data['new-reg']
|
||||||
, revokeCert: data['revoke-cert']
|
, revokeCert: data['revoke-cert']
|
||||||
, keyChange: data['key-change']
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,14 +17,8 @@ function _toStandardBase64(str) {
|
||||||
return b64;
|
return b64;
|
||||||
}
|
}
|
||||||
|
|
||||||
function certBufferToPem(cert) {
|
|
||||||
cert = _toStandardBase64(cert.toString('base64'));
|
|
||||||
cert = cert.match(/.{1,64}/g).join('\r\n');
|
|
||||||
return '-----BEGIN CERTIFICATE-----\r\n'+cert+'\r\n-----END CERTIFICATE-----\r\n';
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports.create = function (deps) {
|
module.exports.create = function (deps) {
|
||||||
var acmeRequest = deps.acmeRequest;
|
var request=deps.request;
|
||||||
var Acme = deps.Acme;
|
var Acme = deps.Acme;
|
||||||
var RSA = deps.RSA;
|
var RSA = deps.RSA;
|
||||||
|
|
||||||
|
@ -193,7 +187,7 @@ module.exports.create = function (deps) {
|
||||||
|
|
||||||
if (authz.status==='pending') {
|
if (authz.status==='pending') {
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
acmeRequest.create()({
|
request({
|
||||||
method: 'GET'
|
method: 'GET'
|
||||||
, url: state.authorizationUrl
|
, url: state.authorizationUrl
|
||||||
}, function(err, res, body) {
|
}, function(err, res, body) {
|
||||||
|
@ -278,7 +272,7 @@ module.exports.create = function (deps) {
|
||||||
|
|
||||||
state.certificate=body;
|
state.certificate=body;
|
||||||
certUrl=res.headers.location;
|
certUrl=res.headers.location;
|
||||||
acmeRequest.create()({
|
request({
|
||||||
method: 'GET'
|
method: 'GET'
|
||||||
, url: certUrl
|
, url: certUrl
|
||||||
, encoding: null
|
, encoding: null
|
||||||
|
@ -310,7 +304,7 @@ module.exports.create = function (deps) {
|
||||||
|
|
||||||
function downloadIssuerCert(links) {
|
function downloadIssuerCert(links) {
|
||||||
log('Requesting issuer certificate...');
|
log('Requesting issuer certificate...');
|
||||||
acmeRequest.create()({
|
request({
|
||||||
method: 'GET'
|
method: 'GET'
|
||||||
, url: links.up
|
, url: links.up
|
||||||
, encoding: null
|
, encoding: null
|
||||||
|
@ -327,7 +321,7 @@ module.exports.create = function (deps) {
|
||||||
return handleErr(err, 'Failed to fetch issuer certificate');
|
return handleErr(err, 'Failed to fetch issuer certificate');
|
||||||
}
|
}
|
||||||
|
|
||||||
state.chainPem = certBufferToPem(body);
|
state.chainPem=certBufferToPem(body);
|
||||||
log('Requesting issuer certificate: done');
|
log('Requesting issuer certificate: done');
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
@ -408,5 +402,11 @@ module.exports.create = function (deps) {
|
||||||
nextDomain();
|
nextDomain();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function certBufferToPem(cert) {
|
||||||
|
cert=_toStandardBase64(cert.toString('base64'));
|
||||||
|
cert=cert.match(/.{1,64}/g).join('\r\n');
|
||||||
|
return '-----BEGIN CERTIFICATE-----\r\n'+cert+'\r\n-----END CERTIFICATE-----\r\n';
|
||||||
|
}
|
||||||
|
|
||||||
return getCert;
|
return getCert;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,72 +0,0 @@
|
||||||
/*!
|
|
||||||
* le-acme-core
|
|
||||||
* Author: Kelly Johnson
|
|
||||||
* Copyright 2017
|
|
||||||
* Apache-2.0 OR MIT (and hence also MPL 2.0)
|
|
||||||
*/
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
const request = require('request');
|
|
||||||
const pkgJSON = require('../package.json');
|
|
||||||
const version = pkgJSON.version;
|
|
||||||
const os = require('os');
|
|
||||||
|
|
||||||
const uaDefaults = {
|
|
||||||
pkg: `Greenlock/${version}`
|
|
||||||
, os: ` (${os.type()}; ${process.arch} ${os.platform()} ${os.release()})`
|
|
||||||
, node: ` Node.js/${process.version}`
|
|
||||||
, user: ''
|
|
||||||
}
|
|
||||||
|
|
||||||
let currentUAProps;
|
|
||||||
|
|
||||||
function getUaString() {
|
|
||||||
let userAgent = '';
|
|
||||||
for (let key in currentUAProps) {
|
|
||||||
userAgent += currentUAProps[key];
|
|
||||||
}
|
|
||||||
return userAgent.trim();
|
|
||||||
}
|
|
||||||
|
|
||||||
function getRequest() {
|
|
||||||
return request.defaults({
|
|
||||||
headers: {
|
|
||||||
'User-Agent': getUaString()
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function resetUa() {
|
|
||||||
currentUAProps = {};
|
|
||||||
for (let key in uaDefaults) {
|
|
||||||
currentUAProps[key] = uaDefaults[key];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function addUaString(string) {
|
|
||||||
currentUAProps.user += ` ${string}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
function omitUaProperties(opts) {
|
|
||||||
if (opts.all) {
|
|
||||||
currentUAProps = {};
|
|
||||||
} else {
|
|
||||||
for (let key in opts) {
|
|
||||||
currentUAProps[key] = '';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set our UA to begin with
|
|
||||||
resetUa();
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
create: function create() {
|
|
||||||
// get deps and modify here if need be
|
|
||||||
return getRequest();
|
|
||||||
}
|
|
||||||
, addUaString: addUaString
|
|
||||||
, omitUaProperties: omitUaProperties
|
|
||||||
, resetUa: resetUa
|
|
||||||
, getUaString: getUaString
|
|
||||||
};
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
/*!
|
||||||
|
* letiny-core
|
||||||
|
* Copyright(c) 2015 AJ ONeal <aj@daplie.com> https://daplie.com
|
||||||
|
* Apache-2.0 OR MIT (and hence also MPL 2.0)
|
||||||
|
*/
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var request = require('request');
|
||||||
|
var RSA = require('rsa-compat').RSA;
|
||||||
|
|
||||||
|
module.exports.request = request;
|
||||||
|
module.exports.RSA = RSA;
|
|
@ -8,7 +8,7 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
module.exports.create = function (deps) {
|
module.exports.create = function (deps) {
|
||||||
var NOOP=function () {}, log=NOOP;
|
var NOOP=function () {}, log=NOOP;
|
||||||
var acmeRequest = deps.acmeRequest;
|
var request=deps.request;
|
||||||
var RSA = deps.RSA;
|
var RSA = deps.RSA;
|
||||||
var Acme = deps.Acme;
|
var Acme = deps.Acme;
|
||||||
|
|
||||||
|
@ -24,11 +24,7 @@ module.exports.create = function (deps) {
|
||||||
function getTerms(err, res) {
|
function getTerms(err, res) {
|
||||||
var links;
|
var links;
|
||||||
|
|
||||||
if (err) {
|
if (err || Math.floor(res.statusCode/100)!==2) {
|
||||||
return handleErr(err, 'Registration request failed: ' + err.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Math.floor(res.statusCode/100)!==2) {
|
|
||||||
return handleErr(err, 'Registration request failed: ' + res.body.toString('utf8'));
|
return handleErr(err, 'Registration request failed: ' + res.body.toString('utf8'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,7 +51,7 @@ module.exports.create = function (deps) {
|
||||||
state.agreeTerms = agree;
|
state.agreeTerms = agree;
|
||||||
state.termsUrl=links['terms-of-service'];
|
state.termsUrl=links['terms-of-service'];
|
||||||
log(state.termsUrl);
|
log(state.termsUrl);
|
||||||
acmeRequest.create().get(state.termsUrl, getAgreement);
|
request.get(state.termsUrl, getAgreement);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
cb(null, null);
|
cb(null, null);
|
||||||
|
|
57
node.js
57
node.js
|
@ -1,53 +1,30 @@
|
||||||
/*!
|
/*!
|
||||||
* letiny-core
|
* letiny-core
|
||||||
* Copyright(c) 2015 AJ ONeal <coolaj86@gmail.com> https://coolaj86.com
|
* Copyright(c) 2015 AJ ONeal <aj@daplie.com> https://daplie.com
|
||||||
* Apache-2.0 OR MIT (and hence also MPL 2.0)
|
* Apache-2.0 OR MIT (and hence also MPL 2.0)
|
||||||
*/
|
*/
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var defaults = {
|
|
||||||
productionServerUrl: 'https://acme-v01.api.letsencrypt.org/directory'
|
|
||||||
, stagingServerUrl: 'https://acme-staging.api.letsencrypt.org/directory'
|
|
||||||
, acmeChallengePrefix: '/.well-known/acme-challenge/'
|
|
||||||
, knownEndpoints: [ 'new-authz', 'new-cert', 'new-reg', 'revoke-cert', 'key-change' ]
|
|
||||||
, challengeType: 'http-01'
|
|
||||||
, rsaKeySize: 2048
|
|
||||||
};
|
|
||||||
|
|
||||||
function create(deps) {
|
function create(deps) {
|
||||||
deps = deps || {};
|
var LeCore = {};
|
||||||
deps.LeCore = {};
|
|
||||||
|
|
||||||
Object.keys(defaults).forEach(function (key) {
|
// Note: these are NOT DEFAULTS
|
||||||
deps[key] = defaults[key];
|
// They are de facto standards that you may
|
||||||
deps.LeCore[key] = defaults[key];
|
// or may not use in your implementation
|
||||||
});
|
LeCore.productionServerUrl = "https://acme-v01.api.letsencrypt.org/directory";
|
||||||
|
LeCore.stagingServerUrl = "https://acme-staging.api.letsencrypt.org/directory";
|
||||||
|
LeCore.acmeChallengePrefix = "/.well-known/acme-challenge/";
|
||||||
|
LeCore.knownEndpoints = [ 'new-authz', 'new-cert', 'new-reg', 'revoke-cert' ];
|
||||||
|
|
||||||
deps.RSA = deps.RSA || require('rsa-compat').RSA;
|
deps.LeCore = LeCore;
|
||||||
deps.acmeRequest = require('./lib/le-acme-request');
|
deps.Acme = LeCore.Acme = require('./lib/acme-client').create(deps);
|
||||||
deps.Acme = require('./lib/acme-client').create(deps);
|
|
||||||
|
|
||||||
deps.LeCore.Acme = deps.Acme;
|
LeCore.getAcmeUrls = require('./lib/get-acme-urls').create(deps);
|
||||||
deps.LeCore.acmeRequest = deps.acmeRequest;
|
LeCore.registerNewAccount = require('./lib/register-new-account').create(deps);
|
||||||
deps.LeCore.getAcmeUrls = require('./lib/get-acme-urls').create(deps);
|
LeCore.getCertificate = require('./lib/get-certificate').create(deps);
|
||||||
deps.LeCore.registerNewAccount = require('./lib/register-new-account').create(deps);
|
|
||||||
deps.LeCore.getCertificate = require('./lib/get-certificate').create(deps);
|
|
||||||
deps.LeCore.getOptions = function () {
|
|
||||||
var defs = {};
|
|
||||||
|
|
||||||
Object.keys(defaults).forEach(function (key) {
|
return LeCore;
|
||||||
defs[key] = defs[deps] || defaults[key];
|
|
||||||
});
|
|
||||||
|
|
||||||
return defs;
|
|
||||||
};
|
|
||||||
|
|
||||||
return deps.LeCore;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO make this the official usage
|
module.exports = create(require('./lib/node'));
|
||||||
module.exports.ACME = { create: create };
|
module.exports.create = create;
|
||||||
|
|
||||||
Object.keys(defaults).forEach(function (key) {
|
|
||||||
module.exports.ACME[key] = defaults[key];
|
|
||||||
});
|
|
||||||
|
|
30
package.json
30
package.json
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "le-acme-core",
|
"name": "letiny-core",
|
||||||
"version": "2.1.4",
|
"version": "2.0.3",
|
||||||
"description": "A framework for building letsencrypt clients, forked from letiny",
|
"description": "A framework for building letsencrypt clients, forked from letiny",
|
||||||
"main": "node.js",
|
"main": "node.js",
|
||||||
"browser": "browser.js",
|
"browser": "browser.js",
|
||||||
|
@ -8,34 +8,36 @@
|
||||||
"example": "example",
|
"example": "example",
|
||||||
"test": "test"
|
"test": "test"
|
||||||
},
|
},
|
||||||
|
"scripts": {
|
||||||
|
"test": "node example/letsencrypt.js"
|
||||||
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "git+https://git.coolaj86.com/coolaj86/le-acme-core.js.git"
|
"url": "git+https://github.com/Daplie/letiny-core.git"
|
||||||
},
|
},
|
||||||
"license": "MPL-2.0",
|
"license": "MPL-2.0",
|
||||||
"bugs": {
|
"bugs": {
|
||||||
"url": "https://git.coolaj86.com/coolaj86/le-acme-core.js/issues"
|
"url": "https://github.com/Daplie/letiny-core/issues"
|
||||||
},
|
},
|
||||||
"homepage": "https://git.coolaj86.com/coolaj86/le-acme-core.js#readme",
|
"homepage": "https://github.com/Daplie/letiny-core#readme",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"le-acme",
|
|
||||||
"le-acme-",
|
|
||||||
"tiny",
|
"tiny",
|
||||||
"acme",
|
"acme",
|
||||||
"letsencrypt",
|
"letsencrypt",
|
||||||
"client",
|
"client",
|
||||||
"pem",
|
"pem",
|
||||||
"jwk",
|
|
||||||
"pfx"
|
"pfx"
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"request": "^2.74.0",
|
"node-forge": "^0.6.38",
|
||||||
"rsa-compat": "^1.3.2"
|
"request": "^2.55.0",
|
||||||
|
"rsa-compat": "^1.2.3"
|
||||||
|
},
|
||||||
|
"optionalDependencies": {
|
||||||
|
"ursa": "^0.9.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"better-assert": "^1.0.2",
|
"mocha": "^2.3.3",
|
||||||
"chai": "^3.5.0",
|
"better-assert": "^1.0.2"
|
||||||
"chai-string": "^1.3.0",
|
|
||||||
"request-debug": "^0.2.0"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,74 +0,0 @@
|
||||||
/*!
|
|
||||||
* le-acme-core
|
|
||||||
* Author: Kelly Johnson
|
|
||||||
* Copyright 2017
|
|
||||||
* Apache-2.0 OR MIT (and hence also MPL 2.0)
|
|
||||||
*/
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
const acmeRequest = require('../lib/le-acme-request');
|
|
||||||
const debugRequest = require('request-debug');
|
|
||||||
const chai = require('chai');
|
|
||||||
chai.use(require('chai-string'));
|
|
||||||
const expect = chai.expect;
|
|
||||||
|
|
||||||
const productId = 'Greenlock';
|
|
||||||
const UA = 'User-Agent';
|
|
||||||
|
|
||||||
function checkRequest(req, done, tester) {
|
|
||||||
debugRequest(req, function dbg(type, data, r) {
|
|
||||||
if (type !== 'request') return; // Only interested in the request
|
|
||||||
expect(data.headers).to.have.property(UA);
|
|
||||||
let uaString = data.headers[UA];
|
|
||||||
tester(uaString);
|
|
||||||
req.stopDebugging();
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
req('http://www.google.com', function (error, response, body) {
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
describe('le-acme-request', function () {
|
|
||||||
|
|
||||||
beforeEach(function () {
|
|
||||||
acmeRequest.resetUa();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should build User-Agent string', function () {
|
|
||||||
let uaString = acmeRequest.getUaString();
|
|
||||||
expect(uaString).to.startsWith(productId);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should have proper User-Agent in request', function (done) {
|
|
||||||
let request = acmeRequest.create();
|
|
||||||
checkRequest(request, done, function (uaString) {
|
|
||||||
expect(uaString).to.startsWith(productId);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should add custom string to User Agent', function (done) {
|
|
||||||
let testStr = 'check it';
|
|
||||||
acmeRequest.addUaString(testStr);
|
|
||||||
let request = acmeRequest.create();
|
|
||||||
checkRequest(request, done, function (uaString) {
|
|
||||||
// Added space to ensure str was properly appended
|
|
||||||
expect(uaString).to.endsWith(` ${testStr}`);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should remove all items from User Agent', function (done) {
|
|
||||||
acmeRequest.omitUaProperties({all: true});
|
|
||||||
let request = acmeRequest.create();
|
|
||||||
checkRequest(request, done, function (uaString) {
|
|
||||||
expect(uaString).to.be.empty;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should remove one item from User Agent', function (done) {
|
|
||||||
acmeRequest.omitUaProperties({pkg: true});
|
|
||||||
const request = acmeRequest.create();
|
|
||||||
checkRequest(request, done, function (uaString) {
|
|
||||||
expect(uaString).to.not.have.string(productId);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,5 +1,5 @@
|
||||||
var forge=require('node-forge'), assert=require('better-assert'), fs=require('fs'),
|
var forge=require('node-forge'), assert=require('better-assert'), fs=require('fs'),
|
||||||
letiny=require('../'), config=require('./config.json'),
|
letiny=require('../lib/client'), config=require('./config.json'),
|
||||||
res, newReg='https://acme-staging.api.letsencrypt.org/acme/new-reg';
|
res, newReg='https://acme-staging.api.letsencrypt.org/acme/new-reg';
|
||||||
|
|
||||||
config.newReg=config.newReg || newReg;
|
config.newReg=config.newReg || newReg;
|
||||||
|
|
Loading…
Reference in New Issue