feat(access-policies): Allow policy limits on access request times

This commit is contained in:
x032205
2025-08-07 23:15:48 -04:00
parent efa043c3d2
commit 5c9243d691
15 changed files with 166 additions and 23 deletions
@@ -26,7 +26,8 @@ export const useCreateAccessApprovalPolicy = () => {
secretPath,
enforcementLevel,
allowedSelfApprovals,
approvalsRequired
approvalsRequired,
maxTimePeriod
}) => {
const { data } = await apiRequest.post("/api/v1/access-approvals/policies", {
environments,
@@ -38,7 +39,8 @@ export const useCreateAccessApprovalPolicy = () => {
name,
enforcementLevel,
allowedSelfApprovals,
approvalsRequired
approvalsRequired,
maxTimePeriod
});
return data;
},
@@ -64,7 +66,8 @@ export const useUpdateAccessApprovalPolicy = () => {
enforcementLevel,
allowedSelfApprovals,
approvalsRequired,
environments
environments,
maxTimePeriod
}) => {
const { data } = await apiRequest.patch(`/api/v1/access-approvals/policies/${id}`, {
approvals,
@@ -75,7 +78,8 @@ export const useUpdateAccessApprovalPolicy = () => {
enforcementLevel,
allowedSelfApprovals,
approvalsRequired,
environments
environments,
maxTimePeriod
});
return data;
},
@@ -18,6 +18,7 @@ export type TAccessApprovalPolicy = {
approvers?: Approver[];
bypassers?: Bypasser[];
allowedSelfApprovals: boolean;
maxTimePeriod?: string;
};
export enum ApproverType {
@@ -93,6 +94,7 @@ export type TAccessApprovalRequest = {
enforcementLevel: EnforcementLevel;
deletedAt: Date | null;
allowedSelfApprovals: boolean;
maxTimePeriod: string | null;
};
reviewers: {
@@ -173,6 +175,7 @@ export type TCreateAccessPolicyDTO = {
enforcementLevel?: EnforcementLevel;
allowedSelfApprovals: boolean;
approvalsRequired?: { numberOfApprovals: number; stepNumber: number }[];
maxTimePeriod?: string;
};
export type TUpdateAccessPolicyDTO = {
@@ -188,6 +191,7 @@ export type TUpdateAccessPolicyDTO = {
// for invalidating list
projectSlug: string;
approvalsRequired?: { numberOfApprovals: number; stepNumber: number }[];
maxTimePeriod?: string;
};
export type TDeleteSecretPolicyDTO = {
@@ -220,6 +220,24 @@ export const SpecificPrivilegeSecretForm = ({
return;
}
const policy = policies.find(
(p) =>
p.environments.find((e) => e.slug === selectedEnvironment) && p.secretPath === secretPath
);
if (
policy?.maxTimePeriod &&
(!data.temporaryAccess.isTemporary ||
ms(data.temporaryAccess.temporaryRange) > ms(policy.maxTimePeriod))
) {
createNotification({
type: "error",
text: `Requested access time range is limited to ${policy.maxTimePeriod} by policy`,
title: "Error"
});
return;
}
const actions = [
{ action: ProjectPermissionActions.Read, allowed: data.read },
{ action: ProjectPermissionActions.Create, allowed: data.create },
@@ -91,7 +91,8 @@ const formSchema = z
})
.array()
.default([])
.optional()
.optional(),
maxTimePeriod: z.string().trim().optional()
})
.superRefine((data, ctx) => {
if (data.policyType === PolicyType.ChangePolicy) {
@@ -440,6 +441,25 @@ const Form = ({
</FormControl>
)}
/>
{isAccessPolicyType && (
<Controller
control={control}
name="maxTimePeriod"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Max. Time Period"
tooltipText="The maximum amount of time someone can request access for. Ex: 1h, 3w, 30d"
isError={Boolean(error)}
errorText={error?.message}
className="flex-shrink"
>
<Input {...field} value={field.value} placeholder="permanent" />
</FormControl>
)}
/>
)}
{!isAccessPolicyType && (
<Controller
control={control}
@@ -27,7 +27,10 @@ import { twMerge } from "tailwind-merge";
import { UpgradePlanModal } from "@app/components/license/UpgradePlanModal";
import { createNotification } from "@app/components/notifications";
import { ProjectPermissionCan } from "@app/components/permissions";
import { hasSecretReference, SecretReferenceTree } from "@app/components/secrets/SecretReferenceDetails";
import {
hasSecretReference,
SecretReferenceTree
} from "@app/components/secrets/SecretReferenceDetails";
import {
Button,
Drawer,
@@ -49,8 +52,12 @@ import {
Tooltip
} from "@app/components/v2";
import { InfisicalSecretInput } from "@app/components/v2/InfisicalSecretInput";
import { ProjectPermissionActions, ProjectPermissionSub, useProjectPermission, useWorkspace } from "@app/context";
import {
ProjectPermissionActions,
ProjectPermissionSub,
useProjectPermission,
useWorkspace
} from "@app/context";
import { ProjectPermissionSecretActions } from "@app/context/ProjectPermissionContext/types";
import { getProjectBaseURL } from "@app/helpers/project";
import { usePopUp } from "@app/hooks";