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

Add support for reading request ID from X-Opaque-Id header #71019

Merged
merged 18 commits into from
Aug 19, 2020

Conversation

joshdover
Copy link
Contributor

@joshdover joshdover commented Jul 7, 2020

Summary

Fixes #62018

This PR essentially does 3 things:

  • Adds new requestId field to KibanaRequest that is sourced from the X-Opaque-Id header
    • The user can configure which IP addresses this header should be trusted from
  • Forwards the requestId to all requests to Elasticsearch that are made using the LegacyScopedClusterClient
  • Adds requestId to AuditEvents in the audit_trail plugin

TODO:

  • If Add new elasticsearch client #69905 is merged first, the changes to the Elasticsearch service need to be ported to the new client implementation
  • Add docs for new config settings

Checklist

Delete any items that are not applicable to this PR.

For maintainers

src/core/server/http/http_config.ts Outdated Show resolved Hide resolved
src/core/server/http/http_server.test.ts Outdated Show resolved Hide resolved
src/core/server/http/router/request.test.ts Outdated Show resolved Hide resolved
@@ -13,4 +13,5 @@ export interface AuditEvent {
scope?: string;
user?: string;
space?: string;
requestId?: string;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is probably not the right name since this identifier may not come from a request (eg. background task).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In ECS audit log this will be logged as trace.id but I'd say don't worry about updating the schema for now. I am happy to implement this as part of audit log PR as it's just going to create merge conflicts.

@pgayvallet
Copy link
Contributor

pgayvallet commented Jul 8, 2020

If #69905 is merged first, the changes to the Elasticsearch service need to be ported to the new client implementation

I added a task to add X-Opaque-Id support for the new client in #35508. It doesn't (necessarily) need to be done in this PR if #69905 is merged first though, or for the internal changes in core (as we are not using a scoped client) but it would be necessary before we expose the new client to the plugins.

src/core/server/http/router/request.ts Outdated Show resolved Hide resolved
src/core/server/http/router/request.ts Outdated Show resolved Hide resolved
src/core/server/http/router/request.ts Outdated Show resolved Hide resolved
@joshdover
Copy link
Contributor Author

This PR is still in draft and WIP. Just wanted to push up what I had at the end of my day to run CI. There's definitely some still some rough edges. I will get back to this tomorrow and address the feedback. Also big +1 on using Joi here, I had forgotten that it included very specific validations like IP.

Copy link
Member

@delvedor delvedor left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a heads up, if you need it, the client does have first-class support for the X-Opaque-Id header :)

@joshdover
Copy link
Contributor Author

Just a heads up, if you need it, the client does have first-class support for the X-Opaque-Id header :)

It could be useful to include the audittrail's current scope name as a prefix in the X-Opaque-Id. I will explore in a follow up.

@pgayvallet
Copy link
Contributor

Just a heads up, if you need it, the client does have first-class support for the X-Opaque-Id header :)

Not sure how to leverage that however, as we decided to get rid of our facade. We can't create a child client with preconfigured opaqueId, can we?

@delvedor
Copy link
Member

Not sure how to leverage that however, as we decided to get rid of our facade. We can't create a child client with preconfigured opaqueId, can we?

@pgayvallet correct, the global configuration is used as a prefix for the local configuration, and it should be handwritten each time. Anyhow, the client does not complain at all if you directly configure it in the headers, the only catch is that if you configure both headers and the opaqueId option, the option will take precedence (see here).


export class IpType extends Type<string> {
constructor(options: IpOptions = { versions: ['ipv4', 'ipv6'] }) {
const schema = internals.string().ip({ version: options.versions, cidr: 'forbidden' });
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cidr not needed right now, so I just set to forbidden. Can be exposed in the future if needed.

@joshdover
Copy link
Contributor Author

This will be on hold while I'm on PTO. It should not block any other Audit Logging work, it just needs to be completed for 7.10 FF

@joshdover joshdover added release_note:enhancement Team:Core Core services & architecture: plugins, logging, config, saved objects, http, ES client, i18n, etc v7.10.0 labels Aug 4, 2020
@elasticmachine
Copy link
Contributor

Pinging @elastic/kibana-platform (Team:Platform)

Copy link
Contributor

@mikecote mikecote left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alerting code LGTM

Copy link
Contributor

@thomheymann thomheymann left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great, can't wait to use this in audit log 🥳

@@ -13,4 +13,5 @@ export interface AuditEvent {
scope?: string;
user?: string;
space?: string;
requestId?: string;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In ECS audit log this will be logged as trace.id but I'd say don't worry about updating the schema for now. I am happy to implement this as part of audit log PR as it's just going to create merge conflicts.

src/core/server/http/http_server.test.ts Show resolved Hide resolved
@kobelb kobelb mentioned this pull request Aug 13, 2020
11 tasks
@joshdover
Copy link
Contributor Author

@elasticmachine merge upstream

@joshdover
Copy link
Contributor Author

@elasticmachine merge upstream

Copy link
Contributor

@pgayvallet pgayvallet left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Few nits and a question, but overall LGTM.

src/core/server/elasticsearch/client/cluster_client.ts Outdated Show resolved Hide resolved
src/core/server/elasticsearch/client/cluster_client.ts Outdated Show resolved Hide resolved
src/core/server/elasticsearch/legacy/cluster_client.ts Outdated Show resolved Hide resolved
src/core/server/http/http_server.ts Show resolved Hide resolved
Comment on lines +146 to +154
/**
* A identifier to identify this request.
*
* @remarks
* Depending on the user's configuration, this value may be sourced from the
* incoming request's `X-Opaque-Id` header which is not guaranteed to be unique
* per request.
*/
public readonly id: string;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment makes me wonder if we really have the correct approach by having a single property for the request 'id' and the 'x-opaque-id' that we forward to ES.

The risk I see here is that it would make our audit logging virtually 'useless' to debug a specific user scenario in a environment where the kibana instance is configured to allow x-opaque-id from requests and where the user would send a constant value for multiple requests, as all requests/log entries would have the same id in the logs.

This feels like an edge case though, so it's probably not worth changing everything just for that (or maybe this is even what we want?)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The risk I see here is that it would make our audit logging virtually 'useless' to debug a specific user scenario in a environment where the kibana instance is configured to allow x-opaque-id from requests and where the user would send a constant value for multiple requests, as all requests/log entries would have the same id in the logs.

I think we should treat this as an invalid configuration. I'm not sure how else we could properly support forwarding the header from the incoming request to ES without introducing this possibility. I think this case is kind of an edge case but it's hard to know for sure since it is so dependent on the infrastructure Kibana is running behind. Operators will have to explicitly turn on request ID forwarding from the incoming request, so I would hope that they also validate that the configuration is correct end-to-end with their proxy.

We could help the operator experience here by logging a warning message if we see the duplicate x-opaque-id headers being sent in the last N requests. @thomheymann do you have any thoughts? Should we add a warning like this for the MVP?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Merging as-is for now, but we can address this in a follow up PR if needed.

@kibanamachine
Copy link
Contributor

💚 Build Succeeded

Build metrics

✅ unchanged

History

To update your PR or re-run it, just comment with:
@elasticmachine merge upstream

@joshdover joshdover merged commit 51a80c6 into elastic:master Aug 19, 2020
@joshdover joshdover deleted the al/x-opaque-id branch August 19, 2020 21:41
joshdover added a commit to joshdover/kibana that referenced this pull request Aug 19, 2020
…1019)

Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
(request.raw.req.socket?.remoteAddress &&
options.ipAllowlist.includes(request.raw.req.socket.remoteAddress))
? request.headers['x-opaque-id'] ?? uuid.v4()
: uuid.v4();
Copy link
Contributor

@mshustov mshustov Aug 20, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we extract the id generation logic in a common place to use it here and in KibanaRequest contructor?

export function generateId() {
  return uuid.v4();
}

joshdover added a commit that referenced this pull request Aug 21, 2020
…75502)

Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>

Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
jportner added a commit that referenced this pull request Aug 22, 2020
These broke due to the recently merged code for reading request ID
from the X-Opaque-Id header in #71019.
@mshustov mshustov mentioned this pull request Jul 1, 2021
2 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
release_note:enhancement Team:Core Core services & architecture: plugins, logging, config, saved objects, http, ES client, i18n, etc v7.10.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Pipe X-Opaque-Id header to AuditTrail logs and Elasticsearch API calls