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

Propagate the bearer token to the gRPC plugin server #1822

Merged

Conversation

radekg
Copy link
Contributor

@radekg radekg commented Sep 28, 2019

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 with spanstore.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:

  str, ok := spanstore.GetBearerToken(ctx)
  fmt.Println(fmt.Sprintf(" =====================> CLIENT: The context is: %v ::: %b", str, ok))

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 to true.

plugin/storage/grpc/proto/storage.proto Outdated Show resolved Hide resolved
readerClient storage_v1.SpanReaderPluginClient
writerClient storage_v1.SpanWriterPluginClient
depsReaderClient storage_v1.DependenciesReaderPluginClient
allowTokenFromContext bool
Copy link
Member

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.

Copy link
Contributor

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.

Copy link
Member

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)
Copy link
Member

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 {
Copy link
Member

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

@radekg
Copy link
Contributor Author

radekg commented Sep 30, 2019

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 {
Copy link
Contributor Author

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,
Copy link
Contributor Author

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?

Copy link
Member

Choose a reason for hiding this comment

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

+1

Copy link
Contributor Author

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?

Copy link
Member

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

Copy link
Member

@yurishkuro yurishkuro left a 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.

storage/spanstore/token_propagation.go Show resolved Hide resolved
// 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 {
Copy link
Member

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>
@radekg radekg force-pushed the grpc-storage-bearer-token-propagation branch from f650352 to 308d113 Compare October 1, 2019 16:33
@jpkrohling
Copy link
Contributor

Looks like there's one or more files that need formatting. The CI job failed with:

Go fmt, license check, or import ordering failures, run 'make fmt'

Signed-off-by: radekg <radek@gruchalski.com>
@radekg radekg force-pushed the grpc-storage-bearer-token-propagation branch from d10a84b to 2b8bb78 Compare October 2, 2019 10:04
@radekg
Copy link
Contributor Author

radekg commented Oct 2, 2019

All fixed and signed off.

@codecov
Copy link

codecov bot commented Oct 2, 2019

Codecov Report

❗ No coverage uploaded for pull request base (master@2957d89). Click here to learn what that means.
The diff coverage is 100%.

Impacted file tree graph

@@            Coverage Diff            @@
##             master    #1822   +/-   ##
=========================================
  Coverage          ?   98.22%           
=========================================
  Files             ?      195           
  Lines             ?     9611           
  Branches          ?        0           
=========================================
  Hits              ?     9440           
  Misses            ?      134           
  Partials          ?       37
Impacted Files Coverage Δ
storage/spanstore/token_propagation.go 71.42% <ø> (ø)
plugin/storage/grpc/shared/grpc_client.go 83.67% <100%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 2957d89...8fb5e57. Read the comment docs.

yurishkuro
yurishkuro previously approved these changes Oct 2, 2019
Copy link
Member

@yurishkuro yurishkuro left a 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?

@yurishkuro
Copy link
Member

This code is not covered:
image

Signed-off-by: radekg <radek@gruchalski.com>
Signed-off-by: radekg <radek@gruchalski.com>
@radekg
Copy link
Contributor Author

radekg commented Oct 3, 2019

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.

@pavolloffay pavolloffay merged commit 9a701bc into jaegertracing:master Oct 9, 2019
@pavolloffay
Copy link
Member

thanks @radekg

@radekg
Copy link
Contributor Author

radekg commented Oct 9, 2019

Thank you.

@radekg radekg deleted the grpc-storage-bearer-token-propagation branch October 9, 2019 17:47
@yurishkuro yurishkuro added this to the Release 1.15 milestone Nov 7, 2019
backjo pushed a commit to backjo/jaeger that referenced this pull request Dec 19, 2019
)

* 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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants