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
This commit is contained in:
Sid
2025-08-02 00:29:53 +05:30
committed by GitHub
parent 55e5360dd4
commit a45bba8537
11 changed files with 80 additions and 8 deletions

View File

@@ -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 };
};

View File

@@ -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: [

View File

@@ -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)
};
}
});

View File

@@ -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.
</ParamField>
<ParamField query="DISABLE_AUDIT_LOG_STORAGE" type="string" default="false">
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.
</ParamField>
## CORS

View File

@@ -35,6 +35,7 @@ export type TServerConfig = {
initialized: boolean;
allowSignUp: boolean;
allowedSignUpDomain?: string | null;
disableAuditLogStorage: boolean;
isMigrationModeOn?: boolean;
trustSamlEmails: boolean;
trustLdapEmails: boolean;

View File

@@ -5,4 +5,5 @@ export type ServerStatus = {
secretScanningConfigured: boolean;
redisConfigured: boolean;
samlDefaultOrgSlug: string;
auditLogStorageDisabled: boolean;
};

View File

@@ -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 = () => {
<Navbar />
{!isLoading && !serverDetails?.redisConfigured && <RedisBanner />}
{!isLoading && !serverDetails?.emailConfigured && <SmtpBanner />}
{!isLoading && subscription.auditLogs && <AuditLogBanner />}
{!window.isSecureContext && <InsecureConnectionBanner />}
<div className="flex flex-grow flex-col overflow-y-hidden md:flex-row">
<OrgSidebar isHidden={isInsideProject} />

View File

@@ -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 (
<OrgAlertBanner
text="Attention: Audit logs storage is disabled but no audit log streams have been configured."
link="https://infisical.com/docs/documentation/platform/audit-log-streams/audit-log-streams"
/>
);
}
return null;
};

View File

@@ -0,0 +1 @@
export * from "./AuditLogBanner";

View File

@@ -12,6 +12,7 @@ export const AuditLogsPage = () => {
<link rel="icon" href="/infisical.ico" />
<meta property="og:image" content="/images/message.png" />
</Helmet>
<div className="flex h-full w-full justify-center bg-bunker-800 text-white">
<div className="w-full max-w-7xl">
<PageHeader

View File

@@ -1,5 +1,5 @@
import { Fragment } from "react";
import { faFile } from "@fortawesome/free-solid-svg-icons";
import { faCancel, faFile } from "@fortawesome/free-solid-svg-icons";
import { twMerge } from "tailwind-merge";
import {
@@ -16,7 +16,7 @@ import {
Tr
} from "@app/components/v2";
import { Timezone } from "@app/helpers/datetime";
import { useGetAuditLogs } from "@app/hooks/api";
import { useFetchServerStatus, useGetAuditLogs } from "@app/hooks/api";
import { TGetAuditLogsFilter } from "@app/hooks/api/auditLogs/types";
import { LogsTableRow } from "./LogsTableRow";
@@ -30,6 +30,8 @@ type Props = {
const AUDIT_LOG_LIMIT = 30;
export const LogsTable = ({ filter, refetchInterval, timezone }: Props) => {
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 && (
<Tr>
<Td colSpan={3}>
<EmptyState title="No audit logs on file" icon={faFile} />
{status?.auditLogStorageDisabled ? (
<EmptyState title="Audit log storage is disabled" icon={faCancel} />
) : (
<EmptyState title="No audit logs on file" icon={faFile} />
)}
</Td>
</Tr>
)}