@push.rocks/smartacme 4.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (C) 2016, Lossless GmbH
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
4
+ this software and associated documentation files (the "Software"), to deal in
5
+ the Software without restriction, including without limitation the rights to
6
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7
+ of the Software, and to permit persons to whom the Software is furnished to do
8
+ so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ SOFTWARE.
@@ -0,0 +1,8 @@
1
+ /**
2
+ * autocreated commitinfo by @pushrocks/commitinfo
3
+ */
4
+ export declare const commitinfo: {
5
+ name: string;
6
+ version: string;
7
+ description: string;
8
+ };
@@ -0,0 +1,9 @@
1
+ /**
2
+ * autocreated commitinfo by @pushrocks/commitinfo
3
+ */
4
+ export const commitinfo = {
5
+ name: '@pushrocks/smartacme',
6
+ version: '4.0.3',
7
+ description: 'acme with an easy yet powerful interface in TypeScript'
8
+ };
9
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSxzQkFBc0I7SUFDNUIsT0FBTyxFQUFFLE9BQU87SUFDaEIsV0FBVyxFQUFFLHdEQUF3RDtDQUN0RSxDQUFBIn0=
@@ -0,0 +1 @@
1
+ export * from './smartacme.classes.smartacme.js';
@@ -0,0 +1,2 @@
1
+ export * from './smartacme.classes.smartacme.js';
2
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxjQUFjLGtDQUFrQyxDQUFDIn0=
@@ -0,0 +1,13 @@
1
+ export interface IAccountData {
2
+ id: number;
3
+ key: {
4
+ kty: 'RSA';
5
+ n: string;
6
+ e: string;
7
+ kid: string;
8
+ };
9
+ contact: string[];
10
+ initialIp: string;
11
+ createdAt: string;
12
+ status: string;
13
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWNjb3VudGRhdGEuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9pbnRlcmZhY2VzL2FjY291bnRkYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiIifQ==
@@ -0,0 +1 @@
1
+ export * from './accountdata.js';
@@ -0,0 +1,2 @@
1
+ export * from './accountdata.js';
2
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9pbnRlcmZhY2VzL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLGNBQWMsa0JBQWtCLENBQUMifQ==
@@ -0,0 +1,14 @@
1
+ import * as plugins from './smartacme.plugins.js';
2
+ export declare class Cert extends plugins.smartdata.SmartDataDbDoc<Cert, plugins.tsclass.network.ICert> implements plugins.tsclass.network.ICert {
3
+ id: string;
4
+ domainName: string;
5
+ created: number;
6
+ privateKey: string;
7
+ publicKey: string;
8
+ csr: string;
9
+ validUntil: number;
10
+ isStillValid(): boolean;
11
+ shouldBeRenewed(): boolean;
12
+ update(certDataArg: plugins.tsclass.network.ICert): void;
13
+ constructor(optionsArg: plugins.tsclass.network.ICert);
14
+ }
@@ -0,0 +1,74 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ import * as plugins from './smartacme.plugins.js';
11
+ import './interfaces/index.js';
12
+ import { CertManager } from './smartacme.classes.certmanager.js';
13
+ import { svDb, unI } from '@pushrocks/smartdata';
14
+ let Cert = class Cert extends plugins.smartdata.SmartDataDbDoc {
15
+ isStillValid() {
16
+ return this.validUntil >= Date.now();
17
+ }
18
+ shouldBeRenewed() {
19
+ const shouldBeValidAtLeastUntil = Date.now() +
20
+ plugins.smarttime.getMilliSecondsFromUnits({
21
+ days: 10,
22
+ });
23
+ return !(this.validUntil >= shouldBeValidAtLeastUntil);
24
+ }
25
+ update(certDataArg) {
26
+ Object.keys(certDataArg).forEach((key) => {
27
+ this[key] = certDataArg[key];
28
+ });
29
+ }
30
+ constructor(optionsArg) {
31
+ super();
32
+ if (optionsArg) {
33
+ Object.keys(optionsArg).forEach((key) => {
34
+ this[key] = optionsArg[key];
35
+ });
36
+ }
37
+ }
38
+ };
39
+ __decorate([
40
+ unI(),
41
+ __metadata("design:type", String)
42
+ ], Cert.prototype, "id", void 0);
43
+ __decorate([
44
+ svDb(),
45
+ __metadata("design:type", String)
46
+ ], Cert.prototype, "domainName", void 0);
47
+ __decorate([
48
+ svDb(),
49
+ __metadata("design:type", Number)
50
+ ], Cert.prototype, "created", void 0);
51
+ __decorate([
52
+ svDb(),
53
+ __metadata("design:type", String)
54
+ ], Cert.prototype, "privateKey", void 0);
55
+ __decorate([
56
+ svDb(),
57
+ __metadata("design:type", String)
58
+ ], Cert.prototype, "publicKey", void 0);
59
+ __decorate([
60
+ svDb(),
61
+ __metadata("design:type", String)
62
+ ], Cert.prototype, "csr", void 0);
63
+ __decorate([
64
+ svDb(),
65
+ __metadata("design:type", Number)
66
+ ], Cert.prototype, "validUntil", void 0);
67
+ Cert = __decorate([
68
+ plugins.smartdata.Collection(() => {
69
+ return CertManager.activeDB;
70
+ }),
71
+ __metadata("design:paramtypes", [Object])
72
+ ], Cert);
73
+ export { Cert };
74
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRhY21lLmNsYXNzZXMuY2VydC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL3NtYXJ0YWNtZS5jbGFzc2VzLmNlcnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7O0FBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSx3QkFBd0IsQ0FBQztBQUVsRCxPQUE0Qix1QkFBdUIsQ0FBQztBQUVwRCxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sb0NBQW9DLENBQUM7QUFFakUsT0FBTyxFQUFjLElBQUksRUFBRSxHQUFHLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUt0RCxJQUFNLElBQUksR0FBVixNQUFNLElBQUssU0FBUSxPQUFPLENBQUMsU0FBUyxDQUFDLGNBQW1EO0lBdUJ0RixZQUFZO1FBQ2pCLE9BQU8sSUFBSSxDQUFDLFVBQVUsSUFBSSxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7SUFDdkMsQ0FBQztJQUVNLGVBQWU7UUFDcEIsTUFBTSx5QkFBeUIsR0FDN0IsSUFBSSxDQUFDLEdBQUcsRUFBRTtZQUNWLE9BQU8sQ0FBQyxTQUFTLENBQUMsd0JBQXdCLENBQUM7Z0JBQ3pDLElBQUksRUFBRSxFQUFFO2FBQ1QsQ0FBQyxDQUFDO1FBQ0wsT0FBTyxDQUFDLENBQUMsSUFBSSxDQUFDLFVBQVUsSUFBSSx5QkFBeUIsQ0FBQyxDQUFDO0lBQ3pELENBQUM7SUFFTSxNQUFNLENBQUMsV0FBMEM7UUFDdEQsTUFBTSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxHQUFHLEVBQUUsRUFBRTtZQUN2QyxJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsV0FBVyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQy9CLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVELFlBQVksVUFBeUM7UUFDbkQsS0FBSyxFQUFFLENBQUM7UUFDUixJQUFJLFVBQVUsRUFBRTtZQUNkLE1BQU0sQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsR0FBRyxFQUFFLEVBQUU7Z0JBQ3RDLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxVQUFVLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDOUIsQ0FBQyxDQUFDLENBQUM7U0FDSjtJQUNILENBQUM7Q0FDRixDQUFBO0FBaERDO0lBQUMsR0FBRyxFQUFFOztnQ0FDWTtBQUVsQjtJQUFDLElBQUksRUFBRTs7d0NBQ21CO0FBRTFCO0lBQUMsSUFBSSxFQUFFOztxQ0FDZ0I7QUFFdkI7SUFBQyxJQUFJLEVBQUU7O3dDQUNtQjtBQUUxQjtJQUFDLElBQUksRUFBRTs7dUNBQ2tCO0FBRXpCO0lBQUMsSUFBSSxFQUFFOztpQ0FDWTtBQUVuQjtJQUFDLElBQUksRUFBRTs7d0NBQ21CO0FBckJmLElBQUk7SUFIaEIsT0FBTyxDQUFDLFNBQVMsQ0FBQyxVQUFVLENBQUMsR0FBRyxFQUFFO1FBQ2pDLE9BQU8sV0FBVyxDQUFDLFFBQVEsQ0FBQztJQUM5QixDQUFDLENBQUM7O0dBQ1csSUFBSSxDQWtEaEI7U0FsRFksSUFBSSJ9
@@ -0,0 +1,25 @@
1
+ import * as plugins from './smartacme.plugins.js';
2
+ import { Cert } from './smartacme.classes.cert.js';
3
+ import { SmartAcme } from './smartacme.classes.smartacme.js';
4
+ export declare class CertManager {
5
+ static activeDB: plugins.smartdata.SmartdataDb;
6
+ private mongoDescriptor;
7
+ smartdataDb: plugins.smartdata.SmartdataDb;
8
+ interestMap: plugins.lik.InterestMap<string, Cert>;
9
+ constructor(smartAcmeArg: SmartAcme, optionsArg: {
10
+ mongoDescriptor: plugins.smartdata.IMongoDescriptor;
11
+ });
12
+ init(): Promise<void>;
13
+ /**
14
+ * retrieves a certificate
15
+ * @returns the Cert class or null
16
+ * @param certDomainNameArg the domain Name to retrieve the vcertificate for
17
+ */
18
+ retrieveCertificate(certDomainNameArg: string): Promise<Cert>;
19
+ /**
20
+ * stores the certificate
21
+ * @param optionsArg
22
+ */
23
+ storeCertificate(optionsArg: plugins.tsclass.network.ICert): Promise<void>;
24
+ deleteCertificate(certDomainNameArg: string): Promise<void>;
25
+ }
@@ -0,0 +1,53 @@
1
+ import * as plugins from './smartacme.plugins.js';
2
+ import { Cert } from './smartacme.classes.cert.js';
3
+ import './smartacme.classes.smartacme.js';
4
+ import './interfaces/index.js';
5
+ export class CertManager {
6
+ constructor(smartAcmeArg, optionsArg) {
7
+ this.mongoDescriptor = optionsArg.mongoDescriptor;
8
+ }
9
+ async init() {
10
+ // Smartdata DB
11
+ this.smartdataDb = new plugins.smartdata.SmartdataDb(this.mongoDescriptor);
12
+ await this.smartdataDb.init();
13
+ CertManager.activeDB = this.smartdataDb;
14
+ // Pending Map
15
+ this.interestMap = new plugins.lik.InterestMap((certName) => certName);
16
+ }
17
+ /**
18
+ * retrieves a certificate
19
+ * @returns the Cert class or null
20
+ * @param certDomainNameArg the domain Name to retrieve the vcertificate for
21
+ */
22
+ async retrieveCertificate(certDomainNameArg) {
23
+ const existingCertificate = await Cert.getInstance({
24
+ domainName: certDomainNameArg,
25
+ });
26
+ if (existingCertificate) {
27
+ return existingCertificate;
28
+ }
29
+ else {
30
+ return null;
31
+ }
32
+ }
33
+ /**
34
+ * stores the certificate
35
+ * @param optionsArg
36
+ */
37
+ async storeCertificate(optionsArg) {
38
+ const cert = new Cert(optionsArg);
39
+ await cert.save();
40
+ const interest = this.interestMap.findInterest(cert.domainName);
41
+ if (interest) {
42
+ interest.fullfillInterest(cert);
43
+ interest.markLost();
44
+ }
45
+ }
46
+ async deleteCertificate(certDomainNameArg) {
47
+ const cert = await Cert.getInstance({
48
+ domainName: certDomainNameArg,
49
+ });
50
+ await cert.delete();
51
+ }
52
+ }
53
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRhY21lLmNsYXNzZXMuY2VydG1hbmFnZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9zbWFydGFjbWUuY2xhc3Nlcy5jZXJ0bWFuYWdlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLHdCQUF3QixDQUFDO0FBQ2xELE9BQU8sRUFBRSxJQUFJLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUNuRCxPQUEwQixrQ0FBa0MsQ0FBQztBQUU3RCxPQUE0Qix1QkFBdUIsQ0FBQztBQUVwRCxNQUFNLE9BQU8sV0FBVztJQWN0QixZQUNFLFlBQXVCLEVBQ3ZCLFVBRUM7UUFFRCxJQUFJLENBQUMsZUFBZSxHQUFHLFVBQVUsQ0FBQyxlQUFlLENBQUM7SUFDcEQsQ0FBQztJQUVNLEtBQUssQ0FBQyxJQUFJO1FBQ2YsZUFBZTtRQUNmLElBQUksQ0FBQyxXQUFXLEdBQUcsSUFBSSxPQUFPLENBQUMsU0FBUyxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsZUFBZSxDQUFDLENBQUM7UUFDM0UsTUFBTSxJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksRUFBRSxDQUFDO1FBQzlCLFdBQVcsQ0FBQyxRQUFRLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQztRQUV4QyxjQUFjO1FBQ2QsSUFBSSxDQUFDLFdBQVcsR0FBRyxJQUFJLE9BQU8sQ0FBQyxHQUFHLENBQUMsV0FBVyxDQUFDLENBQUMsUUFBUSxFQUFFLEVBQUUsQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUN6RSxDQUFDO0lBRUQ7Ozs7T0FJRztJQUNJLEtBQUssQ0FBQyxtQkFBbUIsQ0FBQyxpQkFBeUI7UUFDeEQsTUFBTSxtQkFBbUIsR0FBUyxNQUFNLElBQUksQ0FBQyxXQUFXLENBQU87WUFDN0QsVUFBVSxFQUFFLGlCQUFpQjtTQUM5QixDQUFDLENBQUM7UUFFSCxJQUFJLG1CQUFtQixFQUFFO1lBQ3ZCLE9BQU8sbUJBQW1CLENBQUM7U0FDNUI7YUFBTTtZQUNMLE9BQU8sSUFBSSxDQUFDO1NBQ2I7SUFDSCxDQUFDO0lBRUQ7OztPQUdHO0lBQ0ksS0FBSyxDQUFDLGdCQUFnQixDQUFDLFVBQXlDO1FBQ3JFLE1BQU0sSUFBSSxHQUFHLElBQUksSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBQ2xDLE1BQU0sSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO1FBQ2xCLE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQztRQUNoRSxJQUFJLFFBQVEsRUFBRTtZQUNaLFFBQVEsQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUNoQyxRQUFRLENBQUMsUUFBUSxFQUFFLENBQUM7U0FDckI7SUFDSCxDQUFDO0lBRU0sS0FBSyxDQUFDLGlCQUFpQixDQUFDLGlCQUF5QjtRQUN0RCxNQUFNLElBQUksR0FBUyxNQUFNLElBQUksQ0FBQyxXQUFXLENBQU87WUFDOUMsVUFBVSxFQUFFLGlCQUFpQjtTQUM5QixDQUFDLENBQUM7UUFDSCxNQUFNLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztJQUN0QixDQUFDO0NBQ0YifQ==
@@ -0,0 +1,11 @@
1
+ /**
2
+ * certmatcher is responsible for matching certificates
3
+ */
4
+ export declare class CertMatcher {
5
+ /**
6
+ * creates a domainName for the certificate that will include the broadest scope
7
+ * for wild card certificates
8
+ * @param domainNameArg the domainNameArg to create the scope from
9
+ */
10
+ getCertificateDomainNameByDomainName(domainNameArg: string): string;
11
+ }
@@ -0,0 +1,19 @@
1
+ import * as plugins from './smartacme.plugins.js';
2
+ import './interfaces/index.js';
3
+ /**
4
+ * certmatcher is responsible for matching certificates
5
+ */
6
+ export class CertMatcher {
7
+ /**
8
+ * creates a domainName for the certificate that will include the broadest scope
9
+ * for wild card certificates
10
+ * @param domainNameArg the domainNameArg to create the scope from
11
+ */
12
+ getCertificateDomainNameByDomainName(domainNameArg) {
13
+ const originalDomain = new plugins.smartstring.Domain(domainNameArg);
14
+ if (!originalDomain.level4) {
15
+ return `${originalDomain.level2}.${originalDomain.level1}`;
16
+ }
17
+ }
18
+ }
19
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRhY21lLmNsYXNzZXMuY2VydG1hdGNoZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9zbWFydGFjbWUuY2xhc3Nlcy5jZXJ0bWF0Y2hlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLHdCQUF3QixDQUFDO0FBQ2xELE9BQTRCLHVCQUF1QixDQUFDO0FBRXBEOztHQUVHO0FBQ0gsTUFBTSxPQUFPLFdBQVc7SUFDdEI7Ozs7T0FJRztJQUNJLG9DQUFvQyxDQUFDLGFBQXFCO1FBQy9ELE1BQU0sY0FBYyxHQUFHLElBQUksT0FBTyxDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUMsYUFBYSxDQUFDLENBQUM7UUFDckUsSUFBSSxDQUFDLGNBQWMsQ0FBQyxNQUFNLEVBQUU7WUFDMUIsT0FBTyxHQUFHLGNBQWMsQ0FBQyxNQUFNLElBQUksY0FBYyxDQUFDLE1BQU0sRUFBRSxDQUFDO1NBQzVEO0lBQ0gsQ0FBQztDQUNGIn0=
@@ -0,0 +1,58 @@
1
+ import * as plugins from './smartacme.plugins.js';
2
+ import { Cert } from './smartacme.classes.cert.js';
3
+ /**
4
+ * the options for the class @see SmartAcme
5
+ */
6
+ export interface ISmartAcmeOptions {
7
+ accountPrivateKey?: string;
8
+ accountEmail: string;
9
+ mongoDescriptor: plugins.smartdata.IMongoDescriptor;
10
+ setChallenge: (dnsChallengeArg: plugins.tsclass.network.IDnsChallenge) => Promise<any>;
11
+ removeChallenge: (dnsChallengeArg: plugins.tsclass.network.IDnsChallenge) => Promise<any>;
12
+ environment: 'production' | 'integration';
13
+ }
14
+ /**
15
+ * class SmartAcme
16
+ * can be used for setting up communication with an ACME authority
17
+ *
18
+ * ```ts
19
+ * const mySmartAcmeInstance = new SmartAcme({
20
+ * // see ISmartAcmeOptions for options
21
+ * })
22
+ * ```
23
+ */
24
+ export declare class SmartAcme {
25
+ private options;
26
+ private client;
27
+ private smartdns;
28
+ logger: plugins.smartlog.ConsoleLog;
29
+ private privateKey;
30
+ private setChallenge;
31
+ private removeChallenge;
32
+ private certmanager;
33
+ private certmatcher;
34
+ constructor(optionsArg: ISmartAcmeOptions);
35
+ /**
36
+ * inits the instance
37
+ * ```ts
38
+ * await myCloudlyInstance.init() // does not support options
39
+ * ```
40
+ */
41
+ init(): Promise<void>;
42
+ stop(): Promise<void>;
43
+ /**
44
+ * gets a certificate
45
+ * it runs through the following steps
46
+ *
47
+ * * look in the database
48
+ * * if in the database and still valid return it
49
+ * * if not in the database announce it
50
+ * * then get it from letsencrypt
51
+ * * store it
52
+ * * remove it from the pending map (which it go onto by announcing it)
53
+ * * retrieve it from the databse and return it
54
+ *
55
+ * @param domainArg
56
+ */
57
+ getCertificateForDomain(domainArg: string): Promise<Cert>;
58
+ }
@@ -0,0 +1,164 @@
1
+ import * as plugins from './smartacme.plugins.js';
2
+ import './smartacme.classes.cert.js';
3
+ import { CertManager } from './smartacme.classes.certmanager.js';
4
+ import { CertMatcher } from './smartacme.classes.certmatcher.js';
5
+ /**
6
+ * class SmartAcme
7
+ * can be used for setting up communication with an ACME authority
8
+ *
9
+ * ```ts
10
+ * const mySmartAcmeInstance = new SmartAcme({
11
+ * // see ISmartAcmeOptions for options
12
+ * })
13
+ * ```
14
+ */
15
+ export class SmartAcme {
16
+ constructor(optionsArg) {
17
+ this.smartdns = new plugins.smartdns.Smartdns({});
18
+ this.options = optionsArg;
19
+ this.logger = new plugins.smartlog.ConsoleLog();
20
+ }
21
+ /**
22
+ * inits the instance
23
+ * ```ts
24
+ * await myCloudlyInstance.init() // does not support options
25
+ * ```
26
+ */
27
+ async init() {
28
+ this.privateKey =
29
+ this.options.accountPrivateKey || (await plugins.acme.forge.createPrivateKey()).toString();
30
+ this.setChallenge = this.options.setChallenge;
31
+ this.removeChallenge = this.options.removeChallenge;
32
+ // CertMangaer
33
+ this.certmanager = new CertManager(this, {
34
+ mongoDescriptor: this.options.mongoDescriptor,
35
+ });
36
+ await this.certmanager.init();
37
+ // CertMatcher
38
+ this.certmatcher = new CertMatcher();
39
+ // ACME Client
40
+ this.client = new plugins.acme.Client({
41
+ directoryUrl: (() => {
42
+ if (this.options.environment === 'production') {
43
+ return plugins.acme.directory.letsencrypt.production;
44
+ }
45
+ else {
46
+ return plugins.acme.directory.letsencrypt.staging;
47
+ }
48
+ })(),
49
+ accountKey: this.privateKey,
50
+ });
51
+ /* Register account */
52
+ await this.client.createAccount({
53
+ termsOfServiceAgreed: true,
54
+ contact: [`mailto:${this.options.accountEmail}`],
55
+ });
56
+ }
57
+ async stop() {
58
+ await this.certmanager.smartdataDb.close();
59
+ }
60
+ /**
61
+ * gets a certificate
62
+ * it runs through the following steps
63
+ *
64
+ * * look in the database
65
+ * * if in the database and still valid return it
66
+ * * if not in the database announce it
67
+ * * then get it from letsencrypt
68
+ * * store it
69
+ * * remove it from the pending map (which it go onto by announcing it)
70
+ * * retrieve it from the databse and return it
71
+ *
72
+ * @param domainArg
73
+ */
74
+ async getCertificateForDomain(domainArg) {
75
+ const certDomainName = this.certmatcher.getCertificateDomainNameByDomainName(domainArg);
76
+ const retrievedCertificate = await this.certmanager.retrieveCertificate(certDomainName);
77
+ if (!retrievedCertificate &&
78
+ (await this.certmanager.interestMap.checkInterest(certDomainName))) {
79
+ const existingCertificateInterest = this.certmanager.interestMap.findInterest(certDomainName);
80
+ const certificate = existingCertificateInterest.interestFullfilled;
81
+ return certificate;
82
+ }
83
+ else if (retrievedCertificate && !retrievedCertificate.shouldBeRenewed()) {
84
+ return retrievedCertificate;
85
+ }
86
+ else if (retrievedCertificate && retrievedCertificate.shouldBeRenewed()) {
87
+ await retrievedCertificate.delete();
88
+ }
89
+ // lets make sure others get the same interest
90
+ const currentDomainInterst = await this.certmanager.interestMap.addInterest(certDomainName);
91
+ /* Place new order */
92
+ const order = await this.client.createOrder({
93
+ identifiers: [
94
+ { type: 'dns', value: certDomainName },
95
+ { type: 'dns', value: `*.${certDomainName}` },
96
+ ],
97
+ });
98
+ /* Get authorizations and select challenges */
99
+ const authorizations = await this.client.getAuthorizations(order);
100
+ for (const authz of authorizations) {
101
+ console.log(authz);
102
+ const fullHostName = `_acme-challenge.${authz.identifier.value}`;
103
+ const dnsChallenge = authz.challenges.find((challengeArg) => {
104
+ return challengeArg.type === 'dns-01';
105
+ });
106
+ // process.exit(1);
107
+ const keyAuthorization = await this.client.getChallengeKeyAuthorization(dnsChallenge);
108
+ try {
109
+ /* Satisfy challenge */
110
+ await this.setChallenge({
111
+ hostName: fullHostName,
112
+ challenge: keyAuthorization,
113
+ });
114
+ await plugins.smartdelay.delayFor(30000);
115
+ await this.smartdns.checkUntilAvailable(fullHostName, 'TXT', keyAuthorization, 100, 5000);
116
+ console.log('Cool down an extra 60 second for region availability');
117
+ await plugins.smartdelay.delayFor(60000);
118
+ /* Verify that challenge is satisfied */
119
+ await this.client.verifyChallenge(authz, dnsChallenge);
120
+ /* Notify ACME provider that challenge is satisfied */
121
+ await this.client.completeChallenge(dnsChallenge);
122
+ /* Wait for ACME provider to respond with valid status */
123
+ await this.client.waitForValidStatus(dnsChallenge);
124
+ }
125
+ finally {
126
+ /* Clean up challenge response */
127
+ try {
128
+ await this.removeChallenge({
129
+ hostName: fullHostName,
130
+ challenge: keyAuthorization,
131
+ });
132
+ }
133
+ catch (e) {
134
+ console.log(e);
135
+ }
136
+ }
137
+ }
138
+ /* Finalize order */
139
+ const [key, csr] = await plugins.acme.forge.createCsr({
140
+ commonName: `*.${certDomainName}`,
141
+ altNames: [certDomainName],
142
+ });
143
+ await this.client.finalizeOrder(order, csr);
144
+ const cert = await this.client.getCertificate(order);
145
+ /* Done */
146
+ await this.certmanager.storeCertificate({
147
+ id: plugins.smartunique.shortId(),
148
+ domainName: certDomainName,
149
+ privateKey: key.toString(),
150
+ publicKey: cert.toString(),
151
+ csr: csr.toString(),
152
+ created: Date.now(),
153
+ validUntil: Date.now() +
154
+ plugins.smarttime.getMilliSecondsFromUnits({
155
+ days: 90,
156
+ }),
157
+ });
158
+ const newCertificate = await this.certmanager.retrieveCertificate(certDomainName);
159
+ currentDomainInterst.fullfillInterest(newCertificate);
160
+ currentDomainInterst.destroy();
161
+ return newCertificate;
162
+ }
163
+ }
164
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRhY21lLmNsYXNzZXMuc21hcnRhY21lLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvc21hcnRhY21lLmNsYXNzZXMuc21hcnRhY21lLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sd0JBQXdCLENBQUM7QUFDbEQsT0FBcUIsNkJBQTZCLENBQUM7QUFDbkQsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLG9DQUFvQyxDQUFDO0FBQ2pFLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxvQ0FBb0MsQ0FBQztBQWNqRTs7Ozs7Ozs7O0dBU0c7QUFDSCxNQUFNLE9BQU8sU0FBUztJQW1CcEIsWUFBWSxVQUE2QjtRQWRqQyxhQUFRLEdBQUcsSUFBSSxPQUFPLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUMsQ0FBQztRQWVuRCxJQUFJLENBQUMsT0FBTyxHQUFHLFVBQVUsQ0FBQztRQUMxQixJQUFJLENBQUMsTUFBTSxHQUFHLElBQUksT0FBTyxDQUFDLFFBQVEsQ0FBQyxVQUFVLEVBQUUsQ0FBQztJQUNsRCxDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDSSxLQUFLLENBQUMsSUFBSTtRQUNmLElBQUksQ0FBQyxVQUFVO1lBQ2IsSUFBSSxDQUFDLE9BQU8sQ0FBQyxpQkFBaUIsSUFBSSxDQUFDLE1BQU0sT0FBTyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQyxDQUFDLFFBQVEsRUFBRSxDQUFDO1FBQzdGLElBQUksQ0FBQyxZQUFZLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxZQUFZLENBQUM7UUFDOUMsSUFBSSxDQUFDLGVBQWUsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLGVBQWUsQ0FBQztRQUVwRCxjQUFjO1FBQ2QsSUFBSSxDQUFDLFdBQVcsR0FBRyxJQUFJLFdBQVcsQ0FBQyxJQUFJLEVBQUU7WUFDdkMsZUFBZSxFQUFFLElBQUksQ0FBQyxPQUFPLENBQUMsZUFBZTtTQUM5QyxDQUFDLENBQUM7UUFDSCxNQUFNLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxFQUFFLENBQUM7UUFFOUIsY0FBYztRQUNkLElBQUksQ0FBQyxXQUFXLEdBQUcsSUFBSSxXQUFXLEVBQUUsQ0FBQztRQUVyQyxjQUFjO1FBQ2QsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLE9BQU8sQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDO1lBQ3BDLFlBQVksRUFBRSxDQUFDLEdBQUcsRUFBRTtnQkFDbEIsSUFBSSxJQUFJLENBQUMsT0FBTyxDQUFDLFdBQVcsS0FBSyxZQUFZLEVBQUU7b0JBQzdDLE9BQU8sT0FBTyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsV0FBVyxDQUFDLFVBQVUsQ0FBQztpQkFDdEQ7cUJBQU07b0JBQ0wsT0FBTyxPQUFPLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxXQUFXLENBQUMsT0FBTyxDQUFDO2lCQUNuRDtZQUNILENBQUMsQ0FBQyxFQUFFO1lBQ0osVUFBVSxFQUFFLElBQUksQ0FBQyxVQUFVO1NBQzVCLENBQUMsQ0FBQztRQUVILHNCQUFzQjtRQUN0QixNQUFNLElBQUksQ0FBQyxNQUFNLENBQUMsYUFBYSxDQUFDO1lBQzlCLG9CQUFvQixFQUFFLElBQUk7WUFDMUIsT0FBTyxFQUFFLENBQUMsVUFBVSxJQUFJLENBQUMsT0FBTyxDQUFDLFlBQVksRUFBRSxDQUFDO1NBQ2pELENBQUMsQ0FBQztJQUNMLENBQUM7SUFFTSxLQUFLLENBQUMsSUFBSTtRQUNmLE1BQU0sSUFBSSxDQUFDLFdBQVcsQ0FBQyxXQUFXLENBQUMsS0FBSyxFQUFFLENBQUM7SUFDN0MsQ0FBQztJQUVEOzs7Ozs7Ozs7Ozs7O09BYUc7SUFDSSxLQUFLLENBQUMsdUJBQXVCLENBQUMsU0FBaUI7UUFDcEQsTUFBTSxjQUFjLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQyxvQ0FBb0MsQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUN4RixNQUFNLG9CQUFvQixHQUFHLE1BQU0sSUFBSSxDQUFDLFdBQVcsQ0FBQyxtQkFBbUIsQ0FBQyxjQUFjLENBQUMsQ0FBQztRQUV4RixJQUNFLENBQUMsb0JBQW9CO1lBQ3JCLENBQUMsTUFBTSxJQUFJLENBQUMsV0FBVyxDQUFDLFdBQVcsQ0FBQyxhQUFhLENBQUMsY0FBYyxDQUFDLENBQUMsRUFDbEU7WUFDQSxNQUFNLDJCQUEyQixHQUFHLElBQUksQ0FBQyxXQUFXLENBQUMsV0FBVyxDQUFDLFlBQVksQ0FBQyxjQUFjLENBQUMsQ0FBQztZQUM5RixNQUFNLFdBQVcsR0FBRywyQkFBMkIsQ0FBQyxrQkFBa0IsQ0FBQztZQUNuRSxPQUFPLFdBQVcsQ0FBQztTQUNwQjthQUFNLElBQUksb0JBQW9CLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxlQUFlLEVBQUUsRUFBRTtZQUMxRSxPQUFPLG9CQUFvQixDQUFDO1NBQzdCO2FBQU0sSUFBSSxvQkFBb0IsSUFBSSxvQkFBb0IsQ0FBQyxlQUFlLEVBQUUsRUFBRTtZQUN6RSxNQUFNLG9CQUFvQixDQUFDLE1BQU0sRUFBRSxDQUFDO1NBQ3JDO1FBRUQsOENBQThDO1FBQzlDLE1BQU0sb0JBQW9CLEdBQUcsTUFBTSxJQUFJLENBQUMsV0FBVyxDQUFDLFdBQVcsQ0FBQyxXQUFXLENBQUMsY0FBYyxDQUFDLENBQUM7UUFFNUYscUJBQXFCO1FBQ3JCLE1BQU0sS0FBSyxHQUFHLE1BQU0sSUFBSSxDQUFDLE1BQU0sQ0FBQyxXQUFXLENBQUM7WUFDMUMsV0FBVyxFQUFFO2dCQUNYLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsY0FBYyxFQUFFO2dCQUN0QyxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFFLEtBQUssY0FBYyxFQUFFLEVBQUU7YUFDOUM7U0FDRixDQUFDLENBQUM7UUFFSCw4Q0FBOEM7UUFDOUMsTUFBTSxjQUFjLEdBQUcsTUFBTSxJQUFJLENBQUMsTUFBTSxDQUFDLGlCQUFpQixDQUFDLEtBQUssQ0FBQyxDQUFDO1FBRWxFLEtBQUssTUFBTSxLQUFLLElBQUksY0FBYyxFQUFFO1lBQ2xDLE9BQU8sQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDbkIsTUFBTSxZQUFZLEdBQVcsbUJBQW1CLEtBQUssQ0FBQyxVQUFVLENBQUMsS0FBSyxFQUFFLENBQUM7WUFDekUsTUFBTSxZQUFZLEdBQVcsS0FBSyxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxZQUFZLEVBQUUsRUFBRTtnQkFDbEUsT0FBTyxZQUFZLENBQUMsSUFBSSxLQUFLLFFBQVEsQ0FBQztZQUN4QyxDQUFDLENBQUMsQ0FBQztZQUNILG1CQUFtQjtZQUNuQixNQUFNLGdCQUFnQixHQUFXLE1BQU0sSUFBSSxDQUFDLE1BQU0sQ0FBQyw0QkFBNEIsQ0FBQyxZQUFZLENBQUMsQ0FBQztZQUU5RixJQUFJO2dCQUNGLHVCQUF1QjtnQkFDdkIsTUFBTSxJQUFJLENBQUMsWUFBWSxDQUFDO29CQUN0QixRQUFRLEVBQUUsWUFBWTtvQkFDdEIsU0FBUyxFQUFFLGdCQUFnQjtpQkFDNUIsQ0FBQyxDQUFDO2dCQUNILE1BQU0sT0FBTyxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUM7Z0JBQ3pDLE1BQU0sSUFBSSxDQUFDLFFBQVEsQ0FBQyxtQkFBbUIsQ0FBQyxZQUFZLEVBQUUsS0FBSyxFQUFFLGdCQUFnQixFQUFFLEdBQUcsRUFBRSxJQUFJLENBQUMsQ0FBQztnQkFDMUYsT0FBTyxDQUFDLEdBQUcsQ0FBQyxzREFBc0QsQ0FBQyxDQUFDO2dCQUNwRSxNQUFNLE9BQU8sQ0FBQyxVQUFVLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDO2dCQUV6Qyx3Q0FBd0M7Z0JBQ3hDLE1BQU0sSUFBSSxDQUFDLE1BQU0sQ0FBQyxlQUFlLENBQUMsS0FBSyxFQUFFLFlBQVksQ0FBQyxDQUFDO2dCQUV2RCxzREFBc0Q7Z0JBQ3RELE1BQU0sSUFBSSxDQUFDLE1BQU0sQ0FBQyxpQkFBaUIsQ0FBQyxZQUFZLENBQUMsQ0FBQztnQkFFbEQseURBQXlEO2dCQUN6RCxNQUFNLElBQUksQ0FBQyxNQUFNLENBQUMsa0JBQWtCLENBQUMsWUFBWSxDQUFDLENBQUM7YUFDcEQ7b0JBQVM7Z0JBQ1IsaUNBQWlDO2dCQUNqQyxJQUFJO29CQUNGLE1BQU0sSUFBSSxDQUFDLGVBQWUsQ0FBQzt3QkFDekIsUUFBUSxFQUFFLFlBQVk7d0JBQ3RCLFNBQVMsRUFBRSxnQkFBZ0I7cUJBQzVCLENBQUMsQ0FBQztpQkFDSjtnQkFBQyxPQUFPLENBQUMsRUFBRTtvQkFDVixPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDO2lCQUNoQjthQUNGO1NBQ0Y7UUFFRCxvQkFBb0I7UUFDcEIsTUFBTSxDQUFDLEdBQUcsRUFBRSxHQUFHLENBQUMsR0FBRyxNQUFNLE9BQU8sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLFNBQVMsQ0FBQztZQUNwRCxVQUFVLEVBQUUsS0FBSyxjQUFjLEVBQUU7WUFDakMsUUFBUSxFQUFFLENBQUMsY0FBYyxDQUFDO1NBQzNCLENBQUMsQ0FBQztRQUVILE1BQU0sSUFBSSxDQUFDLE1BQU0sQ0FBQyxhQUFhLENBQUMsS0FBSyxFQUFFLEdBQUcsQ0FBQyxDQUFDO1FBQzVDLE1BQU0sSUFBSSxHQUFHLE1BQU0sSUFBSSxDQUFDLE1BQU0sQ0FBQyxjQUFjLENBQUMsS0FBSyxDQUFDLENBQUM7UUFFckQsVUFBVTtRQUVWLE1BQU0sSUFBSSxDQUFDLFdBQVcsQ0FBQyxnQkFBZ0IsQ0FBQztZQUN0QyxFQUFFLEVBQUUsT0FBTyxDQUFDLFdBQVcsQ0FBQyxPQUFPLEVBQUU7WUFDakMsVUFBVSxFQUFFLGNBQWM7WUFDMUIsVUFBVSxFQUFFLEdBQUcsQ0FBQyxRQUFRLEVBQUU7WUFDMUIsU0FBUyxFQUFFLElBQUksQ0FBQyxRQUFRLEVBQUU7WUFDMUIsR0FBRyxFQUFFLEdBQUcsQ0FBQyxRQUFRLEVBQUU7WUFDbkIsT0FBTyxFQUFFLElBQUksQ0FBQyxHQUFHLEVBQUU7WUFDbkIsVUFBVSxFQUNSLElBQUksQ0FBQyxHQUFHLEVBQUU7Z0JBQ1YsT0FBTyxDQUFDLFNBQVMsQ0FBQyx3QkFBd0IsQ0FBQztvQkFDekMsSUFBSSxFQUFFLEVBQUU7aUJBQ1QsQ0FBQztTQUNMLENBQUMsQ0FBQztRQUVILE1BQU0sY0FBYyxHQUFHLE1BQU0sSUFBSSxDQUFDLFdBQVcsQ0FBQyxtQkFBbUIsQ0FBQyxjQUFjLENBQUMsQ0FBQztRQUNsRixvQkFBb0IsQ0FBQyxnQkFBZ0IsQ0FBQyxjQUFjLENBQUMsQ0FBQztRQUN0RCxvQkFBb0IsQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUMvQixPQUFPLGNBQWMsQ0FBQztJQUN4QixDQUFDO0NBQ0YifQ==
@@ -0,0 +1,16 @@
1
+ import * as lik from '@pushrocks/lik';
2
+ import * as smartdata from '@pushrocks/smartdata';
3
+ import * as smartdelay from '@pushrocks/smartdelay';
4
+ import * as smartdns from '@pushrocks/smartdns';
5
+ import * as smartexpress from '@pushrocks/smartexpress';
6
+ import * as smartlog from '@pushrocks/smartlog';
7
+ import * as smartpromise from '@pushrocks/smartpromise';
8
+ import * as smartrequest from '@pushrocks/smartrequest';
9
+ import * as smartunique from '@pushrocks/smartunique';
10
+ import * as smartstring from '@pushrocks/smartstring';
11
+ import * as smarttime from '@pushrocks/smarttime';
12
+ export { lik, smartdata, smartdelay, smartdns, smartexpress, smartlog, smartpromise, smartrequest, smartunique, smartstring, smarttime, };
13
+ import * as tsclass from '@tsclass/tsclass';
14
+ export { tsclass };
15
+ import * as acme from 'acme-client';
16
+ export { acme };
@@ -0,0 +1,20 @@
1
+ // @pushrocks scope
2
+ import * as lik from '@pushrocks/lik';
3
+ import * as smartdata from '@pushrocks/smartdata';
4
+ import * as smartdelay from '@pushrocks/smartdelay';
5
+ import * as smartdns from '@pushrocks/smartdns';
6
+ import * as smartexpress from '@pushrocks/smartexpress';
7
+ import * as smartlog from '@pushrocks/smartlog';
8
+ import * as smartpromise from '@pushrocks/smartpromise';
9
+ import * as smartrequest from '@pushrocks/smartrequest';
10
+ import * as smartunique from '@pushrocks/smartunique';
11
+ import * as smartstring from '@pushrocks/smartstring';
12
+ import * as smarttime from '@pushrocks/smarttime';
13
+ export { lik, smartdata, smartdelay, smartdns, smartexpress, smartlog, smartpromise, smartrequest, smartunique, smartstring, smarttime, };
14
+ // @tsclass scope
15
+ import * as tsclass from '@tsclass/tsclass';
16
+ export { tsclass };
17
+ // third party scope
18
+ import * as acme from 'acme-client';
19
+ export { acme };
20
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRhY21lLnBsdWdpbnMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9zbWFydGFjbWUucGx1Z2lucy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxtQkFBbUI7QUFDbkIsT0FBTyxLQUFLLEdBQUcsTUFBTSxnQkFBZ0IsQ0FBQztBQUN0QyxPQUFPLEtBQUssU0FBUyxNQUFNLHNCQUFzQixDQUFDO0FBQ2xELE9BQU8sS0FBSyxVQUFVLE1BQU0sdUJBQXVCLENBQUM7QUFDcEQsT0FBTyxLQUFLLFFBQVEsTUFBTSxxQkFBcUIsQ0FBQztBQUNoRCxPQUFPLEtBQUssWUFBWSxNQUFNLHlCQUF5QixDQUFDO0FBQ3hELE9BQU8sS0FBSyxRQUFRLE1BQU0scUJBQXFCLENBQUM7QUFDaEQsT0FBTyxLQUFLLFlBQVksTUFBTSx5QkFBeUIsQ0FBQztBQUN4RCxPQUFPLEtBQUssWUFBWSxNQUFNLHlCQUF5QixDQUFDO0FBQ3hELE9BQU8sS0FBSyxXQUFXLE1BQU0sd0JBQXdCLENBQUM7QUFDdEQsT0FBTyxLQUFLLFdBQVcsTUFBTSx3QkFBd0IsQ0FBQztBQUN0RCxPQUFPLEtBQUssU0FBUyxNQUFNLHNCQUFzQixDQUFDO0FBRWxELE9BQU8sRUFDTCxHQUFHLEVBQ0gsU0FBUyxFQUNULFVBQVUsRUFDVixRQUFRLEVBQ1IsWUFBWSxFQUNaLFFBQVEsRUFDUixZQUFZLEVBQ1osWUFBWSxFQUNaLFdBQVcsRUFDWCxXQUFXLEVBQ1gsU0FBUyxHQUNWLENBQUM7QUFFRixpQkFBaUI7QUFDakIsT0FBTyxLQUFLLE9BQU8sTUFBTSxrQkFBa0IsQ0FBQztBQUU1QyxPQUFPLEVBQUUsT0FBTyxFQUFFLENBQUM7QUFFbkIsb0JBQW9CO0FBQ3BCLE9BQU8sS0FBSyxJQUFJLE1BQU0sYUFBYSxDQUFDO0FBRXBDLE9BQU8sRUFBRSxJQUFJLEVBQUUsQ0FBQyJ9
package/npmextra.json ADDED
@@ -0,0 +1,18 @@
1
+ {
2
+ "gitzone": {
3
+ "projectType": "npm",
4
+ "module": {
5
+ "githost": "gitlab.com",
6
+ "gitscope": "pushrocks",
7
+ "gitrepo": "smartacme",
8
+ "shortDescription": "acme with an easy yet powerful interface in TypeScript",
9
+ "npmPackagename": "@pushrocks/smartacme",
10
+ "license": "MIT",
11
+ "projectDomain": "push.rocks"
12
+ }
13
+ },
14
+ "npmci": {
15
+ "npmGlobalTools": [],
16
+ "npmAccessLevel": "public"
17
+ }
18
+ }
package/package.json ADDED
@@ -0,0 +1,67 @@
1
+ {
2
+ "name": "@push.rocks/smartacme",
3
+ "version": "4.0.3",
4
+ "private": false,
5
+ "description": "acme with an easy yet powerful interface in TypeScript",
6
+ "main": "dist_ts/index.js",
7
+ "typings": "dist_ts/index.d.ts",
8
+ "type": "module",
9
+ "scripts": {
10
+ "test": "(tstest test/)",
11
+ "build": "(tsbuild --web --allowimplicitany)"
12
+ },
13
+ "repository": {
14
+ "type": "git",
15
+ "url": "git+ssh://git@gitlab.com/umbrellazone/smartacme.git"
16
+ },
17
+ "keywords": [
18
+ "TypeScript",
19
+ "acme",
20
+ "letsencrypt"
21
+ ],
22
+ "author": "Lossless GmbH",
23
+ "license": "MIT",
24
+ "bugs": {
25
+ "url": "https://gitlab.com/umbrellazone/smartacme/issues"
26
+ },
27
+ "homepage": "https://gitlab.com/umbrellazone/smartacme#README",
28
+ "dependencies": {
29
+ "@pushrocks/lik": "^6.0.0",
30
+ "@pushrocks/smartdata": "^5.0.8",
31
+ "@pushrocks/smartdelay": "^2.0.13",
32
+ "@pushrocks/smartdns": "^5.0.2",
33
+ "@pushrocks/smartexpress": "^4.0.21",
34
+ "@pushrocks/smartlog": "^3.0.1",
35
+ "@pushrocks/smartpromise": "^3.1.7",
36
+ "@pushrocks/smartrequest": "^2.0.11",
37
+ "@pushrocks/smartstring": "^4.0.5",
38
+ "@pushrocks/smarttime": "^4.0.0",
39
+ "@pushrocks/smartunique": "^3.0.3",
40
+ "@tsclass/tsclass": "^4.0.21",
41
+ "acme-client": "^4.2.5"
42
+ },
43
+ "devDependencies": {
44
+ "@gitzone/tsbuild": "^2.1.65",
45
+ "@gitzone/tsrun": "^1.2.37",
46
+ "@gitzone/tstest": "^1.0.73",
47
+ "@mojoio/cloudflare": "^6.0.1",
48
+ "@pushrocks/qenv": "^5.0.2",
49
+ "@pushrocks/tapbundle": "^5.0.4",
50
+ "@types/node": "^18.7.23"
51
+ },
52
+ "files": [
53
+ "ts/**/*",
54
+ "ts_web/**/*",
55
+ "dist/**/*",
56
+ "dist_*/**/*",
57
+ "dist_ts/**/*",
58
+ "dist_ts_web/**/*",
59
+ "assets/**/*",
60
+ "cli.js",
61
+ "npmextra.json",
62
+ "readme.md"
63
+ ],
64
+ "browserslist": [
65
+ "last 1 chrome versions"
66
+ ]
67
+ }
package/readme.md ADDED
@@ -0,0 +1,66 @@
1
+ # @pushrocks/smartacme
2
+ acme with an easy yet powerful interface in TypeScript
3
+
4
+ ## Availabililty and Links
5
+ * [npmjs.org (npm package)](https://www.npmjs.com/package/@pushrocks/smartacme)
6
+ * [gitlab.com (source)](https://gitlab.com/pushrocks/smartacme)
7
+ * [github.com (source mirror)](https://github.com/pushrocks/smartacme)
8
+ * [docs (typedoc)](https://pushrocks.gitlab.io/smartacme/)
9
+
10
+ ## Status for master
11
+
12
+ Status Category | Status Badge
13
+ -- | --
14
+ GitLab Pipelines | [![pipeline status](https://gitlab.com/pushrocks/smartacme/badges/master/pipeline.svg)](https://lossless.cloud)
15
+ GitLab Pipline Test Coverage | [![coverage report](https://gitlab.com/pushrocks/smartacme/badges/master/coverage.svg)](https://lossless.cloud)
16
+ npm | [![npm downloads per month](https://badgen.net/npm/dy/@pushrocks/smartacme)](https://lossless.cloud)
17
+ Snyk | [![Known Vulnerabilities](https://badgen.net/snyk/pushrocks/smartacme)](https://lossless.cloud)
18
+ TypeScript Support | [![TypeScript](https://badgen.net/badge/TypeScript/>=%203.x/blue?icon=typescript)](https://lossless.cloud)
19
+ node Support | [![node](https://img.shields.io/badge/node->=%2010.x.x-blue.svg)](https://nodejs.org/dist/latest-v10.x/docs/api/)
20
+ Code Style | [![Code Style](https://badgen.net/badge/style/prettier/purple)](https://lossless.cloud)
21
+ PackagePhobia (total standalone install weight) | [![PackagePhobia](https://badgen.net/packagephobia/install/@pushrocks/smartacme)](https://lossless.cloud)
22
+ PackagePhobia (package size on registry) | [![PackagePhobia](https://badgen.net/packagephobia/publish/@pushrocks/smartacme)](https://lossless.cloud)
23
+ BundlePhobia (total size when bundled) | [![BundlePhobia](https://badgen.net/bundlephobia/minzip/@pushrocks/smartacme)](https://lossless.cloud)
24
+ Platform support | [![Supports Windows 10](https://badgen.net/badge/supports%20Windows%2010/yes/green?icon=windows)](https://lossless.cloud) [![Supports Mac OS X](https://badgen.net/badge/supports%20Mac%20OS%20X/yes/green?icon=apple)](https://lossless.cloud)
25
+
26
+ ## Usage
27
+
28
+ Use TypeScript for best in class instellisense.
29
+
30
+ ```javascript
31
+ import { SmartAcme } from 'smartacme';
32
+
33
+ const run = async () => {
34
+ smartAcmeInstance = new smartacme.SmartAcme({
35
+ accountEmail: 'domains@lossless.org',
36
+ accountPrivateKey: null,
37
+ mongoDescriptor: {
38
+ mongoDbName: testQenv.getEnvVarRequired('MONGODB_DATABASE'),
39
+ mongoDbPass: testQenv.getEnvVarRequired('MONGODB_PASSWORD'),
40
+ mongoDbUrl: testQenv.getEnvVarRequired('MONGODB_URL'),
41
+ },
42
+ removeChallenge: async (dnsChallenge) => {
43
+ // somehow provide a function that is able to remove the dns challenge
44
+ },
45
+ setChallenge: async (dnsChallenge) => {
46
+ // somehow provide a function that is able to the dns challenge
47
+ },
48
+ environment: 'integration',
49
+ });
50
+ await smartAcmeInstance.init();
51
+
52
+ // myCert has properties for public/private keys and csr ;)
53
+ const myCert = await smartAcmeInstance.getCertificateForDomain('bleu.de');
54
+ };
55
+ ```
56
+
57
+ ## Contribution
58
+
59
+ We are always happy for code contributions. If you are not the code contributing type that is ok. Still, maintaining Open Source repositories takes considerable time and thought. If you like the quality of what we do and our modules are useful to you we would appreciate a little monthly contribution: You can [contribute one time](https://lossless.link/contribute-onetime) or [contribute monthly](https://lossless.link/contribute). :)
60
+
61
+ For further information read the linked docs at the top of this readme.
62
+
63
+ > MIT licensed | **&copy;** [Lossless GmbH](https://lossless.gmbh)
64
+ | By using this npm module you agree to our [privacy policy](https://lossless.gmbH/privacy)
65
+
66
+ [![repo-footer](https://lossless.gitlab.io/publicrelations/repofooter.svg)](https://maintainedby.lossless.com)
@@ -0,0 +1,8 @@
1
+ /**
2
+ * autocreated commitinfo by @pushrocks/commitinfo
3
+ */
4
+ export const commitinfo = {
5
+ name: '@pushrocks/smartacme',
6
+ version: '4.0.3',
7
+ description: 'acme with an easy yet powerful interface in TypeScript'
8
+ }
package/ts/index.ts ADDED
@@ -0,0 +1 @@
1
+ export * from './smartacme.classes.smartacme.js';
@@ -0,0 +1,8 @@
1
+ export interface IAccountData {
2
+ id: number;
3
+ key: { kty: 'RSA'; n: string; e: string; kid: string };
4
+ contact: string[];
5
+ initialIp: string;
6
+ createdAt: string;
7
+ status: string;
8
+ }
@@ -0,0 +1 @@
1
+ export * from './accountdata.js';
@@ -0,0 +1,62 @@
1
+ import * as plugins from './smartacme.plugins.js';
2
+
3
+ import * as interfaces from './interfaces/index.js';
4
+
5
+ import { CertManager } from './smartacme.classes.certmanager.js';
6
+
7
+ import { Collection, svDb, unI } from '@pushrocks/smartdata';
8
+
9
+ @plugins.smartdata.Collection(() => {
10
+ return CertManager.activeDB;
11
+ })
12
+ export class Cert extends plugins.smartdata.SmartDataDbDoc<Cert, plugins.tsclass.network.ICert>
13
+ implements plugins.tsclass.network.ICert {
14
+ @unI()
15
+ public id: string;
16
+
17
+ @svDb()
18
+ public domainName: string;
19
+
20
+ @svDb()
21
+ public created: number;
22
+
23
+ @svDb()
24
+ public privateKey: string;
25
+
26
+ @svDb()
27
+ public publicKey: string;
28
+
29
+ @svDb()
30
+ public csr: string;
31
+
32
+ @svDb()
33
+ public validUntil: number;
34
+
35
+ public isStillValid(): boolean {
36
+ return this.validUntil >= Date.now();
37
+ }
38
+
39
+ public shouldBeRenewed(): boolean {
40
+ const shouldBeValidAtLeastUntil =
41
+ Date.now() +
42
+ plugins.smarttime.getMilliSecondsFromUnits({
43
+ days: 10,
44
+ });
45
+ return !(this.validUntil >= shouldBeValidAtLeastUntil);
46
+ }
47
+
48
+ public update(certDataArg: plugins.tsclass.network.ICert) {
49
+ Object.keys(certDataArg).forEach((key) => {
50
+ this[key] = certDataArg[key];
51
+ });
52
+ }
53
+
54
+ constructor(optionsArg: plugins.tsclass.network.ICert) {
55
+ super();
56
+ if (optionsArg) {
57
+ Object.keys(optionsArg).forEach((key) => {
58
+ this[key] = optionsArg[key];
59
+ });
60
+ }
61
+ }
62
+ }
@@ -0,0 +1,77 @@
1
+ import * as plugins from './smartacme.plugins.js';
2
+ import { Cert } from './smartacme.classes.cert.js';
3
+ import { SmartAcme } from './smartacme.classes.smartacme.js';
4
+
5
+ import * as interfaces from './interfaces/index.js';
6
+
7
+ export class CertManager {
8
+ // =========
9
+ // STATIC
10
+ // =========
11
+ public static activeDB: plugins.smartdata.SmartdataDb;
12
+
13
+ // =========
14
+ // INSTANCE
15
+ // =========
16
+ private mongoDescriptor: plugins.smartdata.IMongoDescriptor;
17
+ public smartdataDb: plugins.smartdata.SmartdataDb;
18
+
19
+ public interestMap: plugins.lik.InterestMap<string, Cert>;
20
+
21
+ constructor(
22
+ smartAcmeArg: SmartAcme,
23
+ optionsArg: {
24
+ mongoDescriptor: plugins.smartdata.IMongoDescriptor;
25
+ }
26
+ ) {
27
+ this.mongoDescriptor = optionsArg.mongoDescriptor;
28
+ }
29
+
30
+ public async init() {
31
+ // Smartdata DB
32
+ this.smartdataDb = new plugins.smartdata.SmartdataDb(this.mongoDescriptor);
33
+ await this.smartdataDb.init();
34
+ CertManager.activeDB = this.smartdataDb;
35
+
36
+ // Pending Map
37
+ this.interestMap = new plugins.lik.InterestMap((certName) => certName);
38
+ }
39
+
40
+ /**
41
+ * retrieves a certificate
42
+ * @returns the Cert class or null
43
+ * @param certDomainNameArg the domain Name to retrieve the vcertificate for
44
+ */
45
+ public async retrieveCertificate(certDomainNameArg: string): Promise<Cert> {
46
+ const existingCertificate: Cert = await Cert.getInstance<Cert>({
47
+ domainName: certDomainNameArg,
48
+ });
49
+
50
+ if (existingCertificate) {
51
+ return existingCertificate;
52
+ } else {
53
+ return null;
54
+ }
55
+ }
56
+
57
+ /**
58
+ * stores the certificate
59
+ * @param optionsArg
60
+ */
61
+ public async storeCertificate(optionsArg: plugins.tsclass.network.ICert) {
62
+ const cert = new Cert(optionsArg);
63
+ await cert.save();
64
+ const interest = this.interestMap.findInterest(cert.domainName);
65
+ if (interest) {
66
+ interest.fullfillInterest(cert);
67
+ interest.markLost();
68
+ }
69
+ }
70
+
71
+ public async deleteCertificate(certDomainNameArg: string) {
72
+ const cert: Cert = await Cert.getInstance<Cert>({
73
+ domainName: certDomainNameArg,
74
+ });
75
+ await cert.delete();
76
+ }
77
+ }
@@ -0,0 +1,19 @@
1
+ import * as plugins from './smartacme.plugins.js';
2
+ import * as interfaces from './interfaces/index.js';
3
+
4
+ /**
5
+ * certmatcher is responsible for matching certificates
6
+ */
7
+ export class CertMatcher {
8
+ /**
9
+ * creates a domainName for the certificate that will include the broadest scope
10
+ * for wild card certificates
11
+ * @param domainNameArg the domainNameArg to create the scope from
12
+ */
13
+ public getCertificateDomainNameByDomainName(domainNameArg: string): string {
14
+ const originalDomain = new plugins.smartstring.Domain(domainNameArg);
15
+ if (!originalDomain.level4) {
16
+ return `${originalDomain.level2}.${originalDomain.level1}`;
17
+ }
18
+ }
19
+ }
@@ -0,0 +1,212 @@
1
+ import * as plugins from './smartacme.plugins.js';
2
+ import { Cert } from './smartacme.classes.cert.js';
3
+ import { CertManager } from './smartacme.classes.certmanager.js';
4
+ import { CertMatcher } from './smartacme.classes.certmatcher.js';
5
+
6
+ /**
7
+ * the options for the class @see SmartAcme
8
+ */
9
+ export interface ISmartAcmeOptions {
10
+ accountPrivateKey?: string;
11
+ accountEmail: string;
12
+ mongoDescriptor: plugins.smartdata.IMongoDescriptor;
13
+ setChallenge: (dnsChallengeArg: plugins.tsclass.network.IDnsChallenge) => Promise<any>;
14
+ removeChallenge: (dnsChallengeArg: plugins.tsclass.network.IDnsChallenge) => Promise<any>;
15
+ environment: 'production' | 'integration';
16
+ }
17
+
18
+ /**
19
+ * class SmartAcme
20
+ * can be used for setting up communication with an ACME authority
21
+ *
22
+ * ```ts
23
+ * const mySmartAcmeInstance = new SmartAcme({
24
+ * // see ISmartAcmeOptions for options
25
+ * })
26
+ * ```
27
+ */
28
+ export class SmartAcme {
29
+ private options: ISmartAcmeOptions;
30
+
31
+ // the acme client
32
+ private client: any;
33
+ private smartdns = new plugins.smartdns.Smartdns({});
34
+ public logger: plugins.smartlog.ConsoleLog;
35
+
36
+ // the account private key
37
+ private privateKey: string;
38
+
39
+ // challenge fullfillment
40
+ private setChallenge: (dnsChallengeArg: plugins.tsclass.network.IDnsChallenge) => Promise<any>;
41
+ private removeChallenge: (dnsChallengeArg: plugins.tsclass.network.IDnsChallenge) => Promise<any>;
42
+
43
+ // certmanager
44
+ private certmanager: CertManager;
45
+ private certmatcher: CertMatcher;
46
+
47
+ constructor(optionsArg: ISmartAcmeOptions) {
48
+ this.options = optionsArg;
49
+ this.logger = new plugins.smartlog.ConsoleLog();
50
+ }
51
+
52
+ /**
53
+ * inits the instance
54
+ * ```ts
55
+ * await myCloudlyInstance.init() // does not support options
56
+ * ```
57
+ */
58
+ public async init() {
59
+ this.privateKey =
60
+ this.options.accountPrivateKey || (await plugins.acme.forge.createPrivateKey()).toString();
61
+ this.setChallenge = this.options.setChallenge;
62
+ this.removeChallenge = this.options.removeChallenge;
63
+
64
+ // CertMangaer
65
+ this.certmanager = new CertManager(this, {
66
+ mongoDescriptor: this.options.mongoDescriptor,
67
+ });
68
+ await this.certmanager.init();
69
+
70
+ // CertMatcher
71
+ this.certmatcher = new CertMatcher();
72
+
73
+ // ACME Client
74
+ this.client = new plugins.acme.Client({
75
+ directoryUrl: (() => {
76
+ if (this.options.environment === 'production') {
77
+ return plugins.acme.directory.letsencrypt.production;
78
+ } else {
79
+ return plugins.acme.directory.letsencrypt.staging;
80
+ }
81
+ })(),
82
+ accountKey: this.privateKey,
83
+ });
84
+
85
+ /* Register account */
86
+ await this.client.createAccount({
87
+ termsOfServiceAgreed: true,
88
+ contact: [`mailto:${this.options.accountEmail}`],
89
+ });
90
+ }
91
+
92
+ public async stop() {
93
+ await this.certmanager.smartdataDb.close();
94
+ }
95
+
96
+ /**
97
+ * gets a certificate
98
+ * it runs through the following steps
99
+ *
100
+ * * look in the database
101
+ * * if in the database and still valid return it
102
+ * * if not in the database announce it
103
+ * * then get it from letsencrypt
104
+ * * store it
105
+ * * remove it from the pending map (which it go onto by announcing it)
106
+ * * retrieve it from the databse and return it
107
+ *
108
+ * @param domainArg
109
+ */
110
+ public async getCertificateForDomain(domainArg: string): Promise<Cert> {
111
+ const certDomainName = this.certmatcher.getCertificateDomainNameByDomainName(domainArg);
112
+ const retrievedCertificate = await this.certmanager.retrieveCertificate(certDomainName);
113
+
114
+ if (
115
+ !retrievedCertificate &&
116
+ (await this.certmanager.interestMap.checkInterest(certDomainName))
117
+ ) {
118
+ const existingCertificateInterest = this.certmanager.interestMap.findInterest(certDomainName);
119
+ const certificate = existingCertificateInterest.interestFullfilled;
120
+ return certificate;
121
+ } else if (retrievedCertificate && !retrievedCertificate.shouldBeRenewed()) {
122
+ return retrievedCertificate;
123
+ } else if (retrievedCertificate && retrievedCertificate.shouldBeRenewed()) {
124
+ await retrievedCertificate.delete();
125
+ }
126
+
127
+ // lets make sure others get the same interest
128
+ const currentDomainInterst = await this.certmanager.interestMap.addInterest(certDomainName);
129
+
130
+ /* Place new order */
131
+ const order = await this.client.createOrder({
132
+ identifiers: [
133
+ { type: 'dns', value: certDomainName },
134
+ { type: 'dns', value: `*.${certDomainName}` },
135
+ ],
136
+ });
137
+
138
+ /* Get authorizations and select challenges */
139
+ const authorizations = await this.client.getAuthorizations(order);
140
+
141
+ for (const authz of authorizations) {
142
+ console.log(authz);
143
+ const fullHostName: string = `_acme-challenge.${authz.identifier.value}`;
144
+ const dnsChallenge: string = authz.challenges.find((challengeArg) => {
145
+ return challengeArg.type === 'dns-01';
146
+ });
147
+ // process.exit(1);
148
+ const keyAuthorization: string = await this.client.getChallengeKeyAuthorization(dnsChallenge);
149
+
150
+ try {
151
+ /* Satisfy challenge */
152
+ await this.setChallenge({
153
+ hostName: fullHostName,
154
+ challenge: keyAuthorization,
155
+ });
156
+ await plugins.smartdelay.delayFor(30000);
157
+ await this.smartdns.checkUntilAvailable(fullHostName, 'TXT', keyAuthorization, 100, 5000);
158
+ console.log('Cool down an extra 60 second for region availability');
159
+ await plugins.smartdelay.delayFor(60000);
160
+
161
+ /* Verify that challenge is satisfied */
162
+ await this.client.verifyChallenge(authz, dnsChallenge);
163
+
164
+ /* Notify ACME provider that challenge is satisfied */
165
+ await this.client.completeChallenge(dnsChallenge);
166
+
167
+ /* Wait for ACME provider to respond with valid status */
168
+ await this.client.waitForValidStatus(dnsChallenge);
169
+ } finally {
170
+ /* Clean up challenge response */
171
+ try {
172
+ await this.removeChallenge({
173
+ hostName: fullHostName,
174
+ challenge: keyAuthorization,
175
+ });
176
+ } catch (e) {
177
+ console.log(e);
178
+ }
179
+ }
180
+ }
181
+
182
+ /* Finalize order */
183
+ const [key, csr] = await plugins.acme.forge.createCsr({
184
+ commonName: `*.${certDomainName}`,
185
+ altNames: [certDomainName],
186
+ });
187
+
188
+ await this.client.finalizeOrder(order, csr);
189
+ const cert = await this.client.getCertificate(order);
190
+
191
+ /* Done */
192
+
193
+ await this.certmanager.storeCertificate({
194
+ id: plugins.smartunique.shortId(),
195
+ domainName: certDomainName,
196
+ privateKey: key.toString(),
197
+ publicKey: cert.toString(),
198
+ csr: csr.toString(),
199
+ created: Date.now(),
200
+ validUntil:
201
+ Date.now() +
202
+ plugins.smarttime.getMilliSecondsFromUnits({
203
+ days: 90,
204
+ }),
205
+ });
206
+
207
+ const newCertificate = await this.certmanager.retrieveCertificate(certDomainName);
208
+ currentDomainInterst.fullfillInterest(newCertificate);
209
+ currentDomainInterst.destroy();
210
+ return newCertificate;
211
+ }
212
+ }
@@ -0,0 +1,36 @@
1
+ // @pushrocks scope
2
+ import * as lik from '@pushrocks/lik';
3
+ import * as smartdata from '@pushrocks/smartdata';
4
+ import * as smartdelay from '@pushrocks/smartdelay';
5
+ import * as smartdns from '@pushrocks/smartdns';
6
+ import * as smartexpress from '@pushrocks/smartexpress';
7
+ import * as smartlog from '@pushrocks/smartlog';
8
+ import * as smartpromise from '@pushrocks/smartpromise';
9
+ import * as smartrequest from '@pushrocks/smartrequest';
10
+ import * as smartunique from '@pushrocks/smartunique';
11
+ import * as smartstring from '@pushrocks/smartstring';
12
+ import * as smarttime from '@pushrocks/smarttime';
13
+
14
+ export {
15
+ lik,
16
+ smartdata,
17
+ smartdelay,
18
+ smartdns,
19
+ smartexpress,
20
+ smartlog,
21
+ smartpromise,
22
+ smartrequest,
23
+ smartunique,
24
+ smartstring,
25
+ smarttime,
26
+ };
27
+
28
+ // @tsclass scope
29
+ import * as tsclass from '@tsclass/tsclass';
30
+
31
+ export { tsclass };
32
+
33
+ // third party scope
34
+ import * as acme from 'acme-client';
35
+
36
+ export { acme };