-
Notifications
You must be signed in to change notification settings - Fork 8.3k
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
[http] Add log for route path access #152621
[http] Add log for route path access #152621
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comments to reviewers.
@@ -526,6 +527,10 @@ export class HttpServer { | |||
xsrfRequired: route.options.xsrfRequired ?? !isSafeMethod(route.method), | |||
access: route.options.access ?? (route.path.startsWith('/internal') ? 'internal' : 'public'), | |||
}; | |||
// Log HTTP API target consumer. Warning: may log sensitive information on paths including secrets |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added a warning to remind ourselves (and API owners) where debug logs could cause issues.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IIUC, something like POST /api/my-secret/is/:mySecret
would log ... for path [/api/my-secret/is/:mySecret]
, and not the actual value in the secret when the user performs the request. Am I missing anything?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're not missing anything, the warning is to remind folks that anything in the path will log as is and to think very carefully about what they are fine with exposing is.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry... I'm a bit slow today... 😞
AFAIK, this comment is only read by Kibana Core devs. I don't get how this comment would warn a plugin developer to design their API so that they don't register an HTTP route like POST /api/my/plugin/${config.secret}/:id
. Bear in mind we are logging the registered path, not the final path that is requested with the variables replaced by the values (:id
in the example)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@afharo I believe what you are describing has already been introduced with
this.log.debug(`registering route handler for [${route.path}]`); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not a reason skip reviewing the decision, just saying it's not being added with this PR :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't want to block this PR 😇. These are nits rather than anything. Also, I noticed @TinaHeiligers removed the comment.
@afharo I believe what you are describing has already been introduced with
this.log.debug(`registering route handler for [${route.path}]`);
IIUC, I'm describing both lines. This PR adds a new entry in the logs that rephrases and adds info to the already existing entry. The new log entry is also logging the registered path, not the accessed path.
@@ -516,6 +516,7 @@ export class HttpServer { | |||
} | |||
|
|||
private configureRoute(route: RouterRoute) { | |||
const optionsLogger = this.logger.get('http', 'server', this.name, 'options'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I chose to add a new logger to make it easier to filter for these specific log lines
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we want to avoid repeating the http
and server
part, I think we can define the logger asthis.log.get(this.name, 'options);
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We'd lose the full context around where the log comes from if we remove http
and server
, which makes it very hard to analyze the debug-level logs.
Personally, I'd prefer being able to filter logs by a full logger name that keeps some sort of record of where it's coming from.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We'd lose the full context around where the log comes from if we remove
http
andserver
, which makes it very hard to analyze the debug-level logs.
Mind that I'm using this.log
(instead of this.logger
). AFAIK, this.log
is already scoped to http.server
, calling this.log.get
calls a nested logger. If we ever change the parent, it all changes together (as opposed to using the root logger this.logger
). I hope it makes sense.
Personally, I'd prefer being able to filter logs by a full logger name that keeps some sort of record of where it's coming from.
++ I agree.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
using this.log (instead of this.logger)
I did a quick test with this.log.get(this.name, 'options') with the same
http-console` appender. We end up duplicating the server name:
HTTP--[2023-03-06T10:05:25.632-07:00][DEBUG][http.server.Kibana.Kibana.options]---access [internal] for path [/internal/apm/service-map/service/{serviceName}]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh! cool! I didn't notice the existing entry is logged as http.server.Kibana
. In that case, this.log.get('options')
is enough :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done: commit fb86412
(#152621)
@elasticmachine merge upstream |
Pinging @elastic/kibana-core (Team:Core) |
@elasticmachine merge upstream |
@@ -526,6 +527,10 @@ export class HttpServer { | |||
xsrfRequired: route.options.xsrfRequired ?? !isSafeMethod(route.method), | |||
access: route.options.access ?? (route.path.startsWith('/internal') ? 'internal' : 'public'), | |||
}; | |||
// Log HTTP API target consumer. Warning: may log sensitive information on paths including secrets | |||
optionsLogger.debug( | |||
`kibanaRouteOptions [${kibanaRouteOptions.access}] for path [${route.path}]` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shall we log the method too? IMO "access" is a clearer prefix than "kibanaRouteOptions":
`kibanaRouteOptions [${kibanaRouteOptions.access}] for path [${route.path}]` | |
`access [${kibanaRouteOptions.access}] for path [${route.method} ${route.path}]` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Approved!
I've also removed the code comment's warning.
Please TAL.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Having this is awesome! Thanks for making it happen, Tina!
I added a few comments that I'd like to clarify before LGTM :)
@@ -516,6 +516,7 @@ export class HttpServer { | |||
} | |||
|
|||
private configureRoute(route: RouterRoute) { | |||
const optionsLogger = this.logger.get('http', 'server', this.name, 'options'); | |||
this.log.debug(`registering route handler for [${route.path}]`); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if extending this log entry with the values suggested in https://github.com/elastic/kibana/pull/152621/files/bf7a3c36cb4394b06a3b3fa09a0553c3f958bfed#r1126120651 would suffice. Both entries look too similar and are logged at the same time. If the only reason is so that we can use a new logger, I wonder if we can use it here (as long as it's nested, it should still log with the same config)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought about that but went a new logger route to be able to silence the extra info or to later remove the logger completely without losing the original log
@@ -516,6 +516,7 @@ export class HttpServer { | |||
} | |||
|
|||
private configureRoute(route: RouterRoute) { | |||
const optionsLogger = this.logger.get('http', 'server', this.name, 'options'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we want to avoid repeating the http
and server
part, I think we can define the logger asthis.log.get(this.name, 'options);
.
@@ -526,6 +527,10 @@ export class HttpServer { | |||
xsrfRequired: route.options.xsrfRequired ?? !isSafeMethod(route.method), | |||
access: route.options.access ?? (route.path.startsWith('/internal') ? 'internal' : 'public'), | |||
}; | |||
// Log HTTP API target consumer. Warning: may log sensitive information on paths including secrets |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IIUC, something like POST /api/my-secret/is/:mySecret
would log ... for path [/api/my-secret/is/:mySecret]
, and not the actual value in the secret when the user performs the request. Am I missing anything?
@@ -526,6 +527,8 @@ export class HttpServer { | |||
xsrfRequired: route.options.xsrfRequired ?? !isSafeMethod(route.method), | |||
access: route.options.access ?? (route.path.startsWith('/internal') ? 'internal' : 'public'), | |||
}; | |||
// Log HTTP API target consumer. | |||
optionsLogger.debug(`access [${kibanaRouteOptions.access}] for path [${route.path}]`); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mind that @jloleysens's comment also suggested adding the method
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Apologies, adding that now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done: commit fb86412
💚 Build Succeeded
Metrics [docs]Unknown metric groupsESLint disabled line counts
Total ESLint disabled count
History
To update your PR or re-run it, just comment with: |
Co-authored-by: Kibana Machine <[email protected]>
part of 151940
follow up to 152404
As part of implementing API versioning, we need an easy way to identify which HTTP APIs are intended for internal vs public consumption and added an
access
route option param laying the foundation for future work.The
access
setting is configurable and falls back to a naïve interpretation of the path string.Given that we now have some
internal/public
classification, we can use logs to generate a list of all HTTP APIs registered with core's HTTP server.This PR adds a debug logger (
http.server.kibana.options
) that will log the route path and theaccess
value on startup.Usage
Configure logging as follows:
On server startup, you should see the logs similar to: