34 Commits

Author SHA1 Message Date
3ca368755b 1.0.5 2016-07-24 19:56:36 +02:00
86fedee9ed now recovering from errors 2016-07-24 19:56:32 +02:00
fc91384a76 1.0.4 2016-07-24 19:39:23 +02:00
2e8cfd00d2 now paying respect to same zone subdomains 2016-07-24 19:39:20 +02:00
6c67556756 1.0.3 2016-07-22 03:39:54 +02:00
8e892c14bc test 2016-07-22 03:39:45 +02:00
adcf49d729 1.0.2 2016-07-22 03:28:33 +02:00
22d79491ce testing 2016-07-22 03:28:30 +02:00
1b23d1e435 1.0.1 2016-07-22 02:59:33 +02:00
1c2063ef82 now retrying 2016-07-22 02:59:11 +02:00
d48a6c8315 1.0.0 2016-07-22 02:13:23 +02:00
1185480b91 0.0.18 2016-07-22 02:12:58 +02:00
afddfe5217 improve README 2016-07-22 02:12:49 +02:00
159ffe0728 now requesting in parallel 2016-07-22 02:11:04 +02:00
3c3da30966 update README 2016-07-21 15:02:51 +02:00
d4b249a59b update 2016-07-21 14:58:05 +02:00
06256f7a4d 0.0.17 2016-07-13 16:06:27 +02:00
be6fc3adfd cleanup after oneself 2016-07-13 16:06:16 +02:00
5ccf5b81e2 0.0.16 2016-07-13 12:09:41 +02:00
d06a2cee2f update sslDir handling 2016-07-13 12:09:34 +02:00
a7525184ef 0.0.15 2016-07-12 18:00:15 +02:00
ae9865749a use interface for Cert constructor 2016-07-12 18:00:08 +02:00
b2482b3cfd 0.0.14 2016-07-12 16:36:34 +02:00
41988da3ed fix types 2016-07-12 16:36:29 +02:00
55d450be69 0.0.13 2016-07-06 03:23:54 +02:00
ae2ade8680 updated test 2016-07-06 03:23:51 +02:00
d7ec7e254e 0.0.12 2016-07-06 03:10:49 +02:00
4bd7aee8ea add typings to package.json 2016-07-06 03:10:36 +02:00
bf711c2bb6 update tests 2016-07-04 21:57:14 +02:00
eb9e6679c4 0.0.11 2016-07-04 09:00:31 +02:00
96c801cdbd now fully working 2016-07-04 08:41:58 +02:00
ee844fd348 implement Git Repo Sync 2016-07-04 04:56:49 +02:00
d06c7059bb update dependency typings 2016-07-01 06:26:10 +02:00
d36f2f0c33 update for latest npmts compatibility 2016-07-01 06:18:48 +02:00
24 changed files with 649 additions and 265 deletions

View File

@ -1,6 +1,9 @@
# Cert # Cert
Easily obain SSL certificates from LetsEncrypt. Supports DNS-01 challenge. TypeScript ready. Easily obain SSL certificates from LetsEncrypt. Supports DNS-01 challenge. TypeScript ready.
## Status
[![build status](https://gitlab.com/pushrocks/cert/badges/master/build.svg)](https://gitlab.com/pushrocks/cert/commits/master)
## Usage ## Usage
```typescript ```typescript
@ -13,13 +16,15 @@ let myCert = new Cert({
gitOriginRepo: "git@githhub.com/someuser/somereopo" // good for persistence in highly volatile environments like docker gitOriginRepo: "git@githhub.com/someuser/somereopo" // good for persistence in highly volatile environments like docker
}); });
myCert.getDomainCert("example.com"); myCert.getDomainCert("example.com"); // returns promise
``` ```
### sslDir > **Note:** cert supports async parallel cert fetching. If called twice for the same domain, only the first one will trigger.
## sslDir
to use the certificates it is important to understand what the structure of the ssl directory looks like. to use the certificates it is important to understand what the structure of the ssl directory looks like.
### using a git origin repo. ## using a git origin repo.
Often times you want to keep track of certificates in order to keep them Often times you want to keep track of certificates in order to keep them
even if the point of initial certificate request is gone. Imagine you have a dockerenvironement even if the point of initial certificate request is gone. Imagine you have a dockerenvironement
and you keep starting new container versions for the same domain. YOu ideally want to use a proxy and you keep starting new container versions for the same domain. YOu ideally want to use a proxy
@ -27,3 +32,8 @@ that handles SSL managemet for you. But even the proxy needs to be updated from
So you need some kind of persistence between versions. This is why you can sync up all certificates to a git repo over ssh So you need some kind of persistence between versions. This is why you can sync up all certificates to a git repo over ssh
Just make sure your id_rsa is in place for the node user and is allowed for the origin repo. Just make sure your id_rsa is in place for the node user and is allowed for the origin repo.
## Environment
Since cert relies on [letsencrypt.sh](https://github.com/lukas2511/letsencrypt.sh) in the background bash is needed on the system.
If you plan on using this on Windows check out [npmdocker](https://www.npmjs.com/package/npmdocker) which runs node programs in docker.
As of summer 2016 Windows will also ship with bash nativly included.

44
dist/cert.classes.cert.d.ts vendored Normal file
View File

@ -0,0 +1,44 @@
/// <reference types="q" />
import * as plugins from "./cert.plugins";
export interface ICertConstructorOptions {
cfEmail: string;
cfKey: string;
sslDir?: string;
gitOriginRepo?: string;
testMode?: boolean;
}
export declare class Cert {
private _cfEmail;
private _cfKey;
private _sslDir;
private _gitOriginRepo;
private _testMode;
domainCertRequestMap: plugins.lik.Stringmap;
certificatesPresent: Certificate[];
certificatesValid: Certificate[];
/**
* Constructor for Cert object
*/
constructor(optionsArg: ICertConstructorOptions);
/**
* Pulls already requested certificates from git origin
*/
sslGitOriginPull: () => void;
/**
* Pushes all new requested certificates to git origin
*/
sslGitOriginAddCommitPush: () => void;
/**
* gets a ssl cert for a given domain
*/
getDomainCert(domainNameArg: string, optionsArg?: {
force: boolean;
}): plugins.q.Promise<{}>;
cleanOldCertificates(): void;
}
export declare class Certificate {
domainName: string;
creationDate: Date;
expiryDate: Date;
constructor();
}

20
dist/cert.classes.cert.helpers.d.ts vendored Normal file
View File

@ -0,0 +1,20 @@
/// <reference types="q" />
import { Cert } from "./index.ts";
import * as plugins from "./cert.plugins";
/**
* schedule a retry of certificate request
*/
export declare let scheduleRetry: (domainArg: string, certClassArg: Cert) => 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;

59
dist/cert.classes.cert.helpers.js vendored Normal file
View File

@ -0,0 +1,59 @@
"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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2VydC5jbGFzc2VzLmNlcnQuaGVscGVycy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL2NlcnQuY2xhc3Nlcy5jZXJ0LmhlbHBlcnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUNBLE1BQVksT0FBTyxXQUFNLGdCQUFnQixDQUFDLENBQUE7QUFDMUMsTUFBWSxLQUFLLFdBQU0sY0FBYyxDQUFDLENBQUE7QUFJdEM7O0dBRUc7QUFDUSxxQkFBYSxHQUFHLENBQUMsU0FBZ0IsRUFBQyxZQUFpQjtJQUMxRCxJQUFJLElBQUksR0FBRyxPQUFPLENBQUMsQ0FBQyxDQUFDLEtBQUssRUFBRSxDQUFDO0lBQzdCLFVBQVUsQ0FBQztRQUNQLFlBQVksQ0FBQyxhQUFhLENBQUMsU0FBUyxDQUFDO2FBQ2hDLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDNUIsQ0FBQyxFQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ1QsTUFBTSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUM7QUFDeEIsQ0FBQyxDQUFDO0FBRUY7O0dBRUc7QUFDUSw4QkFBc0IsR0FBRyxDQUFDLGFBQXFCLEVBQUUsU0FBaUI7SUFDekUsSUFBSSxnQkFBZ0IsR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsYUFBYSxFQUFFLGFBQWEsQ0FBQyxDQUFDO0lBQ2xGLEVBQUUsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDLGNBQWMsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUN4RCxJQUFJLFlBQVksR0FBRyxPQUFPLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQyxZQUFZLENBQ2hELGdCQUFnQixFQUNoQixNQUFNLENBQ1QsQ0FBQztRQUNGLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsSUFBSSxDQUFDLENBQUMsWUFBWSxDQUFDLE9BQU8sR0FBRyxNQUFNLENBQUMsR0FBRyxJ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

137
dist/cert.classes.cert.js vendored Normal file

File diff suppressed because one or more lines are too long

1
dist/cert.hook.d.ts vendored
View File

@ -1 +0,0 @@
import "typings-global";

47
dist/cert.hook.js vendored

File diff suppressed because one or more lines are too long

View File

@ -1,5 +1,8 @@
import "typings-global"; export declare let certDir: string;
export declare let defaultSslDir: string;
export declare let assetDir: string;
export declare let accountsDir: string;
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;

14
dist/cert.paths.js vendored
View File

@ -1,9 +1,13 @@
"use strict"; "use strict";
require("typings-global"); const plugins = require("./cert.plugins");
var 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.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");
exports.certDir = plugins.path.join(__dirname, "/assets/certs"); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2VydC5wYXRocy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL2NlcnQucGF0aHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLE1BQVksT0FBTyxXQUFNLGdCQUFnQixDQUFDLENBQUE7QUFFMUMsTUFBTTtBQUNLLGVBQU8sR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUMsY0FBYyxDQUFDLENBQUM7QUFDdEQscUJBQWEsR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUMsc0JBQXNCLENBQUMsQ0FBQztBQUNwRSxnQkFBUSxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBQyxTQUFTLENBQUMsQ0FBQztBQUNsRCxtQkFBVyxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBQyxrQkFBa0IsQ0FBQyxDQUFDO0FBRXpFLFFBQVE7QUFDRyxnQkFBUSxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBQyxjQUFjLENBQUMsQ0FBQztBQUN2RCxjQUFNLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFDLG9CQUFvQixDQUFDLENBQUM7QUFDM0Qsa0JBQVUsR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUMsd0JBQXdCLENBQUMsQ0FBQztBQUNuRSxxQkFBYSxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBQyx1QkFBdUIsQ0FBQyxDQUFDIn0=
//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImNlcnQucGF0aHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLFFBQU8sZ0JBQWdCLENBQUMsQ0FBQTtBQUN4QixJQUFZLE9BQU8sV0FBTSxnQkFBZ0IsQ0FBQyxDQUFBO0FBRS9CLGdCQUFRLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFDLGNBQWMsQ0FBQyxDQUFDO0FBQ3ZELGNBQU0sR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUMsb0JBQW9CLENBQUMsQ0FBQztBQUMzRCxxQkFBYSxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBQyx1QkFBdUIsQ0FBQyxDQUFDO0FBQ3JFLGVBQU8sR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUMsZUFBZSxDQUFDLENBQUMiLCJmaWxlIjoiY2VydC5wYXRocy5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBcInR5cGluZ3MtZ2xvYmFsXCI7XG5pbXBvcnQgKiBhcyBwbHVnaW5zIGZyb20gXCIuL2NlcnQucGx1Z2luc1wiO1xuXG5leHBvcnQgbGV0IGNlcnRIb29rID0gcGx1Z2lucy5wYXRoLmpvaW4oX19kaXJuYW1lLFwiY2VydC5ob29rLmpzXCIpO1xuZXhwb3J0IGxldCBjb25maWcgPSBwbHVnaW5zLnBhdGguam9pbihfX2Rpcm5hbWUsXCJhc3NldHMvY29uZmlnLmpzb25cIik7XG5leHBvcnQgbGV0IGxldHNlbmNyeXB0U2ggPSBwbHVnaW5zLnBhdGguam9pbihfX2Rpcm5hbWUsXCJhc3NldHMvbGV0c2VuY3J5cHQuc2hcIik7XG5leHBvcnQgbGV0IGNlcnREaXIgPSBwbHVnaW5zLnBhdGguam9pbihfX2Rpcm5hbWUsXCIvYXNzZXRzL2NlcnRzXCIpOyJdfQ==

View File

@ -2,9 +2,10 @@ import "typings-global";
export import beautylog = require("beautylog"); export import beautylog = require("beautylog");
export import cflare = require("cflare"); export import cflare = require("cflare");
export declare let fs: any; export declare let fs: any;
export import lik = require("lik");
export import path = require("path"); export import path = require("path");
export declare let q: any; export import q = require("q");
export declare let shelljs: any; export import shelljs = require("shelljs");
export import smartcli = require("smartcli"); export import smartcli = require("smartcli");
export import smartfile = require("smartfile"); export import smartfile = require("smartfile");
export import smartgit = require("smartgit"); export import smartgit = require("smartgit");

View File

@ -3,6 +3,7 @@ require("typings-global");
exports.beautylog = require("beautylog"); exports.beautylog = require("beautylog");
exports.cflare = require("cflare"); exports.cflare = require("cflare");
exports.fs = require("fs-extra"); exports.fs = require("fs-extra");
exports.lik = require("lik");
exports.path = require("path"); exports.path = require("path");
exports.q = require("q"); exports.q = require("q");
exports.shelljs = require("shelljs"); exports.shelljs = require("shelljs");
@ -10,5 +11,4 @@ exports.smartcli = require("smartcli");
exports.smartfile = require("smartfile"); exports.smartfile = require("smartfile");
exports.smartgit = require("smartgit"); exports.smartgit = require("smartgit");
exports.smartstring = require("smartstring"); exports.smartstring = require("smartstring");
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2VydC5wbHVnaW5zLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvY2VydC5wbHVnaW5zLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSxRQUFPLGdCQUFnQixDQUFDLENBQUE7QUFDVixpQkFBUyxXQUFXLFdBQVcsQ0FBQyxDQUFDO0FBQ2pDLGNBQU0sV0FBVyxRQUFRLENBQUMsQ0FBQztBQUM5QixVQUFFLEdBQUcsT0FBTyxDQUFDLFVBQVUsQ0FBQyxDQUFDO0FBQ3RCLFdBQUcsV0FBVyxLQUFLLENBQUMsQ0FBQztBQUNyQixZQUFJLFdBQVcsTUFBTSxDQUFDLENBQUM7QUFDdkIsU0FBQyxXQUFXLEdBQUcsQ0FBQyxDQUFDO0FBQ2pCLGVBQU8sV0FBVyxTQUFTLENBQUMsQ0FBQztBQUM3QixnQkFBUSxXQUFXLFVBQVUsQ0FBQyxDQUFDO0FBQy9CLGlCQUFTLFdBQVcsV0FBVyxDQUFDLENBQUM7QUFDakMsZ0JBQVEsV0FBVyxVQUFVLENBQUMsQ0FBQztBQUMvQixtQkFBVyxXQUFXLGFBQWEsQ0FBQyxDQUFDIn0=
//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImNlcnQucGx1Z2lucy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsUUFBTyxnQkFBZ0IsQ0FBQyxDQUFBO0FBQ1YsaUJBQVMsV0FBVyxXQUFXLENBQUMsQ0FBQztBQUNqQyxjQUFNLFdBQVcsUUFBUSxDQUFDLENBQUM7QUFDOUIsVUFBRSxHQUFHLE9BQU8sQ0FBQyxVQUFVLENBQUMsQ0FBQztBQUN0QixZQUFJLFdBQVcsTUFBTSxDQUFDLENBQUM7QUFDMUIsU0FBQyxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQztBQUNqQixlQUFPLEdBQUcsT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQUFDO0FBQzFCLGdCQUFRLFdBQVcsVUFBVSxDQUFDLENBQUM7QUFDL0IsaUJBQVMsV0FBVyxXQUFXLENBQUMsQ0FBQztBQUNqQyxnQkFBUSxXQUFXLFVBQVUsQ0FBQyxDQUFDO0FBQy9CLG1CQUFXLFdBQVcsYUFBYSxDQUFDLENBQUMiLCJmaWxlIjoiY2VydC5wbHVnaW5zLmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IFwidHlwaW5ncy1nbG9iYWxcIjtcbmV4cG9ydCBpbXBvcnQgYmVhdXR5bG9nID0gcmVxdWlyZShcImJlYXV0eWxvZ1wiKTtcbmV4cG9ydCBpbXBvcnQgY2ZsYXJlID0gcmVxdWlyZShcImNmbGFyZVwiKTtcbmV4cG9ydCBsZXQgZnMgPSByZXF1aXJlKFwiZnMtZXh0cmFcIik7XG5leHBvcnQgaW1wb3J0IHBhdGggPSByZXF1aXJlKFwicGF0aFwiKTtcbmV4cG9ydCBsZXQgcSA9IHJlcXVpcmUoXCJxXCIpO1xuZXhwb3J0IGxldCBzaGVsbGpzID0gcmVxdWlyZShcInNoZWxsanNcIik7XG5leHBvcnQgaW1wb3J0IHNtYXJ0Y2xpID0gcmVxdWlyZShcInNtYXJ0Y2xpXCIpO1xuZXhwb3J0IGltcG9ydCBzbWFydGZpbGUgPSByZXF1aXJlKFwic21hcnRmaWxlXCIpO1xuZXhwb3J0IGltcG9ydCBzbWFydGdpdCA9IHJlcXVpcmUoXCJzbWFydGdpdFwiKTtcbmV4cG9ydCBpbXBvcnQgc21hcnRzdHJpbmcgPSByZXF1aXJlKFwic21hcnRzdHJpbmdcIik7XG5cbiJdfQ==

24
dist/index.d.ts vendored
View File

@ -1,23 +1 @@
export declare class Cert { export * from "./cert.classes.cert";
private _cfEmail;
private _cfKey;
private _sslDir;
certificatesPresent: Certificate[];
certificatesValid: Certificate[];
gitOriginRepo: any;
constructor(optionsArg: {
cfEmail: string;
cfKey: string;
sslDir: string;
gitOriginRepo?: string;
});
getDomainCert(domainNameArg: string, optionsArg?: {
force: boolean;
}): any;
}
export declare class Certificate {
domainName: string;
creationDate: Date;
expiryDate: Date;
constructor();
}

73
dist/index.js vendored

File diff suppressed because one or more lines are too long

4
dist/install.d.ts vendored
View File

@ -1 +1,3 @@
export declare let startInstall: () => any; /// <reference types="q" />
import * as plugins from "./cert.plugins";
export declare let startInstall: () => plugins.q.Promise<{}>;

15
dist/install.js vendored
View File

@ -1,20 +1,19 @@
"use strict"; "use strict";
var plugins = require("./cert.plugins"); const plugins = require("./cert.plugins");
var paths = require("./cert.paths"); const paths = require("./cert.paths");
exports.startInstall = function () { exports.startInstall = () => {
var done = plugins.q.defer(); let done = plugins.q.defer();
plugins.beautylog.info("installing letsencrypt.sh locally..."); plugins.beautylog.info("installing letsencrypt.sh locally...");
plugins.fs.ensureDir(plugins.path.join(__dirname, "assets/")); 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(function () { plugins.smartfile.remote.toFs("https://raw.githubusercontent.com/lukas2511/letsencrypt.sh/master/letsencrypt.sh", paths.letsencryptSh).then(() => {
plugins.beautylog.success("Done!"); plugins.beautylog.success("Done!");
done.resolve(); done.resolve();
}); });
return done.promise; return done.promise;
}; };
var smartcli = new plugins.smartcli.Smartcli(); let smartcli = new plugins.smartcli.Smartcli();
smartcli.addCommand({ smartcli.addCommand({
commandName: "install" commandName: "install"
}).then(exports.startInstall); }).then(exports.startInstall);
smartcli.startParse(); smartcli.startParse();
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5zdGFsbC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL2luc3RhbGwudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLE1BQVksT0FBTyxXQUFNLGdCQUFnQixDQUFDLENBQUE7QUFDMUMsTUFBWSxLQUFLLFdBQU0sY0FBYyxDQUFDLENBQUE7QUFFM0Isb0JBQVksR0FBRztJQUN0QixJQUFJLElBQUksR0FBRyxPQUFPLENBQUMsQ0FBQyxDQUFDLEtBQUssRUFBRSxDQUFDO0lBQzdCLE9BQU8sQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLHNDQUFzQyxDQUFDLENBQUM7SUFFL0QsT0FBTyxDQUFDLEVBQUUsQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLFNBQVMsQ0FBQyxDQUFDLENBQUM7SUFDOUQsT0FBTyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUN6QixrRkFBa0YsRUFDbEYsS0FBSyxDQUFDLGFBQWEsQ0FDdEIsQ0FBQyxJQUFJLENBQUM7UUFDSCxPQUFPLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUNuQyxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7SUFDbkIsQ0FBQyxDQUFDLENBQUM7SUFDSCxNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQztBQUN4QixDQUFDLENBQUM7QUFFRixJQUFJLFFBQVEsR0FBRyxJQUFJLE9BQU8sQ0FBQyxRQUFRLENBQUMsUUFBUSxFQUFFLENBQUM7QUFDL0MsUUFBUSxDQUFDLFVBQVUsQ0FBQztJQUNoQixXQUFXLEVBQUMsU0FBUztDQUN4QixDQUFDLENBQUMsSUFBSSxDQUFDLG9CQUFZLENBQUMsQ0FBQztBQUN0QixRQUFRLENBQUMsVUFBVSxFQUFFLENBQUMifQ==
//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImluc3RhbGwudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLElBQVksT0FBTyxXQUFNLGdCQUFnQixDQUFDLENBQUE7QUFDMUMsSUFBWSxLQUFLLFdBQU0sY0FBYyxDQUFDLENBQUE7QUFFM0Isb0JBQVksR0FBRztJQUN0QixJQUFJLElBQUksR0FBRyxPQUFPLENBQUMsQ0FBQyxDQUFDLEtBQUssRUFBRSxDQUFDO0lBQzdCLE9BQU8sQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLHNDQUFzQyxDQUFDLENBQUM7SUFFL0QsT0FBTyxDQUFDLEVBQUUsQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLFNBQVMsQ0FBQyxDQUFDLENBQUM7SUFDOUQsT0FBTyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUN6QixrRkFBa0YsRUFDbEYsS0FBSyxDQUFDLGFBQWEsQ0FDdEIsQ0FBQyxJQUFJLENBQUM7UUFDSCxPQUFPLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUNuQyxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7SUFDbkIsQ0FBQyxDQUFDLENBQUM7SUFDSCxNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQztBQUN4QixDQUFDLENBQUM7QUFFRixJQUFJLFFBQVEsR0FBRyxJQUFJLE9BQU8sQ0FBQyxRQUFRLENBQUMsUUFBUSxFQUFFLENBQUM7QUFDL0MsUUFBUSxDQUFDLFVBQVUsQ0FBQztJQUNoQixXQUFXLEVBQUMsU0FBUztDQUN4QixDQUFDLENBQUMsSUFBSSxDQUFDLG9CQUFZLENBQUMsQ0FBQztBQUN0QixRQUFRLENBQUMsVUFBVSxFQUFFLENBQUMiLCJmaWxlIjoiaW5zdGFsbC5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIHBsdWdpbnMgZnJvbSBcIi4vY2VydC5wbHVnaW5zXCI7XG5pbXBvcnQgKiBhcyBwYXRocyBmcm9tIFwiLi9jZXJ0LnBhdGhzXCI7XG5cbmV4cG9ydCBsZXQgc3RhcnRJbnN0YWxsID0gKCkgPT4ge1xuICAgIGxldCBkb25lID0gcGx1Z2lucy5xLmRlZmVyKCk7XG4gICAgcGx1Z2lucy5iZWF1dHlsb2cuaW5mbyhcImluc3RhbGxpbmcgbGV0c2VuY3J5cHQuc2ggbG9jYWxseS4uLlwiKTtcblxuICAgIHBsdWdpbnMuZnMuZW5zdXJlRGlyKHBsdWdpbnMucGF0aC5qb2luKF9fZGlybmFtZSwgXCJhc3NldHMvXCIpKTtcbiAgICBwbHVnaW5zLnNtYXJ0ZmlsZS5yZW1vdGUudG9GcyhcbiAgICAgICAgXCJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vbHVrYXMyNTExL2xldHNlbmNyeXB0LnNoL21hc3Rlci9sZXRzZW5jcnlwdC5zaFwiLFxuICAgICAgICBwYXRocy5sZXRzZW5jcnlwdFNoXG4gICAgKS50aGVuKCgpID0+IHtcbiAgICAgICAgcGx1Z2lucy5iZWF1dHlsb2cuc3VjY2VzcyhcIkRvbmUhXCIpO1xuICAgICAgICBkb25lLnJlc29sdmUoKTtcbiAgICB9KTtcbiAgICByZXR1cm4gZG9uZS5wcm9taXNlO1xufTtcblxubGV0IHNtYXJ0Y2xpID0gbmV3IHBsdWdpbnMuc21hcnRjbGkuU21hcnRjbGkoKTtcbnNtYXJ0Y2xpLmFkZENvbW1hbmQoe1xuICAgIGNvbW1hbmROYW1lOlwiaW5zdGFsbFwiXG59KS50aGVuKHN0YXJ0SW5zdGFsbCk7XG5zbWFydGNsaS5zdGFydFBhcnNlKCk7Il19

View File

@ -1,11 +1,14 @@
{ {
"name": "cert", "name": "cert",
"version": "0.0.10", "version": "1.0.5",
"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",
"typings": "dist/index.d.ts",
"scripts": { "scripts": {
"test": "(npmts)", "test": "(npm run cleanTest && npmts)",
"install": "node dist/install.js install" "cleanTest": "(rm -rf ./test/assets)",
"install": "node dist/install.js install",
"compile": "(npmts --notest)"
}, },
"repository": { "repository": {
"type": "git", "type": "git",
@ -24,21 +27,25 @@
}, },
"homepage": "https://gitlab.com/pushrocks/cert#readme", "homepage": "https://gitlab.com/pushrocks/cert#readme",
"dependencies": { "dependencies": {
"beautylog": "^5.0.12", "@types/minimatch": "^2.0.28",
"@types/q": "^0.0.27",
"@types/shelljs": "^0.3.27",
"beautylog": "^5.0.18",
"cflare": "0.0.9", "cflare": "0.0.9",
"fs-extra": "^0.30.0", "fs-extra": "^0.30.0",
"lik": "^1.0.5",
"q": "^1.4.1", "q": "^1.4.1",
"shelljs": "^0.7.0", "shelljs": "^0.7.1",
"smartcli": "^1.0.4", "smartcli": "^1.0.4",
"smartfile": "^4.0.8", "smartfile": "^4.0.12",
"smartgit": "0.1.0", "smartgit": "0.1.9",
"smartstring": "^2.0.10", "smartstring": "^2.0.15",
"typings-global": "^1.0.3" "typings-global": "^1.0.6"
}, },
"devDependencies": { "devDependencies": {
"npmts-g": "^5.2.6", "npmts-g": "^5.2.6",
"qenv": "^1.0.8", "qenv": "^1.0.8",
"should": "^9.0.2", "should": "^10.0.0",
"typings-test": "^1.0.1" "typings-test": "^1.0.1"
} }
} }

View File

@ -1,37 +1,47 @@
"use strict"; "use strict";
require("typings-test"); require("typings-test");
require("should"); require("should");
var qenv_1 = require("qenv"); const qenv_1 = require("qenv");
var path = require("path"); const path = require("path");
var install_1 = require("../dist/install"); const q = require("q");
var cert = require("../dist/index"); const install_1 = require("../dist/install");
var testQenv = new qenv_1.Qenv(process.cwd(), process.cwd() + "/.nogit"); const cert = require("../dist/index");
var testCert; let testQenv = new qenv_1.Qenv(process.cwd(), process.cwd() + "/.nogit");
let testCert;
describe("cert", function () { describe("cert", function () {
describe("install", function () { describe("install", function () {
it("should download letsencrypt.sh", function (done) { it("should download letsencrypt.sh", function (done) {
this.timeout(5000); this.timeout(5000);
install_1.startInstall().then(function () { install_1.startInstall().then(() => {
done(); done();
}); });
}); });
}); });
describe("Cert", function () { describe("Cert", function () {
it("should create a new Cert object from class", function () { it("should create a new Cert object from class", function () {
this.timeout(40000);
testCert = new cert.Cert({ testCert = new cert.Cert({
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: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(400000);
testCert.getDomainCert("sub9.bleu.de").then(function () { 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`));
q.all(promiseArray).then(() => {
done(); done();
}); });
}); });
}); });
}); });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbInRlc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLFFBQU8sY0FBYyxDQUFDLENBQUE7QUFDdEIsUUFBTyxRQUFRLENBQUMsQ0FBQTtBQUNoQix1QkFBbUIsTUFBTSxDQUFDLENBQUE7QUFDMUIsTUFBTyxJQUFJLFdBQVcsTUFBTSxDQUFDLENBQUM7QUFDOUIsTUFBTyxDQUFDLFdBQVcsR0FBRyxDQUFDLENBQUM7QUFDeEIsMEJBQTJCLGlCQUFpQixDQUFDLENBQUE7QUFDN0MsTUFBWSxJQUFJLFdBQU0sZUFBZSxDQUFDLENBQUE7QUFHdEMsSUFBSSxRQUFRLEdBQUcsSUFBSSxXQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsRUFBRSxFQUFFLE9BQU8sQ0FBQyxHQUFHLEVBQUUsR0FBRyxTQUFTLENBQUMsQ0FBQztBQUVsRSxJQUFJLFFBQWtCLENBQUM7QUFFdkIsUUFBUSxDQUFDLE1BQU0sRUFBQztJQUNaLFFBQVEsQ0FBQyxTQUFTLEVBQUM7UUFDZixFQUFFLENBQUMsZ0NBQWdDLEVBQUMsVUFBUyxJQUFJO1lBQzdDLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDbkIsc0JBQVksRUFBRSxDQUFDLElBQUksQ0FBQztnQkFDaEIsSUFBSSxFQUFFLENBQUM7WUFDWCxDQUFDLENBQUMsQ0FBQTtRQUNOLENBQUMsQ0FBQyxDQUFBO0lBQ04sQ0FBQyxDQUFDLENBQUE7SUFDRixRQUFRLENBQUMsTUFBTSxFQUFDO1FBQ1osRUFBRSxDQUFDLDRDQUE0QyxFQUFDO1lBQzVDLElBQUksQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDcEIsUUFBUSxHQUFHLElBQUksSUFBSSxDQUFDLElBQUksQ0FBQztnQkFDckIsT0FBTyxFQUFFLE9BQU8sQ0FBQyxHQUFHLENBQUMsUUFBUTtnQkFDN0IsS0FBSyxFQUFFLE9BQU8sQ0FBQyxHQUFHLENBQUMsTUFBTTtnQkFDekIsTUFBTSxFQUFFLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsRUFBRSxFQUFDLGFBQWEsQ0FBQztnQkFDOUMsYUFBYSxFQUFDLGtEQUFrRDtnQkFDaEUsUUFBUSxFQUFDLElBQUk7YUFDaEIsQ0FBQyxDQUFDO1lBQ0gsUUFBUSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUM3QyxDQUFDLENBQUMsQ0FBQTtRQUNGLEVBQUUsQ0FBQyxnQ0FBZ0MsRUFBQyxVQUFTLElBQUk7WUFDN0MsSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQztZQUNyQixJQUFJLFlBQVksR0FBRyxFQUFFLENBQUM7WUFDdEIsNEJBQTRCLEdBQUcsRUFBRSxHQUFHO2dCQUNoQyxNQUFNLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLEdBQUcsQ0FBQyxHQUFHLEdBQUcsR0FBRyxDQUFDLEdBQUcsR0FBRyxDQUFDLENBQUM7WUFDekQsQ0FBQztZQUNELFlBQVksQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLGFBQWEsQ0FBQyxVQUFVLGtCQUFrQixDQUFDLENBQUMsRUFBQyxNQUFNLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQztZQUM1RixZQUFZLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxhQUFhLENBQUMsVUFBVSxrQkFBa0IsQ0FBQyxDQUFDLEVBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUM7WUFDNUYsWUFBWSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsYUFBYSxDQUFDLFVBQVUsa0JBQWtCLENBQUMsQ0FBQyxFQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDO1lBQzVGLENBQUMsQ0FBQyxHQUFHLENBQUMsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDO2dCQUNyQixJQUFJLEVBQUUsQ0FBQztZQUNYLENBQUMsQ0FBQyxDQUFDO1FBQ1AsQ0FBQyxDQUFDLENBQUE7SUFDTixDQUFDLENBQUMsQ0FBQTtBQUNOLENBQUMsQ0FBQyxDQUFDIn0=
//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLFFBQU8sY0FBYyxDQUFDLENBQUE7QUFDdEIsUUFBTyxRQUFRLENBQUMsQ0FBQTtBQUNoQixxQkFBbUIsTUFBTSxDQUFDLENBQUE7QUFDMUIsSUFBTyxJQUFJLFdBQVcsTUFBTSxDQUFDLENBQUM7QUFFOUIsd0JBQTJCLGlCQUFpQixDQUFDLENBQUE7QUFDN0MsSUFBWSxJQUFJLFdBQU0sZUFBZSxDQUFDLENBQUE7QUFHdEMsSUFBSSxRQUFRLEdBQUcsSUFBSSxXQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsRUFBRSxFQUFFLE9BQU8sQ0FBQyxHQUFHLEVBQUUsR0FBRyxTQUFTLENBQUMsQ0FBQztBQUVsRSxJQUFJLFFBQWtCLENBQUM7QUFFdkIsUUFBUSxDQUFDLE1BQU0sRUFBQztJQUNaLFFBQVEsQ0FBQyxTQUFTLEVBQUM7UUFDZixFQUFFLENBQUMsZ0NBQWdDLEVBQUMsVUFBUyxJQUFJO1lBQzdDLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDbkIsc0JBQVksRUFBRSxDQUFDLElBQUksQ0FBQztnQkFDaEIsSUFBSSxFQUFFLENBQUM7WUFDWCxDQUFDLENBQUMsQ0FBQTtRQUNOLENBQUMsQ0FBQyxDQUFBO0lBQ04sQ0FBQyxDQUFDLENBQUE7SUFDRixRQUFRLENBQUMsTUFBTSxFQUFDO1FBQ1osRUFBRSxDQUFDLDRDQUE0QyxFQUFDO1lBQzVDLFFBQVEsR0FBRyxJQUFJLElBQUksQ0FBQyxJQUFJLENBQUM7Z0JBQ3JCLE9BQU8sRUFBRSxPQUFPLENBQUMsR0FBRyxDQUFDLFFBQVE7Z0JBQzdCLEtBQUssRUFBRSxPQUFPLENBQUMsR0FBRyxDQUFDLE1BQU07Z0JBQ3pCLE1BQU0sRUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLEVBQUUsRUFBQyxhQUFhLENBQUM7YUFDakQsQ0FBQyxDQUFDO1lBQ0gsUUFBUSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUM3QyxDQUFDLENBQUMsQ0FBQTtRQUNGLEVBQUUsQ0FBQyxnQ0FBZ0MsRUFBQyxVQUFTLElBQUk7WUFDN0MsSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQztZQUNyQixRQUFRLENBQUMsYUFBYSxDQUFDLGNBQWMsQ0FBQyxDQUFDLElBQUksQ0FBQztnQkFDeEMsSUFBSSxFQUFFLENBQUM7WUFDWCxDQUFDLENBQUMsQ0FBQztRQUNQLENBQUMsQ0FBQyxDQUFBO0lBQ04sQ0FBQyxDQUFDLENBQUE7QUFDTixDQUFDLENBQUMsQ0FBQyIsImZpbGUiOiJ0ZXN0LmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IFwidHlwaW5ncy10ZXN0XCI7XG5pbXBvcnQgXCJzaG91bGRcIjtcbmltcG9ydCB7UWVudn0gZnJvbSBcInFlbnZcIjtcbmltcG9ydCBwYXRoID0gcmVxdWlyZShcInBhdGhcIik7XG5cbmltcG9ydCB7c3RhcnRJbnN0YWxsfSBmcm9tIFwiLi4vZGlzdC9pbnN0YWxsXCI7XG5pbXBvcnQgKiBhcyBjZXJ0IGZyb20gXCIuLi9kaXN0L2luZGV4XCI7XG5cblxubGV0IHRlc3RRZW52ID0gbmV3IFFlbnYocHJvY2Vzcy5jd2QoKSwgcHJvY2Vzcy5jd2QoKSArIFwiLy5ub2dpdFwiKTtcblxubGV0IHRlc3RDZXJ0OmNlcnQuQ2VydDtcblxuZGVzY3JpYmUoXCJjZXJ0XCIsZnVuY3Rpb24oKXtcbiAgICBkZXNjcmliZShcImluc3RhbGxcIixmdW5jdGlvbigpe1xuICAgICAgICBpdChcInNob3VsZCBkb3dubG9hZCBsZXRzZW5jcnlwdC5zaFwiLGZ1bmN0aW9uKGRvbmUpe1xuICAgICAgICAgICAgdGhpcy50aW1lb3V0KDUwMDApO1xuICAgICAgICAgICAgc3RhcnRJbnN0YWxsKCkudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgZG9uZSgpO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgfSlcbiAgICB9KVxuICAgIGRlc2NyaWJlKFwiQ2VydFwiLGZ1bmN0aW9uKCl7XG4gICAgICAgIGl0KFwic2hvdWxkIGNyZWF0ZSBhIG5ldyBDZXJ0IG9iamVjdCBmcm9tIGNsYXNzXCIsZnVuY3Rpb24oKXtcbiAgICAgICAgICAgIHRlc3RDZXJ0ID0gbmV3IGNlcnQuQ2VydCh7XG4gICAgICAgICAgICAgICAgY2ZFbWFpbDogcHJvY2Vzcy5lbnYuQ0ZfRU1BSUwsXG4gICAgICAgICAgICAgICAgY2ZLZXk6IHByb2Nlc3MuZW52LkNGX0tFWSxcbiAgICAgICAgICAgICAgICBzc2xEaXI6IHBhdGguam9pbihwcm9jZXNzLmN3ZCgpLFwidGVzdC9hc3NldHNcIilcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdGVzdENlcnQuc2hvdWxkLmJlLmluc3RhbmNlb2YoY2VydC5DZXJ0KTtcbiAgICAgICAgfSlcbiAgICAgICAgaXQoXCJzaG91bGQgZ2V0IGEgdmFsaWQgY2VydGlmaWNhdGVcIixmdW5jdGlvbihkb25lKXtcbiAgICAgICAgICAgIHRoaXMudGltZW91dCgxMjAwMDApO1xuICAgICAgICAgICAgdGVzdENlcnQuZ2V0RG9tYWluQ2VydChcInN1YjkuYmxldS5kZVwiKS50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICBkb25lKCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSlcbiAgICB9KVxufSk7Il19

View File

@ -2,7 +2,7 @@ import "typings-test";
import "should"; import "should";
import {Qenv} from "qenv"; import {Qenv} from "qenv";
import path = require("path"); import path = require("path");
import q = require("q");
import {startInstall} from "../dist/install"; import {startInstall} from "../dist/install";
import * as cert from "../dist/index"; import * as cert from "../dist/index";
@ -22,16 +22,26 @@ describe("cert",function(){
}) })
describe("Cert",function(){ describe("Cert",function(){
it("should create a new Cert object from class",function(){ it("should create a new Cert object from class",function(){
this.timeout(40000);
testCert = new cert.Cert({ testCert = new cert.Cert({
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: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(1200000);
testCert.getDomainCert("sub9.bleu.de").then(() => { 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`));
q.all(promiseArray).then(() => {
done(); done();
}); });
}) })

View File

@ -0,0 +1,86 @@
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);

160
ts/cert.classes.cert.ts Normal file
View File

@ -0,0 +1,160 @@
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) {
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));
};
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();
};
} else {
plugins.beautylog.warn(`${domainNameArg} is already requesting`);
};
return done.promise;
};
cleanOldCertificates() {
};
}
export class Certificate {
domainName: string;
creationDate: Date;
expiryDate: Date;
constructor() {
};
};

View File

@ -1,7 +1,6 @@
#!/usr/bin/env node #!/usr/bin/env node
// the shebang line above makes sure this script will get interpreted by node // the shebang line above makes sure this script will get interpreted by node
import "typings-global";
import * as plugins from "./cert.plugins"; import * as plugins from "./cert.plugins";
import * as paths from "./cert.paths"; import * as paths from "./cert.paths";
@ -31,12 +30,15 @@ let cleanChallenge = (domainNameArg) => {
let done = plugins.q.defer(); let done = plugins.q.defer();
plugins.beautylog.log("cleaning challenge for " + domainNameArg); plugins.beautylog.log("cleaning challenge for " + domainNameArg);
cflare.removeRecord(prefixName(domainNameArg), "TXT"); cflare.removeRecord(prefixName(domainNameArg), "TXT");
cooldown().then(() => {
done.resolve();
});
return done.promise; return done.promise;
} }
let cooldown = () => { let cooldown = () => {
let done = plugins.q.defer(); let done = plugins.q.defer();
let cooldowntime = 40000; let cooldowntime = 60000;
let passedTime = 0; let passedTime = 0;
plugins.beautylog.log("Cooling down! " + (cooldowntime/1000).toString() + " seconds left"); plugins.beautylog.log("Cooling down! " + (cooldowntime/1000).toString() + " seconds left");
let coolDownCounter = () => { let coolDownCounter = () => {

View File

@ -1,7 +1,14 @@
import "typings-global";
import * as plugins from "./cert.plugins"; 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 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");
export let certDir = plugins.path.join(__dirname,"/assets/certs");

View File

@ -2,9 +2,10 @@ import "typings-global";
export import beautylog = require("beautylog"); export import beautylog = require("beautylog");
export import cflare = require("cflare"); export import cflare = require("cflare");
export let fs = require("fs-extra"); export let fs = require("fs-extra");
export import lik = require("lik");
export import path = require("path"); export import path = require("path");
export let q = require("q"); export import q = require("q");
export let shelljs = require("shelljs"); export import shelljs = require("shelljs");
export import smartcli = require("smartcli"); export import smartcli = require("smartcli");
export import smartfile = require("smartfile"); export import smartfile = require("smartfile");
export import smartgit = require("smartgit"); export import smartgit = require("smartgit");

View File

@ -1,95 +1,4 @@
import * as plugins from "./cert.plugins"; import * as plugins from "./cert.plugins";
import * as paths from "./cert.paths"; import * as paths from "./cert.paths";
export class Cert { export * from "./cert.classes.cert";
private _cfEmail: string;
private _cfKey: string;
private _sslDir: string;
certificatesPresent:Certificate[];
certificatesValid:Certificate[];
gitOriginRepo;
constructor(optionsArg: {
cfEmail: string,
cfKey: string,
sslDir: string,
gitOriginRepo?: string
}) {
this._cfEmail = optionsArg.cfEmail;
this._cfKey = optionsArg.cfKey;
this._sslDir = optionsArg.sslDir;
this.gitOriginRepo = optionsArg.gitOriginRepo;
let config = {
cfEmail: this._cfEmail,
cfKey: this._cfKey
}
plugins.smartfile.memory.toFsSync(JSON.stringify(config),plugins.path.join(__dirname, "assets/config.json"));
};
getDomainCert(domainNameArg: string,optionsArg?:{force:boolean}) {
let done = plugins.q.defer();
if (!checkDomainsStillValid(domainNameArg) || optionsArg.force) {
plugins.shelljs.exec("chmod 700 " + paths.letsencryptSh);
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 + "\"");
let fetchedCertsArray:string[] = plugins.smartfile.fs.listFoldersSync(paths.certDir);
if(fetchedCertsArray.indexOf(domainNameArg) != -1){
updateSslDirSync(this._sslDir,domainNameArg);
}
done.resolve();
} else {
plugins.beautylog.info("certificate for " + domainNameArg + " is still valid! Not fetching new one!");
done.resolve();
}
return done.promise;
};
}
export class Certificate {
domainName: string;
creationDate: Date;
expiryDate: Date;
constructor() {
};
}
interface certConfig {
domainName:string;
created:number;
expires:number;
}
let checkDomainsStillValid = (domainNameArg: string): boolean => {
return false;
}
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.toFs(
JSON.stringify(certConfig),
plugins.path.join(sslDirArg,domainNameArg,"config.json")
);
};
}
let updateGitOrigin = () => {
}