update
This commit is contained in:
parent
5313edc306
commit
a2c6b6a259
4
dist/smartacme.classes.acmeclient.d.ts
vendored
4
dist/smartacme.classes.acmeclient.d.ts
vendored
@ -186,9 +186,9 @@ export declare class AcmeClient {
|
|||||||
* @param {number} days_valid
|
* @param {number} days_valid
|
||||||
* @return {{resource: string, csr: string, notBefore: string, notAfter: string}}
|
* @return {{resource: string, csr: string, notBefore: string, notAfter: string}}
|
||||||
*/
|
*/
|
||||||
makeCertRequest(csr: any, DAYS_VALID: number): {
|
makeCertRequest(csr: string, DAYS_VALID: number): {
|
||||||
'resource': string;
|
'resource': string;
|
||||||
'csr': string;
|
'csr': any;
|
||||||
'notBefore': string;
|
'notBefore': string;
|
||||||
'notAfter': string;
|
'notAfter': string;
|
||||||
};
|
};
|
||||||
|
280
dist/smartacme.classes.acmeclient.js
vendored
280
dist/smartacme.classes.acmeclient.js
vendored
File diff suppressed because one or more lines are too long
41
dist/smartacme.classes.jwebclient.js
vendored
41
dist/smartacme.classes.jwebclient.js
vendored
File diff suppressed because one or more lines are too long
4
dist/smartacme.classes.smartacme.d.ts
vendored
4
dist/smartacme.classes.smartacme.d.ts
vendored
@ -1,5 +1,9 @@
|
|||||||
import * as acmeclient from './smartacme.classes.acmeclient';
|
import * as acmeclient from './smartacme.classes.acmeclient';
|
||||||
export declare class SmartAcme {
|
export declare class SmartAcme {
|
||||||
|
acmeAccount: AcmeAccount;
|
||||||
acmeClient: acmeclient.AcmeClient;
|
acmeClient: acmeclient.AcmeClient;
|
||||||
constructor(directoryUrlArg?: string);
|
constructor(directoryUrlArg?: string);
|
||||||
|
createAccount(): void;
|
||||||
|
}
|
||||||
|
export declare class AcmeAccount {
|
||||||
}
|
}
|
||||||
|
10
dist/smartacme.classes.smartacme.js
vendored
10
dist/smartacme.classes.smartacme.js
vendored
@ -4,6 +4,14 @@ class SmartAcme {
|
|||||||
constructor(directoryUrlArg = 'https://acme-staging.api.letsencrypt.org/directory') {
|
constructor(directoryUrlArg = 'https://acme-staging.api.letsencrypt.org/directory') {
|
||||||
this.acmeClient = new acmeclient.AcmeClient(directoryUrlArg);
|
this.acmeClient = new acmeclient.AcmeClient(directoryUrlArg);
|
||||||
}
|
}
|
||||||
|
createAccount() {
|
||||||
|
this.acmeClient.createAccount('test@bleu.de', (answer) => {
|
||||||
|
console.log(answer);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
exports.SmartAcme = SmartAcme;
|
exports.SmartAcme = SmartAcme;
|
||||||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRhY21lLmNsYXNzZXMuc21hcnRhY21lLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvc21hcnRhY21lLmNsYXNzZXMuc21hcnRhY21lLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFDQSw2REFBNEQ7QUFFNUQ7SUFFSSxZQUFZLGtCQUEwQixvREFBb0Q7UUFDdEYsSUFBSSxDQUFDLFVBQVUsR0FBRyxJQUFJLFVBQVUsQ0FBQyxVQUFVLENBQUMsZUFBZSxDQUFDLENBQUE7SUFDaEUsQ0FBQztDQUNKO0FBTEQsOEJBS0MifQ==
|
class AcmeAccount {
|
||||||
|
}
|
||||||
|
exports.AcmeAccount = AcmeAccount;
|
||||||
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRhY21lLmNsYXNzZXMuc21hcnRhY21lLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvc21hcnRhY21lLmNsYXNzZXMuc21hcnRhY21lLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFDQSw2REFBNEQ7QUFFNUQ7SUFHSSxZQUFZLGtCQUEwQixvREFBb0Q7UUFDdEYsSUFBSSxDQUFDLFVBQVUsR0FBRyxJQUFJLFVBQVUsQ0FBQyxVQUFVLENBQUMsZUFBZSxDQUFDLENBQUE7SUFDaEUsQ0FBQztJQUVELGFBQWE7UUFDVCxJQUFJLENBQUMsVUFBVSxDQUFDLGFBQWEsQ0FBQyxjQUFjLEVBQUMsQ0FBQyxNQUFNO1lBQ2hELE9BQU8sQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUE7UUFDdkIsQ0FBQyxDQUFDLENBQUE7SUFDTixDQUFDO0NBQ0o7QUFaRCw4QkFZQztBQUVEO0NBRUM7QUFGRCxrQ0FFQyJ9
|
3
dist/smartacme.plugins.d.ts
vendored
3
dist/smartacme.plugins.d.ts
vendored
@ -1,3 +1,4 @@
|
|||||||
import 'typings-global';
|
import 'typings-global';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
export { path };
|
import * as smartstring from 'smartstring';
|
||||||
|
export { path, smartstring };
|
||||||
|
4
dist/smartacme.plugins.js
vendored
4
dist/smartacme.plugins.js
vendored
@ -2,4 +2,6 @@
|
|||||||
require("typings-global");
|
require("typings-global");
|
||||||
const path = require("path");
|
const path = require("path");
|
||||||
exports.path = path;
|
exports.path = path;
|
||||||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRhY21lLnBsdWdpbnMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9zbWFydGFjbWUucGx1Z2lucy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsMEJBQXVCO0FBQ3ZCLDZCQUE0QjtBQUd4QixvQkFBSSJ9
|
const smartstring = require("smartstring");
|
||||||
|
exports.smartstring = smartstring;
|
||||||
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRhY21lLnBsdWdpbnMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9zbWFydGFjbWUucGx1Z2lucy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsMEJBQXVCO0FBQ3ZCLDZCQUE0QjtBQUl4QixvQkFBSTtBQUhSLDJDQUEwQztBQUl0QyxrQ0FBVyJ9
|
@ -24,10 +24,9 @@
|
|||||||
"homepage": "https://gitlab.com/pushrocks/smartacme#README",
|
"homepage": "https://gitlab.com/pushrocks/smartacme#README",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/base64url": "^2.0.3",
|
"@types/base64url": "^2.0.3",
|
||||||
"base64url": "^2.0.0",
|
|
||||||
"jwa": "^1.1.3",
|
"jwa": "^1.1.3",
|
||||||
"rsa-pem-to-jwk": "^1.1.3",
|
"rsa-pem-to-jwk": "^1.1.3",
|
||||||
"smartstring": "^2.0.19",
|
"smartstring": "^2.0.20",
|
||||||
"typings-global": "^1.0.14"
|
"typings-global": "^1.0.14"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
13
test/test.js
13
test/test.js
@ -1,7 +1,16 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
require("typings-test");
|
require("typings-test");
|
||||||
|
const should = require("should");
|
||||||
|
// import the module to test
|
||||||
|
const smartacme = require("../dist/index");
|
||||||
describe('smartacme', function () {
|
describe('smartacme', function () {
|
||||||
let testAcme;
|
let testAcme;
|
||||||
it('should create a valid instance');
|
it('should create a valid instance', function () {
|
||||||
|
testAcme = new smartacme.SmartAcme();
|
||||||
|
should(testAcme).be.instanceOf(smartacme.SmartAcme);
|
||||||
|
});
|
||||||
|
it('should register a new account', function () {
|
||||||
|
testAcme.createAccount();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbInRlc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLHdCQUFxQjtBQU1yQixRQUFRLENBQUMsV0FBVyxFQUFFO0lBQ2xCLElBQUksUUFBNkIsQ0FBQTtJQUNqQyxFQUFFLENBQUMsZ0NBQWdDLENBQUMsQ0FBQTtBQUN4QyxDQUFDLENBQUMsQ0FBQSJ9
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbInRlc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLHdCQUFxQjtBQUNyQixpQ0FBZ0M7QUFFaEMsNEJBQTRCO0FBQzVCLDJDQUEwQztBQUUxQyxRQUFRLENBQUMsV0FBVyxFQUFFO0lBQ2xCLElBQUksUUFBNkIsQ0FBQTtJQUNqQyxFQUFFLENBQUMsZ0NBQWdDLEVBQUU7UUFDakMsUUFBUSxHQUFHLElBQUksU0FBUyxDQUFDLFNBQVMsRUFBRSxDQUFBO1FBQ3BDLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQyxFQUFFLENBQUMsVUFBVSxDQUFDLFNBQVMsQ0FBQyxTQUFTLENBQUMsQ0FBQTtJQUN2RCxDQUFDLENBQUMsQ0FBQTtJQUNGLEVBQUUsQ0FBQywrQkFBK0IsRUFBRTtRQUNoQyxRQUFRLENBQUMsYUFBYSxFQUFFLENBQUE7SUFDNUIsQ0FBQyxDQUFDLENBQUE7QUFDTixDQUFDLENBQUMsQ0FBQSJ9
|
10
test/test.ts
10
test/test.ts
@ -5,6 +5,12 @@ import * as should from 'should'
|
|||||||
import * as smartacme from '../dist/index'
|
import * as smartacme from '../dist/index'
|
||||||
|
|
||||||
describe('smartacme', function(){
|
describe('smartacme', function(){
|
||||||
let testAcme: smartacme.smartacme
|
let testAcme: smartacme.SmartAcme
|
||||||
it('should create a valid instance')
|
it('should create a valid instance', function(){
|
||||||
|
testAcme = new smartacme.SmartAcme()
|
||||||
|
should(testAcme).be.instanceOf(smartacme.SmartAcme)
|
||||||
|
})
|
||||||
|
it('should register a new account', function() {
|
||||||
|
testAcme.createAccount()
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import * as plugins from './smartacme.plugins'
|
import * as plugins from './smartacme.plugins'
|
||||||
import * as base64url from 'base64url'
|
|
||||||
import * as child_process from 'child_process'
|
import * as child_process from 'child_process'
|
||||||
import * as crypto from 'crypto'
|
import * as crypto from 'crypto'
|
||||||
import * as fs from 'fs'
|
import * as fs from 'fs'
|
||||||
@ -14,7 +13,7 @@ import { JWebClient } from './smartacme.classes.jwebclient'
|
|||||||
* @return {Buffer}
|
* @return {Buffer}
|
||||||
* @throws Exception if object cannot be stringified or contains cycle
|
* @throws Exception if object cannot be stringified or contains cycle
|
||||||
*/
|
*/
|
||||||
let json_to_utf8buffer = function (obj) {
|
let json_to_utf8buffer = (obj) => {
|
||||||
return new Buffer(JSON.stringify(obj), 'utf8')
|
return new Buffer(JSON.stringify(obj), 'utf8')
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -27,7 +26,7 @@ let json_to_utf8buffer = function (obj) {
|
|||||||
*/
|
*/
|
||||||
export class AcmeClient {
|
export class AcmeClient {
|
||||||
clientProfilePubKey: any
|
clientProfilePubKey: any
|
||||||
days_valid: number
|
daysValid: number
|
||||||
defaultRsaKeySize: number
|
defaultRsaKeySize: number
|
||||||
directory: any
|
directory: any
|
||||||
directoryUrl: string
|
directoryUrl: string
|
||||||
@ -37,7 +36,7 @@ export class AcmeClient {
|
|||||||
regLink: string
|
regLink: string
|
||||||
tosLink: string
|
tosLink: string
|
||||||
webroot: string
|
webroot: string
|
||||||
well_known_path: string
|
wellKnownPath: string
|
||||||
withInteraction: boolean
|
withInteraction: boolean
|
||||||
constructor(directoryUrlArg) {
|
constructor(directoryUrlArg) {
|
||||||
/**
|
/**
|
||||||
@ -50,7 +49,7 @@ export class AcmeClient {
|
|||||||
* @desc Validity period in days
|
* @desc Validity period in days
|
||||||
* @default 1
|
* @default 1
|
||||||
*/
|
*/
|
||||||
this.days_valid = 1
|
this.daysValid = 1
|
||||||
/**
|
/**
|
||||||
* @member {number} module:AcmeClient~AcmeClient#defaultRsaKeySize
|
* @member {number} module:AcmeClient~AcmeClient#defaultRsaKeySize
|
||||||
* @desc Key strength in bits
|
* @desc Key strength in bits
|
||||||
@ -104,7 +103,7 @@ export class AcmeClient {
|
|||||||
* @desc Directory structure for challenge data
|
* @desc Directory structure for challenge data
|
||||||
* @default "/.well-known/acme-challenge/"
|
* @default "/.well-known/acme-challenge/"
|
||||||
*/
|
*/
|
||||||
this.well_known_path = '/.well-known/acme-challenge/' // {string}
|
this.wellKnownPath = '/.well-known/acme-challenge/' // {string}
|
||||||
/**
|
/**
|
||||||
* @member {boolean} module:AcmeClient~AcmeClient#withInteraction
|
* @member {boolean} module:AcmeClient~AcmeClient#withInteraction
|
||||||
* @desc Determines if interaction of user is required
|
* @desc Determines if interaction of user is required
|
||||||
@ -154,7 +153,6 @@ export class AcmeClient {
|
|||||||
*/
|
*/
|
||||||
getRegistration(uri, payload, callback) {
|
getRegistration(uri, payload, callback) {
|
||||||
/*jshint -W069 */
|
/*jshint -W069 */
|
||||||
let ctx = this
|
|
||||||
if (!(payload instanceof Object)) {
|
if (!(payload instanceof Object)) {
|
||||||
payload = {} // ensure payload is object
|
payload = {} // ensure payload is object
|
||||||
}
|
}
|
||||||
@ -162,33 +160,28 @@ export class AcmeClient {
|
|||||||
if (typeof callback !== 'function') {
|
if (typeof callback !== 'function') {
|
||||||
callback = this.emptyCallback // ensure callback is function
|
callback = this.emptyCallback // ensure callback is function
|
||||||
}
|
}
|
||||||
this.jWebClient.post(uri, payload, function (ans, res) {
|
this.jWebClient.post(uri, payload,(ans, res) => {
|
||||||
if (ans instanceof Object) {
|
if (ans instanceof Object) {
|
||||||
ctx.clientProfilePubKey = ans.key // cache or reset returned public key
|
this.clientProfilePubKey = ans.key // cache or reset returned public key
|
||||||
if ((res instanceof Object) && (res['headers'] instanceof Object)) {
|
if ((res instanceof Object) && (res['headers'] instanceof Object)) {
|
||||||
let linkStr = res.headers['link']
|
let linkStr = res.headers['link']
|
||||||
if (typeof linkStr === 'string') {
|
if (typeof linkStr === 'string') {
|
||||||
let tosLink = ctx.getTosLink(linkStr)
|
let tosLink = this.getTosLink(linkStr)
|
||||||
if (typeof tosLink === 'string') {
|
if (typeof tosLink === 'string') {
|
||||||
ctx.tosLink = tosLink // cache TOS link
|
this.tosLink = tosLink // cache TOS link
|
||||||
} else {
|
} else {
|
||||||
ctx.tosLink = null // reset TOS link
|
this.tosLink = null // reset TOS link
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ctx.tosLink = null // reset TOS link
|
this.tosLink = null // reset TOS link
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ctx.tosLink = null // reset TOS link
|
this.tosLink = null // reset TOS link
|
||||||
}
|
}
|
||||||
callback(ans, res)
|
callback(ans, res)
|
||||||
} else {
|
} else {
|
||||||
callback(false)
|
callback(false)
|
||||||
}
|
}
|
||||||
// dereference
|
|
||||||
ans = null
|
|
||||||
callback = null
|
|
||||||
ctx = null
|
|
||||||
res = null
|
|
||||||
})
|
})
|
||||||
// dereference
|
// dereference
|
||||||
payload = null
|
payload = null
|
||||||
@ -202,37 +195,25 @@ export class AcmeClient {
|
|||||||
*/
|
*/
|
||||||
authorizeDomain(domain, callback) {
|
authorizeDomain(domain, callback) {
|
||||||
/*jshint -W069 */
|
/*jshint -W069 */
|
||||||
let ctx = this
|
|
||||||
if (typeof callback !== 'function') {
|
if (typeof callback !== 'function') {
|
||||||
callback = this.emptyCallback // ensure callback is function
|
callback = this.emptyCallback // ensure callback is function
|
||||||
}
|
}
|
||||||
this.getProfile(function (profile) {
|
this.getProfile((profile) => {
|
||||||
if (!(profile instanceof Object)) {
|
if (!(profile instanceof Object)) {
|
||||||
callback(false) // no profile returned
|
callback(false) // no profile returned
|
||||||
// dereference
|
|
||||||
callback = null
|
|
||||||
ctx = null
|
|
||||||
} else {
|
} else {
|
||||||
ctx.jWebClient.post(ctx.directory['new-authz'], ctx.makeDomainAuthorizationRequest(domain), function (ans, res) {
|
this.jWebClient.post(this.directory['new-authz'], this.makeDomainAuthorizationRequest(domain), (ans, res) => {
|
||||||
if ((res instanceof Object) && (res['statusCode'] === 403)) { // if unauthorized
|
if ((res instanceof Object) && (res['statusCode'] === 403)) { // if unauthorized
|
||||||
ctx.agreeTos(ctx.tosLink, function (ans_, res_) { // agree to TOS
|
this.agreeTos(this.tosLink, (ans_, res_) => { // agree to TOS
|
||||||
if ( // if TOS were agreed successfully
|
if ( // if TOS were agreed successfully
|
||||||
(res_ instanceof Object)
|
(res_ instanceof Object)
|
||||||
&& (res_['statusCode'] >= 200)
|
&& (res_['statusCode'] >= 200)
|
||||||
&& (res_['statusCode'] <= 400)
|
&& (res_['statusCode'] <= 400)
|
||||||
) {
|
) {
|
||||||
ctx.authorizeDomain(domain, callback) // try authorization again
|
this.authorizeDomain(domain, callback) // try authorization again
|
||||||
} else {
|
} else {
|
||||||
callback(false) // agreement failed
|
callback(false) // agreement failed
|
||||||
}
|
}
|
||||||
// dereference
|
|
||||||
ans = null
|
|
||||||
ans_ = null
|
|
||||||
callback = null
|
|
||||||
ctx = null
|
|
||||||
profile = null
|
|
||||||
res = null
|
|
||||||
res_ = null
|
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
if (
|
if (
|
||||||
@ -242,48 +223,29 @@ export class AcmeClient {
|
|||||||
&& (ans instanceof Object)
|
&& (ans instanceof Object)
|
||||||
) {
|
) {
|
||||||
let poll_uri = res.headers['location'] // status URI for polling
|
let poll_uri = res.headers['location'] // status URI for polling
|
||||||
let challenge = ctx.selectChallenge(ans, 'http-01') // select simple http challenge
|
let challenge = this.selectChallenge(ans, 'http-01') // select simple http challenge
|
||||||
if (challenge instanceof Object) { // desired challenge is in list
|
if (challenge instanceof Object) { // desired challenge is in list
|
||||||
ctx.prepareChallenge(domain, challenge, function () { // prepare all objects and files for challenge
|
this.prepareChallenge(domain, challenge, () => { // prepare all objects and files for challenge
|
||||||
// reset
|
// reset
|
||||||
ans = null
|
ans = null
|
||||||
res = null
|
res = null
|
||||||
// accept challenge
|
// accept challenge
|
||||||
ctx.acceptChallenge(challenge, function (ans, res) {
|
this.acceptChallenge(challenge, (ans, res) => {
|
||||||
if (
|
if (
|
||||||
(res instanceof Object)
|
(res instanceof Object)
|
||||||
&& (res['statusCode'] < 400) // server confirms challenge acceptance
|
&& (res['statusCode'] < 400) // server confirms challenge acceptance
|
||||||
) {
|
) {
|
||||||
ctx.pollUntilValid(poll_uri, callback) // poll status until server states success
|
this.pollUntilValid(poll_uri, callback) // poll status until server states success
|
||||||
} else {
|
} else {
|
||||||
callback(false) // server did not confirm challenge acceptance
|
callback(false) // server did not confirm challenge acceptance
|
||||||
}
|
}
|
||||||
// dereference
|
|
||||||
ans = null
|
|
||||||
callback = null
|
|
||||||
challenge = null
|
|
||||||
ctx = null
|
|
||||||
profile = null
|
|
||||||
res = null
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
callback(false) // desired challenge is not in list
|
callback(false) // desired challenge is not in list
|
||||||
// dereference
|
|
||||||
ans = null
|
|
||||||
callback = null
|
|
||||||
ctx = null
|
|
||||||
profile = null
|
|
||||||
res = null
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
callback(false) // server did not respond with status URI
|
callback(false) // server did not respond with status URI
|
||||||
// dereference
|
|
||||||
ans = null
|
|
||||||
callback = null
|
|
||||||
ctx = null
|
|
||||||
profile = null
|
|
||||||
res = null
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -317,37 +279,22 @@ export class AcmeClient {
|
|||||||
*/
|
*/
|
||||||
pollUntilValid(uri, callback, retry = 1) {
|
pollUntilValid(uri, callback, retry = 1) {
|
||||||
/*jshint -W069 */
|
/*jshint -W069 */
|
||||||
let ctx = this
|
|
||||||
if (typeof callback !== 'function') {
|
if (typeof callback !== 'function') {
|
||||||
callback = this.emptyCallback // ensure callback is function
|
callback = this.emptyCallback // ensure callback is function
|
||||||
}
|
}
|
||||||
if (retry > 128) {
|
if (retry > 128) {
|
||||||
callback(false) // stop if retry value exceeds maximum
|
callback(false) // stop if retry value exceeds maximum
|
||||||
} else {
|
} else {
|
||||||
this.jWebClient.get(uri, function (ans, res) {
|
this.jWebClient.get(uri, (ans, res) => {
|
||||||
if (!(ans instanceof Object)) {
|
if (!(ans instanceof Object)) {
|
||||||
callback(false) // invalid answer
|
callback(false) // invalid answer
|
||||||
// dereference
|
|
||||||
callback = null
|
|
||||||
ctx = null
|
|
||||||
res = null
|
|
||||||
} else {
|
} else {
|
||||||
if (ans['status'] === 'pending') { // still pending
|
if (ans['status'] === 'pending') { // still pending
|
||||||
setTimeout(function () {
|
setTimeout(() => {
|
||||||
ctx.pollUntilValid(uri, callback, retry * 2) // retry
|
this.pollUntilValid(uri, callback, retry * 2) // retry
|
||||||
// dereference
|
|
||||||
ans = null
|
|
||||||
callback = null
|
|
||||||
ctx = null
|
|
||||||
res = null
|
|
||||||
}, retry * 500)
|
}, retry * 500)
|
||||||
} else {
|
} else {
|
||||||
callback(ans, res) // challenge complete
|
callback(ans, res) // challenge complete
|
||||||
// dereference
|
|
||||||
ans = null
|
|
||||||
callback = null
|
|
||||||
ctx = null
|
|
||||||
res = null
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -363,38 +310,22 @@ export class AcmeClient {
|
|||||||
*/
|
*/
|
||||||
pollUntilIssued(uri, callback, retry = 1) {
|
pollUntilIssued(uri, callback, retry = 1) {
|
||||||
/*jshint -W069 */
|
/*jshint -W069 */
|
||||||
let ctx = this
|
|
||||||
if (typeof callback !== 'function') {
|
if (typeof callback !== 'function') {
|
||||||
callback = this.emptyCallback // ensure callback is function
|
callback = this.emptyCallback // ensure callback is function
|
||||||
}
|
}
|
||||||
if (retry > 128) {
|
if (retry > 128) {
|
||||||
callback(false) // stop if retry value exceeds maximum
|
callback(false) // stop if retry value exceeds maximum
|
||||||
} else {
|
} else {
|
||||||
this.jWebClient.get(uri, function (ans, res) {
|
this.jWebClient.get(uri,(ans, res) => {
|
||||||
if ((ans instanceof Buffer) && (ans.length > 0)) {
|
if ((ans instanceof Buffer) && (ans.length > 0)) {
|
||||||
callback(ans) // certificate was returned with answer
|
callback(ans) // certificate was returned with answer
|
||||||
// dereference
|
|
||||||
ans = null
|
|
||||||
callback = null
|
|
||||||
ctx = null
|
|
||||||
res = null
|
|
||||||
} else {
|
} else {
|
||||||
if ((res instanceof Object) && (res['statusCode'] < 400)) { // still pending
|
if ((res instanceof Object) && (res['statusCode'] < 400)) { // still pending
|
||||||
setTimeout(function () {
|
setTimeout(() => {
|
||||||
ctx.pollUntilIssued(uri, callback, retry * 2) // retry
|
this.pollUntilIssued(uri, callback, retry * 2) // retry
|
||||||
// dereference
|
|
||||||
ans = null
|
|
||||||
callback = null
|
|
||||||
ctx = null
|
|
||||||
res = null
|
|
||||||
}, retry * 500)
|
}, retry * 500)
|
||||||
} else {
|
} else {
|
||||||
callback(false) // CSR complete
|
callback(false) // CSR complete
|
||||||
// dereference
|
|
||||||
ans = null
|
|
||||||
callback = null
|
|
||||||
ctx = null
|
|
||||||
res = null
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -409,32 +340,20 @@ export class AcmeClient {
|
|||||||
*/
|
*/
|
||||||
requestSigning(domain, callback) {
|
requestSigning(domain, callback) {
|
||||||
/*jshint -W069 */
|
/*jshint -W069 */
|
||||||
let ctx = this
|
|
||||||
if (typeof callback !== 'function') {
|
if (typeof callback !== 'function') {
|
||||||
callback = this.emptyCallback // ensure callback is function
|
callback = this.emptyCallback // ensure callback is function
|
||||||
}
|
}
|
||||||
fs.readFile(domain + '.csr', function (err, csr) {
|
fs.readFile(domain + '.csr', (err, csrBuffer: Buffer) => {
|
||||||
if (err instanceof Object) { // file system error
|
if (err instanceof Object) { // file system error
|
||||||
if (ctx.jWebClient.verbose) {
|
if (this.jWebClient.verbose) {
|
||||||
console.error('Error : File system error', err['code'], 'while reading key from file')
|
console.error('Error : File system error', err['code'], 'while reading key from file')
|
||||||
}
|
}
|
||||||
callback(false)
|
callback(false)
|
||||||
// dereference
|
|
||||||
callback = null
|
|
||||||
csr = null
|
|
||||||
ctx = null
|
|
||||||
err = null
|
|
||||||
} else {
|
} else {
|
||||||
ctx.jWebClient.post(ctx.directory['new-cert'], ctx.makeCertRequest(csr, ctx.days_valid), function (ans, res) {
|
let csr = csrBuffer.toString()
|
||||||
|
this.jWebClient.post(this.directory['new-cert'], this.makeCertRequest(csr, this.daysValid), (ans, res) => {
|
||||||
if ((ans instanceof Buffer) && (ans.length > 0)) { // answer is buffer
|
if ((ans instanceof Buffer) && (ans.length > 0)) { // answer is buffer
|
||||||
callback(ans) // certificate was returned with answer
|
callback(ans) // certificate was returned with answer
|
||||||
// dereference
|
|
||||||
ans = null
|
|
||||||
callback = null
|
|
||||||
csr = null
|
|
||||||
ctx = null
|
|
||||||
err = null
|
|
||||||
res = null
|
|
||||||
} else {
|
} else {
|
||||||
if (res instanceof Object) {
|
if (res instanceof Object) {
|
||||||
if ((res['statusCode'] < 400) && !ans) { // success response, but no answer was provided
|
if ((res['statusCode'] < 400) && !ans) { // success response, but no answer was provided
|
||||||
@ -442,7 +361,7 @@ export class AcmeClient {
|
|||||||
if (!(headers instanceof Object)) {
|
if (!(headers instanceof Object)) {
|
||||||
headers = {} // ensure headers is object
|
headers = {} // ensure headers is object
|
||||||
}
|
}
|
||||||
ctx.pollUntilIssued(headers['location'], callback) // poll provided status URI
|
this.pollUntilIssued(headers['location'], callback) // poll provided status URI
|
||||||
// dereference
|
// dereference
|
||||||
headers = null
|
headers = null
|
||||||
} else {
|
} else {
|
||||||
@ -451,13 +370,6 @@ export class AcmeClient {
|
|||||||
} else {
|
} else {
|
||||||
callback(false) // invalid response
|
callback(false) // invalid response
|
||||||
}
|
}
|
||||||
// dereference
|
|
||||||
ans = null
|
|
||||||
callback = null
|
|
||||||
csr = null
|
|
||||||
ctx = null
|
|
||||||
err = null
|
|
||||||
res = null
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -471,35 +383,25 @@ export class AcmeClient {
|
|||||||
*/
|
*/
|
||||||
getProfile(callback) {
|
getProfile(callback) {
|
||||||
/*jshint -W069 */
|
/*jshint -W069 */
|
||||||
let ctx = this
|
|
||||||
if (typeof callback !== 'function') {
|
if (typeof callback !== 'function') {
|
||||||
callback = this.emptyCallback // ensure callback is function
|
callback = this.emptyCallback // ensure callback is function
|
||||||
}
|
}
|
||||||
this.getDirectory(function (dir) {
|
this.getDirectory((dir) => {
|
||||||
if (!(dir instanceof Object)) {
|
if (!(dir instanceof Object)) {
|
||||||
callback(false) // server did not respond with directory
|
callback(false) // server did not respond with directory
|
||||||
// dereference
|
|
||||||
callback = null
|
|
||||||
ctx = null
|
|
||||||
} else {
|
} else {
|
||||||
ctx.directory = dir // cache directory
|
this.directory = dir // cache directory
|
||||||
ctx.newRegistration(null, function (ans, res) { // try new registration to get registration link
|
this.newRegistration(null, (ans, res) => { // try new registration to get registration link
|
||||||
if (
|
if (
|
||||||
(res instanceof Object)
|
(res instanceof Object)
|
||||||
&& (res['headers'] instanceof Object)
|
&& (res['headers'] instanceof Object)
|
||||||
&& (typeof res.headers['location'] === 'string')
|
&& (typeof res.headers['location'] === 'string')
|
||||||
) {
|
) {
|
||||||
ctx.regLink = res.headers['location']
|
this.regLink = res.headers['location']
|
||||||
ctx.getRegistration(ctx.regLink, null, callback) // get registration info from link
|
this.getRegistration(this.regLink, null, callback) // get registration info from link
|
||||||
} else {
|
} else {
|
||||||
callback(false) // registration failed
|
callback(false) // registration failed
|
||||||
}
|
}
|
||||||
// dereference
|
|
||||||
ans = null
|
|
||||||
callback = null
|
|
||||||
ctx = null
|
|
||||||
dir = null
|
|
||||||
res = null
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -513,40 +415,31 @@ export class AcmeClient {
|
|||||||
*/
|
*/
|
||||||
createAccount(email, callback) {
|
createAccount(email, callback) {
|
||||||
/*jshint -W069 */
|
/*jshint -W069 */
|
||||||
let ctx = this
|
|
||||||
if (typeof email === 'string') {
|
if (typeof email === 'string') {
|
||||||
if (typeof callback !== 'function') {
|
if (typeof callback !== 'function') {
|
||||||
callback = this.emptyCallback // ensure callback is function
|
callback = this.emptyCallback // ensure callback is function
|
||||||
}
|
}
|
||||||
ctx.newRegistration(
|
this.newRegistration(
|
||||||
{
|
{
|
||||||
contact: [
|
contact: [
|
||||||
'mailto:' + email
|
'mailto:' + email
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
function (ans, res) {
|
(ans, res) => {
|
||||||
if (
|
if (
|
||||||
(res instanceof Object)
|
(res instanceof Object)
|
||||||
&& (res['statusCode'] === 201)
|
&& (res['statusCode'] === 201)
|
||||||
&& (res['headers'] instanceof Object)
|
&& (res['headers'] instanceof Object)
|
||||||
&& (typeof res.headers['location'] === 'string')
|
&& (typeof res.headers['location'] === 'string')
|
||||||
) {
|
) {
|
||||||
ctx.regLink = res.headers['location']
|
this.regLink = res.headers['location']
|
||||||
callback(ctx.regLink) // registration URI
|
callback(this.regLink) // registration URI
|
||||||
} else {
|
} else {
|
||||||
callback(false) // registration failed
|
callback(false) // registration failed
|
||||||
}
|
}
|
||||||
// dereference
|
|
||||||
ans = null
|
|
||||||
callback = null
|
|
||||||
ctx = null
|
|
||||||
res = null
|
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
callback(false) // no email address provided
|
callback(false) // no email address provided
|
||||||
// dereference
|
|
||||||
callback = null
|
|
||||||
ctx = null
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -573,66 +466,47 @@ export class AcmeClient {
|
|||||||
*/
|
*/
|
||||||
requestCertificate(domain, organization, country, callback) {
|
requestCertificate(domain, organization, country, callback) {
|
||||||
/*jshint -W069 */
|
/*jshint -W069 */
|
||||||
let ctx = this
|
|
||||||
if (typeof domain !== 'string') {
|
if (typeof domain !== 'string') {
|
||||||
domain = '' // ensure domain is string
|
domain = '' // ensure domain is string
|
||||||
}
|
}
|
||||||
if (typeof callback !== 'function') {
|
if (typeof callback !== 'function') {
|
||||||
callback = this.emptyCallback // ensure callback is function
|
callback = this.emptyCallback // ensure callback is function
|
||||||
}
|
}
|
||||||
this.getProfile(function (profile) {
|
this.getProfile((profile) => {
|
||||||
let email = ctx.extractEmail(profile) // try to determine email address from profile
|
let email = this.extractEmail(profile) // try to determine email address from profile
|
||||||
if (typeof ctx.emailOverride === 'string') {
|
if (typeof this.emailOverride === 'string') {
|
||||||
email = ctx.emailOverride // override email address if set
|
email = this.emailOverride // override email address if set
|
||||||
} else if (typeof email !== 'string') {
|
} else if (typeof email !== 'string') {
|
||||||
email = ctx.emailDefaultPrefix + '@' + domain // or set default
|
email = this.emailDefaultPrefix + '@' + domain // or set default
|
||||||
}
|
}
|
||||||
let bit = ctx.defaultRsaKeySize
|
let bit = this.defaultRsaKeySize
|
||||||
// sanitize
|
// sanitize
|
||||||
bit = Number(bit)
|
bit = Number(bit)
|
||||||
country = ctx.makeSafeFileName(country)
|
country = this.makeSafeFileName(country)
|
||||||
domain = ctx.makeSafeFileName(domain)
|
domain = this.makeSafeFileName(domain)
|
||||||
email = ctx.makeSafeFileName(email)
|
email = this.makeSafeFileName(email)
|
||||||
organization = ctx.makeSafeFileName(organization)
|
organization = this.makeSafeFileName(organization)
|
||||||
// create key pair
|
// create key pair
|
||||||
ctx.createKeyPair(bit, country, organization, domain, email, function (e) { // create key pair
|
this.createKeyPair(bit, country, organization, domain, email, (e) => { // create key pair
|
||||||
if (!e) {
|
if (!e) {
|
||||||
ctx.requestSigning(domain, function (cert) { // send CSR
|
this.requestSigning(domain, (cert) => { // send CSR
|
||||||
if ((cert instanceof Buffer) || (typeof cert === 'string')) { // valid certificate data
|
if ((cert instanceof Buffer) || (typeof cert === 'string')) { // valid certificate data
|
||||||
fs.writeFile(domain + '.der', cert, function (err) { // sanitize domain name for file path
|
fs.writeFile(domain + '.der', cert, (err) => { // sanitize domain name for file path
|
||||||
if (err instanceof Object) { // file system error
|
if (err instanceof Object) { // file system error
|
||||||
if (ctx.jWebClient.verbose) {
|
if (this.jWebClient.verbose) {
|
||||||
console.error('Error : File system error', err['code'], 'while writing certificate to file')
|
console.error('Error : File system error', err['code'], 'while writing certificate to file')
|
||||||
}
|
}
|
||||||
callback(false)
|
callback(false)
|
||||||
} else {
|
} else {
|
||||||
callback(true) // CSR complete and certificate written to file system
|
callback(true) // CSR complete and certificate written to file system
|
||||||
}
|
}
|
||||||
// dereference
|
|
||||||
callback = null
|
|
||||||
cert = null
|
|
||||||
ctx = null
|
|
||||||
e = null
|
|
||||||
err = null
|
|
||||||
profile = null
|
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
callback(false) // invalid certificate data
|
callback(false) // invalid certificate data
|
||||||
// dereference
|
|
||||||
callback = null
|
|
||||||
cert = null
|
|
||||||
ctx = null
|
|
||||||
e = null
|
|
||||||
profile = null
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
callback(false) // could not create key pair
|
callback(false) // could not create key pair
|
||||||
// dereference
|
|
||||||
callback = null
|
|
||||||
ctx = null
|
|
||||||
e = null
|
|
||||||
profile = null
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -656,7 +530,7 @@ export class AcmeClient {
|
|||||||
if (this.jWebClient.verbose) {
|
if (this.jWebClient.verbose) {
|
||||||
console.error('Running:', openssl)
|
console.error('Running:', openssl)
|
||||||
}
|
}
|
||||||
child_process.exec(openssl, function (e) {
|
child_process.exec(openssl, (e) => {
|
||||||
if (!e) {
|
if (!e) {
|
||||||
console.error('Result : done')
|
console.error('Result : done')
|
||||||
} else {
|
} else {
|
||||||
@ -690,7 +564,7 @@ export class AcmeClient {
|
|||||||
// respects file name restrictions for ntfs and ext2
|
// respects file name restrictions for ntfs and ext2
|
||||||
let regex_file = '[<>:\"/\\\\\\|\\?\\*\\u0000-\\u001f\\u007f\\u0080-\\u009f]'
|
let regex_file = '[<>:\"/\\\\\\|\\?\\*\\u0000-\\u001f\\u007f\\u0080-\\u009f]'
|
||||||
let regex_path = '[<>:\"\\\\\\|\\?\\*\\u0000-\\u001f\\u007f\\u0080-\\u009f]'
|
let regex_path = '[<>:\"\\\\\\|\\?\\*\\u0000-\\u001f\\u007f\\u0080-\\u009f]'
|
||||||
return name.replace(new RegExp(withPath ? regex_path : regex_file, 'g'), function (charToReplace) {
|
return name.replace(new RegExp(withPath ? regex_path : regex_file, 'g'), (charToReplace) => {
|
||||||
if (typeof charToReplace === 'string') {
|
if (typeof charToReplace === 'string') {
|
||||||
return '%' + charToReplace.charCodeAt(0).toString(16).toLocaleUpperCase()
|
return '%' + charToReplace.charCodeAt(0).toString(16).toLocaleUpperCase()
|
||||||
}
|
}
|
||||||
@ -706,66 +580,42 @@ export class AcmeClient {
|
|||||||
*/
|
*/
|
||||||
prepareChallenge(domain, challenge, callback) {
|
prepareChallenge(domain, challenge, callback) {
|
||||||
/*jshint -W069, unused:false*/
|
/*jshint -W069, unused:false*/
|
||||||
let ctx = this
|
|
||||||
if (typeof callback !== 'function') {
|
if (typeof callback !== 'function') {
|
||||||
callback = this.emptyCallback // ensure callback is function
|
callback = this.emptyCallback // ensure callback is function
|
||||||
}
|
}
|
||||||
if (challenge instanceof Object) {
|
if (challenge instanceof Object) {
|
||||||
if (challenge['type'] === 'http-01') { // simple http challenge
|
if (challenge['type'] === 'http-01') { // simple http challenge
|
||||||
let path = this.webroot + this.well_known_path + challenge['token'] // webroot and well_known_path are expected to be already sanitized
|
let path = this.webroot + this.wellKnownPath + challenge['token'] // webroot and well_known_path are expected to be already sanitized
|
||||||
fs.writeFile(path, this.makeKeyAuthorization(challenge), function (err) { // create challenge file
|
fs.writeFile(path, this.makeKeyAuthorization(challenge), (err) => { // create challenge file
|
||||||
if (err instanceof Object) { // file system error
|
if (err instanceof Object) { // file system error
|
||||||
if (ctx.jWebClient.verbose) {
|
if (this.jWebClient.verbose) {
|
||||||
console.error(
|
console.error(
|
||||||
'Error : File system error',
|
'Error : File system error',
|
||||||
err['code'], 'while writing challenge data to file'
|
err['code'], 'while writing challenge data to file'
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
callback()
|
callback()
|
||||||
// dereference
|
|
||||||
callback = null
|
|
||||||
challenge = null
|
|
||||||
ctx = null
|
|
||||||
err = null
|
|
||||||
} else {
|
} else {
|
||||||
// let uri = "http://" + domain + this.well_known_path + challenge["token"]
|
// let uri = "http://" + domain + this.well_known_path + challenge["token"]
|
||||||
let rl = readline.createInterface(process.stdin, process.stdout)
|
let rl = readline.createInterface(process.stdin, process.stdout)
|
||||||
if (ctx.withInteraction) {
|
if (this.withInteraction) {
|
||||||
rl.question('Press enter to proceed', function (answer) { // wait for user to proceed
|
rl.question('Press enter to proceed', (answer) => { // wait for user to proceed
|
||||||
rl.close()
|
rl.close()
|
||||||
callback()
|
callback()
|
||||||
// dereference
|
|
||||||
callback = null
|
|
||||||
challenge = null
|
|
||||||
ctx = null
|
|
||||||
rl = null
|
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
rl.close()
|
rl.close()
|
||||||
callback() // skip interaction prompt if desired
|
callback() // skip interaction prompt if desired
|
||||||
// dereference
|
|
||||||
callback = null
|
|
||||||
challenge = null
|
|
||||||
ctx = null
|
|
||||||
rl = null
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
} else { // no supported challenge
|
} else { // no supported challenge
|
||||||
console.error('Error : Challenge not supported')
|
console.error('Error : Challenge not supported')
|
||||||
callback()
|
callback()
|
||||||
// dereference
|
|
||||||
callback = null
|
|
||||||
challenge = null
|
|
||||||
ctx = null
|
|
||||||
}
|
}
|
||||||
} else { // invalid challenge response
|
} else { // invalid challenge response
|
||||||
console.error('Error : Invalid challenge response')
|
console.error('Error : Invalid challenge response')
|
||||||
callback()
|
callback()
|
||||||
// dereference
|
|
||||||
callback = null
|
|
||||||
challenge = null
|
|
||||||
ctx = null
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -782,9 +632,6 @@ export class AcmeClient {
|
|||||||
match = null
|
match = null
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
// dereference
|
|
||||||
match = null
|
|
||||||
return void 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -796,7 +643,7 @@ export class AcmeClient {
|
|||||||
selectChallenge(ans, challengeType: string) {
|
selectChallenge(ans, challengeType: string) {
|
||||||
/*jshint -W069 */
|
/*jshint -W069 */
|
||||||
if ((ans instanceof Object) && (ans['challenges'] instanceof Array)) {
|
if ((ans instanceof Object) && (ans['challenges'] instanceof Array)) {
|
||||||
return ans.challenges.filter(function (entry) {
|
return ans.challenges.filter((entry) => {
|
||||||
let type = entry['type']
|
let type = entry['type']
|
||||||
// dereference
|
// dereference
|
||||||
entry = null
|
entry = null
|
||||||
@ -824,7 +671,7 @@ export class AcmeClient {
|
|||||||
return void 0 // invalid profile
|
return void 0 // invalid profile
|
||||||
}
|
}
|
||||||
let prefix = 'mailto:'
|
let prefix = 'mailto:'
|
||||||
let email = profile.contact.filter(function (entry) {
|
let email = profile.contact.filter((entry) => {
|
||||||
if (typeof entry !== 'string') {
|
if (typeof entry !== 'string') {
|
||||||
return false
|
return false
|
||||||
} else {
|
} else {
|
||||||
@ -871,11 +718,9 @@ export class AcmeClient {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
let hash = crypto.createHash('sha256').update(jwk.toString('utf8'), 'utf8').digest()
|
let hash = crypto.createHash('sha256').update(jwk.toString('utf8'), 'utf8').digest()
|
||||||
let ACCOUNT_KEY = base64url.default.encode(hash) // create base64 encoded hash of account key
|
// create base64 encoded hash of account key
|
||||||
|
let ACCOUNT_KEY = plugins.smartstring.base64.encodeUri(hash.toString())
|
||||||
let token = challenge['token']
|
let token = challenge['token']
|
||||||
// dereference
|
|
||||||
challenge = null
|
|
||||||
jwk = null
|
|
||||||
return token + '.' + ACCOUNT_KEY
|
return token + '.' + ACCOUNT_KEY
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -901,14 +746,14 @@ export class AcmeClient {
|
|||||||
* @param {number} days_valid
|
* @param {number} days_valid
|
||||||
* @return {{resource: string, csr: string, notBefore: string, notAfter: string}}
|
* @return {{resource: string, csr: string, notBefore: string, notAfter: string}}
|
||||||
*/
|
*/
|
||||||
makeCertRequest(csr, DAYS_VALID: number) {
|
makeCertRequest(csr: string, DAYS_VALID: number) {
|
||||||
if (typeof csr !== 'string' && !(csr instanceof Buffer)) {
|
if (typeof csr !== 'string' && !(csr instanceof Buffer)) {
|
||||||
csr = '' // default string for CSR
|
csr = '' // default string for CSR
|
||||||
}
|
}
|
||||||
if ((typeof DAYS_VALID !== 'number') || (isNaN(DAYS_VALID)) || (DAYS_VALID === 0)) {
|
if ((typeof DAYS_VALID !== 'number') || (isNaN(DAYS_VALID)) || (DAYS_VALID === 0)) {
|
||||||
DAYS_VALID = 1 // default validity duration (1 day)
|
DAYS_VALID = 1 // default validity duration (1 day)
|
||||||
}
|
}
|
||||||
let DOMAIN_CSR_DER = base64url.default.encode(csr) // create base64 encoded CSR
|
let DOMAIN_CSR_DER = plugins.smartstring.base64.encodeUri(csr) // create base64 encoded CSR
|
||||||
let CURRENT_DATE = (new Date()).toISOString() // set start date to current date
|
let CURRENT_DATE = (new Date()).toISOString() // set start date to current date
|
||||||
|
|
||||||
// set end date to current date + days_valid
|
// set end date to current date + days_valid
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import * as plugins from './smartacme.plugins'
|
import * as plugins from './smartacme.plugins'
|
||||||
import * as base64url from 'base64url'
|
|
||||||
import * as https from 'https'
|
import * as https from 'https'
|
||||||
let jwa = require('jwa')
|
let jwa = require('jwa')
|
||||||
import * as url from 'url'
|
import * as url from 'url'
|
||||||
@ -13,7 +12,7 @@ import * as url from 'url'
|
|||||||
* @throws Exception if object cannot be stringified or contains cycle
|
* @throws Exception if object cannot be stringified or contains cycle
|
||||||
*/
|
*/
|
||||||
let json_to_utf8base64url = function (obj) {
|
let json_to_utf8base64url = function (obj) {
|
||||||
return base64url.default.encode(new Buffer(JSON.stringify(obj), 'utf8'))
|
return plugins.smartstring.base64.encodeUri(JSON.stringify(obj))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -30,17 +29,17 @@ export class JWebClient {
|
|||||||
* @member {Object} module:JWebClient~JWebClient#key_pair
|
* @member {Object} module:JWebClient~JWebClient#key_pair
|
||||||
* @desc User account key pair
|
* @desc User account key pair
|
||||||
*/
|
*/
|
||||||
this.key_pair = null // {Object}
|
this.key_pair = {}
|
||||||
/**
|
/**
|
||||||
* @member {string} module:JWebClient~JWebClient#last_nonce
|
* @member {string} module:JWebClient~JWebClient#last_nonce
|
||||||
* @desc Cached nonce returned with last request
|
* @desc Cached nonce returned with last request
|
||||||
*/
|
*/
|
||||||
this.last_nonce = null // {string}
|
this.last_nonce = null
|
||||||
/**
|
/**
|
||||||
* @member {boolean} module:JWebClient~JWebClient#verbose
|
* @member {boolean} module:JWebClient~JWebClient#verbose
|
||||||
* @desc Determines verbose mode
|
* @desc Determines verbose mode
|
||||||
*/
|
*/
|
||||||
this.verbose = false // {boolean}
|
this.verbose = false
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -57,7 +56,7 @@ export class JWebClient {
|
|||||||
/*jshint -W069 */
|
/*jshint -W069 */
|
||||||
// prepare key
|
// prepare key
|
||||||
if (key instanceof Object) {
|
if (key instanceof Object) {
|
||||||
key = base64url.default.toBuffer(key['k'])
|
key = new Buffer(plugins.smartstring.base64.decode(key['k']))
|
||||||
}
|
}
|
||||||
// prepare header
|
// prepare header
|
||||||
let header = {
|
let header = {
|
||||||
@ -83,13 +82,6 @@ export class JWebClient {
|
|||||||
input,
|
input,
|
||||||
sig
|
sig
|
||||||
].join('.')
|
].join('.')
|
||||||
// dereference
|
|
||||||
header = null
|
|
||||||
hmac = null
|
|
||||||
input = null
|
|
||||||
jwk = null
|
|
||||||
key = null
|
|
||||||
payload = null
|
|
||||||
// output
|
// output
|
||||||
return output
|
return output
|
||||||
}
|
}
|
||||||
@ -218,11 +210,12 @@ export class JWebClient {
|
|||||||
if (typeof callback !== 'function') {
|
if (typeof callback !== 'function') {
|
||||||
callback = this.emptyCallback // ensure callback is function
|
callback = this.emptyCallback // ensure callback is function
|
||||||
}
|
}
|
||||||
let key_pair = this.key_pair
|
let jwt = this.createJWT(
|
||||||
if (!(key_pair instanceof Object)) {
|
this.last_nonce,
|
||||||
key_pair = {} // ensure key pair is object
|
payload,
|
||||||
}
|
'RS256',
|
||||||
let jwt = this.createJWT(this.last_nonce, payload, 'RS256', key_pair['private_pem'], key_pair['public_jwk'])
|
this.key_pair['private_pem'],
|
||||||
|
this.key_pair['public_jwk'])
|
||||||
this.request(uri, jwt, (ans, res) => {
|
this.request(uri, jwt, (ans, res) => {
|
||||||
ctx.evaluateStatus(uri, payload, ans, res)
|
ctx.evaluateStatus(uri, payload, ans, res)
|
||||||
// save replay nonce for later requests
|
// save replay nonce for later requests
|
||||||
@ -230,16 +223,7 @@ export class JWebClient {
|
|||||||
ctx.last_nonce = res.headers['replay-nonce']
|
ctx.last_nonce = res.headers['replay-nonce']
|
||||||
}
|
}
|
||||||
callback(ans, res)
|
callback(ans, res)
|
||||||
// dereference
|
}, errorCallback )
|
||||||
ans = null
|
|
||||||
callback = null
|
|
||||||
ctx = null
|
|
||||||
key_pair = null
|
|
||||||
payload = null
|
|
||||||
res = null
|
|
||||||
}, errorCallback)
|
|
||||||
// dereference
|
|
||||||
errorCallback = null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -278,11 +262,6 @@ export class JWebClient {
|
|||||||
console.error('Receive:', res['headers']) // received headers
|
console.error('Receive:', res['headers']) // received headers
|
||||||
console.error('Receive:', ans) // received data
|
console.error('Receive:', ans) // received data
|
||||||
}
|
}
|
||||||
// dereference
|
|
||||||
ans = null
|
|
||||||
payload = null
|
|
||||||
res = null
|
|
||||||
uri_parsed = null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2,8 +2,19 @@ import * as plugins from './smartacme.plugins'
|
|||||||
import * as acmeclient from './smartacme.classes.acmeclient'
|
import * as acmeclient from './smartacme.classes.acmeclient'
|
||||||
|
|
||||||
export class SmartAcme {
|
export class SmartAcme {
|
||||||
|
acmeAccount: AcmeAccount
|
||||||
acmeClient: acmeclient.AcmeClient
|
acmeClient: acmeclient.AcmeClient
|
||||||
constructor(directoryUrlArg: string = 'https://acme-staging.api.letsencrypt.org/directory') {
|
constructor(directoryUrlArg: string = 'https://acme-staging.api.letsencrypt.org/directory') {
|
||||||
this.acmeClient = new acmeclient.AcmeClient(directoryUrlArg)
|
this.acmeClient = new acmeclient.AcmeClient(directoryUrlArg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
createAccount() {
|
||||||
|
this.acmeClient.createAccount('test@bleu.de',(answer) => {
|
||||||
|
console.log(answer)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class AcmeAccount {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
import 'typings-global'
|
import 'typings-global'
|
||||||
import * as path from 'path'
|
import * as path from 'path'
|
||||||
|
import * as smartstring from 'smartstring'
|
||||||
|
|
||||||
export {
|
export {
|
||||||
path
|
path,
|
||||||
|
smartstring
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user