From e09930d9d02e18fa6315e2d3c7f171a46809112c Mon Sep 17 00:00:00 2001 From: Asier Isayas Date: Fri, 22 Mar 2024 13:18:02 -0400 Subject: [PATCH] Support Token API in new Portal Backend (#1773) * added support for generate token * fix checks * fix checks * deactivate mongo proxy * fix tests * remove mongo proxy from mpac * change endpoints to prod * npm run format * add await --------- Co-authored-by: Asier Isayas --- src/Common/Constants.ts | 44 ++++++++++++------- src/Common/MongoProxyClient.ts | 3 +- src/ConfigContext.ts | 12 ++++- .../Hosted/Components/ConnectExplorer.tsx | 20 ++++++++- src/Utils/EndpointUtils.ts | 15 ++++++- 5 files changed, 74 insertions(+), 20 deletions(-) diff --git a/src/Common/Constants.ts b/src/Common/Constants.ts index 041ecf132..fe9c2672d 100644 --- a/src/Common/Constants.ts +++ b/src/Common/Constants.ts @@ -124,6 +124,34 @@ export enum MongoBackendEndpointType { remote, } +export enum BackendApi { + GenerateToken, +} + +export class PortalBackendEndpoints { + public static readonly Development: string = "https://localhost:7235"; + public static readonly Mpac: string = "https://cdb-ms-mpac-pbe.cosmos.azure.com"; + public static readonly Prod: string = "https://cdb-ms-prod-pbe.cosmos.azure.com"; + public static readonly Fairfax: string = "https://cdb-ff-prod-pbe.cosmos.azure.us"; + public static readonly Mooncake: string = "https://cdb-mc-prod-pbe.cosmos.azure.cn"; +} + +export class MongoProxyEndpoints { + public static readonly Development: string = "https://localhost:7238"; + public static readonly Mpac: string = "https://cdb-ms-mpac-mp.cosmos.azure.com"; + public static readonly Prod: string = "https://cdb-ms-prod-mp.cosmos.azure.com"; + public static readonly Fairfax: string = "https://cdb-ff-prod-mp.cosmos.azure.us"; + public static readonly Mooncake: string = "https://cdb-mc-prod-mp.cosmos.azure.cn"; +} + +export class CassandraProxyEndpoints { + public static readonly Development: string = "https://localhost:7240"; + public static readonly Mpac: string = "https://cdb-ms-mpac-cp.cosmos.azure.com"; + public static readonly Prod: string = "https://cdb-ms-prod-cp.cosmos.azure.com"; + public static readonly Fairfax: string = "https://cdb-ff-prod-cp.cosmos.azure.us"; + public static readonly Mooncake: string = "https://cdb-mc-prod-cp.cosmos.azure.cn"; +} + //TODO: Remove this when new backend is migrated over export class CassandraBackend { public static readonly createOrDeleteApi: string = "api/cassandra/createordelete"; @@ -446,22 +474,6 @@ export class JunoEndpoints { public static readonly Stage = "https://tools-staging.cosmos.azure.com"; } -export class MongoProxyEndpoints { - public static readonly Development: string = "https://localhost:7238"; - public static readonly Mpac: string = "https://cdb-ms-mpac-mp.cosmos.azure.com"; - public static readonly Prod: string = "https://cdb-ms-prod-mp.cosmos.azure.com"; - public static readonly Fairfax: string = "https://cdb-ff-prod-mp.cosmos.azure.us"; - public static readonly Mooncake: string = "https://cdb-mc-prod-mp.cosmos.azure.cn"; -} - -export class CassandraProxyEndpoints { - public static readonly Development: string = "https://localhost:7240"; - public static readonly Mpac: string = "https://cdb-ms-mpac-cp.cosmos.azure.com"; - public static readonly Prod: string = "https://cdb-ms-prod-cp.cosmos.azure.com"; - public static readonly Fairfax: string = "https://cdb-ff-prod-cp.cosmos.azure.us"; - public static readonly Mooncake: string = "https://cdb-mc-prod-cp.cosmos.azure.cn"; -} - export class PriorityLevel { public static readonly High = "high"; public static readonly Low = "low"; diff --git a/src/Common/MongoProxyClient.ts b/src/Common/MongoProxyClient.ts index 357ce1f50..e37b0eff5 100644 --- a/src/Common/MongoProxyClient.ts +++ b/src/Common/MongoProxyClient.ts @@ -690,6 +690,7 @@ export function getARMCreateCollectionEndpoint(params: DataModels.MongoParameter } function useMongoProxyEndpoint(api: string): boolean { + const activeMongoProxyEndpoints: string[] = [MongoProxyEndpoints.Development]; let canAccessMongoProxy: boolean = userContext.databaseAccount.properties.publicNetworkAccess === "Enabled"; if (userContext.databaseAccount.properties.ipRules?.length > 0) { canAccessMongoProxy = canAccessMongoProxy && configContext.MONGO_PROXY_OUTBOUND_IPS_ALLOWLISTED; @@ -698,6 +699,6 @@ function useMongoProxyEndpoint(api: string): boolean { return ( canAccessMongoProxy && configContext.NEW_MONGO_APIS?.includes(api) && - [MongoProxyEndpoints.Development, MongoProxyEndpoints.Mpac].includes(configContext.MONGO_PROXY_ENDPOINT) + activeMongoProxyEndpoints.includes(configContext.MONGO_PROXY_ENDPOINT) ); } diff --git a/src/ConfigContext.ts b/src/ConfigContext.ts index f02fa260d..e3350c7f6 100644 --- a/src/ConfigContext.ts +++ b/src/ConfigContext.ts @@ -1,4 +1,10 @@ -import { CassandraProxyEndpoints, JunoEndpoints, MongoProxyEndpoints } from "Common/Constants"; +import { + BackendApi, + CassandraProxyEndpoints, + JunoEndpoints, + MongoProxyEndpoints, + PortalBackendEndpoints, +} from "Common/Constants"; import { allowedAadEndpoints, allowedArcadiaEndpoints, @@ -39,6 +45,8 @@ export interface ConfigContext { ARCADIA_ENDPOINT: string; ARCADIA_LIVY_ENDPOINT_DNS_ZONE: string; BACKEND_ENDPOINT?: string; + PORTAL_BACKEND_ENDPOINT?: string; + NEW_BACKEND_APIS?: BackendApi[]; MONGO_BACKEND_ENDPOINT?: string; MONGO_PROXY_ENDPOINT?: string; MONGO_PROXY_OUTBOUND_IPS_ALLOWLISTED?: boolean; @@ -90,6 +98,8 @@ let configContext: Readonly = { GITHUB_TEST_ENV_CLIENT_ID: "b63fc8cbf87fd3c6e2eb", // Registered OAuth app: https://github.com/organizations/AzureCosmosDBNotebooks/settings/applications/1777772 JUNO_ENDPOINT: JunoEndpoints.Prod, BACKEND_ENDPOINT: "https://main.documentdb.ext.azure.com", + PORTAL_BACKEND_ENDPOINT: PortalBackendEndpoints.Prod, + NEW_BACKEND_APIS: [BackendApi.GenerateToken], MONGO_PROXY_ENDPOINT: MongoProxyEndpoints.Prod, NEW_MONGO_APIS: [ // "resourcelist", diff --git a/src/Platform/Hosted/Components/ConnectExplorer.tsx b/src/Platform/Hosted/Components/ConnectExplorer.tsx index dd291f279..6b33d021b 100644 --- a/src/Platform/Hosted/Components/ConnectExplorer.tsx +++ b/src/Platform/Hosted/Components/ConnectExplorer.tsx @@ -1,10 +1,11 @@ import { useBoolean } from "@fluentui/react-hooks"; import { userContext } from "UserContext"; +import { usePortalBackendEndpoint } from "Utils/EndpointUtils"; import * as React from "react"; import ConnectImage from "../../../../images/HdeConnectCosmosDB.svg"; import ErrorImage from "../../../../images/error.svg"; import { AuthType } from "../../../AuthType"; -import { HttpHeaders } from "../../../Common/Constants"; +import { BackendApi, HttpHeaders } from "../../../Common/Constants"; import { configContext } from "../../../ConfigContext"; import { GenerateTokenResponse } from "../../../Contracts/DataModels"; import { isResourceTokenConnectionString } from "../Helpers/ResourceTokenUtils"; @@ -18,6 +19,23 @@ interface Props { } export const fetchEncryptedToken = async (connectionString: string): Promise => { + if (!usePortalBackendEndpoint(BackendApi.GenerateToken)) { + return await fetchEncryptedToken_ToBeDeprecated(connectionString); + } + + const headers = new Headers(); + headers.append(HttpHeaders.connectionString, connectionString); + const url = configContext.PORTAL_BACKEND_ENDPOINT + "/api/connectionstring/token/generatetoken"; + const response = await fetch(url, { headers, method: "POST" }); + if (!response.ok) { + throw response; + } + + const encryptedTokenResponse: string = await response.json(); + return decodeURIComponent(encryptedTokenResponse); +}; + +export const fetchEncryptedToken_ToBeDeprecated = async (connectionString: string): Promise => { const headers = new Headers(); headers.append(HttpHeaders.connectionString, connectionString); const url = configContext.BACKEND_ENDPOINT + "/api/guest/tokens/generateToken"; diff --git a/src/Utils/EndpointUtils.ts b/src/Utils/EndpointUtils.ts index ee01f7f9a..4962c285b 100644 --- a/src/Utils/EndpointUtils.ts +++ b/src/Utils/EndpointUtils.ts @@ -1,4 +1,11 @@ -import { CassandraProxyEndpoints, JunoEndpoints, MongoProxyEndpoints } from "Common/Constants"; +import { + BackendApi, + CassandraProxyEndpoints, + JunoEndpoints, + MongoProxyEndpoints, + PortalBackendEndpoints, +} from "Common/Constants"; +import { configContext } from "ConfigContext"; import * as Logger from "../Common/Logger"; export function validateEndpoint( @@ -137,3 +144,9 @@ export const allowedJunoOrigins: ReadonlyArray = [ ]; export const allowedNotebookServerUrls: ReadonlyArray = []; + +export function usePortalBackendEndpoint(backendApi: BackendApi): boolean { + const activePortalBackendEndpoints: string[] = [PortalBackendEndpoints.Development]; + const activeBackendApi: boolean = configContext.NEW_BACKEND_APIS?.includes(backendApi) || false; + return activeBackendApi && activePortalBackendEndpoints.includes(configContext.PORTAL_BACKEND_ENDPOINT as string); +}