From f02550993859d16b0dfd276f578f5e1b599a6475 Mon Sep 17 00:00:00 2001 From: Carlos Monastyrski Date: Fri, 18 Jul 2025 19:41:04 -0300 Subject: [PATCH] Add audit logs for each resource on batch commits --- backend/src/ee/routes/v1/pit-router.ts | 10 +- .../ee/services/audit-log/audit-log-types.ts | 8 +- backend/src/ee/services/pit/pit-service.ts | 98 +++++++++++++++++-- 3 files changed, 102 insertions(+), 14 deletions(-) diff --git a/backend/src/ee/routes/v1/pit-router.ts b/backend/src/ee/routes/v1/pit-router.ts index 4b745ca51..14a82bce4 100644 --- a/backend/src/ee/routes/v1/pit-router.ts +++ b/backend/src/ee/routes/v1/pit-router.ts @@ -557,7 +557,6 @@ export const registerPITRouter = async (server: FastifyZodProvider) => { type: EventType.PIT_PROCESS_NEW_COMMIT_RAW, metadata: { commitId: result.commitId, - folderChanges: result.folderChanges, approvalId: result.approvalId, projectId: req.body.projectId, environment: req.body.environment, @@ -567,6 +566,15 @@ export const registerPITRouter = async (server: FastifyZodProvider) => { } }); + for await (const event of result.secretMutationEvents) { + await server.services.auditLog.createAuditLog({ + ...req.auditLogInfo, + orgId: req.permission.orgId, + projectId: req.body.projectId, + event + }); + } + return { message: "success" }; } }); 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 451699953..83458e691 100644 --- a/backend/src/ee/services/audit-log/audit-log-types.ts +++ b/backend/src/ee/services/audit-log/audit-log-types.ts @@ -1547,8 +1547,9 @@ interface UpdateFolderEvent { metadata: { environment: string; folderId: string; - oldFolderName: string; + oldFolderName?: string; newFolderName: string; + newFolderDescription?: string; folderPath: string; }; } @@ -3230,11 +3231,6 @@ interface PitProcessNewCommitRawEvent { environment: string; secretPath: string; message: string; - folderChanges: { - create: string[]; - update: string[]; - delete: string[]; - }; approvalId?: string; commitId?: string; }; diff --git a/backend/src/ee/services/pit/pit-service.ts b/backend/src/ee/services/pit/pit-service.ts index 0dfeab1c9..782827c98 100644 --- a/backend/src/ee/services/pit/pit-service.ts +++ b/backend/src/ee/services/pit/pit-service.ts @@ -1,6 +1,7 @@ /* eslint-disable no-await-in-loop */ import { ForbiddenError } from "@casl/ability"; +import { Event, EventType } from "@app/ee/services/audit-log/audit-log-types"; import { ProjectPermissionCommitsActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission"; import { BadRequestError, NotFoundError } from "@app/lib/errors"; import { logger } from "@app/lib/logger"; @@ -534,6 +535,7 @@ export const pitServiceFactory = ({ actor === ActorType.USER ? await secretApprovalPolicyService.getSecretApprovalPolicy(projectId, environment, secretPath) : undefined; + const secretMutationEvents: Event[] = []; const project = await projectDAL.findById(projectId); if (project.enforceCapitalization) { @@ -589,6 +591,20 @@ export const pitServiceFactory = ({ tx: trx, commitChanges }); + const newFolderEvents = createdFolders.folders.map( + (folder) => + ({ + type: EventType.CREATE_FOLDER, + metadata: { + environment, + folderId: folder.id, + folderName: folder.name, + folderPath: secretPath, + ...(folder.description ? { description: folder.description } : {}) + } + }) as Event + ); + secretMutationEvents.push(...newFolderEvents); folderChanges.create.push(...createdFolders.folders.map((folder) => folder.id)); } @@ -610,6 +626,21 @@ export const pitServiceFactory = ({ tx: trx, commitChanges }); + + const updatedFolderEvents = updatedFolders.newFolders.map( + (folder) => + ({ + type: EventType.UPDATE_FOLDER, + metadata: { + environment, + folderId: folder.id, + folderPath: secretPath, + newFolderName: folder.name, + newFolderDescription: folder.description + } + }) as Event + ); + secretMutationEvents.push(...updatedFolderEvents); folderChanges.update.push(...updatedFolders.newFolders.map((folder) => folder.id)); } @@ -629,6 +660,19 @@ export const pitServiceFactory = ({ tx: trx, commitChanges }); + const deletedFolderEvents = deletedFolders.folders.map( + (folder) => + ({ + type: EventType.DELETE_FOLDER, + metadata: { + environment, + folderId: folder.id, + folderPath: secretPath, + folderName: folder.name + } + }) as Event + ); + secretMutationEvents.push(...deletedFolderEvents); folderChanges.delete.push(...deletedFolders.folders.map((folder) => folder.id)); } @@ -677,16 +721,18 @@ export const pitServiceFactory = ({ }); return { approvalId: approval.id, - folderChanges + folderChanges, + secretMutationEvents }; } return { - folderChanges + folderChanges, + secretMutationEvents }; } if ((changes.secrets?.create?.length ?? 0) > 0) { - await secretV2BridgeService.createManySecret({ + const newSecrets = await secretV2BridgeService.createManySecret({ secretPath, environment, projectId, @@ -698,9 +744,21 @@ export const pitServiceFactory = ({ tx: trx, commitChanges }); + secretMutationEvents.push({ + type: EventType.CREATE_SECRETS, + metadata: { + environment, + secretPath, + secrets: newSecrets.map((secret) => ({ + secretId: secret.id, + secretKey: secret.secretKey, + secretVersion: secret.version + })) + } + }); } if ((changes.secrets?.update?.length ?? 0) > 0) { - await secretV2BridgeService.updateManySecret({ + const updatedSecrets = await secretV2BridgeService.updateManySecret({ secretPath, environment, projectId, @@ -713,9 +771,21 @@ export const pitServiceFactory = ({ tx: trx, commitChanges }); + secretMutationEvents.push({ + type: EventType.UPDATE_SECRETS, + metadata: { + environment, + secretPath, + secrets: updatedSecrets.map((secret) => ({ + secretId: secret.id, + secretKey: secret.secretKey, + secretVersion: secret.version + })) + } + }); } if ((changes.secrets?.delete?.length ?? 0) > 0) { - await secretV2BridgeService.deleteManySecret({ + const deletedSecrets = await secretV2BridgeService.deleteManySecret({ secretPath, environment, projectId, @@ -727,6 +797,18 @@ export const pitServiceFactory = ({ tx: trx, commitChanges }); + secretMutationEvents.push({ + type: EventType.DELETE_SECRETS, + metadata: { + environment, + secretPath, + secrets: deletedSecrets.map((secret) => ({ + secretId: secret.id, + secretKey: secret.secretKey, + secretVersion: secret.version + })) + } + }); } if (commitChanges?.length > 0) { const commit = await folderCommitService.createCommit( @@ -745,11 +827,13 @@ export const pitServiceFactory = ({ ); return { folderChanges, - commitId: commit?.id + commitId: commit?.id, + secretMutationEvents }; } return { - folderChanges + folderChanges, + secretMutationEvents }; });