mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-09-22 13:39:35 +00:00
misc: audit logs for slack integration management
This commit is contained in:
@@ -16,10 +16,10 @@ export async function up(knex: Knex): Promise<void> {
|
||||
tb.binary("encryptedBotAccessToken").notNullable();
|
||||
tb.string("slackBotId").notNullable();
|
||||
tb.string("slackBotUserId").notNullable();
|
||||
tb.boolean("isAccessRequestNotificationEnabled").defaultTo(false);
|
||||
tb.string("accessRequestChannels").defaultTo("");
|
||||
tb.boolean("isSecretRequestNotificationEnabled").defaultTo(false);
|
||||
tb.string("secretRequestChannels").defaultTo("");
|
||||
tb.boolean("isAccessRequestNotificationEnabled").notNullable().defaultTo(false);
|
||||
tb.string("accessRequestChannels").notNullable().defaultTo("");
|
||||
tb.boolean("isSecretRequestNotificationEnabled").notNullable().defaultTo(false);
|
||||
tb.string("secretRequestChannels").notNullable().defaultTo("");
|
||||
tb.timestamps(true, true, true);
|
||||
});
|
||||
|
||||
|
||||
@@ -19,10 +19,10 @@ export const SlackIntegrationsSchema = z.object({
|
||||
encryptedBotAccessToken: zodBuffer,
|
||||
slackBotId: z.string(),
|
||||
slackBotUserId: z.string(),
|
||||
isAccessRequestNotificationEnabled: z.boolean().nullable().optional(),
|
||||
accessRequestChannels: z.string().nullable().optional(),
|
||||
isSecretRequestNotificationEnabled: z.boolean().nullable().optional(),
|
||||
secretRequestChannels: z.string().nullable().optional(),
|
||||
isAccessRequestNotificationEnabled: z.boolean().default(false),
|
||||
accessRequestChannels: z.string().default(""),
|
||||
isSecretRequestNotificationEnabled: z.boolean().default(false),
|
||||
secretRequestChannels: z.string().default(""),
|
||||
createdAt: z.date(),
|
||||
updatedAt: z.date()
|
||||
});
|
||||
|
||||
@@ -169,7 +169,11 @@ export enum EventType {
|
||||
GET_CERTIFICATE_TEMPLATE = "get-certificate-template",
|
||||
CREATE_CERTIFICATE_TEMPLATE_EST_CONFIG = "create-certificate-template-est-config",
|
||||
UPDATE_CERTIFICATE_TEMPLATE_EST_CONFIG = "update-certificate-template-est-config",
|
||||
GET_CERTIFICATE_TEMPLATE_EST_CONFIG = "get-certificate-template-est-config"
|
||||
GET_CERTIFICATE_TEMPLATE_EST_CONFIG = "get-certificate-template-est-config",
|
||||
ATTEMPT_CREATE_SLACK_INTEGRATION = "attempt-create-slack-integration",
|
||||
GET_SLACK_INTEGRATION = "get-slack-integration",
|
||||
UPDATE_SLACK_INTEGRATION = "update-slack-integration",
|
||||
DELETE_SLACK_INTEGRATION = "delete-slack-integration"
|
||||
}
|
||||
|
||||
interface UserActorMetadata {
|
||||
@@ -1446,6 +1450,38 @@ interface GetCertificateTemplateEstConfig {
|
||||
};
|
||||
}
|
||||
|
||||
interface AttemptCreateSlackIntegration {
|
||||
type: EventType.ATTEMPT_CREATE_SLACK_INTEGRATION;
|
||||
metadata: {
|
||||
projectId?: string;
|
||||
}; // no metadata
|
||||
}
|
||||
|
||||
interface UpdateSlackIntegration {
|
||||
type: EventType.UPDATE_SLACK_INTEGRATION;
|
||||
metadata: {
|
||||
id: string;
|
||||
isAccessRequestNotificationEnabled: boolean;
|
||||
accessRequestChannels: string;
|
||||
isSecretRequestNotificationEnabled: boolean;
|
||||
secretRequestChannels: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface DeleteSlackIntegration {
|
||||
type: EventType.DELETE_SLACK_INTEGRATION;
|
||||
metadata: {
|
||||
id: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface GetSlackIntegration {
|
||||
type: EventType.GET_SLACK_INTEGRATION;
|
||||
metadata: {
|
||||
id: string;
|
||||
};
|
||||
}
|
||||
|
||||
export type Event =
|
||||
| GetSecretsEvent
|
||||
| GetSecretEvent
|
||||
@@ -1576,4 +1612,8 @@ export type Event =
|
||||
| DeleteCertificateTemplate
|
||||
| CreateCertificateTemplateEstConfig
|
||||
| UpdateCertificateTemplateEstConfig
|
||||
| GetCertificateTemplateEstConfig;
|
||||
| GetCertificateTemplateEstConfig
|
||||
| AttemptCreateSlackIntegration
|
||||
| UpdateSlackIntegration
|
||||
| DeleteSlackIntegration
|
||||
| GetSlackIntegration;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { z } from "zod";
|
||||
|
||||
import { SlackIntegrationsSchema } from "@app/db/schemas";
|
||||
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
|
||||
import { getConfig } from "@app/lib/config/env";
|
||||
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||
@@ -31,14 +32,24 @@ export const registerSlackRouter = async (server: FastifyZodProvider) => {
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
handler: async (req) => {
|
||||
// TODO: add audit logs
|
||||
return server.services.slack.getInstallUrl({
|
||||
const url = await server.services.slack.getInstallUrl({
|
||||
actor: req.permission.type,
|
||||
actorId: req.permission.id,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
projectId: req.query.projectId
|
||||
});
|
||||
|
||||
await server.services.auditLog.createAuditLog({
|
||||
...req.auditLogInfo,
|
||||
projectId: req.query.projectId,
|
||||
event: {
|
||||
type: EventType.ATTEMPT_CREATE_SLACK_INTEGRATION,
|
||||
metadata: {}
|
||||
}
|
||||
});
|
||||
|
||||
return url;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -70,13 +81,26 @@ export const registerSlackRouter = async (server: FastifyZodProvider) => {
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
handler: async (req) => {
|
||||
return server.services.slack.getSlackIntegrationByProjectId({
|
||||
const slackIntegration = await server.services.slack.getSlackIntegrationByProjectId({
|
||||
actor: req.permission.type,
|
||||
actorId: req.permission.id,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
projectId: req.query.projectId
|
||||
});
|
||||
|
||||
await server.services.auditLog.createAuditLog({
|
||||
...req.auditLogInfo,
|
||||
projectId: req.query.projectId,
|
||||
event: {
|
||||
type: EventType.GET_SLACK_INTEGRATION,
|
||||
metadata: {
|
||||
id: slackIntegration?.id
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return slackIntegration;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -114,8 +138,7 @@ export const registerSlackRouter = async (server: FastifyZodProvider) => {
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
handler: async (req) => {
|
||||
// TODO: add audit logs
|
||||
return server.services.slack.updateSlackIntegration({
|
||||
const updatedSlackIntegration = await server.services.slack.updateSlackIntegration({
|
||||
actor: req.permission.type,
|
||||
actorId: req.permission.id,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
@@ -123,6 +146,23 @@ export const registerSlackRouter = async (server: FastifyZodProvider) => {
|
||||
id: req.params.slackIntegrationId,
|
||||
...req.body
|
||||
});
|
||||
|
||||
await server.services.auditLog.createAuditLog({
|
||||
...req.auditLogInfo,
|
||||
projectId: updatedSlackIntegration.projectId,
|
||||
event: {
|
||||
type: EventType.UPDATE_SLACK_INTEGRATION,
|
||||
metadata: {
|
||||
id: updatedSlackIntegration.id,
|
||||
isAccessRequestNotificationEnabled: updatedSlackIntegration.isAccessRequestNotificationEnabled,
|
||||
accessRequestChannels: updatedSlackIntegration.accessRequestChannels,
|
||||
isSecretRequestNotificationEnabled: updatedSlackIntegration.isSecretRequestNotificationEnabled,
|
||||
secretRequestChannels: updatedSlackIntegration.secretRequestChannels
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return updatedSlackIntegration;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -154,15 +194,26 @@ export const registerSlackRouter = async (server: FastifyZodProvider) => {
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
handler: async (req) => {
|
||||
// TODO: add audit logs
|
||||
|
||||
return server.services.slack.deleteSlackIntegration({
|
||||
const deletedSlackIntegration = await server.services.slack.deleteSlackIntegration({
|
||||
actor: req.permission.type,
|
||||
actorId: req.permission.id,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
id: req.params.slackIntegrationId
|
||||
});
|
||||
|
||||
await server.services.auditLog.createAuditLog({
|
||||
...req.auditLogInfo,
|
||||
projectId: deletedSlackIntegration.projectId,
|
||||
event: {
|
||||
type: EventType.DELETE_SLACK_INTEGRATION,
|
||||
metadata: {
|
||||
id: deletedSlackIntegration.id
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return deletedSlackIntegration;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -162,7 +162,7 @@ export const slackServiceFactory = ({
|
||||
actorOrgId
|
||||
);
|
||||
|
||||
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Settings);
|
||||
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.Settings);
|
||||
const project = await projectDAL.findById(projectId);
|
||||
if (!project) {
|
||||
throw new NotFoundError({
|
||||
|
||||
@@ -77,7 +77,11 @@ export const eventToNameMap: { [K in EventType]: string } = {
|
||||
[EventType.CREATE_CERTIFICATE_TEMPLATE_EST_CONFIG]:
|
||||
"Create certificate template EST configuration",
|
||||
[EventType.UPDATE_CERTIFICATE_TEMPLATE_EST_CONFIG]:
|
||||
"Update certificate template EST configuration"
|
||||
"Update certificate template EST configuration",
|
||||
[EventType.UPDATE_SLACK_INTEGRATION]: "Update slack integration",
|
||||
[EventType.DELETE_SLACK_INTEGRATION]: "Delete slack integration",
|
||||
[EventType.GET_SLACK_INTEGRATION]: "Get slack integration",
|
||||
[EventType.ATTEMPT_CREATE_SLACK_INTEGRATION]: "Initiate create slack integration flow"
|
||||
};
|
||||
|
||||
export const userAgentTTypeoNameMap: { [K in UserAgentType]: string } = {
|
||||
|
||||
@@ -89,5 +89,9 @@ export enum EventType {
|
||||
GET_CERTIFICATE_TEMPLATE = "get-certificate-template",
|
||||
CREATE_CERTIFICATE_TEMPLATE_EST_CONFIG = "create-certificate-template-est-config",
|
||||
UPDATE_CERTIFICATE_TEMPLATE_EST_CONFIG = "update-certificate-template-est-config",
|
||||
GET_CERTIFICATE_TEMPLATE_EST_CONFIG = "get-certificate-template-est-config"
|
||||
GET_CERTIFICATE_TEMPLATE_EST_CONFIG = "get-certificate-template-est-config",
|
||||
ATTEMPT_CREATE_SLACK_INTEGRATION = "attempt-create-slack-integration",
|
||||
GET_SLACK_INTEGRATION = "get-slack-integration",
|
||||
UPDATE_SLACK_INTEGRATION = "update-slack-integration",
|
||||
DELETE_SLACK_INTEGRATION = "delete-slack-integration"
|
||||
}
|
||||
|
||||
@@ -742,6 +742,31 @@ interface GetCertificateTemplateEstConfig {
|
||||
};
|
||||
}
|
||||
|
||||
interface UpdateSlackIntegration {
|
||||
type: EventType.UPDATE_SLACK_INTEGRATION;
|
||||
metadata: {
|
||||
id: string;
|
||||
isAccessRequestNotificationEnabled: boolean;
|
||||
accessRequestChannels: string;
|
||||
isSecretRequestNotificationEnabled: boolean;
|
||||
secretRequestChannels: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface DeleteSlackIntegration {
|
||||
type: EventType.DELETE_SLACK_INTEGRATION;
|
||||
metadata: {
|
||||
id: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface GetSlackIntegration {
|
||||
type: EventType.GET_SLACK_INTEGRATION;
|
||||
metadata: {
|
||||
id: string;
|
||||
};
|
||||
}
|
||||
|
||||
export type Event =
|
||||
| GetSecretsEvent
|
||||
| GetSecretEvent
|
||||
@@ -817,7 +842,10 @@ export type Event =
|
||||
| DeleteCertificateTemplate
|
||||
| UpdateCertificateTemplateEstConfig
|
||||
| CreateCertificateTemplateEstConfig
|
||||
| GetCertificateTemplateEstConfig;
|
||||
| GetCertificateTemplateEstConfig
|
||||
| UpdateSlackIntegration
|
||||
| DeleteSlackIntegration
|
||||
| GetSlackIntegration;
|
||||
|
||||
export type AuditLog = {
|
||||
id: string;
|
||||
|
||||
@@ -442,6 +442,23 @@ export const LogsTableRow = ({ auditLog }: Props) => {
|
||||
<p>{`Certificate Template ID: ${event.metadata.certificateTemplateId}`}</p>
|
||||
</Td>
|
||||
);
|
||||
case EventType.UPDATE_SLACK_INTEGRATION:
|
||||
return (
|
||||
<Td>
|
||||
<p>{`Slack integration ID: ${event.metadata.id}`}</p>
|
||||
<p>{`Access Request Notification Status: ${event.metadata.isAccessRequestNotificationEnabled}`}</p>
|
||||
<p>{`Access Request Channels: ${event.metadata.accessRequestChannels}`}</p>
|
||||
<p>{`Secret Approval Request Notification Status: ${event.metadata.isSecretRequestNotificationEnabled}`}</p>
|
||||
<p>{`Secret Request Channels: ${event.metadata.secretRequestChannels}`}</p>
|
||||
</Td>
|
||||
);
|
||||
case EventType.DELETE_SLACK_INTEGRATION:
|
||||
case EventType.GET_SLACK_INTEGRATION:
|
||||
return (
|
||||
<Td>
|
||||
<p>{`Slack integration ID: ${event.metadata.id}`}</p>
|
||||
</Td>
|
||||
);
|
||||
default:
|
||||
return <Td />;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user