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

Establish the auth context for authenticators to add data to #3552

Conversation

jpkrohling
Copy link
Member

This commit modifies the Authenticate method from configauth.ServerAuthenticator to return a context. At this point, there's no further change in the behavior, as a concrete solution is going to be added as part of #2733/#2734.

This should be the only breaking change required for the auth propagation to work, making the collector ready for GA from the auth perspective.

Signed-off-by: Juraci Paixão Kröhling juraci@kroehling.de

Signed-off-by: Juraci Paixão Kröhling <juraci@kroehling.de>
@jpkrohling jpkrohling requested review from a team and tigrannajaryan July 2, 2021 10:36
@jpkrohling
Copy link
Member Author

cc @alolita

@jpkrohling
Copy link
Member Author

I tried finding @tigrannajaryan's PoC but couldn't. I would like to review it before getting this merged, to make sure we don't need other changes before GA.

@tigrannajaryan
Copy link
Member

I tried finding @tigrannajaryan's PoC but couldn't. I would like to review it before getting this merged, to make sure we don't need other changes before GA.

Here is the link to the PoC for reference:

here is a VERY incomplete and draft changeset that shows what I was thinking about passthrough auth context: https://github.com/open-telemetry/opentelemetry-collector/compare/main...tigrannajaryan:feature/tigran/auth-passthrough?expand=1
I think it also uncovered that our ServerAuthenticactor.Authenticate() method needs to return a context. We do not have an HTTP Server authentication implementation, so I was not sure how exactly to do it.

@jpkrohling
Copy link
Member Author

I reviewed the branch and the only change that would be breaking is the change to the Authenticate function to return a context, which is being covered by this PR here.

I think we are good to go then!

@@ -40,7 +40,7 @@ type ServerAuthenticator interface {
// When the authentication fails, an error must be returned and the caller must not retry. This function is typically called from interceptors,
// on behalf of receivers, but receivers can still call this directly if the usage of interceptors isn't suitable.
// The deadline and cancellation given to this function must be respected, but note that authentication data has to be part of the map, not context.
Authenticate(ctx context.Context, headers map[string][]string) error
Authenticate(ctx context.Context, headers map[string][]string) (context.Context, error)
Copy link
Member

Choose a reason for hiding this comment

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

Can we add an explanation in the comments about what the returned context is expected to be?

Copy link
Member Author

Choose a reason for hiding this comment

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

I left that part out so that we can define it when we have a first implementation making use of it, but I added the best information we have so far.

Should I define the context keys as part of this PR? It would be basically this: https://github.com/open-telemetry/opentelemetry-collector/pull/3239/files#diff-1c8371e19129e2092ab7abfce04e6558218579f1be29d90adb958d230475584f

Copy link
Member Author

Choose a reason for hiding this comment

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

In any case, I updated the PR to include a few words about the resulting context.

Copy link
Member Author

@jpkrohling jpkrohling Jul 8, 2021

Choose a reason for hiding this comment

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

Sorry about the noise, but I thought it would be better to include the auth keys as part of the API for v1, so, I included it in this PR.

Signed-off-by: Juraci Paixão Kröhling <juraci@kroehling.de>
Signed-off-by: Juraci Paixão Kröhling <juraci@kroehling.de>
@jpkrohling
Copy link
Member Author

@tigrannajaryan would you mind taking a look at the latest commits?

@jpkrohling
Copy link
Member Author

@bogdandrutu, do you have some time to re-review this one?

@jpkrohling jpkrohling requested a review from bogdandrutu July 9, 2021 19:21
Copy link
Member

@bogdandrutu bogdandrutu left a comment

Choose a reason for hiding this comment

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

I would strongly encourage to split this in separate PR (the 3rd commit), so I can more confident merge this PR and have more time thinking about the new API especially because it is a public API

Comment on lines +25 to +27
type rawType struct{}
type subjectType struct{}
type groupsType struct{}
Copy link
Member

Choose a reason for hiding this comment

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

Is it possible to have all three of them in the same time? Can we actually have one key with an enum type?

Copy link
Member

Choose a reason for hiding this comment

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

Maybe have a "AuthContext" struct which embeds different auth types?

Copy link
Member

Choose a reason for hiding this comment

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

Is there a library that provides this?

Copy link
Member Author

@jpkrohling jpkrohling Jul 12, 2021

Choose a reason for hiding this comment

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

Is it possible to have all three of them in the same time? Can we actually have one key with an enum type?

Yes, and quite common actually.

Maybe have a "AuthContext" struct which embeds different auth types?

Those are not auth types. The raw auth data might be a JWT, which contains the principal and group memberships. The authenticator (OIDC, for instance) will then place all the three components in the context. Another authenticator might get the subject and groups from the auth server.

I can split this if we need more time, but I think the third commit brings only a minimal API, generic enough to be extended with custom types in the future. The idea about AuthContext has been brought by @tigrannajaryan as well, though:

6b6e713#diff-208f8af800c6aa88673523930b718a5d1a5b3f2a2d2f6edbdcf97171ce3d15ca

Is there a library that provides this?

I'm not aware of any. This is really only about adding auth to a context.Context, but I'm open to using a library if it brings value.

@tigrannajaryan tigrannajaryan self-requested a review July 13, 2021 18:39
Comment on lines +19 to +26
var (
rawKey = rawType{}
subjectKey = subjectType{}
groupsKey = groupsType{}
)

type rawType struct{}
type subjectType struct{}
Copy link
Member

Choose a reason for hiding this comment

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

Why do we need this in a generic auth/context.go at all? These appear to be specific context data for example by oidc auth extension. Why not declare there on oidc implementation?
I think we should aim for every auth extension to declare its own context data.

Copy link
Member Author

Choose a reason for hiding this comment

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

These are not specific to the OIDC auth extension. Those three pieces should be common to most authenticators, as they are common parts of any authorization system. For example, we might have a basic auth authenticator, a la Apache httpd: in such case, we would have a .htpasswd that would serve as the user data source (subject), and an optional .htgroups, linking groups with users like Unix' /etc/group. The raw field would be the base64 encoded username:password received by the HTTP server from the client.

I think we should aim for every auth extension to declare its own context data.

I think every extension (not only auth) should be allowed to enhance the context data as they wish so that other components can make use of that information, but we should have a minimal set of options that are common to all authenticators, and this auth/context represents that in my opinion.

Copy link
Member

Choose a reason for hiding this comment

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

Sorry, I still do not understand why this needs to be in the auth package and not in the specific extension's package which needs this. We are not expecting that we can mix auth extensions in any way, right? So why not move these declarations to the extension which plans to inject these values in the context?
I may be missing something but I think different authenticator extensions will need different values. Some authenticators will only need raw auth token others may need a subject or whatever it is called.
I don't understand what do we gain by making these concepts part of the public API of core and not just delegate it to individual auth extensions.

Copy link
Member Author

Choose a reason for hiding this comment

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

We are not expecting that we can mix auth extensions in any way, right?

We certainly expect auth extensions to provide data that will be consumed by other components in the pipeline. For instance, the routing processor can make decisions based on the principal or group membership (tenant "acme" should go to this Jaeger, tenant "ecorp" should go to that Zipkin, ...).

All auth extensions are expected to have at least the notion of principal (like a username, or a service account name, or ...) Raw can certainly be removed from the generic package, though. I would also keep the group information, as it's also a common aspect of auth no matter the backend used.

I don't understand what do we gain by making these concepts part of the public API of core and not just delegate it to individual auth extensions.

Other components, like the routing processor I mentioned earlier, might provide tighter integration with the auth features, without requiring specific authenticators to exist.

Copy link
Member

Choose a reason for hiding this comment

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

@jpkrohling can you please show how a routing processor could use the auth data? A sample code somewhere would be great to see and would help review this PR.

Copy link
Member Author

@jpkrohling jpkrohling Jul 30, 2021

Choose a reason for hiding this comment

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

It cannot right now because of this missing piece, but this is how a configuration would look like for the existing routingprocessor:

receivers:
  nop:

processors:
  routing:
    default_exporters:
    - otlp
    from_auth: membership
    table:
    - value: acme
      exporters: 
      - jaeger/acme
      - otlp/acme
    - value: globex
      exporters:
      - otlp/globex

exporters:
  otlp:
  otlp/acme:
  otlp/globex:
  jaeger/acme:
    endpoint: localhost:14250

service:
  pipelines:
    traces:
      receivers:
      - nop
      processors:
      - routing
      exporters:
      - jaeger/acme
      - otlp/acme
      - otlp/globex

In this example, the authentication for a hypothetical user "service-a", belonging to the tenant "acme" would cause the authenticator to place "service-a" as the subject/principal and "acme" in the group membership.

The routingprocessor would probably need to group the data by auth/membership, but minimal changes would be required to the current code, probably isolated to this function here: https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/36a7da6a4c29ddf81d118ec159e0a7a1682c6f21/processor/routingprocessor/routing.go#L133-L134 . Instead of extracting the route destination from the context, it would extract from the pdata.

Copy link
Member Author

Choose a reason for hiding this comment

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

Looking at my notes, I think we did discuss something else though:

  • the authenticators would place auth data into the context
  • something at the junction point between receivers and processors would place this into pdata
  • processors/exporters should rely on the data from pdata instead of the context

Other than that, the general idea remains.

@jpkrohling jpkrohling changed the title Prepare auth API to return a context Establish the auth context for authenticators to add data to Jul 14, 2021
@jpkrohling
Copy link
Member Author

Based on today's SIG Collector call, I'm renaming this PR and splitting the first two commits on its own PR (#3618). Things we discussed about this one:

  1. Perhaps we want an interface that the authenticators implement, so that downstream processors/exporters can ask the authenticators about things like subjects/groups?
  2. Or have a generic way to add entries to the context? Like the client package would need.
  3. Or just settle on the names we want in the third commit here.

One thing I did forget during the call is that this context is relevant only for the junction points: they would take data out of the context and place in the new pdata.Context object, which will be part of the pdata.Resource* structs. So, this auth here would need to be part of an internal API only.

@bogdandrutu
Copy link
Member

Please rebase :)

@jpkrohling jpkrohling mentioned this pull request Jul 15, 2021
3 tasks
@jpkrohling jpkrohling added the release:required-for-ga Must be resolved before GA release label Jul 15, 2021
@github-actions
Copy link
Contributor

This PR was marked stale due to lack of activity. It will be closed in 7 days.

@tigrannajaryan
Copy link
Member

@jpkrohling now that #3618 is merged do you plan to rebase this?

@jpkrohling
Copy link
Member Author

Yes, and your timing is perfect. I just cleared some things up from my queue and I'm working on this right now.

@jpkrohling
Copy link
Member Author

Closing this in favor of #3745.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
release:required-for-ga Must be resolved before GA release
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants