Skip to content

Commit a1b219d

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 redhat-developer#3838 Signed-off-by: David Thompson <[email protected]>
1 parent 5e6d2fb commit a1b219d

File tree

1 file changed

+73
-15
lines changed

1 file changed

+73
-15
lines changed

src/openshift/cluster.ts

Lines changed: 73 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,22 @@ 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+
await Cluster.installPipelineUserContext();
849+
}
850+
return Cluster.loginMessage(clusterURL);
851+
} catch (error) {
852+
throw new VsCommandError(
853+
`Failed to login to cluster '${clusterURL}' with '${Filters.filterToken(
854+
error.message,
855+
)}'!`,
856+
'Failed to login to cluster',
857+
);
858+
}
859+
});
854860
}
855861

856862
static validateLoginToken(token: string): boolean {
@@ -877,6 +883,53 @@ export class Cluster extends OpenShiftItem {
877883
return Cluster.tokenLogin(apiEndpointUrl, true, clipboard);
878884
}
879885

886+
static async installPipelineUserContext(): Promise<void> {
887+
const SANDBOX_PIPELINE_USER_CTX = 'sandbox-pipeline-user';
888+
const SANDBOX_PIPELINE_USERNAME = 'pipeline';
889+
const kcu = new KubeConfigUtils();
890+
const kcPath = path.join(homedir(), '.kube', 'config');
891+
const kcActual = YAML.load((await fs.readFile(kcPath)).toString('utf-8')) as {
892+
users: { name: string, user: { token: string } }[];
893+
contexts: object[];
894+
'current-context': string;
895+
clusters: object[];
896+
};
897+
898+
const secrets = await Oc.Instance.getKubernetesObjects('Secret')
899+
const pipelineTokenSecret = secrets.find((secret) => secret.metadata.name.startsWith('pipeline-token')) as any;
900+
const pipelineToken = Buffer.from(pipelineTokenSecret.data.token, 'base64').toString()
901+
902+
if (!kcu.contexts.find(ctx => ctx.name === SANDBOX_PIPELINE_USER_CTX)) {
903+
const currentCtx = kcu.getCurrentContext();
904+
const currentCtxObj = kcu.contexts.find(ctx => ctx.name === currentCtx);
905+
906+
const newContextEntry = {
907+
context: {
908+
user: SANDBOX_PIPELINE_USERNAME,
909+
cluster: currentCtxObj.cluster,
910+
namespace: currentCtxObj.namespace
911+
},
912+
name: SANDBOX_PIPELINE_USER_CTX,
913+
};
914+
915+
const newUserEntry = {
916+
user: {
917+
token: pipelineToken
918+
},
919+
name: SANDBOX_PIPELINE_USERNAME,
920+
};
921+
922+
kcActual.users.push(newUserEntry);
923+
kcActual.contexts.push(newContextEntry);
924+
} else {
925+
const pipelineUser = kcActual.users.find(user => user.name === SANDBOX_PIPELINE_USERNAME);
926+
pipelineUser.user.token = pipelineToken;
927+
}
928+
929+
kcActual['current-context'] = SANDBOX_PIPELINE_USER_CTX;
930+
await fs.writeFile(kcPath, YAML.dump(kcActual));
931+
}
932+
880933
static async loginUsingClipboardInfo(dashboardUrl: string): Promise<string | null> {
881934
const clipboard = await Cluster.readFromClipboard();
882935
if (!NameValidator.ocLoginCommandMatches(clipboard)) {
@@ -898,4 +951,9 @@ export class Cluster extends OpenShiftItem {
898951
await commands.executeCommand('setContext', 'isLoggedIn', true);
899952
return `Successfully logged in to '${clusterURL}'`;
900953
}
954+
955+
static isOpenShiftSandbox(url :string): boolean {
956+
const asUrl = new URL(url);
957+
return asUrl.hostname.endsWith('openshiftapps.com');
958+
}
901959
}

0 commit comments

Comments
 (0)