mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-06 17:27:16 +00:00
Merge pull request #839 from Infisical/permissions-audit-log
Add audit logs for workspace user role and read/write permission changes
This commit is contained in:
@@ -104,9 +104,9 @@ export const changeMembershipRole = async (req: Request, res: Response) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// validate target membership
|
// validate target membership
|
||||||
const membershipToChangeRole = await findMembership({
|
const membershipToChangeRole = await Membership
|
||||||
_id: membershipId
|
.findById(membershipId)
|
||||||
});
|
.populate<{ user: IUser }>("user");
|
||||||
|
|
||||||
if (!membershipToChangeRole) {
|
if (!membershipToChangeRole) {
|
||||||
throw new Error("Failed to find membership to change role");
|
throw new Error("Failed to find membership to change role");
|
||||||
@@ -127,9 +127,27 @@ export const changeMembershipRole = async (req: Request, res: Response) => {
|
|||||||
// user is not an admin member of the workspace
|
// user is not an admin member of the workspace
|
||||||
throw new Error("Insufficient role for changing member roles");
|
throw new Error("Insufficient role for changing member roles");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const oldRole = membershipToChangeRole.role;
|
||||||
|
|
||||||
membershipToChangeRole.role = role;
|
membershipToChangeRole.role = role;
|
||||||
await membershipToChangeRole.save();
|
await membershipToChangeRole.save();
|
||||||
|
|
||||||
|
await EEAuditLogService.createAuditLog(
|
||||||
|
req.authData,
|
||||||
|
{
|
||||||
|
type: EventType.UPDATE_USER_WORKSPACE_ROLE,
|
||||||
|
metadata: {
|
||||||
|
userId: membershipToChangeRole.user._id.toString(),
|
||||||
|
email: membershipToChangeRole.user.email,
|
||||||
|
oldRole,
|
||||||
|
newRole: membershipToChangeRole.role
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
workspaceId: membershipToChangeRole.workspace
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
membership: membershipToChangeRole
|
membership: membershipToChangeRole
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
import { Request, Response } from "express";
|
import { Request, Response } from "express";
|
||||||
import { Membership, Workspace } from "../../../models";
|
import { IUser, Membership, Workspace } from "../../../models";
|
||||||
|
import { EventType } from "../../../ee/models";
|
||||||
import { IMembershipPermission } from "../../../models/membership";
|
import { IMembershipPermission } from "../../../models/membership";
|
||||||
import { BadRequestError, UnauthorizedRequestError } from "../../../utils/errors";
|
import { BadRequestError, UnauthorizedRequestError } from "../../../utils/errors";
|
||||||
import { ADMIN, MEMBER } from "../../../variables/organization";
|
import { ADMIN, MEMBER } from "../../../variables/organization";
|
||||||
import { PERMISSION_READ_SECRETS, PERMISSION_WRITE_SECRETS } from "../../../variables";
|
import { PERMISSION_READ_SECRETS, PERMISSION_WRITE_SECRETS } from "../../../variables";
|
||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
|
import { EEAuditLogService } from "../../services";
|
||||||
|
|
||||||
export const denyMembershipPermissions = async (req: Request, res: Response) => {
|
export const denyMembershipPermissions = async (req: Request, res: Response) => {
|
||||||
const { membershipId } = req.params;
|
const { membershipId } = req.params;
|
||||||
@@ -51,12 +53,33 @@ export const denyMembershipPermissions = async (req: Request, res: Response) =>
|
|||||||
{ _id: membershipToModify._id },
|
{ _id: membershipToModify._id },
|
||||||
{ $set: { deniedPermissions: sanitizedMembershipPermissionsUnique } },
|
{ $set: { deniedPermissions: sanitizedMembershipPermissionsUnique } },
|
||||||
{ new: true }
|
{ new: true }
|
||||||
)
|
).populate<{ user: IUser }>("user");
|
||||||
|
|
||||||
if (!updatedMembershipWithPermissions) {
|
if (!updatedMembershipWithPermissions) {
|
||||||
throw BadRequestError({ message: "The resource has been removed before it can be modified" })
|
throw BadRequestError({ message: "The resource has been removed before it can be modified" })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await EEAuditLogService.createAuditLog(
|
||||||
|
req.authData,
|
||||||
|
{
|
||||||
|
type: EventType.UPDATE_USER_WORKSPACE_DENIED_PERMISSIONS,
|
||||||
|
metadata: {
|
||||||
|
userId: updatedMembershipWithPermissions.user._id.toString(),
|
||||||
|
email: updatedMembershipWithPermissions.user.email,
|
||||||
|
deniedPermissions: updatedMembershipWithPermissions.deniedPermissions.map(({
|
||||||
|
environmentSlug,
|
||||||
|
ability
|
||||||
|
}) => ({
|
||||||
|
environmentSlug,
|
||||||
|
ability
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
workspaceId: updatedMembershipWithPermissions.workspace
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
res.send({
|
res.send({
|
||||||
permissionsDenied: updatedMembershipWithPermissions.deniedPermissions,
|
permissionsDenied: updatedMembershipWithPermissions.deniedPermissions,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -42,4 +42,6 @@ export enum EventType {
|
|||||||
CREATE_SECRET_IMPORT = "create-secret-import",
|
CREATE_SECRET_IMPORT = "create-secret-import",
|
||||||
UPDATE_SECRET_IMPORT = "update-secret-import",
|
UPDATE_SECRET_IMPORT = "update-secret-import",
|
||||||
DELETE_SECRET_IMPORT = "delete-secret-import",
|
DELETE_SECRET_IMPORT = "delete-secret-import",
|
||||||
|
UPDATE_USER_WORKSPACE_ROLE = "update-user-workspace-role",
|
||||||
|
UPDATE_USER_WORKSPACE_DENIED_PERMISSIONS = "update-user-workspace-denied-permissions"
|
||||||
}
|
}
|
||||||
@@ -346,6 +346,28 @@ interface DeleteSecretImportEvent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface UpdateUserRole {
|
||||||
|
type: EventType.UPDATE_USER_WORKSPACE_ROLE,
|
||||||
|
metadata: {
|
||||||
|
userId: string;
|
||||||
|
email: string;
|
||||||
|
oldRole: string;
|
||||||
|
newRole: string;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface UpdateUserDeniedPermissions {
|
||||||
|
type: EventType.UPDATE_USER_WORKSPACE_DENIED_PERMISSIONS,
|
||||||
|
metadata: {
|
||||||
|
userId: string;
|
||||||
|
email: string;
|
||||||
|
deniedPermissions: {
|
||||||
|
environmentSlug: string;
|
||||||
|
ability: string;
|
||||||
|
}[]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export type Event =
|
export type Event =
|
||||||
| GetSecretsEvent
|
| GetSecretsEvent
|
||||||
| GetSecretEvent
|
| GetSecretEvent
|
||||||
@@ -376,4 +398,6 @@ export type Event =
|
|||||||
| GetSecretImportsEvent
|
| GetSecretImportsEvent
|
||||||
| CreateSecretImportEvent
|
| CreateSecretImportEvent
|
||||||
| UpdateSecretImportEvent
|
| UpdateSecretImportEvent
|
||||||
| DeleteSecretImportEvent;
|
| DeleteSecretImportEvent
|
||||||
|
| UpdateUserRole
|
||||||
|
| UpdateUserDeniedPermissions;
|
||||||
@@ -26,9 +26,9 @@ const updateUserProjectPermission = async ({
|
|||||||
permissions: denials
|
permissions: denials
|
||||||
})
|
})
|
||||||
}).then(async (res) => {
|
}).then(async (res) => {
|
||||||
console.log({
|
// console.log({
|
||||||
permissions: denials
|
// permissions: denials
|
||||||
}, res)
|
// }, res)
|
||||||
if (res && res.status === 200) {
|
if (res && res.status === 200) {
|
||||||
return res.json();
|
return res.json();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,7 +31,8 @@ export const eventToNameMap: { [K in EventType]: string } = {
|
|||||||
[EventType.CREATE_SECRET_IMPORT]: "Create secret import",
|
[EventType.CREATE_SECRET_IMPORT]: "Create secret import",
|
||||||
[EventType.UPDATE_SECRET_IMPORT]: "Update secret import",
|
[EventType.UPDATE_SECRET_IMPORT]: "Update secret import",
|
||||||
[EventType.DELETE_SECRET_IMPORT]: "Delete secret import",
|
[EventType.DELETE_SECRET_IMPORT]: "Delete secret import",
|
||||||
|
[EventType.UPDATE_USER_WORKSPACE_DENIED_PERMISSIONS]: "Update denied permissions",
|
||||||
|
[EventType.UPDATE_USER_WORKSPACE_ROLE]: "Update user role"
|
||||||
};
|
};
|
||||||
|
|
||||||
export const userAgentTTypeoNameMap: { [K in UserAgentType]: string } = {
|
export const userAgentTTypeoNameMap: { [K in UserAgentType]: string } = {
|
||||||
|
|||||||
@@ -40,5 +40,7 @@ export enum EventType {
|
|||||||
GET_SECRET_IMPORTS = "get-secret-imports",
|
GET_SECRET_IMPORTS = "get-secret-imports",
|
||||||
CREATE_SECRET_IMPORT = "create-secret-import",
|
CREATE_SECRET_IMPORT = "create-secret-import",
|
||||||
UPDATE_SECRET_IMPORT = "update-secret-import",
|
UPDATE_SECRET_IMPORT = "update-secret-import",
|
||||||
DELETE_SECRET_IMPORT = "delete-secret-import"
|
DELETE_SECRET_IMPORT = "delete-secret-import",
|
||||||
|
UPDATE_USER_WORKSPACE_ROLE = "update-user-workspace-role",
|
||||||
|
UPDATE_USER_WORKSPACE_DENIED_PERMISSIONS = "update-user-workspace-denied-permissions"
|
||||||
}
|
}
|
||||||
@@ -348,6 +348,29 @@ interface DeleteSecretImportEvent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface UpdateUserRole {
|
||||||
|
type: EventType.UPDATE_USER_WORKSPACE_ROLE,
|
||||||
|
metadata: {
|
||||||
|
userId: string;
|
||||||
|
email: string;
|
||||||
|
oldRole: string;
|
||||||
|
newRole: string;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface UpdateUserDeniedPermissions {
|
||||||
|
type: EventType.UPDATE_USER_WORKSPACE_DENIED_PERMISSIONS,
|
||||||
|
metadata: {
|
||||||
|
userId: string;
|
||||||
|
email: string;
|
||||||
|
deniedPermissions: {
|
||||||
|
environmentSlug: string;
|
||||||
|
ability: string;
|
||||||
|
}[]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
export type Event =
|
export type Event =
|
||||||
| GetSecretsEvent
|
| GetSecretsEvent
|
||||||
| GetSecretEvent
|
| GetSecretEvent
|
||||||
@@ -378,7 +401,9 @@ export type Event =
|
|||||||
| GetSecretImportsEvent
|
| GetSecretImportsEvent
|
||||||
| CreateSecretImportEvent
|
| CreateSecretImportEvent
|
||||||
| UpdateSecretImportEvent
|
| UpdateSecretImportEvent
|
||||||
| DeleteSecretImportEvent;
|
| DeleteSecretImportEvent
|
||||||
|
| UpdateUserRole
|
||||||
|
| UpdateUserDeniedPermissions;
|
||||||
|
|
||||||
export type AuditLog = {
|
export type AuditLog = {
|
||||||
_id: string;
|
_id: string;
|
||||||
|
|||||||
@@ -279,6 +279,27 @@ export const LogsTableRow = ({
|
|||||||
<p>{`Import to path: ${event.metadata.importToSecretPath}`}</p>
|
<p>{`Import to path: ${event.metadata.importToSecretPath}`}</p>
|
||||||
</Td>
|
</Td>
|
||||||
);
|
);
|
||||||
|
case EventType.UPDATE_USER_WORKSPACE_ROLE:
|
||||||
|
return (
|
||||||
|
<Td>
|
||||||
|
<p>{`Email: ${event.metadata.email}`}</p>
|
||||||
|
<p>{`Old role: ${event.metadata.oldRole}`}</p>
|
||||||
|
<p>{`New role: ${event.metadata.newRole}`}</p>
|
||||||
|
</Td>
|
||||||
|
);
|
||||||
|
case EventType.UPDATE_USER_WORKSPACE_DENIED_PERMISSIONS:
|
||||||
|
return (
|
||||||
|
<Td>
|
||||||
|
<p>{`Email: ${event.metadata.email}`}</p>
|
||||||
|
{event.metadata.deniedPermissions.map((permission) => {
|
||||||
|
return (
|
||||||
|
<p key={`audit-log-denied-permission-${event.metadata.userId}-${permission.environmentSlug}-${permission.ability}`}>
|
||||||
|
{`Denied env-ability: ${permission.environmentSlug}-${permission.ability}`}
|
||||||
|
</p>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</Td>
|
||||||
|
);
|
||||||
default:
|
default:
|
||||||
return (
|
return (
|
||||||
<Td />
|
<Td />
|
||||||
|
|||||||
Reference in New Issue
Block a user