ROX-13596: Determine user-agent in gRPC-gateway and HTTP#3924
ROX-13596: Determine user-agent in gRPC-gateway and HTTP#3924parametalol merged 2 commits intomasterfrom
Conversation
|
|
||
| if throughGrpcGateway { | ||
| // By default, all permanent HTTP headers are added grpcgateway- prefix: | ||
| // https://github.com/grpc-ecosystem/grpc-gateway/blob/master/runtime/mux.go#L106-L114 | ||
| // User-Agent header is occupied with internal grpc-go value: | ||
| // https://github.com/grpc/grpc-go/blob/0238b6e1cec37b55820b461d3d30652c54efe2c4/clientconn.go#L211-L215 | ||
| userAgentKey := fmt.Sprintf("%suser-agent", runtime.MetadataPrefix) | ||
| userAgent = strings.Join(ri.Metadata.Get(userAgentKey), ", ") | ||
| } | ||
| // Fallback to HTTP | ||
| if !throughGrpcGateway || userAgent == "" { | ||
| userAgent = strings.Join(ri.Metadata.Get("User-Agent"), ", ") | ||
| } |
There was a problem hiding this comment.
May we just try to find the grpcgatewayuser-agent key and use it if found or fallback to User-Agent otherwise?
There was a problem hiding this comment.
I think the code here has clearer intent: if grpc-gateway is used, use grpc-gateway header; if it does not work or we are not on gRPC protocol, use HTTP header. It would be unexpected to see grpcgateway-user-agent in the HTTP interceptor, and I would think we should ignore such header in such context.
There was a problem hiding this comment.
I think there is too much code for this intent: you even had to add more parameters to two functions and compute the normal User-Agent twice.
Instead, you could move this grpc related check (i.e. try to read the grpcgatewayuser-agent header, and you don't need any bool parameter) to the beginning of the function, and put the existing User-Agent retrieval under else.
| } | ||
| // Fallback to HTTP | ||
| if !throughGrpcGateway || userAgent == "" { | ||
| userAgent = strings.Join(ri.Metadata.Get("User-Agent"), ", ") |
There was a problem hiding this comment.
FWIW, with such branching you don't need userAgent declaration at L43. If you keep the current structure, pull L43 right before branching and make it var userAgent string. However, I'm in favor of Michaël's suggestion below.
|
|
||
| if throughGrpcGateway { | ||
| // By default, all permanent HTTP headers are added grpcgateway- prefix: | ||
| // https://github.com/grpc-ecosystem/grpc-gateway/blob/master/runtime/mux.go#L106-L114 | ||
| // User-Agent header is occupied with internal grpc-go value: | ||
| // https://github.com/grpc/grpc-go/blob/0238b6e1cec37b55820b461d3d30652c54efe2c4/clientconn.go#L211-L215 | ||
| userAgentKey := fmt.Sprintf("%suser-agent", runtime.MetadataPrefix) | ||
| userAgent = strings.Join(ri.Metadata.Get(userAgentKey), ", ") | ||
| } | ||
| // Fallback to HTTP | ||
| if !throughGrpcGateway || userAgent == "" { | ||
| userAgent = strings.Join(ri.Metadata.Get("User-Agent"), ", ") | ||
| } |
| "google.golang.org/grpc" | ||
| ) | ||
|
|
||
| const grpcGatewayUserAgentHeader = runtime.MetadataPrefix + "user-agent" |
There was a problem hiding this comment.
| const grpcGatewayUserAgentHeader = runtime.MetadataPrefix + "user-agent" | |
| const grpcGatewayUserAgentHeader = runtime.MetadataPrefix + "User-Agent" |
I understand that metadata.MD converts keys to lowercase but this is not obvious here, is not common knowledge, and who knows when it changes. Canonical form is "User-Agent".
| } | ||
|
|
||
| // By default, all permanent HTTP headers in grpc-gateway are added grpcgateway- prefix: | ||
| // https://github.com/grpc-ecosystem/grpc-gateway/blob/master/runtime/mux.go#L106-L114 |
There was a problem hiding this comment.
| // https://github.com/grpc-ecosystem/grpc-gateway/blob/master/runtime/mux.go#L106-L114 | |
| // https://github.com/grpc-ecosystem/grpc-gateway/blob/8952e38d5addd28308e29c272c696a578aa8ace8/runtime/mux.go#L106-L114 |
Always press y in GitHub to get a link with pinned line references.
| // By default, all permanent HTTP headers in grpc-gateway are added grpcgateway- prefix: | ||
| // https://github.com/grpc-ecosystem/grpc-gateway/blob/master/runtime/mux.go#L106-L114 | ||
| // User-Agent header is occupied with internal grpc-go value: | ||
| // https://github.com/grpc/grpc-go/blob/0238b6e1cec37b55820b461d3d30652c54efe2c4/clientconn.go#L211-L215 |
There was a problem hiding this comment.
It's actually not clear to me what this code reference proves. cc.dopts.copts.UserAgent += " " + grpcUA hints that User-Agent value is not overwritten but appended to, so it will be something like ACS roxctl user agent blah grpc-go/1.50.1. Which sort of contradicts what's claimed in ROX-13596.
Could you please split the "Testing Performed" section into before / after?
There was a problem hiding this comment.
Regarding cc.dopts.copts.UserAgent: this shows where the user agent's value grpc-go/1.51.0 is initially taken from.
Answering the question of why there's no other user-agent value:
- To transform from HTTP to GRPC request, we connect to our gRPC server as a client from within the central
Lines 352 to 353 in 0529062
Lines 311 to 317 in 0529062
- Connection for this client is created once during central initialization, thus we cannot override it on every request.
- Value for
user-agentdial option is not specified in our code, thus we use the default
Lines 226 to 233 in 0529062
There was a problem hiding this comment.
Ah, I see, didn't know that we persist the connection — thanks. This makes sense.
It does not make sense to capture your reply as a code comment because it builds on non-local knowledge which might change any time and render the comment misleading, but it does make sense to explain that in the PR description.
One last thing: do you want to follow up and augment grpc server init code with User-Agent for HTTP muxer?
There was a problem hiding this comment.
One last thing: do you want to follow up and augment grpc server init code with User-Agent for HTTP muxer?
If I understand correctly what you suggest, that would add some additional user-agent value to all requests going through the muxer. Essentially, what @0x656b694d did here:
https://github.com/stackrox/stackrox/pull/3672/files#diff-af62cb3a3a7c777bd1b8feed18657c3ecae951d2dbdea55527f08c8c67967c71R233
I think it works as a fallback option. It's better than displaying grpc-go/1.51.0, so why not?
I had a small concern regarding introducing more variety to potential user-agent values in Segment, but Segment supports contains filter, so that shouldn't be a problem.
There was a problem hiding this comment.
Yeah, essentially what's done in #3672, so my comment should be irrelevant. Why do we still see "User-Agent": "grpc-go/1.51.0" in the Before section then?
There was a problem hiding this comment.
"grpc-go/1.51.0" is always appended by the gogrpc library to the User-Agent, should we set or not anything with WithUserAgent.
rukletsov
left a comment
There was a problem hiding this comment.
Thanks, Ivan. Please update the PR description per my recent comment and 🚢 it.
0529062 to
00170b0
Compare
00170b0 to
63c3298
Compare
b88ffc0 to
8e09a92
Compare
5cfdcb9 to
101fdee
Compare
bf1637b to
3b370cf
Compare
Co-authored-by: Ivan Degtiarenko <78353299+ivan-degtiarenko@users.noreply.github.com>
728c7e3 to
800e342
Compare
|
Images are ready for the commit at 5bb6250. To use with deploy scripts, first |
Description
This is fix to telemetry interceptors to correctly determine
User-Agent.The reason why the request
user-agentvalue was ignored in gRPC case is that:stackrox/pkg/grpc/server.go
Lines 352 to 353 in 0529062
stackrox/pkg/grpc/server.go
Lines 311 to 317 in 0529062
user-agentdial option is not specified in our code, thus we use the defaultstackrox/pkg/grpc/server.go
Lines 226 to 233 in 0529062
Checklist
If any of these don't apply, please comment below.
Testing Performed
User-AgentBefore in telemetry(UI)
After in telemetry(UI)
roxctlis tracked withroxctl/<versionuser agent/v1/pingis tracked withkube-probeuser agent