mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-08 22:28:15 +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.binary("encryptedBotAccessToken").notNullable();
|
||||||
tb.string("slackBotId").notNullable();
|
tb.string("slackBotId").notNullable();
|
||||||
tb.string("slackBotUserId").notNullable();
|
tb.string("slackBotUserId").notNullable();
|
||||||
tb.boolean("isAccessRequestNotificationEnabled").defaultTo(false);
|
tb.boolean("isAccessRequestNotificationEnabled").notNullable().defaultTo(false);
|
||||||
tb.string("accessRequestChannels").defaultTo("");
|
tb.string("accessRequestChannels").notNullable().defaultTo("");
|
||||||
tb.boolean("isSecretRequestNotificationEnabled").defaultTo(false);
|
tb.boolean("isSecretRequestNotificationEnabled").notNullable().defaultTo(false);
|
||||||
tb.string("secretRequestChannels").defaultTo("");
|
tb.string("secretRequestChannels").notNullable().defaultTo("");
|
||||||
tb.timestamps(true, true, true);
|
tb.timestamps(true, true, true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -19,10 +19,10 @@ export const SlackIntegrationsSchema = z.object({
|
|||||||
encryptedBotAccessToken: zodBuffer,
|
encryptedBotAccessToken: zodBuffer,
|
||||||
slackBotId: z.string(),
|
slackBotId: z.string(),
|
||||||
slackBotUserId: z.string(),
|
slackBotUserId: z.string(),
|
||||||
isAccessRequestNotificationEnabled: z.boolean().nullable().optional(),
|
isAccessRequestNotificationEnabled: z.boolean().default(false),
|
||||||
accessRequestChannels: z.string().nullable().optional(),
|
accessRequestChannels: z.string().default(""),
|
||||||
isSecretRequestNotificationEnabled: z.boolean().nullable().optional(),
|
isSecretRequestNotificationEnabled: z.boolean().default(false),
|
||||||
secretRequestChannels: z.string().nullable().optional(),
|
secretRequestChannels: z.string().default(""),
|
||||||
createdAt: z.date(),
|
createdAt: z.date(),
|
||||||
updatedAt: z.date()
|
updatedAt: z.date()
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -169,7 +169,11 @@ export enum EventType {
|
|||||||
GET_CERTIFICATE_TEMPLATE = "get-certificate-template",
|
GET_CERTIFICATE_TEMPLATE = "get-certificate-template",
|
||||||
CREATE_CERTIFICATE_TEMPLATE_EST_CONFIG = "create-certificate-template-est-config",
|
CREATE_CERTIFICATE_TEMPLATE_EST_CONFIG = "create-certificate-template-est-config",
|
||||||
UPDATE_CERTIFICATE_TEMPLATE_EST_CONFIG = "update-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 {
|
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 =
|
export type Event =
|
||||||
| GetSecretsEvent
|
| GetSecretsEvent
|
||||||
| GetSecretEvent
|
| GetSecretEvent
|
||||||
@@ -1576,4 +1612,8 @@ export type Event =
|
|||||||
| DeleteCertificateTemplate
|
| DeleteCertificateTemplate
|
||||||
| CreateCertificateTemplateEstConfig
|
| CreateCertificateTemplateEstConfig
|
||||||
| UpdateCertificateTemplateEstConfig
|
| UpdateCertificateTemplateEstConfig
|
||||||
| GetCertificateTemplateEstConfig;
|
| GetCertificateTemplateEstConfig
|
||||||
|
| AttemptCreateSlackIntegration
|
||||||
|
| UpdateSlackIntegration
|
||||||
|
| DeleteSlackIntegration
|
||||||
|
| GetSlackIntegration;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
import { SlackIntegrationsSchema } from "@app/db/schemas";
|
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 { getConfig } from "@app/lib/config/env";
|
||||||
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
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]),
|
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||||
handler: async (req) => {
|
handler: async (req) => {
|
||||||
// TODO: add audit logs
|
const url = await server.services.slack.getInstallUrl({
|
||||||
return server.services.slack.getInstallUrl({
|
|
||||||
actor: req.permission.type,
|
actor: req.permission.type,
|
||||||
actorId: req.permission.id,
|
actorId: req.permission.id,
|
||||||
actorAuthMethod: req.permission.authMethod,
|
actorAuthMethod: req.permission.authMethod,
|
||||||
actorOrgId: req.permission.orgId,
|
actorOrgId: req.permission.orgId,
|
||||||
projectId: req.query.projectId
|
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]),
|
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||||
handler: async (req) => {
|
handler: async (req) => {
|
||||||
return server.services.slack.getSlackIntegrationByProjectId({
|
const slackIntegration = await server.services.slack.getSlackIntegrationByProjectId({
|
||||||
actor: req.permission.type,
|
actor: req.permission.type,
|
||||||
actorId: req.permission.id,
|
actorId: req.permission.id,
|
||||||
actorAuthMethod: req.permission.authMethod,
|
actorAuthMethod: req.permission.authMethod,
|
||||||
actorOrgId: req.permission.orgId,
|
actorOrgId: req.permission.orgId,
|
||||||
projectId: req.query.projectId
|
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]),
|
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||||
handler: async (req) => {
|
handler: async (req) => {
|
||||||
// TODO: add audit logs
|
const updatedSlackIntegration = await server.services.slack.updateSlackIntegration({
|
||||||
return server.services.slack.updateSlackIntegration({
|
|
||||||
actor: req.permission.type,
|
actor: req.permission.type,
|
||||||
actorId: req.permission.id,
|
actorId: req.permission.id,
|
||||||
actorAuthMethod: req.permission.authMethod,
|
actorAuthMethod: req.permission.authMethod,
|
||||||
@@ -123,6 +146,23 @@ export const registerSlackRouter = async (server: FastifyZodProvider) => {
|
|||||||
id: req.params.slackIntegrationId,
|
id: req.params.slackIntegrationId,
|
||||||
...req.body
|
...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]),
|
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||||
handler: async (req) => {
|
handler: async (req) => {
|
||||||
// TODO: add audit logs
|
const deletedSlackIntegration = await server.services.slack.deleteSlackIntegration({
|
||||||
|
|
||||||
return server.services.slack.deleteSlackIntegration({
|
|
||||||
actor: req.permission.type,
|
actor: req.permission.type,
|
||||||
actorId: req.permission.id,
|
actorId: req.permission.id,
|
||||||
actorAuthMethod: req.permission.authMethod,
|
actorAuthMethod: req.permission.authMethod,
|
||||||
actorOrgId: req.permission.orgId,
|
actorOrgId: req.permission.orgId,
|
||||||
id: req.params.slackIntegrationId
|
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
|
actorOrgId
|
||||||
);
|
);
|
||||||
|
|
||||||
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Settings);
|
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.Settings);
|
||||||
const project = await projectDAL.findById(projectId);
|
const project = await projectDAL.findById(projectId);
|
||||||
if (!project) {
|
if (!project) {
|
||||||
throw new NotFoundError({
|
throw new NotFoundError({
|
||||||
|
|||||||
@@ -77,7 +77,11 @@ export const eventToNameMap: { [K in EventType]: string } = {
|
|||||||
[EventType.CREATE_CERTIFICATE_TEMPLATE_EST_CONFIG]:
|
[EventType.CREATE_CERTIFICATE_TEMPLATE_EST_CONFIG]:
|
||||||
"Create certificate template EST configuration",
|
"Create certificate template EST configuration",
|
||||||
[EventType.UPDATE_CERTIFICATE_TEMPLATE_EST_CONFIG]:
|
[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 } = {
|
export const userAgentTTypeoNameMap: { [K in UserAgentType]: string } = {
|
||||||
|
|||||||
@@ -89,5 +89,9 @@ export enum EventType {
|
|||||||
GET_CERTIFICATE_TEMPLATE = "get-certificate-template",
|
GET_CERTIFICATE_TEMPLATE = "get-certificate-template",
|
||||||
CREATE_CERTIFICATE_TEMPLATE_EST_CONFIG = "create-certificate-template-est-config",
|
CREATE_CERTIFICATE_TEMPLATE_EST_CONFIG = "create-certificate-template-est-config",
|
||||||
UPDATE_CERTIFICATE_TEMPLATE_EST_CONFIG = "update-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 =
|
export type Event =
|
||||||
| GetSecretsEvent
|
| GetSecretsEvent
|
||||||
| GetSecretEvent
|
| GetSecretEvent
|
||||||
@@ -817,7 +842,10 @@ export type Event =
|
|||||||
| DeleteCertificateTemplate
|
| DeleteCertificateTemplate
|
||||||
| UpdateCertificateTemplateEstConfig
|
| UpdateCertificateTemplateEstConfig
|
||||||
| CreateCertificateTemplateEstConfig
|
| CreateCertificateTemplateEstConfig
|
||||||
| GetCertificateTemplateEstConfig;
|
| GetCertificateTemplateEstConfig
|
||||||
|
| UpdateSlackIntegration
|
||||||
|
| DeleteSlackIntegration
|
||||||
|
| GetSlackIntegration;
|
||||||
|
|
||||||
export type AuditLog = {
|
export type AuditLog = {
|
||||||
id: string;
|
id: string;
|
||||||
|
|||||||
@@ -442,6 +442,23 @@ export const LogsTableRow = ({ auditLog }: Props) => {
|
|||||||
<p>{`Certificate Template ID: ${event.metadata.certificateTemplateId}`}</p>
|
<p>{`Certificate Template ID: ${event.metadata.certificateTemplateId}`}</p>
|
||||||
</Td>
|
</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:
|
default:
|
||||||
return <Td />;
|
return <Td />;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user