From 2a80cdc6596392b6f62ebe99b943f3c520d89582 Mon Sep 17 00:00:00 2001 From: Fang-Pen Lin Date: Tue, 9 Dec 2025 16:45:19 -0800 Subject: [PATCH] Audit logs --- .../ee/services/audit-log/audit-log-types.ts | 48 +++++++++++++++++-- .../ee/services/pki-acme/pki-acme-service.ts | 42 +++++++++++++++- backend/src/server/routes/index.ts | 3 +- backend/src/services/auth/auth-type.ts | 1 + 4 files changed, 87 insertions(+), 7 deletions(-) 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 b89137ec6..c961b6005 100644 --- a/backend/src/ee/services/audit-log/audit-log-types.ts +++ b/backend/src/ee/services/audit-log/audit-log-types.ts @@ -78,7 +78,8 @@ export type TCreateAuditLogDTO = { | ScimClientActor | PlatformActor | UnknownUserActor - | KmipClientActor; + | KmipClientActor + | AcmeProfileActor; orgId?: string; projectId?: string; } & BaseAuthData; @@ -574,7 +575,11 @@ export enum EventType { APPROVAL_REQUEST_CANCEL = "approval-request-cancel", APPROVAL_REQUEST_GRANT_LIST = "approval-request-grant-list", APPROVAL_REQUEST_GRANT_GET = "approval-request-grant-get", - APPROVAL_REQUEST_GRANT_REVOKE = "approval-request-grant-revoke" + APPROVAL_REQUEST_GRANT_REVOKE = "approval-request-grant-revoke", + + // PKI ACME + CREATE_ACME_ACCOUNT = "create-acme-account", + RETRIEVE_ACME_ACCOUNT = "retrieve-acme-account" } export const filterableSecretEvents: EventType[] = [ @@ -615,6 +620,10 @@ interface KmipClientActorMetadata { name: string; } +interface AcmeProfileActorMetadata { + profileId: string; +} + interface UnknownUserActorMetadata {} export interface UserActor { @@ -652,7 +661,19 @@ export interface ScimClientActor { metadata: ScimClientActorMetadata; } -export type Actor = UserActor | ServiceActor | IdentityActor | ScimClientActor | PlatformActor | KmipClientActor; +export interface AcmeProfileActor { + type: ActorType.ACME_PROFILE; + metadata: AcmeProfileActorMetadata; +} + +export type Actor = + | UserActor + | ServiceActor + | IdentityActor + | ScimClientActor + | PlatformActor + | KmipClientActor + | AcmeProfileActor; interface GetSecretsEvent { type: EventType.GET_SECRETS; @@ -4368,6 +4389,23 @@ interface ApprovalRequestGrantRevokeEvent { }; } +interface CreateAcmeAccountEvent { + type: EventType.CREATE_ACME_ACCOUNT; + metadata: { + accountId: string; + publicKeyThumbprint: string; + emails?: string[]; + }; +} + +interface RetrieveAcmeAccountEvent { + type: EventType.RETRIEVE_ACME_ACCOUNT; + metadata: { + accountId: string; + publicKeyThumbprint: string; + }; +} + export type Event = | CreateSubOrganizationEvent | UpdateSubOrganizationEvent @@ -4768,4 +4806,6 @@ export type Event = | ApprovalRequestCancelEvent | ApprovalRequestGrantListEvent | ApprovalRequestGrantGetEvent - | ApprovalRequestGrantRevokeEvent; + | ApprovalRequestGrantRevokeEvent + | CreateAcmeAccountEvent + | RetrieveAcmeAccountEvent; diff --git a/backend/src/ee/services/pki-acme/pki-acme-service.ts b/backend/src/ee/services/pki-acme/pki-acme-service.ts index c86f0efd1..353f5287f 100644 --- a/backend/src/ee/services/pki-acme/pki-acme-service.ts +++ b/backend/src/ee/services/pki-acme/pki-acme-service.ts @@ -47,6 +47,7 @@ import { TKmsServiceFactory } from "@app/services/kms/kms-service"; import { TProjectDALFactory } from "@app/services/project/project-dal"; import { getProjectKmsCertificateKeyId } from "@app/services/project/project-fns"; +import { EventType, TAuditLogServiceFactory } from "../audit-log/audit-log-types"; import { TLicenseServiceFactory } from "../license/license-service"; import { TPkiAcmeAccountDALFactory } from "./pki-acme-account-dal"; import { TPkiAcmeAuthDALFactory } from "./pki-acme-auth-dal"; @@ -136,6 +137,7 @@ type TPkiAcmeServiceFactoryDep = { certificateTemplateV2Service: Pick; acmeChallengeService: Pick; pkiAcmeQueueService: Pick; + auditLogService: Pick; }; export const pkiAcmeServiceFactory = ({ @@ -159,7 +161,8 @@ export const pkiAcmeServiceFactory = ({ certificateV3Service, certificateTemplateV2Service, acmeChallengeService, - pkiAcmeQueueService + pkiAcmeQueueService, + auditLogService }: TPkiAcmeServiceFactoryDep): TPkiAcmeServiceFactory => { const validateAcmeProfile = async (profileId: string): Promise => { const profile = await certificateProfileDAL.findByIdWithConfigs(profileId); @@ -446,6 +449,23 @@ export const pkiAcmeServiceFactory = ({ throw new AcmeExternalAccountRequiredError({ message: "External account binding is required" }); } if (existingAccount) { + await auditLogService.createAuditLog({ + projectId: profile.projectId, + actor: { + type: ActorType.ACME_PROFILE, + metadata: { + profileId: profile.id + } + }, + event: { + type: EventType.RETRIEVE_ACME_ACCOUNT, + metadata: { + accountId: existingAccount.id, + publicKeyThumbprint + } + } + }); + return { status: 200, body: { @@ -518,7 +538,25 @@ export const pkiAcmeServiceFactory = ({ publicKeyThumbprint, emails: contact ?? [] }); - // TODO: create audit log here + + await auditLogService.createAuditLog({ + projectId: profile.projectId, + actor: { + type: ActorType.ACME_PROFILE, + metadata: { + profileId: profile.id + } + }, + event: { + type: EventType.CREATE_ACME_ACCOUNT, + metadata: { + accountId: newAccount.id, + publicKeyThumbprint: newAccount.publicKeyThumbprint, + emails: newAccount.emails + } + } + }); + return { status: 201, body: { diff --git a/backend/src/server/routes/index.ts b/backend/src/server/routes/index.ts index 6611f4a59..493763e68 100644 --- a/backend/src/server/routes/index.ts +++ b/backend/src/server/routes/index.ts @@ -2332,7 +2332,8 @@ export const registerRoutes = async ( certificateV3Service, certificateTemplateV2Service, acmeChallengeService, - pkiAcmeQueueService + pkiAcmeQueueService, + auditLogService }); const pkiSubscriberService = pkiSubscriberServiceFactory({ diff --git a/backend/src/services/auth/auth-type.ts b/backend/src/services/auth/auth-type.ts index 9e692dcd3..f93f511dd 100644 --- a/backend/src/services/auth/auth-type.ts +++ b/backend/src/services/auth/auth-type.ts @@ -41,6 +41,7 @@ export enum ActorType { // would extend to AWS, Azure, ... IDENTITY = "identity", Machine = "machine", SCIM_CLIENT = "scimClient", + ACME_PROFILE = "acmeProfile", ACME_ACCOUNT = "acmeAccount", UNKNOWN_USER = "unknownUser" }