[http] Add log for route path access#152621
Conversation
TinaHeiligers
left a comment
There was a problem hiding this comment.
Comments to reviewers.
| 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.
I added a warning to remind ourselves (and API owners) where debug logs could cause issues.
There was a problem hiding this comment.
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.
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.
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.
@afharo I believe what you are describing has already been introduced with
There was a problem hiding this comment.
Not a reason skip reviewing the decision, just saying it's not being added with this PR :)
There was a problem hiding this comment.
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
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.
| } | ||
|
|
||
| private configureRoute(route: RouterRoute) { | ||
| const optionsLogger = this.logger.get('http', 'server', this.name, 'options'); |
There was a problem hiding this comment.
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.
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.
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.
We'd lose the full context around where the log comes from if we remove
httpandserver, 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.
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.
oh! cool! I didn't notice the existing entry is logged as http.server.Kibana. In that case, this.log.get('options') is enough :)
|
@elasticmachine merge upstream |
|
Pinging @elastic/kibana-core (Team:Core) |
|
@elasticmachine merge upstream |
| }; | ||
| // 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.
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.
Approved!
I've also removed the code comment's warning.
Please TAL.
afharo
left a comment
There was a problem hiding this comment.
Having this is awesome! Thanks for making it happen, Tina!
I added a few comments that I'd like to clarify before LGTM :)
|
|
||
| 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.
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.
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
| } | ||
|
|
||
| private configureRoute(route: RouterRoute) { | ||
| const optionsLogger = this.logger.get('http', 'server', this.name, 'options'); |
There was a problem hiding this comment.
If we want to avoid repeating the http and server part, I think we can define the logger asthis.log.get(this.name, 'options);.
| 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.
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?
| 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.
mind that @jloleysens's comment also suggested adding the method
There was a problem hiding this comment.
Apologies, adding that now.
💚 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 <42973632+kibanamachine@users.noreply.github.com>
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
accessroute option param laying the foundation for future work.The
accesssetting is configurable and falls back to a naïve interpretation of the path string.Given that we now have some
internal/publicclassification, 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 theaccessvalue on startup.Usage
Configure logging as follows:
On server startup, you should see the logs similar to: