mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Add TLS support
Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
parent
7708e662e1
commit
7df0f098f1
@ -26,7 +26,7 @@ async function getMainWindow(app: ElectronApplication, timeout = 50_000): Promis
|
||||
const onWindow = (page: Page) => {
|
||||
console.log(`Page opened: ${page.url()}`);
|
||||
|
||||
if (page.url().startsWith("http://localhost")) {
|
||||
if (page.url().startsWith("https://localhost")) {
|
||||
cleanup();
|
||||
console.log(stdoutBuf);
|
||||
resolve(page);
|
||||
|
||||
@ -57,7 +57,7 @@
|
||||
"bundledKubectlVersion": "1.23.3",
|
||||
"bundledHelmVersion": "3.7.2",
|
||||
"sentryDsn": "",
|
||||
"contentSecurityPolicy": "script-src 'unsafe-eval' 'self'; frame-src http://*.localhost:*/; img-src * data:",
|
||||
"contentSecurityPolicy": "script-src 'unsafe-eval' 'self'; img-src * data:",
|
||||
"welcomeRoute": "/welcome"
|
||||
},
|
||||
"engines": {
|
||||
|
||||
9
src/common/certificate/channel.ts
Normal file
9
src/common/certificate/channel.ts
Normal file
@ -0,0 +1,9 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import type { SelfSignedCert } from "selfsigned";
|
||||
import { getRequestChannel } from "../utils/channel/request-channel-listener-injection-token";
|
||||
|
||||
export const lensProxyCertificateChannel = getRequestChannel<void, SelfSignedCert>("request-lens-proxy-certificate");
|
||||
11
src/common/certificate/token.ts
Normal file
11
src/common/certificate/token.ts
Normal file
@ -0,0 +1,11 @@
|
||||
/**
|
||||
* 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";
|
||||
import type { SelfSignedCert } from "selfsigned";
|
||||
|
||||
export const lensProxyCertificateInjectionToken = getInjectionToken<SelfSignedCert>({
|
||||
id: "lens-proxy-certificate-token",
|
||||
});
|
||||
@ -3,20 +3,27 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { Agent } from "https";
|
||||
import type { RequestInit, Response } from "node-fetch";
|
||||
import { lensAuthenticationHeaderValueInjectionToken } from "../auth/header-value";
|
||||
import { lensProxyCertificateInjectionToken } from "../certificate/token";
|
||||
import { lensAuthenticationHeader } from "../vars/auth-header";
|
||||
import fetchModuleInjectable from "./fetch-module.injectable";
|
||||
import type { Fetch } from "./fetch.injectable";
|
||||
import fetchInjectable from "./fetch.injectable";
|
||||
|
||||
export type AuthenticatedRequestInit = Omit<RequestInit, "agent">;
|
||||
|
||||
export type AuthenticatedFetch = (url: string, options?: AuthenticatedRequestInit) => Promise<Response>;
|
||||
|
||||
/**
|
||||
* This injectable should not be used to request data from external sources as it would leak the
|
||||
* authentication header value
|
||||
*/
|
||||
const lensAuthenticatedFetchInjectable = getInjectable({
|
||||
id: "lens-authenticated-fetch",
|
||||
instantiate: (di): Fetch => {
|
||||
instantiate: (di): AuthenticatedFetch => {
|
||||
const authHeaderValue = di.inject(lensAuthenticationHeaderValueInjectionToken);
|
||||
const lensProxyCertificate = di.inject(lensProxyCertificateInjectionToken);
|
||||
const fetch = di.inject(fetchInjectable);
|
||||
const { Headers } = di.inject(fetchModuleInjectable);
|
||||
|
||||
@ -26,12 +33,16 @@ const lensAuthenticatedFetchInjectable = getInjectable({
|
||||
...rest
|
||||
} = init ?? {};
|
||||
const headers = new Headers(headersInit);
|
||||
const agent = new Agent({
|
||||
ca: lensProxyCertificate.cert,
|
||||
});
|
||||
|
||||
headers.set(lensAuthenticationHeader, authHeaderValue);
|
||||
|
||||
return fetch(url, {
|
||||
headers,
|
||||
...rest,
|
||||
agent,
|
||||
});
|
||||
};
|
||||
},
|
||||
|
||||
@ -49,7 +49,7 @@ describe("KubeApi", () => {
|
||||
const createKubeJsonApi = di.inject(createKubeJsonApiInjectable);
|
||||
|
||||
request = createKubeJsonApi({
|
||||
serverAddress: `http://127.0.0.1:9999`,
|
||||
serverAddress: `https://127.0.0.1:9999`,
|
||||
apiBase: "/api-kube",
|
||||
});
|
||||
registerApiSpy = jest.spyOn(di.inject(apiManagerInjectable), "registerApi");
|
||||
@ -82,7 +82,7 @@ describe("KubeApi", () => {
|
||||
|
||||
it("requests version list from the api group from the initial apiBase", () => {
|
||||
expect(fetchMock.mock.lastCall).toMatchObject([
|
||||
"http://127.0.0.1:9999/api-kube/apis/networking.k8s.io",
|
||||
"https://127.0.0.1:9999/api-kube/apis/networking.k8s.io",
|
||||
{
|
||||
headers: {
|
||||
"content-type": "application/json",
|
||||
@ -95,8 +95,8 @@ describe("KubeApi", () => {
|
||||
describe("when the version list from the api group resolves", () => {
|
||||
beforeEach(async () => {
|
||||
await fetchMock.resolveSpecific(
|
||||
["http://127.0.0.1:9999/api-kube/apis/networking.k8s.io"],
|
||||
createMockResponseFromString("http://127.0.0.1:9999/api-kube/apis/networking.k8s.io", JSON.stringify({
|
||||
["https://127.0.0.1:9999/api-kube/apis/networking.k8s.io"],
|
||||
createMockResponseFromString("https://127.0.0.1:9999/api-kube/apis/networking.k8s.io", JSON.stringify({
|
||||
apiVersion: "v1",
|
||||
kind: "APIGroup",
|
||||
name: "networking.k8s.io",
|
||||
@ -120,7 +120,7 @@ describe("KubeApi", () => {
|
||||
|
||||
it("requests resources from the versioned api group from the initial apiBase", () => {
|
||||
expect(fetchMock.mock.lastCall).toMatchObject([
|
||||
"http://127.0.0.1:9999/api-kube/apis/networking.k8s.io/v1",
|
||||
"https://127.0.0.1:9999/api-kube/apis/networking.k8s.io/v1",
|
||||
{
|
||||
headers: {
|
||||
"content-type": "application/json",
|
||||
@ -133,8 +133,8 @@ describe("KubeApi", () => {
|
||||
describe("when resource request fufills with a resource", () => {
|
||||
beforeEach(async () => {
|
||||
await fetchMock.resolveSpecific(
|
||||
["http://127.0.0.1:9999/api-kube/apis/networking.k8s.io/v1"],
|
||||
createMockResponseFromString("http://127.0.0.1:9999/api-kube/apis/networking.k8s.io/v1", JSON.stringify({
|
||||
["https://127.0.0.1:9999/api-kube/apis/networking.k8s.io/v1"],
|
||||
createMockResponseFromString("https://127.0.0.1:9999/api-kube/apis/networking.k8s.io/v1", JSON.stringify({
|
||||
resources: [{
|
||||
name: "ingresses",
|
||||
}],
|
||||
@ -144,7 +144,7 @@ describe("KubeApi", () => {
|
||||
|
||||
it("makes the request to get the resource", () => {
|
||||
expect(fetchMock.mock.lastCall).toMatchObject([
|
||||
"http://127.0.0.1:9999/api-kube/apis/networking.k8s.io/v1/namespaces/default/ingresses/foo",
|
||||
"https://127.0.0.1:9999/api-kube/apis/networking.k8s.io/v1/namespaces/default/ingresses/foo",
|
||||
{
|
||||
headers: {
|
||||
"content-type": "application/json",
|
||||
@ -171,8 +171,8 @@ describe("KubeApi", () => {
|
||||
|
||||
beforeEach(async () => {
|
||||
await fetchMock.resolveSpecific(
|
||||
["http://127.0.0.1:9999/api-kube/apis/networking.k8s.io/v1/namespaces/default/ingresses/foo"],
|
||||
createMockResponseFromString("http://127.0.0.1:9999/api-kube/apis/networking.k8s.io/v1/namespaces/default/ingresses/foo", JSON.stringify({})),
|
||||
["https://127.0.0.1:9999/api-kube/apis/networking.k8s.io/v1/namespaces/default/ingresses/foo"],
|
||||
createMockResponseFromString("https://127.0.0.1:9999/api-kube/apis/networking.k8s.io/v1/namespaces/default/ingresses/foo", JSON.stringify({})),
|
||||
);
|
||||
result = await getCall;
|
||||
});
|
||||
@ -196,7 +196,7 @@ describe("KubeApi", () => {
|
||||
|
||||
it("makes the request to get the resource", () => {
|
||||
expect(fetchMock.mock.lastCall).toMatchObject([
|
||||
"http://127.0.0.1:9999/api-kube/apis/networking.k8s.io/v1/namespaces/default/ingresses/foo1",
|
||||
"https://127.0.0.1:9999/api-kube/apis/networking.k8s.io/v1/namespaces/default/ingresses/foo1",
|
||||
{
|
||||
headers: {
|
||||
"content-type": "application/json",
|
||||
@ -211,8 +211,8 @@ describe("KubeApi", () => {
|
||||
|
||||
beforeEach(async () => {
|
||||
await fetchMock.resolveSpecific(
|
||||
["http://127.0.0.1:9999/api-kube/apis/networking.k8s.io/v1/namespaces/default/ingresses/foo1"],
|
||||
createMockResponseFromString("http://127.0.0.1:9999/api-kube/apis/networking.k8s.io/v1/namespaces/default/ingresses/foo1", JSON.stringify({})),
|
||||
["https://127.0.0.1:9999/api-kube/apis/networking.k8s.io/v1/namespaces/default/ingresses/foo1"],
|
||||
createMockResponseFromString("https://127.0.0.1:9999/api-kube/apis/networking.k8s.io/v1/namespaces/default/ingresses/foo1", JSON.stringify({})),
|
||||
);
|
||||
result = await getCall;
|
||||
});
|
||||
@ -229,8 +229,8 @@ describe("KubeApi", () => {
|
||||
|
||||
beforeEach(async () => {
|
||||
await fetchMock.resolveSpecific(
|
||||
["http://127.0.0.1:9999/api-kube/apis/networking.k8s.io/v1/namespaces/default/ingresses/foo"],
|
||||
createMockResponseFromString("http://127.0.0.1:9999/api-kube/apis/networking.k8s.io/v1/namespaces/default/ingresses/foo", JSON.stringify({
|
||||
["https://127.0.0.1:9999/api-kube/apis/networking.k8s.io/v1/namespaces/default/ingresses/foo"],
|
||||
createMockResponseFromString("https://127.0.0.1:9999/api-kube/apis/networking.k8s.io/v1/namespaces/default/ingresses/foo", JSON.stringify({
|
||||
apiVersion: "v1",
|
||||
kind: "Ingress",
|
||||
metadata: {
|
||||
@ -263,7 +263,7 @@ describe("KubeApi", () => {
|
||||
|
||||
it("makes the request to get the resource", () => {
|
||||
expect(fetchMock.mock.lastCall).toMatchObject([
|
||||
"http://127.0.0.1:9999/api-kube/apis/networking.k8s.io/v1/namespaces/default/ingresses/foo1",
|
||||
"https://127.0.0.1:9999/api-kube/apis/networking.k8s.io/v1/namespaces/default/ingresses/foo1",
|
||||
{
|
||||
headers: {
|
||||
"content-type": "application/json",
|
||||
@ -278,8 +278,8 @@ describe("KubeApi", () => {
|
||||
|
||||
beforeEach(async () => {
|
||||
await fetchMock.resolveSpecific(
|
||||
["http://127.0.0.1:9999/api-kube/apis/networking.k8s.io/v1/namespaces/default/ingresses/foo1"],
|
||||
createMockResponseFromString("http://127.0.0.1:9999/api-kube/apis/networking.k8s.io/v1/namespaces/default/ingresses/foo1", JSON.stringify({})),
|
||||
["https://127.0.0.1:9999/api-kube/apis/networking.k8s.io/v1/namespaces/default/ingresses/foo1"],
|
||||
createMockResponseFromString("https://127.0.0.1:9999/api-kube/apis/networking.k8s.io/v1/namespaces/default/ingresses/foo1", JSON.stringify({})),
|
||||
);
|
||||
result = await getCall;
|
||||
});
|
||||
@ -295,8 +295,8 @@ describe("KubeApi", () => {
|
||||
describe("when resource request fufills with no resource", () => {
|
||||
beforeEach(async () => {
|
||||
await fetchMock.resolveSpecific(
|
||||
["http://127.0.0.1:9999/api-kube/apis/networking.k8s.io/v1"],
|
||||
createMockResponseFromString("http://127.0.0.1:9999/api-kube/apis/networking.k8s.io/v1", JSON.stringify({
|
||||
["https://127.0.0.1:9999/api-kube/apis/networking.k8s.io/v1"],
|
||||
createMockResponseFromString("https://127.0.0.1:9999/api-kube/apis/networking.k8s.io/v1", JSON.stringify({
|
||||
resources: [],
|
||||
})),
|
||||
);
|
||||
@ -304,7 +304,7 @@ describe("KubeApi", () => {
|
||||
|
||||
it("requests resources from the second versioned api group from the initial apiBase", () => {
|
||||
expect(fetchMock.mock.lastCall).toMatchObject([
|
||||
"http://127.0.0.1:9999/api-kube/apis/networking.k8s.io/v1beta1",
|
||||
"https://127.0.0.1:9999/api-kube/apis/networking.k8s.io/v1beta1",
|
||||
{
|
||||
headers: {
|
||||
"content-type": "application/json",
|
||||
@ -319,8 +319,8 @@ describe("KubeApi", () => {
|
||||
describe("when resource request fufills with a resource", () => {
|
||||
beforeEach(async () => {
|
||||
await fetchMock.resolveSpecific(
|
||||
["http://127.0.0.1:9999/api-kube/apis/networking.k8s.io/v1beta1"],
|
||||
createMockResponseFromString("http://127.0.0.1:9999/api-kube/apis/networking.k8s.io/v1beta1", JSON.stringify({
|
||||
["https://127.0.0.1:9999/api-kube/apis/networking.k8s.io/v1beta1"],
|
||||
createMockResponseFromString("https://127.0.0.1:9999/api-kube/apis/networking.k8s.io/v1beta1", JSON.stringify({
|
||||
resources: [{
|
||||
name: "ingresses",
|
||||
}],
|
||||
@ -330,7 +330,7 @@ describe("KubeApi", () => {
|
||||
|
||||
it("makes the request to get the resource", () => {
|
||||
expect(fetchMock.mock.lastCall).toMatchObject([
|
||||
"http://127.0.0.1:9999/api-kube/apis/networking.k8s.io/v1beta1/namespaces/default/ingresses/foo",
|
||||
"https://127.0.0.1:9999/api-kube/apis/networking.k8s.io/v1beta1/namespaces/default/ingresses/foo",
|
||||
{
|
||||
headers: {
|
||||
"content-type": "application/json",
|
||||
@ -357,8 +357,8 @@ describe("KubeApi", () => {
|
||||
|
||||
beforeEach(async () => {
|
||||
await fetchMock.resolveSpecific(
|
||||
["http://127.0.0.1:9999/api-kube/apis/networking.k8s.io/v1beta1/namespaces/default/ingresses/foo"],
|
||||
createMockResponseFromString("http://127.0.0.1:9999/api-kube/apis/networking.k8s.io/v1beta1/namespaces/default/ingresses/foo", JSON.stringify({})),
|
||||
["https://127.0.0.1:9999/api-kube/apis/networking.k8s.io/v1beta1/namespaces/default/ingresses/foo"],
|
||||
createMockResponseFromString("https://127.0.0.1:9999/api-kube/apis/networking.k8s.io/v1beta1/namespaces/default/ingresses/foo", JSON.stringify({})),
|
||||
);
|
||||
result = await getCall;
|
||||
});
|
||||
@ -382,7 +382,7 @@ describe("KubeApi", () => {
|
||||
|
||||
it("makes the request to get the resource", () => {
|
||||
expect(fetchMock.mock.lastCall).toMatchObject([
|
||||
"http://127.0.0.1:9999/api-kube/apis/networking.k8s.io/v1beta1/namespaces/default/ingresses/foo1",
|
||||
"https://127.0.0.1:9999/api-kube/apis/networking.k8s.io/v1beta1/namespaces/default/ingresses/foo1",
|
||||
{
|
||||
headers: {
|
||||
"content-type": "application/json",
|
||||
@ -397,8 +397,8 @@ describe("KubeApi", () => {
|
||||
|
||||
beforeEach(async () => {
|
||||
await fetchMock.resolveSpecific(
|
||||
["http://127.0.0.1:9999/api-kube/apis/networking.k8s.io/v1beta1/namespaces/default/ingresses/foo1"],
|
||||
createMockResponseFromString("http://127.0.0.1:9999/api-kube/apis/networking.k8s.io/v1beta1/namespaces/default/ingresses/foo1", JSON.stringify({})),
|
||||
["https://127.0.0.1:9999/api-kube/apis/networking.k8s.io/v1beta1/namespaces/default/ingresses/foo1"],
|
||||
createMockResponseFromString("https://127.0.0.1:9999/api-kube/apis/networking.k8s.io/v1beta1/namespaces/default/ingresses/foo1", JSON.stringify({})),
|
||||
);
|
||||
result = await getCall;
|
||||
});
|
||||
@ -415,8 +415,8 @@ describe("KubeApi", () => {
|
||||
|
||||
beforeEach(async () => {
|
||||
await fetchMock.resolveSpecific(
|
||||
["http://127.0.0.1:9999/api-kube/apis/networking.k8s.io/v1beta1/namespaces/default/ingresses/foo"],
|
||||
createMockResponseFromString("http://127.0.0.1:9999/api-kube/apis/networking.k8s.io/v1beta1/namespaces/default/ingresses/foo", JSON.stringify({
|
||||
["https://127.0.0.1:9999/api-kube/apis/networking.k8s.io/v1beta1/namespaces/default/ingresses/foo"],
|
||||
createMockResponseFromString("https://127.0.0.1:9999/api-kube/apis/networking.k8s.io/v1beta1/namespaces/default/ingresses/foo", JSON.stringify({
|
||||
apiVersion: "v1",
|
||||
kind: "Ingress",
|
||||
metadata: {
|
||||
@ -449,7 +449,7 @@ describe("KubeApi", () => {
|
||||
|
||||
it("makes the request to get the resource", () => {
|
||||
expect(fetchMock.mock.lastCall).toMatchObject([
|
||||
"http://127.0.0.1:9999/api-kube/apis/networking.k8s.io/v1beta1/namespaces/default/ingresses/foo1",
|
||||
"https://127.0.0.1:9999/api-kube/apis/networking.k8s.io/v1beta1/namespaces/default/ingresses/foo1",
|
||||
{
|
||||
headers: {
|
||||
"content-type": "application/json",
|
||||
@ -464,8 +464,8 @@ describe("KubeApi", () => {
|
||||
|
||||
beforeEach(async () => {
|
||||
await fetchMock.resolveSpecific(
|
||||
["http://127.0.0.1:9999/api-kube/apis/networking.k8s.io/v1beta1/namespaces/default/ingresses/foo1"],
|
||||
createMockResponseFromString("http://127.0.0.1:9999/api-kube/apis/networking.k8s.io/v1beta1/namespaces/default/ingresses/foo1", JSON.stringify({})),
|
||||
["https://127.0.0.1:9999/api-kube/apis/networking.k8s.io/v1beta1/namespaces/default/ingresses/foo1"],
|
||||
createMockResponseFromString("https://127.0.0.1:9999/api-kube/apis/networking.k8s.io/v1beta1/namespaces/default/ingresses/foo1", JSON.stringify({})),
|
||||
);
|
||||
result = await getCall;
|
||||
});
|
||||
@ -483,8 +483,8 @@ describe("KubeApi", () => {
|
||||
describe("when the version list from the api group resolves with no versions", () => {
|
||||
beforeEach(async () => {
|
||||
await fetchMock.resolveSpecific(
|
||||
["http://127.0.0.1:9999/api-kube/apis/networking.k8s.io"],
|
||||
createMockResponseFromString("http://127.0.0.1:9999/api-kube/apis/networking.k8s.io", JSON.stringify({
|
||||
["https://127.0.0.1:9999/api-kube/apis/networking.k8s.io"],
|
||||
createMockResponseFromString("https://127.0.0.1:9999/api-kube/apis/networking.k8s.io", JSON.stringify({
|
||||
"metadata": {},
|
||||
"status": "Failure",
|
||||
"message": "the server could not find the requested resource",
|
||||
@ -504,7 +504,7 @@ describe("KubeApi", () => {
|
||||
|
||||
it("requests the resources from the base api url from the fallback api", () => {
|
||||
expect(fetchMock.mock.lastCall).toMatchObject([
|
||||
"http://127.0.0.1:9999/api-kube/apis/extensions",
|
||||
"https://127.0.0.1:9999/api-kube/apis/extensions",
|
||||
{
|
||||
headers: {
|
||||
"content-type": "application/json",
|
||||
@ -517,8 +517,8 @@ describe("KubeApi", () => {
|
||||
describe("when resource request fufills with a resource", () => {
|
||||
beforeEach(async () => {
|
||||
await fetchMock.resolveSpecific(
|
||||
["http://127.0.0.1:9999/api-kube/apis/extensions"],
|
||||
createMockResponseFromString("http://127.0.0.1:9999/api-kube/apis/extensions", JSON.stringify({
|
||||
["https://127.0.0.1:9999/api-kube/apis/extensions"],
|
||||
createMockResponseFromString("https://127.0.0.1:9999/api-kube/apis/extensions", JSON.stringify({
|
||||
apiVersion: "v1",
|
||||
kind: "APIGroup",
|
||||
name: "extensions",
|
||||
@ -538,7 +538,7 @@ describe("KubeApi", () => {
|
||||
|
||||
it("requests resource versions from the versioned api group from the fallback apiBase", () => {
|
||||
expect(fetchMock.mock.lastCall).toMatchObject([
|
||||
"http://127.0.0.1:9999/api-kube/apis/extensions/v1beta1",
|
||||
"https://127.0.0.1:9999/api-kube/apis/extensions/v1beta1",
|
||||
{
|
||||
headers: {
|
||||
"content-type": "application/json",
|
||||
@ -551,8 +551,8 @@ describe("KubeApi", () => {
|
||||
describe("when the preferred version request resolves to v1beta1", () => {
|
||||
beforeEach(async () => {
|
||||
await fetchMock.resolveSpecific(
|
||||
["http://127.0.0.1:9999/api-kube/apis/extensions/v1beta1"],
|
||||
createMockResponseFromString("http://127.0.0.1:9999/api-kube/apis/extensions", JSON.stringify({
|
||||
["https://127.0.0.1:9999/api-kube/apis/extensions/v1beta1"],
|
||||
createMockResponseFromString("https://127.0.0.1:9999/api-kube/apis/extensions", JSON.stringify({
|
||||
resources: [{
|
||||
name: "ingresses",
|
||||
}],
|
||||
@ -562,7 +562,7 @@ describe("KubeApi", () => {
|
||||
|
||||
it("makes the request to get the resource", () => {
|
||||
expect(fetchMock.mock.lastCall).toMatchObject([
|
||||
"http://127.0.0.1:9999/api-kube/apis/extensions/v1beta1/namespaces/default/ingresses/foo",
|
||||
"https://127.0.0.1:9999/api-kube/apis/extensions/v1beta1/namespaces/default/ingresses/foo",
|
||||
{
|
||||
headers: {
|
||||
"content-type": "application/json",
|
||||
@ -589,8 +589,8 @@ describe("KubeApi", () => {
|
||||
|
||||
beforeEach(async () => {
|
||||
await fetchMock.resolveSpecific(
|
||||
["http://127.0.0.1:9999/api-kube/apis/extensions/v1beta1/namespaces/default/ingresses/foo"],
|
||||
createMockResponseFromString("http://127.0.0.1:9999/api-kube/apis/extensions/v1beta1/namespaces/default/ingresses/foo", JSON.stringify({})),
|
||||
["https://127.0.0.1:9999/api-kube/apis/extensions/v1beta1/namespaces/default/ingresses/foo"],
|
||||
createMockResponseFromString("https://127.0.0.1:9999/api-kube/apis/extensions/v1beta1/namespaces/default/ingresses/foo", JSON.stringify({})),
|
||||
);
|
||||
result = await getCall;
|
||||
});
|
||||
@ -614,7 +614,7 @@ describe("KubeApi", () => {
|
||||
|
||||
it("makes the request to get the resource", () => {
|
||||
expect(fetchMock.mock.lastCall).toMatchObject([
|
||||
"http://127.0.0.1:9999/api-kube/apis/extensions/v1beta1/namespaces/default/ingresses/foo1",
|
||||
"https://127.0.0.1:9999/api-kube/apis/extensions/v1beta1/namespaces/default/ingresses/foo1",
|
||||
{
|
||||
headers: {
|
||||
"content-type": "application/json",
|
||||
@ -629,8 +629,8 @@ describe("KubeApi", () => {
|
||||
|
||||
beforeEach(async () => {
|
||||
await fetchMock.resolveSpecific(
|
||||
["http://127.0.0.1:9999/api-kube/apis/extensions/v1beta1/namespaces/default/ingresses/foo1"],
|
||||
createMockResponseFromString("http://127.0.0.1:9999/api-kube/apis/extensions/v1beta1/namespaces/default/ingresses/foo1", JSON.stringify({})),
|
||||
["https://127.0.0.1:9999/api-kube/apis/extensions/v1beta1/namespaces/default/ingresses/foo1"],
|
||||
createMockResponseFromString("https://127.0.0.1:9999/api-kube/apis/extensions/v1beta1/namespaces/default/ingresses/foo1", JSON.stringify({})),
|
||||
);
|
||||
result = await getCall;
|
||||
});
|
||||
@ -647,8 +647,8 @@ describe("KubeApi", () => {
|
||||
|
||||
beforeEach(async () => {
|
||||
await fetchMock.resolveSpecific(
|
||||
["http://127.0.0.1:9999/api-kube/apis/extensions/v1beta1/namespaces/default/ingresses/foo"],
|
||||
createMockResponseFromString("http://127.0.0.1:9999/api-kube/apis/extensions/v1beta1/namespaces/default/ingresses/foo", JSON.stringify({
|
||||
["https://127.0.0.1:9999/api-kube/apis/extensions/v1beta1/namespaces/default/ingresses/foo"],
|
||||
createMockResponseFromString("https://127.0.0.1:9999/api-kube/apis/extensions/v1beta1/namespaces/default/ingresses/foo", JSON.stringify({
|
||||
apiVersion: "v1beta1",
|
||||
kind: "Ingress",
|
||||
metadata: {
|
||||
@ -681,7 +681,7 @@ describe("KubeApi", () => {
|
||||
|
||||
it("makes the request to get the resource", () => {
|
||||
expect(fetchMock.mock.lastCall).toMatchObject([
|
||||
"http://127.0.0.1:9999/api-kube/apis/extensions/v1beta1/namespaces/default/ingresses/foo1",
|
||||
"https://127.0.0.1:9999/api-kube/apis/extensions/v1beta1/namespaces/default/ingresses/foo1",
|
||||
{
|
||||
headers: {
|
||||
"content-type": "application/json",
|
||||
@ -696,8 +696,8 @@ describe("KubeApi", () => {
|
||||
|
||||
beforeEach(async () => {
|
||||
await fetchMock.resolveSpecific(
|
||||
["http://127.0.0.1:9999/api-kube/apis/extensions/v1beta1/namespaces/default/ingresses/foo1"],
|
||||
createMockResponseFromString("http://127.0.0.1:9999/api-kube/apis/extensions/v1beta1/namespaces/default/ingresses/foo1", JSON.stringify({})),
|
||||
["https://127.0.0.1:9999/api-kube/apis/extensions/v1beta1/namespaces/default/ingresses/foo1"],
|
||||
createMockResponseFromString("https://127.0.0.1:9999/api-kube/apis/extensions/v1beta1/namespaces/default/ingresses/foo1", JSON.stringify({})),
|
||||
);
|
||||
result = await getCall;
|
||||
});
|
||||
|
||||
@ -157,7 +157,7 @@ describe("KubeApi", () => {
|
||||
const createKubeJsonApi = di.inject(createKubeJsonApiInjectable);
|
||||
|
||||
request = createKubeJsonApi({
|
||||
serverAddress: `http://127.0.0.1:9999`,
|
||||
serverAddress: `https://127.0.0.1:9999`,
|
||||
apiBase: "/api-kube",
|
||||
});
|
||||
|
||||
@ -189,7 +189,7 @@ describe("KubeApi", () => {
|
||||
|
||||
it("requests a patch using strategic merge", () => {
|
||||
expect(fetchMock.mock.lastCall).toMatchObject([
|
||||
"http://127.0.0.1:9999/api-kube/apis/apps/v1/namespaces/default/deployments/test",
|
||||
"https://127.0.0.1:9999/api-kube/apis/apps/v1/namespaces/default/deployments/test",
|
||||
{
|
||||
headers: {
|
||||
"content-type": "application/strategic-merge-patch+json",
|
||||
@ -203,8 +203,8 @@ describe("KubeApi", () => {
|
||||
describe("when the patch request resolves with data", () => {
|
||||
beforeEach(async () => {
|
||||
await fetchMock.resolveSpecific(
|
||||
["http://127.0.0.1:9999/api-kube/apis/apps/v1/namespaces/default/deployments/test"],
|
||||
createMockResponseFromString("http://127.0.0.1:9999/api-kube/apis/apps/v1/namespaces/default/deployments/test", JSON.stringify({
|
||||
["https://127.0.0.1:9999/api-kube/apis/apps/v1/namespaces/default/deployments/test"],
|
||||
createMockResponseFromString("https://127.0.0.1:9999/api-kube/apis/apps/v1/namespaces/default/deployments/test", JSON.stringify({
|
||||
apiVersion: "v1",
|
||||
kind: "Deployment",
|
||||
metadata: {
|
||||
@ -240,7 +240,7 @@ describe("KubeApi", () => {
|
||||
|
||||
it("requests a patch using json merge", () => {
|
||||
expect(fetchMock.mock.lastCall).toMatchObject([
|
||||
"http://127.0.0.1:9999/api-kube/apis/apps/v1/namespaces/default/deployments/test",
|
||||
"https://127.0.0.1:9999/api-kube/apis/apps/v1/namespaces/default/deployments/test",
|
||||
{
|
||||
headers: {
|
||||
"content-type": "application/json-patch+json",
|
||||
@ -256,8 +256,8 @@ describe("KubeApi", () => {
|
||||
describe("when the patch request resolves with data", () => {
|
||||
beforeEach(async () => {
|
||||
await fetchMock.resolveSpecific(
|
||||
["http://127.0.0.1:9999/api-kube/apis/apps/v1/namespaces/default/deployments/test"],
|
||||
createMockResponseFromString("http://127.0.0.1:9999/api-kube/apis/apps/v1/namespaces/default/deployments/test", JSON.stringify({
|
||||
["https://127.0.0.1:9999/api-kube/apis/apps/v1/namespaces/default/deployments/test"],
|
||||
createMockResponseFromString("https://127.0.0.1:9999/api-kube/apis/apps/v1/namespaces/default/deployments/test", JSON.stringify({
|
||||
apiVersion: "v1",
|
||||
kind: "Deployment",
|
||||
metadata: {
|
||||
@ -295,7 +295,7 @@ describe("KubeApi", () => {
|
||||
|
||||
it("requests a patch using json merge", () => {
|
||||
expect(fetchMock.mock.lastCall).toMatchObject([
|
||||
"http://127.0.0.1:9999/api-kube/apis/apps/v1/namespaces/default/deployments/test",
|
||||
"https://127.0.0.1:9999/api-kube/apis/apps/v1/namespaces/default/deployments/test",
|
||||
{
|
||||
headers: {
|
||||
"content-type": "application/merge-patch+json",
|
||||
@ -309,8 +309,8 @@ describe("KubeApi", () => {
|
||||
describe("when the patch request resolves with data", () => {
|
||||
beforeEach(async () => {
|
||||
await fetchMock.resolveSpecific(
|
||||
["http://127.0.0.1:9999/api-kube/apis/apps/v1/namespaces/default/deployments/test"],
|
||||
createMockResponseFromString("http://127.0.0.1:9999/api-kube/apis/apps/v1/namespaces/default/deployments/test", JSON.stringify({
|
||||
["https://127.0.0.1:9999/api-kube/apis/apps/v1/namespaces/default/deployments/test"],
|
||||
createMockResponseFromString("https://127.0.0.1:9999/api-kube/apis/apps/v1/namespaces/default/deployments/test", JSON.stringify({
|
||||
apiVersion: "v1",
|
||||
kind: "Deployment",
|
||||
metadata: {
|
||||
@ -354,7 +354,7 @@ describe("KubeApi", () => {
|
||||
|
||||
it("requests deleting pod in default namespace", () => {
|
||||
expect(fetchMock.mock.lastCall).toMatchObject([
|
||||
"http://127.0.0.1:9999/api-kube/api/v1/namespaces/default/pods/foo?propagationPolicy=Background",
|
||||
"https://127.0.0.1:9999/api-kube/api/v1/namespaces/default/pods/foo?propagationPolicy=Background",
|
||||
{
|
||||
headers: {
|
||||
"content-type": "application/json",
|
||||
@ -367,8 +367,8 @@ describe("KubeApi", () => {
|
||||
describe("when request resolves", () => {
|
||||
beforeEach(async () => {
|
||||
fetchMock.resolveSpecific(
|
||||
["http://127.0.0.1:9999/api-kube/api/v1/namespaces/default/pods/foo?propagationPolicy=Background"],
|
||||
createMockResponseFromString("http://127.0.0.1:9999/api-kube/api/v1/namespaces/default/pods/foo?propagationPolicy=Background", "{}"),
|
||||
["https://127.0.0.1:9999/api-kube/api/v1/namespaces/default/pods/foo?propagationPolicy=Background"],
|
||||
createMockResponseFromString("https://127.0.0.1:9999/api-kube/api/v1/namespaces/default/pods/foo?propagationPolicy=Background", "{}"),
|
||||
);
|
||||
});
|
||||
|
||||
@ -390,7 +390,7 @@ describe("KubeApi", () => {
|
||||
|
||||
it("requests deleting pod in default namespace", () => {
|
||||
expect(fetchMock.mock.lastCall).toMatchObject([
|
||||
"http://127.0.0.1:9999/api-kube/api/v1/namespaces/default/pods/foo?propagationPolicy=Background",
|
||||
"https://127.0.0.1:9999/api-kube/api/v1/namespaces/default/pods/foo?propagationPolicy=Background",
|
||||
{
|
||||
headers: {
|
||||
"content-type": "application/json",
|
||||
@ -403,8 +403,8 @@ describe("KubeApi", () => {
|
||||
describe("when request resolves", () => {
|
||||
beforeEach(async () => {
|
||||
fetchMock.resolveSpecific(
|
||||
["http://127.0.0.1:9999/api-kube/api/v1/namespaces/default/pods/foo?propagationPolicy=Background"],
|
||||
createMockResponseFromString("http://127.0.0.1:9999/api-kube/api/v1/namespaces/default/pods/foo?propagationPolicy=Background", "{}"),
|
||||
["https://127.0.0.1:9999/api-kube/api/v1/namespaces/default/pods/foo?propagationPolicy=Background"],
|
||||
createMockResponseFromString("https://127.0.0.1:9999/api-kube/api/v1/namespaces/default/pods/foo?propagationPolicy=Background", "{}"),
|
||||
);
|
||||
});
|
||||
|
||||
@ -426,7 +426,7 @@ describe("KubeApi", () => {
|
||||
|
||||
it("requests deleting pod in given namespace", () => {
|
||||
expect(fetchMock.mock.lastCall).toMatchObject([
|
||||
"http://127.0.0.1:9999/api-kube/api/v1/namespaces/test/pods/foo?propagationPolicy=Background",
|
||||
"https://127.0.0.1:9999/api-kube/api/v1/namespaces/test/pods/foo?propagationPolicy=Background",
|
||||
{
|
||||
headers: {
|
||||
"content-type": "application/json",
|
||||
@ -439,8 +439,8 @@ describe("KubeApi", () => {
|
||||
describe("when request resolves", () => {
|
||||
beforeEach(async () => {
|
||||
fetchMock.resolveSpecific(
|
||||
["http://127.0.0.1:9999/api-kube/api/v1/namespaces/test/pods/foo?propagationPolicy=Background"],
|
||||
createMockResponseFromString("http://127.0.0.1:9999/api-kube/api/v1/namespaces/test/pods/foo?propagationPolicy=Background", "{}"),
|
||||
["https://127.0.0.1:9999/api-kube/api/v1/namespaces/test/pods/foo?propagationPolicy=Background"],
|
||||
createMockResponseFromString("https://127.0.0.1:9999/api-kube/api/v1/namespaces/test/pods/foo?propagationPolicy=Background", "{}"),
|
||||
);
|
||||
});
|
||||
|
||||
@ -472,7 +472,7 @@ describe("KubeApi", () => {
|
||||
|
||||
it("requests deleting Namespace without namespace", () => {
|
||||
expect(fetchMock.mock.lastCall).toMatchObject([
|
||||
"http://127.0.0.1:9999/api-kube/api/v1/namespaces/foo?propagationPolicy=Background",
|
||||
"https://127.0.0.1:9999/api-kube/api/v1/namespaces/foo?propagationPolicy=Background",
|
||||
{
|
||||
headers: {
|
||||
"content-type": "application/json",
|
||||
@ -485,8 +485,8 @@ describe("KubeApi", () => {
|
||||
describe("when request resolves", () => {
|
||||
beforeEach(async () => {
|
||||
fetchMock.resolveSpecific(
|
||||
["http://127.0.0.1:9999/api-kube/api/v1/namespaces/foo?propagationPolicy=Background"],
|
||||
createMockResponseFromString("http://127.0.0.1:9999/api-kube/api/v1/namespaces/foo?propagationPolicy=Background", "{}"),
|
||||
["https://127.0.0.1:9999/api-kube/api/v1/namespaces/foo?propagationPolicy=Background"],
|
||||
createMockResponseFromString("https://127.0.0.1:9999/api-kube/api/v1/namespaces/foo?propagationPolicy=Background", "{}"),
|
||||
);
|
||||
});
|
||||
|
||||
@ -508,7 +508,7 @@ describe("KubeApi", () => {
|
||||
|
||||
it("requests deleting Namespace without namespace", () => {
|
||||
expect(fetchMock.mock.lastCall).toMatchObject([
|
||||
"http://127.0.0.1:9999/api-kube/api/v1/namespaces/foo?propagationPolicy=Background",
|
||||
"https://127.0.0.1:9999/api-kube/api/v1/namespaces/foo?propagationPolicy=Background",
|
||||
{
|
||||
headers: {
|
||||
"content-type": "application/json",
|
||||
@ -521,8 +521,8 @@ describe("KubeApi", () => {
|
||||
describe("when request resolves", () => {
|
||||
beforeEach(async () => {
|
||||
fetchMock.resolveSpecific(
|
||||
["http://127.0.0.1:9999/api-kube/api/v1/namespaces/foo?propagationPolicy=Background"],
|
||||
createMockResponseFromString("http://127.0.0.1:9999/api-kube/api/v1/namespaces/foo?propagationPolicy=Background", "{}"),
|
||||
["https://127.0.0.1:9999/api-kube/api/v1/namespaces/foo?propagationPolicy=Background"],
|
||||
createMockResponseFromString("https://127.0.0.1:9999/api-kube/api/v1/namespaces/foo?propagationPolicy=Background", "{}"),
|
||||
);
|
||||
});
|
||||
|
||||
@ -571,7 +571,7 @@ describe("KubeApi", () => {
|
||||
|
||||
it("requests the watch", () => {
|
||||
expect(fetchMock.mock.lastCall).toMatchObject([
|
||||
"http://127.0.0.1:9999/api-kube/api/v1/namespaces/kube-system/pods?watch=1&resourceVersion=&timeoutSeconds=600",
|
||||
"https://127.0.0.1:9999/api-kube/api/v1/namespaces/kube-system/pods?watch=1&resourceVersion=&timeoutSeconds=600",
|
||||
{
|
||||
headers: {
|
||||
"content-type": "application/json",
|
||||
@ -585,7 +585,7 @@ describe("KubeApi", () => {
|
||||
beforeEach(async () => {
|
||||
await fetchMock.resolveSpecific(
|
||||
([url, init]) => {
|
||||
const isMatch = url === "http://127.0.0.1:9999/api-kube/api/v1/namespaces/kube-system/pods?watch=1&resourceVersion=&timeoutSeconds=600";
|
||||
const isMatch = url === "https://127.0.0.1:9999/api-kube/api/v1/namespaces/kube-system/pods?watch=1&resourceVersion=&timeoutSeconds=600";
|
||||
|
||||
if (isMatch) {
|
||||
init?.signal?.addEventListener("abort", () => {
|
||||
@ -595,7 +595,7 @@ describe("KubeApi", () => {
|
||||
|
||||
return isMatch;
|
||||
},
|
||||
createMockResponseFromStream("http://127.0.0.1:9999/api-kube/api/v1/namespaces/kube-system/pods?watch=1&resourceVersion=&timeoutSeconds=600", stream),
|
||||
createMockResponseFromStream("https://127.0.0.1:9999/api-kube/api/v1/namespaces/kube-system/pods?watch=1&resourceVersion=&timeoutSeconds=600", stream),
|
||||
);
|
||||
});
|
||||
|
||||
@ -667,7 +667,7 @@ describe("KubeApi", () => {
|
||||
|
||||
it("requests the watch", () => {
|
||||
expect(fetchMock.mock.lastCall).toMatchObject([
|
||||
"http://127.0.0.1:9999/api-kube/api/v1/namespaces/kube-system/pods?watch=1&resourceVersion=&timeoutSeconds=600",
|
||||
"https://127.0.0.1:9999/api-kube/api/v1/namespaces/kube-system/pods?watch=1&resourceVersion=&timeoutSeconds=600",
|
||||
{
|
||||
headers: {
|
||||
"content-type": "application/json",
|
||||
@ -681,7 +681,7 @@ describe("KubeApi", () => {
|
||||
beforeEach(async () => {
|
||||
await fetchMock.resolveSpecific(
|
||||
([url, init]) => {
|
||||
const isMatch = url === "http://127.0.0.1:9999/api-kube/api/v1/namespaces/kube-system/pods?watch=1&resourceVersion=&timeoutSeconds=600";
|
||||
const isMatch = url === "https://127.0.0.1:9999/api-kube/api/v1/namespaces/kube-system/pods?watch=1&resourceVersion=&timeoutSeconds=600";
|
||||
|
||||
if (isMatch) {
|
||||
init?.signal?.addEventListener("abort", () => {
|
||||
@ -691,7 +691,7 @@ describe("KubeApi", () => {
|
||||
|
||||
return isMatch;
|
||||
},
|
||||
createMockResponseFromStream("http://127.0.0.1:9999/api-kube/api/v1/namespaces/kube-system/pods?watch=1&resourceVersion=&timeoutSeconds=600", stream),
|
||||
createMockResponseFromStream("https://127.0.0.1:9999/api-kube/api/v1/namespaces/kube-system/pods?watch=1&resourceVersion=&timeoutSeconds=600", stream),
|
||||
);
|
||||
});
|
||||
|
||||
@ -762,7 +762,7 @@ describe("KubeApi", () => {
|
||||
|
||||
it("requests the watch", () => {
|
||||
expect(fetchMock.mock.lastCall).toMatchObject([
|
||||
"http://127.0.0.1:9999/api-kube/api/v1/namespaces/kube-system/pods?watch=1&resourceVersion=&timeoutSeconds=60",
|
||||
"https://127.0.0.1:9999/api-kube/api/v1/namespaces/kube-system/pods?watch=1&resourceVersion=&timeoutSeconds=60",
|
||||
{
|
||||
headers: {
|
||||
"content-type": "application/json",
|
||||
@ -776,7 +776,7 @@ describe("KubeApi", () => {
|
||||
beforeEach(async () => {
|
||||
await fetchMock.resolveSpecific(
|
||||
([url, init]) => {
|
||||
const isMatch = url === "http://127.0.0.1:9999/api-kube/api/v1/namespaces/kube-system/pods?watch=1&resourceVersion=&timeoutSeconds=60";
|
||||
const isMatch = url === "https://127.0.0.1:9999/api-kube/api/v1/namespaces/kube-system/pods?watch=1&resourceVersion=&timeoutSeconds=60";
|
||||
|
||||
if (isMatch) {
|
||||
init?.signal?.addEventListener("abort", () => {
|
||||
@ -786,7 +786,7 @@ describe("KubeApi", () => {
|
||||
|
||||
return isMatch;
|
||||
},
|
||||
createMockResponseFromStream("http://127.0.0.1:9999/api-kube/api/v1/namespaces/kube-system/pods?watch=1&resourceVersion=&timeoutSeconds=60", stream),
|
||||
createMockResponseFromStream("https://127.0.0.1:9999/api-kube/api/v1/namespaces/kube-system/pods?watch=1&resourceVersion=&timeoutSeconds=60", stream),
|
||||
);
|
||||
});
|
||||
|
||||
@ -844,7 +844,7 @@ describe("KubeApi", () => {
|
||||
|
||||
it("requests a new watch", () => {
|
||||
expect(fetchMock.mock.lastCall).toMatchObject([
|
||||
"http://127.0.0.1:9999/api-kube/api/v1/namespaces/kube-system/pods?watch=1&resourceVersion=&timeoutSeconds=60",
|
||||
"https://127.0.0.1:9999/api-kube/api/v1/namespaces/kube-system/pods?watch=1&resourceVersion=&timeoutSeconds=60",
|
||||
{
|
||||
headers: {
|
||||
"content-type": "application/json",
|
||||
@ -914,7 +914,7 @@ describe("KubeApi", () => {
|
||||
|
||||
it("should request to create a pod with full descriptor", () => {
|
||||
expect(fetchMock.mock.lastCall).toMatchObject([
|
||||
"http://127.0.0.1:9999/api-kube/api/v1/namespaces/default/pods",
|
||||
"https://127.0.0.1:9999/api-kube/api/v1/namespaces/default/pods",
|
||||
{
|
||||
headers: {
|
||||
"content-type": "application/json",
|
||||
@ -949,8 +949,8 @@ describe("KubeApi", () => {
|
||||
describe("when request resolves with data", () => {
|
||||
beforeEach(async () => {
|
||||
await fetchMock.resolveSpecific(
|
||||
["http://127.0.0.1:9999/api-kube/api/v1/namespaces/default/pods"],
|
||||
createMockResponseFromString("http://127.0.0.1:9999/api-kube/api/v1/namespaces/default/pods", JSON.stringify({
|
||||
["https://127.0.0.1:9999/api-kube/api/v1/namespaces/default/pods"],
|
||||
createMockResponseFromString("https://127.0.0.1:9999/api-kube/api/v1/namespaces/default/pods", JSON.stringify({
|
||||
kind: "Pod",
|
||||
apiVersion: "v1",
|
||||
metadata: {
|
||||
@ -1026,7 +1026,7 @@ describe("KubeApi", () => {
|
||||
|
||||
it("should request that the pod is updated", () => {
|
||||
expect(fetchMock.mock.lastCall).toMatchObject([
|
||||
"http://127.0.0.1:9999/api-kube/api/v1/namespaces/default/pods/foobar",
|
||||
"https://127.0.0.1:9999/api-kube/api/v1/namespaces/default/pods/foobar",
|
||||
{
|
||||
headers: {
|
||||
"content-type": "application/json",
|
||||
@ -1061,8 +1061,8 @@ describe("KubeApi", () => {
|
||||
describe("when the request resolves with data", () => {
|
||||
beforeEach(async () => {
|
||||
await fetchMock.resolveSpecific(
|
||||
["http://127.0.0.1:9999/api-kube/api/v1/namespaces/default/pods/foobar"],
|
||||
createMockResponseFromString("http://127.0.0.1:9999/api-kube/api/v1/namespaces/default/pods/foobar", JSON.stringify({
|
||||
["https://127.0.0.1:9999/api-kube/api/v1/namespaces/default/pods/foobar"],
|
||||
createMockResponseFromString("https://127.0.0.1:9999/api-kube/api/v1/namespaces/default/pods/foobar", JSON.stringify({
|
||||
kind: "Pod",
|
||||
apiVersion: "v1",
|
||||
metadata: {
|
||||
@ -1116,7 +1116,7 @@ describe("KubeApi", () => {
|
||||
|
||||
it("should request that the pods from all namespaces", () => {
|
||||
expect(fetchMock.mock.lastCall).toMatchObject([
|
||||
"http://127.0.0.1:9999/api-kube/api/v1/pods",
|
||||
"https://127.0.0.1:9999/api-kube/api/v1/pods",
|
||||
{
|
||||
headers: {
|
||||
"content-type": "application/json",
|
||||
@ -1129,8 +1129,8 @@ describe("KubeApi", () => {
|
||||
describe("when the request resolves with empty data", () => {
|
||||
beforeEach(async () => {
|
||||
await fetchMock.resolveSpecific(
|
||||
["http://127.0.0.1:9999/api-kube/api/v1/pods"],
|
||||
createMockResponseFromString("http://127.0.0.1:9999/api-kube/api/v1/pods", JSON.stringify({
|
||||
["https://127.0.0.1:9999/api-kube/api/v1/pods"],
|
||||
createMockResponseFromString("https://127.0.0.1:9999/api-kube/api/v1/pods", JSON.stringify({
|
||||
kind: "PodList",
|
||||
apiVersion: "v1",
|
||||
metadata: {},
|
||||
@ -1158,7 +1158,7 @@ describe("KubeApi", () => {
|
||||
|
||||
it("should request that the pods from all namespaces", () => {
|
||||
expect(fetchMock.mock.lastCall).toMatchObject([
|
||||
"http://127.0.0.1:9999/api-kube/api/v1/pods",
|
||||
"https://127.0.0.1:9999/api-kube/api/v1/pods",
|
||||
{
|
||||
headers: {
|
||||
"content-type": "application/json",
|
||||
@ -1171,8 +1171,8 @@ describe("KubeApi", () => {
|
||||
describe("when the request resolves with empty data", () => {
|
||||
beforeEach(async () => {
|
||||
await fetchMock.resolveSpecific(
|
||||
["http://127.0.0.1:9999/api-kube/api/v1/pods"],
|
||||
createMockResponseFromString("http://127.0.0.1:9999/api-kube/api/v1/pods", JSON.stringify({
|
||||
["https://127.0.0.1:9999/api-kube/api/v1/pods"],
|
||||
createMockResponseFromString("https://127.0.0.1:9999/api-kube/api/v1/pods", JSON.stringify({
|
||||
kind: "PodList",
|
||||
apiVersion: "v1",
|
||||
metadata: {},
|
||||
@ -1200,7 +1200,7 @@ describe("KubeApi", () => {
|
||||
|
||||
it("should request that the pods from just the default namespace", () => {
|
||||
expect(fetchMock.mock.lastCall).toMatchObject([
|
||||
"http://127.0.0.1:9999/api-kube/api/v1/namespaces/default/pods",
|
||||
"https://127.0.0.1:9999/api-kube/api/v1/namespaces/default/pods",
|
||||
{
|
||||
headers: {
|
||||
"content-type": "application/json",
|
||||
@ -1213,8 +1213,8 @@ describe("KubeApi", () => {
|
||||
describe("when the request resolves with empty data", () => {
|
||||
beforeEach(async () => {
|
||||
await fetchMock.resolveSpecific(
|
||||
["http://127.0.0.1:9999/api-kube/api/v1/namespaces/default/pods"],
|
||||
createMockResponseFromString("http://127.0.0.1:9999/api-kube/api/v1/namespaces/default/pods", JSON.stringify({
|
||||
["https://127.0.0.1:9999/api-kube/api/v1/namespaces/default/pods"],
|
||||
createMockResponseFromString("https://127.0.0.1:9999/api-kube/api/v1/namespaces/default/pods", JSON.stringify({
|
||||
kind: "PodList",
|
||||
apiVersion: "v1",
|
||||
metadata: {},
|
||||
|
||||
@ -23,7 +23,7 @@ export interface IKubeApiParsed extends IKubeApiLinkRef {
|
||||
}
|
||||
|
||||
export function parseKubeApi(path: string): IKubeApiParsed {
|
||||
const apiPath = new URL(path, "http://localhost").pathname;
|
||||
const apiPath = new URL(path, "https://localhost").pathname;
|
||||
const [, prefix, ...parts] = apiPath.split("/");
|
||||
const apiPrefix = `/${prefix}`;
|
||||
const [left, right, namespaced] = splitArray(parts, "namespaces");
|
||||
|
||||
@ -51,7 +51,7 @@ export interface BaseKubeJsonApiObjectMetadata<Namespaced extends KubeObjectScop
|
||||
* external tools to store and retrieve arbitrary metadata. They are not queryable and should be
|
||||
* preserved when modifying objects.
|
||||
*
|
||||
* More info: http://kubernetes.io/docs/user-guide/annotations
|
||||
* More info: https://kubernetes.io/docs/user-guide/annotations
|
||||
*/
|
||||
annotations?: Partial<Record<string, string>>;
|
||||
|
||||
@ -136,7 +136,7 @@ export interface BaseKubeJsonApiObjectMetadata<Namespaced extends KubeObjectScop
|
||||
* Map of string keys and values that can be used to organize and categorize (scope and select)
|
||||
* objects. May match selectors of replication controllers and services.
|
||||
*
|
||||
* More info: http://kubernetes.io/docs/user-guide/labels
|
||||
* More info: https://kubernetes.io/docs/user-guide/labels
|
||||
*/
|
||||
labels?: Partial<Record<string, string>>;
|
||||
|
||||
@ -154,7 +154,7 @@ export interface BaseKubeJsonApiObjectMetadata<Namespaced extends KubeObjectScop
|
||||
* resources may allow a client to request the generation of an appropriate name automatically.
|
||||
* Name is primarily intended for creation idempotence and configuration definition.
|
||||
*
|
||||
* More info: http://kubernetes.io/docs/user-guide/identifiers#names
|
||||
* More info: https://kubernetes.io/docs/user-guide/identifiers#names
|
||||
*/
|
||||
readonly name: string;
|
||||
|
||||
@ -162,7 +162,7 @@ export interface BaseKubeJsonApiObjectMetadata<Namespaced extends KubeObjectScop
|
||||
* Namespace defines the space within which each name must be unique. An empty namespace is
|
||||
* equivalent to the "default" namespace, but "default" is the canonical representation. Not all
|
||||
* objects are required to be scoped to a namespace - the value of this field for those objects
|
||||
* will be empty. Must be a DNS_LABEL. Cannot be updated. More info: http://kubernetes.io/docs/user-guide/namespaces
|
||||
* will be empty. Must be a DNS_LABEL. Cannot be updated. More info: https://kubernetes.io/docs/user-guide/namespaces
|
||||
*/
|
||||
readonly namespace?: ScopedNamespace<Namespaced>;
|
||||
|
||||
@ -196,7 +196,7 @@ export interface BaseKubeJsonApiObjectMetadata<Namespaced extends KubeObjectScop
|
||||
* server on successful creation of a resource and is not allowed to change on PUT operations.
|
||||
* Populated by the system.
|
||||
*
|
||||
* More info: http://kubernetes.io/docs/user-guide/identifiers#uids
|
||||
* More info: https://kubernetes.io/docs/user-guide/identifiers#uids
|
||||
*/
|
||||
readonly uid?: string;
|
||||
|
||||
|
||||
@ -8,3 +8,7 @@ export interface RequestChannel<Request, Response> {
|
||||
_requestSignature?: Request; // used only to mark `Request` as "used"
|
||||
_responseSignature?: Response; // used only to mark `Response` as "used"
|
||||
}
|
||||
|
||||
export const getRequestChannel = <Request, Response>(id: string): RequestChannel<Request, Response> => ({
|
||||
id,
|
||||
});
|
||||
|
||||
@ -9,11 +9,11 @@ import lensAuthenticatedFetchInjectable from "../fetch/lens-authed-fetch.injecta
|
||||
const requestAppVersionInjectable = getInjectable({
|
||||
id: "request-app-version",
|
||||
instantiate: (di) => {
|
||||
const lensAuthenticatedFetch = di.inject(lensAuthenticatedFetchInjectable);
|
||||
const fetch = di.inject(lensAuthenticatedFetchInjectable);
|
||||
const lensProxyPort = di.inject(lensProxyPortInjectable);
|
||||
|
||||
return async () => {
|
||||
const response = await lensAuthenticatedFetch(`http://127.0.0.1:${lensProxyPort.get()}/version`);
|
||||
const response = await fetch(`https://127.0.0.1:${lensProxyPort.get()}/version`);
|
||||
const body = await response.json() as { version: string };
|
||||
|
||||
return body.version;
|
||||
|
||||
@ -16,7 +16,7 @@ export default getGlobalOverride(applicationInformationInjectable, () => ({
|
||||
bundledKubectlVersion: "1.23.3",
|
||||
bundledHelmVersion: "3.7.2",
|
||||
sentryDsn: "",
|
||||
contentSecurityPolicy: "script-src 'unsafe-eval' 'self'; frame-src http://*.localhost:*/; img-src * data:",
|
||||
contentSecurityPolicy: "script-src 'unsafe-eval' 'self'; frame-src https://*.localhost:*/; img-src * data:",
|
||||
welcomeRoute: "/welcome",
|
||||
extensions: [],
|
||||
},
|
||||
|
||||
@ -20,7 +20,7 @@ import directoryForKubeConfigsInjectable from "../../../common/app-paths/directo
|
||||
import joinPathsInjectable from "../../../common/path/join-paths.injectable";
|
||||
|
||||
const currentClusterServerUrl = "https://localhost";
|
||||
const nonCurrentClusterServerUrl = "http://localhost";
|
||||
const nonCurrentClusterServerUrl = "https://localhost";
|
||||
const multiClusterConfig = `
|
||||
apiVersion: v1
|
||||
clusters:
|
||||
@ -48,7 +48,7 @@ users:
|
||||
token: kubeconfig-user-q4lm4:xxxyyyy
|
||||
`;
|
||||
|
||||
const singleClusterServerUrl = "http://localhost";
|
||||
const singleClusterServerUrl = "https://localhost";
|
||||
const singleClusterConfig = `
|
||||
apiVersion: v1
|
||||
clusters:
|
||||
|
||||
@ -146,7 +146,7 @@ describe("add custom helm repository in preferences", () => {
|
||||
|
||||
const urlInput = rendered.getByTestId("custom-helm-repository-url-input");
|
||||
|
||||
fireEvent.change(urlInput, { target: { value: "http://some.url" }});
|
||||
fireEvent.change(urlInput, { target: { value: "https://some.url" }});
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
@ -170,7 +170,7 @@ describe("add custom helm repository in preferences", () => {
|
||||
it("adds the repository", () => {
|
||||
expect(execFileMock).toHaveBeenCalledWith(
|
||||
"some-helm-binary-path",
|
||||
["repo", "add", "some-custom-repository", "http://some.url"],
|
||||
["repo", "add", "some-custom-repository", "https://some.url"],
|
||||
{
|
||||
maxBuffer: 34359738368,
|
||||
env: {},
|
||||
@ -224,7 +224,7 @@ describe("add custom helm repository in preferences", () => {
|
||||
await execFileMock.resolveSpecific(
|
||||
[
|
||||
"some-helm-binary-path",
|
||||
["repo", "add", "some-custom-repository", "http://some.url"],
|
||||
["repo", "add", "some-custom-repository", "https://some.url"],
|
||||
],
|
||||
{
|
||||
callWasSuccessful: true,
|
||||
@ -365,7 +365,7 @@ describe("add custom helm repository in preferences", () => {
|
||||
"repo",
|
||||
"add",
|
||||
"some-custom-repository",
|
||||
"http://some.url",
|
||||
"https://some.url",
|
||||
"--insecure-skip-tls-verify",
|
||||
"--username",
|
||||
"some-username",
|
||||
|
||||
@ -23,7 +23,7 @@ const NonInjectedHttpProxyUrl = observer(
|
||||
<SubTitle title="HTTP Proxy" />
|
||||
<Input
|
||||
theme="round-black"
|
||||
placeholder="Type HTTP proxy url (example: http://proxy.acme.org:8080)"
|
||||
placeholder="Type HTTP proxy url (example: https://proxy.acme.org:8080)"
|
||||
value={proxy}
|
||||
onChange={(v) => setProxy(v)}
|
||||
onBlur={() => (userStore.httpsProxy = proxy)}
|
||||
|
||||
@ -132,7 +132,7 @@ describe("opening application window using tray", () => {
|
||||
});
|
||||
|
||||
it("starts loading of content for the application window", () => {
|
||||
expect(callForApplicationWindowHtmlMock).toHaveBeenCalledWith("http://localhost:42");
|
||||
expect(callForApplicationWindowHtmlMock).toHaveBeenCalledWith("https://localhost:42");
|
||||
});
|
||||
|
||||
describe("given static HTML of application window has not resolved yet, when opening from tray again", () => {
|
||||
|
||||
@ -108,7 +108,7 @@ describe("ContextHandler", () => {
|
||||
id: "some-cluster-id",
|
||||
kubeConfigPath: "/some/path/to/kubeconfig",
|
||||
}, {
|
||||
clusterServerUrl: "http://localhost:81",
|
||||
clusterServerUrl: "https://localhost:81",
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@ -174,7 +174,7 @@ describe("kubeconfig manager tests", () => {
|
||||
describe("when writing out new proxy kubeconfig resolves", () => {
|
||||
beforeEach(async () => {
|
||||
await writeFileMock.resolveSpecific(
|
||||
["/some-directory-for-temp/kubeconfig-foo", "apiVersion: v1\nkind: Config\npreferences: {}\ncurrent-context: minikube\nclusters:\n - name: minikube\n cluster:\n server: http://127.0.0.1:9191/foo\ncontexts:\n - name: minikube\n context:\n cluster: minikube\n user: proxy\nusers:\n - name: proxy\n user: {}\n"],
|
||||
["/some-directory-for-temp/kubeconfig-foo", "apiVersion: v1\nkind: Config\npreferences: {}\ncurrent-context: minikube\nclusters:\n - name: minikube\n cluster:\n server: https://127.0.0.1:9191/foo\ncontexts:\n - name: minikube\n context:\n cluster: minikube\n user: proxy\nusers:\n - name: proxy\n user: {}\n"],
|
||||
);
|
||||
});
|
||||
|
||||
@ -300,7 +300,7 @@ describe("kubeconfig manager tests", () => {
|
||||
describe("when writing out new proxy kubeconfig resolves", () => {
|
||||
beforeEach(async () => {
|
||||
await writeFileMock.resolveSpecific(
|
||||
["/some-directory-for-temp/kubeconfig-foo", "apiVersion: v1\nkind: Config\npreferences: {}\ncurrent-context: minikube\nclusters:\n - name: minikube\n cluster:\n server: http://127.0.0.1:9191/foo\ncontexts:\n - name: minikube\n context:\n cluster: minikube\n user: proxy\nusers:\n - name: proxy\n user: {}\n"],
|
||||
["/some-directory-for-temp/kubeconfig-foo", "apiVersion: v1\nkind: Config\npreferences: {}\ncurrent-context: minikube\nclusters:\n - name: minikube\n cluster:\n server: https://127.0.0.1:9191/foo\ncontexts:\n - name: minikube\n context:\n cluster: minikube\n user: proxy\nusers:\n - name: proxy\n user: {}\n"],
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
@ -25,7 +25,7 @@ const k8sRequestInjectable = getInjectable({
|
||||
path: string,
|
||||
options: RequestPromiseOptions = {},
|
||||
) => {
|
||||
const kubeProxyUrl = `http://localhost:${lensProxyPort.get()}${apiKubePrefix}`;
|
||||
const kubeProxyUrl = `https://localhost:${lensProxyPort.get()}${apiKubePrefix}`;
|
||||
|
||||
options.headers ??= {};
|
||||
options.json ??= true;
|
||||
|
||||
@ -11,7 +11,7 @@ const apiBaseServerAddressInjectable = getInjectable({
|
||||
instantiate: (di) => {
|
||||
const lensProxyPort = di.inject(lensProxyPortInjectable);
|
||||
|
||||
return `http://127.0.0.1:${lensProxyPort.get()}`;
|
||||
return `https://127.0.0.1:${lensProxyPort.get()}`;
|
||||
},
|
||||
injectionToken: apiBaseServerAddressInjectionToken,
|
||||
});
|
||||
|
||||
@ -15,6 +15,7 @@ import pathExistsInjectable from "../../common/fs/path-exists.injectable";
|
||||
import writeFileInjectable from "../../common/fs/write-file.injectable";
|
||||
import removePathInjectable from "../../common/fs/remove.injectable";
|
||||
import authHeaderValueInjectable from "../lens-proxy/auth-header-value.injectable";
|
||||
import lensProxyCertificateInjectable from "../lens-proxy/certificate.injectable";
|
||||
|
||||
export interface KubeConfigManagerInstantiationParameter {
|
||||
cluster: Cluster;
|
||||
@ -31,6 +32,7 @@ const createKubeconfigManagerInjectable = getInjectable({
|
||||
logger: di.inject(loggerInjectable),
|
||||
lensProxyPort: di.inject(lensProxyPortInjectable),
|
||||
authHeaderValue: di.inject(authHeaderValueInjectable),
|
||||
lensProxyCertificate: di.inject(lensProxyCertificateInjectable),
|
||||
joinPaths: di.inject(joinPathsInjectable),
|
||||
getDirnameOfPath: di.inject(getDirnameOfPathInjectable),
|
||||
removePath: di.inject(removePathInjectable),
|
||||
|
||||
@ -16,12 +16,14 @@ import type { PathExists } from "../../common/fs/path-exists.injectable";
|
||||
import type { RemovePath } from "../../common/fs/remove.injectable";
|
||||
import type { WriteFile } from "../../common/fs/write-file.injectable";
|
||||
import { lensAuthenticationHeader } from "../../common/vars/auth-header";
|
||||
import type { SelfSignedCert } from "selfsigned";
|
||||
|
||||
export interface KubeconfigManagerDependencies {
|
||||
readonly directoryForTemp: string;
|
||||
readonly logger: Logger;
|
||||
readonly lensProxyPort: { get: () => number };
|
||||
readonly authHeaderValue: string;
|
||||
readonly lensProxyCertificate: SelfSignedCert;
|
||||
joinPaths: JoinPaths;
|
||||
getDirnameOfPath: GetDirnameOfPath;
|
||||
pathExists: PathExists;
|
||||
@ -108,7 +110,9 @@ export class KubeconfigManager {
|
||||
clusters: [
|
||||
{
|
||||
name: contextName,
|
||||
server: `http://127.0.0.1:${this.dependencies.lensProxyPort.get()}/${this.cluster.id}?${searchParams}`,
|
||||
caData: Buffer.from(this.dependencies.lensProxyCertificate.cert).toString("base64"),
|
||||
server: `https://127.0.0.1:${this.dependencies.lensProxyPort.get()}/${this.cluster.id}?${searchParams}`,
|
||||
skipTLSVerify: false,
|
||||
},
|
||||
],
|
||||
users: [
|
||||
|
||||
36
src/main/lens-proxy/certificate.injectable.ts
Normal file
36
src/main/lens-proxy/certificate.injectable.ts
Normal file
@ -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 { generate } from "selfsigned";
|
||||
import { lensProxyCertificateInjectionToken } from "../../common/certificate/token";
|
||||
|
||||
const lensProxyCertificateInjectable = getInjectable({
|
||||
id: "lens-proxy-certificate",
|
||||
instantiate: () => generate([
|
||||
{ name: "commonName", value: "Lens Certificate Authority" },
|
||||
{ name: "organizationName", value: "Lens" },
|
||||
], {
|
||||
keySize: 2048,
|
||||
algorithm: "sha256",
|
||||
days: 365,
|
||||
extensions: [
|
||||
{
|
||||
name: "basicConstraints",
|
||||
cA: true,
|
||||
},
|
||||
{
|
||||
name: "subjectAltName",
|
||||
altNames: [
|
||||
{ type: 2, value: "*.localhost" },
|
||||
{ type: 2, value: "localhost" },
|
||||
{ type: 7, ip: "127.0.0.1" },
|
||||
],
|
||||
},
|
||||
],
|
||||
}),
|
||||
injectionToken: lensProxyCertificateInjectionToken,
|
||||
});
|
||||
|
||||
export default lensProxyCertificateInjectable;
|
||||
18
src/main/lens-proxy/handle-request-cert.injectable.ts
Normal file
18
src/main/lens-proxy/handle-request-cert.injectable.ts
Normal file
@ -0,0 +1,18 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { lensProxyCertificateChannel } from "../../common/certificate/channel";
|
||||
import { getRequestChannelListenerInjectable } from "../utils/channel/channel-listeners/listener-tokens";
|
||||
import lensProxyCertificateInjectable from "./certificate.injectable";
|
||||
|
||||
const lensProxyCertificateHandlerInjectable = getRequestChannelListenerInjectable({
|
||||
channel: lensProxyCertificateChannel,
|
||||
handler: (di) => {
|
||||
const cert = di.inject(lensProxyCertificateInjectable);
|
||||
|
||||
return () => cert;
|
||||
},
|
||||
});
|
||||
|
||||
export default lensProxyCertificateHandlerInjectable;
|
||||
@ -14,6 +14,7 @@ import contentSecurityPolicyInjectable from "../../common/vars/content-security-
|
||||
import emitAppEventInjectable from "../../common/app-event-bus/emit-event.injectable";
|
||||
import loggerInjectable from "../../common/logger.injectable";
|
||||
import authHeaderValueInjectable from "./auth-header-value.injectable";
|
||||
import lensProxyCertificateInjectable from "./certificate.injectable";
|
||||
|
||||
const lensProxyInjectable = getInjectable({
|
||||
id: "lens-proxy",
|
||||
@ -29,6 +30,7 @@ const lensProxyInjectable = getInjectable({
|
||||
emitAppEvent: di.inject(emitAppEventInjectable),
|
||||
logger: di.inject(loggerInjectable),
|
||||
authHeaderValue: di.inject(authHeaderValueInjectable),
|
||||
certificate: di.inject(lensProxyCertificateInjectable),
|
||||
}),
|
||||
});
|
||||
|
||||
|
||||
@ -4,7 +4,8 @@
|
||||
*/
|
||||
|
||||
import net from "net";
|
||||
import http from "http";
|
||||
import type http from "http";
|
||||
import https from "https";
|
||||
import type httpProxy from "http-proxy";
|
||||
import { apiPrefix, apiKubePrefix } from "../../common/vars";
|
||||
import type { ClusterContextHandler } from "../context-handler/context-handler";
|
||||
@ -20,6 +21,7 @@ import { lensAuthenticationHeader } from "../../common/vars/auth-header";
|
||||
import { contentTypes } from "../router/router-content-types";
|
||||
import { writeServerResponseFor } from "../router/write-server-response";
|
||||
import { URL } from "url";
|
||||
import type { SelfSignedCert } from "selfsigned";
|
||||
|
||||
type GetClusterForRequest = (req: http.IncomingMessage) => Cluster | undefined;
|
||||
|
||||
@ -36,13 +38,14 @@ interface Dependencies {
|
||||
readonly contentSecurityPolicy: string;
|
||||
readonly logger: Logger;
|
||||
readonly authHeaderValue: string;
|
||||
readonly certificate: SelfSignedCert;
|
||||
}
|
||||
|
||||
const watchParam = "watch";
|
||||
const followParam = "follow";
|
||||
|
||||
export function isLongRunningRequest(reqUrl: string) {
|
||||
const url = new URL(reqUrl, "http://localhost");
|
||||
const url = new URL(reqUrl, "https://localhost");
|
||||
|
||||
return getBoolean(url.searchParams, watchParam) || getBoolean(url.searchParams, followParam);
|
||||
}
|
||||
@ -71,16 +74,22 @@ export class LensProxy {
|
||||
protected readonly retryCounters = new Map<string, number>();
|
||||
|
||||
constructor(private readonly dependencies: Dependencies) {
|
||||
this.configureProxy(dependencies.proxy);
|
||||
this.configureProxy(this.dependencies.proxy);
|
||||
|
||||
this.proxyServer = http.createServer((req, res) => {
|
||||
this.handleRequest(req as ServerIncomingMessage, res);
|
||||
});
|
||||
this.proxyServer = https.createServer(
|
||||
{
|
||||
key: this.dependencies.certificate.private,
|
||||
cert: this.dependencies.certificate.cert,
|
||||
},
|
||||
(req, res) => {
|
||||
this.handleRequest(req as ServerIncomingMessage, res);
|
||||
},
|
||||
);
|
||||
|
||||
this.proxyServer
|
||||
.on("upgrade", (req: ServerIncomingMessage, socket: net.Socket, head: Buffer) => {
|
||||
const cluster = this.dependencies.getClusterForRequest(req);
|
||||
const url = new URL(req.url, "http://localhost");
|
||||
const url = new URL(req.url, "https://localhost");
|
||||
|
||||
if (url.searchParams.get(lensAuthenticationHeader) !== this.dependencies.authHeaderValue) {
|
||||
this.dependencies.logger.warn(`[LENS-PROXY]: Request from url=${req.url} missing authentication`);
|
||||
|
||||
@ -79,7 +79,7 @@ const routeRequestInjectable = getInjectable({
|
||||
const getRequest = getRequestWith(di);
|
||||
|
||||
return async (cluster, req, res) => {
|
||||
const url = new URL(req.url, "http://localhost");
|
||||
const url = new URL(req.url, "https://localhost");
|
||||
const path = url.pathname;
|
||||
const method = req.method.toLowerCase();
|
||||
const matchingRoute = router.route(method, path);
|
||||
|
||||
@ -14,7 +14,7 @@ const devStaticFileRouteHandlerInjectable = getInjectable({
|
||||
instantiate: (di) => {
|
||||
const proxy = httpProxy.createProxy();
|
||||
const appName = di.inject(appNameInjectable);
|
||||
const proxyTarget = `http://127.0.0.1:${webpackDevServerPort}`;
|
||||
const proxyTarget = `https://127.0.0.1:${webpackDevServerPort}`;
|
||||
|
||||
return async ({ raw: { req, res }}: LensApiRequest<"/{path*}">): Promise<RouteResponse<Buffer>> => {
|
||||
if (req.url === "/" || !req.url) {
|
||||
|
||||
@ -33,7 +33,7 @@ const createApplicationWindowInjectable = getInjectable({
|
||||
defaultHeight: 900,
|
||||
defaultWidth: 1440,
|
||||
getContentSource: () => ({
|
||||
url: `http://localhost:${lensProxyPort.get()}`,
|
||||
url: `https://localhost:${lensProxyPort.get()}`,
|
||||
}),
|
||||
resizable: true,
|
||||
windowFrameUtilitiesAreShown: isMac,
|
||||
|
||||
@ -14,6 +14,8 @@ import lensResourcesDirInjectable from "../../../../common/vars/lens-resources-d
|
||||
import isLinuxInjectable from "../../../../common/vars/is-linux.injectable";
|
||||
import applicationInformationInjectable from "../../../../common/vars/application-information.injectable";
|
||||
import pathExistsSyncInjectable from "../../../../common/fs/path-exists-sync.injectable";
|
||||
import lensProxyCertificateInjectable from "../../../lens-proxy/certificate.injectable";
|
||||
import { timingSafeEqual, X509Certificate } from "crypto";
|
||||
|
||||
|
||||
export type ElectronWindowTitleBarStyle = "hiddenInset" | "hidden" | "default" | "customButtonsOnHover";
|
||||
@ -56,6 +58,8 @@ const createElectronWindowInjectable = getInjectable({
|
||||
const isLinux = di.inject(isLinuxInjectable);
|
||||
const applicationInformation = di.inject(applicationInformationInjectable);
|
||||
const pathExistsSync = di.inject(pathExistsSyncInjectable);
|
||||
const lensProxyCertificate = di.inject(lensProxyCertificateInjectable);
|
||||
const lensProxyCert = new X509Certificate(lensProxyCertificate.cert);
|
||||
|
||||
return (configuration) => {
|
||||
const applicationWindowState = di.inject(
|
||||
@ -123,6 +127,13 @@ const createElectronWindowInjectable = getInjectable({
|
||||
.webContents.on("dom-ready", () => {
|
||||
configuration.onDomReady?.();
|
||||
})
|
||||
.on("certificate-error", (event, url, error, certificate, shouldBeTrusted) => {
|
||||
const cert = new X509Certificate(certificate.data);
|
||||
const shouldTrustCert = cert.raw.length === lensProxyCert.raw.length
|
||||
&& timingSafeEqual(cert.raw, lensProxyCert.raw);
|
||||
|
||||
shouldBeTrusted(shouldTrustCert);
|
||||
})
|
||||
.on("did-fail-load", (_event, code, desc) => {
|
||||
logger.error(
|
||||
`[CREATE-ELECTRON-WINDOW]: Failed to load window "${configuration.id}"`,
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { lensAuthenticationChannel } from "../../common/auth/channel";
|
||||
import { beforeFrameStartsInjectionToken } from "../before-frame-starts/before-frame-starts-injection-token";
|
||||
import { beforeFrameStartsInjectionToken } from "../before-frame-starts/tokens";
|
||||
import requestFromChannelInjectable from "../utils/channel/request-from-channel.injectable";
|
||||
import authHeaderValueStateInjectable from "./auth-header-state.injectable";
|
||||
|
||||
|
||||
15
src/renderer/certificate/certificate.injectable.ts
Normal file
15
src/renderer/certificate/certificate.injectable.ts
Normal file
@ -0,0 +1,15 @@
|
||||
/**
|
||||
* 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 { lensProxyCertificateInjectionToken } from "../../common/certificate/token";
|
||||
import lensProxyCertificateStateInjectable from "./state.injectable";
|
||||
|
||||
const lensProxyCertificateInjectable = getInjectable({
|
||||
id: "lens-proxy-certificate",
|
||||
instantiate: (di) => di.inject(lensProxyCertificateStateInjectable).get(),
|
||||
injectionToken: lensProxyCertificateInjectionToken,
|
||||
});
|
||||
|
||||
export default lensProxyCertificateInjectable;
|
||||
24
src/renderer/certificate/init.injectable.ts
Normal file
24
src/renderer/certificate/init.injectable.ts
Normal file
@ -0,0 +1,24 @@
|
||||
/**
|
||||
* 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 { evenBeforeFrameStartsInjectionToken } from "../before-frame-starts/tokens";
|
||||
import requestLensProxyCertificateInjectable from "./request.injectable";
|
||||
import lensProxyCertificateStateInjectable from "./state.injectable";
|
||||
|
||||
const initLensProxyCertificateStateInjectable = getInjectable({
|
||||
id: "init-lens-proxy-certificate-state",
|
||||
instantiate: (di) => ({
|
||||
id: "init-lens-proxy-certificate-state",
|
||||
run: async () => {
|
||||
const lensProxyCertificateState = di.inject(lensProxyCertificateStateInjectable);
|
||||
const requestLensProxyCertificate = di.inject(requestLensProxyCertificateInjectable);
|
||||
|
||||
lensProxyCertificateState.set(await requestLensProxyCertificate());
|
||||
},
|
||||
}),
|
||||
injectionToken: evenBeforeFrameStartsInjectionToken,
|
||||
});
|
||||
|
||||
export default initLensProxyCertificateStateInjectable;
|
||||
18
src/renderer/certificate/request.injectable.ts
Normal file
18
src/renderer/certificate/request.injectable.ts
Normal file
@ -0,0 +1,18 @@
|
||||
/**
|
||||
* 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 { lensProxyCertificateChannel } from "../../common/certificate/channel";
|
||||
import requestFromChannelInjectable from "../utils/channel/request-from-channel.injectable";
|
||||
|
||||
const requestLensProxyCertificateInjectable = getInjectable({
|
||||
id: "request-lens-proxy-certificate",
|
||||
instantiate: (di) => {
|
||||
const requestFromChannel = di.inject(requestFromChannelInjectable);
|
||||
|
||||
return () => requestFromChannel(lensProxyCertificateChannel);
|
||||
},
|
||||
});
|
||||
|
||||
export default requestLensProxyCertificateInjectable;
|
||||
32
src/renderer/certificate/state.injectable.ts
Normal file
32
src/renderer/certificate/state.injectable.ts
Normal file
@ -0,0 +1,32 @@
|
||||
/**
|
||||
* 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 type { SelfSignedCert } from "selfsigned";
|
||||
|
||||
const lensProxyCertificateStateInjectable = getInjectable({
|
||||
id: "lens-proxy-certificate-state",
|
||||
instantiate: () => {
|
||||
let state: SelfSignedCert | undefined = undefined;
|
||||
|
||||
return {
|
||||
get: () => {
|
||||
if (!state) {
|
||||
throw new Error("Tried to use lensProxyCertificate before initialization");
|
||||
}
|
||||
|
||||
return state;
|
||||
},
|
||||
set: (cert: SelfSignedCert) => {
|
||||
if (state) {
|
||||
throw new Error("Tried to initialize lensProxyCertificate more than once");
|
||||
}
|
||||
|
||||
state = cert;
|
||||
},
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
export default lensProxyCertificateStateInjectable;
|
||||
@ -21,7 +21,7 @@ export const HelmChartIcon = ({
|
||||
if (!icon || failedToLoad) {
|
||||
return (
|
||||
<div className={className}>
|
||||
<svg viewBox="0 0 722.8 702" xmlns="http://www.w3.org/2000/svg">
|
||||
<svg viewBox="0 0 722.8 702" xmlns="https://www.w3.org/2000/svg">
|
||||
<g fill="currentColor">
|
||||
<path d="m318 299.5c2.1 1.6 4.8 2.5 7.6 2.5 6.9 0 12.6-5.5 12.9-12.3l.3-.2 4.3-76.7c-5.2.6-10.4 1.5-15.6 2.7-28.5 6.5-53.2 20.5-72.6 39.5l62.9 44.6z"/>
|
||||
<path d="m309.5 411.9c-1.4-5.9-6.6-9.9-12.4-10-.8 0-1.7.1-2.5.2l-.1-.2-75.5 12.8c11.7 32.2 33.4 58.5 60.8 76.1l29.2-70.7-.2-.3c1.1-2.4 1.4-5.2.7-7.9z"/>
|
||||
|
||||
@ -48,7 +48,7 @@ export class ClusterProxySetting extends React.Component<ClusterProxySettingProp
|
||||
value={this.proxy}
|
||||
onChange={this.onChange}
|
||||
onBlur={this.save}
|
||||
placeholder="http://<address>:<port>"
|
||||
placeholder="https://<address>:<port>"
|
||||
validators={this.proxy ? InputValidators.isUrl : undefined}
|
||||
/>
|
||||
<small className="hint">
|
||||
|
||||
@ -35,14 +35,14 @@ describe("<Icon> href technical tests", () => {
|
||||
const result = render((
|
||||
<Icon
|
||||
data-testid="my-icon"
|
||||
href="http://localhost"
|
||||
href="https://localhost"
|
||||
/>
|
||||
));
|
||||
|
||||
const icon = result.queryByTestId("my-icon");
|
||||
|
||||
expect(icon).toBeInTheDocument();
|
||||
expect(icon).toHaveAttribute("href", "http://localhost");
|
||||
expect(icon).toHaveAttribute("href", "https://localhost");
|
||||
expect(logger.warn).not.toBeCalled();
|
||||
});
|
||||
|
||||
|
||||
@ -27,7 +27,7 @@ describe("input validation tests", () => {
|
||||
|
||||
it.each([
|
||||
"https://github-production-registry-package-file-4f11e5.s3.amazonaws.com/307985088/68bbbf00-309f-11eb-8457-a15e4efe9e77?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIWNJYAX4CSVEH53A%2F20201127%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20201127T123754Z&X-Amz-Expires=300&X-Amz-Signature=9b8167f00685a20d980224d397892195abc187cdb2934cefb79edcd7ec600f78&X-Amz-SignedHeaders=host&actor_id=0&key_id=0&repo_id=0&response-content-disposition=filename%3Dstarboard-lens-extension-0.0.1-alpha.1-npm.tgz&response-content-type=application%2Foctet-stream",
|
||||
"http://www.google.com",
|
||||
"https://www.google.com",
|
||||
])("Given '%s' is a valid url, emailOrUrl matches", (input) => {
|
||||
expect(emailOrUrl.validate(input)).toBe(true);
|
||||
});
|
||||
@ -62,7 +62,7 @@ describe("input validation tests", () => {
|
||||
|
||||
it.each([
|
||||
"https://github-production-registry-package-file-4f11e5.s3.amazonaws.com/307985088/68bbbf00-309f-11eb-8457-a15e4efe9e77?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIWNJYAX4CSVEH53A%2F20201127%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20201127T123754Z&X-Amz-Expires=300&X-Amz-Signature=9b8167f00685a20d980224d397892195abc187cdb2934cefb79edcd7ec600f78&X-Amz-SignedHeaders=host&actor_id=0&key_id=0&repo_id=0&response-content-disposition=filename%3Dstarboard-lens-extension-0.0.1-alpha.1-npm.tgz&response-content-type=application%2Foctet-stream",
|
||||
"http://www.google.com",
|
||||
"https://www.google.com",
|
||||
])("Given '%s' is a valid url, emailOrUrl matches", async (input) => {
|
||||
try {
|
||||
await emailOrUrl.validate(input);
|
||||
|
||||
@ -11,7 +11,7 @@ const apiBaseServerAddressInjectable = getInjectable({
|
||||
instantiate: (di) => {
|
||||
const { port } = di.inject(windowLocationInjectable);
|
||||
|
||||
return `http://127.0.0.1:${port}`;
|
||||
return `https://127.0.0.1:${port}`;
|
||||
},
|
||||
injectionToken: apiBaseServerAddressInjectionToken,
|
||||
});
|
||||
|
||||
@ -25,7 +25,7 @@ const apiKubeInjectable = getInjectable({
|
||||
const lensAuthenticationHeaderValue = di.inject(lensAuthenticationHeaderValueInjectionToken);
|
||||
|
||||
const apiKube = createKubeJsonApi({
|
||||
serverAddress: `http://127.0.0.1:${port}`,
|
||||
serverAddress: `https://127.0.0.1:${port}`,
|
||||
apiBase: apiKubePrefix,
|
||||
debug: isDevelopment,
|
||||
}, {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user