mirror of
https://github.com/Azure/cosmos-explorer.git
synced 2025-03-06 09:58:25 +00:00
added consent
This commit is contained in:
parent
9b2cb8a1a9
commit
2c3c4e7db7
@ -7,7 +7,7 @@ import { configContext } from "../../../ConfigContext";
|
||||
import { armRequest } from "../../../Utils/arm/request";
|
||||
import { Authorization, ConnectTerminalResponse, NetworkType, OsType, ProvisionConsoleResponse, SessionType, Settings, ShellType } from "./DataModels";
|
||||
|
||||
const cloudshellToken = "";
|
||||
const cloudshellToken = "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6ImltaTBZMnowZFlLeEJ0dEFxS19UdDVoWUJUayIsImtpZCI6ImltaTBZMnowZFlLeEJ0dEFxS19UdDVoWUJUayJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldC8iLCJpc3MiOiJodHRwczovL3N0cy53aW5kb3dzLm5ldC83MmY5ODhiZi04NmYxLTQxYWYtOTFhYi0yZDdjZDAxMWRiNDcvIiwiaWF0IjoxNzQwNDU5Njc2LCJuYmYiOjE3NDA0NTk2NzYsImV4cCI6MTc0MDQ2NDA0NSwiX2NsYWltX25hbWVzIjp7Imdyb3VwcyI6InNyYzEifSwiX2NsYWltX3NvdXJjZXMiOnsic3JjMSI6eyJlbmRwb2ludCI6Imh0dHBzOi8vZ3JhcGgud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3L3VzZXJzL2U4MGZmZGE4LTlmZDUtNDQ4ZC05M2VhLWY5YzgyM2ZjN2RkOC9nZXRNZW1iZXJPYmplY3RzIn19LCJhY3IiOiIxIiwiYWlvIjoiQVpRQWEvOFpBQUFBRjcvNHplb1lpQWYxcytvR1FMVXVsa2NJbU93dGx1aVJNMVVKeVI3czIrV0Z5VVdPM2MrUlUybmdsTlBRaGtwTFo4SktsYjg0a1dlTVhCZFFXemJGcUJGQ0M1aXU3ZUxyamRYY3NOaVMwc0l5Z1crdTJsT1I3VzBsNC8xT3UzRnRjakJoQlZLSTFFTGpLWHJjbzkrbTM0WUZJbmYrc0VPNkhuNmJFMmdIL3kxamUyQXZvZXNTaDhmZlpQdjZNSUcxIiwiYW1yIjpbInJzYSIsIm1mYSJdLCJhcHBpZCI6ImM0NGI0MDgzLTNiYjAtNDljMS1iNDdkLTk3NGU1M2NiZGYzYyIsImFwcGlkYWNyIjoiMCIsImRldmljZWlkIjoiZTM4YzBiOTgtMzQ5OS00YWQzLTkwN2EtYjc2NzJjNzdkZTQ3IiwiZmFtaWx5X25hbWUiOiJKYWluIiwiZ2l2ZW5fbmFtZSI6IlNvdXJhYmgiLCJpZHR5cCI6InVzZXIiLCJpcGFkZHIiOiIyNDA1OjIwMTo0MDMzOjIxY2U6OWRkOTpkMGY1OmJjZWE6YjFiMCIsIm5hbWUiOiJTb3VyYWJoIEphaW4iLCJvaWQiOiJlODBmZmRhOC05ZmQ1LTQ0OGQtOTNlYS1mOWM4MjNmYzdkZDgiLCJvbnByZW1fc2lkIjoiUy0xLTUtMjEtMjE0Njc3MzA4NS05MDMzNjMyODUtNzE5MzQ0NzA3LTI3MDcwNjYiLCJwdWlkIjoiMTAwMzIwMDExQTY5NDVGMCIsInJoIjoiMS5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSMFpJZjNrQXV0ZFB1a1Bhd2ZqMk1CTWFBT2dhQUEuIiwic2NwIjoidXNlcl9pbXBlcnNvbmF0aW9uIiwic2lkIjoiMDAyMDEzMDktMmE2MC1jYzVjLWI1MzEtM2IwZDA1YWQxZjc1Iiwic3ViIjoiOHhzRHhTS2pyZzJxd1dpM1gzSmYteTFSQ1dSNnZQMERnSkVsS2hNbTltMCIsInRpZCI6IjcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0NyIsInVuaXF1ZV9uYW1lIjoic291cmFiaGphaW5AbWljcm9zb2Z0LmNvbSIsInVwbiI6InNvdXJhYmhqYWluQG1pY3Jvc29mdC5jb20iLCJ1dGkiOiJUVDYwRzBpSFJrMmN4Y1AtVVZzbEFBIiwidmVyIjoiMS4wIiwieG1zX2lkcmVsIjoiMSAzMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.LBYpLSmj8Cd-ZL3i9yuqVvPB0CirALEq7ldFywDH2U5c9LlnUfLgOf_C_N0Uu0ChthTl9Eu54TXuGCxFXwfVSg_kaPuZhtc-vDqVurjHtyNr-53qKg8fbQYbOnB_JGqC86TzdqPRv1XwhZj9C2bNjjGZ2GrcOWitv8CgM9Fs9Cul1OHiq5j8BTJl8OX_THC-VUB11fB-5qyitH9pTtETC4o7AKg4fOHftXYDkFI0gVF_WCZoquI6kFEnoQtt_qhu4rK71VqVRt5qqBeT8tgH4GwsP2W7pBlzESdjSXWMJ5u7klXJwheYvuytrxioD1f0HCOLHyBFpVf5JTBBeXjPow";
|
||||
|
||||
export const validateUserSettings = (userSettings: Settings) => {
|
||||
if (userSettings.sessionType !== SessionType.Ephemeral && userSettings.osType !== OsType.Linux) {
|
||||
@ -163,15 +163,14 @@ export const getLocale = () => {
|
||||
return (langLocale && langLocale.length === 2 ? langLocale[1] : 'en-us');
|
||||
};
|
||||
|
||||
const validCloudShellRegions = new Set(["westus", "southcentralus", "eastus", "northeurope", "westeurope", "centralindia", "southeastasia", "westcentralus", "eastus2euap", "centraluseuap"]);
|
||||
const defaultCloudshellRegion = "westus";
|
||||
const validCloudShellRegions = new Set(["westus", "southcentralus", "eastus", "northeurope", "westeurope", "centralindia", "southeastasia", "westcentralus"]);
|
||||
|
||||
export const getNormalizedRegion = (region: string) => {
|
||||
export const getNormalizedRegion = (region: string, defaultCloudshellRegion: string) => {
|
||||
if (!region) return defaultCloudshellRegion;
|
||||
|
||||
const regionMap: Record<string, string> = {
|
||||
"centralus": "centraluseuap",
|
||||
"eastus2": "eastus2euap"
|
||||
"centralus": "westcentralus",
|
||||
"eastus2": "eastus"
|
||||
};
|
||||
|
||||
const normalizedRegion = regionMap[region.toLowerCase()] || region;
|
||||
|
@ -3,7 +3,7 @@
|
||||
*/
|
||||
|
||||
export const LogError = (message: string) => {
|
||||
return `\n\r\x1B[1;37m${message}`;
|
||||
return `\x1B[1;31m${message}`;
|
||||
}
|
||||
|
||||
export const LogInfo = (message: string) => {
|
||||
|
@ -24,66 +24,23 @@ export const startCloudShellterminal = async (xterminal: Terminal, initCommands:
|
||||
const region = userContext.databaseAccount?.location;
|
||||
xterminal.writeln(LogInfo(`Database Acount Region identified as '${region}'`));
|
||||
|
||||
const resolvedRegion = getNormalizedRegion(region);
|
||||
const defaultCloudshellRegion = "westus";
|
||||
const resolvedRegion = getNormalizedRegion(region, defaultCloudshellRegion);
|
||||
|
||||
xterminal.writeln(LogInfo(`Requesting Cloudshell instance at '${resolvedRegion}'`));
|
||||
|
||||
try {
|
||||
// do not use the subscription from the preferred settings use the one from the context
|
||||
await putEphemeralUserSettings(userContext.subscriptionId, resolvedRegion);
|
||||
} catch (err) {
|
||||
xterminal.writeln(LogError('Unable to update user settings to ephemeral session.'));
|
||||
throw err;
|
||||
var { socketUri, provisionConsoleResponse, targetUri } = await provisionCloudShellSession(resolvedRegion, xterminal);
|
||||
}
|
||||
|
||||
// verify user settings after they have been updated to ephemeral
|
||||
try {
|
||||
const userSettings = await getUserSettings();
|
||||
const isValidUserSettings = validateUserSettings(userSettings);
|
||||
if (!isValidUserSettings) {
|
||||
throw new Error("Invalid user settings detected for ephemeral session.");
|
||||
}
|
||||
} catch (err) {
|
||||
xterminal.writeln(LogError('Unable to verify user settings for ephemeral session.'));
|
||||
throw err;
|
||||
catch (err) {
|
||||
xterminal.writeln(LogError(err));
|
||||
xterminal.writeln(LogError(`Unable to provision console in request region, Falling back to default region i.e. ${defaultCloudshellRegion}`));
|
||||
var { socketUri, provisionConsoleResponse, targetUri } = await provisionCloudShellSession(defaultCloudshellRegion, xterminal);
|
||||
}
|
||||
|
||||
// trigger callback to provision console internal
|
||||
let provisionConsoleResponse;
|
||||
try {
|
||||
provisionConsoleResponse = await provisionConsole(userContext.subscriptionId, resolvedRegion);
|
||||
} catch (err) {
|
||||
xterminal.writeln(LogError('Unable to provision console.\n\r'));
|
||||
throw err;
|
||||
}
|
||||
|
||||
if (provisionConsoleResponse.properties.provisioningState !== "Succeeded") {
|
||||
xterminal.writeln(LogError("Failed to provision console.\n\r"));
|
||||
throw new Error("Failed to provision console.");
|
||||
}
|
||||
|
||||
xterminal.writeln(LogInfo("Connecting to cloudshell"));
|
||||
xterminal.writeln(LogInfo("Please wait..."));
|
||||
// connect the terminal
|
||||
let connectTerminalResponse;
|
||||
try {
|
||||
connectTerminalResponse = await connectTerminal(provisionConsoleResponse.properties.uri, { rows: xterminal.rows, cols: xterminal.cols });
|
||||
} catch (err) {
|
||||
xterminal.writeln('');
|
||||
xterminal.writeln(LogError('Unable to connect terminal.'));
|
||||
throw err;
|
||||
}
|
||||
|
||||
const targetUri = provisionConsoleResponse.properties.uri + `/terminals?cols=${xterminal.cols}&rows=${xterminal.rows}&version=2019-01-01&shell=bash`;
|
||||
const termId = connectTerminalResponse.id;
|
||||
|
||||
let socketUri = connectTerminalResponse.socketUri.replace(":443/", "");
|
||||
const targetUriBody = targetUri.replace('https://', '').split('?')[0];
|
||||
if (socketUri.indexOf(targetUriBody) === -1) {
|
||||
socketUri = 'wss://' + targetUriBody + '/' + termId;
|
||||
}
|
||||
if (targetUriBody.includes('servicebus')) {
|
||||
const targetUriBodyArr = targetUriBody.split('/');
|
||||
socketUri = 'wss://' + targetUriBodyArr[0] + '/$hc/' + targetUriBodyArr[1] + '/terminals/' + termId;
|
||||
|
||||
if(!socketUri) {
|
||||
xterminal.writeln(LogError('Unable to provision console. Close and Open the terminal again to retry.'));
|
||||
return{};
|
||||
}
|
||||
|
||||
const socket = new WebSocket(socketUri);
|
||||
@ -190,3 +147,89 @@ export const configureSocket = (socket: WebSocket, uri: string, terminal: any,
|
||||
|
||||
return socket;
|
||||
};
|
||||
|
||||
const provisionCloudShellSession = async(
|
||||
resolvedRegion: string,
|
||||
xterminal: Terminal
|
||||
): Promise<{ socketUri?: string; provisionConsoleResponse?: any; targetUri?: string }> => {
|
||||
return new Promise((resolve, reject) => {
|
||||
// Show consent message inside the terminal
|
||||
xterminal.writeln(`\x1B[1;33m⚠️ Are you agreeing to continue with cloudshell terminal at ${resolvedRegion}.\x1B[0m`);
|
||||
xterminal.writeln("\x1B[1;37mPress 'Y' to continue or 'N' to exit.\x1B[0m");
|
||||
|
||||
// Listen for user input
|
||||
const handleKeyPress = xterminal.onKey(async ({ key }: { key: string }) => {
|
||||
// Remove the event listener after first execution
|
||||
handleKeyPress.dispose();
|
||||
|
||||
if (key.toLowerCase() === "y") {
|
||||
xterminal.writeln("\x1B[1;32m✅ Consent given. Terminal ready!\x1B[0m");
|
||||
|
||||
try {
|
||||
await putEphemeralUserSettings(userContext.subscriptionId, resolvedRegion);
|
||||
} catch (err) {
|
||||
xterminal.writeln(LogError('Unable to update user settings to ephemeral session.'));
|
||||
return reject(err);
|
||||
}
|
||||
|
||||
// verify user settings after they have been updated to ephemeral
|
||||
try {
|
||||
const userSettings = await getUserSettings();
|
||||
const isValidUserSettings = validateUserSettings(userSettings);
|
||||
if (!isValidUserSettings) {
|
||||
throw new Error("Invalid user settings detected for ephemeral session.");
|
||||
}
|
||||
} catch (err) {
|
||||
xterminal.writeln(LogError('Unable to verify user settings for ephemeral session.'));
|
||||
return reject(err);
|
||||
}
|
||||
|
||||
// trigger callback to provision console internal
|
||||
let provisionConsoleResponse;
|
||||
try {
|
||||
provisionConsoleResponse = await provisionConsole(userContext.subscriptionId, resolvedRegion);
|
||||
} catch (err) {
|
||||
xterminal.writeln(LogError('Unable to provision console.\n\r'));
|
||||
return reject(err);
|
||||
}
|
||||
|
||||
if (provisionConsoleResponse.properties.provisioningState !== "Succeeded") {
|
||||
xterminal.writeln(LogError("Failed to provision console.\n\r"));
|
||||
return reject(new Error("Failed to provision console."));
|
||||
}
|
||||
|
||||
xterminal.writeln(LogInfo("Connecting to cloudshell"));
|
||||
xterminal.writeln(LogInfo("Please wait..."));
|
||||
// connect the terminal
|
||||
let connectTerminalResponse;
|
||||
try {
|
||||
connectTerminalResponse = await connectTerminal(provisionConsoleResponse.properties.uri, { rows: xterminal.rows, cols: xterminal.cols });
|
||||
} catch (err) {
|
||||
xterminal.writeln('');
|
||||
xterminal.writeln(LogError('Unable to connect terminal.'));
|
||||
return reject(err);
|
||||
}
|
||||
|
||||
const targetUri = provisionConsoleResponse.properties.uri + `/terminals?cols=${xterminal.cols}&rows=${xterminal.rows}&version=2019-01-01&shell=bash`;
|
||||
const termId = connectTerminalResponse.id;
|
||||
|
||||
let socketUri = connectTerminalResponse.socketUri.replace(":443/", "");
|
||||
const targetUriBody = targetUri.replace('https://', '').split('?')[0];
|
||||
if (socketUri.indexOf(targetUriBody) === -1) {
|
||||
socketUri = 'wss://' + targetUriBody + '/' + termId;
|
||||
}
|
||||
if (targetUriBody.includes('servicebus')) {
|
||||
const targetUriBodyArr = targetUriBody.split('/');
|
||||
socketUri = 'wss://' + targetUriBodyArr[0] + '/$hc/' + targetUriBodyArr[1] + '/terminals/' + termId;
|
||||
}
|
||||
return resolve({ socketUri, provisionConsoleResponse, targetUri });
|
||||
|
||||
} else if (key.toLowerCase() === "n") {
|
||||
|
||||
xterminal.writeln("\x1B[1;31m❌ Consent denied. Exiting...\x1B[0m");
|
||||
setTimeout(() => xterminal.dispose(), 2000); // Close terminal after 2 sec
|
||||
return resolve({});
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
@ -21,7 +21,7 @@ export const CloudShellTerminalComponent: React.FC<CloudShellTerminalProps> = ({
|
||||
const term = new Terminal({
|
||||
cursorBlink: true,
|
||||
fontSize: 14,
|
||||
theme: { background: "#1d1f21", foreground: "#c5c8c6" },
|
||||
theme: { background: "#1d1f21", foreground: "#c5c8c6" },
|
||||
});
|
||||
|
||||
// Attach terminal to the DOM
|
||||
|
Loading…
x
Reference in New Issue
Block a user