diff --git a/extensions/v1alpha1/extension_filter.pb.go b/extensions/v1alpha1/extension_filter.pb.go new file mode 100644 index 0000000000..07d19fdcd9 --- /dev/null +++ b/extensions/v1alpha1/extension_filter.pb.go @@ -0,0 +1,947 @@ +// Copyright Istio Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.11 +// protoc (unknown) +// source: extensions/v1alpha1/extension_filter.proto + +// $schema: istio.extensions.v1alpha1.ExtensionFilter +// $title: Extension Filter +// $description: Extend the functionality provided by the Istio proxy through WebAssembly or Lua filters. +// $location: https://istio.io/docs/reference/config/proxy_extensions/v1alpha1/extension_filter.html +// $aliases: [/docs/reference/config/extensions/v1alpha1/extension_filter] + +// ExtensionFilter provides a mechanism to extend the functionality provided by +// the Istio proxy through WebAssembly or Lua filters. +// +// This API supersedes WasmPlugin by providing a unified mechanism for configuring +// multiple extension types (WebAssembly and Lua) while maintaining consistent +// targeting and configuration patterns. +// +// The order of execution (as part of Envoy's filter chain) is determined by +// phase and priority settings, allowing the configuration of complex +// interactions between user-supplied WebAssembly or Lua and Istio's internal +// filters. +// +// Examples: +// +// AuthN Filter deployed to ingress-gateway that implements an OpenID flow +// and populates the `Authorization` header with a JWT to be consumed by +// Istio AuthN. +// +// ```yaml +// apiVersion: extensions.istio.io/v1alpha1 +// kind: ExtensionFilter +// metadata: +// name: openid-connect +// namespace: istio-ingress +// spec: +// selector: +// matchLabels: +// istio: ingressgateway +// phase: AUTHN +// wasm: +// url: file:///opt/filters/openid.wasm +// sha256: 1ef0c9a92b0420cf25f7fe5d481b231464bc88f486ca3b9c83ed5cc21d2f6210 +// pluginConfig: +// openid_server: authn +// openid_realm: ingress +// ``` +// +// This is the same as the last example, but using an OCI image. +// +// ```yaml +// apiVersion: extensions.istio.io/v1alpha1 +// kind: ExtensionFilter +// metadata: +// name: openid-connect +// namespace: istio-ingress +// spec: +// selector: +// matchLabels: +// istio: ingressgateway +// phase: AUTHN +// wasm: +// url: oci://private-registry:5000/openid-connect/openid:latest +// imagePullPolicy: IfNotPresent +// imagePullSecret: private-registry-pull-secret +// pluginConfig: +// openid_server: authn +// openid_realm: ingress +// ``` +// +// This is the same as the last example, but using VmConfig to configure environment variables in the VM. +// +// ```yaml +// apiVersion: extensions.istio.io/v1alpha1 +// kind: ExtensionFilter +// metadata: +// name: openid-connect +// namespace: istio-ingress +// spec: +// selector: +// matchLabels: +// istio: ingressgateway +// phase: AUTHN +// wasm: +// url: oci://private-registry:5000/openid-connect/openid:latest +// imagePullPolicy: IfNotPresent +// imagePullSecret: private-registry-pull-secret +// pluginConfig: +// openid_server: authn +// openid_realm: ingress +// vmConfig: +// env: +// - name: POD_NAME +// valueFrom: HOST +// - name: TRUST_DOMAIN +// value: "cluster.local" +// ``` +// +// This is also the same as the last example, but the Wasm module is pulled via https and updated for each time when this plugin resource is changed. +// +// ```yaml +// apiVersion: extensions.istio.io/v1alpha1 +// kind: ExtensionFilter +// metadata: +// name: openid-connect +// namespace: istio-ingress +// spec: +// selector: +// matchLabels: +// istio: ingressgateway +// phase: AUTHN +// wasm: +// url: https://private-bucket/filters/openid.wasm +// imagePullPolicy: Always +// pluginConfig: +// openid_server: authn +// openid_realm: ingress +// vmConfig: +// env: +// - name: POD_NAME +// valueFrom: HOST +// - name: TRUST_DOMAIN +// value: "cluster.local" +// ``` +// +// And a more complex example that deploys three ExtensionFilters and orders them +// using `phase` and `priority`. The (hypothetical) setup is that the +// `openid-connect` filter performs an OpenID Connect flow to authenticate the +// user, writing a signed JWT into the Authorization header of the request, +// which can be verified by the Istio authn plugin. Then, the `acl-check` plugin +// kicks in, passing the JWT to a policy server, which in turn responds with a +// signed token that contains information about which files and functions of the +// system are available to the user that was previously authenticated. The +// `acl-check` filter writes this token to a header. Finally, the `check-header` +// filter verifies the token in that header and makes sure that the token's +// contents (the permitted 'function') matches its plugin configuration. +// +// The resulting filter chain looks like this: +// -> openid-connect -> istio.authn -> acl-check -> check-header -> router +// +// ```yaml +// apiVersion: extensions.istio.io/v1alpha1 +// kind: ExtensionFilter +// metadata: +// name: openid-connect +// namespace: istio-ingress +// spec: +// selector: +// matchLabels: +// istio: ingressgateway +// phase: AUTHN +// wasm: +// url: oci://private-registry:5000/openid-connect/openid:latest +// imagePullPolicy: IfNotPresent +// imagePullSecret: private-registry-pull-secret +// pluginConfig: +// openid_server: authn +// openid_realm: ingress +// ``` +// +// ```yaml +// apiVersion: extensions.istio.io/v1alpha1 +// kind: ExtensionFilter +// metadata: +// name: acl-check +// namespace: istio-ingress +// spec: +// selector: +// matchLabels: +// istio: ingressgateway +// phase: AUTHZ +// priority: 1000 +// wasm: +// url: oci://private-registry:5000/acl-check/acl:latest +// imagePullPolicy: Always +// imagePullSecret: private-registry-pull-secret +// pluginConfig: +// acl_server: some_server +// set_header: authz_complete +// ``` +// +// ```yaml +// apiVersion: extensions.istio.io/v1alpha1 +// kind: ExtensionFilter +// metadata: +// name: check-header +// namespace: istio-ingress +// spec: +// selector: +// matchLabels: +// istio: ingressgateway +// phase: AUTHZ +// priority: 10 +// wasm: +// url: oci://private-registry:5000/check-header:latest +// imagePullPolicy: IfNotPresent +// imagePullSecret: private-registry-pull-secret +// pluginConfig: +// read_header: authz_complete +// verification_key: a89gAzxvls0JKAKIJSBnnvvvkIO +// function: read_data +// ``` +// +// Gateway with Lua filter for conditional header modification: +// +// ```yaml +// apiVersion: extensions.istio.io/v1alpha1 +// kind: ExtensionFilter +// metadata: +// name: conditional-header-modifier +// namespace: istio-ingress +// spec: +// selector: +// matchLabels: +// istio: ingressgateway +// match: +// - mode: CLIENT +// ports: +// - number: 8080 +// - number: 8081 +// phase: AUTHN +// priority: 1000 +// lua: +// inlineCode: | +// function envoy_on_request(request_handle) +// local domain = "foo.com" +// local headers = request_handle:headers() +// local host = headers:get(":authority") +// local existing_auth_header = headers:get("Authorization") +// if (domain ~= nil and host ~= nil and existing_auth_header == nil and domain == host) then +// local bearer_token = headers:get("cookie"):match("foo") +// if (bearer_token ~= nil) then +// headers:add("Authorization", "Bearer " .. bearer_token) +// end +// end +// end +// ``` +// +// Waypoint with Lua filter for header count logging: +// +// ```yaml +// apiVersion: extensions.istio.io/v1alpha1 +// kind: ExtensionFilter +// metadata: +// name: reviews-header-logger +// namespace: default +// spec: +// targetRefs: +// - kind: Service +// name: reviews +// match: +// - mode: SERVER +// phase: STATS +// lua: +// inlineCode: | +// function envoy_on_request(request_handle) +// local headers = request_handle:headers() +// local num_headers = 0 +// for key, value in pairs(headers) do +// num_headers = num_headers + 1 +// end +// request_handle:logInfo("Request to reviews service has " .. num_headers .. " headers") +// end +// ``` + +package v1alpha1 + +import ( + _struct "github.com/golang/protobuf/ptypes/struct" + wrappers "github.com/golang/protobuf/ptypes/wrappers" + _ "google.golang.org/genproto/googleapis/api/annotations" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + v1beta1 "istio.io/api/type/v1beta1" + reflect "reflect" + sync "sync" + unsafe "unsafe" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// +// +// +// +kubebuilder:validation:XValidation:message="only one of targetRefs or selector can be set",rule="(has(self.selector)?1:0)+(has(self.targetRef)?1:0)+(has(self.targetRefs)?1:0)<=1" +// +kubebuilder:validation:XValidation:message="exactly one of wasm or lua must be set",rule="has(self.wasm) != has(self.lua)" +type ExtensionFilter struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Criteria used to select the specific set of pods/VMs on which + // this plugin configuration should be applied. If omitted, this + // configuration will be applied to all workload instances in the same + // namespace. If the `ExtensionFilter` is present in the config root + // namespace, it will be applied to all applicable workloads in any + // namespace. + // + // At most, only one of `selector` or `targetRefs` can be set for a given policy. + Selector *v1beta1.WorkloadSelector `protobuf:"bytes,1,opt,name=selector,proto3" json:"selector,omitempty"` + // Optional. The targetRef specifies the gateway the policy should be + // applied to. The targeted resource specified will determine which + // workloads the extension filter applies to. The targeted resource + // must be a resource in the same namespace as the ExtensionFilter. + // + // If the targeted resource is a Gateway, the extension filter will be + // applied to all pods that match the targeted Gateway. If the targeted + // resource is a Service, the extension filter will be applied to all pods + // that match the service selector. + // + // If not set, the extension filter is applied to all workloads in the same + // namespace as the ExtensionFilter resource. + // + // At most one of `selector` or `targetRefs` can be set for a given policy. + // + // NOTE: If you are using the `targetRefs` field in "WAYPOINT" mode, you + // should either set a single `targetRef` or set multiple `targetRefs` (using + // the `targetRefs` field). You should not set both the `targetRef` and + // `targetRefs` fields at the same time as it is invalid. + // + // +kubebuilder:validation:XValidation:message="targetRef namespace must be unset",rule="!has(self.__namespace__)" + // + // Deprecated: Marked as deprecated in extensions/v1alpha1/extension_filter.proto. + TargetRef *v1beta1.PolicyTargetReference `protobuf:"bytes,2,opt,name=targetRef,proto3" json:"targetRef,omitempty"` + // Optional. The targetRefs specifies a list of resources the policy should be + // applied to. The targeted resources specified will determine which workloads + // the policy applies to. + // + // Currently, the following resource attachment types are supported: + // * `kind: Gateway` with `group: gateway.networking.k8s.io` in the same namespace. + // * `kind: GatewayClass` with `group: gateway.networking.k8s.io` in the root namespace. + // * `kind: Service` with `group: ""` or `group: "core"` in the same namespace. This type is only supported for waypoints. + // * `kind: ServiceEntry` with `group: networking.istio.io` in the same namespace. + // + // If not set, the policy is applied as defined by the selector. + // At most one of the selector and targetRefs can be set. + // + // NOTE: If you are using the `targetRefs` field in a multi-revision environment with Istio versions prior to 1.22, + // it is highly recommended that you pin the policy to a revision running 1.22+ via the `istio.io/rev` label. + // This is to prevent proxies connected to older control planes (that don't know about the `targetRefs` field) + // from misinterpreting the policy as namespace-wide during the upgrade process. + // + // NOTE: Waypoint proxies are required to use this field for policies to apply; `selector` policies will be ignored. + // +kubebuilder:validation:MaxItems=16 + TargetRefs []*v1beta1.PolicyTargetReference `protobuf:"bytes,3,rep,name=targetRefs,proto3" json:"targetRefs,omitempty"` + // Determines where in the filter chain this `ExtensionFilter` is to be injected. + Phase PluginPhase `protobuf:"varint,4,opt,name=phase,proto3,enum=istio.extensions.v1alpha1.PluginPhase" json:"phase,omitempty"` + // Determines ordering of `ExtensionFilters` in the same `phase`. + // When multiple `ExtensionFilters` are applied to the same workload in the + // same `phase`, they will be applied by priority, in descending order. + // If `priority` is not set, or two `ExtensionFilters` exist with the same + // value, the ordering will be deterministically derived from name and + // namespace of the `ExtensionFilters`. Defaults to `0`. + Priority *wrappers.Int32Value `protobuf:"bytes,5,opt,name=priority,proto3" json:"priority,omitempty"` + // Specifies the criteria to determine which traffic is passed to ExtensionFilter. + // If a traffic satisfies any of TrafficSelectors, + // the traffic passes the ExtensionFilter. + Match []*TrafficSelector `protobuf:"bytes,6,rep,name=match,proto3" json:"match,omitempty"` + // WebAssembly filter configuration. Mutually exclusive with `lua`. + Wasm *WasmConfig `protobuf:"bytes,10,opt,name=wasm,proto3" json:"wasm,omitempty"` + // Lua filter configuration. Mutually exclusive with `wasm`. + Lua *LuaConfig `protobuf:"bytes,11,opt,name=lua,proto3" json:"lua,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ExtensionFilter) Reset() { + *x = ExtensionFilter{} + mi := &file_extensions_v1alpha1_extension_filter_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ExtensionFilter) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ExtensionFilter) ProtoMessage() {} + +func (x *ExtensionFilter) ProtoReflect() protoreflect.Message { + mi := &file_extensions_v1alpha1_extension_filter_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ExtensionFilter.ProtoReflect.Descriptor instead. +func (*ExtensionFilter) Descriptor() ([]byte, []int) { + return file_extensions_v1alpha1_extension_filter_proto_rawDescGZIP(), []int{0} +} + +func (x *ExtensionFilter) GetSelector() *v1beta1.WorkloadSelector { + if x != nil { + return x.Selector + } + return nil +} + +// Deprecated: Marked as deprecated in extensions/v1alpha1/extension_filter.proto. +func (x *ExtensionFilter) GetTargetRef() *v1beta1.PolicyTargetReference { + if x != nil { + return x.TargetRef + } + return nil +} + +func (x *ExtensionFilter) GetTargetRefs() []*v1beta1.PolicyTargetReference { + if x != nil { + return x.TargetRefs + } + return nil +} + +func (x *ExtensionFilter) GetPhase() PluginPhase { + if x != nil { + return x.Phase + } + return PluginPhase_UNSPECIFIED_PHASE +} + +func (x *ExtensionFilter) GetPriority() *wrappers.Int32Value { + if x != nil { + return x.Priority + } + return nil +} + +func (x *ExtensionFilter) GetMatch() []*TrafficSelector { + if x != nil { + return x.Match + } + return nil +} + +func (x *ExtensionFilter) GetWasm() *WasmConfig { + if x != nil { + return x.Wasm + } + return nil +} + +func (x *ExtensionFilter) GetLua() *LuaConfig { + if x != nil { + return x.Lua + } + return nil +} + +// WasmConfig configures a WebAssembly filter. +// +// Example: +// +// ```yaml +// wasm: +// +// url: oci://gcr.io/myproject/filter:v1.0.0 +// sha256: abc123... +// imagePullPolicy: IfNotPresent +// imagePullSecret: gcr-secret +// pluginName: my-filter +// pluginConfig: +// key1: value1 +// key2: value2 +// failStrategy: FAIL_CLOSE +// vmConfig: +// env: +// - name: SOME_ENV_VAR +// value: some_value +// type: HTTP +// +// ``` +type WasmConfig struct { + state protoimpl.MessageState `protogen:"open.v1"` + // URL of a Wasm module or OCI container. If no scheme is present, + // defaults to `oci://`, referencing an OCI image. Other valid schemes + // are `file://` for referencing .wasm module files present locally + // within the proxy container, and `http[s]://` for .wasm module files + // hosted remotely. + // + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:XValidation:message="url must have schema one of [http, https, file, oci]",rule="isURL(self) ? (url(self).getScheme() in [”, 'http', 'https', 'file', 'oci']) : (isURL('http://' + self) && url('http://' + self).getScheme() in [”, 'http', 'https', 'file', 'oci'])" + Url string `protobuf:"bytes,1,opt,name=url,proto3" json:"url,omitempty"` + // SHA256 checksum that will be used to verify Wasm module or OCI container. + // If the `url` field already references a SHA256 (using the `@sha256:` + // notation), it must match the value of this field. If an OCI image is + // referenced by tag and this field is set, its checksum will be verified + // against the contents of this field after pulling. + // +kubebuilder:validation:Pattern="(^$|^[a-f0-9]{64}$)" + Sha256 string `protobuf:"bytes,2,opt,name=sha256,proto3" json:"sha256,omitempty"` + // The pull behaviour to be applied when fetching Wasm module by either + // OCI image or `http/https`. Only relevant when referencing Wasm module without + // any digest, including the digest in OCI image URL or `sha256` field in `vm_config`. + // Defaults to `IfNotPresent`, except when an OCI image is referenced in the `url` + // and the `latest` tag is used, in which case `Always` is the default, + // mirroring Kubernetes behaviour. + ImagePullPolicy PullPolicy `protobuf:"varint,3,opt,name=image_pull_policy,json=imagePullPolicy,proto3,enum=istio.extensions.v1alpha1.PullPolicy" json:"image_pull_policy,omitempty"` + // Credentials to use for OCI image pulling. + // Name of a Kubernetes Secret in the same namespace as the `ExtensionFilter` that + // contains a Docker pull secret which is to be used to authenticate + // against the registry when pulling the image. + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=253 + ImagePullSecret string `protobuf:"bytes,4,opt,name=image_pull_secret,json=imagePullSecret,proto3" json:"image_pull_secret,omitempty"` + // $hide_from_docs + // Public key that will be used to verify signatures of signed OCI images + // or Wasm modules. + // + // At this moment, various ways for signing/verifying are emerging and being proposed. + // We can observe two major streams for signing OCI images: Cosign from Sigstore and Notary, + // which is used in Docker Content Trust. + // In case of Wasm module, multiple approaches are still in discussion. + // - https://github.com/WebAssembly/design/issues/1413 + // - https://github.com/wasm-signatures/design (various signing tools are enumerated) + // + // In addition, for each method for signing&verifying, we may need to consider to provide + // additional data or configuration (e.g., key rolling, KMS, root certs, ...) as well. + // + // To deal with this situation, we need to elaborate more generic way to describe + // how to sign and verify the image or wasm binary, and how to specify relevant data, + // including this `verification_key`. + // + // Therefore, this field will not be implemented until the detailed design is established. + // For the future use, just keep this field in proto and hide from documentation. + VerificationKey string `protobuf:"bytes,5,opt,name=verification_key,json=verificationKey,proto3" json:"verification_key,omitempty"` + // The configuration that will be passed on to the plugin. + PluginConfig *_struct.Struct `protobuf:"bytes,6,opt,name=plugin_config,json=pluginConfig,proto3" json:"plugin_config,omitempty"` + // The plugin name to be used in the Envoy configuration (used to be called + // `rootID`). Some .wasm modules might require this value to select the Wasm + // plugin to execute. + // +kubebuilder:validation:MaxLength=256 + // +kubebuilder:validation:MinLength=1 + PluginName string `protobuf:"bytes,7,opt,name=plugin_name,json=pluginName,proto3" json:"plugin_name,omitempty"` + // Specifies the failure behavior for the plugin due to fatal errors. + FailStrategy FailStrategy `protobuf:"varint,8,opt,name=fail_strategy,json=failStrategy,proto3,enum=istio.extensions.v1alpha1.FailStrategy" json:"fail_strategy,omitempty"` + // Configuration for a Wasm VM. + // More details can be found [here](https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/wasm/v3/wasm.proto#extensions-wasm-v3-vmconfig). + VmConfig *VmConfig `protobuf:"bytes,9,opt,name=vm_config,json=vmConfig,proto3" json:"vm_config,omitempty"` + // Specifies the type of Wasm Extension to be used. + Type PluginType `protobuf:"varint,10,opt,name=type,proto3,enum=istio.extensions.v1alpha1.PluginType" json:"type,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *WasmConfig) Reset() { + *x = WasmConfig{} + mi := &file_extensions_v1alpha1_extension_filter_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *WasmConfig) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*WasmConfig) ProtoMessage() {} + +func (x *WasmConfig) ProtoReflect() protoreflect.Message { + mi := &file_extensions_v1alpha1_extension_filter_proto_msgTypes[1] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use WasmConfig.ProtoReflect.Descriptor instead. +func (*WasmConfig) Descriptor() ([]byte, []int) { + return file_extensions_v1alpha1_extension_filter_proto_rawDescGZIP(), []int{1} +} + +func (x *WasmConfig) GetUrl() string { + if x != nil { + return x.Url + } + return "" +} + +func (x *WasmConfig) GetSha256() string { + if x != nil { + return x.Sha256 + } + return "" +} + +func (x *WasmConfig) GetImagePullPolicy() PullPolicy { + if x != nil { + return x.ImagePullPolicy + } + return PullPolicy_UNSPECIFIED_POLICY +} + +func (x *WasmConfig) GetImagePullSecret() string { + if x != nil { + return x.ImagePullSecret + } + return "" +} + +func (x *WasmConfig) GetVerificationKey() string { + if x != nil { + return x.VerificationKey + } + return "" +} + +func (x *WasmConfig) GetPluginConfig() *_struct.Struct { + if x != nil { + return x.PluginConfig + } + return nil +} + +func (x *WasmConfig) GetPluginName() string { + if x != nil { + return x.PluginName + } + return "" +} + +func (x *WasmConfig) GetFailStrategy() FailStrategy { + if x != nil { + return x.FailStrategy + } + return FailStrategy_FAIL_CLOSE +} + +func (x *WasmConfig) GetVmConfig() *VmConfig { + if x != nil { + return x.VmConfig + } + return nil +} + +func (x *WasmConfig) GetType() PluginType { + if x != nil { + return x.Type + } + return PluginType_UNSPECIFIED_PLUGIN_TYPE +} + +// LuaConfig configures a Lua filter. +// +// Lua filters provide a lightweight alternative to WebAssembly for simple +// request/response transformations. The Lua code is executed inline within +// the Envoy proxy. +// +// Example: Simple header manipulation +// +// ```yaml +// lua: +// +// inlineCode: | +// function envoy_on_request(request_handle) +// request_handle:headers():add("x-custom-header", "custom-value") +// end +// +// ``` +// +// The Lua script must define one or both of the following functions: +// - `envoy_on_request(request_handle)`: Called when a request is received +// - `envoy_on_response(response_handle)`: Called when a response is received +// +// The request_handle and response_handle provide access to headers, body, +// metadata, and other request/response attributes. See the Envoy Lua filter +// documentation for the complete API: +// https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/lua_filter +type LuaConfig struct { + state protoimpl.MessageState `protogen:"open.v1"` + // The inline Lua code to be executed. The code must be a valid Lua script + // that defines the appropriate callback functions (`envoy_on_request` and/or + // `envoy_on_response`). + // + // The maximum size is 64KB. For larger or more complex filters, use a + // WebAssembly filter instead. + // + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=65536 + InlineCode string `protobuf:"bytes,1,opt,name=inline_code,json=inlineCode,proto3" json:"inline_code,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *LuaConfig) Reset() { + *x = LuaConfig{} + mi := &file_extensions_v1alpha1_extension_filter_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *LuaConfig) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LuaConfig) ProtoMessage() {} + +func (x *LuaConfig) ProtoReflect() protoreflect.Message { + mi := &file_extensions_v1alpha1_extension_filter_proto_msgTypes[2] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use LuaConfig.ProtoReflect.Descriptor instead. +func (*LuaConfig) Descriptor() ([]byte, []int) { + return file_extensions_v1alpha1_extension_filter_proto_rawDescGZIP(), []int{2} +} + +func (x *LuaConfig) GetInlineCode() string { + if x != nil { + return x.InlineCode + } + return "" +} + +// TrafficSelector provides a mechanism to select a specific traffic flow +// for which this Extension Filter will be enabled. +// When all the sub conditions in the TrafficSelector are satisfied, the +// traffic will be selected. +type TrafficSelector struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Criteria for selecting traffic by their direction. + // Note that `CLIENT` and `SERVER` are analogous to OUTBOUND and INBOUND, + // respectively. + // For the gateway, the field should be `CLIENT` or `CLIENT_AND_SERVER`. + // If not specified, the default value is `CLIENT_AND_SERVER`. + Mode v1beta1.WorkloadMode `protobuf:"varint,1,opt,name=mode,proto3,enum=istio.type.v1beta1.WorkloadMode" json:"mode,omitempty"` + // Criteria for selecting traffic by their destination port. + // More specifically, for the outbound traffic, the destination port would be + // the port of the target service. On the other hand, for the inbound traffic, + // the destination port is the port bound by the server process in the same Pod. + // + // If one of the given `ports` is matched, this condition is evaluated to true. + // If not specified, this condition is evaluated to true for any port. + // +listType=map + // +listMapKey=number + Ports []*v1beta1.PortSelector `protobuf:"bytes,2,rep,name=ports,proto3" json:"ports,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *TrafficSelector) Reset() { + *x = TrafficSelector{} + mi := &file_extensions_v1alpha1_extension_filter_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *TrafficSelector) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TrafficSelector) ProtoMessage() {} + +func (x *TrafficSelector) ProtoReflect() protoreflect.Message { + mi := &file_extensions_v1alpha1_extension_filter_proto_msgTypes[3] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TrafficSelector.ProtoReflect.Descriptor instead. +func (*TrafficSelector) Descriptor() ([]byte, []int) { + return file_extensions_v1alpha1_extension_filter_proto_rawDescGZIP(), []int{3} +} + +func (x *TrafficSelector) GetMode() v1beta1.WorkloadMode { + if x != nil { + return x.Mode + } + return v1beta1.WorkloadMode(0) +} + +func (x *TrafficSelector) GetPorts() []*v1beta1.PortSelector { + if x != nil { + return x.Ports + } + return nil +} + +var File_extensions_v1alpha1_extension_filter_proto protoreflect.FileDescriptor + +const file_extensions_v1alpha1_extension_filter_proto_rawDesc = "" + + "\n" + + "*extensions/v1alpha1/extension_filter.proto\x12\x19istio.extensions.v1alpha1\x1a\x1eextensions/v1alpha1/wasm.proto\x1a\x1fgoogle/api/field_behavior.proto\x1a\x1cgoogle/protobuf/struct.proto\x1a\x1egoogle/protobuf/wrappers.proto\x1a\x1btype/v1beta1/selector.proto\"\x97\x04\n" + + "\x0fExtensionFilter\x12@\n" + + "\bselector\x18\x01 \x01(\v2$.istio.type.v1beta1.WorkloadSelectorR\bselector\x12K\n" + + "\ttargetRef\x18\x02 \x01(\v2).istio.type.v1beta1.PolicyTargetReferenceB\x02\x18\x01R\ttargetRef\x12I\n" + + "\n" + + "targetRefs\x18\x03 \x03(\v2).istio.type.v1beta1.PolicyTargetReferenceR\n" + + "targetRefs\x12<\n" + + "\x05phase\x18\x04 \x01(\x0e2&.istio.extensions.v1alpha1.PluginPhaseR\x05phase\x127\n" + + "\bpriority\x18\x05 \x01(\v2\x1b.google.protobuf.Int32ValueR\bpriority\x12@\n" + + "\x05match\x18\x06 \x03(\v2*.istio.extensions.v1alpha1.TrafficSelectorR\x05match\x129\n" + + "\x04wasm\x18\n" + + " \x01(\v2%.istio.extensions.v1alpha1.WasmConfigR\x04wasm\x126\n" + + "\x03lua\x18\v \x01(\v2$.istio.extensions.v1alpha1.LuaConfigR\x03lua\"\x90\x04\n" + + "\n" + + "WasmConfig\x12\x16\n" + + "\x03url\x18\x01 \x01(\tB\x04\xe2A\x01\x02R\x03url\x12\x16\n" + + "\x06sha256\x18\x02 \x01(\tR\x06sha256\x12Q\n" + + "\x11image_pull_policy\x18\x03 \x01(\x0e2%.istio.extensions.v1alpha1.PullPolicyR\x0fimagePullPolicy\x12*\n" + + "\x11image_pull_secret\x18\x04 \x01(\tR\x0fimagePullSecret\x12)\n" + + "\x10verification_key\x18\x05 \x01(\tR\x0fverificationKey\x12<\n" + + "\rplugin_config\x18\x06 \x01(\v2\x17.google.protobuf.StructR\fpluginConfig\x12\x1f\n" + + "\vplugin_name\x18\a \x01(\tR\n" + + "pluginName\x12L\n" + + "\rfail_strategy\x18\b \x01(\x0e2'.istio.extensions.v1alpha1.FailStrategyR\ffailStrategy\x12@\n" + + "\tvm_config\x18\t \x01(\v2#.istio.extensions.v1alpha1.VmConfigR\bvmConfig\x129\n" + + "\x04type\x18\n" + + " \x01(\x0e2%.istio.extensions.v1alpha1.PluginTypeR\x04type\"2\n" + + "\tLuaConfig\x12%\n" + + "\vinline_code\x18\x01 \x01(\tB\x04\xe2A\x01\x02R\n" + + "inlineCode\"\x7f\n" + + "\x0fTrafficSelector\x124\n" + + "\x04mode\x18\x01 \x01(\x0e2 .istio.type.v1beta1.WorkloadModeR\x04mode\x126\n" + + "\x05ports\x18\x02 \x03(\v2 .istio.type.v1beta1.PortSelectorR\x05portsB\"Z istio.io/api/extensions/v1alpha1b\x06proto3" + +var ( + file_extensions_v1alpha1_extension_filter_proto_rawDescOnce sync.Once + file_extensions_v1alpha1_extension_filter_proto_rawDescData []byte +) + +func file_extensions_v1alpha1_extension_filter_proto_rawDescGZIP() []byte { + file_extensions_v1alpha1_extension_filter_proto_rawDescOnce.Do(func() { + file_extensions_v1alpha1_extension_filter_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_extensions_v1alpha1_extension_filter_proto_rawDesc), len(file_extensions_v1alpha1_extension_filter_proto_rawDesc))) + }) + return file_extensions_v1alpha1_extension_filter_proto_rawDescData +} + +var file_extensions_v1alpha1_extension_filter_proto_msgTypes = make([]protoimpl.MessageInfo, 4) +var file_extensions_v1alpha1_extension_filter_proto_goTypes = []any{ + (*ExtensionFilter)(nil), // 0: istio.extensions.v1alpha1.ExtensionFilter + (*WasmConfig)(nil), // 1: istio.extensions.v1alpha1.WasmConfig + (*LuaConfig)(nil), // 2: istio.extensions.v1alpha1.LuaConfig + (*TrafficSelector)(nil), // 3: istio.extensions.v1alpha1.TrafficSelector + (*v1beta1.WorkloadSelector)(nil), // 4: istio.type.v1beta1.WorkloadSelector + (*v1beta1.PolicyTargetReference)(nil), // 5: istio.type.v1beta1.PolicyTargetReference + (PluginPhase)(0), // 6: istio.extensions.v1alpha1.PluginPhase + (*wrappers.Int32Value)(nil), // 7: google.protobuf.Int32Value + (PullPolicy)(0), // 8: istio.extensions.v1alpha1.PullPolicy + (*_struct.Struct)(nil), // 9: google.protobuf.Struct + (FailStrategy)(0), // 10: istio.extensions.v1alpha1.FailStrategy + (*VmConfig)(nil), // 11: istio.extensions.v1alpha1.VmConfig + (PluginType)(0), // 12: istio.extensions.v1alpha1.PluginType + (v1beta1.WorkloadMode)(0), // 13: istio.type.v1beta1.WorkloadMode + (*v1beta1.PortSelector)(nil), // 14: istio.type.v1beta1.PortSelector +} +var file_extensions_v1alpha1_extension_filter_proto_depIdxs = []int32{ + 4, // 0: istio.extensions.v1alpha1.ExtensionFilter.selector:type_name -> istio.type.v1beta1.WorkloadSelector + 5, // 1: istio.extensions.v1alpha1.ExtensionFilter.targetRef:type_name -> istio.type.v1beta1.PolicyTargetReference + 5, // 2: istio.extensions.v1alpha1.ExtensionFilter.targetRefs:type_name -> istio.type.v1beta1.PolicyTargetReference + 6, // 3: istio.extensions.v1alpha1.ExtensionFilter.phase:type_name -> istio.extensions.v1alpha1.PluginPhase + 7, // 4: istio.extensions.v1alpha1.ExtensionFilter.priority:type_name -> google.protobuf.Int32Value + 3, // 5: istio.extensions.v1alpha1.ExtensionFilter.match:type_name -> istio.extensions.v1alpha1.TrafficSelector + 1, // 6: istio.extensions.v1alpha1.ExtensionFilter.wasm:type_name -> istio.extensions.v1alpha1.WasmConfig + 2, // 7: istio.extensions.v1alpha1.ExtensionFilter.lua:type_name -> istio.extensions.v1alpha1.LuaConfig + 8, // 8: istio.extensions.v1alpha1.WasmConfig.image_pull_policy:type_name -> istio.extensions.v1alpha1.PullPolicy + 9, // 9: istio.extensions.v1alpha1.WasmConfig.plugin_config:type_name -> google.protobuf.Struct + 10, // 10: istio.extensions.v1alpha1.WasmConfig.fail_strategy:type_name -> istio.extensions.v1alpha1.FailStrategy + 11, // 11: istio.extensions.v1alpha1.WasmConfig.vm_config:type_name -> istio.extensions.v1alpha1.VmConfig + 12, // 12: istio.extensions.v1alpha1.WasmConfig.type:type_name -> istio.extensions.v1alpha1.PluginType + 13, // 13: istio.extensions.v1alpha1.TrafficSelector.mode:type_name -> istio.type.v1beta1.WorkloadMode + 14, // 14: istio.extensions.v1alpha1.TrafficSelector.ports:type_name -> istio.type.v1beta1.PortSelector + 15, // [15:15] is the sub-list for method output_type + 15, // [15:15] is the sub-list for method input_type + 15, // [15:15] is the sub-list for extension type_name + 15, // [15:15] is the sub-list for extension extendee + 0, // [0:15] is the sub-list for field type_name +} + +func init() { file_extensions_v1alpha1_extension_filter_proto_init() } +func file_extensions_v1alpha1_extension_filter_proto_init() { + if File_extensions_v1alpha1_extension_filter_proto != nil { + return + } + file_extensions_v1alpha1_wasm_proto_init() + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_extensions_v1alpha1_extension_filter_proto_rawDesc), len(file_extensions_v1alpha1_extension_filter_proto_rawDesc)), + NumEnums: 0, + NumMessages: 4, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_extensions_v1alpha1_extension_filter_proto_goTypes, + DependencyIndexes: file_extensions_v1alpha1_extension_filter_proto_depIdxs, + MessageInfos: file_extensions_v1alpha1_extension_filter_proto_msgTypes, + }.Build() + File_extensions_v1alpha1_extension_filter_proto = out.File + file_extensions_v1alpha1_extension_filter_proto_goTypes = nil + file_extensions_v1alpha1_extension_filter_proto_depIdxs = nil +} diff --git a/extensions/v1alpha1/extension_filter.pb.html b/extensions/v1alpha1/extension_filter.pb.html new file mode 100644 index 0000000000..2f5f646148 --- /dev/null +++ b/extensions/v1alpha1/extension_filter.pb.html @@ -0,0 +1,592 @@ +--- +title: Extension Filter +description: Extend the functionality provided by the Istio proxy through WebAssembly or Lua filters. +location: https://istio.io/docs/reference/config/proxy_extensions/v1alpha1/extension_filter.html +layout: protoc-gen-docs +generator: protoc-gen-docs +schema: istio.extensions.v1alpha1.ExtensionFilter +aliases: [/docs/reference/config/extensions/v1alpha1/extension_filter] +number_of_entries: 4 +--- +

ExtensionFilter provides a mechanism to extend the functionality provided by +the Istio proxy through WebAssembly or Lua filters.

+

This API supersedes WasmPlugin by providing a unified mechanism for configuring +multiple extension types (WebAssembly and Lua) while maintaining consistent +targeting and configuration patterns.

+

The order of execution (as part of Envoy’s filter chain) is determined by +phase and priority settings, allowing the configuration of complex +interactions between user-supplied WebAssembly or Lua and Istio’s internal +filters.

+

Examples:

+

AuthN Filter deployed to ingress-gateway that implements an OpenID flow +and populates the Authorization header with a JWT to be consumed by +Istio AuthN.

+
apiVersion: extensions.istio.io/v1alpha1
+kind: ExtensionFilter
+metadata:
+  name: openid-connect
+  namespace: istio-ingress
+spec:
+  selector:
+    matchLabels:
+      istio: ingressgateway
+  phase: AUTHN
+  wasm:
+    url: file:///opt/filters/openid.wasm
+    sha256: 1ef0c9a92b0420cf25f7fe5d481b231464bc88f486ca3b9c83ed5cc21d2f6210
+    pluginConfig:
+      openid_server: authn
+      openid_realm: ingress
+
+

This is the same as the last example, but using an OCI image.

+
apiVersion: extensions.istio.io/v1alpha1
+kind: ExtensionFilter
+metadata:
+  name: openid-connect
+  namespace: istio-ingress
+spec:
+  selector:
+    matchLabels:
+      istio: ingressgateway
+  phase: AUTHN
+  wasm:
+    url: oci://private-registry:5000/openid-connect/openid:latest
+    imagePullPolicy: IfNotPresent
+    imagePullSecret: private-registry-pull-secret
+    pluginConfig:
+      openid_server: authn
+      openid_realm: ingress
+
+

This is the same as the last example, but using VmConfig to configure environment variables in the VM.

+
apiVersion: extensions.istio.io/v1alpha1
+kind: ExtensionFilter
+metadata:
+  name: openid-connect
+  namespace: istio-ingress
+spec:
+  selector:
+    matchLabels:
+      istio: ingressgateway
+  phase: AUTHN
+  wasm:
+    url: oci://private-registry:5000/openid-connect/openid:latest
+    imagePullPolicy: IfNotPresent
+    imagePullSecret: private-registry-pull-secret
+    pluginConfig:
+      openid_server: authn
+      openid_realm: ingress
+    vmConfig:
+      env:
+      - name: POD_NAME
+        valueFrom: HOST
+      - name: TRUST_DOMAIN
+        value: "cluster.local"
+
+

This is also the same as the last example, but the Wasm module is pulled via https and updated for each time when this plugin resource is changed.

+
apiVersion: extensions.istio.io/v1alpha1
+kind: ExtensionFilter
+metadata:
+  name: openid-connect
+  namespace: istio-ingress
+spec:
+  selector:
+    matchLabels:
+      istio: ingressgateway
+  phase: AUTHN
+  wasm:
+    url: https://private-bucket/filters/openid.wasm
+    imagePullPolicy: Always
+    pluginConfig:
+      openid_server: authn
+      openid_realm: ingress
+    vmConfig:
+      env:
+      - name: POD_NAME
+        valueFrom: HOST
+      - name: TRUST_DOMAIN
+        value: "cluster.local"
+
+

And a more complex example that deploys three ExtensionFilters and orders them +using phase and priority. The (hypothetical) setup is that the +openid-connect filter performs an OpenID Connect flow to authenticate the +user, writing a signed JWT into the Authorization header of the request, +which can be verified by the Istio authn plugin. Then, the acl-check plugin +kicks in, passing the JWT to a policy server, which in turn responds with a +signed token that contains information about which files and functions of the +system are available to the user that was previously authenticated. The +acl-check filter writes this token to a header. Finally, the check-header +filter verifies the token in that header and makes sure that the token’s +contents (the permitted ‘function’) matches its plugin configuration.

+

The resulting filter chain looks like this: +-> openid-connect -> istio.authn -> acl-check -> check-header -> router

+
apiVersion: extensions.istio.io/v1alpha1
+kind: ExtensionFilter
+metadata:
+  name: openid-connect
+  namespace: istio-ingress
+spec:
+  selector:
+    matchLabels:
+      istio: ingressgateway
+  phase: AUTHN
+  wasm:
+    url: oci://private-registry:5000/openid-connect/openid:latest
+    imagePullPolicy: IfNotPresent
+    imagePullSecret: private-registry-pull-secret
+    pluginConfig:
+      openid_server: authn
+      openid_realm: ingress
+
+
apiVersion: extensions.istio.io/v1alpha1
+kind: ExtensionFilter
+metadata:
+  name: acl-check
+  namespace: istio-ingress
+spec:
+  selector:
+    matchLabels:
+      istio: ingressgateway
+  phase: AUTHZ
+  priority: 1000
+  wasm:
+    url: oci://private-registry:5000/acl-check/acl:latest
+    imagePullPolicy: Always
+    imagePullSecret: private-registry-pull-secret
+    pluginConfig:
+      acl_server: some_server
+      set_header: authz_complete
+
+
apiVersion: extensions.istio.io/v1alpha1
+kind: ExtensionFilter
+metadata:
+  name: check-header
+  namespace: istio-ingress
+spec:
+  selector:
+    matchLabels:
+      istio: ingressgateway
+  phase: AUTHZ
+  priority: 10
+  wasm:
+    url: oci://private-registry:5000/check-header:latest
+    imagePullPolicy: IfNotPresent
+    imagePullSecret: private-registry-pull-secret
+    pluginConfig:
+      read_header: authz_complete
+      verification_key: a89gAzxvls0JKAKIJSBnnvvvkIO
+      function: read_data
+
+

Gateway with Lua filter for conditional header modification:

+
apiVersion: extensions.istio.io/v1alpha1
+kind: ExtensionFilter
+metadata:
+  name: conditional-header-modifier
+  namespace: istio-ingress
+spec:
+  selector:
+    matchLabels:
+      istio: ingressgateway
+  match:
+  - mode: CLIENT
+    ports:
+    - number: 8080
+    - number: 8081
+  phase: AUTHN
+  priority: 1000
+  lua:
+    inlineCode: |
+      function envoy_on_request(request_handle)
+        local domain = "foo.com"
+        local headers = request_handle:headers()
+        local host = headers:get(":authority")
+        local existing_auth_header = headers:get("Authorization")
+        if (domain ~= nil and host ~= nil and existing_auth_header == nil and domain == host) then
+          local bearer_token = headers:get("cookie"):match("foo")
+          if (bearer_token ~= nil) then
+            headers:add("Authorization", "Bearer " .. bearer_token)
+          end
+        end
+      end
+
+

Waypoint with Lua filter for header count logging:

+
apiVersion: extensions.istio.io/v1alpha1
+kind: ExtensionFilter
+metadata:
+  name: reviews-header-logger
+  namespace: default
+spec:
+  targetRefs:
+  - kind: Service
+    name: reviews
+  match:
+  - mode: SERVER
+  phase: STATS
+  lua:
+    inlineCode: |
+      function envoy_on_request(request_handle)
+        local headers = request_handle:headers()
+        local num_headers = 0
+        for key, value in pairs(headers) do
+          num_headers = num_headers + 1
+        end
+        request_handle:logInfo("Request to reviews service has " .. num_headers .. " headers")
+      end
+
+ +

ExtensionFilter

+
+

+kubebuilder:validation:XValidation:message=“only one of targetRefs or selector can be set”,rule="(has(self.selector)?1:0)+(has(self.targetRef)?1:0)+(has(self.targetRefs)?1:0)<=1" ++kubebuilder:validation:XValidation:message=“exactly one of wasm or lua must be set”,rule=“has(self.wasm) != has(self.lua)”

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldDescription
+

Criteria used to select the specific set of pods/VMs on which +this plugin configuration should be applied. If omitted, this +configuration will be applied to all workload instances in the same +namespace. If the ExtensionFilter is present in the config root +namespace, it will be applied to all applicable workloads in any +namespace.

+

At most, only one of selector or targetRefs can be set for a given policy.

+ +
+

The targetRefs specifies a list of resources the policy should be +applied to. The targeted resources specified will determine which workloads +the policy applies to.

+

Currently, the following resource attachment types are supported:

+
    +
  • kind: Gateway with group: gateway.networking.k8s.io in the same namespace.
  • +
  • kind: GatewayClass with group: gateway.networking.k8s.io in the root namespace.
  • +
  • kind: Service with group: "" or group: "core" in the same namespace. This type is only supported for waypoints.
  • +
  • kind: ServiceEntry with group: networking.istio.io in the same namespace.
  • +
+

If not set, the policy is applied as defined by the selector. +At most one of the selector and targetRefs can be set.

+

NOTE: If you are using the targetRefs field in a multi-revision environment with Istio versions prior to 1.22, +it is highly recommended that you pin the policy to a revision running 1.22+ via the istio.io/rev label. +This is to prevent proxies connected to older control planes (that don’t know about the targetRefs field) +from misinterpreting the policy as namespace-wide during the upgrade process.

+

NOTE: Waypoint proxies are required to use this field for policies to apply; selector policies will be ignored.

+ +
+

Determines where in the filter chain this ExtensionFilter is to be injected.

+ +
+

Determines ordering of ExtensionFilters in the same phase. +When multiple ExtensionFilters are applied to the same workload in the +same phase, they will be applied by priority, in descending order. +If priority is not set, or two ExtensionFilters exist with the same +value, the ordering will be deterministically derived from name and +namespace of the ExtensionFilters. Defaults to 0.

+ +
+

Specifies the criteria to determine which traffic is passed to ExtensionFilter. +If a traffic satisfies any of TrafficSelectors, +the traffic passes the ExtensionFilter.

+ +
+

WebAssembly filter configuration. Mutually exclusive with lua.

+ +
+

Lua filter configuration. Mutually exclusive with wasm.

+ +
+

The targetRef specifies the gateway the policy should be +applied to. The targeted resource specified will determine which +workloads the extension filter applies to. The targeted resource +must be a resource in the same namespace as the ExtensionFilter.

+

If the targeted resource is a Gateway, the extension filter will be +applied to all pods that match the targeted Gateway. If the targeted +resource is a Service, the extension filter will be applied to all pods +that match the service selector.

+

If not set, the extension filter is applied to all workloads in the same +namespace as the ExtensionFilter resource.

+

At most one of selector or targetRefs can be set for a given policy.

+

NOTE: If you are using the targetRefs field in “WAYPOINT” mode, you +should either set a single targetRef or set multiple targetRefs (using +the targetRefs field). You should not set both the targetRef and +targetRefs fields at the same time as it is invalid.

+ +
+
+

WasmConfig

+
+

WasmConfig configures a WebAssembly filter.

+

Example:

+
wasm:
+  url: oci://gcr.io/myproject/filter:v1.0.0
+  sha256: abc123...
+  imagePullPolicy: IfNotPresent
+  imagePullSecret: gcr-secret
+  pluginName: my-filter
+  pluginConfig:
+    key1: value1
+    key2: value2
+  failStrategy: FAIL_CLOSE
+  vmConfig:
+    env:
+    - name: SOME_ENV_VAR
+      value: some_value
+  type: HTTP
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldDescription
+
string
+
Required
+
+

URL of a Wasm module or OCI container. If no scheme is present, +defaults to oci://, referencing an OCI image. Other valid schemes +are file:// for referencing .wasm module files present locally +within the proxy container, and http[s]:// for .wasm module files +hosted remotely.

+ +
+
string
+
+

SHA256 checksum that will be used to verify Wasm module or OCI container. +If the url field already references a SHA256 (using the @sha256: +notation), it must match the value of this field. If an OCI image is +referenced by tag and this field is set, its checksum will be verified +against the contents of this field after pulling.

+ +
+

The pull behaviour to be applied when fetching Wasm module by either +OCI image or http/https. Only relevant when referencing Wasm module without +any digest, including the digest in OCI image URL or sha256 field in vm_config. +Defaults to IfNotPresent, except when an OCI image is referenced in the url +and the latest tag is used, in which case Always is the default, +mirroring Kubernetes behaviour.

+ +
+
string
+
+

Credentials to use for OCI image pulling. +Name of a Kubernetes Secret in the same namespace as the ExtensionFilter that +contains a Docker pull secret which is to be used to authenticate +against the registry when pulling the image.

+ +
+

The configuration that will be passed on to the plugin.

+ +
+
string
+
+

The plugin name to be used in the Envoy configuration (used to be called +rootID). Some .wasm modules might require this value to select the Wasm +plugin to execute.

+ +
+

Specifies the failure behavior for the plugin due to fatal errors.

+ +
+

Configuration for a Wasm VM. +More details can be found here.

+ +
+

Specifies the type of Wasm Extension to be used.

+ +
+
+

LuaConfig

+
+

LuaConfig configures a Lua filter.

+

Lua filters provide a lightweight alternative to WebAssembly for simple +request/response transformations. The Lua code is executed inline within +the Envoy proxy.

+

Example: Simple header manipulation

+
lua:
+  inlineCode: |
+    function envoy_on_request(request_handle)
+      request_handle:headers():add("x-custom-header", "custom-value")
+    end
+
+

The Lua script must define one or both of the following functions:

+ +

The request_handle and response_handle provide access to headers, body, +metadata, and other request/response attributes. See the Envoy Lua filter +documentation for the complete API: +https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/lua_filter

+ + + + + + + + + + + + + + +
FieldDescription
+
string
+
Required
+
+

The inline Lua code to be executed. The code must be a valid Lua script +that defines the appropriate callback functions (envoy_on_request and/or +envoy_on_response).

+

The maximum size is 64KB. For larger or more complex filters, use a +WebAssembly filter instead.

+ +
+
+

TrafficSelector

+
+

TrafficSelector provides a mechanism to select a specific traffic flow +for which this Extension Filter will be enabled. +When all the sub conditions in the TrafficSelector are satisfied, the +traffic will be selected.

+ + + + + + + + + + + + + + + + + + +
FieldDescription
+

Criteria for selecting traffic by their direction. +Note that CLIENT and SERVER are analogous to OUTBOUND and INBOUND, +respectively. +For the gateway, the field should be CLIENT or CLIENT_AND_SERVER. +If not specified, the default value is CLIENT_AND_SERVER.

+ +
+

Criteria for selecting traffic by their destination port. +More specifically, for the outbound traffic, the destination port would be +the port of the target service. On the other hand, for the inbound traffic, +the destination port is the port bound by the server process in the same Pod.

+

If one of the given ports is matched, this condition is evaluated to true. +If not specified, this condition is evaluated to true for any port.

+ +
+
diff --git a/extensions/v1alpha1/extension_filter.proto b/extensions/v1alpha1/extension_filter.proto new file mode 100644 index 0000000000..1c3bf6ee1c --- /dev/null +++ b/extensions/v1alpha1/extension_filter.proto @@ -0,0 +1,495 @@ +// Copyright Istio Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +// $schema: istio.extensions.v1alpha1.ExtensionFilter +// $title: Extension Filter +// $description: Extend the functionality provided by the Istio proxy through WebAssembly or Lua filters. +// $location: https://istio.io/docs/reference/config/proxy_extensions/v1alpha1/extension_filter.html +// $aliases: [/docs/reference/config/extensions/v1alpha1/extension_filter] + +// ExtensionFilter provides a mechanism to extend the functionality provided by +// the Istio proxy through WebAssembly or Lua filters. +// +// This API supersedes WasmPlugin by providing a unified mechanism for configuring +// multiple extension types (WebAssembly and Lua) while maintaining consistent +// targeting and configuration patterns. +// +// The order of execution (as part of Envoy's filter chain) is determined by +// phase and priority settings, allowing the configuration of complex +// interactions between user-supplied WebAssembly or Lua and Istio's internal +// filters. +// +// Examples: +// +// AuthN Filter deployed to ingress-gateway that implements an OpenID flow +// and populates the `Authorization` header with a JWT to be consumed by +// Istio AuthN. +// +// ```yaml +// apiVersion: extensions.istio.io/v1alpha1 +// kind: ExtensionFilter +// metadata: +// name: openid-connect +// namespace: istio-ingress +// spec: +// selector: +// matchLabels: +// istio: ingressgateway +// phase: AUTHN +// wasm: +// url: file:///opt/filters/openid.wasm +// sha256: 1ef0c9a92b0420cf25f7fe5d481b231464bc88f486ca3b9c83ed5cc21d2f6210 +// pluginConfig: +// openid_server: authn +// openid_realm: ingress +// ``` +// +// This is the same as the last example, but using an OCI image. +// +// ```yaml +// apiVersion: extensions.istio.io/v1alpha1 +// kind: ExtensionFilter +// metadata: +// name: openid-connect +// namespace: istio-ingress +// spec: +// selector: +// matchLabels: +// istio: ingressgateway +// phase: AUTHN +// wasm: +// url: oci://private-registry:5000/openid-connect/openid:latest +// imagePullPolicy: IfNotPresent +// imagePullSecret: private-registry-pull-secret +// pluginConfig: +// openid_server: authn +// openid_realm: ingress +// ``` +// +// This is the same as the last example, but using VmConfig to configure environment variables in the VM. +// +// ```yaml +// apiVersion: extensions.istio.io/v1alpha1 +// kind: ExtensionFilter +// metadata: +// name: openid-connect +// namespace: istio-ingress +// spec: +// selector: +// matchLabels: +// istio: ingressgateway +// phase: AUTHN +// wasm: +// url: oci://private-registry:5000/openid-connect/openid:latest +// imagePullPolicy: IfNotPresent +// imagePullSecret: private-registry-pull-secret +// pluginConfig: +// openid_server: authn +// openid_realm: ingress +// vmConfig: +// env: +// - name: POD_NAME +// valueFrom: HOST +// - name: TRUST_DOMAIN +// value: "cluster.local" +// ``` +// +// This is also the same as the last example, but the Wasm module is pulled via https and updated for each time when this plugin resource is changed. +// +// ```yaml +// apiVersion: extensions.istio.io/v1alpha1 +// kind: ExtensionFilter +// metadata: +// name: openid-connect +// namespace: istio-ingress +// spec: +// selector: +// matchLabels: +// istio: ingressgateway +// phase: AUTHN +// wasm: +// url: https://private-bucket/filters/openid.wasm +// imagePullPolicy: Always +// pluginConfig: +// openid_server: authn +// openid_realm: ingress +// vmConfig: +// env: +// - name: POD_NAME +// valueFrom: HOST +// - name: TRUST_DOMAIN +// value: "cluster.local" +// ``` +// +// And a more complex example that deploys three ExtensionFilters and orders them +// using `phase` and `priority`. The (hypothetical) setup is that the +// `openid-connect` filter performs an OpenID Connect flow to authenticate the +// user, writing a signed JWT into the Authorization header of the request, +// which can be verified by the Istio authn plugin. Then, the `acl-check` plugin +// kicks in, passing the JWT to a policy server, which in turn responds with a +// signed token that contains information about which files and functions of the +// system are available to the user that was previously authenticated. The +// `acl-check` filter writes this token to a header. Finally, the `check-header` +// filter verifies the token in that header and makes sure that the token's +// contents (the permitted 'function') matches its plugin configuration. +// +// The resulting filter chain looks like this: +// -> openid-connect -> istio.authn -> acl-check -> check-header -> router +// +// ```yaml +// apiVersion: extensions.istio.io/v1alpha1 +// kind: ExtensionFilter +// metadata: +// name: openid-connect +// namespace: istio-ingress +// spec: +// selector: +// matchLabels: +// istio: ingressgateway +// phase: AUTHN +// wasm: +// url: oci://private-registry:5000/openid-connect/openid:latest +// imagePullPolicy: IfNotPresent +// imagePullSecret: private-registry-pull-secret +// pluginConfig: +// openid_server: authn +// openid_realm: ingress +// ``` +// +// ```yaml +// apiVersion: extensions.istio.io/v1alpha1 +// kind: ExtensionFilter +// metadata: +// name: acl-check +// namespace: istio-ingress +// spec: +// selector: +// matchLabels: +// istio: ingressgateway +// phase: AUTHZ +// priority: 1000 +// wasm: +// url: oci://private-registry:5000/acl-check/acl:latest +// imagePullPolicy: Always +// imagePullSecret: private-registry-pull-secret +// pluginConfig: +// acl_server: some_server +// set_header: authz_complete +// ``` +// +// ```yaml +// apiVersion: extensions.istio.io/v1alpha1 +// kind: ExtensionFilter +// metadata: +// name: check-header +// namespace: istio-ingress +// spec: +// selector: +// matchLabels: +// istio: ingressgateway +// phase: AUTHZ +// priority: 10 +// wasm: +// url: oci://private-registry:5000/check-header:latest +// imagePullPolicy: IfNotPresent +// imagePullSecret: private-registry-pull-secret +// pluginConfig: +// read_header: authz_complete +// verification_key: a89gAzxvls0JKAKIJSBnnvvvkIO +// function: read_data +// ``` +// +// Gateway with Lua filter for conditional header modification: +// +// ```yaml +// apiVersion: extensions.istio.io/v1alpha1 +// kind: ExtensionFilter +// metadata: +// name: conditional-header-modifier +// namespace: istio-ingress +// spec: +// selector: +// matchLabels: +// istio: ingressgateway +// match: +// - mode: CLIENT +// ports: +// - number: 8080 +// - number: 8081 +// phase: AUTHN +// priority: 1000 +// lua: +// inlineCode: | +// function envoy_on_request(request_handle) +// local domain = "foo.com" +// local headers = request_handle:headers() +// local host = headers:get(":authority") +// local existing_auth_header = headers:get("Authorization") +// if (domain ~= nil and host ~= nil and existing_auth_header == nil and domain == host) then +// local bearer_token = headers:get("cookie"):match("foo") +// if (bearer_token ~= nil) then +// headers:add("Authorization", "Bearer " .. bearer_token) +// end +// end +// end +// ``` +// +// Waypoint with Lua filter for header count logging: +// +// ```yaml +// apiVersion: extensions.istio.io/v1alpha1 +// kind: ExtensionFilter +// metadata: +// name: reviews-header-logger +// namespace: default +// spec: +// targetRefs: +// - kind: Service +// name: reviews +// match: +// - mode: SERVER +// phase: STATS +// lua: +// inlineCode: | +// function envoy_on_request(request_handle) +// local headers = request_handle:headers() +// local num_headers = 0 +// for key, value in pairs(headers) do +// num_headers = num_headers + 1 +// end +// request_handle:logInfo("Request to reviews service has " .. num_headers .. " headers") +// end +// ``` +package istio.extensions.v1alpha1; + +import "extensions/v1alpha1/wasm.proto"; +import "google/api/field_behavior.proto"; +import "google/protobuf/struct.proto"; +import "google/protobuf/wrappers.proto"; +import "type/v1beta1/selector.proto"; + +option go_package = "istio.io/api/extensions/v1alpha1"; + +// +// +// +// +// +kubebuilder:validation:XValidation:message="only one of targetRefs or selector can be set",rule="(has(self.selector)?1:0)+(has(self.targetRef)?1:0)+(has(self.targetRefs)?1:0)<=1" +// +kubebuilder:validation:XValidation:message="exactly one of wasm or lua must be set",rule="has(self.wasm) != has(self.lua)" +message ExtensionFilter { + // Optional. Criteria used to select the specific set of pods/VMs on which + // this plugin configuration should be applied. If omitted, this + // configuration will be applied to all workload instances in the same + // namespace. If the `ExtensionFilter` is present in the config root + // namespace, it will be applied to all applicable workloads in any + // namespace. + // + // At most, only one of `selector` or `targetRefs` can be set for a given policy. + istio.type.v1beta1.WorkloadSelector selector = 1; + + // Optional. The targetRefs specifies a list of resources the policy should be + // applied to. The targeted resources specified will determine which workloads + // the policy applies to. + // + // Currently, the following resource attachment types are supported: + // * `kind: Gateway` with `group: gateway.networking.k8s.io` in the same namespace. + // * `kind: GatewayClass` with `group: gateway.networking.k8s.io` in the root namespace. + // * `kind: Service` with `group: ""` or `group: "core"` in the same namespace. This type is only supported for waypoints. + // * `kind: ServiceEntry` with `group: networking.istio.io` in the same namespace. + // + // If not set, the policy is applied as defined by the selector. + // At most one of the selector and targetRefs can be set. + // + // NOTE: Waypoint proxies are required to use this field for policies to apply; `selector` policies will be ignored. + // +kubebuilder:validation:MaxItems=16 + repeated istio.type.v1beta1.PolicyTargetReference targetRefs = 3; + + // Determines where in the filter chain this `ExtensionFilter` is to be injected. + PluginPhase phase = 4; + + // Determines ordering of `ExtensionFilters` in the same `phase`. + // When multiple `ExtensionFilters` are applied to the same workload in the + // same `phase`, they will be applied by priority, in descending order. + // If `priority` is not set, or two `ExtensionFilters` exist with the same + // value, the ordering will be deterministically derived from name and + // namespace of the `ExtensionFilters`. Defaults to `0`. + google.protobuf.Int32Value priority = 5; + + // Specifies the criteria to determine which traffic is passed to ExtensionFilter. + // If a traffic satisfies any of TrafficSelectors, + // the traffic passes the ExtensionFilter. + repeated TrafficSelector match = 6; + + // WebAssembly filter configuration. Mutually exclusive with `lua`. + WasmConfig wasm = 10; + + // Lua filter configuration. Mutually exclusive with `wasm`. + LuaConfig lua = 11; +} + +// WasmConfig configures a WebAssembly filter. +// +// Example: +// +// ```yaml +// wasm: +// url: oci://gcr.io/myproject/filter:v1.0.0 +// sha256: abc123... +// imagePullPolicy: IfNotPresent +// imagePullSecret: gcr-secret +// pluginName: my-filter +// pluginConfig: +// key1: value1 +// key2: value2 +// failStrategy: FAIL_CLOSE +// vmConfig: +// env: +// - name: SOME_ENV_VAR +// value: some_value +// type: HTTP +// ``` +message WasmConfig { + // URL of a Wasm module or OCI container. If no scheme is present, + // defaults to `oci://`, referencing an OCI image. Other valid schemes + // are `file://` for referencing .wasm module files present locally + // within the proxy container, and `http[s]://` for .wasm module files + // hosted remotely. + // + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:XValidation:message="url must have schema one of [http, https, file, oci]",rule="isURL(self) ? (url(self).getScheme() in ['', 'http', 'https', 'file', 'oci']) : (isURL('http://' + self) && url('http://' + self).getScheme() in ['', 'http', 'https', 'file', 'oci'])" + string url = 1 [(google.api.field_behavior) = REQUIRED]; + + // SHA256 checksum that will be used to verify Wasm module or OCI container. + // If the `url` field already references a SHA256 (using the `@sha256:` + // notation), it must match the value of this field. If an OCI image is + // referenced by tag and this field is set, its checksum will be verified + // against the contents of this field after pulling. + // +kubebuilder:validation:Pattern="(^$|^[a-f0-9]{64}$)" + string sha256 = 2; + + // The pull behaviour to be applied when fetching Wasm module by either + // OCI image or `http/https`. Only relevant when referencing Wasm module without + // any digest, including the digest in OCI image URL or `sha256` field in `vm_config`. + // Defaults to `IfNotPresent`, except when an OCI image is referenced in the `url` + // and the `latest` tag is used, in which case `Always` is the default, + // mirroring Kubernetes behaviour. + PullPolicy image_pull_policy = 3; + + // Credentials to use for OCI image pulling. + // Name of a Kubernetes Secret in the same namespace as the `ExtensionFilter` that + // contains a Docker pull secret which is to be used to authenticate + // against the registry when pulling the image. + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=253 + string image_pull_secret = 4; + + // $hide_from_docs + // Public key that will be used to verify signatures of signed OCI images + // or Wasm modules. + // + // At this moment, various ways for signing/verifying are emerging and being proposed. + // We can observe two major streams for signing OCI images: Cosign from Sigstore and Notary, + // which is used in Docker Content Trust. + // In case of Wasm module, multiple approaches are still in discussion. + // * https://github.com/WebAssembly/design/issues/1413 + // * https://github.com/wasm-signatures/design (various signing tools are enumerated) + // + // In addition, for each method for signing&verifying, we may need to consider to provide + // additional data or configuration (e.g., key rolling, KMS, root certs, ...) as well. + // + // To deal with this situation, we need to elaborate more generic way to describe + // how to sign and verify the image or wasm binary, and how to specify relevant data, + // including this `verification_key`. + // + // Therefore, this field will not be implemented until the detailed design is established. + // For the future use, just keep this field in proto and hide from documentation. + string verification_key = 5; + + // The configuration that will be passed on to the plugin. + google.protobuf.Struct plugin_config = 6; + + // The plugin name to be used in the Envoy configuration (used to be called + // `rootID`). Some .wasm modules might require this value to select the Wasm + // plugin to execute. + // +kubebuilder:validation:MaxLength=256 + // +kubebuilder:validation:MinLength=1 + string plugin_name = 7; + + // Specifies the failure behavior for the plugin due to fatal errors. + FailStrategy fail_strategy = 8; + + // Configuration for a Wasm VM. + // More details can be found [here](https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/wasm/v3/wasm.proto#extensions-wasm-v3-vmconfig). + VmConfig vm_config = 9; + + // Specifies the type of Wasm Extension to be used. + PluginType type = 10; +} + +// LuaConfig configures a Lua filter. +// +// Lua filters provide a lightweight alternative to WebAssembly for simple +// request/response transformations. The Lua code is executed inline within +// the Envoy proxy. +// +// Example: Simple header manipulation +// +// ```yaml +// lua: +// inlineCode: | +// function envoy_on_request(request_handle) +// request_handle:headers():add("x-custom-header", "custom-value") +// end +// ``` +// +// The Lua script must define one or both of the following functions: +// - `envoy_on_request(request_handle)`: Called when a request is received +// - `envoy_on_response(response_handle)`: Called when a response is received +// +// The request_handle and response_handle provide access to headers, body, +// metadata, and other request/response attributes. See the Envoy Lua filter +// documentation for the complete API: +// https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/lua_filter +message LuaConfig { + // The inline Lua code to be executed. The code must be a valid Lua script + // that defines the appropriate callback functions (`envoy_on_request` and/or + // `envoy_on_response`). + // + // The maximum size is 64KB. For larger or more complex filters, use a + // WebAssembly filter instead. + // + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=65536 + string inline_code = 1 [(google.api.field_behavior) = REQUIRED]; +} diff --git a/extensions/v1alpha1/extension_filter_deepcopy.gen.go b/extensions/v1alpha1/extension_filter_deepcopy.gen.go new file mode 100644 index 0000000000..112f4df20e --- /dev/null +++ b/extensions/v1alpha1/extension_filter_deepcopy.gen.go @@ -0,0 +1,90 @@ +// Code generated by protoc-gen-deepcopy. DO NOT EDIT. +package v1alpha1 + +import ( + proto "google.golang.org/protobuf/proto" +) + +// DeepCopyInto supports using ExtensionFilter within kubernetes types, where deepcopy-gen is used. +func (in *ExtensionFilter) DeepCopyInto(out *ExtensionFilter) { + p := proto.Clone(in).(*ExtensionFilter) + *out = *p +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExtensionFilter. Required by controller-gen. +func (in *ExtensionFilter) DeepCopy() *ExtensionFilter { + if in == nil { + return nil + } + out := new(ExtensionFilter) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new ExtensionFilter. Required by controller-gen. +func (in *ExtensionFilter) DeepCopyInterface() interface{} { + return in.DeepCopy() +} + +// DeepCopyInto supports using WasmConfig within kubernetes types, where deepcopy-gen is used. +func (in *WasmConfig) DeepCopyInto(out *WasmConfig) { + p := proto.Clone(in).(*WasmConfig) + *out = *p +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WasmConfig. Required by controller-gen. +func (in *WasmConfig) DeepCopy() *WasmConfig { + if in == nil { + return nil + } + out := new(WasmConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new WasmConfig. Required by controller-gen. +func (in *WasmConfig) DeepCopyInterface() interface{} { + return in.DeepCopy() +} + +// DeepCopyInto supports using LuaConfig within kubernetes types, where deepcopy-gen is used. +func (in *LuaConfig) DeepCopyInto(out *LuaConfig) { + p := proto.Clone(in).(*LuaConfig) + *out = *p +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LuaConfig. Required by controller-gen. +func (in *LuaConfig) DeepCopy() *LuaConfig { + if in == nil { + return nil + } + out := new(LuaConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new LuaConfig. Required by controller-gen. +func (in *LuaConfig) DeepCopyInterface() interface{} { + return in.DeepCopy() +} + +// DeepCopyInto supports using TrafficSelector within kubernetes types, where deepcopy-gen is used. +func (in *TrafficSelector) DeepCopyInto(out *TrafficSelector) { + p := proto.Clone(in).(*TrafficSelector) + *out = *p +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TrafficSelector. Required by controller-gen. +func (in *TrafficSelector) DeepCopy() *TrafficSelector { + if in == nil { + return nil + } + out := new(TrafficSelector) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new TrafficSelector. Required by controller-gen. +func (in *TrafficSelector) DeepCopyInterface() interface{} { + return in.DeepCopy() +} diff --git a/extensions/v1alpha1/extension_filter_json.gen.go b/extensions/v1alpha1/extension_filter_json.gen.go new file mode 100644 index 0000000000..c3879c93fa --- /dev/null +++ b/extensions/v1alpha1/extension_filter_json.gen.go @@ -0,0 +1,56 @@ +// Code generated by protoc-gen-jsonshim. DO NOT EDIT. +package v1alpha1 + +import ( + bytes "bytes" + jsonpb "github.com/golang/protobuf/jsonpb" +) + +// MarshalJSON is a custom marshaler for ExtensionFilter +func (this *ExtensionFilter) MarshalJSON() ([]byte, error) { + str, err := ExtensionFilterMarshaler.MarshalToString(this) + return []byte(str), err +} + +// UnmarshalJSON is a custom unmarshaler for ExtensionFilter +func (this *ExtensionFilter) UnmarshalJSON(b []byte) error { + return ExtensionFilterUnmarshaler.Unmarshal(bytes.NewReader(b), this) +} + +// MarshalJSON is a custom marshaler for WasmConfig +func (this *WasmConfig) MarshalJSON() ([]byte, error) { + str, err := ExtensionFilterMarshaler.MarshalToString(this) + return []byte(str), err +} + +// UnmarshalJSON is a custom unmarshaler for WasmConfig +func (this *WasmConfig) UnmarshalJSON(b []byte) error { + return ExtensionFilterUnmarshaler.Unmarshal(bytes.NewReader(b), this) +} + +// MarshalJSON is a custom marshaler for LuaConfig +func (this *LuaConfig) MarshalJSON() ([]byte, error) { + str, err := ExtensionFilterMarshaler.MarshalToString(this) + return []byte(str), err +} + +// UnmarshalJSON is a custom unmarshaler for LuaConfig +func (this *LuaConfig) UnmarshalJSON(b []byte) error { + return ExtensionFilterUnmarshaler.Unmarshal(bytes.NewReader(b), this) +} + +// MarshalJSON is a custom marshaler for TrafficSelector +func (this *TrafficSelector) MarshalJSON() ([]byte, error) { + str, err := ExtensionFilterMarshaler.MarshalToString(this) + return []byte(str), err +} + +// UnmarshalJSON is a custom unmarshaler for TrafficSelector +func (this *TrafficSelector) UnmarshalJSON(b []byte) error { + return ExtensionFilterUnmarshaler.Unmarshal(bytes.NewReader(b), this) +} + +var ( + ExtensionFilterMarshaler = &jsonpb.Marshaler{} + ExtensionFilterUnmarshaler = &jsonpb.Unmarshaler{AllowUnknownFields: true} +) diff --git a/extensions/v1alpha1/wasm.proto b/extensions/v1alpha1/wasm.proto index 0c2e22468d..1862368e44 100644 --- a/extensions/v1alpha1/wasm.proto +++ b/extensions/v1alpha1/wasm.proto @@ -356,30 +356,6 @@ message WasmPlugin { // More details can be found [here](https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/wasm/v3/wasm.proto#extensions-wasm-v3-vmconfig). VmConfig vm_config = 11; - // TrafficSelector provides a mechanism to select a specific traffic flow - // for which this Wasm Plugin will be enabled. - // When all the sub conditions in the TrafficSelector are satisfied, the - // traffic will be selected. - message TrafficSelector { - // Criteria for selecting traffic by their direction. - // Note that `CLIENT` and `SERVER` are analogous to OUTBOUND and INBOUND, - // respectively. - // For the gateway, the field should be `CLIENT` or `CLIENT_AND_SERVER`. - // If not specified, the default value is `CLIENT_AND_SERVER`. - istio.type.v1beta1.WorkloadMode mode = 1; - - // Criteria for selecting traffic by their destination port. - // More specifically, for the outbound traffic, the destination port would be - // the port of the target service. On the other hand, for the inbound traffic, - // the destination port is the port bound by the server process in the same Pod. - // - // If one of the given `ports` is matched, this condition is evaluated to true. - // If not specified, this condition is evaluated to true for any port. - // +listType=map - // +listMapKey=number - repeated istio.type.v1beta1.PortSelector ports = 2; - } - // Specifies the criteria to determine which traffic is passed to WasmPlugin. // If a traffic satisfies any of TrafficSelectors, // the traffic passes the WasmPlugin. @@ -389,6 +365,30 @@ message WasmPlugin { PluginType type = 14; } +// TrafficSelector provides a mechanism to select a specific traffic flow +// for which this Wasm Plugin or Extension Filter will be enabled. +// When all the sub conditions in the TrafficSelector are satisfied, the +// traffic will be selected. +message TrafficSelector { + // Criteria for selecting traffic by their direction. + // Note that `CLIENT` and `SERVER` are analogous to OUTBOUND and INBOUND, + // respectively. + // For the gateway, the field should be `CLIENT` or `CLIENT_AND_SERVER`. + // If not specified, the default value is `CLIENT_AND_SERVER`. + istio.type.v1beta1.WorkloadMode mode = 1; + + // Criteria for selecting traffic by their destination port. + // More specifically, for the outbound traffic, the destination port would be + // the port of the target service. On the other hand, for the inbound traffic, + // the destination port is the port bound by the server process in the same Pod. + // + // If one of the given `ports` is matched, this condition is evaluated to true. + // If not specified, this condition is evaluated to true for any port. + // +listType=map + // +listMapKey=number + repeated istio.type.v1beta1.PortSelector ports = 2; +} + // PluginType indicates the type of Wasm extension to be used. // There are two types of extensions: `HTTP` and `NETWORK`. // diff --git a/kubernetes/customresourcedefinitions.gen.yaml b/kubernetes/customresourcedefinitions.gen.yaml index 2055db0036..13a77efb8b 100644 --- a/kubernetes/customresourcedefinitions.gen.yaml +++ b/kubernetes/customresourcedefinitions.gen.yaml @@ -1,6 +1,389 @@ # DO NOT EDIT - Generated by Cue OpenAPI generator based on Istio APIs. apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition +metadata: + annotations: + "helm.sh/resource-policy": keep + labels: + app: istio-pilot + chart: istio + heritage: Tiller + release: istio + name: extensionfilters.extensions.istio.io +spec: + group: extensions.istio.io + names: + categories: + - istio-io + - extensions-istio-io + kind: ExtensionFilter + listKind: ExtensionFilterList + plural: extensionfilters + singular: extensionfilter + scope: Namespaced + versions: + - additionalPrinterColumns: + - description: 'CreationTimestamp is a timestamp representing the server time + when this object was created. It is not guaranteed to be set in happens-before + order across separate operations. Clients may not set this value. It is represented + in RFC3339 form and is in UTC. Populated by the system. Read-only. Null for + lists. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata' + jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + properties: + spec: + description: 'Extend the functionality provided by the Istio proxy through + WebAssembly or Lua filters. See more details at: https://istio.io/docs/reference/config/proxy_extensions/v1alpha1/extension_filter.html' + properties: + lua: + description: Lua filter configuration. + properties: + inlineCode: + description: The inline Lua code to be executed. + maxLength: 65536 + minLength: 1 + type: string + required: + - inlineCode + type: object + match: + description: Specifies the criteria to determine which traffic is + passed to ExtensionFilter. + items: + properties: + mode: + description: |- + Criteria for selecting traffic by their direction. + + Valid Options: CLIENT, SERVER, CLIENT_AND_SERVER + enum: + - UNDEFINED + - CLIENT + - SERVER + - CLIENT_AND_SERVER + type: string + ports: + description: Criteria for selecting traffic by their destination + port. + items: + properties: + number: + maximum: 65535 + minimum: 1 + type: integer + required: + - number + type: object + type: array + x-kubernetes-list-map-keys: + - number + x-kubernetes-list-type: map + type: object + type: array + phase: + description: |- + Determines where in the filter chain this `ExtensionFilter` is to be injected. + + Valid Options: AUTHN, AUTHZ, STATS + enum: + - UNSPECIFIED_PHASE + - AUTHN + - AUTHZ + - STATS + type: string + priority: + description: Determines ordering of `ExtensionFilters` in the same + `phase`. + format: int32 + nullable: true + type: integer + selector: + description: Criteria used to select the specific set of pods/VMs + on which this plugin configuration should be applied. + properties: + matchLabels: + additionalProperties: + maxLength: 63 + type: string + x-kubernetes-validations: + - message: wildcard not allowed in label value match + rule: '!self.contains("*")' + description: One or more labels that indicate a specific set of + pods/VMs on which a policy should be applied. + maxProperties: 4096 + type: object + x-kubernetes-validations: + - message: wildcard not allowed in label key match + rule: self.all(key, !key.contains("*")) + - message: key must not be empty + rule: self.all(key, key.size() != 0) + type: object + targetRef: + description: Optional. + properties: + group: + description: group is the group of the target resource. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: kind is kind of the target resource. + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: name is the name of the target resource. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: namespace is the namespace of the referent. + type: string + x-kubernetes-validations: + - message: cross namespace referencing is not currently supported + rule: self.size() == 0 + required: + - kind + - name + type: object + x-kubernetes-validations: + - message: targetRef namespace must be unset + rule: '!has(self.__namespace__)' + targetRefs: + description: Optional. + items: + properties: + group: + description: group is the group of the target resource. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: kind is kind of the target resource. + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: name is the name of the target resource. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: namespace is the namespace of the referent. + type: string + x-kubernetes-validations: + - message: cross namespace referencing is not currently supported + rule: self.size() == 0 + required: + - kind + - name + type: object + maxItems: 16 + type: array + wasm: + description: WebAssembly filter configuration. + properties: + failStrategy: + description: |- + Specifies the failure behavior for the plugin due to fatal errors. + + Valid Options: FAIL_CLOSE, FAIL_OPEN, FAIL_RELOAD + enum: + - FAIL_CLOSE + - FAIL_OPEN + - FAIL_RELOAD + type: string + imagePullPolicy: + description: |- + The pull behaviour to be applied when fetching Wasm module by either OCI image or `http/https`. + + Valid Options: IfNotPresent, Always + enum: + - UNSPECIFIED_POLICY + - IfNotPresent + - Always + type: string + imagePullSecret: + description: Credentials to use for OCI image pulling. + maxLength: 253 + minLength: 1 + type: string + pluginConfig: + description: The configuration that will be passed on to the plugin. + type: object + x-kubernetes-preserve-unknown-fields: true + pluginName: + description: The plugin name to be used in the Envoy configuration + (used to be called `rootID`). + maxLength: 256 + minLength: 1 + type: string + sha256: + description: SHA256 checksum that will be used to verify Wasm + module or OCI container. + pattern: (^$|^[a-f0-9]{64}$) + type: string + type: + description: |- + Specifies the type of Wasm Extension to be used. + + Valid Options: HTTP, NETWORK + enum: + - UNSPECIFIED_PLUGIN_TYPE + - HTTP + - NETWORK + type: string + url: + description: URL of a Wasm module or OCI container. + minLength: 1 + type: string + x-kubernetes-validations: + - message: url must have schema one of [http, https, file, oci] + rule: |- + isURL(self) ? (url(self).getScheme() in ["", "http", "https", "file", "oci"]) : (isURL("http://" + self) && + url("http://" + self).getScheme() in ["", "http", "https", "file", "oci"]) + verificationKey: + type: string + vmConfig: + description: Configuration for a Wasm VM. + properties: + env: + description: Specifies environment variables to be injected + to this VM. + items: + properties: + name: + description: Name of the environment variable. + maxLength: 256 + minLength: 1 + type: string + value: + description: Value for the environment variable. + maxLength: 2048 + type: string + valueFrom: + description: |- + Source for the environment variable's value. + + Valid Options: INLINE, HOST + enum: + - INLINE + - HOST + type: string + required: + - name + type: object + x-kubernetes-validations: + - message: value may only be set when valueFrom is INLINE + rule: '(has(self.valueFrom) ? self.valueFrom : "") != + "HOST" || !has(self.value)' + maxItems: 256 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + required: + - url + type: object + type: object + x-kubernetes-validations: + - message: only one of targetRefs or selector can be set + rule: '(has(self.selector) ? 1 : 0) + (has(self.targetRef) ? 1 : 0) + + (has(self.targetRefs) ? 1 : 0) <= 1' + - message: exactly one of wasm or lua must be set + rule: has(self.wasm) != has(self.lua) + status: + properties: + conditions: + description: Current service state of the resource. + items: + properties: + lastProbeTime: + description: Last time we probed the condition. + format: date-time + type: string + lastTransitionTime: + description: Last time the condition transitioned from one status + to another. + format: date-time + type: string + message: + description: Human-readable message indicating details about + last transition. + type: string + observedGeneration: + anyOf: + - type: integer + - type: string + description: Resource Generation to which the Condition refers. + x-kubernetes-int-or-string: true + reason: + description: Unique, one-word, CamelCase reason for the condition's + last transition. + type: string + status: + description: Status is the status of the condition. + type: string + type: + description: Type is the type of the condition. + type: string + type: object + type: array + observedGeneration: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + validationMessages: + description: Includes any errors or warnings detected by Istio's analyzers. + items: + properties: + documentationUrl: + description: A url pointing to the Istio documentation for this + specific error type. + type: string + level: + description: |- + Represents how severe a message is. + + Valid Options: UNKNOWN, ERROR, WARNING, INFO + enum: + - UNKNOWN + - ERROR + - WARNING + - INFO + type: string + type: + properties: + code: + description: A 7 character code matching `^IST[0-9]{4}$` + intended to uniquely identify the message type. + type: string + name: + description: A human-readable name for the message type. + type: string + type: object + type: object + type: array + type: object + x-kubernetes-preserve-unknown-fields: true + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition metadata: annotations: "helm.sh/resource-policy": keep