smartcert/ts/cert.classes.cert.ts

165 lines
6.5 KiB
TypeScript
Raw Normal View History

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,
cfKey: string,
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[];
/**
* 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();
}
// 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");
}
};
/**
* 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 }) {
let done = plugins.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) {
2016-07-24 18:17:23 +00:00
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));
2016-07-24 18:17:23 +00:00
this.sslGitOriginAddCommitPush();
} else {
plugins.beautylog.error(`Couldn't copy final certificate for ${domainNameArg}!`);
};
done.resolve();
} else {
2016-07-24 17:56:32 +00:00
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();
};
} else {
plugins.beautylog.warn(`${domainNameArg} is already requesting`);
};
return done.promise;
};
cleanOldCertificates() {
};
}
export class Certificate {
domainName: string;
creationDate: Date;
expiryDate: Date;
constructor() {
};
};