Merge branch 'main' of https://github.com/Infisical/infisical into feat/chef-data-bag-app-connection-secret-sync

This commit is contained in:
Piyush Gupta
2025-11-01 03:09:48 +05:30
145 changed files with 4657 additions and 1490 deletions
+3 -1
View File
@@ -141,7 +141,9 @@ export const main = async ({
await server.register(fastifyRequestContext, {
defaultStoreValues: (req) => ({
reqId: req.id,
log: req.log.child({ reqId: req.id })
log: req.log.child({ reqId: req.id }),
ip: req.realIp,
userAgent: req.headers["user-agent"]
})
});
+81 -5
View File
@@ -1,12 +1,26 @@
import { requestContext } from "@fastify/request-context";
import opentelemetry from "@opentelemetry/api";
import fp from "fastify-plugin";
export const apiMetrics = fp(async (fastify) => {
const apiMeter = opentelemetry.metrics.getMeter("API");
const latencyHistogram = apiMeter.createHistogram("API_latency", {
unit: "ms"
});
const apiMeter = opentelemetry.metrics.getMeter("API");
const latencyHistogram = apiMeter.createHistogram("API_latency", {
unit: "ms"
});
const infisicalMeter = opentelemetry.metrics.getMeter("Infisical");
const requestCounter = infisicalMeter.createCounter("infisical.http.server.request.count", {
description: "Total number of API requests to Infisical (covers both human users and machine identities)",
unit: "{request}"
});
const requestDurationHistogram = infisicalMeter.createHistogram("infisical.http.server.request.duration", {
description: "API request latency",
unit: "s"
});
export const apiMetrics = fp(async (fastify) => {
fastify.addHook("onResponse", async (request, reply) => {
const { method } = request;
const route = request.routerPath;
@@ -17,5 +31,67 @@ export const apiMetrics = fp(async (fastify) => {
method,
statusCode
});
const orgId = requestContext.get("orgId");
const orgName = requestContext.get("orgName");
const userAuthInfo = requestContext.get("userAuthInfo");
const identityAuthInfo = requestContext.get("identityAuthInfo");
const projectDetails = requestContext.get("projectDetails");
const userAgent = requestContext.get("userAgent");
const ip = requestContext.get("ip");
const attributes: Record<string, string | number> = {
"http.request.method": method,
"http.route": route,
"http.response.status_code": statusCode
};
if (orgId) {
attributes["infisical.organization.id"] = orgId;
}
if (orgName) {
attributes["infisical.organization.name"] = orgName;
}
if (userAuthInfo) {
if (userAuthInfo.userId) {
attributes["infisical.user.id"] = userAuthInfo.userId;
}
if (userAuthInfo.email) {
attributes["infisical.user.email"] = userAuthInfo.email;
}
}
if (identityAuthInfo) {
if (identityAuthInfo.identityId) {
attributes["infisical.identity.id"] = identityAuthInfo.identityId;
}
if (identityAuthInfo.identityName) {
attributes["infisical.identity.name"] = identityAuthInfo.identityName;
}
if (identityAuthInfo.authMethod) {
attributes["infisical.auth.method"] = identityAuthInfo.authMethod;
}
}
if (projectDetails) {
if (projectDetails.id) {
attributes["infisical.project.id"] = projectDetails.id;
}
if (projectDetails.name) {
attributes["infisical.project.name"] = projectDetails.name;
}
}
if (userAgent) {
attributes["user_agent.original"] = userAgent;
}
if (ip) {
attributes["client.address"] = ip;
}
requestCounter.add(1, attributes);
requestDurationHistogram.record(reply.elapsedTime / 1000, attributes);
});
});
@@ -1,4 +1,4 @@
import { requestContext } from "@fastify/request-context";
import { requestContext, RequestContextData } from "@fastify/request-context";
import { FastifyRequest } from "fastify";
import fp from "fastify-plugin";
import type { JwtPayload } from "jsonwebtoken";
@@ -159,10 +159,11 @@ export const injectIdentity = fp(
switch (authMode) {
case AuthMode.JWT: {
const { user, tokenVersionId, orgId, rootOrgId, parentOrgId } =
const { user, tokenVersionId, orgId, orgName, rootOrgId, parentOrgId } =
await server.services.authToken.fnValidateJwtIdentity(token, subOrganizationSelector);
requestContext.set("orgId", orgId);
requestContext.set("orgName", orgName);
requestContext.set("userAuthInfo", { userId: user.id, email: user.email || "" });
req.auth = {
authMode: AuthMode.JWT,
user,
@@ -186,6 +187,7 @@ export const injectIdentity = fp(
);
const serverCfg = await getServerCfg();
requestContext.set("orgId", identity.orgId);
requestContext.set("orgName", identity.orgName);
req.auth = {
authMode: AuthMode.IDENTITY_ACCESS_TOKEN,
actor,
@@ -198,24 +200,23 @@ export const injectIdentity = fp(
isInstanceAdmin: serverCfg?.adminIdentityIds?.includes(identity.identityId),
token
};
const identityAuthInfo: RequestContextData["identityAuthInfo"] = {
identityId: identity.identityId,
identityName: identity.name,
authMethod: identity.authMethod
};
if (token?.identityAuth?.oidc) {
requestContext.set("identityAuthInfo", {
identityId: identity.identityId,
oidc: token?.identityAuth?.oidc
});
identityAuthInfo.oidc = token?.identityAuth?.oidc;
}
if (token?.identityAuth?.kubernetes) {
requestContext.set("identityAuthInfo", {
identityId: identity.identityId,
kubernetes: token?.identityAuth?.kubernetes
});
identityAuthInfo.kubernetes = token?.identityAuth?.kubernetes;
}
if (token?.identityAuth?.aws) {
requestContext.set("identityAuthInfo", {
identityId: identity.identityId,
aws: token?.identityAuth?.aws
});
identityAuthInfo.aws = token?.identityAuth?.aws;
}
requestContext.set("identityAuthInfo", identityAuthInfo);
break;
}
case AuthMode.SERVICE_TOKEN: {
@@ -1,4 +1,5 @@
import { ForbiddenError, PureAbility } from "@casl/ability";
import { requestContext } from "@fastify/request-context";
import opentelemetry from "@opentelemetry/api";
import fastifyPlugin from "fastify-plugin";
import jwt from "jsonwebtoken";
@@ -47,6 +48,12 @@ export const fastifyErrHandler = fastifyPlugin(async (server: FastifyZodProvider
unit: "1"
});
const infisicalMeter = opentelemetry.metrics.getMeter("Infisical");
const errorCounter = infisicalMeter.createCounter("infisical.http.server.error.count", {
description: "Total number of API errors in Infisical (covers both human users and machine identities)",
unit: "{error}"
});
server.setErrorHandler((error, req, res) => {
req.log.error(error);
if (appCfg.OTEL_TELEMETRY_COLLECTION_ENABLED) {
@@ -61,6 +68,67 @@ export const fastifyErrHandler = fastifyPlugin(async (server: FastifyZodProvider
type: errorType,
name: error.name
});
const orgId = requestContext.get("orgId");
const orgName = requestContext.get("orgName");
const userAuthInfo = requestContext.get("userAuthInfo");
const identityAuthInfo = requestContext.get("identityAuthInfo");
const projectDetails = requestContext.get("projectDetails");
const attributes: Record<string, string | number> = {
"http.request.method": method,
"http.route": route,
"error.type": errorType,
"error.name": error.name
};
if (orgId) {
attributes["infisical.organization.id"] = orgId;
}
if (orgName) {
attributes["infisical.organization.name"] = orgName;
}
if (userAuthInfo) {
if (userAuthInfo.userId) {
attributes["infisical.user.id"] = userAuthInfo.userId;
}
if (userAuthInfo.email) {
attributes["infisical.user.email"] = userAuthInfo.email;
}
}
if (identityAuthInfo) {
if (identityAuthInfo.identityId) {
attributes["infisical.identity.id"] = identityAuthInfo.identityId;
}
if (identityAuthInfo.identityName) {
attributes["infisical.identity.name"] = identityAuthInfo.identityName;
}
if (identityAuthInfo.authMethod) {
attributes["infisical.auth.method"] = identityAuthInfo.authMethod;
}
}
if (projectDetails) {
if (projectDetails.id) {
attributes["infisical.project.id"] = projectDetails.id;
}
if (projectDetails.name) {
attributes["infisical.project.name"] = projectDetails.name;
}
}
const userAgent = req.headers["user-agent"];
if (userAgent) {
attributes["user_agent.original"] = userAgent;
}
if (req.realIp) {
attributes["client.address"] = req.realIp;
}
errorCounter.add(1, attributes);
}
if (error instanceof BadRequestError) {
+6 -1
View File
@@ -608,6 +608,10 @@ export const registerRoutes = async (
const membershipGroupService = membershipGroupServiceFactory({
membershipGroupDAL,
membershipRoleDAL,
accessApprovalPolicyDAL,
accessApprovalPolicyApproverDAL,
secretApprovalPolicyDAL,
secretApprovalPolicyApproverDAL: sapApproverDAL,
roleDAL,
permissionService,
orgDAL
@@ -1705,7 +1709,8 @@ export const registerRoutes = async (
licenseService,
permissionService,
kmsService,
membershipIdentityDAL
membershipIdentityDAL,
orgDAL
});
const identityAwsAuthService = identityAwsAuthServiceFactory({
@@ -89,6 +89,10 @@ import {
NetlifyConnectionListItemSchema,
SanitizedNetlifyConnectionSchema
} from "@app/services/app-connection/netlify";
import {
NorthflankConnectionListItemSchema,
SanitizedNorthflankConnectionSchema
} from "@app/services/app-connection/northflank";
import { OktaConnectionListItemSchema, SanitizedOktaConnectionSchema } from "@app/services/app-connection/okta";
import {
PostgresConnectionListItemSchema,
@@ -161,6 +165,7 @@ const SanitizedAppConnectionSchema = z.union([
...SanitizedSupabaseConnectionSchema.options,
...SanitizedDigitalOceanConnectionSchema.options,
...SanitizedNetlifyConnectionSchema.options,
...SanitizedNorthflankConnectionSchema.options,
...SanitizedOktaConnectionSchema.options,
...SanitizedAzureADCSConnectionSchema.options,
...SanitizedRedisConnectionSchema.options,
@@ -205,6 +210,7 @@ const AppConnectionOptionsSchema = z.discriminatedUnion("app", [
SupabaseConnectionListItemSchema,
DigitalOceanConnectionListItemSchema,
NetlifyConnectionListItemSchema,
NorthflankConnectionListItemSchema,
OktaConnectionListItemSchema,
AzureADCSConnectionListItemSchema,
RedisConnectionListItemSchema,
@@ -30,6 +30,7 @@ import { registerLdapConnectionRouter } from "./ldap-connection-router";
import { registerMsSqlConnectionRouter } from "./mssql-connection-router";
import { registerMySqlConnectionRouter } from "./mysql-connection-router";
import { registerNetlifyConnectionRouter } from "./netlify-connection-router";
import { registerNorthflankConnectionRouter } from "./northflank-connection-router";
import { registerOktaConnectionRouter } from "./okta-connection-router";
import { registerPostgresConnectionRouter } from "./postgres-connection-router";
import { registerRailwayConnectionRouter } from "./railway-connection-router";
@@ -84,6 +85,7 @@ export const APP_CONNECTION_REGISTER_ROUTER_MAP: Record<AppConnection, (server:
[AppConnection.Supabase]: registerSupabaseConnectionRouter,
[AppConnection.DigitalOcean]: registerDigitalOceanConnectionRouter,
[AppConnection.Netlify]: registerNetlifyConnectionRouter,
[AppConnection.Northflank]: registerNorthflankConnectionRouter,
[AppConnection.Okta]: registerOktaConnectionRouter,
[AppConnection.Redis]: registerRedisConnectionRouter,
[AppConnection.Chef]: registerChefConnectionRouter
@@ -0,0 +1,87 @@
import { z } from "zod";
import { readLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AppConnection } from "@app/services/app-connection/app-connection-enums";
import {
CreateNorthflankConnectionSchema,
SanitizedNorthflankConnectionSchema,
UpdateNorthflankConnectionSchema
} from "@app/services/app-connection/northflank";
import { AuthMode } from "@app/services/auth/auth-type";
import { registerAppConnectionEndpoints } from "./app-connection-endpoints";
export const registerNorthflankConnectionRouter = async (server: FastifyZodProvider) => {
registerAppConnectionEndpoints({
app: AppConnection.Northflank,
server,
sanitizedResponseSchema: SanitizedNorthflankConnectionSchema,
createSchema: CreateNorthflankConnectionSchema,
updateSchema: UpdateNorthflankConnectionSchema
});
// The below endpoints are not exposed and for Infisical App use
server.route({
method: "GET",
url: `/:connectionId/projects`,
config: {
rateLimit: readLimit
},
schema: {
params: z.object({
connectionId: z.string().uuid()
}),
response: {
200: z.object({
projects: z
.object({
name: z.string(),
id: z.string()
})
.array()
})
}
},
onRequest: verifyAuth([AuthMode.JWT]),
handler: async (req) => {
const { connectionId } = req.params;
const projects = await server.services.appConnection.northflank.listProjects(connectionId, req.permission);
return { projects };
}
});
server.route({
method: "GET",
url: `/:connectionId/projects/:projectId/secret-groups`,
config: {
rateLimit: readLimit
},
schema: {
params: z.object({
connectionId: z.string().uuid(),
projectId: z.string()
}),
response: {
200: z.object({
secretGroups: z
.object({
name: z.string(),
id: z.string()
})
.array()
})
}
},
onRequest: verifyAuth([AuthMode.JWT]),
handler: async (req) => {
const { connectionId, projectId } = req.params;
const secretGroups = await server.services.appConnection.northflank.listSecretGroups(
connectionId,
projectId,
req.permission
);
return { secretGroups };
}
});
};
@@ -24,6 +24,7 @@ import { registerHerokuSyncRouter } from "./heroku-sync-router";
import { registerHumanitecSyncRouter } from "./humanitec-sync-router";
import { registerLaravelForgeSyncRouter } from "./laravel-forge-sync-router";
import { registerNetlifySyncRouter } from "./netlify-sync-router";
import { registerNorthflankSyncRouter } from "./northflank-sync-router";
import { registerRailwaySyncRouter } from "./railway-sync-router";
import { registerRenderSyncRouter } from "./render-sync-router";
import { registerSupabaseSyncRouter } from "./supabase-sync-router";
@@ -65,6 +66,7 @@ export const SECRET_SYNC_REGISTER_ROUTER_MAP: Record<SecretSync, (server: Fastif
[SecretSync.Checkly]: registerChecklySyncRouter,
[SecretSync.DigitalOceanAppPlatform]: registerDigitalOceanAppPlatformSyncRouter,
[SecretSync.Netlify]: registerNetlifySyncRouter,
[SecretSync.Northflank]: registerNorthflankSyncRouter,
[SecretSync.Bitbucket]: registerBitbucketSyncRouter,
[SecretSync.LaravelForge]: registerLaravelForgeSyncRouter,
[SecretSync.Chef]: registerChefSyncRouter
@@ -0,0 +1,17 @@
import {
CreateNorthflankSyncSchema,
NorthflankSyncSchema,
UpdateNorthflankSyncSchema
} from "@app/services/secret-sync/northflank";
import { SecretSync } from "@app/services/secret-sync/secret-sync-enums";
import { registerSyncSecretsEndpoints } from "./secret-sync-endpoints";
export const registerNorthflankSyncRouter = async (server: FastifyZodProvider) =>
registerSyncSecretsEndpoints({
destination: SecretSync.Northflank,
server,
responseSchema: NorthflankSyncSchema,
createSchema: CreateNorthflankSyncSchema,
updateSchema: UpdateNorthflankSyncSchema
});
@@ -47,6 +47,7 @@ import { HerokuSyncListItemSchema, HerokuSyncSchema } from "@app/services/secret
import { HumanitecSyncListItemSchema, HumanitecSyncSchema } from "@app/services/secret-sync/humanitec";
import { LaravelForgeSyncListItemSchema, LaravelForgeSyncSchema } from "@app/services/secret-sync/laravel-forge";
import { NetlifySyncListItemSchema, NetlifySyncSchema } from "@app/services/secret-sync/netlify";
import { NorthflankSyncListItemSchema, NorthflankSyncSchema } from "@app/services/secret-sync/northflank";
import { RailwaySyncListItemSchema, RailwaySyncSchema } from "@app/services/secret-sync/railway/railway-sync-schemas";
import { RenderSyncListItemSchema, RenderSyncSchema } from "@app/services/secret-sync/render/render-sync-schemas";
import { SupabaseSyncListItemSchema, SupabaseSyncSchema } from "@app/services/secret-sync/supabase";
@@ -86,6 +87,7 @@ const SecretSyncSchema = z.discriminatedUnion("destination", [
ChecklySyncSchema,
DigitalOceanAppPlatformSyncSchema,
NetlifySyncSchema,
NorthflankSyncSchema,
BitbucketSyncSchema,
LaravelForgeSyncSchema,
ChefSyncSchema
@@ -121,6 +123,7 @@ const SecretSyncOptionsSchema = z.discriminatedUnion("destination", [
ChecklySyncListItemSchema,
SupabaseSyncListItemSchema,
NetlifySyncListItemSchema,
NorthflankSyncListItemSchema,
BitbucketSyncListItemSchema,
LaravelForgeSyncListItemSchema,
ChefSyncListItemSchema
+113 -39
View File
@@ -7,6 +7,7 @@
// All the any rules are disabled because passport typesense with fastify is really poor
import { Authenticator } from "@fastify/passport";
import { requestContext } from "@fastify/request-context";
import fastifySession from "@fastify/session";
import RedisStore from "connect-redis";
import { CronJob } from "cron";
@@ -21,6 +22,7 @@ import { BadRequestError, NotFoundError } from "@app/lib/errors";
import { logger } from "@app/lib/logger";
import { ms } from "@app/lib/ms";
import { fetchGithubEmails, fetchGithubUser } from "@app/lib/requests/github";
import { AuthAttemptAuthMethod, AuthAttemptAuthResult, authAttemptCounter } from "@app/lib/telemetry/metrics";
import { authRateLimit } from "@app/server/config/rateLimiter";
import { addAuthOriginDomainCookie } from "@app/server/lib/cookie";
import { AuthMethod } from "@app/services/auth/auth-type";
@@ -51,30 +53,54 @@ export const registerOauthMiddlewares = (server: FastifyZodProvider) => {
},
// eslint-disable-next-line
async (req, _accessToken, _refreshToken, profile, cb) => {
try {
// @ts-expect-error this is because this is express type and not fastify
const callbackPort = req.session.get("callbackPort");
// @ts-expect-error this is because this is express type and not fastify
const orgSlug = req.session.get("orgSlug");
// @ts-expect-error this is because this is express type and not fastify
const callbackPort = req.session.get("callbackPort");
// @ts-expect-error this is because this is express type and not fastify
const orgSlug = req.session.get("orgSlug");
const email = profile?.emails?.[0]?.value;
if (!email)
throw new NotFoundError({
message: "Email not found",
name: "OauthGoogleRegister"
const email = profile?.emails?.[0]?.value;
if (!email)
throw new NotFoundError({
message: "Email not found",
name: "OauthGoogleRegister"
});
try {
const { isUserCompleted, providerAuthToken, user, orgId, orgName } =
await server.services.login.oauth2Login({
email,
firstName: profile?.name?.givenName || "",
lastName: profile?.name?.familyName || "",
authMethod: AuthMethod.GOOGLE,
callbackPort,
orgSlug
});
const { isUserCompleted, providerAuthToken } = await server.services.login.oauth2Login({
email,
firstName: profile?.name?.givenName || "",
lastName: profile?.name?.familyName || "",
authMethod: AuthMethod.GOOGLE,
callbackPort,
orgSlug
});
if (appCfg.OTEL_TELEMETRY_COLLECTION_ENABLED) {
authAttemptCounter.add(1, {
"infisical.user.email": email,
"infisical.user.id": user.id,
"infisical.organization.id": orgId,
"infisical.organization.name": orgName,
"infisical.auth.method": AuthAttemptAuthMethod.GOOGLE,
"infisical.auth.result": AuthAttemptAuthResult.SUCCESS,
"client.address": requestContext.get("ip"),
"user_agent.original": requestContext.get("userAgent")
});
}
cb(null, { isUserCompleted, providerAuthToken });
} catch (error) {
logger.error(error);
if (appCfg.OTEL_TELEMETRY_COLLECTION_ENABLED) {
authAttemptCounter.add(1, {
"infisical.user.email": email,
"infisical.auth.method": AuthAttemptAuthMethod.GOOGLE,
"infisical.auth.result": AuthAttemptAuthResult.FAILURE,
"client.address": requestContext.get("ip"),
"user_agent.original": requestContext.get("userAgent")
});
}
cb(error as Error, false);
}
}
@@ -101,27 +127,50 @@ export const registerOauthMiddlewares = (server: FastifyZodProvider) => {
},
// eslint-disable-next-line
async (req: any, accessToken: string, _refreshToken: string, _profile: any, done: Function) => {
const ghEmails = await fetchGithubEmails(accessToken);
const { email } = ghEmails.filter((gitHubEmail) => gitHubEmail.primary)[0];
if (!email) throw new Error("No primary email found");
try {
const ghEmails = await fetchGithubEmails(accessToken);
const { email } = ghEmails.filter((gitHubEmail) => gitHubEmail.primary)[0];
if (!email) throw new Error("No primary email found");
// profile does not get automatically populated so we need to manually fetch user info
const user = await fetchGithubUser(accessToken);
const githubUser = await fetchGithubUser(accessToken);
const callbackPort = req.session.get("callbackPort");
const { isUserCompleted, providerAuthToken } = await server.services.login.oauth2Login({
email,
firstName: user.name || user.login,
lastName: "",
authMethod: AuthMethod.GITHUB,
callbackPort
});
const { isUserCompleted, providerAuthToken, user, orgId, orgName } =
await server.services.login.oauth2Login({
email,
firstName: githubUser.name || githubUser.login,
lastName: "",
authMethod: AuthMethod.GITHUB,
callbackPort
});
if (appCfg.OTEL_TELEMETRY_COLLECTION_ENABLED) {
authAttemptCounter.add(1, {
"infisical.user.email": email,
"infisical.user.id": user.id,
"infisical.organization.id": orgId,
"infisical.organization.name": orgName,
"infisical.auth.method": AuthAttemptAuthMethod.GITHUB,
"infisical.auth.result": AuthAttemptAuthResult.SUCCESS,
"client.address": requestContext.get("ip"),
"user_agent.original": requestContext.get("userAgent")
});
}
done(null, { isUserCompleted, providerAuthToken, externalProviderAccessToken: accessToken });
} catch (err) {
if (appCfg.OTEL_TELEMETRY_COLLECTION_ENABLED) {
authAttemptCounter.add(1, {
"infisical.user.email": email,
"infisical.auth.method": AuthAttemptAuthMethod.GITHUB,
"infisical.auth.result": AuthAttemptAuthResult.FAILURE,
"client.address": requestContext.get("ip"),
"user_agent.original": requestContext.get("userAgent")
});
}
logger.error(err);
done(err as Error, false);
}
@@ -147,20 +196,45 @@ export const registerOauthMiddlewares = (server: FastifyZodProvider) => {
pkce: true
},
async (req: any, _accessToken: string, _refreshToken: string, profile: any, cb: any) => {
const email = profile.emails[0].value;
try {
const callbackPort = req.session.get("callbackPort");
const email = profile.emails[0].value;
const { isUserCompleted, providerAuthToken } = await server.services.login.oauth2Login({
email,
firstName: profile.displayName || profile.username || "",
lastName: "",
authMethod: AuthMethod.GITLAB,
callbackPort
});
const { isUserCompleted, providerAuthToken, user, orgId, orgName } =
await server.services.login.oauth2Login({
email,
firstName: profile.displayName || profile.username || "",
lastName: "",
authMethod: AuthMethod.GITLAB,
callbackPort
});
if (appCfg.OTEL_TELEMETRY_COLLECTION_ENABLED) {
authAttemptCounter.add(1, {
"infisical.user.email": email,
"infisical.user.id": user.id,
"infisical.organization.id": orgId,
"infisical.organization.name": orgName,
"infisical.auth.method": AuthAttemptAuthMethod.GITLAB,
"infisical.auth.result": AuthAttemptAuthResult.SUCCESS,
"client.address": requestContext.get("ip"),
"user_agent.original": requestContext.get("userAgent")
});
}
return cb(null, { isUserCompleted, providerAuthToken });
} catch (error) {
if (appCfg.OTEL_TELEMETRY_COLLECTION_ENABLED) {
authAttemptCounter.add(1, {
"infisical.user.email": email,
"infisical.auth.method": AuthAttemptAuthMethod.GITLAB,
"infisical.auth.result": AuthAttemptAuthResult.FAILURE,
"client.address": requestContext.get("ip"),
"user_agent.original": requestContext.get("userAgent")
});
}
logger.error(error);
cb(error as Error, false);
}