diff --git a/backend/src/ee/services/audit-log/audit-log-types.ts b/backend/src/ee/services/audit-log/audit-log-types.ts index 1bb58764c..e124c1f45 100644 --- a/backend/src/ee/services/audit-log/audit-log-types.ts +++ b/backend/src/ee/services/audit-log/audit-log-types.ts @@ -352,6 +352,7 @@ interface CreateSecretBatchEvent { secrets: Array<{ secretId: string; secretKey: string; + secretPath?: string; secretVersion: number; secretMetadata?: TSecretMetadata; }>; @@ -374,8 +375,14 @@ interface UpdateSecretBatchEvent { type: EventType.UPDATE_SECRETS; metadata: { environment: string; - secretPath: string; - secrets: Array<{ secretId: string; secretKey: string; secretVersion: number; secretMetadata?: TSecretMetadata }>; + secretPath?: string; + secrets: Array<{ + secretId: string; + secretKey: string; + secretVersion: number; + secretMetadata?: TSecretMetadata; + secretPath?: string; + }>; }; } diff --git a/backend/src/lib/api-docs/constants.ts b/backend/src/lib/api-docs/constants.ts index d4604e28c..7e85c2031 100644 --- a/backend/src/lib/api-docs/constants.ts +++ b/backend/src/lib/api-docs/constants.ts @@ -722,7 +722,7 @@ export const RAW_SECRETS = { secretComment: "Update comment to the secret.", environment: "The slug of the environment where the secret is located.", mode: "Defines how the system should handle missing secrets during an update.", - secretPath: "The path of the secret to update.", + secretPath: "The default path for secrets to update or upsert, if not provided in the secret details.", secretValue: "The new value of the secret.", skipMultilineEncoding: "Skip multiline encoding for the secret value.", type: "The type of the secret to update.", diff --git a/backend/src/server/routes/v3/secret-router.ts b/backend/src/server/routes/v3/secret-router.ts index 803bf1594..5dbe3c93b 100644 --- a/backend/src/server/routes/v3/secret-router.ts +++ b/backend/src/server/routes/v3/secret-router.ts @@ -2035,7 +2035,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => { .nativeEnum(SecretUpdateMode) .optional() .default(SecretUpdateMode.FailOnNotFound) - .describe(RAW_SECRETS.UPDATE.environment), + .describe(RAW_SECRETS.UPDATE.mode), secrets: z .object({ secretKey: SecretNameSchema.describe(RAW_SECRETS.UPDATE.secretName), @@ -2105,15 +2105,39 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => { metadata: { environment: req.body.environment, secretPath: req.body.secretPath, - secrets: secrets.map((secret) => ({ - secretId: secret.id, - secretKey: secret.secretKey, - secretVersion: secret.version, - secretMetadata: secretMetadataMap.get(secret.secretKey) - })) + secrets: secrets + .filter((el) => el.version > 1) + .map((secret) => ({ + secretId: secret.id, + secretPath: secret.secretPath, + secretKey: secret.secretKey, + secretVersion: secret.version, + secretMetadata: secretMetadataMap.get(secret.secretKey) + })) } } }); + const createdSecrets = secrets.filter((el) => el.version === 1); + if (createdSecrets.length) { + await server.services.auditLog.createAuditLog({ + projectId: secrets[0].workspace, + ...req.auditLogInfo, + event: { + type: EventType.CREATE_SECRETS, + metadata: { + environment: req.body.environment, + secretPath: req.body.secretPath, + secrets: createdSecrets.map((secret) => ({ + secretId: secret.id, + secretPath: secret.secretPath, + secretKey: secret.secretKey, + secretVersion: secret.version, + secretMetadata: secretMetadataMap.get(secret.secretKey) + })) + } + } + }); + } await server.services.telemetry.sendPostHogEvents({ event: PostHogEventTypes.SecretUpdated, diff --git a/backend/src/services/secret-v2-bridge/secret-v2-bridge-service.ts b/backend/src/services/secret-v2-bridge/secret-v2-bridge-service.ts index cd425a6ca..0ffb0ea4c 100644 --- a/backend/src/services/secret-v2-bridge/secret-v2-bridge-service.ts +++ b/backend/src/services/secret-v2-bridge/secret-v2-bridge-service.ts @@ -1294,9 +1294,8 @@ export const secretV2BridgeServiceFactory = ({ await kmsService.createCipherPairWithDataKey({ type: KmsDataKey.SecretManager, projectId }); const updatedSecrets: Array = []; - /* eslint-disable no-await-in-loop */ await secretDAL.transaction(async (tx) => { - for (const folder of folders) { + for await (const folder of folders) { if (!folder) throw new NotFoundError({ message: "Folder not found" }); const folderId = folder.id; @@ -1336,7 +1335,7 @@ export const secretV2BridgeServiceFactory = ({ message: `Secret does not exist: ${diff( secretsToUpdate.map((el) => el.secretKey), secretsToUpdateInDB.map((el) => el.key) - ).join(",")} in path ${folder.path}` + ).join(", ")} in path ${folder.path}` }); const secretsToUpdateInDBGroupedByKey = groupBy(secretsToUpdateInDB, (i) => i.key); @@ -1426,7 +1425,7 @@ export const secretV2BridgeServiceFactory = ({ throw new BadRequestError({ message: `Secret with new name already exists: ${secretsWithNewName .map((el) => el.newSecretName) - .join(",")}` + .join(", ")}` }); secretsWithNewName.forEach((el) => { @@ -1530,7 +1529,6 @@ export const secretV2BridgeServiceFactory = ({ } }); - /* eslint-enable */ await Promise.allSettled(folders.map((el) => (el?.id ? snapshotService.performSnapshot(el.id) : undefined))); await Promise.allSettled( folders.map((el) =>