Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Make injecting CAs injectable, remove mac-ca as dependency
Signed-off-by: Sebastian Malton <sebastian@malton.name>
- Loading branch information
Showing
15 changed files
with
249 additions
and
233 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
9 changes: 9 additions & 0 deletions
9
...mmon/certificate-authorities/inject-system-cas-on-macos.global-override-for-injectable.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
/** | ||
* Copyright (c) OpenLens Authors. All rights reserved. | ||
* Licensed under MIT License. See LICENSE in root directory for more information. | ||
*/ | ||
|
||
import { getGlobalOverride } from "../test-utils/get-global-override"; | ||
import injectSystemCAsOnMacOSInjectable from "./inject-system-cas-on-macos.injectable"; | ||
|
||
export default getGlobalOverride(injectSystemCAsOnMacOSInjectable, () => async () => {}); |
62 changes: 62 additions & 0 deletions
62
src/common/certificate-authorities/inject-system-cas-on-macos.injectable.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
/** | ||
* Copyright (c) OpenLens Authors. All rights reserved. | ||
* Licensed under MIT License. See LICENSE in root directory for more information. | ||
*/ | ||
import { getInjectable } from "@ogre-tools/injectable"; | ||
import { globalAgent } from "https"; | ||
import execFileInjectable from "../fs/exec-file.injectable"; | ||
import loggerInjectable from "../logger.injectable"; | ||
import { isCertActive } from "./is-cert-active"; | ||
import isMacInjectable from "../vars/is-mac.injectable"; | ||
import { systemCAsInjectorInjectionToken } from "./system-cas-injector-token"; | ||
|
||
function injectCAs(CAs: string[]) { | ||
for (const cert of CAs) { | ||
if (Array.isArray(globalAgent.options.ca) && !globalAgent.options.ca.includes(cert)) { | ||
globalAgent.options.ca.push(cert); | ||
} else { | ||
globalAgent.options.ca = [cert]; | ||
} | ||
} | ||
} | ||
|
||
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions/Cheatsheet#other_assertions | ||
const certSplitPattern = /(?=-----BEGIN\sCERTIFICATE-----)/g; | ||
|
||
const injectSystemCAsOnMacOSInjectable = getInjectable({ | ||
id: "inject-system-cas-on-macOS", | ||
instantiate: (di) => { | ||
const execFile = di.inject(execFileInjectable); | ||
const logger = di.inject(loggerInjectable); | ||
const isMac = di.inject(isMacInjectable); | ||
|
||
const execSecurity = async (...args: string[]) => { | ||
const output = await execFile("/usr/bin/security", args); | ||
|
||
return output.split(certSplitPattern); | ||
}; | ||
|
||
if (!isMac) { | ||
return async () => {}; | ||
} | ||
|
||
return async () => { | ||
try { | ||
const [trusted, rootCA] = await Promise.all([ | ||
execSecurity("find-certificate", "-a", "-p"), | ||
execSecurity("find-certificate", "-a", "-p", "/System/Library/Keychains/SystemRootCertificates.keychain"), | ||
]); | ||
|
||
const certs = [...new Set([...trusted, ...rootCA])].filter(isCertActive); | ||
|
||
injectCAs(certs); | ||
} catch (error) { | ||
logger.warn(`[INJECT-CAS]: Error injecting root CAs from MacOSX: ${error}`); | ||
} | ||
}; | ||
}, | ||
causesSideEffects: true, | ||
injectionToken: systemCAsInjectorInjectionToken, | ||
}); | ||
|
||
export default injectSystemCAsOnMacOSInjectable; |
9 changes: 9 additions & 0 deletions
9
...on/certificate-authorities/inject-system-cas-on-windows.global-override-for-injectable.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
/** | ||
* Copyright (c) OpenLens Authors. All rights reserved. | ||
* Licensed under MIT License. See LICENSE in root directory for more information. | ||
*/ | ||
|
||
import { getGlobalOverride } from "../test-utils/get-global-override"; | ||
import injectSystemCAsOnWindowsInjectable from "./inject-system-cas-on-windows.injectable"; | ||
|
||
export default getGlobalOverride(injectSystemCAsOnWindowsInjectable, () => async () => {}); |
53 changes: 53 additions & 0 deletions
53
src/common/certificate-authorities/inject-system-cas-on-windows.injectable.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
/** | ||
* Copyright (c) OpenLens Authors. All rights reserved. | ||
* Licensed under MIT License. See LICENSE in root directory for more information. | ||
*/ | ||
import { getInjectable } from "@ogre-tools/injectable"; | ||
import wincaAPI from "win-ca/api"; | ||
import loggerInjectable from "../logger.injectable"; | ||
import { isCertActive } from "./is-cert-active"; | ||
import isWindowsInjectable from "../vars/is-windows.injectable"; | ||
import { systemCAsInjectorInjectionToken } from "./system-cas-injector-token"; | ||
|
||
function getWinRootCA(): Promise<string[]> { | ||
return new Promise((resolve) => { | ||
const CAs: string[] = []; | ||
|
||
wincaAPI({ | ||
format: wincaAPI.der2.pem, | ||
inject: false, | ||
ondata: (ca: string) => { | ||
CAs.push(ca); | ||
}, | ||
onend: () => { | ||
resolve(CAs.filter(isCertActive)); | ||
}, | ||
}); | ||
}); | ||
} | ||
|
||
const injectSystemCAsOnWindowsInjectable = getInjectable({ | ||
id: "inject-system-cas-on-windows", | ||
instantiate: (di) => { | ||
const logger = di.inject(loggerInjectable); | ||
const isWindows = di.inject(isWindowsInjectable); | ||
|
||
if (!isWindows) { | ||
return async () => {}; | ||
} | ||
|
||
return async () => { | ||
try { | ||
const winRootCAs = await getWinRootCA(); | ||
|
||
wincaAPI.inject("+", winRootCAs); | ||
} catch (error) { | ||
logger.warn(`[INJECT-CAS]: Error injecting root CAs from Windows: ${error}`); | ||
} | ||
}; | ||
}, | ||
causesSideEffects: true, | ||
injectionToken: systemCAsInjectorInjectionToken, | ||
}); | ||
|
||
export default injectSystemCAsOnWindowsInjectable; |
23 changes: 23 additions & 0 deletions
23
src/common/certificate-authorities/inject-system-cas.injectable.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
/** | ||
* Copyright (c) OpenLens Authors. All rights reserved. | ||
* Licensed under MIT License. See LICENSE in root directory for more information. | ||
*/ | ||
|
||
import { getInjectable } from "@ogre-tools/injectable"; | ||
import { systemCAsInjectorInjectionToken } from "./system-cas-injector-token"; | ||
|
||
const injectSystemCAsInjectable = getInjectable({ | ||
id: "inject-system-cas", | ||
instantiate: (di) => { | ||
const systemCAsInjectors = di.injectMany(systemCAsInjectorInjectionToken); | ||
|
||
return async () => { | ||
for (const systemCAsInjector of systemCAsInjectors) { | ||
await systemCAsInjector(); | ||
} | ||
}; | ||
}, | ||
}); | ||
|
||
export default injectSystemCAsInjectable; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
/** | ||
* Copyright (c) OpenLens Authors. All rights reserved. | ||
* Licensed under MIT License. See LICENSE in root directory for more information. | ||
*/ | ||
|
||
|
||
// DST Root CA X3, which was expired on 9.30.2021 | ||
export const DSTRootCAX3 = "-----BEGIN CERTIFICATE-----\nMIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/\nMSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT\nDkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow\nPzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD\nEw5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB\nAN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O\nrz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq\nOLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b\nxiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw\n7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD\naeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV\nHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG\nSIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69\nikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr\nAvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz\nR8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5\nJDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo\nOb8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ\n-----END CERTIFICATE-----\n"; | ||
|
||
export function isCertActive(cert: string) { | ||
const isExpired = typeof cert !== "string" || cert.includes(DSTRootCAX3); | ||
|
||
return !isExpired; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
/** | ||
* Copyright (c) OpenLens Authors. All rights reserved. | ||
* Licensed under MIT License. See LICENSE in root directory for more information. | ||
*/ | ||
import https from "https"; | ||
import { DSTRootCAX3 } from "./is-cert-active"; | ||
import assert from "assert"; | ||
import { describeIf } from "../../test-utils/skippers"; | ||
import { platform } from "process"; | ||
import { getDiForUnitTesting } from "../../main/getDiForUnitTesting"; | ||
import injectSystemCAsOnMacOSInjectable from "./inject-system-cas-on-macos.injectable"; | ||
import injectSystemCAsOnWindowsInjectable from "./inject-system-cas-on-windows.injectable"; | ||
|
||
describe("CA tests", () => { | ||
let injectSystemCAsOnMacOS: () => Promise<void>; | ||
let injectSystemCAsOnWindows: () => Promise<void>; | ||
|
||
beforeEach(() => { | ||
const di = getDiForUnitTesting(); | ||
|
||
di.unoverride(injectSystemCAsOnMacOSInjectable); | ||
di.permitSideEffects(injectSystemCAsOnMacOSInjectable); | ||
|
||
injectSystemCAsOnMacOS = di.inject(injectSystemCAsOnMacOSInjectable); | ||
|
||
di.unoverride(injectSystemCAsOnWindowsInjectable); | ||
di.permitSideEffects(injectSystemCAsOnWindowsInjectable); | ||
|
||
injectSystemCAsOnWindows = di.inject(injectSystemCAsOnWindowsInjectable); | ||
}); | ||
|
||
// for reset https.globalAgent.options.ca after testing | ||
let _ca: string | Buffer | (string | Buffer)[] | undefined; | ||
|
||
beforeEach(() => { | ||
_ca = https.globalAgent.options.ca; | ||
}); | ||
|
||
afterEach(() => { | ||
https.globalAgent.options.ca = _ca; | ||
}); | ||
|
||
describeIf(platform === "darwin")("on macos", () => { | ||
it("shouldn't included the expired DST Root CA X3 on Mac", async () => { | ||
await injectSystemCAsOnMacOS(); | ||
|
||
const injected = https.globalAgent.options.ca; | ||
|
||
assert(injected); | ||
expect(injected.includes(DSTRootCAX3)).toBeFalsy(); | ||
}); | ||
}); | ||
|
||
describeIf(platform === "win32")("on windows", () => { | ||
it("shouldn't included the expired DST Root CA X3 on Windows", async () => { | ||
await injectSystemCAsOnWindows(); | ||
|
||
const injected = https.globalAgent.options.ca as (string | Buffer)[]; | ||
|
||
expect(injected.includes(DSTRootCAX3)).toBeFalsy(); | ||
}); | ||
}); | ||
}); |
10 changes: 10 additions & 0 deletions
10
src/common/certificate-authorities/system-cas-injector-token.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
/** | ||
* Copyright (c) OpenLens Authors. All rights reserved. | ||
* Licensed under MIT License. See LICENSE in root directory for more information. | ||
*/ | ||
|
||
import { getInjectionToken } from "@ogre-tools/injectable"; | ||
|
||
export const systemCAsInjectorInjectionToken = getInjectionToken<() => Promise<void>>({ | ||
id: "system-cas-injector-token", | ||
}); |
Oops, something went wrong.