misc: review comments

This commit is contained in:
Sheen Capadngan
2025-03-27 12:17:36 +08:00
parent c376add0fa
commit 956d0f6c5d
30 changed files with 346 additions and 312 deletions

View File

@@ -3,7 +3,7 @@ import slugify from "@sindresorhus/slugify";
import { OrgMembershipRole, TOrgRoles } from "@app/db/schemas";
import { TOidcConfigDALFactory } from "@app/ee/services/oidc/oidc-config-dal";
import { BadRequestError, ForbiddenRequestError, NotFoundError, UnauthorizedError } from "@app/lib/errors";
import { BadRequestError, NotFoundError, PermissionBoundaryError, UnauthorizedError } from "@app/lib/errors";
import { alphaNumericNanoId } from "@app/lib/nanoid";
import { TGroupProjectDALFactory } from "@app/services/group-project/group-project-dal";
import { TOrgDALFactory } from "@app/services/org/org-dal";
@@ -90,19 +90,18 @@ export const groupServiceFactory = ({
const permissionBoundary = validatePrivilegeChangeOperation(
membership.shouldUseNewPrivilegeSystem,
OrgPermissionGroupActions.ManagePrivileges,
OrgPermissionGroupActions.GrantPrivileges,
OrgPermissionSubjects.Groups,
permission,
rolePermission
);
if (!permissionBoundary.isValid)
throw new ForbiddenRequestError({
name: "PermissionBoundaryError",
throw new PermissionBoundaryError({
message: constructPermissionErrorMessage(
"Failed to create group",
membership.shouldUseNewPrivilegeSystem,
OrgPermissionGroupActions.ManagePrivileges,
OrgPermissionGroupActions.GrantPrivileges,
OrgPermissionSubjects.Groups
),
details: { missingPermissions: permissionBoundary.missingPermissions }
@@ -176,18 +175,17 @@ export const groupServiceFactory = ({
const isCustomRole = Boolean(customOrgRole);
const permissionBoundary = validatePrivilegeChangeOperation(
membership.shouldUseNewPrivilegeSystem,
OrgPermissionGroupActions.ManagePrivileges,
OrgPermissionGroupActions.GrantPrivileges,
OrgPermissionSubjects.Groups,
permission,
rolePermission
);
if (!permissionBoundary.isValid)
throw new ForbiddenRequestError({
name: "PermissionBoundaryError",
throw new PermissionBoundaryError({
message: constructPermissionErrorMessage(
"Failed to update group",
membership.shouldUseNewPrivilegeSystem,
OrgPermissionGroupActions.ManagePrivileges,
OrgPermissionGroupActions.GrantPrivileges,
OrgPermissionSubjects.Groups
),
details: { missingPermissions: permissionBoundary.missingPermissions }
@@ -371,8 +369,7 @@ export const groupServiceFactory = ({
);
if (!permissionBoundary.isValid)
throw new ForbiddenRequestError({
name: "PermissionBoundaryError",
throw new PermissionBoundaryError({
message: constructPermissionErrorMessage(
"Failed to add user to more privileged group",
membership.shouldUseNewPrivilegeSystem,
@@ -453,8 +450,7 @@ export const groupServiceFactory = ({
groupRolePermission
);
if (!permissionBoundary.isValid)
throw new ForbiddenRequestError({
name: "PermissionBoundaryError",
throw new PermissionBoundaryError({
message: constructPermissionErrorMessage(
"Failed to delete user from more privileged group",
membership.shouldUseNewPrivilegeSystem,

View File

@@ -2,7 +2,7 @@ import { ForbiddenError, subject } from "@casl/ability";
import { packRules } from "@casl/ability/extra";
import { ActionProjectType, TableName } from "@app/db/schemas";
import { BadRequestError, ForbiddenRequestError, NotFoundError } from "@app/lib/errors";
import { BadRequestError, NotFoundError, PermissionBoundaryError } from "@app/lib/errors";
import { ms } from "@app/lib/ms";
import { unpackPermissions } from "@app/server/routes/sanitizedSchema/permission";
import { ActorType } from "@app/services/auth/auth-type";
@@ -81,18 +81,17 @@ export const identityProjectAdditionalPrivilegeV2ServiceFactory = ({
targetIdentityPermission.update(targetIdentityPermission.rules.concat(customPermission));
const permissionBoundary = validatePrivilegeChangeOperation(
membership.shouldUseNewPrivilegeSystem,
ProjectPermissionIdentityActions.ManagePrivileges,
ProjectPermissionIdentityActions.GrantPrivileges,
ProjectPermissionSub.Identity,
permission,
targetIdentityPermission
);
if (!permissionBoundary.isValid)
throw new ForbiddenRequestError({
name: "PermissionBoundaryError",
throw new PermissionBoundaryError({
message: constructPermissionErrorMessage(
"Failed to update more privileged identity",
membership.shouldUseNewPrivilegeSystem,
ProjectPermissionIdentityActions.ManagePrivileges,
ProjectPermissionIdentityActions.GrantPrivileges,
ProjectPermissionSub.Identity
),
details: { missingPermissions: permissionBoundary.missingPermissions }
@@ -178,18 +177,17 @@ export const identityProjectAdditionalPrivilegeV2ServiceFactory = ({
targetIdentityPermission.update(targetIdentityPermission.rules.concat(data.permissions || []));
const permissionBoundary = validatePrivilegeChangeOperation(
membership.shouldUseNewPrivilegeSystem,
ProjectPermissionIdentityActions.ManagePrivileges,
ProjectPermissionIdentityActions.GrantPrivileges,
ProjectPermissionSub.Identity,
permission,
targetIdentityPermission
);
if (!permissionBoundary.isValid)
throw new ForbiddenRequestError({
name: "PermissionBoundaryError",
throw new PermissionBoundaryError({
message: constructPermissionErrorMessage(
"Failed to update more privileged identity",
membership.shouldUseNewPrivilegeSystem,
ProjectPermissionIdentityActions.ManagePrivileges,
ProjectPermissionIdentityActions.GrantPrivileges,
ProjectPermissionSub.Identity
),
details: { missingPermissions: permissionBoundary.missingPermissions }
@@ -271,18 +269,17 @@ export const identityProjectAdditionalPrivilegeV2ServiceFactory = ({
});
const permissionBoundary = validatePrivilegeChangeOperation(
membership.shouldUseNewPrivilegeSystem,
ProjectPermissionIdentityActions.ManagePrivileges,
ProjectPermissionIdentityActions.GrantPrivileges,
ProjectPermissionSub.Identity,
permission,
identityRolePermission
);
if (!permissionBoundary.isValid)
throw new ForbiddenRequestError({
name: "PermissionBoundaryError",
throw new PermissionBoundaryError({
message: constructPermissionErrorMessage(
"Failed to update more privileged identity",
membership.shouldUseNewPrivilegeSystem,
ProjectPermissionIdentityActions.ManagePrivileges,
ProjectPermissionIdentityActions.GrantPrivileges,
ProjectPermissionSub.Identity
),
details: { missingPermissions: permissionBoundary.missingPermissions }

View File

@@ -2,7 +2,7 @@ import { ForbiddenError, MongoAbility, RawRuleOf, subject } from "@casl/ability"
import { PackRule, packRules, unpackRules } from "@casl/ability/extra";
import { ActionProjectType } from "@app/db/schemas";
import { BadRequestError, ForbiddenRequestError, NotFoundError } from "@app/lib/errors";
import { BadRequestError, NotFoundError, PermissionBoundaryError } from "@app/lib/errors";
import { ms } from "@app/lib/ms";
import { UnpackedPermissionSchema } from "@app/server/routes/sanitizedSchema/permission";
import { ActorType } from "@app/services/auth/auth-type";
@@ -95,18 +95,17 @@ export const identityProjectAdditionalPrivilegeServiceFactory = ({
targetIdentityPermission.update(targetIdentityPermission.rules.concat(customPermission));
const permissionBoundary = validatePrivilegeChangeOperation(
membership.shouldUseNewPrivilegeSystem,
ProjectPermissionIdentityActions.ManagePrivileges,
ProjectPermissionIdentityActions.GrantPrivileges,
ProjectPermissionSub.Identity,
permission,
targetIdentityPermission
);
if (!permissionBoundary.isValid)
throw new ForbiddenRequestError({
name: "PermissionBoundaryError",
throw new PermissionBoundaryError({
message: constructPermissionErrorMessage(
"Failed to update more privileged identity",
membership.shouldUseNewPrivilegeSystem,
ProjectPermissionIdentityActions.ManagePrivileges,
ProjectPermissionIdentityActions.GrantPrivileges,
ProjectPermissionSub.Identity
),
details: { missingPermissions: permissionBoundary.missingPermissions }
@@ -194,18 +193,17 @@ export const identityProjectAdditionalPrivilegeServiceFactory = ({
targetIdentityPermission.update(targetIdentityPermission.rules.concat(data.permissions || []));
const permissionBoundary = validatePrivilegeChangeOperation(
membership.shouldUseNewPrivilegeSystem,
ProjectPermissionIdentityActions.ManagePrivileges,
ProjectPermissionIdentityActions.GrantPrivileges,
ProjectPermissionSub.Identity,
permission,
targetIdentityPermission
);
if (!permissionBoundary.isValid)
throw new ForbiddenRequestError({
name: "PermissionBoundaryError",
throw new PermissionBoundaryError({
message: constructPermissionErrorMessage(
"Failed to update more privileged identity",
membership.shouldUseNewPrivilegeSystem,
ProjectPermissionIdentityActions.ManagePrivileges,
ProjectPermissionIdentityActions.GrantPrivileges,
ProjectPermissionSub.Identity
),
details: { missingPermissions: permissionBoundary.missingPermissions }
@@ -305,18 +303,17 @@ export const identityProjectAdditionalPrivilegeServiceFactory = ({
});
const permissionBoundary = validatePrivilegeChangeOperation(
membership.shouldUseNewPrivilegeSystem,
ProjectPermissionIdentityActions.ManagePrivileges,
ProjectPermissionIdentityActions.GrantPrivileges,
ProjectPermissionSub.Identity,
permission,
identityRolePermission
);
if (!permissionBoundary.isValid)
throw new ForbiddenRequestError({
name: "PermissionBoundaryError",
throw new PermissionBoundaryError({
message: constructPermissionErrorMessage(
"Failed to edit more privileged identity",
membership.shouldUseNewPrivilegeSystem,
ProjectPermissionIdentityActions.ManagePrivileges,
ProjectPermissionIdentityActions.GrantPrivileges,
ProjectPermissionSub.Identity
),
details: { missingPermissions: permissionBoundary.missingPermissions }

View File

@@ -49,7 +49,7 @@ export enum OrgPermissionIdentityActions {
Create = "create",
Edit = "edit",
Delete = "delete",
ManagePrivileges = "manage-privileges",
GrantPrivileges = "grant-privileges",
RevokeAuth = "revoke-auth",
CreateToken = "create-token",
GetToken = "get-token",
@@ -61,7 +61,7 @@ export enum OrgPermissionGroupActions {
Create = "create",
Edit = "edit",
Delete = "delete",
ManagePrivileges = "manage-privileges",
GrantPrivileges = "grant-privileges",
AddMembers = "add-members",
RemoveMembers = "remove-members"
}
@@ -282,7 +282,7 @@ const buildAdminPermission = () => {
can(OrgPermissionGroupActions.Create, OrgPermissionSubjects.Groups);
can(OrgPermissionGroupActions.Edit, OrgPermissionSubjects.Groups);
can(OrgPermissionGroupActions.Delete, OrgPermissionSubjects.Groups);
can(OrgPermissionGroupActions.ManagePrivileges, OrgPermissionSubjects.Groups);
can(OrgPermissionGroupActions.GrantPrivileges, OrgPermissionSubjects.Groups);
can(OrgPermissionGroupActions.AddMembers, OrgPermissionSubjects.Groups);
can(OrgPermissionGroupActions.RemoveMembers, OrgPermissionSubjects.Groups);
@@ -295,7 +295,7 @@ const buildAdminPermission = () => {
can(OrgPermissionIdentityActions.Create, OrgPermissionSubjects.Identity);
can(OrgPermissionIdentityActions.Edit, OrgPermissionSubjects.Identity);
can(OrgPermissionIdentityActions.Delete, OrgPermissionSubjects.Identity);
can(OrgPermissionIdentityActions.ManagePrivileges, OrgPermissionSubjects.Identity);
can(OrgPermissionIdentityActions.GrantPrivileges, OrgPermissionSubjects.Identity);
can(OrgPermissionIdentityActions.RevokeAuth, OrgPermissionSubjects.Identity);
can(OrgPermissionIdentityActions.CreateToken, OrgPermissionSubjects.Identity);
can(OrgPermissionIdentityActions.GetToken, OrgPermissionSubjects.Identity);

View File

@@ -48,7 +48,7 @@ export enum ProjectPermissionIdentityActions {
Create = "create",
Edit = "edit",
Delete = "delete",
ManagePrivileges = "manage-privileges"
GrantPrivileges = "grant-privileges"
}
export enum ProjectPermissionMemberActions {
@@ -56,7 +56,7 @@ export enum ProjectPermissionMemberActions {
Create = "create",
Edit = "edit",
Delete = "delete",
ManagePrivileges = "manage-privileges"
GrantPrivileges = "grant-privileges"
}
export enum ProjectPermissionGroupActions {
@@ -64,7 +64,7 @@ export enum ProjectPermissionGroupActions {
Create = "create",
Edit = "edit",
Delete = "delete",
ManagePrivileges = "manage-privileges"
GrantPrivileges = "grant-privileges"
}
export enum ProjectPermissionSecretSyncActions {
@@ -590,7 +590,7 @@ const buildAdminPermissionRules = () => {
ProjectPermissionMemberActions.Edit,
ProjectPermissionMemberActions.Delete,
ProjectPermissionMemberActions.Read,
ProjectPermissionMemberActions.ManagePrivileges
ProjectPermissionMemberActions.GrantPrivileges
],
ProjectPermissionSub.Member
);
@@ -601,7 +601,7 @@ const buildAdminPermissionRules = () => {
ProjectPermissionGroupActions.Edit,
ProjectPermissionGroupActions.Delete,
ProjectPermissionGroupActions.Read,
ProjectPermissionGroupActions.ManagePrivileges
ProjectPermissionGroupActions.GrantPrivileges
],
ProjectPermissionSub.Groups
);
@@ -612,7 +612,7 @@ const buildAdminPermissionRules = () => {
ProjectPermissionIdentityActions.Edit,
ProjectPermissionIdentityActions.Delete,
ProjectPermissionIdentityActions.Read,
ProjectPermissionIdentityActions.ManagePrivileges
ProjectPermissionIdentityActions.GrantPrivileges
],
ProjectPermissionSub.Identity
);

View File

@@ -2,7 +2,7 @@ import { ForbiddenError, MongoAbility, RawRuleOf } from "@casl/ability";
import { PackRule, packRules, unpackRules } from "@casl/ability/extra";
import { ActionProjectType, TableName } from "@app/db/schemas";
import { BadRequestError, ForbiddenRequestError, NotFoundError } from "@app/lib/errors";
import { BadRequestError, NotFoundError, PermissionBoundaryError } from "@app/lib/errors";
import { ms } from "@app/lib/ms";
import { UnpackedPermissionSchema } from "@app/server/routes/sanitizedSchema/permission";
import { ActorType } from "@app/services/auth/auth-type";
@@ -82,18 +82,17 @@ export const projectUserAdditionalPrivilegeServiceFactory = ({
targetUserPermission.update(targetUserPermission.rules.concat(customPermission));
const permissionBoundary = validatePrivilegeChangeOperation(
membership.shouldUseNewPrivilegeSystem,
ProjectPermissionMemberActions.ManagePrivileges,
ProjectPermissionMemberActions.GrantPrivileges,
ProjectPermissionSub.Member,
permission,
targetUserPermission
);
if (!permissionBoundary.isValid)
throw new ForbiddenRequestError({
name: "PermissionBoundaryError",
throw new PermissionBoundaryError({
message: constructPermissionErrorMessage(
"Failed to update more privileged user",
membership.shouldUseNewPrivilegeSystem,
ProjectPermissionMemberActions.ManagePrivileges,
ProjectPermissionMemberActions.GrantPrivileges,
ProjectPermissionSub.Member
),
details: { missingPermissions: permissionBoundary.missingPermissions }
@@ -184,18 +183,17 @@ export const projectUserAdditionalPrivilegeServiceFactory = ({
targetUserPermission.update(targetUserPermission.rules.concat(dto.permissions || []));
const permissionBoundary = validatePrivilegeChangeOperation(
membership.shouldUseNewPrivilegeSystem,
ProjectPermissionMemberActions.ManagePrivileges,
ProjectPermissionMemberActions.GrantPrivileges,
ProjectPermissionSub.Member,
permission,
targetUserPermission
);
if (!permissionBoundary.isValid)
throw new ForbiddenRequestError({
name: "PermissionBoundaryError",
throw new PermissionBoundaryError({
message: constructPermissionErrorMessage(
"Failed to update more privileged user",
membership.shouldUseNewPrivilegeSystem,
ProjectPermissionMemberActions.ManagePrivileges,
ProjectPermissionMemberActions.GrantPrivileges,
ProjectPermissionSub.Member
),
details: { missingPermissions: permissionBoundary.missingPermissions }

View File

@@ -68,6 +68,23 @@ export class ForbiddenRequestError extends Error {
}
}
export class PermissionBoundaryError extends ForbiddenRequestError {
constructor({
message,
name,
error,
details
}: {
message?: string;
name?: string;
error?: unknown;
details?: unknown;
}) {
super({ message, name, error, details });
this.name = "PermissionBoundaryError";
}
}
export class BadRequestError extends Error {
name: string;

View File

@@ -13,6 +13,7 @@ import {
InternalServerError,
NotFoundError,
OidcAuthError,
PermissionBoundaryError,
RateLimitError,
ScimRequestError,
UnauthorizedError
@@ -117,7 +118,7 @@ export const fastifyErrHandler = fastifyPlugin(async (server: FastifyZodProvider
conditions: el.conditions
}))
});
} else if (error instanceof ForbiddenRequestError) {
} else if (error instanceof ForbiddenRequestError || error instanceof PermissionBoundaryError) {
void res.status(HttpStatusCodes.Forbidden).send({
reqId: req.id,
statusCode: HttpStatusCodes.Forbidden,

View File

@@ -9,7 +9,7 @@ import { TPermissionServiceFactory } from "@app/ee/services/permission/permissio
import { ProjectPermissionGroupActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission";
import { decryptAsymmetric, encryptAsymmetric } from "@app/lib/crypto";
import { infisicalSymmetricDecrypt } from "@app/lib/crypto/encryption";
import { BadRequestError, ForbiddenRequestError, NotFoundError } from "@app/lib/errors";
import { BadRequestError, NotFoundError, PermissionBoundaryError } from "@app/lib/errors";
import { groupBy } from "@app/lib/fn";
import { ms } from "@app/lib/ms";
import { isUuidV4 } from "@app/lib/validator";
@@ -107,18 +107,17 @@ export const groupProjectServiceFactory = ({
const permissionBoundary = validatePrivilegeChangeOperation(
membership.shouldUseNewPrivilegeSystem,
ProjectPermissionGroupActions.ManagePrivileges,
ProjectPermissionGroupActions.GrantPrivileges,
ProjectPermissionSub.Groups,
permission,
rolePermission
);
if (!permissionBoundary.isValid)
throw new ForbiddenRequestError({
name: "PermissionBoundaryError",
throw new PermissionBoundaryError({
message: constructPermissionErrorMessage(
"Failed to assign group to role",
membership.shouldUseNewPrivilegeSystem,
ProjectPermissionGroupActions.ManagePrivileges,
ProjectPermissionGroupActions.GrantPrivileges,
ProjectPermissionSub.Groups
),
details: { missingPermissions: permissionBoundary.missingPermissions }
@@ -285,18 +284,17 @@ export const groupProjectServiceFactory = ({
);
const permissionBoundary = validatePrivilegeChangeOperation(
membership.shouldUseNewPrivilegeSystem,
ProjectPermissionGroupActions.ManagePrivileges,
ProjectPermissionGroupActions.GrantPrivileges,
ProjectPermissionSub.Groups,
permission,
rolePermission
);
if (!permissionBoundary.isValid)
throw new ForbiddenRequestError({
name: "PermissionBoundaryError",
throw new PermissionBoundaryError({
message: constructPermissionErrorMessage(
"Failed to assign group to role",
membership.shouldUseNewPrivilegeSystem,
ProjectPermissionGroupActions.ManagePrivileges,
ProjectPermissionGroupActions.GrantPrivileges,
ProjectPermissionSub.Groups
),
details: { missingPermissions: permissionBoundary.missingPermissions }

View File

@@ -12,7 +12,7 @@ import {
} from "@app/ee/services/permission/permission-fns";
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service";
import { getConfig } from "@app/lib/config/env";
import { BadRequestError, ForbiddenRequestError, NotFoundError, UnauthorizedError } from "@app/lib/errors";
import { BadRequestError, NotFoundError, PermissionBoundaryError, UnauthorizedError } from "@app/lib/errors";
import { extractIPDetails, isValidIpOrCidr } from "@app/lib/ip";
import { ActorType, AuthTokenType } from "../auth/auth-type";
@@ -355,8 +355,7 @@ export const identityAwsAuthServiceFactory = ({
);
if (!permissionBoundary.isValid)
throw new ForbiddenRequestError({
name: "PermissionBoundaryError",
throw new PermissionBoundaryError({
message: constructPermissionErrorMessage(
"Failed to revoke aws auth of identity with more privileged role",
membership.shouldUseNewPrivilegeSystem,

View File

@@ -10,7 +10,7 @@ import {
} from "@app/ee/services/permission/permission-fns";
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service";
import { getConfig } from "@app/lib/config/env";
import { BadRequestError, ForbiddenRequestError, NotFoundError, UnauthorizedError } from "@app/lib/errors";
import { BadRequestError, NotFoundError, PermissionBoundaryError, UnauthorizedError } from "@app/lib/errors";
import { extractIPDetails, isValidIpOrCidr } from "@app/lib/ip";
import { ActorType, AuthTokenType } from "../auth/auth-type";
@@ -327,8 +327,7 @@ export const identityAzureAuthServiceFactory = ({
rolePermission
);
if (!permissionBoundary.isValid)
throw new ForbiddenRequestError({
name: "PermissionBoundaryError",
throw new PermissionBoundaryError({
message: constructPermissionErrorMessage(
"Failed to revoke azure auth of identity with more privileged role",
membership.shouldUseNewPrivilegeSystem,

View File

@@ -10,7 +10,7 @@ import {
} from "@app/ee/services/permission/permission-fns";
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service";
import { getConfig } from "@app/lib/config/env";
import { BadRequestError, ForbiddenRequestError, NotFoundError, UnauthorizedError } from "@app/lib/errors";
import { BadRequestError, NotFoundError, PermissionBoundaryError, UnauthorizedError } from "@app/lib/errors";
import { extractIPDetails, isValidIpOrCidr } from "@app/lib/ip";
import { ActorType, AuthTokenType } from "../auth/auth-type";
@@ -373,8 +373,7 @@ export const identityGcpAuthServiceFactory = ({
rolePermission
);
if (!permissionBoundary.isValid)
throw new ForbiddenRequestError({
name: "PermissionBoundaryError",
throw new PermissionBoundaryError({
message: constructPermissionErrorMessage(
"Failed to revoke gcp auth of identity with more privileged role",
membership.shouldUseNewPrivilegeSystem,

View File

@@ -12,7 +12,13 @@ import {
} from "@app/ee/services/permission/permission-fns";
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service";
import { getConfig } from "@app/lib/config/env";
import { BadRequestError, ForbiddenRequestError, NotFoundError, UnauthorizedError } from "@app/lib/errors";
import {
BadRequestError,
ForbiddenRequestError,
NotFoundError,
PermissionBoundaryError,
UnauthorizedError
} from "@app/lib/errors";
import { extractIPDetails, isValidIpOrCidr } from "@app/lib/ip";
import { getStringValueByDot } from "@app/lib/template/dot-access";
@@ -533,8 +539,7 @@ export const identityJwtAuthServiceFactory = ({
rolePermission
);
if (!permissionBoundary.isValid)
throw new ForbiddenRequestError({
name: "PermissionBoundaryError",
throw new PermissionBoundaryError({
message: constructPermissionErrorMessage(
"Failed to revoke jwt auth of identity with more privileged role",
membership.shouldUseNewPrivilegeSystem,

View File

@@ -12,7 +12,7 @@ import {
} from "@app/ee/services/permission/permission-fns";
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service";
import { getConfig } from "@app/lib/config/env";
import { BadRequestError, ForbiddenRequestError, NotFoundError, UnauthorizedError } from "@app/lib/errors";
import { BadRequestError, NotFoundError, PermissionBoundaryError, UnauthorizedError } from "@app/lib/errors";
import { extractIPDetails, isValidIpOrCidr } from "@app/lib/ip";
import { ActorType, AuthTokenType } from "../auth/auth-type";
@@ -503,8 +503,7 @@ export const identityKubernetesAuthServiceFactory = ({
rolePermission
);
if (!permissionBoundary.isValid)
throw new ForbiddenRequestError({
name: "PermissionBoundaryError",
throw new PermissionBoundaryError({
message: constructPermissionErrorMessage(
"Failed to revoke kubernetes auth of identity with more privileged role",
membership.shouldUseNewPrivilegeSystem,

View File

@@ -13,7 +13,13 @@ import {
} from "@app/ee/services/permission/permission-fns";
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service";
import { getConfig } from "@app/lib/config/env";
import { BadRequestError, ForbiddenRequestError, NotFoundError, UnauthorizedError } from "@app/lib/errors";
import {
BadRequestError,
ForbiddenRequestError,
NotFoundError,
PermissionBoundaryError,
UnauthorizedError
} from "@app/lib/errors";
import { extractIPDetails, isValidIpOrCidr } from "@app/lib/ip";
import { getStringValueByDot } from "@app/lib/template/dot-access";
@@ -472,8 +478,7 @@ export const identityOidcAuthServiceFactory = ({
);
if (!permissionBoundary.isValid)
throw new ForbiddenRequestError({
name: "PermissionBoundaryError",
throw new PermissionBoundaryError({
message: constructPermissionErrorMessage(
"Failed to revoke oidc auth of identity with more privileged role",
membership.shouldUseNewPrivilegeSystem,

View File

@@ -7,7 +7,7 @@ import {
} from "@app/ee/services/permission/permission-fns";
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service";
import { ProjectPermissionIdentityActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission";
import { BadRequestError, ForbiddenRequestError, NotFoundError } from "@app/lib/errors";
import { BadRequestError, NotFoundError, PermissionBoundaryError } from "@app/lib/errors";
import { groupBy } from "@app/lib/fn";
import { ms } from "@app/lib/ms";
@@ -95,18 +95,17 @@ export const identityProjectServiceFactory = ({
const permissionBoundary = validatePrivilegeChangeOperation(
membership.shouldUseNewPrivilegeSystem,
ProjectPermissionIdentityActions.ManagePrivileges,
ProjectPermissionIdentityActions.GrantPrivileges,
ProjectPermissionSub.Identity,
permission,
rolePermission
);
if (!permissionBoundary.isValid)
throw new ForbiddenRequestError({
name: "PermissionBoundaryError",
throw new PermissionBoundaryError({
message: constructPermissionErrorMessage(
"Failed to assign to role",
membership.shouldUseNewPrivilegeSystem,
ProjectPermissionIdentityActions.ManagePrivileges,
ProjectPermissionIdentityActions.GrantPrivileges,
ProjectPermissionSub.Identity
),
details: { missingPermissions: permissionBoundary.missingPermissions }
@@ -202,19 +201,18 @@ export const identityProjectServiceFactory = ({
const permissionBoundary = validatePrivilegeChangeOperation(
membership.shouldUseNewPrivilegeSystem,
ProjectPermissionIdentityActions.ManagePrivileges,
ProjectPermissionIdentityActions.GrantPrivileges,
ProjectPermissionSub.Identity,
permission,
rolePermission
);
if (!permissionBoundary.isValid)
throw new ForbiddenRequestError({
name: "PermissionBoundaryError",
throw new PermissionBoundaryError({
message: constructPermissionErrorMessage(
"Failed to change role",
membership.shouldUseNewPrivilegeSystem,
ProjectPermissionIdentityActions.ManagePrivileges,
ProjectPermissionIdentityActions.GrantPrivileges,
ProjectPermissionSub.Identity
),
details: { missingPermissions: permissionBoundary.missingPermissions }

View File

@@ -10,7 +10,7 @@ import {
} from "@app/ee/services/permission/permission-fns";
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service";
import { getConfig } from "@app/lib/config/env";
import { BadRequestError, ForbiddenRequestError, NotFoundError } from "@app/lib/errors";
import { BadRequestError, NotFoundError, PermissionBoundaryError } from "@app/lib/errors";
import { extractIPDetails, isValidIpOrCidr } from "@app/lib/ip";
import { ActorType, AuthTokenType } from "../auth/auth-type";
@@ -266,8 +266,7 @@ export const identityTokenAuthServiceFactory = ({
rolePermission
);
if (!permissionBoundary.isValid)
throw new ForbiddenRequestError({
name: "PermissionBoundaryError",
throw new PermissionBoundaryError({
message: constructPermissionErrorMessage(
"Failed to revoke token auth of identity with more privileged role",
membership.shouldUseNewPrivilegeSystem,
@@ -333,8 +332,7 @@ export const identityTokenAuthServiceFactory = ({
rolePermission
);
if (!permissionBoundary.isValid)
throw new ForbiddenRequestError({
name: "PermissionBoundaryError",
throw new PermissionBoundaryError({
message: constructPermissionErrorMessage(
"Failed to create token for identity with more privileged role",
membership.shouldUseNewPrivilegeSystem,
@@ -472,8 +470,7 @@ export const identityTokenAuthServiceFactory = ({
rolePermission
);
if (!permissionBoundary.isValid)
throw new ForbiddenRequestError({
name: "PermissionBoundaryError",
throw new PermissionBoundaryError({
message: constructPermissionErrorMessage(
"Failed to update token for identity with more privileged role",
membership.shouldUseNewPrivilegeSystem,

View File

@@ -13,7 +13,7 @@ import {
} from "@app/ee/services/permission/permission-fns";
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service";
import { getConfig } from "@app/lib/config/env";
import { BadRequestError, ForbiddenRequestError, NotFoundError, UnauthorizedError } from "@app/lib/errors";
import { BadRequestError, NotFoundError, PermissionBoundaryError, UnauthorizedError } from "@app/lib/errors";
import { checkIPAgainstBlocklist, extractIPDetails, isValidIpOrCidr, TIp } from "@app/lib/ip";
import { ActorType, AuthTokenType } from "../auth/auth-type";
@@ -382,8 +382,7 @@ export const identityUaServiceFactory = ({
rolePermission
);
if (!permissionBoundary.isValid)
throw new ForbiddenRequestError({
name: "PermissionBoundaryError",
throw new PermissionBoundaryError({
message: constructPermissionErrorMessage(
"Failed to revoke universal auth of identity with more privileged role",
membership.shouldUseNewPrivilegeSystem,
@@ -443,8 +442,7 @@ export const identityUaServiceFactory = ({
rolePermission
);
if (!permissionBoundary.isValid)
throw new ForbiddenRequestError({
name: "PermissionBoundaryError",
throw new PermissionBoundaryError({
message: constructPermissionErrorMessage(
"Failed to create client secret for identity.",
membership.shouldUseNewPrivilegeSystem,
@@ -517,8 +515,7 @@ export const identityUaServiceFactory = ({
rolePermission
);
if (!permissionBoundary.isValid)
throw new ForbiddenRequestError({
name: "PermissionBoundaryError",
throw new PermissionBoundaryError({
message: constructPermissionErrorMessage(
"Failed to get identity client secret with more privileged role",
membership.shouldUseNewPrivilegeSystem,
@@ -580,8 +577,7 @@ export const identityUaServiceFactory = ({
rolePermission
);
if (!permissionBoundary.isValid)
throw new ForbiddenRequestError({
name: "PermissionBoundaryError",
throw new PermissionBoundaryError({
message: constructPermissionErrorMessage(
"Failed to read identity client secret of identity with more privileged role",
membership.shouldUseNewPrivilegeSystem,
@@ -637,8 +633,7 @@ export const identityUaServiceFactory = ({
rolePermission
);
if (!permissionBoundary.isValid) {
throw new ForbiddenRequestError({
name: "PermissionBoundaryError",
throw new PermissionBoundaryError({
message: constructPermissionErrorMessage(
"Failed to revoke identity client secret with more privileged role",
membership.shouldUseNewPrivilegeSystem,

View File

@@ -8,7 +8,7 @@ import {
validatePrivilegeChangeOperation
} from "@app/ee/services/permission/permission-fns";
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service";
import { BadRequestError, ForbiddenRequestError, NotFoundError } from "@app/lib/errors";
import { BadRequestError, NotFoundError, PermissionBoundaryError } from "@app/lib/errors";
import { TIdentityProjectDALFactory } from "@app/services/identity-project/identity-project-dal";
import { validateIdentityUpdateForSuperAdminPrivileges } from "../super-admin/super-admin-fns";
@@ -69,18 +69,17 @@ export const identityServiceFactory = ({
const isCustomRole = Boolean(customRole);
const permissionBoundary = validatePrivilegeChangeOperation(
membership.shouldUseNewPrivilegeSystem,
OrgPermissionIdentityActions.ManagePrivileges,
OrgPermissionIdentityActions.GrantPrivileges,
OrgPermissionSubjects.Identity,
permission,
rolePermission
);
if (!permissionBoundary.isValid)
throw new ForbiddenRequestError({
name: "PermissionBoundaryError",
throw new PermissionBoundaryError({
message: constructPermissionErrorMessage(
"Failed to create identity",
membership.shouldUseNewPrivilegeSystem,
OrgPermissionIdentityActions.ManagePrivileges,
OrgPermissionIdentityActions.GrantPrivileges,
OrgPermissionSubjects.Identity
),
details: { missingPermissions: permissionBoundary.missingPermissions }
@@ -159,18 +158,17 @@ export const identityServiceFactory = ({
const isCustomRole = Boolean(customOrgRole);
const appliedRolePermissionBoundary = validatePrivilegeChangeOperation(
membership.shouldUseNewPrivilegeSystem,
OrgPermissionIdentityActions.ManagePrivileges,
OrgPermissionIdentityActions.GrantPrivileges,
OrgPermissionSubjects.Identity,
permission,
rolePermission
);
if (!appliedRolePermissionBoundary.isValid)
throw new ForbiddenRequestError({
name: "PermissionBoundaryError",
throw new PermissionBoundaryError({
message: constructPermissionErrorMessage(
"Failed to update identity",
membership.shouldUseNewPrivilegeSystem,
OrgPermissionIdentityActions.ManagePrivileges,
OrgPermissionIdentityActions.GrantPrivileges,
OrgPermissionSubjects.Identity
),
details: { missingPermissions: appliedRolePermissionBoundary.missingPermissions }

View File

@@ -37,7 +37,13 @@ import { getConfig } from "@app/lib/config/env";
import { generateAsymmetricKeyPair } from "@app/lib/crypto";
import { generateSymmetricKey, infisicalSymmetricDecrypt, infisicalSymmetricEncypt } from "@app/lib/crypto/encryption";
import { generateUserSrpKeys } from "@app/lib/crypto/srp";
import { BadRequestError, ForbiddenRequestError, NotFoundError, UnauthorizedError } from "@app/lib/errors";
import {
BadRequestError,
ForbiddenRequestError,
NotFoundError,
PermissionBoundaryError,
UnauthorizedError
} from "@app/lib/errors";
import { groupBy } from "@app/lib/fn";
import { alphaNumericNanoId } from "@app/lib/nanoid";
import { isDisposableEmail } from "@app/lib/validator";
@@ -941,19 +947,18 @@ export const orgServiceFactory = ({
const permissionBoundary = validatePrivilegeChangeOperation(
membership.shouldUseNewPrivilegeSystem,
ProjectPermissionMemberActions.ManagePrivileges,
ProjectPermissionMemberActions.GrantPrivileges,
ProjectPermissionSub.Member,
projectPermission,
rolePermission
);
if (!permissionBoundary.isValid)
throw new ForbiddenRequestError({
name: "PermissionBoundaryError",
throw new PermissionBoundaryError({
message: constructPermissionErrorMessage(
"Failed to invite user to the project",
membership.shouldUseNewPrivilegeSystem,
ProjectPermissionMemberActions.ManagePrivileges,
ProjectPermissionMemberActions.GrantPrivileges,
ProjectPermissionSub.Member
),
details: { missingPermissions: permissionBoundary.missingPermissions }

View File

@@ -11,7 +11,7 @@ import { TPermissionServiceFactory } from "@app/ee/services/permission/permissio
import { ProjectPermissionMemberActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission";
import { TProjectUserAdditionalPrivilegeDALFactory } from "@app/ee/services/project-user-additional-privilege/project-user-additional-privilege-dal";
import { getConfig } from "@app/lib/config/env";
import { BadRequestError, ForbiddenRequestError, NotFoundError } from "@app/lib/errors";
import { BadRequestError, ForbiddenRequestError, NotFoundError, PermissionBoundaryError } from "@app/lib/errors";
import { groupBy } from "@app/lib/fn";
import { ms } from "@app/lib/ms";
@@ -279,18 +279,17 @@ export const projectMembershipServiceFactory = ({
const permissionBoundary = validatePrivilegeChangeOperation(
membership.shouldUseNewPrivilegeSystem,
ProjectPermissionMemberActions.ManagePrivileges,
ProjectPermissionMemberActions.GrantPrivileges,
ProjectPermissionSub.Member,
permission,
rolePermission
);
if (!permissionBoundary.isValid)
throw new ForbiddenRequestError({
name: "PermissionBoundaryError",
throw new PermissionBoundaryError({
message: constructPermissionErrorMessage(
`Failed to change role ${requestedRoleChange}`,
membership.shouldUseNewPrivilegeSystem,
ProjectPermissionMemberActions.ManagePrivileges,
ProjectPermissionMemberActions.GrantPrivileges,
ProjectPermissionSub.Member
),
details: { missingPermissions: permissionBoundary.missingPermissions }

View File

@@ -50,29 +50,29 @@ Below is a comprehensive list of all available organization-level subjects and t
#### Subject: `groups`
| Action | Description |
| ------------------- | ------------------------------------------------ |
| `read` | View organization groups |
| `create` | Create new groups in the organization |
| `edit` | Modify existing groups |
| `delete` | Remove groups from the organization |
| `manage-privileges` | Change permission levels for organization groups |
| `add-members` | Add members to groups |
| `remove-members` | Remove members from groups |
| Action | Description |
| ------------------ | ------------------------------------------------ |
| `read` | View organization groups |
| `create` | Create new groups in the organization |
| `edit` | Modify existing groups |
| `delete` | Remove groups from the organization |
| `grant-privileges` | Change permission levels for organization groups |
| `add-members` | Add members to groups |
| `remove-members` | Remove members from groups |
#### Subject: `identity`
| Action | Description |
| ------------------- | --------------------------------------------------- |
| `read` | View organization identities |
| `create` | Add new identities to organization |
| `edit` | Modify organization identities |
| `delete` | Remove identities from organization |
| `manage-privileges` | Change permission levels of organization identities |
| `revoke-auth` | Revoke authentication for identities |
| `create-token` | Create new authentication tokens |
| `delete-token` | Delete authentication tokens |
| `get-token` | Retrieve authentication tokens |
| Action | Description |
| ------------------ | --------------------------------------------------- |
| `read` | View organization identities |
| `create` | Add new identities to organization |
| `edit` | Modify organization identities |
| `delete` | Remove identities from organization |
| `grant-privileges` | Change permission levels of organization identities |
| `revoke-auth` | Revoke authentication for identities |
| `create-token` | Create new authentication tokens |
| `delete-token` | Delete authentication tokens |
| `get-token` | Retrieve authentication tokens |
### Security & Compliance
@@ -163,6 +163,7 @@ Below is a comprehensive list of all available organization-level subjects and t
### Integrations
#### Subject: `app-connections`
Supports conditions and permission inversion
| Action | Description |

View File

@@ -21,6 +21,7 @@ Below is a comprehensive list of all available project-level subjects and their
### Core Platform & Access Control
#### Subject: `role`
| Action | Description |
| -------- | ------------------------------------------------- |
| `read` | View project roles and their assigned permissions |
@@ -29,33 +30,37 @@ Below is a comprehensive list of all available project-level subjects and their
| `delete` | Remove project roles |
#### Subject: `member`
| Action | Description |
| ------------------- | ------------------------------------------- |
| `read` | View project members |
| `create` | Add new members to the project |
| `edit` | Modify member details |
| `delete` | Remove members from the project |
| `manage-privileges` | Change permission levels of project members |
| Action | Description |
| ------------------ | ------------------------------------------- |
| `read` | View project members |
| `create` | Add new members to the project |
| `edit` | Modify member details |
| `delete` | Remove members from the project |
| `grant-privileges` | Change permission levels of project members |
#### Subject: `groups`
| Action | Description |
| ------------------- | ------------------------------------------ |
| `read` | View project groups |
| `create` | Create new groups within the project |
| `edit` | Modify existing groups |
| `delete` | Remove groups from the project |
| `manage-privileges` | Change permission levels of project groups |
| Action | Description |
| ------------------ | ------------------------------------------ |
| `read` | View project groups |
| `create` | Create new groups within the project |
| `edit` | Modify existing groups |
| `delete` | Remove groups from the project |
| `grant-privileges` | Change permission levels of project groups |
#### Subject: `identity`
| Action | Description |
| ------------------- | ---------------------------------------------- |
| `read` | View project identities |
| `create` | Add new identities to project |
| `edit` | Modify project identities |
| `delete` | Remove identities from project |
| `manage-privileges` | Change permission levels of project identities |
| Action | Description |
| ------------------ | ---------------------------------------------- |
| `read` | View project identities |
| `create` | Add new identities to project |
| `edit` | Modify project identities |
| `delete` | Remove identities from project |
| `grant-privileges` | Change permission levels of project identities |
#### Subject: `settings`
| Action | Description |
| -------- | -------------------------------------- |
| `read` | View project settings |
@@ -64,6 +69,7 @@ Below is a comprehensive list of all available project-level subjects and their
| `delete` | Remove project settings |
#### Subject: `environments`
| Action | Description |
| -------- | ------------------------------------ |
| `read` | View project environments |
@@ -72,6 +78,7 @@ Below is a comprehensive list of all available project-level subjects and their
| `delete` | Remove environments from the project |
#### Subject: `tags`
| Action | Description |
| -------- | ---------------------------------------- |
| `read` | View project tags |
@@ -80,12 +87,14 @@ Below is a comprehensive list of all available project-level subjects and their
| `delete` | Remove tags from the project |
#### Subject: `workspace`
| Action | Description |
| -------- | ------------------------- |
| `edit` | Modify workspace settings |
| `delete` | Delete the workspace |
#### Subject: `ip-allowlist`
| Action | Description |
| -------- | -------------------------------------------- |
| `read` | View IP allowlists |
@@ -94,11 +103,13 @@ Below is a comprehensive list of all available project-level subjects and their
| `delete` | Remove IP addresses from allowlists |
#### Subject: `audit-logs`
| Action | Description |
| ------ | ------------------------------------------------------- |
| `read` | View audit logs of actions performed within the project |
#### Subject: `integrations`
| Action | Description |
| -------- | -------------------------------- |
| `read` | View configured integrations |
@@ -107,6 +118,7 @@ Below is a comprehensive list of all available project-level subjects and their
| `delete` | Remove integrations |
#### Subject: `webhooks`
| Action | Description |
| -------- | ------------------------------------ |
| `read` | View webhook configurations |
@@ -115,6 +127,7 @@ Below is a comprehensive list of all available project-level subjects and their
| `delete` | Remove webhooks |
#### Subject: `service-tokens`
| Action | Description |
| -------- | ---------------------------------------- |
| `read` | View service tokens |
@@ -125,39 +138,44 @@ Below is a comprehensive list of all available project-level subjects and their
### Secrets Management
#### Subject: `secrets`
Supports conditions and permission inversion
| Action | Description |
| Action | Description |
| -------- | ------------------------------- |
| `read` | View secrets and their values |
| `create` | Add new secrets to the project |
| `edit` | Modify existing secret values |
| `read` | View secrets and their values |
| `create` | Add new secrets to the project |
| `edit` | Modify existing secret values |
| `delete` | Remove secrets from the project |
#### Subject: `secret-folders`
Supports conditions and permission inversion
| Action | Description |
| Action | Description |
| -------- | ------------------------ |
| `read` | View secret folders |
| `create` | Create new folders |
| `edit` | Modify folder properties |
| `delete` | Remove secret folders |
| `read` | View secret folders |
| `create` | Create new folders |
| `edit` | Modify folder properties |
| `delete` | Remove secret folders |
#### Subject: `secret-imports`
Supports conditions and permission inversion
| Action | Description |
| Action | Description |
| -------- | --------------------- |
| `read` | View secret imports |
| `read` | View secret imports |
| `create` | Create secret imports |
| `edit` | Modify secret imports |
| `edit` | Modify secret imports |
| `delete` | Remove secret imports |
#### Subject: `secret-rollback`
| Action | Description |
| -------- | ---------------------------------- |
| `read` | View secret versions and snapshots |
| `create` | Roll back secrets to snapshots |
#### Subject: `secret-approval`
| Action | Description |
| -------- | ----------------------------------- |
| `read` | View approval policies and requests |
@@ -166,6 +184,7 @@ Supports conditions and permission inversion
| `delete` | Remove approval policies |
#### Subject: `secret-rotation`
| Action | Description |
| -------- | ------------------------------------- |
| `read` | View secret rotation policies |
@@ -174,6 +193,7 @@ Supports conditions and permission inversion
| `delete` | Remove rotation policies |
#### Subject: `secret-syncs`
| Action | Description |
| ---------------- | -------------------------------------------------- |
| `read` | View secret synchronization configurations |
@@ -185,23 +205,26 @@ Supports conditions and permission inversion
| `remove-secrets` | Remove secrets from sync destinations |
#### Subject: `dynamic-secrets`
Supports conditions and permission inversion
| Action | Description |
| Action | Description |
| ------------------------ | ---------------------------------- |
| `read-root-credential` | View dynamic secret configurations |
| `create-root-credential` | Create dynamic secrets |
| `edit-root-credential` | Edit dynamic secrets |
| `delete-root-credential` | Remove dynamic secrets |
| `lease` | Create dynamic secret leases |
| `read-root-credential` | View dynamic secret configurations |
| `create-root-credential` | Create dynamic secrets |
| `edit-root-credential` | Edit dynamic secrets |
| `delete-root-credential` | Remove dynamic secrets |
| `lease` | Create dynamic secret leases |
### Key Management Service (KMS)
#### Subject: `kms`
| Action | Description |
| ------ | --------------------------- |
| `edit` | Modify project KMS settings |
#### Subject: `cmek`
| Action | Description |
| --------- | ------------------------------------- |
| `read` | View Customer-Managed Encryption Keys |
@@ -214,6 +237,7 @@ Supports conditions and permission inversion
### Public Key Infrastructure (PKI)
#### Subject: `certificate-authorities`
| Action | Description |
| -------- | ---------------------------------- |
| `read` | View certificate authorities |
@@ -222,6 +246,7 @@ Supports conditions and permission inversion
| `delete` | Remove certificate authorities |
#### Subject: `certificates`
| Action | Description |
| -------- | ----------------------------- |
| `read` | View certificates |
@@ -229,6 +254,7 @@ Supports conditions and permission inversion
| `delete` | Revoke or remove certificates |
#### Subject: `certificate-templates`
| Action | Description |
| -------- | -------------------------------- |
| `read` | View certificate templates |
@@ -237,6 +263,7 @@ Supports conditions and permission inversion
| `delete` | Remove certificate templates |
#### Subject: `pki-alerts`
| Action | Description |
| -------- | ------------------------------------------------------------ |
| `read` | View PKI alert configurations |
@@ -245,6 +272,7 @@ Supports conditions and permission inversion
| `delete` | Remove PKI alerts |
#### Subject: `pki-collections`
| Action | Description |
| -------- | --------------------------------------------------- |
| `read` | View PKI resource collections |
@@ -255,6 +283,7 @@ Supports conditions and permission inversion
### SSH Certificate Management
#### Subject: `ssh-certificate-authorities`
| Action | Description |
| -------- | -------------------------------------- |
| `read` | View SSH certificate authorities |
@@ -263,6 +292,7 @@ Supports conditions and permission inversion
| `delete` | Remove SSH certificate authorities |
#### Subject: `ssh-certificates`
| Action | Description |
| -------- | --------------------------------- |
| `read` | View SSH certificates |
@@ -271,9 +301,10 @@ Supports conditions and permission inversion
| `delete` | Revoke or remove SSH certificates |
#### Subject: `ssh-certificate-templates`
| Action | Description |
| -------- | ------------------------------------ |
| `read` | View SSH certificate templates |
| `create` | Create new SSH certificate templates |
| `edit` | Modify SSH template configurations |
| `delete` | Remove SSH certificate templates |
| `delete` | Remove SSH certificate templates |

View File

@@ -64,7 +64,7 @@ export enum OrgPermissionIdentityActions {
Create = "create",
Edit = "edit",
Delete = "delete",
ManagePrivileges = "manage-privileges",
GrantPrivileges = "grant-privileges",
RevokeAuth = "revoke-auth",
CreateToken = "create-token",
GetToken = "get-token",
@@ -76,7 +76,7 @@ export enum OrgPermissionGroupActions {
Create = "create",
Edit = "edit",
Delete = "delete",
ManagePrivileges = "manage-privileges",
GrantPrivileges = "grant-privileges",
AddMembers = "add-members",
RemoveMembers = "remove-members"
}

View File

@@ -56,7 +56,7 @@ export enum ProjectPermissionIdentityActions {
Create = "create",
Edit = "edit",
Delete = "delete",
ManagePrivileges = "manage-privileges"
GrantPrivileges = "grant-privileges"
}
export enum ProjectPermissionMemberActions {
@@ -64,7 +64,7 @@ export enum ProjectPermissionMemberActions {
Create = "create",
Edit = "edit",
Delete = "delete",
ManagePrivileges = "manage-privileges"
GrantPrivileges = "grant-privileges"
}
export enum ProjectPermissionGroupActions {
@@ -72,7 +72,7 @@ export enum ProjectPermissionGroupActions {
Create = "create",
Edit = "edit",
Delete = "delete",
ManagePrivileges = "manage-privileges"
GrantPrivileges = "grant-privileges"
}
export enum PermissionConditionOperators {

View File

@@ -1,7 +1,7 @@
import { useState } from "react";
import { Controller, useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { z } from "zod";
import { useState } from "react";
import { createNotification } from "@app/components/notifications";
import { Button, Checkbox, Modal, ModalContent } from "@app/components/v2";
@@ -71,94 +71,95 @@ export const UpgradePrivilegeSystemModal = ({ isOpen, onOpenChange }: Props) =>
<Modal isOpen={isOpen} onOpenChange={handleClose}>
<ModalContent title="Privilege Management System Upgrade" className="max-w-2xl">
{step === "info" ? (
<>
<div className="mb-4">
<p className="mb-4 text-sm text-mineshaft-300">
We&apos;ve developed an improved privilege management system that enhances how access controls work in your organization.
</p>
<div className="mb-4">
<p className="mb-4 text-sm text-mineshaft-300">
We&apos;ve developed an improved privilege management system that enhances how access
controls work in your organization.
</p>
<div className="mb-4 rounded-lg border border-mineshaft-600 bg-mineshaft-800 p-4">
<div className="mb-4 rounded-lg border border-mineshaft-600 bg-mineshaft-800 p-4">
<div className="mb-3">
<div className="mb-3">
<div className="mb-3">
<p className="mb-3 text-sm text-mineshaft-300">
<strong>Current system: </strong>
Users with higher privilege levels can modify access for anyone below them.
This rigid hierarchy makes it difficult to implement precise access control policies,
forcing you to either over-grant permissions or create complex workarounds when specialized roles (like team leads) need to manage their team&apos;s access without receiving broader administrative powers.
</p>
<p className="text-sm text-mineshaft-300">
<strong>New system:</strong> Users need explicit permission to modify specific
access levels, providing targeted control. After upgrading, you&apos;ll need to
grant the new &apos;Manage Privileges&apos; permission. At the organization level,
this is available for the{" "}
<a
href="https://infisical.com/docs/internals/permissions/organization-permissions#subject%3A-groups"
target="_blank"
rel="noreferrer"
className="underline hover:text-bunker-200 hover:decoration-primary-700"
>
Group
</a>{" "}
and{" "}
<a
href="https://infisical.com/docs/internals/permissions/organization-permissions#subject%3A-identity"
target="_blank"
rel="noreferrer"
className="underline hover:text-bunker-200 hover:decoration-primary-700"
>
Identity
</a>{" "}
subjects while at the project level, this is available for the{" "}
<a
href="https://infisical.com/docs/internals/permissions/project-permissions#subject%3A-member"
target="_blank"
rel="noreferrer"
className="underline hover:text-bunker-200 hover:decoration-primary-700"
>
Member,
</a>{" "}
<a
href="https://infisical.com/docs/internals/permissions/project-permissions#subject%3A-groups"
target="_blank"
rel="noreferrer"
className="underline hover:text-bunker-200 hover:decoration-primary-700"
>
Group,
</a>{" "}
and{" "}
<a
href="https://infisical.com/docs/internals/permissions/project-permissions#subject%3A-identity"
target="_blank"
rel="noreferrer"
className="underline hover:text-bunker-200 hover:decoration-primary-700"
>
Identity
</a>{" "}
subjects.
</p>
</div>
<p className="mb-3 text-sm text-mineshaft-300">
<strong>Current system: </strong>
Users with higher privilege levels can modify access for anyone below them. This
rigid hierarchy makes it difficult to implement precise access control policies,
forcing you to either over-grant permissions or create complex workarounds when
specialized roles (like team leads) need to manage their team&apos;s access
without receiving broader administrative powers.
</p>
<p className="text-sm text-mineshaft-300">
<strong>New system:</strong> Users need explicit permission to modify specific
access levels, providing targeted control. After upgrading, you&apos;ll need to
grant the new &apos;Grant Privileges&apos; permission. At the organization
level, this is available for the{" "}
<a
href="https://infisical.com/docs/internals/permissions/organization-permissions#subject%3A-groups"
target="_blank"
rel="noreferrer"
className="underline hover:text-bunker-200 hover:decoration-primary-700"
>
Group
</a>{" "}
and{" "}
<a
href="https://infisical.com/docs/internals/permissions/organization-permissions#subject%3A-identity"
target="_blank"
rel="noreferrer"
className="underline hover:text-bunker-200 hover:decoration-primary-700"
>
Identity
</a>{" "}
subjects while at the project level, this is available for the{" "}
<a
href="https://infisical.com/docs/internals/permissions/project-permissions#subject%3A-member"
target="_blank"
rel="noreferrer"
className="underline hover:text-bunker-200 hover:decoration-primary-700"
>
Member,
</a>{" "}
<a
href="https://infisical.com/docs/internals/permissions/project-permissions#subject%3A-groups"
target="_blank"
rel="noreferrer"
className="underline hover:text-bunker-200 hover:decoration-primary-700"
>
Group,
</a>{" "}
and{" "}
<a
href="https://infisical.com/docs/internals/permissions/project-permissions#subject%3A-identity"
target="_blank"
rel="noreferrer"
className="underline hover:text-bunker-200 hover:decoration-primary-700"
>
Identity
</a>{" "}
subjects.
</p>
</div>
</div>
<div className="mt-4 flex justify-end">
<Button
onClick={() => setStep("upgrade")}
variant="solid"
colorSchema="primary"
size="md"
className="w-[120px] bg-primary hover:bg-primary-600"
>
Continue
</Button>
</div>
</div>
</>
<div className="mt-4 flex justify-end">
<Button
onClick={() => setStep("upgrade")}
variant="solid"
colorSchema="primary"
size="md"
className="w-[120px] bg-primary hover:bg-primary-600"
>
Continue
</Button>
</div>
</div>
) : (
<div className="mb-4">
<p className="mb-4 text-sm text-mineshaft-300">
Your existing access control workflows will continue to function. However, actions that
involve modifying privileges or permissions will now use the new permission-based system,
requiring users to have explicit permission to modify given resource.
Your existing access control workflows will continue to function. However, actions
that involve modifying privileges or permissions will now use the new permission-based
system, requiring users to have explicit permission to modify given resource.
</p>
<p className="mb-4 text-sm text-mineshaft-300">
@@ -168,9 +169,9 @@ export const UpgradePrivilegeSystemModal = ({ isOpen, onOpenChange }: Props) =>
<div className="mb-4 rounded-lg border border-mineshaft-600 bg-mineshaft-800 p-4">
<p className="mb-4 text-sm text-mineshaft-300">
Once upgraded, your organization <span className="font-bold">cannot</span> revert to the
legacy privilege system. Please ensure you&apos;ve completed all preparations before
proceeding.
Once upgraded, your organization <span className="font-bold">cannot</span> revert to
the legacy privilege system. Please ensure you&apos;ve completed all preparations
before proceeding.
</p>
<div className="mb-4">
@@ -233,8 +234,8 @@ export const UpgradePrivilegeSystemModal = ({ isOpen, onOpenChange }: Props) =>
onBlur={onBlur}
isError={Boolean(error?.message)}
>
I have checked Terraform configurations and API integrations for compatibility
with the new system
I have checked Terraform configurations and API integrations for
compatibility with the new system
</Checkbox>
)}
/>
@@ -265,6 +266,7 @@ export const UpgradePrivilegeSystemModal = ({ isOpen, onOpenChange }: Props) =>
<form onSubmit={handleSubmit(handlePrivilegeSystemUpgrade)}>
<div className="mt-6 flex items-center justify-end gap-4">
<button
type="button"
onClick={() => setStep("info")}
className="w-[120px] text-sm text-mineshaft-300 hover:text-mineshaft-200"
>

View File

@@ -44,7 +44,7 @@ const identityPermissionSchema = z
[OrgPermissionIdentityActions.Edit]: z.boolean().optional(),
[OrgPermissionIdentityActions.Delete]: z.boolean().optional(),
[OrgPermissionIdentityActions.Create]: z.boolean().optional(),
[OrgPermissionIdentityActions.ManagePrivileges]: z.boolean().optional(),
[OrgPermissionIdentityActions.GrantPrivileges]: z.boolean().optional(),
[OrgPermissionIdentityActions.RevokeAuth]: z.boolean().optional(),
[OrgPermissionIdentityActions.CreateToken]: z.boolean().optional(),
[OrgPermissionIdentityActions.GetToken]: z.boolean().optional(),
@@ -58,7 +58,7 @@ const groupPermissionSchema = z
[OrgPermissionGroupActions.Create]: z.boolean().optional(),
[OrgPermissionGroupActions.Edit]: z.boolean().optional(),
[OrgPermissionGroupActions.Delete]: z.boolean().optional(),
[OrgPermissionGroupActions.ManagePrivileges]: z.boolean().optional(),
[OrgPermissionGroupActions.GrantPrivileges]: z.boolean().optional(),
[OrgPermissionGroupActions.AddMembers]: z.boolean().optional(),
[OrgPermissionGroupActions.RemoveMembers]: z.boolean().optional()
})

View File

@@ -15,7 +15,7 @@ const PERMISSION_ACTIONS = [
{ action: OrgPermissionGroupActions.Create, label: "Create Groups" },
{ action: OrgPermissionGroupActions.Edit, label: "Edit Groups" },
{ action: OrgPermissionGroupActions.Delete, label: "Delete Groups" },
{ action: OrgPermissionGroupActions.ManagePrivileges, label: "Manage Privileges" },
{ action: OrgPermissionGroupActions.GrantPrivileges, label: "Grant Privileges" },
{ action: OrgPermissionGroupActions.AddMembers, label: "Add Members" },
{ action: OrgPermissionGroupActions.RemoveMembers, label: "Remove Members" }
] as const;
@@ -84,7 +84,7 @@ export const OrgPermissionGroupRow = ({ isEditable, control, setValue }: Props)
[OrgPermissionGroupActions.Create]: false,
[OrgPermissionGroupActions.Edit]: false,
[OrgPermissionGroupActions.Delete]: false,
[OrgPermissionGroupActions.ManagePrivileges]: false,
[OrgPermissionGroupActions.GrantPrivileges]: false,
[OrgPermissionGroupActions.AddMembers]: false,
[OrgPermissionGroupActions.RemoveMembers]: false
},
@@ -99,7 +99,7 @@ export const OrgPermissionGroupRow = ({ isEditable, control, setValue }: Props)
[OrgPermissionGroupActions.Create]: true,
[OrgPermissionGroupActions.Edit]: true,
[OrgPermissionGroupActions.Delete]: true,
[OrgPermissionGroupActions.ManagePrivileges]: true,
[OrgPermissionGroupActions.GrantPrivileges]: true,
[OrgPermissionGroupActions.AddMembers]: true,
[OrgPermissionGroupActions.RemoveMembers]: true
},
@@ -114,7 +114,7 @@ export const OrgPermissionGroupRow = ({ isEditable, control, setValue }: Props)
[OrgPermissionGroupActions.Edit]: false,
[OrgPermissionGroupActions.Create]: false,
[OrgPermissionGroupActions.Delete]: false,
[OrgPermissionGroupActions.ManagePrivileges]: false,
[OrgPermissionGroupActions.GrantPrivileges]: false,
[OrgPermissionGroupActions.AddMembers]: false,
[OrgPermissionGroupActions.RemoveMembers]: false
},
@@ -129,7 +129,7 @@ export const OrgPermissionGroupRow = ({ isEditable, control, setValue }: Props)
[OrgPermissionGroupActions.Edit]: false,
[OrgPermissionGroupActions.Create]: false,
[OrgPermissionGroupActions.Delete]: false,
[OrgPermissionGroupActions.ManagePrivileges]: false,
[OrgPermissionGroupActions.GrantPrivileges]: false,
[OrgPermissionGroupActions.AddMembers]: false,
[OrgPermissionGroupActions.RemoveMembers]: false
},

View File

@@ -15,7 +15,7 @@ const PERMISSION_ACTIONS = [
{ action: OrgPermissionIdentityActions.Create, label: "Create Identities" },
{ action: OrgPermissionIdentityActions.Edit, label: "Edit Identities" },
{ action: OrgPermissionIdentityActions.Delete, label: "Delete Identities" },
{ action: OrgPermissionIdentityActions.ManagePrivileges, label: "Manage Privileges" },
{ action: OrgPermissionIdentityActions.GrantPrivileges, label: "Grant Privileges" },
{ action: OrgPermissionIdentityActions.RevokeAuth, label: "Revoke Auth" },
{ action: OrgPermissionIdentityActions.CreateToken, label: "Create Token" },
{ action: OrgPermissionIdentityActions.GetToken, label: "Get Token" },
@@ -86,7 +86,7 @@ export const OrgPermissionIdentityRow = ({ isEditable, control, setValue }: Prop
[OrgPermissionIdentityActions.Edit]: false,
[OrgPermissionIdentityActions.Create]: false,
[OrgPermissionIdentityActions.Delete]: false,
[OrgPermissionIdentityActions.ManagePrivileges]: false,
[OrgPermissionIdentityActions.GrantPrivileges]: false,
[OrgPermissionIdentityActions.RevokeAuth]: false,
[OrgPermissionIdentityActions.CreateToken]: false,
[OrgPermissionIdentityActions.GetToken]: false,
@@ -103,7 +103,7 @@ export const OrgPermissionIdentityRow = ({ isEditable, control, setValue }: Prop
[OrgPermissionIdentityActions.Edit]: true,
[OrgPermissionIdentityActions.Create]: true,
[OrgPermissionIdentityActions.Delete]: true,
[OrgPermissionIdentityActions.ManagePrivileges]: true,
[OrgPermissionIdentityActions.GrantPrivileges]: true,
[OrgPermissionIdentityActions.RevokeAuth]: true,
[OrgPermissionIdentityActions.CreateToken]: true,
[OrgPermissionIdentityActions.GetToken]: true,
@@ -120,7 +120,7 @@ export const OrgPermissionIdentityRow = ({ isEditable, control, setValue }: Prop
[OrgPermissionIdentityActions.Edit]: false,
[OrgPermissionIdentityActions.Create]: false,
[OrgPermissionIdentityActions.Delete]: false,
[OrgPermissionIdentityActions.ManagePrivileges]: false,
[OrgPermissionIdentityActions.GrantPrivileges]: false,
[OrgPermissionIdentityActions.RevokeAuth]: false,
[OrgPermissionIdentityActions.CreateToken]: false,
[OrgPermissionIdentityActions.GetToken]: false,
@@ -137,7 +137,7 @@ export const OrgPermissionIdentityRow = ({ isEditable, control, setValue }: Prop
[OrgPermissionIdentityActions.Edit]: false,
[OrgPermissionIdentityActions.Create]: false,
[OrgPermissionIdentityActions.Delete]: false,
[OrgPermissionIdentityActions.ManagePrivileges]: false,
[OrgPermissionIdentityActions.GrantPrivileges]: false,
[OrgPermissionIdentityActions.RevokeAuth]: false,
[OrgPermissionIdentityActions.CreateToken]: false,
[OrgPermissionIdentityActions.GetToken]: false,

View File

@@ -79,7 +79,7 @@ const MemberPolicyActionSchema = z.object({
[ProjectPermissionMemberActions.Create]: z.boolean().optional(),
[ProjectPermissionMemberActions.Edit]: z.boolean().optional(),
[ProjectPermissionMemberActions.Delete]: z.boolean().optional(),
[ProjectPermissionMemberActions.ManagePrivileges]: z.boolean().optional()
[ProjectPermissionMemberActions.GrantPrivileges]: z.boolean().optional()
});
const IdentityPolicyActionSchema = z.object({
@@ -87,7 +87,7 @@ const IdentityPolicyActionSchema = z.object({
[ProjectPermissionIdentityActions.Create]: z.boolean().optional(),
[ProjectPermissionIdentityActions.Edit]: z.boolean().optional(),
[ProjectPermissionIdentityActions.Delete]: z.boolean().optional(),
[ProjectPermissionIdentityActions.ManagePrivileges]: z.boolean().optional()
[ProjectPermissionIdentityActions.GrantPrivileges]: z.boolean().optional()
});
const GroupPolicyActionSchema = z.object({
@@ -95,7 +95,7 @@ const GroupPolicyActionSchema = z.object({
[ProjectPermissionGroupActions.Create]: z.boolean().optional(),
[ProjectPermissionGroupActions.Edit]: z.boolean().optional(),
[ProjectPermissionGroupActions.Delete]: z.boolean().optional(),
[ProjectPermissionGroupActions.ManagePrivileges]: z.boolean().optional()
[ProjectPermissionGroupActions.GrantPrivileges]: z.boolean().optional()
});
const SecretRollbackPolicyActionSchema = z.object({
@@ -461,7 +461,7 @@ export const rolePermission2Form = (permissions: TProjectPermission[] = []) => {
const canCreate = action.includes(ProjectPermissionMemberActions.Create);
const canEdit = action.includes(ProjectPermissionMemberActions.Edit);
const canDelete = action.includes(ProjectPermissionMemberActions.Delete);
const canManagePrivileges = action.includes(ProjectPermissionMemberActions.ManagePrivileges);
const canGrantPrivileges = action.includes(ProjectPermissionMemberActions.GrantPrivileges);
if (!formVal[subject]) formVal[subject] = [{}];
@@ -470,8 +470,8 @@ export const rolePermission2Form = (permissions: TProjectPermission[] = []) => {
if (canCreate) formVal[subject]![0][ProjectPermissionMemberActions.Create] = true;
if (canEdit) formVal[subject]![0][ProjectPermissionMemberActions.Edit] = true;
if (canDelete) formVal[subject]![0][ProjectPermissionMemberActions.Delete] = true;
if (canManagePrivileges)
formVal[subject]![0][ProjectPermissionMemberActions.ManagePrivileges] = true;
if (canGrantPrivileges)
formVal[subject]![0][ProjectPermissionMemberActions.GrantPrivileges] = true;
return;
}
@@ -480,9 +480,7 @@ export const rolePermission2Form = (permissions: TProjectPermission[] = []) => {
const canCreate = action.includes(ProjectPermissionIdentityActions.Create);
const canEdit = action.includes(ProjectPermissionIdentityActions.Edit);
const canDelete = action.includes(ProjectPermissionIdentityActions.Delete);
const canManagePrivileges = action.includes(
ProjectPermissionIdentityActions.ManagePrivileges
);
const canGrantPrivileges = action.includes(ProjectPermissionIdentityActions.GrantPrivileges);
if (!formVal[subject]) formVal[subject] = [{ conditions: [] }];
@@ -491,8 +489,8 @@ export const rolePermission2Form = (permissions: TProjectPermission[] = []) => {
if (canCreate) formVal[subject]![0][ProjectPermissionIdentityActions.Create] = true;
if (canEdit) formVal[subject]![0][ProjectPermissionIdentityActions.Edit] = true;
if (canDelete) formVal[subject]![0][ProjectPermissionIdentityActions.Delete] = true;
if (canManagePrivileges)
formVal[subject]![0][ProjectPermissionIdentityActions.ManagePrivileges] = true;
if (canGrantPrivileges)
formVal[subject]![0][ProjectPermissionIdentityActions.GrantPrivileges] = true;
return;
}
@@ -501,7 +499,7 @@ export const rolePermission2Form = (permissions: TProjectPermission[] = []) => {
const canCreate = action.includes(ProjectPermissionGroupActions.Create);
const canEdit = action.includes(ProjectPermissionGroupActions.Edit);
const canDelete = action.includes(ProjectPermissionGroupActions.Delete);
const canManagePrivileges = action.includes(ProjectPermissionGroupActions.ManagePrivileges);
const canGrantPrivileges = action.includes(ProjectPermissionGroupActions.GrantPrivileges);
if (!formVal[subject]) formVal[subject] = [{}];
@@ -510,8 +508,8 @@ export const rolePermission2Form = (permissions: TProjectPermission[] = []) => {
if (canCreate) formVal[subject]![0][ProjectPermissionGroupActions.Create] = true;
if (canEdit) formVal[subject]![0][ProjectPermissionGroupActions.Edit] = true;
if (canDelete) formVal[subject]![0][ProjectPermissionGroupActions.Delete] = true;
if (canManagePrivileges)
formVal[subject]![0][ProjectPermissionGroupActions.ManagePrivileges] = true;
if (canGrantPrivileges)
formVal[subject]![0][ProjectPermissionGroupActions.GrantPrivileges] = true;
return;
}
@@ -724,7 +722,7 @@ export const PROJECT_PERMISSION_OBJECT: TProjectPermissionObject = {
{ label: "Add", value: ProjectPermissionMemberActions.Create },
{ label: "Modify", value: ProjectPermissionMemberActions.Edit },
{ label: "Remove", value: ProjectPermissionMemberActions.Delete },
{ label: "Manage Privileges", value: ProjectPermissionMemberActions.ManagePrivileges }
{ label: "Grant Privileges", value: ProjectPermissionMemberActions.GrantPrivileges }
]
},
[ProjectPermissionSub.Identity]: {
@@ -734,7 +732,7 @@ export const PROJECT_PERMISSION_OBJECT: TProjectPermissionObject = {
{ label: "Add", value: ProjectPermissionIdentityActions.Create },
{ label: "Modify", value: ProjectPermissionIdentityActions.Edit },
{ label: "Remove", value: ProjectPermissionIdentityActions.Delete },
{ label: "Manage Privileges", value: ProjectPermissionIdentityActions.ManagePrivileges }
{ label: "Grant Privileges", value: ProjectPermissionIdentityActions.GrantPrivileges }
]
},
[ProjectPermissionSub.Groups]: {
@@ -744,7 +742,7 @@ export const PROJECT_PERMISSION_OBJECT: TProjectPermissionObject = {
{ label: "Create", value: ProjectPermissionGroupActions.Create },
{ label: "Modify", value: ProjectPermissionGroupActions.Edit },
{ label: "Remove", value: ProjectPermissionGroupActions.Delete },
{ label: "Manage Privileges", value: ProjectPermissionGroupActions.ManagePrivileges }
{ label: "Grant Privileges", value: ProjectPermissionGroupActions.GrantPrivileges }
]
},
[ProjectPermissionSub.Webhooks]: {