mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-08 18:28:12 +00:00
Update MI authz logic
This commit is contained in:
@@ -26,7 +26,7 @@ declare module "jsonwebtoken" {
|
|||||||
refreshVersion?: number;
|
refreshVersion?: number;
|
||||||
}
|
}
|
||||||
export interface MachineRefreshTokenJwtPayload extends jwt.JwtPayload {
|
export interface MachineRefreshTokenJwtPayload extends jwt.JwtPayload {
|
||||||
serviceTokenDataId: string;
|
_id: string;
|
||||||
authTokenType: string;
|
authTokenType: string;
|
||||||
tokenVersion: number;
|
tokenVersion: number;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { IUser, Key, Membership, MembershipOrg, User, Workspace } from "../../mo
|
|||||||
import { EventType, Role } from "../../ee/models";
|
import { EventType, Role } from "../../ee/models";
|
||||||
import { deleteMembership as deleteMember, findMembership } from "../../helpers/membership";
|
import { deleteMembership as deleteMember, findMembership } from "../../helpers/membership";
|
||||||
import { sendMail } from "../../helpers/nodemailer";
|
import { sendMail } from "../../helpers/nodemailer";
|
||||||
import { ACCEPTED, ADMIN, CUSTOM, MEMBER, VIEWER } from "../../variables";
|
import { ACCEPTED, ADMIN, CUSTOM, MEMBER, NO_ACCESS, VIEWER } from "../../variables";
|
||||||
import { getSiteURL } from "../../config";
|
import { getSiteURL } from "../../config";
|
||||||
import { EEAuditLogService, EELicenseService } from "../../ee/services";
|
import { EEAuditLogService, EELicenseService } from "../../ee/services";
|
||||||
import { validateRequest } from "../../helpers/validation";
|
import { validateRequest } from "../../helpers/validation";
|
||||||
@@ -129,7 +129,7 @@ export const changeMembershipRole = async (req: Request, res: Response) => {
|
|||||||
ProjectPermissionSub.Member
|
ProjectPermissionSub.Member
|
||||||
);
|
);
|
||||||
|
|
||||||
const isCustomRole = ![ADMIN, MEMBER, VIEWER].includes(role);
|
const isCustomRole = ![ADMIN, MEMBER, VIEWER, NO_ACCESS].includes(role);
|
||||||
if (isCustomRole) {
|
if (isCustomRole) {
|
||||||
const wsRole = await Role.findOne({
|
const wsRole = await Role.findOne({
|
||||||
slug: role,
|
slug: role,
|
||||||
|
|||||||
@@ -516,7 +516,7 @@ export const addMachineToWorkspace = async (req: Request, res: Response) => {
|
|||||||
body: {
|
body: {
|
||||||
role
|
role
|
||||||
}
|
}
|
||||||
} = await validateRequest(reqValidator.AddWorkspaceServiceMemberV2, req);
|
} = await validateRequest(reqValidator.AddMachineToWorkspaceV2, req);
|
||||||
|
|
||||||
const { permission } = await getAuthDataProjectPermissions({
|
const { permission } = await getAuthDataProjectPermissions({
|
||||||
authData: req.authData,
|
authData: req.authData,
|
||||||
@@ -592,7 +592,7 @@ export const addMachineToWorkspace = async (req: Request, res: Response) => {
|
|||||||
body: {
|
body: {
|
||||||
role
|
role
|
||||||
}
|
}
|
||||||
} = await validateRequest(reqValidator.AddWorkspaceServiceMemberV2, req);
|
} = await validateRequest(reqValidator.UpdateMachineWorkspaceRoleV2, req);
|
||||||
|
|
||||||
const { permission } = await getAuthDataProjectPermissions({
|
const { permission } = await getAuthDataProjectPermissions({
|
||||||
authData: req.authData,
|
authData: req.authData,
|
||||||
@@ -650,7 +650,7 @@ export const addMachineToWorkspace = async (req: Request, res: Response) => {
|
|||||||
workspace: new Types.ObjectId(workspaceId),
|
workspace: new Types.ObjectId(workspaceId),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
role,
|
role: customRole ? CUSTOM : role,
|
||||||
customRole
|
customRole
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -672,7 +672,7 @@ export const addMachineToWorkspace = async (req: Request, res: Response) => {
|
|||||||
export const deleteMachineFromWorkspace = async (req: Request, res: Response) => {
|
export const deleteMachineFromWorkspace = async (req: Request, res: Response) => {
|
||||||
const {
|
const {
|
||||||
params: { workspaceId, machineId }
|
params: { workspaceId, machineId }
|
||||||
} = await validateRequest(reqValidator.DeleteWorkspaceServiceMemberV2, req);
|
} = await validateRequest(reqValidator.DeleteMachineFromWorkspaceV2, req);
|
||||||
|
|
||||||
const { permission } = await getAuthDataProjectPermissions({
|
const { permission } = await getAuthDataProjectPermissions({
|
||||||
authData: req.authData,
|
authData: req.authData,
|
||||||
@@ -705,7 +705,7 @@ export const addMachineToWorkspace = async (req: Request, res: Response) => {
|
|||||||
export const getWorkspaceMachineMemberships = async (req: Request, res: Response) => {
|
export const getWorkspaceMachineMemberships = async (req: Request, res: Response) => {
|
||||||
const {
|
const {
|
||||||
params: { workspaceId }
|
params: { workspaceId }
|
||||||
} = await validateRequest(reqValidator.GetWorkspaceServiceMembersV2, req);
|
} = await validateRequest(reqValidator.GetWorkspaceMachineMembersV2, req);
|
||||||
|
|
||||||
const { permission } = await getAuthDataProjectPermissions({
|
const { permission } = await getAuthDataProjectPermissions({
|
||||||
authData: req.authData,
|
authData: req.authData,
|
||||||
|
|||||||
@@ -757,19 +757,19 @@ export const getWorkspaceAuditLogActorFilterOpts = async (req: Request, res: Res
|
|||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const serviceV3Actors: MachineActor[] = (
|
const machineActors: MachineActor[] = (
|
||||||
await MachineIdentity.find({
|
await MachineIdentity.find({
|
||||||
workspace: new Types.ObjectId(workspaceId)
|
workspace: new Types.ObjectId(workspaceId)
|
||||||
})
|
})
|
||||||
).map((machineIdentity) => ({
|
).map((machineIdentity) => ({
|
||||||
type: ActorType.MACHINE,
|
type: ActorType.MACHINE,
|
||||||
metadata: {
|
metadata: {
|
||||||
serviceId: machineIdentity._id.toString(),
|
machineId: machineIdentity._id.toString(),
|
||||||
name: machineIdentity.name
|
name: machineIdentity.name
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const actors = [...userActors, ...serviceActors, ...serviceV3Actors];
|
const actors = [...userActors, ...serviceActors, ...machineActors];
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
actors
|
actors
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ import { ForbiddenError } from "@casl/ability";
|
|||||||
if (decodedToken.authTokenType !== AuthTokenType.MACHINE_REFRESH_TOKEN) throw UnauthorizedRequestError();
|
if (decodedToken.authTokenType !== AuthTokenType.MACHINE_REFRESH_TOKEN) throw UnauthorizedRequestError();
|
||||||
|
|
||||||
let machineIdentity = await MachineIdentity.findOne({
|
let machineIdentity = await MachineIdentity.findOne({
|
||||||
_id: new Types.ObjectId(decodedToken.serviceTokenDataId),
|
_id: new Types.ObjectId(decodedToken._id),
|
||||||
isActive: true
|
isActive: true
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -101,7 +101,7 @@ import { ForbiddenError } from "@casl/ability";
|
|||||||
|
|
||||||
response.accessToken = createToken({
|
response.accessToken = createToken({
|
||||||
payload: {
|
payload: {
|
||||||
_id: machineIdentity._id.toString(), // TODO: fix this
|
_id: machineIdentity._id.toString(),
|
||||||
authTokenType: AuthTokenType.MACHINE_ACCESS_TOKEN,
|
authTokenType: AuthTokenType.MACHINE_ACCESS_TOKEN,
|
||||||
tokenVersion: machineIdentity.tokenVersion
|
tokenVersion: machineIdentity.tokenVersion
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -332,6 +332,7 @@ export const getAuthDataProjectPermissions = async ({
|
|||||||
|
|
||||||
role = machineMembership.role;
|
role = machineMembership.role;
|
||||||
customRole = machineMembership.customRole;
|
customRole = machineMembership.customRole;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -280,7 +280,7 @@ export const ToggleAutoCapitalizationV2 = z.object({
|
|||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
export const AddWorkspaceServiceMemberV2 = z.object({
|
export const AddMachineToWorkspaceV2 = z.object({
|
||||||
params: z.object({
|
params: z.object({
|
||||||
workspaceId: z.string().trim(),
|
workspaceId: z.string().trim(),
|
||||||
machineId: z.string().trim()
|
machineId: z.string().trim()
|
||||||
@@ -290,14 +290,24 @@ export const AddWorkspaceServiceMemberV2 = z.object({
|
|||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
export const DeleteWorkspaceServiceMemberV2 = z.object({
|
export const UpdateMachineWorkspaceRoleV2 = z.object({
|
||||||
|
params: z.object({
|
||||||
|
workspaceId: z.string().trim(),
|
||||||
|
machineId: z.string().trim()
|
||||||
|
}),
|
||||||
|
body: z.object({
|
||||||
|
role: z.string().trim().min(1).default(NO_ACCESS),
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
export const DeleteMachineFromWorkspaceV2 = z.object({
|
||||||
params: z.object({
|
params: z.object({
|
||||||
workspaceId: z.string().trim(),
|
workspaceId: z.string().trim(),
|
||||||
machineId: z.string().trim()
|
machineId: z.string().trim()
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
export const GetWorkspaceServiceMembersV2 = z.object({
|
export const GetWorkspaceMachineMembersV2 = z.object({
|
||||||
params: z.object({
|
params: z.object({
|
||||||
workspaceId: z.string().trim()
|
workspaceId: z.string().trim()
|
||||||
}),
|
}),
|
||||||
|
|||||||
+2
-2
@@ -31,7 +31,7 @@ export const MachineIdentitySection = withPermission(
|
|||||||
machineId
|
machineId
|
||||||
});
|
});
|
||||||
createNotification({
|
createNotification({
|
||||||
text: "Successfully deleted service token v3",
|
text: "Successfully deleted machine identity",
|
||||||
type: "success"
|
type: "success"
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -39,7 +39,7 @@ export const MachineIdentitySection = withPermission(
|
|||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
createNotification({
|
createNotification({
|
||||||
text: "Failed to delete service token v3",
|
text: "Failed to delete machine identity",
|
||||||
type: "error"
|
type: "error"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -103,13 +103,13 @@ export const MachineIdentityTable = ({
|
|||||||
// });
|
// });
|
||||||
|
|
||||||
// createNotification({
|
// createNotification({
|
||||||
// text: `Successfully ${isActive ? "enabled" : "disabled"} service token v3`,
|
// text: `Successfully ${isActive ? "enabled" : "disabled"} machine identity`,
|
||||||
// type: "success"
|
// type: "success"
|
||||||
// });
|
// });
|
||||||
// } catch (err) {
|
// } catch (err) {
|
||||||
// console.log(err);
|
// console.log(err);
|
||||||
// createNotification({
|
// createNotification({
|
||||||
// text: `Failed to ${isActive ? "enable" : "disable"} service token v3`,
|
// text: `Failed to ${isActive ? "enable" : "disable"} machine identity`,
|
||||||
// type: "error"
|
// type: "error"
|
||||||
// });
|
// });
|
||||||
// }
|
// }
|
||||||
|
|||||||
+1
-1
@@ -84,7 +84,7 @@ const SIMPLE_PERMISSION_OPTIONS = [
|
|||||||
] as const;
|
] as const;
|
||||||
|
|
||||||
export const OrgRoleModifySection = ({ role, onGoBack }: Props) => {
|
export const OrgRoleModifySection = ({ role, onGoBack }: Props) => {
|
||||||
const isNonEditable = ["owner", "admin", "member"].includes(role?.slug || "");
|
const isNonEditable = ["owner", "admin", "member", "no-access"].includes(role?.slug || "");
|
||||||
const isNewRole = !role?.slug;
|
const isNewRole = !role?.slug;
|
||||||
|
|
||||||
const { createNotification } = useNotificationContext();
|
const { createNotification } = useNotificationContext();
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ export const LogsTableRow = ({
|
|||||||
return (
|
return (
|
||||||
<Td>
|
<Td>
|
||||||
<p>{`${actor.metadata.name}`}</p>
|
<p>{`${actor.metadata.name}`}</p>
|
||||||
<p>Service token V3</p>
|
<p>Machine identity</p>
|
||||||
</Td>
|
</Td>
|
||||||
);
|
);
|
||||||
default:
|
default:
|
||||||
|
|||||||
+3
-2
@@ -27,7 +27,7 @@ import { UsePopUpState } from "@app/hooks/usePopUp";
|
|||||||
|
|
||||||
const schema = yup.object({
|
const schema = yup.object({
|
||||||
machineId: yup.string().required("Machine identity id is required"),
|
machineId: yup.string().required("Machine identity id is required"),
|
||||||
role: yup.string().required("Machine identity role is required")
|
role: yup.string()
|
||||||
}).required();
|
}).required();
|
||||||
|
|
||||||
export type FormData = yup.InferType<typeof schema>;
|
export type FormData = yup.InferType<typeof schema>;
|
||||||
@@ -85,10 +85,11 @@ export const AddMachineIdentityModal = ({
|
|||||||
role
|
role
|
||||||
}: FormData) => {
|
}: FormData) => {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
await addMachineToWorkspaceMutateAsync({
|
await addMachineToWorkspaceMutateAsync({
|
||||||
workspaceId,
|
workspaceId,
|
||||||
machineId,
|
machineId,
|
||||||
role
|
role: role || undefined
|
||||||
});
|
});
|
||||||
|
|
||||||
createNotification({
|
createNotification({
|
||||||
|
|||||||
+8
-1
@@ -9,6 +9,7 @@ import {
|
|||||||
faLock,
|
faLock,
|
||||||
faNetworkWired,
|
faNetworkWired,
|
||||||
faPuzzlePiece,
|
faPuzzlePiece,
|
||||||
|
faServer,
|
||||||
faShield,
|
faShield,
|
||||||
faTags,
|
faTags,
|
||||||
faUser,
|
faUser,
|
||||||
@@ -59,6 +60,12 @@ const SINGLE_PERMISSION_LIST = [
|
|||||||
icon: faUser,
|
icon: faUser,
|
||||||
formName: "member"
|
formName: "member"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: "Machine identity management",
|
||||||
|
subtitle: "Add, view, update and remove machine identities from the project",
|
||||||
|
icon: faServer,
|
||||||
|
formName: "machine-identity"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: "Webhooks",
|
title: "Webhooks",
|
||||||
subtitle: "Webhook management control",
|
subtitle: "Webhook management control",
|
||||||
@@ -109,7 +116,7 @@ type Props = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const ProjectRoleModifySection = ({ role, onGoBack }: Props) => {
|
export const ProjectRoleModifySection = ({ role, onGoBack }: Props) => {
|
||||||
const isNonEditable = ["admin", "member", "viewer"].includes(role?.slug || "");
|
const isNonEditable = ["admin", "member", "viewer", "no-access"].includes(role?.slug || "");
|
||||||
const isNewRole = !role?.slug;
|
const isNewRole = !role?.slug;
|
||||||
|
|
||||||
const { createNotification } = useNotificationContext();
|
const { createNotification } = useNotificationContext();
|
||||||
|
|||||||
+1
@@ -33,6 +33,7 @@ export const formSchema = z.object({
|
|||||||
.object({
|
.object({
|
||||||
secrets: z.record(multiEnvPermissionSchema).optional(),
|
secrets: z.record(multiEnvPermissionSchema).optional(),
|
||||||
member: generalPermissionSchema,
|
member: generalPermissionSchema,
|
||||||
|
"machine-identity": generalPermissionSchema,
|
||||||
role: generalPermissionSchema,
|
role: generalPermissionSchema,
|
||||||
integrations: generalPermissionSchema,
|
integrations: generalPermissionSchema,
|
||||||
webhooks: generalPermissionSchema,
|
webhooks: generalPermissionSchema,
|
||||||
|
|||||||
Reference in New Issue
Block a user