feat: completed conditional rendering of identity for sub org

This commit is contained in:
=
2025-10-20 18:58:22 +05:30
parent b7644c9294
commit 03e4918362
20 changed files with 329 additions and 65 deletions
+1
View File
@@ -1583,6 +1583,7 @@ export const registerRoutes = async (
}); });
const identityService = identityServiceFactory({ const identityService = identityServiceFactory({
additionalPrivilegeDAL,
permissionService, permissionService,
identityDAL, identityDAL,
identityOrgMembershipDAL, identityOrgMembershipDAL,
@@ -249,7 +249,7 @@ export const registerIdentityRouter = async (server: FastifyZodProvider) => {
permissions: true, permissions: true,
description: true description: true
}).optional(), }).optional(),
identity: IdentitiesSchema.pick({ name: true, id: true, hasDeleteProtection: true }).extend({ identity: IdentitiesSchema.pick({ name: true, id: true, hasDeleteProtection: true, orgId: true }).extend({
authMethods: z.array(z.string()), authMethods: z.array(z.string()),
activeLockoutAuthMethods: z.array(z.string()) activeLockoutAuthMethods: z.array(z.string())
}) })
@@ -13,7 +13,13 @@ import { TPermissionServiceFactory } from "@app/ee/services/permission/permissio
import { getConfig } from "@app/lib/config/env"; import { getConfig } from "@app/lib/config/env";
import { request } from "@app/lib/config/request"; import { request } from "@app/lib/config/request";
import { crypto } from "@app/lib/crypto"; import { crypto } from "@app/lib/crypto";
import { BadRequestError, NotFoundError, PermissionBoundaryError, UnauthorizedError } from "@app/lib/errors"; import {
BadRequestError,
ForbiddenRequestError,
NotFoundError,
PermissionBoundaryError,
UnauthorizedError
} from "@app/lib/errors";
import { extractIPDetails, isValidIpOrCidr } from "@app/lib/ip"; import { extractIPDetails, isValidIpOrCidr } from "@app/lib/ip";
import { logger } from "@app/lib/logger"; import { logger } from "@app/lib/logger";
@@ -162,6 +168,9 @@ export const identityAliCloudAuthServiceFactory = ({
identityId identityId
}); });
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (identityMembershipOrg.identity.identityOrgId !== actorOrgId) {
throw new ForbiddenRequestError({ message: "Sub organization not authorized to access this identity" });
}
if (identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.ALICLOUD_AUTH)) { if (identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.ALICLOUD_AUTH)) {
throw new BadRequestError({ throw new BadRequestError({
@@ -239,6 +248,9 @@ export const identityAliCloudAuthServiceFactory = ({
identityId identityId
}); });
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (identityMembershipOrg.identity.identityOrgId !== actorOrgId) {
throw new ForbiddenRequestError({ message: "Sub organization not authorized to access this identity" });
}
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.ALICLOUD_AUTH)) { if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.ALICLOUD_AUTH)) {
throw new NotFoundError({ throw new NotFoundError({
@@ -306,6 +318,9 @@ export const identityAliCloudAuthServiceFactory = ({
identityId identityId
}); });
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (identityMembershipOrg.identity.identityOrgId !== actorOrgId) {
throw new ForbiddenRequestError({ message: "Sub organization not authorized to access this identity" });
}
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.ALICLOUD_AUTH)) { if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.ALICLOUD_AUTH)) {
throw new BadRequestError({ throw new BadRequestError({
@@ -342,6 +357,9 @@ export const identityAliCloudAuthServiceFactory = ({
identityId identityId
}); });
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (identityMembershipOrg.identity.identityOrgId !== actorOrgId) {
throw new ForbiddenRequestError({ message: "Sub organization not authorized to access this identity" });
}
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.ALICLOUD_AUTH)) { if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.ALICLOUD_AUTH)) {
throw new BadRequestError({ throw new BadRequestError({
message: "The identity does not have Alibaba Cloud auth" message: "The identity does not have Alibaba Cloud auth"
@@ -13,7 +13,13 @@ import {
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types"; import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types";
import { getConfig } from "@app/lib/config/env"; import { getConfig } from "@app/lib/config/env";
import { crypto } from "@app/lib/crypto"; import { crypto } from "@app/lib/crypto";
import { BadRequestError, NotFoundError, PermissionBoundaryError, UnauthorizedError } from "@app/lib/errors"; import {
BadRequestError,
ForbiddenRequestError,
NotFoundError,
PermissionBoundaryError,
UnauthorizedError
} from "@app/lib/errors";
import { extractIPDetails, isValidIpOrCidr } from "@app/lib/ip"; import { extractIPDetails, isValidIpOrCidr } from "@app/lib/ip";
import { ActorType, AuthTokenType } from "../auth/auth-type"; import { ActorType, AuthTokenType } from "../auth/auth-type";
@@ -240,6 +246,9 @@ export const identityAwsAuthServiceFactory = ({
identityId identityId
}); });
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (identityMembershipOrg.identity.identityOrgId !== actorOrgId) {
throw new ForbiddenRequestError({ message: "Sub organization not authorized to access this identity" });
}
if (identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.AWS_AUTH)) { if (identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.AWS_AUTH)) {
throw new BadRequestError({ throw new BadRequestError({
@@ -321,6 +330,9 @@ export const identityAwsAuthServiceFactory = ({
identityId identityId
}); });
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (identityMembershipOrg.identity.identityOrgId !== actorOrgId) {
throw new ForbiddenRequestError({ message: "Sub organization not authorized to access this identity" });
}
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.AWS_AUTH)) { if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.AWS_AUTH)) {
throw new NotFoundError({ throw new NotFoundError({
@@ -389,6 +401,9 @@ export const identityAwsAuthServiceFactory = ({
identityId identityId
}); });
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (identityMembershipOrg.identity.identityOrgId !== actorOrgId) {
throw new ForbiddenRequestError({ message: "Sub organization not authorized to access this identity" });
}
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.AWS_AUTH)) { if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.AWS_AUTH)) {
throw new BadRequestError({ throw new BadRequestError({
@@ -425,6 +440,9 @@ export const identityAwsAuthServiceFactory = ({
identityId identityId
}); });
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (identityMembershipOrg.identity.identityOrgId !== actorOrgId) {
throw new ForbiddenRequestError({ message: "Sub organization not authorized to access this identity" });
}
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.AWS_AUTH)) { if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.AWS_AUTH)) {
throw new BadRequestError({ throw new BadRequestError({
message: "The identity does not have aws auth" message: "The identity does not have aws auth"
@@ -10,7 +10,13 @@ import {
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types"; import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types";
import { getConfig } from "@app/lib/config/env"; import { getConfig } from "@app/lib/config/env";
import { crypto } from "@app/lib/crypto"; import { crypto } from "@app/lib/crypto";
import { BadRequestError, NotFoundError, PermissionBoundaryError, UnauthorizedError } from "@app/lib/errors"; import {
BadRequestError,
ForbiddenRequestError,
NotFoundError,
PermissionBoundaryError,
UnauthorizedError
} from "@app/lib/errors";
import { extractIPDetails, isValidIpOrCidr } from "@app/lib/ip"; import { extractIPDetails, isValidIpOrCidr } from "@app/lib/ip";
import { ActorType, AuthTokenType } from "../auth/auth-type"; import { ActorType, AuthTokenType } from "../auth/auth-type";
@@ -153,6 +159,9 @@ export const identityAzureAuthServiceFactory = ({
identityId identityId
}); });
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (identityMembershipOrg.identity.identityOrgId !== actorOrgId) {
throw new ForbiddenRequestError({ message: "Sub organization not authorized to access this identity" });
}
if (identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.AZURE_AUTH)) { if (identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.AZURE_AUTH)) {
throw new BadRequestError({ throw new BadRequestError({
@@ -233,6 +242,9 @@ export const identityAzureAuthServiceFactory = ({
identityId identityId
}); });
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (identityMembershipOrg.identity.identityOrgId !== actorOrgId) {
throw new ForbiddenRequestError({ message: "Sub organization not authorized to access this identity" });
}
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.AZURE_AUTH)) { if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.AZURE_AUTH)) {
throw new BadRequestError({ throw new BadRequestError({
message: "Failed to update Azure Auth" message: "Failed to update Azure Auth"
@@ -303,6 +315,9 @@ export const identityAzureAuthServiceFactory = ({
identityId identityId
}); });
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (identityMembershipOrg.identity.identityOrgId !== actorOrgId) {
throw new ForbiddenRequestError({ message: "Sub organization not authorized to access this identity" });
}
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.AZURE_AUTH)) { if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.AZURE_AUTH)) {
throw new BadRequestError({ throw new BadRequestError({
message: "The identity does not have Azure Auth attached" message: "The identity does not have Azure Auth attached"
@@ -339,6 +354,9 @@ export const identityAzureAuthServiceFactory = ({
identityId identityId
}); });
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (identityMembershipOrg.identity.identityOrgId !== actorOrgId) {
throw new ForbiddenRequestError({ message: "Sub organization not authorized to access this identity" });
}
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.AZURE_AUTH)) { if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.AZURE_AUTH)) {
throw new BadRequestError({ throw new BadRequestError({
message: "The identity does not have azure auth" message: "The identity does not have azure auth"
@@ -10,7 +10,13 @@ import {
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types"; import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types";
import { getConfig } from "@app/lib/config/env"; import { getConfig } from "@app/lib/config/env";
import { crypto } from "@app/lib/crypto"; import { crypto } from "@app/lib/crypto";
import { BadRequestError, NotFoundError, PermissionBoundaryError, UnauthorizedError } from "@app/lib/errors"; import {
BadRequestError,
ForbiddenRequestError,
NotFoundError,
PermissionBoundaryError,
UnauthorizedError
} from "@app/lib/errors";
import { extractIPDetails, isValidIpOrCidr } from "@app/lib/ip"; import { extractIPDetails, isValidIpOrCidr } from "@app/lib/ip";
import { ActorType, AuthTokenType } from "../auth/auth-type"; import { ActorType, AuthTokenType } from "../auth/auth-type";
@@ -193,6 +199,9 @@ export const identityGcpAuthServiceFactory = ({
identityId identityId
}); });
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (identityMembershipOrg.identity.identityOrgId !== actorOrgId) {
throw new ForbiddenRequestError({ message: "Sub organization not authorized to access this identity" });
}
if (identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.GCP_AUTH)) { if (identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.GCP_AUTH)) {
throw new BadRequestError({ throw new BadRequestError({
@@ -275,6 +284,9 @@ export const identityGcpAuthServiceFactory = ({
identityId identityId
}); });
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (identityMembershipOrg.identity.identityOrgId !== actorOrgId) {
throw new ForbiddenRequestError({ message: "Sub organization not authorized to access this identity" });
}
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.GCP_AUTH)) { if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.GCP_AUTH)) {
throw new BadRequestError({ throw new BadRequestError({
@@ -347,6 +359,9 @@ export const identityGcpAuthServiceFactory = ({
identityId identityId
}); });
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (identityMembershipOrg.identity.identityOrgId !== actorOrgId) {
throw new ForbiddenRequestError({ message: "Sub organization not authorized to access this identity" });
}
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.GCP_AUTH)) { if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.GCP_AUTH)) {
throw new BadRequestError({ throw new BadRequestError({
@@ -384,6 +399,9 @@ export const identityGcpAuthServiceFactory = ({
identityId identityId
}); });
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (identityMembershipOrg.identity.identityOrgId !== actorOrgId) {
throw new ForbiddenRequestError({ message: "Sub organization not authorized to access this identity" });
}
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.GCP_AUTH)) { if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.GCP_AUTH)) {
throw new BadRequestError({ throw new BadRequestError({
@@ -284,6 +284,9 @@ export const identityJwtAuthServiceFactory = ({
identityId identityId
}); });
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (identityMembershipOrg.identity.identityOrgId !== actorOrgId) {
throw new ForbiddenRequestError({ message: "Sub organization not authorized to access this identity" });
}
if (identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.JWT_AUTH)) { if (identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.JWT_AUTH)) {
throw new BadRequestError({ throw new BadRequestError({
message: "Failed to add JWT Auth to already configured identity" message: "Failed to add JWT Auth to already configured identity"
@@ -388,6 +391,9 @@ export const identityJwtAuthServiceFactory = ({
identityId identityId
}); });
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (identityMembershipOrg.identity.identityOrgId !== actorOrgId) {
throw new ForbiddenRequestError({ message: "Sub organization not authorized to access this identity" });
}
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.JWT_AUTH)) { if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.JWT_AUTH)) {
throw new BadRequestError({ throw new BadRequestError({
@@ -493,6 +499,9 @@ export const identityJwtAuthServiceFactory = ({
identityId identityId
}); });
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (identityMembershipOrg.identity.identityOrgId !== actorOrgId) {
throw new ForbiddenRequestError({ message: "Sub organization not authorized to access this identity" });
}
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.JWT_AUTH)) { if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.JWT_AUTH)) {
throw new BadRequestError({ throw new BadRequestError({
@@ -542,6 +551,9 @@ export const identityJwtAuthServiceFactory = ({
if (!identityMembershipOrg) { if (!identityMembershipOrg) {
throw new NotFoundError({ message: "Failed to find identity" }); throw new NotFoundError({ message: "Failed to find identity" });
} }
if (identityMembershipOrg.identity.identityOrgId !== actorOrgId) {
throw new ForbiddenRequestError({ message: "Sub organization not authorized to access this identity" });
}
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.JWT_AUTH)) { if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.JWT_AUTH)) {
throw new BadRequestError({ throw new BadRequestError({
@@ -26,7 +26,13 @@ import {
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types"; import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types";
import { getConfig } from "@app/lib/config/env"; import { getConfig } from "@app/lib/config/env";
import { crypto } from "@app/lib/crypto"; import { crypto } from "@app/lib/crypto";
import { BadRequestError, NotFoundError, PermissionBoundaryError, UnauthorizedError } from "@app/lib/errors"; import {
BadRequestError,
ForbiddenRequestError,
NotFoundError,
PermissionBoundaryError,
UnauthorizedError
} from "@app/lib/errors";
import { GatewayHttpProxyActions, GatewayProxyProtocol, withGatewayProxy } from "@app/lib/gateway"; import { GatewayHttpProxyActions, GatewayProxyProtocol, withGatewayProxy } from "@app/lib/gateway";
import { withGatewayV2Proxy } from "@app/lib/gateway-v2/gateway-v2"; import { withGatewayV2Proxy } from "@app/lib/gateway-v2/gateway-v2";
import { extractIPDetails, isValidIpOrCidr } from "@app/lib/ip"; import { extractIPDetails, isValidIpOrCidr } from "@app/lib/ip";
@@ -513,6 +519,9 @@ export const identityKubernetesAuthServiceFactory = ({
identityId identityId
}); });
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (identityMembershipOrg.identity.identityOrgId !== actorOrgId) {
throw new ForbiddenRequestError({ message: "Sub organization not authorized to access this identity" });
}
if (identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.KUBERNETES_AUTH)) { if (identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.KUBERNETES_AUTH)) {
throw new BadRequestError({ throw new BadRequestError({
@@ -640,6 +649,9 @@ export const identityKubernetesAuthServiceFactory = ({
identityId identityId
}); });
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (identityMembershipOrg.identity.identityOrgId !== actorOrgId) {
throw new ForbiddenRequestError({ message: "Sub organization not authorized to access this identity" });
}
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.KUBERNETES_AUTH)) { if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.KUBERNETES_AUTH)) {
throw new BadRequestError({ throw new BadRequestError({
@@ -788,6 +800,9 @@ export const identityKubernetesAuthServiceFactory = ({
identityId identityId
}); });
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (identityMembershipOrg.identity.identityOrgId !== actorOrgId) {
throw new ForbiddenRequestError({ message: "Sub organization not authorized to access this identity" });
}
const identityKubernetesAuth = await identityKubernetesAuthDAL.findOne({ identityId }); const identityKubernetesAuth = await identityKubernetesAuthDAL.findOne({ identityId });
if (!identityKubernetesAuth) { if (!identityKubernetesAuth) {
@@ -851,6 +866,9 @@ export const identityKubernetesAuthServiceFactory = ({
identityId identityId
}); });
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (identityMembershipOrg.identity.identityOrgId !== actorOrgId) {
throw new ForbiddenRequestError({ message: "Sub organization not authorized to access this identity" });
}
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.KUBERNETES_AUTH)) { if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.KUBERNETES_AUTH)) {
throw new BadRequestError({ throw new BadRequestError({
@@ -21,6 +21,7 @@ import { getConfig } from "@app/lib/config/env";
import { crypto } from "@app/lib/crypto"; import { crypto } from "@app/lib/crypto";
import { import {
BadRequestError, BadRequestError,
ForbiddenRequestError,
NotFoundError, NotFoundError,
PermissionBoundaryError, PermissionBoundaryError,
RateLimitError, RateLimitError,
@@ -254,6 +255,9 @@ export const identityLdapAuthServiceFactory = ({
identityId identityId
}); });
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (identityMembershipOrg.identity.identityOrgId !== actorOrgId) {
throw new ForbiddenRequestError({ message: "Sub organization not authorized to access this identity" });
}
if (identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.LDAP_AUTH)) { if (identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.LDAP_AUTH)) {
throw new BadRequestError({ throw new BadRequestError({
@@ -426,6 +430,9 @@ export const identityLdapAuthServiceFactory = ({
identityId identityId
}); });
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (identityMembershipOrg.identity.identityOrgId !== actorOrgId) {
throw new ForbiddenRequestError({ message: "Sub organization not authorized to access this identity" });
}
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.LDAP_AUTH)) { if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.LDAP_AUTH)) {
throw new NotFoundError({ throw new NotFoundError({
@@ -590,6 +597,9 @@ export const identityLdapAuthServiceFactory = ({
identityId identityId
}); });
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (identityMembershipOrg.identity.identityOrgId !== actorOrgId) {
throw new ForbiddenRequestError({ message: "Sub organization not authorized to access this identity" });
}
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.LDAP_AUTH)) { if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.LDAP_AUTH)) {
throw new BadRequestError({ throw new BadRequestError({
@@ -638,6 +648,9 @@ export const identityLdapAuthServiceFactory = ({
identityId identityId
}); });
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (identityMembershipOrg.identity.identityOrgId !== actorOrgId) {
throw new ForbiddenRequestError({ message: "Sub organization not authorized to access this identity" });
}
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.LDAP_AUTH)) { if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.LDAP_AUTH)) {
throw new BadRequestError({ throw new BadRequestError({
message: "The identity does not have LDAP Auth attached" message: "The identity does not have LDAP Auth attached"
@@ -14,7 +14,13 @@ import { TPermissionServiceFactory } from "@app/ee/services/permission/permissio
import { getConfig } from "@app/lib/config/env"; import { getConfig } from "@app/lib/config/env";
import { request } from "@app/lib/config/request"; import { request } from "@app/lib/config/request";
import { crypto } from "@app/lib/crypto"; import { crypto } from "@app/lib/crypto";
import { BadRequestError, NotFoundError, PermissionBoundaryError, UnauthorizedError } from "@app/lib/errors"; import {
BadRequestError,
ForbiddenRequestError,
NotFoundError,
PermissionBoundaryError,
UnauthorizedError
} from "@app/lib/errors";
import { extractIPDetails, isValidIpOrCidr } from "@app/lib/ip"; import { extractIPDetails, isValidIpOrCidr } from "@app/lib/ip";
import { logger } from "@app/lib/logger"; import { logger } from "@app/lib/logger";
@@ -168,6 +174,9 @@ export const identityOciAuthServiceFactory = ({
identityId identityId
}); });
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (identityMembershipOrg.identity.identityOrgId !== actorOrgId) {
throw new ForbiddenRequestError({ message: "Sub organization not authorized to access this identity" });
}
if (identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.OCI_AUTH)) { if (identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.OCI_AUTH)) {
throw new BadRequestError({ throw new BadRequestError({
@@ -247,6 +256,9 @@ export const identityOciAuthServiceFactory = ({
identityId identityId
}); });
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (identityMembershipOrg.identity.identityOrgId !== actorOrgId) {
throw new ForbiddenRequestError({ message: "Sub organization not authorized to access this identity" });
}
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.OCI_AUTH)) { if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.OCI_AUTH)) {
throw new NotFoundError({ throw new NotFoundError({
@@ -314,6 +326,9 @@ export const identityOciAuthServiceFactory = ({
identityId identityId
}); });
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (identityMembershipOrg.identity.identityOrgId !== actorOrgId) {
throw new ForbiddenRequestError({ message: "Sub organization not authorized to access this identity" });
}
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.OCI_AUTH)) { if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.OCI_AUTH)) {
throw new BadRequestError({ throw new BadRequestError({
@@ -350,6 +365,9 @@ export const identityOciAuthServiceFactory = ({
identityId identityId
}); });
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (identityMembershipOrg.identity.identityOrgId !== actorOrgId) {
throw new ForbiddenRequestError({ message: "Sub organization not authorized to access this identity" });
}
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.OCI_AUTH)) { if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.OCI_AUTH)) {
throw new BadRequestError({ throw new BadRequestError({
message: "The identity does not have OCI auth" message: "The identity does not have OCI auth"
@@ -259,6 +259,9 @@ export const identityOidcAuthServiceFactory = ({
if (!identityMembershipOrg) { if (!identityMembershipOrg) {
throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
} }
if (identityMembershipOrg.identity.identityOrgId !== actorOrgId) {
throw new ForbiddenRequestError({ message: "Sub organization not authorized to access this identity" });
}
if (identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.OIDC_AUTH)) { if (identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.OIDC_AUTH)) {
throw new BadRequestError({ throw new BadRequestError({
message: "Failed to add OIDC Auth to already configured identity" message: "Failed to add OIDC Auth to already configured identity"
@@ -352,6 +355,9 @@ export const identityOidcAuthServiceFactory = ({
identityId identityId
}); });
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (identityMembershipOrg.identity.identityOrgId !== actorOrgId) {
throw new ForbiddenRequestError({ message: "Sub organization not authorized to access this identity" });
}
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.OIDC_AUTH)) { if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.OIDC_AUTH)) {
throw new BadRequestError({ throw new BadRequestError({
@@ -442,6 +448,9 @@ export const identityOidcAuthServiceFactory = ({
identityId identityId
}); });
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (identityMembershipOrg.identity.identityOrgId !== actorOrgId) {
throw new ForbiddenRequestError({ message: "Sub organization not authorized to access this identity" });
}
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.OIDC_AUTH)) { if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.OIDC_AUTH)) {
throw new BadRequestError({ throw new BadRequestError({
@@ -484,6 +493,9 @@ export const identityOidcAuthServiceFactory = ({
if (!identityMembershipOrg) { if (!identityMembershipOrg) {
throw new NotFoundError({ message: "Failed to find identity" }); throw new NotFoundError({ message: "Failed to find identity" });
} }
if (identityMembershipOrg.identity.identityOrgId !== actorOrgId) {
throw new ForbiddenRequestError({ message: "Sub organization not authorized to access this identity" });
}
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.OIDC_AUTH)) { if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.OIDC_AUTH)) {
throw new BadRequestError({ throw new BadRequestError({
@@ -11,7 +11,13 @@ import { TPermissionServiceFactory } from "@app/ee/services/permission/permissio
import { extractX509CertFromChain } from "@app/lib/certificates/extract-certificate"; import { extractX509CertFromChain } from "@app/lib/certificates/extract-certificate";
import { getConfig } from "@app/lib/config/env"; import { getConfig } from "@app/lib/config/env";
import { crypto } from "@app/lib/crypto/cryptography"; import { crypto } from "@app/lib/crypto/cryptography";
import { BadRequestError, NotFoundError, PermissionBoundaryError, UnauthorizedError } from "@app/lib/errors"; import {
BadRequestError,
ForbiddenRequestError,
NotFoundError,
PermissionBoundaryError,
UnauthorizedError
} from "@app/lib/errors";
import { extractIPDetails, isValidIpOrCidr } from "@app/lib/ip"; import { extractIPDetails, isValidIpOrCidr } from "@app/lib/ip";
import { ActorType, AuthTokenType } from "../auth/auth-type"; import { ActorType, AuthTokenType } from "../auth/auth-type";
@@ -189,6 +195,9 @@ export const identityTlsCertAuthServiceFactory = ({
identityId identityId
}); });
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (identityMembershipOrg.identity.identityOrgId !== actorOrgId) {
throw new ForbiddenRequestError({ message: "Sub organization not authorized to access this identity" });
}
if (identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.TLS_CERT_AUTH)) { if (identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.TLS_CERT_AUTH)) {
throw new BadRequestError({ throw new BadRequestError({
@@ -272,6 +281,9 @@ export const identityTlsCertAuthServiceFactory = ({
identityId identityId
}); });
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (identityMembershipOrg.identity.identityOrgId !== actorOrgId) {
throw new ForbiddenRequestError({ message: "Sub organization not authorized to access this identity" });
}
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.TLS_CERT_AUTH)) { if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.TLS_CERT_AUTH)) {
throw new NotFoundError({ throw new NotFoundError({
@@ -352,6 +364,9 @@ export const identityTlsCertAuthServiceFactory = ({
identityId identityId
}); });
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (identityMembershipOrg.identity.identityOrgId !== actorOrgId) {
throw new ForbiddenRequestError({ message: "Sub organization not authorized to access this identity" });
}
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.TLS_CERT_AUTH)) { if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.TLS_CERT_AUTH)) {
throw new BadRequestError({ throw new BadRequestError({
@@ -397,6 +412,9 @@ export const identityTlsCertAuthServiceFactory = ({
identityId identityId
}); });
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (identityMembershipOrg.identity.identityOrgId !== actorOrgId) {
throw new ForbiddenRequestError({ message: "Sub organization not authorized to access this identity" });
}
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.TLS_CERT_AUTH)) { if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.TLS_CERT_AUTH)) {
throw new BadRequestError({ throw new BadRequestError({
message: "The identity does not have TLS Certificate auth" message: "The identity does not have TLS Certificate auth"
@@ -10,7 +10,7 @@ import {
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types"; import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types";
import { getConfig } from "@app/lib/config/env"; import { getConfig } from "@app/lib/config/env";
import { crypto } from "@app/lib/crypto"; import { crypto } from "@app/lib/crypto";
import { BadRequestError, NotFoundError, PermissionBoundaryError } from "@app/lib/errors"; import { BadRequestError, ForbiddenRequestError, NotFoundError, PermissionBoundaryError } from "@app/lib/errors";
import { extractIPDetails, isValidIpOrCidr } from "@app/lib/ip"; import { extractIPDetails, isValidIpOrCidr } from "@app/lib/ip";
import { ActorType, AuthTokenType } from "../auth/auth-type"; import { ActorType, AuthTokenType } from "../auth/auth-type";
@@ -79,6 +79,9 @@ export const identityTokenAuthServiceFactory = ({
identityId identityId
}); });
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (identityMembershipOrg.identity.identityOrgId !== actorOrgId) {
throw new ForbiddenRequestError({ message: "Sub organization not authorized to access this identity" });
}
if (identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.TOKEN_AUTH)) { if (identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.TOKEN_AUTH)) {
throw new BadRequestError({ throw new BadRequestError({
@@ -156,6 +159,9 @@ export const identityTokenAuthServiceFactory = ({
identityId identityId
}); });
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (identityMembershipOrg.identity.identityOrgId !== actorOrgId) {
throw new ForbiddenRequestError({ message: "Sub organization not authorized to access this identity" });
}
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.TOKEN_AUTH)) { if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.TOKEN_AUTH)) {
throw new BadRequestError({ throw new BadRequestError({
@@ -225,6 +231,9 @@ export const identityTokenAuthServiceFactory = ({
identityId identityId
}); });
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (identityMembershipOrg.identity.identityOrgId !== actorOrgId) {
throw new ForbiddenRequestError({ message: "Sub organization not authorized to access this identity" });
}
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.TOKEN_AUTH)) { if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.TOKEN_AUTH)) {
throw new BadRequestError({ throw new BadRequestError({
@@ -265,6 +274,9 @@ export const identityTokenAuthServiceFactory = ({
identityId identityId
}); });
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (identityMembershipOrg.identity.identityOrgId !== actorOrgId) {
throw new ForbiddenRequestError({ message: "Sub organization not authorized to access this identity" });
}
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.TOKEN_AUTH)) { if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.TOKEN_AUTH)) {
throw new BadRequestError({ throw new BadRequestError({
@@ -13,6 +13,7 @@ import { getConfig } from "@app/lib/config/env";
import { crypto } from "@app/lib/crypto/cryptography"; import { crypto } from "@app/lib/crypto/cryptography";
import { import {
BadRequestError, BadRequestError,
ForbiddenRequestError,
NotFoundError, NotFoundError,
PermissionBoundaryError, PermissionBoundaryError,
RateLimitError, RateLimitError,
@@ -315,6 +316,13 @@ export const identityUaServiceFactory = ({
message: "Failed to add universal auth to already configured identity" message: "Failed to add universal auth to already configured identity"
}); });
} }
if (identityMembershipOrg.identity.identityOrgId !== actorOrgId) {
throw new ForbiddenRequestError({ message: "Sub organization not authorized to access this identity" });
}
if (identityMembershipOrg.identity.identityOrgId !== actorOrgId) {
throw new ForbiddenRequestError({ message: "Sub organization not authorized to access this identity" });
}
if (accessTokenMaxTTL > 0 && accessTokenTTL > accessTokenMaxTTL) { if (accessTokenMaxTTL > 0 && accessTokenTTL > accessTokenMaxTTL) {
throw new BadRequestError({ message: "Access token TTL cannot be greater than max TTL" }); throw new BadRequestError({ message: "Access token TTL cannot be greater than max TTL" });
@@ -425,6 +433,10 @@ export const identityUaServiceFactory = ({
}); });
} }
if (identityMembershipOrg.identity.identityOrgId !== actorOrgId) {
throw new ForbiddenRequestError({ message: "Sub organization not authorized to access this identity" });
}
if ( if (
(accessTokenMaxTTL || uaIdentityAuth.accessTokenMaxTTL) > 0 && (accessTokenMaxTTL || uaIdentityAuth.accessTokenMaxTTL) > 0 &&
(accessTokenTTL || uaIdentityAuth.accessTokenMaxTTL) > (accessTokenMaxTTL || uaIdentityAuth.accessTokenMaxTTL) (accessTokenTTL || uaIdentityAuth.accessTokenMaxTTL) > (accessTokenMaxTTL || uaIdentityAuth.accessTokenMaxTTL)
@@ -515,6 +527,9 @@ export const identityUaServiceFactory = ({
message: "The identity does not have universal auth" message: "The identity does not have universal auth"
}); });
} }
if (identityMembershipOrg.identity.identityOrgId !== actorOrgId) {
throw new ForbiddenRequestError({ message: "Sub organization not authorized to access this identity" });
}
const { permission } = await permissionService.getOrgPermission({ const { permission } = await permissionService.getOrgPermission({
scope: OrganizationActionScope.Any, scope: OrganizationActionScope.Any,
@@ -549,6 +564,9 @@ export const identityUaServiceFactory = ({
message: "The identity does not have universal auth" message: "The identity does not have universal auth"
}); });
} }
if (identityMembershipOrg.identity.identityOrgId !== actorOrgId) {
throw new ForbiddenRequestError({ message: "Sub organization not authorized to access this identity" });
}
const { permission } = await permissionService.getOrgPermission({ const { permission } = await permissionService.getOrgPermission({
scope: OrganizationActionScope.Any, scope: OrganizationActionScope.Any,
actor, actor,
@@ -617,6 +635,9 @@ export const identityUaServiceFactory = ({
message: "The identity does not have universal auth" message: "The identity does not have universal auth"
}); });
} }
if (identityMembershipOrg.identity.identityOrgId !== actorOrgId) {
throw new ForbiddenRequestError({ message: "Sub organization not authorized to access this identity" });
}
const { permission } = await permissionService.getOrgPermission({ const { permission } = await permissionService.getOrgPermission({
scope: OrganizationActionScope.Any, scope: OrganizationActionScope.Any,
@@ -700,6 +721,10 @@ export const identityUaServiceFactory = ({
message: "The identity does not have universal auth" message: "The identity does not have universal auth"
}); });
} }
if (identityMembershipOrg.identity.identityOrgId !== actorOrgId) {
throw new ForbiddenRequestError({ message: "Sub organization not authorized to access this identity" });
}
const { permission } = await permissionService.getOrgPermission({ const { permission } = await permissionService.getOrgPermission({
scope: OrganizationActionScope.Any, scope: OrganizationActionScope.Any,
actor, actor,
@@ -770,6 +795,9 @@ export const identityUaServiceFactory = ({
message: "The identity does not have universal auth" message: "The identity does not have universal auth"
}); });
} }
if (identityMembershipOrg.identity.identityOrgId !== actorOrgId) {
throw new ForbiddenRequestError({ message: "Sub organization not authorized to access this identity" });
}
const identityUa = await identityUaDAL.findOne({ identityId }); const identityUa = await identityUaDAL.findOne({ identityId });
if (!identityUa) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); if (!identityUa) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
@@ -839,6 +867,9 @@ export const identityUaServiceFactory = ({
message: "The identity does not have universal auth" message: "The identity does not have universal auth"
}); });
} }
if (identityMembershipOrg.identity.identityOrgId !== actorOrgId) {
throw new ForbiddenRequestError({ message: "Sub organization not authorized to access this identity" });
}
const identityUa = await identityUaDAL.findOne({ identityId }); const identityUa = await identityUaDAL.findOne({ identityId });
if (!identityUa) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); if (!identityUa) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
@@ -913,6 +944,9 @@ export const identityUaServiceFactory = ({
message: "The identity does not have universal auth" message: "The identity does not have universal auth"
}); });
} }
if (identityMembershipOrg.identity.identityOrgId !== actorOrgId) {
throw new ForbiddenRequestError({ message: "Sub organization not authorized to access this identity" });
}
const { permission } = await permissionService.getOrgPermission({ const { permission } = await permissionService.getOrgPermission({
scope: OrganizationActionScope.Any, scope: OrganizationActionScope.Any,
@@ -163,7 +163,8 @@ export const identityOrgDALFactory = (db: TDbClient) => {
.select( .select(
selectAllTableCols(TableName.Membership), selectAllTableCols(TableName.Membership),
db.ref("name").withSchema(TableName.Identity).as("identityName"), db.ref("name").withSchema(TableName.Identity).as("identityName"),
db.ref("hasDeleteProtection").withSchema(TableName.Identity) db.ref("hasDeleteProtection").withSchema(TableName.Identity),
db.ref("orgId").withSchema(TableName.Identity)
) )
.where(filter) .where(filter)
.as("paginatedIdentity"); .as("paginatedIdentity");
@@ -257,6 +258,7 @@ export const identityOrgDALFactory = (db: TDbClient) => {
db.ref("customRoleId").withSchema(TableName.MembershipRole).as("roleId"), db.ref("customRoleId").withSchema(TableName.MembershipRole).as("roleId"),
db.ref("scopeOrgId").withSchema("paginatedIdentity").as("orgId"), db.ref("scopeOrgId").withSchema("paginatedIdentity").as("orgId"),
db.ref("lastLoginAuthMethod").withSchema("paginatedIdentity"), db.ref("lastLoginAuthMethod").withSchema("paginatedIdentity"),
db.ref("orgId").withSchema("paginatedIdentity").as("identityOrgId"),
db.ref("lastLoginTime").withSchema("paginatedIdentity"), db.ref("lastLoginTime").withSchema("paginatedIdentity"),
db.ref("createdAt").withSchema("paginatedIdentity"), db.ref("createdAt").withSchema("paginatedIdentity"),
db.ref("updatedAt").withSchema("paginatedIdentity"), db.ref("updatedAt").withSchema("paginatedIdentity"),
@@ -309,6 +311,7 @@ export const identityOrgDALFactory = (db: TDbClient) => {
roleId, roleId,
id, id,
orgId, orgId,
identityOrgId,
uaId, uaId,
alicloudId, alicloudId,
awsId, awsId,
@@ -348,6 +351,7 @@ export const identityOrgDALFactory = (db: TDbClient) => {
id: identityId as string, id: identityId as string,
name: identityName, name: identityName,
hasDeleteProtection, hasDeleteProtection,
orgId: identityOrgId,
authMethods: buildAuthMethods({ authMethods: buildAuthMethods({
uaId, uaId,
alicloudId, alicloudId,
@@ -28,6 +28,7 @@ import {
TSearchOrgIdentitiesByOrgIdDTO, TSearchOrgIdentitiesByOrgIdDTO,
TUpdateIdentityDTO TUpdateIdentityDTO
} from "./identity-types"; } from "./identity-types";
import { TAdditionalPrivilegeDALFactory } from "../additional-privilege/additional-privilege-dal";
type TIdentityServiceFactoryDep = { type TIdentityServiceFactoryDep = {
identityDAL: TIdentityDALFactory; identityDAL: TIdentityDALFactory;
@@ -40,6 +41,7 @@ type TIdentityServiceFactoryDep = {
licenseService: Pick<TLicenseServiceFactory, "getPlan" | "updateSubscriptionOrgMemberCount">; licenseService: Pick<TLicenseServiceFactory, "getPlan" | "updateSubscriptionOrgMemberCount">;
keyStore: Pick<TKeyStoreFactory, "getKeysByPattern" | "getItem">; keyStore: Pick<TKeyStoreFactory, "getKeysByPattern" | "getItem">;
orgDAL: Pick<TOrgDALFactory, "findById">; orgDAL: Pick<TOrgDALFactory, "findById">;
additionalPrivilegeDAL: Pick<TAdditionalPrivilegeDALFactory, "delete">;
}; };
export type TIdentityServiceFactory = ReturnType<typeof identityServiceFactory>; export type TIdentityServiceFactory = ReturnType<typeof identityServiceFactory>;
@@ -54,7 +56,8 @@ export const identityServiceFactory = ({
keyStore, keyStore,
orgDAL, orgDAL,
membershipIdentityDAL, membershipIdentityDAL,
membershipRoleDAL membershipRoleDAL,
additionalPrivilegeDAL
}: TIdentityServiceFactoryDep) => { }: TIdentityServiceFactoryDep) => {
const createIdentity = async ({ const createIdentity = async ({
name, name,
@@ -337,10 +340,35 @@ export const identityServiceFactory = ({
if (identityOrgMembership.identity.hasDeleteProtection) if (identityOrgMembership.identity.hasDeleteProtection)
throw new BadRequestError({ message: "Identity has delete protection" }); throw new BadRequestError({ message: "Identity has delete protection" });
const deletedIdentity = await identityDAL.deleteById(id); if (identityOrgMembership.identity.identityOrgId === actorOrgId) {
const deletedIdentity = await identityDAL.deleteById(id);
await licenseService.updateSubscriptionOrgMemberCount(identityOrgMembership.scopeOrgId);
return { ...deletedIdentity, orgId: identityOrgMembership.scopeOrgId };
}
await licenseService.updateSubscriptionOrgMemberCount(identityOrgMembership.scopeOrgId); await membershipIdentityDAL.transaction(async (tx) => {
const identityProjectMembership = await membershipIdentityDAL.find(
{
actorIdentityId: id,
scope: AccessScope.Project,
scopeOrgId: actorOrgId
},
{ tx }
);
await additionalPrivilegeDAL.delete(
{
actorIdentityId: id,
$in: {
projectId: identityProjectMembership.map((el) => el.scopeProjectId)
}
},
tx
);
const doc = await membershipIdentityDAL.delete({ actorIdentityId: id, scopeOrgId: actorOrgId }, tx);
return doc;
});
const deletedIdentity = await identityDAL.findById(id);
return { ...deletedIdentity, orgId: identityOrgMembership.scopeOrgId }; return { ...deletedIdentity, orgId: identityOrgMembership.scopeOrgId };
}; };
@@ -20,6 +20,7 @@ export type Identity = {
createdAt: string; createdAt: string;
updatedAt: string; updatedAt: string;
isInstanceAdmin?: boolean; isInstanceAdmin?: boolean;
orgId: string;
}; };
export type IdentityAccessToken = { export type IdentityAccessToken = {
@@ -53,6 +53,7 @@ export const IdentityModal = ({ popUp, handlePopUpToggle }: Props) => {
const orgId = currentOrg?.id || ""; const orgId = currentOrg?.id || "";
const { data: roles } = useGetOrgRoles(orgId); const { data: roles } = useGetOrgRoles(orgId);
const isOrgIdentity = orgId === popUp?.identity?.data?.orgId;
const { mutateAsync: createMutateAsync } = useCreateIdentity(); const { mutateAsync: createMutateAsync } = useCreateIdentity();
const { mutateAsync: updateMutateAsync } = useUpdateIdentity(); const { mutateAsync: updateMutateAsync } = useUpdateIdentity();
@@ -113,6 +114,7 @@ export const IdentityModal = ({ popUp, handlePopUpToggle }: Props) => {
name: string; name: string;
role: string; role: string;
hasDeleteProtection: boolean; hasDeleteProtection: boolean;
orgId: string;
}; };
if (identity) { if (identity) {
@@ -196,16 +198,23 @@ export const IdentityModal = ({ popUp, handlePopUpToggle }: Props) => {
title={`${popUp?.identity?.data ? "Update" : "Create"} Identity`} title={`${popUp?.identity?.data ? "Update" : "Create"} Identity`}
> >
<form onSubmit={handleSubmit(onFormSubmit)}> <form onSubmit={handleSubmit(onFormSubmit)}>
<Controller {isOrgIdentity && (
control={control} <Controller
defaultValue="" control={control}
name="name" defaultValue=""
render={({ field, fieldState: { error } }) => ( name="name"
<FormControl label="Name" isError={Boolean(error)} errorText={error?.message}> render={({ field, fieldState: { error } }) => (
<Input {...field} placeholder="Machine 1" /> <FormControl
</FormControl> className="mb-4"
)} label="Name"
/> isError={Boolean(error)}
errorText={error?.message}
>
<Input {...field} placeholder="Machine 1" />
</FormControl>
)}
/>
)}
<Controller <Controller
control={control} control={control}
name="role" name="role"
@@ -214,7 +223,6 @@ export const IdentityModal = ({ popUp, handlePopUpToggle }: Props) => {
label={`${popUp?.identity?.data ? "Update" : ""} Role`} label={`${popUp?.identity?.data ? "Update" : ""} Role`}
errorText={error?.message} errorText={error?.message}
isError={Boolean(error)} isError={Boolean(error)}
className="mt-4"
> >
<FilterableSelect <FilterableSelect
placeholder="Select role..." placeholder="Select role..."
@@ -227,24 +235,26 @@ export const IdentityModal = ({ popUp, handlePopUpToggle }: Props) => {
</FormControl> </FormControl>
)} )}
/> />
<Controller {isOrgIdentity && (
control={control} <Controller
name="hasDeleteProtection" control={control}
render={({ field: { onChange, value }, fieldState: { error } }) => ( name="hasDeleteProtection"
<FormControl errorText={error?.message} isError={Boolean(error)}> render={({ field: { onChange, value }, fieldState: { error } }) => (
<Switch <FormControl errorText={error?.message} isError={Boolean(error)}>
className="mr-2 ml-0 bg-mineshaft-400/80 shadow-inner data-[state=checked]:bg-green/80" <Switch
containerClassName="flex-row-reverse w-fit" className="mr-2 ml-0 bg-mineshaft-400/80 shadow-inner data-[state=checked]:bg-green/80"
id="delete-protection-enabled" containerClassName="flex-row-reverse w-fit"
thumbClassName="bg-mineshaft-800" id="delete-protection-enabled"
onCheckedChange={onChange} thumbClassName="bg-mineshaft-800"
isChecked={value} onCheckedChange={onChange}
> isChecked={value}
<p>Delete Protection {value ? "Enabled" : "Disabled"}</p> >
</Switch> <p>Delete Protection {value ? "Enabled" : "Disabled"}</p>
</FormControl> </Switch>
)} </FormControl>
/> )}
/>
)}
<div> <div>
<FormLabel label="Metadata" /> <FormLabel label="Metadata" />
</div> </div>
@@ -33,6 +33,7 @@ const Page = () => {
const orgId = currentOrg?.id || ""; const orgId = currentOrg?.id || "";
const { data } = useGetIdentityById(identityId); const { data } = useGetIdentityById(identityId);
const { mutateAsync: deleteIdentity } = useDeleteIdentity(); const { mutateAsync: deleteIdentity } = useDeleteIdentity();
const isAuthHidden = orgId !== data?.identity?.orgId;
const { popUp, handlePopUpOpen, handlePopUpClose, handlePopUpToggle } = usePopUp([ const { popUp, handlePopUpOpen, handlePopUpClose, handlePopUpToggle } = usePopUp([
"identity", "identity",
@@ -91,10 +92,12 @@ const Page = () => {
<div className="flex"> <div className="flex">
<div className="mr-4 w-96"> <div className="mr-4 w-96">
<IdentityDetailsSection identityId={identityId} handlePopUpOpen={handlePopUpOpen} /> <IdentityDetailsSection identityId={identityId} handlePopUpOpen={handlePopUpOpen} />
<IdentityAuthenticationSection {!isAuthHidden && (
identityId={identityId} <IdentityAuthenticationSection
handlePopUpOpen={handlePopUpOpen} identityId={identityId}
/> handlePopUpOpen={handlePopUpOpen}
/>
)}
</div> </div>
<IdentityProjectsSection identityId={identityId} /> <IdentityProjectsSection identityId={identityId} />
</div> </div>
@@ -28,13 +28,14 @@ import { UsePopUpState } from "@app/hooks/usePopUp";
type Props = { type Props = {
identityId: string; identityId: string;
isOrgIdentity?: boolean;
handlePopUpOpen: ( handlePopUpOpen: (
popUpName: keyof UsePopUpState<["identity", "identityAuthMethod", "deleteIdentity"]>, popUpName: keyof UsePopUpState<["identity", "identityAuthMethod", "deleteIdentity"]>,
data?: object data?: object
) => void; ) => void;
}; };
export const IdentityDetailsSection = ({ identityId, handlePopUpOpen }: Props) => { export const IdentityDetailsSection = ({ identityId, handlePopUpOpen, isOrgIdentity }: Props) => {
const [copyTextId, isCopyingId, setCopyTextId] = useTimedReset<string>({ const [copyTextId, isCopyingId, setCopyTextId] = useTimedReset<string>({
initialState: "Copy ID to clipboard" initialState: "Copy ID to clipboard"
}); });
@@ -75,6 +76,7 @@ export const IdentityDetailsSection = ({ identityId, handlePopUpOpen }: Props) =
handlePopUpOpen("identity", { handlePopUpOpen("identity", {
identityId, identityId,
name: data.identity.name, name: data.identity.name,
orgId: data.identity.orgId,
hasDeleteProtection: data.identity.hasDeleteProtection, hasDeleteProtection: data.identity.hasDeleteProtection,
role: data.role, role: data.role,
customRole: data.customRole, customRole: data.customRole,
@@ -140,24 +142,30 @@ export const IdentityDetailsSection = ({ identityId, handlePopUpOpen }: Props) =
<p className="text-sm font-medium text-mineshaft-300">Name</p> <p className="text-sm font-medium text-mineshaft-300">Name</p>
<p className="text-sm text-mineshaft-300">{data.identity.name}</p> <p className="text-sm text-mineshaft-300">{data.identity.name}</p>
</div> </div>
<div className="mb-4"> {isOrgIdentity && (
<p className="text-sm font-medium text-mineshaft-300">Last Login Auth Method</p> <div className="mb-4">
<p className="text-sm text-mineshaft-300"> <p className="text-sm font-medium text-mineshaft-300">Last Login Auth Method</p>
{data.lastLoginAuthMethod ? identityAuthToNameMap[data.lastLoginAuthMethod] : "-"} <p className="text-sm text-mineshaft-300">
</p> {data.lastLoginAuthMethod ? identityAuthToNameMap[data.lastLoginAuthMethod] : "-"}
</div> </p>
<div className="mb-4"> </div>
<p className="text-sm font-medium text-mineshaft-300">Last Login Time</p> )}
<p className="text-sm text-mineshaft-300"> {isOrgIdentity && (
{data.lastLoginTime ? format(data.lastLoginTime, "PPpp") : "-"} <div className="mb-4">
</p> <p className="text-sm font-medium text-mineshaft-300">Last Login Time</p>
</div> <p className="text-sm text-mineshaft-300">
<div className="mb-4"> {data.lastLoginTime ? format(data.lastLoginTime, "PPpp") : "-"}
<p className="text-sm font-medium text-mineshaft-300">Delete Protection</p> </p>
<p className="text-sm text-mineshaft-300"> </div>
{data.identity.hasDeleteProtection ? "On" : "Off"} )}
</p> {isOrgIdentity && (
</div> <div className="mb-4">
<p className="text-sm font-medium text-mineshaft-300">Delete Protection</p>
<p className="text-sm text-mineshaft-300">
{data.identity.hasDeleteProtection ? "On" : "Off"}
</p>
</div>
)}
<div className="mb-4"> <div className="mb-4">
<p className="text-sm font-medium text-mineshaft-300">Organization Role</p> <p className="text-sm font-medium text-mineshaft-300">Organization Role</p>
<p className="text-sm text-mineshaft-300">{data.role}</p> <p className="text-sm text-mineshaft-300">{data.role}</p>