Skip to content
Open
Show file tree
Hide file tree
Changes from 9 commits
Commits
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
2 changes: 1 addition & 1 deletion .github/workflows/e2e.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ jobs:
# August 29, 2025: ~10 minutes
- cluster-name: 'cluster-five'
go-test-args: '-timeout=25m'
go-test-run-regex: '^TestKgateway$$/^TimeoutRetry$$|^TestKgateway$$/^HeaderModifiers$$|^TestKgateway$$/^RBAC$$|^TestKgateway$$/^Deployer$$|^TestKgateway$$/^Transforms$$|^TestRouteReplacement$$|^TestKgateway$$/^RouteDelegation$$'
go-test-run-regex: '^TestKgateway$$/^TimeoutRetry$$|^TestKgateway$$/^HeaderModifiers$$|^TestKgateway$$/^RBAC$$|^TestKgateway$$/^APIKeyAuth$$|^TestKgateway$$/^Deployer$$|^TestKgateway$$/^Transforms$$|^TestRouteReplacement$$|^TestKgateway$$/^RouteDelegation$$'
localstack: 'false'
# August 29, 2025: ~9 minutes
- cluster-name: 'cluster-six'
Expand Down
118 changes: 118 additions & 0 deletions api/v1alpha1/traffic_policy_types.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package v1alpha1

import (
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
gwv1 "sigs.k8s.io/gateway-api/apis/v1"
Expand Down Expand Up @@ -121,6 +122,10 @@ type TrafficPolicySpec struct {
// This defines the JWT providers and their configurations.
// +optional
JWT *JWTAuthentication `json:"jwt,omitempty"`

// APIKeyAuthentication authenticates users based on a configured API Key.
// +optional
APIKeyAuthentication *APIKeyAuthentication `json:"apiKeyAuthentication,omitempty"`
}

// TransformationPolicy config is used to modify envoy behavior at a route level.
Expand Down Expand Up @@ -369,6 +374,119 @@ type CSRFPolicy struct {
AdditionalOrigins []StringMatcher `json:"additionalOrigins,omitempty"`
}

// APIKeySource defines where to extract the API key from within a single key source.
// Within a single key source, if multiple types are specified, precedence is:
// header > query parameter > cookie. The header is checked first, and only falls back
// to query parameter if the header is not present, then to cookie if both header and query
// are not present.
// +kubebuilder:validation:AtLeastOneOf=header;query;cookie
type APIKeySource struct {
// header specifies the name of the header that contains the API key.
// +optional
// +kubebuilder:validation:MinLength=1
// +kubebuilder:validation:MaxLength=256
Header *string `json:"header,omitempty"`

// query specifies the name of the query parameter that contains the API key.
// +optional
// +kubebuilder:validation:MinLength=1
// +kubebuilder:validation:MaxLength=256
Query *string `json:"query,omitempty"`

// cookie specifies the name of the cookie that contains the API key.
// +optional
// +kubebuilder:validation:MinLength=1
// +kubebuilder:validation:MaxLength=256
Cookie *string `json:"cookie,omitempty"`
}

// +kubebuilder:validation:ExactlyOneOf=secretRef;secretSelector
type APIKeyAuthentication struct {
// keySources specifies the list of key sources to extract the API key from.
// Key sources are processed in array order and the first one that successfully
// extracts a key is used. Within each key source, if multiple types (header, query, cookie) are
// specified, precedence is: header > query parameter > cookie.
//
// If empty, defaults to a single key source with header "api-key".
//
// Example:
// keySources:
// - header: "X-API-KEY"
// - query: "api_key"
// - header: "Authorization"
// query: "token"
// cookie: "auth_token"
//
// In this example, the system will:
// 1. First try header "X-API-KEY"
// 2. If not found, try query parameter "api_key"
// 3. If not found, try header "Authorization" (then query "token", then cookie "auth_token" within that key source)
//
// +kubebuilder:validation:MinItems=0
// +kubebuilder:validation:MaxItems=16
// +optional
KeySources []APIKeySource `json:"keySources,omitempty"`

// forwardCredential controls whether the API key is included in the request sent to the upstream.
// If false (default), the API key is removed from the request before sending to upstream.
// If true, the API key is included in the request sent to upstream.
// This applies to all configured key sources (header, query parameter, or cookie).
// +kubebuilder:default=false
// +optional
ForwardCredential *bool `json:"forwardCredential,omitempty"`

// clientIdHeader specifies the header name to forward the authenticated client identifier.
// If not specified, the client identifier will not be forwarded in any header.
// Example: "x-client-id"
// +optional
ClientIdHeader *string `json:"clientIdHeader,omitempty"`

// secretRef references a Kubernetes secret storing a set of API Keys. If there are many keys, 'secretSelector' can be
// used instead.
//
// Each entry in the Secret represents one API Key. The key is an arbitrary identifier.
// The value is a string, representing the API Key.
//
// Example:
//
// apiVersion: v1
// kind: Secret
// metadata:
// name: api-key
// stringData:
// client1: "k-123"
// client2: "k-456"
//
// +optional
SecretRef *corev1.LocalObjectReference `json:"secretRef,omitempty"`

// secretSelector selects multiple secrets containing API Keys. If the same key is defined in multiple secrets, the
// behavior is undefined.
//
// Each entry in the Secret represents one API Key. The key is an arbitrary identifier.
// The value is a string, representing the API Key.
//
// Example:
//
// apiVersion: v1
// kind: Secret
// metadata:
// name: api-key
// stringData:
// client1: "k-123"
// client2: "k-456"
//
// +optional
SecretSelector *LabelSelector `json:"secretSelector,omitempty"`
}

// LabelSelector selects resources using label selectors.
type LabelSelector struct {
// Label selector to select the target resource.
// +required
MatchLabels map[string]string `json:"matchLabels"`
}

// HeaderModifiers can be used to define the policy to modify request and response headers.
// +kubebuilder:validation:AtLeastOneOf=request;response
type HeaderModifiers struct {
Expand Down
99 changes: 99 additions & 0 deletions api/v1alpha1/zz_generated.deepcopy.go

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

Loading