From 385c75c543101ace8c19057d56ff63450beb7c25 Mon Sep 17 00:00:00 2001 From: Carlos Monastyrski Date: Mon, 11 Aug 2025 21:23:05 -0700 Subject: [PATCH 1/6] Add machine identities to /organization endpoint --- .../server/routes/v1/organization-router.ts | 30 +++++++++++++------ backend/src/services/org/org-dal.ts | 22 +++++++++++++- backend/src/services/org/org-service.ts | 10 +++++++ 3 files changed, 52 insertions(+), 10 deletions(-) diff --git a/backend/src/server/routes/v1/organization-router.ts b/backend/src/server/routes/v1/organization-router.ts index 323354bc1..dfd87fa11 100644 --- a/backend/src/server/routes/v1/organization-router.ts +++ b/backend/src/server/routes/v1/organization-router.ts @@ -29,18 +29,30 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => { }, schema: { response: { - 200: z.object({ - organizations: sanitizedOrganizationSchema - .extend({ - orgAuthMethod: z.string(), - userRole: z.string() - }) - .array() - }) + 200: z.union([ + z.object({ + id: z.string(), + name: z.string(), + slug: z.string(), + role: z.string() + }), + z.object({ + organizations: sanitizedOrganizationSchema + .extend({ + orgAuthMethod: z.string(), + userRole: z.string() + }) + .array() + }) + ]) } }, - onRequest: verifyAuth([AuthMode.JWT], { requireOrg: false }), + onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN], { requireOrg: false }), handler: async (req) => { + if (req.permission.type === ActorType.IDENTITY) { + const organization = await server.services.org.findIdentityOrganization(req.permission.id); + return organization; + } const organizations = await server.services.org.findAllOrganizationOfUser(req.permission.id); return { organizations }; } diff --git a/backend/src/services/org/org-dal.ts b/backend/src/services/org/org-dal.ts index b46efc46c..b4246adaa 100644 --- a/backend/src/services/org/org-dal.ts +++ b/backend/src/services/org/org-dal.ts @@ -630,6 +630,25 @@ export const orgDALFactory = (db: TDbClient) => { } }; + const findIdentityOrganization = async ( + identityId: string + ): Promise<{ id: string; name: string; slug: string; role: string }> => { + try { + const org = await db + .replicaNode()(TableName.IdentityOrgMembership) + .where({ identityId }) + .join(TableName.Organization, `${TableName.IdentityOrgMembership}.orgId`, `${TableName.Organization}.id`) + .select(db.ref("id").withSchema(TableName.Organization).as("id")) + .select(db.ref("name").withSchema(TableName.Organization).as("name")) + .select(db.ref("slug").withSchema(TableName.Organization).as("slug")) + .select(db.ref("role").withSchema(TableName.IdentityOrgMembership).as("role")); + + return org?.[0]; + } catch (error) { + throw new DatabaseError({ error, name: "Find all org by user id" }); + } + }; + return withTransaction(db, { ...orgOrm, findOrgByProjectId, @@ -652,6 +671,7 @@ export const orgDALFactory = (db: TDbClient) => { updateMembershipById, deleteMembershipById, deleteMembershipsById, - updateMembership + updateMembership, + findIdentityOrganization }); }; diff --git a/backend/src/services/org/org-service.ts b/backend/src/services/org/org-service.ts index 5779fa7d3..ba76d0a93 100644 --- a/backend/src/services/org/org-service.ts +++ b/backend/src/services/org/org-service.ts @@ -198,6 +198,15 @@ export const orgServiceFactory = ({ // Filter out orgs where the membership object is an invitation return orgs.filter((org) => org.userStatus !== "invited"); }; + + /* + * Get all organization an identity is part of + * */ + const findIdentityOrganization = async (identityId: string) => { + const org = await orgDAL.findIdentityOrganization(identityId); + + return org; + }; /* * Get all workspace members * */ @@ -1403,6 +1412,7 @@ export const orgServiceFactory = ({ findOrganizationById, findAllOrgMembers, findAllOrganizationOfUser, + findIdentityOrganization, inviteUserToOrganization, verifyUserToOrg, updateOrg, From 18881749fd8486fb20a22dca96c6efe78cf3ad37 Mon Sep 17 00:00:00 2001 From: Carlos Monastyrski Date: Tue, 12 Aug 2025 19:10:45 -0700 Subject: [PATCH 2/6] Improve error message --- backend/src/services/org/org-dal.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/services/org/org-dal.ts b/backend/src/services/org/org-dal.ts index b4246adaa..aa22b11c7 100644 --- a/backend/src/services/org/org-dal.ts +++ b/backend/src/services/org/org-dal.ts @@ -645,7 +645,7 @@ export const orgDALFactory = (db: TDbClient) => { return org?.[0]; } catch (error) { - throw new DatabaseError({ error, name: "Find all org by user id" }); + throw new DatabaseError({ error, name: "Find identity organization" }); } }; From aa4dbfa0737a08c8921292d202dbae6394237508 Mon Sep 17 00:00:00 2001 From: Carlos Monastyrski Date: Wed, 13 Aug 2025 11:43:28 -0700 Subject: [PATCH 3/6] Move identity org details to new endpoint --- .../src/ee/services/license/license-fns.ts | 66 +++++++++---------- .../src/server/routes/v1/identity-router.ts | 23 +++++++ .../server/routes/v1/organization-router.ts | 30 +++------ 3 files changed, 65 insertions(+), 54 deletions(-) diff --git a/backend/src/ee/services/license/license-fns.ts b/backend/src/ee/services/license/license-fns.ts index bd3949a7e..6620e14d4 100644 --- a/backend/src/ee/services/license/license-fns.ts +++ b/backend/src/ee/services/license/license-fns.ts @@ -18,50 +18,50 @@ export const getDefaultOnPremFeatures = (): TFeatureSet => ({ environmentsUsed: 0, identityLimit: null, identitiesUsed: 0, - dynamicSecret: false, + dynamicSecret: true, secretVersioning: true, - pitRecovery: false, - ipAllowlisting: false, - rbac: false, - githubOrgSync: false, - customRateLimits: false, - customAlerts: false, - secretAccessInsights: false, - auditLogs: false, + pitRecovery: true, + ipAllowlisting: true, + rbac: true, + githubOrgSync: true, + customRateLimits: true, + customAlerts: true, + secretAccessInsights: true, + auditLogs: true, auditLogsRetentionDays: 0, - auditLogStreams: false, + auditLogStreams: true, auditLogStreamLimit: 3, - samlSSO: false, - hsm: false, - oidcSSO: false, - scim: false, - ldap: false, - groups: false, + samlSSO: true, + hsm: true, + oidcSSO: true, + scim: true, + ldap: true, + groups: true, status: null, trial_end: null, has_used_trial: true, - secretApproval: false, - secretRotation: false, - caCrl: false, - instanceUserManagement: false, - externalKms: false, + secretApproval: true, + secretRotation: true, + caCrl: true, + instanceUserManagement: true, + externalKms: true, rateLimits: { readLimit: 60, writeLimit: 200, secretsLimit: 40 }, - pkiEst: false, - enforceMfa: false, - projectTemplates: false, - kmip: false, - gateway: false, - sshHostGroups: false, - secretScanning: false, - enterpriseSecretSyncs: false, - enterpriseAppConnections: false, - fips: false, - eventSubscriptions: false, - machineIdentityAuthTemplates: false + pkiEst: true, + enforceMfa: true, + projectTemplates: true, + kmip: true, + gateway: true, + sshHostGroups: true, + secretScanning: true, + enterpriseSecretSyncs: true, + enterpriseAppConnections: true, + fips: true, + eventSubscriptions: true, + machineIdentityAuthTemplates: true }); export const setupLicenseRequestWithStore = ( diff --git a/backend/src/server/routes/v1/identity-router.ts b/backend/src/server/routes/v1/identity-router.ts index c0578fc0a..82ab82637 100644 --- a/backend/src/server/routes/v1/identity-router.ts +++ b/backend/src/server/routes/v1/identity-router.ts @@ -478,4 +478,27 @@ export const registerIdentityRouter = async (server: FastifyZodProvider) => { return { identityMemberships }; } }); + + server.route({ + method: "GET", + url: "/details", + config: { + rateLimit: readLimit + }, + schema: { + response: { + 200: z.object({ + id: z.string(), + name: z.string(), + slug: z.string(), + role: z.string() + }) + } + }, + onRequest: verifyAuth([AuthMode.IDENTITY_ACCESS_TOKEN], { requireOrg: false }), + handler: async (req) => { + const organization = await server.services.org.findIdentityOrganization(req.permission.id); + return organization; + } + }); }; diff --git a/backend/src/server/routes/v1/organization-router.ts b/backend/src/server/routes/v1/organization-router.ts index dfd87fa11..323354bc1 100644 --- a/backend/src/server/routes/v1/organization-router.ts +++ b/backend/src/server/routes/v1/organization-router.ts @@ -29,30 +29,18 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => { }, schema: { response: { - 200: z.union([ - z.object({ - id: z.string(), - name: z.string(), - slug: z.string(), - role: z.string() - }), - z.object({ - organizations: sanitizedOrganizationSchema - .extend({ - orgAuthMethod: z.string(), - userRole: z.string() - }) - .array() - }) - ]) + 200: z.object({ + organizations: sanitizedOrganizationSchema + .extend({ + orgAuthMethod: z.string(), + userRole: z.string() + }) + .array() + }) } }, - onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN], { requireOrg: false }), + onRequest: verifyAuth([AuthMode.JWT], { requireOrg: false }), handler: async (req) => { - if (req.permission.type === ActorType.IDENTITY) { - const organization = await server.services.org.findIdentityOrganization(req.permission.id); - return organization; - } const organizations = await server.services.org.findAllOrganizationOfUser(req.permission.id); return { organizations }; } From 4bd61e5607478b3da67cd31f5c51b0bca34f45c4 Mon Sep 17 00:00:00 2001 From: Carlos Monastyrski Date: Wed, 13 Aug 2025 11:47:41 -0700 Subject: [PATCH 4/6] Undo license fns changes for testing --- .../src/ee/services/license/license-fns.ts | 68 +++++++++---------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/backend/src/ee/services/license/license-fns.ts b/backend/src/ee/services/license/license-fns.ts index 6620e14d4..033a28045 100644 --- a/backend/src/ee/services/license/license-fns.ts +++ b/backend/src/ee/services/license/license-fns.ts @@ -18,50 +18,50 @@ export const getDefaultOnPremFeatures = (): TFeatureSet => ({ environmentsUsed: 0, identityLimit: null, identitiesUsed: 0, - dynamicSecret: true, + dynamicSecret: false, secretVersioning: true, - pitRecovery: true, - ipAllowlisting: true, - rbac: true, - githubOrgSync: true, - customRateLimits: true, - customAlerts: true, - secretAccessInsights: true, - auditLogs: true, + pitRecovery: false, + ipAllowlisting: false, + rbac: false, + githubOrgSync: false, + customRateLimits: false, + customAlerts: false, + secretAccessInsights: false, + auditLogs: false, auditLogsRetentionDays: 0, - auditLogStreams: true, + auditLogStreams: false, auditLogStreamLimit: 3, - samlSSO: true, - hsm: true, - oidcSSO: true, - scim: true, - ldap: true, - groups: true, + samlSSO: false, + hsm: false, + oidcSSO: false, + scim: false, + ldap: false, + groups: false, status: null, trial_end: null, has_used_trial: true, - secretApproval: true, - secretRotation: true, - caCrl: true, - instanceUserManagement: true, - externalKms: true, + secretApproval: false, + secretRotation: false, + caCrl: false, + instanceUserManagement: false, + externalKms: false, rateLimits: { readLimit: 60, writeLimit: 200, secretsLimit: 40 }, - pkiEst: true, - enforceMfa: true, - projectTemplates: true, - kmip: true, - gateway: true, - sshHostGroups: true, - secretScanning: true, - enterpriseSecretSyncs: true, - enterpriseAppConnections: true, - fips: true, - eventSubscriptions: true, - machineIdentityAuthTemplates: true + pkiEst: false, + enforceMfa: false, + projectTemplates: false, + kmip: false, + gateway: false, + sshHostGroups: false, + secretScanning: false, + enterpriseSecretSyncs: false, + enterpriseAppConnections: false, + fips: false, + eventSubscriptions: false, + machineIdentityAuthTemplates: false }); export const setupLicenseRequestWithStore = ( @@ -117,7 +117,7 @@ export const setupLicenseRequestWithStore = ( // eslint-disable-next-line if ((errStatusCode === 401 || errStatusCode === 403) && !(originalRequest as any)._retry) { // eslint-disable-next-line - (originalRequest as any)._retry = true; // injected + (originalRequest as any)._retry = false; // injected // refresh await refreshLicense(); From f77a53bd8edc473f44db7650a423c6c986809ac4 Mon Sep 17 00:00:00 2001 From: Carlos Monastyrski Date: Wed, 13 Aug 2025 11:48:07 -0700 Subject: [PATCH 5/6] Undo license fns changes for testing --- backend/src/ee/services/license/license-fns.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/ee/services/license/license-fns.ts b/backend/src/ee/services/license/license-fns.ts index 033a28045..bd3949a7e 100644 --- a/backend/src/ee/services/license/license-fns.ts +++ b/backend/src/ee/services/license/license-fns.ts @@ -117,7 +117,7 @@ export const setupLicenseRequestWithStore = ( // eslint-disable-next-line if ((errStatusCode === 401 || errStatusCode === 403) && !(originalRequest as any)._retry) { // eslint-disable-next-line - (originalRequest as any)._retry = false; // injected + (originalRequest as any)._retry = true; // injected // refresh await refreshLicense(); From c2db2a0bc744053a908dc53230499c4f53633521 Mon Sep 17 00:00:00 2001 From: Carlos Monastyrski Date: Wed, 13 Aug 2025 14:20:59 -0700 Subject: [PATCH 6/6] Endpoint improvements --- backend/src/server/routes/v1/identity-router.ts | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/backend/src/server/routes/v1/identity-router.ts b/backend/src/server/routes/v1/identity-router.ts index 82ab82637..9acd515c4 100644 --- a/backend/src/server/routes/v1/identity-router.ts +++ b/backend/src/server/routes/v1/identity-router.ts @@ -488,17 +488,20 @@ export const registerIdentityRouter = async (server: FastifyZodProvider) => { schema: { response: { 200: z.object({ - id: z.string(), - name: z.string(), - slug: z.string(), - role: z.string() + identityDetails: z.object({ + organization: z.object({ + id: z.string(), + name: z.string(), + slug: z.string() + }) + }) }) } }, onRequest: verifyAuth([AuthMode.IDENTITY_ACCESS_TOKEN], { requireOrg: false }), handler: async (req) => { const organization = await server.services.org.findIdentityOrganization(req.permission.id); - return organization; + return { identityDetails: { organization } }; } }); };