mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-07 14:27:30 +00:00
Fix: Validate approvers access
This commit is contained in:
@@ -3,22 +3,26 @@ import { ForbiddenError } from "@casl/ability";
|
|||||||
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service";
|
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service";
|
||||||
import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission";
|
import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission";
|
||||||
import { BadRequestError } from "@app/lib/errors";
|
import { BadRequestError } from "@app/lib/errors";
|
||||||
|
import { TProjectDALFactory } from "@app/services/project/project-dal";
|
||||||
import { TProjectEnvDALFactory } from "@app/services/project-env/project-env-dal";
|
import { TProjectEnvDALFactory } from "@app/services/project-env/project-env-dal";
|
||||||
import { TProjectMembershipDALFactory } from "@app/services/project-membership/project-membership-dal";
|
import { TProjectMembershipDALFactory } from "@app/services/project-membership/project-membership-dal";
|
||||||
|
|
||||||
import { TAccessApprovalPolicyApproverDALFactory } from "./access-approval-policy-approver-dal";
|
import { TAccessApprovalPolicyApproverDALFactory } from "./access-approval-policy-approver-dal";
|
||||||
import { TAccessApprovalPolicyDALFactory } from "./access-approval-policy-dal";
|
import { TAccessApprovalPolicyDALFactory } from "./access-approval-policy-dal";
|
||||||
|
import { verifyApprovers } from "./access-approval-policy-fns";
|
||||||
import {
|
import {
|
||||||
TCreateAccessApprovalPolicy,
|
TCreateAccessApprovalPolicy,
|
||||||
TDeleteAccessApprovalPolicy,
|
TDeleteAccessApprovalPolicy,
|
||||||
|
TGetAccessPolicyCountByEnvironmentDTO,
|
||||||
TListAccessApprovalPoliciesDTO,
|
TListAccessApprovalPoliciesDTO,
|
||||||
TUpdateAccessApprovalPolicy
|
TUpdateAccessApprovalPolicy
|
||||||
} from "./access-approval-policy-types";
|
} from "./access-approval-policy-types";
|
||||||
|
|
||||||
type TSecretApprovalPolicyServiceFactoryDep = {
|
type TSecretApprovalPolicyServiceFactoryDep = {
|
||||||
|
projectDAL: TProjectDALFactory;
|
||||||
permissionService: Pick<TPermissionServiceFactory, "getProjectPermission">;
|
permissionService: Pick<TPermissionServiceFactory, "getProjectPermission">;
|
||||||
accessApprovalPolicyDAL: TAccessApprovalPolicyDALFactory;
|
accessApprovalPolicyDAL: TAccessApprovalPolicyDALFactory;
|
||||||
projectEnvDAL: Pick<TProjectEnvDALFactory, "findOne">;
|
projectEnvDAL: Pick<TProjectEnvDALFactory, "find" | "findOne">;
|
||||||
accessApprovalPolicyApproverDAL: TAccessApprovalPolicyApproverDALFactory;
|
accessApprovalPolicyApproverDAL: TAccessApprovalPolicyApproverDALFactory;
|
||||||
projectMembershipDAL: Pick<TProjectMembershipDALFactory, "find">;
|
projectMembershipDAL: Pick<TProjectMembershipDALFactory, "find">;
|
||||||
};
|
};
|
||||||
@@ -30,6 +34,7 @@ export const accessApprovalPolicyServiceFactory = ({
|
|||||||
accessApprovalPolicyApproverDAL,
|
accessApprovalPolicyApproverDAL,
|
||||||
permissionService,
|
permissionService,
|
||||||
projectEnvDAL,
|
projectEnvDAL,
|
||||||
|
projectDAL,
|
||||||
projectMembershipDAL
|
projectMembershipDAL
|
||||||
}: TSecretApprovalPolicyServiceFactoryDep) => {
|
}: TSecretApprovalPolicyServiceFactoryDep) => {
|
||||||
const createAccessApprovalPolicy = async ({
|
const createAccessApprovalPolicy = async ({
|
||||||
@@ -37,19 +42,24 @@ export const accessApprovalPolicyServiceFactory = ({
|
|||||||
actor,
|
actor,
|
||||||
actorId,
|
actorId,
|
||||||
actorOrgId,
|
actorOrgId,
|
||||||
|
secretPath,
|
||||||
actorAuthMethod,
|
actorAuthMethod,
|
||||||
approvals,
|
approvals,
|
||||||
approvers,
|
approvers,
|
||||||
projectId,
|
projectSlug,
|
||||||
environment
|
environment
|
||||||
}: TCreateAccessApprovalPolicy) => {
|
}: TCreateAccessApprovalPolicy) => {
|
||||||
|
const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId);
|
||||||
|
if (!project) throw new BadRequestError({ message: "Project not found" });
|
||||||
|
|
||||||
if (approvals > approvers.length)
|
if (approvals > approvers.length)
|
||||||
throw new BadRequestError({ message: "Approvals cannot be greater than approvers" });
|
throw new BadRequestError({ message: "Approvals cannot be greater than approvers" });
|
||||||
|
if (!secretPath) throw new BadRequestError({ message: "Secret path is required" });
|
||||||
|
|
||||||
const { permission } = await permissionService.getProjectPermission(
|
const { permission } = await permissionService.getProjectPermission(
|
||||||
actor,
|
actor,
|
||||||
actorId,
|
actorId,
|
||||||
projectId,
|
project.id,
|
||||||
actorAuthMethod,
|
actorAuthMethod,
|
||||||
actorOrgId
|
actorOrgId
|
||||||
);
|
);
|
||||||
@@ -57,13 +67,24 @@ export const accessApprovalPolicyServiceFactory = ({
|
|||||||
ProjectPermissionActions.Create,
|
ProjectPermissionActions.Create,
|
||||||
ProjectPermissionSub.SecretApproval
|
ProjectPermissionSub.SecretApproval
|
||||||
);
|
);
|
||||||
const env = await projectEnvDAL.findOne({ slug: environment, projectId });
|
const env = await projectEnvDAL.findOne({ slug: environment, projectId: project.id });
|
||||||
if (!env) throw new BadRequestError({ message: "Environment not found" });
|
if (!env) throw new BadRequestError({ message: "Environment not found" });
|
||||||
|
|
||||||
const secretApprovers = await projectMembershipDAL.find({
|
const secretApprovers = await projectMembershipDAL.find({
|
||||||
projectId,
|
projectId: project.id,
|
||||||
$in: { id: approvers }
|
$in: { id: approvers }
|
||||||
});
|
});
|
||||||
|
|
||||||
|
await verifyApprovers({
|
||||||
|
projectId: project.id,
|
||||||
|
orgId: actorOrgId,
|
||||||
|
envSlug: environment,
|
||||||
|
secretPath,
|
||||||
|
actorAuthMethod,
|
||||||
|
permissionService,
|
||||||
|
approverProjectMemberships: secretApprovers
|
||||||
|
});
|
||||||
|
|
||||||
if (secretApprovers.length !== approvers.length) {
|
if (secretApprovers.length !== approvers.length) {
|
||||||
throw new BadRequestError({ message: "Approver not found in project" });
|
throw new BadRequestError({ message: "Approver not found in project" });
|
||||||
}
|
}
|
||||||
@@ -73,6 +94,7 @@ export const accessApprovalPolicyServiceFactory = ({
|
|||||||
{
|
{
|
||||||
envId: env.id,
|
envId: env.id,
|
||||||
approvals,
|
approvals,
|
||||||
|
secretPath,
|
||||||
name
|
name
|
||||||
},
|
},
|
||||||
tx
|
tx
|
||||||
@@ -86,7 +108,7 @@ export const accessApprovalPolicyServiceFactory = ({
|
|||||||
);
|
);
|
||||||
return doc;
|
return doc;
|
||||||
});
|
});
|
||||||
return { ...accessApproval, environment: env, projectId };
|
return { ...accessApproval, environment: env, projectId: project.id };
|
||||||
};
|
};
|
||||||
|
|
||||||
const getAccessApprovalPolicyByProjectId = async ({
|
const getAccessApprovalPolicyByProjectId = async ({
|
||||||
@@ -94,24 +116,29 @@ export const accessApprovalPolicyServiceFactory = ({
|
|||||||
actor,
|
actor,
|
||||||
actorOrgId,
|
actorOrgId,
|
||||||
actorAuthMethod,
|
actorAuthMethod,
|
||||||
projectId
|
projectSlug
|
||||||
}: TListAccessApprovalPoliciesDTO) => {
|
}: TListAccessApprovalPoliciesDTO) => {
|
||||||
const { permission } = await permissionService.getProjectPermission(
|
const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId);
|
||||||
|
if (!project) throw new BadRequestError({ message: "Project not found" });
|
||||||
|
|
||||||
|
// Anyone in the project should be able to get the policies.
|
||||||
|
/* const { permission } = */ await permissionService.getProjectPermission(
|
||||||
actor,
|
actor,
|
||||||
actorId,
|
actorId,
|
||||||
projectId,
|
project.id,
|
||||||
actorAuthMethod,
|
actorAuthMethod,
|
||||||
actorOrgId
|
actorOrgId
|
||||||
);
|
);
|
||||||
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SecretApproval);
|
// ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SecretApproval);
|
||||||
|
|
||||||
const accessApprovalPolicies = await accessApprovalPolicyDAL.find({ projectId });
|
const accessApprovalPolicies = await accessApprovalPolicyDAL.find({ projectId: project.id });
|
||||||
return accessApprovalPolicies;
|
return accessApprovalPolicies;
|
||||||
};
|
};
|
||||||
|
|
||||||
const updateAccessApprovalPolicy = async ({
|
const updateAccessApprovalPolicy = async ({
|
||||||
policyId,
|
policyId,
|
||||||
approvers,
|
approvers,
|
||||||
|
secretPath,
|
||||||
name,
|
name,
|
||||||
actorId,
|
actorId,
|
||||||
actor,
|
actor,
|
||||||
@@ -121,7 +148,6 @@ export const accessApprovalPolicyServiceFactory = ({
|
|||||||
}: TUpdateAccessApprovalPolicy) => {
|
}: TUpdateAccessApprovalPolicy) => {
|
||||||
const accessApprovalPolicy = await accessApprovalPolicyDAL.findById(policyId);
|
const accessApprovalPolicy = await accessApprovalPolicyDAL.findById(policyId);
|
||||||
if (!accessApprovalPolicy) throw new BadRequestError({ message: "Secret approval policy not found" });
|
if (!accessApprovalPolicy) throw new BadRequestError({ message: "Secret approval policy not found" });
|
||||||
|
|
||||||
const { permission } = await permissionService.getProjectPermission(
|
const { permission } = await permissionService.getProjectPermission(
|
||||||
actor,
|
actor,
|
||||||
actorId,
|
actorId,
|
||||||
@@ -129,6 +155,7 @@ export const accessApprovalPolicyServiceFactory = ({
|
|||||||
actorAuthMethod,
|
actorAuthMethod,
|
||||||
actorOrgId
|
actorOrgId
|
||||||
);
|
);
|
||||||
|
|
||||||
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.SecretApproval);
|
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.SecretApproval);
|
||||||
|
|
||||||
const updatedPolicy = await accessApprovalPolicyDAL.transaction(async (tx) => {
|
const updatedPolicy = await accessApprovalPolicyDAL.transaction(async (tx) => {
|
||||||
@@ -136,6 +163,7 @@ export const accessApprovalPolicyServiceFactory = ({
|
|||||||
accessApprovalPolicy.id,
|
accessApprovalPolicy.id,
|
||||||
{
|
{
|
||||||
approvals,
|
approvals,
|
||||||
|
secretPath,
|
||||||
name
|
name
|
||||||
},
|
},
|
||||||
tx
|
tx
|
||||||
@@ -149,6 +177,17 @@ export const accessApprovalPolicyServiceFactory = ({
|
|||||||
},
|
},
|
||||||
{ tx }
|
{ tx }
|
||||||
);
|
);
|
||||||
|
|
||||||
|
await verifyApprovers({
|
||||||
|
projectId: accessApprovalPolicy.projectId,
|
||||||
|
orgId: actorOrgId,
|
||||||
|
envSlug: accessApprovalPolicy.environment.slug,
|
||||||
|
secretPath: doc.secretPath!,
|
||||||
|
actorAuthMethod,
|
||||||
|
permissionService,
|
||||||
|
approverProjectMemberships: secretApprovers
|
||||||
|
});
|
||||||
|
|
||||||
if (secretApprovers.length !== approvers.length)
|
if (secretApprovers.length !== approvers.length)
|
||||||
throw new BadRequestError({ message: "Approver not found in project" });
|
throw new BadRequestError({ message: "Approver not found in project" });
|
||||||
if (doc.approvals > secretApprovers.length)
|
if (doc.approvals > secretApprovers.length)
|
||||||
@@ -197,7 +236,31 @@ export const accessApprovalPolicyServiceFactory = ({
|
|||||||
return policy;
|
return policy;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getAccessPolicyCountByEnvSlug = async ({
|
||||||
|
actor,
|
||||||
|
actorOrgId,
|
||||||
|
actorAuthMethod,
|
||||||
|
projectSlug,
|
||||||
|
actorId,
|
||||||
|
envSlug
|
||||||
|
}: TGetAccessPolicyCountByEnvironmentDTO) => {
|
||||||
|
const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId);
|
||||||
|
|
||||||
|
if (!project) throw new BadRequestError({ message: "Project not found" });
|
||||||
|
|
||||||
|
await permissionService.getProjectPermission(actor, actorId, project.id, actorAuthMethod, actorOrgId);
|
||||||
|
|
||||||
|
const environment = await projectEnvDAL.findOne({ projectId: project.id, slug: envSlug });
|
||||||
|
if (!environment) throw new BadRequestError({ message: "Environment not found" });
|
||||||
|
|
||||||
|
const policies = await accessApprovalPolicyDAL.find({ envId: environment.id, projectId: project.id });
|
||||||
|
if (!policies) throw new BadRequestError({ message: "No policies found" });
|
||||||
|
|
||||||
|
return { policyCount: policies.length };
|
||||||
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
getAccessPolicyCountByEnvSlug,
|
||||||
createAccessApprovalPolicy,
|
createAccessApprovalPolicy,
|
||||||
deleteAccessApprovalPolicy,
|
deleteAccessApprovalPolicy,
|
||||||
updateAccessApprovalPolicy,
|
updateAccessApprovalPolicy,
|
||||||
|
|||||||
Reference in New Issue
Block a user