Skip to content

Commit 71c1e4f

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 5e6d2fb commit 71c1e4f

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';
@@ -23,7 +28,6 @@ import { VsCommandError, vsCommand } from '../vscommand';
2328
import { OpenShiftTerminalManager } from '../webview/openshift-terminal/openShiftTerminal';
2429
import OpenShiftItem, { clusterRequired } from './openshiftItem';
2530
import fetch = require('make-fetch-happen');
26-
import { Cluster as KcuCluster, Context as KcuContext } from '@kubernetes/client-node/dist/config_types';
2731

2832
export interface QuickPickItemExt extends QuickPickItem {
2933
name: string,
@@ -837,20 +841,26 @@ export class Cluster extends OpenShiftItem {
837841
} else {
838842
ocToken = userToken;
839843
}
840-
return Progress.execFunctionWithProgress(`Login to the cluster: ${clusterURL}`, () =>
841-
Oc.Instance.loginWithToken(clusterURL, ocToken)
842-
.then(() => Cluster.loginMessage(clusterURL))
843-
.catch((error) =>
844-
Promise.reject(
845-
new VsCommandError(
846-
`Failed to login to cluster '${clusterURL}' with '${Filters.filterToken(
847-
error.message,
848-
)}'!`,
849-
'Failed to login to cluster',
850-
),
851-
),
852-
),
853-
);
844+
return Progress.execFunctionWithProgress(`Login to the cluster: ${clusterURL}`, async () => {
845+
try {
846+
await Oc.Instance.loginWithToken(clusterURL, ocToken);
847+
if (Cluster.isOpenShiftSandbox(clusterURL)) {
848+
const YES = 'Yes';
849+
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');
850+
if (result === YES) {
851+
await Cluster.installPipelineUserContext();
852+
}
853+
}
854+
return Cluster.loginMessage(clusterURL);
855+
} catch (error) {
856+
throw new VsCommandError(
857+
`Failed to login to cluster '${clusterURL}' with '${Filters.filterToken(
858+
error.message,
859+
)}'!`,
860+
'Failed to login to cluster',
861+
);
862+
}
863+
});
854864
}
855865

856866
static validateLoginToken(token: string): boolean {
@@ -877,6 +887,35 @@ export class Cluster extends OpenShiftItem {
877887
return Cluster.tokenLogin(apiEndpointUrl, true, clipboard);
878888
}
879889

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

0 commit comments

Comments
 (0)