1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00

Working POC against DECC

For the demo to work the following env vars need to passed when running lens in dev
mode:

- DECC_URL: This is the DECC Manager URL
- DECC_USERNAME: This is the username you would use against keycloak
- DECC_PASSWORD: This is the password you would use against keycloak
- NODE_ENV: Should be set to `development`
This commit is contained in:
Steve Richards 2020-09-24 15:14:26 +01:00
parent 9c2c6b1c71
commit 48c712da32
3 changed files with 82 additions and 18 deletions

View File

@ -6,7 +6,7 @@ import { Cluster } from "./cluster"
import logger from "./logger";
import { apiKubePrefix } from "../common/vars";
import { workspaceStore, Workspace } from "../common/workspace-store";
import { userStore } from "../common/user-store";
import { userStore, UserStore } from "../common/user-store";
import * as request from "request-promise-native";
import { v4 as uuid } from "uuid";
import {kubeconfig} from '../common/utils/k8sTemplates';
@ -15,6 +15,7 @@ import { readFile } from "fs-extra"
import { getNodeWarningConditions, loadConfig, podHasIssues } from "../common/kube-helpers"
import { customRequestPromise } from "../common/request";
import orderBy from "lodash/orderBy";
import queryString from 'query-string';
const ignoredDECCNamespaces = [
'kube-system', 'kube-public', 'openstack-provider-system', 'system',
@ -53,6 +54,31 @@ export class DECCManager {
return res.body;
}
async getK8sToken(): Promise<[]> {
const headers = {
Accept: 'application/json',
'Content-Type': 'application/x-www-form-urlencoded'
};
const res = await customRequestPromise({
uri: `http://${process.env.DECC_URL}/auth/realms/iam/protocol/openid-connect/token`,
headers: headers,
method: 'POST', body: queryString.stringify({
grant_type: 'password',
response_type: 'id_token',
scope: 'openid',
client_id: 'k8s',
username: `${process.env.DECC_USERNAME}`,
password: `${process.env.DECC_PASSWORD}`,
}),
json: true,
resolveWithFullResponse: true,
timeout: 10000,
});
// logger.info(`getTokenForCluster: res - ${JSON.stringify(res)}`);
return res.body;
}
async getDECCNamespaces() {
try {
const res = await this.getNamespaces();
@ -99,6 +125,15 @@ export class DECCManager {
}
}
async getK8sTokenForUser() {
try {
const res = await this.getK8sToken();
return res;
} catch(err) {
logger.error(`getK8sTokenForUser: ${String(err)}`);
}
}
addLensDECCWorkspace(ws: string) {
const wsPrefix = `decc`;
@ -108,7 +143,7 @@ export class DECCManager {
}
}
addLensClusterToDECCWorkspace(deccCluster, idToken: string, refreshToken: string, username: string, workspace: Workspace) {
addLensClusterToDECCWorkspace(deccCluster, idToken: string, refreshToken: string, username: string, workspace: Workspace, k8sToken) {
// check if cluster is already in the cluster store
var clusterPresent = false;
const clusterPrefix = `decc`
@ -123,6 +158,15 @@ export class DECCManager {
let ucpDashboard = `https://${deccCluster.status.providerStatus.ucpDashboard.split(":", 2).reverse()[0].substring(2)}:443`;
//logger.info(`addLensClusterToDECCWorkspace: ucpDashboard - ${ucpDashboard}`);
//let clusterToken = this.getTokenForCluster(deccCluster.metadata.uid);
//logger.info(`addLensClusterToDECCWorkspace: clusterToken - ${clusterToken}`);
// let parsedClusterIdToken = userStore.decodeToken(k8sToken["id_token"]);
// logger.info(`addLensClusterToDECCWorkspace: parsedClusterToken - ${parsedClusterIdToken}`);
const idTokenToUse = `${clusterPrefix}-${deccCluster.metadata.name}` === "decc-kaas-mgmt" ? idToken : k8sToken["id_token"]
const refreshTokenToUse = `${clusterPrefix}-${deccCluster.metadata.name}` === "decc-kaas-mgmt" ? refreshToken : k8sToken["refresh_token"]
const jsConfig = kubeconfig({
username: username,
clusterName: `${clusterPrefix}-${deccCluster.metadata.name}`,
@ -131,8 +175,8 @@ export class DECCManager {
idpIssuerUrl: deccCluster.status.providerStatus.oidc.issuerUrl,
server: ucpDashboard,
apiCertificate: deccCluster.status.providerStatus.apiServerCertificate,
idToken: idToken,
refreshToken: refreshToken
idToken: idTokenToUse,
refreshToken: refreshTokenToUse
});
//console.log(`Generated kubeconfig: ${YAML.stringify(jsConfig)}`)
@ -162,14 +206,14 @@ export class DECCManager {
};
}
addLensClustersToDECCWorkspace(deccClusters, idToken: string, refreshToken: string, username: string, wsName: string) {
addLensClustersToDECCWorkspace(deccClusters, idToken: string, refreshToken: string, username: string, wsName: string, k8sToken) {
const wsPrefix = `decc`;
const workspace = workspaceStore.getByName(`${wsPrefix}-${wsName}`);
//logger.info(`addLensClustersToDECCWorkspace: Processing clusters in Workspace ${workspace.name} for User ${username}`);
deccClusters.forEach(cluster => {
this.addLensClusterToDECCWorkspace(cluster, idToken, refreshToken, username, workspace)
this.addLensClusterToDECCWorkspace(cluster, idToken, refreshToken, username, workspace, k8sToken)
});
}
@ -198,7 +242,7 @@ export class DECCManager {
});
}
refreshLensDECCClusterKubeconfigs(idToken:string , refreshToken: string, username: string, workspace: string) {
refreshLensDECCClusterKubeconfigs(idToken:string , refreshToken: string, username: string, workspace: string, k8sToken) {
//logger.info(`refreshLensDECCClusterKubeconfigs: Processing Workspace Name ${workspace}`);
const wsPrefix = `decc`;
const ws = workspaceStore.getByName(`${wsPrefix}-${workspace}`);
@ -207,6 +251,8 @@ export class DECCManager {
//logger.info(`refreshLensDECCClusterKubeconfigs: Processing Workspace ${JSON.stringify(ws)}`)
clusterStore.getByWorkspaceId(ws.id).forEach(cluster => {
const idTokenToUse = cluster.preferences.clusterName === "decc-kaas-mgmt" ? idToken : k8sToken["id_token"]
const refreshTokenToUse = cluster.preferences.clusterName === "decc-kaas-mgmt" ? refreshToken : k8sToken["refresh_token"]
const currentKubeConfig = loadConfig(cluster.kubeConfigPath); //readFile(cluster.kubeConfigPath, "utf8");
// console.log(`refreshClusterKubeConfigs: Read kubeconfig from file: ${cluster.kubeConfigPath}. Contents: ${YAML.stringify(kubeConfig)}`);
// console.log(`refreshClusterKubeConfigs: kubeconfig users[0]: ${YAML.stringify(kubeConfig.users[0])}`);
@ -220,10 +266,11 @@ export class DECCManager {
idpIssuerUrl: currentKubeConfig.users[0].authProvider.config["idp-issuer-url"],
server: currentKubeConfig.clusters[0].server,
apiCertificate: currentKubeConfig.clusters[0].caData,
idToken: idToken,
refreshToken: refreshToken
idToken: idTokenToUse,
refreshToken: refreshTokenToUse
});
cluster.contextName = `${username}@${currentKubeConfig.clusters[0].name}`;
ClusterStore.embedCustomKubeConfig(cluster.id, YAML.stringify(jsConfig));
logger.info(`refreshLensDECCClusterKubeconfigs: Updated Cluster ${cluster.preferences.clusterName} kubeconfig with new token values`);
cluster.refresh();
@ -237,6 +284,9 @@ export class DECCManager {
const username = parsedIdToken.preferred_username;
const userIAMRoles = parsedIdToken.iam_roles;
// get the token from the k8s client for this user
const k8sToken = await this.getK8sTokenForUser();
// get all available DECC Namespaces
const deccNamespaces = await this.getDECCNamespaces();
// logger.info(`createDECCLensEnv: The following namespaces exist in DECC - ${deccNamespaces.toString()}`);
@ -256,13 +306,13 @@ export class DECCManager {
//logger.info(`createDECCLensEnv: The following clusters exist in Namespace ${ns} - ${JSON.stringify(deccClustersByNamespace)}`);
// refresh tokens for any existing clusters
this.refreshLensDECCClusterKubeconfigs(idToken, refreshToken, username, ns);
this.refreshLensDECCClusterKubeconfigs(idToken, refreshToken, username, ns, k8sToken);
// now lets add the workspace in Lens
this.addLensDECCWorkspace(ns);
// now lets add the clusters to the workspace
this.addLensClustersToDECCWorkspace(deccClustersByNamespace, idToken, refreshToken, username, ns);
this.addLensClustersToDECCWorkspace(deccClustersByNamespace, idToken, refreshToken, username, ns, k8sToken);
} catch (err) {
logger.error(`createDECCLensEnv: ${String(err)}`);

View File

@ -134,12 +134,16 @@ export class LensProxy {
protected async handleRequest(proxy: httpProxy, req: http.IncomingMessage, res: http.ServerResponse) {
const cluster = this.clusterManager.getClusterForRequest(req)
if (cluster) {
await cluster.contextHandler.ensureServer();
const proxyTarget = await this.getProxyTarget(req, cluster.contextHandler)
if (proxyTarget) {
// allow to fetch apis in "clusterId.localhost:port" from "localhost:port"
res.setHeader("Access-Control-Allow-Origin", this.origin);
return proxy.web(req, res, proxyTarget);
try {
await cluster.contextHandler.ensureServer();
const proxyTarget = await this.getProxyTarget(req, cluster.contextHandler)
if (proxyTarget) {
// allow to fetch apis in "clusterId.localhost:port" from "localhost:port"
res.setHeader("Access-Control-Allow-Origin", this.origin);
return proxy.web(req, res, proxyTarget);
}
} catch (err) {
logger.error(`[lens-proxy] handleRequest: ${String(err)}`);
}
}
this.router.route(cluster, req, res);

View File

@ -3,6 +3,7 @@
<script src="https://a69adcd0687194b2b8adebdbe93f2a02-977850409.eu-west-2.elb.amazonaws.com/auth/js/keycloak.js"></script>
<script>
const { ipcRenderer } = require('electron')
const useK8sClientId = new URL(location.href).searchParams.get('k8s');
var keycloak = new Keycloak({
url: 'https://a69adcd0687194b2b8adebdbe93f2a02-977850409.eu-west-2.elb.amazonaws.com/auth',
@ -11,13 +12,22 @@ var keycloak = new Keycloak({
scope: 'offline_access openid',
});
var keycloakOptions = {
flow: 'standard',
enableLogging: true,
useNonce: false,
onLoad: 'login-required',
checkLoginIframe: false,
redirectUri: 'http://localhost:3000'
}
//if param "logout" was passed to this page, logout user!
const logoutUser = new URL(location.href).searchParams.get('logout');
if(logoutUser){
keycloak.init();
keycloak.logout({redirectUri: 'http://localhost:3000'});
}else{
keycloak.init({ flow: 'standard', enableLogging: true, useNonce: false, onLoad: 'login-required', checkLoginIframe: false, redirectUri: 'http://localhost:3000'}).success(function(authenticated) {
keycloak.init(keycloakOptions).success(function(authenticated) {
console.log('success!!');
if (authenticated) {
console.log("keycloak.token: " + keycloak.token);