start transition to letsencrypt

This commit is contained in:
Philipp Kunz 2016-10-22 16:21:25 +02:00
parent 738c249a3e
commit 5c7bf24c56
6 changed files with 102 additions and 126 deletions

View File

@ -28,11 +28,12 @@
"homepage": "https://gitlab.com/pushrocks/cert#readme",
"dependencies": {
"@types/minimatch": "2.x.x",
"@types/q": "0.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",
"letsencrypt": "^2.1.8",
"lik": "^1.0.24",
"q": "^1.4.1",
"shelljs": "^0.7.4",

View File

@ -1,6 +1,7 @@
import * as plugins from "./cert.plugins";
import * as paths from "./cert.paths";
import * as helpers from "./cert.classes.cert.helpers"
import * as q from 'q'
import * as plugins from './cert.plugins'
import * as paths from './cert.paths'
import * as helpers from './cert.classes.cert.helpers'
export interface ICertConstructorOptions {
cfEmail: string,
@ -8,27 +9,27 @@ export interface ICertConstructorOptions {
sslDir?: string,
gitOriginRepo?: string,
testMode?: boolean
};
}
export class Cert {
private _cfEmail: string;
private _cfKey: string;
private _sslDir: string;
private _gitOriginRepo: string;
private _testMode: boolean;
domainCertRequestMap: plugins.lik.Stringmap = new plugins.lik.Stringmap();
certificatesPresent: Certificate[];
certificatesValid: Certificate[];
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
/**
* 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;
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,
@ -36,129 +37,111 @@ export class Cert {
}
plugins.smartfile.memory.toFsSync(
JSON.stringify(config),
plugins.path.join(__dirname, "assets/config.json")
);
plugins.path.join(__dirname, 'assets/config.json')
)
// setup sslDir
if (!this._sslDir) this._sslDir = paths.defaultSslDir;
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();
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
});
};
}
/**
* Pulls already requested certificates from git origin
*/
sslGitOriginPull = () => {
if (this._gitOriginRepo) {
plugins.smartgit.pull(this._sslDir, "origin", "master");
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");
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 }) {
let done = plugins.q.defer();
let domainStringData = new plugins.smartstring.Domain(domainNameArg);
let sameZoneRequesting: boolean = this.domainCertRequestMap.checkMinimatch("*" + domainStringData.zoneName)
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);
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}`);
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 (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();
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();
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);
plugins.beautylog.warn(`${domainNameArg} scheduled for retry. Waiting 1 minute!`)
helpers.scheduleRetry(domainNameArg, this).then(done.resolve)
}
this.domainCertRequestMap.removeString(domainNameArg);
this.domainCertRequestMap.removeString(domainNameArg)
}
);
)
} else {
plugins.beautylog.info(`${domainNameArg} is waiting for domains names of same zone to finish`);
this.domainCertRequestMap.removeString(domainNameArg);
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);
return !this.domainCertRequestMap.checkMinimatch('*' + domainStringData.zoneName)
},
() => {
this.getDomainCert(domainNameArg).then(done.resolve);
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();
};
plugins.beautylog.info('certificate for ' + domainNameArg + ' is still valid! Not fetching new one!')
this.domainCertRequestMap.removeString(domainNameArg)
done.resolve()
}
} else {
plugins.beautylog.warn(`${domainNameArg} is already requesting`);
};
plugins.beautylog.warn(`${domainNameArg} is already requesting`)
}
return done.promise;
};
return done.promise
}
cleanOldCertificates() {
};
}
}
export class Certificate {
domainName: string;
creationDate: Date;
expiryDate: Date;
domainName: string
creationDate: Date
expiryDate: Date
constructor() {
};
};
}
}

View File

@ -1,6 +1,3 @@
#!/usr/bin/env node
// the shebang line above makes sure this script will get interpreted by node
import * as plugins from "./cert.plugins";
import * as paths from "./cert.paths";

View File

@ -1,13 +1,28 @@
import "typings-global";
export import beautylog = require("beautylog");
export import cflare = require("cflare");
export let fs = require("fs-extra");
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'
let fs = require('fs-extra')
let letsencrypt = require('letsencrypt')
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,
letsencrypt,
lik,
path,
q,
shelljs,
smartcli,
smartfile,
smartgit,
smartstring
}

View File

@ -1,23 +0,0 @@
import * as plugins from "./cert.plugins";
import * as paths from "./cert.paths";
export let 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(startInstall);
smartcli.startParse();

3
tslint.json Normal file
View File

@ -0,0 +1,3 @@
{
"extends": "tslint-config-standard"
}