Use the right encryption

This commit is contained in:
Owen
2026-04-03 17:59:21 -04:00
parent 8cbc8dec89
commit eb4b2daaab
4 changed files with 21 additions and 51 deletions

View File

@@ -23,8 +23,8 @@ import {
} from "@server/db"; } from "@server/db";
import logger from "@server/logger"; import logger from "@server/logger";
import { and, eq, gt, desc, max, sql } from "drizzle-orm"; import { and, eq, gt, desc, max, sql } from "drizzle-orm";
import { decryptData } from "@server/lib/encryption"; import { decrypt } from "@server/lib/crypto";
import privateConfig from "#private/lib/config"; import config from "@server/lib/config";
import { import {
LogType, LogType,
LOG_TYPES, LOG_TYPES,
@@ -36,21 +36,6 @@ import { LogDestinationProvider } from "./providers/LogDestinationProvider";
import { HttpLogDestination } from "./providers/HttpLogDestination"; import { HttpLogDestination } from "./providers/HttpLogDestination";
import type { EventStreamingDestination } from "@server/db"; import type { EventStreamingDestination } from "@server/db";
// ---------------------------------------------------------------------------
// Encryption helpers
// ---------------------------------------------------------------------------
let encryptionKey: Buffer | undefined;
function getEncryptionKey(): Buffer {
if (!encryptionKey) {
const keyHex =
privateConfig.getRawPrivateConfig().server.encryption_key;
encryptionKey = Buffer.from(keyHex, "hex");
}
return encryptionKey;
}
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Configuration // Configuration
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@@ -290,10 +275,10 @@ export class LogStreamingManager {
} }
// Decrypt and parse config skip destination if either step fails // Decrypt and parse config skip destination if either step fails
let config: HttpConfig; let configFromDb: HttpConfig;
try { try {
const decryptedConfig = decryptData(dest.config, getEncryptionKey()); const decryptedConfig = decrypt(dest.config, config.getRawConfig().server.secret!);
config = JSON.parse(decryptedConfig) as HttpConfig; configFromDb = JSON.parse(decryptedConfig) as HttpConfig;
} catch (err) { } catch (err) {
logger.error( logger.error(
`LogStreamingManager: destination ${dest.destinationId} has invalid or undecryptable config`, `LogStreamingManager: destination ${dest.destinationId} has invalid or undecryptable config`,
@@ -302,7 +287,7 @@ export class LogStreamingManager {
return; return;
} }
const provider = this.createProvider(dest.type, config); const provider = this.createProvider(dest.type, configFromDb);
if (!provider) { if (!provider) {
logger.warn( logger.warn(
`LogStreamingManager: unsupported destination type "${dest.type}" ` + `LogStreamingManager: unsupported destination type "${dest.type}" ` +

View File

@@ -22,8 +22,8 @@ import createHttpError from "http-errors";
import logger from "@server/logger"; import logger from "@server/logger";
import { fromError } from "zod-validation-error"; import { fromError } from "zod-validation-error";
import { OpenAPITags, registry } from "@server/openApi"; import { OpenAPITags, registry } from "@server/openApi";
import { encryptData } from "@server/lib/encryption"; import { encrypt } from "@server/lib/crypto";
import privateConfig from "#private/lib/config"; import config from "@server/lib/config";
const paramsSchema = z.strictObject({ const paramsSchema = z.strictObject({
orgId: z.string().nonempty() orgId: z.string().nonempty()
@@ -89,12 +89,10 @@ export async function createEventStreamingDestination(
); );
} }
const { type, config, enabled } = parsedBody.data; const { type, config: configToSet, enabled } = parsedBody.data;
const encryptionKeyHex = const key = config.getRawConfig().server.secret!;
privateConfig.getRawPrivateConfig().server.encryption_key; const encryptedConfig = encrypt(configToSet, key);
const encryptionKey = Buffer.from(encryptionKeyHex, "hex");
const encryptedConfig = encryptData(config, encryptionKey);
const now = Date.now(); const now = Date.now();

View File

@@ -22,19 +22,8 @@ import logger from "@server/logger";
import { fromError } from "zod-validation-error"; import { fromError } from "zod-validation-error";
import { OpenAPITags, registry } from "@server/openApi"; import { OpenAPITags, registry } from "@server/openApi";
import { eq, sql } from "drizzle-orm"; import { eq, sql } from "drizzle-orm";
import { decryptData } from "@server/lib/encryption"; import { decrypt } from "@server/lib/crypto";
import privateConfig from "#private/lib/config"; import config from "@server/lib/config";
let encryptionKey: Buffer;
function getEncryptionKey(): Buffer {
if (!encryptionKey) {
const keyHex =
privateConfig.getRawPrivateConfig().server.encryption_key;
encryptionKey = Buffer.from(keyHex, "hex");
}
return encryptionKey;
}
const paramsSchema = z.strictObject({ const paramsSchema = z.strictObject({
orgId: z.string().nonempty() orgId: z.string().nonempty()
@@ -134,10 +123,10 @@ export async function listEventStreamingDestinations(
.from(eventStreamingDestinations) .from(eventStreamingDestinations)
.where(eq(eventStreamingDestinations.orgId, orgId)); .where(eq(eventStreamingDestinations.orgId, orgId));
const key = getEncryptionKey(); const key = config.getRawConfig().server.secret!;
const decryptedList = list.map((dest) => { const decryptedList = list.map((dest) => {
try { try {
return { ...dest, config: decryptData(dest.config, key) }; return { ...dest, config: decrypt(dest.config, key) };
} catch (err) { } catch (err) {
logger.error( logger.error(
`listEventStreamingDestinations: failed to decrypt config for destination ${dest.destinationId}`, `listEventStreamingDestinations: failed to decrypt config for destination ${dest.destinationId}`,

View File

@@ -22,9 +22,8 @@ import logger from "@server/logger";
import { fromError } from "zod-validation-error"; import { fromError } from "zod-validation-error";
import { OpenAPITags, registry } from "@server/openApi"; import { OpenAPITags, registry } from "@server/openApi";
import { and, eq } from "drizzle-orm"; import { and, eq } from "drizzle-orm";
import { encryptData } from "@server/lib/encryption"; import { encrypt } from "@server/lib/crypto";
import privateConfig from "#private/lib/config"; import config from "@server/lib/config";
const paramsSchema = z const paramsSchema = z
.object({ .object({
@@ -112,17 +111,16 @@ export async function updateEventStreamingDestination(
); );
} }
const { type, config, enabled, sendAccessLogs, sendActionLogs, sendConnectionLogs, sendRequestLogs } = parsedBody.data; const { type, config: configToUpdate, enabled, sendAccessLogs, sendActionLogs, sendConnectionLogs, sendRequestLogs } = parsedBody.data;
const updateData: Record<string, unknown> = { const updateData: Record<string, unknown> = {
updatedAt: Date.now() updatedAt: Date.now()
}; };
if (type !== undefined) updateData.type = type; if (type !== undefined) updateData.type = type;
if (config !== undefined) { if (configToUpdate !== undefined) {
const encryptionKeyHex = privateConfig.getRawPrivateConfig().server.encryption_key; const key = config.getRawConfig().server.secret!;
const encryptionKey = Buffer.from(encryptionKeyHex, "hex"); updateData.config = encrypt(configToUpdate, key);
updateData.config = encryptData(config, encryptionKey);
} }
if (enabled !== undefined) updateData.enabled = enabled; if (enabled !== undefined) updateData.enabled = enabled;
if (sendAccessLogs !== undefined) updateData.sendAccessLogs = sendAccessLogs; if (sendAccessLogs !== undefined) updateData.sendAccessLogs = sendAccessLogs;