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

API: EnvoyExtensionPolicy #2570

Merged
merged 8 commits into from
Mar 16, 2024
Merged
Show file tree
Hide file tree
Changes from 3 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
76 changes: 76 additions & 0 deletions api/v1alpha1/envoyextensionypolicy_types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
// Copyright Envoy Gateway Authors
// SPDX-License-Identifier: Apache-2.0
// The full text of the Apache license is available in the LICENSE file at
// the root of the repo.

package v1alpha1

import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
gwapiv1a2 "sigs.k8s.io/gateway-api/apis/v1alpha2"
)

const (
// KindEnvoyExtensionPolicy is the name of the EnvoyExtensionPolicy kind.
KindEnvoyExtensionPolicy = "EnvoyExtensionPolicy"
)

// +kubebuilder:object:root=true
// +kubebuilder:resource:shortName=eep
// +kubebuilder:subresource:status
// +kubebuilder:printcolumn:name="Status",type=string,JSONPath=`.status.conditions[?(@.type=="Accepted")].reason`
// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp`

// EnvoyExtensionPolicy allows the user to configure various envoy extensibility options for the Gateway.
type EnvoyExtensionPolicy struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`

// Spec defines the desired state of EnvoyExtensionPolicy.
Spec EnvoyExtensionPolicySpec `json:"spec"`

// Status defines the current status of EnvoyExtensionPolicy.
Status gwapiv1a2.PolicyStatus `json:"status,omitempty"`
}

// EnvoyExtensionPolicySpec defines the desired state of EnvoyExtensionPolicy.
type EnvoyExtensionPolicySpec struct {
// +kubebuilder:validation:XValidation:rule="self.group == 'gateway.networking.k8s.io'", message="this policy can only have a targetRef.group of gateway.networking.k8s.io"
// +kubebuilder:validation:XValidation:rule="self.kind in ['Gateway']", message="this policy can only have a targetRef.kind of Gateway"
Copy link
Contributor

@arkodg arkodg Mar 15, 2024

Choose a reason for hiding this comment

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

should target Gateway and Route

// +kubebuilder:validation:XValidation:rule="!has(self.sectionName)",message="this policy does not yet support the sectionName field"
//
// TargetRef is the name of the Gateway resource this policy
// is being attached to.
// This Policy and the TargetRef MUST be in the same namespace
// for this Policy to have effect and be applied to the Gateway.
// TargetRef
TargetRef gwapiv1a2.PolicyTargetReferenceWithSectionName `json:"targetRef"`

// Priority of the EnvoyExtensionPolicy.
// If multiple EnvoyExtensionPolices are applied to the same
// TargetRef, extensions will execute in the ascending order of
// the priority i.e. int32.min has the highest priority and
// int32.max has the lowest priority.
// Defaults to 0.
//
// +optional
Priority int32 `json:"priority,omitempty"`

// ExtProc defines the configuration for the external processor extension.
//
// +optional
ExtProc *ExtProc `json:"extProc,omitempty"`
Copy link
Contributor

Choose a reason for hiding this comment

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

as per huabing's point, should we make this a list ?

}

//+kubebuilder:object:root=true

// EnvoyExtensionPolicyList contains a list of EnvoyExtensionPolicy resources.
type EnvoyExtensionPolicyList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []EnvoyExtensionPolicy `json:"items"`
}

func init() {
SchemeBuilder.Register(&EnvoyExtensionPolicy{}, &EnvoyExtensionPolicyList{})
}
4 changes: 4 additions & 0 deletions api/v1alpha1/envoygateway_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,10 @@ type ExtensionAPISettings struct {
// EnableEnvoyPatchPolicy enables Envoy Gateway to
// reconcile and implement the EnvoyPatchPolicy resources.
EnableEnvoyPatchPolicy bool `json:"enableEnvoyPatchPolicy"`

// EnableEnvoyExtensionPolicy enables Envoy Gateway to
Copy link
Contributor

Choose a reason for hiding this comment

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

@envoyproxy/gateway-maintainers @envoyproxy/gateway-reviewers thoughts on this ?

Copy link
Member

Choose a reason for hiding this comment

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

I'm fine to remove all these, it will not happen unless you create a CR.

// reconcile and implement the EnvoyExtensionPolicy resources.
EnableEnvoyExtensionPolicy bool `json:"enableEnvoyExtensionPolicy"`
}

// EnvoyGatewayProvider defines the desired configuration of a provider.
Expand Down
40 changes: 40 additions & 0 deletions api/v1alpha1/envoyproxy_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,24 @@ const (
KindEnvoyProxy = "EnvoyProxy"
)

// +kubebuilder:validation:Enum=CORS;External-Authorization;Basic-Authorization;OAuth2;JWT-Authentication;Fault-Injection;Fault-Injection;Local-Rate-Limit;Global-Rate-Limit
//
// EnvoyFilterName is the name of an Envoy HTTP filter
type EnvoyFilterName string

const (
CORSFilterName EnvoyFilterName = "CORS"
ExtAuthFilterName EnvoyFilterName = "External-Authorization"
BasicAuthFilterName EnvoyFilterName = "Basic-Authorization"
OAuth2FilterName EnvoyFilterName = "OAuth2"
JWTAuthnOAuth2FilterName EnvoyFilterName = "JWT-Authentication"
FaultInjectionFilterName EnvoyFilterName = "Fault-Injection"
LocalRateLimitFilterName EnvoyFilterName = "Local-Rate-Limit"
GlobalRateLimitFilterName EnvoyFilterName = "Global-Rate-Limit"
ExtProcFilterName EnvoyFilterName = "External-Processing"
WASMFilterName EnvoyFilterName = "WASM"
)

// +kubebuilder:object:root=true
// +kubebuilder:resource:categories=envoy-gateway,shortName=eproxy
// +kubebuilder:subresource:status
Expand Down Expand Up @@ -86,6 +104,14 @@ type EnvoyProxySpec struct {
//
// +optional
Shutdown *ShutdownConfig `json:"shutdown,omitempty"`

// FilterOrdering defines the order of Envoy HTTP filter execution. If a partial filter list is provided, the default
// order will apply, and only the listed filters will be re-ordered amongst themselves.
// Default: CORS, External-Processing, WASM, External-Authorization, Basic-Authorization, OAuth2, JWT-Authentication,
// Fault-Injection, Local-Rate-Limit, Global-Rate-Limit
//
// +optional
FilterOrdering []EnvoyFilterName `json:"filterOrdering,omitempty"`
Copy link
Contributor

Choose a reason for hiding this comment

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

suggest keep filter ordering out of scope of this API, and solving it separately in #2571

}

type ProxyTelemetry struct {
Expand Down Expand Up @@ -134,6 +160,20 @@ type ShutdownConfig struct {
MinDrainDuration *metav1.Duration `json:"minDrainDuration,omitempty"`
}

// FilterOrdering defines the ordering of well-known.
type FilterOrdering struct {
zirain marked this conversation as resolved.
Show resolved Hide resolved
// DrainTimeout defines the graceful drain timeout. This should be less than the pod's terminationGracePeriodSeconds.
// If unspecified, defaults to 600 seconds.
//
// +optional
DrainTimeout *metav1.Duration `json:"drainTimeout,omitempty"`
// MinDrainDuration defines the minimum drain duration allowing time for endpoint deprogramming to complete.
// If unspecified, defaults to 5 seconds.
//
// +optional
MinDrainDuration *metav1.Duration `json:"minDrainDuration,omitempty"`
}

// EnvoyProxyKubernetesProvider defines configuration for the Kubernetes resource
// provider.
type EnvoyProxyKubernetesProvider struct {
Expand Down
130 changes: 130 additions & 0 deletions api/v1alpha1/ext_proc_types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
// Copyright Envoy Gateway Authors
// SPDX-License-Identifier: Apache-2.0
// The full text of the Apache license is available in the LICENSE file at
// the root of the repo.

package v1alpha1

import (
gwapiv1 "sigs.k8s.io/gateway-api/apis/v1"
)

// +kubebuilder:validation:Enum=Default;Send;Skip
type ExtProcHeaderProcessingMode string
guydc marked this conversation as resolved.
Show resolved Hide resolved

const (
guydc marked this conversation as resolved.
Show resolved Hide resolved
DefaultExtProcHeaderProcessingMode ExtProcHeaderProcessingMode = "Default"
SendExtProcHeaderProcessingMode ExtProcHeaderProcessingMode = "Send"
SkipExtProcHeaderProcessingMode ExtProcHeaderProcessingMode = "Skip"
)

// +kubebuilder:validation:Enum=None;Streamed;Buffered;BufferedPartial
type ExtProcBodyProcessingMode string
guydc marked this conversation as resolved.
Show resolved Hide resolved

const (
guydc marked this conversation as resolved.
Show resolved Hide resolved
NoneExtProcHeaderProcessingMode ExtProcBodyProcessingMode = "None"
StreamedExtProcHeaderProcessingMode ExtProcBodyProcessingMode = "Streamed"
BufferedExtProcHeaderProcessingMode ExtProcBodyProcessingMode = "Buffered"
BufferedPartialExtProcHeaderProcessingMode ExtProcBodyProcessingMode = "BufferedPartial"
)

type ProcessingModeOptions struct {
// Defines header processing mode
//
// +kubebuilder:default:=Send
// +optional
Headers *ExtProcHeaderProcessingMode `json:"header,omitempty"`
// Defines body processing mode
//
// +kubebuilder:default:=None
// +optional
Body *ExtProcBodyProcessingMode `json:"body,omitempty"`
}

// ExtProcProcessingMode defines if and how headers and bodies are sent to the service.
// https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/http/ext_proc/v3/processing_mode.proto#envoy-v3-api-msg-extensions-filters-http-ext-proc-v3-processingmode
type ExtProcProcessingMode struct {
// Defines header and body treatment for requests
//
// +optional
Request *ProcessingModeOptions `json:"request,omitempty"`
// Defines header and body treatment for responses
//
// +optional
Response *ProcessingModeOptions `json:"response,omitempty"`
guydc marked this conversation as resolved.
Show resolved Hide resolved
}

// ExtProcAttributes defines which attributes are
type ExtProcAttributes struct {
// defines attributes to send for Request processing
//
// +optional
Request []string `json:"request,omitempty"`
// defines attributes to send for Response processing
//
// +optional
Response []string `json:"response,omitempty"`
}

// MetadataNamespaces defines metadata namespaces that can be used to forward or receive dynamic metadata
type MetadataNamespaces struct {
// Specifies a list of metadata namespaces whose values, if present, will be passed to the ext_proc service as an opaque protobuf::Struct.
//
// +optional
Untyped []string `json:"untyped,omitempty"`
guydc marked this conversation as resolved.
Show resolved Hide resolved
// Specifies a list of metadata namespaces whose values, if present, will be passed to the ext_proc service as a protobuf::Any.
//
// +optional
Typed []string `json:"typed,omitempty"`
guydc marked this conversation as resolved.
Show resolved Hide resolved
}

// ExtProcMetadataOptions defines options related to the sending and receiving of dynamic metadata
type ExtProcMetadataOptions struct {
// metadata namespaces forwarded to external processor
//
// +optional
ForwardingNamespaces []MetadataNamespaces `json:"forwardingNamespaces,omitempty"`
// metadata namespaces updatable by external processor
//
// +optional
ReceivingNamespaces []MetadataNamespaces `json:"receivingNamespaces,omitempty"`
}

// +kubebuilder:validation:XValidation:rule="has(self.service) ? (!has(self.service.backendRef.group) || self.service.backendRef.group == \"\") : true", message="group is invalid, only the core API group (specified by omitting the group field or setting it to an empty string) is supported"
// +kubebuilder:validation:XValidation:rule="has(self.service) ? (!has(self.service.backendRef.kind) || self.service.backendRef.kind == 'Service') : true", message="kind is invalid, only Service (specified by omitting the kind field or setting it to 'Service') is supported"
//
// ExtProc defines the configuration for External Processing.
type ExtProc struct {
guydc marked this conversation as resolved.
Show resolved Hide resolved
// Service defines the configuration of the external processing service
Service ExtProcService `json:"service"`
// ProcessingMode defines how request and response headers and body are processed
// Default: request and response headers are sent, bodies are not sent
//
// +optional
ProcessingMode *ExtProcProcessingMode `json:"processingMode,omitempty"`
// Attributes defines which envoy request and response attributes are provided as context to external processor
// Default: no attributes are sent
//
// +optional
Attributes *ExtProcAttributes `json:"attributes,omitempty"`
// MetadataOptions defines options related to the sending and receiving of dynamic metadata
// Default: no metadata context is sent or received
//
// +optional
MetadataOptions *ExtProcMetadataOptions `json:"metadataOptions,omitempty"`
// The timeout for a response to be returned from the external processor
// Default: 200ms
Copy link
Contributor

Choose a reason for hiding this comment

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

Add a +kubebuilder:default comment for MessageTimeout.

//
// +optional
MessageTimeout *gwapiv1.Duration `json:"messageTimeout,omitempty"`
}

// ExtProcService defines the gRPC External Processing service using the envoy grpc client
// The processing request and response messages are defined in
// https://www.envoyproxy.io/docs/envoy/latest/api-v3/service/ext_proc/v3/external_processor.proto
type ExtProcService struct {
// BackendObjectReference references a Kubernetes object that represents the
// backend server to which the processing requests will be sent.
// Only service Kind is supported for now.
BackendRef gwapiv1.BackendObjectReference `json:"backendRef"`
}
Loading
Loading