From 94bea192db91d84be5a35d713212b6e27b705737 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Tue, 15 Dec 2015 20:18:01 -0800 Subject: [PATCH 01/13] Update README.md --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index fa9b98f..ee466f0 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,8 @@ You will follow these steps to obtain certificates: * implement a method to get the challenge token as `getChallenge` * implement a method to remove the challenge token as `removeChallenge` +#### Register Account & Domain + ```javascript 'use strict'; @@ -85,6 +87,8 @@ LeCore.getAcmeUrls( ); ``` +#### Run a Server on 80, 443, and 5001 (https/tls) + That will fail unless you have a webserver running on 80 and 443 (or 5001) to respond to `/.well-known/acme-challenge/xxxxxxxx` with the proper token @@ -107,6 +111,8 @@ http.createServer() Finally, you need an implementation of `challengeStore`: +#### Put some storage in place + ```javascript var challengeCache = {}; var challengeStore = { From 04160710e970abfeb786dba2670f9337af7d4ae4 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Tue, 15 Dec 2015 20:21:03 -0800 Subject: [PATCH 02/13] add AUTHORS --- AUTHORS | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 AUTHORS diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..996cc58 --- /dev/null +++ b/AUTHORS @@ -0,0 +1,3 @@ +ISRG +Anatol Sommer +AJ ONeal (https://daplie.com/) From b430cbce7a3ab7ee0ce3695ad838fdc60e10edf7 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Tue, 15 Dec 2015 20:22:25 -0800 Subject: [PATCH 03/13] make npm happy --- package.json | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index e99ae5f..e198b35 100644 --- a/package.json +++ b/package.json @@ -1,18 +1,25 @@ { "name": "letiny-core", "version": "1.0.0", - "description": "A framework for building letsencrypt clients, forked from `letiny`", - "authors": [ - "Anatol Sommer ", - "AJ ONeal " - ], + "description": "A framework for building letsencrypt clients, forked from letiny", "main": "node.js", "browser": "browser.js", - "license": "MPL-2.0", + "directories": { + "example": "example", + "test": "test" + }, + "scripts": { + "test": "node example/letsencrypt.js" + }, "repository": { "type": "git", - "url": "https://github.com/Daplie/letiny-core.git" + "url": "git+https://github.com/Daplie/letiny-core.git" }, + "license": "MPL-2.0", + "bugs": { + "url": "https://github.com/Daplie/letiny-core/issues" + }, + "homepage": "https://github.com/Daplie/letiny-core#readme", "keywords": [ "tiny", "acme", From bcad51d046924c0ed480f08b891ec0c30ff04259 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Tue, 15 Dec 2015 20:32:40 -0800 Subject: [PATCH 04/13] examples in README.md --- README.md | 155 +++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 114 insertions(+), 41 deletions(-) diff --git a/README.md b/README.md index ee466f0..7289847 100644 --- a/README.md +++ b/README.md @@ -41,50 +41,77 @@ You will follow these steps to obtain certificates: var LeCore = require('letiny-core'); -var accountPrivateKeyPem = '...'; // leCrypto.generateRsaKeypair(bitLen, exp, cb) -var domainPrivateKeyPem = '...'; // (same) -var challengeStore = { /*get, set, remove*/ }; // see below for example +var email = 'user@example.com'; // CHANGE TO YOUR EMAIL +var domains = 'example.com'; // CHANGE TO YOUR DOMAIN +var acmeDiscoveryUrl = LeCore.stagingServerUrl; // CHANGE to production, when ready -LeCore.getAcmeUrls( - LeCore.stagingServerUrl // or choose LeCore.productionServerUrl -, function (err, urls) { +var challengeStore = require('./challenge-store'); +var certStore = require('./cert-store'); +var serve = require('./serve'); +var closer; +var accountPrivateKeyPem = null; +var domainPrivateKeyPem = null; +var acmeUrls = null; + +LeCore.leCrypto.generateRsaKeypair(2048, 65537, function (err, pems) { + // ... + LeCore.getAcmeUrls(acmeDiscoveryUrl, function (err, urls) { + // ... + runDemo(); + }); +}); + +function runDemo() { LeCore.registerNewAccount( - { newRegUrl: urls.newReg - , email: 'user@example.com' - , accountPrivateKeyPem: accountPrivateKeyPem - , agreeToTerms: function (tosUrl, done) { - // agree to these exact terms - done(null, tosUrl); + { newRegUrl: acmeUrls.newReg + , email: email + , accountPrivateKeyPem: accountPrivateKeyPem + , agreeToTerms: function (tosUrl, done) { + + // agree to the exact version of these terms + done(null, tosUrl); + } } - } - , function (err, regr) { + , function (err, regr) { - // Note: you should save the registration - // record to disk (or db) + console.log('Registering New Certificate'); + LeCore.getCertificate( + { newAuthzUrl: acmeUrls.newAuthz + , newCertUrl: acmeUrls.newCert - LeCore.getCertificate( - { newAuthzUrl: urls.newAuthz - , newCertUrl: urls.newCert + , domainPrivateKeyPem: domainPrivateKeyPem + , accountPrivateKeyPem: accountPrivateKeyPem + , domains: domains - , domainPrivateKeyPem: domainPrivateKeyPem - , accountPrivateKeyPem: accountPrivateKeyPem + , setChallenge: challengeStore.set + , removeChallenge: challengeStore.remove + } + , function (err, certs) { - , setChallenge: challengeStore.set - , removeChallenge: challengeStore.remove - } - , function (err, certs) { + // Note: you should save certs to disk (or db) + certStore.set(domains[0], certs, function () { - // Note: you should save certs to disk (or db) - - } - ) + // ... - } + }); + + } + ); + } ); +} - } -); +// +// Setup the Server +// +closer = serve.init({ + LeCore: LeCore + // needs a default key and cert chain, anything will do +, httpsOptions: require('localhost.daplie.com-certificates') +, challengeStore: challengeStore +, certStore: certStore +}); ``` #### Run a Server on 80, 443, and 5001 (https/tls) @@ -92,26 +119,57 @@ LeCore.getAcmeUrls( That will fail unless you have a webserver running on 80 and 443 (or 5001) to respond to `/.well-known/acme-challenge/xxxxxxxx` with the proper token -```javascript -var localCerts = require('localhost.daplie.com-certificates'); // needs default certificates -var http = require('http'); -var httsp = require('https'); +**But wait**, there's more! +See [example/serve.js](https://github.com/Daplie/letiny-core/blob/master/example/serve.js) +```javascript +var https = require('https'); +var http = require('http'); + + +var LeCore = deps.LeCore; +var httpsOptions = deps.httpsOptions; +var challengeStore = deps.challengeStore; +var certStore = deps.certStore; + + +// +// Challenge Handler +// function acmeResponder(req, res) { - if (0 !== req.url.indexOf(LeCore.acmeChallengePrefixUrl)) { + if (0 !== req.url.indexOf(LeCore.acmeChallengePrefix)) { res.end('Hello World!'); return; } - LeCore. + var key = req.url.slice(LeCore.acmeChallengePrefix.length); + + challengeStore.get(req.hostname, key, function (err, val) { + res.end(val || 'Error'); + }); } -http.createServer() + +// +// Server +// +https.createServer(httpsOptions, acmeResponder).listen(5001, function () { + console.log('Listening https on', this.address()); +}); +http.createServer(acmeResponder).listen(80, function () { + console.log('Listening http on', this.address()); +}); ``` +#### Put some storage in place + Finally, you need an implementation of `challengeStore`: -#### Put some storage in place +**But wait**, there's more! +See + +* [example/challenge-store.js](https://github.com/Daplie/letiny-core/blob/master/challenge-store.js) +* [example/cert-store.js](https://github.com/Daplie/letiny-core/blob/master/cert-store.js) ```javascript var challengeCache = {}; @@ -128,6 +186,21 @@ var challengeStore = { cb(null); } }; + +var certCache = {}; +var certStore = { + set: function (hostname, certs, cb) { + certCache[hostname] = certs; + cb(null); + } +, get: function (hostname, cb) { + cb(null, certCache[hostname]); + } +, remove: function (hostname, cb) { + delete certCache[hostname]; + cb(null); + } +}; ``` ## API @@ -137,7 +210,7 @@ The Goodies ```javascript { newRegUrl: '...' // no defaults, specify LeCore.nproductionServerUrl -// Accounts +// Accounts LeCore.registerNewAccount(options, cb) // returns (err, acmeUrls={newReg,newAuthz,newCert,revokeCert}) { newRegUrl: '...' // no defaults, specify LeCore.newAuthz From ffb130ec0a596e522090a498d42fd4788fc09363 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Tue, 15 Dec 2015 20:34:16 -0800 Subject: [PATCH 05/13] update --- README.md | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 7289847..aeede0c 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,11 @@ You will follow these steps to obtain certificates: #### Register Account & Domain +**But wait**, there's more! +See [example/letsencrypt.js](https://github.com/Daplie/letiny-core/blob/master/example/letsencrypt.js) + +See + ```javascript 'use strict'; @@ -45,11 +50,6 @@ var email = 'user@example.com'; // CHANGE TO YOUR EMAIL var domains = 'example.com'; // CHANGE TO YOUR DOMAIN var acmeDiscoveryUrl = LeCore.stagingServerUrl; // CHANGE to production, when ready -var challengeStore = require('./challenge-store'); -var certStore = require('./cert-store'); -var serve = require('./serve'); -var closer; - var accountPrivateKeyPem = null; var domainPrivateKeyPem = null; var acmeUrls = null; @@ -101,17 +101,6 @@ function runDemo() { } ); } - -// -// Setup the Server -// -closer = serve.init({ - LeCore: LeCore - // needs a default key and cert chain, anything will do -, httpsOptions: require('localhost.daplie.com-certificates') -, challengeStore: challengeStore -, certStore: certStore -}); ``` #### Run a Server on 80, 443, and 5001 (https/tls) From 550bcc484abd242d0aa800d6f0cbe3d878a8c8f6 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Tue, 15 Dec 2015 20:41:17 -0800 Subject: [PATCH 06/13] it is ready! --- README.md | 45 ++++++++++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index aeede0c..96bfccb 100644 --- a/README.md +++ b/README.md @@ -197,21 +197,28 @@ var certStore = { The Goodies ```javascript - { newRegUrl: '...' // no defaults, specify LeCore.nproductionServerUrl - // Accounts LeCore.registerNewAccount(options, cb) // returns (err, acmeUrls={newReg,newAuthz,newCert,revokeCert}) - { newRegUrl: '...' // no defaults, specify LeCore.newAuthz - , email: '...' // valid email (server checks MX records) - , agreeToTerms: fn (tosUrl, cb) {} // callback to allow user interaction for tosUrl - // cb(err=null, agree=tosUrl) // must specify agree=tosUrl to continue (or falsey to end) - } + { newRegUrl: '' // no defaults, specify acmeUrls.newAuthz + , email: '' // valid email (server checks MX records) + , accountPrivateKeyPem: '' // callback to allow user interaction for tosUrl + , agreeToTerms: fn (tosUrl, cb) {} // must specify agree=tosUrl to continue (or falsey to end) + } // Registration -LeCore.getCertificate(options, cb) +LeCore.getCertificate(options, cb) // returns (err, pems={ key, cert, ca }) - { newAuthzUrl: '...' // no defaults, specify acmeUrls.newAuthz + { newAuthzUrl: '' // specify acmeUrls.newAuthz + , newCertUrl: '' // specify acmeUrls.newCert + + , domainPrivateKeyPem: '' + , accountPrivateKeyPem: '' + , domains: ['example.com'] + + , setChallenge: fn (hostname, key, val, cb) + , removeChallenge: fn (hostname, key, cb) + } ``` Helpers & Stuff @@ -229,10 +236,10 @@ LeCore.knownEndpoints // new-authz, new-cert, new-reg, revok // HTTP Client Helpers LeCore.Acme // Signs requests with JWK - acme = new Acme(lePrivateKey) // privateKey format is abstract - acme.post(url, body, cb) // POST with signature - acme.parseLinks(link) // (internal) parses 'link' header - acme.getNonce(url, cb) // (internal) HEAD request to get 'replay-nonce' strings + acme = new Acme(lePrivateKey) // privateKey format is abstract + acme.post(url, body, cb) // POST with signature + acme.parseLinks(link) // (internal) parses 'link' header + acme.getNonce(url, cb) // (internal) HEAD request to get 'replay-nonce' strings // Note: some of these are not async, // but they will be soon. Don't rely @@ -240,12 +247,12 @@ LeCore.Acme // Signs requests with JWK // Crypto Helpers LeCore.leCrypto - generateRsaKeypair(bitLen, exponent, cb); // returns { privateKeyPem, privateKeyJwk, publicKeyPem, publicKeyMd5 } - thumbprint(lePubKey) // generates public key thumbprint - generateSignature(lePrivKey, bodyBuf, nonce) // generates a signature - privateJwkToPems(jwk) // { n: '...', e: '...', iq: '...', ... } to PEMs - privatePemToJwk // PEM to JWK (see line above) - importPemPrivateKey(privateKeyPem) // (internal) returns abstract private key + generateRsaKeypair(bitLen, exponent, cb); // returns { privateKeyPem, privateKeyJwk, publicKeyPem, publicKeyMd5 } + thumbprint(lePubKey) // generates public key thumbprint + generateSignature(lePrivKey, bodyBuf, nonce) // generates a signature + privateJwkToPems(jwk) // { n: '...', e: '...', iq: '...', ... } to PEMs + privatePemToJwk // PEM to JWK (see line above) + importPemPrivateKey(privateKeyPem) // (internal) returns abstract private key ``` For testing and development, you can also inject the dependencies you want to use: From cadd31eba4fe4952b1b07e91d8346fe79d22a60e Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Tue, 15 Dec 2015 20:41:41 -0800 Subject: [PATCH 07/13] v1.0.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e198b35..37934bd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "letiny-core", - "version": "1.0.0", + "version": "1.0.1", "description": "A framework for building letsencrypt clients, forked from letiny", "main": "node.js", "browser": "browser.js", From 4f74fd90c98c8eea8248c510f48e0cb33086ef17 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Tue, 15 Dec 2015 20:46:47 -0800 Subject: [PATCH 08/13] Update README.md --- README.md | 167 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 86 insertions(+), 81 deletions(-) diff --git a/README.md b/README.md index 96bfccb..267ddb9 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ You probably want one of these pre-built clients instead: * `letiny` (lightweight client) * `letsencrypt-express` (automatic https for express) -## Usage: +## Install & Usage: ```bash npm install --save letiny-core @@ -34,13 +34,96 @@ You will follow these steps to obtain certificates: * implement a method to get the challenge token as `getChallenge` * implement a method to remove the challenge token as `removeChallenge` +## API + +The Goodies + +```javascript +// Accounts +LeCore.registerNewAccount(options, cb) // returns (err, acmeUrls={newReg,newAuthz,newCert,revokeCert}) + + { newRegUrl: '' // no defaults, specify acmeUrls.newAuthz + , email: '' // valid email (server checks MX records) + , accountPrivateKeyPem: '' // callback to allow user interaction for tosUrl + , agreeToTerms: fn (tosUrl, cb) {} // must specify agree=tosUrl to continue (or falsey to end) + } + +// Registration +LeCore.getCertificate(options, cb) // returns (err, pems={ key, cert, ca }) + + { newAuthzUrl: '' // specify acmeUrls.newAuthz + , newCertUrl: '' // specify acmeUrls.newCert + + , domainPrivateKeyPem: '' + , accountPrivateKeyPem: '' + , domains: ['example.com'] + + , setChallenge: fn (hostname, key, val, cb) + , removeChallenge: fn (hostname, key, cb) + } +``` + +Helpers & Stuff + +```javascript +// Constants +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.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 +LeCore.Acme // Signs requests with JWK + acme = new Acme(lePrivateKey) // privateKey format is abstract + acme.post(url, body, cb) // POST with signature + acme.parseLinks(link) // (internal) parses 'link' header + acme.getNonce(url, cb) // (internal) HEAD request to get 'replay-nonce' strings + +// Note: some of these are not async, +// but they will be soon. Don't rely +// on their API yet. + +// Crypto Helpers +LeCore.leCrypto + generateRsaKeypair(bitLen, exponent, cb); // returns { privateKeyPem, privateKeyJwk, publicKeyPem, publicKeyMd5 } + thumbprint(lePubKey) // generates public key thumbprint + generateSignature(lePrivKey, bodyBuf, nonce) // generates a signature + privateJwkToPems(jwk) // { n: '...', e: '...', iq: '...', ... } to PEMs + privatePemToJwk // PEM to JWK (see line above) + importPemPrivateKey(privateKeyPem) // (internal) returns abstract private key +``` + +For testing and development, you can also inject the dependencies you want to use: + +```javascript +LeCore = LeCore.create({ + request: require('request') +, leCrypto: rquire('./lib/letsencrypt-forge') +}); + +// now uses node `request` (could also use jQuery or Angular in the browser) +LeCore.getAcmeUrls(discoveryUrl, function (err, urls) { + console.log(urls); +}); +``` + +## Example + +Below you'll find a stripped-down example. You can see the full example in the example folder. + +* [example/](https://github.com/Daplie/letiny-core/blob/master/example/) + #### Register Account & Domain +This is how you **register an ACME account** and **get an HTTPS certificate** + **But wait**, there's more! See [example/letsencrypt.js](https://github.com/Daplie/letiny-core/blob/master/example/letsencrypt.js) -See - ```javascript 'use strict'; @@ -75,7 +158,6 @@ function runDemo() { } , function (err, regr) { - console.log('Registering New Certificate'); LeCore.getCertificate( { newAuthzUrl: acmeUrls.newAuthz , newCertUrl: acmeUrls.newCert @@ -192,83 +274,6 @@ var certStore = { }; ``` -## API - -The Goodies - -```javascript -// Accounts -LeCore.registerNewAccount(options, cb) // returns (err, acmeUrls={newReg,newAuthz,newCert,revokeCert}) - - { newRegUrl: '' // no defaults, specify acmeUrls.newAuthz - , email: '' // valid email (server checks MX records) - , accountPrivateKeyPem: '' // callback to allow user interaction for tosUrl - , agreeToTerms: fn (tosUrl, cb) {} // must specify agree=tosUrl to continue (or falsey to end) - } - -// Registration -LeCore.getCertificate(options, cb) // returns (err, pems={ key, cert, ca }) - - { newAuthzUrl: '' // specify acmeUrls.newAuthz - , newCertUrl: '' // specify acmeUrls.newCert - - , domainPrivateKeyPem: '' - , accountPrivateKeyPem: '' - , domains: ['example.com'] - - , setChallenge: fn (hostname, key, val, cb) - , removeChallenge: fn (hostname, key, cb) - } -``` - -Helpers & Stuff - -```javascript -// Constants -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.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 -LeCore.Acme // Signs requests with JWK - acme = new Acme(lePrivateKey) // privateKey format is abstract - acme.post(url, body, cb) // POST with signature - acme.parseLinks(link) // (internal) parses 'link' header - acme.getNonce(url, cb) // (internal) HEAD request to get 'replay-nonce' strings - -// Note: some of these are not async, -// but they will be soon. Don't rely -// on their API yet. - -// Crypto Helpers -LeCore.leCrypto - generateRsaKeypair(bitLen, exponent, cb); // returns { privateKeyPem, privateKeyJwk, publicKeyPem, publicKeyMd5 } - thumbprint(lePubKey) // generates public key thumbprint - generateSignature(lePrivKey, bodyBuf, nonce) // generates a signature - privateJwkToPems(jwk) // { n: '...', e: '...', iq: '...', ... } to PEMs - privatePemToJwk // PEM to JWK (see line above) - importPemPrivateKey(privateKeyPem) // (internal) returns abstract private key -``` - -For testing and development, you can also inject the dependencies you want to use: - -```javascript -LeCore = LeCore.create({ - request: require('request') -, leCrypto: rquire('./lib/letsencrypt-forge') -}); - -// now uses node `request` (could also use jQuery or Angular in the browser) -LeCore.getAcmeUrls(discoveryUrl, function (err, urls) { - console.log(urls); -}); -``` - ## Authors * ISRG From b07f079360e0c598c6ea1ab790d22f0382276f37 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Tue, 15 Dec 2015 21:01:40 -0800 Subject: [PATCH 09/13] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 267ddb9..662847e 100644 --- a/README.md +++ b/README.md @@ -14,8 +14,8 @@ Supports all of: This is a library / framework for building letsencrypt clients. You probably want one of these pre-built clients instead: - * `letsencrypt` (100% compatible with the official client) - * `letiny` (lightweight client) + * [`letsencrypt`](https://github.com/Daplie/node-letsencrypt) (compatible with the official client) + * `letiny` (lightweight client cli) * `letsencrypt-express` (automatic https for express) ## Install & Usage: From 77286c8c260d443fe02387ad38f9d6fcc1266429 Mon Sep 17 00:00:00 2001 From: Bryson Hill Date: Tue, 15 Dec 2015 22:03:02 -0800 Subject: [PATCH 10/13] Update README.md Updating Discovery URL and fixing documentation for registerNewAccount --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 662847e..4c53a1c 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ The Goodies ```javascript // Accounts -LeCore.registerNewAccount(options, cb) // returns (err, acmeUrls={newReg,newAuthz,newCert,revokeCert}) +LeCore.registerNewAccount(options, cb) // returns "regr" registration data { newRegUrl: '' // no defaults, specify acmeUrls.newAuthz , email: '' // valid email (server checks MX records) @@ -61,6 +61,9 @@ LeCore.getCertificate(options, cb) // returns (err, pems={ key, cert, , setChallenge: fn (hostname, key, val, cb) , removeChallenge: fn (hostname, key, cb) } + +// Discovery URLs +LeCore.getAcmeUrls(acmeDiscoveryUrl, cb) // returns (err, acmeUrls={newReg,newAuthz,newCert,revokeCert}) ``` Helpers & Stuff From 1d3ecd8fcf640a1c411bf49bd9318e3fda1871eb Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Wed, 16 Dec 2015 00:06:19 -0800 Subject: [PATCH 11/13] Update README.md --- README.md | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/README.md b/README.md index 4c53a1c..7f06832 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,39 @@ You will follow these steps to obtain certificates: * implement a method to get the challenge token as `getChallenge` * implement a method to remove the challenge token as `removeChallenge` +### Demo + +You can see this working for yourself, but you'll need to be on an internet connected computer with a domain. + +Get a temporary domain for testing + +```bash +npm install -g ddns-cli +ddns --random --email user@example.com --agree +``` + +Note: use **YOUR EMAIL** and accept the terms of service (run `ddns --help` to see them). + + + +Install letiny-core and its dependencies. **Note**: it's okay if you're on windows +and `ursa` fails to compile. It'll still work. + +```bash +git clone https://github.com/Daplie/letiny-core.git ~/letiny-core +pushd ~/letiny-core + +npm install +``` + +Run the demo: + +``` +node examples/letsencrypt.js user@example.com example.com +``` + +Note: use **YOUR TEMPORARY DOMAIN** and **YOUR EMAIL**. + ## API The Goodies From abf436b2bb3d1d05728cac121216db4c86b9b62a Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Wed, 16 Dec 2015 00:15:29 -0800 Subject: [PATCH 12/13] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7f06832..9330353 100644 --- a/README.md +++ b/README.md @@ -61,7 +61,7 @@ npm install Run the demo: -``` +```bash node examples/letsencrypt.js user@example.com example.com ``` From d9b5aa5a28e3c865b7cc2ff2ae8cf0757270ab56 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Wed, 16 Dec 2015 00:17:33 -0800 Subject: [PATCH 13/13] but wait, there's more! --- README.md | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 9330353..0aeb614 100644 --- a/README.md +++ b/README.md @@ -157,9 +157,6 @@ Below you'll find a stripped-down example. You can see the full example in the e This is how you **register an ACME account** and **get an HTTPS certificate** -**But wait**, there's more! -See [example/letsencrypt.js](https://github.com/Daplie/letiny-core/blob/master/example/letsencrypt.js) - ```javascript 'use strict'; @@ -221,14 +218,14 @@ function runDemo() { } ``` +**But wait**, there's more! +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) That will fail unless you have a webserver running on 80 and 443 (or 5001) to respond to `/.well-known/acme-challenge/xxxxxxxx` with the proper token -**But wait**, there's more! -See [example/serve.js](https://github.com/Daplie/letiny-core/blob/master/example/serve.js) - ```javascript var https = require('https'); var http = require('http'); @@ -268,16 +265,13 @@ http.createServer(acmeResponder).listen(80, function () { }); ``` +**But wait**, there's more! +See [example/serve.js](https://github.com/Daplie/letiny-core/blob/master/example/serve.js) + #### Put some storage in place Finally, you need an implementation of `challengeStore`: -**But wait**, there's more! -See - -* [example/challenge-store.js](https://github.com/Daplie/letiny-core/blob/master/challenge-store.js) -* [example/cert-store.js](https://github.com/Daplie/letiny-core/blob/master/cert-store.js) - ```javascript var challengeCache = {}; var challengeStore = { @@ -310,6 +304,12 @@ var certStore = { }; ``` +**But wait**, there's more! +See + +* [example/challenge-store.js](https://github.com/Daplie/letiny-core/blob/master/challenge-store.js) +* [example/cert-store.js](https://github.com/Daplie/letiny-core/blob/master/cert-store.js) + ## Authors * ISRG