From b03d8bfb65ee94db3c312fb2184034e3b279743f Mon Sep 17 00:00:00 2001 From: PhilKunz Date: Mon, 24 Oct 2016 00:35:00 +0200 Subject: [PATCH] fix --- .gitignore | 2 + dist/cert.classes.cert.d.ts | 49 +++---- dist/cert.classes.cert.helpers.d.ts | 19 --- dist/cert.classes.cert.helpers.js | 59 -------- dist/cert.classes.cert.js | 173 +++++++---------------- dist/cert.classes.certificate.d.ts | 48 +++++++ dist/cert.classes.certificate.js | 103 ++++++++++++++ dist/cert.classes.certrepo.d.ts | 26 ++++ dist/cert.classes.certrepo.js | 49 +++++++ dist/cert.classes.challengehandler.d.ts | 20 +++ dist/cert.classes.challengehandler.js | 75 ++++++++++ dist/cert.classes.letsencrypt.d.ts | 27 ++++ dist/cert.classes.letsencrypt.js | 114 +++++++++++++++ dist/cert.hook.d.ts | 0 dist/cert.hook.js | 68 --------- dist/cert.paths.d.ts | 10 +- dist/cert.paths.js | 19 ++- dist/cert.plugins.d.ts | 25 ++-- dist/cert.plugins.js | 35 +++-- dist/index.d.ts | 2 +- dist/index.js | 2 +- dist/install.d.ts | 3 - dist/install.js | 19 --- package.json | 5 +- test/test.d.ts | 3 +- test/test.js | 37 ++--- test/test.ts | 63 ++++----- ts/cert.classes.cert.helpers.ts | 86 ------------ ts/cert.classes.cert.ts | 176 ++++++++---------------- ts/cert.classes.certificate.ts | 129 +++++++++++++++++ ts/cert.classes.certrepo.ts | 65 +++++++++ ts/cert.classes.challengehandler.ts | 84 +++++++++++ ts/cert.classes.letsencrypt.ts | 139 +++++++++++++++++++ ts/cert.hook.ts | 73 ---------- ts/cert.paths.ts | 21 ++- ts/cert.plugins.ts | 2 - ts/index.ts | 5 +- ts/temp | 3 + 38 files changed, 1117 insertions(+), 721 deletions(-) delete mode 100644 dist/cert.classes.cert.helpers.d.ts delete mode 100644 dist/cert.classes.cert.helpers.js create mode 100644 dist/cert.classes.certificate.d.ts create mode 100644 dist/cert.classes.certificate.js create mode 100644 dist/cert.classes.certrepo.d.ts create mode 100644 dist/cert.classes.certrepo.js create mode 100644 dist/cert.classes.challengehandler.d.ts create mode 100644 dist/cert.classes.challengehandler.js create mode 100644 dist/cert.classes.letsencrypt.d.ts create mode 100644 dist/cert.classes.letsencrypt.js delete mode 100644 dist/cert.hook.d.ts delete mode 100755 dist/cert.hook.js delete mode 100644 dist/install.d.ts delete mode 100644 dist/install.js delete mode 100644 ts/cert.classes.cert.helpers.ts create mode 100644 ts/cert.classes.certificate.ts create mode 100644 ts/cert.classes.certrepo.ts create mode 100644 ts/cert.classes.challengehandler.ts create mode 100644 ts/cert.classes.letsencrypt.ts delete mode 100644 ts/cert.hook.ts create mode 100644 ts/temp diff --git a/.gitignore b/.gitignore index edd60d0..7036b29 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,7 @@ node_modules docs/ +public/ +pages/ coverage/ .nogit/ dist/assets/ diff --git a/dist/cert.classes.cert.d.ts b/dist/cert.classes.cert.d.ts index a739484..68d0ccc 100644 --- a/dist/cert.classes.cert.d.ts +++ b/dist/cert.classes.cert.d.ts @@ -1,44 +1,37 @@ /// -import * as plugins from "./cert.plugins"; +import * as q from 'q'; +import { Stringmap, Objectmap } from 'lik'; +import { Certificate } from './cert.classes.certificate'; +import { Letsencrypt, TLeEnv } from './cert.classes.letsencrypt'; export interface ICertConstructorOptions { cfEmail: string; cfKey: string; - sslDir?: string; + sslDirPath?: string; gitOriginRepo?: string; - testMode?: boolean; + leEnv?: TLeEnv; } export declare class Cert { - private _cfEmail; - private _cfKey; - private _sslDir; - private _gitOriginRepo; - private _testMode; - domainCertRequestMap: plugins.lik.Stringmap; - certificatesPresent: Certificate[]; - certificatesValid: Certificate[]; + domainStringRequestMap: Stringmap; + certificateMap: Objectmap; + letsencrypt: Letsencrypt; + private _challengeHandler; + private _certRepo; /** * Constructor for Cert object */ constructor(optionsArg: ICertConstructorOptions); /** - * Pulls already requested certificates from git origin + * adds a Certificate for a given domain */ - sslGitOriginPull: () => void; - /** - * Pushes all new requested certificates to git origin - */ - sslGitOriginAddCommitPush: () => void; - /** - * gets a ssl cert for a given domain - */ - getDomainCert(domainNameArg: string, optionsArg?: { + addCertificate(domainNameArg: string, optionsArg?: { force: boolean; - }): plugins.q.Promise<{}>; + }): q.Promise<{}>; + /** + * cleans up old certificates + */ cleanOldCertificates(): void; -} -export declare class Certificate { - domainName: string; - creationDate: Date; - expiryDate: Date; - constructor(); + /** + * executes the current batch of jobs + */ + deploy(): void; } diff --git a/dist/cert.classes.cert.helpers.d.ts b/dist/cert.classes.cert.helpers.d.ts deleted file mode 100644 index 6d04a73..0000000 --- a/dist/cert.classes.cert.helpers.d.ts +++ /dev/null @@ -1,19 +0,0 @@ -/// -import * as plugins from "./cert.plugins"; -/** - * schedule a retry of certificate request - */ -export declare let scheduleRetry: (domainArg: string, certClassArg: any) => plugins.q.Promise<{}>; -/** - * check if a given domainCert is still valid - */ -export declare let checkDomainsStillValid: (domainNameArg: string, sslDirArg: string) => boolean; -export interface certConfig { - domainName: string; - created: number; - expires: number; -} -/** - * update a ssl directory - */ -export declare let updateSslDirSync: (sslDirArg: string, domainNameArg: string) => void; diff --git a/dist/cert.classes.cert.helpers.js b/dist/cert.classes.cert.helpers.js deleted file mode 100644 index 72ad546..0000000 --- a/dist/cert.classes.cert.helpers.js +++ /dev/null @@ -1,59 +0,0 @@ -"use strict"; -const plugins = require("./cert.plugins"); -const paths = require("./cert.paths"); -/** - * schedule a retry of certificate request - */ -exports.scheduleRetry = (domainArg, certClassArg) => { - let done = plugins.q.defer(); - setTimeout(() => { - certClassArg.getDomainCert(domainArg) - .then(done.resolve); - }, 60000); - return done.promise; -}; -/** - * check if a given domainCert is still valid - */ -exports.checkDomainsStillValid = (domainNameArg, sslDirArg) => { - let domainConfigPath = plugins.path.join(sslDirArg, domainNameArg, "config.json"); - if (plugins.smartfile.fs.fileExistsSync(domainConfigPath)) { - let domainConfig = plugins.smartfile.fs.toObjectSync(domainConfigPath, "json"); - if (Date.now() >= ((domainConfig.expires - 604800) * 1000)) { - return false; - } - else { - return true; - } - } - else { - return false; - } -}; -; -/** - * update a ssl directory - */ -exports.updateSslDirSync = (sslDirArg, domainNameArg) => { - plugins.smartfile.fs.ensureDirSync(sslDirArg); - let domainCertFolder = plugins.path.join(paths.certDir, domainNameArg); - if (plugins.smartfile.fs.listFoldersSync(paths.certDir).indexOf(domainNameArg) != -1) { - plugins.smartfile.fs.copySync(plugins.path.join(domainCertFolder, "fullchain.pem"), plugins.path.join(sslDirArg, domainNameArg, "fullchain.pem")); - plugins.smartfile.fs.copySync(plugins.path.join(domainCertFolder, "privkey.pem"), plugins.path.join(sslDirArg, domainNameArg, "privkey.pem")); - // create cert config - let certRegex = /.*\-([0-9]*)\.pem/; - let certFileNameWithTime = plugins.smartfile.fs.listFilesSync(domainCertFolder, certRegex)[0]; - let certTime = parseInt(certRegex.exec(certFileNameWithTime)[1]); - let certConfig = { - domainName: domainNameArg, - created: certTime, - expires: certTime + 7776000 - }; - plugins.smartfile.memory.toFsSync(JSON.stringify(certConfig), plugins.path.join(sslDirArg, domainNameArg, "config.json")); - } - ; -}; -let updateGitOrigin = (syncDirectionArg) => { -}; -updateGitOrigin(0 /* toOrigin */); -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2VydC5jbGFzc2VzLmNlcnQuaGVscGVycy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL2NlcnQuY2xhc3Nlcy5jZXJ0LmhlbHBlcnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUNBLDBDQUEwQztBQUMxQyxzQ0FBc0M7QUFJdEM7O0dBRUc7QUFDUSxRQUFBLGFBQWEsR0FBRyxDQUFDLFNBQWdCLEVBQUMsWUFBaUI7SUFDMUQsSUFBSSxJQUFJLEdBQUcsT0FBTyxDQUFDLENBQUMsQ0FBQyxLQUFLLEVBQUUsQ0FBQztJQUM3QixVQUFVLENBQUM7UUFDUCxZQUFZLENBQUMsYUFBYSxDQUFDLFNBQVMsQ0FBQzthQUNoQyxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQzVCLENBQUMsRUFBQyxLQUFLLENBQUMsQ0FBQztJQUNULE1BQU0sQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDO0FBQ3hCLENBQUMsQ0FBQztBQUVGOztHQUVHO0FBQ1EsUUFBQSxzQkFBc0IsR0FBRyxDQUFDLGFBQXFCLEVBQUUsU0FBaUI7SUFDekUsSUFBSSxnQkFBZ0IsR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsYUFBYSxFQUFFLGFBQWEsQ0FBQyxDQUFDO0lBQ2xGLEVBQUUsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDLGNBQWMsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUN4RCxJQUFJLFlBQVksR0FBRyxPQUFPLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQyxZQUFZLENBQ2hELGdCQUFnQixFQUNoQixNQUFNLENBQ1QsQ0FBQztRQUNGLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsSUFBSSxDQUFDLENBQUMsWUFBWSxDQUFDLE9BQU8sR0FBRyxNQUFNLENBQUMsR0FBRyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDekQsTUFBTSxDQUFDLEtBQUssQ0FBQztRQUNqQixDQUFDO1FBQUMsSUFBSSxDQUFDLENBQUM7WUFDSixNQUFNLENBQUMsSUFBSSxDQUFDO1FBQ2hCLENBQUM7SUFDTCxDQUFDO0lBQUMsSUFBSSxDQUFDLENBQUM7UUFDSixNQUFNLENBQUMsS0FBSyxDQUFDO0lBQ2pCLENBQUM7QUFFTCxDQUFDLENBQUE7QUFNQSxDQUFDO0FBRUY7O0dBRUc7QUFDUSxRQUFBLGdCQUFnQixHQUFHLENBQUMsU0FBaUIsRUFBRSxhQUFxQjtJQUNuRSxPQUFPLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQyxhQUFhLENBQUMsU0FBUyxDQUFDLENBQUM7SUFDOUMsSUFBSSxnQkFBZ0IsR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxFQUFFLGFBQWEsQ0FBQyxDQUFBO0lBQ3RFLEVBQUUsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDLGVBQWUsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUMsT0FBTyxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNuRixPQUFPLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQyxRQUFRLENBQ3pCLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLGdCQUFnQixFQUFFLGVBQWUsQ0FBQyxFQUNwRCxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsYUFBYSxFQUFFLGVBQWUsQ0FBQyxDQUMvRCxDQUFDO1FBQ0YsT0FBTyxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUMsUUFBUSxDQUN6QixPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxhQUFhLENBQUMsRUFDbEQsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLGFBQWEsRUFBRSxhQUFhLENBQUMsQ0FDN0QsQ0FBQztRQUNGLHFCQUFxQjtRQUNyQixJQUFJLFNBQVMsR0FBRyxtQkFBbUIsQ0FBQztRQUNwQyxJQUFJLG9CQUFvQixHQUFXLE9BQU8sQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDLGFBQWEsQ0FBQyxnQkFBZ0IsRUFBRSxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUN0RyxJQUFJLFFBQVEsR0FBRyxRQUFRLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDakUsSUFBSSxVQUFVLEdBQWU7WUFDekIsVUFBVSxFQUFFLGFBQWE7WUFDekIsT0FBTyxFQUFFLFFBQVE7WUFDakIsT0FBTyxFQUFFLFFBQVEsR0FBRyxPQUFPO1NBQzlCLENBQUM7UUFDRixPQUFPLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQzdCLElBQUksQ0FBQyxTQUFTLENBQUMsVUFBVSxDQUFDLEVBQzFCLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxhQUFhLEVBQUUsYUFBYSxDQUFDLENBQzdELENBQUM7SUFDTixDQUFDO0lBQUEsQ0FBQztBQUNOLENBQUMsQ0FBQTtBQU9ELElBQUksZUFBZSxHQUFHLENBQUMsZ0JBQWtDO0FBRXpELENBQUMsQ0FBQztBQUVGLGVBQWUsQ0FBQyxnQkFBeUIsQ0FBQyxDQUFDIn0= \ No newline at end of file diff --git a/dist/cert.classes.cert.js b/dist/cert.classes.cert.js index a7c7124..257acdb 100644 --- a/dist/cert.classes.cert.js +++ b/dist/cert.classes.cert.js @@ -1,142 +1,69 @@ "use strict"; -const plugins = require("./cert.plugins"); -const paths = require("./cert.paths"); -const helpers = require("./cert.classes.cert.helpers"); -; +const q = require("q"); +const lik_1 = require("lik"); +// classes +const cert_classes_certificate_1 = require("./cert.classes.certificate"); +const cert_classes_certrepo_1 = require("./cert.classes.certrepo"); +const cert_classes_letsencrypt_1 = require("./cert.classes.letsencrypt"); +const cert_classes_challengehandler_1 = require("./cert.classes.challengehandler"); class Cert { /** * Constructor for Cert object */ constructor(optionsArg) { - this.domainCertRequestMap = new plugins.lik.Stringmap(); - /** - * Pulls already requested certificates from git origin - */ - this.sslGitOriginPull = () => { - if (this._gitOriginRepo) { - plugins.smartgit.pull(this._sslDir, "origin", "master"); - } - }; - /** - * Pushes all new requested certificates to git origin - */ - this.sslGitOriginAddCommitPush = () => { - if (this._gitOriginRepo) { - plugins.smartgit.add.addAll(this._sslDir); - plugins.smartgit.commit(this._sslDir, "added new SSL certificates and deleted obsolete ones."); - plugins.smartgit.push(this._sslDir, "origin", "master"); - } - }; - this._cfEmail = optionsArg.cfEmail; - this._cfKey = optionsArg.cfKey; - this._sslDir = optionsArg.sslDir; - this._gitOriginRepo = optionsArg.gitOriginRepo; - this._testMode = optionsArg.testMode; - // write hook config - let config = { - cfEmail: this._cfEmail, - cfKey: this._cfKey - }; - plugins.smartfile.memory.toFsSync(JSON.stringify(config), plugins.path.join(__dirname, "assets/config.json")); - // setup sslDir - if (!this._sslDir) - this._sslDir = paths.defaultSslDir; - // setup Git - if (this._gitOriginRepo) { - plugins.smartgit.init(this._sslDir); - plugins.smartgit.remote.add(this._sslDir, "origin", this._gitOriginRepo); - this.sslGitOriginPull(); - } - // setup leSh config; - let leShConfigString; - if (this._testMode) { - leShConfigString = `CA="https://acme-staging.api.letsencrypt.org/directory"\n`; - } - else { - leShConfigString = " "; - } - ; - plugins.smartfile.memory.toFsSync(leShConfigString, paths.leShConfig); - plugins.shelljs.exec("chmod 700 " + paths.letsencryptSh); - plugins.shelljs.exec("chmod 700 " + paths.certHook); - plugins.shelljs.exec(`bash -c "${paths.letsencryptSh} -c --no-lock -f ${paths.leShConfig} -d notthere.notthere -t dns-01 -k ${paths.certHook} -o ${paths.certDir}"`, { - silent: true + this.domainStringRequestMap = new lik_1.Stringmap(); + this.certificateMap = new lik_1.Objectmap(); + // set up challengehandler + this._challengeHandler = new cert_classes_challengehandler_1.ChallengeHandler({ + cfEmail: optionsArg.cfEmail, + cfKey: optionsArg.cfKey }); + // setup Letsencrypt + this.letsencrypt = new cert_classes_letsencrypt_1.Letsencrypt({ + leEnv: optionsArg.leEnv, + sslDir: optionsArg.sslDirPath, + challengeHandler: this._challengeHandler + }); + // setup CertRpo + this._certRepo = new cert_classes_certrepo_1.CertRepo({ + sslDirPath: optionsArg.sslDirPath, + gitOriginRepo: optionsArg.gitOriginRepo, + certInstance: this + }); + this._certRepo; } - ; /** - * gets a ssl cert for a given domain + * adds a Certificate for a given domain */ - getDomainCert(domainNameArg, optionsArg = { force: false }) { - let done = plugins.q.defer(); - let domainStringData = new plugins.smartstring.Domain(domainNameArg); - let sameZoneRequesting = this.domainCertRequestMap.checkMinimatch("*" + domainStringData.zoneName); - // make sure no one else requires the same domain at the same time - if (!this.domainCertRequestMap.checkString(domainNameArg)) { - this.domainCertRequestMap.addString(domainNameArg); - if (!helpers.checkDomainsStillValid(domainNameArg, this._sslDir) || optionsArg.force) { - if (!sameZoneRequesting) { - this.sslGitOriginPull(); - plugins.smartfile.fs.ensureDir(paths.certDir); - plugins.beautylog.info(`getting cert for ${domainNameArg}`); - plugins.shelljs.exec(`bash -c "${paths.letsencryptSh} -c --no-lock -f ${paths.leShConfig} -d ${domainNameArg} -t dns-01 -k ${paths.certHook} -o ${paths.certDir}"`, { - silent: true - }, (codeArg, stdoutArg) => { - if (codeArg == 0) { - console.log(stdoutArg); - let fetchedCertsArray = plugins.smartfile.fs.listFoldersSync(paths.certDir); - if (fetchedCertsArray.indexOf(domainNameArg) != -1) { - helpers.updateSslDirSync(this._sslDir, domainNameArg); - plugins.smartfile.fs.removeSync(plugins.path.join(paths.certDir, domainNameArg)); - this.sslGitOriginAddCommitPush(); - } - else { - plugins.beautylog.error(`Couldn't copy final certificate for ${domainNameArg}!`); - } - ; - done.resolve(); - } - else { - plugins.beautylog.warn(`${domainNameArg} scheduled for retry. Waiting 1 minute!`); - helpers.scheduleRetry(domainNameArg, this).then(done.resolve); - } - this.domainCertRequestMap.removeString(domainNameArg); - }); - } - else { - plugins.beautylog.info(`${domainNameArg} is waiting for domains names of same zone to finish`); - this.domainCertRequestMap.removeString(domainNameArg); - this.domainCertRequestMap.registerUntilTrue(() => { - return !this.domainCertRequestMap.checkMinimatch("*" + domainStringData.zoneName); - }, () => { - this.getDomainCert(domainNameArg).then(done.resolve); - }); - } - } - else { - plugins.beautylog.info("certificate for " + domainNameArg + " is still valid! Not fetching new one!"); - this.domainCertRequestMap.removeString(domainNameArg); - done.resolve(); - } - ; + addCertificate(domainNameArg, optionsArg = { force: false }) { + let done = q.defer(); + let certificateForDomain = this.certificateMap.find((certificate) => { + return certificate.domainName === domainNameArg; + }); + if (certificateForDomain instanceof cert_classes_certificate_1.Certificate) { + certificateForDomain.renew() + .then(done.resolve); } else { - plugins.beautylog.warn(`${domainNameArg} is already requesting`); + certificateForDomain = new cert_classes_certificate_1.Certificate({ + certInstance: this, + domainName: domainNameArg + }); + certificateForDomain.renew() + .then(done.resolve); } - ; return done.promise; } - ; + /** + * cleans up old certificates + */ cleanOldCertificates() { } - ; + /** + * executes the current batch of jobs + */ + deploy() { + } } exports.Cert = Cert; -class Certificate { - constructor() { - } - ; -} -exports.Certificate = Certificate; -; -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2VydC5jbGFzc2VzLmNlcnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9jZXJ0LmNsYXNzZXMuY2VydC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsMENBQTBDO0FBQzFDLHNDQUFzQztBQUN0Qyx1REFBc0Q7QUFRckQsQ0FBQztBQUVGO0lBVUk7O09BRUc7SUFDSCxZQUFZLFVBQW1DO1FBUC9DLHlCQUFvQixHQUEwQixJQUFJLE9BQU8sQ0FBQyxHQUFHLENBQUMsU0FBUyxFQUFFLENBQUM7UUFrRDFFOztXQUVHO1FBQ0gscUJBQWdCLEdBQUc7WUFDZixFQUFFLENBQUMsQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDLENBQUMsQ0FBQztnQkFDdEIsT0FBTyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxRQUFRLEVBQUUsUUFBUSxDQUFDLENBQUM7WUFDNUQsQ0FBQztRQUNMLENBQUMsQ0FBQztRQUVGOztXQUVHO1FBQ0gsOEJBQXlCLEdBQUc7WUFDeEIsRUFBRSxDQUFDLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxDQUFDLENBQUM7Z0JBQ3RCLE9BQU8sQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7Z0JBQzFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsdURBQXVELENBQUMsQ0FBQztnQkFDL0YsT0FBTyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxRQUFRLEVBQUUsUUFBUSxDQUFDLENBQUM7WUFDNUQsQ0FBQztRQUNMLENBQUMsQ0FBQztRQTVERSxJQUFJLENBQUMsUUFBUSxHQUFHLFVBQVUsQ0FBQyxPQUFPLENBQUM7UUFDbkMsSUFBSSxDQUFDLE1BQU0sR0FBRyxVQUFVLENBQUMsS0FBSyxDQUFDO1FBQy9CLElBQUksQ0FBQyxPQUFPLEdB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 \ No newline at end of file +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2VydC5jbGFzc2VzLmNlcnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9jZXJ0LmNsYXNzZXMuY2VydC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsdUJBQXNCO0FBQ3RCLDZCQUEwQztBQUsxQyxVQUFVO0FBQ1YseUVBQXdEO0FBQ3hELG1FQUFrRDtBQUNsRCx5RUFBZ0U7QUFDaEUsbUZBQWtFO0FBV2xFO0lBT0k7O09BRUc7SUFDSCxZQUFZLFVBQW1DO1FBVC9DLDJCQUFzQixHQUFHLElBQUksZUFBUyxFQUFFLENBQUE7UUFDeEMsbUJBQWMsR0FBRyxJQUFJLGVBQVMsRUFBZSxDQUFBO1FBVXpDLDBCQUEwQjtRQUMxQixJQUFJLENBQUMsaUJBQWlCLEdBQUcsSUFBSSxnREFBZ0IsQ0FBQztZQUMxQyxPQUFPLEVBQUUsVUFBVSxDQUFDLE9BQU87WUFDM0IsS0FBSyxFQUFFLFVBQVUsQ0FBQyxLQUFLO1NBQzFCLENBQUMsQ0FBQTtRQUVGLG9CQUFvQjtRQUNwQixJQUFJLENBQUMsV0FBVyxHQUFHLElBQUksc0NBQVcsQ0FBQztZQUMvQixLQUFLLEVBQUUsVUFBVSxDQUFDLEtBQUs7WUFDdkIsTUFBTSxFQUFFLFVBQVUsQ0FBQyxVQUFVO1lBQzdCLGdCQUFnQixFQUFFLElBQUksQ0FBQyxpQkFBaUI7U0FDM0MsQ0FBQyxDQUFBO1FBRUYsZ0JBQWdCO1FBQ2hCLElBQUksQ0FBQyxTQUFTLEdBQUcsSUFBSSxnQ0FBUSxDQUFDO1lBQzFCLFVBQVUsRUFBRSxVQUFVLENBQUMsVUFBVTtZQUNqQyxhQUFhLEVBQUUsVUFBVSxDQUFDLGFBQWE7WUFDdkMsWUFBWSxFQUFFLElBQUk7U0FDckIsQ0FBQyxDQUFBO1FBRUYsSUFBSSxDQUFDLFNBQVMsQ0FBQTtJQUNsQixDQUFDO0lBRUQ7O09BRUc7SUFDSCxjQUFjLENBQUMsYUFBcUIsRUFBRSxhQUFpQyxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUU7UUFDbkYsSUFBSSxJQUFJLEdBQUcsQ0FBQyxDQUFDLEtBQUssRUFBRSxDQUFBO1FBQ3BCLElBQUksb0JBQW9CLEdBQUcsSUFBSSxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxXQUFXO1lBQzVELE1BQU0sQ0FBQyxXQUFXLENBQUMsVUFBVSxLQUFLLGFBQWEsQ0FBQTtRQUNuRCxDQUFDLENBQUMsQ0FBQTtRQUNGLEVBQUUsQ0FBQyxDQUFDLG9CQUFvQixZQUFZLHNDQUFXLENBQUMsQ0FBQyxDQUFDO1lBQzlDLG9CQUFvQixDQUFDLEtBQUssRUFBRTtpQkFDdkIsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQTtRQUMzQixDQUFDO1FBQUMsSUFBSSxDQUFDLENBQUM7WUFDSixvQkFBb0IsR0FBRyxJQUFJLHNDQUFXLENBQUM7Z0JBQ25DLFlBQVksRUFBRSxJQUFJO2dCQUNsQixVQUFVLEVBQUUsYUFBYTthQUM1QixDQUFDLENBQUE7WUFDRixvQkFBb0IsQ0FBQyxLQUFLLEVBQUU7aUJBQ3ZCLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUE7UUFDM0IsQ0FBQztRQUNELE1BQU0sQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFBO0lBQ3ZCLENBQUM7SUFFRDs7T0FFRztJQUNILG9CQUFvQjtJQUVwQixDQUFDO0lBRUQ7O09BRUc7SUFDSCxNQUFNO0lBRU4sQ0FBQztDQUNKO0FBdEVELG9CQXNFQyJ9 \ No newline at end of file diff --git a/dist/cert.classes.certificate.d.ts b/dist/cert.classes.certificate.d.ts new file mode 100644 index 0000000..29b9975 --- /dev/null +++ b/dist/cert.classes.certificate.d.ts @@ -0,0 +1,48 @@ +/// +import * as q from 'q'; +import * as plugins from './cert.plugins'; +import { Cert } from './cert.classes.cert'; +export interface ICertificateFsConfig { + domainName: string; + creationTime: number; + expiryTime: number; +} +export interface ICertificateConstructorOptions { + domainName: string; + certInstance: Cert; +} +export declare type TCertificateStatus = 'unregistered' | 'valid' | 'expiring' | 'expired'; +export declare class Certificate { + domainName: string; + certInstance: Cert; + domainData: plugins.smartstring.Domain; + creationDate: Date; + expiryDate: Date; + publicKey: string; + privKey: string; + /** + * run when creating a new instance of Certificate + */ + constructor(optionsArg: ICertificateConstructorOptions); + /** + * the status of the Certificate + */ + readonly status: TCertificateStatus; + readonly sameZoneRequesting: boolean; + /** + * schedule a retry of certificate request + */ + scheduleRetry(): q.Promise<{}>; + /** + * renew certificate if needed + */ + renew(force?: boolean): q.Promise<{}>; + /** + * syncFs syncs the certificate with disk + */ + syncFs(): void; + /** + * deletes the certificate + */ + delete(): void; +} diff --git a/dist/cert.classes.certificate.js b/dist/cert.classes.certificate.js new file mode 100644 index 0000000..6aee6f2 --- /dev/null +++ b/dist/cert.classes.certificate.js @@ -0,0 +1,103 @@ +"use strict"; +const q = require("q"); +const plugins = require("./cert.plugins"); +class Certificate { + /** + * run when creating a new instance of Certificate + */ + constructor(optionsArg) { + this.creationDate = null; + this.expiryDate = null; + this.publicKey = null; + this.privKey = null; + this.domainName = optionsArg.domainName; + this.domainData = new plugins.smartstring.Domain(this.domainName); + this.certInstance = optionsArg.certInstance; + } + /** + * the status of the Certificate + */ + get status() { + let validTimeRemaining = 0; + if (this.creationDate !== null && this.expiryDate !== null) { + validTimeRemaining = this.expiryDate.getTime() - Date.now(); + } + let MonthMilliseconds = 2629746000; + if (this.publicKey === null || this.privKey === null) { + return 'unregistered'; + } + else if (validTimeRemaining >= MonthMilliseconds) { + return 'valid'; + } + else if (validTimeRemaining < MonthMilliseconds && validTimeRemaining >= 0) { + return 'expiring'; + } + else { + return 'expired'; + } + } + get sameZoneRequesting() { + return this.certInstance.domainStringRequestMap.checkMinimatch('*' + this.domainData.zoneName); + } + /** + * schedule a retry of certificate request + */ + scheduleRetry() { + let done = plugins.q.defer(); + setTimeout(() => { + this.renew() + .then(done.resolve); + }, 60000); + return done.promise; + } + /** + * renew certificate if needed + */ + renew(force = false) { + let done = q.defer(); + if (this.status === 'valid') { + plugins.beautylog.log('Certificate still valid for more than 1 month, so it is not renewed now'); + done.resolve(); + } + else if (this.status === 'expiring' || this.status === 'expired' || this.status === 'unregistered') { + plugins.beautylog.info('Certificate not valid currently, going to renew now!'); + if (this.sameZoneRequesting) { + this.certInstance.domainStringRequestMap.registerUntilTrue(() => { + return !this.sameZoneRequesting; + }, () => { + this.renew().then(done.resolve); + }); + } + else { + this.certInstance.letsencrypt.registerDomain(this.domainName) + .then(() => { + return this.syncFs(); + }) + .then(() => { + done.resolve(); + }).catch((err) => { console.log(err); }); + } + } + else { + throw Error(`weird status for certificate with domain name ${this.domainName}`); + } + done.resolve(); + return done.promise; + } + /** + * syncFs syncs the certificate with disk + */ + syncFs() { + let configJsonMemory = { + domainName: this.domainName, + creationTime: this.creationDate.getTime(), + expiryTime: this.expiryDate.getTime() + }; + } + /** + * deletes the certificate + */ + delete() { } +} +exports.Certificate = Certificate; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2VydC5jbGFzc2VzLmNlcnRpZmljYXRlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvY2VydC5jbGFzc2VzLmNlcnRpZmljYXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSx1QkFBc0I7QUFFdEIsMENBQXlDO0FBcUJ6QztJQVNJOztPQUVHO0lBQ0gsWUFBWSxVQUEwQztRQVJ0RCxpQkFBWSxHQUFTLElBQUksQ0FBQTtRQUN6QixlQUFVLEdBQVMsSUFBSSxDQUFBO1FBQ3ZCLGNBQVMsR0FBVyxJQUFJLENBQUE7UUFDeEIsWUFBTyxHQUFXLElBQUksQ0FBQTtRQU1sQixJQUFJLENBQUMsVUFBVSxHQUFHLFVBQVUsQ0FBQyxVQUFVLENBQUE7UUFDdkMsSUFBSSxDQUFDLFVBQVUsR0FBRyxJQUFJLE9BQU8sQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQTtRQUNqRSxJQUFJLENBQUMsWUFBWSxHQUFHLFVBQVUsQ0FBQyxZQUFZLENBQUE7SUFDL0MsQ0FBQztJQUVEOztPQUVHO0lBQ0gsSUFBSSxNQUFNO1FBQ04sSUFBSSxrQkFBa0IsR0FBVyxDQUFDLENBQUE7UUFDbEMsRUFBRSxDQUFDLENBQUMsSUFBSSxDQUFDLFlBQVksS0FBSyxJQUFJLElBQUksSUFBSSxDQUFDLFVBQVUsS0FBSyxJQUFJLENBQUMsQ0FBQyxDQUFDO1lBQ3hELGtCQUFrQixHQUFHLElBQUksQ0FBQyxVQUFVLENBQUMsT0FBTyxFQUFFLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFBO1FBQ2hFLENBQUM7UUFDRCxJQUFJLGlCQUFpQixHQUFHLFVBQVUsQ0FBQTtRQUNsQyxFQUFFLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxLQUFLLElBQUksSUFBSSxJQUFJLENBQUMsT0FBTyxLQUFLLElBQUksQ0FBQyxDQUFDLENBQUM7WUFDbkQsTUFBTSxDQUFDLGNBQWMsQ0FBQTtRQUN6QixDQUFDO1FBQUMsSUFBSSxD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 \ No newline at end of file diff --git a/dist/cert.classes.certrepo.d.ts b/dist/cert.classes.certrepo.d.ts new file mode 100644 index 0000000..3937125 --- /dev/null +++ b/dist/cert.classes.certrepo.d.ts @@ -0,0 +1,26 @@ +/// +import * as q from 'q'; +import { Cert } from './cert.classes.cert'; +export interface ICertRepoConstructorOptions { + sslDirPath: string; + gitOriginRepo: string; + certInstance: Cert; +} +export declare class CertRepo { + private _sslDirPath; + private _gitOriginRepo; + private _certInstance; + constructor(optionsArg: ICertRepoConstructorOptions); + /** + * syncs an objectmap of Certificates with repo + */ + syncFs(): q.Promise<{}>; + /** + * Pulls already requested certificates from git origin + */ + sslGitOriginPull: () => void; + /** + * Pushes all new requested certificates to git origin + */ + sslGitOriginAddCommitPush: () => void; +} diff --git a/dist/cert.classes.certrepo.js b/dist/cert.classes.certrepo.js new file mode 100644 index 0000000..9581f91 --- /dev/null +++ b/dist/cert.classes.certrepo.js @@ -0,0 +1,49 @@ +"use strict"; +const q = require("q"); +const plugins = require("./cert.plugins"); +const paths = require("./cert.paths"); +class CertRepo { + constructor(optionsArg) { + /** + * Pulls already requested certificates from git origin + */ + this.sslGitOriginPull = () => { + if (this._gitOriginRepo) { + plugins.smartgit.pull(this._sslDirPath, 'origin', 'master'); + } + }; + /** + * Pushes all new requested certificates to git origin + */ + this.sslGitOriginAddCommitPush = () => { + if (this._gitOriginRepo) { + plugins.smartgit.add.addAll(this._sslDirPath); + plugins.smartgit.commit(this._sslDirPath, 'added new SSL certificates and deleted obsolete ones.'); + plugins.smartgit.push(this._sslDirPath, 'origin', 'master'); + } + }; + this._sslDirPath = optionsArg.sslDirPath; + this._gitOriginRepo = optionsArg.gitOriginRepo; + this._certInstance = optionsArg.certInstance; + // setup sslDir + if (!this._sslDirPath) { + this._sslDirPath = paths.defaultSslDir; + } + // setup Git + if (this._gitOriginRepo) { + plugins.smartgit.init(this._sslDirPath); + plugins.smartgit.remote.add(this._sslDirPath, 'origin', this._gitOriginRepo); + this.sslGitOriginPull(); + } + } + /** + * syncs an objectmap of Certificates with repo + */ + syncFs() { + let done = q.defer(); + done.resolve(); + return done.promise; + } +} +exports.CertRepo = CertRepo; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2VydC5jbGFzc2VzLmNlcnRyZXBvLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvY2VydC5jbGFzc2VzLmNlcnRyZXBvLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSx1QkFBc0I7QUFFdEIsMENBQXlDO0FBQ3pDLHNDQUFxQztBQVdyQztJQUlJLFlBQVksVUFBdUM7UUEyQm5EOztXQUVHO1FBQ0gscUJBQWdCLEdBQUc7WUFDZixFQUFFLENBQUMsQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDLENBQUMsQ0FBQztnQkFDdEIsT0FBTyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFdBQVcsRUFBRSxRQUFRLEVBQUUsUUFBUSxDQUFDLENBQUE7WUFDL0QsQ0FBQztRQUNMLENBQUMsQ0FBQTtRQUVEOztXQUVHO1FBQ0gsOEJBQXlCLEdBQUc7WUFDeEIsRUFBRSxDQUFDLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxDQUFDLENBQUM7Z0JBQ3RCLE9BQU8sQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUE7Z0JBQzdDLE9BQU8sQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxXQUFXLEVBQUUsdURBQXVELENBQUMsQ0FBQTtnQkFDbEcsT0FBTyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFdBQVcsRUFBRSxRQUFRLEVBQUUsUUFBUSxDQUFDLENBQUE7WUFDL0QsQ0FBQztRQUNMLENBQUMsQ0FBQTtRQTVDRyxJQUFJLENBQUMsV0FBVyxHQUFHLFVBQVUsQ0FBQyxVQUFVLENBQUE7UUFDeEMsSUFBSSxDQUFDLGNBQWMsR0FBRyxVQUFVLENBQUMsYUFBYSxDQUFBO1FBQzlDLElBQUksQ0FBQyxhQUFhLEdBQUcsVUFBVSxDQUFDLFlBQVksQ0FBQTtRQUU1QyxlQUFlO1FBQ2YsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUEsQ0FBQztZQUNuQixJQUFJLENBQUMsV0FBVyxHQUFHLEtBQUssQ0FBQyxhQUFhLENBQUE7UUFDMUMsQ0FBQztRQUVELFlBQVk7UUFDWixFQUFFLENBQUMsQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDLENBQUMsQ0FBQztZQUN0QixPQUFPLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUE7WUFDdkMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxXQUFXLEVBQUUsUUFBUSxFQUFFLElBQUksQ0FBQyxjQUFjLENBQUMsQ0FBQTtZQUM1RSxJQUFJLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQTtRQUMzQixDQUFDO0lBQ0wsQ0FBQztJQUVEOztPQUVHO0lBQ0gsTUFBTTtRQUNGLElBQUksSUFBSSxHQUFHLENBQUMsQ0FBQyxLQUFLLEVBQUUsQ0FBQTtRQUNwQixJQUFJLENBQUMsT0FBTyxFQUFFLENBQUE7UUFDZCxNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQTtJQUN2QixDQUFDO0NBcUJKO0FBbERELDRCQWtEQyJ9 \ No newline at end of file diff --git a/dist/cert.classes.challengehandler.d.ts b/dist/cert.classes.challengehandler.d.ts new file mode 100644 index 0000000..b2da280 --- /dev/null +++ b/dist/cert.classes.challengehandler.d.ts @@ -0,0 +1,20 @@ +/// +export interface IChallengehandlerConstructorOptions { + cfEmail: string; + cfKey: string; +} +/** + * class ChallengeHandler handles challenges + */ +export declare class ChallengeHandler { + private _cfInstance; + constructor(optionsArg: IChallengehandlerConstructorOptions); + /** + * set a challenge + */ + setChallenge(domainNameArg: string, challengeArg: string): Q.Promise<{}>; + /** + * cleans a challenge + */ + cleanChallenge(domainNameArg: any): Q.Promise<{}>; +} diff --git a/dist/cert.classes.challengehandler.js b/dist/cert.classes.challengehandler.js new file mode 100644 index 0000000..4657aa5 --- /dev/null +++ b/dist/cert.classes.challengehandler.js @@ -0,0 +1,75 @@ +"use strict"; +const plugins = require("./cert.plugins"); +/** + * class ChallengeHandler handles challenges + */ +class ChallengeHandler { + constructor(optionsArg) { + this._cfInstance = new plugins.cflare.CflareAccount(); + this._cfInstance.auth({ + email: optionsArg.cfEmail, + key: optionsArg.cfKey + }); + } + /** + * set a challenge + */ + setChallenge(domainNameArg, challengeArg) { + let done = plugins.q.defer(); + plugins.beautylog.log('setting challenge for ' + domainNameArg); + this._cfInstance.createRecord(prefixName(domainNameArg), 'TXT', challengeArg).then(() => { + plugins.beautylog.ok('Challenge has been set!'); + plugins.beautylog.info('We need to cool down to let DNS propagate to edge locations!'); + cooldown().then(() => { + done.resolve(); + }); + }); + return done.promise; + } + /** + * cleans a challenge + */ + cleanChallenge(domainNameArg) { + let done = plugins.q.defer(); + plugins.beautylog.log('cleaning challenge for ' + domainNameArg); + this._cfInstance.removeRecord(prefixName(domainNameArg), 'TXT'); + cooldown().then(() => { + done.resolve(); + }); + return done.promise; + } +} +exports.ChallengeHandler = ChallengeHandler; +/** + * cooldown timer for letting DNS settle before answering the challengerequest + */ +let cooldown = () => { + let done = plugins.q.defer(); + let cooldowntime = 60000; + let passedTime = 0; + plugins.beautylog.log('Cooling down! ' + (cooldowntime / 1000).toString() + ' seconds left'); + let coolDownCounter = () => { + setTimeout(() => { + if (cooldowntime <= passedTime) { + plugins.beautylog.ok('Cooled down!'); + done.resolve(); + } + else { + passedTime = passedTime + 5000; + plugins.beautylog.log('Cooling down! ' + + ((cooldowntime - passedTime) / 1000).toString() + + ' seconds left'); + coolDownCounter(); + } + }, 5000); + }; + coolDownCounter(); + return done.promise; +}; +/** + * prefix a domain name to make sure it complies with letsencrypt + */ +let prefixName = (domainNameArg) => { + return '_acme-challenge.' + domainNameArg; +}; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2VydC5jbGFzc2VzLmNoYWxsZW5nZWhhbmRsZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9jZXJ0LmNsYXNzZXMuY2hhbGxlbmdlaGFuZGxlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsMENBQXlDO0FBUXpDOztHQUVHO0FBQ0g7SUFFSSxZQUFZLFVBQStDO1FBQ3ZELElBQUksQ0FBQyxXQUFXLEdBQUcsSUFBSSxPQUFPLENBQUMsTUFBTSxDQUFDLGFBQWEsRUFBRSxDQUFBO1FBQ3JELElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDO1lBQ2xCLEtBQUssRUFBRSxVQUFVLENBQUMsT0FBTztZQUN6QixHQUFHLEVBQUUsVUFBVSxDQUFDLEtBQUs7U0FDeEIsQ0FBQyxDQUFBO0lBQ04sQ0FBQztJQUVEOztPQUVHO0lBQ0gsWUFBWSxDQUFDLGFBQXFCLEVBQUUsWUFBb0I7UUFDcEQsSUFBSSxJQUFJLEdBQUcsT0FBTyxDQUFDLENBQUMsQ0FBQyxLQUFLLEVBQUUsQ0FBQTtRQUM1QixPQUFPLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyx3QkFBd0IsR0FBRyxhQUFhLENBQUMsQ0FBQTtRQUMvRCxJQUFJLENBQUMsV0FBVyxDQUFDLFlBQVksQ0FBQyxVQUFVLENBQUMsYUFBYSxDQUFDLEVBQUUsS0FBSyxFQUFFLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQztZQUMvRSxPQUFPLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQyx5QkFBeUIsQ0FBQyxDQUFBO1lBQy9DLE9BQU8sQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLDhEQUE4RCxDQUFDLENBQUE7WUFDdEYsUUFBUSxFQUFFLENBQUMsSUFBSSxDQUFDO2dCQUNaLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQTtZQUNsQixDQUFDLENBQUMsQ0FBQTtRQUNOLENBQUMsQ0FBQyxDQUFBO1FBQ0YsTUFBTSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUE7SUFDdkIsQ0FBQztJQUVEOztPQUVHO0lBQ0gsY0FBYyxDQUFDLGFBQWE7UUFDeEIsSUFBSSxJQUFJLEdBQUcsT0FBTyxDQUFDLENBQUMsQ0FBQyxLQUFLLEVBQUUsQ0FBQTtRQUM1QixPQUFPLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyx5QkFBeUIsR0FBRyxhQUFhLENBQUMsQ0FBQTtRQUNoRSxJQUFJLENBQUMsV0FBVyxDQUFDLFlBQVksQ0FBQyxVQUFVLENBQUMsYUFBYSxDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUE7UUFDL0QsUUFBUSxFQUFFLENBQUMsSUFBSSxDQUFDO1lBQ1osSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFBO1FBQ2xCLENBQUMsQ0FBQyxDQUFBO1FBQ0YsTUFBTSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUE7SUFDdkIsQ0FBQztDQUNKO0FBdENELDRDQXNDQztBQUVEOztHQUVHO0FBQ0gsSUFBSSxRQUFRLEdBQUc7SUFDWCxJQUFJLElBQUksR0FBRyxPQUFPLENBQUMsQ0FBQyxDQUFDLEtBQUssRUFBRSxDQUFBO0lBQzVCLElBQUksWUFBWSxHQUFHLEtBQUssQ0FBQTtJQUN4QixJQUFJLFVBQVUsR0FBRyxDQUFDLENBQUE7SUFDbEIsT0FBTyxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsZ0JBQWdCLEdBQUcsQ0FBQyxZQUFZLEdBQUcsSUFBSSxDQUFDLENBQUMsUUFBUSxFQUFFLEdBQUcsZUFBZSxDQUFDLENBQUE7SUFDNUYsSUFBSSxlQUFlLEdBQUc7UUFDbEIsVUFBVSxDQUFDO1lBQ1AsRUFBRSxDQUFDLENBQUMsWUFBWSxJQUFJLFVBQVUsQ0FBQyxDQUFDLENBQUM7Z0JBQzdCLE9BQU8sQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDLGNBQWMsQ0FBQyxDQUFBO2dCQUNwQyxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUE7WUFDbEIsQ0FBQztZQUFDLElBQUksQ0FBQyxDQUFDO2dCQUNKLFVBQVUsR0FBRyxVQUFVLEdBQUcsSUFBSSxDQUFBO2dCQUM5QixPQUFPLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxnQkFBZ0I7c0JBQ2hDLENBQUMsQ0FBQyxZQUFZLEdBQUcsVUFBVSxDQUFDLEdBQUcsSUFBSSxDQUFDLENBQUMsUUFBUSxFQUFFO3NCQUMvQyxlQUFlLENBQ3BCLENBQUE7Z0JBQ0QsZUFBZSxFQUFFLENBQUE7WUFDckIsQ0FBQztRQUNMLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQTtJQUNaLENBQUMsQ0FBQTtJQUNELGVBQWUsRUFBRSxDQUFBO0lBQ2pCLE1BQU0sQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFBO0FBQ3ZCLENBQUMsQ0FBQTtBQUVEOztHQUVHO0FBQ0gsSUFBSSxVQUFVLEdBQUcsQ0FBQyxhQUFxQjtJQUNuQyxNQUFNLENBQUMsa0JBQWtCLEdBQUcsYUFBYSxDQUFBO0FBQzdDLENBQUMsQ0FBQSJ9 \ No newline at end of file diff --git a/dist/cert.classes.letsencrypt.d.ts b/dist/cert.classes.letsencrypt.d.ts new file mode 100644 index 0000000..5f62936 --- /dev/null +++ b/dist/cert.classes.letsencrypt.d.ts @@ -0,0 +1,27 @@ +/// +import * as q from 'q'; +import { ChallengeHandler } from './cert.classes.challengehandler'; +export declare type TLeEnv = 'production' | 'staging'; +export interface ILetsencryptConstructorOptions { + leEnv: TLeEnv; + challengeHandler: ChallengeHandler; + sslDir: string; +} +export declare class Letsencrypt { + leEnv: TLeEnv; + challengeHandler: ChallengeHandler; + sslDir: string; + private _leInstance; + private _leServerUrl; + constructor(optionsArg: ILetsencryptConstructorOptions); + /** + * register a domain + */ + registerDomain(domainNameArg: string): q.Promise<{}>; + private _leCopyToDestination(domainNameArg); + /** + * translates to the format expected by letsencrypt node implementation + */ + private _leChallengeHandler(); + private _leAgree(opts, agreeCb); +} diff --git a/dist/cert.classes.letsencrypt.js b/dist/cert.classes.letsencrypt.js new file mode 100644 index 0000000..9d5761c --- /dev/null +++ b/dist/cert.classes.letsencrypt.js @@ -0,0 +1,114 @@ +"use strict"; +const q = require("q"); +let letsencrypt = require('letsencrypt'); +const plugins = require("./cert.plugins"); +const paths = require("./cert.paths"); +class Letsencrypt { + constructor(optionsArg) { + // determine leEnv + this.leEnv = optionsArg.leEnv; + this.challengeHandler = optionsArg.challengeHandler; + this.sslDir = optionsArg.sslDir; + // set letsencrypt environment + if (this.leEnv === 'production') { + this._leServerUrl = letsencrypt.productionServerUrl; + } + else if (this.leEnv === 'staging') { + this._leServerUrl = letsencrypt.stagingServerUrl; + } + // create leInstance + this._leInstance = letsencrypt.create({ + server: this._leServerUrl, + challenges: { 'dns-01': this._leChallengeHandler() }, + challengeType: 'dns-01', + configDir: paths.leConfigDir, + privkeyPath: ':configDir/live/:hostname/privkey.pem', + fullchainPath: ':configDir/live/:hostname/fullchain.pem', + certPath: ':config/live/:hostname/cert.pem', + chainPath: ':config/live/:hostname/chain.pem', + agreeToTerms: this._leAgree, + debug: true + }); + } + /** + * register a domain + */ + registerDomain(domainNameArg) { + plugins.beautylog.log(`trying to register domain ${domainNameArg}`); + let done = q.defer(); + console.log('test'); + this._leInstance.register({ + domains: [domainNameArg], + email: 'domains@lossless.org', + agreeTos: true, + rsaKeySize: 2048, + challengeType: 'dns-01' + }).then((results) => { + plugins.beautylog.success(`Got certificates for ${domainNameArg}`); + this._leCopyToDestination(domainNameArg).then(done.resolve); + }, (err) => { + console.error('[Error]: node-letsencrypt/examples/standalone'); + console.error(err.stack); + done.resolve(); + }).catch(err => { console.log(err); }); + return done.promise; + } + // -------------------------------------------- + // Translate for official letsencrypt stuff + // -------------------------------------------- + _leCopyToDestination(domainNameArg) { + let done = q.defer(); + return done.promise; + } + /** + * translates to the format expected by letsencrypt node implementation + */ + _leChallengeHandler() { + return { + getOptions: (...args) => { + return { + debug: true + }; + }, + set: (args, domain, challenge, keyAuthorization, cb) => { + let keyAuthDigest = require('crypto') + .createHash('sha256').update(keyAuthorization || '') + .digest('base64') + .replace(/\+/g, '-') + .replace(/\//g, '_') + .replace(/=+$/g, ''); + this.challengeHandler.setChallenge(domain, keyAuthDigest) + .then(() => { + cb(); + }); + }, + get: (defaults, domain, challenge, cb) => { + console.log(defaults); + console.log(domain); + console.log(challenge); + cb(); + }, + remove: (args, domain, challenge, cb) => { + this.challengeHandler.cleanChallenge(domain) + .then(() => { + cb(); + }); + }, + loopback: (args, domain, challenge, cb) => { + console.log(args); + console.log(domain); + console.log(challenge); + cb(); + }, + test: (defaults, domain, challenge, cb) => { + cb(); + } + }; + } + _leAgree(opts, agreeCb) { + // opts = { email, domains, tosUrl } + agreeCb(null, opts.tosUrl); + } +} +exports.Letsencrypt = Letsencrypt; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2VydC5jbGFzc2VzLmxldHNlbmNyeXB0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvY2VydC5jbGFzc2VzLmxldHNlbmNyeXB0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSx1QkFBc0I7QUFDdEIsSUFBSSxXQUFXLEdBQUcsT0FBTyxDQUFDLGFBQWEsQ0FBQyxDQUFBO0FBRXhDLDBDQUF5QztBQUN6QyxzQ0FBcUM7QUFZckM7SUFRSSxZQUFZLFVBQTBDO1FBQ2xELGtCQUFrQjtRQUNsQixJQUFJLENBQUMsS0FBSyxHQUFHLFVBQVUsQ0FBQyxLQUFLLENBQUE7UUFDN0IsSUFBSSxDQUFDLGdCQUFnQixHQUFHLFVBQVUsQ0FBQyxnQkFBZ0IsQ0FBQTtRQUNuRCxJQUFJLENBQUMsTUFBTSxHQUFHLFVBQVUsQ0FBQyxNQUFNLENBQUE7UUFFL0IsOEJBQThCO1FBQzlCLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxLQUFLLEtBQUssWUFBWSxDQUFDLENBQUMsQ0FBQztZQUM5QixJQUFJLENBQUMsWUFBWSxHQUFHLFdBQVcsQ0FBQyxtQkFBbUIsQ0FBQTtRQUN2RCxDQUFDO1FBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxLQUFLLEtBQUssU0FBUyxDQUFDLENBQUMsQ0FBQztZQUNsQyxJQUFJLENBQUMsWUFBWSxHQUFHLFdBQVcsQ0FBQyxnQkFBZ0IsQ0FBQTtRQUNwRCxDQUFDO1FBRUQsb0JBQW9CO1FBQ3BCLElBQUksQ0FBQyxXQUFXLEdBQUcsV0FBVyxDQUFDLE1BQU0sQ0FBQztZQUNsQyxNQUFNLEVBQUUsSUFBSSxDQUFDLFlBQVk7WUFDekIsVUFBVSxFQUFFLEVBQUUsUUFBUSxFQUFFLElBQUksQ0FBQyxtQkFBbUIsRUFBRSxFQUFFO1lBQ3BELGFBQWEsRUFBRSxRQUFRO1lBQ3ZCLFNBQVMsRUFBRSxLQUFLLENBQUMsV0FBVztZQUM1QixXQUFXLEVBQUUsdUNBQXVDO1lBQ3BELGFBQWEsRUFBRSx5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 \ No newline at end of file diff --git a/dist/cert.hook.d.ts b/dist/cert.hook.d.ts deleted file mode 100644 index e69de29..0000000 diff --git a/dist/cert.hook.js b/dist/cert.hook.js deleted file mode 100755 index 422ca6f..0000000 --- a/dist/cert.hook.js +++ /dev/null @@ -1,68 +0,0 @@ -#!/usr/bin/env node -"use strict"; -const plugins = require("./cert.plugins"); -const paths = require("./cert.paths"); -let smartcli = new plugins.smartcli.Smartcli(); -let config = plugins.smartfile.fs.toObjectSync(paths.config); -let cflare = new plugins.cflare.CflareAccount(); -cflare.auth({ - email: config.cfEmail, - key: config.cfKey -}); -let setChallenge = (domainNameArg, challengeArg) => { - let done = plugins.q.defer(); - plugins.beautylog.log("setting challenge for " + domainNameArg); - cflare.createRecord(prefixName(domainNameArg), "TXT", challengeArg).then(() => { - plugins.beautylog.ok("Challenge has been set!"); - plugins.beautylog.info("We need to cool down to let DNS propagate to edge locations!"); - cooldown().then(() => { - done.resolve(); - }); - }); - return done.promise; -}; -let cleanChallenge = (domainNameArg) => { - let done = plugins.q.defer(); - plugins.beautylog.log("cleaning challenge for " + domainNameArg); - cflare.removeRecord(prefixName(domainNameArg), "TXT"); - cooldown().then(() => { - done.resolve(); - }); - return done.promise; -}; -let cooldown = () => { - let done = plugins.q.defer(); - let cooldowntime = 60000; - let passedTime = 0; - plugins.beautylog.log("Cooling down! " + (cooldowntime / 1000).toString() + " seconds left"); - let coolDownCounter = () => { - setTimeout(() => { - if (cooldowntime <= passedTime) { - plugins.beautylog.ok("Cooled down!"); - done.resolve(); - } - else { - passedTime = passedTime + 5000; - plugins.beautylog.log("Cooling down! " + ((cooldowntime - passedTime) / 1000).toString() + " seconds left"); - coolDownCounter(); - } - }, 5000); - }; - coolDownCounter(); - return done.promise; -}; -let prefixName = (domainNameArg) => { - return "_acme-challenge." + domainNameArg; -}; -smartcli.addCommand({ - commandName: "deploy_challenge" -}).then((argv) => { - setChallenge(argv._[1], argv._[3]); -}); -smartcli.addCommand({ - commandName: "clean_challenge" -}).then((argv) => { - cleanChallenge(argv._[1]); -}); -smartcli.startParse(); -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2VydC5ob29rLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvY2VydC5ob29rLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBR0EsMENBQTBDO0FBQzFDLHNDQUFzQztBQUV0QyxJQUFJLFFBQVEsR0FBRyxJQUFJLE9BQU8sQ0FBQyxRQUFRLENBQUMsUUFBUSxFQUFFLENBQUM7QUFFL0MsSUFBSSxNQUFNLEdBQUcsT0FBTyxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUMsWUFBWSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQztBQUM3RCxJQUFJLE1BQU0sR0FBRyxJQUFJLE9BQU8sQ0FBQyxNQUFNLENBQUMsYUFBYSxFQUFFLENBQUM7QUFDaEQsTUFBTSxDQUFDLElBQUksQ0FBQztJQUNSLEtBQUssRUFBRSxNQUFNLENBQUMsT0FBTztJQUNyQixHQUFHLEVBQUUsTUFBTSxDQUFDLEtBQUs7Q0FDcEIsQ0FBQyxDQUFDO0FBRUgsSUFBSSxZQUFZLEdBQUcsQ0FBQyxhQUFxQixFQUFFLFlBQW9CO0lBQzNELElBQUksSUFBSSxHQUFHLE9BQU8sQ0FBQyxDQUFDLENBQUMsS0FBSyxFQUFFLENBQUM7SUFDN0IsT0FBTyxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsd0JBQXdCLEdBQUcsYUFBYSxDQUFDLENBQUM7SUFDaEUsTUFBTSxDQUFDLFlBQVksQ0FBQyxVQUFVLENBQUMsYUFBYSxDQUFDLEVBQUUsS0FBSyxFQUFFLFlBQVksQ0FBQyxDQUFDLElBQUksQ0FBQztRQUNyRSxPQUFPLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQyx5QkFBeUIsQ0FBQyxDQUFDO1FBQ2hELE9BQU8sQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLDhEQUE4RCxDQUFDLENBQUM7UUFDdkYsUUFBUSxFQUFFLENBQUMsSUFBSSxDQUFDO1lBQ1osSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDO1FBQ25CLENBQUMsQ0FBQyxDQUFDO0lBQ1AsQ0FBQyxDQUFDLENBQUM7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 \ No newline at end of file diff --git a/dist/cert.paths.d.ts b/dist/cert.paths.d.ts index cf04b3b..dc51658 100644 --- a/dist/cert.paths.d.ts +++ b/dist/cert.paths.d.ts @@ -1,8 +1,4 @@ -export declare let certDir: string; -export declare let defaultSslDir: string; +export declare let projectDir: string; export declare let assetDir: string; -export declare let accountsDir: string; -export declare let certHook: string; -export declare let config: string; -export declare let leShConfig: string; -export declare let letsencryptSh: string; +export declare let defaultSslDir: string; +export declare let leConfigDir: string; diff --git a/dist/cert.paths.js b/dist/cert.paths.js index 680e5f5..616a02d 100644 --- a/dist/cert.paths.js +++ b/dist/cert.paths.js @@ -1,13 +1,10 @@ "use strict"; const plugins = require("./cert.plugins"); -//dirs -exports.certDir = plugins.path.join(__dirname, "assets/certs"); -exports.defaultSslDir = plugins.path.join(__dirname, "assets/defaultSslDir"); -exports.assetDir = plugins.path.join(__dirname, "assets/"); -exports.accountsDir = plugins.path.join(__dirname, "assets/accounts/"); -// files -exports.certHook = plugins.path.join(__dirname, "cert.hook.js"); -exports.config = plugins.path.join(__dirname, "assets/config.json"); -exports.leShConfig = plugins.path.join(__dirname, "assets/leshconfig.json"); -exports.letsencryptSh = plugins.path.join(__dirname, "assets/letsencrypt.sh"); -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2VydC5wYXRocy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL2NlcnQucGF0aHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLDBDQUEwQztBQUUxQyxNQUFNO0FBQ0ssUUFBQSxPQUFPLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFDLGNBQWMsQ0FBQyxDQUFDO0FBQ3RELFFBQUEsYUFBYSxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBQyxzQkFBc0IsQ0FBQyxDQUFDO0FBQ3BFLFFBQUEsUUFBUSxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBQyxTQUFTLENBQUMsQ0FBQztBQUNsRCxRQUFBLFdBQVcsR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUMsa0JBQWtCLENBQUMsQ0FBQztBQUV6RSxRQUFRO0FBQ0csUUFBQSxRQUFRLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFDLGNBQWMsQ0FBQyxDQUFDO0FBQ3ZELFFBQUEsTUFBTSxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBQyxvQkFBb0IsQ0FBQyxDQUFDO0FBQzNELFFBQUEsVUFBVSxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBQyx3QkFBd0IsQ0FBQyxDQUFDO0FBQ25FLFFBQUEsYUFBYSxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBQyx1QkFBdUIsQ0FBQyxDQUFDIn0= \ No newline at end of file +// dirs +exports.projectDir = plugins.path.join(__dirname, '../'); +exports.assetDir = plugins.path.join(exports.projectDir, 'assets'); +exports.defaultSslDir = plugins.path.join(exports.assetDir, 'defaultSslDir'); +exports.leConfigDir = plugins.path.join(exports.assetDir, 'letsencrypt'); +plugins.smartfile.fs.ensureDirSync(exports.leConfigDir); +plugins.smartfile.fs.ensureDirSync(exports.defaultSslDir); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2VydC5wYXRocy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL2NlcnQucGF0aHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLDBDQUF5QztBQUV6QyxPQUFPO0FBQ0ksUUFBQSxVQUFVLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFDLEtBQUssQ0FBQyxDQUFBO0FBQy9DLFFBQUEsUUFBUSxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLGtCQUFVLEVBQUMsUUFBUSxDQUFDLENBQUE7QUFDakQsUUFBQSxhQUFhLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsZ0JBQVEsRUFBQyxlQUFlLENBQUMsQ0FBQTtBQUMzRCxRQUFBLFdBQVcsR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxnQkFBUSxFQUFDLGFBQWEsQ0FBQyxDQUFBO0FBQ2xFLE9BQU8sQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDLGFBQWEsQ0FBQyxtQkFBVyxDQUFDLENBQUE7QUFDL0MsT0FBTyxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUMsYUFBYSxDQUFDLHFCQUFhLENBQUMsQ0FBQSJ9 \ No newline at end of file diff --git a/dist/cert.plugins.d.ts b/dist/cert.plugins.d.ts index 4523d89..1d5bc0c 100644 --- a/dist/cert.plugins.d.ts +++ b/dist/cert.plugins.d.ts @@ -1,12 +1,13 @@ -import "typings-global"; -export import beautylog = require("beautylog"); -export import cflare = require("cflare"); -export declare let fs: any; -export import lik = require("lik"); -export import path = require("path"); -export import q = require("q"); -export import shelljs = require("shelljs"); -export import smartcli = require("smartcli"); -export import smartfile = require("smartfile"); -export import smartgit = require("smartgit"); -export import smartstring = require("smartstring"); +import 'typings-global'; +import * as beautylog from 'beautylog'; +import * as cflare from 'cflare'; +declare let fs: any; +import * as lik from 'lik'; +import * as path from 'path'; +import * as q from 'q'; +import * as shelljs from 'shelljs'; +import * as smartcli from 'smartcli'; +import * as smartfile from 'smartfile'; +import * as smartgit from 'smartgit'; +import * as smartstring from 'smartstring'; +export { beautylog, cflare, fs, lik, path, q, shelljs, smartcli, smartfile, smartgit, smartstring }; diff --git a/dist/cert.plugins.js b/dist/cert.plugins.js index a943e99..b8205f1 100644 --- a/dist/cert.plugins.js +++ b/dist/cert.plugins.js @@ -1,14 +1,25 @@ "use strict"; require("typings-global"); -exports.beautylog = require("beautylog"); -exports.cflare = require("cflare"); -exports.fs = require("fs-extra"); -exports.lik = require("lik"); -exports.path = require("path"); -exports.q = require("q"); -exports.shelljs = require("shelljs"); -exports.smartcli = require("smartcli"); -exports.smartfile = require("smartfile"); -exports.smartgit = require("smartgit"); -exports.smartstring = require("smartstring"); -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2VydC5wbHVnaW5zLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvY2VydC5wbHVnaW5zLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSwwQkFBd0I7QUFDeEIseUNBQStDO0FBQy9DLG1DQUF5QztBQUM5QixRQUFBLEVBQUUsR0FBRyxPQUFPLENBQUMsVUFBVSxDQUFDLENBQUM7QUFDcEMsNkJBQW1DO0FBQ25DLCtCQUFxQztBQUNyQyx5QkFBK0I7QUFDL0IscUNBQTJDO0FBQzNDLHVDQUE2QztBQUM3Qyx5Q0FBK0M7QUFDL0MsdUNBQTZDO0FBQzdDLDZDQUFtRCJ9 \ No newline at end of file +const beautylog = require("beautylog"); +exports.beautylog = beautylog; +const cflare = require("cflare"); +exports.cflare = cflare; +let fs = require('fs-extra'); +exports.fs = fs; +const lik = require("lik"); +exports.lik = lik; +const path = require("path"); +exports.path = path; +const q = require("q"); +exports.q = q; +const shelljs = require("shelljs"); +exports.shelljs = shelljs; +const smartcli = require("smartcli"); +exports.smartcli = smartcli; +const smartfile = require("smartfile"); +exports.smartfile = smartfile; +const smartgit = require("smartgit"); +exports.smartgit = smartgit; +const smartstring = require("smartstring"); +exports.smartstring = smartstring; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2VydC5wbHVnaW5zLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvY2VydC5wbHVnaW5zLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSwwQkFBdUI7QUFDdkIsdUNBQXNDO0FBYWxDLG9CQWJRLFNBQVMsQ0FhUjtBQVpiLGlDQUFnQztBQWE1QixpQkFiUSxNQUFNLENBYVI7QUFaVixJQUFJLEVBQUUsR0FBRyxPQUFPLENBQUMsVUFBVSxDQUFDLENBQUE7QUFheEIsYUFiQSxFQUFFLENBYUE7QUFaTiwyQkFBMEI7QUFhdEIsY0FiUSxHQUFHLENBYVI7QUFaUCw2QkFBNEI7QUFheEIsZUFiUSxJQUFJLENBYVI7QUFaUix1QkFBc0I7QUFhbEIsWUFiUSxDQUFDLENBYVI7QUFaTCxtQ0FBa0M7QUFhOUIsa0JBYlEsT0FBTyxDQWFSO0FBWlgscUNBQW9DO0FBYWhDLG1CQWJRLFFBQVEsQ0FhUjtBQVpaLHVDQUFzQztBQWFsQyxvQkFiUSxTQUFTLENBYVI7QUFaYixxQ0FBb0M7QUFhaEMsbUJBYlEsUUFBUSxDQWFSO0FBWlosMkNBQTBDO0FBYXRDLHNCQWJRLFdBQVcsQ0FhUiJ9 \ No newline at end of file diff --git a/dist/index.d.ts b/dist/index.d.ts index b406cb4..5e745a6 100644 --- a/dist/index.d.ts +++ b/dist/index.d.ts @@ -1 +1 @@ -export * from "./cert.classes.cert"; +export * from './cert.classes.cert'; diff --git a/dist/index.js b/dist/index.js index f15dc71..84c0870 100644 --- a/dist/index.js +++ b/dist/index.js @@ -3,4 +3,4 @@ function __export(m) { for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; } __export(require("./cert.classes.cert")); -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7O0FBR0EseUNBQW9DIn0= \ No newline at end of file +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7O0FBQUEseUNBQW1DIn0= \ No newline at end of file diff --git a/dist/install.d.ts b/dist/install.d.ts deleted file mode 100644 index 4b21607..0000000 --- a/dist/install.d.ts +++ /dev/null @@ -1,3 +0,0 @@ -/// -import * as plugins from "./cert.plugins"; -export declare let startInstall: () => plugins.q.Promise<{}>; diff --git a/dist/install.js b/dist/install.js deleted file mode 100644 index 9339416..0000000 --- a/dist/install.js +++ /dev/null @@ -1,19 +0,0 @@ -"use strict"; -const plugins = require("./cert.plugins"); -const paths = require("./cert.paths"); -exports.startInstall = () => { - let done = plugins.q.defer(); - plugins.beautylog.info("installing letsencrypt.sh locally..."); - plugins.fs.ensureDir(plugins.path.join(__dirname, "assets/")); - plugins.smartfile.remote.toFs("https://raw.githubusercontent.com/lukas2511/letsencrypt.sh/master/letsencrypt.sh", paths.letsencryptSh).then(() => { - plugins.beautylog.success("Done!"); - done.resolve(); - }); - return done.promise; -}; -let smartcli = new plugins.smartcli.Smartcli(); -smartcli.addCommand({ - commandName: "install" -}).then(exports.startInstall); -smartcli.startParse(); -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5zdGFsbC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL2luc3RhbGwudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLDBDQUEwQztBQUMxQyxzQ0FBc0M7QUFFM0IsUUFBQSxZQUFZLEdBQUc7SUFDdEIsSUFBSSxJQUFJLEdBQUcsT0FBTyxDQUFDLENBQUMsQ0FBQyxLQUFLLEVBQUUsQ0FBQztJQUM3QixPQUFPLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxzQ0FBc0MsQ0FBQyxDQUFDO0lBRS9ELE9BQU8sQ0FBQyxFQUFFLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxTQUFTLENBQUMsQ0FBQyxDQUFDO0lBQzlELE9BQU8sQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLElBQUksQ0FDekIsa0ZBQWtGLEVBQ2xGLEtBQUssQ0FBQyxhQUFhLENBQ3RCLENBQUMsSUFBSSxDQUFDO1FBQ0gsT0FBTyxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDbkMsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDO0lBQ25CLENBQUMsQ0FBQyxDQUFDO0lBQ0gsTUFBTSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUM7QUFDeEIsQ0FBQyxDQUFDO0FBRUYsSUFBSSxRQUFRLEdBQUcsSUFBSSxPQUFPLENBQUMsUUFBUSxDQUFDLFFBQVEsRUFBRSxDQUFDO0FBQy9DLFFBQVEsQ0FBQyxVQUFVLENBQUM7SUFDaEIsV0FBVyxFQUFDLFNBQVM7Q0FDeEIsQ0FBQyxDQUFDLElBQUksQ0FBQyxvQkFBWSxDQUFDLENBQUM7QUFDdEIsUUFBUSxDQUFDLFVBQVUsRUFBRSxDQUFDIn0= \ No newline at end of file diff --git a/package.json b/package.json index c539194..7090ed0 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,6 @@ "scripts": { "test": "(npm run cleanTest && npmts)", "cleanTest": "(rm -rf ./test/assets)", - "install": "node dist/install.js install", "compile": "(npmts --notest)" }, "repository": { @@ -29,14 +28,13 @@ "dependencies": { "@types/minimatch": "2.x.x", "@types/q": "0.0.32", - "@types/shelljs": "0.x.x", "beautylog": "^6.0.0", "cflare": "0.0.10", "fs-extra": "^0.30.0", + "le-store-certbot": "^2.0.3", "letsencrypt": "^2.1.8", "lik": "^1.0.24", "q": "^1.4.1", - "shelljs": "^0.7.4", "smartcli": "^1.0.10", "smartfile": "^4.0.24", "smartgit": "0.1.9", @@ -44,6 +42,7 @@ "typings-global": "^1.0.14" }, "devDependencies": { + "@types/should": "^8.1.30", "npmts-g": "^5.2.8", "qenv": "^1.1.1", "should": "^11.1.1", diff --git a/test/test.d.ts b/test/test.d.ts index b973566..2fd432a 100644 --- a/test/test.d.ts +++ b/test/test.d.ts @@ -1,2 +1 @@ -import "typings-test"; -import "should"; +import 'typings-test'; diff --git a/test/test.js b/test/test.js index 8beafb8..3cac396 100644 --- a/test/test.js +++ b/test/test.js @@ -1,47 +1,38 @@ "use strict"; require("typings-test"); -require("should"); +const should = require("should"); const qenv_1 = require("qenv"); const path = require("path"); const q = require("q"); -const install_1 = require("../dist/install"); const cert = require("../dist/index"); -let testQenv = new qenv_1.Qenv(process.cwd(), process.cwd() + "/.nogit"); +let testQenv = new qenv_1.Qenv(process.cwd(), process.cwd() + '/.nogit'); let testCert; -describe("cert", function () { - describe("install", function () { - it("should download letsencrypt.sh", function (done) { - this.timeout(5000); - install_1.startInstall().then(() => { - done(); - }); - }); - }); - describe("Cert", function () { - it("should create a new Cert object from class", function () { +describe('cert', function () { + describe('Cert', function () { + it('should create a new Cert object from class', function () { this.timeout(40000); testCert = new cert.Cert({ cfEmail: process.env.CF_EMAIL, cfKey: process.env.CF_KEY, - sslDir: path.join(process.cwd(), "test/assets"), - gitOriginRepo: "git@gitlab.com:sandboxzone/sandbox-sslorigin.git", - testMode: true + sslDirPath: path.join(process.cwd(), 'test/assets'), + gitOriginRepo: 'git@gitlab.com:sandboxzone/sandbox-sslorigin.git', + leEnv: 'staging' }); - testCert.should.be.instanceof(cert.Cert); + should(testCert).be.instanceof(cert.Cert); }); - it("should get a valid certificate", function (done) { + it('should get a valid certificate', function (done) { this.timeout(1200000); let promiseArray = []; function getRandomArbitrary(min, max) { return Math.floor(Math.random() * (max - min) + min); } - promiseArray.push(testCert.getDomainCert(`testing${getRandomArbitrary(1, 100000)}.bleu.de`)); - promiseArray.push(testCert.getDomainCert(`testing${getRandomArbitrary(1, 100000)}.bleu.de`)); - promiseArray.push(testCert.getDomainCert(`testing${getRandomArbitrary(1, 100000)}.bleu.de`)); + promiseArray.push(testCert.addCertificate(`testing${getRandomArbitrary(1, 100000)}.bleu.de`)); + // promiseArray.push(testCert.addCertificate(`testing${getRandomArbitrary(1,100000)}.bleu.de`)) + // promiseArray.push(testCert.addCertificate(`testing${getRandomArbitrary(1,100000)}.bleu.de`)) q.all(promiseArray).then(() => { done(); }); }); }); }); -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbInRlc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLHdCQUFzQjtBQUN0QixrQkFBZ0I7QUFDaEIsK0JBQTBCO0FBQzFCLDZCQUE4QjtBQUM5Qix1QkFBd0I7QUFDeEIsNkNBQTZDO0FBQzdDLHNDQUFzQztBQUd0QyxJQUFJLFFBQVEsR0FBRyxJQUFJLFdBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxFQUFFLEVBQUUsT0FBTyxDQUFDLEdBQUcsRUFBRSxHQUFHLFNBQVMsQ0FBQyxDQUFDO0FBRWxFLElBQUksUUFBa0IsQ0FBQztBQUV2QixRQUFRLENBQUMsTUFBTSxFQUFDO0lBQ1osUUFBUSxDQUFDLFNBQVMsRUFBQztRQUNmLEVBQUUsQ0FBQyxnQ0FBZ0MsRUFBQyxVQUFTLElBQUk7WUFDN0MsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUNuQixzQkFBWSxFQUFFLENBQUMsSUFBSSxDQUFDO2dCQUNoQixJQUFJLEVBQUUsQ0FBQztZQUNYLENBQUMsQ0FBQyxDQUFBO1FBQ04sQ0FBQyxDQUFDLENBQUE7SUFDTixDQUFDLENBQUMsQ0FBQTtJQUNGLFFBQVEsQ0FBQyxNQUFNLEVBQUM7UUFDWixFQUFFLENBQUMsNENBQTRDLEVBQUM7WUFDNUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUNwQixRQUFRLEdBQUcsSUFBSSxJQUFJLENBQUMsSUFBSSxDQUFDO2dCQUNyQixPQUFPLEVBQUUsT0FBTyxDQUFDLEdBQUcsQ0FBQyxRQUFRO2dCQUM3QixLQUFLLEVBQUUsT0FBTyxDQUFDLEdBQUcsQ0FBQyxNQUFNO2dCQUN6QixNQUFNLEVBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxFQUFFLEVBQUMsYUFBYSxDQUFDO2dCQUM5QyxhQUFhLEVBQUMsa0RBQWtEO2dCQUNoRSxRQUFRLEVBQUMsSUFBSTthQUNoQixDQUFDLENBQUM7WUFDSCxRQUFRLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQzdDLENBQUMsQ0FBQyxDQUFBO1FBQ0YsRUFBRSxDQUFDLGdDQUFnQyxFQUFDLFVBQVMsSUFBSTtZQUM3QyxJQUFJLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBQ3RCLElBQUksWUFBWSxHQUFHLEVBQUUsQ0FBQztZQUN0Qiw0QkFBNEIsR0FBRyxFQUFFLEdBQUc7Z0JBQ2hDLE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsR0FBRyxDQUFDLEdBQUcsR0FBRyxHQUFHLENBQUMsR0FBRyxHQUFHLENBQUMsQ0FBQztZQUN6RCxDQUFDO1lBQ0QsWUFBWSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsYUFBYSxDQUFDLFVBQVUsa0JBQWtCLENBQUMsQ0FBQyxFQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDO1lBQzVGLFlBQVksQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLGFBQWEsQ0FBQyxVQUFVLGtCQUFrQixDQUFDLENBQUMsRUFBQyxNQUFNLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQztZQUM1RixZQUFZLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxhQUFhLENBQUMsVUFBVSxrQkFBa0IsQ0FBQyxDQUFDLEVBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUM7WUFDNUYsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUM7Z0JBQ3JCLElBQUksRUFBRSxDQUFDO1lBQ1gsQ0FBQyxDQUFDLENBQUM7UUFDUCxDQUFDLENBQUMsQ0FBQTtJQUNOLENBQUMsQ0FBQyxDQUFBO0FBQ04sQ0FBQyxDQUFDLENBQUMifQ== \ No newline at end of file +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbInRlc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLHdCQUFxQjtBQUNyQixpQ0FBZ0M7QUFDaEMsK0JBQXlCO0FBQ3pCLDZCQUE2QjtBQUM3Qix1QkFBdUI7QUFDdkIsc0NBQXFDO0FBR3JDLElBQUksUUFBUSxHQUFHLElBQUksV0FBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLEVBQUUsRUFBRSxPQUFPLENBQUMsR0FBRyxFQUFFLEdBQUcsU0FBUyxDQUFDLENBQUE7QUFFakUsSUFBSSxRQUFtQixDQUFBO0FBRXZCLFFBQVEsQ0FBQyxNQUFNLEVBQUM7SUFDWixRQUFRLENBQUMsTUFBTSxFQUFDO1FBQ1osRUFBRSxDQUFDLDRDQUE0QyxFQUFDO1lBQzVDLElBQUksQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUE7WUFDbkIsUUFBUSxHQUFHLElBQUksSUFBSSxDQUFDLElBQUksQ0FBQztnQkFDckIsT0FBTyxFQUFFLE9BQU8sQ0FBQyxHQUFHLENBQUMsUUFBUTtnQkFDN0IsS0FBSyxFQUFFLE9BQU8sQ0FBQyxHQUFHLENBQUMsTUFBTTtnQkFDekIsVUFBVSxFQUFFLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsRUFBRSxFQUFDLGFBQWEsQ0FBQztnQkFDbEQsYUFBYSxFQUFFLGtEQUFrRDtnQkFDakUsS0FBSyxFQUFFLFNBQVM7YUFDbkIsQ0FBQyxDQUFBO1lBQ0YsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFBO1FBQzdDLENBQUMsQ0FBQyxDQUFBO1FBQ0YsRUFBRSxDQUFDLGdDQUFnQyxFQUFDLFVBQVMsSUFBSTtZQUM3QyxJQUFJLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQUFBO1lBQ3JCLElBQUksWUFBWSxHQUFHLEVBQUUsQ0FBQTtZQUNyQiw0QkFBNEIsR0FBRyxFQUFFLEdBQUc7Z0JBQ2hDLE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsR0FBRyxDQUFDLEdBQUcsR0FBRyxHQUFHLENBQUMsR0FBRyxHQUFHLENBQUMsQ0FBQTtZQUN4RCxDQUFDO1lBQ0QsWUFBWSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsY0FBYyxDQUFDLFVBQVUsa0JBQWtCLENBQUMsQ0FBQyxFQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFBO1lBQzVGLCtGQUErRjtZQUMvRiwrRkFBK0Y7WUFDL0YsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUM7Z0JBQ3JCLElBQUksRUFBRSxDQUFBO1lBQ1YsQ0FBQyxDQUFDLENBQUE7UUFDTixDQUFDLENBQUMsQ0FBQTtJQUNOLENBQUMsQ0FBQyxDQUFBO0FBQ04sQ0FBQyxDQUFDLENBQUEifQ== \ No newline at end of file diff --git a/test/test.ts b/test/test.ts index 51802cb..827f4ae 100644 --- a/test/test.ts +++ b/test/test.ts @@ -1,49 +1,40 @@ -import "typings-test"; -import "should"; -import {Qenv} from "qenv"; -import path = require("path"); -import q = require("q"); -import {startInstall} from "../dist/install"; -import * as cert from "../dist/index"; +import 'typings-test' +import * as should from 'should' +import {Qenv} from 'qenv' +import path = require('path') +import q = require('q') +import * as cert from '../dist/index' -let testQenv = new Qenv(process.cwd(), process.cwd() + "/.nogit"); +let testQenv = new Qenv(process.cwd(), process.cwd() + '/.nogit') -let testCert:cert.Cert; +let testCert: cert.Cert -describe("cert",function(){ - describe("install",function(){ - it("should download letsencrypt.sh",function(done){ - this.timeout(5000); - startInstall().then(() => { - done(); - }) - }) - }) - describe("Cert",function(){ - it("should create a new Cert object from class",function(){ - this.timeout(40000); +describe('cert',function(){ + describe('Cert',function(){ + it('should create a new Cert object from class',function(){ + this.timeout(40000) testCert = new cert.Cert({ cfEmail: process.env.CF_EMAIL, cfKey: process.env.CF_KEY, - sslDir: path.join(process.cwd(),"test/assets"), - gitOriginRepo:"git@gitlab.com:sandboxzone/sandbox-sslorigin.git", - testMode:true - }); - testCert.should.be.instanceof(cert.Cert); + sslDirPath: path.join(process.cwd(),'test/assets'), + gitOriginRepo: 'git@gitlab.com:sandboxzone/sandbox-sslorigin.git', + leEnv: 'staging' + }) + should(testCert).be.instanceof(cert.Cert) }) - it("should get a valid certificate",function(done){ - this.timeout(1200000); - let promiseArray = []; + it('should get a valid certificate',function(done){ + this.timeout(1200000) + let promiseArray = [] function getRandomArbitrary(min, max) { - return Math.floor(Math.random() * (max - min) + min); + return Math.floor(Math.random() * (max - min) + min) } - promiseArray.push(testCert.getDomainCert(`testing${getRandomArbitrary(1,100000)}.bleu.de`)); - promiseArray.push(testCert.getDomainCert(`testing${getRandomArbitrary(1,100000)}.bleu.de`)); - promiseArray.push(testCert.getDomainCert(`testing${getRandomArbitrary(1,100000)}.bleu.de`)); + promiseArray.push(testCert.addCertificate(`testing${getRandomArbitrary(1,100000)}.bleu.de`)) + // promiseArray.push(testCert.addCertificate(`testing${getRandomArbitrary(1,100000)}.bleu.de`)) + // promiseArray.push(testCert.addCertificate(`testing${getRandomArbitrary(1,100000)}.bleu.de`)) q.all(promiseArray).then(() => { - done(); - }); + done() + }) }) }) -}); \ No newline at end of file +}) \ No newline at end of file diff --git a/ts/cert.classes.cert.helpers.ts b/ts/cert.classes.cert.helpers.ts deleted file mode 100644 index 7688bca..0000000 --- a/ts/cert.classes.cert.helpers.ts +++ /dev/null @@ -1,86 +0,0 @@ -import {Cert} from "./index.ts"; -import * as plugins from "./cert.plugins"; -import * as paths from "./cert.paths"; - - - -/** - * schedule a retry of certificate request - */ -export let scheduleRetry = (domainArg:string,certClassArg:Cert) => { - let done = plugins.q.defer(); - setTimeout(() => { - certClassArg.getDomainCert(domainArg) - .then(done.resolve); - },60000); - return done.promise; -}; - -/** - * check if a given domainCert is still valid - */ -export let checkDomainsStillValid = (domainNameArg: string, sslDirArg: string): boolean => { - let domainConfigPath = plugins.path.join(sslDirArg, domainNameArg, "config.json"); - if (plugins.smartfile.fs.fileExistsSync(domainConfigPath)) { - let domainConfig = plugins.smartfile.fs.toObjectSync( - domainConfigPath, - "json" - ); - if (Date.now() >= ((domainConfig.expires - 604800) * 1000)) { - return false; - } else { - return true; - } - } else { - return false; - } - -} - -export interface certConfig { - domainName: string; - created: number; - expires: number; -}; - -/** - * update a ssl directory - */ -export let updateSslDirSync = (sslDirArg: string, domainNameArg: string) => { - plugins.smartfile.fs.ensureDirSync(sslDirArg); - let domainCertFolder = plugins.path.join(paths.certDir, domainNameArg) - if (plugins.smartfile.fs.listFoldersSync(paths.certDir).indexOf(domainNameArg) != -1) { - plugins.smartfile.fs.copySync( - plugins.path.join(domainCertFolder, "fullchain.pem"), - plugins.path.join(sslDirArg, domainNameArg, "fullchain.pem") - ); - plugins.smartfile.fs.copySync( - plugins.path.join(domainCertFolder, "privkey.pem"), - plugins.path.join(sslDirArg, domainNameArg, "privkey.pem") - ); - // create cert config - let certRegex = /.*\-([0-9]*)\.pem/; - let certFileNameWithTime: string = plugins.smartfile.fs.listFilesSync(domainCertFolder, certRegex)[0]; - let certTime = parseInt(certRegex.exec(certFileNameWithTime)[1]); - let certConfig: certConfig = { - domainName: domainNameArg, - created: certTime, - expires: certTime + 7776000 - }; - plugins.smartfile.memory.toFsSync( - JSON.stringify(certConfig), - plugins.path.join(sslDirArg, domainNameArg, "config.json") - ); - }; -} - -const enum gitSyncDirection { - toOrigin, - fromOrigin -} - -let updateGitOrigin = (syncDirectionArg: gitSyncDirection) => { - -}; - -updateGitOrigin(gitSyncDirection.toOrigin); \ No newline at end of file diff --git a/ts/cert.classes.cert.ts b/ts/cert.classes.cert.ts index feb3182..bfa367e 100644 --- a/ts/cert.classes.cert.ts +++ b/ts/cert.classes.cert.ts @@ -1,148 +1,92 @@ import * as q from 'q' +import { Stringmap, Objectmap } from 'lik' + import * as plugins from './cert.plugins' import * as paths from './cert.paths' -import * as helpers from './cert.classes.cert.helpers' + +// classes +import { Certificate } from './cert.classes.certificate' +import { CertRepo } from './cert.classes.certrepo' +import { Letsencrypt, TLeEnv } from './cert.classes.letsencrypt' +import { ChallengeHandler } from './cert.classes.challengehandler' + export interface ICertConstructorOptions { cfEmail: string, cfKey: string, - sslDir?: string, + sslDirPath?: string, gitOriginRepo?: string, - testMode?: boolean + leEnv?: TLeEnv } export class Cert { - domainCertRequestMap: plugins.lik.Stringmap = new plugins.lik.Stringmap() - certificatesPresent: Certificate[] - certificatesValid: Certificate[] - private _cfEmail: string - private _cfKey: string - private _sslDir: string - private _gitOriginRepo: string - private _testMode: boolean - private letsencryptInstance + domainStringRequestMap = new Stringmap() + certificateMap = new Objectmap() + letsencrypt: Letsencrypt + private _challengeHandler: ChallengeHandler + private _certRepo: CertRepo /** * Constructor for Cert object */ constructor(optionsArg: ICertConstructorOptions) { - this._cfEmail = optionsArg.cfEmail - this._cfKey = optionsArg.cfKey - this._sslDir = optionsArg.sslDir - this._gitOriginRepo = optionsArg.gitOriginRepo - this._testMode = optionsArg.testMode - // write hook config - let config = { - cfEmail: this._cfEmail, - cfKey: this._cfKey - } - plugins.smartfile.memory.toFsSync( - JSON.stringify(config), - plugins.path.join(__dirname, 'assets/config.json') - ) - // setup sslDir - if (!this._sslDir) this._sslDir = paths.defaultSslDir - // setup Git - if (this._gitOriginRepo) { - plugins.smartgit.init(this._sslDir) - plugins.smartgit.remote.add(this._sslDir, 'origin', this._gitOriginRepo) - this.sslGitOriginPull() - } + + // set up challengehandler + this._challengeHandler = new ChallengeHandler({ + cfEmail: optionsArg.cfEmail, + cfKey: optionsArg.cfKey + }) + + // setup Letsencrypt + this.letsencrypt = new Letsencrypt({ + leEnv: optionsArg.leEnv, + sslDir: optionsArg.sslDirPath, + challengeHandler: this._challengeHandler + }) + + // setup CertRpo + this._certRepo = new CertRepo({ + sslDirPath: optionsArg.sslDirPath, + gitOriginRepo: optionsArg.gitOriginRepo, + certInstance: this + }) + + this._certRepo } /** - * Pulls already requested certificates from git origin + * adds a Certificate for a given domain */ - sslGitOriginPull = () => { - if (this._gitOriginRepo) { - plugins.smartgit.pull(this._sslDir, 'origin', 'master') - } - } - - /** - * Pushes all new requested certificates to git origin - */ - sslGitOriginAddCommitPush = () => { - if (this._gitOriginRepo) { - plugins.smartgit.add.addAll(this._sslDir) - plugins.smartgit.commit(this._sslDir, 'added new SSL certificates and deleted obsolete ones.') - plugins.smartgit.push(this._sslDir, 'origin', 'master') - } - } - - /** - * gets a ssl cert for a given domain - */ - getDomainCert(domainNameArg: string, optionsArg: { force: boolean } = { force: false }) { + addCertificate(domainNameArg: string, optionsArg: { force: boolean } = { force: false }) { let done = q.defer() - let domainStringData = new plugins.smartstring.Domain(domainNameArg) - let sameZoneRequesting: boolean = this.domainCertRequestMap.checkMinimatch('*' + domainStringData.zoneName) - // make sure no one else requires the same domain at the same time - if (!this.domainCertRequestMap.checkString(domainNameArg)) { - this.domainCertRequestMap.addString(domainNameArg) - if (!helpers.checkDomainsStillValid(domainNameArg, this._sslDir) || optionsArg.force) { - if (!sameZoneRequesting) { - this.sslGitOriginPull() - plugins.smartfile.fs.ensureDir(paths.certDir) - plugins.beautylog.info(`getting cert for ${domainNameArg}`) - plugins.shelljs.exec( - `bash -c "${paths.letsencryptSh} -c --no-lock -f ${paths.leShConfig} -d ${domainNameArg} -t dns-01 -k ${paths.certHook} -o ${paths.certDir}"`, - { - silent: true - }, - (codeArg, stdoutArg) => { - if (codeArg === 0) { - console.log(stdoutArg) - let fetchedCertsArray: string[] = plugins.smartfile.fs.listFoldersSync(paths.certDir) - if (fetchedCertsArray.indexOf(domainNameArg) != -1) { - helpers.updateSslDirSync(this._sslDir, domainNameArg) - plugins.smartfile.fs.removeSync(plugins.path.join(paths.certDir, domainNameArg)) - this.sslGitOriginAddCommitPush() - } else { - plugins.beautylog.error(`Couldn't copy final certificate for ${domainNameArg}!`) - } - done.resolve() - } else { - plugins.beautylog.warn(`${domainNameArg} scheduled for retry. Waiting 1 minute!`) - helpers.scheduleRetry(domainNameArg, this).then(done.resolve) - } - this.domainCertRequestMap.removeString(domainNameArg) - } - ) - } else { - plugins.beautylog.info(`${domainNameArg} is waiting for domains names of same zone to finish`) - this.domainCertRequestMap.removeString(domainNameArg) - this.domainCertRequestMap.registerUntilTrue( - () => { - return !this.domainCertRequestMap.checkMinimatch('*' + domainStringData.zoneName) - }, - () => { - this.getDomainCert(domainNameArg).then(done.resolve) - } - ) - } - } else { - plugins.beautylog.info('certificate for ' + domainNameArg + ' is still valid! Not fetching new one!') - this.domainCertRequestMap.removeString(domainNameArg) - done.resolve() - } + let certificateForDomain = this.certificateMap.find((certificate) => { + return certificate.domainName === domainNameArg + }) + if (certificateForDomain instanceof Certificate) { + certificateForDomain.renew() + .then(done.resolve) } else { - plugins.beautylog.warn(`${domainNameArg} is already requesting`) + certificateForDomain = new Certificate({ + certInstance: this, + domainName: domainNameArg + }) + certificateForDomain.renew() + .then(done.resolve) } - return done.promise } + + /** + * cleans up old certificates + */ cleanOldCertificates() { } -} -export class Certificate { - domainName: string - creationDate: Date - expiryDate: Date - constructor() { + /** + * executes the current batch of jobs + */ + deploy() { } } - diff --git a/ts/cert.classes.certificate.ts b/ts/cert.classes.certificate.ts new file mode 100644 index 0000000..1694e7f --- /dev/null +++ b/ts/cert.classes.certificate.ts @@ -0,0 +1,129 @@ +import * as q from 'q' + +import * as plugins from './cert.plugins' +import * as paths from './cert.paths' + +// import classes +import { Cert } from './cert.classes.cert' +import { Letsencrypt } from './cert.classes.letsencrypt' +import { CertRepo } from './cert.classes.certrepo' + +export interface ICertificateFsConfig { + domainName: string + creationTime: number + expiryTime: number +} + +export interface ICertificateConstructorOptions { + domainName: string, + certInstance: Cert +} + +export type TCertificateStatus = 'unregistered' | 'valid' | 'expiring' | 'expired' + +export class Certificate { + domainName: string + certInstance: Cert + domainData: plugins.smartstring.Domain + creationDate: Date = null + expiryDate: Date = null + publicKey: string = null + privKey: string = null + + /** + * run when creating a new instance of Certificate + */ + constructor(optionsArg: ICertificateConstructorOptions) { + this.domainName = optionsArg.domainName + this.domainData = new plugins.smartstring.Domain(this.domainName) + this.certInstance = optionsArg.certInstance + } + + /** + * the status of the Certificate + */ + get status(): TCertificateStatus { + let validTimeRemaining: number = 0 + if (this.creationDate !== null && this.expiryDate !== null) { + validTimeRemaining = this.expiryDate.getTime() - Date.now() + } + let MonthMilliseconds = 2629746000 + if (this.publicKey === null || this.privKey === null) { + return 'unregistered' + } else if (validTimeRemaining >= MonthMilliseconds) { + return 'valid' + } else if (validTimeRemaining < MonthMilliseconds && validTimeRemaining >= 0) { + return 'expiring' + } else { + return 'expired' + } + } + + get sameZoneRequesting(): boolean { + return this.certInstance.domainStringRequestMap.checkMinimatch('*' + this.domainData.zoneName) + } + + /** + * schedule a retry of certificate request + */ + scheduleRetry() { + let done = plugins.q.defer() + setTimeout(() => { + this.renew() + .then(done.resolve) + }, 60000) + return done.promise + } + + /** + * renew certificate if needed + */ + renew(force: boolean = false) { + let done = q.defer() + if (this.status === 'valid') { + plugins.beautylog.log('Certificate still valid for more than 1 month, so it is not renewed now') + done.resolve() + } else if (this.status === 'expiring' || this.status === 'expired' || this.status === 'unregistered') { + plugins.beautylog.info('Certificate not valid currently, going to renew now!') + if (this.sameZoneRequesting) { + this.certInstance.domainStringRequestMap.registerUntilTrue( + () => { + return !this.sameZoneRequesting + }, + () => { + this.renew().then(done.resolve) + } + ) + } else { + this.certInstance.letsencrypt.registerDomain(this.domainName) + .then(() => { + return this.syncFs() + }) + .then(() => { + done.resolve() + }).catch((err) => { console.log(err) }) + } + } else { + throw Error(`weird status for certificate with domain name ${this.domainName}`) + } + done.resolve() + return done.promise + } + + /** + * syncFs syncs the certificate with disk + */ + syncFs() { + let configJsonMemory: ICertificateFsConfig = { + domainName: this.domainName, + creationTime: this.creationDate.getTime(), + expiryTime: this.expiryDate.getTime() + } + + } + + /** + * deletes the certificate + */ + delete() { } +} diff --git a/ts/cert.classes.certrepo.ts b/ts/cert.classes.certrepo.ts new file mode 100644 index 0000000..5f8f756 --- /dev/null +++ b/ts/cert.classes.certrepo.ts @@ -0,0 +1,65 @@ +import * as q from 'q' + +import * as plugins from './cert.plugins' +import * as paths from './cert.paths' + +import { Cert } from './cert.classes.cert' +import { Certificate } from './cert.classes.certificate' + +export interface ICertRepoConstructorOptions { + sslDirPath: string + gitOriginRepo: string + certInstance: Cert +} + +export class CertRepo { + private _sslDirPath: string + private _gitOriginRepo: string + private _certInstance: Cert + constructor(optionsArg: ICertRepoConstructorOptions) { + this._sslDirPath = optionsArg.sslDirPath + this._gitOriginRepo = optionsArg.gitOriginRepo + this._certInstance = optionsArg.certInstance + + // setup sslDir + if (!this._sslDirPath){ + this._sslDirPath = paths.defaultSslDir + } + + // setup Git + if (this._gitOriginRepo) { + plugins.smartgit.init(this._sslDirPath) + plugins.smartgit.remote.add(this._sslDirPath, 'origin', this._gitOriginRepo) + this.sslGitOriginPull() + } + } + + /** + * syncs an objectmap of Certificates with repo + */ + syncFs() { + let done = q.defer() + done.resolve() + return done.promise + } + + /** + * Pulls already requested certificates from git origin + */ + sslGitOriginPull = () => { + if (this._gitOriginRepo) { + plugins.smartgit.pull(this._sslDirPath, 'origin', 'master') + } + } + + /** + * Pushes all new requested certificates to git origin + */ + sslGitOriginAddCommitPush = () => { + if (this._gitOriginRepo) { + plugins.smartgit.add.addAll(this._sslDirPath) + plugins.smartgit.commit(this._sslDirPath, 'added new SSL certificates and deleted obsolete ones.') + plugins.smartgit.push(this._sslDirPath, 'origin', 'master') + } + } +} diff --git a/ts/cert.classes.challengehandler.ts b/ts/cert.classes.challengehandler.ts new file mode 100644 index 0000000..3c8c2ad --- /dev/null +++ b/ts/cert.classes.challengehandler.ts @@ -0,0 +1,84 @@ +import * as plugins from './cert.plugins' +import * as paths from './cert.paths' + +export interface IChallengehandlerConstructorOptions { + cfEmail: string, + cfKey: string, +} + +/** + * class ChallengeHandler handles challenges + */ +export class ChallengeHandler { + private _cfInstance: plugins.cflare.CflareAccount + constructor(optionsArg: IChallengehandlerConstructorOptions) { + this._cfInstance = new plugins.cflare.CflareAccount() + this._cfInstance.auth({ + email: optionsArg.cfEmail, + key: optionsArg.cfKey + }) + } + + /** + * set a challenge + */ + setChallenge(domainNameArg: string, challengeArg: string) { + let done = plugins.q.defer() + plugins.beautylog.log('setting challenge for ' + domainNameArg) + this._cfInstance.createRecord(prefixName(domainNameArg), 'TXT', challengeArg).then(() => { + plugins.beautylog.ok('Challenge has been set!') + plugins.beautylog.info('We need to cool down to let DNS propagate to edge locations!') + cooldown().then(() => { + done.resolve() + }) + }) + return done.promise + } + + /** + * cleans a challenge + */ + cleanChallenge(domainNameArg) { + let done = plugins.q.defer() + plugins.beautylog.log('cleaning challenge for ' + domainNameArg) + this._cfInstance.removeRecord(prefixName(domainNameArg), 'TXT') + cooldown().then(() => { + done.resolve() + }) + return done.promise + } +} + +/** + * cooldown timer for letting DNS settle before answering the challengerequest + */ +let cooldown = () => { + let done = plugins.q.defer() + let cooldowntime = 60000 + let passedTime = 0 + plugins.beautylog.log('Cooling down! ' + (cooldowntime / 1000).toString() + ' seconds left') + let coolDownCounter = () => { + setTimeout(() => { + if (cooldowntime <= passedTime) { + plugins.beautylog.ok('Cooled down!') + done.resolve() + } else { + passedTime = passedTime + 5000 + plugins.beautylog.log('Cooling down! ' + + ((cooldowntime - passedTime) / 1000).toString() + + ' seconds left' + ) + coolDownCounter() + } + }, 5000) + } + coolDownCounter() + return done.promise +} + +/** + * prefix a domain name to make sure it complies with letsencrypt + */ +let prefixName = (domainNameArg: string): string => { + return '_acme-challenge.' + domainNameArg +} diff --git a/ts/cert.classes.letsencrypt.ts b/ts/cert.classes.letsencrypt.ts new file mode 100644 index 0000000..32a9f70 --- /dev/null +++ b/ts/cert.classes.letsencrypt.ts @@ -0,0 +1,139 @@ +import * as q from 'q' +let letsencrypt = require('letsencrypt') + +import * as plugins from './cert.plugins' +import * as paths from './cert.paths' + +import { ChallengeHandler } from './cert.classes.challengehandler' + +export type TLeEnv = 'production' | 'staging' + +export interface ILetsencryptConstructorOptions { + leEnv: TLeEnv, + challengeHandler: ChallengeHandler, + sslDir: string +} + +export class Letsencrypt { + leEnv: TLeEnv + challengeHandler: ChallengeHandler // this is the format we use + sslDir: string + + private _leInstance: any + private _leServerUrl: string + + constructor(optionsArg: ILetsencryptConstructorOptions) { + // determine leEnv + this.leEnv = optionsArg.leEnv + this.challengeHandler = optionsArg.challengeHandler + this.sslDir = optionsArg.sslDir + + // set letsencrypt environment + if (this.leEnv === 'production') { + this._leServerUrl = letsencrypt.productionServerUrl + } else if (this.leEnv === 'staging') { + this._leServerUrl = letsencrypt.stagingServerUrl + } + + // create leInstance + this._leInstance = letsencrypt.create({ + server: this._leServerUrl, + challenges: { 'dns-01': this._leChallengeHandler() }, + challengeType: 'dns-01', + configDir: paths.leConfigDir, + privkeyPath: ':configDir/live/:hostname/privkey.pem', // + fullchainPath: ':configDir/live/:hostname/fullchain.pem', // Note: both that :config and :hostname + certPath: ':config/live/:hostname/cert.pem', // will be templated as expected + chainPath: ':config/live/:hostname/chain.pem', + agreeToTerms: this._leAgree, + debug: true + }) + } + + /** + * register a domain + */ + registerDomain(domainNameArg: string) { + plugins.beautylog.log(`trying to register domain ${domainNameArg}`) + let done = q.defer() + console.log('test') + this._leInstance.register({ + domains: [domainNameArg], + email: 'domains@lossless.org', + agreeTos: true, + rsaKeySize: 2048, + challengeType: 'dns-01' + }).then( + (results) => { + plugins.beautylog.success(`Got certificates for ${domainNameArg}`) + this._leCopyToDestination(domainNameArg).then(done.resolve) + }, + (err) => { + console.error('[Error]: node-letsencrypt/examples/standalone') + console.error(err.stack) + done.resolve() + } + ).catch(err => { console.log(err) }) + return done.promise + } + + // -------------------------------------------- + // Translate for official letsencrypt stuff + // -------------------------------------------- + + private _leCopyToDestination(domainNameArg) { + let done = q.defer() + return done.promise + } + + /** + * translates to the format expected by letsencrypt node implementation + */ + private _leChallengeHandler() { + return { + getOptions: (...args) => { + return { + debug: true + } + }, + set: (args, domain, challenge, keyAuthorization, cb) => { + let keyAuthDigest = require('crypto') + .createHash('sha256').update(keyAuthorization || '') + .digest('base64') + .replace(/\+/g, '-') + .replace(/\//g, '_') + .replace(/=+$/g, '') + this.challengeHandler.setChallenge(domain, keyAuthDigest) + .then(() => { + cb() + }) + }, + get: (defaults, domain, challenge, cb) => { + console.log(defaults) + console.log(domain) + console.log(challenge) + cb() + }, + remove: (args, domain, challenge, cb) => { + this.challengeHandler.cleanChallenge(domain) + .then(() => { + cb() + }) + }, + loopback: (args, domain, challenge, cb) => { + console.log(args) + console.log(domain) + console.log(challenge) + cb() + }, + test: (defaults, domain, challenge, cb) => { + cb() + } + } + } + + private _leAgree(opts, agreeCb) { + // opts = { email, domains, tosUrl } + agreeCb(null, opts.tosUrl); + } +} diff --git a/ts/cert.hook.ts b/ts/cert.hook.ts deleted file mode 100644 index 9c9495c..0000000 --- a/ts/cert.hook.ts +++ /dev/null @@ -1,73 +0,0 @@ -import * as plugins from "./cert.plugins"; -import * as paths from "./cert.paths"; - -let smartcli = new plugins.smartcli.Smartcli(); - -let config = plugins.smartfile.fs.toObjectSync(paths.config); -let cflare = new plugins.cflare.CflareAccount(); -cflare.auth({ - email: config.cfEmail, - key: config.cfKey -}); - -let setChallenge = (domainNameArg: string, challengeArg: string) => { - let done = plugins.q.defer(); - plugins.beautylog.log("setting challenge for " + domainNameArg); - cflare.createRecord(prefixName(domainNameArg), "TXT", challengeArg).then(() => { - plugins.beautylog.ok("Challenge has been set!"); - plugins.beautylog.info("We need to cool down to let DNS propagate to edge locations!"); - cooldown().then(() => { - done.resolve(); - }); - }); - return done.promise; -} - -let cleanChallenge = (domainNameArg) => { - let done = plugins.q.defer(); - plugins.beautylog.log("cleaning challenge for " + domainNameArg); - cflare.removeRecord(prefixName(domainNameArg), "TXT"); - cooldown().then(() => { - done.resolve(); - }); - return done.promise; -} - -let cooldown = () => { - let done = plugins.q.defer(); - let cooldowntime = 60000; - let passedTime = 0; - plugins.beautylog.log("Cooling down! " + (cooldowntime/1000).toString() + " seconds left"); - let coolDownCounter = () => { - setTimeout(() => { - if(cooldowntime <= passedTime){ - plugins.beautylog.ok("Cooled down!"); - done.resolve(); - } else { - passedTime = passedTime + 5000; - plugins.beautylog.log("Cooling down! " + ((cooldowntime - passedTime)/1000).toString() + " seconds left"); - coolDownCounter(); - } - }, 5000); - } - coolDownCounter(); - return done.promise; -} - -let prefixName = (domainNameArg: string): string => { - return "_acme-challenge." + domainNameArg; -} - -smartcli.addCommand({ - commandName: "deploy_challenge" -}).then((argv) => { - setChallenge(argv._[1], argv._[3]); -}); - -smartcli.addCommand({ - commandName: "clean_challenge" -}).then((argv) => { - cleanChallenge(argv._[1]); -}); - -smartcli.startParse(); diff --git a/ts/cert.paths.ts b/ts/cert.paths.ts index ba38048..3745631 100644 --- a/ts/cert.paths.ts +++ b/ts/cert.paths.ts @@ -1,14 +1,9 @@ -import * as plugins from "./cert.plugins"; - -//dirs -export let certDir = plugins.path.join(__dirname,"assets/certs"); -export let defaultSslDir = plugins.path.join(__dirname,"assets/defaultSslDir"); -export let assetDir = plugins.path.join(__dirname,"assets/"); -export let accountsDir = plugins.path.join(__dirname,"assets/accounts/"); - -// files -export let certHook = plugins.path.join(__dirname,"cert.hook.js"); -export let config = plugins.path.join(__dirname,"assets/config.json"); -export let leShConfig = plugins.path.join(__dirname,"assets/leshconfig.json"); -export let letsencryptSh = plugins.path.join(__dirname,"assets/letsencrypt.sh"); +import * as plugins from './cert.plugins' +// dirs +export let projectDir = plugins.path.join(__dirname,'../') +export let assetDir = plugins.path.join(projectDir,'assets') +export let defaultSslDir = plugins.path.join(assetDir,'defaultSslDir') +export let leConfigDir = plugins.path.join(assetDir,'letsencrypt') +plugins.smartfile.fs.ensureDirSync(leConfigDir) +plugins.smartfile.fs.ensureDirSync(defaultSslDir) diff --git a/ts/cert.plugins.ts b/ts/cert.plugins.ts index 1537296..909ae7e 100644 --- a/ts/cert.plugins.ts +++ b/ts/cert.plugins.ts @@ -2,7 +2,6 @@ import 'typings-global' import * as beautylog from 'beautylog' import * as cflare from 'cflare' let fs = require('fs-extra') -let letsencrypt = require('letsencrypt') import * as lik from 'lik' import * as path from 'path' import * as q from 'q' @@ -16,7 +15,6 @@ export { beautylog, cflare, fs, - letsencrypt, lik, path, q, diff --git a/ts/index.ts b/ts/index.ts index 6c686ef..f635b28 100644 --- a/ts/index.ts +++ b/ts/index.ts @@ -1,4 +1 @@ -import * as plugins from "./cert.plugins"; -import * as paths from "./cert.paths"; - -export * from "./cert.classes.cert"; \ No newline at end of file +export * from './cert.classes.cert' diff --git a/ts/temp b/ts/temp new file mode 100644 index 0000000..74bd985 --- /dev/null +++ b/ts/temp @@ -0,0 +1,3 @@ +helpers.updateSslDirSync(this._sslDir, domainNameArg) +helpers.scheduleRetry(domainNameArg, this).then(done.resolve) +this.domainCertRequestMap.removeString(domainNameArg) \ No newline at end of file