diff --git a/packages/nodejs/.changesets/add-opentelemetry-node-redis-and-ioredis-query-sanitizers.md b/packages/nodejs/.changesets/add-opentelemetry-node-redis-and-ioredis-query-sanitizers.md new file mode 100644 index 00000000..4b6a2696 --- /dev/null +++ b/packages/nodejs/.changesets/add-opentelemetry-node-redis-and-ioredis-query-sanitizers.md @@ -0,0 +1,39 @@ +--- +bump: "patch" +type: "add" +--- + +Add OpenTelemetry node-redis and ioredis query sanitizers. We recommend using these sanitizers to ensure no sensitive data is sent in query statements. Add the sanitizer to the `dbStatementSerializer` config as demonstrated below. + +```js +// tracing.js +// Add the RedisDbStatementSerializer import +const { RedisDbStatementSerializer } = require("@appsignal/nodejs"); +const { RedisInstrumentation } = require("@opentelemetry/instrumentation-redis"); +const sdk = new opentelemetry.NodeSDK({ + instrumentations: [ + new RedisInstrumentation({ + // Configure the AppSignal RedisDbStatementSerializer to sanitize queries + dbStatementSerializer: RedisDbStatementSerializer + }) + ] +}); +``` + +The same can be done for the ioredis instrumentation: + +```js +// tracing.js +// Add the IORedisDbStatementSerializer import +const { IORedisDbStatementSerializer } = require('@appsignal/nodejs'); +const { IORedisInstrumentation } = require('@opentelemetry/instrumentation-ioredis'); +const sdk = new opentelemetry.NodeSDK({ + instrumentations: [ + // Add the IORedisInstrumentation + new IORedisInstrumentation({ + // Configure the AppSignal IORedisDbStatementSerializer to sanitize queries + dbStatementSerializer: IORedisDbStatementSerializer + }) + ] +}); +``` diff --git a/packages/nodejs/src/index.ts b/packages/nodejs/src/index.ts index cd7c044f..2ef487f5 100644 --- a/packages/nodejs/src/index.ts +++ b/packages/nodejs/src/index.ts @@ -8,4 +8,6 @@ export { BaseClient as Appsignal } from "./client" export { SpanProcessor } from "./span_processor" +export { RedisDbStatementSerializer } from "./instrumentation/redis/opentelemetry" +export { RedisDbStatementSerializer as IORedisDbStatementSerializer } from "./instrumentation/redis/opentelemetry" export * from "./interfaces" diff --git a/packages/nodejs/src/instrumentation/redis/__tests__/opentelemetry.test.ts b/packages/nodejs/src/instrumentation/redis/__tests__/opentelemetry.test.ts new file mode 100644 index 00000000..e03331a4 --- /dev/null +++ b/packages/nodejs/src/instrumentation/redis/__tests__/opentelemetry.test.ts @@ -0,0 +1,21 @@ +import { RedisDbStatementSerializer } from "../opentelemetry" + +describe("RedisDbStatementSerializer", () => { + it("sanitizes queries without arguments", () => { + const result = RedisDbStatementSerializer("get", []) + + expect(result).toEqual("get") + }) + + it("sanitizes queries with single arguments", () => { + const result = RedisDbStatementSerializer("get", ["my_key"]) + + expect(result).toEqual("get ?") + }) + + it("sanitizes queries with multiple argumentsj", () => { + const result = RedisDbStatementSerializer("set", ["my_key", "my value"]) + + expect(result).toEqual("set ? ?") + }) +}) diff --git a/packages/nodejs/src/instrumentation/redis/opentelemetry.ts b/packages/nodejs/src/instrumentation/redis/opentelemetry.ts new file mode 100644 index 00000000..f3925aa8 --- /dev/null +++ b/packages/nodejs/src/instrumentation/redis/opentelemetry.ts @@ -0,0 +1,13 @@ +// dbStatementSerializer for OpenTelemetry node-redis and ioredis packages +// This ensures no sensitive data is sent in Redis queries. +export function RedisDbStatementSerializer(command: string, args: Array) { + const values = [] + if (args.length > 0) { + for (let i = 0; i < args.length; i++) { + values.push("?") + } + return `${command} ${values.join(" ")}` + } else { + return command + } +}