VOOZH about

URL: https://pkg.go.dev/github.com/jamstah/k8ssaauthextension

⇱ k8ssaauthextension package - github.com/jamstah/k8ssaauthextension - Go Packages


👁 Image
README

Kubernetes Service Account Auth Extension

Status
Stability development
Distributions
Issues 👁 Open issues
👁 Closed issues

Overview

This extension implements server-side authentication for the OpenTelemetry Collector using Kubernetes service account tokens with RBAC (Role-Based Access Control) authorization. It validates incoming bearer tokens against the Kubernetes API and checks if the authenticated service account has permission to perform a specified action on a resource.

How It Works

The extension performs two-step authentication and authorization:

  1. Token Validation: Uses the Kubernetes TokenReview API to validate that the bearer token is a legitimate Kubernetes service account token.

  2. RBAC Authorization: Uses the Kubernetes SubjectAccessReview API to check if the authenticated service account has permission to perform the configured action on the specified resource.

Configuration

Parameters
  • auth_type (default: serviceAccount): How to authenticate to the Kubernetes API server. Options:

    • serviceAccount: Use the service account token mounted in the pod
    • kubeConfig: Use credentials from ~/.kube/config
    • none: No authentication (insecure, for testing only)
  • resource_attributes (required): Defines the Kubernetes resource and action to check for authorization

    • group (optional): API group of the resource (e.g., "opentelemetry.io")
    • version (optional): API version (e.g., "v1")
    • resource (required): Resource type to check (e.g., "collector")
    • verb (required): Action to authorize (e.g., "export")
    • namespace (optional): Namespace for namespaced resources. Empty means cluster-scoped.
    • name (optional): Specific resource name. Empty means any resource of this type.
  • header (default: "Authorization"): HTTP header name containing the bearer token

  • scheme (default: "Bearer"): Authentication scheme prefix

  • audiences (default: ["https://kubernetes.default.svc"]): The token must contain one of these audiences. The default works with standard Kubernetes service account. The recommended approach is to use a custom audience with a projected service account token with a defined audience.

Example Configuration
extensions:
 k8ssaauth:
 # Kubernetes API configuration
 auth_type: serviceAccount
 
 # RBAC check configuration
 resource_attributes:
 group: "telemetry.opentelemetry.io"
 version: "v1"
 resource: "telemetry"
 verb: "export"
 namespace: "observability" # Optional: check permissions in specific namespace
 name: "mytelemetry" # Optional: check permissions for a specific resource

receivers:
 otlp:
 protocols:
 grpc:
 endpoint: 0.0.0.0:4317
 auth:
 authenticator: k8ssaauth
 http:
 endpoint: 0.0.0.0:4318
 auth:
 authenticator: k8ssaauth

service:
 extensions: [k8ssaauth]
 pipelines:
 traces:
 receivers: [otlp]
 exporters: [...]
 metrics:
 receivers: [otlp]
 exporters: [...]

Kubernetes Setup

1. Create Custom Resource Definition (Optional)

If using a custom resource for semantic authorization:

apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
 name: collectors.opentelemetry.io
spec:
 group: opentelemetry.io
 versions:
 - name: v1
 served: true
 storage: true
 schema:
 openAPIV3Schema:
 type: object
 properties:
 spec:
 type: object
 scope: Namespaced
 names:
 plural: collectors
 singular: collector
 kind: Collector
2. Create RBAC Resources

Create a Role (or ClusterRole for cluster-wide permissions):

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
 name: telemetry-exporter
 namespace: observability
rules:
- apiGroups: ["opentelemetry.io"]
 resources: ["collectors"]
 verbs: ["export"] # Custom verb for semantic clarity
3. Create RoleBinding

Bind the role to service accounts that should be allowed to send telemetry:

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
 name: app-telemetry-exporter
 namespace: observability
subjects:
- kind: ServiceAccount
 name: my-app
 namespace: default
roleRef:
 kind: Role
 name: telemetry-exporter
 apiGroup: rbac.authorization.k8s.io
4. Collector Deployment

The collector needs permissions to perform TokenReview and SubjectAccessReview:

apiVersion: v1
kind: ServiceAccount
metadata:
 name: otel-collector
 namespace: observability
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
 name: otel-collector-auth
rules:
- apiGroups: ["authentication.k8s.io"]
 resources: ["tokenreviews"]
 verbs: ["create"]
- apiGroups: ["authorization.k8s.io"]
 resources: ["subjectaccessreviews"]
 verbs: ["create"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
 name: otel-collector-auth
subjects:
- kind: ServiceAccount
 name: otel-collector
 namespace: observability
roleRef:
 kind: ClusterRole
 name: otel-collector-auth
 apiGroup: rbac.authorization.k8s.io

Client Configuration

Applications sending telemetry to the collector must include their service account token in the Authorization header:

Go Example
import (
 "context"
 "os"
 
 "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc"
 "google.golang.org/grpc"
 "google.golang.org/grpc/credentials"
 "google.golang.org/grpc/metadata"
)

// Read service account token
token, err := os.ReadFile("/var/run/secrets/kubernetes.io/serviceaccount/token")
if err != nil {
 // handle error
}

// Create interceptor to add token to requests
authInterceptor := func(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
 ctx = metadata.AppendToOutgoingContext(ctx, "authorization", "Bearer "+string(token))
 return invoker(ctx, method, req, reply, cc, opts...)
}

// Create exporter with auth
exporter, err := otlptracegrpc.New(
 context.Background(),
 otlptracegrpc.WithEndpoint("otel-collector.observability.svc.cluster.local:4317"),
 otlptracegrpc.WithTLSCredentials(credentials.NewClientTLSFromCert(nil, "")),
 otlptracegrpc.WithDialOption(grpc.WithUnaryInterceptor(authInterceptor)),
)
Python Example
import os
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor

# Read service account token
with open('/var/run/secrets/kubernetes.io/serviceaccount/token', 'r') as f:
 token = f.read().strip()

# Create exporter with auth headers
exporter = OTLPSpanExporter(
 endpoint="otel-collector.observability.svc.cluster.local:4317",
 headers={"authorization": f"Bearer {token}"},
)

# Setup tracer
provider = TracerProvider()
provider.add_span_processor(BatchSpanProcessor(exporter))

Use Cases

  • Multi-Tenant Observability - Ensure that applications can only send telemetry data if they have the appropriate RBAC permissions, preventing unauthorized data injection.
  • Namespace Isolation - Configure different RBAC rules per namespace to isolate telemetry data between teams or environments.
  • Audit Trail - Leverage Kubernetes audit logs to track which service accounts are sending telemetry data.
  • Zero-Trust Security - Implement defense-in-depth by requiring both network policies and RBAC authorization for telemetry ingestion.

Security Considerations

  1. Token Rotation: Service account tokens are automatically rotated by Kubernetes. Ensure your applications reload tokens periodically.

  2. TLS: Always use TLS for the collector endpoints when using bearer token authentication.

  3. Least Privilege: Grant only the minimum required permissions to service accounts.

  4. Token audience: Use a projected service account token with a defined audience so that tokens used for authorizing export aren't trusted by the Kubernetes API to perform other actions.

Troubleshooting

Authentication Failures

Check collector logs for detailed error messages:

kubectl logs -n observability deployment/otel-collector | grep k8ssaauth

Common issues:

  • "missing or empty authorization header": Client not sending token
  • "token is not authenticated": Invalid or expired token
  • "permission denied": Service account lacks required RBAC permissions
Verify RBAC Configuration

Test if a service account has the required permissions:

kubectl auth can-i export telemetries.telemetry.opentelemetry.io \
 --as=system:serviceaccount:default:my-app \
 -n observability
Debug Mode

Enable debug logging in the collector to see detailed authentication flow:

service:
 telemetry:
 logs:
 level: debug

References

👁 Image
Documentation

Overview

Package k8ssaauthextension implements an extension that validates Kubernetes service account tokens and checks RBAC permissions for incoming requests.

This extension uses the Kubernetes TokenReview API to validate bearer tokens and the SubjectAccessReview API to verify that the authenticated service account has permission to perform a specified action on a resource.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func NewFactory

func NewFactory() extension.Factory

NewFactory creates a factory for the Kubernetes service account authenticator extension.

Types

type Config

type Config struct {
	k8sconfig.APIConfig `mapstructure:",squash"`

	// ResourceAttributes defines what resource and action to check for authorization
	ResourceAttributes ResourceAttributes `mapstructure:"resource_attributes"`

	// Header specifies the auth-header for the token. Defaults to "Authorization"
	Header string `mapstructure:"header,omitempty"`

	// Scheme specifies the auth-scheme for the token. Defaults to "Bearer"
	Scheme string `mapstructure:"scheme,omitempty"`

	// Audiences specifies the expected audiences in the token.
	// Defaults to ["https://kubernetes.default.svc"].
	Audiences []string `mapstructure:"audiences,omitempty"`
}

Config specifies the configuration for the Kubernetes service account token authenticator

func (*Config) Validate

func (cfg *Config) Validate() error

Validate checks if the extension configuration is valid

type ResourceAttributes

type ResourceAttributes struct {
	// Group is the API group of the resource (e.g., "telemetry.opentelemetry.io")
	Group string `mapstructure:"group"`

	// Version is the API version of the resource (e.g., "v1")
	Version string `mapstructure:"version"`

	// Resource is the resource type (e.g., "telemetry")
	Resource string `mapstructure:"resource"`

	// Verb is the action to check (e.g., "export", "create", "get")
	Verb string `mapstructure:"verb"`

	// Namespace is the namespace to check permissions in. Empty string means cluster-scoped.
	Namespace string `mapstructure:"namespace,omitempty"`

	// Name is the specific resource name to check. Empty string means any resource of this type.
	Name string `mapstructure:"name,omitempty"`
}

ResourceAttributes defines the Kubernetes resource and action to check for authorization

👁 Image
Directories

Path Synopsis
internal
go.dev uses cookies from Google to deliver and enhance the quality of its services and to analyze traffic. Learn more.