Show portal networking banner for new backend (#1952)
* show portal networking banner for new backend * fixed valid endpoints * format * fixed tests * Fixed tests * fix tests * fixed tests --------- Co-authored-by: Asier Isayas <aisayas@microsoft.com>
This commit is contained in:
parent
c5b7f599b3
commit
4b207f3fa6
|
@ -135,6 +135,7 @@ export class BackendApi {
|
||||||
public static readonly PortalSettings: string = "PortalSettings";
|
public static readonly PortalSettings: string = "PortalSettings";
|
||||||
public static readonly AccountRestrictions: string = "AccountRestrictions";
|
public static readonly AccountRestrictions: string = "AccountRestrictions";
|
||||||
public static readonly RuntimeProxy: string = "RuntimeProxy";
|
public static readonly RuntimeProxy: string = "RuntimeProxy";
|
||||||
|
public static readonly DisallowedLocations: string = "DisallowedLocations";
|
||||||
}
|
}
|
||||||
|
|
||||||
export class PortalBackendEndpoints {
|
export class PortalBackendEndpoints {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { isPublicInternetAccessAllowed } from "Common/DatabaseAccountUtility";
|
import { isPublicInternetAccessAllowed } from "Common/DatabaseAccountUtility";
|
||||||
import { PhoenixClient } from "Phoenix/PhoenixClient";
|
import { PhoenixClient } from "Phoenix/PhoenixClient";
|
||||||
|
import { useNewPortalBackendEndpoint } from "Utils/EndpointUtils";
|
||||||
import { cloneDeep } from "lodash";
|
import { cloneDeep } from "lodash";
|
||||||
import create, { UseStore } from "zustand";
|
import create, { UseStore } from "zustand";
|
||||||
import { AuthType } from "../../AuthType";
|
import { AuthType } from "../../AuthType";
|
||||||
|
@ -127,7 +128,9 @@ export const useNotebook: UseStore<NotebookState> = create((set, get) => ({
|
||||||
userContext.apiType === "Postgres" || userContext.apiType === "VCoreMongo"
|
userContext.apiType === "Postgres" || userContext.apiType === "VCoreMongo"
|
||||||
? databaseAccount?.location
|
? databaseAccount?.location
|
||||||
: databaseAccount?.properties?.writeLocations?.[0]?.locationName.toLowerCase();
|
: databaseAccount?.properties?.writeLocations?.[0]?.locationName.toLowerCase();
|
||||||
const disallowedLocationsUri = `${configContext.BACKEND_ENDPOINT}/api/disallowedLocations`;
|
const disallowedLocationsUri: string = useNewPortalBackendEndpoint(Constants.BackendApi.DisallowedLocations)
|
||||||
|
? `${configContext.PORTAL_BACKEND_ENDPOINT}/api/disallowedlocations`
|
||||||
|
: `${configContext.BACKEND_ENDPOINT}/api/disallowedLocations`;
|
||||||
const authorizationHeader = getAuthorizationHeader();
|
const authorizationHeader = getAuthorizationHeader();
|
||||||
try {
|
try {
|
||||||
const response = await fetch(disallowedLocationsUri, {
|
const response = await fetch(disallowedLocationsUri, {
|
||||||
|
|
|
@ -78,6 +78,13 @@ export const PortalBackendIPs: { [key: string]: string[] } = {
|
||||||
//usnat: ["7.28.202.68"],
|
//usnat: ["7.28.202.68"],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const PortalBackendOutboundIPs: { [key: string]: string[] } = {
|
||||||
|
[PortalBackendEndpoints.Mpac]: ["13.91.105.215", "4.210.172.107"],
|
||||||
|
[PortalBackendEndpoints.Prod]: ["13.88.56.148", "40.91.218.243"],
|
||||||
|
[PortalBackendEndpoints.Fairfax]: ["52.247.163.6", "52.244.134.181"],
|
||||||
|
[PortalBackendEndpoints.Mooncake]: ["163.228.137.6", "143.64.170.142"],
|
||||||
|
};
|
||||||
|
|
||||||
export const MongoProxyOutboundIPs: { [key: string]: string[] } = {
|
export const MongoProxyOutboundIPs: { [key: string]: string[] } = {
|
||||||
[MongoProxyEndpoints.Mpac]: ["20.245.81.54", "40.118.23.126"],
|
[MongoProxyEndpoints.Mpac]: ["20.245.81.54", "40.118.23.126"],
|
||||||
[MongoProxyEndpoints.Prod]: ["40.80.152.199", "13.95.130.121"],
|
[MongoProxyEndpoints.Prod]: ["40.80.152.199", "13.95.130.121"],
|
||||||
|
@ -178,6 +185,13 @@ export function useNewPortalBackendEndpoint(backendApi: string): boolean {
|
||||||
PortalBackendEndpoints.Mpac,
|
PortalBackendEndpoints.Mpac,
|
||||||
PortalBackendEndpoints.Prod,
|
PortalBackendEndpoints.Prod,
|
||||||
],
|
],
|
||||||
|
[BackendApi.DisallowedLocations]: [
|
||||||
|
PortalBackendEndpoints.Development,
|
||||||
|
PortalBackendEndpoints.Mpac,
|
||||||
|
PortalBackendEndpoints.Prod,
|
||||||
|
PortalBackendEndpoints.Fairfax,
|
||||||
|
PortalBackendEndpoints.Mooncake,
|
||||||
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!newBackendApiEnvironmentMap[backendApi] || !configContext.PORTAL_BACKEND_ENDPOINT) {
|
if (!newBackendApiEnvironmentMap[backendApi] || !configContext.PORTAL_BACKEND_ENDPOINT) {
|
||||||
|
|
|
@ -1,20 +1,15 @@
|
||||||
|
import { MongoProxyEndpoints, PortalBackendEndpoints } from "Common/Constants";
|
||||||
import { resetConfigContext, updateConfigContext } from "ConfigContext";
|
import { resetConfigContext, updateConfigContext } from "ConfigContext";
|
||||||
import { DatabaseAccount, IpRule } from "Contracts/DataModels";
|
import { DatabaseAccount, IpRule } from "Contracts/DataModels";
|
||||||
import { updateUserContext } from "UserContext";
|
import { updateUserContext } from "UserContext";
|
||||||
import { PortalBackendIPs } from "Utils/EndpointUtils";
|
import { MongoProxyOutboundIPs, PortalBackendIPs, PortalBackendOutboundIPs } from "Utils/EndpointUtils";
|
||||||
import { getNetworkSettingsWarningMessage } from "./NetworkUtility";
|
import { getNetworkSettingsWarningMessage } from "./NetworkUtility";
|
||||||
|
|
||||||
describe("NetworkUtility tests", () => {
|
describe("NetworkUtility tests", () => {
|
||||||
describe("getNetworkSettingsWarningMessage", () => {
|
describe("getNetworkSettingsWarningMessage", () => {
|
||||||
|
const legacyBackendEndpoint: string = "https://main.documentdb.ext.azure.com";
|
||||||
const publicAccessMessagePart = "Please enable public access to proceed";
|
const publicAccessMessagePart = "Please enable public access to proceed";
|
||||||
const accessMessagePart = "Please allow access from Azure Portal to proceed";
|
const accessMessagePart = "Please allow access from Azure Portal to proceed";
|
||||||
// validEnpoints are a subset of those from Utils/EndpointValidation/PortalBackendIPs
|
|
||||||
const validEndpoints = [
|
|
||||||
"https://main.documentdb.ext.azure.com",
|
|
||||||
"https://main.documentdb.ext.azure.cn",
|
|
||||||
"https://main.documentdb.ext.azure.us",
|
|
||||||
];
|
|
||||||
|
|
||||||
let warningMessageResult: string;
|
let warningMessageResult: string;
|
||||||
const warningMessageFunc = (msg: string) => (warningMessageResult = msg);
|
const warningMessageFunc = (msg: string) => (warningMessageResult = msg);
|
||||||
|
|
||||||
|
@ -52,52 +47,59 @@ describe("NetworkUtility tests", () => {
|
||||||
expect(warningMessageResult).toContain(publicAccessMessagePart);
|
expect(warningMessageResult).toContain(publicAccessMessagePart);
|
||||||
});
|
});
|
||||||
|
|
||||||
it(`should return no message when the appropriate ip rules are added to mongo/cassandra account per endpoint`, () => {
|
it(`should return no message when the appropriate ip rules are added to mongo/cassandra account per endpoint`, async () => {
|
||||||
validEndpoints.forEach(async (endpoint) => {
|
const portalBackendOutboundIPsWithLegacyIPs: string[] = [
|
||||||
updateUserContext({
|
...PortalBackendOutboundIPs[PortalBackendEndpoints.Mpac],
|
||||||
databaseAccount: {
|
...PortalBackendOutboundIPs[PortalBackendEndpoints.Prod],
|
||||||
kind: "MongoDB",
|
...MongoProxyOutboundIPs[MongoProxyEndpoints.Mpac],
|
||||||
properties: {
|
...MongoProxyOutboundIPs[MongoProxyEndpoints.Prod],
|
||||||
ipRules: PortalBackendIPs[endpoint].map((ip: string) => ({ ipAddressOrRange: ip }) as IpRule),
|
...PortalBackendIPs["https://main.documentdb.ext.azure.com"],
|
||||||
publicNetworkAccess: "Enabled",
|
];
|
||||||
},
|
updateUserContext({
|
||||||
} as DatabaseAccount,
|
databaseAccount: {
|
||||||
});
|
kind: "MongoDB",
|
||||||
|
properties: {
|
||||||
updateConfigContext({
|
ipRules: portalBackendOutboundIPsWithLegacyIPs.map((ip: string) => ({ ipAddressOrRange: ip }) as IpRule),
|
||||||
BACKEND_ENDPOINT: endpoint,
|
publicNetworkAccess: "Enabled",
|
||||||
});
|
},
|
||||||
|
} as DatabaseAccount,
|
||||||
let asyncWarningMessageResult: string;
|
|
||||||
const asyncWarningMessageFunc = (msg: string) => (asyncWarningMessageResult = msg);
|
|
||||||
|
|
||||||
await getNetworkSettingsWarningMessage(asyncWarningMessageFunc);
|
|
||||||
expect(asyncWarningMessageResult).toBeUndefined();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
updateConfigContext({
|
||||||
|
BACKEND_ENDPOINT: legacyBackendEndpoint,
|
||||||
|
PORTAL_BACKEND_ENDPOINT: PortalBackendEndpoints.Mpac,
|
||||||
|
MONGO_PROXY_ENDPOINT: MongoProxyEndpoints.Mpac,
|
||||||
|
});
|
||||||
|
|
||||||
|
let asyncWarningMessageResult: string;
|
||||||
|
const asyncWarningMessageFunc = (msg: string) => (asyncWarningMessageResult = msg);
|
||||||
|
|
||||||
|
await getNetworkSettingsWarningMessage(asyncWarningMessageFunc);
|
||||||
|
expect(asyncWarningMessageResult).toBeUndefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should return accessMessage when incorrent ip rule is added to mongo/cassandra account per endpoint", () => {
|
it("should return accessMessage when incorrent ip rule is added to mongo/cassandra account per endpoint", async () => {
|
||||||
validEndpoints.forEach(async (endpoint) => {
|
updateUserContext({
|
||||||
updateUserContext({
|
databaseAccount: {
|
||||||
databaseAccount: {
|
kind: "MongoDB",
|
||||||
kind: "MongoDB",
|
properties: {
|
||||||
properties: {
|
ipRules: [{ ipAddressOrRange: "1.1.1.1" }],
|
||||||
ipRules: [{ ipAddressOrRange: "1.1.1.1" }],
|
publicNetworkAccess: "Enabled",
|
||||||
publicNetworkAccess: "Enabled",
|
},
|
||||||
},
|
} as DatabaseAccount,
|
||||||
} as DatabaseAccount,
|
|
||||||
});
|
|
||||||
|
|
||||||
updateConfigContext({
|
|
||||||
BACKEND_ENDPOINT: endpoint,
|
|
||||||
});
|
|
||||||
|
|
||||||
let asyncWarningMessageResult: string;
|
|
||||||
const asyncWarningMessageFunc = (msg: string) => (asyncWarningMessageResult = msg);
|
|
||||||
|
|
||||||
await getNetworkSettingsWarningMessage(asyncWarningMessageFunc);
|
|
||||||
expect(asyncWarningMessageResult).toContain(accessMessagePart);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
updateConfigContext({
|
||||||
|
BACKEND_ENDPOINT: legacyBackendEndpoint,
|
||||||
|
PORTAL_BACKEND_ENDPOINT: PortalBackendEndpoints.Mpac,
|
||||||
|
MONGO_PROXY_ENDPOINT: MongoProxyEndpoints.Mpac,
|
||||||
|
});
|
||||||
|
|
||||||
|
let asyncWarningMessageResult: string;
|
||||||
|
const asyncWarningMessageFunc = (msg: string) => (asyncWarningMessageResult = msg);
|
||||||
|
|
||||||
|
await getNetworkSettingsWarningMessage(asyncWarningMessageFunc);
|
||||||
|
expect(asyncWarningMessageResult).toContain(accessMessagePart);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Postgres and vcore mongo account checks basically pass through to CheckFirewallRules so those
|
// Postgres and vcore mongo account checks basically pass through to CheckFirewallRules so those
|
||||||
|
|
|
@ -1,7 +1,13 @@
|
||||||
|
import { CassandraProxyEndpoints, MongoProxyEndpoints, PortalBackendEndpoints } from "Common/Constants";
|
||||||
import { configContext } from "ConfigContext";
|
import { configContext } from "ConfigContext";
|
||||||
import { checkFirewallRules } from "Explorer/Tabs/Shared/CheckFirewallRules";
|
import { checkFirewallRules } from "Explorer/Tabs/Shared/CheckFirewallRules";
|
||||||
import { userContext } from "UserContext";
|
import { userContext } from "UserContext";
|
||||||
import { PortalBackendIPs } from "Utils/EndpointUtils";
|
import {
|
||||||
|
CassandraProxyOutboundIPs,
|
||||||
|
MongoProxyOutboundIPs,
|
||||||
|
PortalBackendIPs,
|
||||||
|
PortalBackendOutboundIPs,
|
||||||
|
} from "Utils/EndpointUtils";
|
||||||
|
|
||||||
export const getNetworkSettingsWarningMessage = async (
|
export const getNetworkSettingsWarningMessage = async (
|
||||||
setStateFunc: (warningMessage: string) => void,
|
setStateFunc: (warningMessage: string) => void,
|
||||||
|
@ -45,18 +51,53 @@ export const getNetworkSettingsWarningMessage = async (
|
||||||
const ipRules = accountProperties.ipRules;
|
const ipRules = accountProperties.ipRules;
|
||||||
// public network access is NOT set to "All networks"
|
// public network access is NOT set to "All networks"
|
||||||
if (ipRules?.length > 0) {
|
if (ipRules?.length > 0) {
|
||||||
if (userContext.apiType === "Cassandra" || userContext.apiType === "Mongo") {
|
const isProdOrMpacPortalBackendEndpoint: boolean = [
|
||||||
const portalIPs = PortalBackendIPs[configContext.BACKEND_ENDPOINT];
|
PortalBackendEndpoints.Mpac,
|
||||||
let numberOfMatches = 0;
|
PortalBackendEndpoints.Prod,
|
||||||
ipRules.forEach((ipRule) => {
|
].includes(configContext.PORTAL_BACKEND_ENDPOINT);
|
||||||
if (portalIPs.indexOf(ipRule.ipAddressOrRange) !== -1) {
|
const portalBackendOutboundIPs: string[] = isProdOrMpacPortalBackendEndpoint
|
||||||
numberOfMatches++;
|
? [
|
||||||
}
|
...PortalBackendOutboundIPs[PortalBackendEndpoints.Mpac],
|
||||||
});
|
...PortalBackendOutboundIPs[PortalBackendEndpoints.Prod],
|
||||||
|
]
|
||||||
|
: PortalBackendOutboundIPs[configContext.PORTAL_BACKEND_ENDPOINT];
|
||||||
|
let portalIPs: string[] = [...portalBackendOutboundIPs, ...PortalBackendIPs[configContext.BACKEND_ENDPOINT]];
|
||||||
|
|
||||||
if (numberOfMatches !== portalIPs.length) {
|
if (userContext.apiType === "Mongo") {
|
||||||
setStateFunc(accessMessage);
|
const isProdOrMpacMongoProxyEndpoint: boolean = [MongoProxyEndpoints.Mpac, MongoProxyEndpoints.Prod].includes(
|
||||||
|
configContext.MONGO_PROXY_ENDPOINT,
|
||||||
|
);
|
||||||
|
|
||||||
|
const mongoProxyOutboundIPs: string[] = isProdOrMpacMongoProxyEndpoint
|
||||||
|
? [...MongoProxyOutboundIPs[MongoProxyEndpoints.Mpac], ...MongoProxyOutboundIPs[MongoProxyEndpoints.Prod]]
|
||||||
|
: MongoProxyOutboundIPs[configContext.MONGO_PROXY_ENDPOINT];
|
||||||
|
|
||||||
|
portalIPs = [...portalIPs, ...mongoProxyOutboundIPs];
|
||||||
|
} else if (userContext.apiType === "Cassandra") {
|
||||||
|
const isProdOrMpacCassandraProxyEndpoint: boolean = [
|
||||||
|
CassandraProxyEndpoints.Mpac,
|
||||||
|
CassandraProxyEndpoints.Prod,
|
||||||
|
].includes(configContext.CASSANDRA_PROXY_ENDPOINT);
|
||||||
|
|
||||||
|
const cassandraProxyOutboundIPs: string[] = isProdOrMpacCassandraProxyEndpoint
|
||||||
|
? [
|
||||||
|
...CassandraProxyOutboundIPs[CassandraProxyEndpoints.Mpac],
|
||||||
|
...CassandraProxyOutboundIPs[CassandraProxyEndpoints.Prod],
|
||||||
|
]
|
||||||
|
: CassandraProxyOutboundIPs[configContext.CASSANDRA_PROXY_ENDPOINT];
|
||||||
|
|
||||||
|
portalIPs = [...portalIPs, ...cassandraProxyOutboundIPs];
|
||||||
|
}
|
||||||
|
|
||||||
|
let numberOfMatches = 0;
|
||||||
|
ipRules.forEach((ipRule) => {
|
||||||
|
if (portalIPs.indexOf(ipRule.ipAddressOrRange) !== -1) {
|
||||||
|
numberOfMatches++;
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (numberOfMatches !== portalIPs.length) {
|
||||||
|
setStateFunc(accessMessage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue