| 
									
										
										
										
											2016-06-22 13:22:09 +02:00
										 |  |  | import * as plugins from "./cert.plugins"; | 
					
						
							| 
									
										
										
										
											2016-06-18 15:59:03 +02:00
										 |  |  | import * as paths from "./cert.paths"; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-13 12:09:34 +02:00
										 |  |  | export interface ICertConstructorOptions { | 
					
						
							| 
									
										
										
										
											2016-07-12 18:00:08 +02:00
										 |  |  |     cfEmail: string, | 
					
						
							|  |  |  |     cfKey: string, | 
					
						
							| 
									
										
										
										
											2016-07-13 12:09:34 +02:00
										 |  |  |     sslDir?: string, | 
					
						
							| 
									
										
										
										
											2016-07-12 18:00:08 +02:00
										 |  |  |     gitOriginRepo?: string, | 
					
						
							|  |  |  |     testMode?: boolean | 
					
						
							|  |  |  | };  | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-18 15:59:03 +02:00
										 |  |  | export class Cert { | 
					
						
							| 
									
										
										
										
											2016-06-28 09:32:01 +02:00
										 |  |  |     private _cfEmail: string; | 
					
						
							|  |  |  |     private _cfKey: string; | 
					
						
							|  |  |  |     private _sslDir: string; | 
					
						
							| 
									
										
										
										
											2016-07-04 08:41:58 +02:00
										 |  |  |     private _gitOriginRepo: string; | 
					
						
							|  |  |  |     private _testMode: boolean | 
					
						
							|  |  |  |     certificatesPresent: Certificate[]; | 
					
						
							|  |  |  |     certificatesValid: Certificate[]; | 
					
						
							| 
									
										
										
										
											2016-07-13 12:09:34 +02:00
										 |  |  |     constructor(optionsArg:ICertConstructorOptions) { | 
					
						
							| 
									
										
										
										
											2016-06-28 09:32:01 +02:00
										 |  |  |         this._cfEmail = optionsArg.cfEmail; | 
					
						
							|  |  |  |         this._cfKey = optionsArg.cfKey; | 
					
						
							|  |  |  |         this._sslDir = optionsArg.sslDir; | 
					
						
							| 
									
										
										
										
											2016-07-04 04:56:49 +02:00
										 |  |  |         this._gitOriginRepo = optionsArg.gitOriginRepo; | 
					
						
							| 
									
										
										
										
											2016-07-04 08:41:58 +02:00
										 |  |  |         this._testMode = optionsArg.testMode; | 
					
						
							|  |  |  |         // write hook config
 | 
					
						
							| 
									
										
										
										
											2016-06-22 13:22:09 +02:00
										 |  |  |         let config = { | 
					
						
							| 
									
										
										
										
											2016-06-28 09:32:01 +02:00
										 |  |  |             cfEmail: this._cfEmail, | 
					
						
							|  |  |  |             cfKey: this._cfKey | 
					
						
							| 
									
										
										
										
											2016-06-22 13:22:09 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2016-07-04 08:41:58 +02:00
										 |  |  |         plugins.smartfile.memory.toFsSync( | 
					
						
							|  |  |  |             JSON.stringify(config), | 
					
						
							|  |  |  |             plugins.path.join(__dirname, "assets/config.json") | 
					
						
							|  |  |  |         ); | 
					
						
							| 
									
										
										
										
											2016-07-13 12:09:34 +02:00
										 |  |  |         // setup sslDir
 | 
					
						
							|  |  |  |         if (!this._sslDir) this._sslDir = paths.defaultSslDir; | 
					
						
							| 
									
										
										
										
											2016-07-04 08:41:58 +02:00
										 |  |  |         // setup Git
 | 
					
						
							|  |  |  |         if (this._gitOriginRepo) { | 
					
						
							| 
									
										
										
										
											2016-07-04 04:56:49 +02:00
										 |  |  |             plugins.smartgit.init(this._sslDir); | 
					
						
							| 
									
										
										
										
											2016-07-04 08:41:58 +02:00
										 |  |  |             plugins.smartgit.remote.add(this._sslDir, "origin", this._gitOriginRepo); | 
					
						
							| 
									
										
										
										
											2016-07-04 04:56:49 +02:00
										 |  |  |             this.sslGitOriginPull(); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2016-07-04 08:41:58 +02:00
										 |  |  |         // 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 | 
					
						
							|  |  |  |         ); | 
					
						
							| 
									
										
										
										
											2016-07-04 04:56:49 +02:00
										 |  |  |     }; | 
					
						
							|  |  |  |     sslGitOriginPull = () => { | 
					
						
							| 
									
										
										
										
											2016-07-04 08:41:58 +02:00
										 |  |  |         if (this._gitOriginRepo) { | 
					
						
							|  |  |  |             plugins.smartgit.pull(this._sslDir, "origin", "master"); | 
					
						
							| 
									
										
										
										
											2016-07-04 04:56:49 +02:00
										 |  |  |         } | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |     sslGitOriginAddCommitPush = () => { | 
					
						
							| 
									
										
										
										
											2016-07-04 08:41:58 +02:00
										 |  |  |         if (this._gitOriginRepo) { | 
					
						
							| 
									
										
										
										
											2016-07-04 04:56:49 +02:00
										 |  |  |             plugins.smartgit.add.addAll(this._sslDir); | 
					
						
							| 
									
										
										
										
											2016-07-04 08:41:58 +02:00
										 |  |  |             plugins.smartgit.commit(this._sslDir, "added new SSL certificates and deleted obsolete ones."); | 
					
						
							|  |  |  |             plugins.smartgit.push(this._sslDir, "origin", "master"); | 
					
						
							| 
									
										
										
										
											2016-07-04 04:56:49 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2016-06-22 13:22:09 +02:00
										 |  |  |     }; | 
					
						
							| 
									
										
										
										
											2016-07-04 08:41:58 +02:00
										 |  |  |     getDomainCert(domainNameArg: string, optionsArg: { force: boolean } = { force: false }) { | 
					
						
							| 
									
										
										
										
											2016-06-22 13:22:09 +02:00
										 |  |  |         let done = plugins.q.defer(); | 
					
						
							| 
									
										
										
										
											2016-07-04 04:56:49 +02:00
										 |  |  |         this.sslGitOriginPull(); | 
					
						
							| 
									
										
										
										
											2016-07-04 08:41:58 +02:00
										 |  |  |         if (!checkDomainsStillValid(domainNameArg, this._sslDir) || optionsArg.force) { | 
					
						
							| 
									
										
										
										
											2016-06-23 03:46:37 +02:00
										 |  |  |             plugins.shelljs.exec("chmod 700 " + paths.letsencryptSh); | 
					
						
							|  |  |  |             plugins.shelljs.exec("chmod 700 " + paths.certHook); | 
					
						
							| 
									
										
										
										
											2016-07-04 08:41:58 +02:00
										 |  |  |             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); | 
					
						
							|  |  |  |             if (fetchedCertsArray.indexOf(domainNameArg) != -1) { | 
					
						
							|  |  |  |                 updateSslDirSync(this._sslDir, domainNameArg); | 
					
						
							| 
									
										
										
										
											2016-07-13 16:06:16 +02:00
										 |  |  |                 plugins.smartfile.fs.removeSync(plugins.path.join(paths.certDir,domainNameArg)); | 
					
						
							| 
									
										
										
										
											2016-06-28 05:53:49 +02:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2016-07-04 04:56:49 +02:00
										 |  |  |             this.sslGitOriginAddCommitPush(); | 
					
						
							| 
									
										
										
										
											2016-06-23 03:46:37 +02:00
										 |  |  |             done.resolve(); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             plugins.beautylog.info("certificate for " + domainNameArg + " is still valid! Not fetching new one!"); | 
					
						
							|  |  |  |             done.resolve(); | 
					
						
							| 
									
										
										
										
											2016-07-04 04:56:49 +02:00
										 |  |  |         }; | 
					
						
							| 
									
										
										
										
											2016-06-22 13:22:09 +02:00
										 |  |  |         return done.promise; | 
					
						
							| 
									
										
										
										
											2016-06-18 15:59:03 +02:00
										 |  |  |     }; | 
					
						
							| 
									
										
										
										
											2016-07-04 08:41:58 +02:00
										 |  |  |     cleanOldCertificates() { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     }; | 
					
						
							| 
									
										
										
										
											2016-06-18 15:59:03 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-28 05:53:49 +02:00
										 |  |  | export class Certificate { | 
					
						
							| 
									
										
										
										
											2016-06-23 03:46:37 +02:00
										 |  |  |     domainName: string; | 
					
						
							|  |  |  |     creationDate: Date; | 
					
						
							|  |  |  |     expiryDate: Date; | 
					
						
							|  |  |  |     constructor() { | 
					
						
							| 
									
										
										
										
											2016-06-18 15:59:03 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     }; | 
					
						
							| 
									
										
										
										
											2016-06-22 13:55:38 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-28 09:32:01 +02:00
										 |  |  | interface certConfig { | 
					
						
							| 
									
										
										
										
											2016-07-04 08:41:58 +02:00
										 |  |  |     domainName: string; | 
					
						
							|  |  |  |     created: number; | 
					
						
							|  |  |  |     expires: number; | 
					
						
							| 
									
										
										
										
											2016-06-28 09:32:01 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-04 08:41:58 +02:00
										 |  |  | 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; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-23 03:46:37 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2016-06-22 13:55:38 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-04 08:41:58 +02:00
										 |  |  | let updateSslDirSync = (sslDirArg: string, domainNameArg: string) => { | 
					
						
							| 
									
										
										
										
											2016-06-28 09:32:01 +02:00
										 |  |  |     plugins.smartfile.fs.ensureDirSync(sslDirArg); | 
					
						
							| 
									
										
										
										
											2016-07-04 08:41:58 +02:00
										 |  |  |     let domainCertFolder = plugins.path.join(paths.certDir, domainNameArg) | 
					
						
							|  |  |  |     if (plugins.smartfile.fs.listFoldersSync(paths.certDir).indexOf(domainNameArg) != -1) { | 
					
						
							| 
									
										
										
										
											2016-06-28 09:32:01 +02:00
										 |  |  |         plugins.smartfile.fs.copySync( | 
					
						
							| 
									
										
										
										
											2016-07-04 08:41:58 +02:00
										 |  |  |             plugins.path.join(domainCertFolder, "fullchain.pem"), | 
					
						
							|  |  |  |             plugins.path.join(sslDirArg, domainNameArg, "fullchain.pem") | 
					
						
							| 
									
										
										
										
											2016-06-28 09:32:01 +02:00
										 |  |  |         ); | 
					
						
							|  |  |  |         plugins.smartfile.fs.copySync( | 
					
						
							| 
									
										
										
										
											2016-07-04 08:41:58 +02:00
										 |  |  |             plugins.path.join(domainCertFolder, "privkey.pem"), | 
					
						
							|  |  |  |             plugins.path.join(sslDirArg, domainNameArg, "privkey.pem") | 
					
						
							| 
									
										
										
										
											2016-06-28 09:32:01 +02:00
										 |  |  |         ); | 
					
						
							|  |  |  |         // create cert config
 | 
					
						
							| 
									
										
										
										
											2016-06-28 10:34:59 +02:00
										 |  |  |         let certRegex = /.*\-([0-9]*)\.pem/; | 
					
						
							| 
									
										
										
										
											2016-07-04 08:41:58 +02:00
										 |  |  |         let certFileNameWithTime: string = plugins.smartfile.fs.listFilesSync(domainCertFolder, certRegex)[0]; | 
					
						
							| 
									
										
										
										
											2016-06-28 09:32:01 +02:00
										 |  |  |         let certTime = parseInt(certRegex.exec(certFileNameWithTime)[1]); | 
					
						
							| 
									
										
										
										
											2016-07-04 08:41:58 +02:00
										 |  |  |         let certConfig: certConfig = { | 
					
						
							| 
									
										
										
										
											2016-06-28 09:32:01 +02:00
										 |  |  |             domainName: domainNameArg, | 
					
						
							|  |  |  |             created: certTime, | 
					
						
							|  |  |  |             expires: certTime + 7776000 | 
					
						
							|  |  |  |         }; | 
					
						
							| 
									
										
										
										
											2016-07-04 08:41:58 +02:00
										 |  |  |         plugins.smartfile.memory.toFsSync( | 
					
						
							| 
									
										
										
										
											2016-06-28 09:32:01 +02:00
										 |  |  |             JSON.stringify(certConfig), | 
					
						
							| 
									
										
										
										
											2016-07-04 08:41:58 +02:00
										 |  |  |             plugins.path.join(sslDirArg, domainNameArg, "config.json") | 
					
						
							| 
									
										
										
										
											2016-06-28 09:32:01 +02:00
										 |  |  |         ); | 
					
						
							|  |  |  |     }; | 
					
						
							| 
									
										
										
										
											2016-06-22 13:55:38 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-04 04:56:49 +02:00
										 |  |  | const enum gitSyncDirection { | 
					
						
							|  |  |  |     toOrigin, | 
					
						
							|  |  |  |     fromOrigin | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-04 08:41:58 +02:00
										 |  |  | let updateGitOrigin = (syncDirectionArg: gitSyncDirection) => { | 
					
						
							| 
									
										
										
										
											2016-07-04 04:56:49 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2016-06-23 03:46:37 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-04 04:56:49 +02:00
										 |  |  | updateGitOrigin(gitSyncDirection.toOrigin); |