Skip to content

Commit d00cc52

Browse files
[Backport 8.11] Bump transport to 8.4.0 (#2096)
* Support for transport 8.4.0 redaction functionality * Docs for `redaction` options (cherry picked from commit c2c417a) Co-authored-by: Josh Mock <[email protected]>
1 parent dda20a4 commit d00cc52

File tree

4 files changed

+107
-6
lines changed

4 files changed

+107
-6
lines changed

docs/advanced-config.asciidoc

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,94 @@ const client = new Client({
9191
})
9292
----
9393

94+
[discrete]
95+
==== Redaction of potentially sensitive data
96+
97+
When the client raises an `Error` that originated at the HTTP layer, like a `ConnectionError` or `TimeoutError`, a `meta` object is often attached to the error object that includes metadata useful for debugging, like request and response information. Because this can include potentially sensitive data, like authentication secrets in an `Authorization` header, the client takes measures to redact common sources of sensitive data when this metadata is attached and serialized.
98+
99+
If your configuration requires extra headers or other configurations that may include sensitive data, you may want to adjust these settings to account for that.
100+
101+
By default, the `redaction` option is set to `{ type: 'replace' }`, which recursively searches for sensitive key names, case insensitive, and replaces their values with the string `[redacted]`.
102+
103+
[source,js]
104+
----
105+
const { Client } = require('@elastic/elasticsearch')
106+
107+
const client = new Client({
108+
cloud: { id: '<cloud-id>' },
109+
auth: { apiKey: 'base64EncodedKey' },
110+
})
111+
112+
try {
113+
await client.indices.create({ index: 'my_index' })
114+
} catch (err) {
115+
console.log(err.meta.meta.request.options.headers.authorization) // prints "[redacted]"
116+
}
117+
----
118+
119+
If you would like to redact additional properties, you can include additional key names to search and replace:
120+
121+
[source,js]
122+
----
123+
const { Client } = require('@elastic/elasticsearch')
124+
125+
const client = new Client({
126+
cloud: { id: '<cloud-id>' },
127+
auth: { apiKey: 'base64EncodedKey' },
128+
headers: { 'X-My-Secret-Password': 'shhh it's a secret!' },
129+
redaction: {
130+
type: "replace",
131+
additionalKeys: ["x-my-secret-password"]
132+
}
133+
})
134+
135+
try {
136+
await client.indices.create({ index: 'my_index' })
137+
} catch (err) {
138+
console.log(err.meta.meta.request.options.headers['X-My-Secret-Password']) // prints "[redacted]"
139+
}
140+
----
141+
142+
Alternatively, if you know you're not going to use the metadata at all, setting the redaction type to `remove` will remove all optional sources of potentially sensitive data entirely, or replacing them with `null` for required properties.
143+
144+
[source,js]
145+
----
146+
const { Client } = require('@elastic/elasticsearch')
147+
148+
const client = new Client({
149+
cloud: { id: '<cloud-id>' },
150+
auth: { apiKey: 'base64EncodedKey' },
151+
redaction: { type: "remove" }
152+
})
153+
154+
try {
155+
await client.indices.create({ index: 'my_index' })
156+
} catch (err) {
157+
console.log(err.meta.meta.request.options.headers) // undefined
158+
}
159+
----
160+
161+
Finally, if you prefer to turn off redaction altogether, perhaps while debugging on a local developer environment, you can set the redaction type to `off`. This will revert the client to pre-8.11.0 behavior, where basic redaction is only performed during common serialization methods like `console.log` and `JSON.stringify`.
162+
163+
WARNING: Setting `redaction.type` to `off` is not recommended in production environments.
164+
165+
[source,js]
166+
----
167+
const { Client } = require('@elastic/elasticsearch')
168+
169+
const client = new Client({
170+
cloud: { id: '<cloud-id>' },
171+
auth: { apiKey: 'base64EncodedKey' },
172+
redaction: { type: "off" }
173+
})
174+
175+
try {
176+
await client.indices.create({ index: 'my_index' })
177+
} catch (err) {
178+
console.log(err.meta.meta.request.options.headers.authorization) // the actual header value will be logged
179+
}
180+
----
181+
94182
[discrete]
95183
==== Migrate to v8
96184

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@
8282
"zx": "^7.2.2"
8383
},
8484
"dependencies": {
85-
"@elastic/transport": "^8.3.4",
85+
"@elastic/transport": "^8.4.0",
8686
"tslib": "^2.4.0"
8787
},
8888
"tap": {

src/client.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ import {
4343
BearerAuth,
4444
Context
4545
} from '@elastic/transport/lib/types'
46+
import { RedactionOptions } from '@elastic/transport/lib/Transport'
4647
import BaseConnection, { prepareHeaders } from '@elastic/transport/lib/connection/BaseConnection'
4748
import SniffingTransport from './sniffingTransport'
4849
import Helpers from './helpers'
@@ -113,6 +114,7 @@ export interface ClientOptions {
113114
caFingerprint?: string
114115
maxResponseSize?: number
115116
maxCompressedResponseSize?: number
117+
redaction?: RedactionOptions
116118
}
117119

118120
export default class Client extends API {
@@ -186,7 +188,11 @@ export default class Client extends API {
186188
proxy: null,
187189
enableMetaHeader: true,
188190
maxResponseSize: null,
189-
maxCompressedResponseSize: null
191+
maxCompressedResponseSize: null,
192+
redaction: {
193+
type: 'replace',
194+
additionalKeys: []
195+
}
190196
}, opts)
191197

192198
if (options.caFingerprint != null && isHttpConnection(opts.node ?? opts.nodes)) {
@@ -259,7 +265,8 @@ export default class Client extends API {
259265
jsonContentType: 'application/vnd.elasticsearch+json; compatible-with=8',
260266
ndjsonContentType: 'application/vnd.elasticsearch+x-ndjson; compatible-with=8',
261267
accept: 'application/vnd.elasticsearch+json; compatible-with=8,text/plain'
262-
}
268+
},
269+
redaction: options.redaction
263270
})
264271

265272
this.helpers = new Helpers({

src/helpers.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -196,8 +196,11 @@ export default class Helpers {
196196
await sleep(wait)
197197
}
198198
assert(response !== undefined, 'The response is undefined, please file a bug report')
199+
200+
const { redaction = { type: 'replace' } } = options
201+
const errorOptions = { redaction }
199202
if (response.statusCode === 429) {
200-
throw new ResponseError(response)
203+
throw new ResponseError(response, errorOptions)
201204
}
202205

203206
let scroll_id = response.body._scroll_id
@@ -237,7 +240,7 @@ export default class Helpers {
237240
await sleep(wait)
238241
}
239242
if (response.statusCode === 429) {
240-
throw new ResponseError(response)
243+
throw new ResponseError(response, errorOptions)
241244
}
242245
}
243246

@@ -289,6 +292,9 @@ export default class Helpers {
289292
} = options
290293
reqOptions.meta = true
291294

295+
const { redaction = { type: 'replace' } } = reqOptions
296+
const errorOptions = { redaction }
297+
292298
let stopReading = false
293299
let stopError: Error | null = null
294300
let timeoutRef = null
@@ -502,7 +508,7 @@ export default class Helpers {
502508
// @ts-expect-error
503509
addDocumentsGetter(result)
504510
if (response.status != null && response.status >= 400) {
505-
callbacks[i](new ResponseError(result), result)
511+
callbacks[i](new ResponseError(result, errorOptions), result)
506512
} else {
507513
callbacks[i](null, result)
508514
}

0 commit comments

Comments
 (0)