mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-07 01:27:41 +00:00
feat(infisical-pg): added telemtry service
This commit is contained in:
@@ -1,2 +1,3 @@
|
|||||||
vitest-environment-infisical.ts
|
vitest-environment-infisical.ts
|
||||||
vitest.config.ts
|
vitest.config.ts
|
||||||
|
.eslintrc.js
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ module.exports = {
|
|||||||
tsconfigRootDir: __dirname
|
tsconfigRootDir: __dirname
|
||||||
},
|
},
|
||||||
rules: {
|
rules: {
|
||||||
"@typescript-eslint/no-empty-function": "off",
|
// "@typescript-eslint/no-empty-function": "off",
|
||||||
"consistent-return": "off", // my style
|
"consistent-return": "off", // my style
|
||||||
"import/order": "off", // for simple-import-order
|
"import/order": "off", // for simple-import-order
|
||||||
"import/prefer-default-export": "off", // why
|
"import/prefer-default-export": "off", // why
|
||||||
|
|||||||
Generated
+18
@@ -55,6 +55,7 @@
|
|||||||
"pg": "^8.11.3",
|
"pg": "^8.11.3",
|
||||||
"picomatch": "^3.0.1",
|
"picomatch": "^3.0.1",
|
||||||
"pino": "^8.16.2",
|
"pino": "^8.16.2",
|
||||||
|
"posthog-node": "^3.6.0",
|
||||||
"probot": "^12.3.3",
|
"probot": "^12.3.3",
|
||||||
"smee-client": "^2.0.0",
|
"smee-client": "^2.0.0",
|
||||||
"tweetnacl": "^1.0.3",
|
"tweetnacl": "^1.0.3",
|
||||||
@@ -10100,6 +10101,18 @@
|
|||||||
"integrity": "sha512-VdlZoocy5lCP0c/t66xAfclglEapXPCIVhqqJRncYpvbCgImF0w67aPKfbqUMr72tO2k5q0TdTZwCLjPTI6C9g==",
|
"integrity": "sha512-VdlZoocy5lCP0c/t66xAfclglEapXPCIVhqqJRncYpvbCgImF0w67aPKfbqUMr72tO2k5q0TdTZwCLjPTI6C9g==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/posthog-node": {
|
||||||
|
"version": "3.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/posthog-node/-/posthog-node-3.6.0.tgz",
|
||||||
|
"integrity": "sha512-N/4//SIQR4fhwbHnDdJ2rQCYdu9wo0EVPK4lVgZswp5R/E42RKlpuO6ZfPsBl+Bcg06OYiOd/WR/jLV90FCoSw==",
|
||||||
|
"dependencies": {
|
||||||
|
"axios": "^1.6.2",
|
||||||
|
"rusha": "^0.8.14"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=15.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/prelude-ls": {
|
"node_modules/prelude-ls": {
|
||||||
"version": "1.2.1",
|
"version": "1.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
|
||||||
@@ -11129,6 +11142,11 @@
|
|||||||
"queue-microtask": "^1.2.2"
|
"queue-microtask": "^1.2.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/rusha": {
|
||||||
|
"version": "0.8.14",
|
||||||
|
"resolved": "https://registry.npmjs.org/rusha/-/rusha-0.8.14.tgz",
|
||||||
|
"integrity": "sha512-cLgakCUf6PedEu15t8kbsjnwIFFR2D4RfL+W3iWFJ4iac7z4B0ZI8fxy4R3J956kAI68HclCFGL8MPoUVC3qVA=="
|
||||||
|
},
|
||||||
"node_modules/safe-array-concat": {
|
"node_modules/safe-array-concat": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.1.tgz",
|
||||||
|
|||||||
@@ -112,6 +112,7 @@
|
|||||||
"pg": "^8.11.3",
|
"pg": "^8.11.3",
|
||||||
"picomatch": "^3.0.1",
|
"picomatch": "^3.0.1",
|
||||||
"pino": "^8.16.2",
|
"pino": "^8.16.2",
|
||||||
|
"posthog-node": "^3.6.0",
|
||||||
"probot": "^12.3.3",
|
"probot": "^12.3.3",
|
||||||
"smee-client": "^2.0.0",
|
"smee-client": "^2.0.0",
|
||||||
"tweetnacl": "^1.0.3",
|
"tweetnacl": "^1.0.3",
|
||||||
|
|||||||
Vendored
+2
@@ -40,6 +40,7 @@ import { TSecretImportServiceFactory } from "@app/services/secret-import/secret-
|
|||||||
import { TSecretTagServiceFactory } from "@app/services/secret-tag/secret-tag-service";
|
import { TSecretTagServiceFactory } from "@app/services/secret-tag/secret-tag-service";
|
||||||
import { TServiceTokenServiceFactory } from "@app/services/service-token/service-token-service";
|
import { TServiceTokenServiceFactory } from "@app/services/service-token/service-token-service";
|
||||||
import { TSuperAdminServiceFactory } from "@app/services/super-admin/super-admin-service";
|
import { TSuperAdminServiceFactory } from "@app/services/super-admin/super-admin-service";
|
||||||
|
import { TTelemetryServiceFactory } from "@app/services/telemetry/telemetry-service";
|
||||||
import { TUserDALFactory } from "@app/services/user/user-dal";
|
import { TUserDALFactory } from "@app/services/user/user-dal";
|
||||||
import { TUserServiceFactory } from "@app/services/user/user-service";
|
import { TUserServiceFactory } from "@app/services/user/user-service";
|
||||||
import { TWebhookServiceFactory } from "@app/services/webhook/webhook-service";
|
import { TWebhookServiceFactory } from "@app/services/webhook/webhook-service";
|
||||||
@@ -107,6 +108,7 @@ declare module "fastify" {
|
|||||||
license: TLicenseServiceFactory;
|
license: TLicenseServiceFactory;
|
||||||
trustedIp: TTrustedIpServiceFactory;
|
trustedIp: TTrustedIpServiceFactory;
|
||||||
secretBlindIndex: TSecretBlindIndexServiceFactory;
|
secretBlindIndex: TSecretBlindIndexServiceFactory;
|
||||||
|
telemetry: TTelemetryServiceFactory;
|
||||||
};
|
};
|
||||||
// this is exclusive use for middlewares in which we need to inject data
|
// this is exclusive use for middlewares in which we need to inject data
|
||||||
// everywhere else access using service layer
|
// everywhere else access using service layer
|
||||||
|
|||||||
+17
-1
@@ -12,6 +12,8 @@ import { QueueJobs, QueueName, TQueueServiceFactory } from "@app/queue";
|
|||||||
import { TProjectBotServiceFactory } from "@app/services/project-bot/project-bot-service";
|
import { TProjectBotServiceFactory } from "@app/services/project-bot/project-bot-service";
|
||||||
import { TSecretDALFactory } from "@app/services/secret/secret-dal";
|
import { TSecretDALFactory } from "@app/services/secret/secret-dal";
|
||||||
import { TSecretVersionDALFactory } from "@app/services/secret/secret-version-dal";
|
import { TSecretVersionDALFactory } from "@app/services/secret/secret-version-dal";
|
||||||
|
import { TTelemetryServiceFactory } from "@app/services/telemetry/telemetry-service";
|
||||||
|
import { PostHogEventTypes } from "@app/services/telemetry/telemetry-types";
|
||||||
|
|
||||||
import { TSecretRotationDALFactory } from "../secret-rotation-dal";
|
import { TSecretRotationDALFactory } from "../secret-rotation-dal";
|
||||||
import { rotationTemplates } from "../templates";
|
import { rotationTemplates } from "../templates";
|
||||||
@@ -41,6 +43,7 @@ type TSecretRotationQueueFactoryDep = {
|
|||||||
projectBotService: Pick<TProjectBotServiceFactory, "getBotKey">;
|
projectBotService: Pick<TProjectBotServiceFactory, "getBotKey">;
|
||||||
secretDAL: Pick<TSecretDALFactory, "bulkUpdate" | "find">;
|
secretDAL: Pick<TSecretDALFactory, "bulkUpdate" | "find">;
|
||||||
secretVersionDAL: Pick<TSecretVersionDALFactory, "insertMany" | "findLatestVersionMany">;
|
secretVersionDAL: Pick<TSecretVersionDALFactory, "insertMany" | "findLatestVersionMany">;
|
||||||
|
telemetryService: Pick<TTelemetryServiceFactory, "sendPostHogEvents">;
|
||||||
};
|
};
|
||||||
|
|
||||||
// These error should stop the repeatable job and ask user to reconfigure rotation
|
// These error should stop the repeatable job and ask user to reconfigure rotation
|
||||||
@@ -61,7 +64,8 @@ export const secretRotationQueueFactory = ({
|
|||||||
secretRotationDAL,
|
secretRotationDAL,
|
||||||
projectBotService,
|
projectBotService,
|
||||||
secretDAL,
|
secretDAL,
|
||||||
secretVersionDAL
|
secretVersionDAL,
|
||||||
|
telemetryService
|
||||||
}: TSecretRotationQueueFactoryDep) => {
|
}: TSecretRotationQueueFactoryDep) => {
|
||||||
const addToQueue = async (rotationId: string, interval: number) => {
|
const addToQueue = async (rotationId: string, interval: number) => {
|
||||||
const appCfg = getConfig();
|
const appCfg = getConfig();
|
||||||
@@ -262,6 +266,18 @@ export const secretRotationQueueFactory = ({
|
|||||||
tx
|
tx
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
telemetryService.sendPostHogEvents({
|
||||||
|
event: PostHogEventTypes.SecretRotated,
|
||||||
|
distinctId: "",
|
||||||
|
properties: {
|
||||||
|
numberOfSecrets: encryptedSecrets.length,
|
||||||
|
environment: secretRotation.environment.slug,
|
||||||
|
folderId: "",
|
||||||
|
workspaceId: secretRotation.projectId
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
logger.info("Finished rotating: rotation id: ", rotationId);
|
logger.info("Finished rotating: rotation id: ", rotationId);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error(error);
|
logger.error(error);
|
||||||
|
|||||||
+21
-1
@@ -6,6 +6,8 @@ import { logger } from "@app/lib/logger";
|
|||||||
import { QueueJobs, QueueName, TQueueServiceFactory } from "@app/queue";
|
import { QueueJobs, QueueName, TQueueServiceFactory } from "@app/queue";
|
||||||
import { TOrgDALFactory } from "@app/services/org/org-dal";
|
import { TOrgDALFactory } from "@app/services/org/org-dal";
|
||||||
import { SmtpTemplates, TSmtpService } from "@app/services/smtp/smtp-service";
|
import { SmtpTemplates, TSmtpService } from "@app/services/smtp/smtp-service";
|
||||||
|
import { TTelemetryServiceFactory } from "@app/services/telemetry/telemetry-service";
|
||||||
|
import { PostHogEventTypes } from "@app/services/telemetry/telemetry-types";
|
||||||
|
|
||||||
import { TSecretScanningDALFactory } from "../secret-scanning-dal";
|
import { TSecretScanningDALFactory } from "../secret-scanning-dal";
|
||||||
import {
|
import {
|
||||||
@@ -23,6 +25,7 @@ type TSecretScanningQueueFactoryDep = {
|
|||||||
secretScanningDAL: TSecretScanningDALFactory;
|
secretScanningDAL: TSecretScanningDALFactory;
|
||||||
smtpService: Pick<TSmtpService, "sendMail">;
|
smtpService: Pick<TSmtpService, "sendMail">;
|
||||||
orgMembershipDAL: Pick<TOrgDALFactory, "findMembership">;
|
orgMembershipDAL: Pick<TOrgDALFactory, "findMembership">;
|
||||||
|
telemetryService: Pick<TTelemetryServiceFactory, "sendPostHogEvents">;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type TSecretScanningQueueFactory = ReturnType<typeof secretScanningQueueFactory>;
|
export type TSecretScanningQueueFactory = ReturnType<typeof secretScanningQueueFactory>;
|
||||||
@@ -31,7 +34,8 @@ export const secretScanningQueueFactory = ({
|
|||||||
queueService,
|
queueService,
|
||||||
secretScanningDAL,
|
secretScanningDAL,
|
||||||
smtpService,
|
smtpService,
|
||||||
orgMembershipDAL: orgMemberDAL,
|
telemetryService,
|
||||||
|
orgMembershipDAL: orgMemberDAL
|
||||||
}: TSecretScanningQueueFactoryDep) => {
|
}: TSecretScanningQueueFactoryDep) => {
|
||||||
const startFullRepoScan = async (payload: TScanFullRepoEventPayload) => {
|
const startFullRepoScan = async (payload: TScanFullRepoEventPayload) => {
|
||||||
await queueService.queue(QueueName.SecretFullRepoScan, QueueJobs.SecretScan, payload, {
|
await queueService.queue(QueueName.SecretFullRepoScan, QueueJobs.SecretScan, payload, {
|
||||||
@@ -160,6 +164,14 @@ export const secretScanningQueueFactory = ({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
telemetryService.sendPostHogEvents({
|
||||||
|
event: PostHogEventTypes.SecretScannerPush,
|
||||||
|
distinctId: repository.fullName,
|
||||||
|
properties: {
|
||||||
|
numberOfRisks: Object.keys(allFindingsByFingerprint).length
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
queueService.start(QueueName.SecretFullRepoScan, async (job) => {
|
queueService.start(QueueName.SecretFullRepoScan, async (job) => {
|
||||||
@@ -220,6 +232,14 @@ export const secretScanningQueueFactory = ({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
telemetryService.sendPostHogEvents({
|
||||||
|
event: PostHogEventTypes.SecretScannerFull,
|
||||||
|
distinctId: repository.fullName,
|
||||||
|
properties: {
|
||||||
|
numberOfRisks: findings.length
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
queueService.listen(QueueName.SecretPushEventScan, "failed", (job, err) => {
|
queueService.listen(QueueName.SecretPushEventScan, "failed", (job, err) => {
|
||||||
|
|||||||
@@ -35,6 +35,13 @@ const envSchema = z
|
|||||||
.min(32)
|
.min(32)
|
||||||
.default("#5VihU%rbXHcHwWwCot5L3vyPsx$7dWYw^iGk!EJg2bC*f$PD$%KCqx^R@#^LSEf"),
|
.default("#5VihU%rbXHcHwWwCot5L3vyPsx$7dWYw^iGk!EJg2bC*f$PD$%KCqx^R@#^LSEf"),
|
||||||
SITE_URL: zpStr(z.string().optional()),
|
SITE_URL: zpStr(z.string().optional()),
|
||||||
|
// Telemetry
|
||||||
|
TELEMETRY_ENABLED: zodStrBool.default("true"),
|
||||||
|
POSTHOG_HOST: zpStr(z.string().optional().default("https://app.posthog.com")),
|
||||||
|
POSTHOG_PROJECT_API_KEY: zpStr(
|
||||||
|
z.string().optional().default("phc_nSin8j5q2zdhpFDI1ETmFNUIuTG4DwKVyIigrY10XiE")
|
||||||
|
),
|
||||||
|
LOOPS_API_KEY: zpStr(z.string().optional()),
|
||||||
// jwt options
|
// jwt options
|
||||||
AUTH_SECRET: zpStr(z.string()).default(process.env.JWT_AUTH_SECRET), // for those still using old JWT_AUTH_SECRET
|
AUTH_SECRET: zpStr(z.string()).default(process.env.JWT_AUTH_SECRET), // for those still using old JWT_AUTH_SECRET
|
||||||
JWT_AUTH_LIFETIME: zpStr(z.string().default("10d")),
|
JWT_AUTH_LIFETIME: zpStr(z.string().default("10d")),
|
||||||
|
|||||||
@@ -93,6 +93,7 @@ import { serviceTokenServiceFactory } from "@app/services/service-token/service-
|
|||||||
import { TSmtpService } from "@app/services/smtp/smtp-service";
|
import { TSmtpService } from "@app/services/smtp/smtp-service";
|
||||||
import { superAdminDALFactory } from "@app/services/super-admin/super-admin-dal";
|
import { superAdminDALFactory } from "@app/services/super-admin/super-admin-dal";
|
||||||
import { getServerCfg, superAdminServiceFactory } from "@app/services/super-admin/super-admin-service";
|
import { getServerCfg, superAdminServiceFactory } from "@app/services/super-admin/super-admin-service";
|
||||||
|
import { telemetryServiceFactory } from "@app/services/telemetry/telemetry-service";
|
||||||
import { userDALFactory } from "@app/services/user/user-dal";
|
import { userDALFactory } from "@app/services/user/user-dal";
|
||||||
import { userServiceFactory } from "@app/services/user/user-service";
|
import { userServiceFactory } from "@app/services/user/user-service";
|
||||||
import { webhookDALFactory } from "@app/services/webhook/webhook-dal";
|
import { webhookDALFactory } from "@app/services/webhook/webhook-dal";
|
||||||
@@ -214,6 +215,7 @@ export const registerRoutes = async (
|
|||||||
licenseService
|
licenseService
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const telemetryService = telemetryServiceFactory();
|
||||||
const tokenService = tokenServiceFactory({ tokenDAL: authTokenDAL, userDAL });
|
const tokenService = tokenServiceFactory({ tokenDAL: authTokenDAL, userDAL });
|
||||||
const userService = userServiceFactory({ userDAL });
|
const userService = userServiceFactory({ userDAL });
|
||||||
const loginService = authLoginServiceFactory({ userDAL, smtpService, tokenService });
|
const loginService = authLoginServiceFactory({ userDAL, smtpService, tokenService });
|
||||||
@@ -254,6 +256,7 @@ export const registerRoutes = async (
|
|||||||
const apiKeyService = apiKeyServiceFactory({ apiKeyDAL, userDAL });
|
const apiKeyService = apiKeyServiceFactory({ apiKeyDAL, userDAL });
|
||||||
|
|
||||||
const secretScanningQueue = secretScanningQueueFactory({
|
const secretScanningQueue = secretScanningQueueFactory({
|
||||||
|
telemetryService,
|
||||||
smtpService,
|
smtpService,
|
||||||
secretScanningDAL,
|
secretScanningDAL,
|
||||||
queueService,
|
queueService,
|
||||||
@@ -389,6 +392,7 @@ export const registerRoutes = async (
|
|||||||
secretQueueService
|
secretQueueService
|
||||||
});
|
});
|
||||||
const secretRotationQueue = secretRotationQueueFactory({
|
const secretRotationQueue = secretRotationQueueFactory({
|
||||||
|
telemetryService,
|
||||||
secretRotationDAL,
|
secretRotationDAL,
|
||||||
queue: queueService,
|
queue: queueService,
|
||||||
secretDAL,
|
secretDAL,
|
||||||
@@ -483,7 +487,8 @@ export const registerRoutes = async (
|
|||||||
secretScanning: secretScanningService,
|
secretScanning: secretScanningService,
|
||||||
license: licenseService,
|
license: licenseService,
|
||||||
trustedIp: trustedIpService,
|
trustedIp: trustedIpService,
|
||||||
secretBlindIndex: secretBlindIndexService
|
secretBlindIndex: secretBlindIndexService,
|
||||||
|
telemetry: telemetryService
|
||||||
});
|
});
|
||||||
|
|
||||||
server.decorate<FastifyZodProvider["store"]>("store", {
|
server.decorate<FastifyZodProvider["store"]>("store", {
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import { verifySuperAdmin } from "@app/server/plugins/auth/superAdmin";
|
|||||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||||
import { AuthMode } from "@app/services/auth/auth-type";
|
import { AuthMode } from "@app/services/auth/auth-type";
|
||||||
import { getServerCfg } from "@app/services/super-admin/super-admin-service";
|
import { getServerCfg } from "@app/services/super-admin/super-admin-service";
|
||||||
|
import { PostHogEventTypes } from "@app/services/telemetry/telemetry-types";
|
||||||
|
|
||||||
export const registerAdminRouter = async (server: FastifyZodProvider) => {
|
export const registerAdminRouter = async (server: FastifyZodProvider) => {
|
||||||
server.route({
|
server.route({
|
||||||
@@ -86,6 +87,16 @@ export const registerAdminRouter = async (server: FastifyZodProvider) => {
|
|||||||
userAgent: req.headers["user-agent"] || ""
|
userAgent: req.headers["user-agent"] || ""
|
||||||
});
|
});
|
||||||
|
|
||||||
|
server.services.telemetry.sendPostHogEvents({
|
||||||
|
event: PostHogEventTypes.AdminInit,
|
||||||
|
distinctId: user.user.email,
|
||||||
|
properties: {
|
||||||
|
email: user.user.email,
|
||||||
|
lastName: user.user.lastName || "",
|
||||||
|
firstName: user.user.firstName || ""
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
res.setCookie("jid", token.refresh, {
|
res.setCookie("jid", token.refresh, {
|
||||||
httpOnly: true,
|
httpOnly: true,
|
||||||
path: "/",
|
path: "/",
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { FastifyRequest } from "fastify";
|
||||||
import picomatch from "picomatch";
|
import picomatch from "picomatch";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
@@ -13,9 +14,23 @@ import { CommitType } from "@app/ee/services/secret-approval-request/secret-appr
|
|||||||
import { BadRequestError } from "@app/lib/errors";
|
import { BadRequestError } from "@app/lib/errors";
|
||||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||||
import { ActorType, AuthMode } from "@app/services/auth/auth-type";
|
import { ActorType, AuthMode } from "@app/services/auth/auth-type";
|
||||||
|
import { PostHogEventTypes } from "@app/services/telemetry/telemetry-types";
|
||||||
|
|
||||||
import { secretRawSchema } from "../sanitizedSchemas";
|
import { secretRawSchema } from "../sanitizedSchemas";
|
||||||
|
|
||||||
|
const getDistinctId = (req: FastifyRequest) => {
|
||||||
|
if (req.auth.actor === ActorType.USER) {
|
||||||
|
return req.auth.user.email;
|
||||||
|
}
|
||||||
|
if (req.auth.actor === ActorType.IDENTITY) {
|
||||||
|
return `identity-${req.auth.identityId}`;
|
||||||
|
}
|
||||||
|
if (req.auth.actor === ActorType.SERVICE) {
|
||||||
|
return `service-token-${req.auth.serviceToken.id}`;
|
||||||
|
}
|
||||||
|
return "unknown-auth-data";
|
||||||
|
};
|
||||||
|
|
||||||
export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
||||||
server.route({
|
server.route({
|
||||||
url: "/raw",
|
url: "/raw",
|
||||||
@@ -88,6 +103,18 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
server.services.telemetry.sendPostHogEvents({
|
||||||
|
event: PostHogEventTypes.SecretPulled,
|
||||||
|
distinctId: getDistinctId(req),
|
||||||
|
properties: {
|
||||||
|
numberOfSecrets: secrets.length,
|
||||||
|
workspaceId,
|
||||||
|
environment,
|
||||||
|
secretPath: req.query.secretPath,
|
||||||
|
...req.auditLogInfo
|
||||||
|
}
|
||||||
|
});
|
||||||
return { secrets, imports };
|
return { secrets, imports };
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -163,6 +190,18 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
server.services.telemetry.sendPostHogEvents({
|
||||||
|
event: PostHogEventTypes.SecretPulled,
|
||||||
|
distinctId: getDistinctId(req),
|
||||||
|
properties: {
|
||||||
|
numberOfSecrets: 1,
|
||||||
|
workspaceId,
|
||||||
|
environment,
|
||||||
|
secretPath: req.query.secretPath,
|
||||||
|
...req.auditLogInfo
|
||||||
|
}
|
||||||
|
});
|
||||||
return { secret };
|
return { secret };
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -217,7 +256,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
|||||||
event: {
|
event: {
|
||||||
type: EventType.CREATE_SECRET,
|
type: EventType.CREATE_SECRET,
|
||||||
metadata: {
|
metadata: {
|
||||||
environment: req.body.environment,
|
environment: req.body.environment,
|
||||||
secretPath: req.body.secretPath,
|
secretPath: req.body.secretPath,
|
||||||
secretId: secret.id,
|
secretId: secret.id,
|
||||||
secretKey: req.params.secretName,
|
secretKey: req.params.secretName,
|
||||||
@@ -225,6 +264,20 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
server.services.telemetry.sendPostHogEvents({
|
||||||
|
event: PostHogEventTypes.SecretCreated,
|
||||||
|
distinctId: getDistinctId(req),
|
||||||
|
properties: {
|
||||||
|
numberOfSecrets: 1,
|
||||||
|
workspaceId: req.body.workspaceId,
|
||||||
|
environment: req.body.environment,
|
||||||
|
secretPath: req.body.secretPath,
|
||||||
|
|
||||||
|
...req.auditLogInfo
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
return { secret };
|
return { secret };
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -285,6 +338,19 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
server.services.telemetry.sendPostHogEvents({
|
||||||
|
event: PostHogEventTypes.SecretUpdated,
|
||||||
|
distinctId: getDistinctId(req),
|
||||||
|
properties: {
|
||||||
|
numberOfSecrets: 1,
|
||||||
|
workspaceId: req.body.workspaceId,
|
||||||
|
environment: req.body.environment,
|
||||||
|
secretPath: req.body.secretPath,
|
||||||
|
|
||||||
|
...req.auditLogInfo
|
||||||
|
}
|
||||||
|
});
|
||||||
return { secret };
|
return { secret };
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -339,6 +405,20 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
server.services.telemetry.sendPostHogEvents({
|
||||||
|
event: PostHogEventTypes.SecretDeleted,
|
||||||
|
distinctId: getDistinctId(req),
|
||||||
|
properties: {
|
||||||
|
numberOfSecrets: 1,
|
||||||
|
workspaceId: req.body.workspaceId,
|
||||||
|
environment: req.body.environment,
|
||||||
|
secretPath: req.body.secretPath,
|
||||||
|
|
||||||
|
...req.auditLogInfo
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
return { secret };
|
return { secret };
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -411,6 +491,19 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
server.services.telemetry.sendPostHogEvents({
|
||||||
|
event: PostHogEventTypes.SecretPulled,
|
||||||
|
distinctId: getDistinctId(req),
|
||||||
|
properties: {
|
||||||
|
numberOfSecrets: secrets.length,
|
||||||
|
workspaceId: req.query.workspaceId,
|
||||||
|
environment: req.query.environment,
|
||||||
|
secretPath: req.query.secretPath,
|
||||||
|
|
||||||
|
...req.auditLogInfo
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
return { secrets, imports };
|
return { secrets, imports };
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -472,6 +565,19 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
server.services.telemetry.sendPostHogEvents({
|
||||||
|
event: PostHogEventTypes.SecretPulled,
|
||||||
|
distinctId: getDistinctId(req),
|
||||||
|
properties: {
|
||||||
|
numberOfSecrets: 1,
|
||||||
|
workspaceId: req.query.workspaceId,
|
||||||
|
environment: req.query.environment,
|
||||||
|
secretPath: req.query.secretPath,
|
||||||
|
|
||||||
|
...req.auditLogInfo
|
||||||
|
}
|
||||||
|
});
|
||||||
return { secret };
|
return { secret };
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -583,6 +689,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return { approval };
|
return { approval };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -621,6 +728,20 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
server.services.telemetry.sendPostHogEvents({
|
||||||
|
event: PostHogEventTypes.SecretCreated,
|
||||||
|
distinctId: getDistinctId(req),
|
||||||
|
properties: {
|
||||||
|
numberOfSecrets: 1,
|
||||||
|
workspaceId: req.body.workspaceId,
|
||||||
|
environment: req.body.environment,
|
||||||
|
secretPath: req.body.secretPath,
|
||||||
|
|
||||||
|
...req.auditLogInfo
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
return { secret };
|
return { secret };
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -788,6 +909,19 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
server.services.telemetry.sendPostHogEvents({
|
||||||
|
event: PostHogEventTypes.SecretUpdated,
|
||||||
|
distinctId: getDistinctId(req),
|
||||||
|
properties: {
|
||||||
|
numberOfSecrets: 1,
|
||||||
|
workspaceId: req.body.workspaceId,
|
||||||
|
environment: req.body.environment,
|
||||||
|
secretPath: req.body.secretPath,
|
||||||
|
|
||||||
|
...req.auditLogInfo
|
||||||
|
}
|
||||||
|
});
|
||||||
return { secret };
|
return { secret };
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -892,6 +1026,19 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
server.services.telemetry.sendPostHogEvents({
|
||||||
|
event: PostHogEventTypes.SecretDeleted,
|
||||||
|
distinctId: getDistinctId(req),
|
||||||
|
properties: {
|
||||||
|
numberOfSecrets: 1,
|
||||||
|
workspaceId: req.body.workspaceId,
|
||||||
|
environment: req.body.environment,
|
||||||
|
secretPath: req.body.secretPath,
|
||||||
|
|
||||||
|
...req.auditLogInfo
|
||||||
|
}
|
||||||
|
});
|
||||||
return { secret };
|
return { secret };
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -1005,6 +1152,19 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
server.services.telemetry.sendPostHogEvents({
|
||||||
|
event: PostHogEventTypes.SecretCreated,
|
||||||
|
distinctId: getDistinctId(req),
|
||||||
|
properties: {
|
||||||
|
numberOfSecrets: secrets.length,
|
||||||
|
workspaceId: req.body.workspaceId,
|
||||||
|
environment: req.body.environment,
|
||||||
|
secretPath: req.body.secretPath,
|
||||||
|
|
||||||
|
...req.auditLogInfo
|
||||||
|
}
|
||||||
|
});
|
||||||
return { secrets };
|
return { secrets };
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -1117,6 +1277,19 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
server.services.telemetry.sendPostHogEvents({
|
||||||
|
event: PostHogEventTypes.SecretUpdated,
|
||||||
|
distinctId: getDistinctId(req),
|
||||||
|
properties: {
|
||||||
|
numberOfSecrets: secrets.length,
|
||||||
|
workspaceId: req.body.workspaceId,
|
||||||
|
environment: req.body.environment,
|
||||||
|
secretPath: req.body.secretPath,
|
||||||
|
|
||||||
|
...req.auditLogInfo
|
||||||
|
}
|
||||||
|
});
|
||||||
return { secrets };
|
return { secrets };
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -1217,6 +1390,19 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
server.services.telemetry.sendPostHogEvents({
|
||||||
|
event: PostHogEventTypes.SecretDeleted,
|
||||||
|
distinctId: getDistinctId(req),
|
||||||
|
properties: {
|
||||||
|
numberOfSecrets: secrets.length,
|
||||||
|
workspaceId: req.body.workspaceId,
|
||||||
|
environment: req.body.environment,
|
||||||
|
secretPath: req.body.secretPath,
|
||||||
|
|
||||||
|
...req.auditLogInfo
|
||||||
|
}
|
||||||
|
});
|
||||||
return { secrets };
|
return { secrets };
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { z } from "zod";
|
|||||||
import { UsersSchema } from "@app/db/schemas";
|
import { UsersSchema } from "@app/db/schemas";
|
||||||
import { getConfig } from "@app/lib/config/env";
|
import { getConfig } from "@app/lib/config/env";
|
||||||
import { authRateLimit } from "@app/server/config/rateLimiter";
|
import { authRateLimit } from "@app/server/config/rateLimiter";
|
||||||
|
import { PostHogEventTypes } from "@app/services/telemetry/telemetry-types";
|
||||||
|
|
||||||
export const registerSignupRouter = async (server: FastifyZodProvider) => {
|
export const registerSignupRouter = async (server: FastifyZodProvider) => {
|
||||||
server.route({
|
server.route({
|
||||||
@@ -100,13 +101,27 @@ export const registerSignupRouter = async (server: FastifyZodProvider) => {
|
|||||||
authorization: req.headers.authorization as string
|
authorization: req.headers.authorization as string
|
||||||
});
|
});
|
||||||
|
|
||||||
|
server.services.telemetry.sendLoopsEvent(
|
||||||
|
user.email,
|
||||||
|
user.firstName || "",
|
||||||
|
user.lastName || ""
|
||||||
|
);
|
||||||
|
|
||||||
|
server.services.telemetry.sendPostHogEvents({
|
||||||
|
event: PostHogEventTypes.UserSignedUp,
|
||||||
|
distinctId: user.email,
|
||||||
|
properties: {
|
||||||
|
email: user.email,
|
||||||
|
attributionSource: req.body.attributionSource
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
res.setCookie("jid", refreshToken, {
|
res.setCookie("jid", refreshToken, {
|
||||||
httpOnly: true,
|
httpOnly: true,
|
||||||
path: "/",
|
path: "/",
|
||||||
sameSite: "strict",
|
sameSite: "strict",
|
||||||
secure: appCfg.HTTPS_ENABLED
|
secure: appCfg.HTTPS_ENABLED
|
||||||
});
|
});
|
||||||
// TODO(akhilmhdh-pg): add telemetry service
|
|
||||||
|
|
||||||
return { message: "Successfully set up account", user, token: accessToken };
|
return { message: "Successfully set up account", user, token: accessToken };
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,68 @@
|
|||||||
|
import { PostHog } from "posthog-node";
|
||||||
|
|
||||||
|
import { getConfig } from "@app/lib/config/env";
|
||||||
|
import { request } from "@app/lib/config/request";
|
||||||
|
import { logger } from "@app/lib/logger";
|
||||||
|
|
||||||
|
import { TPostHogEvent } from "./telemetry-types";
|
||||||
|
|
||||||
|
export type TTelemetryServiceFactory = ReturnType<typeof telemetryServiceFactory>;
|
||||||
|
|
||||||
|
// type TTelemetryServiceFactoryDep = {};
|
||||||
|
export const telemetryServiceFactory = () => {
|
||||||
|
const appCfg = getConfig();
|
||||||
|
|
||||||
|
if (appCfg.isProductionMode && !appCfg.TELEMETRY_ENABLED) {
|
||||||
|
// eslint-disable-next-line
|
||||||
|
console.log(`
|
||||||
|
To improve, Infisical collects telemetry data about general usage.
|
||||||
|
This helps us understand how the product is doing and guide our product development to create the best possible platform; it also helps us demonstrate growth as we support Infisical as open-source software.
|
||||||
|
To opt into telemetry, you can set "TELEMETRY_ENABLED=true" within the environment variables.
|
||||||
|
`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const postHog =
|
||||||
|
appCfg.isProductionMode && appCfg.TELEMETRY_ENABLED
|
||||||
|
? new PostHog(appCfg.POSTHOG_PROJECT_API_KEY, { host: appCfg.POSTHOG_HOST })
|
||||||
|
: undefined;
|
||||||
|
|
||||||
|
// used for email marketting email sending purpose
|
||||||
|
const sendLoopsEvent = async (email: string, firstName?: string, lastName?: string) => {
|
||||||
|
if (appCfg.isProductionMode && appCfg.LOOPS_API_KEY) {
|
||||||
|
try {
|
||||||
|
await request.post(
|
||||||
|
"https://app.loops.so/api/v1/events/send",
|
||||||
|
{
|
||||||
|
eventName: "Sign Up",
|
||||||
|
email,
|
||||||
|
firstName,
|
||||||
|
lastName
|
||||||
|
},
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
Accept: "application/json",
|
||||||
|
Authorization: `Bearer ${appCfg.LOOPS_API_KEY}`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
logger.error(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const sendPostHogEvents = async (event: TPostHogEvent) => {
|
||||||
|
if (postHog) {
|
||||||
|
postHog.capture({
|
||||||
|
event: event.event,
|
||||||
|
distinctId: event.distinctId,
|
||||||
|
properties: event.properties
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
sendLoopsEvent,
|
||||||
|
sendPostHogEvents
|
||||||
|
};
|
||||||
|
};
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
export enum PostHogEventTypes {
|
||||||
|
SecretPush = "secrets pushed",
|
||||||
|
SecretPulled = "secrets pulled",
|
||||||
|
SecretCreated = "secrets added",
|
||||||
|
SecretUpdated = "secrets modified",
|
||||||
|
SecretDeleted = "secrets deleted",
|
||||||
|
AdminInit = "admin initialization",
|
||||||
|
UserSignedUp = "User Signed Up",
|
||||||
|
SecretRotated = "secrets rotated",
|
||||||
|
SecretScannerFull = "historical cloud secret scan",
|
||||||
|
SecretScannerPush = "cloud secret scan"
|
||||||
|
}
|
||||||
|
|
||||||
|
export type TSecretModifiedEvent = {
|
||||||
|
event:
|
||||||
|
| PostHogEventTypes.SecretPush
|
||||||
|
| PostHogEventTypes.SecretRotated
|
||||||
|
| PostHogEventTypes.SecretPulled
|
||||||
|
| PostHogEventTypes.SecretCreated
|
||||||
|
| PostHogEventTypes.SecretUpdated
|
||||||
|
| PostHogEventTypes.SecretDeleted;
|
||||||
|
properties: {
|
||||||
|
numberOfSecrets: number;
|
||||||
|
environment: string;
|
||||||
|
workspaceId: string;
|
||||||
|
secretPath: string;
|
||||||
|
channel?: string;
|
||||||
|
userAgent?: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export type TAdminInitEvent = {
|
||||||
|
event: PostHogEventTypes.AdminInit;
|
||||||
|
properties: {
|
||||||
|
email: string;
|
||||||
|
firstName: string;
|
||||||
|
lastName: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export type TUserSignedUpEvent = {
|
||||||
|
event: PostHogEventTypes.UserSignedUp;
|
||||||
|
properties: {
|
||||||
|
email: string;
|
||||||
|
attributionSource?: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export type TSecretScannerEvent = {
|
||||||
|
event: PostHogEventTypes.SecretScannerFull | PostHogEventTypes.SecretScannerPush;
|
||||||
|
properties: {
|
||||||
|
numberOfRisks: number;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export type TPostHogEvent = { distinctId: string } & (
|
||||||
|
| TSecretModifiedEvent
|
||||||
|
| TAdminInitEvent
|
||||||
|
| TUserSignedUpEvent
|
||||||
|
| TSecretScannerEvent
|
||||||
|
);
|
||||||
@@ -27,6 +27,6 @@
|
|||||||
"@server/*": ["./src/server/*"]
|
"@server/*": ["./src/server/*"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"include": ["src/**/*", "scripts/**/*", "e2e-test/**/*", ".eslintrc.js"],
|
"include": ["src/**/*", "scripts/**/*", "e2e-test/**/*"],
|
||||||
"exclude": ["node_modules"]
|
"exclude": ["node_modules"]
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user