From a45bba853713bd7bfcbac5a524afbfbbcbca479f Mon Sep 17 00:00:00 2001 From: Sid <58144379+sidwebworks@users.noreply.github.com> Date: Sat, 2 Aug 2025 00:29:53 +0530 Subject: [PATCH] feat: audit log disable storage flag (#4295) * feat: audit log disable storage flag * fix: pr changes * fix: revert license fns * Update frontend/src/layouts/OrganizationLayout/components/AuditLogBanner/AuditLogBanner.tsx --- .../ee/services/audit-log/audit-log-dal.ts | 19 ++++++++++++++- backend/src/lib/config/env.ts | 10 ++++++++ backend/src/server/routes/index.ts | 6 +++-- docs/self-hosting/configuration/envars.mdx | 9 +++++++- frontend/src/hooks/api/admin/types.ts | 1 + frontend/src/hooks/api/serverDetails/types.ts | 1 + .../OrganizationLayout/OrganizationLayout.tsx | 5 +++- .../AuditLogBanner/AuditLogBanner.tsx | 23 +++++++++++++++++++ .../components/AuditLogBanner/index.ts | 1 + .../AuditLogsPage/AuditLogsPage.tsx | 1 + .../AuditLogsPage/components/LogsTable.tsx | 12 +++++++--- 11 files changed, 80 insertions(+), 8 deletions(-) create mode 100644 frontend/src/layouts/OrganizationLayout/components/AuditLogBanner/AuditLogBanner.tsx create mode 100644 frontend/src/layouts/OrganizationLayout/components/AuditLogBanner/index.ts diff --git a/backend/src/ee/services/audit-log/audit-log-dal.ts b/backend/src/ee/services/audit-log/audit-log-dal.ts index 2df779795..c0dd76547 100644 --- a/backend/src/ee/services/audit-log/audit-log-dal.ts +++ b/backend/src/ee/services/audit-log/audit-log-dal.ts @@ -1,8 +1,10 @@ // weird commonjs-related error in the CI requires us to do the import like this import knex from "knex"; +import { v4 as uuidv4 } from "uuid"; import { TDbClient } from "@app/db"; import { TableName, TAuditLogs } from "@app/db/schemas"; +import { getConfig } from "@app/lib/config/env"; import { DatabaseError, GatewayTimeoutError } from "@app/lib/errors"; import { ormify, selectAllTableCols, TOrmify } from "@app/lib/knex"; import { logger } from "@app/lib/logger"; @@ -188,5 +190,20 @@ export const auditLogDALFactory = (db: TDbClient) => { logger.info(`${QueueName.DailyResourceCleanUp}: audit log completed`); }; - return { ...auditLogOrm, pruneAuditLog, find }; + const create: TAuditLogDALFactory["create"] = async (tx) => { + const config = getConfig(); + + if (config.DISABLE_AUDIT_LOG_STORAGE) { + return { + ...tx, + id: uuidv4(), + createdAt: new Date(), + updatedAt: new Date() + }; + } + + return auditLogOrm.create(tx); + }; + + return { ...auditLogOrm, create, pruneAuditLog, find }; }; diff --git a/backend/src/lib/config/env.ts b/backend/src/lib/config/env.ts index 9ff7339c0..29883a7ad 100644 --- a/backend/src/lib/config/env.ts +++ b/backend/src/lib/config/env.ts @@ -59,6 +59,7 @@ const envSchema = z AUDIT_LOGS_DB_ROOT_CERT: zpStr( z.string().describe("Postgres database base64-encoded CA cert for Audit logs").optional() ), + DISABLE_AUDIT_LOG_STORAGE: zodStrBool.default("false").optional().describe("Disable audit log storage"), MAX_LEASE_LIMIT: z.coerce.number().default(10000), DB_ROOT_CERT: zpStr(z.string().describe("Postgres database base64-encoded CA cert").optional()), DB_HOST: zpStr(z.string().describe("Postgres database host").optional()), @@ -482,6 +483,15 @@ export const overwriteSchema: { fields: { key: keyof TEnvConfig; description?: string }[]; }; } = { + auditLogs: { + name: "Audit Logs", + fields: [ + { + key: "DISABLE_AUDIT_LOG_STORAGE", + description: "Disable audit log storage" + } + ] + }, aws: { name: "AWS", fields: [ diff --git a/backend/src/server/routes/index.ts b/backend/src/server/routes/index.ts index 256c622f9..ee0b2e0f3 100644 --- a/backend/src/server/routes/index.ts +++ b/backend/src/server/routes/index.ts @@ -2144,7 +2144,8 @@ export const registerRoutes = async ( inviteOnlySignup: z.boolean().optional(), redisConfigured: z.boolean().optional(), secretScanningConfigured: z.boolean().optional(), - samlDefaultOrgSlug: z.string().optional() + samlDefaultOrgSlug: z.string().optional(), + auditLogStorageDisabled: z.boolean().optional() }) } }, @@ -2171,7 +2172,8 @@ export const registerRoutes = async ( inviteOnlySignup: Boolean(serverCfg.allowSignUp), redisConfigured: cfg.isRedisConfigured, secretScanningConfigured: cfg.isSecretScanningConfigured, - samlDefaultOrgSlug: cfg.samlDefaultOrgSlug + samlDefaultOrgSlug: cfg.samlDefaultOrgSlug, + auditLogStorageDisabled: Boolean(cfg.DISABLE_AUDIT_LOG_STORAGE) }; } }); diff --git a/docs/self-hosting/configuration/envars.mdx b/docs/self-hosting/configuration/envars.mdx index 1e050ff14..53adf95a4 100644 --- a/docs/self-hosting/configuration/envars.mdx +++ b/docs/self-hosting/configuration/envars.mdx @@ -65,7 +65,14 @@ Example values: default="false" optional > - Determines whether your Infisical instance can automatically read the service account token of the pod it's running on. Used for features such as the IRSA auth method. + Determines whether your Infisical instance can automatically read the service + account token of the pod it's running on. Used for features such as the IRSA + auth method. + + + + Disable storing audit logs in the database. This is useful if you're using + audit log streams and don't want to store them in the database. ## CORS diff --git a/frontend/src/hooks/api/admin/types.ts b/frontend/src/hooks/api/admin/types.ts index 51ff5a908..fe2cc3eed 100644 --- a/frontend/src/hooks/api/admin/types.ts +++ b/frontend/src/hooks/api/admin/types.ts @@ -35,6 +35,7 @@ export type TServerConfig = { initialized: boolean; allowSignUp: boolean; allowedSignUpDomain?: string | null; + disableAuditLogStorage: boolean; isMigrationModeOn?: boolean; trustSamlEmails: boolean; trustLdapEmails: boolean; diff --git a/frontend/src/hooks/api/serverDetails/types.ts b/frontend/src/hooks/api/serverDetails/types.ts index 3e22c2684..d43521382 100644 --- a/frontend/src/hooks/api/serverDetails/types.ts +++ b/frontend/src/hooks/api/serverDetails/types.ts @@ -5,4 +5,5 @@ export type ServerStatus = { secretScanningConfigured: boolean; redisConfigured: boolean; samlDefaultOrgSlug: string; + auditLogStorageDisabled: boolean; }; diff --git a/frontend/src/layouts/OrganizationLayout/OrganizationLayout.tsx b/frontend/src/layouts/OrganizationLayout/OrganizationLayout.tsx index c5a0953de..c33f81699 100644 --- a/frontend/src/layouts/OrganizationLayout/OrganizationLayout.tsx +++ b/frontend/src/layouts/OrganizationLayout/OrganizationLayout.tsx @@ -6,10 +6,11 @@ import { twMerge } from "tailwind-merge"; import { CreateOrgModal } from "@app/components/organization/CreateOrgModal"; import { Banner } from "@app/components/page-frames/Banner"; -import { useServerConfig } from "@app/context"; +import { useServerConfig, useSubscription } from "@app/context"; import { usePopUp } from "@app/hooks"; import { useFetchServerStatus } from "@app/hooks/api"; +import { AuditLogBanner } from "./components/AuditLogBanner"; import { InsecureConnectionBanner } from "./components/InsecureConnectionBanner"; import { Navbar } from "./components/NavBar"; import { OrgSidebar } from "./components/OrgSidebar"; @@ -31,6 +32,7 @@ export const OrganizationLayout = () => { const containerHeight = config.pageFrameContent ? "h-[94vh]" : "h-screen"; const { data: serverDetails, isLoading } = useFetchServerStatus(); + const { subscription } = useSubscription(); return ( <> @@ -41,6 +43,7 @@ export const OrganizationLayout = () => { {!isLoading && !serverDetails?.redisConfigured && } {!isLoading && !serverDetails?.emailConfigured && } + {!isLoading && subscription.auditLogs && } {!window.isSecureContext && }
diff --git a/frontend/src/layouts/OrganizationLayout/components/AuditLogBanner/AuditLogBanner.tsx b/frontend/src/layouts/OrganizationLayout/components/AuditLogBanner/AuditLogBanner.tsx new file mode 100644 index 000000000..9f7494076 --- /dev/null +++ b/frontend/src/layouts/OrganizationLayout/components/AuditLogBanner/AuditLogBanner.tsx @@ -0,0 +1,23 @@ +import { useOrganization } from "@app/context"; +import { useFetchServerStatus, useGetAuditLogStreams } from "@app/hooks/api"; + +import { OrgAlertBanner } from "../OrgAlertBanner"; + +export const AuditLogBanner = () => { + const org = useOrganization(); + const { data: status, isLoading: isLoadingStatus } = useFetchServerStatus(); + const { data: streams, isLoading: isLoadingStreams } = useGetAuditLogStreams(org.currentOrg.id); + + if (isLoadingStreams || isLoadingStatus || !streams) return null; + + if (status?.auditLogStorageDisabled && !streams.length) { + return ( + + ); + } + + return null; +}; diff --git a/frontend/src/layouts/OrganizationLayout/components/AuditLogBanner/index.ts b/frontend/src/layouts/OrganizationLayout/components/AuditLogBanner/index.ts new file mode 100644 index 000000000..c7bf7d475 --- /dev/null +++ b/frontend/src/layouts/OrganizationLayout/components/AuditLogBanner/index.ts @@ -0,0 +1 @@ +export * from "./AuditLogBanner"; diff --git a/frontend/src/pages/organization/AuditLogsPage/AuditLogsPage.tsx b/frontend/src/pages/organization/AuditLogsPage/AuditLogsPage.tsx index 25459719f..11628ce98 100644 --- a/frontend/src/pages/organization/AuditLogsPage/AuditLogsPage.tsx +++ b/frontend/src/pages/organization/AuditLogsPage/AuditLogsPage.tsx @@ -12,6 +12,7 @@ export const AuditLogsPage = () => { +
{ + const { data: status } = useFetchServerStatus(); + // Determine the project ID for filtering const filterProjectId = // Use the projectId from the filter if it exists @@ -79,7 +81,11 @@ export const LogsTable = ({ filter, refetchInterval, timezone }: Props) => { {isEmpty && ( - + {status?.auditLogStorageDisabled ? ( + + ) : ( + + )} )}