diff --git a/backend/src/@types/fastify.d.ts b/backend/src/@types/fastify.d.ts index 153700463..60bcf7348 100644 --- a/backend/src/@types/fastify.d.ts +++ b/backend/src/@types/fastify.d.ts @@ -162,7 +162,7 @@ declare module "fastify" { }; // identity injection. depending on which kinda of token the information is filled in auth auth: TAuthMode; - isPrimaryForwardingMode: boolean; + shouldForwardWritesToPrimaryInstance: boolean; permission: { authMethod: ActorAuthMethod; type: ActorType; diff --git a/backend/src/lib/config/env.ts b/backend/src/lib/config/env.ts index 7add25e70..7416baa59 100644 --- a/backend/src/lib/config/env.ts +++ b/backend/src/lib/config/env.ts @@ -218,7 +218,7 @@ const envSchema = z ), PARAMS_FOLDER_SECRET_DETECTION_ENTROPY: z.coerce.number().optional().default(3.7), - INFISICAL_PRIMARY_URL: zpStr(z.string().optional()), + INFISICAL_PRIMARY_INSTANCE_URL: zpStr(z.string().optional()), // HSM HSM_LIB_PATH: zpStr(z.string().optional()), diff --git a/backend/src/server/plugins/auth/inject-identity.ts b/backend/src/server/plugins/auth/inject-identity.ts index 28bfd8814..2f128dda1 100644 --- a/backend/src/server/plugins/auth/inject-identity.ts +++ b/backend/src/server/plugins/auth/inject-identity.ts @@ -107,115 +107,117 @@ export const extractAuth = async (req: FastifyRequest, jwtSecret: string) => { }; // ! Important: You can only 100% count on the `req.permission.orgId` field being present when the auth method is Identity Access Token (Machine Identity). -export const injectIdentity = fp(async (server: FastifyZodProvider, opt: { isPrimaryForwardingMode?: boolean }) => { - server.decorateRequest("auth", null); - server.decorateRequest("isPrimaryForwardingMode", Boolean(opt.isPrimaryForwardingMode)); - server.addHook("onRequest", async (req) => { - const appCfg = getConfig(); +export const injectIdentity = fp( + async (server: FastifyZodProvider, opt: { shouldForwardWritesToPrimaryInstance?: boolean }) => { + server.decorateRequest("auth", null); + server.decorateRequest("shouldForwardWritesToPrimaryInstance", Boolean(opt.shouldForwardWritesToPrimaryInstance)); + server.addHook("onRequest", async (req) => { + const appCfg = getConfig(); - if (opt.isPrimaryForwardingMode && req.method !== "GET") { - return; - } - - if (req.url.includes(".well-known/est") || req.url.includes("/api/v3/auth/")) { - return; - } - - // Authentication is handled on a route-level here. - if (req.url.includes("/api/v1/workflow-integrations/microsoft-teams/message-endpoint")) { - return; - } - - const { authMode, token, actor } = await extractAuth(req, appCfg.AUTH_SECRET); - - if (!authMode) return; - - switch (authMode) { - case AuthMode.JWT: { - const { user, tokenVersionId, orgId } = await server.services.authToken.fnValidateJwtIdentity(token); - requestContext.set("orgId", orgId); - req.auth = { - authMode: AuthMode.JWT, - user, - userId: user.id, - tokenVersionId, - actor, - orgId: orgId as string, - authMethod: token.authMethod, - isMfaVerified: token.isMfaVerified, - token - }; - break; + if (opt.shouldForwardWritesToPrimaryInstance && req.method !== "GET") { + return; } - case AuthMode.IDENTITY_ACCESS_TOKEN: { - const identity = await server.services.identityAccessToken.fnValidateIdentityAccessToken(token, req.realIp); - const serverCfg = await getServerCfg(); - requestContext.set("orgId", identity.orgId); - req.auth = { - authMode: AuthMode.IDENTITY_ACCESS_TOKEN, - actor, - orgId: identity.orgId, - identityId: identity.identityId, - identityName: identity.name, - authMethod: null, - isInstanceAdmin: serverCfg?.adminIdentityIds?.includes(identity.identityId), - token - }; - if (token?.identityAuth?.oidc) { - requestContext.set("identityAuthInfo", { - identityId: identity.identityId, - oidc: token?.identityAuth?.oidc - }); + + if (req.url.includes(".well-known/est") || req.url.includes("/api/v3/auth/")) { + return; + } + + // Authentication is handled on a route-level here. + if (req.url.includes("/api/v1/workflow-integrations/microsoft-teams/message-endpoint")) { + return; + } + + const { authMode, token, actor } = await extractAuth(req, appCfg.AUTH_SECRET); + + if (!authMode) return; + + switch (authMode) { + case AuthMode.JWT: { + const { user, tokenVersionId, orgId } = await server.services.authToken.fnValidateJwtIdentity(token); + requestContext.set("orgId", orgId); + req.auth = { + authMode: AuthMode.JWT, + user, + userId: user.id, + tokenVersionId, + actor, + orgId: orgId as string, + authMethod: token.authMethod, + isMfaVerified: token.isMfaVerified, + token + }; + break; } - if (token?.identityAuth?.kubernetes) { - requestContext.set("identityAuthInfo", { + case AuthMode.IDENTITY_ACCESS_TOKEN: { + const identity = await server.services.identityAccessToken.fnValidateIdentityAccessToken(token, req.realIp); + const serverCfg = await getServerCfg(); + requestContext.set("orgId", identity.orgId); + req.auth = { + authMode: AuthMode.IDENTITY_ACCESS_TOKEN, + actor, + orgId: identity.orgId, identityId: identity.identityId, - kubernetes: token?.identityAuth?.kubernetes - }); + identityName: identity.name, + authMethod: null, + isInstanceAdmin: serverCfg?.adminIdentityIds?.includes(identity.identityId), + token + }; + if (token?.identityAuth?.oidc) { + requestContext.set("identityAuthInfo", { + identityId: identity.identityId, + oidc: token?.identityAuth?.oidc + }); + } + if (token?.identityAuth?.kubernetes) { + requestContext.set("identityAuthInfo", { + identityId: identity.identityId, + kubernetes: token?.identityAuth?.kubernetes + }); + } + if (token?.identityAuth?.aws) { + requestContext.set("identityAuthInfo", { + identityId: identity.identityId, + aws: token?.identityAuth?.aws + }); + } + break; } - if (token?.identityAuth?.aws) { - requestContext.set("identityAuthInfo", { - identityId: identity.identityId, - aws: token?.identityAuth?.aws - }); + case AuthMode.SERVICE_TOKEN: { + const serviceToken = await server.services.serviceToken.fnValidateServiceToken(token); + requestContext.set("orgId", serviceToken.orgId); + req.auth = { + orgId: serviceToken.orgId, + authMode: AuthMode.SERVICE_TOKEN as const, + serviceToken, + serviceTokenId: serviceToken.id, + actor, + authMethod: null, + token + }; + break; } - break; + case AuthMode.API_KEY: { + const user = await server.services.apiKey.fnValidateApiKey(token as string); + req.auth = { + authMode: AuthMode.API_KEY as const, + userId: user.id, + actor, + user, + orgId: "API_KEY", // We set the orgId to an arbitrary value, since we can't link an API key to a specific org. We have to deprecate API keys soon! + authMethod: null, + token: token as string + }; + break; + } + case AuthMode.SCIM_TOKEN: { + const { orgId, scimTokenId } = await server.services.scim.fnValidateScimToken(token); + requestContext.set("orgId", orgId); + req.auth = { authMode: AuthMode.SCIM_TOKEN, actor, scimTokenId, orgId, authMethod: null }; + break; + } + default: + throw new BadRequestError({ message: "Invalid token strategy provided" }); } - case AuthMode.SERVICE_TOKEN: { - const serviceToken = await server.services.serviceToken.fnValidateServiceToken(token); - requestContext.set("orgId", serviceToken.orgId); - req.auth = { - orgId: serviceToken.orgId, - authMode: AuthMode.SERVICE_TOKEN as const, - serviceToken, - serviceTokenId: serviceToken.id, - actor, - authMethod: null, - token - }; - break; - } - case AuthMode.API_KEY: { - const user = await server.services.apiKey.fnValidateApiKey(token as string); - req.auth = { - authMode: AuthMode.API_KEY as const, - userId: user.id, - actor, - user, - orgId: "API_KEY", // We set the orgId to an arbitrary value, since we can't link an API key to a specific org. We have to deprecate API keys soon! - authMethod: null, - token: token as string - }; - break; - } - case AuthMode.SCIM_TOKEN: { - const { orgId, scimTokenId } = await server.services.scim.fnValidateScimToken(token); - requestContext.set("orgId", orgId); - req.auth = { authMode: AuthMode.SCIM_TOKEN, actor, scimTokenId, orgId, authMethod: null }; - break; - } - default: - throw new BadRequestError({ message: "Invalid token strategy provided" }); - } - }); -}); + }); + } +); diff --git a/backend/src/server/plugins/auth/verify-auth.ts b/backend/src/server/plugins/auth/verify-auth.ts index 0358a8117..c63199769 100644 --- a/backend/src/server/plugins/auth/verify-auth.ts +++ b/backend/src/server/plugins/auth/verify-auth.ts @@ -10,7 +10,7 @@ interface TAuthOptions { export const verifyAuth = (authStrategies: AuthMode[], options: TAuthOptions = { requireOrg: true }) => (req: T, _res: FastifyReply, done: HookHandlerDoneFunction) => { - if (req.isPrimaryForwardingMode && req.method !== "GET") { + if (req.shouldForwardWritesToPrimaryInstance && req.method !== "GET") { return done(); } diff --git a/backend/src/server/plugins/primary-forwarding-mode.ts b/backend/src/server/plugins/primary-forwarding-mode.ts index c609bbf64..611806a6b 100644 --- a/backend/src/server/plugins/primary-forwarding-mode.ts +++ b/backend/src/server/plugins/primary-forwarding-mode.ts @@ -1,7 +1,7 @@ import replyFrom from "@fastify/reply-from"; import fp from "fastify-plugin"; -export const primaryForwardingMode = fp(async (server, opt: { primaryUrl: string }) => { +export const forwardWritesToPrimary = fp(async (server, opt: { primaryUrl: string }) => { await server.register(replyFrom, { base: opt.primaryUrl }); diff --git a/backend/src/server/routes/index.ts b/backend/src/server/routes/index.ts index f932d34ca..24294b46a 100644 --- a/backend/src/server/routes/index.ts +++ b/backend/src/server/routes/index.ts @@ -312,7 +312,7 @@ import { injectAssumePrivilege } from "../plugins/auth/inject-assume-privilege"; import { injectIdentity } from "../plugins/auth/inject-identity"; import { injectPermission } from "../plugins/auth/inject-permission"; import { injectRateLimits } from "../plugins/inject-rate-limits"; -import { primaryForwardingMode } from "../plugins/primary-forwarding-mode"; +import { forwardWritesToPrimary } from "../plugins/primary-forwarding-mode"; import { registerV1Routes } from "./v1"; import { initializeOauthConfigSync } from "./v1/sso-router"; import { registerV2Routes } from "./v2"; @@ -2147,14 +2147,14 @@ export const registerRoutes = async ( user: userDAL, kmipClient: kmipClientDAL }); - const isPrimaryForwardingMode = Boolean(envConfig.INFISICAL_PRIMARY_URL); - if (isPrimaryForwardingMode) { - logger.info(`Infisical primary instance is configured: ${envConfig.INFISICAL_PRIMARY_URL}`); + const shouldForwardWritesToPrimaryInstance = Boolean(envConfig.INFISICAL_PRIMARY_INSTANCE_URL); + if (shouldForwardWritesToPrimaryInstance) { + logger.info(`Infisical primary instance is configured: ${envConfig.INFISICAL_PRIMARY_INSTANCE_URL}`); - await server.register(primaryForwardingMode, { primaryUrl: envConfig.INFISICAL_PRIMARY_URL as string }); + await server.register(forwardWritesToPrimary, { primaryUrl: envConfig.INFISICAL_PRIMARY_INSTANCE_URL as string }); } - await server.register(injectIdentity, { isPrimaryForwardingMode }); + await server.register(injectIdentity, { shouldForwardWritesToPrimaryInstance }); await server.register(injectAssumePrivilege); await server.register(injectPermission); await server.register(injectRateLimits);