Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Backport 8.12] Bump transport to 8.4.0 #2098

Merged
merged 1 commit into from
Dec 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 88 additions & 0 deletions docs/advanced-config.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,94 @@ const client = new Client({
})
----

[discrete]
==== Redaction of potentially sensitive data

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.

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.

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]`.

[source,js]
----
const { Client } = require('@elastic/elasticsearch')

const client = new Client({
cloud: { id: '<cloud-id>' },
auth: { apiKey: 'base64EncodedKey' },
})

try {
await client.indices.create({ index: 'my_index' })
} catch (err) {
console.log(err.meta.meta.request.options.headers.authorization) // prints "[redacted]"
}
----

If you would like to redact additional properties, you can include additional key names to search and replace:

[source,js]
----
const { Client } = require('@elastic/elasticsearch')

const client = new Client({
cloud: { id: '<cloud-id>' },
auth: { apiKey: 'base64EncodedKey' },
headers: { 'X-My-Secret-Password': 'shhh it's a secret!' },
redaction: {
type: "replace",
additionalKeys: ["x-my-secret-password"]
}
})

try {
await client.indices.create({ index: 'my_index' })
} catch (err) {
console.log(err.meta.meta.request.options.headers['X-My-Secret-Password']) // prints "[redacted]"
}
----

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.

[source,js]
----
const { Client } = require('@elastic/elasticsearch')

const client = new Client({
cloud: { id: '<cloud-id>' },
auth: { apiKey: 'base64EncodedKey' },
redaction: { type: "remove" }
})

try {
await client.indices.create({ index: 'my_index' })
} catch (err) {
console.log(err.meta.meta.request.options.headers) // undefined
}
----

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`.

WARNING: Setting `redaction.type` to `off` is not recommended in production environments.

[source,js]
----
const { Client } = require('@elastic/elasticsearch')

const client = new Client({
cloud: { id: '<cloud-id>' },
auth: { apiKey: 'base64EncodedKey' },
redaction: { type: "off" }
})

try {
await client.indices.create({ index: 'my_index' })
} catch (err) {
console.log(err.meta.meta.request.options.headers.authorization) // the actual header value will be logged
}
----

[discrete]
==== Migrate to v8

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@
"zx": "^7.2.2"
},
"dependencies": {
"@elastic/transport": "^8.3.4",
"@elastic/transport": "^8.4.0",
"tslib": "^2.4.0"
},
"tap": {
Expand Down
11 changes: 9 additions & 2 deletions src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import {
BearerAuth,
Context
} from '@elastic/transport/lib/types'
import { RedactionOptions } from '@elastic/transport/lib/Transport'
import BaseConnection, { prepareHeaders } from '@elastic/transport/lib/connection/BaseConnection'
import SniffingTransport from './sniffingTransport'
import Helpers from './helpers'
Expand Down Expand Up @@ -113,6 +114,7 @@ export interface ClientOptions {
caFingerprint?: string
maxResponseSize?: number
maxCompressedResponseSize?: number
redaction?: RedactionOptions
}

export default class Client extends API {
Expand Down Expand Up @@ -186,7 +188,11 @@ export default class Client extends API {
proxy: null,
enableMetaHeader: true,
maxResponseSize: null,
maxCompressedResponseSize: null
maxCompressedResponseSize: null,
redaction: {
type: 'replace',
additionalKeys: []
}
}, opts)

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

this.helpers = new Helpers({
Expand Down
12 changes: 9 additions & 3 deletions src/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -196,8 +196,11 @@ export default class Helpers {
await sleep(wait)
}
assert(response !== undefined, 'The response is undefined, please file a bug report')

const { redaction = { type: 'replace' } } = options
const errorOptions = { redaction }
if (response.statusCode === 429) {
throw new ResponseError(response)
throw new ResponseError(response, errorOptions)
}

let scroll_id = response.body._scroll_id
Expand Down Expand Up @@ -237,7 +240,7 @@ export default class Helpers {
await sleep(wait)
}
if (response.statusCode === 429) {
throw new ResponseError(response)
throw new ResponseError(response, errorOptions)
}
}

Expand Down Expand Up @@ -289,6 +292,9 @@ export default class Helpers {
} = options
reqOptions.meta = true

const { redaction = { type: 'replace' } } = reqOptions
const errorOptions = { redaction }

let stopReading = false
let stopError: Error | null = null
let timeoutRef = null
Expand Down Expand Up @@ -502,7 +508,7 @@ export default class Helpers {
// @ts-expect-error
addDocumentsGetter(result)
if (response.status != null && response.status >= 400) {
callbacks[i](new ResponseError(result), result)
callbacks[i](new ResponseError(result, errorOptions), result)
} else {
callbacks[i](null, result)
}
Expand Down