Skip to content

Commit 75c09dd

Browse files
committed
chore(middleware-logger): log-filter for schemas
1 parent 0c9e1b8 commit 75c09dd

File tree

3 files changed

+72
-11
lines changed

3 files changed

+72
-11
lines changed

packages/middleware-logger/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@
2525
"types": "./dist-types/index.d.ts",
2626
"dependencies": {
2727
"@aws-sdk/types": "*",
28+
"@smithy/core": "^3.8.0",
2829
"@smithy/types": "^4.3.2",
30+
"@smithy/util-middleware": "^4.0.5",
2931
"tslib": "^2.6.2"
3032
},
3133
"devDependencies": {

packages/middleware-logger/src/loggerMiddleware.ts

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
1-
import {
1+
import type {
22
AbsoluteLocation,
33
HandlerExecutionContext,
44
InitializeHandler,
55
InitializeHandlerArguments,
66
InitializeHandlerOptions,
77
InitializeHandlerOutput,
88
MetadataBearer,
9+
OperationSchema,
910
Pluggable,
1011
} from "@smithy/types";
12+
import { getSmithyContext } from "@smithy/util-middleware";
13+
14+
import { schemaLogFilter } from "./schemaLogFilter";
1115

1216
export const loggerMiddleware =
1317
() =>
@@ -16,33 +20,42 @@ export const loggerMiddleware =
1620
context: HandlerExecutionContext
1721
): InitializeHandler<any, Output> =>
1822
async (args: InitializeHandlerArguments<any>): Promise<InitializeHandlerOutput<Output>> => {
23+
const { operationSchema } = getSmithyContext(context) as {
24+
operationSchema: OperationSchema;
25+
};
26+
1927
try {
2028
const response = await next(args);
21-
const { clientName, commandName, logger, dynamoDbDocumentClientOptions = {} } = context;
2229

23-
const { overrideInputFilterSensitiveLog, overrideOutputFilterSensitiveLog } = dynamoDbDocumentClientOptions;
24-
const inputFilterSensitiveLog = overrideInputFilterSensitiveLog ?? context.inputFilterSensitiveLog;
25-
const outputFilterSensitiveLog = overrideOutputFilterSensitiveLog ?? context.outputFilterSensitiveLog;
30+
const { clientName, commandName, logger } = context;
31+
32+
const inputLogFilter = operationSchema
33+
? schemaLogFilter.bind(operationSchema.input)
34+
: context.inputFilterSensitiveLog;
35+
const outputLogFilter = operationSchema
36+
? schemaLogFilter.bind(operationSchema.output)
37+
: context.outputFilterSensitiveLog;
2638

2739
const { $metadata, ...outputWithoutMetadata } = response.output;
2840
logger?.info?.({
2941
clientName,
3042
commandName,
31-
input: inputFilterSensitiveLog(args.input),
32-
output: outputFilterSensitiveLog(outputWithoutMetadata),
43+
input: inputLogFilter(args.input),
44+
output: outputLogFilter(outputWithoutMetadata),
3345
metadata: $metadata,
3446
});
3547
return response;
3648
} catch (error) {
37-
const { clientName, commandName, logger, dynamoDbDocumentClientOptions = {} } = context;
49+
const { clientName, commandName, logger } = context;
3850

39-
const { overrideInputFilterSensitiveLog } = dynamoDbDocumentClientOptions;
40-
const inputFilterSensitiveLog = overrideInputFilterSensitiveLog ?? context.inputFilterSensitiveLog;
51+
const inputLogFilter = operationSchema
52+
? schemaLogFilter.bind(operationSchema.input)
53+
: context.inputFilterSensitiveLog;
4154

4255
logger?.error?.({
4356
clientName,
4457
commandName,
45-
input: inputFilterSensitiveLog(args.input),
58+
input: inputLogFilter(args.input),
4659
error,
4760
metadata: (error as any).$metadata,
4861
});
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import { NormalizedSchema } from "@smithy/core/schema";
2+
import type { Schema as ISchema } from "@smithy/types";
3+
4+
const SENSITIVE_STRING = "***SensitiveInformation***";
5+
6+
/**
7+
* Redacts sensitive parts of any data object using its schema, for logging.
8+
*
9+
* @internal
10+
* @param schema - with filtering traits.
11+
* @param data - to be logged.
12+
*/
13+
export function schemaLogFilter(schema: ISchema, data: unknown): any {
14+
if (data == null) {
15+
return data;
16+
}
17+
const ns = NormalizedSchema.of(schema);
18+
if (ns.getMergedTraits().sensitive) {
19+
return SENSITIVE_STRING;
20+
}
21+
22+
if (ns.isListSchema()) {
23+
const isSensitive = !!ns.getValueSchema().getMergedTraits().sensitive;
24+
if (isSensitive) {
25+
return SENSITIVE_STRING;
26+
}
27+
} else if (ns.isMapSchema()) {
28+
const isSensitive =
29+
!!ns.getKeySchema().getMergedTraits().sensitive || !!ns.getValueSchema().getMergedTraits().sensitive;
30+
if (isSensitive) {
31+
return SENSITIVE_STRING;
32+
}
33+
} else if (ns.isStructSchema() && typeof data === "object") {
34+
const object = data as Record<string, unknown>;
35+
36+
const newObject = {} as any;
37+
for (const [member, memberNs] of ns.structIterator()) {
38+
if (object[member] != null) {
39+
newObject[member] = schemaLogFilter(memberNs, object[member]);
40+
}
41+
}
42+
return newObject;
43+
}
44+
45+
return data;
46+
}

0 commit comments

Comments
 (0)