diff --git a/dist/smartacme.classes.acmeaccount.d.ts b/dist/smartacme.classes.acmeaccount.d.ts index 709829e..a93d7d9 100644 --- a/dist/smartacme.classes.acmeaccount.d.ts +++ b/dist/smartacme.classes.acmeaccount.d.ts @@ -1,3 +1,22 @@ -import 'typings-global'; +/// +import * as q from 'q'; +import { SmartAcme } from './smartacme.classes.smartacme'; +/** + * class AcmeAccount represents an AcmeAccount + */ export declare class AcmeAccount { + parentSmartAcme: SmartAcme; + location: string; + link: string; + JWK: any; + constructor(smartAcmeParentArg: SmartAcme); + /** + * register the account with letsencrypt + */ + register(): q.Promise<{}>; + /** + * agree to letsencrypr terms of service + */ + agreeTos(): q.Promise<{}>; + createAcmeCert(domainNameArg: string): void; } diff --git a/dist/smartacme.classes.acmeaccount.js b/dist/smartacme.classes.acmeaccount.js index 9ad1454..fd073dc 100644 --- a/dist/smartacme.classes.acmeaccount.js +++ b/dist/smartacme.classes.acmeaccount.js @@ -1,6 +1,54 @@ "use strict"; -require("typings-global"); +const q = require("q"); +/** + * class AcmeAccount represents an AcmeAccount + */ class AcmeAccount { + constructor(smartAcmeParentArg) { + this.parentSmartAcme = smartAcmeParentArg; + } + /** + * register the account with letsencrypt + */ + register() { + let done = q.defer(); + this.parentSmartAcme.rawacmeClient.newReg({ + contact: ['mailto:domains@lossless.org'] + }, (err, res) => { + if (err) { + console.error('smartacme: something went wrong:'); + console.log(err); + done.reject(err); + return; + } + this.JWK = res.body.key; + this.link = res.headers.link; + console.log(this.link); + this.location = res.headers.location; + done.resolve(); + }); + return done.promise; + } + /** + * agree to letsencrypr terms of service + */ + agreeTos() { + let done = q.defer(); + let tosPart = this.link.split(',')[1]; + let tosLinkPortion = tosPart.split(';')[0]; + let url = tosLinkPortion.split(';')[0].trim().replace(/[<>]/g, ''); + this.parentSmartAcme.rawacmeClient.post(this.location, { Agreement: url, resource: 'reg' }, (err, res) => { + if (err) { + console.log(err); + done.reject(err); + return; + } + done.resolve(); + }); + return done.promise; + } + createAcmeCert(domainNameArg) { + } } exports.AcmeAccount = AcmeAccount; -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRhY21lLmNsYXNzZXMuYWNtZWFjY291bnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9zbWFydGFjbWUuY2xhc3Nlcy5hY21lYWNjb3VudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsMEJBQXVCO0FBRXZCO0NBRUM7QUFGRCxrQ0FFQyJ9 \ No newline at end of file +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRhY21lLmNsYXNzZXMuYWNtZWFjY291bnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9zbWFydGFjbWUuY2xhc3Nlcy5hY21lYWNjb3VudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsdUJBQXNCO0FBUXRCOztHQUVHO0FBQ0g7SUFLSSxZQUFZLGtCQUE2QjtRQUNyQyxJQUFJLENBQUMsZUFBZSxHQUFHLGtCQUFrQixDQUFBO0lBQzdDLENBQUM7SUFFRDs7T0FFRztJQUNILFFBQVE7UUFDSixJQUFJLElBQUksR0FBRyxDQUFDLENBQUMsS0FBSyxFQUFFLENBQUE7UUFDcEIsSUFBSSxDQUFDLGVBQWUsQ0FBQyxhQUFhLENBQUMsTUFBTSxDQUNyQztZQUNJLE9BQU8sRUFBRSxDQUFDLDZCQUE2QixDQUFDO1NBQzNDLEVBQ0QsQ0FBQyxHQUFHLEVBQUUsR0FBRztZQUNMLEVBQUUsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7Z0JBQ04sT0FBTyxDQUFDLEtBQUssQ0FBQyxrQ0FBa0MsQ0FBQyxDQUFBO2dCQUNqRCxPQUFPLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFBO2dCQUNoQixJQUFJLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFBO2dCQUNoQixNQUFNLENBQUE7WUFDVixDQUFDO1lBQ0QsSUFBSSxDQUFDLEdBQUcsR0FBRyxHQUFHLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQTtZQUN2QixJQUFJLENBQUMsSUFBSSxHQUFHLEdBQUcsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFBO1lBQzVCLE9BQU8sQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFBO1lBQ3RCLElBQUksQ0FBQyxRQUFRLEdBQUcsR0FBRyxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUE7WUFDcEMsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFBO1FBQ2xCLENBQUMsQ0FBQyxDQUFBO1FBQ04sTUFBTSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUE7SUFDdkIsQ0FBQztJQUVEOztPQUVHO0lBQ0gsUUFBUTtRQUNKLElBQUksSUFBSSxHQUFHLENBQUMsQ0FBQyxLQUFLLEVBQUUsQ0FBQTtRQUNwQixJQUFJLE9BQU8sR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQTtRQUNyQyxJQUFJLGNBQWMsR0FBRyxPQUFPLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFBO1FBQzFDLElBQUksR0FBRyxHQUFHLGNBQWMsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUMsT0FBTyxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUMsQ0FBQTtRQUNsRSxJQUFJLENBQUMsZUFBZSxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsRUFBRSxFQUFFLFNBQVMsRUFBRSxHQUFHLEVBQUUsUUFBUSxFQUFFLEtBQUssRUFBRSxFQUFFLENBQUMsR0FBRyxFQUFFLEdBQUc7WUFDakcsRUFBRSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztnQkFDTixPQUFPLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFBO2dCQUNoQixJQUFJLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFBO2dCQUNoQixNQUFNLENBQUE7WUFDVixDQUFDO1lBQ0QsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFBO1FBQ2xCLENBQUMsQ0FBQyxDQUFBO1FBQ0YsTUFBTSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUE7SUFDdkIsQ0FBQztJQUVELGNBQWMsQ0FBQyxhQUFxQjtJQUVwQyxDQUFDO0NBQ0o7QUF4REQsa0NBd0RDIn0= \ No newline at end of file diff --git a/dist/smartacme.classes.acmecert.d.ts b/dist/smartacme.classes.acmecert.d.ts index d66570b..3766f48 100644 --- a/dist/smartacme.classes.acmecert.d.ts +++ b/dist/smartacme.classes.acmecert.d.ts @@ -1,3 +1,71 @@ -import 'typings-global'; -export declare class AcmeCert { +/// +import * as q from 'q'; +import { IRsaKeypair } from './smartacme.classes.smartacme'; +import { AcmeAccount } from './smartacme.classes.acmeaccount'; +/** + * types of challenges supported by letsencrypt and this module + */ +export declare type TChallengeType = 'dns-01' | 'http-01'; +/** + * values that a challenge's status can have + */ +export declare type TChallengeStatus = 'pending'; +export interface ISmartAcmeChallenge { + uri: string; + status: TChallengeStatus; + type: TChallengeType; + token: string; + keyAuthorization: string; +} +export interface ISmartAcmeChallengeAccepted extends ISmartAcmeChallenge { + keyHash: string; +} +export interface IAcmeCsrConstructorOptions { + bit: number; + key: string; + domain: string; + country: string; + country_short: string; + locality: string; + organization: string; + organization_short: string; + password: string; + unstructured: string; + subject_alt_names: string[]; +} +/** + * class AcmeCert represents a cert for domain + */ +export declare class AcmeCert { + attributes: any; + fullchain: string; + parentAcmeAccount: AcmeAccount; + csr: any; + validFrom: Date; + validTo: Date; + keypair: IRsaKeypair; + keyPairFinal: IRsaKeypair; + constructor(optionsArg: IAcmeCsrConstructorOptions, parentSmartAcmeArg: any); + /** + * requests a challenge for a domain + * @param domainNameArg - the domain name to request a challenge for + * @param challengeType - the challenge type to request + */ + requestChallenge(domainNameArg: string, challengeTypeArg?: TChallengeType): q.Promise; + /** + * validates a challenge, only call after you have set the challenge at the expected location + */ + validate(challenge: ISmartAcmeChallengeAccepted): q.Promise<{}>; + /** + * requests a certificate + */ + requestCert(): q.Promise<{}>; + /** + * getCertificate - takes care of cooldown, validation polling and certificate retrieval + */ + getCertificate(): void; + /** + * accept a challenge - for private use only + */ + private acceptChallenge(challenge); } diff --git a/dist/smartacme.classes.acmecert.js b/dist/smartacme.classes.acmecert.js index 967677a..c13a1dc 100644 --- a/dist/smartacme.classes.acmecert.js +++ b/dist/smartacme.classes.acmecert.js @@ -1,6 +1,144 @@ "use strict"; -require("typings-global"); +const q = require("q"); +const plugins = require("./smartacme.plugins"); +const helpers = require("./smartacme.helpers"); +/** + * class AcmeCert represents a cert for domain + */ class AcmeCert { + constructor(optionsArg, parentSmartAcmeArg) { + this.parentAcmeAccount = parentSmartAcmeArg; + this.keypair = helpers.createKeypair(optionsArg.bit); + let privateKeyForged = plugins.nodeForge.pki.privateKeyFromPem(this.keypair.privateKey); + let publicKeyForged = plugins.nodeForge.pki.publicKeyToPem(plugins.nodeForge.pki.setRsaPublicKey(privateKeyForged.n, privateKeyForged.e)); + this.keyPairFinal = { + privateKey: privateKeyForged, + publicKey: publicKeyForged + }; + // set dates + this.validFrom = new Date(); + this.validTo = new Date(); + this.validTo.setDate(this.validFrom.getDate() + 90); + // set attributes + this.attributes = [ + { name: 'commonName', value: optionsArg.domain }, + { name: 'countryName', value: optionsArg.country }, + { shortName: 'ST', value: optionsArg.country_short }, + { name: 'localityName', value: optionsArg.locality }, + { name: 'organizationName', value: optionsArg.organization }, + { shortName: 'OU', value: optionsArg.organization_short }, + { name: 'challengePassword', value: optionsArg.password }, + { name: 'unstructuredName', value: optionsArg.unstructured } + ]; + // set up csr + this.csr = plugins.nodeForge.pki.createCertificationRequest(); + this.csr.setSubject(this.attributes); + this.csr.setAttributes(this.attributes); + } + /** + * requests a challenge for a domain + * @param domainNameArg - the domain name to request a challenge for + * @param challengeType - the challenge type to request + */ + requestChallenge(domainNameArg, challengeTypeArg = 'dns-01') { + let done = q.defer(); + this.parentAcmeAccount.parentSmartAcme.rawacmeClient.newAuthz({ + identifier: { + type: 'dns', + value: domainNameArg + } + }, this.parentAcmeAccount.parentSmartAcme.keyPair, (err, res) => { + if (err) { + console.error('smartacme: something went wrong:'); + console.log(err); + done.reject(err); + } + console.log(JSON.stringify(res.body)); + let dnsChallenge = res.body.challenges.filter(x => { + return x.type === challengeTypeArg; + })[0]; + this.acceptChallenge(dnsChallenge) + .then((x) => { + done.resolve(x); + }); + }); + return done.promise; + } + /** + * validates a challenge, only call after you have set the challenge at the expected location + */ + validate(challenge) { + let done = q.defer(); + this.parentAcmeAccount.parentSmartAcme.rawacmeClient.poll(challenge.uri, function (err, res) { + if (err) { + console.log(err); + done.reject(err); + } + console.log(res.status); + console.log(JSON.stringify(res.body)); + done.resolve(); + }); + return done.promise; + } + /** + * requests a certificate + */ + requestCert() { + let done = q.defer(); + let payload = { + csr: plugins.rawacme.base64.encode(plugins.rawacme.toDer(plugins.nodeForge.pki.certificationRequestToPem(this.csr))), + notBefore: this.validFrom.toISOString(), + notAfter: this.validTo.toISOString() + }; + this.parentAcmeAccount.parentSmartAcme.rawacmeClient.newCert(payload, helpers.createKeypair(), (err, res) => { + if (err) { + console.log(err); + done.reject(err); + } + }); + return done.promise; + } + /** + * getCertificate - takes care of cooldown, validation polling and certificate retrieval + */ + getCertificate() { + } + /** + * accept a challenge - for private use only + */ + acceptChallenge(challenge) { + let done = q.defer(); + /** + * the key is needed to accept the challenge + */ + let authKey = plugins.rawacme.keyAuthz(challenge.token, this.parentAcmeAccount.parentSmartAcme.keyPair.publicKey); + /** + * needed in case selected challenge is of type dns-01 + */ + let keyHash = plugins.rawacme.dnsKeyAuthzHash(authKey); // needed if dns challenge is chosen + /** + * the return challenge + */ + let returnDNSChallenge = { + uri: challenge.uri, + type: challenge.type, + token: challenge.token, + keyAuthorization: challenge.keyAuthorization, + keyHash: keyHash, + status: challenge.status + }; + this.parentAcmeAccount.parentSmartAcme.rawacmeClient.post(challenge.uri, { + resource: 'challenge', + keyAuthorization: authKey + }, this.parentAcmeAccount.parentSmartAcme.keyPair, (err, res) => { + if (err) { + console.log(err); + done.reject(err); + } + done.resolve(returnDNSChallenge); + }); + return done.promise; + } } exports.AcmeCert = AcmeCert; -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRhY21lLmNsYXNzZXMuYWNtZWNlcnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9zbWFydGFjbWUuY2xhc3Nlcy5hY21lY2VydC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsMEJBQXVCO0FBRXZCO0NBRUM7QUFGRCw0QkFFQyJ9 \ No newline at end of file +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRhY21lLmNsYXNzZXMuYWNtZWNlcnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9zbWFydGFjbWUuY2xhc3Nlcy5hY21lY2VydC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsdUJBQXNCO0FBRXRCLCtDQUE4QztBQUM5QywrQ0FBOEM7QUF5QzlDOztHQUVHO0FBQ0g7SUFTSSxZQUFZLFVBQXNDLEVBQUUsa0JBQWtCO1FBQ2xFLElBQUksQ0FBQyxpQkFBaUIsR0FBRyxrQkFBa0IsQ0FBQTtRQUMzQyxJQUFJLENBQUMsT0FBTyxHQUFHLE9BQU8sQ0FBQyxhQUFhLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQyxDQUFBO1FBQ3BELElBQUksZ0JBQWdCLEdBQUcsT0FBTyxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsaUJBQWlCLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUMsQ0FBQTtRQUN2RixJQUFJLGVBQWUsR0FBRyxPQUFPLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxjQUFjLENBQ3RELE9BQU8sQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLGVBQWUsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLEVBQUUsZ0JBQWdCLENBQUMsQ0FBQyxDQUFDLENBQ2hGLENBQUE7UUFDRCxJQUFJLENBQUMsWUFBWSxHQUFHO1lBQ2hCLFVBQVUsRUFBRSxnQkFBZ0I7WUFDNUIsU0FBUyxFQUFFLGVBQWU7U0FDN0IsQ0FBQTtRQUVELFlBQVk7UUFDWixJQUFJLENBQUMsU0FBUyxHQUFHLElBQUksSUFBSSxFQUFFLENBQUE7UUFDM0IsSUFBSSxDQUFDLE9BQU8sR0FBRyxJQUFJLElBQUksRUFBRSxDQUFBO1FBQ3pCLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsT0FBTyxFQUFFLEdBQUcsRUFBRSxDQUFDLENBQUE7UUFFbkQsaUJBQWlCO1FBQ2pCLElBQUksQ0FBQyxVQUFVLEdBQUc7WUFDZCxFQUFFLElBQUksRUFBRSxZQUFZLEVBQUUsS0FBSyxFQUFFLFVBQVUsQ0FBQyxNQUFNLEVBQUU7WUFDaEQsRUFBRSxJQUFJLEVBQUUsYUFBYSxFQUFFLEtBQUssRUFBRSxVQUFVLENBQUMsT0FBTyxFQUFFO1lBQ2xELEVBQUUsU0FBUyxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsVUFBVSxDQUFDLGFBQWEsRUFBRTtZQUNwRCxFQUFFLElBQUksRUFBRSxjQUFjLEVBQUUsS0FBSyxFQUFFLFVBQVUsQ0FBQyxRQUFRLEVBQUU7WUFDcEQsRUFBRSxJQUFJLEVBQUUsa0JBQWtCLEVBQUUsS0FBSyxFQUFFLFVBQVUsQ0FBQyxZQUFZLEVBQUU7WUFDNUQsRUFBRSxTQUFTLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxVQUFVLENBQUMsa0JBQWtCLEVBQUU7WUFDekQsRUFBRSxJQUFJLEVBQUUsbUJBQW1CLEVBQUUsS0FBSyxFQUFFLFVBQVUsQ0FBQyxRQUFRLEVBQUU7WUFDekQsRUFBRSxJQUFJLEVBQUUsa0JBQWtCLEVBQUUsS0FBSyxFQUFFLFVBQVUsQ0FBQyxZQUFZLEVBQUU7U0FDL0QsQ0FBQTtRQUVELGFBQWE7UUFDYixJQUFJLENBQUMsR0FBRyxHQUFHLE9BQU8sQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLDBCQUEwQixFQUFFLENBQUE7UUFDN0QsSUFBSSxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFBO1FBQ3BDLElBQUksQ0FBQyxHQUFHLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQTtJQUMzQyxDQUFDO0lBRUQ7Ozs7T0FJRztJQUNILGdCQUFnQixDQUFDLGFBQXFCLEVBQUUsbUJBQW1DLFFBQVE7UUFDL0UsSUFBSSxJQUFJLEdBQUcsQ0FBQyxDQUFDLEtBQUssRUFBK0IsQ0FBQTtRQUNqRCxJQUFJLENBQUMsaUJBQWlCLENBQUMsZUFBZSxDQUFDLGFBQWEsQ0FBQyxRQUFRLENBQ3pEO1lBQ0ksVUFBVSxFQUFFO2dCQUNSLElBQUksRUFBRSxLQUFLO2dCQUNYLEtBQUssRUFBRSxhQUFhO2FBQ3ZCO1NBQ0osRUFDRCxJQUFJLENBQUMsaUJBQWlCLENBQUMsZUFBZSxDQUFDLE9BQU8sRUFDOUMsQ0FBQyxHQUFHLEVBQUUsR0FBRztZQUNMLEVBQUUsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7Z0JBQ04sT0FBTyxDQUFDLEtBQUssQ0FBQyxrQ0FBa0MsQ0FBQyxDQUFBO2dCQUNqRCxPQUFPLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFBO2dCQUNoQixJQUFJLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFBO1lBQ3BCLENBQUM7WUFDRCxPQUFPLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUE7WUFDckMsSUFBSSxZQUFZLEdBQUcsR0FBRyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsTUFBTSxDQUFDLENBQUM7Z0JBQzNDLE1BQU0sQ0FBQyxDQUFDLENBQUMsSUFBSSxLQUFLLGdCQUFnQixDQUFBO1lBQ3RDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFBO1lBQ0wsSUFBSSxDQUFDLGVBQWUsQ0FBQyxZQUFZLENBQUM7aUJBQzdCLElBQUksQ0FBQyxDQUFDLENBQThCO2dCQUNqQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFBO1lBQ25CLENBQUMsQ0FBQyxDQUFBO1FBQ1YsQ0FBQyxDQUNKLENBQUE7UUFDRCxNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQTtJQUN2QixDQUFDO0lBRUQ7O09BRUc7SUFDSCxRQUFRLENBQUMsU0FBc0M7UUFDM0MsSUFBSSxJQUFJLEdBQUcsQ0FBQyxDQUFDLEtBQUssRUFBRSxDQUFBO1FBQ3BCLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxlQUFlLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsR0FBRyxFQUFFLFVBQVUsR0FBRyxFQUFFLEdBQUc7WUFDdkYsRUFBRSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztnQkFDTixPQUFPLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFBO2dCQUNoQixJQUFJLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFBO1lBQ3BCLENBQUM7WUFDRCxPQUFPLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQTtZQUN2QixPQUFPLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUE7WUFDckMsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFBO1FBQ2xCLENBQUMsQ0FBQyxDQUFBO1FBQ0YsTUFBTSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUE7SUFDdkIsQ0FBQztJQUVEOztPQUVHO0lBQ0gsV0FBVztRQUNQLElBQUksSUFBSSxHQUFHLENBQUMsQ0FBQyxLQUFLLEVBQUUsQ0FBQTtRQUNwQixJQUFJLE9BQU8sR0FBRztZQUNWLEdBQUcsRUFBRSxPQUFPLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQzlCLE9BQU8sQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUNqQixPQUFPLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyx5QkFBeUIsQ0FDM0MsSUFBSSxDQUFDLEdBQUcsQ0FDWCxDQUNKLENBQ0o7WUFDRCxTQUFTLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxXQUFXLEVBQUU7WUFDdkMsUUFBUSxFQUFFLElBQUksQ0FBQyxPQUFPLENBQUMsV0FBVyxFQUFFO1NBQ3ZDLENBQUE7UUFDRCxJQUFJLENBQUMsaUJBQWlCLENBQUMsZUFBZSxDQUFDLGFBQWEsQ0FBQyxPQUFPLENBQ3hELE9BQU8sRUFDUCxPQUFPLENBQUMsYUFBYSxFQUFFLEVBQ3ZCLENBQUMsR0FBRyxFQUFFLEdBQUc7WUFDTCxFQUFFLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO2dCQUNOLE9BQU8sQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUE7Z0JBQ2hCLElBQUksQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUE7WUFDcEIsQ0FBQztRQUNMLENBQUMsQ0FBQyxDQUFBO1FBQ04sTUFBTSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUE7SUFDdkIsQ0FBQztJQUVEOztPQUVHO0lBQ0gsY0FBYztJQUVkLENBQUM7SUFFRDs7T0FFRztJQUNLLGVBQWUsQ0FBQyxTQUE4QjtRQUNsRCxJQUFJLElBQUksR0FBRyxDQUFDLENBQUMsS0FBSyxFQUFFLENBQUE7UUFFcEI7O1dBRUc7UUFDSCxJQUFJLE9BQU8sR0FBVyxPQUFPLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FDMUMsU0FBUyxDQUFDLEtBQUssRUFDZixJQUFJLENBQUMsaUJBQWlCLENBQUMsZUFBZSxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQzNELENBQUE7UUFFRDs7V0FFRztRQUNILElBQUksT0FBTyxHQUFXLE9BQU8sQ0FBQyxPQUFPLENBQUMsZUFBZSxDQUFDLE9BQU8sQ0FBQyxDQUFBLENBQUMsb0NBQW9DO1FBRW5HOztXQUVHO1FBQ0gsSUFBSSxrQkFBa0IsR0FBZ0M7WUFDbEQsR0FBRyxFQUFFLFNBQVMsQ0FBQyxHQUFHO1lBQ2xCLElBQUksRUFBRSxTQUFTLENBQUMsSUFBSTtZQUNwQixLQUFLLEVBQUUsU0FBUyxDQUFDLEtBQUs7WUFDdEIsZ0JBQWdCLEVBQUUsU0FBUyxDQUFDLGdCQUFnQjtZQUM1QyxPQUFPLEVBQUUsT0FBTztZQUNoQixNQUFNLEVBQUUsU0FBUyxDQUFDLE1BQU07U0FDM0IsQ0FBQTtRQUVELElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxlQUFlLENBQUMsYUFBYSxDQUFDLElBQUksQ0FDckQsU0FBUyxDQUFDLEdBQUcsRUFDYjtZQUNJLFFBQVEsRUFBRSxXQUFXO1lBQ3JCLGdCQUFnQixFQUFFLE9BQU87U0FDNUIsRUFDRCxJQUFJLENBQUMsaUJBQWlCLENBQUMsZUFBZSxDQUFDLE9BQU8sRUFDOUMsQ0FBQyxHQUFHLEVBQUUsR0FBRztZQUNMLEVBQUUsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7Z0JBQ04sT0FBTyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQTtnQkFDaEIsSUFBSSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQTtZQUNwQixDQUFDO1lBQ0QsSUFBSSxDQUFDLE9BQU8sQ0FBQyxrQkFBa0IsQ0FBQyxDQUFBO1FBQ3BDLENBQUMsQ0FDSixDQUFBO1FBQ0QsTUFBTSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUE7SUFDdkIsQ0FBQztDQUNKO0FBbExELDRCQWtMQyJ9 \ No newline at end of file diff --git a/dist/smartacme.classes.helper.d.ts b/dist/smartacme.classes.helper.d.ts deleted file mode 100644 index e20c4eb..0000000 --- a/dist/smartacme.classes.helper.d.ts +++ /dev/null @@ -1,21 +0,0 @@ -/// -import 'typings-global'; -import * as q from 'q'; -import { SmartAcme } from './smartacme.classes.smartacme'; -export interface IRsaKeypair { - publicKey: string; - privateKey: string; -} -export declare class SmartacmeHelper { - parentSmartAcme: SmartAcme; - constructor(smartAcmeArg: SmartAcme); - /** - * creates a keypair to use with requests and to generate JWK from - */ - createKeypair(bit?: number): IRsaKeypair; - /** - * gets an existing registration - * @executes ASYNC - */ - getReg(): q.Promise<{}>; -} diff --git a/dist/smartacme.classes.helper.js b/dist/smartacme.classes.helper.js deleted file mode 100644 index a04892c..0000000 --- a/dist/smartacme.classes.helper.js +++ /dev/null @@ -1,40 +0,0 @@ -"use strict"; -require("typings-global"); -const q = require("q"); -let rsaKeygen = require('rsa-keygen'); -class SmartacmeHelper { - constructor(smartAcmeArg) { - this.parentSmartAcme = smartAcmeArg; - } - /** - * creates a keypair to use with requests and to generate JWK from - */ - createKeypair(bit = 2048) { - let result = rsaKeygen.generate(bit); - return { - publicKey: result.public_key, - privateKey: result.private_key - }; - } - /** - * gets an existing registration - * @executes ASYNC - */ - getReg() { - let done = q.defer(); - let body = { resource: 'reg' }; - this.parentSmartAcme.rawacmeClient.post(this.parentSmartAcme.location, body, this.parentSmartAcme.keyPair, (err, res) => { - if (err) { - console.error('smartacme: something went wrong:'); - console.log(err); - done.reject(err); - return; - } - console.log(JSON.stringify(res.body)); - done.resolve(); - }); - return done.promise; - } -} -exports.SmartacmeHelper = SmartacmeHelper; -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRhY21lLmNsYXNzZXMuaGVscGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvc21hcnRhY21lLmNsYXNzZXMuaGVscGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSwwQkFBdUI7QUFDdkIsdUJBQXNCO0FBQ3RCLElBQUksU0FBUyxHQUFHLE9BQU8sQ0FBQyxZQUFZLENBQUMsQ0FBQTtBQVNyQztJQUdJLFlBQVksWUFBdUI7UUFDL0IsSUFBSSxDQUFDLGVBQWUsR0FBRyxZQUFZLENBQUE7SUFDdkMsQ0FBQztJQUVEOztPQUVHO0lBQ0gsYUFBYSxDQUFDLEdBQUcsR0FBRyxJQUFJO1FBQ3BCLElBQUksTUFBTSxHQUFHLFNBQVMsQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLENBQUE7UUFDcEMsTUFBTSxDQUFDO1lBQ0gsU0FBUyxFQUFFLE1BQU0sQ0FBQyxVQUFVO1lBQzVCLFVBQVUsRUFBRSxNQUFNLENBQUMsV0FBVztTQUNqQyxDQUFBO0lBQ0wsQ0FBQztJQUVEOzs7T0FHRztJQUNILE1BQU07UUFDRixJQUFJLElBQUksR0FBRyxDQUFDLENBQUMsS0FBSyxFQUFFLENBQUE7UUFDcEIsSUFBSSxJQUFJLEdBQUcsRUFBRSxRQUFRLEVBQUUsS0FBSyxFQUFFLENBQUE7UUFDOUIsSUFBSSxDQUFDLGVBQWUsQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUNuQyxJQUFJLENBQUMsZUFBZSxDQUFDLFFBQVEsRUFDN0IsSUFBSSxFQUFFLElBQUksQ0FBQyxlQUFlLENBQUMsT0FBTyxFQUNsQyxDQUFDLEdBQUcsRUFBRSxHQUFHO1lBQ0wsRUFBRSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztnQkFDTixPQUFPLENBQUMsS0FBSyxDQUFDLGtDQUFrQyxDQUFDLENBQUE7Z0JBQ2pELE9BQU8sQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUE7Z0JBQ2hCLElBQUksQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUE7Z0JBQ2hCLE1BQU0sQ0FBQTtZQUNWLENBQUM7WUFDRCxPQUFPLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUE7WUFDckMsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFBO1FBQ2xCLENBQUMsQ0FDSixDQUFBO1FBQ0QsTUFBTSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUE7SUFDdkIsQ0FBQztDQUNKO0FBekNELDBDQXlDQyJ9 \ No newline at end of file diff --git a/dist/smartacme.classes.smartacme.d.ts b/dist/smartacme.classes.smartacme.d.ts index 5a2df31..1792cba 100644 --- a/dist/smartacme.classes.smartacme.d.ts +++ b/dist/smartacme.classes.smartacme.d.ts @@ -1,57 +1,34 @@ /// -import 'typings-global'; import * as q from 'q'; -import { SmartacmeHelper, IRsaKeypair } from './smartacme.classes.helper'; -export declare type TChallengeType = 'dns-01' | 'http-01'; -export declare type TChallengeStatus = 'pending'; -export interface ISmartAcmeChallenge { - uri: string; - status: TChallengeStatus; - type: TChallengeType; - token: string; - keyAuthorization: string; -} -export interface ISmartAcmeChallengeAccepted extends ISmartAcmeChallenge { - keyHash: string; +import { AcmeAccount } from './smartacme.classes.acmeaccount'; +/** + * a rsa keypair needed for account creation and subsequent requests + */ +export interface IRsaKeypair { + publicKey: string; + privateKey: string; } +export { AcmeAccount } from './smartacme.classes.acmeaccount'; +export { AcmeCert, ISmartAcmeChallenge, ISmartAcmeChallengeAccepted } from './smartacme.classes.acmecert'; /** * class SmartAcme exports methods for maintaining SSL Certificates */ export declare class SmartAcme { - helper: SmartacmeHelper; acmeUrl: string; productionBool: boolean; keyPair: IRsaKeypair; - location: string; - link: string; rawacmeClient: any; - JWK: any; /** * the constructor for class SmartAcme */ constructor(productionArg?: boolean); + /** + * init the smartacme instance + */ + init(): q.Promise<{}>; /** * creates an account if not currently present in module * @executes ASYNC */ - createAccount(): q.Promise<{}>; - agreeTos(): q.Promise<{}>; - /** - * requests a challenge for a domain - * @param domainNameArg - the domain name to request a challenge for - * @param challengeType - the challenge type to request - */ - requestChallenge(domainNameArg: string, challengeTypeArg?: TChallengeType): q.Promise; - /** - * getCertificate - takes care of cooldown, validation polling and certificate retrieval - */ - getCertificate(): void; - /** - * validates a challenge - */ - validate(challenge: ISmartAcmeChallengeAccepted): q.Promise<{}>; - /** - * accept a challenge - for private use only - */ - private acceptChallenge(challenge); + createAccount(): q.Promise; } diff --git a/dist/smartacme.classes.smartacme.js b/dist/smartacme.classes.smartacme.js index d20f434..50b6ed0 100644 --- a/dist/smartacme.classes.smartacme.js +++ b/dist/smartacme.classes.smartacme.js @@ -1,11 +1,13 @@ "use strict"; -// typings -require("typings-global"); // typings for node // third party modules const q = require("q"); // promises -let rsaKeygen = require('rsa-keygen'); // rsa keygen -let rawacme = require('rawacme'); // acme helper functions -const smartacme_classes_helper_1 = require("./smartacme.classes.helper"); +const plugins = require("./smartacme.plugins"); +const helpers = require("./smartacme.helpers"); +const smartacme_classes_acmeaccount_1 = require("./smartacme.classes.acmeaccount"); +var smartacme_classes_acmeaccount_2 = require("./smartacme.classes.acmeaccount"); +exports.AcmeAccount = smartacme_classes_acmeaccount_2.AcmeAccount; +var smartacme_classes_acmecert_1 = require("./smartacme.classes.acmecert"); +exports.AcmeCert = smartacme_classes_acmecert_1.AcmeCert; /** * class SmartAcme exports methods for maintaining SSL Certificates */ @@ -15,22 +17,20 @@ class SmartAcme { */ constructor(productionArg = false) { this.productionBool = productionArg; - this.helper = new smartacme_classes_helper_1.SmartacmeHelper(this); - this.keyPair = this.helper.createKeypair(); + this.keyPair = helpers.createKeypair(); if (this.productionBool) { - this.acmeUrl = rawacme.LETSENCRYPT_URL; + this.acmeUrl = plugins.rawacme.LETSENCRYPT_URL; } else { - this.acmeUrl = rawacme.LETSENCRYPT_STAGING_URL; + this.acmeUrl = plugins.rawacme.LETSENCRYPT_STAGING_URL; } } /** - * creates an account if not currently present in module - * @executes ASYNC + * init the smartacme instance */ - createAccount() { + init() { let done = q.defer(); - rawacme.createClient({ + plugins.rawacme.createClient({ url: this.acmeUrl, publicKey: this.keyPair.publicKey, privateKey: this.keyPair.privateKey @@ -43,126 +43,24 @@ class SmartAcme { } // make client available in class this.rawacmeClient = client; - // create the registration - client.newReg({ - contact: ['mailto:domains@lossless.org'] - }, (err, res) => { - if (err) { - console.error('smartacme: something went wrong:'); - console.log(err); - done.reject(err); - return; - } - this.JWK = res.body.key; - this.link = res.headers.link; - console.log(this.link); - this.location = res.headers.location; - done.resolve(); - }); - }); - return done.promise; - } - agreeTos() { - let done = q.defer(); - let tosPart = this.link.split(',')[1]; - let tosLinkPortion = tosPart.split(';')[0]; - let url = tosLinkPortion.split(';')[0].trim().replace(/[<>]/g, ''); - this.rawacmeClient.post(this.location, { Agreement: url, resource: 'reg' }, (err, res) => { - if (err) { - console.log(err); - done.reject(err); - return; - } done.resolve(); }); return done.promise; } /** - * requests a challenge for a domain - * @param domainNameArg - the domain name to request a challenge for - * @param challengeType - the challenge type to request + * creates an account if not currently present in module + * @executes ASYNC */ - requestChallenge(domainNameArg, challengeTypeArg = 'dns-01') { + createAccount() { let done = q.defer(); - this.rawacmeClient.newAuthz({ - identifier: { - type: 'dns', - value: domainNameArg - } - }, this.keyPair, (err, res) => { - if (err) { - console.error('smartacme: something went wrong:'); - console.log(err); - done.reject(err); - } - console.log(JSON.stringify(res.body)); - let dnsChallenge = res.body.challenges.filter(x => { - return x.type === challengeTypeArg; - })[0]; - this.acceptChallenge(dnsChallenge) - .then((x) => { - done.resolve(x); - }); - }); - return done.promise; - } - /** - * getCertificate - takes care of cooldown, validation polling and certificate retrieval - */ - getCertificate() { - } - /** - * validates a challenge - */ - validate(challenge) { - let done = q.defer(); - this.rawacmeClient.poll(challenge.uri, function (err, res) { - if (err) { - console.log(err); - done.reject(err); - } - console.log(res.status); - console.log(JSON.stringify(res.body)); - done.resolve(); - }); - return done.promise; - } - /** - * accept a challenge - for private use only - */ - acceptChallenge(challenge) { - let done = q.defer(); - /** - * the key is needed to accept the challenge - */ - let authKey = rawacme.keyAuthz(challenge.token, this.keyPair.publicKey); - /** - * needed in case selected challenge is of type dns-01 - */ - let keyHash = rawacme.dnsKeyAuthzHash(authKey); // needed if dns challenge is chosen - /** - * the return challenge - */ - let returnDNSChallenge = { - uri: challenge.uri, - type: challenge.type, - token: challenge.token, - keyAuthorization: challenge.keyAuthorization, - keyHash: keyHash, - status: challenge.status - }; - this.rawacmeClient.post(challenge.uri, { - resource: 'challenge', - keyAuthorization: authKey - }, this.keyPair, (err, res) => { - if (err) { - console.log(err); - done.reject(err); - } - done.resolve(returnDNSChallenge); + let acmeAccount = new smartacme_classes_acmeaccount_1.AcmeAccount(this); + acmeAccount.register().then(() => { + return acmeAccount.agreeTos(); + }).then(() => { + done.resolve(acmeAccount); }); return done.promise; } } exports.SmartAcme = SmartAcme; -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRhY21lLmNsYXNzZXMuc21hcnRhY21lLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvc21hcnRhY21lLmNsYXNzZXMuc21hcnRhY21lLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSxVQUFVO0FBQ1YsMEJBQXVCLENBQUMsbUJBQW1CO0FBRTNDLHNCQUFzQjtBQUN0Qix1QkFBc0IsQ0FBQyxXQUFXO0FBRWxDLElBQUksU0FBUyxHQUFHLE9BQU8sQ0FBQyxZQUFZLENBQUMsQ0FBQSxDQUFDLGFBQWE7QUFDbkQsSUFBSSxPQUFPLEdBQUcsT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQUFBLENBQUMsd0JBQXdCO0FBT3pELHlFQUF5RTtBQWlCekU7O0dBRUc7QUFDSDtJQVVJOztPQUVHO0lBQ0gsWUFBWSxnQkFBeUIsS0FBSztRQUN0QyxJQUFJLENBQUMsY0FBYyxHQUFHLGFBQWEsQ0FBQTtRQUNuQyxJQUFJLENBQUMsTUFBTSxHQUFHLElBQUksMENBQWUsQ0FBQyxJQUFJLENBQUMsQ0FBQTtRQUN2QyxJQUFJLENBQUMsT0FBTyxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsYUFBYSxFQUFFLENBQUE7UUFDMUMsRUFBRSxDQUFDLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxDQUFDLENBQUM7WUFDdEIsSUFBSSxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUMsZUFBZSxDQUFBO1FBQzFDLENBQUM7UUFBQyxJQUFJLENBQUMsQ0FBQztZQUNKLElBQUksQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDLHVCQUF1QixDQUFBO1FBQ2xELENBQUM7SUFDTCxDQUFDO0lBRUQ7OztPQUdHO0lBQ0gsYUFBYTtRQUNULElBQUksSUFBSSxHQUFHLENBQUMsQ0FBQyxLQUFLLEVBQUUsQ0FBQTtRQUNwQixPQUFPLENBQUMsWUFBWSxDQUNoQjtZQUNJLEdBQUcsRUFBRSxJQUFJLENBQUMsT0FBTztZQUNqQixTQUFTLEVBQUUsSUFBSSxDQUFDLE9BQU8sQ0FB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 \ No newline at end of file +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRhY21lLmNsYXNzZXMuc21hcnRhY21lLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvc21hcnRhY21lLmNsYXNzZXMuc21hcnRhY21lLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSxzQkFBc0I7QUFDdEIsdUJBQXNCLENBQUMsV0FBVztBQUNsQywrQ0FBOEM7QUFDOUMsK0NBQThDO0FBRTlDLG1GQUE2RDtBQVU3RCxpRkFBNkQ7QUFBcEQsc0RBQUEsV0FBVyxDQUFBO0FBQ3BCLDJFQUF5RztBQUFoRyxnREFBQSxRQUFRLENBQUE7QUFFakI7O0dBRUc7QUFDSDtJQU1JOztPQUVHO0lBQ0gsWUFBWSxnQkFBeUIsS0FBSztRQUN0QyxJQUFJLENBQUMsY0FBYyxHQUFHLGFBQWEsQ0FBQTtRQUNuQyxJQUFJLENBQUMsT0FBTyxHQUFHLE9BQU8sQ0FBQyxhQUFhLEVBQUUsQ0FBQTtRQUN0QyxFQUFFLENBQUMsQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDLENBQUMsQ0FBQztZQUN0QixJQUFJLENBQUMsT0FBTyxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUMsZUFBZSxDQUFBO1FBQ2xELENBQUM7UUFBQyxJQUFJLENBQUMsQ0FBQztZQUNKLElBQUksQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDLE9BQU8sQ0FBQyx1QkFBdUIsQ0FBQTtRQUMxRCxDQUFDO0lBQ0wsQ0FBQztJQUVEOztPQUVHO0lBQ0gsSUFBSTtRQUNBLElBQUksSUFBSSxHQUFHLENBQUMsQ0FBQyxLQUFLLEVBQUUsQ0FBQTtRQUNwQixPQUFPLENBQUMsT0FBTyxDQUFDLFlBQVksQ0FDeEI7WUFDSSxHQUFHLEVBQUUsSUFBSSxDQUFDLE9BQU87WUFDakIsU0FBUyxFQUFFLElBQUksQ0FBQyxPQUFPLENBQUMsU0FBUztZQUNqQyxVQUFVLEVBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxVQUFVO1NBQ3RDLEVBQ0QsQ0FBQyxHQUFHLEVBQUUsTUFBTTtZQUNSLEVBQUUsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7Z0JBQ04sT0FBTyxDQUFDLEtBQUssQ0FBQyxrQ0FBa0MsQ0FBQyxDQUFBO2dCQUNqRCxPQUFPLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFBO2dCQUNoQixJQUFJLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFBO2dCQUNoQixNQUFNLENBQUE7WUFDVixDQUFDO1lBRUQsa0NBQWtDO1lBQ2xDLElBQUksQ0FBQyxhQUFhLEdBQUcsTUFBTSxDQUFBO1lBQzNCLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQTtRQUNsQixDQUFDLENBQ0osQ0FBQTtRQUNELE1BQU0sQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFBO0lBQ3ZCLENBQUM7SUFFRDs7O09BR0c7SUFDSCxhQUFhO1FBQ1QsSUFBSSxJQUFJLEdBQUcsQ0FBQyxDQUFDLEtBQUssRUFBZSxDQUFBO1FBQ2pDLElBQUksV0FBVyxHQUFHLElBQUksMkNBQVcsQ0FBQyxJQUFJLENBQUMsQ0FBQTtRQUN2QyxXQUFXLENBQUMsUUFBUSxFQUFFLENBQUMsSUFBSSxDQUFDO1lBQ3hCLE1BQU0sQ0FBQyxXQUFXLENBQUMsUUFBUSxFQUFFLENBQUE7UUFDakMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDO1lBQ0osSUFBSSxDQUFDLE9BQU8sQ0FBQyxXQUFXLENBQUMsQ0FBQTtRQUM3QixDQUFDLENBQUMsQ0FBQTtRQUNGLE1BQU0sQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFBO0lBQ3ZCLENBQUM7Q0FDSjtBQTVERCw4QkE0REMifQ== \ No newline at end of file diff --git a/dist/smartacme.helpers.d.ts b/dist/smartacme.helpers.d.ts new file mode 100644 index 0000000..4acef35 --- /dev/null +++ b/dist/smartacme.helpers.d.ts @@ -0,0 +1,6 @@ +import 'typings-global'; +import { IRsaKeypair } from './smartacme.classes.smartacme'; +/** + * creates a keypair to use with requests and to generate JWK from + */ +export declare let createKeypair: (bit?: number) => IRsaKeypair; diff --git a/dist/smartacme.helpers.js b/dist/smartacme.helpers.js new file mode 100644 index 0000000..f0049fd --- /dev/null +++ b/dist/smartacme.helpers.js @@ -0,0 +1,34 @@ +"use strict"; +require("typings-global"); +const q = require("q"); +const plugins = require("./smartacme.plugins"); +/** + * creates a keypair to use with requests and to generate JWK from + */ +exports.createKeypair = (bit = 2048) => { + let result = plugins.rsaKeygen.generate(bit); + return { + publicKey: result.public_key, + privateKey: result.private_key + }; +}; +/** + * gets an existing registration + * @executes ASYNC + */ +let getReg = (SmartAcmeArg, location) => { + let done = q.defer(); + let body = { resource: 'reg' }; + SmartAcmeArg.rawacmeClient.post(location, body, SmartAcmeArg.keyPair, (err, res) => { + if (err) { + console.error('smartacme: something went wrong:'); + console.log(err); + done.reject(err); + return; + } + console.log(JSON.stringify(res.body)); + done.resolve(); + }); + return done.promise; +}; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRhY21lLmhlbHBlcnMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9zbWFydGFjbWUuaGVscGVycy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsMEJBQXVCO0FBQ3ZCLHVCQUFzQjtBQUV0QiwrQ0FBOEM7QUFLOUM7O0dBRUc7QUFDUSxRQUFBLGFBQWEsR0FBRyxDQUFDLEdBQUcsR0FBRyxJQUFJO0lBQ2xDLElBQUksTUFBTSxHQUFHLE9BQU8sQ0FBQyxTQUFTLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxDQUFBO0lBQzVDLE1BQU0sQ0FBQztRQUNILFNBQVMsRUFBRSxNQUFNLENBQUMsVUFBVTtRQUM1QixVQUFVLEVBQUUsTUFBTSxDQUFDLFdBQVc7S0FDakMsQ0FBQTtBQUNMLENBQUMsQ0FBQTtBQUVEOzs7R0FHRztBQUNILElBQUksTUFBTSxHQUFHLENBQUMsWUFBdUIsRUFBRSxRQUFnQjtJQUNuRCxJQUFJLElBQUksR0FBRyxDQUFDLENBQUMsS0FBSyxFQUFFLENBQUE7SUFDcEIsSUFBSSxJQUFJLEdBQUcsRUFBRSxRQUFRLEVBQUUsS0FBSyxFQUFFLENBQUE7SUFDOUIsWUFBWSxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQzNCLFFBQVEsRUFDUixJQUFJLEVBQ0osWUFBWSxDQUFDLE9BQU8sRUFDcEIsQ0FBQyxHQUFHLEVBQUUsR0FBRztRQUNMLEVBQUUsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7WUFDTixPQUFPLENBQUMsS0FBSyxDQUFDLGtDQUFrQyxDQUFDLENBQUE7WUFDakQsT0FBTyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQTtZQUNoQixJQUFJLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFBO1lBQ2hCLE1BQU0sQ0FBQTtRQUNWLENBQUM7UUFDRCxPQUFPLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUE7UUFDckMsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFBO0lBQ2xCLENBQUMsQ0FDSixDQUFBO0lBQ0QsTUFBTSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUE7QUFDdkIsQ0FBQyxDQUFBIn0= \ No newline at end of file diff --git a/dist/smartacme.plugins.d.ts b/dist/smartacme.plugins.d.ts new file mode 100644 index 0000000..0b48b83 --- /dev/null +++ b/dist/smartacme.plugins.d.ts @@ -0,0 +1,8 @@ +import 'typings-global'; +declare let rsaKeygen: any; +declare let rawacme: any; +declare let nodeForge: any; +import * as smartfile from 'smartfile'; +import * as smartstring from 'smartstring'; +import * as paths from './smartacme.paths'; +export { rsaKeygen, rawacme, nodeForge, smartfile, smartstring, paths }; diff --git a/dist/smartacme.plugins.js b/dist/smartacme.plugins.js new file mode 100644 index 0000000..9f636d2 --- /dev/null +++ b/dist/smartacme.plugins.js @@ -0,0 +1,16 @@ +"use strict"; +require("typings-global"); // typings for node +let rsaKeygen = require('rsa-keygen'); // rsa keygen +exports.rsaKeygen = rsaKeygen; +let rawacme = require('rawacme'); // acme helper functions +exports.rawacme = rawacme; +let nodeForge = require('node-forge'); +exports.nodeForge = nodeForge; +// push.rocks modules here +const smartfile = require("smartfile"); +exports.smartfile = smartfile; +const smartstring = require("smartstring"); +exports.smartstring = smartstring; +const paths = require("./smartacme.paths"); +exports.paths = paths; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRhY21lLnBsdWdpbnMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9zbWFydGFjbWUucGx1Z2lucy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsMEJBQXVCLENBQUMsbUJBQW1CO0FBRzNDLElBQUksU0FBUyxHQUFHLE9BQU8sQ0FBQyxZQUFZLENBQUMsQ0FBQSxDQUFDLGFBQWE7QUFVL0MsOEJBQVM7QUFUYixJQUFJLE9BQU8sR0FBRyxPQUFPLENBQUMsU0FBUyxDQUFDLENBQUEsQ0FBQyx3QkFBd0I7QUFVckQsMEJBQU87QUFUWCxJQUFJLFNBQVMsR0FBRyxPQUFPLENBQUMsWUFBWSxDQUFDLENBQUE7QUFVakMsOEJBQVM7QUFSYiwwQkFBMEI7QUFDMUIsdUNBQXNDO0FBUWxDLDhCQUFTO0FBUGIsMkNBQTBDO0FBUXRDLGtDQUFXO0FBUGYsMkNBQTBDO0FBUXRDLHNCQUFLIn0= \ No newline at end of file diff --git a/package.json b/package.json index d290b81..d53fe49 100644 --- a/package.json +++ b/package.json @@ -35,6 +35,7 @@ }, "devDependencies": { "@types/should": "^8.1.30", + "cflare": "0.0.10", "should": "^11.1.1", "typings-test": "^1.0.3" } diff --git a/test/test.js b/test/test.js index 594d74b..4810dce 100644 --- a/test/test.js +++ b/test/test.js @@ -4,44 +4,42 @@ const should = require("should"); // import the module to test const smartacme = require("../dist/index"); describe('smartacme', function () { - let testAcme; + let testSmartAcme; + let testAcmeAccount; let testChallenge; - it('should create a valid instance', function () { + it('should create a valid instance', function (done) { this.timeout(10000); - testAcme = new smartacme.SmartAcme(); - should(testAcme).be.instanceOf(smartacme.SmartAcme); + testSmartAcme = new smartacme.SmartAcme(); + testSmartAcme.init().then(() => { + should(testSmartAcme).be.instanceOf(smartacme.SmartAcme); + done(); + }).catch(err => { done(err); }); }); it('should have created keyPair', function () { - should(testAcme.acmeUrl).be.of.type('string'); + should(testSmartAcme.acmeUrl).be.of.type('string'); }); it('should register a new account', function (done) { this.timeout(10000); - testAcme.createAccount().then(x => { + testSmartAcme.createAccount().then(x => { done(); }).catch(err => { console.log(err); done(err); }); }); - it('should agree to ToS', function (done) { + it.skip('should request a cert for a domain', function (done) { this.timeout(10000); - testAcme.agreeTos().then(() => { - done(); - }); - }); - it('should request a challenge for a domain', function (done) { - this.timeout(10000); - testAcme.requestChallenge('bleu.de').then((challengeAccepted) => { + testAcmeAccount.requestChallenge('bleu.de').then((challengeAccepted) => { console.log(challengeAccepted); testChallenge = challengeAccepted; done(); }); }); - it('should poll for validation of a challenge', function (done) { + it.skip('should poll for validation of a challenge', function (done) { this.timeout(10000); - testAcme.validate(testChallenge).then(x => { + testSmartAcme.validate(testChallenge).then(x => { done(); }); }); }); -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbInRlc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLHdCQUFxQjtBQUNyQixpQ0FBZ0M7QUFFaEMsNEJBQTRCO0FBQzVCLDJDQUEwQztBQUUxQyxRQUFRLENBQUMsV0FBVyxFQUFFO0lBQ2xCLElBQUksUUFBNkIsQ0FBQTtJQUNqQyxJQUFJLGFBQW9ELENBQUE7SUFDeEQsRUFBRSxDQUFDLGdDQUFnQyxFQUFFO1FBQ2pDLElBQUksQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUE7UUFDbkIsUUFBUSxHQUFHLElBQUksU0FBUyxDQUFDLFNBQVMsRUFBRSxDQUFBO1FBQ3BDLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQyxFQUFFLENBQUMsVUFBVSxDQUFDLFNBQVMsQ0FBQyxTQUFTLENBQUMsQ0FBQTtJQUN2RCxDQUFDLENBQUMsQ0FBQTtJQUVGLEVBQUUsQ0FBQyw2QkFBNkIsRUFBRTtRQUM5QixNQUFNLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFBO0lBQ2pELENBQUMsQ0FBQyxDQUFBO0lBRUYsRUFBRSxDQUFDLCtCQUErQixFQUFFLFVBQVUsSUFBSTtRQUM5QyxJQUFJLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFBO1FBQ25CLFFBQVEsQ0FBQyxhQUFhLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUMzQixJQUFJLEVBQUUsQ0FBQTtRQUNWLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxHQUFHO1lBQ1IsT0FBTyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQTtZQUNoQixJQUFJLENBQUMsR0FBRyxDQUFDLENBQUE7UUFDYixDQUFDLENBQUMsQ0FBQTtJQUNOLENBQUMsQ0FBQyxDQUFBO0lBRUYsRUFBRSxDQUFDLHFCQUFxQixFQUFFLFVBQVMsSUFBSTtRQUNuQyxJQUFJLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFBO1FBQ25CLFFBQVEsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxJQUFJLENBQUM7WUFDckIsSUFBSSxFQUFFLENBQUE7UUFDVixDQUFDLENBQUMsQ0FBQTtJQUNOLENBQUMsQ0FBQyxDQUFBO0lBRUYsRUFBRSxDQUFDLHlDQUF5QyxFQUFFLFVBQVMsSUFBSTtRQUN2RCxJQUFJLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFBO1FBQ25CLFFBQVEsQ0FBQyxnQkFBZ0IsQ0FBQyxTQUFTLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxpQkFBaUI7WUFDeEQsT0FBTyxDQUFDLEdBQUcsQ0FBQyxpQkFBaUIsQ0FBQyxDQUFBO1lBQzlCLGFBQWEsR0FBRyxpQkFBaUIsQ0FBQTtZQUNqQyxJQUFJLEVBQUUsQ0FBQTtRQUNWLENBQUMsQ0FBQyxDQUFBO0lBQ04sQ0FBQyxDQUFDLENBQUE7SUFFRixFQUFFLENBQUMsMkNBQTJDLEVBQUMsVUFBUyxJQUFJO1FBQ3hELElBQUksQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUE7UUFDbkIsUUFBUSxDQUFDLFFBQVEsQ0FBQyxhQUFhLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUNuQyxJQUFJLEVBQUUsQ0FBQTtRQUNWLENBQUMsQ0FBQyxDQUFBO0lBQ04sQ0FBQyxDQUFDLENBQUE7QUFDTixDQUFDLENBQUMsQ0FBQSJ9 \ No newline at end of file +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbInRlc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLHdCQUFxQjtBQUNyQixpQ0FBZ0M7QUFHaEMsNEJBQTRCO0FBQzVCLDJDQUEwQztBQUUxQyxRQUFRLENBQUMsV0FBVyxFQUFFO0lBQ2xCLElBQUksYUFBa0MsQ0FBQTtJQUN0QyxJQUFJLGVBQXNDLENBQUE7SUFDMUMsSUFBSSxhQUFvRCxDQUFBO0lBQ3hELEVBQUUsQ0FBQyxnQ0FBZ0MsRUFBRSxVQUFVLElBQUk7UUFDL0MsSUFBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQTtRQUNuQixhQUFhLEdBQUcsSUFBSSxTQUFTLENBQUMsU0FBUyxFQUFFLENBQUE7UUFDekMsYUFBYSxDQUFDLElBQUksRUFBRSxDQUFDLElBQUksQ0FBQztZQUN0QixNQUFNLENBQUMsYUFBYSxDQUFDLENBQUMsRUFBRSxDQUFDLFVBQVUsQ0FBQyxTQUFTLENBQUMsU0FBUyxDQUFDLENBQUE7WUFDeEQsSUFBSSxFQUFFLENBQUE7UUFDVixDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsR0FBRyxNQUFNLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQSxDQUFDLENBQUMsQ0FBQyxDQUFBO0lBQ2xDLENBQUMsQ0FBQyxDQUFBO0lBRUYsRUFBRSxDQUFDLDZCQUE2QixFQUFFO1FBQzlCLE1BQU0sQ0FBQyxhQUFhLENBQUMsT0FBTyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUE7SUFDdEQsQ0FBQyxDQUFDLENBQUE7SUFFRixFQUFFLENBQUMsK0JBQStCLEVBQUUsVUFBVSxJQUFJO1FBQzlDLElBQUksQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUE7UUFDbkIsYUFBYSxDQUFDLGFBQWEsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQ2hDLElBQUksRUFBRSxDQUFBO1FBQ1YsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLEdBQUc7WUFDUixPQUFPLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFBO1lBQ2hCLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQTtRQUNiLENBQUMsQ0FBQyxDQUFBO0lBQ04sQ0FBQyxDQUFDLENBQUE7SUFFRixFQUFFLENBQUMsSUFBSSxDQUFDLG9DQUFvQyxFQUFFLFVBQVUsSUFBSTtRQUN4RCxJQUFJLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFBO1FBQ25CLGVBQWUsQ0FBQyxnQkFBZ0IsQ0FBQyxTQUFTLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxpQkFBaUI7WUFDL0QsT0FBTyxDQUFDLEdBQUcsQ0FBQyxpQkFBaUIsQ0FBQyxDQUFBO1lBQzlCLGFBQWEsR0FBRyxpQkFBaUIsQ0FBQTtZQUNqQyxJQUFJLEVBQUUsQ0FBQTtRQUNWLENBQUMsQ0FBQyxDQUFBO0lBQ04sQ0FBQyxDQUFDLENBQUE7SUFFRixFQUFFLENBQUMsSUFBSSxDQUFDLDJDQUEyQyxFQUFFLFVBQVUsSUFBSTtRQUMvRCxJQUFJLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFBO1FBQ25CLGFBQWEsQ0FBQyxRQUFRLENBQUMsYUFBYSxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDeEMsSUFBSSxFQUFFLENBQUE7UUFDVixDQUFDLENBQUMsQ0FBQTtJQUNOLENBQUMsQ0FBQyxDQUFBO0FBQ04sQ0FBQyxDQUFDLENBQUEifQ== \ No newline at end of file diff --git a/test/test.ts b/test/test.ts index 99219e4..35a24ee 100644 --- a/test/test.ts +++ b/test/test.ts @@ -1,25 +1,30 @@ import 'typings-test' import * as should from 'should' +import * as cflare from 'cflare' // import the module to test import * as smartacme from '../dist/index' describe('smartacme', function () { - let testAcme: smartacme.SmartAcme + let testSmartAcme: smartacme.SmartAcme + let testAcmeAccount: smartacme.AcmeAccount let testChallenge: smartacme.ISmartAcmeChallengeAccepted - it('should create a valid instance', function () { + it('should create a valid instance', function (done) { this.timeout(10000) - testAcme = new smartacme.SmartAcme() - should(testAcme).be.instanceOf(smartacme.SmartAcme) + testSmartAcme = new smartacme.SmartAcme() + testSmartAcme.init().then(() => { + should(testSmartAcme).be.instanceOf(smartacme.SmartAcme) + done() + }).catch(err => { done(err) }) }) it('should have created keyPair', function () { - should(testAcme.acmeUrl).be.of.type('string') + should(testSmartAcme.acmeUrl).be.of.type('string') }) it('should register a new account', function (done) { this.timeout(10000) - testAcme.createAccount().then(x => { + testSmartAcme.createAccount().then(x => { done() }).catch(err => { console.log(err) @@ -27,25 +32,18 @@ describe('smartacme', function () { }) }) - it('should agree to ToS', function(done) { + it.skip('should request a cert for a domain', function (done) { this.timeout(10000) - testAcme.agreeTos().then(() => { - done() - }) - }) - - it('should request a challenge for a domain', function(done) { - this.timeout(10000) - testAcme.requestChallenge('bleu.de').then((challengeAccepted) => { + testAcmeAccount.requestChallenge('bleu.de').then((challengeAccepted) => { console.log(challengeAccepted) testChallenge = challengeAccepted done() }) }) - it('should poll for validation of a challenge',function(done) { + it.skip('should poll for validation of a challenge', function (done) { this.timeout(10000) - testAcme.validate(testChallenge).then(x => { + testSmartAcme.validate(testChallenge).then(x => { done() }) }) diff --git a/ts/smartacme.classes.acmeaccount.ts b/ts/smartacme.classes.acmeaccount.ts index ba2666f..c727f75 100644 --- a/ts/smartacme.classes.acmeaccount.ts +++ b/ts/smartacme.classes.acmeaccount.ts @@ -1,8 +1,68 @@ -import 'typings-global' +import * as q from 'q' + +import * as plugins from './smartacme.plugins' +import * as helpers from './smartacme.helpers' + +import { SmartAcme, IRsaKeypair } from './smartacme.classes.smartacme' +import { AcmeCert } from './smartacme.classes.acmecert' /** * class AcmeAccount represents an AcmeAccount */ export class AcmeAccount { - -} \ No newline at end of file + parentSmartAcme: SmartAcme + location: string + link: string + JWK + constructor(smartAcmeParentArg: SmartAcme) { + this.parentSmartAcme = smartAcmeParentArg + } + + /** + * register the account with letsencrypt + */ + register() { + let done = q.defer() + this.parentSmartAcme.rawacmeClient.newReg( + { + contact: ['mailto:domains@lossless.org'] + }, + (err, res) => { + if (err) { + console.error('smartacme: something went wrong:') + console.log(err) + done.reject(err) + return + } + this.JWK = res.body.key + this.link = res.headers.link + console.log(this.link) + this.location = res.headers.location + done.resolve() + }) + return done.promise + } + + /** + * agree to letsencrypr terms of service + */ + agreeTos() { + let done = q.defer() + let tosPart = this.link.split(',')[1] + let tosLinkPortion = tosPart.split(';')[0] + let url = tosLinkPortion.split(';')[0].trim().replace(/[<>]/g, '') + this.parentSmartAcme.rawacmeClient.post(this.location, { Agreement: url, resource: 'reg' }, (err, res) => { + if (err) { + console.log(err) + done.reject(err) + return + } + done.resolve() + }) + return done.promise + } + + createAcmeCert(domainNameArg: string) { + + } +} diff --git a/ts/smartacme.classes.acmecert.ts b/ts/smartacme.classes.acmecert.ts index 6b17e50..a07d7ee 100644 --- a/ts/smartacme.classes.acmecert.ts +++ b/ts/smartacme.classes.acmecert.ts @@ -1,8 +1,226 @@ -import 'typings-global' +import * as q from 'q' + +import * as plugins from './smartacme.plugins' +import * as helpers from './smartacme.helpers' + +import { SmartAcme, IRsaKeypair } from './smartacme.classes.smartacme' +import { AcmeAccount } from './smartacme.classes.acmeaccount' + +/** + * types of challenges supported by letsencrypt and this module + */ +export type TChallengeType = 'dns-01' | 'http-01' + +/** + * values that a challenge's status can have + */ +export type TChallengeStatus = 'pending' + +export interface ISmartAcmeChallenge { + uri: string + status: TChallengeStatus + type: TChallengeType + token: string + keyAuthorization: string +} + +export interface ISmartAcmeChallengeAccepted extends ISmartAcmeChallenge { + keyHash: string +} + +export interface IAcmeCsrConstructorOptions { + bit: number, + key: string, + domain: string, + country: string, + country_short: string, + locality: string, + organization: string, + organization_short: string, + password: string, + unstructured: string, + subject_alt_names: string[] +} /** * class AcmeCert represents a cert for domain */ export class AcmeCert { + attributes fullchain: string -} \ No newline at end of file + parentAcmeAccount: AcmeAccount + csr + validFrom: Date + validTo: Date + keypair: IRsaKeypair + keyPairFinal: IRsaKeypair + constructor(optionsArg: IAcmeCsrConstructorOptions, parentSmartAcmeArg) { + this.parentAcmeAccount = parentSmartAcmeArg + this.keypair = helpers.createKeypair(optionsArg.bit) + let privateKeyForged = plugins.nodeForge.pki.privateKeyFromPem(this.keypair.privateKey) + let publicKeyForged = plugins.nodeForge.pki.publicKeyToPem( + plugins.nodeForge.pki.setRsaPublicKey(privateKeyForged.n, privateKeyForged.e) + ) + this.keyPairFinal = { + privateKey: privateKeyForged, + publicKey: publicKeyForged + } + + // set dates + this.validFrom = new Date() + this.validTo = new Date() + this.validTo.setDate(this.validFrom.getDate() + 90) + + // set attributes + this.attributes = [ + { name: 'commonName', value: optionsArg.domain }, + { name: 'countryName', value: optionsArg.country }, + { shortName: 'ST', value: optionsArg.country_short }, + { name: 'localityName', value: optionsArg.locality }, + { name: 'organizationName', value: optionsArg.organization }, + { shortName: 'OU', value: optionsArg.organization_short }, + { name: 'challengePassword', value: optionsArg.password }, + { name: 'unstructuredName', value: optionsArg.unstructured } + ] + + // set up csr + this.csr = plugins.nodeForge.pki.createCertificationRequest() + this.csr.setSubject(this.attributes) + this.csr.setAttributes(this.attributes) + } + + /** + * requests a challenge for a domain + * @param domainNameArg - the domain name to request a challenge for + * @param challengeType - the challenge type to request + */ + requestChallenge(domainNameArg: string, challengeTypeArg: TChallengeType = 'dns-01') { + let done = q.defer() + this.parentAcmeAccount.parentSmartAcme.rawacmeClient.newAuthz( + { + identifier: { + type: 'dns', + value: domainNameArg + } + }, + this.parentAcmeAccount.parentSmartAcme.keyPair, + (err, res) => { + if (err) { + console.error('smartacme: something went wrong:') + console.log(err) + done.reject(err) + } + console.log(JSON.stringify(res.body)) + let dnsChallenge = res.body.challenges.filter(x => { + return x.type === challengeTypeArg + })[0] + this.acceptChallenge(dnsChallenge) + .then((x: ISmartAcmeChallengeAccepted) => { + done.resolve(x) + }) + } + ) + return done.promise + } + + /** + * validates a challenge, only call after you have set the challenge at the expected location + */ + validate(challenge: ISmartAcmeChallengeAccepted) { + let done = q.defer() + this.parentAcmeAccount.parentSmartAcme.rawacmeClient.poll(challenge.uri, function (err, res) { + if (err) { + console.log(err) + done.reject(err) + } + console.log(res.status) + console.log(JSON.stringify(res.body)) + done.resolve() + }) + return done.promise + } + + /** + * requests a certificate + */ + requestCert() { + let done = q.defer() + let payload = { + csr: plugins.rawacme.base64.encode( + plugins.rawacme.toDer( + plugins.nodeForge.pki.certificationRequestToPem( + this.csr + ) + ) + ), + notBefore: this.validFrom.toISOString(), + notAfter: this.validTo.toISOString() + } + this.parentAcmeAccount.parentSmartAcme.rawacmeClient.newCert( + payload, + helpers.createKeypair(), + (err, res) => { + if (err) { + console.log(err) + done.reject(err) + } + }) + return done.promise + } + + /** + * getCertificate - takes care of cooldown, validation polling and certificate retrieval + */ + getCertificate() { + + } + + /** + * accept a challenge - for private use only + */ + private acceptChallenge(challenge: ISmartAcmeChallenge) { + let done = q.defer() + + /** + * the key is needed to accept the challenge + */ + let authKey: string = plugins.rawacme.keyAuthz( + challenge.token, + this.parentAcmeAccount.parentSmartAcme.keyPair.publicKey + ) + + /** + * needed in case selected challenge is of type dns-01 + */ + let keyHash: string = plugins.rawacme.dnsKeyAuthzHash(authKey) // needed if dns challenge is chosen + + /** + * the return challenge + */ + let returnDNSChallenge: ISmartAcmeChallengeAccepted = { + uri: challenge.uri, + type: challenge.type, + token: challenge.token, + keyAuthorization: challenge.keyAuthorization, + keyHash: keyHash, + status: challenge.status + } + + this.parentAcmeAccount.parentSmartAcme.rawacmeClient.post( + challenge.uri, + { + resource: 'challenge', + keyAuthorization: authKey + }, + this.parentAcmeAccount.parentSmartAcme.keyPair, + (err, res) => { + if (err) { + console.log(err) + done.reject(err) + } + done.resolve(returnDNSChallenge) + } + ) + return done.promise + } +} diff --git a/ts/smartacme.classes.acmecsr.ts b/ts/smartacme.classes.acmecsr.ts deleted file mode 100644 index 097ef6f..0000000 --- a/ts/smartacme.classes.acmecsr.ts +++ /dev/null @@ -1,52 +0,0 @@ -import * as plugins from './smartacme.plugins' -import * as helpers from './smartacme.helpers' - -import { IRsaKeypair } from './smartacme.classes.smartacme' - -export interface IAcmeCsrConstructorOptions { - bit: number, - key: string, - domain: string, - country: string, - country_short: string, - locality: string, - organization: string, - organization_short: string, - password: string, - unstructured: string, - subject_alt_names: string[] -} - -export class AcmeCsr { - validFrom: Date - validTo: Date - keypair: IRsaKeypair - keyPairForged: IRsaKeypair - constructor(optionsArg: IAcmeCsrConstructorOptions) { - this.keypair = helpers.createKeypair(optionsArg.bit) - let privateKeyForged = plugins.nodeForge.pki.privateKeyFromPem(this.keypair.privateKey) - let publicKeyForged = plugins.nodeForge.pki.publicKeyToPem( - plugins.nodeForge.pki.setRsaPublicKey(privateKeyForged.n, privateKeyForged.e) - ) - this.keyPairForged = { - privateKey: privateKeyForged, - publicKey: publicKeyForged - } - - // set dates - this.validFrom = new Date() - this.validTo = new Date() - this.validTo.setDate(this.validFrom.getDate() + 90) - - // create the csr - let attributes = [ - { name: "commonName", value: domain }, - { name: "countryName", value: country }, - { shortName: "ST", value: country_short }, - { name: "localityName", value: locality }, - { name: "organizationName", value: organization }, - { shortName: "OU", value: organization_short } - ] - - } -} diff --git a/ts/smartacme.classes.smartacme.ts b/ts/smartacme.classes.smartacme.ts index 475e6a6..68bfa4e 100644 --- a/ts/smartacme.classes.smartacme.ts +++ b/ts/smartacme.classes.smartacme.ts @@ -3,37 +3,27 @@ import * as q from 'q' // promises import * as plugins from './smartacme.plugins' import * as helpers from './smartacme.helpers' +import { AcmeAccount } from './smartacme.classes.acmeaccount' + +/** + * a rsa keypair needed for account creation and subsequent requests + */ export interface IRsaKeypair { publicKey: string privateKey: string } -export type TChallengeType = 'dns-01' | 'http-01' -export type TChallengeStatus = 'pending' - -export interface ISmartAcmeChallenge { - uri: string - status: TChallengeStatus - type: TChallengeType - token: string - keyAuthorization: string -} - -export interface ISmartAcmeChallengeAccepted extends ISmartAcmeChallenge { - keyHash: string -} +export { AcmeAccount } from './smartacme.classes.acmeaccount' +export { AcmeCert, ISmartAcmeChallenge, ISmartAcmeChallengeAccepted } from './smartacme.classes.acmecert' /** * class SmartAcme exports methods for maintaining SSL Certificates */ export class SmartAcme { - acmeUrl: string // the acme url to use + acmeUrl: string // the acme url to use for this instance productionBool: boolean // a boolean to quickly know wether we are in production or not keyPair: IRsaKeypair // the keyPair needed for account creation - location: string - link: string rawacmeClient - JWK /** * the constructor for class SmartAcme @@ -49,10 +39,9 @@ export class SmartAcme { } /** - * creates an account if not currently present in module - * @executes ASYNC + * init the smartacme instance */ - createAccount() { + init() { let done = q.defer() plugins.rawacme.createClient( { @@ -70,151 +59,24 @@ export class SmartAcme { // make client available in class this.rawacmeClient = client - - // create the registration - client.newReg( - { - contact: ['mailto:domains@lossless.org'] - }, - (err, res) => { - if (err) { - console.error('smartacme: something went wrong:') - console.log(err) - done.reject(err) - return - } - this.JWK = res.body.key - this.link = res.headers.link - console.log(this.link) - this.location = res.headers.location - done.resolve() - }) - + done.resolve() } ) return done.promise } - agreeTos() { - let done = q.defer() - let tosPart = this.link.split(',')[1] - let tosLinkPortion = tosPart.split(';')[0] - let url = tosLinkPortion.split(';')[0].trim().replace(/[<>]/g, '') - this.rawacmeClient.post(this.location, { Agreement: url, resource: 'reg' }, (err, res) => { - if (err) { - console.log(err) - done.reject(err) - return - } - done.resolve() + /** + * creates an account if not currently present in module + * @executes ASYNC + */ + createAccount() { + let done = q.defer() + let acmeAccount = new AcmeAccount(this) + acmeAccount.register().then(() => { + return acmeAccount.agreeTos() + }).then(() => { + done.resolve(acmeAccount) }) return done.promise } - - /** - * requests a challenge for a domain - * @param domainNameArg - the domain name to request a challenge for - * @param challengeType - the challenge type to request - */ - requestChallenge(domainNameArg: string, challengeTypeArg: TChallengeType = 'dns-01') { - let done = q.defer() - this.rawacmeClient.newAuthz( - { - identifier: { - type: 'dns', - value: domainNameArg - } - }, - this.keyPair, - (err, res) => { - if (err) { - console.error('smartacme: something went wrong:') - console.log(err) - done.reject(err) - } - console.log(JSON.stringify(res.body)) - let dnsChallenge = res.body.challenges.filter(x => { - return x.type === challengeTypeArg - })[0] - this.acceptChallenge(dnsChallenge) - .then((x: ISmartAcmeChallengeAccepted) => { - done.resolve(x) - }) - } - ) - return done.promise - } - - /** - * getCertificate - takes care of cooldown, validation polling and certificate retrieval - */ - getCertificate() { - - } - - /** - * validates a challenge - */ - validate(challenge: ISmartAcmeChallengeAccepted) { - let done = q.defer() - this.rawacmeClient.poll(challenge.uri, function(err, res) { - if (err) { - console.log(err) - done.reject(err) - } - console.log(res.status) - console.log(JSON.stringify(res.body)) - done.resolve() - }) - return done.promise - } - - - /** - * accept a challenge - for private use only - */ - private acceptChallenge(challenge: ISmartAcmeChallenge) { - let done = q.defer() - - /** - * the key is needed to accept the challenge - */ - let authKey: string = plugins.rawacme.keyAuthz(challenge.token, this.keyPair.publicKey) - - /** - * needed in case selected challenge is of type dns-01 - */ - let keyHash: string = plugins.rawacme.dnsKeyAuthzHash(authKey) // needed if dns challenge is chosen - - /** - * the return challenge - */ - let returnDNSChallenge: ISmartAcmeChallengeAccepted = { - uri: challenge.uri, - type: challenge.type, - token: challenge.token, - keyAuthorization: challenge.keyAuthorization, - keyHash: keyHash, - status: challenge.status - } - - this.rawacmeClient.post( - challenge.uri, - { - resource: 'challenge', - keyAuthorization: authKey - }, - this.keyPair, - (err, res) => { - if (err) { - console.log(err) - done.reject(err) - } - done.resolve(returnDNSChallenge) - } - ) - return done.promise - } - - } diff --git a/ts/smartacme.helpers.ts b/ts/smartacme.helpers.ts index 85e1b35..06d550b 100644 --- a/ts/smartacme.helpers.ts +++ b/ts/smartacme.helpers.ts @@ -4,8 +4,7 @@ import * as q from 'q' import * as plugins from './smartacme.plugins' import { SmartAcme, IRsaKeypair } from './smartacme.classes.smartacme' - - +import { AcmeAccount } from './smartacme.classes.acmeaccount' /** * creates a keypair to use with requests and to generate JWK from @@ -22,12 +21,13 @@ export let createKeypair = (bit = 2048): IRsaKeypair => { * gets an existing registration * @executes ASYNC */ -let getReg = (smartAcmeArg: SmartAcme) => { +let getReg = (SmartAcmeArg: SmartAcme, location: string) => { let done = q.defer() let body = { resource: 'reg' } - smartAcmeArg.rawacmeClient.post( - smartAcmeArg.location, - body, smartAcmeArg.keyPair, + SmartAcmeArg.rawacmeClient.post( + location, + body, + SmartAcmeArg.keyPair, (err, res) => { if (err) { console.error('smartacme: something went wrong:') diff --git a/ts/smartacme.plugins.ts b/ts/smartacme.plugins.ts index 795e22d..4848784 100644 --- a/ts/smartacme.plugins.ts +++ b/ts/smartacme.plugins.ts @@ -17,4 +17,4 @@ export { smartfile, smartstring, paths -} \ No newline at end of file +}