Skip to content

Commit c7dab09

Browse files
committed
chore(core/schema): use schema log filter when available
1 parent d79dc91 commit c7dab09

22 files changed

+196
-45
lines changed

.changeset/lemon-wasps-itch.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@smithy/smithy-client": minor
3+
---
4+
5+
default schema log filter

packages/smithy-client/src/command.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ import type {
2020
} from "@smithy/types";
2121
import { SMITHY_CONTEXT_KEY } from "@smithy/types";
2222

23+
import { schemaLogFilter } from "./schemaLogFilter";
24+
2325
/**
2426
* @public
2527
*/
@@ -130,8 +132,8 @@ class ClassBuilder<
130132
private _clientName = "";
131133
private _additionalContext = {} as HandlerExecutionContext;
132134
private _smithyContext = {} as Record<string, unknown>;
133-
private _inputFilterSensitiveLog = (_: any) => _;
134-
private _outputFilterSensitiveLog = (_: any) => _;
135+
private _inputFilterSensitiveLog: any = undefined;
136+
private _outputFilterSensitiveLog: any = undefined;
135137
private _serializer: (input: I, context: SerdeContext | any) => Promise<IHttpRequest> = null as any;
136138
private _deserializer: (output: IHttpResponse, context: SerdeContext | any) => Promise<O> = null as any;
137139
private _operationSchema?: OperationSchema;
@@ -268,8 +270,12 @@ class ClassBuilder<
268270
middlewareFn: closure._middlewareFn,
269271
clientName: closure._clientName,
270272
commandName: closure._commandName,
271-
inputFilterSensitiveLog: closure._inputFilterSensitiveLog,
272-
outputFilterSensitiveLog: closure._outputFilterSensitiveLog,
273+
inputFilterSensitiveLog:
274+
closure._inputFilterSensitiveLog ??
275+
(closure._operationSchema ? schemaLogFilter.bind(null, closure._operationSchema!.input) : (_) => _),
276+
outputFilterSensitiveLog:
277+
closure._outputFilterSensitiveLog ??
278+
(closure._operationSchema ? schemaLogFilter.bind(null, closure._operationSchema!.output) : (_) => _),
273279
smithyContext: closure._smithyContext,
274280
additionalContext: closure._additionalContext,
275281
});
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
import { list, map, SCHEMA, sim, struct } from "@smithy/core/schema";
2+
import { describe, expect, test as it } from "vitest";
3+
4+
import { schemaLogFilter } from "./schemaLogFilter";
5+
6+
describe(schemaLogFilter.name, () => {
7+
it("should filter sensitive trait-marked fields", () => {
8+
const sensitiveString = sim("ns", "SensitiveString", 0, { sensitive: 1 });
9+
10+
const schema = struct(
11+
"ns",
12+
"Struct",
13+
0,
14+
["a", "b", "sensitive", "nestedSensitive", "various"],
15+
[
16+
SCHEMA.STRING,
17+
SCHEMA.STRING,
18+
sensitiveString,
19+
struct("ns", "NestedSensitiveStruct", 0, ["sensitive"], [sensitiveString]),
20+
struct(
21+
"ns",
22+
"Various",
23+
0,
24+
["boolean", "number", "struct", "list-s", "list", "map-s", "map"],
25+
[
26+
sim("ns", "Boolean", SCHEMA.BOOLEAN, { sensitive: 1 }),
27+
sim("ns", "Numeric", SCHEMA.NUMERIC, { sensitive: 1 }),
28+
struct("ns", "SensitiveStruct", { sensitive: 1 }, [], []),
29+
list("ns", "List", 0, sensitiveString),
30+
list("ns", "List", 0, SCHEMA.STRING),
31+
map("ns", "Map", 0, sensitiveString, SCHEMA.STRING),
32+
map("ns", "Map", 0, SCHEMA.STRING, SCHEMA.STRING),
33+
]
34+
),
35+
]
36+
);
37+
38+
expect(
39+
schemaLogFilter(schema, {
40+
a: "a",
41+
b: "b",
42+
sensitive: "xyz",
43+
nestedSensitive: {
44+
sensitive: "xyz",
45+
},
46+
various: {
47+
boolean: false,
48+
number: 1,
49+
struct: {
50+
q: "rf",
51+
},
52+
"list-s": [1, 2, 3],
53+
list: [4, 5, 6],
54+
"map-s": {
55+
a: "a",
56+
b: "b",
57+
c: "c",
58+
},
59+
map: {
60+
a: "d",
61+
b: "e",
62+
c: "f",
63+
},
64+
},
65+
})
66+
).toEqual({
67+
a: "a",
68+
b: "b",
69+
sensitive: "***SensitiveInformation***",
70+
nestedSensitive: {
71+
sensitive: "***SensitiveInformation***",
72+
},
73+
various: {
74+
boolean: "***SensitiveInformation***",
75+
number: "***SensitiveInformation***",
76+
struct: "***SensitiveInformation***",
77+
"list-s": "***SensitiveInformation***",
78+
list: [4, 5, 6],
79+
"map-s": "***SensitiveInformation***",
80+
map: {
81+
a: "d",
82+
b: "e",
83+
c: "f",
84+
},
85+
},
86+
});
87+
});
88+
});
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 { SchemaRef } 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: SchemaRef, 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+
}

private/smithy-rpcv2-cbor-schema/src/commands/EmptyInputOutputCommand.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,6 @@ export class EmptyInputOutputCommand extends $Command
6666
})
6767
.s("RpcV2Protocol", "EmptyInputOutput", {})
6868
.n("RpcV2ProtocolClient", "EmptyInputOutputCommand")
69-
.f(void 0, void 0)
7069
.sc(EmptyInputOutput)
7170
.build() {
7271
/** @internal type navigation helper, not in runtime. */

private/smithy-rpcv2-cbor-schema/src/commands/Float16Command.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,6 @@ export class Float16Command extends $Command
6868
})
6969
.s("RpcV2Protocol", "Float16", {})
7070
.n("RpcV2ProtocolClient", "Float16Command")
71-
.f(void 0, void 0)
7271
.sc(Float16)
7372
.build() {
7473
/** @internal type navigation helper, not in runtime. */

private/smithy-rpcv2-cbor-schema/src/commands/FractionalSecondsCommand.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,6 @@ export class FractionalSecondsCommand extends $Command
6868
})
6969
.s("RpcV2Protocol", "FractionalSeconds", {})
7070
.n("RpcV2ProtocolClient", "FractionalSecondsCommand")
71-
.f(void 0, void 0)
7271
.sc(FractionalSeconds)
7372
.build() {
7473
/** @internal type navigation helper, not in runtime. */

private/smithy-rpcv2-cbor-schema/src/commands/GreetingWithErrorsCommand.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,6 @@ export class GreetingWithErrorsCommand extends $Command
8181
})
8282
.s("RpcV2Protocol", "GreetingWithErrors", {})
8383
.n("RpcV2ProtocolClient", "GreetingWithErrorsCommand")
84-
.f(void 0, void 0)
8584
.sc(GreetingWithErrors)
8685
.build() {
8786
/** @internal type navigation helper, not in runtime. */

private/smithy-rpcv2-cbor-schema/src/commands/NoInputOutputCommand.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,6 @@ export class NoInputOutputCommand extends $Command
6565
})
6666
.s("RpcV2Protocol", "NoInputOutput", {})
6767
.n("RpcV2ProtocolClient", "NoInputOutputCommand")
68-
.f(void 0, void 0)
6968
.sc(NoInputOutput)
7069
.build() {
7170
/** @internal type navigation helper, not in runtime. */

private/smithy-rpcv2-cbor-schema/src/commands/OperationWithDefaultsCommand.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,6 @@ export class OperationWithDefaultsCommand extends $Command
134134
})
135135
.s("RpcV2Protocol", "OperationWithDefaults", {})
136136
.n("RpcV2ProtocolClient", "OperationWithDefaultsCommand")
137-
.f(void 0, void 0)
138137
.sc(OperationWithDefaults)
139138
.build() {
140139
/** @internal type navigation helper, not in runtime. */

0 commit comments

Comments
 (0)