now fully working

This commit is contained in:
Philipp Kunz 2016-07-04 08:41:58 +02:00
parent ee844fd348
commit 96c801cdbd
9 changed files with 137 additions and 51 deletions

View File

@ -1,4 +1,6 @@
export declare let certHook: string; export declare let certHook: string;
export declare let config: string; export declare let config: string;
export declare let leShConfig: string;
export declare let letsencryptSh: string; export declare let letsencryptSh: string;
export declare let certDir: string; export declare let certDir: string;
export declare let assetDir: string;

6
dist/cert.paths.js vendored
View File

@ -1,7 +1,11 @@
"use strict"; "use strict";
var plugins = require("./cert.plugins"); var plugins = require("./cert.plugins");
// files
exports.certHook = plugins.path.join(__dirname, "cert.hook.js"); exports.certHook = plugins.path.join(__dirname, "cert.hook.js");
exports.config = plugins.path.join(__dirname, "assets/config.json"); 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"); exports.letsencryptSh = plugins.path.join(__dirname, "assets/letsencrypt.sh");
//dirs
exports.certDir = plugins.path.join(__dirname, "/assets/certs"); exports.certDir = plugins.path.join(__dirname, "/assets/certs");
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2VydC5wYXRocy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL2NlcnQucGF0aHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLElBQVksT0FBTyxXQUFNLGdCQUFnQixDQUFDLENBQUE7QUFFL0IsZ0JBQVEsR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUMsY0FBYyxDQUFDLENBQUM7QUFDdkQsY0FBTSxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBQyxvQkFBb0IsQ0FBQyxDQUFDO0FBQzNELHFCQUFhLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFDLHVCQUF1QixDQUFDLENBQUM7QUFDckUsZUFBTyxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBQyxlQUFlLENBQUMsQ0FBQyJ9 exports.assetDir = plugins.path.join(__dirname, "/assets/");
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2VydC5wYXRocy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL2NlcnQucGF0aHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLElBQVksT0FBTyxXQUFNLGdCQUFnQixDQUFDLENBQUE7QUFFMUMsUUFBUTtBQUNHLGdCQUFRLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFDLGNBQWMsQ0FBQyxDQUFDO0FBQ3ZELGNBQU0sR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUMsb0JBQW9CLENBQUMsQ0FBQztBQUMzRCxrQkFBVSxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBQyx3QkFBd0IsQ0FBQyxDQUFDO0FBQ25FLHFCQUFhLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFDLHVCQUF1QixDQUFDLENBQUM7QUFFaEYsTUFBTTtBQUNLLGVBQU8sR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUMsZUFBZSxDQUFDLENBQUM7QUFDdkQsZ0JBQVEsR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUMsVUFBVSxDQUFDLENBQUMifQ==

5
dist/index.d.ts vendored
View File

@ -4,20 +4,23 @@ export declare class Cert {
private _cfEmail; private _cfEmail;
private _cfKey; private _cfKey;
private _sslDir; private _sslDir;
private _gitOriginRepo;
private _testMode;
certificatesPresent: Certificate[]; certificatesPresent: Certificate[];
certificatesValid: Certificate[]; certificatesValid: Certificate[];
private _gitOriginRepo;
constructor(optionsArg: { constructor(optionsArg: {
cfEmail: string; cfEmail: string;
cfKey: string; cfKey: string;
sslDir: string; sslDir: string;
gitOriginRepo?: string; gitOriginRepo?: string;
testMode?: boolean;
}); });
sslGitOriginPull: () => void; sslGitOriginPull: () => void;
sslGitOriginAddCommitPush: () => void; sslGitOriginAddCommitPush: () => void;
getDomainCert(domainNameArg: string, optionsArg?: { getDomainCert(domainNameArg: string, optionsArg?: {
force: boolean; force: boolean;
}): plugins.q.Promise<{}>; }): plugins.q.Promise<{}>;
cleanOldCertificates(): void;
} }
export declare class Certificate { export declare class Certificate {
domainName: string; domainName: string;

40
dist/index.js vendored

File diff suppressed because one or more lines are too long

View File

@ -4,7 +4,8 @@
"description": "Easily obain SSL certificates from LetsEncrypt. Supports DNS-01 challenge. TypeScript ready.", "description": "Easily obain SSL certificates from LetsEncrypt. Supports DNS-01 challenge. TypeScript ready.",
"main": "dist/index.js", "main": "dist/index.js",
"scripts": { "scripts": {
"test": "(npmts)", "test": "(npm run cleanTest && npmts)",
"cleanTest":"(rm -rf ./test/assets)",
"install": "node dist/install.js install", "install": "node dist/install.js install",
"compile":"(npmts --notest)" "compile":"(npmts --notest)"
}, },
@ -35,7 +36,7 @@
"shelljs": "^0.7.0", "shelljs": "^0.7.0",
"smartcli": "^1.0.4", "smartcli": "^1.0.4",
"smartfile": "^4.0.10", "smartfile": "^4.0.10",
"smartgit": "0.1.7", "smartgit": "0.1.8",
"smartstring": "^2.0.10", "smartstring": "^2.0.10",
"typings-global": "^1.0.6" "typings-global": "^1.0.6"
}, },

View File

@ -23,16 +23,17 @@ describe("cert", function () {
cfEmail: process.env.CF_EMAIL, cfEmail: process.env.CF_EMAIL,
cfKey: process.env.CF_KEY, cfKey: process.env.CF_KEY,
sslDir: path.join(process.cwd(), "test/assets"), sslDir: path.join(process.cwd(), "test/assets"),
gitOriginRepo: "git@gitlab.com:philkunz/sandbox-sslorigin.git" gitOriginRepo: "git@gitlab.com:philkunz/sandbox-sslorigin.git",
testMode: true
}); });
testCert.should.be.instanceof(cert.Cert); testCert.should.be.instanceof(cert.Cert);
}); });
it("should get a valid certificate", function (done) { it("should get a valid certificate", function (done) {
this.timeout(120000); this.timeout(120000);
testCert.getDomainCert("sub11.bleu.de").then(function () { testCert.getDomainCert("sub13.bleu.de").then(function () {
done(); done();
}); });
}); });
}); });
}); });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbInRlc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLFFBQU8sY0FBYyxDQUFDLENBQUE7QUFDdEIsUUFBTyxRQUFRLENBQUMsQ0FBQTtBQUNoQixxQkFBbUIsTUFBTSxDQUFDLENBQUE7QUFDMUIsSUFBTyxJQUFJLFdBQVcsTUFBTSxDQUFDLENBQUM7QUFFOUIsd0JBQTJCLGlCQUFpQixDQUFDLENBQUE7QUFDN0MsSUFBWSxJQUFJLFdBQU0sZUFBZSxDQUFDLENBQUE7QUFHdEMsSUFBSSxRQUFRLEdBQUcsSUFBSSxXQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsRUFBRSxFQUFFLE9BQU8sQ0FBQyxHQUFHLEVBQUUsR0FBRyxTQUFTLENBQUMsQ0FBQztBQUVsRSxJQUFJLFFBQWtCLENBQUM7QUFFdkIsUUFBUSxDQUFDLE1BQU0sRUFBQztJQUNaLFFBQVEsQ0FBQyxTQUFTLEVBQUM7UUFDZixFQUFFLENBQUMsZ0NBQWdDLEVBQUMsVUFBUyxJQUFJO1lBQzdDLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDbkIsc0JBQVksRUFBRSxDQUFDLElBQUksQ0FBQztnQkFDaEIsSUFBSSxFQUFFLENBQUM7WUFDWCxDQUFDLENBQUMsQ0FBQTtRQUNOLENBQUMsQ0FBQyxDQUFBO0lBQ04sQ0FBQyxDQUFDLENBQUE7SUFDRixRQUFRLENBQUMsTUFBTSxFQUFDO1FBQ1osRUFBRSxDQUFDLDRDQUE0QyxFQUFDO1lBQzVDLElBQUksQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDcEIsUUFBUSxHQUFHLElBQUksSUFBSSxDQUFDLElBQUksQ0FBQztnQkFDckIsT0FBTyxFQUFFLE9BQU8sQ0FBQyxHQUFHLENBQUMsUUFBUTtnQkFDN0IsS0FBSyxFQUFFLE9BQU8sQ0FBQyxHQUFHLENBQUMsTUFBTTtnQkFDekIsTUFBTSxFQUFFLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsRUFBRSxFQUFDLGFBQWEsQ0FBQztnQkFDOUMsYUFBYSxFQUFDLCtDQUErQzthQUNoRSxDQUFDLENBQUM7WUFDSCxRQUFRLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQzdDLENBQUMsQ0FBQyxDQUFBO1FBQ0YsRUFBRSxDQUFDLGdDQUFnQyxFQUFDLFVBQVMsSUFBSTtZQUM3QyxJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQ3JCLFFBQVEsQ0FBQyxhQUFhLENBQUMsZUFBZSxDQUFDLENBQUMsSUFBSSxDQUFDO2dCQUN6QyxJQUFJLEVBQUUsQ0FBQztZQUNYLENBQUMsQ0FBQyxDQUFDO1FBQ1AsQ0FBQyxDQUFDLENBQUE7SUFDTixDQUFDLENBQUMsQ0FBQTtBQUNOLENBQUMsQ0FBQyxDQUFDIn0= //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbInRlc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLFFBQU8sY0FBYyxDQUFDLENBQUE7QUFDdEIsUUFBTyxRQUFRLENBQUMsQ0FBQTtBQUNoQixxQkFBbUIsTUFBTSxDQUFDLENBQUE7QUFDMUIsSUFBTyxJQUFJLFdBQVcsTUFBTSxDQUFDLENBQUM7QUFFOUIsd0JBQTJCLGlCQUFpQixDQUFDLENBQUE7QUFDN0MsSUFBWSxJQUFJLFdBQU0sZUFBZSxDQUFDLENBQUE7QUFHdEMsSUFBSSxRQUFRLEdBQUcsSUFBSSxXQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsRUFBRSxFQUFFLE9BQU8sQ0FBQyxHQUFHLEVBQUUsR0FBRyxTQUFTLENBQUMsQ0FBQztBQUVsRSxJQUFJLFFBQWtCLENBQUM7QUFFdkIsUUFBUSxDQUFDLE1BQU0sRUFBQztJQUNaLFFBQVEsQ0FBQyxTQUFTLEVBQUM7UUFDZixFQUFFLENBQUMsZ0NBQWdDLEVBQUMsVUFBUyxJQUFJO1lBQzdDLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDbkIsc0JBQVksRUFBRSxDQUFDLElBQUksQ0FBQztnQkFDaEIsSUFBSSxFQUFFLENBQUM7WUFDWCxDQUFDLENBQUMsQ0FBQTtRQUNOLENBQUMsQ0FBQyxDQUFBO0lBQ04sQ0FBQyxDQUFDLENBQUE7SUFDRixRQUFRLENBQUMsTUFBTSxFQUFDO1FBQ1osRUFBRSxDQUFDLDRDQUE0QyxFQUFDO1lBQzVDLElBQUksQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDcEIsUUFBUSxHQUFHLElBQUksSUFBSSxDQUFDLElBQUksQ0FBQztnQkFDckIsT0FBTyxFQUFFLE9BQU8sQ0FBQyxHQUFHLENBQUMsUUFBUTtnQkFDN0IsS0FBSyxFQUFFLE9BQU8sQ0FBQyxHQUFHLENBQUMsTUFBTTtnQkFDekIsTUFBTSxFQUFFLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsRUFBRSxFQUFDLGFBQWEsQ0FBQztnQkFDOUMsYUFBYSxFQUFDLCtDQUErQztnQkFDN0QsUUFBUSxFQUFDLElBQUk7YUFDaEIsQ0FBQyxDQUFDO1lBQ0gsUUFBUSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUM3QyxDQUFDLENBQUMsQ0FBQTtRQUNGLEVBQUUsQ0FBQyxnQ0FBZ0MsRUFBQyxVQUFTLElBQUk7WUFDN0MsSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQztZQUNyQixRQUFRLENBQUMsYUFBYSxDQUFDLGVBQWUsQ0FBQyxDQUFDLElBQUksQ0FBQztnQkFDekMsSUFBSSxFQUFFLENBQUM7WUFDWCxDQUFDLENBQUMsQ0FBQztRQUNQLENBQUMsQ0FBQyxDQUFBO0lBQ04sQ0FBQyxDQUFDLENBQUE7QUFDTixDQUFDLENBQUMsQ0FBQyJ9

View File

@ -27,13 +27,14 @@ describe("cert",function(){
cfEmail: process.env.CF_EMAIL, cfEmail: process.env.CF_EMAIL,
cfKey: process.env.CF_KEY, cfKey: process.env.CF_KEY,
sslDir: path.join(process.cwd(),"test/assets"), sslDir: path.join(process.cwd(),"test/assets"),
gitOriginRepo:"git@gitlab.com:philkunz/sandbox-sslorigin.git" gitOriginRepo:"git@gitlab.com:sandboxzone/sandbox-sslorigin.git",
testMode:true
}); });
testCert.should.be.instanceof(cert.Cert); testCert.should.be.instanceof(cert.Cert);
}) })
it("should get a valid certificate",function(done){ it("should get a valid certificate",function(done){
this.timeout(120000); this.timeout(120000);
testCert.getDomainCert("sub11.bleu.de").then(() => { testCert.getDomainCert("sub13.bleu.de").then(() => {
done(); done();
}); });
}) })

View File

@ -1,6 +1,11 @@
import * as plugins from "./cert.plugins"; import * as plugins from "./cert.plugins";
// files
export let certHook = plugins.path.join(__dirname,"cert.hook.js"); export let certHook = plugins.path.join(__dirname,"cert.hook.js");
export let config = plugins.path.join(__dirname,"assets/config.json"); 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"); export let letsencryptSh = plugins.path.join(__dirname,"assets/letsencrypt.sh");
//dirs
export let certDir = plugins.path.join(__dirname,"/assets/certs"); export let certDir = plugins.path.join(__dirname,"/assets/certs");
export let assetDir = plugins.path.join(__dirname,"/assets/");

View File

@ -5,29 +5,48 @@ export class Cert {
private _cfEmail: string; private _cfEmail: string;
private _cfKey: string; private _cfKey: string;
private _sslDir: string; private _sslDir: string;
private _gitOriginRepo: string;
private _testMode: boolean
certificatesPresent: Certificate[]; certificatesPresent: Certificate[];
certificatesValid: Certificate[]; certificatesValid: Certificate[];
private _gitOriginRepo;
constructor(optionsArg: { constructor(optionsArg: {
cfEmail: string, cfEmail: string,
cfKey: string, cfKey: string,
sslDir: string, sslDir: string,
gitOriginRepo?: string gitOriginRepo?: string,
testMode?: boolean
}) { }) {
this._cfEmail = optionsArg.cfEmail; this._cfEmail = optionsArg.cfEmail;
this._cfKey = optionsArg.cfKey; this._cfKey = optionsArg.cfKey;
this._sslDir = optionsArg.sslDir; this._sslDir = optionsArg.sslDir;
this._gitOriginRepo = optionsArg.gitOriginRepo; this._gitOriginRepo = optionsArg.gitOriginRepo;
this._testMode = optionsArg.testMode;
// write hook config
let config = { let config = {
cfEmail: this._cfEmail, cfEmail: this._cfEmail,
cfKey: this._cfKey cfKey: this._cfKey
} }
plugins.smartfile.memory.toFsSync(JSON.stringify(config),plugins.path.join(__dirname, "assets/config.json")); plugins.smartfile.memory.toFsSync(
JSON.stringify(config),
plugins.path.join(__dirname, "assets/config.json")
);
// setup Git
if (this._gitOriginRepo) { if (this._gitOriginRepo) {
plugins.smartgit.init(this._sslDir); plugins.smartgit.init(this._sslDir);
plugins.smartgit.remote.add(this._sslDir, "origin", this._gitOriginRepo); plugins.smartgit.remote.add(this._sslDir, "origin", this._gitOriginRepo);
this.sslGitOriginPull(); 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
);
}; };
sslGitOriginPull = () => { sslGitOriginPull = () => {
if (this._gitOriginRepo) { if (this._gitOriginRepo) {
@ -41,13 +60,16 @@ export class Cert {
plugins.smartgit.push(this._sslDir, "origin", "master"); plugins.smartgit.push(this._sslDir, "origin", "master");
} }
}; };
getDomainCert(domainNameArg: string,optionsArg?:{force:boolean}) { getDomainCert(domainNameArg: string, optionsArg: { force: boolean } = { force: false }) {
let done = plugins.q.defer(); let done = plugins.q.defer();
this.sslGitOriginPull(); this.sslGitOriginPull();
if (!checkDomainsStillValid(domainNameArg) || optionsArg.force) { if (!checkDomainsStillValid(domainNameArg, this._sslDir) || optionsArg.force) {
plugins.shelljs.exec("chmod 700 " + paths.letsencryptSh); plugins.shelljs.exec("chmod 700 " + paths.letsencryptSh);
plugins.shelljs.exec("chmod 700 " + paths.certHook); plugins.shelljs.exec("chmod 700 " + paths.certHook);
plugins.shelljs.exec("bash -c \"" + paths.letsencryptSh + " -c -d " + domainNameArg + " -t dns-01 -k " + paths.certHook + " -o " + paths.certDir + "\""); plugins.smartfile.fs.ensureDir(paths.certDir);
plugins.shelljs.exec(
`bash -c "${paths.letsencryptSh} -c -f ${paths.leShConfig} -d ${domainNameArg} -t dns-01 -k ${paths.certHook} -o ${paths.certDir}"`
);
let fetchedCertsArray: string[] = plugins.smartfile.fs.listFoldersSync(paths.certDir); let fetchedCertsArray: string[] = plugins.smartfile.fs.listFoldersSync(paths.certDir);
if (fetchedCertsArray.indexOf(domainNameArg) != -1) { if (fetchedCertsArray.indexOf(domainNameArg) != -1) {
updateSslDirSync(this._sslDir, domainNameArg); updateSslDirSync(this._sslDir, domainNameArg);
@ -60,6 +82,9 @@ export class Cert {
}; };
return done.promise; return done.promise;
}; };
cleanOldCertificates() {
};
} }
export class Certificate { export class Certificate {
@ -77,8 +102,22 @@ interface certConfig {
expires: number; expires: number;
} }
let checkDomainsStillValid = (domainNameArg: string): boolean => { 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; return false;
} else {
return true;
}
} else {
return false;
}
} }
let updateSslDirSync = (sslDirArg: string, domainNameArg: string) => { let updateSslDirSync = (sslDirArg: string, domainNameArg: string) => {
@ -102,7 +141,7 @@ let updateSslDirSync = (sslDirArg:string,domainNameArg:string) => {
created: certTime, created: certTime,
expires: certTime + 7776000 expires: certTime + 7776000
}; };
plugins.smartfile.memory.toFs( plugins.smartfile.memory.toFsSync(
JSON.stringify(certConfig), JSON.stringify(certConfig),
plugins.path.join(sslDirArg, domainNameArg, "config.json") plugins.path.join(sslDirArg, domainNameArg, "config.json")
); );