mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-07 13:27:46 +00:00
Fix bypassing approval policies
This commit is contained in:
@@ -350,6 +350,12 @@ export const accessApprovalRequestServiceFactory = ({
|
|||||||
const canBypass = !policy.bypassers.length || policy.bypassers.some((bypasser) => bypasser.userId === actorId);
|
const canBypass = !policy.bypassers.length || policy.bypassers.some((bypasser) => bypasser.userId === actorId);
|
||||||
const cannotBypassUnderSoftEnforcement = !(isSoftEnforcement && canBypass);
|
const cannotBypassUnderSoftEnforcement = !(isSoftEnforcement && canBypass);
|
||||||
|
|
||||||
|
// Calculate break glass attempt before sequence checks
|
||||||
|
const isBreakGlassApprovalAttempt =
|
||||||
|
policy.enforcementLevel === EnforcementLevel.Soft &&
|
||||||
|
actorId === accessApprovalRequest.requestedByUserId &&
|
||||||
|
status === ApprovalStatus.APPROVED;
|
||||||
|
|
||||||
const isApprover = policy.approvers.find((approver) => approver.userId === actorId);
|
const isApprover = policy.approvers.find((approver) => approver.userId === actorId);
|
||||||
// If user is (not an approver OR cant self approve) AND can't bypass policy
|
// If user is (not an approver OR cant self approve) AND can't bypass policy
|
||||||
if ((!isApprover || (!policy.allowedSelfApprovals && isSelfApproval)) && cannotBypassUnderSoftEnforcement) {
|
if ((!isApprover || (!policy.allowedSelfApprovals && isSelfApproval)) && cannotBypassUnderSoftEnforcement) {
|
||||||
@@ -409,15 +415,14 @@ export const accessApprovalRequestServiceFactory = ({
|
|||||||
const isApproverOfTheSequence = policy.approvers.find(
|
const isApproverOfTheSequence = policy.approvers.find(
|
||||||
(el) => el.sequence === presentSequence.step && el.userId === actorId
|
(el) => el.sequence === presentSequence.step && el.userId === actorId
|
||||||
);
|
);
|
||||||
if (!isApproverOfTheSequence) throw new BadRequestError({ message: "You are not reviewer in this step" });
|
|
||||||
|
// Only throw if actor is not the approver and not bypassing
|
||||||
|
if (!isApproverOfTheSequence && !isBreakGlassApprovalAttempt) {
|
||||||
|
throw new BadRequestError({ message: "You are not a reviewer in this step" });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const reviewStatus = await accessApprovalRequestReviewerDAL.transaction(async (tx) => {
|
const reviewStatus = await accessApprovalRequestReviewerDAL.transaction(async (tx) => {
|
||||||
const isBreakGlassApprovalAttempt =
|
|
||||||
policy.enforcementLevel === EnforcementLevel.Soft &&
|
|
||||||
actorId === accessApprovalRequest.requestedByUserId &&
|
|
||||||
status === ApprovalStatus.APPROVED;
|
|
||||||
|
|
||||||
let reviewForThisActorProcessing: {
|
let reviewForThisActorProcessing: {
|
||||||
id: string;
|
id: string;
|
||||||
requestId: string;
|
requestId: string;
|
||||||
|
|||||||
+28
-32
@@ -439,39 +439,35 @@ export const ReviewAccessRequestModal = ({
|
|||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
{isSoftEnforcement &&
|
{isSoftEnforcement && request.isRequestedByCurrentUser && canBypass && (
|
||||||
request.isRequestedByCurrentUser &&
|
<div className="mt-2 flex flex-col space-y-2">
|
||||||
!(request.isApprover && request.isSelfApproveAllowed) &&
|
<Checkbox
|
||||||
canBypass && (
|
onCheckedChange={(checked) => setBypassApproval(checked === true)}
|
||||||
<div className="mt-2 flex flex-col space-y-2">
|
isChecked={bypassApproval}
|
||||||
<Checkbox
|
id="byPassApproval"
|
||||||
onCheckedChange={(checked) => setBypassApproval(checked === true)}
|
className={twMerge("mr-2", bypassApproval ? "border-red/30 bg-red/10" : "")}
|
||||||
isChecked={bypassApproval}
|
>
|
||||||
id="byPassApproval"
|
<span className="text-xs text-red">
|
||||||
className={twMerge("mr-2", bypassApproval ? "border-red/30 bg-red/10" : "")}
|
Approve without waiting for requirements to be met (bypass policy protection)
|
||||||
|
</span>
|
||||||
|
</Checkbox>
|
||||||
|
{bypassApproval && (
|
||||||
|
<FormControl
|
||||||
|
label="Reason for bypass"
|
||||||
|
className="mt-2"
|
||||||
|
isRequired
|
||||||
|
tooltipText="Enter a reason for bypassing the policy"
|
||||||
>
|
>
|
||||||
<span className="text-xs text-red">
|
<Input
|
||||||
Approve without waiting for requirements to be met (bypass policy
|
value={bypassReason}
|
||||||
protection)
|
onChange={(e) => setBypassReason(e.currentTarget.value)}
|
||||||
</span>
|
placeholder="Enter reason for bypass (min 10 chars)"
|
||||||
</Checkbox>
|
leftIcon={<FontAwesomeIcon icon={faTriangleExclamation} />}
|
||||||
{bypassApproval && (
|
/>
|
||||||
<FormControl
|
</FormControl>
|
||||||
label="Reason for bypass"
|
)}
|
||||||
className="mt-2"
|
</div>
|
||||||
isRequired
|
)}
|
||||||
tooltipText="Enter a reason for bypassing the secret change policy"
|
|
||||||
>
|
|
||||||
<Input
|
|
||||||
value={bypassReason}
|
|
||||||
onChange={(e) => setBypassReason(e.currentTarget.value)}
|
|
||||||
placeholder="Enter reason for bypass (min 10 chars)"
|
|
||||||
leftIcon={<FontAwesomeIcon icon={faTriangleExclamation} />}
|
|
||||||
/>
|
|
||||||
</FormControl>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
<div className="space-x-2">
|
<div className="space-x-2">
|
||||||
<Button
|
<Button
|
||||||
isLoading={isLoading === "approved"}
|
isLoading={isLoading === "approved"}
|
||||||
|
|||||||
Reference in New Issue
Block a user