Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
f015a07
Add OAuth2 API definition
TeodorSAP Nov 18, 2025
920c585
Add API-level validation for authentication method types
TeodorSAP Nov 18, 2025
3cc86a0
Change API validation message
TeodorSAP Nov 19, 2025
652c155
Initial otelcollector config implementation
TeodorSAP Nov 20, 2025
bfbfa62
Fix Basic Auth check
TeodorSAP Nov 21, 2025
8f8ab14
Fix nil pointer panics
TeodorSAP Nov 21, 2025
3162718
Add UTs
TeodorSAP Nov 21, 2025
0d05342
Fix linting, manifests, CRDs, etc.
TeodorSAP Nov 21, 2025
35a6d7d
Add OAuth2 extension to the other config builders
TeodorSAP Nov 21, 2025
b81f54b
Add UTs for the actual configuration, with golden files
TeodorSAP Nov 21, 2025
216f22d
Merge branch 'main' into feat/oauth2
k15r Nov 25, 2025
3a6221f
Add OAuth2 documentation
TeodorSAP Nov 27, 2025
0544737
e2e oauth2 works
k15r Nov 27, 2025
cbdbf5e
properly label MTLS tests
k15r Nov 27, 2025
ce397e7
remove unnecessary file
k15r Nov 28, 2025
1969475
remove more files
k15r Nov 28, 2025
df3fea2
lint-fix
k15r Nov 28, 2025
0f974c2
oops
k15r Nov 28, 2025
afd6b85
wait for oauth2 mock
k15r Nov 28, 2025
8091f0d
use the correct url magically fixes the test ... :)
k15r Nov 28, 2025
e48ecb7
Implement CRD validation
TeodorSAP Nov 28, 2025
0350736
Generate resources based on validation rules
TeodorSAP Nov 28, 2025
39ee47a
Add e2e test cases for CRD validation rejection
TeodorSAP Nov 28, 2025
8374a2a
Fix CRD validation
TeodorSAP Nov 28, 2025
b9f55ee
Fix small spelling mistake
TeodorSAP Nov 28, 2025
747efe8
Merge branch 'main' into feat/oauth2
k15r Nov 28, 2025
906b8af
fix tests?
k15r Nov 28, 2025
53b246a
reorder tests to not run tests from different packages at the same time
k15r Nov 30, 2025
c0dbb31
Merge branch 'main' into feat/oauth2
k15r Nov 30, 2025
b836332
fix generate images formatting
k15r Dec 1, 2025
86e0f00
remove debug logs
k15r Dec 5, 2025
702afd2
change validation rules
k15r Dec 5, 2025
d4740e8
more validation for oauth
k15r Dec 5, 2025
5ee85f9
Merge remote-tracking branch 'upstream/main' into feat/oauth2
k15r Dec 5, 2025
dfce266
lint-fix
k15r Dec 8, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .env
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,14 @@ ENV_GARDENER_MIN_NODES=1
ENV_GARDENER_MAX_NODES=2

## Dependencies
ENV_ISTIO_VERSION=1.23.2
ENV_ISTIO_VERSION=1.23.1
ENV_GORELEASER_VERSION=v1.23.0

## Default Docker Images
ENV_FLUENTBIT_EXPORTER_IMAGE="europe-docker.pkg.dev/kyma-project/prod/directory-size-exporter:v20250910-86122076"
ENV_FLUENTBIT_IMAGE="europe-docker.pkg.dev/kyma-project/prod/external/fluent/fluent-bit:4.2.0"
ENV_OTEL_COLLECTOR_IMAGE="europe-docker.pkg.dev/kyma-project/prod/kyma-otel-collector:0.141.0-main"
ENV_OTEL_COLLECTOR_CONTRIB_IMAGE="otel/opentelemetry-collector-contrib:0.141.0"
ENV_SELFMONITOR_IMAGE="europe-docker.pkg.dev/kyma-project/prod/tpi/telemetry-self-monitor:3.7.3-f4e3fab"
ENV_TEST_TELEMETRYGEN_IMAGE="ghcr.io/open-telemetry/opentelemetry-collector-contrib/telemetrygen:v0.141.0"
ENV_ALPINE_IMAGE="europe-docker.pkg.dev/kyma-project/prod/external/library/alpine:3.22.2"
26 changes: 26 additions & 0 deletions apis/telemetry/v1alpha1/shared_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ const (

// OTLPOutput OTLP output configuration
// +kubebuilder:validation:XValidation:rule="(has(self.path) && size(self.path) > 0) ? self.protocol == 'http' : true",message="Path is only available with HTTP protocol"
// +kubebuilder:validation:XValidation:rule="(has(self.authentication) && has(self.authentication.oauth2) && self.protocol == 'grpc' && has(self.tls)) ? !(has(self.tls.insecure) && self.tls.insecure == true) : true",message="OAuth2 authentication requires TLS when using gRPC protocol"
type OTLPOutput struct {
// Protocol defines the OTLP protocol (`http` or `grpc`). Default is `grpc`.
// +kubebuilder:validation:Optional
Expand All @@ -63,10 +64,15 @@ type OTLPOutput struct {
TLS *OTLPTLS `json:"tls,omitempty"`
}

// AuthenticationOptions OTLP output authentication options
// +kubebuilder:validation:XValidation:rule="!(has(self.basic) && has(self.oauth2))",message="Only one authentication method can be specified"
type AuthenticationOptions struct {
// Basic activates `Basic` authentication for the destination providing relevant Secrets.
// +kubebuilder:validation:Optional
Basic *BasicAuthOptions `json:"basic,omitempty"`
// OAuth2 activates `OAuth2` authentication for the destination providing relevant Secrets.
// +kubebuilder:validation:Optional
OAuth2 *OAuth2Options `json:"oauth2,omitempty"`
}

type BasicAuthOptions struct {
Expand All @@ -78,6 +84,26 @@ type BasicAuthOptions struct {
Password ValueType `json:"password"`
}

// OAuth2Options contains OAuth2 authentication options.
type OAuth2Options struct {
// TokenURL contains the OAuth2 token endpoint URL or a Secret reference.
// +kubebuilder:validation:XValidation:rule="(self.value != '' ) || (has(self.valueFrom))", message="tokenURL' missing"
// +kubebuilder:validation:XValidation:rule="(self.value != '' ) ? (isURL(self.value)) : true", message="'tokenURL' must be a valid URL"
TokenURL ValueType `json:"tokenURL"`
// ClientID contains the OAuth2 client ID or a Secret reference.
// +kubebuilder:validation:XValidation:rule="(self.value != '' ) || (has(self.valueFrom))", message="'clientID' missing"
ClientID ValueType `json:"clientID"`
// ClientSecret contains the OAuth2 client secret or a Secret reference.
// +kubebuilder:validation:XValidation:rule="(self.value != '' ) || (has(self.valueFrom))", message="clientSecret' missing"
ClientSecret ValueType `json:"clientSecret"`
// Scopes contains optional OAuth2 scopes.
// +kubebuilder:validation:Optional
Scopes []string `json:"scopes,omitempty"`
// Params contains optional additional OAuth2 parameters that are sent to the token endpoint.
// +kubebuilder:validation:Optional
Params map[string]string `json:"params,omitempty"`
}

type Header struct {
// Defines the header value.
ValueType `json:",inline"`
Expand Down
34 changes: 32 additions & 2 deletions apis/telemetry/v1alpha1/shared_types_conversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,8 @@ func convertAuthenticationToBeta(a *AuthenticationOptions) *telemetryv1beta1.Aut
}

return &telemetryv1beta1.AuthenticationOptions{
Basic: convertBasicAuthToBeta(a.Basic),
Basic: convertBasicAuthToBeta(a.Basic),
OAuth2: convertOAuth2ToBeta(a.OAuth2),
}
}

Expand All @@ -183,7 +184,8 @@ func convertAuthenticationToAlpha(a *telemetryv1beta1.AuthenticationOptions) *Au
}

return &AuthenticationOptions{
Basic: convertBasicAuthToAlpha(a.Basic),
Basic: convertBasicAuthToAlpha(a.Basic),
OAuth2: convertOAuth2ToAlpha(a.OAuth2),
}
}

Expand All @@ -209,6 +211,34 @@ func convertBasicAuthToAlpha(b *telemetryv1beta1.BasicAuthOptions) *BasicAuthOpt
}
}

func convertOAuth2ToBeta(o *OAuth2Options) *telemetryv1beta1.OAuth2Options {
if o == nil {
return nil
}

return &telemetryv1beta1.OAuth2Options{
TokenURL: convertValueTypeToBeta(o.TokenURL),
ClientID: convertValueTypeToBeta(o.ClientID),
ClientSecret: convertValueTypeToBeta(o.ClientSecret),
Scopes: append([]string{}, o.Scopes...),
Params: make(map[string]string),
}
}

func convertOAuth2ToAlpha(o *telemetryv1beta1.OAuth2Options) *OAuth2Options {
if o == nil {
return nil
}

return &OAuth2Options{
TokenURL: convertValueTypeToAlpha(o.TokenURL),
ClientID: convertValueTypeToAlpha(o.ClientID),
ClientSecret: convertValueTypeToAlpha(o.ClientSecret),
Scopes: append([]string{}, o.Scopes...),
Params: make(map[string]string),
}
}

func convertHeadersToBeta(hs []Header) []telemetryv1beta1.Header {
var out []telemetryv1beta1.Header
for _, h := range hs {
Expand Down
35 changes: 35 additions & 0 deletions apis/telemetry/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

24 changes: 24 additions & 0 deletions apis/telemetry/v1beta1/shared_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ const (

// OTLPOutput OTLP output configuration
// +kubebuilder:validation:XValidation:rule="(has(self.path) && size(self.path) > 0) ? self.protocol == 'http' : true",message="Path is only available with HTTP protocol"
// +kubebuilder:validation:XValidation:rule="(has(self.authentication) && has(self.authentication.oauth2) && self.protocol == 'grpc' && has(self.tls)) ? !(has(self.tls.insecure) && self.tls.insecure == true) : true",message="OAuth2 authentication requires TLS when using gRPC protocol"
type OTLPOutput struct {
// Protocol defines the OTLP protocol (`http` or `grpc`). Default is `grpc`.
// +kubebuilder:validation:Optional
Expand All @@ -65,10 +66,15 @@ type OTLPOutput struct {
TLS *OutputTLS `json:"tls,omitempty"`
}

// AuthenticationOptions OTLP output authentication options
// +kubebuilder:validation:XValidation:rule="!(has(self.basic) && has(self.oauth2))",message="Only one authentication method can be specified"
type AuthenticationOptions struct {
// Basic activates `Basic` authentication for the destination providing relevant Secrets.
// +kubebuilder:validation:Optional
Basic *BasicAuthOptions `json:"basic,omitempty"`
// OAuth2 activates `OAuth2` authentication for the destination providing relevant Secrets.
// +kubebuilder:validation:Optional
OAuth2 *OAuth2Options `json:"oauth2,omitempty"`
}

type BasicAuthOptions struct {
Expand All @@ -80,6 +86,24 @@ type BasicAuthOptions struct {
Password ValueType `json:"password"`
}

type OAuth2Options struct {
// TokenURL contains the OAuth2 token endpoint URL or a Secret reference.
// +kubebuilder:validation:Required
TokenURL ValueType `json:"tokenURL"`
// ClientID contains the OAuth2 client ID or a Secret reference.
// +kubebuilder:validation:Required
ClientID ValueType `json:"clientID"`
// ClientSecret contains the OAuth2 client secret or a Secret reference.
// +kubebuilder:validation:Required
ClientSecret ValueType `json:"clientSecret"`
// Scopes contains optional OAuth2 scopes.
// +kubebuilder:validation:Optional
Scopes []string `json:"scopes,omitempty"`
// Params contains optional additional OAuth2 parameters that are sent to the token endpoint.
// +kubebuilder:validation:Optional
Params map[string]string `json:"params,omitempty"`
}

type Header struct {
// Defines the header value.
ValueType `json:",inline"`
Expand Down
35 changes: 35 additions & 0 deletions apis/telemetry/v1beta1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions dependencies/populateimages/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@ var templates = map[string]string{
package testkit

const (
DefaultTelemetryGenImage = "{{ .ENV_TEST_TELEMETRYGEN_IMAGE }}"
DefaultOTelCollectorImage = "{{ .ENV_OTEL_COLLECTOR_IMAGE }}"
DefaultTelemetryGenImage = "{{ .ENV_TEST_TELEMETRYGEN_IMAGE }}"
DefaultOTelCollectorContribImage = "{{ .ENV_OTEL_COLLECTOR_CONTRIB_IMAGE }}"
DefaultOTelCollectorImage = "{{ .ENV_OTEL_COLLECTOR_IMAGE }}"
)
`,
}
Expand Down
36 changes: 35 additions & 1 deletion docs/user/integrate-otlp-backend/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ Ensure the port in your endpoint URL is correct for the chosen protocol.

## Set Up Authentication

For each pipeline, add authentication details (like user names, passwords, certificates, or tokens) to connect securely to your observability backend. You can use mutual TLS (mTLS), custom headers, or Basic Authentication.
For each pipeline, add authentication details (like user names, passwords, certificates, or tokens) to connect securely to your observability backend. You can use mutual TLS (mTLS), custom headers, OAuth2, or Basic Authentication.

While you can choose to add your authentication details from plain text, it’s recommended to store these sensitive details in a Kubernetes `Secret` and reference the Secret's keys in your pipeline configuration. When you rotate the `Secret` and update its values, Telemetry Manager detects the changes and applies the new `Secret` to your setup.

Expand Down Expand Up @@ -88,6 +88,40 @@ While you can choose to add your authentication details from plain text, it’s
key: token
```

- To use OAuth2 for authentication, configure the `authentication.oauth2` section.

```yaml
...
output:
otlp:
endpoint:
valueFrom:
secretKeyRef:
name: backend
namespace: default
key: endpoint
authentication:
oauth2:
clientId:
valueFrom:
secretKeyRef:
name: backend
namespace: default
key: clientId
clientSecret:
valueFrom:
secretKeyRef:
name: backend
namespace: default
key: clientSecret
tokenUrl:
valueFrom:
secretKeyRef:
name: backend
namespace: default
key: tokenUrl
```

Copy link
Contributor

Choose a reason for hiding this comment

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

Should we add a note about this: DISCLAIMER: GRPC output without TLS configuration is not supported by the OTel collector when OAuth2 is enabled. ?

Copy link
Contributor

@NHingerl NHingerl Dec 4, 2025

Choose a reason for hiding this comment

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

Is there a way to express this in active voice and more user-centric?

Like "If you want to use OAuth2 with gRPC, you must configure TLS."

Copy link
Member Author

@TeodorSAP TeodorSAP Dec 4, 2025

Choose a reason for hiding this comment

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

Yes, I will add it. The user will also get a straight-forward message from the CRD validation if they try configuring it without TLS. But might be good to add it to the documentation as well.

- To use a username and password for authentication, configure the `authentication.basic` section.

```yaml
Expand Down
24 changes: 24 additions & 0 deletions docs/user/resources/02-logpipeline.md
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,30 @@ For details, see the [LogPipeline specification file](https://github.com/kyma-pr
| **output.​otlp.​authentication.​basic.​user.​valueFrom.​secretKeyRef.​key** (required) | string | Key defines the name of the attribute of the Secret holding the referenced value. |
| **output.​otlp.​authentication.​basic.​user.​valueFrom.​secretKeyRef.​name** (required) | string | Name of the Secret containing the referenced value. |
| **output.​otlp.​authentication.​basic.​user.​valueFrom.​secretKeyRef.​namespace** (required) | string | Namespace containing the Secret with the referenced value. |
| **output.​otlp.​authentication.​oauth2** | object | OAuth2 activates `OAuth2` authentication for the destination providing relevant Secrets. |
| **output.​otlp.​authentication.​oauth2.​clientID** (required) | object | ClientID contains the OAuth2 client ID or a Secret reference. |
| **output.​otlp.​authentication.​oauth2.​clientID.​value** | string | Value as plain text. |
| **output.​otlp.​authentication.​oauth2.​clientID.​valueFrom** | object | ValueFrom is the value as a reference to a resource. |
| **output.​otlp.​authentication.​oauth2.​clientID.​valueFrom.​secretKeyRef** (required) | object | SecretKeyRef refers to the value of a specific key in a Secret. You must provide `name` and `namespace` of the Secret, as well as the name of the `key`. |
| **output.​otlp.​authentication.​oauth2.​clientID.​valueFrom.​secretKeyRef.​key** (required) | string | Key defines the name of the attribute of the Secret holding the referenced value. |
| **output.​otlp.​authentication.​oauth2.​clientID.​valueFrom.​secretKeyRef.​name** (required) | string | Name of the Secret containing the referenced value. |
| **output.​otlp.​authentication.​oauth2.​clientID.​valueFrom.​secretKeyRef.​namespace** (required) | string | Namespace containing the Secret with the referenced value. |
| **output.​otlp.​authentication.​oauth2.​clientSecret** (required) | object | ClientSecret contains the OAuth2 client secret or a Secret reference. |
| **output.​otlp.​authentication.​oauth2.​clientSecret.​value** | string | Value as plain text. |
| **output.​otlp.​authentication.​oauth2.​clientSecret.​valueFrom** | object | ValueFrom is the value as a reference to a resource. |
| **output.​otlp.​authentication.​oauth2.​clientSecret.​valueFrom.​secretKeyRef** (required) | object | SecretKeyRef refers to the value of a specific key in a Secret. You must provide `name` and `namespace` of the Secret, as well as the name of the `key`. |
| **output.​otlp.​authentication.​oauth2.​clientSecret.​valueFrom.​secretKeyRef.​key** (required) | string | Key defines the name of the attribute of the Secret holding the referenced value. |
| **output.​otlp.​authentication.​oauth2.​clientSecret.​valueFrom.​secretKeyRef.​name** (required) | string | Name of the Secret containing the referenced value. |
| **output.​otlp.​authentication.​oauth2.​clientSecret.​valueFrom.​secretKeyRef.​namespace** (required) | string | Namespace containing the Secret with the referenced value. |
| **output.​otlp.​authentication.​oauth2.​params** | map\[string\]string | Params contains optional additional OAuth2 parameters that are sent to the token endpoint. |
| **output.​otlp.​authentication.​oauth2.​scopes** | \[\]string | Scopes contains optional OAuth2 scopes. |
| **output.​otlp.​authentication.​oauth2.​tokenURL** (required) | object | TokenURL contains the OAuth2 token endpoint URL or a Secret reference. |
| **output.​otlp.​authentication.​oauth2.​tokenURL.​value** | string | Value as plain text. |
| **output.​otlp.​authentication.​oauth2.​tokenURL.​valueFrom** | object | ValueFrom is the value as a reference to a resource. |
| **output.​otlp.​authentication.​oauth2.​tokenURL.​valueFrom.​secretKeyRef** (required) | object | SecretKeyRef refers to the value of a specific key in a Secret. You must provide `name` and `namespace` of the Secret, as well as the name of the `key`. |
| **output.​otlp.​authentication.​oauth2.​tokenURL.​valueFrom.​secretKeyRef.​key** (required) | string | Key defines the name of the attribute of the Secret holding the referenced value. |
| **output.​otlp.​authentication.​oauth2.​tokenURL.​valueFrom.​secretKeyRef.​name** (required) | string | Name of the Secret containing the referenced value. |
| **output.​otlp.​authentication.​oauth2.​tokenURL.​valueFrom.​secretKeyRef.​namespace** (required) | string | Namespace containing the Secret with the referenced value. |
| **output.&#x200b;otlp.&#x200b;endpoint** (required) | object | Endpoint defines the host and port (`<host>:<port>`) of an OTLP endpoint. |
| **output.&#x200b;otlp.&#x200b;endpoint.&#x200b;value** | string | Value as plain text. |
| **output.&#x200b;otlp.&#x200b;endpoint.&#x200b;valueFrom** | object | ValueFrom is the value as a reference to a resource. |
Expand Down
Loading
Loading