From 956d0f6c5d0ca36c25509b4ff2d2cfb8f0bea6d4 Mon Sep 17 00:00:00 2001 From: Sheen Capadngan Date: Thu, 27 Mar 2025 12:17:36 +0800 Subject: [PATCH] misc: review comments --- .../src/ee/services/group/group-service.ts | 22 +-- ...project-additional-privilege-v2-service.ts | 23 +-- ...ty-project-additional-privilege-service.ts | 23 +-- .../ee/services/permission/org-permission.ts | 8 +- .../services/permission/project-permission.ts | 12 +- ...oject-user-additional-privilege-service.ts | 16 +- backend/src/lib/errors/index.ts | 17 ++ backend/src/server/plugins/error-handler.ts | 3 +- .../group-project/group-project-service.ts | 16 +- .../identity-aws-auth-service.ts | 5 +- .../identity-azure-auth-service.ts | 5 +- .../identity-gcp-auth-service.ts | 5 +- .../identity-jwt-auth-service.ts | 11 +- .../identity-kubernetes-auth-service.ts | 5 +- .../identity-oidc-auth-service.ts | 11 +- .../identity-project-service.ts | 16 +- .../identity-token-auth-service.ts | 11 +- .../identity-ua/identity-ua-service.ts | 17 +- .../src/services/identity/identity-service.ts | 16 +- backend/src/services/org/org-service.ts | 15 +- .../project-membership-service.ts | 9 +- .../permissions/organization-permissions.mdx | 41 +++-- .../permissions/project-permissions.mdx | 111 +++++++---- .../src/context/OrgPermissionContext/types.ts | 4 +- .../context/ProjectPermissionContext/types.ts | 6 +- .../UpgradePrivilegeSystemModal.tsx | 174 +++++++++--------- .../components/OrgRoleModifySection.utils.ts | 4 +- .../OrgPermissionGroupRow.tsx | 10 +- .../OrgPermissionIdentityRow.tsx | 10 +- .../ProjectRoleModifySection.utils.tsx | 32 ++-- 30 files changed, 346 insertions(+), 312 deletions(-) diff --git a/backend/src/ee/services/group/group-service.ts b/backend/src/ee/services/group/group-service.ts index 916e1eee1..be8abf0cd 100644 --- a/backend/src/ee/services/group/group-service.ts +++ b/backend/src/ee/services/group/group-service.ts @@ -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, diff --git a/backend/src/ee/services/identity-project-additional-privilege-v2/identity-project-additional-privilege-v2-service.ts b/backend/src/ee/services/identity-project-additional-privilege-v2/identity-project-additional-privilege-v2-service.ts index 32c32fbe3..e1375744e 100644 --- a/backend/src/ee/services/identity-project-additional-privilege-v2/identity-project-additional-privilege-v2-service.ts +++ b/backend/src/ee/services/identity-project-additional-privilege-v2/identity-project-additional-privilege-v2-service.ts @@ -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 } diff --git a/backend/src/ee/services/identity-project-additional-privilege/identity-project-additional-privilege-service.ts b/backend/src/ee/services/identity-project-additional-privilege/identity-project-additional-privilege-service.ts index be3d60e6a..486ea3451 100644 --- a/backend/src/ee/services/identity-project-additional-privilege/identity-project-additional-privilege-service.ts +++ b/backend/src/ee/services/identity-project-additional-privilege/identity-project-additional-privilege-service.ts @@ -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 } diff --git a/backend/src/ee/services/permission/org-permission.ts b/backend/src/ee/services/permission/org-permission.ts index 8b0292664..17b4e7f6c 100644 --- a/backend/src/ee/services/permission/org-permission.ts +++ b/backend/src/ee/services/permission/org-permission.ts @@ -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); diff --git a/backend/src/ee/services/permission/project-permission.ts b/backend/src/ee/services/permission/project-permission.ts index 95d16e473..2637db994 100644 --- a/backend/src/ee/services/permission/project-permission.ts +++ b/backend/src/ee/services/permission/project-permission.ts @@ -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 ); diff --git a/backend/src/ee/services/project-user-additional-privilege/project-user-additional-privilege-service.ts b/backend/src/ee/services/project-user-additional-privilege/project-user-additional-privilege-service.ts index 388786e82..c592b7afa 100644 --- a/backend/src/ee/services/project-user-additional-privilege/project-user-additional-privilege-service.ts +++ b/backend/src/ee/services/project-user-additional-privilege/project-user-additional-privilege-service.ts @@ -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 } diff --git a/backend/src/lib/errors/index.ts b/backend/src/lib/errors/index.ts index 950bfd29f..a5df64caf 100644 --- a/backend/src/lib/errors/index.ts +++ b/backend/src/lib/errors/index.ts @@ -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; diff --git a/backend/src/server/plugins/error-handler.ts b/backend/src/server/plugins/error-handler.ts index 0fd18bc29..c8170a023 100644 --- a/backend/src/server/plugins/error-handler.ts +++ b/backend/src/server/plugins/error-handler.ts @@ -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, diff --git a/backend/src/services/group-project/group-project-service.ts b/backend/src/services/group-project/group-project-service.ts index 4849b2083..1ff2c78d2 100644 --- a/backend/src/services/group-project/group-project-service.ts +++ b/backend/src/services/group-project/group-project-service.ts @@ -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 } diff --git a/backend/src/services/identity-aws-auth/identity-aws-auth-service.ts b/backend/src/services/identity-aws-auth/identity-aws-auth-service.ts index 8fa34f533..130cd6b74 100644 --- a/backend/src/services/identity-aws-auth/identity-aws-auth-service.ts +++ b/backend/src/services/identity-aws-auth/identity-aws-auth-service.ts @@ -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, diff --git a/backend/src/services/identity-azure-auth/identity-azure-auth-service.ts b/backend/src/services/identity-azure-auth/identity-azure-auth-service.ts index 07a5c0d01..5baa00652 100644 --- a/backend/src/services/identity-azure-auth/identity-azure-auth-service.ts +++ b/backend/src/services/identity-azure-auth/identity-azure-auth-service.ts @@ -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, diff --git a/backend/src/services/identity-gcp-auth/identity-gcp-auth-service.ts b/backend/src/services/identity-gcp-auth/identity-gcp-auth-service.ts index d86f925b7..7420b61cf 100644 --- a/backend/src/services/identity-gcp-auth/identity-gcp-auth-service.ts +++ b/backend/src/services/identity-gcp-auth/identity-gcp-auth-service.ts @@ -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, diff --git a/backend/src/services/identity-jwt-auth/identity-jwt-auth-service.ts b/backend/src/services/identity-jwt-auth/identity-jwt-auth-service.ts index 82c9d06da..39fc28ad2 100644 --- a/backend/src/services/identity-jwt-auth/identity-jwt-auth-service.ts +++ b/backend/src/services/identity-jwt-auth/identity-jwt-auth-service.ts @@ -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, diff --git a/backend/src/services/identity-kubernetes-auth/identity-kubernetes-auth-service.ts b/backend/src/services/identity-kubernetes-auth/identity-kubernetes-auth-service.ts index c61612bfb..c006567d8 100644 --- a/backend/src/services/identity-kubernetes-auth/identity-kubernetes-auth-service.ts +++ b/backend/src/services/identity-kubernetes-auth/identity-kubernetes-auth-service.ts @@ -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, diff --git a/backend/src/services/identity-oidc-auth/identity-oidc-auth-service.ts b/backend/src/services/identity-oidc-auth/identity-oidc-auth-service.ts index 002616f45..0d0aa4504 100644 --- a/backend/src/services/identity-oidc-auth/identity-oidc-auth-service.ts +++ b/backend/src/services/identity-oidc-auth/identity-oidc-auth-service.ts @@ -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, diff --git a/backend/src/services/identity-project/identity-project-service.ts b/backend/src/services/identity-project/identity-project-service.ts index bba30d7bc..ba63f7afd 100644 --- a/backend/src/services/identity-project/identity-project-service.ts +++ b/backend/src/services/identity-project/identity-project-service.ts @@ -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 } diff --git a/backend/src/services/identity-token-auth/identity-token-auth-service.ts b/backend/src/services/identity-token-auth/identity-token-auth-service.ts index 7cfbfc592..549512452 100644 --- a/backend/src/services/identity-token-auth/identity-token-auth-service.ts +++ b/backend/src/services/identity-token-auth/identity-token-auth-service.ts @@ -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, diff --git a/backend/src/services/identity-ua/identity-ua-service.ts b/backend/src/services/identity-ua/identity-ua-service.ts index 117249580..701d87d36 100644 --- a/backend/src/services/identity-ua/identity-ua-service.ts +++ b/backend/src/services/identity-ua/identity-ua-service.ts @@ -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, diff --git a/backend/src/services/identity/identity-service.ts b/backend/src/services/identity/identity-service.ts index d06572d04..f9185ba9d 100644 --- a/backend/src/services/identity/identity-service.ts +++ b/backend/src/services/identity/identity-service.ts @@ -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 } diff --git a/backend/src/services/org/org-service.ts b/backend/src/services/org/org-service.ts index eeb0e09ac..ba7d9dac9 100644 --- a/backend/src/services/org/org-service.ts +++ b/backend/src/services/org/org-service.ts @@ -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 } diff --git a/backend/src/services/project-membership/project-membership-service.ts b/backend/src/services/project-membership/project-membership-service.ts index 98c2b1d3b..f452e381f 100644 --- a/backend/src/services/project-membership/project-membership-service.ts +++ b/backend/src/services/project-membership/project-membership-service.ts @@ -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 } diff --git a/docs/internals/permissions/organization-permissions.mdx b/docs/internals/permissions/organization-permissions.mdx index 2daa90c4e..c68d845e2 100644 --- a/docs/internals/permissions/organization-permissions.mdx +++ b/docs/internals/permissions/organization-permissions.mdx @@ -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 | diff --git a/docs/internals/permissions/project-permissions.mdx b/docs/internals/permissions/project-permissions.mdx index ea3b08fea..a24f6d782 100644 --- a/docs/internals/permissions/project-permissions.mdx +++ b/docs/internals/permissions/project-permissions.mdx @@ -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 | \ No newline at end of file +| `delete` | Remove SSH certificate templates | diff --git a/frontend/src/context/OrgPermissionContext/types.ts b/frontend/src/context/OrgPermissionContext/types.ts index 2c742db14..1c2de52e2 100644 --- a/frontend/src/context/OrgPermissionContext/types.ts +++ b/frontend/src/context/OrgPermissionContext/types.ts @@ -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" } diff --git a/frontend/src/context/ProjectPermissionContext/types.ts b/frontend/src/context/ProjectPermissionContext/types.ts index 0e09a3a12..fb74e675c 100644 --- a/frontend/src/context/ProjectPermissionContext/types.ts +++ b/frontend/src/context/ProjectPermissionContext/types.ts @@ -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 { diff --git a/frontend/src/pages/organization/AccessManagementPage/components/UpgradePrivilegeSystemModal/UpgradePrivilegeSystemModal.tsx b/frontend/src/pages/organization/AccessManagementPage/components/UpgradePrivilegeSystemModal/UpgradePrivilegeSystemModal.tsx index be778f71d..2a92089e5 100644 --- a/frontend/src/pages/organization/AccessManagementPage/components/UpgradePrivilegeSystemModal/UpgradePrivilegeSystemModal.tsx +++ b/frontend/src/pages/organization/AccessManagementPage/components/UpgradePrivilegeSystemModal/UpgradePrivilegeSystemModal.tsx @@ -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) => {step === "info" ? ( - <> -
-

- We've developed an improved privilege management system that enhances how access controls work in your organization. -

+
+

+ We've developed an improved privilege management system that enhances how access + controls work in your organization. +

-
+
+
-
-

- Current system: - 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's access without receiving broader administrative powers. -

-

- New system: Users need explicit permission to modify specific - access levels, providing targeted control. After upgrading, you'll need to - grant the new 'Manage Privileges' permission. At the organization level, - this is available for the{" "} - - Group - {" "} - and{" "} - - Identity - {" "} - subjects while at the project level, this is available for the{" "} - - Member, - {" "} - - Group, - {" "} - and{" "} - - Identity - {" "} - subjects. -

-
+

+ Current system: + 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's access + without receiving broader administrative powers. +

+

+ New system: Users need explicit permission to modify specific + access levels, providing targeted control. After upgrading, you'll need to + grant the new 'Grant Privileges' permission. At the organization + level, this is available for the{" "} + + Group + {" "} + and{" "} + + Identity + {" "} + subjects while at the project level, this is available for the{" "} + + Member, + {" "} + + Group, + {" "} + and{" "} + + Identity + {" "} + subjects. +

- -
- -
- + +
+ +
+
) : (

- 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.

@@ -168,9 +169,9 @@ export const UpgradePrivilegeSystemModal = ({ isOpen, onOpenChange }: Props) =>

- Once upgraded, your organization cannot revert to the - legacy privilege system. Please ensure you've completed all preparations before - proceeding. + Once upgraded, your organization cannot revert to + the legacy privilege system. Please ensure you've completed all preparations + before proceeding.

@@ -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 )} /> @@ -265,6 +266,7 @@ export const UpgradePrivilegeSystemModal = ({ isOpen, onOpenChange }: Props) =>