Merge branch 'main' into feature/north-flank-app-connection

This commit is contained in:
Victor Santos
2025-10-23 12:46:55 -03:00
282 changed files with 7525 additions and 2865 deletions
@@ -94,6 +94,7 @@ export const registerAuthRoutes = async (server: FastifyZodProvider) => {
decodedToken.userId,
decodedToken.organizationId,
decodedToken.authMethod,
decodedToken.organizationId,
decodedToken.organizationId
);
if (org && org.userTokenExpiration) {
@@ -73,12 +73,12 @@ export const registerIdentityAliCloudAuthRouter = async (server: FastifyZodProvi
}
},
handler: async (req) => {
const { identityAliCloudAuth, accessToken, identityAccessToken, identityMembershipOrg } =
const { identityAliCloudAuth, accessToken, identityAccessToken, identity } =
await server.services.identityAliCloudAuth.login(req.body);
await server.services.auditLog.createAuditLog({
...req.auditLogInfo,
orgId: identityMembershipOrg.scopeOrgId,
orgId: identity.orgId,
event: {
type: EventType.LOGIN_IDENTITY_ALICLOUD_AUTH,
metadata: {
@@ -40,12 +40,12 @@ export const registerIdentityAwsAuthRouter = async (server: FastifyZodProvider)
}
},
handler: async (req) => {
const { identityAwsAuth, accessToken, identityAccessToken, identityMembershipOrg } =
const { identityAwsAuth, accessToken, identityAccessToken, identity } =
await server.services.identityAwsAuth.login(req.body);
await server.services.auditLog.createAuditLog({
...req.auditLogInfo,
orgId: identityMembershipOrg.scopeOrgId,
orgId: identity.orgId,
event: {
type: EventType.LOGIN_IDENTITY_AWS_AUTH,
metadata: {
@@ -35,12 +35,12 @@ export const registerIdentityAzureAuthRouter = async (server: FastifyZodProvider
}
},
handler: async (req) => {
const { identityAzureAuth, accessToken, identityAccessToken, identityMembershipOrg } =
const { identityAzureAuth, accessToken, identityAccessToken, identity } =
await server.services.identityAzureAuth.login(req.body);
await server.services.auditLog.createAuditLog({
...req.auditLogInfo,
orgId: identityMembershipOrg.scopeOrgId,
orgId: identity.orgId,
event: {
type: EventType.LOGIN_IDENTITY_AZURE_AUTH,
metadata: {
@@ -35,12 +35,12 @@ export const registerIdentityGcpAuthRouter = async (server: FastifyZodProvider)
}
},
handler: async (req) => {
const { identityGcpAuth, accessToken, identityAccessToken, identityMembershipOrg } =
const { identityGcpAuth, accessToken, identityAccessToken, identity } =
await server.services.identityGcpAuth.login(req.body);
await server.services.auditLog.createAuditLog({
...req.auditLogInfo,
orgId: identityMembershipOrg.scopeOrgId,
orgId: identity.orgId,
event: {
type: EventType.LOGIN_IDENTITY_GCP_AUTH,
metadata: {
@@ -111,7 +111,7 @@ export const registerIdentityJwtAuthRouter = async (server: FastifyZodProvider)
}
},
handler: async (req) => {
const { identityJwtAuth, accessToken, identityAccessToken, identityMembershipOrg } =
const { identityJwtAuth, accessToken, identityAccessToken, identity } =
await server.services.identityJwtAuth.login({
identityId: req.body.identityId,
jwt: req.body.jwt
@@ -119,7 +119,7 @@ export const registerIdentityJwtAuthRouter = async (server: FastifyZodProvider)
await server.services.auditLog.createAuditLog({
...req.auditLogInfo,
orgId: identityMembershipOrg.scopeOrgId,
orgId: identity.orgId,
event: {
type: EventType.LOGIN_IDENTITY_JWT_AUTH,
metadata: {
@@ -56,7 +56,7 @@ export const registerIdentityKubernetesRouter = async (server: FastifyZodProvide
}
},
handler: async (req) => {
const { identityKubernetesAuth, accessToken, identityAccessToken, identityMembershipOrg } =
const { identityKubernetesAuth, accessToken, identityAccessToken, identity } =
await server.services.identityKubernetesAuth.login({
identityId: req.body.identityId,
jwt: req.body.jwt
@@ -64,7 +64,7 @@ export const registerIdentityKubernetesRouter = async (server: FastifyZodProvide
await server.services.auditLog.createAuditLog({
...req.auditLogInfo,
orgId: identityMembershipOrg.scopeOrgId,
orgId: identity.orgId,
event: {
type: EventType.LOGIN_IDENTITY_KUBERNETES_AUTH,
metadata: {
@@ -162,13 +162,13 @@ export const registerIdentityLdapAuthRouter = async (server: FastifyZodProvider)
const { identityId, user } = req.passportMachineIdentity;
const { accessToken, identityLdapAuth, identityMembershipOrg } = await server.services.identityLdapAuth.login({
const { accessToken, identityLdapAuth, identity } = await server.services.identityLdapAuth.login({
identityId
});
await server.services.auditLog.createAuditLog({
...req.auditLogInfo,
orgId: identityMembershipOrg.scopeOrgId,
orgId: identity.orgId,
event: {
type: EventType.LOGIN_IDENTITY_LDAP_AUTH,
metadata: {
@@ -52,12 +52,12 @@ export const registerIdentityOciAuthRouter = async (server: FastifyZodProvider)
}
},
handler: async (req) => {
const { identityOciAuth, accessToken, identityAccessToken, identityMembershipOrg } =
const { identityOciAuth, accessToken, identityAccessToken, identity } =
await server.services.identityOciAuth.login(req.body);
await server.services.auditLog.createAuditLog({
...req.auditLogInfo,
orgId: identityMembershipOrg.scopeOrgId,
orgId: identity.orgId,
event: {
type: EventType.LOGIN_IDENTITY_OCI_AUTH,
metadata: {
@@ -59,7 +59,7 @@ export const registerIdentityOidcAuthRouter = async (server: FastifyZodProvider)
}
},
handler: async (req) => {
const { identityOidcAuth, accessToken, identityAccessToken, identityMembershipOrg, oidcTokenData } =
const { identityOidcAuth, accessToken, identityAccessToken, identity, oidcTokenData } =
await server.services.identityOidcAuth.login({
identityId: req.body.identityId,
jwt: req.body.jwt
@@ -67,7 +67,7 @@ export const registerIdentityOidcAuthRouter = async (server: FastifyZodProvider)
await server.services.auditLog.createAuditLog({
...req.auditLogInfo,
orgId: identityMembershipOrg.scopeOrgId,
orgId: identity.orgId,
event: {
type: EventType.LOGIN_IDENTITY_OIDC_AUTH,
metadata: {
@@ -0,0 +1,137 @@
import { z } from "zod";
import { AccessScope, TemporaryPermissionMode } from "@app/db/schemas";
import { ApiDocsTags, PROJECT_IDENTITIES } from "@app/lib/api-docs";
import { ms } from "@app/lib/ms";
import { writeLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type";
const sanitizedOrgIdentityMembershipSchema = z.object({
id: z.string().uuid(),
orgId: z.string(),
identityId: z.string().uuid(),
createdAt: z.date(),
updatedAt: z.date()
});
export const registerOrgIdentityMembershipRouter = async (server: FastifyZodProvider) => {
server.route({
method: "POST",
url: "/identity-memberships/:identityId",
config: {
rateLimit: writeLimit
},
onRequest: verifyAuth([AuthMode.JWT]),
schema: {
hide: true,
// this is hidden so not updating tags
tags: [ApiDocsTags.ProjectIdentities],
description: "Create org identity membership",
security: [
{
bearerAuth: []
}
],
params: z.object({
identityId: z.string().trim()
}),
body: z.object({
roles: z
.array(
z.union([
z.object({
role: z.string().describe(PROJECT_IDENTITIES.CREATE_IDENTITY_MEMBERSHIP.roles.role),
isTemporary: z
.literal(false)
.default(false)
.describe(PROJECT_IDENTITIES.CREATE_IDENTITY_MEMBERSHIP.roles.role)
}),
z.object({
role: z.string().describe(PROJECT_IDENTITIES.CREATE_IDENTITY_MEMBERSHIP.roles.role),
isTemporary: z.literal(true).describe(PROJECT_IDENTITIES.CREATE_IDENTITY_MEMBERSHIP.roles.role),
temporaryMode: z
.nativeEnum(TemporaryPermissionMode)
.describe(PROJECT_IDENTITIES.CREATE_IDENTITY_MEMBERSHIP.roles.role),
temporaryRange: z
.string()
.refine((val) => ms(val) > 0, "Temporary range must be a positive number")
.describe(PROJECT_IDENTITIES.CREATE_IDENTITY_MEMBERSHIP.roles.role),
temporaryAccessStartTime: z
.string()
.datetime()
.describe(PROJECT_IDENTITIES.CREATE_IDENTITY_MEMBERSHIP.roles.role)
})
])
)
.describe(PROJECT_IDENTITIES.CREATE_IDENTITY_MEMBERSHIP.roles.description)
.max(1)
}),
response: {
200: z.object({
identityMembership: sanitizedOrgIdentityMembershipSchema
})
}
},
handler: async (req) => {
const { membership } = await server.services.membershipIdentity.createMembership({
permission: req.permission,
scopeData: {
scope: AccessScope.Organization,
orgId: req.permission.orgId
},
data: {
identityId: req.params.identityId,
roles: req.body.roles
}
});
return {
identityMembership: { ...membership, identityId: req.params.identityId, orgId: req.permission.orgId }
};
}
});
server.route({
method: "DELETE",
url: "/identity-memberships/:identityId",
config: {
rateLimit: writeLimit
},
onRequest: verifyAuth([AuthMode.JWT]),
schema: {
hide: true,
tags: [ApiDocsTags.ProjectIdentities],
description: "Delete org identity memberships",
security: [
{
bearerAuth: []
}
],
params: z.object({
identityId: z.string().trim().describe(PROJECT_IDENTITIES.DELETE_IDENTITY_MEMBERSHIP.identityId)
}),
response: {
200: z.object({
identityMembership: sanitizedOrgIdentityMembershipSchema
})
}
},
handler: async (req) => {
const { membership } = await server.services.membershipIdentity.deleteMembership({
permission: req.permission,
scopeData: {
scope: AccessScope.Organization,
orgId: req.permission.orgId
},
selector: {
identityId: req.params.identityId
}
});
return {
identityMembership: { ...membership, identityId: req.params.identityId, orgId: req.permission.orgId }
};
}
});
};
@@ -249,7 +249,7 @@ export const registerIdentityRouter = async (server: FastifyZodProvider) => {
permissions: true,
description: true
}).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()),
activeLockoutAuthMethods: z.array(z.string())
})
@@ -393,7 +393,7 @@ export const registerIdentityRouter = async (server: FastifyZodProvider) => {
permissions: true,
description: true
}).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())
})
}).array(),
@@ -64,7 +64,7 @@ export const registerIdentityTlsCertAuthRouter = async (server: FastifyZodProvid
throw new BadRequestError({ message: "Missing TLS certificate in header" });
}
const { identityTlsCertAuth, accessToken, identityAccessToken, identityMembershipOrg } =
const { identityTlsCertAuth, accessToken, identityAccessToken, identity } =
await server.services.identityTlsCertAuth.login({
identityId: req.body.identityId,
clientCertificate: clientCertificate as string
@@ -72,7 +72,7 @@ export const registerIdentityTlsCertAuthRouter = async (server: FastifyZodProvid
await server.services.auditLog.createAuditLog({
...req.auditLogInfo,
orgId: identityMembershipOrg.scopeOrgId,
orgId: identity.orgId,
event: {
type: EventType.LOGIN_IDENTITY_TLS_CERT_AUTH,
metadata: {
@@ -319,7 +319,7 @@ export const registerIdentityTokenAuthRouter = async (server: FastifyZodProvider
}
},
handler: async (req) => {
const { identityTokenAuth, accessToken, identityAccessToken, identityMembershipOrg } =
const { identityTokenAuth, accessToken, identityAccessToken, identity } =
await server.services.identityTokenAuth.createTokenAuthToken({
actor: req.permission.type,
actorId: req.permission.id,
@@ -332,7 +332,7 @@ export const registerIdentityTokenAuthRouter = async (server: FastifyZodProvider
await server.services.auditLog.createAuditLog({
...req.auditLogInfo,
orgId: identityMembershipOrg.scopeOrgId,
orgId: identity.orgId,
event: {
type: EventType.CREATE_TOKEN_IDENTITY_TOKEN_AUTH,
metadata: {
@@ -52,14 +52,14 @@ export const registerIdentityUaRouter = async (server: FastifyZodProvider) => {
accessToken,
identityAccessToken,
validClientSecretInfo,
identityMembershipOrg,
identity,
accessTokenTTL,
accessTokenMaxTTL
} = await server.services.identityUa.login(req.body.clientId, req.body.clientSecret, req.realIp);
await server.services.auditLog.createAuditLog({
...req.auditLogInfo,
orgId: identityMembershipOrg.scopeOrgId,
orgId: identity.orgId,
event: {
type: EventType.LOGIN_IDENTITY_UNIVERSAL_AUTH,
metadata: {
+2
View File
@@ -33,6 +33,7 @@ import { registerIdentityKubernetesRouter } from "./identity-kubernetes-auth-rou
import { registerIdentityLdapAuthRouter } from "./identity-ldap-auth-router";
import { registerIdentityOciAuthRouter } from "./identity-oci-auth-router";
import { registerIdentityOidcAuthRouter } from "./identity-oidc-auth-router";
import { registerOrgIdentityMembershipRouter } from "./identity-org-membership-router";
import { registerIdentityProjectRouter } from "./identity-project-router";
import { registerIdentityRouter } from "./identity-router";
import { registerIdentityTlsCertAuthRouter } from "./identity-tls-cert-auth-router";
@@ -90,6 +91,7 @@ export const registerV1Routes = async (server: FastifyZodProvider) => {
);
await server.register(registerPasswordRouter, { prefix: "/password" });
await server.register(registerOrgRouter, { prefix: "/organization" });
await server.register(registerOrgIdentityMembershipRouter, { prefix: "/organization" });
await server.register(registerAdminRouter, { prefix: "/admin" });
await server.register(registerOrgAdminRouter, { prefix: "/organization-admin" });
await server.register(registerUserRouter, { prefix: "/user" });
@@ -2,6 +2,7 @@ import RE2 from "re2";
import { z } from "zod";
import {
AccessScope,
AuditLogsSchema,
GroupsSchema,
IncidentContactsSchema,
@@ -59,7 +60,14 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
}),
response: {
200: z.object({
organization: sanitizedOrganizationSchema
organization: sanitizedOrganizationSchema.extend({
subOrganization: z
.object({
id: z.string(),
name: z.string()
})
.optional()
})
})
}
},
@@ -69,6 +77,7 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
req.permission.id,
req.params.organizationId,
req.permission.authMethod,
req.permission.rootOrgId,
req.permission.orgId
);
return { organization };
@@ -467,4 +476,68 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
return { groups };
}
});
server.route({
method: "GET",
url: "/users/available",
schema: {
response: {
200: z.object({
users: z
.object({
id: z.string().uuid(),
username: z.string(),
email: z.string().nullable().optional(),
firstName: z.string().nullable().optional(),
lastName: z.string().nullable().optional()
})
.array()
})
}
},
onRequest: verifyAuth([AuthMode.JWT]),
handler: async (req) => {
const { users } = await server.services.membershipUser.listAvailableUsers({
permission: req.permission,
scopeData: {
orgId: req.permission.orgId,
scope: AccessScope.Organization
},
data: {}
});
return { users };
}
});
server.route({
method: "GET",
url: "/identities/available",
schema: {
response: {
200: z.object({
identities: z
.object({
id: z.string().uuid(),
name: z.string(),
hasDeleteProtection: z.boolean()
})
.array()
})
}
},
onRequest: verifyAuth([AuthMode.JWT]),
handler: async (req) => {
const { identities } = await server.services.membershipIdentity.listAvailableIdentities({
permission: req.permission,
scopeData: {
orgId: req.permission.orgId,
scope: AccessScope.Organization
},
data: {}
});
return { identities };
}
});
};