mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Refactor electron window setCertificateVerifyProc (#7185)
* refactor electron window setCertificateVerifyProc Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com> * use ChromiumNetError enum in tests Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com> * Fix unit tests Signed-off-by: Sebastian Malton <sebastian@malton.name> --------- Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com> Signed-off-by: Sebastian Malton <sebastian@malton.name> Co-authored-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
parent
4f2ba5df48
commit
ba4a283af9
@ -0,0 +1,78 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import type { DiContainer } from "@ogre-tools/injectable";
|
||||
import setupLensProxyCertificateInjectable from "../../../../start-main-application/runnables/setup-lens-proxy-certificate.injectable";
|
||||
import lensProxyCertificateInjectable from "../../../../../common/certificate/lens-proxy-certificate.injectable";
|
||||
import { getDiForUnitTesting } from "../../../../getDiForUnitTesting";
|
||||
import sessionCertificateVerifierInjectable, { ChromiumNetError } from "../session-certificate-verifier.injectable";
|
||||
|
||||
const externalCertificate = `-----BEGIN CERTIFICATE-----
|
||||
MIIFzzCCBLegAwIBAgIQByL1wEn7yGRLqHZvmBzvpTANBgkqhkiG9w0BAQsFADA8
|
||||
MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRwwGgYDVQQDExNBbWF6b24g
|
||||
UlNBIDIwNDggTTAyMB4XDTIzMDIwOTAwMDAwMFoXDTIzMTAxNDIzNTk1OVowFjEU
|
||||
MBIGA1UEAxMLazhzbGVucy5kZXYwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
|
||||
AoIBAQDNdPm5tKztUpgHgDHjktelNvRsaj4QHTzShUP5p2uGu+lNHhPByp3+fp8p
|
||||
v6V4PhRyH006RcyvUkQlEOiprP0fF/L16Jlrlo13N7hspVS4drlxE0v4JcLxBKm8
|
||||
pwsv7bfeZ7g6SWKA/0wbSTk8AyL0rCgcpMUWyPloq3gInO1x7kazgCAgrB34CSdj
|
||||
JyD1Y8Od8eH8C9qdRlTcV0rG8y2np8YbK1lF77CXjD2feGjiUAMUAtArGKCZOc33
|
||||
erdhvXgJQ1/SgWcEbbhEZ7j8cfH6y7hPPmU43epyePvY0SZ7x1PBt870W1LjG6lq
|
||||
pfzqxVVxmT6Txiktnd/6cHCzfxjbAgMBAAGjggLxMIIC7TAfBgNVHSMEGDAWgBTA
|
||||
MVLNWlDDgnx0cc7L6Zz5euuC4jAdBgNVHQ4EFgQUcC3Qdy61LUiE9hOvDJGYC/yt
|
||||
fu0wJQYDVR0RBB4wHIILazhzbGVucy5kZXaCDSouazhzbGVucy5kZXYwDgYDVR0P
|
||||
AQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjA7BgNVHR8E
|
||||
NDAyMDCgLqAshipodHRwOi8vY3JsLnIybTAyLmFtYXpvbnRydXN0LmNvbS9yMm0w
|
||||
Mi5jcmwwEwYDVR0gBAwwCjAIBgZngQwBAgEwdQYIKwYBBQUHAQEEaTBnMC0GCCsG
|
||||
AQUFBzABhiFodHRwOi8vb2NzcC5yMm0wMi5hbWF6b250cnVzdC5jb20wNgYIKwYB
|
||||
BQUHMAKGKmh0dHA6Ly9jcnQucjJtMDIuYW1hem9udHJ1c3QuY29tL3IybTAyLmNl
|
||||
cjAMBgNVHRMBAf8EAjAAMIIBfAYKKwYBBAHWeQIEAgSCAWwEggFoAWYAdQDoPtDa
|
||||
PvUGNTLnVyi8iWvJA9PL0RFr7Otp4Xd9bQa9bgAAAYY4etOIAAAEAwBGMEQCIGT/
|
||||
/BWgTcOFQdzEX2qKlArMTvMwXggEY+m4ervIFLFnAiAyuX0I9jbGBI1XBiQ2mjXT
|
||||
FIGw3TMF5b4rrCwhkRBG/gB1ALNzdwfhhFD4Y4bWBancEQlKeS2xZwwLh9zwAw55
|
||||
NqWaAAABhjh6084AAAQDAEYwRAIgewezL8S3+qwozF4fNt+0FiV95luazD1yKb35
|
||||
ZeOqudACIC7eFoZsaySOOivbqIp+nr9PB3qD08C1VKoi/LmnDp+3AHYAtz77JN+c
|
||||
Tbp18jnFulj0bF38Qs96nzXEnh0JgSXttJkAAAGGOHrTlgAABAMARzBFAiAmZyNU
|
||||
1H54FbGdwwXVXPxNYVE3MUlHswkR56WvWkvJ0wIhAJELvOBDIsCJ5uxTam2Xaxe0
|
||||
nZ+YTVzXDoQAfHplV1N6MA0GCSqGSIb3DQEBCwUAA4IBAQAghl2vkfW4Gph6Ez/v
|
||||
EA/INeDXSErm/o3zBv4uTS7kuINPAtTlDtVJW/usw++F5fmgjmyNVc94y35hFG9Q
|
||||
8LTDgJWvxekmiJJ+FCAxbpkhqXjHhugXwoUvAKktpyFnw+1cliYeA01EevOhnN+n
|
||||
ux6vjEyhhEZm/JV/TXWaNSmVprXRXwc1m5dQzEEqkXgIhhhSK7E/63L+Zm548cjp
|
||||
LAp+pJnaHfg0a83QnPWyZeyob+GklQjEdx64i+7wAhhpUp1Ge2TnFfs6zQGv2Y7/
|
||||
mgyzhHkKlUwQb5pi0rgR4oqKhnItyXjWqN3Y3wefTJblIs2sxEtYEzBUwlQZ3YM/
|
||||
ycM4
|
||||
-----END CERTIFICATE-----`;
|
||||
|
||||
describe("sessionCertificateVerifier", () => {
|
||||
let di: DiContainer;
|
||||
|
||||
beforeEach(() => {
|
||||
di = getDiForUnitTesting();
|
||||
di.unoverride(lensProxyCertificateInjectable);
|
||||
di.inject(setupLensProxyCertificateInjectable).run();
|
||||
});
|
||||
|
||||
it("marks lens proxy certificate as trusted", () => {
|
||||
const sessionCertificateVerifier = di.inject(sessionCertificateVerifierInjectable);
|
||||
const lensProxyCertificate = di.inject(lensProxyCertificateInjectable).get();
|
||||
const callback = jest.fn();
|
||||
|
||||
sessionCertificateVerifier({
|
||||
certificate: { data: lensProxyCertificate.cert },
|
||||
} as any, callback);
|
||||
|
||||
expect(callback).toHaveBeenCalledWith(ChromiumNetError.SUCCESS);
|
||||
});
|
||||
|
||||
it("passes verification to chromium on non lens proxy certificate", () => {
|
||||
const sessionCertificateVerifier = di.inject(sessionCertificateVerifierInjectable);
|
||||
const callback = jest.fn();
|
||||
|
||||
sessionCertificateVerifier({
|
||||
certificate: { data: externalCertificate },
|
||||
} as any, callback);
|
||||
|
||||
expect(callback).toHaveBeenCalledWith(ChromiumNetError.RESULT_FROM_CHROMIUM);
|
||||
});
|
||||
});
|
||||
@ -3,7 +3,6 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { timingSafeEqual, X509Certificate } from "crypto";
|
||||
import loggerInjectable from "../../../../common/logger.injectable";
|
||||
import applicationWindowStateInjectable from "./application-window-state.injectable";
|
||||
import { BrowserWindow } from "electron";
|
||||
@ -14,8 +13,8 @@ import getAbsolutePathInjectable from "../../../../common/path/get-absolute-path
|
||||
import lensResourcesDirInjectable from "../../../../common/vars/lens-resources-dir.injectable";
|
||||
import isLinuxInjectable from "../../../../common/vars/is-linux.injectable";
|
||||
import pathExistsSyncInjectable from "../../../../common/fs/path-exists-sync.injectable";
|
||||
import lensProxyCertificateInjectable from "../../../../common/certificate/lens-proxy-certificate.injectable";
|
||||
import { applicationInformationToken } from "@k8slens/application";
|
||||
import sessionCertificateVerifierInjectable from "./session-certificate-verifier.injectable";
|
||||
|
||||
export type ElectronWindowTitleBarStyle = "hiddenInset" | "hidden" | "default" | "customButtonsOnHover";
|
||||
|
||||
@ -27,13 +26,6 @@ export interface UrlSource {
|
||||
}
|
||||
export type ContentSource = RequireExactlyOne<FileSource & UrlSource>;
|
||||
|
||||
// see https://www.electronjs.org/docs/latest/api/session#sessetcertificateverifyprocproc
|
||||
enum ChromiumNetError {
|
||||
SUCCESS = 0,
|
||||
FAILURE = -2,
|
||||
RESULT_FROM_CHROMIUM = -3,
|
||||
}
|
||||
|
||||
export interface ElectronWindowConfiguration {
|
||||
id: string;
|
||||
title: string;
|
||||
@ -64,8 +56,7 @@ const createElectronWindowInjectable = getInjectable({
|
||||
const isLinux = di.inject(isLinuxInjectable);
|
||||
const applicationInformation = di.inject(applicationInformationToken);
|
||||
const pathExistsSync = di.inject(pathExistsSyncInjectable);
|
||||
const lensProxyCertificate = di.inject(lensProxyCertificateInjectable).get();
|
||||
const lensProxyX509Cert = new X509Certificate(lensProxyCertificate.cert);
|
||||
const sessionCertificateVerifier = di.inject(sessionCertificateVerifierInjectable);
|
||||
|
||||
return (configuration) => {
|
||||
const applicationWindowState = di.inject(
|
||||
@ -119,14 +110,7 @@ const createElectronWindowInjectable = getInjectable({
|
||||
|
||||
applicationWindowState.manage(browserWindow);
|
||||
|
||||
browserWindow.webContents.session.setCertificateVerifyProc((request, shouldBeTrusted) => {
|
||||
const { certificate } = request;
|
||||
const cert = new X509Certificate(certificate.data);
|
||||
const shouldTrustCert = cert.raw.length === lensProxyX509Cert.raw.length
|
||||
&& timingSafeEqual(cert.raw, lensProxyX509Cert.raw);
|
||||
|
||||
shouldBeTrusted(shouldTrustCert ? ChromiumNetError.SUCCESS : ChromiumNetError.RESULT_FROM_CHROMIUM);
|
||||
});
|
||||
browserWindow.webContents.session.setCertificateVerifyProc(sessionCertificateVerifier);
|
||||
|
||||
browserWindow
|
||||
.on("focus", () => {
|
||||
|
||||
@ -0,0 +1,36 @@
|
||||
/**
|
||||
* 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 { timingSafeEqual, X509Certificate } from "crypto";
|
||||
import type { Request } from "electron";
|
||||
import lensProxyCertificateInjectable from "../../../../common/certificate/lens-proxy-certificate.injectable";
|
||||
|
||||
// see https://www.electronjs.org/docs/latest/api/session#sessetcertificateverifyprocproc
|
||||
export enum ChromiumNetError {
|
||||
SUCCESS = 0,
|
||||
FAILURE = -2,
|
||||
RESULT_FROM_CHROMIUM = -3,
|
||||
}
|
||||
|
||||
export type CertificateVerificationCallback = (error: ChromiumNetError) => void;
|
||||
|
||||
const sessionCertificateVerifierInjectable = getInjectable({
|
||||
id: "session-certificate-verifier",
|
||||
instantiate: (di) => {
|
||||
const lensProxyCertificate = di.inject(lensProxyCertificateInjectable).get();
|
||||
const lensProxyX509Cert = new X509Certificate(lensProxyCertificate.cert);
|
||||
|
||||
return (request: Request, shouldBeTrusted: CertificateVerificationCallback) => {
|
||||
const { certificate } = request;
|
||||
const cert = new X509Certificate(certificate.data);
|
||||
const shouldTrustCert = cert.raw.length === lensProxyX509Cert.raw.length
|
||||
&& timingSafeEqual(cert.raw, lensProxyX509Cert.raw);
|
||||
|
||||
shouldBeTrusted(shouldTrustCert ? ChromiumNetError.SUCCESS : ChromiumNetError.RESULT_FROM_CHROMIUM);
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
export default sessionCertificateVerifierInjectable;
|
||||
Loading…
Reference in New Issue
Block a user