UNPKG

@canva/create-app

Version:

A command line tool for creating Canva Apps.

132 lines (116 loc) 3.06 kB
import * as crypto from "crypto"; import { pki } from "node-forge"; import * as path from "path"; import * as fs from "fs/promises"; const SSL_CERT_DIR = path.resolve(process.cwd(), "..", "..", ".ssl"); const CERT_FILE = path.resolve(SSL_CERT_DIR, "certificate.pem"); const KEY_FILE = path.resolve(SSL_CERT_DIR, "private-key.pem"); export interface Certificate { keyFile: string; certFile: string; } const CERT_ATTRS: { name: string; value: string }[] = [ { name: "commonName", value: "localhost", }, { name: "countryName", value: "AU", }, { name: "stateOrProvinceName", value: "New South Wales", }, { name: "localityName", value: "Sydney", }, { name: "organizationName", value: "Test", }, { name: "organizationalUnitName", value: "Test", }, ]; const generateRsaKeys = async (): Promise<{ publicKey: string; privateKey: string; }> => new Promise((resolve, reject) => { crypto.generateKeyPair( "rsa", { modulusLength: 2096, publicKeyEncoding: { type: "spki", format: "pem", }, privateKeyEncoding: { type: "pkcs8", format: "pem", }, }, (err, publicKey, privateKey) => { if (err) { reject(err); } else { resolve({ publicKey, privateKey }); } }, ); }); const generateCertificate = (opts: { privateKey: string; publicKey: string; }): string => { const privateKey = pki.privateKeyFromPem(opts.privateKey); const publicKey = pki.publicKeyFromPem(opts.publicKey); const cert = pki.createCertificate(); cert.publicKey = publicKey; cert.serialNumber = "01"; cert.validity.notBefore = new Date(); cert.validity.notAfter = new Date(); cert.validity.notAfter.setFullYear(cert.validity.notBefore.getFullYear() + 1); cert.setSubject(CERT_ATTRS); cert.setIssuer(CERT_ATTRS); // the actual certificate signing cert.sign(privateKey); // now convert the Forge certificate to PEM format return pki.certificateToPem(cert); }; const writeCertFiles = async (opts: { cert: string; privateKey: string; }): Promise<void> => { const { cert, privateKey } = opts; await fs.mkdir(SSL_CERT_DIR, { recursive: true }); await Promise.all([ fs.writeFile(CERT_FILE, cert, { encoding: "utf8" }), fs.writeFile(KEY_FILE, privateKey, { encoding: "utf8" }), ]); }; const cerfFilesExist = async (): Promise<boolean> => { try { await Promise.all([ fs.access(CERT_FILE, fs.constants.R_OK | fs.constants.W_OK), fs.access(KEY_FILE, fs.constants.R_OK | fs.constants.W_OK), ]); return true; } catch { return false; } }; export const createOrRetrieveCertificate = async (): Promise<Certificate> => { if (!(await cerfFilesExist())) { const keys = await generateRsaKeys(); const cert = generateCertificate(keys); await writeCertFiles({ cert, privateKey: keys.privateKey }); } return { certFile: CERT_FILE, keyFile: KEY_FILE, }; };