Skip to content

Commit 1a79756

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

21 files changed

+195
-44
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: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
import { describe, test as it, expect } from "vitest";
2+
import { schemaLogFilter } from "./schemaLogFilter";
3+
import { list, map, SCHEMA, sim, struct } from "@smithy/core/schema";
4+
5+
describe(schemaLogFilter.name, () => {
6+
it("should filter sensitive trait-marked fields", () => {
7+
const sensitiveString = sim("ns", "SensitiveString", 0, { sensitive: 1 });
8+
9+
const schema = struct(
10+
"ns",
11+
"Struct",
12+
0,
13+
["a", "b", "sensitive", "nestedSensitive", "various"],
14+
[
15+
SCHEMA.STRING,
16+
SCHEMA.STRING,
17+
sensitiveString,
18+
struct("ns", "NestedSensitiveStruct", 0, ["sensitive"], [sensitiveString]),
19+
struct(
20+
"ns",
21+
"Various",
22+
0,
23+
["boolean", "number", "struct", "list-s", "list", "map-s", "map"],
24+
[
25+
sim("ns", "Boolean", SCHEMA.BOOLEAN, { sensitive: 1 }),
26+
sim("ns", "Numeric", SCHEMA.NUMERIC, { sensitive: 1 }),
27+
struct("ns", "SensitiveStruct", { sensitive: 1 }, [], []),
28+
list("ns", "List", 0, sensitiveString),
29+
list("ns", "List", 0, SCHEMA.STRING),
30+
map("ns", "Map", 0, sensitiveString, SCHEMA.STRING),
31+
map("ns", "Map", 0, SCHEMA.STRING, SCHEMA.STRING),
32+
]
33+
),
34+
]
35+
);
36+
37+
expect(
38+
schemaLogFilter(schema, {
39+
a: "a",
40+
b: "b",
41+
sensitive: "xyz",
42+
nestedSensitive: {
43+
sensitive: "xyz",
44+
},
45+
various: {
46+
boolean: false,
47+
number: 1,
48+
struct: {
49+
q: "rf",
50+
},
51+
"list-s": [1, 2, 3],
52+
list: [4, 5, 6],
53+
"map-s": {
54+
a: "a",
55+
b: "b",
56+
c: "c",
57+
},
58+
map: {
59+
a: "d",
60+
b: "e",
61+
c: "f",
62+
},
63+
},
64+
})
65+
).toEqual({
66+
a: "a",
67+
b: "b",
68+
sensitive: "***SensitiveInformation***",
69+
nestedSensitive: {
70+
sensitive: "***SensitiveInformation***",
71+
},
72+
various: {
73+
boolean: "***SensitiveInformation***",
74+
number: "***SensitiveInformation***",
75+
struct: "***SensitiveInformation***",
76+
"list-s": "***SensitiveInformation***",
77+
list: [4, 5, 6],
78+
"map-s": "***SensitiveInformation***",
79+
map: {
80+
a: "d",
81+
b: "e",
82+
c: "f",
83+
},
84+
},
85+
});
86+
});
87+
});
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)