From 68a3291235247d44dded81edcb7b9024358b8e10 Mon Sep 17 00:00:00 2001 From: Daniel Hougaard Date: Mon, 16 Dec 2024 23:24:08 +0100 Subject: [PATCH] misc: requested changes --- .../integration-sync-secret-fns.ts | 35 +++++++++++++++++++ .../integration-sync-secret.ts | 19 +++++----- 2 files changed, 43 insertions(+), 11 deletions(-) create mode 100644 backend/src/services/integration-auth/integration-sync-secret-fns.ts diff --git a/backend/src/services/integration-auth/integration-sync-secret-fns.ts b/backend/src/services/integration-auth/integration-sync-secret-fns.ts new file mode 100644 index 000000000..df8b990af --- /dev/null +++ b/backend/src/services/integration-auth/integration-sync-secret-fns.ts @@ -0,0 +1,35 @@ +export const isAzureKeyVaultReference = (uri: string) => { + const tryJsonDecode = () => { + try { + return (JSON.parse(uri) as { uri: string }).uri || uri; + } catch { + return uri; + } + }; + + const cleanUri = tryJsonDecode(); + + if (!cleanUri.startsWith("https://")) { + return false; + } + + if (!cleanUri.includes(".vault.azure.net/secrets/")) { + return false; + } + + // 3. Check for non-empty string between https:// and .vault.azure.net/secrets/ + const parts = cleanUri.split(".vault.azure.net/secrets/"); + const vaultName = parts[0].replace("https://", ""); + if (!vaultName) { + return false; + } + + // 4. Check for non-empty secret name + const secretParts = parts[1].split("/"); + const secretName = secretParts[0]; + if (!secretName) { + return false; + } + + return true; +}; diff --git a/backend/src/services/integration-auth/integration-sync-secret.ts b/backend/src/services/integration-auth/integration-sync-secret.ts index 53ff9ca67..d9c1ac3e6 100644 --- a/backend/src/services/integration-auth/integration-sync-secret.ts +++ b/backend/src/services/integration-auth/integration-sync-secret.ts @@ -46,6 +46,7 @@ import { Integrations, IntegrationUrls } from "./integration-list"; +import { isAzureKeyVaultReference } from "./integration-sync-secret-fns"; const getSecretKeyValuePair = (secrets: Record) => Object.keys(secrets).reduce>((prev, key) => { @@ -299,11 +300,6 @@ const syncSecretsAzureAppConfig = async ({ value: string; } - // Format: {\"uri\":\"https://SOME-KEY-VAULT.vault.azure.net/secrets/SOME-SECRET-KEY\"} - // Also works without the backslash escapes - const azureSecretReferenceUriRegex = - /^\{(\\"|")uri(\\"|"):(\\"|")https:\/\/[a-zA-Z0-9-]+\.vault\.azure\.net\/secrets\/[a-zA-Z0-9-]+\\?\2\}$/; - const getCompleteAzureAppConfigValues = async (url: string) => { let result: AzureAppConfigKeyValue[] = []; while (url) { @@ -325,11 +321,12 @@ const syncSecretsAzureAppConfig = async ({ }; const metadata = IntegrationMetadataSchema.parse(integration.metadata); - const azureAppConfigSecrets = ( - await getCompleteAzureAppConfigValues( - `${integration.app}/kv?api-version=2023-11-01&key=${metadata.secretPrefix || ""}*` - ) - ).reduce( + + const azureAppConfigValuesUrl = `${integration.app}/kv?api-version=2023-11-01&key=${metadata.secretPrefix}*${ + metadata.azureLabel ? `&label=${metadata.azureLabel}` : "" + }`; + + const azureAppConfigSecrets = (await getCompleteAzureAppConfigValues(azureAppConfigValuesUrl)).reduce( (accum, entry) => { accum[entry.key] = entry.value; @@ -417,7 +414,7 @@ const syncSecretsAzureAppConfig = async ({ `${integration.app}/kv/${key}?api-version=2023-11-01`, { value: secrets[key]?.value, - ...(azureSecretReferenceUriRegex.test(secrets[key]?.value || "") && { + ...(isAzureKeyVaultReference(secrets[key]?.value || "") && { content_type: "application/vnd.microsoft.appconfig.keyvaultref+json;charset=utf-8" }) },