-
Notifications
You must be signed in to change notification settings - Fork 1.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
Add auth data to pdata resource #3745
Conversation
config/configauth/pdatacontext.go
Outdated
type AuthContext struct { | ||
sub string | ||
raw string | ||
group []string | ||
} |
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 still don't like that this imposes a rigid structure on what is an authentication information.
In the PoC I gave a an example of a passthrough
authenticator that has neither sub
, nor raw
nor group
, but is a header value. Sure, we could shoehorn it into raw
, but then virtually anything can be argued to be represented in some raw string form.
IMO, AuthContext should be an interface here and each concrete auth extension will have a specific way to implement it. OIDC auth will have (sub,raw,group) tuple, other auth extensions will have something else instead.
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 need a contract with basic fields so that processors can use basic auth primitives, like "username" or "group membership". Otherwise, the contract between components will be on keys within the map, which is way weaker. Usernames (or principal, subject) and group membership (or roles) are the basic constructs in auth/z systems.
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.
Otherwise, the contract between components will be on keys within the map, which is way weaker.
@jpkrohling actually a map may be a good approach. The interaction between the processors and PDataContext is unlikely to be hard-coded to benefit from strong typing. It is most likely going to be config-driven anyway, with the user specifying in the configuration the name of the PDataContext's attribute to use (e.g. in the example of routing processor you posted, the config refers to "membership" attribute directly).
I think we can define AuthContext interface like this:
type AuthContext interface {
Equal(other interface{}) bool
GetAttribute(attrName string) interface{}
}
oidcauthextension.AuthContext
then can define GetAttribute
such that it return the right values for the 3 supported special attribute names ("principal", "membership", whatever is the third one).
This will allow processors to query for AuthContext
attributes.
What do you think?
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.
Sounds reasonable. Let me give it a try.
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.
How does it look now? It does require more work from users to tie the components together, but I don't think it's too bad. We just need to make sure every auth component documents what it produces.
Unfortunately I don't see any other way except patching generated *.pb.go files after Protobuf compiler generates them. Ideally the compiler would have a capability like this (i.e. declare a field that is not serializable), but there is no such thing. |
func (ms ResourceSpans) PDataContext() PDataContext { | ||
return newPDataContext(&(*ms.orig).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 needs to be auto-generated.
// This is expected to be ignored by marshaling/unmarshaling. Double-check that this is true. | ||
Context go_opentelemetry_io_collector_model_internal_data.PDataContext | ||
} |
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 needs to be auto-generated
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.
That's the part that we don't know how to do nicely. Should we use sed to patch this file as part of make genproto
target, after Protobuf compiler does its part of the job? Do we have any other options?
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.
@bogdandrutu, I'll need your help here.
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.
ping @bogdandrutu
package data | ||
|
||
type PDataContext struct { | ||
List []PDataContextKeyValue |
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.
Can we use the already defined "AnyValue"/Attributes?
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.
Not for the Key
, it needs to be an arbitrary interface{}
(and not just a string), like it is done for context.Context
, but for the Value
it is an interesting idea, since it may make some code that needs to deal with both telemetry attributes and PDataContext easier to write. It is worth exploring.
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.
Did you mean pdata.AttributeValue? If so, that would cause an import cycle that is not allowed.
74998d8
to
87cde06
Compare
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.
Thanks @jpkrohling !
I think I like it, with some minor comments/questions.
This PR was marked stale due to lack of activity. It will be closed in 7 days. |
This PR was marked stale due to lack of activity. It will be closed in 7 days. |
This is not stale. Some things are in my queue and I need input from @bogdandrutu, which is likely busy with the moving of the components. |
@jpkrohling how do you plan on making the auth data available to where we can add it to traces/logs/metrics? We're planning on ingesting multiple tenants from one API endpoint and passing the data off to kafka and taking the auth reference and associating it back to the tenant so we can segregate their data. Also not sure if relevant or not, but we took inspiration from your medium article and decided to use ory hydra instead, seems to work thus far :) |
The current idea is to create a new context within the pdata which will contain a map with the auth data. I haven't had much time to work in this, but this is high priority in my queue.
Thanks for letting me know! |
@jpkrohling also if it helps provide context, our plans are to use otel collector that ships to kafka that has the grafana-agent read from kafka and post the spans to loki, cortex(prometheus), and tempo. We're hoping we can abstract the clientId and use that as the x-scope-orgId to support multitenancy (for loki/cortext) and still share spans in tempo so that each team can see how their system interacts with others in the ecosystem. |
This PR was marked stale due to lack of activity. It will be closed in 7 days. |
This PR was marked stale due to lack of activity. It will be closed in 7 days. |
This PR was marked stale due to lack of activity. It will be closed in 7 days. |
This PR was marked stale due to lack of activity. It will be closed in 7 days. |
This PR was marked stale due to lack of activity. It will be closed in 7 days. |
@jpkrohling do you plan to continue working on this? |
Yes, I'm waiting on @bogdandrutu on this one. Whenever he's got some time, I would like to get some pair programming session with him to sort out the questions and problems behind this. |
This PR was marked stale due to lack of activity. It will be closed in 7 days. |
Is there any progress on this PR? |
@CoderPoet, I'll be doing a pair programming session with @bogdandrutu this Wed to unblock this. |
Signed-off-by: Juraci Paixão Kröhling <juraci@kroehling.de>
Signed-off-by: Juraci Paixão Kröhling <juraci@kroehling.de>
Signed-off-by: Juraci Paixão Kröhling <juraci@kroehling.de>
Signed-off-by: Juraci Paixão Kröhling <juraci@kroehling.de>
87cde06
to
126164a
Compare
Codecov Report
@@ Coverage Diff @@
## main #3745 +/- ##
==========================================
- Coverage 88.07% 87.80% -0.27%
==========================================
Files 173 176 +3
Lines 10188 10235 +47
==========================================
+ Hits 8973 8987 +14
- Misses 975 1006 +31
- Partials 240 242 +2
Continue to review full report at Codecov.
|
PR updated, and tested with a branch with the required changes to the OIDC authenticator (as an example, as other server authenticators would need similar changes) with the following config file: extensions:
oidc:
issuer_url: http://localhost:8080/auth/realms/opentelemetry
audience: account
oauth2client:
client_id: agent
client_secret: 0b5fab57-9b0e-449f-9da7-9ff7e1735df6
token_url: http://localhost:8080/auth/realms/opentelemetry/protocol/openid-connect/token
receivers:
otlp:
protocols:
grpc:
otlp/withauth:
protocols:
endpoint: localhost:5317
grpc:
tls:
cert_file: /tmp/certs/cert.pem
key_file: /tmp/certs/cert-key.pem
auth:
authenticator: oidc
processors:
exporters:
logging:
logLevel: debug
otlp:
endpoint: localhost:5317
ca_file: /tmp/certs/ca.pem
auth:
authenticator: oauth2client
service:
extensions: [oidc, oauth2client]
pipelines:
traces/agent:
receivers: [otlp]
processors: []
exporters: [otlp/withauth]
traces/collector:
receivers: [otlp/withauth]
processors: []
exporters: [logging] The OAuth server referenced in the OIDC extension is similar to the one used in the blog post. The logging exporter shows this:
|
@@ -182,6 +183,7 @@ func attachReceiverToPipelines( | |||
switch dataType { | |||
case config.TracesDataType: | |||
junction := buildFanoutTraceConsumer(builtPipelines) | |||
junction = authcontext.NewTracesInjector(junction) | |||
createdReceiver, err = factory.CreateTracesReceiver(ctx, set, cfg, junction) | |||
|
|||
case config.MetricsDataType: |
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.
Support only TraceDataType?
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.
For a first iteration, yes. Once we validate the approach and get it out for testing, we might (will) expand it to other data types.
Is it necessary to implement a tenantgroupprocessor to implement that each consumer request is tenant-isolated? |
Or to implement a batch processor that supports tenant isolation |
That is indeed something we talked about in the past. @tigrannajaryan mentioned this problem explicitly, and I think the consensus was that the existing processors that perform grouping (like the batch processor) should at least provide an option that allows users to tell the attribute to use to group the spans. |
Is there a requirement for pipeline tenant isolation? In this way, the retry queue is also tenant isolation and does not block each other |
There's no such requirement as of now. I would really recommend taking a look at the routing processor for more complex multi-tenant requirements, as you can split each tenant into its own pipeline, or even to its own collector instance. |
This PR was marked stale due to lack of activity. It will be closed in 7 days. |
This PR resolves #2733 by building on top of a previous PoC by @tigrannajaryan, but adapted a bit to allow the inject/extract of auth data to be performed by the configauth package. Other packages, such as the client ones, could use the same approach to inject/extract data.
I tested this with a configuration like this:
When sending a trace to the agent pipeline, it eventually reaches the collector pipeline, which prints the following to the console:
This confirms that the data is propagated down the pipeline to the exporter.
There's still a couple of points to work on: