Skip to content

Commit

Permalink
fix: correct certificate path and post-placement command for RHEL7
Browse files Browse the repository at this point in the history
  • Loading branch information
mike-north committed Feb 11, 2020
1 parent 8a76edd commit 40cca32
Show file tree
Hide file tree
Showing 4 changed files with 125 additions and 14 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
"@types/mkdirp": "^0.5.2",
"@types/node": "^8.5.7",
"@types/rimraf": "^2.0.2",
"@types/systeminformation": "^3.54.1",
"@types/tmp": "^0.0.33",
"@typescript-eslint/eslint-plugin": "^2.17.0",
"@typescript-eslint/parser": "^2.17.0",
Expand Down
5 changes: 5 additions & 0 deletions src/errors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export class UnreachableError extends Error {
constructor(nvr: never, message: string) {
super(`You have encountered a situation that was thought to be impossible\n${message}\nThis value should have been a "never": ${nvr}`)
}
}
121 changes: 107 additions & 14 deletions src/platforms/linux.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import * as path from "path";
import {
existsSync as exists,
readFileSync as read,
writeFileSync as writeFile
writeFileSync as writeFile,
existsSync
} from "fs";
import * as createDebug from "debug";
import { sync as commandExists } from "command-exists";
Expand All @@ -18,9 +19,77 @@ import { run } from "../utils";
import { Options } from "../index";
import UI from "../user-interface";
import { Platform } from ".";
import * as si from 'systeminformation';
import { UnreachableError } from "../errors";

const debug = createDebug("devcert:platforms:linux");

enum LinuxFlavor {
Unknown = 0,
Ubuntu,
Rhel7,
Fedora,
}

async function determineLinuxFlavor(distroPromise: Promise<string> = si.osInfo().then(info => info.distro)): Promise<{ flav: LinuxFlavor, message?: string }> {
const distro = await distroPromise;
switch (distro) {
case 'Red Hat Enterprise Linux Workstation':
return { flav: LinuxFlavor.Rhel7 };
case 'Ubuntu':
return { flav: LinuxFlavor.Ubuntu };
case 'Fedora':
return { flav: LinuxFlavor.Fedora };
default:
return { flav: LinuxFlavor.Unknown, message: `Unknown linux distro: ${distro}` };
}
}

interface Cmd {
command: string;
args: string[]
}

interface LinuxFlavorDetails {
caFolders: string[];
postCaPlacementCommands: Cmd[]
postCaRemovalCommands: Cmd[]
}

function linuxFlavorDetails(flavor: Exclude<LinuxFlavor, LinuxFlavor.Unknown>): LinuxFlavorDetails {
switch (flavor) {
case LinuxFlavor.Rhel7:
case LinuxFlavor.Fedora:
return {
caFolders: ['/etc/pki/ca-trust/source/anchors', '/usr/share/pki/ca-trust-source'],
postCaPlacementCommands: [{
command: 'sudo', args: ['update-ca-trust']
}],
postCaRemovalCommands: [{
command: 'sudo', args: ['update-ca-trust']
}]
};
case LinuxFlavor.Ubuntu:
return {
caFolders: ['/etc/pki/ca-trust/source/anchors', '/usr/local/share/ca-certificates'],
postCaPlacementCommands: [{
command: 'sudo', args: ['update-ca-certificates']
}],
postCaRemovalCommands: [{
command: 'sudo', args: ['update-ca-certificates']
}]
};

default:
throw new UnreachableError(flavor, 'Unable to detect linux flavor');
}
}
async function currentLinuxFlavorDetails(): Promise<LinuxFlavorDetails> {
const { flav: flavor, message } = await determineLinuxFlavor();
if (!flavor) throw new Error(message); // TODO better error
return linuxFlavorDetails(flavor);
}

export default class LinuxPlatform implements Platform {
private FIREFOX_NSS_DIR = path.join(HOME, ".mozilla/firefox/*");
private CHROME_NSS_DIR = path.join(HOME, ".pki/nssdb");
Expand All @@ -44,11 +113,17 @@ export default class LinuxPlatform implements Platform {
): Promise<void> {
debug("Adding devcert root CA to Linux system-wide trust stores");
// run(`sudo cp ${ certificatePath } /etc/ssl/certs/devcert.crt`);
run(
`sudo cp "${certificatePath}" /usr/local/share/ca-certificates/devcert.crt`
);
const linuxInfo = await currentLinuxFlavorDetails();
const { caFolders, postCaPlacementCommands } = linuxInfo;
caFolders.forEach(folder => {
run(
`sudo cp "${certificatePath}" ${path.join(folder, 'devcert.crt')}`
);
})
// run(`sudo bash -c "cat ${ certificatePath } >> /etc/ssl/certs/ca-certificates.crt"`);
run(`sudo update-ca-certificates`);
postCaPlacementCommands.forEach(({ command, args }) => {
run(`${command} ${args.join(' ')}`.trim());
})

if (this.isFirefoxInstalled()) {
// Firefox
Expand Down Expand Up @@ -104,15 +179,33 @@ export default class LinuxPlatform implements Platform {
}
}

removeFromTrustStores(certificatePath: string): void {
try {
run(`sudo rm /usr/local/share/ca-certificates/devcert.crt`);
run(`sudo update-ca-certificates`);
} catch (e) {
debug(
`failed to remove ${certificatePath} from /usr/local/share/ca-certificates, continuing. ${e.toString()}`
);
}
async removeFromTrustStores(certificatePath: string): Promise<void> {
const linuxInfo = await currentLinuxFlavorDetails();
const { caFolders, postCaRemovalCommands } = linuxInfo;
caFolders.forEach(folder => {
const certPath = path.join(folder, 'devcert.crt');
try {
const exists = existsSync(certPath);
debug({ exists })
if (!exists) {
debug(`cert at location ${certPath} was not found. Skipping...`)
return;
} else {
run(
`sudo rm "${certificatePath}" ${certPath}`
);
postCaRemovalCommands.forEach(({ command, args }) => {
run(`${command} ${args.join(' ')}`.trim());
})
}
} catch (e) {
debug(
`failed to remove ${certificatePath} from ${certPath}, continuing. ${e.toString()}`
);
}
})
// run(`sudo bash -c "cat ${ certificatePath } >> /etc/ssl/certs/ca-certificates.crt"`);

if (commandExists("certutil")) {
if (this.isFirefoxInstalled()) {
removeCertificateFromNSSCertDB(
Expand Down
12 changes: 12 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,13 @@
"@types/glob" "*"
"@types/node" "*"

"@types/systeminformation@^3.54.1":
version "3.54.1"
resolved "https://registry.yarnpkg.com/@types/systeminformation/-/systeminformation-3.54.1.tgz#bbc1b9e4ae2e60d45f75906029c6fb5436e1c5cb"
integrity sha512-vvisj2mdWygyc0jk/5XtSVq9gtxCmF3nrGwv8wVway8pwNRhtPji/MU9dc1L0F6rl0F/NFIHa4ScRU7wmNaHmg==
dependencies:
systeminformation "*"

"@types/tmp@^0.0.33":
version "0.0.33"
resolved "https://registry.yarnpkg.com/@types/tmp/-/tmp-0.0.33.tgz#1073c4bc824754ae3d10cfab88ab0237ba964e4d"
Expand Down Expand Up @@ -2169,6 +2176,11 @@ supports-color@^5.3.0:
dependencies:
has-flag "^3.0.0"

systeminformation@*:
version "4.21.2"
resolved "https://registry.yarnpkg.com/systeminformation/-/systeminformation-4.21.2.tgz#0ee92c0565687a5301ba141444643b43d0370ae2"
integrity sha512-7O6laxHTstfj9MSrX77lKLfWz0zqqutWL0+uoJkR7sOOr4XCTwD0QG4shUVCiOWlVX+a8/gHJUio420FrSk8/w==

table@^5.2.3:
version "5.4.6"
resolved "https://registry.yarnpkg.com/table/-/table-5.4.6.tgz#1292d19500ce3f86053b05f0e8e7e4a3bb21079e"
Expand Down

0 comments on commit 40cca32

Please sign in to comment.