diff --git a/packages/office-addin-dev-certs/src/uninstall.ts b/packages/office-addin-dev-certs/src/uninstall.ts index 215d32f86..1a709c972 100644 --- a/packages/office-addin-dev-certs/src/uninstall.ts +++ b/packages/office-addin-dev-certs/src/uninstall.ts @@ -1,12 +1,12 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. - + import { execSync } from "child_process"; import * as fsExtra from "fs-extra"; import * as path from "path"; import * as defaults from "./defaults"; import { isCaCertificateInstalled } from "./verify"; - + function getUninstallCommand(machine: boolean = false): string { switch (process.platform) { case "win32": @@ -18,34 +18,49 @@ function getUninstallCommand(machine: boolean = false): string { throw new Error(`Platform not supported: ${process.platform}`); } } - + // Deletes the generated certificate files and delete the certificate directory if its empty export function deleteCertificateFiles(certificateDirectory: string = defaults.certificateDirectory): void { if (fsExtra.existsSync(certificateDirectory)) { fsExtra.removeSync(path.join(certificateDirectory, defaults.localhostCertificateFileName)); fsExtra.removeSync(path.join(certificateDirectory, defaults.localhostKeyFileName)); fsExtra.removeSync(path.join(certificateDirectory, defaults.caCertificateFileName)); - + if (fsExtra.readdirSync(certificateDirectory).length === 0) { fsExtra.removeSync(certificateDirectory); } } } - + export async function uninstallCaCertificate(machine: boolean = false, verbose: boolean = true) { if (isCaCertificateInstalled()) { const command = getUninstallCommand(machine); - + try { - console.log(`Uninstalling CA certificate "Developer CA for Microsoft Office Add-ins"...`); - execSync(command, {stdio : "pipe" }); + console.log(`Uninstalling CA certificate "Developer CA for Microsoft Office Add-ins"...`); + execSync(command, { stdio: "pipe" }); console.log(`You no longer have trusted access to https://localhost.`); } catch (error) { throw new Error(`Unable to uninstall the CA certificate.\n${error.stderr.toString()}`); } } else { if (verbose) { - console.log(`The CA certificate is not installed.`); + console.log(`The CA certificate is not installed.`); } } } + +// Currently this method is only intended to be used for Mac due to problems on Mac that occur when CA certificates expire +export async function uninstallExpiredCaCertificate() { + if (process.platform === "darwin") { + const command = getUninstallCommand(); + + try { + console.log(`Uninstalling expired CA certificate "Developer CA for Microsoft Office Add-ins".`); + execSync(command, { stdio: "pipe" }); + console.log(`You no longer have trusted access to https://localhost.`); + } catch (error) { + throw new Error(`Unable to uninstall expired the CA certificate.\n${error.stderr.toString()}`); + } + } +} \ No newline at end of file diff --git a/packages/office-addin-dev-certs/src/verify.ts b/packages/office-addin-dev-certs/src/verify.ts index 3471185c2..6f7b83016 100644 --- a/packages/office-addin-dev-certs/src/verify.ts +++ b/packages/office-addin-dev-certs/src/verify.ts @@ -1,72 +1,83 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. - + import { execSync } from "child_process"; import * as crypto from "crypto"; import * as fs from "fs"; import * as path from "path"; import * as defaults from "./defaults"; - +import { uninstallExpiredCaCertificate } from './uninstall' + function getVerifyCommand(): string { switch (process.platform) { case "win32": const script = path.resolve(__dirname, "..\\scripts\\verify.ps1"); return `powershell -ExecutionPolicy Bypass -File "${script}" "${defaults.certificateName}"`; case "darwin": // macOS - return `security find-certificate -c '${defaults.certificateName}' -p | openssl x509 -checkend 86400 -noout`; + return `security find-certificate -c '${defaults.certificateName}' -p | openssl x509 -noout`; default: throw new Error(`Platform not supported: ${process.platform}`); } } - + export function isCaCertificateInstalled(): boolean { const command = getVerifyCommand(); - + try { const output = execSync(command, {stdio : "pipe" }).toString(); if (process.platform === "darwin") { - return true; + // Ceritificate exists. Now check and see if it's expired and remove it if is. + try { + const command = `security find-certificate -c '${defaults.certificateName}' -p | openssl x509 -checkend 86400 -noout`; + execSync(command, {stdio : "pipe" }).toString(); + return true; + } + catch { + uninstallExpiredCaCertificate() + return false; + } + } else if (output.length !== 0) { return true; // powershell command return empty string if the certificate not-found/expired } } catch (error) { - // Mac security command throws error if the certifcate is not-found/expired + // Mac security command throws error if the certifcate is not found } - + return false; } - + function validateCertificateAndKey(certificatePath: string, keyPath: string) { let certificate: string = ""; let key: string = ""; - + try { certificate = fs.readFileSync(certificatePath).toString(); } catch (err) { throw new Error(`Unable to read the certificate.\n${err}`); } - + try { key = fs.readFileSync(keyPath).toString(); } catch (err) { throw new Error(`Unable to read the certificate key.\n${err}`); } - + let encrypted; - + try { encrypted = crypto.publicEncrypt(certificate, Buffer.from("test")); } catch (err) { throw new Error(`The certificate is not valid.\n${err}`); } - + try { crypto.privateDecrypt(key, encrypted); } catch (err) { throw new Error(`The certificate key is not valid.\n${err}`); } } - + export function verifyCertificates(certificatePath: string = defaults.localhostCertificatePath, keyPath: string = defaults.localhostKeyPath): boolean { let isCertificateValid: boolean = true; try { @@ -75,4 +86,4 @@ export function verifyCertificates(certificatePath: string = defaults.localhostC isCertificateValid = false; } return isCertificateValid && isCaCertificateInstalled(); -} +} \ No newline at end of file diff --git a/packages/office-addin-dev-certs/test/test.ts b/packages/office-addin-dev-certs/test/test.ts index 40a0a39d7..5b8914971 100644 --- a/packages/office-addin-dev-certs/test/test.ts +++ b/packages/office-addin-dev-certs/test/test.ts @@ -249,7 +249,7 @@ describe("office-addin-dev-certs", function() { sandbox.stub(childProcess, "execSync").callsFake(execSync); try { const ret = await verify.isCaCertificateInstalled(); - assert.strictEqual(execSync.callCount, 1); + assert.strictEqual(execSync.callCount, (process.platform === "darwin") ? 2 : 1); assert.strictEqual(ret, true); } catch (err) { // not expecting any exception