mirror of
https://github.com/Azure/cosmos-explorer.git
synced 2025-12-25 20:01:45 +00:00
Compare commits
3 Commits
cja/simple
...
cloudshell
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
811a6dd363 | ||
|
|
012d043c78 | ||
|
|
3afd74a957 |
@@ -22,6 +22,7 @@ import { formatErrorMessage, formatInfoMessage, formatWarningMessage } from "./U
|
|||||||
|
|
||||||
// Constants
|
// Constants
|
||||||
const DEFAULT_CLOUDSHELL_REGION = "westus";
|
const DEFAULT_CLOUDSHELL_REGION = "westus";
|
||||||
|
const DEFAULT_FAIRFAX_CLOUDSHELL_REGION = "usgovvirginia";
|
||||||
const POLLING_INTERVAL_MS = 2000;
|
const POLLING_INTERVAL_MS = 2000;
|
||||||
const MAX_RETRY_COUNT = 10;
|
const MAX_RETRY_COUNT = 10;
|
||||||
const MAX_PING_COUNT = 120 * 60; // 120 minutes (60 seconds/minute)
|
const MAX_PING_COUNT = 120 * 60; // 120 minutes (60 seconds/minute)
|
||||||
@@ -153,7 +154,9 @@ export const ensureCloudShellProviderRegistered = async (): Promise<void> => {
|
|||||||
* Determines the appropriate CloudShell region
|
* Determines the appropriate CloudShell region
|
||||||
*/
|
*/
|
||||||
export const determineCloudShellRegion = (): string => {
|
export const determineCloudShellRegion = (): string => {
|
||||||
return getNormalizedRegion(userContext.databaseAccount?.location, DEFAULT_CLOUDSHELL_REGION);
|
const defaultRegion =
|
||||||
|
userContext.portalEnv === "fairfax" ? DEFAULT_FAIRFAX_CLOUDSHELL_REGION : DEFAULT_CLOUDSHELL_REGION;
|
||||||
|
return getNormalizedRegion(userContext.databaseAccount?.location, defaultRegion);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ jest.mock("../../../../UserContext", () => ({
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
jest.mock("../Utils/CommonUtils", () => ({
|
jest.mock("../Utils/CommonUtils", () => ({
|
||||||
|
...jest.requireActual("../Utils/CommonUtils"),
|
||||||
getHostFromUrl: jest.fn().mockReturnValue("test-mongo.documents.azure.com"),
|
getHostFromUrl: jest.fn().mockReturnValue("test-mongo.documents.azure.com"),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@@ -124,7 +125,10 @@ describe("MongoShellHandler", () => {
|
|||||||
|
|
||||||
describe("getTerminalSuppressedData", () => {
|
describe("getTerminalSuppressedData", () => {
|
||||||
it("should return the correct warning message", () => {
|
it("should return the correct warning message", () => {
|
||||||
expect(mongoShellHandler.getTerminalSuppressedData()).toEqual(["Warning: Non-Genuine MongoDB Detected"]);
|
expect(mongoShellHandler.getTerminalSuppressedData()).toEqual([
|
||||||
|
"Warning: Non-Genuine MongoDB Detected",
|
||||||
|
"Telemetry is now disabled.",
|
||||||
|
]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
import { userContext } from "../../../../UserContext";
|
import { userContext } from "../../../../UserContext";
|
||||||
import { getHostFromUrl } from "../Utils/CommonUtils";
|
import { filterAndCleanTerminalOutput, getHostFromUrl, getMongoShellRemoveInfoText } from "../Utils/CommonUtils";
|
||||||
import { AbstractShellHandler, DISABLE_TELEMETRY_COMMAND } from "./AbstractShellHandler";
|
import { AbstractShellHandler, DISABLE_TELEMETRY_COMMAND } from "./AbstractShellHandler";
|
||||||
|
|
||||||
export class MongoShellHandler extends AbstractShellHandler {
|
export class MongoShellHandler extends AbstractShellHandler {
|
||||||
private _key: string;
|
private _key: string;
|
||||||
private _endpoint: string | undefined;
|
private _endpoint: string | undefined;
|
||||||
|
private _removeInfoText: string[] = getMongoShellRemoveInfoText();
|
||||||
constructor(private key: string) {
|
constructor(private key: string) {
|
||||||
super();
|
super();
|
||||||
this._key = key;
|
this._key = key;
|
||||||
@@ -44,6 +45,10 @@ export class MongoShellHandler extends AbstractShellHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public getTerminalSuppressedData(): string[] {
|
public getTerminalSuppressedData(): string[] {
|
||||||
return ["Warning: Non-Genuine MongoDB Detected"];
|
return ["Warning: Non-Genuine MongoDB Detected", "Telemetry is now disabled."];
|
||||||
|
}
|
||||||
|
|
||||||
|
updateTerminalData(data: string): string {
|
||||||
|
return filterAndCleanTerminalOutput(data, this._removeInfoText);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,10 @@
|
|||||||
import { userContext } from "../../../../UserContext";
|
import { userContext } from "../../../../UserContext";
|
||||||
|
import { filterAndCleanTerminalOutput, getMongoShellRemoveInfoText } from "../Utils/CommonUtils";
|
||||||
import { AbstractShellHandler, DISABLE_TELEMETRY_COMMAND } from "./AbstractShellHandler";
|
import { AbstractShellHandler, DISABLE_TELEMETRY_COMMAND } from "./AbstractShellHandler";
|
||||||
|
|
||||||
export class VCoreMongoShellHandler extends AbstractShellHandler {
|
export class VCoreMongoShellHandler extends AbstractShellHandler {
|
||||||
private _endpoint: string | undefined;
|
private _endpoint: string | undefined;
|
||||||
private _textFilterRules: string[] = [
|
private _removeInfoText: string[] = getMongoShellRemoveInfoText();
|
||||||
"For mongosh info see: https://www.mongodb.com/docs/mongodb-shell/",
|
|
||||||
"disableTelemetry() command",
|
|
||||||
"https://www.mongodb.com/legal/privacy-policy",
|
|
||||||
];
|
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
@@ -38,12 +35,7 @@ export class VCoreMongoShellHandler extends AbstractShellHandler {
|
|||||||
return ["Warning: Non-Genuine MongoDB Detected", "Telemetry is now disabled."];
|
return ["Warning: Non-Genuine MongoDB Detected", "Telemetry is now disabled."];
|
||||||
}
|
}
|
||||||
|
|
||||||
updateTerminalData(content: string): string {
|
updateTerminalData(data: string): string {
|
||||||
const updatedContent = content
|
return filterAndCleanTerminalOutput(data, this._removeInfoText);
|
||||||
.split("\n")
|
|
||||||
.filter((line) => !this._textFilterRules.some((part) => line.includes(part)))
|
|
||||||
.filter((line, idx, arr) => (arr.length > 3 && idx <= arr.length - 3 ? !["", "\r"].includes(line) : true)) // Filter out empty lines and carriage returns, but keep the last 3 lines if they exist
|
|
||||||
.join("\n");
|
|
||||||
return updatedContent;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -135,7 +135,11 @@ export class AttachAddon implements ITerminalAddon {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (this._allowTerminalWrite) {
|
if (this._allowTerminalWrite) {
|
||||||
const updatedData = this._shellHandler?.updateTerminalData(data) ?? data;
|
const updatedData =
|
||||||
|
typeof this._shellHandler?.updateTerminalData === "function"
|
||||||
|
? this._shellHandler.updateTerminalData(data)
|
||||||
|
: data;
|
||||||
|
|
||||||
const suppressedData = this._shellHandler?.getTerminalSuppressedData();
|
const suppressedData = this._shellHandler?.getTerminalSuppressedData();
|
||||||
|
|
||||||
const shouldNotWrite = suppressedData.filter(Boolean).some((item) => updatedData.includes(item));
|
const shouldNotWrite = suppressedData.filter(Boolean).some((item) => updatedData.includes(item));
|
||||||
|
|||||||
71
src/Explorer/Tabs/CloudShellTab/Utils/CloudShellIPUtils.ts
Normal file
71
src/Explorer/Tabs/CloudShellTab/Utils/CloudShellIPUtils.ts
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
import { userContext } from "../../../../UserContext";
|
||||||
|
|
||||||
|
export const CLOUDSHELL_IP_RECOMMENDATIONS = {
|
||||||
|
centralindia: [
|
||||||
|
{ startIP: "4.247.135.109", endIP: "4.247.135.109" },
|
||||||
|
{ startIP: "74.225.207.63", endIP: "74.225.207.63" },
|
||||||
|
],
|
||||||
|
southeastasia: [{ startIP: "4.194.5.74", endIP: "4.194.213.10" }],
|
||||||
|
centraluseuap: [
|
||||||
|
{ startIP: "52.158.186.182", endIP: "52.158.186.182" },
|
||||||
|
{ startIP: "172.215.26.246", endIP: "172.215.26.246" },
|
||||||
|
{ startIP: "134.138.154.177", endIP: "134.138.154.177" },
|
||||||
|
{ startIP: "134.138.129.52", endIP: "134.138.129.52" },
|
||||||
|
{ startIP: "172.215.31.177", endIP: "172.215.31.177" },
|
||||||
|
],
|
||||||
|
eastus2euap: [
|
||||||
|
{ startIP: "135.18.43.51", endIP: "135.18.43.51" },
|
||||||
|
{ startIP: "20.252.175.33", endIP: "20.252.175.33" },
|
||||||
|
{ startIP: "40.89.88.111", endIP: "40.89.88.111" },
|
||||||
|
{ startIP: "135.18.17.187", endIP: "135.18.17.187" },
|
||||||
|
{ startIP: "135.18.67.251", endIP: "135.18.67.251" },
|
||||||
|
],
|
||||||
|
eastus: [
|
||||||
|
{ startIP: "40.71.199.151", endIP: "40.71.199.151" },
|
||||||
|
{ startIP: "20.42.18.188", endIP: "20.42.18.188" },
|
||||||
|
{ startIP: "52.190.17.9", endIP: "52.190.17.9" },
|
||||||
|
{ startIP: "20.120.96.152", endIP: "20.120.96.152" },
|
||||||
|
],
|
||||||
|
northeurope: [
|
||||||
|
{ startIP: "74.234.65.146", endIP: "74.234.65.146" },
|
||||||
|
{ startIP: "52.169.70.113", endIP: "52.169.70.113" },
|
||||||
|
],
|
||||||
|
southcentralus: [
|
||||||
|
{ startIP: "4.151.247.81", endIP: "4.151.247.81" },
|
||||||
|
{ startIP: "20.225.211.35", endIP: "20.225.211.35" },
|
||||||
|
{ startIP: "4.151.48.133", endIP: "4.151.48.133" },
|
||||||
|
{ startIP: "4.151.247.225", endIP: "4.151.247.225" },
|
||||||
|
],
|
||||||
|
westeurope: [
|
||||||
|
{ startIP: "52.166.126.216", endIP: "52.166.126.216" },
|
||||||
|
{ startIP: "108.142.162.20", endIP: "108.142.162.20" },
|
||||||
|
{ startIP: "52.178.13.125", endIP: "52.178.13.125" },
|
||||||
|
{ startIP: "172.201.33.160", endIP: "172.201.33.160" },
|
||||||
|
],
|
||||||
|
westus: [
|
||||||
|
{ startIP: "20.245.161.131", endIP: "20.245.161.131" },
|
||||||
|
{ startIP: "57.154.182.51", endIP: "57.154.182.51" },
|
||||||
|
{ startIP: "40.118.133.244", endIP: "40.118.133.244" },
|
||||||
|
{ startIP: "20.253.192.12", endIP: "20.253.192.12" },
|
||||||
|
{ startIP: "20.43.245.209", endIP: "20.43.245.209" },
|
||||||
|
{ startIP: "20.66.22.66", endIP: "20.66.22.66" },
|
||||||
|
],
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
export interface CloudShellIPRange {
|
||||||
|
startIP: string;
|
||||||
|
endIP: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getCloudShellIPsForRegion(region: string): readonly CloudShellIPRange[] {
|
||||||
|
const normalizedRegion = region.toLowerCase();
|
||||||
|
return CLOUDSHELL_IP_RECOMMENDATIONS[normalizedRegion as keyof typeof CLOUDSHELL_IP_RECOMMENDATIONS] || [];
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getClusterRegion(): string {
|
||||||
|
const location = userContext?.databaseAccount?.location;
|
||||||
|
if (location) {
|
||||||
|
return location.toLowerCase();
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
@@ -50,3 +50,34 @@ export const getShellNameForDisplay = (terminalKind: TerminalKind): string => {
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get MongoDB shell information text that should be removed from terminal output
|
||||||
|
*/
|
||||||
|
export const getMongoShellRemoveInfoText = (): string[] => {
|
||||||
|
return [
|
||||||
|
"For mongosh info see: https://www.mongodb.com/docs/mongodb-shell/",
|
||||||
|
"disableTelemetry() command",
|
||||||
|
"https://www.mongodb.com/legal/privacy-policy",
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
export const filterAndCleanTerminalOutput = (data: string, removeInfoText: string[]): string => {
|
||||||
|
if (!data || removeInfoText.length === 0) {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
const lines = data.split("\n");
|
||||||
|
const filteredLines: string[] = [];
|
||||||
|
|
||||||
|
for (let i = 0; i < lines.length; i++) {
|
||||||
|
const line = lines[i];
|
||||||
|
const shouldRemove = removeInfoText.some((text) => line.includes(text));
|
||||||
|
|
||||||
|
if (!shouldRemove) {
|
||||||
|
filteredLines.push(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return filteredLines.join("\n").replace(/((\r\n)|\n|\r){2,}/g, "\r\n");
|
||||||
|
};
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ const validCloudShellRegions = new Set([
|
|||||||
"centralindia",
|
"centralindia",
|
||||||
"southeastasia",
|
"southeastasia",
|
||||||
"westcentralus",
|
"westcentralus",
|
||||||
|
"usgovvirginia",
|
||||||
|
"usgovarizona",
|
||||||
]);
|
]);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
78
src/Explorer/Tabs/Shared/CloudShellIPChecker.ts
Normal file
78
src/Explorer/Tabs/Shared/CloudShellIPChecker.ts
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
import { configContext } from "ConfigContext";
|
||||||
|
import * as DataModels from "Contracts/DataModels";
|
||||||
|
import { userContext } from "UserContext";
|
||||||
|
import { armRequest } from "Utils/arm/request";
|
||||||
|
import {
|
||||||
|
CloudShellIPRange,
|
||||||
|
getCloudShellIPsForRegion,
|
||||||
|
getClusterRegion,
|
||||||
|
} from "../CloudShellTab/Utils/CloudShellIPUtils";
|
||||||
|
import { getNormalizedRegion } from "../CloudShellTab/Utils/RegionUtils";
|
||||||
|
|
||||||
|
// Constants
|
||||||
|
const DEFAULT_CLOUDSHELL_REGION = "westus";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if user has added all CloudShell IPs for their normalized region
|
||||||
|
* @param apiVersion - The API version to use for the ARM request
|
||||||
|
* @returns Promise<boolean> - true if all CloudShell IPs are configured (don't show screenshot), false if missing (show screenshot)
|
||||||
|
*/
|
||||||
|
export async function checkCloudShellIPsConfigured(apiVersion: string): Promise<boolean> {
|
||||||
|
const clusterRegion = getClusterRegion();
|
||||||
|
|
||||||
|
if (!clusterRegion) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const normalizedRegion = getNormalizedRegion(clusterRegion, DEFAULT_CLOUDSHELL_REGION);
|
||||||
|
const cloudShellIPs = getCloudShellIPsForRegion(normalizedRegion);
|
||||||
|
|
||||||
|
if (cloudShellIPs.length === 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const firewallRulesUri = `${userContext.databaseAccount.id}/firewallRules`;
|
||||||
|
const response: any = await armRequest({
|
||||||
|
host: configContext.ARM_ENDPOINT,
|
||||||
|
path: firewallRulesUri,
|
||||||
|
method: "GET",
|
||||||
|
apiVersion: apiVersion,
|
||||||
|
});
|
||||||
|
|
||||||
|
const firewallRules: DataModels.FirewallRule[] = response?.data?.value || response?.value || [];
|
||||||
|
|
||||||
|
const missingIPs: Array<{ startIP: string; endIP: string; reason?: string }> = [];
|
||||||
|
const foundIPs: Array<{ startIP: string; endIP: string; ruleName?: string }> = [];
|
||||||
|
|
||||||
|
for (const cloudShellIP of cloudShellIPs) {
|
||||||
|
const matchingRule = firewallRules.find((rule) => {
|
||||||
|
const startMatch = rule.properties.startIpAddress === cloudShellIP.startIP;
|
||||||
|
const endMatch = rule.properties.endIpAddress === cloudShellIP.endIP;
|
||||||
|
return startMatch && endMatch;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (matchingRule) {
|
||||||
|
foundIPs.push({ ...cloudShellIP, ruleName: matchingRule.name });
|
||||||
|
} else {
|
||||||
|
missingIPs.push({ ...cloudShellIP, reason: "No exact IP match in firewall rules" });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const allConfigured = missingIPs.length === 0;
|
||||||
|
return allConfigured;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the normalized region and its CloudShell IPs for display in the guide
|
||||||
|
* @returns Object with region and IPs for the guide
|
||||||
|
*/
|
||||||
|
export function getCloudShellGuideInfo(): { region: string; cloudShellIPs: readonly CloudShellIPRange[] } {
|
||||||
|
const clusterRegion = getClusterRegion();
|
||||||
|
const normalizedRegion = getNormalizedRegion(clusterRegion || "", DEFAULT_CLOUDSHELL_REGION);
|
||||||
|
const cloudShellIPs = getCloudShellIPsForRegion(normalizedRegion);
|
||||||
|
|
||||||
|
return {
|
||||||
|
region: normalizedRegion,
|
||||||
|
cloudShellIPs: cloudShellIPs,
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -22,10 +22,22 @@ export abstract class BaseTerminalComponentAdapter implements ReactAdapter {
|
|||||||
protected getUsername: () => string,
|
protected getUsername: () => string,
|
||||||
protected isAllPublicIPAddressesEnabled: ko.Observable<boolean>,
|
protected isAllPublicIPAddressesEnabled: ko.Observable<boolean>,
|
||||||
protected kind: ViewModels.TerminalKind,
|
protected kind: ViewModels.TerminalKind,
|
||||||
) {}
|
protected isCloudShellIPsConfigured?: ko.Observable<boolean>,
|
||||||
|
) { }
|
||||||
|
|
||||||
public renderComponent(): JSX.Element {
|
public renderComponent(): JSX.Element {
|
||||||
if (!this.isAllPublicIPAddressesEnabled()) {
|
const publicIPEnabled = this.isAllPublicIPAddressesEnabled();
|
||||||
|
const cloudShellConfigured = this.isCloudShellIPsConfigured ? this.isCloudShellIPsConfigured() : true;
|
||||||
|
let shouldShowScreenshot: boolean;
|
||||||
|
|
||||||
|
if (this.isCloudShellIPsConfigured) {
|
||||||
|
shouldShowScreenshot = !cloudShellConfigured;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
shouldShowScreenshot = !publicIPEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shouldShowScreenshot) {
|
||||||
return (
|
return (
|
||||||
<QuickstartFirewallNotification
|
<QuickstartFirewallNotification
|
||||||
messageType={this.getMessageType()}
|
messageType={this.getMessageType()}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { checkFirewallRules } from "Explorer/Tabs/Shared/CheckFirewallRules";
|
import { checkFirewallRules } from "Explorer/Tabs/Shared/CheckFirewallRules";
|
||||||
|
import { checkCloudShellIPsConfigured } from "Explorer/Tabs/Shared/CloudShellIPChecker";
|
||||||
import { CloudShellTerminalComponentAdapter } from "Explorer/Tabs/ShellAdapters/CloudShellTerminalComponentAdapter";
|
import { CloudShellTerminalComponentAdapter } from "Explorer/Tabs/ShellAdapters/CloudShellTerminalComponentAdapter";
|
||||||
import * as ko from "knockout";
|
import * as ko from "knockout";
|
||||||
import { ReactAdapter } from "../../Bindings/ReactBindingHandler";
|
import { ReactAdapter } from "../../Bindings/ReactBindingHandler";
|
||||||
@@ -23,11 +24,13 @@ export default class TerminalTab extends TabsBase {
|
|||||||
private container: Explorer;
|
private container: Explorer;
|
||||||
private notebookTerminalComponentAdapter: ReactAdapter;
|
private notebookTerminalComponentAdapter: ReactAdapter;
|
||||||
private isAllPublicIPAddressesEnabled: ko.Observable<boolean>;
|
private isAllPublicIPAddressesEnabled: ko.Observable<boolean>;
|
||||||
|
private isCloudShellIPsConfigured: ko.Observable<boolean>;
|
||||||
|
|
||||||
constructor(options: TerminalTabOptions) {
|
constructor(options: TerminalTabOptions) {
|
||||||
super(options);
|
super(options);
|
||||||
this.container = options.container;
|
this.container = options.container;
|
||||||
this.isAllPublicIPAddressesEnabled = ko.observable(true);
|
this.isAllPublicIPAddressesEnabled = ko.observable(true);
|
||||||
|
this.isCloudShellIPsConfigured = ko.observable(true); // Start optimistic, will be updated
|
||||||
|
|
||||||
const commonArgs: [
|
const commonArgs: [
|
||||||
() => DataModels.DatabaseAccount,
|
() => DataModels.DatabaseAccount,
|
||||||
@@ -36,18 +39,33 @@ export default class TerminalTab extends TabsBase {
|
|||||||
ko.Observable<boolean>,
|
ko.Observable<boolean>,
|
||||||
ViewModels.TerminalKind,
|
ViewModels.TerminalKind,
|
||||||
] = [
|
] = [
|
||||||
() => userContext?.databaseAccount,
|
() => userContext?.databaseAccount,
|
||||||
() => this.tabId,
|
() => this.tabId,
|
||||||
() => this.getUsername(),
|
() => this.getUsername(),
|
||||||
this.isAllPublicIPAddressesEnabled,
|
this.isAllPublicIPAddressesEnabled,
|
||||||
options.kind,
|
options.kind,
|
||||||
];
|
];
|
||||||
|
|
||||||
if (userContext.features.enableCloudShell) {
|
if (userContext.features.enableCloudShell) {
|
||||||
this.notebookTerminalComponentAdapter = new CloudShellTerminalComponentAdapter(...commonArgs);
|
this.notebookTerminalComponentAdapter = new CloudShellTerminalComponentAdapter(
|
||||||
|
() => userContext?.databaseAccount,
|
||||||
|
() => this.tabId,
|
||||||
|
() => this.getUsername(),
|
||||||
|
this.isAllPublicIPAddressesEnabled,
|
||||||
|
options.kind,
|
||||||
|
this.isCloudShellIPsConfigured,
|
||||||
|
);
|
||||||
|
|
||||||
this.notebookTerminalComponentAdapter.parameters = ko.computed<boolean>(() => {
|
this.notebookTerminalComponentAdapter.parameters = ko.computed<boolean>(() => {
|
||||||
return this.isTemplateReady() && this.isAllPublicIPAddressesEnabled();
|
const cloudShellConfigured = this.isCloudShellIPsConfigured();
|
||||||
|
return this.isTemplateReady() && cloudShellConfigured;
|
||||||
|
});
|
||||||
|
|
||||||
|
checkCloudShellIPsConfigured("2023-03-01-preview").then(result => {
|
||||||
|
this.isCloudShellIPsConfigured(result);
|
||||||
|
}).catch(error => {
|
||||||
|
console.error(`CloudShell IP Check failed for ${ViewModels.TerminalKind[options.kind]} terminal:`, error);
|
||||||
|
this.isCloudShellIPsConfigured(false);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
this.notebookTerminalComponentAdapter = new NotebookTerminalComponentAdapter(
|
this.notebookTerminalComponentAdapter = new NotebookTerminalComponentAdapter(
|
||||||
@@ -65,22 +83,25 @@ export default class TerminalTab extends TabsBase {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.kind === ViewModels.TerminalKind.Postgres) {
|
// Only run legacy firewall checks for NON-CloudShell terminals cloudShell terminals use the CloudShell IP checker instead
|
||||||
checkFirewallRules(
|
if (!userContext.features.enableCloudShell) {
|
||||||
"2022-11-08",
|
if (options.kind === ViewModels.TerminalKind.Postgres) {
|
||||||
(rule) => rule.properties.startIpAddress === "0.0.0.0" && rule.properties.endIpAddress === "255.255.255.255",
|
checkFirewallRules(
|
||||||
this.isAllPublicIPAddressesEnabled,
|
"2022-11-08",
|
||||||
);
|
(rule) => rule.properties.startIpAddress === "0.0.0.0" && rule.properties.endIpAddress === "255.255.255.255",
|
||||||
}
|
this.isAllPublicIPAddressesEnabled,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (options.kind === ViewModels.TerminalKind.VCoreMongo) {
|
if (options.kind === ViewModels.TerminalKind.VCoreMongo) {
|
||||||
checkFirewallRules(
|
checkFirewallRules(
|
||||||
"2023-03-01-preview",
|
"2023-03-01-preview",
|
||||||
(rule) =>
|
(rule) =>
|
||||||
rule.name.startsWith("AllowAllAzureServicesAndResourcesWithinAzureIps") ||
|
rule.name.startsWith("AllowAllAzureServicesAndResourcesWithinAzureIps") ||
|
||||||
(rule.properties.startIpAddress === "0.0.0.0" && rule.properties.endIpAddress === "255.255.255.255"),
|
(rule.properties.startIpAddress === "0.0.0.0" && rule.properties.endIpAddress === "255.255.255.255"),
|
||||||
this.isAllPublicIPAddressesEnabled,
|
this.isAllPublicIPAddressesEnabled,
|
||||||
);
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user