From ac137c994b714e870670dbde79c142e80a54ce77 Mon Sep 17 00:00:00 2001 From: nishthaAhujaa Date: Tue, 2 Sep 2025 12:40:58 +0530 Subject: [PATCH] partly --- .../CloudShellTab/Utils/CloudShellIPUtils.ts | 13 ++++++ .../Tabs/CloudShellTab/Utils/RegionUtils.tsx | 6 ++- .../Tabs/Shared/CloudShellIPChecker.ts | 40 +++++++++++++++++++ .../BaseTerminalComponentAdapter.tsx | 12 +++++- src/Explorer/Tabs/TerminalTab.tsx | 35 ++++++++++++---- 5 files changed, 96 insertions(+), 10 deletions(-) create mode 100644 src/Explorer/Tabs/CloudShellTab/Utils/CloudShellIPUtils.ts create mode 100644 src/Explorer/Tabs/Shared/CloudShellIPChecker.ts diff --git a/src/Explorer/Tabs/CloudShellTab/Utils/CloudShellIPUtils.ts b/src/Explorer/Tabs/CloudShellTab/Utils/CloudShellIPUtils.ts new file mode 100644 index 000000000..39511fce7 --- /dev/null +++ b/src/Explorer/Tabs/CloudShellTab/Utils/CloudShellIPUtils.ts @@ -0,0 +1,13 @@ +export const CLOUDSHELL_IP_RECOMMENDATIONS = { + centralindia: ["4.247.135.109", "74.225.207.63"], + southeastasia: ["4.194.56.6", "4.194.213.10", "4.194.144.127", "4.194.5.74"], + centraluseuap: ["52.158.186.182", "172.215.26.246", "134.138.154.177", "134.138.129.52", "172.215.31.177"], + eastus2euap: ["135.18.43.51", "20.252.175.33", "40.89.88.111", "135.18.17.187", "135.18.67.251"], + eastus: ["40.71.199.151", "20.42.18.188", "52.190.17.9", "20.120.96.152"], + northeurope: ["74.234.65.146", "52.169.70.113"], + southcentralus: ["4.151.247.81", "20.225.211.35", "4.151.48.133", "4.151.247.225"], + westeurope: ["52.166.126.216", "108.142.162.20", "52.178.13.125", "172.201.33.160"], + westus: ["20.245.161.131", "57.154.182.51", "40.118.133.244", "20.253.192.12", "20.43.245.209", "20.66.22.66"], + usgovarizona: ["62.10.232.179"], + usgovvirginia: ["62.10.26.85"], +}; diff --git a/src/Explorer/Tabs/CloudShellTab/Utils/RegionUtils.tsx b/src/Explorer/Tabs/CloudShellTab/Utils/RegionUtils.tsx index f9d4516fa..9e3c18dd5 100644 --- a/src/Explorer/Tabs/CloudShellTab/Utils/RegionUtils.tsx +++ b/src/Explorer/Tabs/CloudShellTab/Utils/RegionUtils.tsx @@ -10,6 +10,8 @@ const validCloudShellRegions = new Set([ "westcentralus", "usgovvirginia", "usgovarizona", + "centraluseuap", + "eastus2euap", ]); /** @@ -41,8 +43,8 @@ export const getNormalizedRegion = (region: string, defaultCloudshellRegion: str } const regionMap: Record = { - centralus: "westcentralus", - eastus2: "eastus", + centralus: "centraluseuap", + eastus2: "eastus2euap", }; const normalizedRegion = regionMap[region.toLowerCase()] || region; diff --git a/src/Explorer/Tabs/Shared/CloudShellIPChecker.ts b/src/Explorer/Tabs/Shared/CloudShellIPChecker.ts new file mode 100644 index 000000000..caf0a4e28 --- /dev/null +++ b/src/Explorer/Tabs/Shared/CloudShellIPChecker.ts @@ -0,0 +1,40 @@ +import { configContext } from "ConfigContext"; +import * as DataModels from "Contracts/DataModels"; +import { userContext } from "UserContext"; +import { armRequest } from "Utils/arm/request"; +import { CLOUDSHELL_IP_RECOMMENDATIONS } from "../CloudShellTab/Utils/CloudShellIPUtils"; +import { getNormalizedRegion } from "../CloudShellTab/Utils/RegionUtils"; + +export async function checkCloudShellIPsConfigured() { + const databaseRegion = userContext.databaseAccount?.location; + console.log("db region", databaseRegion); + const normalizedRegion = getNormalizedRegion(databaseRegion, "westus"); + const cloudShellIPs = getCloudShellIPsForRegion(normalizedRegion); + console.log("CloudShell IPs for region", normalizedRegion, cloudShellIPs); + if (!cloudShellIPs || cloudShellIPs.length === 0) { + return false; + } + + const firewallRules = await getFirewallRules(); + console.log("firewall rules", firewallRules); + return false; +} + +function getCloudShellIPsForRegion(region: string): string[] { + const regionKey = region.toLowerCase(); + const ips = CLOUDSHELL_IP_RECOMMENDATIONS[regionKey as keyof typeof CLOUDSHELL_IP_RECOMMENDATIONS]; + return ips ? [...ips] : []; +} + +async function getFirewallRules(): Promise { + const firewallRulesUri = `${userContext.databaseAccount.id}/firewallRules`; + + const response: any = await armRequest({ + host: configContext.ARM_ENDPOINT, + path: firewallRulesUri, + method: "GET", + apiVersion: "2023-03-01-preview", + }); + + return response?.data?.value || response?.value || []; +} diff --git a/src/Explorer/Tabs/ShellAdapters/BaseTerminalComponentAdapter.tsx b/src/Explorer/Tabs/ShellAdapters/BaseTerminalComponentAdapter.tsx index 1664326d9..882259953 100644 --- a/src/Explorer/Tabs/ShellAdapters/BaseTerminalComponentAdapter.tsx +++ b/src/Explorer/Tabs/ShellAdapters/BaseTerminalComponentAdapter.tsx @@ -22,9 +22,19 @@ export abstract class BaseTerminalComponentAdapter implements ReactAdapter { protected getUsername: () => string, protected isAllPublicIPAddressesEnabled: ko.Observable, protected kind: ViewModels.TerminalKind, - ) {} + protected isCloudShellIPsConfigured?: ko.Observable, + ) { } public renderComponent(): JSX.Element { + if (this.kind === ViewModels.TerminalKind.VCoreMongo && this.isCloudShellIPsConfigured && !this.isCloudShellIPsConfigured()) { + return ( + + ); + } if (!this.isAllPublicIPAddressesEnabled()) { return ( ; + private isCloudShellIPsConfigured: ko.Observable; constructor(options: TerminalTabOptions) { super(options); this.container = options.container; this.isAllPublicIPAddressesEnabled = ko.observable(true); + this.isCloudShellIPsConfigured = ko.observable(true); const commonArgs: [ () => DataModels.DatabaseAccount, @@ -36,19 +39,37 @@ export default class TerminalTab extends TabsBase { ko.Observable, ViewModels.TerminalKind, ] = [ - () => userContext?.databaseAccount, - () => this.tabId, - () => this.getUsername(), - this.isAllPublicIPAddressesEnabled, - options.kind, - ]; + () => userContext?.databaseAccount, + () => this.tabId, + () => this.getUsername(), + this.isAllPublicIPAddressesEnabled, + options.kind, + ]; if (userContext.features.enableCloudShell) { - this.notebookTerminalComponentAdapter = new CloudShellTerminalComponentAdapter(...commonArgs); + this.notebookTerminalComponentAdapter = new CloudShellTerminalComponentAdapter( + () => userContext?.databaseAccount, + () => this.tabId, + () => this.getUsername(), + this.isAllPublicIPAddressesEnabled, + options.kind, + options.kind === ViewModels.TerminalKind.VCoreMongo ? this.isCloudShellIPsConfigured : undefined, + ); this.notebookTerminalComponentAdapter.parameters = ko.computed(() => { + if (options.kind === ViewModels.TerminalKind.VCoreMongo) { + const cloudShellConfigured = this.isCloudShellIPsConfigured(); + return this.isTemplateReady() && cloudShellConfigured; + } return this.isTemplateReady() && this.isAllPublicIPAddressesEnabled(); }); + + if (options.kind === ViewModels.TerminalKind.VCoreMongo) { + (async () => { + const result = await checkCloudShellIPsConfigured(); + this.isCloudShellIPsConfigured(result); + })(); + } } else { this.notebookTerminalComponentAdapter = new NotebookTerminalComponentAdapter( () => this.getNotebookServerInfo(options),