-
Notifications
You must be signed in to change notification settings - Fork 2.5k
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
Propagate the bearer token to the gRPC plugin server #1822
Propagate the bearer token to the gRPC plugin server #1822
Conversation
a088b29
to
9ce0549
Compare
readerClient storage_v1.SpanReaderPluginClient | ||
writerClient storage_v1.SpanWriterPluginClient | ||
depsReaderClient storage_v1.DependenciesReaderPluginClient | ||
allowTokenFromContext bool |
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.
is the config option actually required? If the query-service is configured to pass the bearer token, it would include it in the context, and this code just needs to respect that.
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 do want a way to tell our components that the token shouldn't be propagated.
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.
There is already configuration to that effect in the query service, which controls token handoff from query to storage. I don't think yet another flag for storage-storagePlugin is needed.
@@ -53,7 +64,8 @@ func (s *grpcServer) WriteSpan(ctx context.Context, r *storage_v1.WriteSpanReque | |||
|
|||
// GetTrace takes a traceID and streams a Trace associated with that traceID | |||
func (s *grpcServer) GetTrace(r *storage_v1.GetTraceRequest, stream storage_v1.SpanReaderPlugin_GetTraceServer) error { | |||
trace, err := s.Impl.SpanReader().GetTrace(stream.Context(), r.TraceID) | |||
opCtx := s.getMaybeBearerTokenContext(stream.Context(), r.BearerToken) |
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.
this may not be needed per my earlier comments, but if needed then it would be better to rename to a more general method of "adapting" the context from request, so that we could, in the future, support different types of middleware.
var PluginMap = map[string]plugin.Plugin{ | ||
StoragePluginIdentifier: &StorageGRPCPlugin{}, | ||
// GetPluginMap returns a plugin map. | ||
func GetPluginMap(allowTokenFromContext bool) map[string]plugin.Plugin { |
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 can get away without explicit configuration, please undo this
Hi @yurishkuro, thank you for a quick review. I have updated the code according to your request / suggestions. Indeed, this is a way cleaner solution than the original one. |
@@ -34,6 +35,18 @@ type grpcClient struct { | |||
depsReaderClient storage_v1.DependenciesReaderPluginClient | |||
} | |||
|
|||
// updateContextWithBearerToken updates the outgoing context with a bearer token extracted from the source | |||
func (c *grpcClient) updateContextWithBearerToken(outgoing context.Context, source context.Context) context.Context { |
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 am not sure what would be a cleaner way to handle this. The problem here is that FindTraces
and FindTraceIDs
uses context.Background()
so this function has to operate on two contexts.
bearerToken, hasToken := spanstore.GetBearerToken(source) | ||
if hasToken { | ||
requestMetadata := metadata.New(map[string]string{ | ||
"bearerToken": bearerToken, |
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.
A suggestion here. There is a place in the code where the property identifying this setting is already defined. It is: https://github.com/jaegertracing/jaeger/blob/master/storage/spanstore/token_propagation.go#L21.
Maybe we could do something like:
const BearerTokenKey = "bearer.token"
const bearerToken = contextKey("bearer.token")
and use the spanstore.BearerTokenKey
here and then in the gRPC plugin server?
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.
+1
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.
Will do. Final question: should I squash before it is merged?
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.
No need, we squash on merge
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.
It looks like one of the earlier commits did not have a DCO sign-off, you may need to squash them to fix that.
// upgradeContextWithBearerToken turns the context into a gRPC outgoing context with bearer token | ||
// in the request metadata, if the original context has bearer token attached. | ||
// Otherwise returns original context. | ||
func (c *grpcClient) upgradeContextWithBearerToken(ctx context.Context) context.Context { |
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.
this function does not need a receiver
Signed-off-by: radekg <radek@gruchalski.com>
Signed-off-by: radekg <radek@gruchalski.com>
…uctions Signed-off-by: radekg <radek@gruchalski.com>
…plugin, FindTraceIDs client context. Signed-off-by: radekg <radek@gruchalski.com>
…unction Signed-off-by: radekg <radek@gruchalski.com>
Signed-off-by: radekg <radek@gruchalski.com>
Signed-off-by: radekg <radek@gruchalski.com>
f650352
to
308d113
Compare
Looks like there's one or more files that need formatting. The CI job failed with:
|
Signed-off-by: radekg <radek@gruchalski.com>
d10a84b
to
2b8bb78
Compare
All fixed and signed off. |
Codecov Report
@@ Coverage Diff @@
## master #1822 +/- ##
=========================================
Coverage ? 98.22%
=========================================
Files ? 195
Lines ? 9611
Branches ? 0
=========================================
Hits ? 9440
Misses ? 134
Partials ? 37
Continue to review full report at Codecov.
|
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.
@radekg could you please add a test somewhere verifying that the token is indeed accessible in the plugin implementation?
Signed-off-by: radekg <radek@gruchalski.com>
Signed-off-by: radekg <radek@gruchalski.com>
Hi @yurishkuro, I'm not sure if the failing tests are related to my changes. I can see cql related fatal errors in the Travis job. |
thanks @radekg |
Thank you. |
) * Add bearer token forward to the GRPC storage plugin Signed-off-by: radekg <radek@gruchalski.com> * Apply the changes suggested by @yurishkuro in the review Signed-off-by: radekg <radek@gruchalski.com> * Update gRPC storage plugin readme with bearer token propagation instructions Signed-off-by: radekg <radek@gruchalski.com> * Expose a literal from token propagation context, use literal in gRPC plugin, FindTraceIDs client context. Signed-off-by: radekg <radek@gruchalski.com> * gRPC plugin client, uses original context everywhere, adapt upgrade function Signed-off-by: radekg <radek@gruchalski.com> * Reuse the bearer token key string in the context key Signed-off-by: radekg <radek@gruchalski.com> * upgradeContextWithBearerToken does not need a receiver Signed-off-by: radekg <radek@gruchalski.com> * Apply make fmt Signed-off-by: radekg <radek@gruchalski.com> * Add test coverage for context upgrades Signed-off-by: radekg <radek@gruchalski.com> * D'oh, fmt for tests... Signed-off-by: radekg <radek@gruchalski.com> Signed-off-by: Jonah Back <jonah@jonahback.com>
This PR attempts to resolve the problem described in #1821.
Problem summary
Query UI has an option to forward Bearer token to the storage back end using
--query.bearer-token-propagation=true
flag. However, when using the gRPC storage plugin, the context created withspanstore.ContextWithBearerToken(ctx, token)
in https://github.com/jaegertracing/jaeger/blob/master/cmd/query/app/token_propagation_handler.go#L48 is not passed to the gRPC plugin.Currently, the last place in the storage where the context with the
bearer.token
can be reached, is the gRPC client: https://github.com/jaegertracing/jaeger/blob/master/plugin/storage/grpc/shared/grpc_client.go.This can be tested by adding these lines of code:
to any of the following methods:
func (c *grpcClient) GetTrace(ctx context.Context, traceID model.TraceID) (*model.Trace, error)
func (c *grpcClient) GetServices(ctx context.Context) ([]string, error)
func (c *grpcClient) GetOperations(ctx context.Context, service string) ([]string, error)
func (c *grpcClient) FindTraces(ctx context.Context, query *spanstore.TraceQueryParameters) ([]*model.Trace, error)
func (c *grpcClient) FindTraceIDs(ctx context.Context, query *spanstore.TraceQueryParameters) ([]model.TraceID, error)
However, on the server part of the plugin, the context is a new instance because the plugin is running as a separate process.
Solution summary
This pull request adds support for bearer token forwarding to the gRPC
spanstore.Reader
methods of the gRPC storage. Similarly to the solution from the ES storage provider, only forward the bearer token when the--query.bearer-token-propagation
flag has been set totrue
.