feat: added back secret referencing expansion support

This commit is contained in:
=
2024-07-25 14:47:41 +05:30
parent a53d0b2334
commit b950bf0cf7
5 changed files with 250 additions and 182 deletions

View File

@@ -17,6 +17,23 @@ export const groupBy = <T, Key extends string | number | symbol>(
{} as Record<Key, T[]>
);
/**
* Sorts an array of items into groups. The return value is a map where the keys are
* the group ids the given getGroupId function produced and the value will be the last found one for the group key
*/
export const groupByUnique = <T, Key extends string | number | symbol>(
array: readonly T[],
getGroupId: (item: T) => Key
): Record<Key, T> =>
array.reduce(
(acc, item) => {
const groupId = getGroupId(item);
acc[groupId] = item;
return acc;
},
{} as Record<Key, T>
);
/**
* Given a list of items returns a new list with only
* unique items. Accepts an optional identity function

View File

@@ -1,5 +1,5 @@
import { SecretType, TSecretImports, TSecrets, TSecretsV2 } from "@app/db/schemas";
import { groupBy } from "@app/lib/fn";
import { groupBy, unique } from "@app/lib/fn";
import { TSecretDALFactory } from "../secret/secret-dal";
import { TSecretFolderDALFactory } from "../secret-folder/secret-folder-dal";
@@ -146,7 +146,8 @@ export const fnSecretsV2FromImports = async ({
secretImportDAL,
depth = 0,
cyclicDetector = new Set(),
decryptor
decryptor,
expandSecretReferences
}: {
allowedImports: (Omit<TSecretImports, "importEnv"> & {
importEnv: { id: string; slug: string; name: string };
@@ -157,6 +158,9 @@ export const fnSecretsV2FromImports = async ({
depth?: number;
cyclicDetector?: Set<string>;
decryptor: (value?: Buffer | null) => string | undefined;
expandSecretReferences?: (
secrets: Record<string, { value?: string; comment?: string; skipMultilineEncoding?: boolean | null }>
) => Promise<Record<string, { value?: string; comment?: string; skipMultilineEncoding?: boolean | null }>>;
}) => {
// avoid going more than a depth
if (depth >= LEVEL_BREAK) return [];
@@ -206,16 +210,27 @@ export const fnSecretsV2FromImports = async ({
secretDAL,
depth: depth + 1,
cyclicDetector,
decryptor
decryptor,
expandSecretReferences
});
}
const secretsFromdeeperImportGroupedByFolderId = groupBy(secretsFromDeeperImports, (i) => i.importFolderId);
const secrets = allowedImports.map(({ importPath, importEnv, id, folderId }, i) => {
const processedImports = allowedImports.map(({ importPath, importEnv, id, folderId }, i) => {
const sourceImportFolder = importedFolderGroupBySourceImport[`${importEnv.id}-${importPath}`][0];
const folderDeeperImportSecrets =
secretsFromdeeperImportGroupedByFolderId?.[sourceImportFolder?.id || ""]?.[0]?.secrets || [];
const secretsWithDuplicate = (importedSecretsGroupByFolderId?.[importedFolders?.[i]?.id as string] || [])
.map((item) => ({
...item,
secretKey: item.key,
secretValue: decryptor(item.encryptedValue),
secretComment: decryptor(item.encryptedComment),
environment: importEnv.slug,
workspace: "", // This field should not be used, it's only here to keep the older Python SDK versions backwards compatible with the new Postgres backend.
_id: item.id // The old Python SDK depends on the _id field being returned. We return this to keep the older Python SDK versions backwards compatible with the new Postgres backend.
}))
.concat(folderDeeperImportSecrets);
return {
secretPath: importPath,
environment: importEnv.slug,
@@ -223,19 +238,33 @@ export const fnSecretsV2FromImports = async ({
folderId: importedFolders?.[i]?.id,
id,
importFolderId: folderId,
secrets: (importedSecretsGroupByFolderId?.[importedFolders?.[i]?.id as string] || [])
.map((item) => ({
...item,
secretKey: item.key,
secretValue: decryptor(item.encryptedValue),
secretComment: decryptor(item.encryptedComment),
environment: importEnv.slug,
workspace: "", // This field should not be used, it's only here to keep the older Python SDK versions backwards compatible with the new Postgres backend.
_id: item.id // The old Python SDK depends on the _id field being returned. We return this to keep the older Python SDK versions backwards compatible with the new Postgres backend.
}))
.concat(folderDeeperImportSecrets)
secrets: unique(secretsWithDuplicate, (el) => el.secretKey)
};
});
return secrets;
if (expandSecretReferences) {
await Promise.all(
processedImports.map(async (processedImport) => {
const secretsGroupByKey = processedImport.secrets.reduce(
(acc, item) => {
acc[item.secretKey] = {
value: item.secretValue,
comment: item.secretComment,
skipMultilineEncoding: item.skipMultilineEncoding
};
return acc;
},
{} as Record<string, { value?: string; comment?: string; skipMultilineEncoding?: boolean | null }>
);
// eslint-disable-next-line
await expandSecretReferences(secretsGroupByKey);
processedImport.secrets.forEach((decryptedSecret) => {
// eslint-disable-next-line no-param-reassign
decryptedSecret.secretValue = secretsGroupByKey[decryptedSecret.secretKey].value;
});
})
);
}
return processedImports;
};

View File

@@ -363,49 +363,60 @@ export const recursivelyGetSecretPaths = async ({
return allowedPaths;
};
// used to convert multi line ones to quotes ones with \n
const formatMultiValueEnv = (val?: string) => {
if (!val) return "";
if (!val.match("\n")) return val;
return `"${val.replace(/\n/g, "\\n")}"`;
};
type TInterpolateSecretArg = {
projectId: string;
decryptSecret: (encryptedValue?: Buffer | null) => string | undefined;
decryptSecretValue: (encryptedValue?: Buffer | null) => string | undefined;
secretDAL: Pick<TSecretV2BridgeDALFactory, "findByFolderId">;
folderDAL: Pick<TSecretFolderDALFactory, "findBySecretPath">;
};
export const interpolateSecrets = ({ projectId, decryptSecret, secretDAL, folderDAL }: TInterpolateSecretArg) => {
const fetchSecretsCrossEnv = () => {
const fetchCache: Record<string, Record<string, string>> = {};
export const expandSecretReferencesFactory = ({
projectId,
decryptSecretValue: decryptSecret,
secretDAL,
folderDAL
}: TInterpolateSecretArg) => {
const fetchSecretFactory = () => {
const secretCache: Record<string, Record<string, string>> = {};
return async (secRefEnv: string, secRefPath: string[], secRefKey: string) => {
const secRefPathUrl = path.join("/", ...secRefPath);
const uniqKey = `${secRefEnv}-${secRefPathUrl}`;
const referredSecretPathURL = path.join("/", ...secRefPath);
const uniqueKey = `${secRefEnv}-${referredSecretPathURL}`;
if (fetchCache?.[uniqKey]) {
return fetchCache[uniqKey][secRefKey];
if (secretCache?.[uniqueKey]) {
return secretCache[uniqueKey][secRefKey];
}
const folder = await folderDAL.findBySecretPath(projectId, secRefEnv, secRefPathUrl);
const folder = await folderDAL.findBySecretPath(projectId, secRefEnv, referredSecretPathURL);
if (!folder) return "";
const secrets = await secretDAL.findByFolderId(folder.id);
const decryptedSec = secrets.reduce<Record<string, string>>((prev, secret) => {
const decryptedSecret = secrets.reduce<Record<string, string>>((prev, secret) => {
// eslint-disable-next-line
prev[secret.key] = decryptSecret(secret.encryptedValue) || "";
return prev;
}, {});
fetchCache[uniqKey] = decryptedSec;
secretCache[uniqueKey] = decryptedSecret;
return fetchCache[uniqKey][secRefKey];
return secretCache[uniqueKey][secRefKey];
};
};
const recursivelyExpandSecret = async (
expandedSec: Record<string, string>,
interpolatedSec: Record<string, string>,
fetchCrossEnv: (env: string, secPath: string[], secKey: string) => Promise<string>,
expandedSec: Record<string, string | undefined>,
interpolatedSec: Record<string, string | undefined>,
fetchSecret: (env: string, secPath: string[], secKey: string) => Promise<string>,
recursionChainBreaker: Record<string, boolean>,
key: string
) => {
): Promise<string | undefined> => {
if (expandedSec?.[key] !== undefined) {
return expandedSec[key];
}
@@ -433,7 +444,7 @@ export const interpolateSecrets = ({ projectId, decryptSecret, secretDAL, folder
const val = await recursivelyExpandSecret(
expandedSec,
interpolatedSec,
fetchCrossEnv,
fetchSecret,
recursionChainBreaker,
interpolationKey
);
@@ -450,7 +461,7 @@ export const interpolateSecrets = ({ projectId, decryptSecret, secretDAL, folder
const secRefKey = entities[entities.length - 1];
// eslint-disable-next-line
const val = await fetchCrossEnv(secRefEnv, secRefPath, secRefKey);
const val = await fetchSecret(secRefEnv, secRefPath, secRefKey);
if (val) {
interpolatedValue = interpolatedValue.replaceAll(interpolationSyntax, val);
}
@@ -463,36 +474,28 @@ export const interpolateSecrets = ({ projectId, decryptSecret, secretDAL, folder
return interpolatedValue;
};
// used to convert multi line ones to quotes ones with \n
const formatMultiValueEnv = (val?: string) => {
if (!val) return "";
if (!val.match("\n")) return val;
return `"${val.replace(/\n/g, "\\n")}"`;
};
const fetchSecret = fetchSecretFactory();
const expandSecrets = async (
secrets: Record<string, { value: string; comment?: string; skipMultilineEncoding?: boolean | null }>
inputSecrets: Record<string, { value?: string; comment?: string; skipMultilineEncoding?: boolean | null }>
) => {
const expandedSec: Record<string, string> = {};
const interpolatedSec: Record<string, string> = {};
const expandedSecrets: Record<string, string | undefined> = {};
const toBeExpandedSecrets: Record<string, string | undefined> = {};
const crossSecEnvFetch = fetchSecretsCrossEnv();
Object.keys(secrets).forEach((key) => {
if (secrets[key].value.match(INTERPOLATION_SYNTAX_REG)) {
interpolatedSec[key] = secrets[key].value;
Object.keys(inputSecrets).forEach((key) => {
if (inputSecrets[key].value?.match(INTERPOLATION_SYNTAX_REG)) {
toBeExpandedSecrets[key] = inputSecrets[key].value;
} else {
expandedSec[key] = secrets[key].value;
expandedSecrets[key] = inputSecrets[key].value;
}
});
for (const key of Object.keys(secrets)) {
if (expandedSec?.[key]) {
for (const key of Object.keys(inputSecrets)) {
if (expandedSecrets?.[key]) {
// should not do multi line encoding if user has set it to skip
// eslint-disable-next-line
secrets[key].value = secrets[key].skipMultilineEncoding
? formatMultiValueEnv(expandedSec[key])
: expandedSec[key];
inputSecrets[key].value = inputSecrets[key].skipMultilineEncoding
? formatMultiValueEnv(expandedSecrets[key])
: expandedSecrets[key];
// eslint-disable-next-line
continue;
}
@@ -502,18 +505,20 @@ export const interpolateSecrets = ({ projectId, decryptSecret, secretDAL, folder
const recursionChainBreaker: Record<string, boolean> = {};
// eslint-disable-next-line
const expandedVal = await recursivelyExpandSecret(
expandedSec,
interpolatedSec,
crossSecEnvFetch,
expandedSecrets,
toBeExpandedSecrets,
fetchSecret,
recursionChainBreaker,
key
);
// eslint-disable-next-line
secrets[key].value = secrets[key].skipMultilineEncoding ? formatMultiValueEnv(expandedVal) : expandedVal;
inputSecrets[key].value = inputSecrets[key].skipMultilineEncoding
? formatMultiValueEnv(expandedVal)
: expandedVal;
}
return secrets;
return inputSecrets;
};
return expandSecrets;
};

View File

@@ -24,11 +24,11 @@ import { fnSecretsV2FromImports } from "../secret-import/secret-import-fns";
import { TSecretTagDALFactory } from "../secret-tag/secret-tag-dal";
import { TSecretV2BridgeDALFactory } from "./secret-v2-bridge-dal";
import {
expandSecretReferencesFactory,
fnSecretBulkDelete,
fnSecretBulkInsert,
fnSecretBulkUpdate,
getAllNestedSecretReferences,
interpolateSecrets,
recursivelyGetSecretPaths,
reshapeBridgeSecret
} from "./secret-v2-bridge-fns";
@@ -428,7 +428,8 @@ export const secretV2BridgeServiceFactory = ({
actorOrgId,
actorAuthMethod,
includeImports,
recursive // TODO(akhilmhdh-sev2): add logic for expandSecretReferences
recursive,
expandSecretReferences: shouldExpandSecretReferences
}: TGetSecretsDTO) => {
const { permission } = await permissionService.getProjectPermission(
actor,
@@ -484,57 +485,81 @@ export const secretV2BridgeServiceFactory = ({
projectId
});
if (includeImports) {
const secretImports = await secretImportDAL.findByFolderIds(paths.map((p) => p.folderId));
const allowedImports = secretImports.filter(({ importEnv, importPath, isReplication }) =>
!isReplication &&
// if its service token allow full access over imported one
actor === ActorType.SERVICE
? true
: permission.can(
ProjectPermissionActions.Read,
subject(ProjectPermissionSub.Secrets, {
environment: importEnv.slug,
secretPath: importPath
})
)
);
const importedSecrets = await fnSecretsV2FromImports({
allowedImports,
secretDAL,
folderDAL,
secretImportDAL,
decryptor: (value) => (value ? secretManagerDecryptor({ cipherTextBlob: value }).toString() : undefined)
});
const decryptedSecrets = secrets.map((secret) =>
reshapeBridgeSecret(projectId, environment, groupedPaths[secret.folderId][0].path, {
...secret,
value: secret.encryptedValue
? secretManagerDecryptor({ cipherTextBlob: secret.encryptedValue }).toString()
: undefined,
comment: secret.encryptedComment
? secretManagerDecryptor({ cipherTextBlob: secret.encryptedComment }).toString()
: undefined
})
);
const expandSecretReferences = expandSecretReferencesFactory({
projectId,
folderDAL,
secretDAL,
decryptSecretValue: (value) => (value ? secretManagerDecryptor({ cipherTextBlob: value }).toString() : undefined)
});
if (shouldExpandSecretReferences) {
const secretsGroupByPath = groupBy(decryptedSecrets, (i) => i.secretPath);
for (const secretPathKey in secretsGroupByPath) {
if (Object.hasOwn(secretsGroupByPath, secretPathKey)) {
const secretsGroupByKey = secretsGroupByPath[secretPathKey].reduce(
(acc, item) => {
acc[item.secretKey] = {
value: item.secretValue,
comment: item.secretComment,
skipMultilineEncoding: item.skipMultilineEncoding
};
return acc;
},
{} as Record<string, { value?: string; comment?: string; skipMultilineEncoding?: boolean | null }>
);
// eslint-disable-next-line
await expandSecretReferences(secretsGroupByKey);
secretsGroupByPath[secretPathKey].forEach((decryptedSecret) => {
// eslint-disable-next-line no-param-reassign
decryptedSecret.secretValue = secretsGroupByKey[decryptedSecret.secretKey].value;
});
}
}
}
if (!includeImports) {
return {
secrets: secrets.map((secret) =>
reshapeBridgeSecret(projectId, environment, groupedPaths[secret.folderId][0].path, {
...secret,
value: secret.encryptedValue
? secretManagerDecryptor({ cipherTextBlob: secret.encryptedValue }).toString()
: undefined,
comment: secret.encryptedComment
? secretManagerDecryptor({ cipherTextBlob: secret.encryptedComment }).toString()
: undefined
})
),
imports: importedSecrets
secrets: decryptedSecrets
};
}
const secretImports = await secretImportDAL.findByFolderIds(paths.map((p) => p.folderId));
const allowedImports = secretImports.filter(({ importEnv, importPath, isReplication }) =>
!isReplication &&
// if its service token allow full access over imported one
actor === ActorType.SERVICE
? true
: permission.can(
ProjectPermissionActions.Read,
subject(ProjectPermissionSub.Secrets, {
environment: importEnv.slug,
secretPath: importPath
})
)
);
const importedSecrets = await fnSecretsV2FromImports({
allowedImports,
secretDAL,
folderDAL,
secretImportDAL,
expandSecretReferences,
decryptor: (value) => (value ? secretManagerDecryptor({ cipherTextBlob: value }).toString() : undefined)
});
return {
secrets: secrets.map((secret) =>
reshapeBridgeSecret(projectId, environment, groupedPaths[secret.folderId][0].path, {
...secret,
value: secret.encryptedValue
? secretManagerDecryptor({ cipherTextBlob: secret.encryptedValue }).toString()
: undefined,
comment: secret.encryptedComment
? secretManagerDecryptor({ cipherTextBlob: secret.encryptedComment }).toString()
: undefined
})
)
secrets: decryptedSecrets,
imports: importedSecrets
};
};
@@ -550,7 +575,7 @@ export const secretV2BridgeServiceFactory = ({
secretName,
version,
includeImports,
expandSecretReferences
expandSecretReferences: shouldExpandSecretReferences
}: TGetASecretDTO) => {
const { permission } = await permissionService.getProjectPermission(
actor,
@@ -600,11 +625,11 @@ export const secretV2BridgeServiceFactory = ({
})
.then((el) => SecretsV2Schema.parse({ ...el, id: el.secretId })));
const interpolateInlineSecretReference = interpolateSecrets({
const expandSecretReferences = expandSecretReferencesFactory({
projectId,
decryptSecret: (value) => (value ? secretManagerDecryptor({ cipherTextBlob: value }).toString() : undefined),
folderDAL,
secretDAL,
folderDAL
decryptSecretValue: (value) => (value ? secretManagerDecryptor({ cipherTextBlob: value }).toString() : undefined)
});
// now if secret is not found
@@ -629,33 +654,20 @@ export const secretV2BridgeServiceFactory = ({
secretDAL,
folderDAL,
secretImportDAL,
decryptor: (value) => (value ? secretManagerDecryptor({ cipherTextBlob: value }).toString() : undefined)
decryptor: (value) => (value ? secretManagerDecryptor({ cipherTextBlob: value }).toString() : undefined),
expandSecretReferences: shouldExpandSecretReferences ? expandSecretReferences : undefined
});
for (let i = importedSecrets.length - 1; i >= 0; i -= 1) {
for (let j = 0; j < importedSecrets[i].secrets.length; j += 1) {
if (secretName === importedSecrets[i].secrets[j].key) {
const importedSecret = importedSecrets[i].secrets[j];
let secretValue = importedSecret.encryptedValue
? secretManagerDecryptor({ cipherTextBlob: importedSecret.encryptedValue }).toString()
: undefined;
if (expandSecretReferences && secretValue) {
const secretReferenceExpandedString = {
[importedSecret.key]: { value: secretValue }
};
// eslint-disable-next-line
await interpolateInlineSecretReference(secretReferenceExpandedString);
secretValue = secretReferenceExpandedString[importedSecret.key].value;
}
return reshapeBridgeSecret(projectId, importedSecrets[i].environment, importedSecrets[i].secretPath, {
...importedSecret,
value: secretValue,
comment: importedSecret.encryptedComment
? secretManagerDecryptor({ cipherTextBlob: importedSecret.encryptedComment }).toString()
: undefined
});
const importedSecret = importedSecrets[i].secrets[j];
if (secretName === importedSecret.key) {
return reshapeBridgeSecret(
projectId,
importedSecrets[i].environment,
importedSecrets[i].secretPath,
importedSecret
);
}
}
}
@@ -665,13 +677,13 @@ export const secretV2BridgeServiceFactory = ({
let secretValue = secret.encryptedValue
? secretManagerDecryptor({ cipherTextBlob: secret.encryptedValue }).toString()
: undefined;
if (expandSecretReferences && secretValue) {
const secretReferenceExpandedString = {
if (shouldExpandSecretReferences && secretValue) {
const secretReferenceExpandedRecord = {
[secret.key]: { value: secretValue }
};
// eslint-disable-next-line
await interpolateInlineSecretReference(secretReferenceExpandedString);
secretValue = secretReferenceExpandedString[secret.key].value;
await expandSecretReferences(secretReferenceExpandedRecord);
secretValue = secretReferenceExpandedRecord[secret.key].value;
}
return reshapeBridgeSecret(projectId, environment, path, {

View File

@@ -30,8 +30,9 @@ import { TProjectEnvDALFactory } from "../project-env/project-env-dal";
import { TProjectMembershipDALFactory } from "../project-membership/project-membership-dal";
import { TSecretFolderDALFactory } from "../secret-folder/secret-folder-dal";
import { TSecretImportDALFactory } from "../secret-import/secret-import-dal";
import { fnSecretsV2FromImports } from "../secret-import/secret-import-fns";
import { TSecretV2BridgeDALFactory } from "../secret-v2-bridge/secret-v2-bridge-dal";
import { getAllNestedSecretReferences } from "../secret-v2-bridge/secret-v2-bridge-fns";
import { expandSecretReferencesFactory, getAllNestedSecretReferences } from "../secret-v2-bridge/secret-v2-bridge-fns";
import { TSecretVersionV2DALFactory } from "../secret-v2-bridge/secret-version-dal";
import { TSecretVersionV2TagDALFactory } from "../secret-v2-bridge/secret-version-tag-dal";
import { SmtpTemplates, TSmtpService } from "../smtp/smtp-service";
@@ -55,7 +56,7 @@ type TSecretQueueFactoryDep = {
integrationAuthService: Pick<TIntegrationAuthServiceFactory, "getIntegrationAccessToken">;
folderDAL: TSecretFolderDALFactory;
secretDAL: TSecretDALFactory;
secretImportDAL: Pick<TSecretImportDALFactory, "find">;
secretImportDAL: Pick<TSecretImportDALFactory, "find" | "findByFolderIds">;
webhookDAL: Pick<TWebhookDALFactory, "findAllWebhooks" | "transaction" | "update" | "bulkUpdate">;
projectEnvDAL: Pick<TProjectEnvDALFactory, "findOne" | "find">;
projectDAL: TProjectDALFactory;
@@ -249,7 +250,7 @@ export const secretQueueFactory = ({
depth: number;
decryptor: (value: Buffer | null | undefined) => string;
}) => {
let content: TIntegrationSecret = {};
const content: TIntegrationSecret = {};
if (dto.depth > MAX_SYNC_SECRET_DEPTH) {
logger.info(
`getIntegrationSecrets: secret depth exceeded for [projectId=${dto.projectId}] [folderId=${dto.folderId}] [depth=${dto.depth}]`
@@ -272,38 +273,40 @@ export const secretQueueFactory = ({
content[secretKey].skipMultilineEncoding = Boolean(secret.skipMultilineEncoding);
});
// TODO(akhilmhdh-sev2): change this to v2 expand secrets
const expandSecretReferences = expandSecretReferencesFactory({
decryptSecretValue: dto.decryptor,
secretDAL: secretV2BridgeDAL,
folderDAL,
projectId: dto.projectId
});
await expandSecretReferences(content);
// check if current folder has any imports from other folders
const secretImport = await secretImportDAL.find({ folderId: dto.folderId, isReplication: false });
const secretImports = await secretImportDAL.find({ folderId: dto.folderId, isReplication: false });
// if no imports then return secrets in the current folder
if (!secretImport) return content;
if (!secretImports.length) return content;
const importedSecrets = await fnSecretsV2FromImports({
decryptor: dto.decryptor,
folderDAL,
secretDAL: secretV2BridgeDAL,
expandSecretReferences,
secretImportDAL,
allowedImports: secretImports
});
const importedFolders = await folderDAL.findByManySecretPath(
secretImport.map(({ importEnv, importPath }) => ({
envId: importEnv.id,
secretPath: importPath
}))
);
for await (const folder of importedFolders) {
if (folder) {
// get secrets contained in each imported folder by recursively calling
// this function against the imported folder
const importedSecrets = await getIntegrationSecretsV2({
environment: dto.environment,
projectId: dto.projectId,
folderId: folder.id,
depth: dto.depth + 1,
decryptor: dto.decryptor
});
// add the imported secrets to the current folder secrets
content = { ...importedSecrets, ...content };
for (let i = importedSecrets.length - 1; i >= 0; i -= 1) {
for (let j = 0; j < importedSecrets[i].secrets.length; j += 1) {
const importedSecret = importedSecrets[i].secrets[j];
if (!content[importedSecret.key]) {
content[importedSecret.key] = {
skipMultilineEncoding: importedSecret.skipMultilineEncoding,
comment: importedSecret.secretComment,
value: importedSecret.secretValue || ""
};
}
}
}
return content;
};
@@ -628,6 +631,23 @@ export const secretQueueFactory = ({
logger.info(
`getIntegrationSecrets: secret integration sync started [jobId=${job.id}] [jobId=${job.id}] [projectId=${job.data.projectId}] [environment=${job.data.environment}] [secretPath=${job.data.secretPath}] [depth=${job.data.depth}]`
);
const secrets = shouldUseSecretV2Bridge
? await getIntegrationSecretsV2({
environment,
projectId,
folderId: folder.id,
depth: 1,
decryptor: (value) => (value ? secretManagerDecryptor({ cipherTextBlob: value }).toString() : "")
})
: await getIntegrationSecrets({
environment,
projectId,
folderId: folder.id,
key: botKey as string,
depth: 1
});
for (const integration of toBeSyncedIntegrations) {
const integrationAuth = {
...integration.integrationAuth,
@@ -661,21 +681,6 @@ export const secretQueueFactory = ({
});
}
const secrets = shouldUseSecretV2Bridge
? await getIntegrationSecretsV2({
environment,
projectId,
folderId: folder.id,
depth: 1,
decryptor: (value) => (value ? secretManagerDecryptor({ cipherTextBlob: value }).toString() : "")
})
: await getIntegrationSecrets({
environment,
projectId,
folderId: folder.id,
key: botKey as string,
depth: 1
});
const suffixedSecrets: typeof secrets = {};
const metadata = integration.metadata as Record<string, string>;
if (metadata) {