Merge remote-tracking branch 'origin/main' into misc/privilege-management-v2-transition

This commit is contained in:
Sheen Capadngan
2025-03-10 15:35:48 +08:00
41 changed files with 1625 additions and 458 deletions
@@ -102,16 +102,18 @@ export const groupProjectServiceFactory = ({
project.id
);
const hasRequiredPrivileges = validatePrivilegeChangeOperation(
const permissionBoundary = validatePrivilegeChangeOperation(
ProjectPermissionGroupActions.ManagePrivileges,
ProjectPermissionSub.Groups,
permission,
rolePermission
);
if (!hasRequiredPrivileges) {
throw new ForbiddenRequestError({ message: "Failed to assign group to a more privileged role" });
}
if (!permissionBoundary.isValid)
throw new ForbiddenRequestError({
name: "PermissionBoundaryError",
message: "Failed to assign group to a more privileged role",
details: { missingPermissions: permissionBoundary.missingPermissions }
});
}
// validate custom roles input
@@ -272,17 +274,18 @@ export const groupProjectServiceFactory = ({
requestedRoleChange,
project.id
);
const hasRequiredPrivileges = validatePrivilegeChangeOperation(
const permissionBoundary = validatePrivilegeChangeOperation(
ProjectPermissionGroupActions.ManagePrivileges,
ProjectPermissionSub.Groups,
permission,
rolePermission
);
if (!hasRequiredPrivileges) {
throw new ForbiddenRequestError({ message: "Failed to assign group to a more privileged role" });
}
if (!permissionBoundary.isValid)
throw new ForbiddenRequestError({
name: "PermissionBoundaryError",
message: "Failed to assign group to a more privileged role",
details: { missingPermissions: permissionBoundary.missingPermissions }
});
}
// validate custom roles input
@@ -339,16 +339,17 @@ export const identityAwsAuthServiceFactory = ({
actorOrgId
);
if (
!validatePrivilegeChangeOperation(
OrgPermissionIdentityActions.RevokeAuth,
OrgPermissionSubjects.Identity,
permission,
rolePermission
)
)
const permissionBoundary = validatePrivilegeChangeOperation(
OrgPermissionIdentityActions.RevokeAuth,
OrgPermissionSubjects.Identity,
permission,
rolePermission
);
if (!permissionBoundary.isValid)
throw new ForbiddenRequestError({
message: "Failed to revoke aws auth of identity with more privileged role"
name: "PermissionBoundaryError",
message: "Failed to revoke aws auth of identity with more privileged role",
details: { missingPermissions: permissionBoundary.missingPermissions }
});
const revokedIdentityAwsAuth = await identityAwsAuthDAL.transaction(async (tx) => {
@@ -312,17 +312,17 @@ export const identityAzureAuthServiceFactory = ({
actorAuthMethod,
actorOrgId
);
if (
!validatePrivilegeChangeOperation(
OrgPermissionIdentityActions.RevokeAuth,
OrgPermissionSubjects.Identity,
permission,
rolePermission
)
)
const permissionBoundary = validatePrivilegeChangeOperation(
OrgPermissionIdentityActions.RevokeAuth,
OrgPermissionSubjects.Identity,
permission,
rolePermission
);
if (!permissionBoundary.isValid)
throw new ForbiddenRequestError({
message: "Failed to revoke azure auth of identity with more privileged role"
name: "PermissionBoundaryError",
message: "Failed to revoke azure auth of identity with more privileged role",
details: { missingPermissions: permissionBoundary.missingPermissions }
});
const revokedIdentityAzureAuth = await identityAzureAuthDAL.transaction(async (tx) => {
@@ -358,17 +358,17 @@ export const identityGcpAuthServiceFactory = ({
actorAuthMethod,
actorOrgId
);
const hasRequiredPrivileges = validatePrivilegeChangeOperation(
const permissionBoundary = validatePrivilegeChangeOperation(
OrgPermissionIdentityActions.RevokeAuth,
OrgPermissionSubjects.Identity,
permission,
rolePermission
);
if (!hasRequiredPrivileges)
if (!permissionBoundary.isValid)
throw new ForbiddenRequestError({
message: "Failed to revoke gcp auth of identity with more privileged role"
name: "PermissionBoundaryError",
message: "Failed to revoke gcp auth of identity with more privileged role",
details: { missingPermissions: permissionBoundary.missingPermissions }
});
const revokedIdentityGcpAuth = await identityGcpAuthDAL.transaction(async (tx) => {
@@ -508,19 +508,18 @@ export const identityJwtAuthServiceFactory = ({
actorOrgId
);
// revoke auth identity - org permission
if (
!validatePrivilegeChangeOperation(
OrgPermissionIdentityActions.RevokeAuth,
OrgPermissionSubjects.Identity,
permission,
rolePermission
)
) {
const permissionBoundary = validatePrivilegeChangeOperation(
OrgPermissionIdentityActions.RevokeAuth,
OrgPermissionSubjects.Identity,
permission,
rolePermission
);
if (!permissionBoundary.isValid)
throw new ForbiddenRequestError({
message: "Failed to revoke JWT auth of identity with more privileged role"
name: "PermissionBoundaryError",
message: "Failed to revoke jwt auth of identity with more privileged role",
details: { missingPermissions: permissionBoundary.missingPermissions }
});
}
const revokedIdentityJwtAuth = await identityJwtAuthDAL.transaction(async (tx) => {
const deletedJwtAuth = await identityJwtAuthDAL.delete({ identityId }, tx);
@@ -487,17 +487,17 @@ export const identityKubernetesAuthServiceFactory = ({
actorAuthMethod,
actorOrgId
);
if (
!validatePrivilegeChangeOperation(
OrgPermissionIdentityActions.RevokeAuth,
OrgPermissionSubjects.Identity,
permission,
rolePermission
)
)
const permissionBoundary = validatePrivilegeChangeOperation(
OrgPermissionIdentityActions.RevokeAuth,
OrgPermissionSubjects.Identity,
permission,
rolePermission
);
if (!permissionBoundary.isValid)
throw new ForbiddenRequestError({
message: "Failed to revoke kubernetes auth of identity with more privileged role"
name: "PermissionBoundaryError",
message: "Failed to revoke kubernetes auth of identity with more privileged role",
details: { missingPermissions: permissionBoundary.missingPermissions }
});
const revokedIdentityKubernetesAuth = await identityKubernetesAuthDAL.transaction(async (tx) => {
@@ -428,18 +428,18 @@ export const identityOidcAuthServiceFactory = ({
actorOrgId
);
if (
!validatePrivilegeChangeOperation(
OrgPermissionIdentityActions.RevokeAuth,
OrgPermissionSubjects.Identity,
permission,
rolePermission
)
) {
const permissionBoundary = validatePrivilegeChangeOperation(
OrgPermissionIdentityActions.RevokeAuth,
OrgPermissionSubjects.Identity,
permission,
rolePermission
);
if (!permissionBoundary.isValid)
throw new ForbiddenRequestError({
message: "Failed to revoke OIDC auth of identity with more privileged role"
name: "PermissionBoundaryError",
message: "Failed to revoke oidc auth of identity with more privileged role",
details: { missingPermissions: permissionBoundary.missingPermissions }
});
}
const revokedIdentityOidcAuth = await identityOidcAuthDAL.transaction(async (tx) => {
const deletedOidcAuth = await identityOidcAuthDAL.delete({ identityId }, tx);
@@ -90,16 +90,18 @@ export const identityProjectServiceFactory = ({
projectId
);
const hasRequiredPriviledges = validatePrivilegeChangeOperation(
const permissionBoundary = validatePrivilegeChangeOperation(
ProjectPermissionIdentityActions.ManagePrivileges,
ProjectPermissionSub.Identity,
permission,
rolePermission
);
if (!hasRequiredPriviledges) {
throw new ForbiddenRequestError({ message: "Failed to change to a more privileged role" });
}
if (!permissionBoundary.isValid)
throw new ForbiddenRequestError({
name: "PermissionBoundaryError",
message: "Failed to assign to a more privileged role",
details: { missingPermissions: permissionBoundary.missingPermissions }
});
}
// validate custom roles input
@@ -189,15 +191,18 @@ export const identityProjectServiceFactory = ({
projectId
);
const hasRequiredPriviledges = validatePrivilegeChangeOperation(
const permissionBoundary = validatePrivilegeChangeOperation(
ProjectPermissionIdentityActions.ManagePrivileges,
ProjectPermissionSub.Identity,
permission,
rolePermission
);
if (!hasRequiredPriviledges) {
throw new ForbiddenRequestError({ message: "Failed to change to a more privileged role" });
}
if (!permissionBoundary.isValid)
throw new ForbiddenRequestError({
name: "PermissionBoundaryError",
message: "Failed to change to a more privileged role",
details: { missingPermissions: permissionBoundary.missingPermissions }
});
}
// validate custom roles input
@@ -245,18 +245,18 @@ export const identityTokenAuthServiceFactory = ({
actorOrgId
);
if (
!validatePrivilegeChangeOperation(
OrgPermissionIdentityActions.RevokeAuth,
OrgPermissionSubjects.Identity,
permission,
rolePermission
)
) {
const permissionBoundary = validatePrivilegeChangeOperation(
OrgPermissionIdentityActions.RevokeAuth,
OrgPermissionSubjects.Identity,
permission,
rolePermission
);
if (!permissionBoundary.isValid)
throw new ForbiddenRequestError({
message: "Failed to revoke Token Auth of identity with more privileged role"
name: "PermissionBoundaryError",
message: "Failed to revoke token auth of identity with more privileged role",
details: { missingPermissions: permissionBoundary.missingPermissions }
});
}
const revokedIdentityTokenAuth = await identityTokenAuthDAL.transaction(async (tx) => {
const deletedTokenAuth = await identityTokenAuthDAL.delete({ identityId }, tx);
@@ -303,16 +303,17 @@ export const identityTokenAuthServiceFactory = ({
actorOrgId
);
const hasPriviledge = validatePrivilegeChangeOperation(
const permissionBoundary = validatePrivilegeChangeOperation(
OrgPermissionIdentityActions.CreateToken,
OrgPermissionSubjects.Identity,
permission,
rolePermission
);
if (!hasPriviledge)
if (!permissionBoundary.isValid)
throw new ForbiddenRequestError({
message: "Failed to create token for identity with more privileged role"
name: "PermissionBoundaryError",
message: "Failed to create token for identity with more privileged role",
details: { missingPermissions: permissionBoundary.missingPermissions }
});
const identityTokenAuth = await identityTokenAuthDAL.findOne({ identityId });
@@ -429,17 +430,17 @@ export const identityTokenAuthServiceFactory = ({
actorAuthMethod,
actorOrgId
);
const hasPriviledge = validatePrivilegeChangeOperation(
const permissionBoundary = validatePrivilegeChangeOperation(
OrgPermissionIdentityActions.CreateToken,
OrgPermissionSubjects.Identity,
permission,
rolePermission
);
if (!hasPriviledge)
if (!permissionBoundary.isValid)
throw new ForbiddenRequestError({
message: "Failed to update token for identity with more privileged role"
name: "PermissionBoundaryError",
message: "Failed to update token for identity with more privileged role",
details: { missingPermissions: permissionBoundary.missingPermissions }
});
const [token] = await identityAccessTokenDAL.update(
@@ -367,17 +367,17 @@ export const identityUaServiceFactory = ({
actorAuthMethod,
actorOrgId
);
if (
!validatePrivilegeChangeOperation(
OrgPermissionIdentityActions.RevokeAuth,
OrgPermissionSubjects.Identity,
permission,
rolePermission
)
)
const permissionBoundary = validatePrivilegeChangeOperation(
OrgPermissionIdentityActions.RevokeAuth,
OrgPermissionSubjects.Identity,
permission,
rolePermission
);
if (!permissionBoundary.isValid)
throw new ForbiddenRequestError({
message: "Failed to revoke universal auth of identity with more privileged role"
name: "PermissionBoundaryError",
message: "Failed to revoke universal auth of identity with more privileged role",
details: { missingPermissions: permissionBoundary.missingPermissions }
});
const revokedIdentityUniversalAuth = await identityUaDAL.transaction(async (tx) => {
@@ -422,17 +422,17 @@ export const identityUaServiceFactory = ({
actorAuthMethod,
actorOrgId
);
if (
!validatePrivilegeChangeOperation(
OrgPermissionIdentityActions.CreateToken,
OrgPermissionSubjects.Identity,
permission,
rolePermission
)
)
const permissionBoundary = validatePrivilegeChangeOperation(
OrgPermissionIdentityActions.CreateToken,
OrgPermissionSubjects.Identity,
permission,
rolePermission
);
if (!permissionBoundary.isValid)
throw new ForbiddenRequestError({
message: "Failed to add identity to project with more privileged role"
name: "PermissionBoundaryError",
message: "Failed to create client secret for a more privileged identity.",
details: { missingPermissions: permissionBoundary.missingPermissions }
});
const appCfg = getConfig();
@@ -490,16 +490,17 @@ export const identityUaServiceFactory = ({
actorOrgId
);
if (
!validatePrivilegeChangeOperation(
OrgPermissionIdentityActions.GetToken,
OrgPermissionSubjects.Identity,
permission,
rolePermission
)
)
const permissionBoundary = validatePrivilegeChangeOperation(
OrgPermissionIdentityActions.GetToken,
OrgPermissionSubjects.Identity,
permission,
rolePermission
);
if (!permissionBoundary.isValid)
throw new ForbiddenRequestError({
message: "Failed to get identity client secret with more privileged role"
name: "PermissionBoundaryError",
message: "Failed to get identity client secret with more privileged role",
details: { missingPermissions: permissionBoundary.missingPermissions }
});
const identityUniversalAuth = await identityUaDAL.findOne({
@@ -546,17 +547,17 @@ export const identityUaServiceFactory = ({
actorAuthMethod,
actorOrgId
);
if (
!validatePrivilegeChangeOperation(
OrgPermissionIdentityActions.GetToken,
OrgPermissionSubjects.Identity,
permission,
rolePermission
)
)
const permissionBoundary = validatePrivilegeChangeOperation(
OrgPermissionIdentityActions.GetToken,
OrgPermissionSubjects.Identity,
permission,
rolePermission
);
if (!permissionBoundary.isValid)
throw new ForbiddenRequestError({
message: "Failed to read identity client secret of project with more privileged role"
name: "PermissionBoundaryError",
message: "Failed to read identity client secret of identity with more privileged role",
details: { missingPermissions: permissionBoundary.missingPermissions }
});
const clientSecret = await identityUaClientSecretDAL.findById(clientSecretId);
@@ -597,22 +598,24 @@ export const identityUaServiceFactory = ({
actorOrgId
);
if (
!validatePrivilegeChangeOperation(
OrgPermissionIdentityActions.DeleteToken,
OrgPermissionSubjects.Identity,
permission,
rolePermission
)
) {
const permissionBoundary = validatePrivilegeChangeOperation(
OrgPermissionIdentityActions.DeleteToken,
OrgPermissionSubjects.Identity,
permission,
rolePermission
);
if (!permissionBoundary.isValid) {
throw new ForbiddenRequestError({
message: "Failed to revoke identity client secret with more privileged role"
name: "PermissionBoundaryError",
message: "Failed to revoke identity client secret with more privileged role",
details: { missingPermissions: permissionBoundary.missingPermissions }
});
}
const clientSecret = await identityUaClientSecretDAL.updateById(clientSecretId, {
isClientSecretRevoked: true
});
return { ...clientSecret, identityId, orgId: identityMembershipOrg.orgId };
};
@@ -57,14 +57,18 @@ export const identityServiceFactory = ({
orgId
);
const isCustomRole = Boolean(customRole);
const hasRequiredPriviledges = validatePrivilegeChangeOperation(
const permissionBoundary = validatePrivilegeChangeOperation(
OrgPermissionIdentityActions.ManagePrivileges,
OrgPermissionSubjects.Identity,
permission,
rolePermission
);
if (!hasRequiredPriviledges)
throw new ForbiddenRequestError({ message: "Failed to create a more privileged identity" });
if (!permissionBoundary.isValid)
throw new ForbiddenRequestError({
name: "PermissionBoundaryError",
message: "Failed to create a more privileged identity",
details: { missingPermissions: permissionBoundary.missingPermissions }
});
const plan = await licenseService.getPlan(orgId);
@@ -134,15 +138,18 @@ export const identityServiceFactory = ({
);
const isCustomRole = Boolean(customOrgRole);
const hasRequiredNewRolePermission = validatePrivilegeChangeOperation(
const appliedRolePermissionBoundary = validatePrivilegeChangeOperation(
OrgPermissionIdentityActions.ManagePrivileges,
OrgPermissionSubjects.Identity,
permission,
rolePermission
);
if (!hasRequiredNewRolePermission)
throw new ForbiddenRequestError({ message: "Failed to create a more privileged identity" });
if (!appliedRolePermissionBoundary.isValid)
throw new ForbiddenRequestError({
name: "PermissionBoundaryError",
message: "Failed to create a more privileged identity",
details: { missingPermissions: appliedRolePermissionBoundary.missingPermissions }
});
if (isCustomRole) customRole = customOrgRole;
}
@@ -207,6 +214,7 @@ export const identityServiceFactory = ({
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionIdentityActions.Delete, OrgPermissionSubjects.Identity);
const deletedIdentity = await identityDAL.deleteById(id);
@@ -274,18 +274,18 @@ export const projectMembershipServiceFactory = ({
projectId
);
const hasRequiredPriviledges = validatePrivilegeChangeOperation(
const permissionBoundary = validatePrivilegeChangeOperation(
ProjectPermissionMemberActions.ManagePrivileges,
ProjectPermissionSub.Member,
permission,
rolePermission
);
if (!hasRequiredPriviledges) {
if (!permissionBoundary.isValid)
throw new ForbiddenRequestError({
message: `Failed to change to a more privileged role ${requestedRoleChange}`
name: "PermissionBoundaryError",
message: `Failed to change to a more privileged role ${requestedRoleChange}`,
details: { missingPermissions: permissionBoundary.missingPermissions }
});
}
}
// validate custom roles input