Skip to content

Commit 5c6c680

Browse files
committed
Switch to service account after logging into OpenShift Sandbox
The service account will remain authenticated for longer than 15 minutes. To try this out: 1. Log into an OpenShift Sandbox cluster using the Login workflow 2. Run `oc whoami`. You should see a reference to `pipeline`, which is the serviceaccount that's being used 3. The Application Explorer should display you as logged in and work as expected Closes #3838 Signed-off-by: David Thompson <davthomp@redhat.com>
1 parent 7c311a7 commit 5c6c680

File tree

1 file changed

+59
-15
lines changed

1 file changed

+59
-15
lines changed

src/openshift/cluster.ts

Lines changed: 59 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@
44
*-----------------------------------------------------------------------------------------------*/
55

66
import { KubernetesObject } from '@kubernetes/client-node';
7+
import { Cluster as KcuCluster, Context as KcuContext } from '@kubernetes/client-node/dist/config_types';
8+
import * as fs from 'fs/promises';
9+
import * as YAML from 'js-yaml';
10+
import { homedir } from 'os';
11+
import * as path from 'path';
712
import { ExtensionContext, QuickInputButtons, QuickPickItem, QuickPickItemButtonEvent, ThemeIcon, Uri, commands, env, window, workspace } from 'vscode';
813
import { CommandText } from '../base/command';
914
import { CliChannel } from '../cli';
@@ -22,7 +27,6 @@ import { VsCommandError, vsCommand } from '../vscommand';
2227
import { OpenShiftTerminalManager } from '../webview/openshift-terminal/openShiftTerminal';
2328
import OpenShiftItem, { clusterRequired } from './openshiftItem';
2429
import fetch = require('make-fetch-happen');
25-
import { Cluster as KcuCluster, Context as KcuContext } from '@kubernetes/client-node/dist/config_types';
2630

2731
export interface QuickPickItemExt extends QuickPickItem {
2832
name: string,
@@ -838,20 +842,26 @@ export class Cluster extends OpenShiftItem {
838842
} else {
839843
ocToken = userToken;
840844
}
841-
return Progress.execFunctionWithProgress(`Login to the cluster: ${clusterURL}`, () =>
842-
Oc.Instance.loginWithToken(clusterURL, ocToken)
843-
.then(() => Cluster.loginMessage(clusterURL))
844-
.catch((error) =>
845-
Promise.reject(
846-
new VsCommandError(
847-
`Failed to login to cluster '${clusterURL}' with '${Filters.filterToken(
848-
error.message,
849-
)}'!`,
850-
'Failed to login to cluster',
851-
),
852-
),
853-
),
854-
);
845+
return Progress.execFunctionWithProgress(`Login to the cluster: ${clusterURL}`, async () => {
846+
try {
847+
await Oc.Instance.loginWithToken(clusterURL, ocToken);
848+
if (Cluster.isOpenShiftSandbox(clusterURL)) {
849+
const YES = 'Yes';
850+
const result = await window.showInformationMessage('OpenShift Sandbox logs you out after 15 minutes. Would you like to switch to a service account to prevent this?', YES, 'No');
851+
if (result === YES) {
852+
await Cluster.installPipelineUserContext();
853+
}
854+
}
855+
return Cluster.loginMessage(clusterURL);
856+
} catch (error) {
857+
throw new VsCommandError(
858+
`Failed to login to cluster '${clusterURL}' with '${Filters.filterToken(
859+
error.message,
860+
)}'!`,
861+
'Failed to login to cluster',
862+
);
863+
}
864+
});
855865
}
856866

857867
static validateLoginToken(token: string): boolean {
@@ -878,6 +888,35 @@ export class Cluster extends OpenShiftItem {
878888
return Cluster.tokenLogin(apiEndpointUrl, true, clipboard);
879889
}
880890

891+
static async installPipelineUserContext(): Promise<void> {
892+
const kcu = new KubeConfigUtils();
893+
const kcPath = path.join(homedir(), '.kube', 'config');
894+
const kcActual = YAML.load((await fs.readFile(kcPath)).toString('utf-8')) as {
895+
users: { name: string; user: { token: string } }[];
896+
contexts: {
897+
context: { cluster: string; user: string; namespace: string };
898+
name: string;
899+
}[];
900+
'current-context': string;
901+
clusters: object[];
902+
};
903+
904+
const currentCtx = kcu.getCurrentContext();
905+
const currentCtxObj = kcActual.contexts.find(ctx => ctx.name === currentCtx);
906+
const sandboxUser = currentCtxObj.context.user;
907+
const sandboxUserObj = kcActual.users.find(user => user.name === sandboxUser);
908+
909+
const secrets = await Oc.Instance.getKubernetesObjects('Secret');
910+
const pipelineTokenSecret = secrets.find((secret) => secret.metadata.name.startsWith('pipeline-token')) as any;
911+
const pipelineToken = Buffer.from(pipelineTokenSecret.data.token, 'base64').toString();
912+
913+
sandboxUserObj.user = {
914+
token: pipelineToken
915+
}
916+
917+
await fs.writeFile(kcPath, YAML.dump(kcActual, { lineWidth: Number.POSITIVE_INFINITY }));
918+
}
919+
881920
static async loginUsingClipboardInfo(dashboardUrl: string): Promise<string | null> {
882921
const clipboard = await Cluster.readFromClipboard();
883922
if (!NameValidator.ocLoginCommandMatches(clipboard)) {
@@ -899,4 +938,9 @@ export class Cluster extends OpenShiftItem {
899938
await commands.executeCommand('setContext', 'isLoggedIn', true);
900939
return `Successfully logged in to '${clusterURL}'`;
901940
}
941+
942+
static isOpenShiftSandbox(url :string): boolean {
943+
const asUrl = new URL(url);
944+
return asUrl.hostname.endsWith('openshiftapps.com');
945+
}
902946
}

0 commit comments

Comments
 (0)