diff --git a/VERSION b/VERSION index 828fcfc8b1..804a616da1 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v1.8.0-rc.1 +v1.8.0 diff --git a/api/v1alpha1/healthcheck_types.go b/api/v1alpha1/healthcheck_types.go index 7edf17744d..eed9a6a179 100644 --- a/api/v1alpha1/healthcheck_types.go +++ b/api/v1alpha1/healthcheck_types.go @@ -177,8 +177,9 @@ const ( // HTTPActiveHealthChecker defines the settings of http health check. type HTTPActiveHealthChecker struct { - // Hostname defines the HTTP host that will be requested during health checking. - // Default: HTTPRoute or GRPCRoute hostname. + // Hostname defines the HTTP Host header used for active HTTP health checks. + // Host selection uses this order: this field, the associated Backend endpoint + // hostname if available, then the effective Route hostname. // // +kubebuilder:validation:MinLength=1 // +kubebuilder:validation:MaxLength=253 diff --git a/api/v1alpha1/policy_helpers.go b/api/v1alpha1/policy_helpers.go index 10b8e099f7..7a0e2679c7 100644 --- a/api/v1alpha1/policy_helpers.go +++ b/api/v1alpha1/policy_helpers.go @@ -58,6 +58,10 @@ type TargetSelector struct { // When specified, the effective set of namespaces is always constrained to the // namespaces watched by Envoy Gateway. // + // Selecting targets across namespaces requires a ReferenceGrant in the target + // namespace that allows this policy kind to reference the selected target kind. + // Cross-namespace targets without a matching ReferenceGrant are ignored. + // // +optional Namespaces *TargetSelectorNamespaces `json:"namespaces,omitempty"` diff --git a/api/v1alpha1/ratelimit_types.go b/api/v1alpha1/ratelimit_types.go index 4603b26bdc..65fd174c78 100644 --- a/api/v1alpha1/ratelimit_types.go +++ b/api/v1alpha1/ratelimit_types.go @@ -228,7 +228,7 @@ type RateLimitSelectCondition struct { // meaning, a request MUST match all the specified headers. // // +optional - // +kubebuilder:validation:MaxItems=16 + // +kubebuilder:validation:MaxItems=64 Headers []HeaderMatch `json:"headers,omitempty"` // Methods is a list of request methods to match. Multiple method values are ORed together, diff --git a/api/v1alpha1/shared_types.go b/api/v1alpha1/shared_types.go index 7db6e22185..ea1ed8382b 100644 --- a/api/v1alpha1/shared_types.go +++ b/api/v1alpha1/shared_types.go @@ -70,10 +70,6 @@ const ( // PolicyReasonDeprecatedField is used with the "Warning" condition when the policy // uses deprecated fields that should be migrated to newer alternatives. PolicyReasonDeprecatedField gwapiv1.PolicyConditionReason = "DeprecatedField" - - // PolicyReasonRefNotPermitted is used when the policy targets a cross-namespace - // object without a matching ReferenceGrant. - PolicyReasonRefNotPermitted gwapiv1.PolicyConditionReason = "RefNotPermitted" ) // GroupVersionKind unambiguously identifies a Kind. diff --git a/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml b/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml index e9a2c99e6f..1ad45ac95a 100644 --- a/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml +++ b/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml @@ -671,8 +671,9 @@ spec: type: array hostname: description: |- - Hostname defines the HTTP host that will be requested during health checking. - Default: HTTPRoute or GRPCRoute hostname. + Hostname defines the HTTP Host header used for active HTTP health checks. + Host selection uses this order: this field, the associated Backend endpoint + hostname if available, then the effective Route hostname. maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ @@ -1506,7 +1507,7 @@ spec: required: - name type: object - maxItems: 16 + maxItems: 64 type: array methods: description: |- @@ -1890,7 +1891,7 @@ spec: required: - name type: object - maxItems: 16 + maxItems: 64 type: array methods: description: |- @@ -2924,6 +2925,10 @@ spec: When specified, the effective set of namespaces is always constrained to the namespaces watched by Envoy Gateway. + + Selecting targets across namespaces requires a ReferenceGrant in the target + namespace that allows this policy kind to reference the selected target kind. + Cross-namespace targets without a matching ReferenceGrant are ignored. properties: from: default: Same diff --git a/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_clienttrafficpolicies.yaml b/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_clienttrafficpolicies.yaml index 5aba61ba83..78e80bb4e5 100644 --- a/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_clienttrafficpolicies.yaml +++ b/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_clienttrafficpolicies.yaml @@ -1181,6 +1181,10 @@ spec: When specified, the effective set of namespaces is always constrained to the namespaces watched by Envoy Gateway. + + Selecting targets across namespaces requires a ReferenceGrant in the target + namespace that allows this policy kind to reference the selected target kind. + Cross-namespace targets without a matching ReferenceGrant are ignored. properties: from: default: Same diff --git a/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml b/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml index e0bd5d49bc..8b24dac2fc 100644 --- a/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml +++ b/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml @@ -567,8 +567,9 @@ spec: type: array hostname: description: |- - Hostname defines the HTTP host that will be requested during health checking. - Default: HTTPRoute or GRPCRoute hostname. + Hostname defines the HTTP Host header used for active HTTP health checks. + Host selection uses this order: this field, the associated Backend endpoint + hostname if available, then the effective Route hostname. maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ @@ -1824,6 +1825,10 @@ spec: When specified, the effective set of namespaces is always constrained to the namespaces watched by Envoy Gateway. + + Selecting targets across namespaces requires a ReferenceGrant in the target + namespace that allows this policy kind to reference the selected target kind. + Cross-namespace targets without a matching ReferenceGrant are ignored. properties: from: default: Same diff --git a/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_envoyproxies.yaml b/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_envoyproxies.yaml index 8b19d5b1b0..33db2b3cde 100644 --- a/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_envoyproxies.yaml +++ b/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_envoyproxies.yaml @@ -11837,8 +11837,9 @@ spec: type: array hostname: description: |- - Hostname defines the HTTP host that will be requested during health checking. - Default: HTTPRoute or GRPCRoute hostname. + Hostname defines the HTTP Host header used for active HTTP health checks. + Host selection uses this order: this field, the associated Backend endpoint + hostname if available, then the effective Route hostname. maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ @@ -13368,8 +13369,9 @@ spec: type: array hostname: description: |- - Hostname defines the HTTP host that will be requested during health checking. - Default: HTTPRoute or GRPCRoute hostname. + Hostname defines the HTTP Host header used for active HTTP health checks. + Host selection uses this order: this field, the associated Backend endpoint + hostname if available, then the effective Route hostname. maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ @@ -15086,8 +15088,9 @@ spec: type: array hostname: description: |- - Hostname defines the HTTP host that will be requested during health checking. - Default: HTTPRoute or GRPCRoute hostname. + Hostname defines the HTTP Host header used for active HTTP health checks. + Host selection uses this order: this field, the associated Backend endpoint + hostname if available, then the effective Route hostname. maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ @@ -16694,8 +16697,9 @@ spec: type: array hostname: description: |- - Hostname defines the HTTP host that will be requested during health checking. - Default: HTTPRoute or GRPCRoute hostname. + Hostname defines the HTTP Host header used for active HTTP health checks. + Host selection uses this order: this field, the associated Backend endpoint + hostname if available, then the effective Route hostname. maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ diff --git a/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_securitypolicies.yaml b/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_securitypolicies.yaml index 34ba4c7907..4d618a9f25 100644 --- a/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_securitypolicies.yaml +++ b/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_securitypolicies.yaml @@ -1194,8 +1194,9 @@ spec: type: array hostname: description: |- - Hostname defines the HTTP host that will be requested during health checking. - Default: HTTPRoute or GRPCRoute hostname. + Hostname defines the HTTP Host header used for active HTTP health checks. + Host selection uses this order: this field, the associated Backend endpoint + hostname if available, then the effective Route hostname. maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ @@ -2597,8 +2598,9 @@ spec: type: array hostname: description: |- - Hostname defines the HTTP host that will be requested during health checking. - Default: HTTPRoute or GRPCRoute hostname. + Hostname defines the HTTP Host header used for active HTTP health checks. + Host selection uses this order: this field, the associated Backend endpoint + hostname if available, then the effective Route hostname. maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ @@ -4279,8 +4281,9 @@ spec: type: array hostname: description: |- - Hostname defines the HTTP host that will be requested during health checking. - Default: HTTPRoute or GRPCRoute hostname. + Hostname defines the HTTP Host header used for active HTTP health checks. + Host selection uses this order: this field, the associated Backend endpoint + hostname if available, then the effective Route hostname. maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ @@ -5993,8 +5996,9 @@ spec: type: array hostname: description: |- - Hostname defines the HTTP host that will be requested during health checking. - Default: HTTPRoute or GRPCRoute hostname. + Hostname defines the HTTP Host header used for active HTTP health checks. + Host selection uses this order: this field, the associated Backend endpoint + hostname if available, then the effective Route hostname. maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ @@ -7142,6 +7146,10 @@ spec: When specified, the effective set of namespaces is always constrained to the namespaces watched by Envoy Gateway. + + Selecting targets across namespaces requires a ReferenceGrant in the target + namespace that allows this policy kind to reference the selected target kind. + Cross-namespace targets without a matching ReferenceGrant are ignored. properties: from: default: Same diff --git a/charts/gateway-helm/charts/crds/crds/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml b/charts/gateway-helm/charts/crds/crds/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml index 3fc645eaf2..64875d52ee 100644 --- a/charts/gateway-helm/charts/crds/crds/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml +++ b/charts/gateway-helm/charts/crds/crds/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml @@ -670,8 +670,9 @@ spec: type: array hostname: description: |- - Hostname defines the HTTP host that will be requested during health checking. - Default: HTTPRoute or GRPCRoute hostname. + Hostname defines the HTTP Host header used for active HTTP health checks. + Host selection uses this order: this field, the associated Backend endpoint + hostname if available, then the effective Route hostname. maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ @@ -1505,7 +1506,7 @@ spec: required: - name type: object - maxItems: 16 + maxItems: 64 type: array methods: description: |- @@ -1889,7 +1890,7 @@ spec: required: - name type: object - maxItems: 16 + maxItems: 64 type: array methods: description: |- @@ -2923,6 +2924,10 @@ spec: When specified, the effective set of namespaces is always constrained to the namespaces watched by Envoy Gateway. + + Selecting targets across namespaces requires a ReferenceGrant in the target + namespace that allows this policy kind to reference the selected target kind. + Cross-namespace targets without a matching ReferenceGrant are ignored. properties: from: default: Same diff --git a/charts/gateway-helm/charts/crds/crds/generated/gateway.envoyproxy.io_clienttrafficpolicies.yaml b/charts/gateway-helm/charts/crds/crds/generated/gateway.envoyproxy.io_clienttrafficpolicies.yaml index 62bd176d62..413730fae0 100644 --- a/charts/gateway-helm/charts/crds/crds/generated/gateway.envoyproxy.io_clienttrafficpolicies.yaml +++ b/charts/gateway-helm/charts/crds/crds/generated/gateway.envoyproxy.io_clienttrafficpolicies.yaml @@ -1180,6 +1180,10 @@ spec: When specified, the effective set of namespaces is always constrained to the namespaces watched by Envoy Gateway. + + Selecting targets across namespaces requires a ReferenceGrant in the target + namespace that allows this policy kind to reference the selected target kind. + Cross-namespace targets without a matching ReferenceGrant are ignored. properties: from: default: Same diff --git a/charts/gateway-helm/charts/crds/crds/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml b/charts/gateway-helm/charts/crds/crds/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml index 85c9878352..51964f1d6a 100644 --- a/charts/gateway-helm/charts/crds/crds/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml +++ b/charts/gateway-helm/charts/crds/crds/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml @@ -566,8 +566,9 @@ spec: type: array hostname: description: |- - Hostname defines the HTTP host that will be requested during health checking. - Default: HTTPRoute or GRPCRoute hostname. + Hostname defines the HTTP Host header used for active HTTP health checks. + Host selection uses this order: this field, the associated Backend endpoint + hostname if available, then the effective Route hostname. maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ @@ -1823,6 +1824,10 @@ spec: When specified, the effective set of namespaces is always constrained to the namespaces watched by Envoy Gateway. + + Selecting targets across namespaces requires a ReferenceGrant in the target + namespace that allows this policy kind to reference the selected target kind. + Cross-namespace targets without a matching ReferenceGrant are ignored. properties: from: default: Same diff --git a/charts/gateway-helm/charts/crds/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml b/charts/gateway-helm/charts/crds/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml index 58f11213f9..19e9614662 100644 --- a/charts/gateway-helm/charts/crds/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml +++ b/charts/gateway-helm/charts/crds/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml @@ -11836,8 +11836,9 @@ spec: type: array hostname: description: |- - Hostname defines the HTTP host that will be requested during health checking. - Default: HTTPRoute or GRPCRoute hostname. + Hostname defines the HTTP Host header used for active HTTP health checks. + Host selection uses this order: this field, the associated Backend endpoint + hostname if available, then the effective Route hostname. maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ @@ -13367,8 +13368,9 @@ spec: type: array hostname: description: |- - Hostname defines the HTTP host that will be requested during health checking. - Default: HTTPRoute or GRPCRoute hostname. + Hostname defines the HTTP Host header used for active HTTP health checks. + Host selection uses this order: this field, the associated Backend endpoint + hostname if available, then the effective Route hostname. maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ @@ -15085,8 +15087,9 @@ spec: type: array hostname: description: |- - Hostname defines the HTTP host that will be requested during health checking. - Default: HTTPRoute or GRPCRoute hostname. + Hostname defines the HTTP Host header used for active HTTP health checks. + Host selection uses this order: this field, the associated Backend endpoint + hostname if available, then the effective Route hostname. maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ @@ -16693,8 +16696,9 @@ spec: type: array hostname: description: |- - Hostname defines the HTTP host that will be requested during health checking. - Default: HTTPRoute or GRPCRoute hostname. + Hostname defines the HTTP Host header used for active HTTP health checks. + Host selection uses this order: this field, the associated Backend endpoint + hostname if available, then the effective Route hostname. maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ diff --git a/charts/gateway-helm/charts/crds/crds/generated/gateway.envoyproxy.io_securitypolicies.yaml b/charts/gateway-helm/charts/crds/crds/generated/gateway.envoyproxy.io_securitypolicies.yaml index 8de423fd20..47686dab2d 100644 --- a/charts/gateway-helm/charts/crds/crds/generated/gateway.envoyproxy.io_securitypolicies.yaml +++ b/charts/gateway-helm/charts/crds/crds/generated/gateway.envoyproxy.io_securitypolicies.yaml @@ -1193,8 +1193,9 @@ spec: type: array hostname: description: |- - Hostname defines the HTTP host that will be requested during health checking. - Default: HTTPRoute or GRPCRoute hostname. + Hostname defines the HTTP Host header used for active HTTP health checks. + Host selection uses this order: this field, the associated Backend endpoint + hostname if available, then the effective Route hostname. maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ @@ -2596,8 +2597,9 @@ spec: type: array hostname: description: |- - Hostname defines the HTTP host that will be requested during health checking. - Default: HTTPRoute or GRPCRoute hostname. + Hostname defines the HTTP Host header used for active HTTP health checks. + Host selection uses this order: this field, the associated Backend endpoint + hostname if available, then the effective Route hostname. maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ @@ -4278,8 +4280,9 @@ spec: type: array hostname: description: |- - Hostname defines the HTTP host that will be requested during health checking. - Default: HTTPRoute or GRPCRoute hostname. + Hostname defines the HTTP Host header used for active HTTP health checks. + Host selection uses this order: this field, the associated Backend endpoint + hostname if available, then the effective Route hostname. maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ @@ -5992,8 +5995,9 @@ spec: type: array hostname: description: |- - Hostname defines the HTTP host that will be requested during health checking. - Default: HTTPRoute or GRPCRoute hostname. + Hostname defines the HTTP Host header used for active HTTP health checks. + Host selection uses this order: this field, the associated Backend endpoint + hostname if available, then the effective Route hostname. maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ @@ -7141,6 +7145,10 @@ spec: When specified, the effective set of namespaces is always constrained to the namespaces watched by Envoy Gateway. + + Selecting targets across namespaces requires a ReferenceGrant in the target + namespace that allows this policy kind to reference the selected target kind. + Cross-namespace targets without a matching ReferenceGrant are ignored. properties: from: default: Same diff --git a/charts/gateway-helm/templates/envoy-gateway-rbac.yaml b/charts/gateway-helm/templates/envoy-gateway-rbac.yaml index fec98a8c83..82df678e26 100644 --- a/charts/gateway-helm/templates/envoy-gateway-rbac.yaml +++ b/charts/gateway-helm/templates/envoy-gateway-rbac.yaml @@ -18,6 +18,8 @@ metadata: creationTimestamp: null name: {{ include "eg.fullname" $ }}-envoy-gateway-role namespace: {{ $ns | quote }} + labels: + {{- include "eg.labels" $ | nindent 4 }} rules: {{ include "eg.rbac.namespaced" $ }} --- @@ -26,6 +28,8 @@ kind: RoleBinding metadata: name: {{ include "eg.fullname" $ }}-envoy-gateway-rolebinding namespace: {{ $ns | quote }} + labels: + {{- include "eg.labels" $ | nindent 4 }} roleRef: apiGroup: rbac.authorization.k8s.io kind: Role @@ -41,6 +45,8 @@ kind: ClusterRole metadata: creationTimestamp: null name: {{ include "eg.fullname" . }}-envoy-gateway-role + labels: + {{- include "eg.labels" . | nindent 4 }} rules: {{ include "eg.rbac.cluster" . }} --- @@ -48,6 +54,8 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: {{ include "eg.fullname" . }}-envoy-gateway-rolebinding + labels: + {{- include "eg.labels" . | nindent 4 }} roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole @@ -63,6 +71,8 @@ kind: ClusterRole metadata: creationTimestamp: null name: {{ include "eg.fullname" . }}-envoy-gateway-role + labels: + {{- include "eg.labels" . | nindent 4 }} rules: {{ include "eg.rbac.cluster" . }} {{ include "eg.rbac.namespaced" . }} @@ -71,6 +81,8 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: {{ include "eg.fullname" . }}-envoy-gateway-rolebinding + labels: + {{- include "eg.labels" . | nindent 4 }} roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole diff --git a/internal/cmd/egctl/testdata/translate/out/default-resources.all.yaml b/internal/cmd/egctl/testdata/translate/out/default-resources.all.yaml index 9d2dc66515..41153fe438 100644 --- a/internal/cmd/egctl/testdata/translate/out/default-resources.all.yaml +++ b/internal/cmd/egctl/testdata/translate/out/default-resources.all.yaml @@ -23,6 +23,8 @@ envoyProxyForGatewayClass: node: locality: zone: $(ENVOY_SERVICE_ZONE) + deferredStatOptions: + enableDeferredCreationStats: true stats_config: use_all_default_tags: true stats_tags: @@ -568,6 +570,8 @@ xds: portValue: 19000 clusterManager: localClusterName: local_cluster + deferredStatOptions: + enableDeferredCreationStats: true dynamicResources: adsConfig: apiType: DELTA_GRPC diff --git a/internal/cmd/egctl/testdata/translate/out/from-gateway-api-to-xds.all.json b/internal/cmd/egctl/testdata/translate/out/from-gateway-api-to-xds.all.json index 45adf15015..ef6c2cdbc7 100644 --- a/internal/cmd/egctl/testdata/translate/out/from-gateway-api-to-xds.all.json +++ b/internal/cmd/egctl/testdata/translate/out/from-gateway-api-to-xds.all.json @@ -25,6 +25,9 @@ "clusterManager": { "localClusterName": "local_cluster" }, + "deferredStatOptions": { + "enableDeferredCreationStats": true + }, "dynamicResources": { "adsConfig": { "apiType": "DELTA_GRPC", diff --git a/internal/cmd/egctl/testdata/translate/out/from-gateway-api-to-xds.all.yaml b/internal/cmd/egctl/testdata/translate/out/from-gateway-api-to-xds.all.yaml index fe7f84b600..93486e9cf9 100644 --- a/internal/cmd/egctl/testdata/translate/out/from-gateway-api-to-xds.all.yaml +++ b/internal/cmd/egctl/testdata/translate/out/from-gateway-api-to-xds.all.yaml @@ -15,6 +15,8 @@ xds: portValue: 19000 clusterManager: localClusterName: local_cluster + deferredStatOptions: + enableDeferredCreationStats: true dynamicResources: adsConfig: apiType: DELTA_GRPC diff --git a/internal/cmd/egctl/testdata/translate/out/from-gateway-api-to-xds.bootstrap.yaml b/internal/cmd/egctl/testdata/translate/out/from-gateway-api-to-xds.bootstrap.yaml index ad785f5ff5..3a5582a922 100644 --- a/internal/cmd/egctl/testdata/translate/out/from-gateway-api-to-xds.bootstrap.yaml +++ b/internal/cmd/egctl/testdata/translate/out/from-gateway-api-to-xds.bootstrap.yaml @@ -14,6 +14,8 @@ xds: portValue: 19000 clusterManager: localClusterName: local_cluster + deferredStatOptions: + enableDeferredCreationStats: true dynamicResources: adsConfig: apiType: DELTA_GRPC diff --git a/internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.all.json b/internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.all.json index 49e5ed4d0c..a05f7566c6 100644 --- a/internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.all.json +++ b/internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.all.json @@ -25,6 +25,9 @@ "clusterManager": { "localClusterName": "local_cluster" }, + "deferredStatOptions": { + "enableDeferredCreationStats": true + }, "dynamicResources": { "adsConfig": { "apiType": "DELTA_GRPC", diff --git a/internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.all.yaml b/internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.all.yaml index 9766fb1e7c..5a3619a007 100644 --- a/internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.all.yaml +++ b/internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.all.yaml @@ -15,6 +15,8 @@ xds: portValue: 19000 clusterManager: localClusterName: local_cluster + deferredStatOptions: + enableDeferredCreationStats: true dynamicResources: adsConfig: apiType: DELTA_GRPC diff --git a/internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.bootstrap.yaml b/internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.bootstrap.yaml index 47ec643913..2072db1fe5 100644 --- a/internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.bootstrap.yaml +++ b/internal/cmd/egctl/testdata/translate/out/jwt-single-route-single-match-to-xds.bootstrap.yaml @@ -14,6 +14,8 @@ xds: portValue: 19000 clusterManager: localClusterName: local_cluster + deferredStatOptions: + enableDeferredCreationStats: true dynamicResources: adsConfig: apiType: DELTA_GRPC diff --git a/internal/cmd/egctl/testdata/translate/out/no-service-cluster-ip.all.yaml b/internal/cmd/egctl/testdata/translate/out/no-service-cluster-ip.all.yaml index c3a4473c6a..ff3d966c61 100644 --- a/internal/cmd/egctl/testdata/translate/out/no-service-cluster-ip.all.yaml +++ b/internal/cmd/egctl/testdata/translate/out/no-service-cluster-ip.all.yaml @@ -15,6 +15,8 @@ xds: portValue: 19000 clusterManager: localClusterName: local_cluster + deferredStatOptions: + enableDeferredCreationStats: true dynamicResources: adsConfig: apiType: DELTA_GRPC diff --git a/internal/gatewayapi/backendtrafficpolicy.go b/internal/gatewayapi/backendtrafficpolicy.go index cb7c6787cc..40380b895b 100644 --- a/internal/gatewayapi/backendtrafficpolicy.go +++ b/internal/gatewayapi/backendtrafficpolicy.go @@ -295,16 +295,14 @@ func (t *Translator) ProcessBackendTrafficPolicies( // Process the policies targeting Routes for i, currPolicy := range backendTrafficPolicies { policyName := utils.NamespacedName(currPolicy) - allowed, denied := resolvePolicyTargetsFromSelectors( - currPolicy.Spec.TargetSelectors, + targetRefs := resolvePolicyTargets( + currPolicy.Spec.PolicyTargetReferences, routes, resources.ReferenceGrants, egv1a1.GroupName, egv1a1.KindBackendTrafficPolicy, currPolicy.Namespace, t.GetNamespace) - plainTargetRefs := resolvePolicyTargetsFromReferences(currPolicy.Spec.PolicyTargetReferences, currPolicy.Namespace) - targetRefs := composePolicyTargetRefs(allowed, plainTargetRefs) for _, currTarget := range targetRefs { if isRoute(currTarget) { policy, found := handledPolicies[policyName] @@ -318,15 +316,6 @@ func (t *Translator) ProcessBackendTrafficPolicies( routeMap, gatewayRouteMap, gatewayPolicyMerged, gatewayPolicyMap, policy, currTarget) } } - if len(denied) > 0 { - policy, found := handledPolicies[policyName] - if !found { - policy = policyCopies[i] - handledPolicies[policyName] = policy - res = append(res, policy) - } - setPolicyTargetRefNotPermittedStatus(&policy.Status, denied, t.GatewayControllerName, policy.Generation) - } } // Process the policies targeting Listeners @@ -351,16 +340,14 @@ func (t *Translator) ProcessBackendTrafficPolicies( // Process the policies targeting Gateways for i, currPolicy := range backendTrafficPolicies { policyName := utils.NamespacedName(currPolicy) - allowed, denied := resolvePolicyTargetsFromSelectors( - currPolicy.Spec.TargetSelectors, + targetRefs := resolvePolicyTargets( + currPolicy.Spec.PolicyTargetReferences, gateways, resources.ReferenceGrants, egv1a1.GroupName, egv1a1.KindBackendTrafficPolicy, currPolicy.Namespace, t.GetNamespace) - plainTargetRefs := resolvePolicyTargetsFromReferences(currPolicy.Spec.PolicyTargetReferences, currPolicy.Namespace) - targetRefs := composePolicyTargetRefs(allowed, plainTargetRefs) for _, currTarget := range targetRefs { if isGateway(currTarget) { policy, found := handledPolicies[policyName] @@ -373,15 +360,6 @@ func (t *Translator) ProcessBackendTrafficPolicies( gatewayMap, gatewayRouteMap, gatewayPolicyMerged, policy, currTarget) } } - if len(denied) > 0 { - policy, found := handledPolicies[policyName] - if !found { - policy = policyCopies[i] - handledPolicies[policyName] = policy - res = append(res, policy) - } - setPolicyTargetRefNotPermittedStatus(&policy.Status, denied, t.GatewayControllerName, policy.Generation) - } } for _, policy := range res { @@ -1042,9 +1020,6 @@ func (t *Translator) applyTrafficFeatureToRoute(route RouteContext, r.Traffic.Timeout = localTo } - // Update the Host field in HealthCheck, now that we have access to the Route Hostname. - r.Traffic.HealthCheck.SetHTTPHostIfAbsent(r.Hostname) - if policy.Spec.UseClientProtocol != nil { r.UseClientProtocol = policy.Spec.UseClientProtocol } @@ -1343,9 +1318,6 @@ func (t *Translator) translateBackendTrafficPolicyForGateway( r.Traffic.Timeout = localTo } - // Update the Host field in HealthCheck, now that we have access to the Route Hostname. - r.Traffic.HealthCheck.SetHTTPHostIfAbsent(r.Hostname) - if policy.Spec.UseClientProtocol != nil { r.UseClientProtocol = policy.Spec.UseClientProtocol } diff --git a/internal/gatewayapi/clienttrafficpolicy.go b/internal/gatewayapi/clienttrafficpolicy.go index e06e84380b..10e830e4a0 100644 --- a/internal/gatewayapi/clienttrafficpolicy.go +++ b/internal/gatewayapi/clienttrafficpolicy.go @@ -195,8 +195,8 @@ func (t *Translator) ProcessClientTrafficPolicies( // Policy with no section set (targeting all sections) for i, currPolicy := range clientTrafficPolicies { policyName := utils.NamespacedName(currPolicy) - allowed, denied := resolvePolicyTargetsFromSelectors( - currPolicy.Spec.TargetSelectors, + targetRefs := resolvePolicyTargets( + currPolicy.Spec.PolicyTargetReferences, gateways, resources.ReferenceGrants, egv1a1.GroupName, @@ -204,8 +204,6 @@ func (t *Translator) ProcessClientTrafficPolicies( currPolicy.Namespace, t.GetNamespace, ) - plainTargetRefs := resolvePolicyTargetsFromReferences(currPolicy.Spec.PolicyTargetReferences, currPolicy.Namespace) - targetRefs := composePolicyTargetRefs(allowed, plainTargetRefs) for _, currTarget := range targetRefs { if !hasSectionName(&currTarget) { @@ -335,15 +333,6 @@ func (t *Translator) ProcessClientTrafficPolicies( } } } - if len(denied) > 0 { - policy, found := handledPolicies[policyName] - if !found { - policy = policyCopies[i] - res = append(res, policy) - handledPolicies[policyName] = policy - } - setPolicyTargetRefNotPermittedStatus(&policy.Status, denied, t.GatewayControllerName, policy.Generation) - } } for _, policy := range res { diff --git a/internal/gatewayapi/contexts.go b/internal/gatewayapi/contexts.go index 60670eebd1..96956810bb 100644 --- a/internal/gatewayapi/contexts.go +++ b/internal/gatewayapi/contexts.go @@ -145,6 +145,10 @@ type ListenerContext struct { namespaceSelector labels.Selector + // specValid indicates whether per-listener spec validation succeeded. + // Conflict detection should only consider listeners with specValid=true. + specValid bool + tls ListenerTLSConfig httpIR *ir.HTTPListener diff --git a/internal/gatewayapi/envoyextensionpolicy.go b/internal/gatewayapi/envoyextensionpolicy.go index 030138cdb6..83ed3b96ed 100644 --- a/internal/gatewayapi/envoyextensionpolicy.go +++ b/internal/gatewayapi/envoyextensionpolicy.go @@ -136,16 +136,14 @@ func (t *Translator) ProcessEnvoyExtensionPolicies( // Process the policies targeting xRoutes for i, currPolicy := range envoyExtensionPolicies { policyName := utils.NamespacedName(currPolicy) - allowed, denied := resolvePolicyTargetsFromSelectors( - currPolicy.Spec.TargetSelectors, + targetRefs := resolvePolicyTargets( + currPolicy.Spec.PolicyTargetReferences, routes, resources.ReferenceGrants, egv1a1.GroupName, egv1a1.KindEnvoyExtensionPolicy, currPolicy.Namespace, t.GetNamespace) - plainTargetRefs := resolvePolicyTargetsFromReferences(currPolicy.Spec.PolicyTargetReferences, currPolicy.Namespace) - targetRefs := composePolicyTargetRefs(allowed, plainTargetRefs) for _, currTarget := range targetRefs { if isRoute(currTarget) { policy, found := handledPolicies[policyName] @@ -159,15 +157,6 @@ func (t *Translator) ProcessEnvoyExtensionPolicies( routeMap, gatewayRouteMap, policy, currTarget) } } - if len(denied) > 0 { - policy, found := handledPolicies[policyName] - if !found { - policy = policyCopies[i] - res = append(res, policy) - handledPolicies[policyName] = policy - } - setPolicyTargetRefNotPermittedStatus(&policy.Status, denied, t.GatewayControllerName, policy.Generation) - } } // Process the policies targeting Listeners @@ -193,16 +182,14 @@ func (t *Translator) ProcessEnvoyExtensionPolicies( // Process the policies targeting Gateways for i, currPolicy := range envoyExtensionPolicies { policyName := utils.NamespacedName(currPolicy) - allowed, denied := resolvePolicyTargetsFromSelectors( - currPolicy.Spec.TargetSelectors, + targetRefs := resolvePolicyTargets( + currPolicy.Spec.PolicyTargetReferences, gateways, resources.ReferenceGrants, egv1a1.GroupName, egv1a1.KindEnvoyExtensionPolicy, currPolicy.Namespace, t.GetNamespace) - plainTargetRefs := resolvePolicyTargetsFromReferences(currPolicy.Spec.PolicyTargetReferences, currPolicy.Namespace) - targetRefs := composePolicyTargetRefs(allowed, plainTargetRefs) for _, currTarget := range targetRefs { if isGateway(currTarget) { policy, found := handledPolicies[policyName] @@ -216,15 +203,6 @@ func (t *Translator) ProcessEnvoyExtensionPolicies( gatewayMap, gatewayRouteMap, policy, currTarget) } } - if len(denied) > 0 { - policy, found := handledPolicies[policyName] - if !found { - policy = policyCopies[i] - res = append(res, policy) - handledPolicies[policyName] = policy - } - setPolicyTargetRefNotPermittedStatus(&policy.Status, denied, t.GatewayControllerName, policy.Generation) - } } for _, policy := range res { diff --git a/internal/gatewayapi/helpers.go b/internal/gatewayapi/helpers.go index a4aa6eab9b..ade73750e4 100644 --- a/internal/gatewayapi/helpers.go +++ b/internal/gatewayapi/helpers.go @@ -27,7 +27,6 @@ import ( egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1" "github.com/envoyproxy/gateway/internal/gatewayapi/resource" - "github.com/envoyproxy/gateway/internal/gatewayapi/status" "github.com/envoyproxy/gateway/internal/ir" "github.com/envoyproxy/gateway/internal/utils" ) @@ -767,11 +766,6 @@ type policyTargetReferenceWithSectionName struct { SectionName *gwapiv1.SectionName `json:"sectionName,omitempty"` } -type policySelectedTarget[T client.Object] struct { - Target T - Ref policyTargetReferenceWithSectionName -} - func isRouteRule(target policyTargetReferenceWithSectionName) bool { // If the target is not a gateway and the section name is not nil, then it's a route rule. return target.Kind != resource.KindGateway && target.SectionName != nil @@ -899,7 +893,7 @@ func isCrossNamespaceReferencePermitted( return false } -// resolvePolicyTargetsFromSelectors returns a list of policy target refs that are allowed and denied by the policy's TargetSelectors. +// resolvePolicyTargetsFromSelectors returns policy target refs allowed by the policy's TargetSelectors. func resolvePolicyTargetsFromSelectors[T client.Object]( targetSelectors []egv1a1.TargetSelector, potentialTargets []T, @@ -908,9 +902,9 @@ func resolvePolicyTargetsFromSelectors[T client.Object]( policyKind string, policyNamespace string, namespaceLookup func(string) *corev1.Namespace, -) (allowed, denied []policySelectedTarget[T]) { +) []targetRefWithTimestamp { allowedDedup := sets.New[targetRefWithTimestamp]() - deniedDedup := sets.New[policyTargetReferenceWithSectionName]() + targetRefs := make([]targetRefWithTimestamp, 0) for _, currSelector := range targetSelectors { labelSelector := selectorFromTargetSelector(currSelector) for _, obj := range potentialTargets { @@ -952,14 +946,6 @@ func resolvePolicyTargetsFromSelectors[T client.Object]( }, referenceGrants, ) { - if deniedDedup.Has(ref) { - continue - } - deniedDedup.Insert(ref) - denied = append(denied, policySelectedTarget[T]{ - Target: obj, - Ref: ref, - }) continue } @@ -971,14 +957,11 @@ func resolvePolicyTargetsFromSelectors[T client.Object]( continue } allowedDedup.Insert(targetRef) - allowed = append(allowed, policySelectedTarget[T]{ - Target: obj, - Ref: ref, - }) + targetRefs = append(targetRefs, targetRef) } } - return allowed, denied + return targetRefs } // resolvePolicyTargetsFromReferences returns a list of policy target refs specified in the policy's TargetRefs, with the namespace field populated. @@ -1007,23 +990,16 @@ func resolvePolicyTargetsFromReferences( } // composePolicyTargetRefs combines the allowed target refs derived from the selectors and the plain target refs specified in the policy. -func composePolicyTargetRefs[T client.Object]( - matches []policySelectedTarget[T], +func composePolicyTargetRefs( + selectorTargetRefs []targetRefWithTimestamp, plainTargetRefs []policyTargetReferenceWithSectionName, ) []policyTargetReferenceWithSectionName { // First add the target refs derived from the selectors, sorted by the creation timestamp of the matched objects. - selectorsList := make([]targetRefWithTimestamp, 0, len(matches)) - for _, match := range matches { - selectorsList = append(selectorsList, targetRefWithTimestamp{ - CreationTimestamp: match.Target.GetCreationTimestamp(), - policyTargetReferenceWithSectionName: match.Ref, - }) - } - slices.SortFunc(selectorsList, func(i, j targetRefWithTimestamp) int { + slices.SortFunc(selectorTargetRefs, func(i, j targetRefWithTimestamp) int { return i.CreationTimestamp.Compare(j.CreationTimestamp.Time) }) - ret := make([]policyTargetReferenceWithSectionName, len(selectorsList)) - for i, v := range selectorsList { + ret := make([]policyTargetReferenceWithSectionName, len(selectorTargetRefs)) + for i, v := range selectorTargetRefs { ret[i] = v.policyTargetReferenceWithSectionName } @@ -1051,7 +1027,7 @@ func resolvePolicyTargets[T client.Object]( policyNamespace string, namespaceLookup func(string) *corev1.Namespace, ) []policyTargetReferenceWithSectionName { - allowed, _ := resolvePolicyTargetsFromSelectors( + selectorTargetRefs := resolvePolicyTargetsFromSelectors( targetRefs.TargetSelectors, potentialTargets, referenceGrants, @@ -1060,77 +1036,7 @@ func resolvePolicyTargets[T client.Object]( policyNamespace, namespaceLookup) plainTargetRefs := resolvePolicyTargetsFromReferences(targetRefs, policyNamespace) - return composePolicyTargetRefs(allowed, plainTargetRefs) -} - -func setPolicyTargetRefNotPermittedStatus[T client.Object]( - policyStatus *gwapiv1.PolicyStatus, - denied []policySelectedTarget[T], - controllerName string, - generation int64, -) { - for _, deniedMatch := range denied { - msg := fmt.Sprintf( - "Target %s %s/%s is not permitted by any ReferenceGrant.", - deniedMatch.Target.GetObjectKind().GroupVersionKind().Kind, - deniedMatch.Target.GetNamespace(), - deniedMatch.Target.GetName(), - ) - - switch obj := any(deniedMatch.Target).(type) { - case *GatewayContext: - ancestorRef := getAncestorRefForPolicy(utils.NamespacedName(obj), nil) - setPolicyTargetRefNotPermittedStatusForAncestor(policyStatus, &ancestorRef, controllerName, generation, msg) - case RouteContext: - parentRefs := GetManagedParentReferences(obj) - ancestorRefs := make([]*gwapiv1.ParentReference, 0, len(parentRefs)) - for _, p := range parentRefs { - if p.Kind != nil && *p.Kind != resource.KindGateway { - continue - } - namespace := obj.GetNamespace() - if p.Namespace != nil { - namespace = string(*p.Namespace) - } - ancestorRef := getAncestorRefForPolicy(types.NamespacedName{ - Name: string(p.Name), - Namespace: namespace, - }, p.SectionName) - ancestorRefs = append(ancestorRefs, &ancestorRef) - } - for _, ancestorRef := range ancestorRefs { - setPolicyTargetRefNotPermittedStatusForAncestor(policyStatus, ancestorRef, controllerName, generation, msg) - } - } - } -} - -func setPolicyTargetRefNotPermittedStatusForAncestor( - policyStatus *gwapiv1.PolicyStatus, - ancestorRef *gwapiv1.ParentReference, - controllerName string, - generation int64, - message string, -) { - // If an ancestor has at least one effective target: Accepted=True, - // If some targets under that same ancestor were skipped due to missing ReferenceGrant: add Warning=True, reason RefNotPermitted. - if status.IsPolicyAncestorAccepted(policyStatus, ancestorRef, controllerName) { - status.SetWarningForPolicyAncestor( - policyStatus, - ancestorRef, - controllerName, - egv1a1.PolicyReasonRefNotPermitted, - message, - generation, - ) - return - } - - // If an ancestor has no effective target due to all targets being skipped by missing ReferenceGrant, the policy should be Rejected with reason RefNotPermitted. - status.SetResolveErrorForPolicyAncestor(policyStatus, ancestorRef, controllerName, generation, &status.PolicyResolveError{ - Reason: egv1a1.PolicyReasonRefNotPermitted, - Message: message, - }) + return composePolicyTargetRefs(selectorTargetRefs, plainTargetRefs) } // legacy function to get policy target refs without considering cross-namespace policy attachment. diff --git a/internal/gatewayapi/listener.go b/internal/gatewayapi/listener.go index 78d59e5718..da6b3f119c 100644 --- a/internal/gatewayapi/listener.go +++ b/internal/gatewayapi/listener.go @@ -219,9 +219,84 @@ func validClientCertificateRef(ref *gwapiv1.SecretObjectReference) error { return nil } +// allowedRouteKindsForProtocol returns the route kinds supported by the given listener protocol. +func allowedRouteKindsForProtocol(protocol gwapiv1.ProtocolType, tlsMode *gwapiv1.TLSModeType) []gwapiv1.Kind { + switch protocol { + case gwapiv1.HTTPProtocolType, gwapiv1.HTTPSProtocolType: + return []gwapiv1.Kind{resource.KindHTTPRoute, resource.KindGRPCRoute} + case gwapiv1.TLSProtocolType: + if tlsMode != nil && *tlsMode == gwapiv1.TLSModePassthrough { + return []gwapiv1.Kind{resource.KindTLSRoute} + } + // Terminate mode or unspecified defaults to accept both TCP and TLS routes + return []gwapiv1.Kind{resource.KindTCPRoute, resource.KindTLSRoute} + case gwapiv1.TCPProtocolType: + return []gwapiv1.Kind{resource.KindTCPRoute} + case gwapiv1.UDPProtocolType: + return []gwapiv1.Kind{resource.KindUDPRoute} + default: + return nil + } +} + +func (t *Translator) validateListenerSpec(listener *ListenerContext, resources *resource.Resources) bool { + // Validate listener spec directly without relying on conditions. + // Start with valid assumption and invalidate on failures. + // Phase 1: Validate fundamental rules + specValid := t.validateAllowedNamespaces(listener) + + // Phase 2: Validate allowed routes based on protocol + if isSupportedListenerProtocol(listener.Protocol) { + var tlsMode *gwapiv1.TLSModeType + if listener.TLS != nil { + tlsMode = listener.TLS.Mode + } + allowedKinds := allowedRouteKindsForProtocol(listener.Protocol, tlsMode) + if !t.validateAllowedRoutes(listener, allowedKinds...) { + specValid = false + } + } else { + // Unsupported protocol + specValid = false + listener.SetSupportedKinds() + listener.SetCondition( + gwapiv1.ListenerConditionAccepted, + metav1.ConditionFalse, + gwapiv1.ListenerReasonUnsupportedProtocol, + fmt.Sprintf("Protocol %s is unsupported, must be %s, %s, %s or %s.", listener.Protocol, + gwapiv1.HTTPProtocolType, gwapiv1.HTTPSProtocolType, gwapiv1.TCPProtocolType, gwapiv1.UDPProtocolType), + ) + } + + // Phase 3: Validate TLS configuration details + if !t.validateTLSConfiguration(listener, resources) { + specValid = false + } + + // Phase 4: Validate Hostname configuration + if !t.validateHostName(listener) { + specValid = false + } + + return specValid +} + func (t *Translator) ProcessListeners(gateways []*GatewayContext, xdsIR resource.XdsIRMap, infraIR resource.InfraIRMap, resources *resource.Resources) { // Infra IR proxy ports must be unique. foundPorts := make(map[string][]*protocolPort) + + // Phase 1: Validate each listener's spec independently. + // This must happen before conflict resolution so that invalid listeners + // don't block valid ones during conflict detection. + for _, gateway := range gateways { + for _, listener := range gateway.listeners { + listener.specValid = t.validateListenerSpec(listener, resources) + } + } + + // Phase 2: Run conflict detection. + // Only listeners that haven't been marked as invalid will participate in conflict resolution. + t.validateConflictedProtocolsListeners(gateways) t.validateConflictedLayer7Listeners(gateways) t.validateConflictedLayer4Listeners(gateways, gwapiv1.TCPProtocolType) t.validateConflictedLayer4Listeners(gateways, gwapiv1.UDPProtocolType) @@ -229,9 +304,7 @@ func (t *Translator) ProcessListeners(gateways []*GatewayContext, xdsIR resource t.validateConflictedMergedListeners(gateways) } - // Iterate through all listeners to validate spec - // and compute status for each, and add valid ones - // to the Xds IR. + // Phase 3: Build IR for valid listeners. for _, gateway := range gateways { irKey := t.getIRKey(gateway.Gateway) @@ -242,49 +315,12 @@ func (t *Translator) ProcessListeners(gateways []*GatewayContext, xdsIR resource t.processProxyObservability(gateway, xdsIR[irKey], infraIR[irKey].Proxy, resources) for _, listener := range gateway.listeners { - // Process protocol & supported kinds - switch listener.Protocol { - case gwapiv1.TLSProtocolType: - if listener.TLS != nil { - switch *listener.TLS.Mode { - case gwapiv1.TLSModePassthrough: - t.validateAllowedRoutes(listener, resource.KindTLSRoute) - case gwapiv1.TLSModeTerminate: - t.validateAllowedRoutes(listener, resource.KindTCPRoute, resource.KindTLSRoute) - default: - t.validateAllowedRoutes(listener, resource.KindTCPRoute, resource.KindTLSRoute) - } - } else { - t.validateAllowedRoutes(listener, resource.KindTCPRoute, resource.KindTLSRoute) - } - case gwapiv1.HTTPProtocolType, gwapiv1.HTTPSProtocolType: - t.validateAllowedRoutes(listener, resource.KindHTTPRoute, resource.KindGRPCRoute) - case gwapiv1.TCPProtocolType: - t.validateAllowedRoutes(listener, resource.KindTCPRoute) - case gwapiv1.UDPProtocolType: - t.validateAllowedRoutes(listener, resource.KindUDPRoute) - default: - listener.SetSupportedKinds() - listener.SetCondition( - gwapiv1.ListenerConditionAccepted, - metav1.ConditionFalse, - gwapiv1.ListenerReasonUnsupportedProtocol, - fmt.Sprintf("Protocol %s is unsupported, must be %s, %s, %s or %s.", listener.Protocol, - gwapiv1.HTTPProtocolType, gwapiv1.HTTPSProtocolType, gwapiv1.TCPProtocolType, gwapiv1.UDPProtocolType), - ) - } - - // Validate allowed namespaces - t.validateAllowedNamespaces(listener) - - // Process TLS configuration - t.validateTLSConfiguration(listener, resources) - - // Process Hostname configuration - t.validateHostName(listener) - - // Process conditions and check if the listener is ready + // Finalize listener conditions and check readiness. t.validateListenerConditions(listener) + if !listener.IsReady() { + // Skip invalid listeners from IR building + continue + } // Skip listeners with invalid frontend TLS validation as they are not functional. if listener.frontendTLSValidationInvalid() { @@ -427,10 +463,18 @@ func checkOverlappingHostnames(httpsListeners []*ListenerContext) { if overlappingListeners[i] != nil { continue } + // Skip listeners that are already marked as invalid from per-listener validation + if hasInvalidCondition(httpsListeners[i]) { + continue + } for j := i + 1; j < len(httpsListeners); j++ { if overlappingListeners[j] != nil { continue } + // Skip listeners that are already marked as invalid from per-listener validation + if hasInvalidCondition(httpsListeners[j]) { + continue + } if httpsListeners[i].Port != httpsListeners[j].Port { continue } @@ -464,14 +508,14 @@ func checkOverlappingHostnames(httpsListeners []*ListenerContext) { if gateway1.Name == gateway2.Name && gateway1.Namespace == gateway2.Namespace { message = fmt.Sprintf( - "The hostname %s overlaps with the hostname %s in listener %s. ALPN will default to HTTP/1.1 to prevent HTTP/2 connection coalescing, unless explicitly configured via ClientTrafficPolicy", + "The hostname %s overlaps with the hostname %s in listener %s.", overlappingListeners[i].hostname1, overlappingListeners[i].hostname2, overlappingListeners[i].listener2, ) } else { message = fmt.Sprintf( - "The hostname %s overlaps with the hostname %s in listener %s of gateway %s. ALPN will default to HTTP/1.1 to prevent HTTP/2 connection coalescing, unless explicitly configured via ClientTrafficPolicy", + "The hostname %s overlaps with the hostname %s in listener %s of gateway %s.", overlappingListeners[i].hostname1, overlappingListeners[i].hostname2, overlappingListeners[i].listener2, @@ -485,9 +529,6 @@ func checkOverlappingHostnames(httpsListeners []*ListenerContext) { gwapiv1.ListenerReasonOverlappingHostnames, message, ) - if listener.httpIR != nil { - listener.httpIR.TLSOverlaps = true - } } } } @@ -509,10 +550,18 @@ func checkOverlappingCertificates(httpsListeners []*ListenerContext) { if overlappingListeners[i] != nil { continue } + // Skip listeners that are already marked as invalid from per-listener validation + if hasInvalidCondition(httpsListeners[i]) { + continue + } for j := i + 1; j < len(httpsListeners); j++ { if overlappingListeners[j] != nil { continue } + // Skip listeners that are already marked as invalid from per-listener validation + if hasInvalidCondition(httpsListeners[j]) { + continue + } if httpsListeners[i].Port != httpsListeners[j].Port { continue } diff --git a/internal/gatewayapi/listener_test.go b/internal/gatewayapi/listener_test.go index 40094dfa6b..ca753c1bbf 100644 --- a/internal/gatewayapi/listener_test.go +++ b/internal/gatewayapi/listener_test.go @@ -385,6 +385,7 @@ func TestCheckOverlappingHostnames(t *testing.T) { for i := range tt.gateway.listeners { tt.gateway.listeners[i].listenerStatusIdx = i tt.gateway.listeners[i].gateway = tt.gateway + tt.gateway.listeners[i].httpIR = &ir.HTTPListener{} tt.gateway.Status.Listeners[i] = gwapiv1.ListenerStatus{ Name: tt.gateway.listeners[i].Name, Conditions: []metav1.Condition{}, @@ -420,6 +421,10 @@ func TestCheckOverlappingHostnames(t *testing.T) { t.Errorf("expected condition for listener %d, got nil or False", idx) } } + for idx, listener := range tt.gateway.listeners { + require.NotNil(t, listener.httpIR) + assert.False(t, listener.httpIR.TLSOverlaps, "hostname overlap must not trigger ALPN downgrade for listener %d", idx) + } if len(tt.expected) == 0 { if len(tt.gateway.Status.Listeners) != 0 { @@ -647,6 +652,7 @@ func TestCheckOverlappingCertificates(t *testing.T) { } gateway.listeners[i].listenerStatusIdx = i gateway.listeners[i].gateway = gateway + gateway.listeners[i].httpIR = &ir.HTTPListener{} } // Process overlapping certificates @@ -700,6 +706,15 @@ func TestCheckOverlappingCertificates(t *testing.T) { } } } + + expectedTLSOverlaps := map[string]bool{} + for _, expected := range tt.expectedStatus { + expectedTLSOverlaps[expected.listenerName] = true + } + for _, listener := range gateway.listeners { + require.NotNil(t, listener.httpIR) + assert.Equal(t, expectedTLSOverlaps[string(listener.Name)], listener.httpIR.TLSOverlaps, "unexpected TLSOverlaps for listener %s", listener.Name) + } }) } } diff --git a/internal/gatewayapi/listenerset.go b/internal/gatewayapi/listenerset.go index 68cdb575ed..03cbfebcac 100644 --- a/internal/gatewayapi/listenerset.go +++ b/internal/gatewayapi/listenerset.go @@ -113,48 +113,69 @@ func (t *Translator) ProcessListenerSetStatus(listenerSets []*gwapiv1.ListenerSe } // Calculate status based on listeners - allListenersValid := true - anyListenerValid := false + allListenersAccepted := true + anyListenerAccepted := false + allListenersProgrammed := true + anyListenerProgrammed := false for _, lStatus := range ls.Status.Listeners { accepted := false + programmed := false for _, cond := range lStatus.Conditions { if cond.Type == string(gwapiv1.ListenerEntryConditionAccepted) && cond.Status == metav1.ConditionTrue { accepted = true - break + } + if cond.Type == string(gwapiv1.ListenerConditionProgrammed) && cond.Status == metav1.ConditionTrue { + programmed = true } } - anyListenerValid = anyListenerValid || accepted - allListenersValid = allListenersValid && accepted + anyListenerAccepted = anyListenerAccepted || accepted + allListenersAccepted = allListenersAccepted && accepted + anyListenerProgrammed = anyListenerProgrammed || programmed + allListenersProgrammed = allListenersProgrammed && programmed } var ( lsAccepted bool - lsReason gwapiv1.ListenerSetConditionReason + lsAcceptedReason gwapiv1.ListenerSetConditionReason + lsAcceptedMsg string + lsProgrammed bool lsProgrammedReason gwapiv1.ListenerSetConditionReason - lsMsg string + lsProgrammedMsg string ) switch { - case allListenersValid: + case allListenersAccepted: lsAccepted = true - lsReason = gwapiv1.ListenerSetReasonAccepted - lsProgrammedReason = gwapiv1.ListenerSetReasonProgrammed - lsMsg = "All listeners are valid" - case anyListenerValid: // TODO: implement PartiallyInvalid conditions when Gateway API supports it + lsAcceptedReason = gwapiv1.ListenerSetReasonAccepted + lsAcceptedMsg = "All listeners are accepted" + case anyListenerAccepted: // TODO: implement PartiallyInvalid conditions when Gateway API supports it lsAccepted = true - lsReason = gwapiv1.ListenerSetReasonListenersNotValid - lsProgrammedReason = gwapiv1.ListenerSetReasonProgrammed - lsMsg = "Some listeners are invalid" + lsAcceptedReason = gwapiv1.ListenerSetReasonListenersNotValid + lsAcceptedMsg = "Some listeners are invalid" default: lsAccepted = false - lsReason = gwapiv1.ListenerSetReasonListenersNotValid + lsAcceptedReason = gwapiv1.ListenerSetReasonListenersNotValid + lsAcceptedMsg = "No listeners are accepted" + } + + switch { + case allListenersProgrammed: + lsProgrammed = true + lsProgrammedReason = gwapiv1.ListenerSetReasonProgrammed + lsProgrammedMsg = "All listeners are programmed" + case anyListenerProgrammed: + lsProgrammed = true + lsProgrammedReason = gwapiv1.ListenerSetReasonProgrammed + lsProgrammedMsg = "Some listeners are not programmed" + default: + lsProgrammed = false lsProgrammedReason = gwapiv1.ListenerSetReasonListenersNotValid - lsMsg = "All listeners are invalid" + lsProgrammedMsg = "No listeners are programmed" } - status.UpdateListenerSetStatusAccepted(ls, lsAccepted, lsReason, lsMsg) - status.UpdateListenerSetStatusProgrammed(ls, lsAccepted, lsProgrammedReason, lsMsg) + status.UpdateListenerSetStatusAccepted(ls, lsAccepted, lsAcceptedReason, lsAcceptedMsg) + status.UpdateListenerSetStatusProgrammed(ls, lsProgrammed, lsProgrammedReason, lsProgrammedMsg) } } diff --git a/internal/gatewayapi/route.go b/internal/gatewayapi/route.go index 4c86bcc38c..da63bf2acf 100644 --- a/internal/gatewayapi/route.go +++ b/internal/gatewayapi/route.go @@ -2287,7 +2287,7 @@ func (t *Translator) processAllowedListenersForParentRefs( } parentRefCtx.SetListeners(allowedListeners...) - if !HasReadyListener(selectedListeners) { + if !HasReadyListener(allowedListeners) { routeStatus := GetRouteStatus(routeContext) status.SetRouteStatusCondition(routeStatus, parentRefCtx.routeParentStatusIdx, diff --git a/internal/gatewayapi/runner/runner.go b/internal/gatewayapi/runner/runner.go index e5b6f21c4a..e8ed6f5e56 100644 --- a/internal/gatewayapi/runner/runner.go +++ b/internal/gatewayapi/runner/runner.go @@ -190,6 +190,8 @@ func (r *Runner) subscribeAndTranslate(sub <-chan watchable.Snapshot[string, *re r.Logger, message.Metadata{Runner: r.Name(), Message: message.ProviderResourcesMessageName}, sub, func(update message.Update[string, *resource.ControllerResourcesContext], errChan chan error) { + message.PublishRunnerEventMetric(r.Name(), update.Delete) + parentCtx := context.Background() if update.Value != nil && update.Value.Context != nil { parentCtx = update.Value.Context diff --git a/internal/gatewayapi/securitypolicy.go b/internal/gatewayapi/securitypolicy.go index 9ccea6da60..779634d9ec 100644 --- a/internal/gatewayapi/securitypolicy.go +++ b/internal/gatewayapi/securitypolicy.go @@ -161,16 +161,14 @@ func (t *Translator) ProcessSecurityPolicies( // Process the policies targeting xRoutes (HTTP + TCP) for i, currPolicy := range securityPolicies { policyName := utils.NamespacedName(currPolicy) - allowed, denied := resolvePolicyTargetsFromSelectors( - currPolicy.Spec.TargetSelectors, + targetRefs := resolvePolicyTargets( + currPolicy.Spec.PolicyTargetReferences, routes, resources.ReferenceGrants, egv1a1.GroupName, egv1a1.KindSecurityPolicy, currPolicy.Namespace, t.GetNamespace) - plainTargetRefs := resolvePolicyTargetsFromReferences(currPolicy.Spec.PolicyTargetReferences, currPolicy.Namespace) - targetRefs := composePolicyTargetRefs(allowed, plainTargetRefs) for _, currTarget := range targetRefs { if isRoute(currTarget) { policy, found := handledPolicies[policyName] @@ -183,15 +181,6 @@ func (t *Translator) ProcessSecurityPolicies( t.processSecurityPolicyForRoute(resources, xdsIR, routeMap, gatewayRouteMap, gatewayPolicyMerged, gatewayPolicyMap, policy, currTarget) } } - if len(denied) > 0 { - policy, found := handledPolicies[policyName] - if !found { - policy = policyCopies[i] - handledPolicies[policyName] = policy - res = append(res, policy) - } - setPolicyTargetRefNotPermittedStatus(&policy.Status, denied, t.GatewayControllerName, policy.Generation) - } } // Process the policies targeting Listeners for i, currPolicy := range securityPolicies { @@ -214,16 +203,14 @@ func (t *Translator) ProcessSecurityPolicies( // Process the policies targeting Gateways for i, currPolicy := range securityPolicies { policyName := utils.NamespacedName(currPolicy) - allowed, denied := resolvePolicyTargetsFromSelectors( - currPolicy.Spec.TargetSelectors, + targetRefs := resolvePolicyTargets( + currPolicy.Spec.PolicyTargetReferences, gateways, resources.ReferenceGrants, egv1a1.GroupName, egv1a1.KindSecurityPolicy, currPolicy.Namespace, t.GetNamespace) - plainTargetRefs := resolvePolicyTargetsFromReferences(currPolicy.Spec.PolicyTargetReferences, currPolicy.Namespace) - targetRefs := composePolicyTargetRefs(allowed, plainTargetRefs) for _, currTarget := range targetRefs { if isGateway(currTarget) { @@ -237,15 +224,6 @@ func (t *Translator) ProcessSecurityPolicies( t.processSecurityPolicyForGateway(resources, xdsIR, gatewayMap, gatewayRouteMap, gatewayPolicyMerged, policy, currTarget) } } - if len(denied) > 0 { - policy, found := handledPolicies[policyName] - if !found { - policy = policyCopies[i] - handledPolicies[policyName] = policy - res = append(res, policy) - } - setPolicyTargetRefNotPermittedStatus(&policy.Status, denied, t.GatewayControllerName, policy.Generation) - } } for _, policy := range res { @@ -412,7 +390,7 @@ func (t *Translator) processSecurityPolicyForRoute( // Check if merging is enabled if policy.Spec.MergeType == nil { // No merging - use existing translation logic - if err := t.translateSecurityPolicyForRoute(policy, targetedRoute, currTarget, resources, xdsIR, nil, nil); err != nil { + if err := t.translateSecurityPolicyForRoute(policy, &securityPolicyOwners{}, targetedRoute, currTarget, resources, xdsIR, nil, nil); err != nil { status.SetTranslationErrorForPolicyAncestors(&policy.Status, ancestorRefs, t.GatewayControllerName, @@ -442,7 +420,7 @@ func (t *Translator) processSecurityPolicyForRoute( if gwPolicy == nil && listenerPolicy == nil { // No parent policy found, fall back to current policy - if err := t.translateSecurityPolicyForRoute(policy, targetedRoute, currTarget, resources, xdsIR, &gwNN, &listener.Name); err != nil { + if err := t.translateSecurityPolicyForRoute(policy, &securityPolicyOwners{}, targetedRoute, currTarget, resources, xdsIR, &gwNN, &listener.Name); err != nil { status.SetConditionForPolicyAncestor(&policy.Status, &ancestorRef, t.GatewayControllerName, @@ -461,7 +439,7 @@ func (t *Translator) processSecurityPolicyForRoute( } // Merge with parent policy - mergedPolicy, err := mergeSecurityPolicy(policy, parentPolicy) + mergedPolicy, owners, err := mergeSecurityPolicy(policy, parentPolicy) if err != nil { status.SetConditionForPolicyAncestor(&policy.Status, &ancestorRef, @@ -487,7 +465,7 @@ func (t *Translator) processSecurityPolicyForRoute( } // Apply merged policy - if err := t.translateSecurityPolicyForRoute(mergedPolicy, targetedRoute, currTarget, resources, xdsIR, &gwNN, &listener.Name); err != nil { + if err := t.translateSecurityPolicyForRoute(mergedPolicy, owners, targetedRoute, currTarget, resources, xdsIR, &gwNN, &listener.Name); err != nil { status.SetConditionForPolicyAncestor(&policy.Status, &ancestorRef, t.GatewayControllerName, @@ -865,6 +843,7 @@ func resolveSecurityPolicyRouteTargetRef( func (t *Translator) translateSecurityPolicyForRoute( policy *egv1a1.SecurityPolicy, + owners *securityPolicyOwners, route RouteContext, target policyTargetReferenceWithSectionName, resources *resource.Resources, @@ -889,7 +868,9 @@ func (t *Translator) translateSecurityPolicyForRoute( if policy.Spec.BasicAuth != nil { if basicAuth, err = t.buildBasicAuth( policy, - resources); err != nil { + owners, + resources, + ); err != nil { err = perr.WithMessage(err, "BasicAuth") errs = errors.Join(errs, err) } @@ -898,14 +879,16 @@ func (t *Translator) translateSecurityPolicyForRoute( if policy.Spec.APIKeyAuth != nil { if apiKeyAuth, err = t.buildAPIKeyAuth( policy, - resources); err != nil { + owners, + resources, + ); err != nil { err = perr.WithMessage(err, "APIKeyAuth") errs = errors.Join(errs, err) } } if policy.Spec.Authorization != nil { - if authorization, err = t.buildAuthorization(policy); err != nil { + if authorization, err = t.buildAuthorization(policy, owners); err != nil { err = perr.WithMessage(err, "Authorization") errs = errors.Join(errs, err) } @@ -945,8 +928,10 @@ func (t *Translator) translateSecurityPolicyForRoute( if policy.Spec.ExtAuth != nil { if extAuth, extAuthErr = t.buildExtAuth( policy, + owners, resources, - gtwCtx); extAuthErr != nil { + gtwCtx, + ); extAuthErr != nil { extAuthErr = perr.WithMessage(extAuthErr, "ExtAuth") errs = errors.Join(errs, extAuthErr) } @@ -956,8 +941,10 @@ func (t *Translator) translateSecurityPolicyForRoute( if policy.Spec.OIDC != nil { if oidc, err = t.buildOIDC( policy, + owners, resources, - gtwCtx); err != nil { + gtwCtx, + ); err != nil { err = perr.WithMessage(err, "OIDC") errs = errors.Join(errs, err) hasNonExtAuthError = true @@ -968,8 +955,10 @@ func (t *Translator) translateSecurityPolicyForRoute( if policy.Spec.JWT != nil { if jwt, err = t.buildJWT( policy, + owners, resources, - gtwCtx); err != nil { + gtwCtx, + ); err != nil { err = perr.WithMessage(err, "JWT") errs = errors.Join(errs, err) hasNonExtAuthError = true @@ -1097,6 +1086,7 @@ func (t *Translator) translateSecurityPolicyForGateway( xdsIR resource.XdsIRMap, ) error { // Build IR + noOwners := &securityPolicyOwners{} var ( cors *ir.CORS jwt *ir.JWT @@ -1116,8 +1106,10 @@ func (t *Translator) translateSecurityPolicyForGateway( if policy.Spec.JWT != nil { if jwt, err = t.buildJWT( policy, + noOwners, resources, - gtwCtx); err != nil { + gtwCtx, + ); err != nil { err = perr.WithMessage(err, "JWT") errs = errors.Join(errs, err) } @@ -1126,8 +1118,10 @@ func (t *Translator) translateSecurityPolicyForGateway( if policy.Spec.OIDC != nil { if oidc, err = t.buildOIDC( policy, + noOwners, resources, - gtwCtx); err != nil { + gtwCtx, + ); err != nil { err = perr.WithMessage(err, "OIDC") errs = errors.Join(errs, err) } @@ -1136,7 +1130,9 @@ func (t *Translator) translateSecurityPolicyForGateway( if policy.Spec.BasicAuth != nil { if basicAuth, err = t.buildBasicAuth( policy, - resources); err != nil { + noOwners, + resources, + ); err != nil { err = perr.WithMessage(err, "BasicAuth") errs = errors.Join(errs, err) } @@ -1145,14 +1141,16 @@ func (t *Translator) translateSecurityPolicyForGateway( if policy.Spec.APIKeyAuth != nil { if apiKeyAuth, err = t.buildAPIKeyAuth( policy, - resources); err != nil { + noOwners, + resources, + ); err != nil { err = perr.WithMessage(err, "APIKeyAuth") errs = errors.Join(errs, err) } } if policy.Spec.Authorization != nil { - if authorization, err = t.buildAuthorization(policy); err != nil { + if authorization, err = t.buildAuthorization(policy, noOwners); err != nil { errs = errors.Join(errs, err) } } @@ -1162,8 +1160,10 @@ func (t *Translator) translateSecurityPolicyForGateway( if policy.Spec.ExtAuth != nil { if extAuth, extAuthErr = t.buildExtAuth( policy, + noOwners, resources, - gtwCtx); extAuthErr != nil { + gtwCtx, + ); extAuthErr != nil { extAuthErr = perr.WithMessage(extAuthErr, "ExtAuth") errs = errors.Join(errs, extAuthErr) } @@ -1337,6 +1337,7 @@ func wildcard2regex(wildcard string) string { func (t *Translator) buildJWT( policy *egv1a1.SecurityPolicy, + owners *securityPolicyOwners, resources *resource.Resources, gtwCtx *GatewayContext, ) (*ir.JWT, error) { @@ -1344,6 +1345,7 @@ func (t *Translator) buildJWT( return nil, err } + jwtOwnerPolicy := policyOwnerOr(owners.jwtProviders, policy) providers := make([]ir.JWTProvider, 0, len(policy.Spec.JWT.Providers)) for i, p := range policy.Spec.JWT.Providers { provider := ir.JWTProvider{ @@ -1355,13 +1357,13 @@ func (t *Translator) buildJWT( ExtractFrom: p.ExtractFrom, } if p.RemoteJWKS != nil { - remoteJWKS, err := t.buildRemoteJWKS(policy, p.RemoteJWKS, i, resources, gtwCtx) + remoteJWKS, err := t.buildRemoteJWKS(jwtOwnerPolicy, p.RemoteJWKS, i, resources, gtwCtx) if err != nil { return nil, err } provider.RemoteJWKS = remoteJWKS } else { - localJWKS, err := t.buildLocalJWKS(policy, p.LocalJWKS) + localJWKS, err := t.buildLocalJWKS(jwtOwnerPolicy, p.LocalJWKS) if err != nil { return nil, err } @@ -1552,6 +1554,7 @@ func (t *Translator) buildLocalJWKS( func (t *Translator) buildOIDC( policy *egv1a1.SecurityPolicy, + owners *securityPolicyOwners, resources *resource.Resources, gtwCtx *GatewayContext, ) (*ir.OIDC, error) { @@ -1570,21 +1573,22 @@ func (t *Translator) buildOIDC( err error ) - if provider, err = t.buildOIDCProvider(policy, resources, gtwCtx); err != nil { + if provider, err = t.buildOIDCProvider(policy, owners, resources, gtwCtx); err != nil { return nil, err } - from := crossNamespaceFrom{ - group: egv1a1.GroupName, - kind: resource.KindSecurityPolicy, - namespace: policy.Namespace, - } - // Client ID can be specified either as a string or as a reference to a secret. switch { case oidc.ClientID != nil: clientID = *oidc.ClientID case oidc.ClientIDRef != nil: + ownerPolicy := policyOwnerOr(owners.oidcClientIDRef, policy) + from := crossNamespaceFrom{ + group: egv1a1.GroupName, + kind: resource.KindSecurityPolicy, + namespace: ownerPolicy.Namespace, + } + var clientIDSecret *corev1.Secret if clientIDSecret, err = t.validateSecretRef(true, from, *oidc.ClientIDRef, resources); err != nil { return nil, err @@ -1599,6 +1603,12 @@ func (t *Translator) buildOIDC( return nil, fmt.Errorf("client ID must be specified in OIDC policy %s/%s", policy.Namespace, policy.Name) } + clientSecretOwner := policyOwnerOr(owners.oidcClientSecret, policy) + from := crossNamespaceFrom{ + group: egv1a1.GroupName, + kind: resource.KindSecurityPolicy, + namespace: clientSecretOwner.Namespace, + } if clientSecret, err = t.validateSecretRef(true, from, oidc.ClientSecret, resources); err != nil { return nil, err } @@ -1637,10 +1647,12 @@ func (t *Translator) buildOIDC( disableTokenEncryption = *oidc.DisableTokenEncryption } + oidcOwner := policyOwnerOr(owners.oidc, policy) + // Generate a unique cookie suffix for oauth filters. // This is to avoid cookie name collision when multiple security policies are applied // to the same route. - suffix := utils.Digest32(string(policy.UID)) + suffix := utils.Digest32(string(oidcOwner.UID)) // Get the HMAC secret. // HMAC secret is generated by the CertGen job and stored in a secret @@ -1657,7 +1669,7 @@ func (t *Translator) buildOIDC( } irOIDC := &ir.OIDC{ - Name: irConfigName(policy), + Name: irConfigName(oidcOwner), Provider: *provider, ClientID: clientID, ClientSecret: clientSecretBytes, @@ -1707,6 +1719,7 @@ func (t *Translator) buildOIDC( func (t *Translator) buildOIDCProvider( policy *egv1a1.SecurityPolicy, + owners *securityPolicyOwners, resources *resource.Resources, gtwCtx *GatewayContext, ) (*ir.OIDCProvider, error) { @@ -1739,9 +1752,10 @@ func (t *Translator) buildOIDCProvider( protocol = ir.HTTP } + oidcProviderOwner := policyOwnerOr(owners.oidcProviderBackendRefs, policy) if len(provider.BackendRefs) > 0 { if rd, err = t.translateExtServiceBackendRefs( - policy, provider.BackendRefs, protocol, resources, gtwCtx, "oidc", 0); err != nil { + oidcProviderOwner, provider.BackendRefs, protocol, resources, gtwCtx, "oidc", 0); err != nil { return nil, err } } @@ -2021,12 +2035,14 @@ func validateTokenEndpoint(tokenEndpoint string) error { func (t *Translator) buildAPIKeyAuth( policy *egv1a1.SecurityPolicy, + owners *securityPolicyOwners, resources *resource.Resources, ) (*ir.APIKeyAuth, error) { + ownerPolicy := policyOwnerOr(owners.apiKeyAuthCredentialRefs, policy) from := crossNamespaceFrom{ group: egv1a1.GroupName, kind: resource.KindSecurityPolicy, - namespace: policy.Namespace, + namespace: ownerPolicy.Namespace, } expected := len(policy.Spec.APIKeyAuth.CredentialRefs) @@ -2077,6 +2093,7 @@ func (t *Translator) buildAPIKeyAuth( func (t *Translator) buildBasicAuth( policy *egv1a1.SecurityPolicy, + owners *securityPolicyOwners, resources *resource.Resources, ) (*ir.BasicAuth, error) { var ( @@ -2085,10 +2102,11 @@ func (t *Translator) buildBasicAuth( err error ) + ownerPolicy := policyOwnerOr(owners.basicAuth, policy) from := crossNamespaceFrom{ group: egv1a1.GroupName, kind: resource.KindSecurityPolicy, - namespace: policy.Namespace, + namespace: ownerPolicy.Namespace, } if usersSecret, err = t.validateSecretRef(true, from, basicAuth.Users, resources); err != nil { return nil, err @@ -2111,7 +2129,7 @@ func (t *Translator) buildBasicAuth( } return &ir.BasicAuth{ - Name: irConfigName(policy), + Name: irConfigName(ownerPolicy), Users: usersSecretBytes, ForwardUsernameHeader: basicAuth.ForwardUsernameHeader, }, nil @@ -2150,6 +2168,7 @@ func validateHtpasswdFormat(data []byte) error { func (t *Translator) buildExtAuth( policy *egv1a1.SecurityPolicy, + owners *securityPolicyOwners, resources *resource.Resources, gtwCtx *GatewayContext, ) (*ir.ExtAuth, error) { @@ -2166,6 +2185,8 @@ func (t *Translator) buildExtAuth( contextExtensions []*ir.ContextExtention ) + backendRefsOwnerPolicy := policyOwnerOr(owners.extAuthBackendRefs, policy) + // These are sanity checks, they should never happen because the API server // should have caught them if http == nil && grpc == nil { @@ -2210,7 +2231,7 @@ func (t *Translator) buildExtAuth( } if rd, err = t.translateExtServiceBackendRefs( - policy, backendRefs, protocol, resources, gtwCtx, "extauth", 0); err != nil { + backendRefsOwnerPolicy, backendRefs, protocol, resources, gtwCtx, "extauth", 0); err != nil { return nil, err } @@ -2220,7 +2241,7 @@ func (t *Translator) buildExtAuth( // When translated to XDS, the authority is used on the filter level not on the cluster level. // There's no way to translate to XDS and use a different authority for each backendref if authority == "" { - authority = t.backendRefAuthority(&backendRef.BackendObjectReference, policy) + authority = t.backendRefAuthority(&backendRef.BackendObjectReference, backendRefsOwnerPolicy) } } @@ -2228,12 +2249,13 @@ func (t *Translator) buildExtAuth( return nil, err } - if contextExtensions, err = t.buildContextExtensions(policy.Spec.ExtAuth.ContextExtensions, policy.Namespace); err != nil { + if contextExtensions, err = t.buildContextExtensions(policy.Spec.ExtAuth.ContextExtensions, owners, policy); err != nil { return nil, err } + extAuthOwner := policyOwnerOr(owners.extAuth, policy) extAuth := &ir.ExtAuth{ - Name: irConfigName(policy), + Name: irConfigName(extAuthOwner), HeadersToExtAuth: policy.Spec.ExtAuth.HeadersToExtAuth, ContextExtensions: contextExtensions, FailOpen: policy.Spec.ExtAuth.FailOpen, @@ -2284,7 +2306,8 @@ func parseExtAuthTimeout(timeout *gwapiv1.Duration) *metav1.Duration { func (t *Translator) buildContextExtensions( contextExtensions []*egv1a1.ContextExtension, - policyNs string, + owners *securityPolicyOwners, + defaultOwner *egv1a1.SecurityPolicy, ) ([]*ir.ContextExtention, error) { if len(contextExtensions) == 0 { return nil, nil @@ -2294,8 +2317,9 @@ func (t *Translator) buildContextExtensions( for _, ext := range contextExtensions { var value ir.PrivateBytes if ext.Type == egv1a1.ContextExtensionValueTypeValueRef { + ownerPolicy := policyOwnerOr(owners.extAuthContextExtensions[ext.Name], defaultOwner) var err error - if value, err = t.getContextExtensionValueFromRef(ext.ValueRef, policyNs); err != nil { + if value, err = t.getContextExtensionValueFromRef(ext.ValueRef, ownerPolicy.Namespace); err != nil { return nil, err } } else if ext.Value != nil { @@ -2382,7 +2406,10 @@ func (t *Translator) backendRefAuthority( return fmt.Sprintf("%s.%s", backendRef.Name, backendNamespace) } -func (t *Translator) buildAuthorization(policy *egv1a1.SecurityPolicy) (*ir.Authorization, error) { +func (t *Translator) buildAuthorization( + policy *egv1a1.SecurityPolicy, + owners *securityPolicyOwners, +) (*ir.Authorization, error) { var ( authorization = policy.Spec.Authorization irAuth = &ir.Authorization{} @@ -2390,6 +2417,8 @@ func (t *Translator) buildAuthorization(policy *egv1a1.SecurityPolicy) (*ir.Auth defaultAction = egv1a1.AuthorizationActionDeny ) + ownerPolicy := policyOwnerOr(owners.authorizationRules, policy) + if authorization.DefaultAction != nil { defaultAction = *authorization.DefaultAction } @@ -2416,7 +2445,7 @@ func (t *Translator) buildAuthorization(policy *egv1a1.SecurityPolicy) (*ir.Auth if rule.Name != nil && *rule.Name != "" { name = *rule.Name } else { - name = defaultAuthorizationRuleName(policy, i) + name = defaultAuthorizationRuleName(ownerPolicy, i) } irAuth.Rules = append(irAuth.Rules, &ir.AuthorizationRule{ Name: name, @@ -2516,13 +2545,120 @@ func defaultAuthorizationRuleName(policy *egv1a1.SecurityPolicy, index int) stri strconv.Itoa(index)) } +type securityPolicyOwners struct { + basicAuth *egv1a1.SecurityPolicy + apiKeyAuthCredentialRefs *egv1a1.SecurityPolicy + authorizationRules *egv1a1.SecurityPolicy + extAuth *egv1a1.SecurityPolicy + extAuthBackendRefs *egv1a1.SecurityPolicy + extAuthContextExtensions map[string]*egv1a1.SecurityPolicy + oidc *egv1a1.SecurityPolicy + oidcProviderBackendRefs *egv1a1.SecurityPolicy + oidcClientIDRef *egv1a1.SecurityPolicy + oidcClientSecret *egv1a1.SecurityPolicy + jwtProviders *egv1a1.SecurityPolicy +} + +// policyOwnerOr returns owner if non-nil, otherwise fallback. +// Used to resolve per-field owners from securityPolicyOwners: the owner is the policy +// that contributed the field (route overrides parent), falling back to the active policy +// when no merge occurred or the field was not set by either side. +func policyOwnerOr(owner, fallback *egv1a1.SecurityPolicy) *egv1a1.SecurityPolicy { + if owner != nil { + return owner + } + return fallback +} + // mergeSecurityPolicy merges a route-level SecurityPolicy with a parent (Gateway/Listener) SecurityPolicy. -func mergeSecurityPolicy(routePolicy, parentPolicy *egv1a1.SecurityPolicy) (*egv1a1.SecurityPolicy, error) { +func mergeSecurityPolicy(routePolicy, parentPolicy *egv1a1.SecurityPolicy) (*egv1a1.SecurityPolicy, *securityPolicyOwners, error) { if routePolicy.Spec.MergeType == nil || parentPolicy == nil { - return routePolicy, nil + return routePolicy, nil, nil } + mergedPolicy, err := utils.Merge[*egv1a1.SecurityPolicy](parentPolicy, routePolicy, *routePolicy.Spec.MergeType) + if err != nil { + return nil, nil, err + } + return mergedPolicy, buildSecurityPolicyOwners(routePolicy, parentPolicy), nil +} - return utils.Merge(parentPolicy, routePolicy, *routePolicy.Spec.MergeType) +// ownerOf returns route if routeOwns(route) is true, otherwise parent. +// Use this when ownership of a merged field is determined by a single predicate. +func ownerOf( + route, parent *egv1a1.SecurityPolicy, + routeOwns func(*egv1a1.SecurityPolicy) bool, +) *egv1a1.SecurityPolicy { + if routeOwns(route) { + return route + } + return parent +} + +// buildSecurityPolicyOwners determines, for each merged field, which policy +// (route or parent) is considered the owner. The owner is used later to resolve +// references (e.g. Secrets, BackendRefs) scoped to the owning policy's namespace, +// and to derive IR resource names tied to the owning policy. +func buildSecurityPolicyOwners(route, parent *egv1a1.SecurityPolicy) *securityPolicyOwners { + return &securityPolicyOwners{ + basicAuth: ownerOf(route, parent, func(p *egv1a1.SecurityPolicy) bool { + return p.Spec.BasicAuth != nil + }), + apiKeyAuthCredentialRefs: ownerOf(route, parent, func(p *egv1a1.SecurityPolicy) bool { + return p.Spec.APIKeyAuth != nil && len(p.Spec.APIKeyAuth.CredentialRefs) > 0 + }), + authorizationRules: ownerOf(route, parent, func(p *egv1a1.SecurityPolicy) bool { + return p.Spec.Authorization != nil && len(p.Spec.Authorization.Rules) > 0 + }), + extAuth: ownerOf(route, parent, func(p *egv1a1.SecurityPolicy) bool { + return p.Spec.ExtAuth != nil + }), + extAuthBackendRefs: ownerOf(route, parent, func(p *egv1a1.SecurityPolicy) bool { + ea := p.Spec.ExtAuth + if ea == nil { + return false + } + if ea.HTTP != nil && (len(ea.HTTP.BackendRefs) > 0 || ea.HTTP.BackendRef != nil) { + return true + } + if ea.GRPC != nil && (len(ea.GRPC.BackendRefs) > 0 || ea.GRPC.BackendRef != nil) { + return true + } + return false + }), + extAuthContextExtensions: buildExtAuthContextExtensionOwners(route, parent), + oidc: ownerOf(route, parent, func(p *egv1a1.SecurityPolicy) bool { + return p.Spec.OIDC != nil + }), + oidcProviderBackendRefs: ownerOf(route, parent, func(p *egv1a1.SecurityPolicy) bool { + return p.Spec.OIDC != nil && len(p.Spec.OIDC.Provider.BackendRefs) > 0 + }), + oidcClientIDRef: ownerOf(route, parent, func(p *egv1a1.SecurityPolicy) bool { + return p.Spec.OIDC != nil && p.Spec.OIDC.ClientIDRef != nil + }), + oidcClientSecret: ownerOf(route, parent, func(p *egv1a1.SecurityPolicy) bool { + return p.Spec.OIDC != nil + }), + jwtProviders: ownerOf(route, parent, func(p *egv1a1.SecurityPolicy) bool { + return p.Spec.JWT != nil && len(p.Spec.JWT.Providers) > 0 + }), + } +} + +// buildExtAuthContextExtensionOwners returns a per-key owner map for ExtAuth ContextExtensions. +// Parent keys are added first so that route-level extensions take precedence on conflict. +func buildExtAuthContextExtensionOwners(route, parent *egv1a1.SecurityPolicy) map[string]*egv1a1.SecurityPolicy { + owners := make(map[string]*egv1a1.SecurityPolicy) + if parent.Spec.ExtAuth != nil { + for _, ext := range parent.Spec.ExtAuth.ContextExtensions { + owners[ext.Name] = parent + } + } + if route.Spec.ExtAuth != nil { + for _, ext := range route.Spec.ExtAuth.ContextExtensions { + owners[ext.Name] = route + } + } + return owners } // securityPolicyCopiesWithStatusDeepCopy returns shallow copies with deep-copied Status fields. diff --git a/internal/gatewayapi/securitypolicy_test.go b/internal/gatewayapi/securitypolicy_test.go index 5ef480a1cb..189db2ff32 100644 --- a/internal/gatewayapi/securitypolicy_test.go +++ b/internal/gatewayapi/securitypolicy_test.go @@ -1421,9 +1421,14 @@ func Test_validateAuthorizationGeoIPForHTTP(t *testing.T) { func Test_buildContextExtensions(t *testing.T) { policyNs := "default" + defaultOwner := &egv1a1.SecurityPolicy{ + ObjectMeta: metav1.ObjectMeta{Namespace: policyNs}, + } tests := []struct { name string contextExtensions []*egv1a1.ContextExtension + owners *securityPolicyOwners + defaultOwner *egv1a1.SecurityPolicy translatorContext *TranslatorContext want []*ir.ContextExtention wantErr bool @@ -1431,11 +1436,13 @@ func Test_buildContextExtensions(t *testing.T) { { name: "Nil", contextExtensions: nil, + owners: &securityPolicyOwners{}, want: nil, }, { name: "Empty", contextExtensions: []*egv1a1.ContextExtension{}, + owners: &securityPolicyOwners{}, want: nil, }, { @@ -1443,11 +1450,13 @@ func Test_buildContextExtensions(t *testing.T) { contextExtensions: []*egv1a1.ContextExtension{ {Name: "foo", Value: new("bar")}, }, - want: []*ir.ContextExtention{{Name: "foo", Value: ir.PrivateBytes("bar")}}, + owners: &securityPolicyOwners{}, + want: []*ir.ContextExtention{{Name: "foo", Value: ir.PrivateBytes("bar")}}, }, { name: "TypeValueEmpty", contextExtensions: []*egv1a1.ContextExtension{{Name: "foo"}}, + owners: &securityPolicyOwners{}, want: []*ir.ContextExtention{{Name: "foo", Value: nil}}, }, { @@ -1459,13 +1468,15 @@ func Test_buildContextExtensions(t *testing.T) { Value: new("bar"), }, }, - want: []*ir.ContextExtention{{Name: "foo", Value: ir.PrivateBytes("bar")}}, + owners: &securityPolicyOwners{}, + want: []*ir.ContextExtention{{Name: "foo", Value: ir.PrivateBytes("bar")}}, }, { name: "TypeValueRefNil", contextExtensions: []*egv1a1.ContextExtension{ {Name: "foo", Type: egv1a1.ContextExtensionValueTypeValueRef}, }, + owners: &securityPolicyOwners{}, wantErr: true, }, { @@ -1481,6 +1492,7 @@ func Test_buildContextExtensions(t *testing.T) { Key: "test-key", }, }}, + owners: &securityPolicyOwners{}, translatorContext: &TranslatorContext{}, wantErr: true, }, @@ -1497,6 +1509,7 @@ func Test_buildContextExtensions(t *testing.T) { Key: "test-key", }, }}, + owners: &securityPolicyOwners{}, translatorContext: &TranslatorContext{ ConfigMapMap: map[types.NamespacedName]*corev1.ConfigMap{ {Namespace: policyNs, Name: "test-cm"}: {}, @@ -1517,6 +1530,7 @@ func Test_buildContextExtensions(t *testing.T) { Key: "test-key", }, }}, + owners: &securityPolicyOwners{}, translatorContext: &TranslatorContext{ ConfigMapMap: map[types.NamespacedName]*corev1.ConfigMap{ {Namespace: policyNs, Name: "test-cm"}: { @@ -1526,6 +1540,56 @@ func Test_buildContextExtensions(t *testing.T) { }, want: []*ir.ContextExtention{{Name: "foo", Value: ir.PrivateBytes("bar")}}, }, + { + name: "TypeValueRefUsesPerKeyOwnerNamespace", + contextExtensions: []*egv1a1.ContextExtension{ + { + Name: "parent-only", + Type: egv1a1.ContextExtensionValueTypeValueRef, + ValueRef: &egv1a1.LocalObjectKeyReference{ + LocalObjectReference: gwapiv1.LocalObjectReference{ + Kind: resource.KindConfigMap, + Name: "parent-cm", + }, + Key: "test-key", + }, + }, + { + Name: "route-only", + Type: egv1a1.ContextExtensionValueTypeValueRef, + ValueRef: &egv1a1.LocalObjectKeyReference{ + LocalObjectReference: gwapiv1.LocalObjectReference{ + Kind: resource.KindConfigMap, + Name: "route-cm", + }, + Key: "test-key", + }, + }, + }, + owners: &securityPolicyOwners{ + extAuthContextExtensions: map[string]*egv1a1.SecurityPolicy{ + "parent-only": {ObjectMeta: metav1.ObjectMeta{Namespace: "parent-ns"}}, + "route-only": {ObjectMeta: metav1.ObjectMeta{Namespace: "route-ns"}}, + }, + }, + defaultOwner: &egv1a1.SecurityPolicy{ + ObjectMeta: metav1.ObjectMeta{Namespace: "default-ns"}, + }, + translatorContext: &TranslatorContext{ + ConfigMapMap: map[types.NamespacedName]*corev1.ConfigMap{ + {Namespace: "parent-ns", Name: "parent-cm"}: { + Data: map[string]string{"test-key": "parent-bar"}, + }, + {Namespace: "route-ns", Name: "route-cm"}: { + Data: map[string]string{"test-key": "route-bar"}, + }, + }, + }, + want: []*ir.ContextExtention{ + {Name: "parent-only", Value: ir.PrivateBytes("parent-bar")}, + {Name: "route-only", Value: ir.PrivateBytes("route-bar")}, + }, + }, { name: "TypeValueRefSecretNotFound", contextExtensions: []*egv1a1.ContextExtension{{ @@ -1539,6 +1603,7 @@ func Test_buildContextExtensions(t *testing.T) { Key: "test-key", }, }}, + owners: &securityPolicyOwners{}, translatorContext: &TranslatorContext{}, wantErr: true, }, @@ -1555,6 +1620,7 @@ func Test_buildContextExtensions(t *testing.T) { Key: "test-key", }, }}, + owners: &securityPolicyOwners{}, translatorContext: &TranslatorContext{ SecretMap: map[types.NamespacedName]*corev1.Secret{ {Namespace: policyNs, Name: "test-secret"}: {}, @@ -1575,6 +1641,7 @@ func Test_buildContextExtensions(t *testing.T) { Key: "test-key", }, }}, + owners: &securityPolicyOwners{}, translatorContext: &TranslatorContext{ SecretMap: map[types.NamespacedName]*corev1.Secret{ {Namespace: policyNs, Name: "test-secret"}: { @@ -1597,13 +1664,18 @@ func Test_buildContextExtensions(t *testing.T) { Key: "test-key", }, }}, + owners: &securityPolicyOwners{}, wantErr: true, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { translator := &Translator{TranslatorContext: tt.translatorContext} - got, err := translator.buildContextExtensions(tt.contextExtensions, policyNs) + owner := tt.defaultOwner + if owner == nil { + owner = defaultOwner + } + got, err := translator.buildContextExtensions(tt.contextExtensions, tt.owners, owner) if tt.wantErr { require.Error(t, err) require.Nil(t, got) @@ -1834,7 +1906,7 @@ func TestMergeSecurityPolicy(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := mergeSecurityPolicy(tt.routePolicy, tt.parentPolicy) + got, _, err := mergeSecurityPolicy(tt.routePolicy, tt.parentPolicy) if (err != nil) != tt.wantErr { t.Errorf("mergeSecurityPolicy() error = %v, wantErr %v", err, tt.wantErr) return @@ -1850,3 +1922,142 @@ func TestMergeSecurityPolicy(t *testing.T) { }) } } + +func Test_securityPolicyOwnerChoose(t *testing.T) { + t.Run("route policy overrides parent for the same owner fields", func(t *testing.T) { + parentPolicy := &egv1a1.SecurityPolicy{ + ObjectMeta: metav1.ObjectMeta{Name: "parent", Namespace: "parent-ns"}, + Spec: egv1a1.SecurityPolicySpec{ + BasicAuth: &egv1a1.BasicAuth{ + Users: gwapiv1.SecretObjectReference{Name: "parent-users"}, + }, + APIKeyAuth: &egv1a1.APIKeyAuth{ + CredentialRefs: []gwapiv1.SecretObjectReference{{Name: "parent-cred"}}, + }, + Authorization: &egv1a1.Authorization{ + Rules: []egv1a1.AuthorizationRule{{Name: new("parent-rule")}}, + }, + ExtAuth: &egv1a1.ExtAuth{ + HTTP: &egv1a1.HTTPExtAuthService{ + BackendCluster: egv1a1.BackendCluster{ + BackendRefs: []egv1a1.BackendRef{{ + BackendObjectReference: gwapiv1.BackendObjectReference{Name: "parent-http-backend-refs"}, + }}, + }, + }, + ContextExtensions: []*egv1a1.ContextExtension{ + {Name: "shared", Type: egv1a1.ContextExtensionValueTypeValue, Value: new("parent-shared")}, + {Name: "parent-only", Type: egv1a1.ContextExtensionValueTypeValue, Value: new("parent-only")}, + }, + }, + OIDC: &egv1a1.OIDC{ + ClientSecret: gwapiv1.SecretObjectReference{Name: "parent-client-secret"}, + ClientIDRef: &gwapiv1.SecretObjectReference{Name: "parent-client-id"}, + Provider: egv1a1.OIDCProvider{ + Issuer: "https://parent.example.com", + BackendCluster: egv1a1.BackendCluster{ + BackendRefs: []egv1a1.BackendRef{{ + BackendObjectReference: gwapiv1.BackendObjectReference{Name: "parent-oidc-provider"}, + }}, + }, + }, + }, + JWT: &egv1a1.JWT{ + Providers: []egv1a1.JWTProvider{{Name: "parent-jwt-provider"}}, + }, + }, + } + + routePolicy := &egv1a1.SecurityPolicy{ + ObjectMeta: metav1.ObjectMeta{Name: "route", Namespace: "route-ns"}, + Spec: egv1a1.SecurityPolicySpec{ + MergeType: new(egv1a1.StrategicMerge), + BasicAuth: &egv1a1.BasicAuth{ + Users: gwapiv1.SecretObjectReference{Name: "route-users"}, + }, + APIKeyAuth: &egv1a1.APIKeyAuth{ + CredentialRefs: []gwapiv1.SecretObjectReference{{Name: "route-cred"}}, + }, + Authorization: &egv1a1.Authorization{ + Rules: []egv1a1.AuthorizationRule{{Name: new("route-rule")}}, + }, + ExtAuth: &egv1a1.ExtAuth{ + HTTP: &egv1a1.HTTPExtAuthService{ + BackendCluster: egv1a1.BackendCluster{ + BackendRefs: []egv1a1.BackendRef{{ + BackendObjectReference: gwapiv1.BackendObjectReference{Name: "route-http-backend-refs"}, + }}, + }, + }, + ContextExtensions: []*egv1a1.ContextExtension{ + {Name: "shared", Type: egv1a1.ContextExtensionValueTypeValue, Value: new("route-shared")}, + {Name: "route-only", Type: egv1a1.ContextExtensionValueTypeValue, Value: new("route-only")}, + }, + }, + OIDC: &egv1a1.OIDC{ + ClientSecret: gwapiv1.SecretObjectReference{Name: "route-client-secret"}, + ClientIDRef: &gwapiv1.SecretObjectReference{Name: "route-client-id"}, + Provider: egv1a1.OIDCProvider{ + Issuer: "https://route.example.com", + BackendCluster: egv1a1.BackendCluster{ + BackendRefs: []egv1a1.BackendRef{{ + BackendObjectReference: gwapiv1.BackendObjectReference{Name: "route-oidc-provider"}, + }}, + }, + }, + }, + JWT: &egv1a1.JWT{ + Providers: []egv1a1.JWTProvider{{Name: "route-jwt-provider"}}, + }, + }, + } + + _, owners, err := mergeSecurityPolicy(routePolicy, parentPolicy) + require.NoError(t, err) + require.NotNil(t, owners) + + assert.Same(t, routePolicy, owners.basicAuth) + assert.Same(t, routePolicy, owners.apiKeyAuthCredentialRefs) + assert.Same(t, routePolicy, owners.authorizationRules) + assert.Same(t, routePolicy, owners.extAuth) + assert.Same(t, routePolicy, owners.extAuthBackendRefs) + assert.Same(t, routePolicy, owners.oidc) + assert.Same(t, routePolicy, owners.oidcClientIDRef) + assert.Same(t, routePolicy, owners.oidcClientSecret) + assert.Same(t, routePolicy, owners.oidcProviderBackendRefs) + assert.Same(t, routePolicy, owners.jwtProviders) + assert.Same(t, routePolicy, owners.extAuthContextExtensions["shared"]) + assert.Same(t, routePolicy, owners.extAuthContextExtensions["route-only"]) + assert.Same(t, parentPolicy, owners.extAuthContextExtensions["parent-only"]) + }) + + t.Run("uses parent owner for grpc backend fields when route does not set them", func(t *testing.T) { + parentPolicy := &egv1a1.SecurityPolicy{ + ObjectMeta: metav1.ObjectMeta{Name: "parent", Namespace: "parent-ns"}, + Spec: egv1a1.SecurityPolicySpec{ + MergeType: new(egv1a1.StrategicMerge), + ExtAuth: &egv1a1.ExtAuth{ + GRPC: &egv1a1.GRPCExtAuthService{ + BackendCluster: egv1a1.BackendCluster{ + BackendRefs: []egv1a1.BackendRef{{ + BackendObjectReference: gwapiv1.BackendObjectReference{Name: "parent-grpc-backend-refs"}, + }}, + }, + }, + }, + }, + } + + routePolicy := &egv1a1.SecurityPolicy{ + ObjectMeta: metav1.ObjectMeta{Name: "route", Namespace: "route-ns"}, + Spec: egv1a1.SecurityPolicySpec{MergeType: new(egv1a1.StrategicMerge)}, + } + + _, owners, err := mergeSecurityPolicy(routePolicy, parentPolicy) + require.NoError(t, err) + require.NotNil(t, owners) + + assert.Same(t, parentPolicy, owners.extAuth) + assert.Same(t, parentPolicy, owners.extAuthBackendRefs) + }) +} diff --git a/internal/gatewayapi/status/conditions.go b/internal/gatewayapi/status/conditions.go index 576281cb3a..6de6f4a92f 100644 --- a/internal/gatewayapi/status/conditions.go +++ b/internal/gatewayapi/status/conditions.go @@ -14,9 +14,10 @@ package status import ( - "reflect" "unicode" + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -36,7 +37,7 @@ func MergeConditions(conditions []metav1.Condition, updates ...metav1.Condition) for j := range conditions { if conditions[j].Type == update.Type { add = false - if !reflect.DeepEqual(conditions[j], update) { + if conditionChanged(&conditions[j], &update) { conditions[j].Status = update.Status conditions[j].Reason = update.Reason conditions[j].Message = update.Message @@ -53,6 +54,11 @@ func MergeConditions(conditions []metav1.Condition, updates ...metav1.Condition) return conditions } +func conditionChanged(a, b *metav1.Condition) bool { + opts := cmpopts.IgnoreFields(metav1.Condition{}, "Type", "LastTransitionTime") + return !cmp.Equal(*a, *b, opts) +} + func newCondition(t string, status metav1.ConditionStatus, reason, msg string, og int64) metav1.Condition { return metav1.Condition{ Type: t, diff --git a/internal/gatewayapi/status/conditions_test.go b/internal/gatewayapi/status/conditions_test.go index b3ed1b2912..e43a7c7199 100644 --- a/internal/gatewayapi/status/conditions_test.go +++ b/internal/gatewayapi/status/conditions_test.go @@ -15,7 +15,6 @@ package status import ( "errors" - "reflect" "strings" "testing" @@ -41,6 +40,20 @@ func TestConditionChanged(t *testing.T) { a: metav1.Condition{}, b: metav1.Condition{}, }, + { + name: "condition LastTransitionTime should be ignored", + expected: false, + a: metav1.Condition{ + Type: string(gwapiv1.GatewayClassConditionStatusAccepted), + Status: metav1.ConditionTrue, + LastTransitionTime: metav1.Unix(0, 0), + }, + b: metav1.Condition{ + Type: string(gwapiv1.GatewayClassConditionStatusAccepted), + Status: metav1.ConditionTrue, + LastTransitionTime: metav1.Unix(1, 0), + }, + }, { name: "check condition reason differs", expected: true, @@ -70,7 +83,7 @@ func TestConditionChanged(t *testing.T) { } for _, tc := range testCases { - if got := !reflect.DeepEqual(tc.a, tc.b); got != tc.expected { + if got := conditionChanged(&tc.a, &tc.b); got != tc.expected { assert.Equal(t, tc.expected, got, tc.name) } } diff --git a/internal/gatewayapi/status/policy.go b/internal/gatewayapi/status/policy.go index 715ad7b5d0..6322e42928 100644 --- a/internal/gatewayapi/status/policy.go +++ b/internal/gatewayapi/status/policy.go @@ -82,13 +82,6 @@ func SetAcceptedForPolicyAncestor(policyStatus *gwapiv1.PolicyStatus, ancestorRe gwapiv1.PolicyConditionAccepted, metav1.ConditionTrue, gwapiv1.PolicyReasonAccepted, message, generation) } -func IsPolicyAncestorAccepted(policyStatus *gwapiv1.PolicyStatus, ancestorRef *gwapiv1.ParentReference, controllerName string) bool { - return meta.IsStatusConditionTrue( - policyAncestorConditions(policyStatus, ancestorRef, controllerName), - string(gwapiv1.PolicyConditionAccepted), - ) -} - // SetDeprecatedFieldsWarningForPolicyAncestors sets deprecated fields warning conditions for each ancestor reference. func SetDeprecatedFieldsWarningForPolicyAncestors(policyStatus *gwapiv1.PolicyStatus, ancestorRefs []*gwapiv1.ParentReference, controllerName string, generation int64, deprecatedFields map[string]string) { for _, ancestorRef := range ancestorRefs { @@ -327,16 +320,6 @@ func getPolicyAncestorCondition(policyStatus *gwapiv1.PolicyStatus, ancestorRef return nil } -func policyAncestorConditions(policyStatus *gwapiv1.PolicyStatus, ancestorRef *gwapiv1.ParentReference, controllerName string) []metav1.Condition { - for _, ancestor := range policyStatus.Ancestors { - if string(ancestor.ControllerName) == controllerName && ancestorRefsEqual(&ancestor.AncestorRef, ancestorRef) { - return ancestor.Conditions - } - } - - return nil -} - func mergePolicyWarningMessages(existing, next string) string { switch { case existing == "": diff --git a/internal/gatewayapi/status/policy_test.go b/internal/gatewayapi/status/policy_test.go index cdff974e5a..7f58333d47 100644 --- a/internal/gatewayapi/status/policy_test.go +++ b/internal/gatewayapi/status/policy_test.go @@ -84,19 +84,3 @@ func TestSetWarningForPolicyAncestorMergesWarnings(t *testing.T) { } } } - -func TestIsPolicyAncestorAccepted(t *testing.T) { - policyStatus := &gwapiv1.PolicyStatus{} - ancestorRef := &gwapiv1.ParentReference{Name: gwapiv1.ObjectName("example")} - controllerName := "example.com/controller" - - assert.False(t, IsPolicyAncestorAccepted(policyStatus, ancestorRef, controllerName)) - - SetConditionForPolicyAncestor(policyStatus, ancestorRef, controllerName, - gwapiv1.PolicyConditionAccepted, metav1.ConditionFalse, egv1a1.PolicyReasonRefNotPermitted, "not permitted", 1) - assert.False(t, IsPolicyAncestorAccepted(policyStatus, ancestorRef, controllerName)) - - SetConditionForPolicyAncestor(policyStatus, ancestorRef, controllerName, - gwapiv1.PolicyConditionAccepted, metav1.ConditionTrue, gwapiv1.PolicyReasonAccepted, "accepted", 1) - assert.True(t, IsPolicyAncestorAccepted(policyStatus, ancestorRef, controllerName)) -} diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-healthcheck-host-hierarchy.in.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-healthcheck-host-hierarchy.in.yaml new file mode 100644 index 0000000000..7a45a5401a --- /dev/null +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-healthcheck-host-hierarchy.in.yaml @@ -0,0 +1,171 @@ +# Health check Host header hierarchy: +# 1. BackendTrafficPolicy healthCheck.active.http.hostname wins. +# 2. Backend.spec.endpoints[].hostname overrides the route-derived default. +# 3. Effective HTTPRoute/GRPCRoute hostname for the listener remains the fallback +# when the endpoint has no hostname. +gateways: +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + namespace: envoy-gateway + name: gateway + spec: + gatewayClassName: envoy-gateway-class + listeners: + - name: http + protocol: HTTP + port: 80 + allowedRoutes: + namespaces: + from: All +backends: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + namespace: default + name: backend-with-hostname + spec: + endpoints: + - hostname: backend-endpoint.example.com + fqdn: + hostname: backend-address.example.com + port: 443 +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + namespace: default + name: backend-without-hostname + spec: + endpoints: + - fqdn: + hostname: backend-no-endpoint-host.example.com + port: 443 +httpRoutes: +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + namespace: default + name: httproute-btp-host + spec: + hostnames: + - btp-route.example.com + parentRefs: + - namespace: envoy-gateway + name: gateway + sectionName: http + rules: + - matches: + - path: + value: /btp-host + backendRefs: + - group: gateway.envoyproxy.io + kind: Backend + name: backend-with-hostname +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + namespace: default + name: httproute-backend-host + spec: + hostnames: + - backend-route.example.com + parentRefs: + - namespace: envoy-gateway + name: gateway + sectionName: http + rules: + - matches: + - path: + value: /backend-host + backendRefs: + - group: gateway.envoyproxy.io + kind: Backend + name: backend-with-hostname +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + namespace: default + name: httproute-route-host + spec: + hostnames: + - route-fallback.example.com + parentRefs: + - namespace: envoy-gateway + name: gateway + sectionName: http + rules: + - matches: + - path: + value: /route-host + backendRefs: + - group: gateway.envoyproxy.io + kind: Backend + name: backend-without-hostname +backendTrafficPolicies: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: BackendTrafficPolicy + metadata: + namespace: default + name: policy-btp-host + spec: + targetRefs: + - group: gateway.networking.k8s.io + kind: HTTPRoute + name: httproute-btp-host + healthCheck: + active: + timeout: 2s + interval: 5s + healthyThreshold: 1 + unhealthyThreshold: 3 + type: HTTP + http: + hostname: btp-health.example.com + path: /healthz + method: GET + expectedStatuses: + - 200 +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: BackendTrafficPolicy + metadata: + namespace: default + name: policy-backend-host + spec: + targetRefs: + - group: gateway.networking.k8s.io + kind: HTTPRoute + name: httproute-backend-host + healthCheck: + active: + timeout: 2s + interval: 5s + healthyThreshold: 1 + unhealthyThreshold: 3 + type: HTTP + http: + path: /healthz + method: GET + expectedStatuses: + - 200 +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: BackendTrafficPolicy + metadata: + namespace: default + name: policy-route-host + spec: + targetRefs: + - group: gateway.networking.k8s.io + kind: HTTPRoute + name: httproute-route-host + healthCheck: + active: + timeout: 2s + interval: 5s + healthyThreshold: 1 + unhealthyThreshold: 3 + type: HTTP + http: + path: /healthz + method: GET + expectedStatuses: + - 200 diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-healthcheck-host-hierarchy.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-healthcheck-host-hierarchy.out.yaml new file mode 100644 index 0000000000..08dfc3af7b --- /dev/null +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-healthcheck-host-hierarchy.out.yaml @@ -0,0 +1,510 @@ +backendTrafficPolicies: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: BackendTrafficPolicy + metadata: + name: policy-btp-host + namespace: default + spec: + healthCheck: + active: + healthyThreshold: 1 + http: + expectedStatuses: + - 200 + hostname: btp-health.example.com + method: GET + path: /healthz + interval: 5s + timeout: 2s + type: HTTP + unhealthyThreshold: 3 + targetRefs: + - group: gateway.networking.k8s.io + kind: HTTPRoute + name: httproute-btp-host + status: + ancestors: + - ancestorRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway + namespace: envoy-gateway + sectionName: http + conditions: + - lastTransitionTime: null + message: Policy has been accepted. + reason: Accepted + status: "True" + type: Accepted + controllerName: gateway.envoyproxy.io/gatewayclass-controller +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: BackendTrafficPolicy + metadata: + name: policy-backend-host + namespace: default + spec: + healthCheck: + active: + healthyThreshold: 1 + http: + expectedStatuses: + - 200 + method: GET + path: /healthz + interval: 5s + timeout: 2s + type: HTTP + unhealthyThreshold: 3 + targetRefs: + - group: gateway.networking.k8s.io + kind: HTTPRoute + name: httproute-backend-host + status: + ancestors: + - ancestorRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway + namespace: envoy-gateway + sectionName: http + conditions: + - lastTransitionTime: null + message: Policy has been accepted. + reason: Accepted + status: "True" + type: Accepted + controllerName: gateway.envoyproxy.io/gatewayclass-controller +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: BackendTrafficPolicy + metadata: + name: policy-route-host + namespace: default + spec: + healthCheck: + active: + healthyThreshold: 1 + http: + expectedStatuses: + - 200 + method: GET + path: /healthz + interval: 5s + timeout: 2s + type: HTTP + unhealthyThreshold: 3 + targetRefs: + - group: gateway.networking.k8s.io + kind: HTTPRoute + name: httproute-route-host + status: + ancestors: + - ancestorRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway + namespace: envoy-gateway + sectionName: http + conditions: + - lastTransitionTime: null + message: Policy has been accepted. + reason: Accepted + status: "True" + type: Accepted + controllerName: gateway.envoyproxy.io/gatewayclass-controller +backends: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + name: backend-with-hostname + namespace: default + spec: + endpoints: + - fqdn: + hostname: backend-address.example.com + port: 443 + hostname: backend-endpoint.example.com + status: + conditions: + - lastTransitionTime: null + message: The Backend was accepted + reason: Accepted + status: "True" + type: Accepted +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + name: backend-without-hostname + namespace: default + spec: + endpoints: + - fqdn: + hostname: backend-no-endpoint-host.example.com + port: 443 + status: + conditions: + - lastTransitionTime: null + message: The Backend was accepted + reason: Accepted + status: "True" + type: Accepted +gateways: +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + name: gateway + namespace: envoy-gateway + spec: + gatewayClassName: envoy-gateway-class + listeners: + - allowedRoutes: + namespaces: + from: All + name: http + port: 80 + protocol: HTTP + status: + listeners: + - attachedRoutes: 3 + conditions: + - lastTransitionTime: null + message: Sending translated listener configuration to the data plane + reason: Programmed + status: "True" + type: Programmed + - lastTransitionTime: null + message: Listener has been successfully translated + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Listener references have been resolved + reason: ResolvedRefs + status: "True" + type: ResolvedRefs + name: http + supportedKinds: + - group: gateway.networking.k8s.io + kind: HTTPRoute + - group: gateway.networking.k8s.io + kind: GRPCRoute +httpRoutes: +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + name: httproute-btp-host + namespace: default + spec: + hostnames: + - btp-route.example.com + parentRefs: + - name: gateway + namespace: envoy-gateway + sectionName: http + rules: + - backendRefs: + - group: gateway.envoyproxy.io + kind: Backend + name: backend-with-hostname + matches: + - path: + value: /btp-host + status: + parents: + - conditions: + - lastTransitionTime: null + message: Route is accepted + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Resolved all the Object references for the Route + reason: ResolvedRefs + status: "True" + type: ResolvedRefs + controllerName: gateway.envoyproxy.io/gatewayclass-controller + parentRef: + name: gateway + namespace: envoy-gateway + sectionName: http +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + name: httproute-backend-host + namespace: default + spec: + hostnames: + - backend-route.example.com + parentRefs: + - name: gateway + namespace: envoy-gateway + sectionName: http + rules: + - backendRefs: + - group: gateway.envoyproxy.io + kind: Backend + name: backend-with-hostname + matches: + - path: + value: /backend-host + status: + parents: + - conditions: + - lastTransitionTime: null + message: Route is accepted + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Resolved all the Object references for the Route + reason: ResolvedRefs + status: "True" + type: ResolvedRefs + controllerName: gateway.envoyproxy.io/gatewayclass-controller + parentRef: + name: gateway + namespace: envoy-gateway + sectionName: http +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + name: httproute-route-host + namespace: default + spec: + hostnames: + - route-fallback.example.com + parentRefs: + - name: gateway + namespace: envoy-gateway + sectionName: http + rules: + - backendRefs: + - group: gateway.envoyproxy.io + kind: Backend + name: backend-without-hostname + matches: + - path: + value: /route-host + status: + parents: + - conditions: + - lastTransitionTime: null + message: Route is accepted + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Resolved all the Object references for the Route + reason: ResolvedRefs + status: "True" + type: ResolvedRefs + controllerName: gateway.envoyproxy.io/gatewayclass-controller + parentRef: + name: gateway + namespace: envoy-gateway + sectionName: http +infraIR: + envoy-gateway/gateway: + proxy: + listeners: + - name: envoy-gateway/gateway/http + ports: + - containerPort: 10080 + name: http-80 + protocol: HTTP + servicePort: 80 + metadata: + labels: + gateway.envoyproxy.io/owning-gateway-name: gateway + gateway.envoyproxy.io/owning-gateway-namespace: envoy-gateway + ownerReference: + kind: GatewayClass + name: envoy-gateway-class + name: envoy-gateway/gateway + namespace: envoy-gateway-system +xdsIR: + envoy-gateway/gateway: + accessLog: + json: + - path: /dev/stdout + globalResources: + proxyServiceCluster: + metadata: + kind: Service + name: envoy-envoy-gateway-gateway-966d2c13 + namespace: envoy-gateway-system + sectionName: "8080" + name: envoy-gateway/gateway + settings: + - addressType: IP + endpoints: + - host: 7.6.5.4 + port: 8080 + zone: zone1 + metadata: + kind: Service + name: envoy-envoy-gateway-gateway-966d2c13 + namespace: envoy-gateway-system + sectionName: "8080" + name: envoy-gateway/gateway + protocol: TCP + http: + - address: 0.0.0.0 + externalPort: 80 + hostnames: + - '*' + metadata: + kind: Gateway + name: gateway + namespace: envoy-gateway + sectionName: http + name: envoy-gateway/gateway/http + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10080 + routes: + - destination: + metadata: + kind: HTTPRoute + name: httproute-backend-host + namespace: default + name: httproute/default/httproute-backend-host/rule/0 + settings: + - addressType: FQDN + endpoints: + - host: backend-address.example.com + hostname: backend-endpoint.example.com + port: 443 + metadata: + kind: Backend + name: backend-with-hostname + namespace: default + name: httproute/default/httproute-backend-host/rule/0/backend/0 + protocol: HTTP + weight: 1 + hostname: backend-route.example.com + isHTTP2: false + metadata: + kind: HTTPRoute + name: httproute-backend-host + namespace: default + policies: + - kind: BackendTrafficPolicy + name: policy-backend-host + namespace: default + name: httproute/default/httproute-backend-host/rule/0/match/0/backend-route_example_com + pathMatch: + distinct: false + name: "" + prefix: /backend-host + traffic: + healthCheck: + active: + healthyThreshold: 1 + http: + expectedStatuses: + - 200 + host: "" + method: GET + path: /healthz + interval: 5s + timeout: 2s + unhealthyThreshold: 3 + - destination: + metadata: + kind: HTTPRoute + name: httproute-route-host + namespace: default + name: httproute/default/httproute-route-host/rule/0 + settings: + - addressType: FQDN + endpoints: + - host: backend-no-endpoint-host.example.com + port: 443 + metadata: + kind: Backend + name: backend-without-hostname + namespace: default + name: httproute/default/httproute-route-host/rule/0/backend/0 + protocol: HTTP + weight: 1 + hostname: route-fallback.example.com + isHTTP2: false + metadata: + kind: HTTPRoute + name: httproute-route-host + namespace: default + policies: + - kind: BackendTrafficPolicy + name: policy-route-host + namespace: default + name: httproute/default/httproute-route-host/rule/0/match/0/route-fallback_example_com + pathMatch: + distinct: false + name: "" + prefix: /route-host + traffic: + healthCheck: + active: + healthyThreshold: 1 + http: + expectedStatuses: + - 200 + host: "" + method: GET + path: /healthz + interval: 5s + timeout: 2s + unhealthyThreshold: 3 + - destination: + metadata: + kind: HTTPRoute + name: httproute-btp-host + namespace: default + name: httproute/default/httproute-btp-host/rule/0 + settings: + - addressType: FQDN + endpoints: + - host: backend-address.example.com + hostname: backend-endpoint.example.com + port: 443 + metadata: + kind: Backend + name: backend-with-hostname + namespace: default + name: httproute/default/httproute-btp-host/rule/0/backend/0 + protocol: HTTP + weight: 1 + hostname: btp-route.example.com + isHTTP2: false + metadata: + kind: HTTPRoute + name: httproute-btp-host + namespace: default + policies: + - kind: BackendTrafficPolicy + name: policy-btp-host + namespace: default + name: httproute/default/httproute-btp-host/rule/0/match/0/btp-route_example_com + pathMatch: + distinct: false + name: "" + prefix: /btp-host + traffic: + healthCheck: + active: + healthyThreshold: 1 + http: + expectedStatuses: + - 200 + host: btp-health.example.com + method: GET + path: /healthz + interval: 5s + timeout: 2s + unhealthyThreshold: 3 + readyListener: + address: 0.0.0.0 + ipFamily: IPv4 + path: /ready + port: 19003 diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-status-conditions.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-status-conditions.out.yaml index af39245f4e..ce7c003177 100644 --- a/internal/gatewayapi/testdata/backendtrafficpolicy-status-conditions.out.yaml +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-status-conditions.out.yaml @@ -508,12 +508,6 @@ infraIR: name: http-80 protocol: HTTP servicePort: 80 - - name: envoy-gateway/gateway-2/https - ports: - - containerPort: 10443 - name: https-443 - protocol: HTTPS - servicePort: 443 - name: envoy-gateway/gateway-2/tcp ports: - containerPort: 10053 @@ -735,20 +729,6 @@ xdsIR: namespace: envoy-gateway name: grpcroute/envoy-gateway/grpcroute-1/rule/0/match/0/* traffic: {} - - address: 0.0.0.0 - externalPort: 443 - hostnames: - - '*' - metadata: - kind: Gateway - name: gateway-2 - namespace: envoy-gateway - sectionName: https - name: envoy-gateway/gateway-2/https - path: - escapedSlashesAction: UnescapeAndRedirect - mergeSlashes: true - port: 10443 readyListener: address: 0.0.0.0 ipFamily: IPv4 diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-healthcheck-overrides.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-healthcheck-overrides.out.yaml index f6b26324dc..6574a89a28 100644 --- a/internal/gatewayapi/testdata/backendtrafficpolicy-with-healthcheck-overrides.out.yaml +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-healthcheck-overrides.out.yaml @@ -446,7 +446,7 @@ xdsIR: http: expectedStatuses: - 200 - host: gateway.envoyproxy.io + host: "" method: GET path: /healthz interval: 5s @@ -493,7 +493,7 @@ xdsIR: http: expectedStatuses: - 200 - host: gateway.envoyproxy.io + host: "" method: GET path: /healthz interval: 5s diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-healthcheck.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-healthcheck.out.yaml index a1480de5e0..ead1bb08f2 100644 --- a/internal/gatewayapi/testdata/backendtrafficpolicy-with-healthcheck.out.yaml +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-healthcheck.out.yaml @@ -885,7 +885,7 @@ xdsIR: expectedStatuses: - 200 - 300 - host: '*' + host: "" method: GET path: /healthz interval: 3s @@ -1173,7 +1173,7 @@ xdsIR: text: pong expectedStatuses: - 200 - host: gateway.envoyproxy.io + host: "" method: GET path: /healthz interval: 5s diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-routing-type-listener.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-routing-type-listener.out.yaml index a29dfb9785..04c0af5b6d 100644 --- a/internal/gatewayapi/testdata/backendtrafficpolicy-with-routing-type-listener.out.yaml +++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-routing-type-listener.out.yaml @@ -126,6 +126,11 @@ gateways: reason: InvalidCertificateRef status: "False" type: ResolvedRefs + - lastTransitionTime: null + message: Listener has been successfully translated + reason: Accepted + status: "True" + type: Accepted - lastTransitionTime: null message: Listener is invalid, see other Conditions for details. reason: Invalid @@ -218,12 +223,6 @@ infraIR: name: http-80 protocol: HTTP servicePort: 80 - - name: envoy-gateway/gateway-1/https - ports: - - containerPort: 10443 - name: https-443 - protocol: HTTPS - servicePort: 443 metadata: labels: gateway.envoyproxy.io/owning-gateway-name: gateway-1 @@ -309,20 +308,6 @@ xdsIR: name: "" prefix: /foo traffic: {} - - address: 0.0.0.0 - externalPort: 443 - hostnames: - - '*' - metadata: - kind: Gateway - name: gateway-1 - namespace: envoy-gateway - sectionName: https - name: envoy-gateway/gateway-1/https - path: - escapedSlashesAction: UnescapeAndRedirect - mergeSlashes: true - port: 10443 readyListener: address: 0.0.0.0 ipFamily: IPv4 diff --git a/internal/gatewayapi/testdata/clienttrafficpolicy-http3.out.yaml b/internal/gatewayapi/testdata/clienttrafficpolicy-http3.out.yaml index 62f58c8205..734d190a24 100644 --- a/internal/gatewayapi/testdata/clienttrafficpolicy-http3.out.yaml +++ b/internal/gatewayapi/testdata/clienttrafficpolicy-http3.out.yaml @@ -92,8 +92,7 @@ gateways: type: ResolvedRefs - lastTransitionTime: null message: The hostname *.example.com overlaps with the hostname bar.example.com - in listener https-bar. ALPN will default to HTTP/1.1 to prevent HTTP/2 connection - coalescing, unless explicitly configured via ClientTrafficPolicy + in listener https-bar. reason: OverlappingHostnames status: "True" type: OverlappingTLSConfig @@ -122,8 +121,7 @@ gateways: type: ResolvedRefs - lastTransitionTime: null message: The hostname foo.example.com overlaps with the hostname *.example.com - in listener https-wildcard. ALPN will default to HTTP/1.1 to prevent HTTP/2 - connection coalescing, unless explicitly configured via ClientTrafficPolicy + in listener https-wildcard. reason: OverlappingHostnames status: "True" type: OverlappingTLSConfig @@ -152,8 +150,7 @@ gateways: type: ResolvedRefs - lastTransitionTime: null message: The hostname bar.example.com overlaps with the hostname *.example.com - in listener https-wildcard. ALPN will default to HTTP/1.1 to prevent HTTP/2 - connection coalescing, unless explicitly configured via ClientTrafficPolicy + in listener https-wildcard. reason: OverlappingHostnames status: "True" type: OverlappingTLSConfig @@ -304,7 +301,6 @@ xdsIR: privateKey: '[redacted]' maxVersion: "1.3" minVersion: "1.2" - tlsOverlaps: true - address: 0.0.0.0 externalPort: 443 hostnames: @@ -359,7 +355,6 @@ xdsIR: privateKey: '[redacted]' maxVersion: "1.3" minVersion: "1.2" - tlsOverlaps: true - address: 0.0.0.0 externalPort: 443 hostnames: @@ -414,7 +409,6 @@ xdsIR: privateKey: '[redacted]' maxVersion: "1.3" minVersion: "1.2" - tlsOverlaps: true readyListener: address: 0.0.0.0 ipFamily: IPv4 diff --git a/internal/gatewayapi/testdata/clienttrafficpolicy-status-conditions.out.yaml b/internal/gatewayapi/testdata/clienttrafficpolicy-status-conditions.out.yaml index 6fa616eead..6d47792238 100644 --- a/internal/gatewayapi/testdata/clienttrafficpolicy-status-conditions.out.yaml +++ b/internal/gatewayapi/testdata/clienttrafficpolicy-status-conditions.out.yaml @@ -453,12 +453,6 @@ infraIR: name: http-80 protocol: HTTP servicePort: 80 - - name: envoy-gateway/gateway-2/https - ports: - - containerPort: 10443 - name: https-443 - protocol: HTTPS - servicePort: 443 - name: envoy-gateway/gateway-2/tcp ports: - containerPort: 10053 @@ -596,20 +590,6 @@ xdsIR: escapedSlashesAction: UnescapeAndRedirect mergeSlashes: true port: 10080 - - address: 0.0.0.0 - externalPort: 443 - hostnames: - - '*' - metadata: - kind: Gateway - name: gateway-2 - namespace: envoy-gateway - sectionName: https - name: envoy-gateway/gateway-2/https - path: - escapedSlashesAction: UnescapeAndRedirect - mergeSlashes: true - port: 10443 readyListener: address: 0.0.0.0 ipFamily: IPv4 diff --git a/internal/gatewayapi/testdata/envoyextensionpolicy-status-conditions.out.yaml b/internal/gatewayapi/testdata/envoyextensionpolicy-status-conditions.out.yaml index 081fd59005..9508ec8d51 100644 --- a/internal/gatewayapi/testdata/envoyextensionpolicy-status-conditions.out.yaml +++ b/internal/gatewayapi/testdata/envoyextensionpolicy-status-conditions.out.yaml @@ -508,12 +508,6 @@ infraIR: name: http-80 protocol: HTTP servicePort: 80 - - name: envoy-gateway/gateway-2/https - ports: - - containerPort: 10443 - name: https-443 - protocol: HTTPS - servicePort: 443 - name: envoy-gateway/gateway-2/tcp ports: - containerPort: 10053 @@ -727,20 +721,6 @@ xdsIR: name: grpcroute-1 namespace: envoy-gateway name: grpcroute/envoy-gateway/grpcroute-1/rule/0/match/0/* - - address: 0.0.0.0 - externalPort: 443 - hostnames: - - '*' - metadata: - kind: Gateway - name: gateway-2 - namespace: envoy-gateway - sectionName: https - name: envoy-gateway/gateway-2/https - path: - escapedSlashesAction: UnescapeAndRedirect - mergeSlashes: true - port: 10443 readyListener: address: 0.0.0.0 ipFamily: IPv4 diff --git a/internal/gatewayapi/testdata/gateway-with-attached-routes.out.yaml b/internal/gatewayapi/testdata/gateway-with-attached-routes.out.yaml index c2ac20067f..430bf42173 100644 --- a/internal/gatewayapi/testdata/gateway-with-attached-routes.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-attached-routes.out.yaml @@ -108,6 +108,11 @@ gateways: reason: InvalidCertificateRef status: "False" type: ResolvedRefs + - lastTransitionTime: null + message: Listener has been successfully translated + reason: Accepted + status: "True" + type: Accepted - lastTransitionTime: null message: Listener is invalid, see other Conditions for details. reason: Invalid @@ -326,13 +331,6 @@ infraIR: namespace: envoy-gateway-system envoy-gateway/unresolved-gateway-with-one-attached-unresolved-route: proxy: - listeners: - - name: envoy-gateway/unresolved-gateway-with-one-attached-unresolved-route/tls - ports: - - containerPort: 10443 - name: https-443 - protocol: HTTPS - servicePort: 443 metadata: labels: gateway.envoyproxy.io/owning-gateway-name: unresolved-gateway-with-one-attached-unresolved-route @@ -487,21 +485,6 @@ xdsIR: sectionName: "8080" name: envoy-gateway/unresolved-gateway-with-one-attached-unresolved-route protocol: TCP - http: - - address: 0.0.0.0 - externalPort: 443 - hostnames: - - '*' - metadata: - kind: Gateway - name: unresolved-gateway-with-one-attached-unresolved-route - namespace: envoy-gateway - sectionName: tls - name: envoy-gateway/unresolved-gateway-with-one-attached-unresolved-route/tls - path: - escapedSlashesAction: UnescapeAndRedirect - mergeSlashes: true - port: 10443 readyListener: address: 0.0.0.0 ipFamily: IPv4 diff --git a/internal/gatewayapi/testdata/gateway-with-conflicting-listeners-one-invalid-ref.in.yaml b/internal/gatewayapi/testdata/gateway-with-conflicting-listeners-one-invalid-ref.in.yaml new file mode 100644 index 0000000000..1b0dfa84fc --- /dev/null +++ b/internal/gatewayapi/testdata/gateway-with-conflicting-listeners-one-invalid-ref.in.yaml @@ -0,0 +1,64 @@ +gateways: + - apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + namespace: envoy-gateway + name: gateway-1 + spec: + gatewayClassName: envoy-gateway-class + listeners: + # This listener has an invalid certificate reference (secret does not exist) + # It should have ResolvedRefs=False with InvalidCertificateRef + # and should be skipped during conflict resolution + - name: invalid-https + protocol: HTTPS + port: 443 + hostname: "*.example.com" + allowedRoutes: + namespaces: + from: All + tls: + mode: Terminate + certificateRefs: + - name: non-existent-secret + # This listener has valid configuration and should be accepted + # even though it's on the same port/hostname as the invalid listener + - name: valid-https + protocol: HTTPS + port: 443 + hostname: "*.example.com" + allowedRoutes: + namespaces: + from: All + tls: + mode: Terminate + certificateRefs: + - name: tls-secret-1 +secrets: + - apiVersion: v1 + kind: Secret + metadata: + namespace: envoy-gateway + name: tls-secret-1 + type: kubernetes.io/tls + data: + tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUR3RENDQXFpZ0F3SUJBZ0lVVDRyelIreStHd1VzMm9ydExIZ0k1MzBKeG9Fd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0xURVZNQk1HQTFVRUNnd01aWGhoYlhCc1pTQkpibU11TVJRd0VnWURWUVFEREF0bGVHRnRjR3hsTG1OdgpiVEFlRncweU5UQTBNakl3TWpVNU1UQmFGdzB6TlRBME1qQXdNalU1TVRCYU1EVXhGREFTQmdOVkJBTU1DMlp2CmJ5NWlZWEl1WTI5dE1SMHdHd1lEVlFRS0RCUmxlR0Z0Y0d4bElHOXlaMkZ1YVhwaGRHbHZiakNDQVNJd0RRWUoKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBTE4wbnJNR1NZNjBPT0JuTFVaSGpCRFkxazhqWHA2RwppeG1RaFNOK3lZUi9VQWVqSmhCOVI3S2RuT3d0eGljTnozdUFtL0p0UTFKRUU0dW5xQnhVTU8ydWpvVXl4ZisrCjRnb2tFYmVpTlhNN0ptaklPOGxEWlJjcEhFTlE3eUNJL3d1cEZBcHgwNnVrNUtBSlpRMUlmVXhZWS9RRkJsc3cKdUx0TWozVlB6eDBJYjRIV1lHdGhXcDIzUWduMUdGUWVTOGMwZHdqWWNBTGtrTFdwWWdUZTZGT0VhR3hvUzdwTQpGbitvZnRFUjlxZCtDcnRDSXM5TzFtOW5MUU9UWGJDNU5nSzR1ZFdhMFBuYjJ6TEk4WjZsVHFRSTNSODE2NkxKCkVDQi9ZSlYzVmtMb2cxUmx0d0FrM3hrWHFnbVhTZUxILzY3MHh6MEx5OGZHQVpmejFMQVpkSXNDQXdFQUFhT0IKenpDQnpEQWRCZ05WSFE0RUZnUVUzbVFodVB2dVl1K0lmN0ZaM010eU9jMWdjQ1V3YUFZRFZSMGpCR0V3WDRBVQpXWmxKWFQ1bXlEVnlsUjlSS2JQQTAxTkVlcytoTWFRdk1DMHhGVEFUQmdOVkJBb01ER1Y0WVcxd2JHVWdTVzVqCkxqRVVNQklHQTFVRUF3d0xaWGhoYlhCc1pTNWpiMjJDRkJuNktuTlBhbm1Db1daVStNYmtwKzJScmN4dU1Bc0cKQTFVZER3UUVBd0lDL0RBcEJnTlZIUkVFSWpBZ2dnOW1iMjh1WlhoaGJYQnNaUzVqYjIyQ0RTb3VaWGhoYlhCcwpaUzVqYjIwd0NRWURWUjBTQkFJd0FEQU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFIa2xEbzkvNnRLcDNFd3JSCnJjVStKOUtmUkFGajc5YU1DREpVb0NyM2J6RFIycXQ4ZzlsbDdFSzZaeEtFa0xzWkFlYzBxU0Z1QjBvbzVqZFEKM3VvT2hNK1JKTkZoTldFd3dHWmpMb0FlK2oxaXByN1A5ajdmdFNzck8ra3M3TVNMeTE2RW9IV2Q0eG00Rk5QZQpmUVpRYWhpTTdMYVFCdW5wdXlhZWtLdG5tU241RzlkSHpGeTVNelRSbFJyVWxhVzdVbDRUeExlOEROZ2ZpR2ZCCnpjcmpVK2l3RUJXeS94b3B2aDEzNmlybmV3NTg3RWt3dzQ3QXFhc3gvZStMK2NhSlYySGVMd0dSaE5xR2pIcjkKQ2dSVHpud3F5QjdtTVNXYStWaXBNSHlUVmRCNjRvYjZxbkdqTldvWXdRbUUraU0vL0VrTURzd2JVcTc2R1pKMApsWlRkTlE9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg== + tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQ3pkSjZ6QmttT3REamcKWnkxR1I0d1EyTlpQSTE2ZWhvc1prSVVqZnNtRWYxQUhveVlRZlVleW5aenNMY1luRGM5N2dKdnliVU5TUkJPTApwNmdjVkREdHJvNkZNc1gvdnVJS0pCRzNvalZ6T3lab3lEdkpRMlVYS1J4RFVPOGdpUDhMcVJRS2NkT3JwT1NnCkNXVU5TSDFNV0dQMEJRWmJNTGk3VEk5MVQ4OGRDRytCMW1CcllWcWR0MElKOVJoVUhrdkhOSGNJMkhBQzVKQzEKcVdJRTN1aFRoR2hzYUV1NlRCWi9xSDdSRWZhbmZncTdRaUxQVHRadlp5MERrMTJ3dVRZQ3VMblZtdEQ1MjlzeQp5UEdlcFU2a0NOMGZOZXVpeVJBZ2YyQ1ZkMVpDNklOVVpiY0FKTjhaRjZvSmwwbml4Lyt1OU1jOUM4dkh4Z0dYCjg5U3dHWFNMQWdNQkFBRUNnZ0VBSmYrYW53UEV6WS9CdjFwNWpya1ZvbmVYb1hnMno5QmpZYzFsTTZma0djY3YKZGY2SXo5TUhQSDM5UFZGUDlQTUtyUGNGam1hdWE1djRtNGlyb3h2OHBFZGk3RGRkRDVNbW44a1ZhMUhRaVk3TAp5a0lqenJFVGxiemh2Q3RHQnhpYkVLZ0RrMWFZNEc1dzdxWXVuSXB0NVoyTnhKelB4TDFqVUYyY3Z0VmdZS0FPCjN2TWY1dENWbS9kL2JBT2xvWnVVc3ArSnc1ZTYvSFN3c3lEdjV2Y2dDQkRXRjFkTFFiYUxCelZDZGJBY0Fma1AKbFUzeGhZMVYyMGU2NmhBbU0veE53MzArSUhvTUlTUTFiQW9MOXVzN3NsTlYxT2ZNZk5hWC83WVdKWFVab1MzNwpyY1IvVXYwZlRtQkhPR3pwK25oaWpLRUlYU1ZESjNxK040amM4Ni9IeVFLQmdRRFhWbzNKSmlia0cvY1JBZ2pICkVqdWROMHJMSGJvVldPanN5ekZmaXg1MHJKTTYwMDJKZURicGdQeEt4ZUtFdGl4ZkVWQmU0eHdqNG9oK1ZubEIKT0dMU3BWcHRRVFRnRVprWXFvVU1iUDIyNHQ2cUZuSXZsTkkwZFJGWDUyS3I2L1FCS0EwWEk3K0I1bTV3Z2hLcgo4ZEQrMGRWNkZzMmxFT0NMWUJKck1weFNIUUtCZ1FEVlY0REVaUlFvVUo5UGRkb3IyK2IweFV2Y3JHeUJ1NlM2CjJZOFJuMzdWUVlBSThHUnlYRkcxTGxZaHpMOWNwd0tUR21SMVhPRTVkMC9mMStaU3h5TVc1d2FSaXU1b0dFK2cKUlNsMXBBdTNUdlEzM1BVNUJzNFhhcHBLOC9BZVk3cG1pd1JhYnRPSFlQa0FHMXNzL3k1d1NjVGUxQXZiWlpsTAo1TmgwdHZvZ3h3S0JnUUNtRkFJOFhlbG15czZ0Vm1WUXE1WkF0YkZBb0VleFNTWXo0cTdNb200MXpCZXRLZVRHCkhtb3pneUNSeHJiaVplSW8zQ0NoWGdXSkE2RUQxMHVqYW9xRkxiUmxTUUl2d2tMU1RFbGJBUUJZdWZiRE5aYVIKYmZVRk1qalRGQWo4MFhrYUh6cWhXeGZMWnQ1TWRYVlRHYWgzcjN3MnNqbWVranFzSThkdzE5TEtYUUtCZ0NoMQp3T0QrUG5WcTNOdklBUWxpV2dtL3hTUmp1dXhidHVFTTA1cEhBbG5WWXovT3YyNEUzaVliVkpCeWNUUlVKQ1BiCjFJT0JpdUZJSkdqU1hFY0VwejMzc0lJM3RBRWY0eklGQzlqWXRMUWVFQ2pzQ2NHMzdhdjVOcXZTV1k2WjRVY0QKUkY4V041MnNJVzBJd3lEa2dGMGhVR25tRXgyWHhodmptYjJBMmkwUEFvR0FUV1kzbXZRVWtZcmU5R0J0alVqYgpDWUx5Mm1VVElKbjVDcmhjTHMvMlh5MkNoVSt5MnhsT3pIcm1vanRIaHFFcnVCK0xyZkpBd3B3cGVRNmxyWnFQCjFGazVKT2c2bmV2U3lDcWF4SDZaenZRMXJ6VzAycm1IMUJrV1BiY0NwKy9VRTIrS3JselZtNHkvZ0ZoRGVGZlcKRUc5UzIzYndKME1JUmF0WVpFQm0wcWs9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K +httpRoutes: + - apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + namespace: default + name: httproute-1 + spec: + parentRefs: + - namespace: envoy-gateway + name: gateway-1 + sectionName: valid-https + rules: + - matches: + - path: + value: "/" + backendRefs: + - name: service-1 + port: 8080 diff --git a/internal/gatewayapi/testdata/gateway-with-conflicting-listeners-one-invalid-ref.out.yaml b/internal/gatewayapi/testdata/gateway-with-conflicting-listeners-one-invalid-ref.out.yaml new file mode 100644 index 0000000000..67882951e3 --- /dev/null +++ b/internal/gatewayapi/testdata/gateway-with-conflicting-listeners-one-invalid-ref.out.yaml @@ -0,0 +1,218 @@ +gateways: +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + name: gateway-1 + namespace: envoy-gateway + spec: + gatewayClassName: envoy-gateway-class + listeners: + - allowedRoutes: + namespaces: + from: All + hostname: '*.example.com' + name: invalid-https + port: 443 + protocol: HTTPS + tls: + certificateRefs: + - name: non-existent-secret + mode: Terminate + - allowedRoutes: + namespaces: + from: All + hostname: '*.example.com' + name: valid-https + port: 443 + protocol: HTTPS + tls: + certificateRefs: + - name: tls-secret-1 + mode: Terminate + status: + listeners: + - attachedRoutes: 0 + conditions: + - lastTransitionTime: null + message: 'No valid secrets exist: certificate refs 0: Secret envoy-gateway/non-existent-secret + does not exist.' + reason: InvalidCertificateRef + status: "False" + type: ResolvedRefs + - lastTransitionTime: null + message: Listener has been successfully translated + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Listener is invalid, see other Conditions for details. + reason: Invalid + status: "False" + type: Programmed + name: invalid-https + supportedKinds: + - group: gateway.networking.k8s.io + kind: HTTPRoute + - group: gateway.networking.k8s.io + kind: GRPCRoute + - attachedRoutes: 1 + conditions: + - lastTransitionTime: null + message: Sending translated listener configuration to the data plane + reason: Programmed + status: "True" + type: Programmed + - lastTransitionTime: null + message: Listener has been successfully translated + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Listener references have been resolved + reason: ResolvedRefs + status: "True" + type: ResolvedRefs + name: valid-https + supportedKinds: + - group: gateway.networking.k8s.io + kind: HTTPRoute + - group: gateway.networking.k8s.io + kind: GRPCRoute +httpRoutes: +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + name: httproute-1 + namespace: default + spec: + parentRefs: + - name: gateway-1 + namespace: envoy-gateway + sectionName: valid-https + rules: + - backendRefs: + - name: service-1 + port: 8080 + matches: + - path: + value: / + status: + parents: + - conditions: + - lastTransitionTime: null + message: Route is accepted + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Resolved all the Object references for the Route + reason: ResolvedRefs + status: "True" + type: ResolvedRefs + controllerName: gateway.envoyproxy.io/gatewayclass-controller + parentRef: + name: gateway-1 + namespace: envoy-gateway + sectionName: valid-https +infraIR: + envoy-gateway/gateway-1: + proxy: + listeners: + - name: envoy-gateway/gateway-1/valid-https + ports: + - containerPort: 10443 + name: https-443 + protocol: HTTPS + servicePort: 443 + metadata: + labels: + gateway.envoyproxy.io/owning-gateway-name: gateway-1 + gateway.envoyproxy.io/owning-gateway-namespace: envoy-gateway + ownerReference: + kind: GatewayClass + name: envoy-gateway-class + name: envoy-gateway/gateway-1 + namespace: envoy-gateway-system +xdsIR: + envoy-gateway/gateway-1: + accessLog: + json: + - path: /dev/stdout + globalResources: + proxyServiceCluster: + metadata: + kind: Service + name: envoy-envoy-gateway-gateway-1-196ae069 + namespace: envoy-gateway-system + sectionName: "8080" + name: envoy-gateway/gateway-1 + settings: + - addressType: IP + endpoints: + - host: 7.6.5.4 + port: 8080 + zone: zone1 + metadata: + kind: Service + name: envoy-envoy-gateway-gateway-1-196ae069 + namespace: envoy-gateway-system + sectionName: "8080" + name: envoy-gateway/gateway-1 + protocol: TCP + http: + - address: 0.0.0.0 + externalPort: 443 + hostnames: + - '*.example.com' + metadata: + kind: Gateway + name: gateway-1 + namespace: envoy-gateway + sectionName: valid-https + name: envoy-gateway/gateway-1/valid-https + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10443 + routes: + - destination: + metadata: + kind: HTTPRoute + name: httproute-1 + namespace: default + name: httproute/default/httproute-1/rule/0 + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8080 + metadata: + kind: Service + name: service-1 + namespace: default + sectionName: "8080" + name: httproute/default/httproute-1/rule/0/backend/0 + protocol: HTTP + weight: 1 + hostname: '*.example.com' + isHTTP2: false + metadata: + kind: HTTPRoute + name: httproute-1 + namespace: default + name: httproute/default/httproute-1/rule/0/match/0/*_example_com + pathMatch: + distinct: false + name: "" + prefix: / + tls: + alpnProtocols: null + certificates: + - certificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUR3RENDQXFpZ0F3SUJBZ0lVVDRyelIreStHd1VzMm9ydExIZ0k1MzBKeG9Fd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0xURVZNQk1HQTFVRUNnd01aWGhoYlhCc1pTQkpibU11TVJRd0VnWURWUVFEREF0bGVHRnRjR3hsTG1OdgpiVEFlRncweU5UQTBNakl3TWpVNU1UQmFGdzB6TlRBME1qQXdNalU1TVRCYU1EVXhGREFTQmdOVkJBTU1DMlp2CmJ5NWlZWEl1WTI5dE1SMHdHd1lEVlFRS0RCUmxlR0Z0Y0d4bElHOXlaMkZ1YVhwaGRHbHZiakNDQVNJd0RRWUoKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBTE4wbnJNR1NZNjBPT0JuTFVaSGpCRFkxazhqWHA2RwppeG1RaFNOK3lZUi9VQWVqSmhCOVI3S2RuT3d0eGljTnozdUFtL0p0UTFKRUU0dW5xQnhVTU8ydWpvVXl4ZisrCjRnb2tFYmVpTlhNN0ptaklPOGxEWlJjcEhFTlE3eUNJL3d1cEZBcHgwNnVrNUtBSlpRMUlmVXhZWS9RRkJsc3cKdUx0TWozVlB6eDBJYjRIV1lHdGhXcDIzUWduMUdGUWVTOGMwZHdqWWNBTGtrTFdwWWdUZTZGT0VhR3hvUzdwTQpGbitvZnRFUjlxZCtDcnRDSXM5TzFtOW5MUU9UWGJDNU5nSzR1ZFdhMFBuYjJ6TEk4WjZsVHFRSTNSODE2NkxKCkVDQi9ZSlYzVmtMb2cxUmx0d0FrM3hrWHFnbVhTZUxILzY3MHh6MEx5OGZHQVpmejFMQVpkSXNDQXdFQUFhT0IKenpDQnpEQWRCZ05WSFE0RUZnUVUzbVFodVB2dVl1K0lmN0ZaM010eU9jMWdjQ1V3YUFZRFZSMGpCR0V3WDRBVQpXWmxKWFQ1bXlEVnlsUjlSS2JQQTAxTkVlcytoTWFRdk1DMHhGVEFUQmdOVkJBb01ER1Y0WVcxd2JHVWdTVzVqCkxqRVVNQklHQTFVRUF3d0xaWGhoYlhCc1pTNWpiMjJDRkJuNktuTlBhbm1Db1daVStNYmtwKzJScmN4dU1Bc0cKQTFVZER3UUVBd0lDL0RBcEJnTlZIUkVFSWpBZ2dnOW1iMjh1WlhoaGJYQnNaUzVqYjIyQ0RTb3VaWGhoYlhCcwpaUzVqYjIwd0NRWURWUjBTQkFJd0FEQU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFIa2xEbzkvNnRLcDNFd3JSCnJjVStKOUtmUkFGajc5YU1DREpVb0NyM2J6RFIycXQ4ZzlsbDdFSzZaeEtFa0xzWkFlYzBxU0Z1QjBvbzVqZFEKM3VvT2hNK1JKTkZoTldFd3dHWmpMb0FlK2oxaXByN1A5ajdmdFNzck8ra3M3TVNMeTE2RW9IV2Q0eG00Rk5QZQpmUVpRYWhpTTdMYVFCdW5wdXlhZWtLdG5tU241RzlkSHpGeTVNelRSbFJyVWxhVzdVbDRUeExlOEROZ2ZpR2ZCCnpjcmpVK2l3RUJXeS94b3B2aDEzNmlybmV3NTg3RWt3dzQ3QXFhc3gvZStMK2NhSlYySGVMd0dSaE5xR2pIcjkKQ2dSVHpud3F5QjdtTVNXYStWaXBNSHlUVmRCNjRvYjZxbkdqTldvWXdRbUUraU0vL0VrTURzd2JVcTc2R1pKMApsWlRkTlE9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg== + name: envoy-gateway/tls-secret-1 + privateKey: '[redacted]' + readyListener: + address: 0.0.0.0 + ipFamily: IPv4 + path: /ready + port: 19003 diff --git a/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-allowed-namespaces-selector.out.yaml b/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-allowed-namespaces-selector.out.yaml index 898c56910c..fb1bca1c0e 100644 --- a/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-allowed-namespaces-selector.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-allowed-namespaces-selector.out.yaml @@ -78,13 +78,6 @@ httpRoutes: infraIR: envoy-gateway/gateway-1: proxy: - listeners: - - name: envoy-gateway/gateway-1/http - ports: - - containerPort: 10080 - name: http-80 - protocol: HTTP - servicePort: 80 metadata: labels: gateway.envoyproxy.io/owning-gateway-name: gateway-1 @@ -120,21 +113,6 @@ xdsIR: sectionName: "8080" name: envoy-gateway/gateway-1 protocol: TCP - http: - - address: 0.0.0.0 - externalPort: 80 - hostnames: - - '*' - metadata: - kind: Gateway - name: gateway-1 - namespace: envoy-gateway - sectionName: http - name: envoy-gateway/gateway-1/http - path: - escapedSlashesAction: UnescapeAndRedirect - mergeSlashes: true - port: 10080 readyListener: address: 0.0.0.0 ipFamily: IPv4 diff --git a/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-allowed-routes-group.out.yaml b/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-allowed-routes-group.out.yaml index c1be28da35..d6eddedd1d 100644 --- a/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-allowed-routes-group.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-allowed-routes-group.out.yaml @@ -69,13 +69,6 @@ httpRoutes: infraIR: envoy-gateway/gateway-1: proxy: - listeners: - - name: envoy-gateway/gateway-1/http - ports: - - containerPort: 10080 - name: http-80 - protocol: HTTP - servicePort: 80 metadata: labels: gateway.envoyproxy.io/owning-gateway-name: gateway-1 @@ -111,21 +104,6 @@ xdsIR: sectionName: "8080" name: envoy-gateway/gateway-1 protocol: TCP - http: - - address: 0.0.0.0 - externalPort: 80 - hostnames: - - '*' - metadata: - kind: Gateway - name: gateway-1 - namespace: envoy-gateway - sectionName: http - name: envoy-gateway/gateway-1/http - path: - escapedSlashesAction: UnescapeAndRedirect - mergeSlashes: true - port: 10080 readyListener: address: 0.0.0.0 ipFamily: IPv4 diff --git a/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-allowed-routes-kind-and-supported.out.yaml b/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-allowed-routes-kind-and-supported.out.yaml index 875e056fd0..ad9f652f5d 100644 --- a/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-allowed-routes-kind-and-supported.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-allowed-routes-kind-and-supported.out.yaml @@ -71,13 +71,6 @@ httpRoutes: infraIR: envoy-gateway/gateway-1: proxy: - listeners: - - name: envoy-gateway/gateway-1/http - ports: - - containerPort: 10080 - name: http-80 - protocol: HTTP - servicePort: 80 metadata: labels: gateway.envoyproxy.io/owning-gateway-name: gateway-1 @@ -113,21 +106,6 @@ xdsIR: sectionName: "8080" name: envoy-gateway/gateway-1 protocol: TCP - http: - - address: 0.0.0.0 - externalPort: 80 - hostnames: - - '*' - metadata: - kind: Gateway - name: gateway-1 - namespace: envoy-gateway - sectionName: http - name: envoy-gateway/gateway-1/http - path: - escapedSlashesAction: UnescapeAndRedirect - mergeSlashes: true - port: 10080 readyListener: address: 0.0.0.0 ipFamily: IPv4 diff --git a/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-allowed-routes-kind.out.yaml b/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-allowed-routes-kind.out.yaml index c9e11f45f4..891bdd8a8b 100644 --- a/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-allowed-routes-kind.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-allowed-routes-kind.out.yaml @@ -69,13 +69,6 @@ httpRoutes: infraIR: envoy-gateway/gateway-1: proxy: - listeners: - - name: envoy-gateway/gateway-1/http - ports: - - containerPort: 10080 - name: http-80 - protocol: HTTP - servicePort: 80 metadata: labels: gateway.envoyproxy.io/owning-gateway-name: gateway-1 @@ -111,21 +104,6 @@ xdsIR: sectionName: "8080" name: envoy-gateway/gateway-1 protocol: TCP - http: - - address: 0.0.0.0 - externalPort: 80 - hostnames: - - '*' - metadata: - kind: Gateway - name: gateway-1 - namespace: envoy-gateway - sectionName: http - name: envoy-gateway/gateway-1/http - path: - escapedSlashesAction: UnescapeAndRedirect - mergeSlashes: true - port: 10080 readyListener: address: 0.0.0.0 ipFamily: IPv4 diff --git a/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-allowed-tls-route-kind.out.yaml b/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-allowed-tls-route-kind.out.yaml index 0127e45fe8..8a474483bb 100644 --- a/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-allowed-tls-route-kind.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-allowed-tls-route-kind.out.yaml @@ -38,13 +38,6 @@ gateways: infraIR: envoy-gateway/gateway-1: proxy: - listeners: - - name: envoy-gateway/gateway-1/tls - ports: - - containerPort: 10080 - name: tls-80 - protocol: TLS - servicePort: 80 metadata: labels: gateway.envoyproxy.io/owning-gateway-name: gateway-1 @@ -116,13 +109,3 @@ xdsIR: ipFamily: IPv4 path: /ready port: 19003 - tcp: - - address: 0.0.0.0 - externalPort: 80 - metadata: - kind: Gateway - name: gateway-1 - namespace: envoy-gateway - sectionName: tls - name: envoy-gateway/gateway-1/tls - port: 10080 diff --git a/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-multiple-tls-configuration.out.yaml b/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-multiple-tls-configuration.out.yaml index 4e0b318363..69173449ba 100644 --- a/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-multiple-tls-configuration.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-multiple-tls-configuration.out.yaml @@ -97,6 +97,11 @@ gateways: reason: InvalidCertificateRef status: "False" type: ResolvedRefs + - lastTransitionTime: null + message: Listener has been successfully translated + reason: Accepted + status: "True" + type: Accepted - lastTransitionTime: null message: Listener is invalid, see other Conditions for details. reason: Invalid @@ -158,12 +163,6 @@ infraIR: name: https-8443 protocol: HTTPS servicePort: 8443 - - name: envoy-gateway/gateway-1/tls-all-invalid-cert - ports: - - containerPort: 8444 - name: https-8444 - protocol: HTTPS - servicePort: 8444 metadata: labels: gateway.envoyproxy.io/owning-gateway-name: gateway-1 @@ -302,20 +301,6 @@ xdsIR: - certificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJ2VENDQVVTZ0F3SUJBZ0lVU2l2SkdURHdva1M3aGVZLzJjc1JzejR2SkIwd0NnWUlLb1pJemowRUF3SXcKRmpFVU1CSUdBMVVFQXd3TFptOXZMbUpoY2k1amIyMHdIaGNOTWpRd01qSTVNRGt6TURFd1doY05NelF3TWpJMgpNRGt6TURFd1dqQVdNUlF3RWdZRFZRUUREQXRtYjI4dVltRnlMbU52YlRCMk1CQUdCeXFHU000OUFnRUdCU3VCCkJBQWlBMklBQkZ2cnZSZWJhYVd1UzZNQUVJZDZ3WmZPS3Z1Q1R5VU1PbFpKcUZDRjlUa3pNWWw4Q2lvZnluT3QKQ3JzMHZ2YTlrZC9QMkpNR0JKcWdZZXZid290clJpMTJxTG5IMDQvam9HSWpqVE9LbzNJb2ZyK0ZrOHdMdkFlMwpPMVpLdFI5c3pxTlRNRkV3SFFZRFZSME9CQllFRklLczFRRm5vRHQ5K3Fva1I0T0RXYk16MWYrUE1COEdBMVVkCkl3UVlNQmFBRklLczFRRm5vRHQ5K3Fva1I0T0RXYk16MWYrUE1BOEdBMVVkRXdFQi93UUZNQU1CQWY4d0NnWUkKS29aSXpqMEVBd0lEWndBd1pBSXdIMzF0SHlmVVAwNFhIcGJXR2UxWjFJYUJaQndJdGg1NURVNGhqZlB1OG0rSgpXdjdiVzh6VFNnd0xpcW9yZmN1bkFqQTBnaE5KQkExWDJYdElLRG1sM3M3L1Z4OEZKY1MwNHZwQ2hoK2xBYkxTCnZlYWEyOFIzVExFWTNVK1FUWEkvd0lrPQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg== name: envoy-gateway/tls-secret-ecdsa-2 privateKey: '[redacted]' - - address: 0.0.0.0 - externalPort: 8444 - hostnames: - - '*' - metadata: - kind: Gateway - name: gateway-1 - namespace: envoy-gateway - sectionName: tls-all-invalid-cert - name: envoy-gateway/gateway-1/tls-all-invalid-cert - path: - escapedSlashesAction: UnescapeAndRedirect - mergeSlashes: true - port: 8444 readyListener: address: 0.0.0.0 ipFamily: IPv4 diff --git a/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-tls-configuration-invalid-mode.out.yaml b/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-tls-configuration-invalid-mode.out.yaml index f5eb3615ea..d3b527cf81 100644 --- a/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-tls-configuration-invalid-mode.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-tls-configuration-invalid-mode.out.yaml @@ -75,13 +75,6 @@ httpRoutes: infraIR: envoy-gateway/gateway-1: proxy: - listeners: - - name: envoy-gateway/gateway-1/tls - ports: - - containerPort: 10443 - name: https-443 - protocol: HTTPS - servicePort: 443 metadata: labels: gateway.envoyproxy.io/owning-gateway-name: gateway-1 @@ -117,21 +110,6 @@ xdsIR: sectionName: "8080" name: envoy-gateway/gateway-1 protocol: TCP - http: - - address: 0.0.0.0 - externalPort: 443 - hostnames: - - foo.com - metadata: - kind: Gateway - name: gateway-1 - namespace: envoy-gateway - sectionName: tls - name: envoy-gateway/gateway-1/tls - path: - escapedSlashesAction: UnescapeAndRedirect - mergeSlashes: true - port: 10443 readyListener: address: 0.0.0.0 ipFamily: IPv4 diff --git a/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-tls-configuration-no-certificate-refs.out.yaml b/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-tls-configuration-no-certificate-refs.out.yaml index f0b8e08392..08b2c9ae80 100644 --- a/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-tls-configuration-no-certificate-refs.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-tls-configuration-no-certificate-refs.out.yaml @@ -72,13 +72,6 @@ httpRoutes: infraIR: envoy-gateway/gateway-1: proxy: - listeners: - - name: envoy-gateway/gateway-1/tls - ports: - - containerPort: 10443 - name: https-443 - protocol: HTTPS - servicePort: 443 metadata: labels: gateway.envoyproxy.io/owning-gateway-name: gateway-1 @@ -114,21 +107,6 @@ xdsIR: sectionName: "8080" name: envoy-gateway/gateway-1 protocol: TCP - http: - - address: 0.0.0.0 - externalPort: 443 - hostnames: - - '*' - metadata: - kind: Gateway - name: gateway-1 - namespace: envoy-gateway - sectionName: tls - name: envoy-gateway/gateway-1/tls - path: - escapedSlashesAction: UnescapeAndRedirect - mergeSlashes: true - port: 10443 readyListener: address: 0.0.0.0 ipFamily: IPv4 diff --git a/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-tls-configuration-secret-does-not-exist.out.yaml b/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-tls-configuration-secret-does-not-exist.out.yaml index 17179618ef..e71962d4a8 100644 --- a/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-tls-configuration-secret-does-not-exist.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-tls-configuration-secret-does-not-exist.out.yaml @@ -27,6 +27,11 @@ gateways: reason: InvalidCertificateRef status: "False" type: ResolvedRefs + - lastTransitionTime: null + message: Listener has been successfully translated + reason: Accepted + status: "True" + type: Accepted - lastTransitionTime: null message: Listener is invalid, see other Conditions for details. reason: Invalid @@ -75,13 +80,6 @@ httpRoutes: infraIR: envoy-gateway/gateway-1: proxy: - listeners: - - name: envoy-gateway/gateway-1/tls - ports: - - containerPort: 10443 - name: https-443 - protocol: HTTPS - servicePort: 443 metadata: labels: gateway.envoyproxy.io/owning-gateway-name: gateway-1 @@ -117,21 +115,6 @@ xdsIR: sectionName: "8080" name: envoy-gateway/gateway-1 protocol: TCP - http: - - address: 0.0.0.0 - externalPort: 443 - hostnames: - - '*' - metadata: - kind: Gateway - name: gateway-1 - namespace: envoy-gateway - sectionName: tls - name: envoy-gateway/gateway-1/tls - path: - escapedSlashesAction: UnescapeAndRedirect - mergeSlashes: true - port: 10443 readyListener: address: 0.0.0.0 ipFamily: IPv4 diff --git a/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-tls-configuration-secret-in-other-namespace.out.yaml b/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-tls-configuration-secret-in-other-namespace.out.yaml index 94d6649edd..be22741fa9 100644 --- a/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-tls-configuration-secret-in-other-namespace.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-tls-configuration-secret-in-other-namespace.out.yaml @@ -76,13 +76,6 @@ httpRoutes: infraIR: envoy-gateway/gateway-1: proxy: - listeners: - - name: envoy-gateway/gateway-1/tls - ports: - - containerPort: 10443 - name: https-443 - protocol: HTTPS - servicePort: 443 metadata: labels: gateway.envoyproxy.io/owning-gateway-name: gateway-1 @@ -118,21 +111,6 @@ xdsIR: sectionName: "8080" name: envoy-gateway/gateway-1 protocol: TCP - http: - - address: 0.0.0.0 - externalPort: 443 - hostnames: - - '*' - metadata: - kind: Gateway - name: gateway-1 - namespace: envoy-gateway - sectionName: tls - name: envoy-gateway/gateway-1/tls - path: - escapedSlashesAction: UnescapeAndRedirect - mergeSlashes: true - port: 10443 readyListener: address: 0.0.0.0 ipFamily: IPv4 diff --git a/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-tls-configuration-secret-is-not-valid.out.yaml b/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-tls-configuration-secret-is-not-valid.out.yaml index acfc47f023..84a07d67f8 100644 --- a/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-tls-configuration-secret-is-not-valid.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-listener-with-invalid-tls-configuration-secret-is-not-valid.out.yaml @@ -27,6 +27,11 @@ gateways: reason: InvalidCertificateRef status: "False" type: ResolvedRefs + - lastTransitionTime: null + message: Listener has been successfully translated + reason: Accepted + status: "True" + type: Accepted - lastTransitionTime: null message: Listener is invalid, see other Conditions for details. reason: Invalid @@ -75,13 +80,6 @@ httpRoutes: infraIR: envoy-gateway/gateway-1: proxy: - listeners: - - name: envoy-gateway/gateway-1/tls - ports: - - containerPort: 10443 - name: https-443 - protocol: HTTPS - servicePort: 443 metadata: labels: gateway.envoyproxy.io/owning-gateway-name: gateway-1 @@ -117,21 +115,6 @@ xdsIR: sectionName: "8080" name: envoy-gateway/gateway-1 protocol: TCP - http: - - address: 0.0.0.0 - externalPort: 443 - hostnames: - - '*' - metadata: - kind: Gateway - name: gateway-1 - namespace: envoy-gateway - sectionName: tls - name: envoy-gateway/gateway-1/tls - path: - escapedSlashesAction: UnescapeAndRedirect - mergeSlashes: true - port: 10443 readyListener: address: 0.0.0.0 ipFamily: IPv4 diff --git a/internal/gatewayapi/testdata/gateway-with-listener-with-missing-allowed-namespaces-selector.out.yaml b/internal/gatewayapi/testdata/gateway-with-listener-with-missing-allowed-namespaces-selector.out.yaml index eb0643097a..ed93a40205 100644 --- a/internal/gatewayapi/testdata/gateway-with-listener-with-missing-allowed-namespaces-selector.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-listener-with-missing-allowed-namespaces-selector.out.yaml @@ -71,13 +71,6 @@ httpRoutes: infraIR: envoy-gateway/gateway-1: proxy: - listeners: - - name: envoy-gateway/gateway-1/http - ports: - - containerPort: 10080 - name: http-80 - protocol: HTTP - servicePort: 80 metadata: labels: gateway.envoyproxy.io/owning-gateway-name: gateway-1 @@ -113,21 +106,6 @@ xdsIR: sectionName: "8080" name: envoy-gateway/gateway-1 protocol: TCP - http: - - address: 0.0.0.0 - externalPort: 80 - hostnames: - - '*' - metadata: - kind: Gateway - name: gateway-1 - namespace: envoy-gateway - sectionName: http - name: envoy-gateway/gateway-1/http - path: - escapedSlashesAction: UnescapeAndRedirect - mergeSlashes: true - port: 10080 readyListener: address: 0.0.0.0 ipFamily: IPv4 diff --git a/internal/gatewayapi/testdata/gateway-with-listener-with-tcp-with-hostname.out.yaml b/internal/gatewayapi/testdata/gateway-with-listener-with-tcp-with-hostname.out.yaml index 1e3bf50365..eee30d760d 100644 --- a/internal/gatewayapi/testdata/gateway-with-listener-with-tcp-with-hostname.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-listener-with-tcp-with-hostname.out.yaml @@ -35,13 +35,6 @@ gateways: infraIR: envoy-gateway/gateway-1: proxy: - listeners: - - name: envoy-gateway/gateway-1/tcp - ports: - - containerPort: 10080 - name: tcp-80 - protocol: TCP - servicePort: 80 metadata: labels: gateway.envoyproxy.io/owning-gateway-name: gateway-1 @@ -82,13 +75,3 @@ xdsIR: ipFamily: IPv4 path: /ready port: 19003 - tcp: - - address: 0.0.0.0 - externalPort: 80 - metadata: - kind: Gateway - name: gateway-1 - namespace: envoy-gateway - sectionName: tcp - name: envoy-gateway/gateway-1/tcp - port: 10080 diff --git a/internal/gatewayapi/testdata/gateway-with-listener-with-udp-with-hostname.out.yaml b/internal/gatewayapi/testdata/gateway-with-listener-with-udp-with-hostname.out.yaml index f3d7139fc7..cdc8155dc4 100644 --- a/internal/gatewayapi/testdata/gateway-with-listener-with-udp-with-hostname.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-listener-with-udp-with-hostname.out.yaml @@ -35,13 +35,6 @@ gateways: infraIR: envoy-gateway/gateway-1: proxy: - listeners: - - name: envoy-gateway/gateway-1/udp - ports: - - containerPort: 10080 - name: udp-80 - protocol: UDP - servicePort: 80 metadata: labels: gateway.envoyproxy.io/owning-gateway-name: gateway-1 @@ -82,13 +75,3 @@ xdsIR: ipFamily: IPv4 path: /ready port: 19003 - udp: - - address: 0.0.0.0 - externalPort: 80 - metadata: - kind: Gateway - name: gateway-1 - namespace: envoy-gateway - sectionName: udp - name: envoy-gateway/gateway-1/udp - port: 10080 diff --git a/internal/gatewayapi/testdata/gateway-with-listener-with-unsupported-protocol.out.yaml b/internal/gatewayapi/testdata/gateway-with-listener-with-unsupported-protocol.out.yaml index 4672cbedfb..1765434059 100644 --- a/internal/gatewayapi/testdata/gateway-with-listener-with-unsupported-protocol.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-listener-with-unsupported-protocol.out.yaml @@ -71,13 +71,6 @@ httpRoutes: infraIR: envoy-gateway/gateway-1: proxy: - listeners: - - name: envoy-gateway/gateway-1/unsupported - ports: - - containerPort: 10080 - name: "-80" - protocol: "" - servicePort: 80 metadata: labels: gateway.envoyproxy.io/owning-gateway-name: gateway-1 diff --git a/internal/gatewayapi/testdata/gateway-with-multiple-https-listeners-with-overlapping-hostnames-merged-gateways.out.yaml b/internal/gatewayapi/testdata/gateway-with-multiple-https-listeners-with-overlapping-hostnames-merged-gateways.out.yaml index b6c9580528..263d61190f 100644 --- a/internal/gatewayapi/testdata/gateway-with-multiple-https-listeners-with-overlapping-hostnames-merged-gateways.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-multiple-https-listeners-with-overlapping-hostnames-merged-gateways.out.yaml @@ -39,9 +39,7 @@ gateways: type: ResolvedRefs - lastTransitionTime: null message: The hostname foo.example.com overlaps with the hostname *.example.com - in listener https-1 of gateway gateway-2. ALPN will default to HTTP/1.1 - to prevent HTTP/2 connection coalescing, unless explicitly configured via - ClientTrafficPolicy + in listener https-1 of gateway gateway-2. reason: OverlappingHostnames status: "True" type: OverlappingTLSConfig @@ -102,9 +100,7 @@ gateways: type: ResolvedRefs - lastTransitionTime: null message: The hostname *.example.com overlaps with the hostname foo.example.com - in listener https-1 of gateway gateway-1. ALPN will default to HTTP/1.1 - to prevent HTTP/2 connection coalescing, unless explicitly configured via - ClientTrafficPolicy + in listener https-1 of gateway gateway-1. reason: OverlappingHostnames status: "True" type: OverlappingTLSConfig @@ -277,7 +273,6 @@ xdsIR: - certificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUMyRENDQWNBQ0FRQXdEUVlKS29aSWh2Y05BUUVMQlFBd0xURVZNQk1HQTFVRUNnd01aWGhoYlhCc1pTQkoKYm1NdU1SUXdFZ1lEVlFRRERBdGxlR0Z0Y0d4bExtTnZiVEFlRncweU5UQTBNakV3T1RFd05ETmFGdzB6TlRBMApNVGt3T1RFd05ETmFNRGN4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHhIVEFiQmdOVkJBb01GR1Y0CllXMXdiR1VnYjNKbllXNXBlbUYwYVc5dU1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0MKQVFFQXY0anl4TUh1YzQzMHdvWkk4M1JSMXVxU2gvbm9MVWVPdDZnMkNKaFVFYXNaeUNOMzN3bFRRRDE0SEhkSwpOb1k4SThWd1pOZFZCNGpjRzlnb3dDVmVQY3lqRzZPaGl1aUZNWnU2NzV6dWZEWnRlRTNEY3lTbFgrY2lSbVZZCkNuSmk3QkV3NlJMUUJ0bVV6WGxtYmRpVXE5djJwalVBL2R3ZnRLRHRZTHFrVytvTSt5MWg3cjRJV0JVK2RVcU0KcGtTem5VSCtKN1JoRkFsdytmRWlVSFRLemlCMkVtdjc3Mi91bS96NHdMWnJIeWNGbmc4L1FCM0JIUktXVTV4eQp3bWNTQ2xrVlMvWWNpMFVXcnR2eGhwck9wTUhQUGR2QkZ2M2NaWGNpUUJjb0ZNcGxsQzV0UURvdWJ0dEV1d3JpCi8rVktKWkUrSVl4ei9YeUd3Y3dJRnIzWG13SURBUUFCTUEwR0NTcUdTSWIzRFFFQkN3VUFBNElCQVFBU3VLaE8KcGtwL1VSclphbEU0OUlnc0xkN3hSTlBhREVkQ1RWZ3Qvc3praUhnSDB1NDBVaVV6KzVzaDRpdlJOazRqTm1zRwprb3FwQlBVS3pvVmtrSTcxUWQ4bHh1VzF2dkxZMXVvM0RIS2svdDFpUWVZWWpERlk3YzUxVG1BT015WUdKTlhxCi9EbW84UWgzaFB1RnI3a29kUjBLSkJyc0RsMEhoWVBjUnpWOW1sQ2lrU1B4THJGTUNwZGx0QUw2UEprSVpucUgKc1g5dEtVZk1uYW5jMkpHZTZVTDE1ODBEV2xQTUcrMU1qRElCVXdxWWYzaWNKb0NYclAwbzNmckRKcTE2VnpidApkalRtVGswakx1bGkvQ2JCZzh4dWp4emo4bmRPcVNkd05kd091OWoxSmZ2Q0I1RjZ4S0VTenowOVo5TzlOZUM5CjMrd1pLTlRSOXVEdDRKNksKLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo= name: envoy-gateway/tls-secret-example-com privateKey: '[redacted]' - tlsOverlaps: true - address: 0.0.0.0 externalPort: 443 hostnames: @@ -298,7 +293,6 @@ xdsIR: - certificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUMyRENDQWNBQ0FRQXdEUVlKS29aSWh2Y05BUUVMQlFBd0xURVZNQk1HQTFVRUNnd01aWGhoYlhCc1pTQkoKYm1NdU1SUXdFZ1lEVlFRRERBdGxlR0Z0Y0d4bExtTnZiVEFlRncweU5UQTBNakV3T1RFd05ETmFGdzB6TlRBMApNVGt3T1RFd05ETmFNRGN4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHhIVEFiQmdOVkJBb01GR1Y0CllXMXdiR1VnYjNKbllXNXBlbUYwYVc5dU1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0MKQVFFQXY0anl4TUh1YzQzMHdvWkk4M1JSMXVxU2gvbm9MVWVPdDZnMkNKaFVFYXNaeUNOMzN3bFRRRDE0SEhkSwpOb1k4SThWd1pOZFZCNGpjRzlnb3dDVmVQY3lqRzZPaGl1aUZNWnU2NzV6dWZEWnRlRTNEY3lTbFgrY2lSbVZZCkNuSmk3QkV3NlJMUUJ0bVV6WGxtYmRpVXE5djJwalVBL2R3ZnRLRHRZTHFrVytvTSt5MWg3cjRJV0JVK2RVcU0KcGtTem5VSCtKN1JoRkFsdytmRWlVSFRLemlCMkVtdjc3Mi91bS96NHdMWnJIeWNGbmc4L1FCM0JIUktXVTV4eQp3bWNTQ2xrVlMvWWNpMFVXcnR2eGhwck9wTUhQUGR2QkZ2M2NaWGNpUUJjb0ZNcGxsQzV0UURvdWJ0dEV1d3JpCi8rVktKWkUrSVl4ei9YeUd3Y3dJRnIzWG13SURBUUFCTUEwR0NTcUdTSWIzRFFFQkN3VUFBNElCQVFBU3VLaE8KcGtwL1VSclphbEU0OUlnc0xkN3hSTlBhREVkQ1RWZ3Qvc3praUhnSDB1NDBVaVV6KzVzaDRpdlJOazRqTm1zRwprb3FwQlBVS3pvVmtrSTcxUWQ4bHh1VzF2dkxZMXVvM0RIS2svdDFpUWVZWWpERlk3YzUxVG1BT015WUdKTlhxCi9EbW84UWgzaFB1RnI3a29kUjBLSkJyc0RsMEhoWVBjUnpWOW1sQ2lrU1B4THJGTUNwZGx0QUw2UEprSVpucUgKc1g5dEtVZk1uYW5jMkpHZTZVTDE1ODBEV2xQTUcrMU1qRElCVXdxWWYzaWNKb0NYclAwbzNmckRKcTE2VnpidApkalRtVGswakx1bGkvQ2JCZzh4dWp4emo4bmRPcVNkd05kd091OWoxSmZ2Q0I1RjZ4S0VTenowOVo5TzlOZUM5CjMrd1pLTlRSOXVEdDRKNksKLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo= name: envoy-gateway/tls-secret-example-com privateKey: '[redacted]' - tlsOverlaps: true - address: 0.0.0.0 externalPort: 443 hostnames: diff --git a/internal/gatewayapi/testdata/gateway-with-multiple-https-listeners-with-overlapping-hostnames.in.yaml b/internal/gatewayapi/testdata/gateway-with-multiple-https-listeners-with-overlapping-hostnames.in.yaml index 1ff5342871..e28cbebb25 100644 --- a/internal/gatewayapi/testdata/gateway-with-multiple-https-listeners-with-overlapping-hostnames.in.yaml +++ b/internal/gatewayapi/testdata/gateway-with-multiple-https-listeners-with-overlapping-hostnames.in.yaml @@ -22,17 +22,6 @@ gateways: protocol: HTTPS port: 443 hostname: "*.example.com" - allowedRoutes: - namespaces: - from: All - tls: - mode: Terminate - certificateRefs: - - name: tls-secret-example-com - - name: https-3 - protocol: HTTPS - port: 443 - hostname: "foo.bar.com" allowedRoutes: namespaces: from: All diff --git a/internal/gatewayapi/testdata/gateway-with-multiple-https-listeners-with-overlapping-hostnames.out.yaml b/internal/gatewayapi/testdata/gateway-with-multiple-https-listeners-with-overlapping-hostnames.out.yaml index ee1e4b38a5..002586dd3e 100644 --- a/internal/gatewayapi/testdata/gateway-with-multiple-https-listeners-with-overlapping-hostnames.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-multiple-https-listeners-with-overlapping-hostnames.out.yaml @@ -25,17 +25,6 @@ gateways: name: https-2 port: 443 protocol: HTTPS - tls: - certificateRefs: - - name: tls-secret-example-com - mode: Terminate - - allowedRoutes: - namespaces: - from: All - hostname: foo.bar.com - name: https-3 - port: 443 - protocol: HTTPS tls: certificateRefs: - name: tls-secret-foo-bar-com @@ -61,8 +50,7 @@ gateways: type: ResolvedRefs - lastTransitionTime: null message: The hostname foo.example.com overlaps with the hostname *.example.com - in listener https-2. ALPN will default to HTTP/1.1 to prevent HTTP/2 connection - coalescing, unless explicitly configured via ClientTrafficPolicy + in listener https-2. reason: OverlappingHostnames status: "True" type: OverlappingTLSConfig @@ -91,8 +79,7 @@ gateways: type: ResolvedRefs - lastTransitionTime: null message: The hostname *.example.com overlaps with the hostname foo.example.com - in listener https-1. ALPN will default to HTTP/1.1 to prevent HTTP/2 connection - coalescing, unless explicitly configured via ClientTrafficPolicy + in listener https-1. reason: OverlappingHostnames status: "True" type: OverlappingTLSConfig @@ -102,29 +89,6 @@ gateways: kind: HTTPRoute - group: gateway.networking.k8s.io kind: GRPCRoute - - attachedRoutes: 1 - conditions: - - lastTransitionTime: null - message: Sending translated listener configuration to the data plane - reason: Programmed - status: "True" - type: Programmed - - lastTransitionTime: null - message: Listener has been successfully translated - reason: Accepted - status: "True" - type: Accepted - - lastTransitionTime: null - message: Listener references have been resolved - reason: ResolvedRefs - status: "True" - type: ResolvedRefs - name: https-3 - supportedKinds: - - group: gateway.networking.k8s.io - kind: HTTPRoute - - group: gateway.networking.k8s.io - kind: GRPCRoute httpRoutes: - apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute @@ -256,7 +220,6 @@ xdsIR: - certificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUMyRENDQWNBQ0FRQXdEUVlKS29aSWh2Y05BUUVMQlFBd0xURVZNQk1HQTFVRUNnd01aWGhoYlhCc1pTQkoKYm1NdU1SUXdFZ1lEVlFRRERBdGxlR0Z0Y0d4bExtTnZiVEFlRncweU5UQTBNakV3T1RFd05ETmFGdzB6TlRBMApNVGt3T1RFd05ETmFNRGN4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHhIVEFiQmdOVkJBb01GR1Y0CllXMXdiR1VnYjNKbllXNXBlbUYwYVc5dU1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0MKQVFFQXY0anl4TUh1YzQzMHdvWkk4M1JSMXVxU2gvbm9MVWVPdDZnMkNKaFVFYXNaeUNOMzN3bFRRRDE0SEhkSwpOb1k4SThWd1pOZFZCNGpjRzlnb3dDVmVQY3lqRzZPaGl1aUZNWnU2NzV6dWZEWnRlRTNEY3lTbFgrY2lSbVZZCkNuSmk3QkV3NlJMUUJ0bVV6WGxtYmRpVXE5djJwalVBL2R3ZnRLRHRZTHFrVytvTSt5MWg3cjRJV0JVK2RVcU0KcGtTem5VSCtKN1JoRkFsdytmRWlVSFRLemlCMkVtdjc3Mi91bS96NHdMWnJIeWNGbmc4L1FCM0JIUktXVTV4eQp3bWNTQ2xrVlMvWWNpMFVXcnR2eGhwck9wTUhQUGR2QkZ2M2NaWGNpUUJjb0ZNcGxsQzV0UURvdWJ0dEV1d3JpCi8rVktKWkUrSVl4ei9YeUd3Y3dJRnIzWG13SURBUUFCTUEwR0NTcUdTSWIzRFFFQkN3VUFBNElCQVFBU3VLaE8KcGtwL1VSclphbEU0OUlnc0xkN3hSTlBhREVkQ1RWZ3Qvc3praUhnSDB1NDBVaVV6KzVzaDRpdlJOazRqTm1zRwprb3FwQlBVS3pvVmtrSTcxUWQ4bHh1VzF2dkxZMXVvM0RIS2svdDFpUWVZWWpERlk3YzUxVG1BT015WUdKTlhxCi9EbW84UWgzaFB1RnI3a29kUjBLSkJyc0RsMEhoWVBjUnpWOW1sQ2lrU1B4THJGTUNwZGx0QUw2UEprSVpucUgKc1g5dEtVZk1uYW5jMkpHZTZVTDE1ODBEV2xQTUcrMU1qRElCVXdxWWYzaWNKb0NYclAwbzNmckRKcTE2VnpidApkalRtVGswakx1bGkvQ2JCZzh4dWp4emo4bmRPcVNkd05kd091OWoxSmZ2Q0I1RjZ4S0VTenowOVo5TzlOZUM5CjMrd1pLTlRSOXVEdDRKNksKLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo= name: envoy-gateway/tls-secret-example-com privateKey: '[redacted]' - tlsOverlaps: true - address: 0.0.0.0 externalPort: 443 hostnames: @@ -302,58 +265,6 @@ xdsIR: distinct: false name: "" prefix: / - tls: - alpnProtocols: null - certificates: - - certificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUMyRENDQWNBQ0FRQXdEUVlKS29aSWh2Y05BUUVMQlFBd0xURVZNQk1HQTFVRUNnd01aWGhoYlhCc1pTQkoKYm1NdU1SUXdFZ1lEVlFRRERBdGxlR0Z0Y0d4bExtTnZiVEFlRncweU5UQTBNakV3T1RFd05ETmFGdzB6TlRBMApNVGt3T1RFd05ETmFNRGN4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHhIVEFiQmdOVkJBb01GR1Y0CllXMXdiR1VnYjNKbllXNXBlbUYwYVc5dU1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0MKQVFFQXY0anl4TUh1YzQzMHdvWkk4M1JSMXVxU2gvbm9MVWVPdDZnMkNKaFVFYXNaeUNOMzN3bFRRRDE0SEhkSwpOb1k4SThWd1pOZFZCNGpjRzlnb3dDVmVQY3lqRzZPaGl1aUZNWnU2NzV6dWZEWnRlRTNEY3lTbFgrY2lSbVZZCkNuSmk3QkV3NlJMUUJ0bVV6WGxtYmRpVXE5djJwalVBL2R3ZnRLRHRZTHFrVytvTSt5MWg3cjRJV0JVK2RVcU0KcGtTem5VSCtKN1JoRkFsdytmRWlVSFRLemlCMkVtdjc3Mi91bS96NHdMWnJIeWNGbmc4L1FCM0JIUktXVTV4eQp3bWNTQ2xrVlMvWWNpMFVXcnR2eGhwck9wTUhQUGR2QkZ2M2NaWGNpUUJjb0ZNcGxsQzV0UURvdWJ0dEV1d3JpCi8rVktKWkUrSVl4ei9YeUd3Y3dJRnIzWG13SURBUUFCTUEwR0NTcUdTSWIzRFFFQkN3VUFBNElCQVFBU3VLaE8KcGtwL1VSclphbEU0OUlnc0xkN3hSTlBhREVkQ1RWZ3Qvc3praUhnSDB1NDBVaVV6KzVzaDRpdlJOazRqTm1zRwprb3FwQlBVS3pvVmtrSTcxUWQ4bHh1VzF2dkxZMXVvM0RIS2svdDFpUWVZWWpERlk3YzUxVG1BT015WUdKTlhxCi9EbW84UWgzaFB1RnI3a29kUjBLSkJyc0RsMEhoWVBjUnpWOW1sQ2lrU1B4THJGTUNwZGx0QUw2UEprSVpucUgKc1g5dEtVZk1uYW5jMkpHZTZVTDE1ODBEV2xQTUcrMU1qRElCVXdxWWYzaWNKb0NYclAwbzNmckRKcTE2VnpidApkalRtVGswakx1bGkvQ2JCZzh4dWp4emo4bmRPcVNkd05kd091OWoxSmZ2Q0I1RjZ4S0VTenowOVo5TzlOZUM5CjMrd1pLTlRSOXVEdDRKNksKLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo= - name: envoy-gateway/tls-secret-example-com - privateKey: '[redacted]' - tlsOverlaps: true - - address: 0.0.0.0 - externalPort: 443 - hostnames: - - foo.bar.com - metadata: - kind: Gateway - name: gateway-1 - namespace: envoy-gateway - sectionName: https-3 - name: envoy-gateway/gateway-1/https-3 - path: - escapedSlashesAction: UnescapeAndRedirect - mergeSlashes: true - port: 10443 - routes: - - destination: - metadata: - kind: HTTPRoute - name: httproute-1 - namespace: envoy-gateway - name: httproute/envoy-gateway/httproute-1/rule/0 - settings: - - addressType: IP - endpoints: - - host: 7.7.7.7 - port: 8080 - metadata: - kind: Service - name: service-1 - namespace: envoy-gateway - sectionName: "8080" - name: httproute/envoy-gateway/httproute-1/rule/0/backend/0 - protocol: HTTP - weight: 1 - hostname: foo.bar.com - isHTTP2: false - metadata: - kind: HTTPRoute - name: httproute-1 - namespace: envoy-gateway - name: httproute/envoy-gateway/httproute-1/rule/0/match/0/foo_bar_com - pathMatch: - distinct: false - name: "" - prefix: / tls: alpnProtocols: null certificates: diff --git a/internal/gatewayapi/testdata/gateway-with-two-listeners-on-same-tcp-or-tls-port.out.yaml b/internal/gatewayapi/testdata/gateway-with-two-listeners-on-same-tcp-or-tls-port.out.yaml index 228b0bf29f..f255acbcf4 100644 --- a/internal/gatewayapi/testdata/gateway-with-two-listeners-on-same-tcp-or-tls-port.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-two-listeners-on-same-tcp-or-tls-port.out.yaml @@ -70,12 +70,6 @@ infraIR: name: tcp-162 protocol: TCP servicePort: 162 - - name: envoy-gateway/gateway-1/tcp2 - ports: - - containerPort: 10162 - name: tls-162 - protocol: TLS - servicePort: 162 metadata: labels: gateway.envoyproxy.io/owning-gateway-name: gateway-1 @@ -182,12 +176,3 @@ xdsIR: name: tcproute-1 namespace: default name: tcproute/default/tcproute-1 - - address: 0.0.0.0 - externalPort: 162 - metadata: - kind: Gateway - name: gateway-1 - namespace: envoy-gateway - sectionName: tcp2 - name: envoy-gateway/gateway-1/tcp2 - port: 10162 diff --git a/internal/gatewayapi/testdata/gateway-with-two-listeners-on-same-udp-port.out.yaml b/internal/gatewayapi/testdata/gateway-with-two-listeners-on-same-udp-port.out.yaml index cac7a60a43..f858c8d772 100644 --- a/internal/gatewayapi/testdata/gateway-with-two-listeners-on-same-udp-port.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-two-listeners-on-same-udp-port.out.yaml @@ -175,12 +175,3 @@ xdsIR: protocol: UDP weight: 1 name: udproute/default/udproute-1 - - address: 0.0.0.0 - externalPort: 162 - metadata: - kind: Gateway - name: gateway-1 - namespace: envoy-gateway - sectionName: udp2 - name: envoy-gateway/gateway-1/udp2 - port: 10162 diff --git a/internal/gatewayapi/testdata/gateway-with-two-listeners-with-http-and-tlsroute-same-hostname-and-port.out.yaml b/internal/gatewayapi/testdata/gateway-with-two-listeners-with-http-and-tlsroute-same-hostname-and-port.out.yaml index 823f9813a5..20c4241d1a 100644 --- a/internal/gatewayapi/testdata/gateway-with-two-listeners-with-http-and-tlsroute-same-hostname-and-port.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-two-listeners-with-http-and-tlsroute-same-hostname-and-port.out.yaml @@ -106,13 +106,6 @@ httpRoutes: infraIR: envoy-gateway/gateway-1: proxy: - listeners: - - name: envoy-gateway/gateway-1/http-1 - ports: - - containerPort: 10080 - name: http-80 - protocol: HTTP - servicePort: 80 metadata: labels: gateway.envoyproxy.io/owning-gateway-name: gateway-1 @@ -179,33 +172,8 @@ xdsIR: sectionName: "8080" name: envoy-gateway/gateway-1 protocol: TCP - http: - - address: 0.0.0.0 - externalPort: 80 - hostnames: - - foo.com - metadata: - kind: Gateway - name: gateway-1 - namespace: envoy-gateway - sectionName: http-1 - name: envoy-gateway/gateway-1/http-1 - path: - escapedSlashesAction: UnescapeAndRedirect - mergeSlashes: true - port: 10080 readyListener: address: 0.0.0.0 ipFamily: IPv4 path: /ready port: 19003 - tcp: - - address: 0.0.0.0 - externalPort: 80 - metadata: - kind: Gateway - name: gateway-1 - namespace: envoy-gateway - sectionName: tls-1 - name: envoy-gateway/gateway-1/tls-1 - port: 10080 diff --git a/internal/gatewayapi/testdata/gateway-with-two-listeners-with-same-port-and-hostname.out.yaml b/internal/gatewayapi/testdata/gateway-with-two-listeners-with-same-port-and-hostname.out.yaml index 0df14ad10c..ecb8190327 100644 --- a/internal/gatewayapi/testdata/gateway-with-two-listeners-with-same-port-and-hostname.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-two-listeners-with-same-port-and-hostname.out.yaml @@ -106,13 +106,6 @@ httpRoutes: infraIR: envoy-gateway/gateway-1: proxy: - listeners: - - name: envoy-gateway/gateway-1/http-1 - ports: - - containerPort: 10080 - name: http-80 - protocol: HTTP - servicePort: 80 metadata: labels: gateway.envoyproxy.io/owning-gateway-name: gateway-1 @@ -148,35 +141,6 @@ xdsIR: sectionName: "8080" name: envoy-gateway/gateway-1 protocol: TCP - http: - - address: 0.0.0.0 - externalPort: 80 - hostnames: - - foo.com - metadata: - kind: Gateway - name: gateway-1 - namespace: envoy-gateway - sectionName: http-1 - name: envoy-gateway/gateway-1/http-1 - path: - escapedSlashesAction: UnescapeAndRedirect - mergeSlashes: true - port: 10080 - - address: 0.0.0.0 - externalPort: 80 - hostnames: - - foo.com - metadata: - kind: Gateway - name: gateway-1 - namespace: envoy-gateway - sectionName: http-2 - name: envoy-gateway/gateway-1/http-2 - path: - escapedSlashesAction: UnescapeAndRedirect - mergeSlashes: true - port: 10080 readyListener: address: 0.0.0.0 ipFamily: IPv4 diff --git a/internal/gatewayapi/testdata/gateway-with-two-listeners-with-same-port-and-incompatible-protocol.in.yaml b/internal/gatewayapi/testdata/gateway-with-two-listeners-with-same-port-and-incompatible-protocol.in.yaml index 37c0a342f3..4d899da6a8 100644 --- a/internal/gatewayapi/testdata/gateway-with-two-listeners-with-same-port-and-incompatible-protocol.in.yaml +++ b/internal/gatewayapi/testdata/gateway-with-two-listeners-with-same-port-and-incompatible-protocol.in.yaml @@ -21,6 +21,20 @@ gateways: allowedRoutes: namespaces: from: All + tls: + mode: Terminate + certificateRefs: + - name: tls-secret-1 +secrets: + - apiVersion: v1 + kind: Secret + metadata: + namespace: envoy-gateway + name: tls-secret-1 + type: kubernetes.io/tls + data: + tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUREVENDQWZXZ0F3SUJBZ0lVRUZNaFA5ZUo5WEFCV3NRNVptNmJSazJjTE5Rd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0ZqRVVNQklHQTFVRUF3d0xabTl2TG1KaGNpNWpiMjB3SGhjTk1qUXdNakk1TURrek1ERXdXaGNOTXpRdwpNakkyTURrek1ERXdXakFXTVJRd0VnWURWUVFEREF0bWIyOHVZbUZ5TG1OdmJUQ0NBU0l3RFFZSktvWklodmNOCkFRRUJCUUFEZ2dFUEFEQ0NBUW9DZ2dFQkFKbEk2WXhFOVprQ1BzNnBDUXhickNtZWl4OVA1RGZ4OVJ1NUxENFQKSm1kVzdJS2R0UVYvd2ZMbXRzdTc2QithVGRDaldlMEJUZmVPT1JCYlIzY1BBRzZFbFFMaWNsUVVydW4zcStncwpKcEsrSTdjSStqNXc4STY4WEg1V1E3clZVdGJ3SHBxYncrY1ZuQnFJVU9MaUlhdGpJZjdLWDUxTTF1RjljZkVICkU0RG5jSDZyYnI1OS9SRlpCc2toeHM1T3p3Sklmb2hreXZGd2V1VHd4Sy9WcGpJKzdPYzQ4QUJDWHBOTzlEL3EKRWgrck9hdWpBTWNYZ0hRSVRrQ2lpVVRjVW82TFNIOXZMWlB0YXFmem9acTZuaE1xcFc2NUUxcEF3RjNqeVRUeAphNUk4SmNmU0Zqa2llWjIwTFVRTW43TThVNHhIamFvL2d2SDBDQWZkQjdSTFUyc0NBd0VBQWFOVE1GRXdIUVlEClZSME9CQllFRk9SQ0U4dS8xRERXN2loWnA3Y3g5dFNtUG02T01COEdBMVVkSXdRWU1CYUFGT1JDRTh1LzFERFcKN2loWnA3Y3g5dFNtUG02T01BOEdBMVVkRXdFQi93UUZNQU1CQWY4d0RRWUpLb1pJaHZjTkFRRUxCUUFEZ2dFQgpBRnQ1M3pqc3FUYUg1YThFMmNodm1XQWdDcnhSSzhiVkxNeGl3TkdqYm1FUFJ6K3c2TngrazBBOEtFY0lEc0tjClNYY2k1OHU0b1didFZKQmx6YS9adWpIUjZQMUJuT3BsK2FveTc4NGJiZDRQMzl3VExvWGZNZmJCQ20xdmV2aDkKQUpLbncyWnRxcjRta2JMY3hFcWxxM3NCTEZBUzlzUUxuS05DZTJjR0xkVHAyYm9HK3FjZ3lRZ0NJTTZmOEVNdgpXUGlmQ01NR3V6Sy9HUkY0YlBPL1lGNDhld0R1M1VlaWgwWFhkVUFPRTlDdFVhOE5JaGMxVVBhT3pQcnRZVnFyClpPR2t2L0t1K0I3OGg4U0VzTzlYclFjdXdiT25KeDZLdFIrYWV5a3ZBcFhDUTNmWkMvYllLQUFSK1A0QUpvUVoKYndJVW1YaTRnajVtK2JLUGhlK2lyK0U9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0= + tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQ2QwZlBDYWtweE1nUnUKT0VXQjFiQk5FM3ZseW55aTZWbkV2VWF1OUhvakR2UHVPTFJIaGI4MmoyY1ovMHhnL1lKR09LelBuV2JERkxGNApHdWh3dDRENmFUR0xYNklPODEwTDZ0SXZIWGZNUXRJS2VwdTZ3K3p1WVo4bG1yejB1RjZlWEtqamVIbHhyb2ZrCnVNekM3OUVaU0lYZlZlczJ1SmdVRSs4VGFzSDUzQ2Y4MFNSRGlIeEdxckttdVNjWCtwejBreGdCZ1VWYTVVS20KUWdTZDFmVUxLOUEwNXAxOXkrdURPM204bVhRNkxVQ0N1STFwZHNROGFlNS9zamlxa0VjWlJjMTdWYVgxWjVVaQpvcGZnNW9SY05VTG9VTHNiek9aNTR0YlVDUmdSV2VLbGZxaElINEZ6OUlkVlUyR3dFdEdhMmV6TjgyMVBaQ3QzCjZhbVRIelJsQWdNQkFBRUNnZ0VBWTFGTUlLNDVXTkVNUHJ6RTZUY3NNdVV2RkdhQVZ4bVk5NW5SMEtwajdvb3IKY21CVys2ZXN0TTQ4S1AwaitPbXd3VFpMY29Cd3VoWGN0V1Bob1lXcDhteWUxRUlEdjNyaHRHMDdocEQ1NGg2dgpCZzh3ejdFYStzMk9sT0N6UnlKNzBSY281YlhjWDNGaGJjdnFlRWJwaFFyQnpOSEtLMjZ4cmZqNWZIT3p6T1FGCmJHdUZ3SDVic3JGdFhlajJXM3c4eW90N0ZQSDV3S3RpdnhvSWU5RjMyOXNnOU9EQnZqWnpiaG1LVTArckFTK1kKRGVield2bFJyaEUrbXVmQTN6M0N0QXhDOFJpNzNscFNoTDRQQWlvcG1SUXlxZXRXMjYzOFFxcnM0R3hnNzhwbApJUXJXTmNBc2s3Slg5d3RZenV6UFBXSXRWTTFscFJiQVRhNTJqdFl2NVFLQmdRRE5tMTFtZTRYam1ZSFV2cStZCmFTUzdwK2UybXZEMHVaOU9JeFluQnBWMGkrckNlYnFFMkE1Rm5hcDQ5Yld4QTgwUElldlVkeUpCL2pUUkoxcVMKRUpXQkpMWm1LVkg2K1QwdWw1ZUtOcWxFTFZHU0dCSXNpeE9SUXpDZHBoMkx0UmtBMHVjSVUzY3hiUmVMZkZCRQpiSkdZWENCdlNGcWd0VDlvZTFldVpMVmFOd0tCZ1FERWdENzJENk81eGIweEQ1NDQ1M0RPMUJhZmd6aThCWDRTCk1SaVd2LzFUQ0w5N05sRWtoeXovNmtQd1owbXJRcE5CMzZFdkpKZFVteHdkU2MyWDhrOGcxMC85NVlLQkdWQWoKL3d0YVZYbE9WeEFvK0ZSelpZeFpyQ29uWWFSMHVwUzFybDRtenN4REhlZU9mUVZUTUgwUjdZN0pnbTA5dXQ4SwplanAvSXZBb1F3S0JnQjNaRWlRUWhvMVYrWjBTMlpiOG5KS0plMy9zMmxJTXFHM0ZkaS9RS3Q0eWViQWx6OGY5ClBZVXBzRmZEQTg5Z3grSU1nSm5sZVptdTk2ZnRXSjZmdmJSenllN216TG5zZU05TXZua1lHbGFGWmJRWnZubXMKN3ZoRmtzY3dHRlh4d21GMlBJZmU1Z3pNMDRBeVdjeTFIaVhLS2dNOXM3cGsxWUdyZGowZzdacmRBb0dCQUtLNApDR3MrbkRmMEZTMFJYOWFEWVJrRTdBNy9YUFhtSG5YMkRnU1h5N0Q4NTRPaWdTTWNoUmtPNTErbVNJejNQbllvCk41T1FXM2lHVVl1M1YvYmhnc0VSUzM1V2xmRk9BdDBzRUR5bjF5SVdXcDF5dG93d3BUNkVvUXVuZ2NYZjA5RjMKS1NROXowd3M4VmsvRWkvSFVXcU5LOWFXbU51cmFaT0ZqL2REK1ZkOUFvR0FMWFN3dEE3K043RDRkN0VEMURSRQpHTWdZNVd3OHFvdDZSdUNlNkpUY0FnU3B1MkhNU3JVY2dXclpiQnJZb09FUnVNQjFoMVJydk5ybU1qQlM0VW9FClgyZC8vbGhpOG1wL2VESWN3UDNRa2puanBJRFJWMFN1eWxrUkVaZURKZjVZb3R6eDdFdkJhbzFIbkQrWEg4eUIKVUtmWGJTaHZKVUdhRmgxT3Q1Y3JoM1k9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K httpRoutes: - apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute diff --git a/internal/gatewayapi/testdata/gateway-with-two-listeners-with-same-port-and-incompatible-protocol.out.yaml b/internal/gatewayapi/testdata/gateway-with-two-listeners-with-same-port-and-incompatible-protocol.out.yaml index 3eab4a3a04..4af2173f3d 100644 --- a/internal/gatewayapi/testdata/gateway-with-two-listeners-with-same-port-and-incompatible-protocol.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-two-listeners-with-same-port-and-incompatible-protocol.out.yaml @@ -21,6 +21,10 @@ gateways: name: http-2 port: 80 protocol: HTTPS + tls: + certificateRefs: + - name: tls-secret-1 + mode: Terminate status: listeners: - attachedRoutes: 1 @@ -54,7 +58,7 @@ gateways: status: "True" type: Conflicted - lastTransitionTime: null - message: Listener must have TLS set when protocol is HTTPS. + message: Listener is invalid, see other Conditions for details. reason: Invalid status: "False" type: Programmed @@ -106,13 +110,6 @@ httpRoutes: infraIR: envoy-gateway/gateway-1: proxy: - listeners: - - name: envoy-gateway/gateway-1/http-1 - ports: - - containerPort: 10080 - name: http-80 - protocol: HTTP - servicePort: 80 metadata: labels: gateway.envoyproxy.io/owning-gateway-name: gateway-1 @@ -148,35 +145,6 @@ xdsIR: sectionName: "8080" name: envoy-gateway/gateway-1 protocol: TCP - http: - - address: 0.0.0.0 - externalPort: 80 - hostnames: - - foo.com - metadata: - kind: Gateway - name: gateway-1 - namespace: envoy-gateway - sectionName: http-1 - name: envoy-gateway/gateway-1/http-1 - path: - escapedSlashesAction: UnescapeAndRedirect - mergeSlashes: true - port: 10080 - - address: 0.0.0.0 - externalPort: 80 - hostnames: - - bar.com - metadata: - kind: Gateway - name: gateway-1 - namespace: envoy-gateway - sectionName: http-2 - name: envoy-gateway/gateway-1/http-2 - path: - escapedSlashesAction: UnescapeAndRedirect - mergeSlashes: true - port: 10080 readyListener: address: 0.0.0.0 ipFamily: IPv4 diff --git a/internal/gatewayapi/testdata/gateway-with-two-listeners-with-same-port-http-tcp-protocol.out.yaml b/internal/gatewayapi/testdata/gateway-with-two-listeners-with-same-port-http-tcp-protocol.out.yaml index 476881b619..1a31d49847 100644 --- a/internal/gatewayapi/testdata/gateway-with-two-listeners-with-same-port-http-tcp-protocol.out.yaml +++ b/internal/gatewayapi/testdata/gateway-with-two-listeners-with-same-port-http-tcp-protocol.out.yaml @@ -25,15 +25,15 @@ gateways: - attachedRoutes: 1 conditions: - lastTransitionTime: null - message: Sending translated listener configuration to the data plane - reason: Programmed + message: All listeners for a given port must use a compatible protocol + reason: ProtocolConflict status: "True" - type: Programmed + type: Conflicted - lastTransitionTime: null - message: Listener has been successfully translated - reason: Accepted - status: "True" - type: Accepted + message: Listener is invalid, see other Conditions for details. + reason: Invalid + status: "False" + type: Programmed - lastTransitionTime: null message: Listener references have been resolved reason: ResolvedRefs @@ -45,18 +45,18 @@ gateways: kind: HTTPRoute - group: gateway.networking.k8s.io kind: GRPCRoute - - attachedRoutes: 1 + - attachedRoutes: 0 conditions: - lastTransitionTime: null - message: Sending translated listener configuration to the data plane - reason: Programmed + message: All listeners for a given port must use a compatible protocol + reason: ProtocolConflict status: "True" - type: Programmed + type: Conflicted - lastTransitionTime: null - message: Listener has been successfully translated - reason: Accepted - status: "True" - type: Accepted + message: Listener is invalid, see other Conditions for details. + reason: Invalid + status: "False" + type: Programmed - lastTransitionTime: null message: Listener references have been resolved reason: ResolvedRefs @@ -87,9 +87,9 @@ httpRoutes: parents: - conditions: - lastTransitionTime: null - message: Route is accepted - reason: Accepted - status: "True" + message: There are no ready listeners for this parent ref + reason: NoReadyListeners + status: "False" type: Accepted - lastTransitionTime: null message: Resolved all the Object references for the Route @@ -103,19 +103,6 @@ httpRoutes: infraIR: envoy-gateway/gateway-1: proxy: - listeners: - - name: envoy-gateway/gateway-1/http - ports: - - containerPort: 10080 - name: http-80 - protocol: HTTP - servicePort: 80 - - name: envoy-gateway/gateway-1/tcp - ports: - - containerPort: 10080 - name: tcp-80 - protocol: TCP - servicePort: 80 metadata: labels: gateway.envoyproxy.io/owning-gateway-name: gateway-1 @@ -143,9 +130,9 @@ tcpRoutes: parents: - conditions: - lastTransitionTime: null - message: Route is accepted - reason: Accepted - status: "True" + message: There are no ready listeners for this parent ref + reason: NoReadyListeners + status: "False" type: Accepted - lastTransitionTime: null message: Resolved all the Object references for the Route @@ -182,89 +169,8 @@ xdsIR: sectionName: "8080" name: envoy-gateway/gateway-1 protocol: TCP - http: - - address: 0.0.0.0 - externalPort: 80 - hostnames: - - '*' - metadata: - kind: Gateway - name: gateway-1 - namespace: envoy-gateway - sectionName: http - name: envoy-gateway/gateway-1/http - path: - escapedSlashesAction: UnescapeAndRedirect - mergeSlashes: true - port: 10080 - routes: - - destination: - metadata: - kind: HTTPRoute - name: httproute-1 - namespace: default - name: httproute/default/httproute-1/rule/0 - settings: - - addressType: IP - endpoints: - - host: 7.7.7.7 - port: 8080 - metadata: - kind: Service - name: service-1 - namespace: default - sectionName: "8080" - name: httproute/default/httproute-1/rule/0/backend/0 - protocol: HTTP - weight: 1 - hostname: '*' - isHTTP2: false - metadata: - kind: HTTPRoute - name: httproute-1 - namespace: default - name: httproute/default/httproute-1/rule/0/match/0/* - pathMatch: - distinct: false - name: "" - prefix: / readyListener: address: 0.0.0.0 ipFamily: IPv4 path: /ready port: 19003 - tcp: - - address: 0.0.0.0 - externalPort: 80 - metadata: - kind: Gateway - name: gateway-1 - namespace: envoy-gateway - sectionName: tcp - name: envoy-gateway/gateway-1/tcp - port: 10080 - routes: - - destination: - metadata: - kind: TCPRoute - name: tcproute-1 - namespace: default - name: tcproute/default/tcproute-1/rule/-1 - settings: - - addressType: IP - endpoints: - - host: 7.7.7.7 - port: 8163 - metadata: - kind: Service - name: service-1 - namespace: default - sectionName: "8163" - name: tcproute/default/tcproute-1/rule/-1/backend/0 - protocol: TCP - weight: 1 - metadata: - kind: TCPRoute - name: tcproute-1 - namespace: default - name: tcproute/default/tcproute-1 diff --git a/internal/gatewayapi/testdata/listenerset-conflict-listeners.out.yaml b/internal/gatewayapi/testdata/listenerset-conflict-listeners.out.yaml index 736ddb24a9..c8ead033c5 100644 --- a/internal/gatewayapi/testdata/listenerset-conflict-listeners.out.yaml +++ b/internal/gatewayapi/testdata/listenerset-conflict-listeners.out.yaml @@ -84,18 +84,6 @@ infraIR: name: http-80 protocol: HTTP servicePort: 80 - - name: gateway-xls/composite-gateway/conflict-listener - ports: - - containerPort: 8888 - name: http-8888 - protocol: HTTP - servicePort: 8888 - - name: gateway-xls/composite-gateway/gateway-xls/conflict-listener-from-same-xls/conflict-listener-1 - ports: - - containerPort: 8089 - name: http-8089 - protocol: HTTP - servicePort: 8089 - name: gateway-xls/composite-gateway/gateway-xls/conflict-listener-from-two-xlss/good-listener ports: - containerPort: 8090 @@ -142,12 +130,12 @@ listenerSets: status: conditions: - lastTransitionTime: null - message: All listeners are invalid + message: No listeners are accepted reason: ListenersNotValid status: "False" type: Accepted - lastTransitionTime: null - message: All listeners are invalid + message: No listeners are programmed reason: ListenersNotValid status: "False" type: Programmed @@ -227,7 +215,7 @@ listenerSets: status: "True" type: Accepted - lastTransitionTime: null - message: Some listeners are invalid + message: Some listeners are not programmed reason: Programmed status: "True" type: Programmed @@ -312,7 +300,7 @@ listenerSets: status: "True" type: Accepted - lastTransitionTime: null - message: Some listeners are invalid + message: Some listeners are not programmed reason: Programmed status: "True" type: Programmed @@ -409,62 +397,6 @@ xdsIR: escapedSlashesAction: UnescapeAndRedirect mergeSlashes: true port: 10080 - - address: 0.0.0.0 - externalPort: 8888 - hostnames: - - '*' - metadata: - kind: Gateway - name: composite-gateway - namespace: gateway-xls - sectionName: conflict-listener - name: gateway-xls/composite-gateway/conflict-listener - path: - escapedSlashesAction: UnescapeAndRedirect - mergeSlashes: true - port: 8888 - - address: 0.0.0.0 - externalPort: 8089 - hostnames: - - '*' - metadata: - kind: Gateway - name: composite-gateway - namespace: gateway-xls - sectionName: conflict-listener-1 - name: gateway-xls/composite-gateway/gateway-xls/conflict-listener-from-same-xls/conflict-listener-1 - path: - escapedSlashesAction: UnescapeAndRedirect - mergeSlashes: true - port: 8089 - - address: 0.0.0.0 - externalPort: 8089 - hostnames: - - '*' - metadata: - kind: Gateway - name: composite-gateway - namespace: gateway-xls - sectionName: conflict-listener-2 - name: gateway-xls/composite-gateway/gateway-xls/conflict-listener-from-same-xls/conflict-listener-2 - path: - escapedSlashesAction: UnescapeAndRedirect - mergeSlashes: true - port: 8089 - - address: 0.0.0.0 - externalPort: 8089 - hostnames: - - '*' - metadata: - kind: Gateway - name: composite-gateway - namespace: gateway-xls - sectionName: conflict-listener - name: gateway-xls/composite-gateway/gateway-xls/conflict-listener-from-two-xlss/conflict-listener - path: - escapedSlashesAction: UnescapeAndRedirect - mergeSlashes: true - port: 8089 - address: 0.0.0.0 externalPort: 8090 hostnames: @@ -479,20 +411,6 @@ xdsIR: escapedSlashesAction: UnescapeAndRedirect mergeSlashes: true port: 8090 - - address: 0.0.0.0 - externalPort: 8888 - hostnames: - - '*' - metadata: - kind: Gateway - name: composite-gateway - namespace: gateway-xls - sectionName: conflict-listener - name: gateway-xls/composite-gateway/gateway-xls/listener-conflict-with-gateway/conflict-listener - path: - escapedSlashesAction: UnescapeAndRedirect - mergeSlashes: true - port: 8888 - address: 0.0.0.0 externalPort: 8091 hostnames: diff --git a/internal/gatewayapi/testdata/listenerset-cross-namespace.out.yaml b/internal/gatewayapi/testdata/listenerset-cross-namespace.out.yaml index 22f5f6236c..3c2b82ad7a 100644 --- a/internal/gatewayapi/testdata/listenerset-cross-namespace.out.yaml +++ b/internal/gatewayapi/testdata/listenerset-cross-namespace.out.yaml @@ -170,12 +170,12 @@ listenerSets: status: conditions: - lastTransitionTime: null - message: All listeners are valid + message: All listeners are accepted reason: Accepted status: "True" type: Accepted - lastTransitionTime: null - message: All listeners are valid + message: All listeners are programmed reason: Programmed status: "True" type: Programmed @@ -227,12 +227,12 @@ listenerSets: status: conditions: - lastTransitionTime: null - message: All listeners are valid + message: All listeners are accepted reason: Accepted status: "True" type: Accepted - lastTransitionTime: null - message: All listeners are valid + message: All listeners are programmed reason: Programmed status: "True" type: Programmed diff --git a/internal/gatewayapi/testdata/listenerset-grpcroute.out.yaml b/internal/gatewayapi/testdata/listenerset-grpcroute.out.yaml index 7b44839908..512f312629 100644 --- a/internal/gatewayapi/testdata/listenerset-grpcroute.out.yaml +++ b/internal/gatewayapi/testdata/listenerset-grpcroute.out.yaml @@ -198,12 +198,12 @@ listenerSets: status: conditions: - lastTransitionTime: null - message: All listeners are valid + message: All listeners are accepted reason: Accepted status: "True" type: Accepted - lastTransitionTime: null - message: All listeners are valid + message: All listeners are programmed reason: Programmed status: "True" type: Programmed @@ -254,12 +254,12 @@ listenerSets: status: conditions: - lastTransitionTime: null - message: All listeners are valid + message: All listeners are accepted reason: Accepted status: "True" type: Accepted - lastTransitionTime: null - message: All listeners are valid + message: All listeners are programmed reason: Programmed status: "True" type: Programmed diff --git a/internal/gatewayapi/testdata/listenerset-httproute.out.yaml b/internal/gatewayapi/testdata/listenerset-httproute.out.yaml index 69aa62ae91..d80d3c20ce 100644 --- a/internal/gatewayapi/testdata/listenerset-httproute.out.yaml +++ b/internal/gatewayapi/testdata/listenerset-httproute.out.yaml @@ -240,12 +240,12 @@ listenerSets: status: conditions: - lastTransitionTime: null - message: All listeners are valid + message: All listeners are accepted reason: Accepted status: "True" type: Accepted - lastTransitionTime: null - message: All listeners are valid + message: All listeners are programmed reason: Programmed status: "True" type: Programmed diff --git a/internal/gatewayapi/testdata/listenerset-https-tls-misuses-gateway-namespace.out.yaml b/internal/gatewayapi/testdata/listenerset-https-tls-misuses-gateway-namespace.out.yaml index a302de7ee8..f56dd359de 100644 --- a/internal/gatewayapi/testdata/listenerset-https-tls-misuses-gateway-namespace.out.yaml +++ b/internal/gatewayapi/testdata/listenerset-https-tls-misuses-gateway-namespace.out.yaml @@ -92,12 +92,6 @@ infraIR: name: http-80 protocol: HTTP servicePort: 80 - - name: gateway/composite-gateway/xls/https-xls/extra-https-same-ns - ports: - - containerPort: 8443 - name: https-8443 - protocol: HTTPS - servicePort: 8443 metadata: labels: gateway.envoyproxy.io/owning-gateway-name: composite-gateway @@ -134,12 +128,12 @@ listenerSets: status: conditions: - lastTransitionTime: null - message: All listeners are invalid + message: No listeners are accepted reason: ListenersNotValid status: "False" type: Accepted - lastTransitionTime: null - message: All listeners are invalid + message: No listeners are programmed reason: ListenersNotValid status: "False" type: Programmed @@ -204,20 +198,6 @@ xdsIR: escapedSlashesAction: UnescapeAndRedirect mergeSlashes: true port: 10080 - - address: 0.0.0.0 - externalPort: 8443 - hostnames: - - '*' - metadata: - kind: Gateway - name: composite-gateway - namespace: gateway - sectionName: extra-https-same-ns - name: gateway/composite-gateway/xls/https-xls/extra-https-same-ns - path: - escapedSlashesAction: UnescapeAndRedirect - mergeSlashes: true - port: 8443 readyListener: address: 0.0.0.0 ipFamily: IPv4 diff --git a/internal/gatewayapi/testdata/listenerset-https-tls-mixed-valid-and-missing-secret.in.yaml b/internal/gatewayapi/testdata/listenerset-https-tls-mixed-valid-and-missing-secret.in.yaml new file mode 100644 index 0000000000..5079af121a --- /dev/null +++ b/internal/gatewayapi/testdata/listenerset-https-tls-mixed-valid-and-missing-secret.in.yaml @@ -0,0 +1,112 @@ +namespaces: +- apiVersion: v1 + kind: Namespace + metadata: + name: gateway +- apiVersion: v1 + kind: Namespace + metadata: + name: xls + labels: + allow-xls: "true" +gateways: +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + namespace: gateway + name: composite-gateway + spec: + gatewayClassName: envoy-gateway-class + allowedListeners: + namespaces: + from: Selector + selector: + matchLabels: + allow-xls: "true" + listeners: + - name: core-http + protocol: HTTP + port: 80 + allowedRoutes: + namespaces: + from: All +listenerSets: +- apiVersion: gateway.networking.k8s.io/v1 + kind: ListenerSet + metadata: + namespace: xls + name: https-xls + spec: + parentRef: + name: composite-gateway + namespace: gateway + listeners: + - name: extra-https-valid + protocol: HTTPS + port: 8443 + tls: + mode: Terminate + certificateRefs: + - group: "" + kind: Secret + name: tls-secret-1 + namespace: xls + allowedRoutes: + namespaces: + from: All + - name: extra-https-missing-cert + protocol: HTTPS + port: 8444 + tls: + mode: Terminate + certificateRefs: + - group: "" + kind: Secret + name: tls-secret-missing + namespace: xls + allowedRoutes: + namespaces: + from: All +httpRoutes: +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + namespace: default + name: route-valid + spec: + parentRefs: + - group: gateway.networking.k8s.io + kind: ListenerSet + namespace: xls + name: https-xls + sectionName: extra-https-valid + rules: + - backendRefs: + - name: service-1 + port: 8080 +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + namespace: default + name: route-missing-cert + spec: + parentRefs: + - group: gateway.networking.k8s.io + kind: ListenerSet + namespace: xls + name: https-xls + sectionName: extra-https-missing-cert + rules: + - backendRefs: + - name: service-1 + port: 8080 +secrets: +- apiVersion: v1 + kind: Secret + metadata: + namespace: xls + name: tls-secret-1 + type: kubernetes.io/tls + data: + tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUREVENDQWZXZ0F3SUJBZ0lVRUZNaFA5ZUo5WEFCV3NRNVptNmJSazJjTE5Rd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0ZqRVVNQklHQTFVRUF3d0xabTl2TG1KaGNpNWpiMjB3SGhjTk1qUXdNakk1TURrek1ERXdXaGNOTXpRdwpNakkyTURrek1ERXdXakFXTVJRd0VnWURWUVFEREF0bWIyOHVZbUZ5TG1OdmJUQ0NBU0l3RFFZSktvWklodmNOCkFRRUJCUUFEZ2dFUEFEQ0NBUW9DZ2dFQkFKbEk2WXhFOVprQ1BzNnBDUXhickNtZWl4OVA1RGZ4OVJ1NUxENFQKSm1kVzdJS2R0UVYvd2ZMbXRzdTc2QithVGRDaldlMEJUZmVPT1JCYlIzY1BBRzZFbFFMaWNsUVVydW4zcStncwpKcEsrSTdjSStqNXc4STY4WEg1V1E3clZVdGJ3SHBxYncrY1ZuQnFJVU9MaUlhdGpJZjdLWDUxTTF1RjljZkVICkU0RG5jSDZyYnI1OS9SRlpCc2toeHM1T3p3Sklmb2hreXZGd2V1VHd4Sy9WcGpJKzdPYzQ4QUJDWHBOTzlEL3EKRWgrck9hdWpBTWNYZ0hRSVRrQ2lpVVRjVW82TFNIOXZMWlB0YXFmem9acTZuaE1xcFc2NUUxcEF3RjNqeVRUeAphNUk4SmNmU0Zqa2llWjIwTFVRTW43TThVNHhIamFvL2d2SDBDQWZkQjdSTFUyc0NBd0VBQWFOVE1GRXdIUVlEClZSME9CQllFRk9SQ0U4dS8xRERXN2loWnA3Y3g5dFNtUG02T01COEdBMVVkSXdRWU1CYUFGT1JDRTh1LzFERFcKN2loWnA3Y3g5dFNtUG02T01BOEdBMVVkRXdFQi93UUZNQU1CQWY4d0RRWUpLb1pJaHZjTkFRRUxCUUFEZ2dFQgpBRnQ1M3pqc3FUYUg1YThFMmNodm1XQWdDcnhSSzhiVkxNeGl3TkdqYm1FUFJ6K3c2TngrazBBOEtFY0lEc0tjClNYY2k1OHU0b1didFZKQmx6YS9adWpIUjZQMUJuT3BsK2FveTc4NGJiZDRQMzl3VExvWGZNZmJCQ20xdmV2aDkKQUpLbncyWnRxcjRta2JMY3hFcWxxM3NCTEZBUzlzUUxuS05DZTJjR0xkVHAyYm9HK3FjZ3lRZ0NJTTZmOEVNdgpXUGlmQ01NR3V6Sy9HUkY0YlBPL1lGNDhld0R1M1VlaWgwWFhkVUFPRTlDdFVhOE5JaGMxVVBhT3pQcnRZVnFyClpPR2t2L0t1K0I3OGg4U0VzTzlYclFjdXdiT25KeDZLdFIrYWV5a3ZBcFhDUTNmWkMvYllLQUFSK1A4QUpvUVoKYndJVW1YaTRnajVtK2JLUGhlK2lyK0U9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0= + tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQ2QwZlBDYWtweE1nUnUKT0VXQjFiQk5FM3ZseW55aTZWbkV2VWF1OUhvakR2UHVPTFJIaGI4MmoyY1ovMHhnL1lKR09LelBuV2JERkxGNApHdWh3dDRENmFUR0xYNklPODEwTDZ0SXZIWGZNUXRJS2VwdTZ3K3p1WVo4bG1yejB1RjZlWEtqamVIbHhyb2ZrCnVNekM3OUVaU0lYZlZlczJ1SmdVRSs4VGFzSDUzQ2Y4MFNSRGlIeEdxckttdVNjWCtwejBreGdCZ1VWYTVVS20KUWdTZDFmVUxLOUEwNXAxOXkrdURPM204bVhRNkxVQ0N1STFwZHNROGFlNS9zamlxa0VjWlJjMTdWYVgxWjVVaQpvcGZnNW9SY05VTG9VTHNiek9aNTR0YlVDUmdSV2VLbGZxaElINEZ6OUlkVlUyR3dFdEdhMmV6TjgyMVBaQ3QzCjZhbVRIelJsQWdNQkFBRUNnZ0VBWTFGTUlLNDVXTkVNUHJ6RTZUY3NNdVV2RkdhQVZ4bVk5NW5SMEtwajdvb3IKY21CVys2ZXN0TTQ4S1AwaitPbXd3VFpMY29Cd3VoWGN0V1Bob1lXcDhteWUxRUlEdjNyaHRHMDdocEQ1NGg2dgpCZzh3ejdFYStzMk9sT0N6UnlKNzBSY281YlhjWDNGaGJjdnFlRWJwaFFyQnpOSEtLMjZ4cmZqNWZIT3p6T1FGCmJHdUZ3SDVic3JGdFhlajJXM3c4eW90N0ZQSDV3S3RpdnhvSWU5RjMyOXNnOU9EQnZqWnpiaG1LVTArckFTK1kKRGVield2bFJyaEUrbXVmQTN6M0N0QXhDOFJpNzNscFNoTDRQQWlvcG1SUXlxZXRXMjYzOFFxcnM0R3hnNzhwbApJUXJXTmNBc2s3Slg5d3RZenV6UFBXSXRWTTFscFJiQVRhNTJqdFl2NVFLQmdRRE5tMTFtZTRYam1ZSFV2cStZCmFTUzdwK2UybXZEMHVaOU9JeFluQnBWMGkrckNlYnFFMkE1Rm5hcDQ5Yld4QTgwUElldlVkeUpCL2pUUkoxcVMKRUpXQkpMWm1LVkg2K1QwdWw1ZUtOcWxFTFZHU0dCSXNpeE9SUXpDZHBoMkx0UmtBMHVjSVUzY3hiUmVMZkZCRQpiSkdZWENCdlNGcWd0VDlvZTFldVpMVmFOd0tCZ1FERWdENzJENk81eGIweEQ1NDQ1M0RPMUJhZmd6aThCWDRTCk1SaVd2LzFUQ0w5N05sRWtoeXovNmtQd1owbXJRcE5CMzZFdkpKZFVteHdkU2MyWDhrOGcxMC85NVlLQkdWQWoKL3d0YVZYbE9WeEFvK0ZSelpZeFpyQ29uWWFSMHVwUzFybDRtenN4REhlZU9mUVZUTUgwUjdZN0pnbTA5dXQ4SwplanAvSXZBb1F3S0JnQjNaRWlRUWhvMVYrWjBTMlpiOG5KS0plMy9zMmxJTXFHM0ZkaS9RS3Q0eWViQWx6OGY5ClBZVXBzRmZEQTg5Z3grSU1nSm5sZVptdTk2ZnRXSjZmdmJSenllN216TG5zZU05TXZua1lHbGFGWmJRWnZubXMKN3ZoRmtzY3dHRlh4d21GMlBJZmU1Z3pNMDRBeVdjeTFIaVhLS2dNOXM3cGsxWUdyZGowZzdacmRBb0dCQUtLNApDR3MrbkRmMEZTMFJYOWFEWVJrRTdBNy9YUFhtSG5YMkRnU1h5N0Q4NTRPaWdTTWNoUmtPNTErbVNJejNQbllvCk41T1FXM2lHVVl1M1YvYmhnc0VSUzM1V2xmRk9BdDBzRUR5bjF5SVdXcDF5dG93d3BUNkVvUXVuZ2NYZjA5RjMKS1NROXowd3M4VmsvRWkvSFVXcU5LOWFXbU51cmFaT0ZqL2REK1ZkOUFvR0FMWFN3dEE3K043RDRkN0VEMURSRQpHTWdZNVd3OHFvdDZSdUNlNkpUY0FnU3B1MkhNU3JVY2dXclpiQnJZb09FUnVNQjFoMVJydk5ybU1qQlM0VW9FClgyZC8vbGhpOG1wL2VESWN3UDNRa2puanBJRFJWMFN1eWxrUkVaZURKZjVZb3R6eDdFdkJhbzFIbkQrWEg4eUIKVUtmWGJTaHZKVUdhRmgxT3Q1Y3JoM1k9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K diff --git a/internal/gatewayapi/testdata/listenerset-https-tls-mixed-valid-and-missing-secret.out.yaml b/internal/gatewayapi/testdata/listenerset-https-tls-mixed-valid-and-missing-secret.out.yaml new file mode 100644 index 0000000000..c9cd6c9736 --- /dev/null +++ b/internal/gatewayapi/testdata/listenerset-https-tls-mixed-valid-and-missing-secret.out.yaml @@ -0,0 +1,340 @@ +gateways: +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + name: composite-gateway + namespace: gateway + spec: + allowedListeners: + namespaces: + from: Selector + selector: + matchLabels: + allow-xls: "true" + gatewayClassName: envoy-gateway-class + listeners: + - allowedRoutes: + namespaces: + from: All + name: core-http + port: 80 + protocol: HTTP + status: + attachedListenerSets: 1 + listeners: + - attachedRoutes: 0 + conditions: + - lastTransitionTime: null + message: Sending translated listener configuration to the data plane + reason: Programmed + status: "True" + type: Programmed + - lastTransitionTime: null + message: Listener has been successfully translated + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Listener references have been resolved + reason: ResolvedRefs + status: "True" + type: ResolvedRefs + name: core-http + supportedKinds: + - group: gateway.networking.k8s.io + kind: HTTPRoute + - group: gateway.networking.k8s.io + kind: GRPCRoute +httpRoutes: +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + name: route-valid + namespace: default + spec: + parentRefs: + - group: gateway.networking.k8s.io + kind: ListenerSet + name: https-xls + namespace: xls + sectionName: extra-https-valid + rules: + - backendRefs: + - name: service-1 + port: 8080 + status: + parents: + - conditions: + - lastTransitionTime: null + message: Route is accepted + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Resolved all the Object references for the Route + reason: ResolvedRefs + status: "True" + type: ResolvedRefs + controllerName: gateway.envoyproxy.io/gatewayclass-controller + parentRef: + group: gateway.networking.k8s.io + kind: ListenerSet + name: https-xls + namespace: xls + sectionName: extra-https-valid +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + name: route-missing-cert + namespace: default + spec: + parentRefs: + - group: gateway.networking.k8s.io + kind: ListenerSet + name: https-xls + namespace: xls + sectionName: extra-https-missing-cert + rules: + - backendRefs: + - name: service-1 + port: 8080 + status: + parents: + - conditions: + - lastTransitionTime: null + message: There are no ready listeners for this parent ref + reason: NoReadyListeners + status: "False" + type: Accepted + - lastTransitionTime: null + message: Resolved all the Object references for the Route + reason: ResolvedRefs + status: "True" + type: ResolvedRefs + controllerName: gateway.envoyproxy.io/gatewayclass-controller + parentRef: + group: gateway.networking.k8s.io + kind: ListenerSet + name: https-xls + namespace: xls + sectionName: extra-https-missing-cert +infraIR: + gateway/composite-gateway: + proxy: + listeners: + - name: gateway/composite-gateway/core-http + ports: + - containerPort: 10080 + name: http-80 + protocol: HTTP + servicePort: 80 + - name: gateway/composite-gateway/xls/https-xls/extra-https-valid + ports: + - containerPort: 8443 + name: https-8443 + protocol: HTTPS + servicePort: 8443 + metadata: + labels: + gateway.envoyproxy.io/owning-gateway-name: composite-gateway + gateway.envoyproxy.io/owning-gateway-namespace: gateway + ownerReference: + kind: GatewayClass + name: envoy-gateway-class + name: gateway/composite-gateway + namespace: envoy-gateway-system +listenerSets: +- apiVersion: gateway.networking.k8s.io/v1 + kind: ListenerSet + metadata: + name: https-xls + namespace: xls + spec: + listeners: + - allowedRoutes: + namespaces: + from: All + name: extra-https-valid + port: 8443 + protocol: HTTPS + tls: + certificateRefs: + - group: "" + kind: Secret + name: tls-secret-1 + namespace: xls + mode: Terminate + - allowedRoutes: + namespaces: + from: All + name: extra-https-missing-cert + port: 8444 + protocol: HTTPS + tls: + certificateRefs: + - group: "" + kind: Secret + name: tls-secret-missing + namespace: xls + mode: Terminate + parentRef: + name: composite-gateway + namespace: gateway + status: + conditions: + - lastTransitionTime: null + message: All listeners are accepted + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Some listeners are not programmed + reason: Programmed + status: "True" + type: Programmed + listeners: + - attachedRoutes: 1 + conditions: + - lastTransitionTime: null + message: Sending translated listener configuration to the data plane + reason: Programmed + status: "True" + type: Programmed + - lastTransitionTime: null + message: Listener has been successfully translated + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Listener references have been resolved + reason: ResolvedRefs + status: "True" + type: ResolvedRefs + - lastTransitionTime: null + message: No conflicts detected + reason: NoConflicts + status: "False" + type: Conflicted + name: extra-https-valid + supportedKinds: + - group: gateway.networking.k8s.io + kind: HTTPRoute + - group: gateway.networking.k8s.io + kind: GRPCRoute + - attachedRoutes: 1 + conditions: + - lastTransitionTime: null + message: 'No valid secrets exist: certificate refs 0: Secret xls/tls-secret-missing + does not exist.' + reason: InvalidCertificateRef + status: "False" + type: ResolvedRefs + - lastTransitionTime: null + message: Listener has been successfully translated + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Listener is invalid, see other Conditions for details. + reason: ListenersNotValid + status: "False" + type: Programmed + name: extra-https-missing-cert + supportedKinds: + - group: gateway.networking.k8s.io + kind: HTTPRoute + - group: gateway.networking.k8s.io + kind: GRPCRoute +xdsIR: + gateway/composite-gateway: + accessLog: + json: + - path: /dev/stdout + globalResources: + proxyServiceCluster: + metadata: + kind: Service + name: envoy-gateway-composite-gateway-acff6ccf + namespace: envoy-gateway-system + sectionName: "8080" + name: gateway/composite-gateway + settings: + - addressType: IP + endpoints: + - host: 7.6.5.4 + port: 8080 + zone: zone1 + metadata: + kind: Service + name: envoy-gateway-composite-gateway-acff6ccf + namespace: envoy-gateway-system + sectionName: "8080" + name: gateway/composite-gateway + protocol: TCP + http: + - address: 0.0.0.0 + externalPort: 80 + hostnames: + - '*' + metadata: + kind: Gateway + name: composite-gateway + namespace: gateway + sectionName: core-http + name: gateway/composite-gateway/core-http + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10080 + - address: 0.0.0.0 + externalPort: 8443 + hostnames: + - '*' + metadata: + kind: Gateway + name: composite-gateway + namespace: gateway + sectionName: extra-https-valid + name: gateway/composite-gateway/xls/https-xls/extra-https-valid + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 8443 + routes: + - destination: + metadata: + kind: HTTPRoute + name: route-valid + namespace: default + name: httproute/default/route-valid/rule/0 + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8080 + metadata: + kind: Service + name: service-1 + namespace: default + sectionName: "8080" + name: httproute/default/route-valid/rule/0/backend/0 + protocol: HTTP + weight: 1 + hostname: '*' + isHTTP2: false + metadata: + kind: HTTPRoute + name: route-valid + namespace: default + name: httproute/default/route-valid/rule/0/match/-1/* + tls: + alpnProtocols: null + certificates: + - certificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUREVENDQWZXZ0F3SUJBZ0lVRUZNaFA5ZUo5WEFCV3NRNVptNmJSazJjTE5Rd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0ZqRVVNQklHQTFVRUF3d0xabTl2TG1KaGNpNWpiMjB3SGhjTk1qUXdNakk1TURrek1ERXdXaGNOTXpRdwpNakkyTURrek1ERXdXakFXTVJRd0VnWURWUVFEREF0bWIyOHVZbUZ5TG1OdmJUQ0NBU0l3RFFZSktvWklodmNOCkFRRUJCUUFEZ2dFUEFEQ0NBUW9DZ2dFQkFKbEk2WXhFOVprQ1BzNnBDUXhickNtZWl4OVA1RGZ4OVJ1NUxENFQKSm1kVzdJS2R0UVYvd2ZMbXRzdTc2QithVGRDaldlMEJUZmVPT1JCYlIzY1BBRzZFbFFMaWNsUVVydW4zcStncwpKcEsrSTdjSStqNXc4STY4WEg1V1E3clZVdGJ3SHBxYncrY1ZuQnFJVU9MaUlhdGpJZjdLWDUxTTF1RjljZkVICkU0RG5jSDZyYnI1OS9SRlpCc2toeHM1T3p3Sklmb2hreXZGd2V1VHd4Sy9WcGpJKzdPYzQ4QUJDWHBOTzlEL3EKRWgrck9hdWpBTWNYZ0hRSVRrQ2lpVVRjVW82TFNIOXZMWlB0YXFmem9acTZuaE1xcFc2NUUxcEF3RjNqeVRUeAphNUk4SmNmU0Zqa2llWjIwTFVRTW43TThVNHhIamFvL2d2SDBDQWZkQjdSTFUyc0NBd0VBQWFOVE1GRXdIUVlEClZSME9CQllFRk9SQ0U4dS8xRERXN2loWnA3Y3g5dFNtUG02T01COEdBMVVkSXdRWU1CYUFGT1JDRTh1LzFERFcKN2loWnA3Y3g5dFNtUG02T01BOEdBMVVkRXdFQi93UUZNQU1CQWY4d0RRWUpLb1pJaHZjTkFRRUxCUUFEZ2dFQgpBRnQ1M3pqc3FUYUg1YThFMmNodm1XQWdDcnhSSzhiVkxNeGl3TkdqYm1FUFJ6K3c2TngrazBBOEtFY0lEc0tjClNYY2k1OHU0b1didFZKQmx6YS9adWpIUjZQMUJuT3BsK2FveTc4NGJiZDRQMzl3VExvWGZNZmJCQ20xdmV2aDkKQUpLbncyWnRxcjRta2JMY3hFcWxxM3NCTEZBUzlzUUxuS05DZTJjR0xkVHAyYm9HK3FjZ3lRZ0NJTTZmOEVNdgpXUGlmQ01NR3V6Sy9HUkY0YlBPL1lGNDhld0R1M1VlaWgwWFhkVUFPRTlDdFVhOE5JaGMxVVBhT3pQcnRZVnFyClpPR2t2L0t1K0I3OGg4U0VzTzlYclFjdXdiT25KeDZLdFIrYWV5a3ZBcFhDUTNmWkMvYllLQUFSK1A4QUpvUVoKYndJVW1YaTRnajVtK2JLUGhlK2lyK0U9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0= + name: xls/tls-secret-1 + privateKey: '[redacted]' + readyListener: + address: 0.0.0.0 + ipFamily: IPv4 + path: /ready + port: 19003 diff --git a/internal/gatewayapi/testdata/listenerset-https-tls-same-namespace.out.yaml b/internal/gatewayapi/testdata/listenerset-https-tls-same-namespace.out.yaml index c4161ade75..781ab63b5a 100644 --- a/internal/gatewayapi/testdata/listenerset-https-tls-same-namespace.out.yaml +++ b/internal/gatewayapi/testdata/listenerset-https-tls-same-namespace.out.yaml @@ -134,12 +134,12 @@ listenerSets: status: conditions: - lastTransitionTime: null - message: All listeners are valid + message: All listeners are accepted reason: Accepted status: "True" type: Accepted - lastTransitionTime: null - message: All listeners are valid + message: All listeners are programmed reason: Programmed status: "True" type: Programmed diff --git a/internal/gatewayapi/testdata/listenerset-https-tls-secret-does-not-exist.in.yaml b/internal/gatewayapi/testdata/listenerset-https-tls-secret-does-not-exist.in.yaml new file mode 100644 index 0000000000..493e6a6b9f --- /dev/null +++ b/internal/gatewayapi/testdata/listenerset-https-tls-secret-does-not-exist.in.yaml @@ -0,0 +1,73 @@ +namespaces: +- apiVersion: v1 + kind: Namespace + metadata: + name: gateway +- apiVersion: v1 + kind: Namespace + metadata: + name: xls + labels: + allow-xls: "true" +gateways: +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + namespace: gateway + name: composite-gateway + spec: + gatewayClassName: envoy-gateway-class + allowedListeners: + namespaces: + from: Selector + selector: + matchLabels: + allow-xls: "true" + listeners: + - name: core-http + protocol: HTTP + port: 80 + allowedRoutes: + namespaces: + from: All +listenerSets: +- apiVersion: gateway.networking.k8s.io/v1 + kind: ListenerSet + metadata: + namespace: xls + name: https-xls + spec: + parentRef: + name: composite-gateway + namespace: gateway + listeners: + - name: extra-https + protocol: HTTPS + port: 8443 + tls: + mode: Terminate + certificateRefs: + - group: "" + kind: Secret + name: tls-secret-1 + namespace: xls + allowedRoutes: + namespaces: + from: All +httpRoutes: +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + namespace: default + name: route-extra-https + spec: + parentRefs: + - group: gateway.networking.k8s.io + kind: ListenerSet + namespace: xls + name: https-xls + sectionName: extra-https + rules: + - backendRefs: + - name: service-1 + port: 8080 diff --git a/internal/gatewayapi/testdata/listenerset-https-tls-secret-does-not-exist.out.yaml b/internal/gatewayapi/testdata/listenerset-https-tls-secret-does-not-exist.out.yaml new file mode 100644 index 0000000000..bf0b1fa843 --- /dev/null +++ b/internal/gatewayapi/testdata/listenerset-https-tls-secret-does-not-exist.out.yaml @@ -0,0 +1,210 @@ +gateways: +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + name: composite-gateway + namespace: gateway + spec: + allowedListeners: + namespaces: + from: Selector + selector: + matchLabels: + allow-xls: "true" + gatewayClassName: envoy-gateway-class + listeners: + - allowedRoutes: + namespaces: + from: All + name: core-http + port: 80 + protocol: HTTP + status: + attachedListenerSets: 1 + listeners: + - attachedRoutes: 0 + conditions: + - lastTransitionTime: null + message: Sending translated listener configuration to the data plane + reason: Programmed + status: "True" + type: Programmed + - lastTransitionTime: null + message: Listener has been successfully translated + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Listener references have been resolved + reason: ResolvedRefs + status: "True" + type: ResolvedRefs + name: core-http + supportedKinds: + - group: gateway.networking.k8s.io + kind: HTTPRoute + - group: gateway.networking.k8s.io + kind: GRPCRoute +httpRoutes: +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + name: route-extra-https + namespace: default + spec: + parentRefs: + - group: gateway.networking.k8s.io + kind: ListenerSet + name: https-xls + namespace: xls + sectionName: extra-https + rules: + - backendRefs: + - name: service-1 + port: 8080 + status: + parents: + - conditions: + - lastTransitionTime: null + message: There are no ready listeners for this parent ref + reason: NoReadyListeners + status: "False" + type: Accepted + - lastTransitionTime: null + message: Resolved all the Object references for the Route + reason: ResolvedRefs + status: "True" + type: ResolvedRefs + controllerName: gateway.envoyproxy.io/gatewayclass-controller + parentRef: + group: gateway.networking.k8s.io + kind: ListenerSet + name: https-xls + namespace: xls + sectionName: extra-https +infraIR: + gateway/composite-gateway: + proxy: + listeners: + - name: gateway/composite-gateway/core-http + ports: + - containerPort: 10080 + name: http-80 + protocol: HTTP + servicePort: 80 + metadata: + labels: + gateway.envoyproxy.io/owning-gateway-name: composite-gateway + gateway.envoyproxy.io/owning-gateway-namespace: gateway + ownerReference: + kind: GatewayClass + name: envoy-gateway-class + name: gateway/composite-gateway + namespace: envoy-gateway-system +listenerSets: +- apiVersion: gateway.networking.k8s.io/v1 + kind: ListenerSet + metadata: + name: https-xls + namespace: xls + spec: + listeners: + - allowedRoutes: + namespaces: + from: All + name: extra-https + port: 8443 + protocol: HTTPS + tls: + certificateRefs: + - group: "" + kind: Secret + name: tls-secret-1 + namespace: xls + mode: Terminate + parentRef: + name: composite-gateway + namespace: gateway + status: + conditions: + - lastTransitionTime: null + message: All listeners are accepted + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: No listeners are programmed + reason: ListenersNotValid + status: "False" + type: Programmed + listeners: + - attachedRoutes: 1 + conditions: + - lastTransitionTime: null + message: 'No valid secrets exist: certificate refs 0: Secret xls/tls-secret-1 + does not exist.' + reason: InvalidCertificateRef + status: "False" + type: ResolvedRefs + - lastTransitionTime: null + message: Listener has been successfully translated + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Listener is invalid, see other Conditions for details. + reason: ListenersNotValid + status: "False" + type: Programmed + name: extra-https + supportedKinds: + - group: gateway.networking.k8s.io + kind: HTTPRoute + - group: gateway.networking.k8s.io + kind: GRPCRoute +xdsIR: + gateway/composite-gateway: + accessLog: + json: + - path: /dev/stdout + globalResources: + proxyServiceCluster: + metadata: + kind: Service + name: envoy-gateway-composite-gateway-acff6ccf + namespace: envoy-gateway-system + sectionName: "8080" + name: gateway/composite-gateway + settings: + - addressType: IP + endpoints: + - host: 7.6.5.4 + port: 8080 + zone: zone1 + metadata: + kind: Service + name: envoy-gateway-composite-gateway-acff6ccf + namespace: envoy-gateway-system + sectionName: "8080" + name: gateway/composite-gateway + protocol: TCP + http: + - address: 0.0.0.0 + externalPort: 80 + hostnames: + - '*' + metadata: + kind: Gateway + name: composite-gateway + namespace: gateway + sectionName: core-http + name: gateway/composite-gateway/core-http + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10080 + readyListener: + address: 0.0.0.0 + ipFamily: IPv4 + path: /ready + port: 19003 diff --git a/internal/gatewayapi/testdata/listenerset-invalid.out.yaml b/internal/gatewayapi/testdata/listenerset-invalid.out.yaml index d456feeb28..e09a3482d6 100644 --- a/internal/gatewayapi/testdata/listenerset-invalid.out.yaml +++ b/internal/gatewayapi/testdata/listenerset-invalid.out.yaml @@ -200,30 +200,12 @@ infraIR: name: http-80 protocol: HTTP servicePort: 80 - - name: gateway-xls/composite-gateway/gateway-xls/same-namespace-invalid/invalid-one - ports: - - containerPort: 8085 - name: "-8085" - protocol: "" - servicePort: 8085 - - name: gateway-xls/composite-gateway/gateway-xls/same-namespace-invalid/invalid-two - ports: - - containerPort: 8086 - name: "-8086" - protocol: "" - servicePort: 8086 - name: gateway-xls/composite-gateway/gateway-xls/same-namespace-mixed/mixed-valid ports: - containerPort: 8087 name: http-8087 protocol: HTTP servicePort: 8087 - - name: gateway-xls/composite-gateway/gateway-xls/same-namespace-mixed/mixed-invalid - ports: - - containerPort: 8088 - name: "-8088" - protocol: "" - servicePort: 8088 metadata: labels: gateway.envoyproxy.io/owning-gateway-name: composite-gateway @@ -258,12 +240,12 @@ listenerSets: status: conditions: - lastTransitionTime: null - message: All listeners are invalid + message: No listeners are accepted reason: ListenersNotValid status: "False" type: Accepted - lastTransitionTime: null - message: All listeners are invalid + message: No listeners are programmed reason: ListenersNotValid status: "False" type: Programmed @@ -333,7 +315,7 @@ listenerSets: status: "True" type: Accepted - lastTransitionTime: null - message: Some listeners are invalid + message: Some listeners are not programmed reason: Programmed status: "True" type: Programmed diff --git a/internal/gatewayapi/testdata/listenerset-no-maching-listener.out.yaml b/internal/gatewayapi/testdata/listenerset-no-maching-listener.out.yaml index 8c7309b61c..1dcf2f3339 100644 --- a/internal/gatewayapi/testdata/listenerset-no-maching-listener.out.yaml +++ b/internal/gatewayapi/testdata/listenerset-no-maching-listener.out.yaml @@ -193,12 +193,12 @@ listenerSets: status: conditions: - lastTransitionTime: null - message: All listeners are valid + message: All listeners are accepted reason: Accepted status: "True" type: Accepted - lastTransitionTime: null - message: All listeners are valid + message: All listeners are programmed reason: Programmed status: "True" type: Programmed diff --git a/internal/gatewayapi/testdata/listenerset-tcproute.out.yaml b/internal/gatewayapi/testdata/listenerset-tcproute.out.yaml index bc69e734fb..efefe794c2 100644 --- a/internal/gatewayapi/testdata/listenerset-tcproute.out.yaml +++ b/internal/gatewayapi/testdata/listenerset-tcproute.out.yaml @@ -92,12 +92,12 @@ listenerSets: status: conditions: - lastTransitionTime: null - message: All listeners are valid + message: All listeners are accepted reason: Accepted status: "True" type: Accepted - lastTransitionTime: null - message: All listeners are valid + message: All listeners are programmed reason: Programmed status: "True" type: Programmed diff --git a/internal/gatewayapi/testdata/listenerset-tlsroute.out.yaml b/internal/gatewayapi/testdata/listenerset-tlsroute.out.yaml index cb8d2b95bf..40d297c879 100644 --- a/internal/gatewayapi/testdata/listenerset-tlsroute.out.yaml +++ b/internal/gatewayapi/testdata/listenerset-tlsroute.out.yaml @@ -116,12 +116,12 @@ listenerSets: status: conditions: - lastTransitionTime: null - message: All listeners are valid + message: All listeners are accepted reason: Accepted status: "True" type: Accepted - lastTransitionTime: null - message: All listeners are valid + message: All listeners are programmed reason: Programmed status: "True" type: Programmed diff --git a/internal/gatewayapi/testdata/listenerset-udproute.out.yaml b/internal/gatewayapi/testdata/listenerset-udproute.out.yaml index 5339bbc54a..5e3287a6cd 100644 --- a/internal/gatewayapi/testdata/listenerset-udproute.out.yaml +++ b/internal/gatewayapi/testdata/listenerset-udproute.out.yaml @@ -92,12 +92,12 @@ listenerSets: status: conditions: - lastTransitionTime: null - message: All listeners are valid + message: All listeners are accepted reason: Accepted status: "True" type: Accepted - lastTransitionTime: null - message: All listeners are valid + message: All listeners are programmed reason: Programmed status: "True" type: Programmed diff --git a/internal/gatewayapi/testdata/merge-invalid-multiple-gateways.out.yaml b/internal/gatewayapi/testdata/merge-invalid-multiple-gateways.out.yaml index 28b1ac3406..f41c3b186d 100644 --- a/internal/gatewayapi/testdata/merge-invalid-multiple-gateways.out.yaml +++ b/internal/gatewayapi/testdata/merge-invalid-multiple-gateways.out.yaml @@ -170,20 +170,6 @@ xdsIR: escapedSlashesAction: UnescapeAndRedirect mergeSlashes: true port: 10080 - - address: 0.0.0.0 - externalPort: 80 - hostnames: - - '*' - metadata: - kind: Gateway - name: gateway-2 - namespace: envoy-gateway - sectionName: http - name: envoy-gateway/gateway-2/http - path: - escapedSlashesAction: UnescapeAndRedirect - mergeSlashes: true - port: 10080 readyListener: address: 0.0.0.0 ipFamily: IPv4 diff --git a/internal/gatewayapi/testdata/policy-cross-namespace-targetselector-partial-referencegrant-gateway-target.in.yaml b/internal/gatewayapi/testdata/policy-cross-namespace-targetselector-missing-partial-referencegrant-gateway-target.in.yaml similarity index 100% rename from internal/gatewayapi/testdata/policy-cross-namespace-targetselector-partial-referencegrant-gateway-target.in.yaml rename to internal/gatewayapi/testdata/policy-cross-namespace-targetselector-missing-partial-referencegrant-gateway-target.in.yaml diff --git a/internal/gatewayapi/testdata/policy-cross-namespace-targetselector-partial-referencegrant-gateway-target.out.yaml b/internal/gatewayapi/testdata/policy-cross-namespace-targetselector-missing-partial-referencegrant-gateway-target.out.yaml similarity index 95% rename from internal/gatewayapi/testdata/policy-cross-namespace-targetselector-partial-referencegrant-gateway-target.out.yaml rename to internal/gatewayapi/testdata/policy-cross-namespace-targetselector-missing-partial-referencegrant-gateway-target.out.yaml index 7be18da1de..2467854087 100644 --- a/internal/gatewayapi/testdata/policy-cross-namespace-targetselector-partial-referencegrant-gateway-target.out.yaml +++ b/internal/gatewayapi/testdata/policy-cross-namespace-targetselector-missing-partial-referencegrant-gateway-target.out.yaml @@ -27,19 +27,6 @@ backendTrafficPolicies: status: "True" type: Accepted controllerName: gateway.envoyproxy.io/gatewayclass-controller - - ancestorRef: - group: gateway.networking.k8s.io - kind: Gateway - name: denied-gateway - namespace: policy-target-b - conditions: - - lastTransitionTime: null - message: Target Gateway policy-target-b/denied-gateway is not permitted by - any ReferenceGrant. - reason: RefNotPermitted - status: "False" - type: Accepted - controllerName: gateway.envoyproxy.io/gatewayclass-controller gateways: - apiVersion: gateway.networking.k8s.io/v1 kind: Gateway diff --git a/internal/gatewayapi/testdata/policy-cross-namespace-targetselector-partial-referencegrant-route-target.in.yaml b/internal/gatewayapi/testdata/policy-cross-namespace-targetselector-missing-partial-referencegrant-route-target.in.yaml similarity index 100% rename from internal/gatewayapi/testdata/policy-cross-namespace-targetselector-partial-referencegrant-route-target.in.yaml rename to internal/gatewayapi/testdata/policy-cross-namespace-targetselector-missing-partial-referencegrant-route-target.in.yaml diff --git a/internal/gatewayapi/testdata/policy-cross-namespace-targetselector-partial-referencegrant-route-target.out.yaml b/internal/gatewayapi/testdata/policy-cross-namespace-targetselector-missing-partial-referencegrant-route-target.out.yaml similarity index 96% rename from internal/gatewayapi/testdata/policy-cross-namespace-targetselector-partial-referencegrant-route-target.out.yaml rename to internal/gatewayapi/testdata/policy-cross-namespace-targetselector-missing-partial-referencegrant-route-target.out.yaml index 6face1741d..0b5a59838d 100644 --- a/internal/gatewayapi/testdata/policy-cross-namespace-targetselector-partial-referencegrant-route-target.out.yaml +++ b/internal/gatewayapi/testdata/policy-cross-namespace-targetselector-missing-partial-referencegrant-route-target.out.yaml @@ -27,13 +27,6 @@ backendTrafficPolicies: reason: Accepted status: "True" type: Accepted - - lastTransitionTime: null - message: Target HTTPRoute policy-target-b/denied-route is not permitted by - any ReferenceGrant.; Target HTTPRoute policy-target-c/denied-route is not - permitted by any ReferenceGrant. - reason: RefNotPermitted - status: "True" - type: Warning controllerName: gateway.envoyproxy.io/gatewayclass-controller gateways: - apiVersion: gateway.networking.k8s.io/v1 diff --git a/internal/gatewayapi/testdata/policy-cross-namespace-targetselector-invalid-referencegrant-gateway.in.yaml b/internal/gatewayapi/testdata/policy-cross-namespace-targetselector-missing-referencegrant-gateway.in.yaml similarity index 100% rename from internal/gatewayapi/testdata/policy-cross-namespace-targetselector-invalid-referencegrant-gateway.in.yaml rename to internal/gatewayapi/testdata/policy-cross-namespace-targetselector-missing-referencegrant-gateway.in.yaml diff --git a/internal/gatewayapi/testdata/policy-cross-namespace-targetselector-invalid-referencegrant-gateway.out.yaml b/internal/gatewayapi/testdata/policy-cross-namespace-targetselector-missing-referencegrant-gateway.out.yaml similarity index 84% rename from internal/gatewayapi/testdata/policy-cross-namespace-targetselector-invalid-referencegrant-gateway.out.yaml rename to internal/gatewayapi/testdata/policy-cross-namespace-targetselector-missing-referencegrant-gateway.out.yaml index 4a883cbcf0..3a1c15c021 100644 --- a/internal/gatewayapi/testdata/policy-cross-namespace-targetselector-invalid-referencegrant-gateway.out.yaml +++ b/internal/gatewayapi/testdata/policy-cross-namespace-targetselector-missing-referencegrant-gateway.out.yaml @@ -1,33 +1,3 @@ -backendTrafficPolicies: -- apiVersion: gateway.envoyproxy.io/v1alpha1 - kind: BackendTrafficPolicy - metadata: - name: cross-ns-policy - namespace: policy-ns - spec: - targetSelectors: - - group: gateway.networking.k8s.io - kind: Gateway - matchLabels: - policy: selected - namespaces: - from: All - useClientProtocol: true - status: - ancestors: - - ancestorRef: - group: gateway.networking.k8s.io - kind: Gateway - name: target-gateway - namespace: policy-target-ns - conditions: - - lastTransitionTime: null - message: Target Gateway policy-target-ns/target-gateway is not permitted by - any ReferenceGrant. - reason: RefNotPermitted - status: "False" - type: Accepted - controllerName: gateway.envoyproxy.io/gatewayclass-controller gateways: - apiVersion: gateway.networking.k8s.io/v1 kind: Gateway diff --git a/internal/gatewayapi/testdata/policy-cross-namespace-targetselector-invalid-referencegrant-route.in.yaml b/internal/gatewayapi/testdata/policy-cross-namespace-targetselector-missing-referencegrant-route.in.yaml similarity index 100% rename from internal/gatewayapi/testdata/policy-cross-namespace-targetselector-invalid-referencegrant-route.in.yaml rename to internal/gatewayapi/testdata/policy-cross-namespace-targetselector-missing-referencegrant-route.in.yaml diff --git a/internal/gatewayapi/testdata/policy-cross-namespace-targetselector-invalid-referencegrant-route.out.yaml b/internal/gatewayapi/testdata/policy-cross-namespace-targetselector-missing-referencegrant-route.out.yaml similarity index 84% rename from internal/gatewayapi/testdata/policy-cross-namespace-targetselector-invalid-referencegrant-route.out.yaml rename to internal/gatewayapi/testdata/policy-cross-namespace-targetselector-missing-referencegrant-route.out.yaml index 7f0dd84ffa..129c29c879 100644 --- a/internal/gatewayapi/testdata/policy-cross-namespace-targetselector-invalid-referencegrant-route.out.yaml +++ b/internal/gatewayapi/testdata/policy-cross-namespace-targetselector-missing-referencegrant-route.out.yaml @@ -1,34 +1,3 @@ -backendTrafficPolicies: -- apiVersion: gateway.envoyproxy.io/v1alpha1 - kind: BackendTrafficPolicy - metadata: - name: cross-ns-policy - namespace: policy-ns - spec: - targetSelectors: - - group: gateway.networking.k8s.io - kind: HTTPRoute - matchLabels: - policy: selected - namespaces: - from: All - useClientProtocol: true - status: - ancestors: - - ancestorRef: - group: gateway.networking.k8s.io - kind: Gateway - name: target-gateway - namespace: policy-target-ns - sectionName: http - conditions: - - lastTransitionTime: null - message: Target HTTPRoute policy-target-ns/target-route is not permitted by - any ReferenceGrant. - reason: RefNotPermitted - status: "False" - type: Accepted - controllerName: gateway.envoyproxy.io/gatewayclass-controller gateways: - apiVersion: gateway.networking.k8s.io/v1 kind: Gateway diff --git a/internal/gatewayapi/testdata/securitypolicy-status-conditions.out.yaml b/internal/gatewayapi/testdata/securitypolicy-status-conditions.out.yaml index c58cf94f48..68afd0fe72 100644 --- a/internal/gatewayapi/testdata/securitypolicy-status-conditions.out.yaml +++ b/internal/gatewayapi/testdata/securitypolicy-status-conditions.out.yaml @@ -228,12 +228,6 @@ infraIR: name: http-80 protocol: HTTP servicePort: 80 - - name: envoy-gateway/gateway-2/https - ports: - - containerPort: 10443 - name: https-443 - protocol: HTTPS - servicePort: 443 - name: envoy-gateway/gateway-2/tcp ports: - containerPort: 10053 @@ -551,20 +545,6 @@ xdsIR: name: "" safeRegex: http://.*\.example\.com maxAge: 16m40s - - address: 0.0.0.0 - externalPort: 443 - hostnames: - - '*' - metadata: - kind: Gateway - name: gateway-2 - namespace: envoy-gateway - sectionName: https - name: envoy-gateway/gateway-2/https - path: - escapedSlashesAction: UnescapeAndRedirect - mergeSlashes: true - port: 10443 readyListener: address: 0.0.0.0 ipFamily: IPv4 diff --git a/internal/gatewayapi/testdata/securitypolicy-with-merge-multi-gateway-same-listener.in.yaml b/internal/gatewayapi/testdata/securitypolicy-with-merge-multi-gateway-same-listener.in.yaml index e13c11c4b5..ee8b0bb9d9 100644 --- a/internal/gatewayapi/testdata/securitypolicy-with-merge-multi-gateway-same-listener.in.yaml +++ b/internal/gatewayapi/testdata/securitypolicy-with-merge-multi-gateway-same-listener.in.yaml @@ -108,20 +108,6 @@ services: - port: 9001 name: http protocol: TCP -referenceGrants: -- apiVersion: gateway.networking.k8s.io/v1alpha2 - kind: ReferenceGrant - metadata: - namespace: envoy-gateway - name: allow-securitypolicy-to-auth-service - spec: - from: - - group: gateway.envoyproxy.io - kind: SecurityPolicy - namespace: default - to: - - group: "" - kind: Service endpointSlices: - apiVersion: discovery.k8s.io/v1 kind: EndpointSlice @@ -149,11 +135,3 @@ secrets: type: Opaque data: .htpasswd: dXNlcjE6e1NIQX15LzJzWUFqNXlyUUlONFRMMFlkUGRtR05LcGM9 -- apiVersion: v1 - kind: Secret - metadata: - namespace: default - name: users-secret - type: Opaque - data: - .htpasswd: dXNlcjE6e1NIQX15LzJzWUFqNXlyUUlONFRMMFlkUGRtR05LcGM9 diff --git a/internal/gatewayapi/testdata/securitypolicy-with-merge-multi-gateway-same-listener.out.yaml b/internal/gatewayapi/testdata/securitypolicy-with-merge-multi-gateway-same-listener.out.yaml index 96bfbf8a65..90fae2f530 100644 --- a/internal/gatewayapi/testdata/securitypolicy-with-merge-multi-gateway-same-listener.out.yaml +++ b/internal/gatewayapi/testdata/securitypolicy-with-merge-multi-gateway-same-listener.out.yaml @@ -372,7 +372,7 @@ xdsIR: prefix: /foo security: basicAuth: - name: securitypolicy/default/policy-for-route + name: securitypolicy/envoy-gateway/policy-for-gateway-1 users: '[redacted]' cors: allowMethods: @@ -473,9 +473,9 @@ xdsIR: destination: metadata: kind: SecurityPolicy - name: policy-for-route - namespace: default - name: securitypolicy/default/policy-for-route/extauth/0 + name: policy-for-gateway-2 + namespace: envoy-gateway + name: securitypolicy/envoy-gateway/policy-for-gateway-2/extauth/0 settings: - addressType: IP endpoints: @@ -486,11 +486,11 @@ xdsIR: name: auth-service namespace: envoy-gateway sectionName: "9001" - name: securitypolicy/default/policy-for-route/extauth/0/backend/0 + name: securitypolicy/envoy-gateway/policy-for-gateway-2/extauth/0/backend/0 protocol: HTTP weight: 1 path: "" - name: securitypolicy/default/policy-for-route + name: securitypolicy/envoy-gateway/policy-for-gateway-2 readyListener: address: 0.0.0.0 ipFamily: IPv4 diff --git a/internal/gatewayapi/testdata/securitypolicy-with-merge-multi-listener.in.yaml b/internal/gatewayapi/testdata/securitypolicy-with-merge-multi-listener.in.yaml index 5dc3bb2a76..4b1592dfc3 100644 --- a/internal/gatewayapi/testdata/securitypolicy-with-merge-multi-listener.in.yaml +++ b/internal/gatewayapi/testdata/securitypolicy-with-merge-multi-listener.in.yaml @@ -104,20 +104,6 @@ services: - port: 9001 name: http protocol: TCP -referenceGrants: -- apiVersion: gateway.networking.k8s.io/v1alpha2 - kind: ReferenceGrant - metadata: - namespace: envoy-gateway - name: allow-securitypolicy-to-auth-service - spec: - from: - - group: gateway.envoyproxy.io - kind: SecurityPolicy - namespace: default - to: - - group: "" - kind: Service endpointSlices: - apiVersion: discovery.k8s.io/v1 kind: EndpointSlice @@ -145,11 +131,3 @@ secrets: type: Opaque data: .htpasswd: dXNlcjE6e1NIQX15LzJzWUFqNXlyUUlONFRMMFlkUGRtR05LcGM9 -- apiVersion: v1 - kind: Secret - metadata: - namespace: default - name: users-secret-a - type: Opaque - data: - .htpasswd: dXNlcjE6e1NIQX15LzJzWUFqNXlyUUlONFRMMFlkUGRtR05LcGM9 diff --git a/internal/gatewayapi/testdata/securitypolicy-with-merge-multi-listener.out.yaml b/internal/gatewayapi/testdata/securitypolicy-with-merge-multi-listener.out.yaml index 19999e159b..5c344fd5ea 100644 --- a/internal/gatewayapi/testdata/securitypolicy-with-merge-multi-listener.out.yaml +++ b/internal/gatewayapi/testdata/securitypolicy-with-merge-multi-listener.out.yaml @@ -350,7 +350,7 @@ xdsIR: prefix: /foo security: basicAuth: - name: securitypolicy/default/policy-for-route + name: securitypolicy/envoy-gateway/policy-for-listener-a users: '[redacted]' cors: allowMethods: @@ -420,9 +420,9 @@ xdsIR: destination: metadata: kind: SecurityPolicy - name: policy-for-route - namespace: default - name: securitypolicy/default/policy-for-route/extauth/0 + name: policy-for-listener-b + namespace: envoy-gateway + name: securitypolicy/envoy-gateway/policy-for-listener-b/extauth/0 settings: - addressType: IP endpoints: @@ -433,11 +433,11 @@ xdsIR: name: auth-service namespace: envoy-gateway sectionName: "9001" - name: securitypolicy/default/policy-for-route/extauth/0/backend/0 + name: securitypolicy/envoy-gateway/policy-for-listener-b/extauth/0/backend/0 protocol: HTTP weight: 1 path: "" - name: securitypolicy/default/policy-for-route + name: securitypolicy/envoy-gateway/policy-for-listener-b readyListener: address: 0.0.0.0 ipFamily: IPv4 diff --git a/internal/gatewayapi/testdata/securitypolicy-with-merge-needs-fieldowner.in.yaml b/internal/gatewayapi/testdata/securitypolicy-with-merge-needs-fieldowner.in.yaml new file mode 100644 index 0000000000..691512bb28 --- /dev/null +++ b/internal/gatewayapi/testdata/securitypolicy-with-merge-needs-fieldowner.in.yaml @@ -0,0 +1,231 @@ +gateways: +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + namespace: envoy-gateway + name: gateway-1 + spec: + gatewayClassName: envoy-gateway-class + listeners: + - name: http + protocol: HTTP + port: 80 + allowedRoutes: + namespaces: + from: All +httpRoutes: +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + namespace: default + name: httproute-1 + spec: + parentRefs: + - namespace: envoy-gateway + name: gateway-1 + sectionName: http + rules: + - matches: + - path: + value: "/foo" + backendRefs: + - name: service-1 + port: 8080 +services: +- apiVersion: v1 + kind: Service + metadata: + namespace: envoy-gateway + name: grpc-backend + spec: + ports: + - port: 9000 + name: grpc + protocol: TCP +- apiVersion: v1 + kind: Service + metadata: + namespace: default + name: grpc-backend + spec: + ports: + - port: 9000 + name: grpc + protocol: TCP +endpointSlices: +- apiVersion: discovery.k8s.io/v1 + kind: EndpointSlice + metadata: + namespace: envoy-gateway + name: endpointslice-grpc-backend + labels: + kubernetes.io/service-name: grpc-backend + addressType: IPv4 + ports: + - name: grpc + protocol: TCP + port: 9000 + endpoints: + - addresses: + - 8.8.8.8 + conditions: + ready: true +- apiVersion: discovery.k8s.io/v1 + kind: EndpointSlice + metadata: + namespace: default + name: endpointslice-grpc-backend + labels: + kubernetes.io/service-name: grpc-backend + addressType: IPv4 + ports: + - name: grpc + protocol: TCP + port: 9000 + endpoints: + - addresses: + - 9.9.9.9 + conditions: + ready: true +securityPolicies: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: SecurityPolicy + metadata: + namespace: envoy-gateway + name: policy-for-gateway + # check: oidc suffix value [c3556d06] + uid: "aaaaaaaa-0000-0000-0000-000000000001" + spec: + targetRefs: + - group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + sectionName: http + # merge basicAuth check: + # - can resolve auth secret in parent ns (envoy-gateway) + basicAuth: + users: + name: users-secret + # merge extAuth check: + # - can resolve backendRef in parent ns (envoy-gateway) + # - merge contextExtensions by name and resolve each item from its owning policy namespace + extAuth: + grpc: + backendRefs: + - name: grpc-backend + port: 9000 + contextExtensions: + - name: shared + type: ValueRef + valueRef: + Group: "" + Kind: ConfigMap + Name: context-extension-for-gateway + key: data-shared + - name: parent-only + type: ValueRef + valueRef: + Group: "" + Kind: ConfigMap + Name: context-extension-for-gateway + key: data + # merge oidc check: + # - can resolve provider backendRef in parent ns (envoy-gateway) + # - can resolve client secret in parent ns (envoy-gateway) + oidc: + provider: + backendRefs: + - group: gateway.envoyproxy.io + kind: Backend + name: backend-ip + port: 3000 + issuer: "https://oauth.foo.com" + authorizationEndpoint: "https://oauth.foo.com/oauth2/v2/auth" + tokenEndpoint: "https://oauth.foo.com/token" + clientID: "client1.apps.googleusercontent.com" + clientSecret: + name: "client-secret" +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: SecurityPolicy + metadata: + namespace: default + name: policy-for-route + # check: oidc suffix value [6ac6170b] + uid: "bbbbbbbb-0000-0000-0000-000000000002" + spec: + mergeType: StrategicMerge + targetRefs: + - group: gateway.networking.k8s.io + kind: HTTPRoute + name: httproute-1 + extAuth: + grpc: + backendRefs: + - name: grpc-backend + port: 9000 + contextExtensions: + - name: shared + type: ValueRef + valueRef: + Group: "" + Kind: ConfigMap + Name: context-extension-for-route + key: data-shared + - name: route-only + type: ValueRef + valueRef: + Group: "" + Kind: ConfigMap + Name: context-extension-for-route + key: data +backends: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + namespace: envoy-gateway + name: backend-ip + spec: + endpoints: + - ip: + address: 7.7.7.7 + port: 3000 +secrets: +- apiVersion: v1 + kind: Secret + metadata: + namespace: envoy-gateway + name: users-secret + type: Opaque + data: + .htpasswd: dXNlcjE6e1NIQX15LzJzWUFqNXlyUUlONFRMMFlkUGRtR05LcGM9 +- apiVersion: v1 + kind: Secret + metadata: + namespace: envoy-gateway + name: client-secret + data: + client-secret: Y2xpZW50MTpzZWNyZXQK +- apiVersion: v1 + kind: Secret + metadata: + namespace: envoy-gateway-system + name: envoy-oidc-hmac + data: + hmac-secret: qrOYACHXoe7UEDI/raOjNSx+Z9ufXSc/22C3T6X/zPY= +configmaps: +- apiVersion: v1 + kind: ConfigMap + metadata: + namespace: envoy-gateway + name: context-extension-for-gateway + data: + data-shared: test-key-gateway + data: test-key-gateway +- apiVersion: v1 + kind: ConfigMap + metadata: + namespace: default + name: context-extension-for-route + data: + data-shared: test-key-route + data: test-key-route diff --git a/internal/gatewayapi/testdata/securitypolicy-with-merge-needs-fieldowner.out.yaml b/internal/gatewayapi/testdata/securitypolicy-with-merge-needs-fieldowner.out.yaml new file mode 100644 index 0000000000..6abe6abfb9 --- /dev/null +++ b/internal/gatewayapi/testdata/securitypolicy-with-merge-needs-fieldowner.out.yaml @@ -0,0 +1,379 @@ +backends: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: Backend + metadata: + name: backend-ip + namespace: envoy-gateway + spec: + endpoints: + - ip: + address: 7.7.7.7 + port: 3000 + status: + conditions: + - lastTransitionTime: null + message: The Backend was accepted + reason: Accepted + status: "True" + type: Accepted +gateways: +- apiVersion: gateway.networking.k8s.io/v1 + kind: Gateway + metadata: + name: gateway-1 + namespace: envoy-gateway + spec: + gatewayClassName: envoy-gateway-class + listeners: + - allowedRoutes: + namespaces: + from: All + name: http + port: 80 + protocol: HTTP + status: + listeners: + - attachedRoutes: 1 + conditions: + - lastTransitionTime: null + message: Sending translated listener configuration to the data plane + reason: Programmed + status: "True" + type: Programmed + - lastTransitionTime: null + message: Listener has been successfully translated + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Listener references have been resolved + reason: ResolvedRefs + status: "True" + type: ResolvedRefs + name: http + supportedKinds: + - group: gateway.networking.k8s.io + kind: HTTPRoute + - group: gateway.networking.k8s.io + kind: GRPCRoute +httpRoutes: +- apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute + metadata: + name: httproute-1 + namespace: default + spec: + parentRefs: + - name: gateway-1 + namespace: envoy-gateway + sectionName: http + rules: + - backendRefs: + - name: service-1 + port: 8080 + matches: + - path: + value: /foo + status: + parents: + - conditions: + - lastTransitionTime: null + message: Route is accepted + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: Resolved all the Object references for the Route + reason: ResolvedRefs + status: "True" + type: ResolvedRefs + controllerName: gateway.envoyproxy.io/gatewayclass-controller + parentRef: + name: gateway-1 + namespace: envoy-gateway + sectionName: http +infraIR: + envoy-gateway/gateway-1: + proxy: + listeners: + - name: envoy-gateway/gateway-1/http + ports: + - containerPort: 10080 + name: http-80 + protocol: HTTP + servicePort: 80 + metadata: + labels: + gateway.envoyproxy.io/owning-gateway-name: gateway-1 + gateway.envoyproxy.io/owning-gateway-namespace: envoy-gateway + ownerReference: + kind: GatewayClass + name: envoy-gateway-class + name: envoy-gateway/gateway-1 + namespace: envoy-gateway-system +securityPolicies: +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: SecurityPolicy + metadata: + name: policy-for-route + namespace: default + uid: bbbbbbbb-0000-0000-0000-000000000002 + spec: + extAuth: + contextExtensions: + - name: shared + type: ValueRef + valueRef: + group: "" + key: data-shared + kind: ConfigMap + name: context-extension-for-route + - name: route-only + type: ValueRef + valueRef: + group: "" + key: data + kind: ConfigMap + name: context-extension-for-route + grpc: + backendRefs: + - name: grpc-backend + port: 9000 + mergeType: StrategicMerge + targetRefs: + - group: gateway.networking.k8s.io + kind: HTTPRoute + name: httproute-1 + status: + ancestors: + - ancestorRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + namespace: envoy-gateway + sectionName: http + conditions: + - lastTransitionTime: null + message: Merged with policy envoy-gateway/policy-for-gateway + reason: Merged + status: "True" + type: Merged + - lastTransitionTime: null + message: Policy has been accepted. + reason: Accepted + status: "True" + type: Accepted + controllerName: gateway.envoyproxy.io/gatewayclass-controller +- apiVersion: gateway.envoyproxy.io/v1alpha1 + kind: SecurityPolicy + metadata: + name: policy-for-gateway + namespace: envoy-gateway + uid: aaaaaaaa-0000-0000-0000-000000000001 + spec: + basicAuth: + users: + name: users-secret + extAuth: + contextExtensions: + - name: shared + type: ValueRef + valueRef: + group: "" + key: data-shared + kind: ConfigMap + name: context-extension-for-gateway + - name: parent-only + type: ValueRef + valueRef: + group: "" + key: data + kind: ConfigMap + name: context-extension-for-gateway + grpc: + backendRefs: + - name: grpc-backend + port: 9000 + oidc: + clientID: client1.apps.googleusercontent.com + clientSecret: + name: client-secret + provider: + authorizationEndpoint: https://oauth.foo.com/oauth2/v2/auth + backendRefs: + - group: gateway.envoyproxy.io + kind: Backend + name: backend-ip + port: 3000 + issuer: https://oauth.foo.com + tokenEndpoint: https://oauth.foo.com/token + targetRefs: + - group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + sectionName: http + status: + ancestors: + - ancestorRef: + group: gateway.networking.k8s.io + kind: Gateway + name: gateway-1 + namespace: envoy-gateway + sectionName: http + conditions: + - lastTransitionTime: null + message: Policy has been accepted. + reason: Accepted + status: "True" + type: Accepted + - lastTransitionTime: null + message: 'This policy is being merged by other securityPolicies for these + routes: [default/httproute-1]' + reason: Merged + status: "True" + type: Merged + controllerName: gateway.envoyproxy.io/gatewayclass-controller +xdsIR: + envoy-gateway/gateway-1: + accessLog: + json: + - path: /dev/stdout + globalResources: + proxyServiceCluster: + metadata: + kind: Service + name: envoy-envoy-gateway-gateway-1-196ae069 + namespace: envoy-gateway-system + sectionName: "8080" + name: envoy-gateway/gateway-1 + settings: + - addressType: IP + endpoints: + - host: 7.6.5.4 + port: 8080 + zone: zone1 + metadata: + kind: Service + name: envoy-envoy-gateway-gateway-1-196ae069 + namespace: envoy-gateway-system + sectionName: "8080" + name: envoy-gateway/gateway-1 + protocol: TCP + http: + - address: 0.0.0.0 + externalPort: 80 + hostnames: + - '*' + metadata: + kind: Gateway + name: gateway-1 + namespace: envoy-gateway + sectionName: http + name: envoy-gateway/gateway-1/http + path: + escapedSlashesAction: UnescapeAndRedirect + mergeSlashes: true + port: 10080 + routes: + - destination: + metadata: + kind: HTTPRoute + name: httproute-1 + namespace: default + name: httproute/default/httproute-1/rule/0 + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 8080 + metadata: + kind: Service + name: service-1 + namespace: default + sectionName: "8080" + name: httproute/default/httproute-1/rule/0/backend/0 + protocol: HTTP + weight: 1 + hostname: '*' + isHTTP2: false + metadata: + kind: HTTPRoute + name: httproute-1 + namespace: default + name: httproute/default/httproute-1/rule/0/match/0/* + pathMatch: + distinct: false + name: "" + prefix: /foo + security: + basicAuth: + name: securitypolicy/envoy-gateway/policy-for-gateway + users: '[redacted]' + extAuth: + contextExtensions: + - name: shared + value: '[redacted]' + - name: route-only + value: '[redacted]' + - name: parent-only + value: '[redacted]' + grpc: + authority: grpc-backend.default:9000 + destination: + metadata: + kind: SecurityPolicy + name: policy-for-route + namespace: default + name: securitypolicy/default/policy-for-route/extauth/0 + settings: + - addressType: IP + endpoints: + - host: 9.9.9.9 + port: 9000 + metadata: + kind: Service + name: grpc-backend + namespace: default + sectionName: "9000" + name: securitypolicy/default/policy-for-route/extauth/0/backend/0 + protocol: GRPC + weight: 1 + name: securitypolicy/default/policy-for-route + oidc: + clientID: client1.apps.googleusercontent.com + clientSecret: '[redacted]' + cookieSuffix: c3556d06 + hmacSecret: '[redacted]' + logoutPath: /logout + name: securitypolicy/envoy-gateway/policy-for-gateway + provider: + authorizationEndpoint: https://oauth.foo.com/oauth2/v2/auth + destination: + metadata: + kind: SecurityPolicy + name: policy-for-gateway + namespace: envoy-gateway + name: securitypolicy/envoy-gateway/policy-for-gateway/oidc/0 + settings: + - addressType: IP + endpoints: + - host: 7.7.7.7 + port: 3000 + metadata: + kind: Backend + name: backend-ip + namespace: envoy-gateway + name: securitypolicy/envoy-gateway/policy-for-gateway/oidc/0/backend/0 + protocol: HTTPS + weight: 1 + tokenEndpoint: https://oauth.foo.com/token + redirectPath: /oauth2/callback + redirectURL: '%REQ(x-forwarded-proto)%://%REQ(:authority)%/oauth2/callback' + refreshToken: true + scopes: + - openid + readyListener: + address: 0.0.0.0 + ipFamily: IPv4 + path: /ready + port: 19003 diff --git a/internal/gatewayapi/testdata/securitypolicy-with-merge.out.yaml b/internal/gatewayapi/testdata/securitypolicy-with-merge.out.yaml index ee2655e8a0..b155bfe2ed 100644 --- a/internal/gatewayapi/testdata/securitypolicy-with-merge.out.yaml +++ b/internal/gatewayapi/testdata/securitypolicy-with-merge.out.yaml @@ -242,7 +242,7 @@ xdsIR: prefix: /foo security: basicAuth: - name: securitypolicy/default/policy-for-route + name: securitypolicy/envoy-gateway/policy-for-gateway users: '[redacted]' cors: allowHeaders: diff --git a/internal/gatewayapi/testdata/tlsroute-invalid-no-matching-listener.out.yaml b/internal/gatewayapi/testdata/tlsroute-invalid-no-matching-listener.out.yaml index 70c8273b9f..3ea4f78801 100644 --- a/internal/gatewayapi/testdata/tlsroute-invalid-no-matching-listener.out.yaml +++ b/internal/gatewayapi/testdata/tlsroute-invalid-no-matching-listener.out.yaml @@ -315,13 +315,6 @@ infraIR: namespace: envoy-gateway-system envoy-gateway/gateway-tlsroute-tcproute-only: proxy: - listeners: - - name: envoy-gateway/gateway-tlsroute-tcproute-only/tls-passthrough - ports: - - containerPort: 10443 - name: tls-443 - protocol: TLS - servicePort: 443 metadata: labels: gateway.envoyproxy.io/owning-gateway-name: gateway-tlsroute-tcproute-only @@ -743,16 +736,6 @@ xdsIR: ipFamily: IPv4 path: /ready port: 19003 - tcp: - - address: 0.0.0.0 - externalPort: 443 - metadata: - kind: Gateway - name: gateway-tlsroute-tcproute-only - namespace: envoy-gateway - sectionName: tls-passthrough - name: envoy-gateway/gateway-tlsroute-tcproute-only/tls-passthrough - port: 10443 envoy-gateway/gateway-tlsroute-tls-passthrough-only: accessLog: json: diff --git a/internal/gatewayapi/testdata/tlsroute-not-attaching-to-gateway-with-no-mode.out.yaml b/internal/gatewayapi/testdata/tlsroute-not-attaching-to-gateway-with-no-mode.out.yaml index f7221094bd..5a7b2c7289 100644 --- a/internal/gatewayapi/testdata/tlsroute-not-attaching-to-gateway-with-no-mode.out.yaml +++ b/internal/gatewayapi/testdata/tlsroute-not-attaching-to-gateway-with-no-mode.out.yaml @@ -36,13 +36,6 @@ gateways: infraIR: envoy-gateway/gateway-1: proxy: - listeners: - - name: envoy-gateway/gateway-1/tls - ports: - - containerPort: 10090 - name: tls-90 - protocol: TLS - servicePort: 90 metadata: labels: gateway.envoyproxy.io/owning-gateway-name: gateway-1 @@ -114,13 +107,3 @@ xdsIR: ipFamily: IPv4 path: /ready port: 19003 - tcp: - - address: 0.0.0.0 - externalPort: 90 - metadata: - kind: Gateway - name: gateway-1 - namespace: envoy-gateway - sectionName: tls - name: envoy-gateway/gateway-1/tls - port: 10090 diff --git a/internal/gatewayapi/testdata/tlsroute-with-listener-both-passthrough-and-cert-data.out.yaml b/internal/gatewayapi/testdata/tlsroute-with-listener-both-passthrough-and-cert-data.out.yaml index eca1a7d9b6..e1f898a957 100644 --- a/internal/gatewayapi/testdata/tlsroute-with-listener-both-passthrough-and-cert-data.out.yaml +++ b/internal/gatewayapi/testdata/tlsroute-with-listener-both-passthrough-and-cert-data.out.yaml @@ -39,13 +39,6 @@ gateways: infraIR: envoy-gateway/gateway-1: proxy: - listeners: - - name: envoy-gateway/gateway-1/tls - ports: - - containerPort: 10090 - name: tls-90 - protocol: TLS - servicePort: 90 metadata: labels: gateway.envoyproxy.io/owning-gateway-name: gateway-1 @@ -117,13 +110,3 @@ xdsIR: ipFamily: IPv4 path: /ready port: 19003 - tcp: - - address: 0.0.0.0 - externalPort: 90 - metadata: - kind: Gateway - name: gateway-1 - namespace: envoy-gateway - sectionName: tls - name: envoy-gateway/gateway-1/tls - port: 10090 diff --git a/internal/gatewayapi/validate.go b/internal/gatewayapi/validate.go index d8138446d9..4332403a71 100644 --- a/internal/gatewayapi/validate.go +++ b/internal/gatewayapi/validate.go @@ -289,15 +289,24 @@ func (t *Translator) validateListenerConditions(listener *ListenerContext) { return } - // Edge case: only one condition which is ResolvedRefs=False, Reason=PartiallyInvalidCertificateRef - // In this case, we can still consider the listener as ready because we only program the listener using only the valid certificates. - if len(lConditions) == 1 && lConditions[0].Type == string(gwapiv1.ListenerConditionResolvedRefs) && - lConditions[0].Reason == string(status.ListenerReasonPartiallyInvalidCertificateRef) { - listener.SetCondition(gwapiv1.ListenerConditionAccepted, metav1.ConditionTrue, gwapiv1.ListenerReasonAccepted, - "Listener has been successfully translated") - listener.SetCondition(gwapiv1.ListenerConditionProgrammed, metav1.ConditionTrue, gwapiv1.ListenerReasonProgrammed, - "Sending translated listener configuration to the data plane") - return + onlyResolvedRefFailure := len(lConditions) == 1 && lConditions[0].Type == string(gwapiv1.ListenerConditionResolvedRefs) + if onlyResolvedRefFailure { + switch lConditions[0].Reason { + case string(status.ListenerReasonPartiallyInvalidCertificateRef): + // The listener is ready because we program it using only the valid certificates. + listener.SetCondition(gwapiv1.ListenerConditionAccepted, metav1.ConditionTrue, gwapiv1.ListenerReasonAccepted, + "Listener has been successfully translated") + listener.SetCondition(gwapiv1.ListenerConditionProgrammed, metav1.ConditionTrue, gwapiv1.ListenerReasonProgrammed, + "Sending translated listener configuration to the data plane") + return + case string(gwapiv1.ListenerReasonInvalidCertificateRef): + // The listener configuration is semantically valid, but the listener cannot serve traffic with an invalid certificate. + listener.SetCondition(gwapiv1.ListenerConditionAccepted, metav1.ConditionTrue, gwapiv1.ListenerReasonAccepted, + "Listener has been successfully translated") + listener.SetCondition(gwapiv1.ListenerConditionProgrammed, metav1.ConditionFalse, gwapiv1.ListenerReasonInvalid, + "Listener is invalid, see other Conditions for details.") + return + } } // Any condition on the listener apart from Programmed=true indicates an error. @@ -332,12 +341,49 @@ func (t *Translator) validateListenerConditions(listener *ListenerContext) { "Listener references have been resolved", ) } - // skip computing IR - return } } -func (t *Translator) validateAllowedNamespaces(listener *ListenerContext) { +// hasInvalidCondition checks if a listener has been marked as invalid during per-listener validation. +// A listener is considered invalid if it has Programmed=False, Accepted=False, or ResolvedRefs=False +// (except for the special case of PartiallyInvalidCertificateRef which is allowed). +// This is used during conflict resolution to skip invalid listeners so they don't block valid ones. +func hasInvalidCondition(listener *ListenerContext) bool { + conditions := listener.GetConditions() + for _, cond := range conditions { + if cond.Type == string(gwapiv1.ListenerConditionProgrammed) && cond.Status == metav1.ConditionFalse { + return true + } + if cond.Type == string(gwapiv1.ListenerConditionAccepted) && cond.Status == metav1.ConditionFalse { + return true + } + // ResolvedRefs=False is invalid except for PartiallyInvalidCertificateRef which allows + // the listener to still be programmed with valid certificates + if cond.Type == string(gwapiv1.ListenerConditionResolvedRefs) && + cond.Status == metav1.ConditionFalse && + cond.Reason != string(status.ListenerReasonPartiallyInvalidCertificateRef) { + return true + } + } + return false +} + +// isSpecValidForConflictChecks returns whether a listener should participate in +// conflict detection. In the normal translation flow this is driven by +// listener.specValid. The fallback to hasInvalidCondition exists only for unit +// tests that invoke conflict checks directly without running per-listener spec +// validation (Phase 1) first. Production code paths always run validateListenerSpec +// before conflict detection. +func isSpecValidForConflictChecks(listener *ListenerContext) bool { + if listener.specValid { + return true + } + return !hasInvalidCondition(listener) +} + +// validateAllowedNamespaces validates namespace selector configuration. +// Returns true if the namespace spec is valid, false otherwise. +func (t *Translator) validateAllowedNamespaces(listener *ListenerContext) bool { if listener.AllowedRoutes != nil && listener.AllowedRoutes.Namespaces != nil && listener.AllowedRoutes.Namespaces.From != nil && @@ -349,26 +395,28 @@ func (t *Translator) validateAllowedNamespaces(listener *ListenerContext) { gwapiv1.ListenerReasonInvalid, "The allowedRoutes.namespaces.selector field must be specified when allowedRoutes.namespaces.from is set to \"Selector\".", ) - } else { - selector, err := metav1.LabelSelectorAsSelector(listener.AllowedRoutes.Namespaces.Selector) - if err != nil { - listener.SetCondition( - gwapiv1.ListenerConditionProgrammed, - metav1.ConditionFalse, - gwapiv1.ListenerReasonInvalid, - fmt.Sprintf("The allowedRoutes.namespaces.selector could not be parsed: %v.", err), - ) - } - - listener.namespaceSelector = selector + return false + } + selector, err := metav1.LabelSelectorAsSelector(listener.AllowedRoutes.Namespaces.Selector) + if err != nil { + listener.SetCondition( + gwapiv1.ListenerConditionProgrammed, + metav1.ConditionFalse, + gwapiv1.ListenerReasonInvalid, + fmt.Sprintf("The allowedRoutes.namespaces.selector could not be parsed: %v.", err), + ) + return false } + + listener.namespaceSelector = selector } + return true } func (t *Translator) validateTerminateModeAndGetTLSSecrets( listener *ListenerContext, resources *resource.Resources, -) ([]*corev1.Secret, []*x509.Certificate) { +) ([]*corev1.Secret, []*x509.Certificate, bool) { if len(listener.TLS.CertificateRefs) == 0 { listener.SetCondition( gwapiv1.ListenerConditionProgrammed, @@ -376,7 +424,7 @@ func (t *Translator) validateTerminateModeAndGetTLSSecrets( gwapiv1.ListenerReasonInvalid, "Listener must have at least 1 TLS certificate ref", ) - return nil, nil + return nil, nil, false } var errs []status.ListenerError @@ -486,7 +534,7 @@ func (t *Translator) validateTerminateModeAndGetTLSSecrets( fmt.Sprintf("No valid secrets exist: %v", errors.Join(errList...)), ) - return nil, nil + return nil, nil, false } validSecrets, certs, err := parseCertsFromTLSSecretsData(secrets) @@ -498,7 +546,7 @@ func (t *Translator) validateTerminateModeAndGetTLSSecrets( err.Reason(), fmt.Sprintf("No valid secrets exist: %v.", err.Error()), ) - return nil, nil + return nil, nil, false } else { errs = append(errs, err) } @@ -517,13 +565,17 @@ func (t *Translator) validateTerminateModeAndGetTLSSecrets( fmt.Sprintf("Some secrets are invalid: %v", errors.Join(errList...)), ) } - return validSecrets, certs + return validSecrets, certs, true } +// validateTLSConfiguration validates TLS configuration per protocol. +// Returns true if the TLS spec is valid, false otherwise. func (t *Translator) validateTLSConfiguration( listener *ListenerContext, resources *resource.Resources, -) { +) bool { + specValid := true + switch listener.Protocol { case gwapiv1.HTTPProtocolType, gwapiv1.UDPProtocolType, gwapiv1.TCPProtocolType: if listener.TLS != nil { @@ -533,6 +585,7 @@ func (t *Translator) validateTLSConfiguration( gwapiv1.ListenerReasonInvalid, fmt.Sprintf("Listener must not have TLS set when protocol is %s.", listener.Protocol), ) + specValid = false } case gwapiv1.HTTPSProtocolType: if listener.TLS == nil { @@ -542,25 +595,29 @@ func (t *Translator) validateTLSConfiguration( gwapiv1.ListenerReasonInvalid, fmt.Sprintf("Listener must have TLS set when protocol is %s.", listener.Protocol), ) - break - } - - if listener.TLS.Mode != nil && *listener.TLS.Mode != gwapiv1.TLSModeTerminate { - listener.SetCondition( - gwapiv1.ListenerConditionProgrammed, - metav1.ConditionFalse, - "UnsupportedTLSMode", - fmt.Sprintf("TLS %s mode is not supported, TLS mode must be Terminate.", *listener.TLS.Mode), - ) - break - } + specValid = false + } else { + if listener.TLS.Mode != nil && *listener.TLS.Mode != gwapiv1.TLSModeTerminate { + listener.SetCondition( + gwapiv1.ListenerConditionProgrammed, + metav1.ConditionFalse, + "UnsupportedTLSMode", + fmt.Sprintf("TLS %s mode is not supported, TLS mode must be Terminate.", *listener.TLS.Mode), + ) + specValid = false + } else { + secrets, certs, ok := t.validateTerminateModeAndGetTLSSecrets(listener, resources) + listener.SetTLSSecrets(secrets) - secrets, certs := t.validateTerminateModeAndGetTLSSecrets(listener, resources) - listener.SetTLSSecrets(secrets) + if !ok { + specValid = false + } - listener.tls.certDNSNames = make([]string, 0) - for _, cert := range certs { - listener.tls.certDNSNames = append(listener.tls.certDNSNames, cert.DNSNames...) + listener.tls.certDNSNames = make([]string, 0) + for _, cert := range certs { + listener.tls.certDNSNames = append(listener.tls.certDNSNames, cert.DNSNames...) + } + } } case gwapiv1.TLSProtocolType: if listener.TLS == nil { @@ -570,33 +627,38 @@ func (t *Translator) validateTLSConfiguration( gwapiv1.ListenerReasonInvalid, fmt.Sprintf("Listener must have TLS set when protocol is %s.", listener.Protocol), ) - break - } - - if listener.TLS.Mode != nil && *listener.TLS.Mode == gwapiv1.TLSModePassthrough { - if len(listener.TLS.CertificateRefs) > 0 { - listener.SetCondition( - gwapiv1.ListenerConditionProgrammed, - metav1.ConditionFalse, - gwapiv1.ListenerReasonInvalid, - "Listener must not have TLS certificate refs set for TLS mode Passthrough.", - ) - break + specValid = false + } else { + if listener.TLS.Mode != nil && *listener.TLS.Mode == gwapiv1.TLSModePassthrough { + if len(listener.TLS.CertificateRefs) > 0 { + listener.SetCondition( + gwapiv1.ListenerConditionProgrammed, + metav1.ConditionFalse, + gwapiv1.ListenerReasonInvalid, + "Listener must not have TLS certificate refs set for TLS mode Passthrough.", + ) + specValid = false + } } - } - if listener.TLS.Mode != nil && *listener.TLS.Mode == gwapiv1.TLSModeTerminate { - if len(listener.TLS.CertificateRefs) == 0 { - listener.SetCondition( - gwapiv1.ListenerConditionProgrammed, - metav1.ConditionFalse, - gwapiv1.ListenerReasonInvalid, - "Listener must have TLS certificate refs set for TLS mode Terminate.", - ) - break + if listener.TLS.Mode != nil && *listener.TLS.Mode == gwapiv1.TLSModeTerminate { + if len(listener.TLS.CertificateRefs) == 0 { + listener.SetCondition( + gwapiv1.ListenerConditionProgrammed, + metav1.ConditionFalse, + gwapiv1.ListenerReasonInvalid, + "Listener must have TLS certificate refs set for TLS mode Terminate.", + ) + specValid = false + } else { + secrets, _, ok := t.validateTerminateModeAndGetTLSSecrets(listener, resources) + listener.SetTLSSecrets(secrets) + + if !ok { + specValid = false + } + } } - secrets, _ := t.validateTerminateModeAndGetTLSSecrets(listener, resources) - listener.SetTLSSecrets(secrets) } } @@ -630,10 +692,15 @@ func (t *Translator) validateTLSConfiguration( gwapiv1.ListenerReasonNoValidCACertificate, message, ) + specValid = false } + + return specValid } -func (t *Translator) validateHostName(listener *ListenerContext) { +// validateHostName validates hostname configuration per protocol. +// Returns true if the hostname spec is valid, false otherwise. +func (t *Translator) validateHostName(listener *ListenerContext) bool { if listener.Protocol == gwapiv1.UDPProtocolType || listener.Protocol == gwapiv1.TCPProtocolType { if listener.Hostname != nil { listener.SetCondition( @@ -642,20 +709,25 @@ func (t *Translator) validateHostName(listener *ListenerContext) { gwapiv1.ListenerReasonInvalid, fmt.Sprintf("Listener must not have hostname set when protocol is %s.", listener.Protocol), ) + return false } } + return true } -func (t *Translator) validateAllowedRoutes(listener *ListenerContext, routeKinds ...gwapiv1.Kind) { +// validateAllowedRoutes validates allowed route kinds configuration. +// Returns true if the allowed routes spec is valid, false otherwise. +func (t *Translator) validateAllowedRoutes(listener *ListenerContext, routeKinds ...gwapiv1.Kind) bool { canSupportKinds := make([]gwapiv1.RouteGroupKind, len(routeKinds)) for i, routeKind := range routeKinds { canSupportKinds[i] = gwapiv1.RouteGroupKind{Group: GroupPtr(gwapiv1.GroupName), Kind: routeKind} } if listener.AllowedRoutes == nil || len(listener.AllowedRoutes.Kinds) == 0 { listener.SetSupportedKinds(canSupportKinds...) - return + return true } + specValid := true supportedRouteKinds := make([]gwapiv1.Kind, 0) supportedKinds := make([]gwapiv1.RouteGroupKind, 0) unSupportedKinds := make([]gwapiv1.RouteGroupKind, 0) @@ -670,6 +742,7 @@ func (t *Translator) validateAllowedRoutes(listener *ListenerContext, routeKinds gwapiv1.ListenerReasonInvalidRouteKinds, fmt.Sprintf("Group is not supported, group must be %s", gwapiv1.GroupName), ) + specValid = false continue } @@ -701,9 +774,11 @@ func (t *Translator) validateAllowedRoutes(listener *ListenerContext, routeKinds gwapiv1.ListenerReasonInvalidRouteKinds, fmt.Sprintf("%s is not supported, kind must be one of %v", string(kind.Kind), printRouteKinds), ) + specValid = false } listener.SetSupportedKinds(supportedKinds...) + return specValid } type portListeners struct { @@ -717,6 +792,11 @@ func (t *Translator) validateConflictedMergedListeners(gateways []*GatewayContex listenerSets := sets.Set[string]{} for _, gateway := range gateways { for _, listener := range gateway.listeners { + // Skip listeners that are already marked as invalid from per-listener validation. + // This prevents an invalid first listener from blocking valid subsequent listeners. + if !isSpecValidForConflictChecks(listener) { + continue + } hostname := new(gwapiv1.Hostname) if listener.Hostname != nil { hostname = listener.Hostname @@ -735,6 +815,118 @@ func (t *Translator) validateConflictedMergedListeners(gateways []*GatewayContex } } +// validateConflictedProtocolsListeners checks for listeners that have conflicting protocols on the same port. +// UDP can coexist with any protocol. HTTPS and TLS are treated as compatible via getProtocolForListener. +func (t *Translator) validateConflictedProtocolsListeners(gateways []*GatewayContext) { + validateByPort := func(listeners []*ListenerContext) { + portListenerInfo := map[gwapiv1.PortNumber][]*ListenerContext{} + for _, listener := range listeners { + if !isSpecValidForConflictChecks(listener) || !isSupportedListenerProtocol(listener.Protocol) { + continue + } + portListenerInfo[listener.Port] = append(portListenerInfo[listener.Port], listener) + } + + for _, listenersOnPort := range portListenerInfo { + nonUDPProtocols := sets.New[string]() + nonListenerSetCount := 0 + for _, listener := range listenersOnPort { + protocol := getProtocolForListener(listener) + if protocol == string(gwapiv1.UDPProtocolType) { + continue + } + nonUDPProtocols.Insert(protocol) + if !listener.isFromListenerSet() { + nonListenerSetCount++ + } + } + + // No protocol conflict when all non-UDP listeners are compatible. + if len(nonUDPProtocols) <= 1 { + continue + } + + // If there are more than 1 non-UDP protocols and more than 1 listener not from ListenerSet, + // we cannot determine a clear winner and all listeners on this port are in conflict. + if nonListenerSetCount > 1 { + // If any conflicted listener is not from ListenerSet, do not pick a winner. + for _, listener := range listenersOnPort { + if getProtocolForListener(listener) == string(gwapiv1.UDPProtocolType) { + continue + } + listener.SetCondition( + gwapiv1.ListenerConditionConflicted, + metav1.ConditionTrue, + gwapiv1.ListenerReasonProtocolConflict, + "All listeners for a given port must use a compatible protocol", + ) + } + continue + } + + // When nonListenerSetCount == 1, explicitly pick the Gateway-owned listener as winner. + // When nonListenerSetCount == 0, pick the first ListenerSet listener as winner. + // Note: UDP conflicts are handled by validateConflictedLayer4Listeners, so we skip + // UDP listeners here (this branch is only reached when len(nonUDPProtocols) > 1). + var winnerProtocol string + if nonListenerSetCount == 1 { + // Find and use the non-ListenerSet listener's protocol as the winner + for _, listener := range listenersOnPort { + protocol := getProtocolForListener(listener) + if !listener.isFromListenerSet() && protocol != string(gwapiv1.UDPProtocolType) { + winnerProtocol = protocol + break + } + } + } + + for _, listener := range listenersOnPort { + protocol := getProtocolForListener(listener) + // Skip UDP listeners as they are handled by validateConflictedLayer4Listeners + if protocol == string(gwapiv1.UDPProtocolType) { + continue + } + + // If we have an explicit winner protocol, use it; otherwise first one wins + if winnerProtocol != "" { + if protocol != winnerProtocol { + listener.SetCondition( + gwapiv1.ListenerConditionConflicted, + metav1.ConditionTrue, + gwapiv1.ListenerReasonProtocolConflict, + "All listeners for a given port must use a compatible protocol", + ) + } + } else { + // All conflicted listeners are from ListenerSet, first one wins + if winnerProtocol == "" { + winnerProtocol = protocol + } else if protocol != winnerProtocol { + listener.SetCondition( + gwapiv1.ListenerConditionConflicted, + metav1.ConditionTrue, + gwapiv1.ListenerReasonProtocolConflict, + "All listeners for a given port must use a compatible protocol", + ) + } + } + } + } + } + + for _, gateway := range gateways { + validateByPort(gateway.listeners) + } + + if t.MergeGateways { + allListeners := make([]*ListenerContext, 0) + for _, gateway := range gateways { + allListeners = append(allListeners, gateway.listeners...) + } + validateByPort(allListeners) + } +} + func (t *Translator) validateConflictedLayer7Listeners(gateways []*GatewayContext) { // Iterate through all layer-7 (HTTP, HTTPS, TLS) listeners and collect info about protocols // and hostnames per port. @@ -744,6 +936,11 @@ func (t *Translator) validateConflictedLayer7Listeners(gateways []*GatewayContex if listener.Protocol == gwapiv1.UDPProtocolType || listener.Protocol == gwapiv1.TCPProtocolType { continue } + // Skip listeners that are already marked as invalid from per-listener validation. + // This prevents an invalid first listener from blocking valid subsequent listeners. + if !isSpecValidForConflictChecks(listener) { + continue + } if portListenerInfo[listener.Port] == nil { portListenerInfo[listener.Port] = &portListeners{ protocols: sets.Set[string]{}, @@ -806,6 +1003,11 @@ func (t *Translator) validateConflictedLayer4Listeners(gateways []*GatewayContex for _, gateway := range gateways { portListenerInfo := map[gwapiv1.PortNumber]*portListeners{} for _, listener := range gateway.listeners { + // Skip listeners that are already marked as invalid from per-listener validation. + // This prevents an invalid first listener from blocking valid subsequent listeners. + if !isSpecValidForConflictChecks(listener) { + continue + } for _, protocol := range protocols { if listener.Protocol == protocol { if portListenerInfo[listener.Port] == nil { @@ -832,6 +1034,26 @@ func (t *Translator) validateConflictedLayer4Listeners(gateways []*GatewayContex } } +func getProtocolForListener(listener *ListenerContext) string { + switch listener.Protocol { + // HTTPS and TLS can co-exist on the same port. + case gwapiv1.HTTPSProtocolType, gwapiv1.TLSProtocolType: + return "https/tls" + default: + return string(listener.Protocol) + } +} + +func isSupportedListenerProtocol(protocol gwapiv1.ProtocolType) bool { + switch protocol { + case gwapiv1.HTTPProtocolType, gwapiv1.HTTPSProtocolType, gwapiv1.TLSProtocolType, + gwapiv1.TCPProtocolType, gwapiv1.UDPProtocolType: + return true + default: + return false + } +} + // Checks if a hostname is valid according to RFC 1123 and gateway API's requirement that it not be an IP address func (t *Translator) validateHostname(hostname string) error { if errs := validation.IsDNS1123Subdomain(hostname); errs != nil { diff --git a/internal/globalratelimit/runner/runner.go b/internal/globalratelimit/runner/runner.go index d684b59044..fd1bab3e02 100644 --- a/internal/globalratelimit/runner/runner.go +++ b/internal/globalratelimit/runner/runner.go @@ -145,6 +145,8 @@ func (r *Runner) translateFromSubscription(ctx context.Context, c <-chan watchab r.Logger, message.Metadata{Runner: r.Name(), Message: message.XDSIRMessageName}, c, func(update message.Update[string, *message.XdsIRWithContext], errChan chan error) { + message.PublishRunnerEventMetric(r.Name(), update.Delete) + parentCtx := ctx if update.Value != nil && update.Value.Context != nil { parentCtx = update.Value.Context diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/custom.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/custom.yaml index 70994ff931..e44185cae5 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/custom.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/custom.yaml @@ -60,6 +60,8 @@ spec: node: locality: zone: $(ENVOY_SERVICE_ZONE) + deferredStatOptions: + enableDeferredCreationStats: true stats_config: use_all_default_tags: true stats_tags: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/default-env.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/default-env.yaml index fbce087da5..4ad641dc6c 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/default-env.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/default-env.yaml @@ -59,6 +59,8 @@ spec: node: locality: zone: $(ENVOY_SERVICE_ZONE) + deferredStatOptions: + enableDeferredCreationStats: true stats_config: use_all_default_tags: true stats_tags: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/default.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/default.yaml index 4f66d16897..e2f4f44858 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/default.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/default.yaml @@ -59,6 +59,8 @@ spec: node: locality: zone: $(ENVOY_SERVICE_ZONE) + deferredStatOptions: + enableDeferredCreationStats: true stats_config: use_all_default_tags: true stats_tags: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/disable-prometheus.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/disable-prometheus.yaml index bf3e58ad33..b237831507 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/disable-prometheus.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/disable-prometheus.yaml @@ -55,6 +55,8 @@ spec: node: locality: zone: $(ENVOY_SERVICE_ZONE) + deferredStatOptions: + enableDeferredCreationStats: true stats_config: use_all_default_tags: true stats_tags: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/extension-env.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/extension-env.yaml index b16624cfca..d1132cdd0d 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/extension-env.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/extension-env.yaml @@ -59,6 +59,8 @@ spec: node: locality: zone: $(ENVOY_SERVICE_ZONE) + deferredStatOptions: + enableDeferredCreationStats: true stats_config: use_all_default_tags: true stats_tags: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/gateway-namespace-mode.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/gateway-namespace-mode.yaml index d803ad0a6a..0c494f9a12 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/gateway-namespace-mode.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/gateway-namespace-mode.yaml @@ -62,6 +62,8 @@ spec: node: locality: zone: $(ENVOY_SERVICE_ZONE) + deferredStatOptions: + enableDeferredCreationStats: true stats_config: use_all_default_tags: true stats_tags: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/override-labels-and-annotations.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/override-labels-and-annotations.yaml index 95143375c1..bfee9b482d 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/override-labels-and-annotations.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/override-labels-and-annotations.yaml @@ -68,6 +68,8 @@ spec: node: locality: zone: $(ENVOY_SERVICE_ZONE) + deferredStatOptions: + enableDeferredCreationStats: true stats_config: use_all_default_tags: true stats_tags: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/override-prometheus-annotations.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/override-prometheus-annotations.yaml index fb3cdb891c..71bb484dbf 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/override-prometheus-annotations.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/override-prometheus-annotations.yaml @@ -59,6 +59,8 @@ spec: node: locality: zone: $(ENVOY_SERVICE_ZONE) + deferredStatOptions: + enableDeferredCreationStats: true stats_config: use_all_default_tags: true stats_tags: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/patch-daemonset.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/patch-daemonset.yaml index 7ed65069d7..48b12abd88 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/patch-daemonset.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/patch-daemonset.yaml @@ -59,6 +59,8 @@ spec: node: locality: zone: $(ENVOY_SERVICE_ZONE) + deferredStatOptions: + enableDeferredCreationStats: true stats_config: use_all_default_tags: true stats_tags: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/shutdown-manager.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/shutdown-manager.yaml index 0934d52cef..3760966734 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/shutdown-manager.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/shutdown-manager.yaml @@ -59,6 +59,8 @@ spec: node: locality: zone: $(ENVOY_SERVICE_ZONE) + deferredStatOptions: + enableDeferredCreationStats: true stats_config: use_all_default_tags: true stats_tags: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/volumes.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/volumes.yaml index 3e6429df11..a565c83350 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/volumes.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/volumes.yaml @@ -59,6 +59,8 @@ spec: node: locality: zone: $(ENVOY_SERVICE_ZONE) + deferredStatOptions: + enableDeferredCreationStats: true stats_config: use_all_default_tags: true stats_tags: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-annotations.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-annotations.yaml index 88a589c337..df23527772 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-annotations.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-annotations.yaml @@ -64,6 +64,8 @@ spec: node: locality: zone: $(ENVOY_SERVICE_ZONE) + deferredStatOptions: + enableDeferredCreationStats: true stats_config: use_all_default_tags: true stats_tags: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-extra-args.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-extra-args.yaml index 1c4291c0c7..7825f45168 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-extra-args.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-extra-args.yaml @@ -59,6 +59,8 @@ spec: node: locality: zone: $(ENVOY_SERVICE_ZONE) + deferredStatOptions: + enableDeferredCreationStats: true stats_config: use_all_default_tags: true stats_tags: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-image-pull-secrets.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-image-pull-secrets.yaml index 588bf45956..0997fa5a45 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-image-pull-secrets.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-image-pull-secrets.yaml @@ -59,6 +59,8 @@ spec: node: locality: zone: $(ENVOY_SERVICE_ZONE) + deferredStatOptions: + enableDeferredCreationStats: true stats_config: use_all_default_tags: true stats_tags: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-name.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-name.yaml index be6c6ae538..44a52f58d1 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-name.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-name.yaml @@ -59,6 +59,8 @@ spec: node: locality: zone: $(ENVOY_SERVICE_ZONE) + deferredStatOptions: + enableDeferredCreationStats: true stats_config: use_all_default_tags: true stats_tags: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-node-selector.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-node-selector.yaml index 46745daad3..a5fe07a19b 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-node-selector.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-node-selector.yaml @@ -59,6 +59,8 @@ spec: node: locality: zone: $(ENVOY_SERVICE_ZONE) + deferredStatOptions: + enableDeferredCreationStats: true stats_config: use_all_default_tags: true stats_tags: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-priority-class-name.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-priority-class-name.yaml index 8189fb4c14..3b39a47f9f 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-priority-class-name.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-priority-class-name.yaml @@ -59,6 +59,8 @@ spec: node: locality: zone: $(ENVOY_SERVICE_ZONE) + deferredStatOptions: + enableDeferredCreationStats: true stats_config: use_all_default_tags: true stats_tags: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-topology-spread-constraints.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-topology-spread-constraints.yaml index a785a381d0..4a24aed510 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-topology-spread-constraints.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-topology-spread-constraints.yaml @@ -59,6 +59,8 @@ spec: node: locality: zone: $(ENVOY_SERVICE_ZONE) + deferredStatOptions: + enableDeferredCreationStats: true stats_config: use_all_default_tags: true stats_tags: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/custom-sa.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/custom-sa.yaml index 5868f58525..2d2a2d7192 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/custom-sa.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/custom-sa.yaml @@ -66,6 +66,8 @@ spec: node: locality: zone: $(ENVOY_SERVICE_ZONE) + deferredStatOptions: + enableDeferredCreationStats: true stats_config: use_all_default_tags: true stats_tags: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/custom.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/custom.yaml index 98b4033ac7..b4490cd918 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/custom.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/custom.yaml @@ -65,6 +65,8 @@ spec: node: locality: zone: $(ENVOY_SERVICE_ZONE) + deferredStatOptions: + enableDeferredCreationStats: true stats_config: use_all_default_tags: true stats_tags: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/custom_with_initcontainers.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/custom_with_initcontainers.yaml index cad31cfb09..e2743d6755 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/custom_with_initcontainers.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/custom_with_initcontainers.yaml @@ -65,6 +65,8 @@ spec: node: locality: zone: $(ENVOY_SERVICE_ZONE) + deferredStatOptions: + enableDeferredCreationStats: true stats_config: use_all_default_tags: true stats_tags: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/default-env.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/default-env.yaml index 0e5b2c5dbc..8aa34a75f6 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/default-env.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/default-env.yaml @@ -64,6 +64,8 @@ spec: node: locality: zone: $(ENVOY_SERVICE_ZONE) + deferredStatOptions: + enableDeferredCreationStats: true stats_config: use_all_default_tags: true stats_tags: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/default.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/default.yaml index a93c49ee50..53167ee716 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/default.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/default.yaml @@ -63,6 +63,8 @@ spec: node: locality: zone: $(ENVOY_SERVICE_ZONE) + deferredStatOptions: + enableDeferredCreationStats: true stats_config: use_all_default_tags: true stats_tags: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/disable-prometheus.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/disable-prometheus.yaml index a7d8ef85f6..bf09b86a9e 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/disable-prometheus.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/disable-prometheus.yaml @@ -59,6 +59,8 @@ spec: node: locality: zone: $(ENVOY_SERVICE_ZONE) + deferredStatOptions: + enableDeferredCreationStats: true stats_config: use_all_default_tags: true stats_tags: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/dual-stack.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/dual-stack.yaml index c96f510d00..fe48b997ce 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/dual-stack.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/dual-stack.yaml @@ -63,6 +63,8 @@ spec: node: locality: zone: $(ENVOY_SERVICE_ZONE) + deferredStatOptions: + enableDeferredCreationStats: true stats_config: use_all_default_tags: true stats_tags: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/extension-env.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/extension-env.yaml index 6d28282d2f..b078c0570b 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/extension-env.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/extension-env.yaml @@ -64,6 +64,8 @@ spec: node: locality: zone: $(ENVOY_SERVICE_ZONE) + deferredStatOptions: + enableDeferredCreationStats: true stats_config: use_all_default_tags: true stats_tags: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/gateway-namespace-mode.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/gateway-namespace-mode.yaml index 0293370ae7..4c2640ff98 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/gateway-namespace-mode.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/gateway-namespace-mode.yaml @@ -66,6 +66,8 @@ spec: node: locality: zone: $(ENVOY_SERVICE_ZONE) + deferredStatOptions: + enableDeferredCreationStats: true stats_config: use_all_default_tags: true stats_tags: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/ipv6.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/ipv6.yaml index ae8f64b489..440a58f6cf 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/ipv6.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/ipv6.yaml @@ -63,6 +63,8 @@ spec: node: locality: zone: $(ENVOY_SERVICE_ZONE) + deferredStatOptions: + enableDeferredCreationStats: true stats_config: use_all_default_tags: true stats_tags: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/override-labels-and-annotations.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/override-labels-and-annotations.yaml index ea7b29aaa3..8a27bf16fb 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/override-labels-and-annotations.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/override-labels-and-annotations.yaml @@ -72,6 +72,8 @@ spec: node: locality: zone: $(ENVOY_SERVICE_ZONE) + deferredStatOptions: + enableDeferredCreationStats: true stats_config: use_all_default_tags: true stats_tags: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/override-prometheus-annotations.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/override-prometheus-annotations.yaml index db3abf75f3..7486149193 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/override-prometheus-annotations.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/override-prometheus-annotations.yaml @@ -65,6 +65,8 @@ spec: node: locality: zone: $(ENVOY_SERVICE_ZONE) + deferredStatOptions: + enableDeferredCreationStats: true stats_config: use_all_default_tags: true stats_tags: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/patch-deployment.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/patch-deployment.yaml index 543023e906..eb51dbeb9e 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/patch-deployment.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/patch-deployment.yaml @@ -63,6 +63,8 @@ spec: node: locality: zone: $(ENVOY_SERVICE_ZONE) + deferredStatOptions: + enableDeferredCreationStats: true stats_config: use_all_default_tags: true stats_tags: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/shutdown-manager.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/shutdown-manager.yaml index 9f2e1fba80..7bbb78abbf 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/shutdown-manager.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/shutdown-manager.yaml @@ -63,6 +63,8 @@ spec: node: locality: zone: $(ENVOY_SERVICE_ZONE) + deferredStatOptions: + enableDeferredCreationStats: true stats_config: use_all_default_tags: true stats_tags: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/volumes.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/volumes.yaml index 0514b52039..d7303a8bf5 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/volumes.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/volumes.yaml @@ -64,6 +64,8 @@ spec: node: locality: zone: $(ENVOY_SERVICE_ZONE) + deferredStatOptions: + enableDeferredCreationStats: true stats_config: use_all_default_tags: true stats_tags: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-annotations.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-annotations.yaml index 30a85adb0a..228a17e8b4 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-annotations.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-annotations.yaml @@ -68,6 +68,8 @@ spec: node: locality: zone: $(ENVOY_SERVICE_ZONE) + deferredStatOptions: + enableDeferredCreationStats: true stats_config: use_all_default_tags: true stats_tags: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-empty-memory-limits.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-empty-memory-limits.yaml index 7e5096bb3f..e70aedcfe8 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-empty-memory-limits.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-empty-memory-limits.yaml @@ -63,6 +63,8 @@ spec: node: locality: zone: $(ENVOY_SERVICE_ZONE) + deferredStatOptions: + enableDeferredCreationStats: true stats_config: use_all_default_tags: true stats_tags: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-extra-args.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-extra-args.yaml index a6e749953a..b7190b38cf 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-extra-args.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-extra-args.yaml @@ -63,6 +63,8 @@ spec: node: locality: zone: $(ENVOY_SERVICE_ZONE) + deferredStatOptions: + enableDeferredCreationStats: true stats_config: use_all_default_tags: true stats_tags: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-image-pull-secrets.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-image-pull-secrets.yaml index d2d39bb446..a19e0e64b5 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-image-pull-secrets.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-image-pull-secrets.yaml @@ -63,6 +63,8 @@ spec: node: locality: zone: $(ENVOY_SERVICE_ZONE) + deferredStatOptions: + enableDeferredCreationStats: true stats_config: use_all_default_tags: true stats_tags: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-name.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-name.yaml index f3947f072c..ac279255cc 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-name.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-name.yaml @@ -63,6 +63,8 @@ spec: node: locality: zone: $(ENVOY_SERVICE_ZONE) + deferredStatOptions: + enableDeferredCreationStats: true stats_config: use_all_default_tags: true stats_tags: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-node-selector.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-node-selector.yaml index 9e7627a3d7..fcbfea7d57 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-node-selector.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-node-selector.yaml @@ -63,6 +63,8 @@ spec: node: locality: zone: $(ENVOY_SERVICE_ZONE) + deferredStatOptions: + enableDeferredCreationStats: true stats_config: use_all_default_tags: true stats_tags: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-priority-class-name.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-priority-class-name.yaml index bb7960aabd..ce108fd5f4 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-priority-class-name.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-priority-class-name.yaml @@ -63,6 +63,8 @@ spec: node: locality: zone: $(ENVOY_SERVICE_ZONE) + deferredStatOptions: + enableDeferredCreationStats: true stats_config: use_all_default_tags: true stats_tags: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-topology-spread-constraints.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-topology-spread-constraints.yaml index 91a9e6533b..97a5984e26 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-topology-spread-constraints.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-topology-spread-constraints.yaml @@ -63,6 +63,8 @@ spec: node: locality: zone: $(ENVOY_SERVICE_ZONE) + deferredStatOptions: + enableDeferredCreationStats: true stats_config: use_all_default_tags: true stats_tags: diff --git a/internal/infrastructure/kubernetes/proxy/testdata/gateway-namespace-mode/deployment.yaml b/internal/infrastructure/kubernetes/proxy/testdata/gateway-namespace-mode/deployment.yaml index 4d8d13f7e3..a92130021d 100644 --- a/internal/infrastructure/kubernetes/proxy/testdata/gateway-namespace-mode/deployment.yaml +++ b/internal/infrastructure/kubernetes/proxy/testdata/gateway-namespace-mode/deployment.yaml @@ -66,6 +66,8 @@ spec: node: locality: zone: $(ENVOY_SERVICE_ZONE) + deferredStatOptions: + enableDeferredCreationStats: true stats_config: use_all_default_tags: true stats_tags: @@ -499,6 +501,8 @@ spec: node: locality: zone: $(ENVOY_SERVICE_ZONE) + deferredStatOptions: + enableDeferredCreationStats: true stats_config: use_all_default_tags: true stats_tags: diff --git a/internal/infrastructure/runner/runner.go b/internal/infrastructure/runner/runner.go index 2b031e8a12..bb5f19db78 100644 --- a/internal/infrastructure/runner/runner.go +++ b/internal/infrastructure/runner/runner.go @@ -108,6 +108,7 @@ func (r *Runner) updateProxyInfraFromSubscription(ctx context.Context, sub <-cha default: } r.Logger.Info("received an update", "key", update.Key, "delete", update.Delete) + message.PublishRunnerEventMetric(r.Name(), update.Delete) val := update.Value if update.Delete { diff --git a/internal/ir/xds.go b/internal/ir/xds.go index 9a1c7e91b3..54bf7096db 100644 --- a/internal/ir/xds.go +++ b/internal/ir/xds.go @@ -69,7 +69,6 @@ var ( ErrHealthCheckUnhealthyThresholdInvalid = errors.New("field HealthCheck.UnhealthyThreshold should be greater than 0") ErrHealthCheckHealthyThresholdInvalid = errors.New("field HealthCheck.HealthyThreshold should be greater than 0") ErrHealthCheckerInvalid = errors.New("health checker setting is invalid, only one health checker can be set") - ErrHCHTTPHostInvalid = errors.New("field HTTPHealthChecker.Host should be specified") ErrHCHTTPPathInvalid = errors.New("field HTTPHealthChecker.Path should be specified") ErrHCHTTPMethodInvalid = errors.New("only one of the GET, HEAD, POST, DELETE, OPTIONS, TRACE, PATCH of HTTPHealthChecker.Method could be set") ErrHCHTTPExpectedStatusesInvalid = errors.New("field HTTPHealthChecker.ExpectedStatuses should be specified") @@ -299,8 +298,8 @@ type HTTPListener struct { Hostnames []string `json:"hostnames" yaml:"hostnames"` // Tls configuration. If omitted, the gateway will expose a plain text HTTP server. TLS *TLSConfig `json:"tls,omitempty" yaml:"tls,omitempty"` - // TLSOverlaps indicates if the listener has TLS configuration that overlaps with other listeners. - // HTTP2 should be disabled if this is true to avoid the HTTP/2 Connection Coalescing issue (see https://gateway-api.sigs.k8s.io/geps/gep-3567/) + // TLSOverlaps indicates if the listener's certificate SANs overlap with another listener's certificate SANs. + // HTTP/2 should be disabled if this is true to avoid the HTTP/2 Connection Coalescing issue (see https://gateway-api.sigs.k8s.io/geps/gep-3567/) // We use a standalone field to avoid messing with the ClientTrafficPolicy ALPN config. TLSOverlaps bool `json:"tlsOverlaps,omitempty" yaml:"tlsOverlaps,omitempty"` // Routes associated with HTTP traffic to the service. @@ -3196,12 +3195,6 @@ type ActiveHealthCheck struct { Overrides *HealthCheckOverrides `json:"overrides,omitempty" yaml:"overrides,omitempty"` } -func (h *HealthCheck) SetHTTPHostIfAbsent(host string) { - if h != nil && h.Active != nil && h.Active.HTTP != nil && h.Active.HTTP.Host == "" { - h.Active.HTTP.Host = host - } -} - // Validate the fields within the HealthCheck structure. func (h *HealthCheck) Validate() error { var errs error @@ -3295,9 +3288,6 @@ type HTTPHealthChecker struct { // Validate the fields within the HTTPHealthChecker structure. func (c *HTTPHealthChecker) Validate() error { var errs error - if c.Host == "" { - errs = errors.Join(errs, ErrHCHTTPHostInvalid) - } if c.Path == "" { errs = errors.Join(errs, ErrHCHTTPPathInvalid) } diff --git a/internal/ir/xds_test.go b/internal/ir/xds_test.go index e1d4ecadb6..2114eb370b 100644 --- a/internal/ir/xds_test.go +++ b/internal/ir/xds_test.go @@ -1676,7 +1676,7 @@ func TestValidateHealthCheck(t *testing.T) { want: ErrHealthCheckHealthyThresholdInvalid, }, { - name: "http-health-check: invalid host", + name: "http-health-check: empty host", input: HealthCheck{ &ActiveHealthCheck{ Timeout: MetaV1DurationPtr(time.Second), @@ -1692,7 +1692,6 @@ func TestValidateHealthCheck(t *testing.T) { &OutlierDetection{}, new(uint32(10)), }, - want: ErrHCHTTPHostInvalid, }, { name: "http-health-check: invalid path", diff --git a/internal/message/metrics.go b/internal/message/metrics.go index c4127e7bfa..c6fe385392 100644 --- a/internal/message/metrics.go +++ b/internal/message/metrics.go @@ -34,6 +34,12 @@ var ( "Total number of published updates to watchable queue.", ) - runnerLabel = metrics.NewLabel("runner") - messageLabel = metrics.NewLabel("message") + watchableEventTotal = metrics.NewCounter( + "watchable_event_total", + "Total number of runner events.", + ) + + runnerLabel = metrics.NewLabel("runner") + messageLabel = metrics.NewLabel("message") + runnerEventTypeLabel = metrics.NewLabel("event_type") ) diff --git a/internal/message/watchutil.go b/internal/message/watchutil.go index ac0d6990b6..1f69202731 100644 --- a/internal/message/watchutil.go +++ b/internal/message/watchutil.go @@ -27,6 +27,17 @@ func PublishMetric(meta Metadata, count int) { watchablePublishTotal.WithSuccess(meta.LabelValues()...).Add(float64(count)) } +func PublishRunnerEventMetric(runnerName string, isDelete bool) { + eventType := "update" + if isDelete { + eventType = "delete" + } + watchableEventTotal.With( + runnerEventTypeLabel.Value(eventType), + runnerLabel.Value(runnerName), + ).Add(1) +} + func (m Metadata) LabelValues() []metrics.LabelValue { labels := make([]metrics.LabelValue, 0, 2) if m.Runner != "" { diff --git a/internal/utils/merge_test.go b/internal/utils/merge_test.go index 73f6a584c9..2c91e27bcd 100644 --- a/internal/utils/merge_test.go +++ b/internal/utils/merge_test.go @@ -19,41 +19,55 @@ import ( "github.com/envoyproxy/gateway/internal/utils/test" ) -func TestMergeBackendTrafficPolicy(t *testing.T) { +func TestMergePolicy(t *testing.T) { baseDir := "testdata" - caseFiles, err := filepath.Glob(filepath.Join(baseDir, "backendtrafficpolicy_*.in.yaml")) + caseFiles, err := filepath.Glob(filepath.Join(baseDir, "*policy_*.in.yaml")) require.NoError(t, err) for _, caseFile := range caseFiles { - // get case name from path - caseName := strings.TrimPrefix(strings.TrimSuffix(caseFile, ".in.yaml"), baseDir+"/backendtrafficpolicy_") + caseName := strings.TrimPrefix(strings.TrimSuffix(caseFile, ".in.yaml"), baseDir+"/") + policyType := strings.SplitN(caseName, "_", 2)[0] + t.Run(caseName, func(t *testing.T) { - for _, mergeType := range []egv1a1.MergeType{egv1a1.StrategicMerge, egv1a1.JSONMerge} { - patchedInput := strings.Replace(caseFile, ".in.yaml", ".patch.yaml", 1) - var output string - if mergeType == egv1a1.StrategicMerge { - output = strings.Replace(caseFile, ".in.yaml", ".strategicmerge.out.yaml", 1) - } else { - output = strings.Replace(caseFile, ".in.yaml", ".jsonmerge.out.yaml", 1) - } + switch policyType { + case "backendtrafficpolicy": + runMergePolicyTest[*egv1a1.BackendTrafficPolicy](t, caseFile) + case "securitypolicy": + runMergePolicyTest[*egv1a1.SecurityPolicy](t, caseFile) + default: + t.Fatalf("unsupported policy type %q in %s", policyType, caseFile) + } + }) + } +} - original := readObject[*egv1a1.BackendTrafficPolicy](t, caseFile) - patch := readObject[*egv1a1.BackendTrafficPolicy](t, patchedInput) +func runMergePolicyTest[T client.Object](t *testing.T, caseFile string) { + t.Helper() - got, err := Merge(original, patch, mergeType) - require.NoError(t, err) + for _, mergeType := range []egv1a1.MergeType{egv1a1.StrategicMerge, egv1a1.JSONMerge} { + patchedInput := strings.Replace(caseFile, ".in.yaml", ".patch.yaml", 1) + var output string + if mergeType == egv1a1.StrategicMerge { + output = strings.Replace(caseFile, ".in.yaml", ".strategicmerge.out.yaml", 1) + } else { + output = strings.Replace(caseFile, ".in.yaml", ".jsonmerge.out.yaml", 1) + } - if test.OverrideTestData() { - b, err := yaml.Marshal(got) - require.NoError(t, err) - require.NoError(t, os.WriteFile(output, b, 0o600)) - continue - } + original := readObject[T](t, caseFile) + patch := readObject[T](t, patchedInput) - expected := readObject[*egv1a1.BackendTrafficPolicy](t, output) - require.Equal(t, expected, got) - } - }) + got, err := Merge(original, patch, mergeType) + require.NoError(t, err) + + if test.OverrideTestData() { + b, err := yaml.Marshal(got) + require.NoError(t, err) + require.NoError(t, os.WriteFile(output, b, 0o600)) + continue + } + + expected := readObject[T](t, output) + require.Equal(t, expected, got) } } diff --git a/internal/utils/testdata/securitypolicy_all.in.yaml b/internal/utils/testdata/securitypolicy_all.in.yaml new file mode 100644 index 0000000000..2524a7a0f9 --- /dev/null +++ b/internal/utils/testdata/securitypolicy_all.in.yaml @@ -0,0 +1,49 @@ +apiVersion: gateway.envoyproxy.io/v1alpha1 +kind: SecurityPolicy +metadata: + name: original +spec: + basicAuth: + users: + name: users-parent + apiKeyAuth: + credentialRefs: + - name: api-keys-parent + authorization: + rules: + - name: parent-rule + action: Allow + principal: + headers: + - name: x-role + values: + - parent + extAuth: + http: + backendRefs: + - name: ext-auth-parent + port: 9001 + contextExtensions: + - name: shared + type: Value + value: parent + - name: parent-only + type: Value + value: parent-only + oidc: + provider: + issuer: https://oidc.parent.example.com + backendRefs: + - name: oidc-parent + port: 443 + clientIDRef: + name: oidc-client-id-parent + clientSecret: + name: oidc-client-secret-parent + jwt: + providers: + - name: jwt-parent + issuer: https://issuer.parent.example.com + localJWKS: + type: Inline + inline: "{}" diff --git a/internal/utils/testdata/securitypolicy_all.jsonmerge.out.yaml b/internal/utils/testdata/securitypolicy_all.jsonmerge.out.yaml new file mode 100644 index 0000000000..eeb4cb0d16 --- /dev/null +++ b/internal/utils/testdata/securitypolicy_all.jsonmerge.out.yaml @@ -0,0 +1,58 @@ +apiVersion: gateway.envoyproxy.io/v1alpha1 +kind: SecurityPolicy +metadata: + name: patched +spec: + apiKeyAuth: + credentialRefs: + - name: api-keys-route + extractFrom: null + sanitize: true + authorization: + defaultAction: null + rules: + - action: Deny + name: route-rule + principal: + headers: + - name: x-role + values: + - route + basicAuth: + users: + name: users-route + extAuth: + contextExtensions: + - name: shared + type: Value + value: route + - name: route-only + type: Value + value: route-only + grpc: + backendRefs: + - name: ext-auth-route + port: 9002 + http: + backendRefs: + - name: ext-auth-parent + port: 9001 + jwt: + providers: + - issuer: https://issuer.route.example.com + localJWKS: + inline: '{}' + type: Inline + name: jwt-route + oidc: + clientIDRef: + name: oidc-client-id-route + clientSecret: + name: oidc-client-secret-route + provider: + backendRefs: + - name: oidc-route + port: 8443 + issuer: "" +status: + ancestors: null diff --git a/internal/utils/testdata/securitypolicy_all.patch.yaml b/internal/utils/testdata/securitypolicy_all.patch.yaml new file mode 100644 index 0000000000..fcee7aca7d --- /dev/null +++ b/internal/utils/testdata/securitypolicy_all.patch.yaml @@ -0,0 +1,50 @@ +apiVersion: gateway.envoyproxy.io/v1alpha1 +kind: SecurityPolicy +metadata: + name: patched +spec: + basicAuth: + users: + name: users-route + apiKeyAuth: + credentialRefs: + - name: api-keys-route + sanitize: true + authorization: + rules: + - name: route-rule + action: Deny + principal: + headers: + - name: x-role + values: + - route + extAuth: + grpc: + backendRefs: + - name: ext-auth-route + port: 9002 + # arrays all replace + contextExtensions: + - name: shared + type: Value + value: route + - name: route-only + type: Value + value: route-only + oidc: + provider: + backendRefs: + - name: oidc-route + port: 8443 + clientIDRef: + name: oidc-client-id-route + clientSecret: + name: oidc-client-secret-route + jwt: + providers: + - name: jwt-route + issuer: https://issuer.route.example.com + localJWKS: + type: Inline + inline: "{}" diff --git a/internal/utils/testdata/securitypolicy_all.strategicmerge.out.yaml b/internal/utils/testdata/securitypolicy_all.strategicmerge.out.yaml new file mode 100644 index 0000000000..8eeabc5212 --- /dev/null +++ b/internal/utils/testdata/securitypolicy_all.strategicmerge.out.yaml @@ -0,0 +1,61 @@ +apiVersion: gateway.envoyproxy.io/v1alpha1 +kind: SecurityPolicy +metadata: + name: patched +spec: + apiKeyAuth: + credentialRefs: + - name: api-keys-route + extractFrom: null + sanitize: true + authorization: + defaultAction: null + rules: + - action: Deny + name: route-rule + principal: + headers: + - name: x-role + values: + - route + basicAuth: + users: + name: users-route + extAuth: + contextExtensions: + - name: shared + type: Value + value: route + - name: route-only + type: Value + value: route-only + - name: parent-only + type: Value + value: parent-only + grpc: + backendRefs: + - name: ext-auth-route + port: 9002 + http: + backendRefs: + - name: ext-auth-parent + port: 9001 + jwt: + providers: + - issuer: https://issuer.route.example.com + localJWKS: + inline: '{}' + type: Inline + name: jwt-route + oidc: + clientIDRef: + name: oidc-client-id-route + clientSecret: + name: oidc-client-secret-route + provider: + backendRefs: + - name: oidc-route + port: 8443 + issuer: "" +status: + ancestors: null diff --git a/internal/xds/bootstrap/bootstrap.yaml.tpl b/internal/xds/bootstrap/bootstrap.yaml.tpl index 1c1c07ce53..3ce7131d88 100644 --- a/internal/xds/bootstrap/bootstrap.yaml.tpl +++ b/internal/xds/bootstrap/bootstrap.yaml.tpl @@ -15,6 +15,8 @@ cluster_manager: node: locality: zone: $(ENVOY_SERVICE_ZONE) +deferredStatOptions: + enableDeferredCreationStats: true stats_config: use_all_default_tags: true stats_tags: diff --git a/internal/xds/bootstrap/testdata/merge/default.out.yaml b/internal/xds/bootstrap/testdata/merge/default.out.yaml index 233616d086..e077a489cc 100644 --- a/internal/xds/bootstrap/testdata/merge/default.out.yaml +++ b/internal/xds/bootstrap/testdata/merge/default.out.yaml @@ -10,6 +10,8 @@ admin: port_value: 20000 cluster_manager: local_cluster_name: local_cluster +deferred_stat_options: + enable_deferred_creation_stats: true dynamic_resources: ads_config: api_type: DELTA_GRPC diff --git a/internal/xds/bootstrap/testdata/merge/merge-user-bootstrap.out.yaml b/internal/xds/bootstrap/testdata/merge/merge-user-bootstrap.out.yaml index ccb594eaad..c147788996 100644 --- a/internal/xds/bootstrap/testdata/merge/merge-user-bootstrap.out.yaml +++ b/internal/xds/bootstrap/testdata/merge/merge-user-bootstrap.out.yaml @@ -10,6 +10,8 @@ admin: port_value: 8080 cluster_manager: local_cluster_name: local_cluster +deferred_stat_options: + enable_deferred_creation_stats: true dynamic_resources: ads_config: api_type: DELTA_GRPC diff --git a/internal/xds/bootstrap/testdata/merge/patch-global-config.out.yaml b/internal/xds/bootstrap/testdata/merge/patch-global-config.out.yaml index 15d248b75b..c6baee4ed8 100644 --- a/internal/xds/bootstrap/testdata/merge/patch-global-config.out.yaml +++ b/internal/xds/bootstrap/testdata/merge/patch-global-config.out.yaml @@ -10,6 +10,8 @@ admin: port_value: 19000 cluster_manager: local_cluster_name: local_cluster +deferredStatOptions: + enableDeferredCreationStats: true dynamic_resources: ads_config: api_type: DELTA_GRPC diff --git a/internal/xds/bootstrap/testdata/merge/stats_sinks.out.yaml b/internal/xds/bootstrap/testdata/merge/stats_sinks.out.yaml index f03f95d6bc..6ebb53bcf7 100644 --- a/internal/xds/bootstrap/testdata/merge/stats_sinks.out.yaml +++ b/internal/xds/bootstrap/testdata/merge/stats_sinks.out.yaml @@ -10,6 +10,8 @@ admin: port_value: 19000 cluster_manager: local_cluster_name: local_cluster +deferred_stat_options: + enable_deferred_creation_stats: true dynamic_resources: ads_config: api_type: DELTA_GRPC diff --git a/internal/xds/bootstrap/testdata/render/custom-server-port.yaml b/internal/xds/bootstrap/testdata/render/custom-server-port.yaml index 2ee07fc73a..07c83680dd 100644 --- a/internal/xds/bootstrap/testdata/render/custom-server-port.yaml +++ b/internal/xds/bootstrap/testdata/render/custom-server-port.yaml @@ -13,6 +13,8 @@ cluster_manager: node: locality: zone: $(ENVOY_SERVICE_ZONE) +deferredStatOptions: + enableDeferredCreationStats: true stats_config: use_all_default_tags: true stats_tags: diff --git a/internal/xds/bootstrap/testdata/render/custom-stats-matcher.yaml b/internal/xds/bootstrap/testdata/render/custom-stats-matcher.yaml index dc1f6a4eb4..4449620532 100644 --- a/internal/xds/bootstrap/testdata/render/custom-stats-matcher.yaml +++ b/internal/xds/bootstrap/testdata/render/custom-stats-matcher.yaml @@ -13,6 +13,8 @@ cluster_manager: node: locality: zone: $(ENVOY_SERVICE_ZONE) +deferredStatOptions: + enableDeferredCreationStats: true stats_config: use_all_default_tags: true stats_tags: diff --git a/internal/xds/bootstrap/testdata/render/disable-prometheus.yaml b/internal/xds/bootstrap/testdata/render/disable-prometheus.yaml index 527784eb06..3fd0df98ff 100644 --- a/internal/xds/bootstrap/testdata/render/disable-prometheus.yaml +++ b/internal/xds/bootstrap/testdata/render/disable-prometheus.yaml @@ -13,6 +13,8 @@ cluster_manager: node: locality: zone: $(ENVOY_SERVICE_ZONE) +deferredStatOptions: + enableDeferredCreationStats: true stats_config: use_all_default_tags: true stats_tags: diff --git a/internal/xds/bootstrap/testdata/render/enable-prometheus-brotli-compression.yaml b/internal/xds/bootstrap/testdata/render/enable-prometheus-brotli-compression.yaml index 887846c1fc..c6b2f9124e 100644 --- a/internal/xds/bootstrap/testdata/render/enable-prometheus-brotli-compression.yaml +++ b/internal/xds/bootstrap/testdata/render/enable-prometheus-brotli-compression.yaml @@ -13,6 +13,8 @@ cluster_manager: node: locality: zone: $(ENVOY_SERVICE_ZONE) +deferredStatOptions: + enableDeferredCreationStats: true stats_config: use_all_default_tags: true stats_tags: diff --git a/internal/xds/bootstrap/testdata/render/enable-prometheus-gzip-compression.yaml b/internal/xds/bootstrap/testdata/render/enable-prometheus-gzip-compression.yaml index ae7bed5578..ba6377862f 100644 --- a/internal/xds/bootstrap/testdata/render/enable-prometheus-gzip-compression.yaml +++ b/internal/xds/bootstrap/testdata/render/enable-prometheus-gzip-compression.yaml @@ -13,6 +13,8 @@ cluster_manager: node: locality: zone: $(ENVOY_SERVICE_ZONE) +deferredStatOptions: + enableDeferredCreationStats: true stats_config: use_all_default_tags: true stats_tags: diff --git a/internal/xds/bootstrap/testdata/render/enable-prometheus-zstd-compression.yaml b/internal/xds/bootstrap/testdata/render/enable-prometheus-zstd-compression.yaml index b584011240..573a8b8970 100644 --- a/internal/xds/bootstrap/testdata/render/enable-prometheus-zstd-compression.yaml +++ b/internal/xds/bootstrap/testdata/render/enable-prometheus-zstd-compression.yaml @@ -13,6 +13,8 @@ cluster_manager: node: locality: zone: $(ENVOY_SERVICE_ZONE) +deferredStatOptions: + enableDeferredCreationStats: true stats_config: use_all_default_tags: true stats_tags: diff --git a/internal/xds/bootstrap/testdata/render/enable-prometheus.yaml b/internal/xds/bootstrap/testdata/render/enable-prometheus.yaml index 846533b79e..73aa82ea46 100644 --- a/internal/xds/bootstrap/testdata/render/enable-prometheus.yaml +++ b/internal/xds/bootstrap/testdata/render/enable-prometheus.yaml @@ -13,6 +13,8 @@ cluster_manager: node: locality: zone: $(ENVOY_SERVICE_ZONE) +deferredStatOptions: + enableDeferredCreationStats: true stats_config: use_all_default_tags: true stats_tags: diff --git a/internal/xds/bootstrap/testdata/render/ipv6.yaml b/internal/xds/bootstrap/testdata/render/ipv6.yaml index d9a1b966a1..714f65bc84 100644 --- a/internal/xds/bootstrap/testdata/render/ipv6.yaml +++ b/internal/xds/bootstrap/testdata/render/ipv6.yaml @@ -13,6 +13,8 @@ cluster_manager: node: locality: zone: $(ENVOY_SERVICE_ZONE) +deferredStatOptions: + enableDeferredCreationStats: true stats_config: use_all_default_tags: true stats_tags: diff --git a/internal/xds/bootstrap/testdata/render/otel-metrics-backendref.yaml b/internal/xds/bootstrap/testdata/render/otel-metrics-backendref.yaml index 8c250afc61..4723cbae86 100644 --- a/internal/xds/bootstrap/testdata/render/otel-metrics-backendref.yaml +++ b/internal/xds/bootstrap/testdata/render/otel-metrics-backendref.yaml @@ -13,6 +13,8 @@ cluster_manager: node: locality: zone: $(ENVOY_SERVICE_ZONE) +deferredStatOptions: + enableDeferredCreationStats: true stats_config: use_all_default_tags: true stats_tags: diff --git a/internal/xds/bootstrap/testdata/render/otel-metrics-custom-ca.yaml b/internal/xds/bootstrap/testdata/render/otel-metrics-custom-ca.yaml index 1ce524eb8b..0a81e308c9 100644 --- a/internal/xds/bootstrap/testdata/render/otel-metrics-custom-ca.yaml +++ b/internal/xds/bootstrap/testdata/render/otel-metrics-custom-ca.yaml @@ -13,6 +13,8 @@ cluster_manager: node: locality: zone: $(ENVOY_SERVICE_ZONE) +deferredStatOptions: + enableDeferredCreationStats: true stats_config: use_all_default_tags: true stats_tags: diff --git a/internal/xds/bootstrap/testdata/render/otel-metrics-delta-temporality.yaml b/internal/xds/bootstrap/testdata/render/otel-metrics-delta-temporality.yaml index d0457354e0..592e3a3d4a 100644 --- a/internal/xds/bootstrap/testdata/render/otel-metrics-delta-temporality.yaml +++ b/internal/xds/bootstrap/testdata/render/otel-metrics-delta-temporality.yaml @@ -13,6 +13,8 @@ cluster_manager: node: locality: zone: $(ENVOY_SERVICE_ZONE) +deferredStatOptions: + enableDeferredCreationStats: true stats_config: use_all_default_tags: true stats_tags: diff --git a/internal/xds/bootstrap/testdata/render/otel-metrics-headers.yaml b/internal/xds/bootstrap/testdata/render/otel-metrics-headers.yaml index 0b72c9fa0f..32d9e17500 100644 --- a/internal/xds/bootstrap/testdata/render/otel-metrics-headers.yaml +++ b/internal/xds/bootstrap/testdata/render/otel-metrics-headers.yaml @@ -13,6 +13,8 @@ cluster_manager: node: locality: zone: $(ENVOY_SERVICE_ZONE) +deferredStatOptions: + enableDeferredCreationStats: true stats_config: use_all_default_tags: true stats_tags: diff --git a/internal/xds/bootstrap/testdata/render/otel-metrics-tls.yaml b/internal/xds/bootstrap/testdata/render/otel-metrics-tls.yaml index dd58f54e80..43e07b5239 100644 --- a/internal/xds/bootstrap/testdata/render/otel-metrics-tls.yaml +++ b/internal/xds/bootstrap/testdata/render/otel-metrics-tls.yaml @@ -13,6 +13,8 @@ cluster_manager: node: locality: zone: $(ENVOY_SERVICE_ZONE) +deferredStatOptions: + enableDeferredCreationStats: true stats_config: use_all_default_tags: true stats_tags: diff --git a/internal/xds/bootstrap/testdata/render/otel-metrics.yaml b/internal/xds/bootstrap/testdata/render/otel-metrics.yaml index 8c250afc61..4723cbae86 100644 --- a/internal/xds/bootstrap/testdata/render/otel-metrics.yaml +++ b/internal/xds/bootstrap/testdata/render/otel-metrics.yaml @@ -13,6 +13,8 @@ cluster_manager: node: locality: zone: $(ENVOY_SERVICE_ZONE) +deferredStatOptions: + enableDeferredCreationStats: true stats_config: use_all_default_tags: true stats_tags: diff --git a/internal/xds/bootstrap/testdata/render/topology-injector-disabled.yaml b/internal/xds/bootstrap/testdata/render/topology-injector-disabled.yaml index 9791827250..62bbb840c0 100644 --- a/internal/xds/bootstrap/testdata/render/topology-injector-disabled.yaml +++ b/internal/xds/bootstrap/testdata/render/topology-injector-disabled.yaml @@ -11,6 +11,8 @@ admin: node: locality: zone: $(ENVOY_SERVICE_ZONE) +deferredStatOptions: + enableDeferredCreationStats: true stats_config: use_all_default_tags: true stats_tags: diff --git a/internal/xds/bootstrap/testdata/render/topology-injector-enabled.yaml b/internal/xds/bootstrap/testdata/render/topology-injector-enabled.yaml index 527784eb06..3fd0df98ff 100644 --- a/internal/xds/bootstrap/testdata/render/topology-injector-enabled.yaml +++ b/internal/xds/bootstrap/testdata/render/topology-injector-enabled.yaml @@ -13,6 +13,8 @@ cluster_manager: node: locality: zone: $(ENVOY_SERVICE_ZONE) +deferredStatOptions: + enableDeferredCreationStats: true stats_config: use_all_default_tags: true stats_tags: diff --git a/internal/xds/bootstrap/testdata/render/with-max-heap-size-bytes.yaml b/internal/xds/bootstrap/testdata/render/with-max-heap-size-bytes.yaml index 132da5aa46..3efccf6f50 100644 --- a/internal/xds/bootstrap/testdata/render/with-max-heap-size-bytes.yaml +++ b/internal/xds/bootstrap/testdata/render/with-max-heap-size-bytes.yaml @@ -13,6 +13,8 @@ cluster_manager: node: locality: zone: $(ENVOY_SERVICE_ZONE) +deferredStatOptions: + enableDeferredCreationStats: true stats_config: use_all_default_tags: true stats_tags: diff --git a/internal/xds/runner/runner.go b/internal/xds/runner/runner.go index e1ffc4d42d..48bbdb678e 100644 --- a/internal/xds/runner/runner.go +++ b/internal/xds/runner/runner.go @@ -263,6 +263,8 @@ func (r *Runner) translateFromSubscription(sub <-chan watchable.Snapshot[string, r.Logger, message.Metadata{Runner: r.Name(), Message: message.XDSIRMessageName}, sub, func(update message.Update[string, *message.XdsIRWithContext], errChan chan error) { + message.PublishRunnerEventMetric(r.Name(), update.Delete) + parentCtx := context.Background() if update.Value != nil && update.Value.Context != nil { parentCtx = update.Value.Context diff --git a/internal/xds/translator/cluster.go b/internal/xds/translator/cluster.go index 40249b03bb..b1534de16b 100644 --- a/internal/xds/translator/cluster.go +++ b/internal/xds/translator/cluster.go @@ -69,6 +69,7 @@ type xdsClusterArgs struct { proxyProtocol *ir.ProxyProtocol circuitBreaker *ir.CircuitBreaker healthCheck *ir.HealthCheck + routeHostname string http1Settings *ir.HTTP1Settings http2Settings *ir.HTTP2Settings timeout *ir.Timeout @@ -455,7 +456,7 @@ func buildXdsCluster(args *xdsClusterArgs) (*buildClusterResult, error) { } if args.healthCheck != nil && args.healthCheck.Active != nil { - cluster.HealthChecks = buildXdsHealthCheck(args.healthCheck.Active) + cluster.HealthChecks = buildXdsHealthCheck(args.healthCheck.Active, args.routeHostname) } if args.healthCheck != nil && args.healthCheck.Passive != nil { @@ -575,7 +576,7 @@ func buildZoneAwareLbConfig(preferLocal *ir.PreferLocalZone) *commonv3.LocalityL return lbConfig } -func buildXdsHealthCheck(healthcheck *ir.ActiveHealthCheck) []*corev3.HealthCheck { +func buildXdsHealthCheck(healthcheck *ir.ActiveHealthCheck, routeHostname string) []*corev3.HealthCheck { hc := &corev3.HealthCheck{ Timeout: durationpb.New(healthcheck.Timeout.Duration), Interval: durationpb.New(healthcheck.Interval.Duration), @@ -594,7 +595,7 @@ func buildXdsHealthCheck(healthcheck *ir.ActiveHealthCheck) []*corev3.HealthChec switch { case healthcheck.HTTP != nil: httpChecker := &corev3.HealthCheck_HttpHealthCheck{ - Host: healthcheck.HTTP.Host, + Host: httpHealthCheckHost(healthcheck.HTTP, routeHostname), Path: healthcheck.HTTP.Path, } if healthcheck.HTTP.Method != nil { @@ -628,6 +629,13 @@ func buildXdsHealthCheck(healthcheck *ir.ActiveHealthCheck) []*corev3.HealthChec return []*corev3.HealthCheck{hc} } +func httpHealthCheckHost(healthcheck *ir.HTTPHealthChecker, routeHostname string) string { + if healthcheck.Host != "" { + return healthcheck.Host + } + return routeHostname +} + func buildXdsOutlierDetection(outlierDetection *ir.OutlierDetection) *clusterv3.OutlierDetection { od := &clusterv3.OutlierDetection{ BaseEjectionTime: durationpb.New(outlierDetection.BaseEjectionTime.Duration), @@ -1005,10 +1013,9 @@ func getHealthCheckOverridesPort(hc *ir.HealthCheck) *uint32 { } func getHealthCheckOverridesHostname(hc *ir.HealthCheck, ep *ir.DestinationEndpoint) string { - // If Active Health Check has an explicit hostname override, it will be used on Cluster. - // Otherwise, if the endpoint has a hostname, set the hostname on the EndpointHealthCheckConfig - // so that Envoy can use it for health checking. - // Note: The "*" wildcard is not an explicit user-provided hostname + // If active HTTP health check has an explicit hostname override, keep that + // cluster-level host. Route hostname is only a default, so Backend endpoint + // hostname can still override it through EndpointHealthCheckConfig. if hc.Active.HTTP != nil && hc.Active.HTTP.Host != "" && hc.Active.HTTP.Host != "*" { return "" } @@ -1417,6 +1424,7 @@ func (httpRoute *HTTPRouteTranslator) asClusterArgs(name string, settings: settings, tSocket: nil, endpointType: buildEndpointType(settings), + routeHostname: httpRoute.Hostname, metrics: extra.metrics, http1Settings: extra.http1Settings, http2Settings: extra.http2Settings, diff --git a/internal/xds/translator/testdata/in/xds-ir/health-check-host-hierarchy.yaml b/internal/xds/translator/testdata/in/xds-ir/health-check-host-hierarchy.yaml new file mode 100644 index 0000000000..7a3ce9243a --- /dev/null +++ b/internal/xds/translator/testdata/in/xds-ir/health-check-host-hierarchy.yaml @@ -0,0 +1,88 @@ +# Health check Host header hierarchy: +# 1. Explicit BackendTrafficPolicy hostname is a cluster-level health check host. +# 2. Backend endpoint hostname is emitted as Endpoint.HealthCheckConfig.hostname +# when the cluster-level host was only defaulted from the effective route +# hostname for the listener. +# 3. Effective route hostname stays as the cluster-level fallback when no +# endpoint hostname exists. +http: +- name: health-check-host-hierarchy-listener + address: "::" + path: + mergeSlashes: true + escapedSlashesAction: UnescapeAndRedirect + port: 10080 + hostnames: + - "*" + routes: + - name: btp-host-route + hostname: btp-route.example.com + traffic: + healthCheck: + active: + timeout: 2s + interval: 5s + healthyThreshold: 1 + unhealthyThreshold: 3 + http: + host: btp-health.example.com + path: /healthz + method: GET + expectedStatuses: + - 200 + destination: + name: btp-host-route-dest + settings: + - name: btp-host-route-dest/backend/0 + addressType: FQDN + endpoints: + - host: backend-address.example.com + hostname: backend-endpoint.example.com + port: 443 + - name: backend-host-route + hostname: backend-route.example.com + traffic: + healthCheck: + active: + timeout: 2s + interval: 5s + healthyThreshold: 1 + unhealthyThreshold: 3 + http: + host: "" + path: /healthz + method: GET + expectedStatuses: + - 200 + destination: + name: backend-host-route-dest + settings: + - name: backend-host-route-dest/backend/0 + addressType: FQDN + endpoints: + - host: backend-address.example.com + hostname: backend-endpoint.example.com + port: 443 + - name: route-host-route + hostname: route-fallback.example.com + traffic: + healthCheck: + active: + timeout: 2s + interval: 5s + healthyThreshold: 1 + unhealthyThreshold: 3 + http: + host: "" + path: /healthz + method: GET + expectedStatuses: + - 200 + destination: + name: route-host-route-dest + settings: + - name: route-host-route-dest/backend/0 + addressType: FQDN + endpoints: + - host: backend-no-endpoint-host.example.com + port: 443 diff --git a/internal/xds/translator/testdata/out/xds-ir/health-check-host-hierarchy.clusters.yaml b/internal/xds/translator/testdata/out/xds-ir/health-check-host-hierarchy.clusters.yaml new file mode 100644 index 0000000000..081c04ab7a --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/health-check-host-hierarchy.clusters.yaml @@ -0,0 +1,139 @@ +- circuitBreakers: + thresholds: + - maxRetries: 1024 + commonLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_PREFERRED + dnsRefreshRate: 30s + healthChecks: + - healthyThreshold: 1 + httpHealthCheck: + expectedStatuses: + - end: "201" + start: "200" + host: btp-health.example.com + method: GET + path: /healthz + interval: 5s + timeout: 2s + unhealthyThreshold: 3 + ignoreHealthOnHostRemoval: true + loadAssignment: + clusterName: btp-host-route-dest + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: backend-address.example.com + portValue: 443 + hostname: backend-endpoint.example.com + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: + region: btp-host-route-dest/backend/0 + loadBalancingPolicy: + policies: + - typedExtensionConfig: + name: envoy.load_balancing_policies.least_request + typedConfig: + '@type': type.googleapis.com/envoy.extensions.load_balancing_policies.least_request.v3.LeastRequest + localityLbConfig: + localityWeightedLbConfig: {} + name: btp-host-route-dest + perConnectionBufferLimitBytes: 32768 + respectDnsTtl: true + type: STRICT_DNS +- circuitBreakers: + thresholds: + - maxRetries: 1024 + commonLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_PREFERRED + dnsRefreshRate: 30s + healthChecks: + - healthyThreshold: 1 + httpHealthCheck: + expectedStatuses: + - end: "201" + start: "200" + host: backend-route.example.com + method: GET + path: /healthz + interval: 5s + timeout: 2s + unhealthyThreshold: 3 + ignoreHealthOnHostRemoval: true + loadAssignment: + clusterName: backend-host-route-dest + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: backend-address.example.com + portValue: 443 + healthCheckConfig: + hostname: backend-endpoint.example.com + hostname: backend-endpoint.example.com + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: + region: backend-host-route-dest/backend/0 + loadBalancingPolicy: + policies: + - typedExtensionConfig: + name: envoy.load_balancing_policies.least_request + typedConfig: + '@type': type.googleapis.com/envoy.extensions.load_balancing_policies.least_request.v3.LeastRequest + localityLbConfig: + localityWeightedLbConfig: {} + name: backend-host-route-dest + perConnectionBufferLimitBytes: 32768 + respectDnsTtl: true + type: STRICT_DNS +- circuitBreakers: + thresholds: + - maxRetries: 1024 + commonLbConfig: {} + connectTimeout: 10s + dnsLookupFamily: V4_PREFERRED + dnsRefreshRate: 30s + healthChecks: + - healthyThreshold: 1 + httpHealthCheck: + expectedStatuses: + - end: "201" + start: "200" + host: route-fallback.example.com + method: GET + path: /healthz + interval: 5s + timeout: 2s + unhealthyThreshold: 3 + ignoreHealthOnHostRemoval: true + loadAssignment: + clusterName: route-host-route-dest + endpoints: + - lbEndpoints: + - endpoint: + address: + socketAddress: + address: backend-no-endpoint-host.example.com + portValue: 443 + loadBalancingWeight: 1 + loadBalancingWeight: 1 + locality: + region: route-host-route-dest/backend/0 + loadBalancingPolicy: + policies: + - typedExtensionConfig: + name: envoy.load_balancing_policies.least_request + typedConfig: + '@type': type.googleapis.com/envoy.extensions.load_balancing_policies.least_request.v3.LeastRequest + localityLbConfig: + localityWeightedLbConfig: {} + name: route-host-route-dest + perConnectionBufferLimitBytes: 32768 + respectDnsTtl: true + type: STRICT_DNS diff --git a/internal/xds/translator/testdata/out/xds-ir/health-check-host-hierarchy.endpoints.yaml b/internal/xds/translator/testdata/out/xds-ir/health-check-host-hierarchy.endpoints.yaml new file mode 100644 index 0000000000..fe51488c70 --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/health-check-host-hierarchy.endpoints.yaml @@ -0,0 +1 @@ +[] diff --git a/internal/xds/translator/testdata/out/xds-ir/health-check-host-hierarchy.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/health-check-host-hierarchy.listeners.yaml new file mode 100644 index 0000000000..a265e79d2a --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/health-check-host-hierarchy.listeners.yaml @@ -0,0 +1,35 @@ +- address: + socketAddress: + address: '::' + portValue: 10080 + defaultFilterChain: + filters: + - name: envoy.filters.network.http_connection_manager + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager + commonHttpProtocolOptions: + headersWithUnderscoresAction: REJECT_REQUEST + http2ProtocolOptions: + initialConnectionWindowSize: 1048576 + initialStreamWindowSize: 65536 + maxConcurrentStreams: 100 + httpFilters: + - name: envoy.filters.http.router + typedConfig: + '@type': type.googleapis.com/envoy.extensions.filters.http.router.v3.Router + suppressEnvoyHeaders: true + mergeSlashes: true + normalizePath: true + pathWithEscapedSlashesAction: UNESCAPE_AND_REDIRECT + rds: + configSource: + ads: {} + resourceApiVersion: V3 + routeConfigName: health-check-host-hierarchy-listener + serverHeaderTransformation: PASS_THROUGH + statPrefix: http-10080 + useRemoteAddress: true + name: health-check-host-hierarchy-listener + maxConnectionsToAcceptPerSocketEvent: 1 + name: health-check-host-hierarchy-listener + perConnectionBufferLimitBytes: 32768 diff --git a/internal/xds/translator/testdata/out/xds-ir/health-check-host-hierarchy.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/health-check-host-hierarchy.routes.yaml new file mode 100644 index 0000000000..98f5a1acaa --- /dev/null +++ b/internal/xds/translator/testdata/out/xds-ir/health-check-host-hierarchy.routes.yaml @@ -0,0 +1,36 @@ +- ignorePortInHostMatching: true + name: health-check-host-hierarchy-listener + virtualHosts: + - domains: + - btp-route.example.com + name: health-check-host-hierarchy-listener/btp-route_example_com + routes: + - match: + prefix: / + name: btp-host-route + route: + cluster: btp-host-route-dest + upgradeConfigs: + - upgradeType: websocket + - domains: + - backend-route.example.com + name: health-check-host-hierarchy-listener/backend-route_example_com + routes: + - match: + prefix: / + name: backend-host-route + route: + cluster: backend-host-route-dest + upgradeConfigs: + - upgradeType: websocket + - domains: + - route-fallback.example.com + name: health-check-host-hierarchy-listener/route-fallback_example_com + routes: + - match: + prefix: / + name: route-host-route + route: + cluster: route-host-route-dest + upgradeConfigs: + - upgradeType: websocket diff --git a/release-notes/v1.8.0.yaml b/release-notes/v1.8.0.yaml new file mode 100644 index 0000000000..76f024062e --- /dev/null +++ b/release-notes/v1.8.0.yaml @@ -0,0 +1,113 @@ +date: May 12, 2026 + +# Changes that are expected to cause an incompatibility with previous versions, such as deletions or modifications to existing APIs. +breaking changes: | + The DirectResponse body in HTTPFilter now supports Envoy command operators for dynamic content. Existing configurations including the template syntax (%) will be interpolated. + The `0s` timeout in SecurityPolicy is now treated as infinite timeout instead of immediate timeout. + Fixed EnvoyProxy `samplingFraction` translation to correctly convert the Gateway API fraction into Envoy's percentage-based `random_sampling` field. Existing `samplingFraction` configurations will now sample 100x more frequently than in previous releases; divide previous values by 100 to preserve prior sampling rates. + The controller now uses production logging encoder config by default, which provides better output when using JSON encoder. + SecurityPolicy OIDC now generates a single native `envoy.filters.http.oauth2` HTTP filter in the HCM filter chain and moves route-specific OAuth2 configuration to route `typed_per_filter_config`. This can break existing EnvoyPatchPolicies and extension managers that depend on the previous per-route OAuth2 filter instances or on the old OAuth2 filter configuration shape in the HCM filter chain. + Merged SecurityPolicy IR/xDS resource names (OIDC, BasicAuth, ExtAuth, JWT) now derive from the policy that contributes the field (parent or route) rather than always using the route-level policy. EnvoyPatchPolicy users who reference those generated names must update their patch targets. + +# Updates addressing vulnerabilities, security flaws, or compliance requirements. +security updates: | + +# New features or capabilities added in this release. +new features: | + Added support for optional active health check configuration. + Added support for shadow mode in local rate limiting. + Added support for MergeType in SecurityPolicy to enable route-level policies to merge with parent Gateway/Listener policies, similar to BackendTrafficPolicy. + Added `egctl config envoy-gateway` commands to retrieve Envoy Gateway admin config dumps. + The DirectResponse body in HTTPFilter now supports Envoy command operators for dynamic content. See https://www.envoyproxy.io/docs/envoy/latest/configuration/observability/access_log/usage#command-operators for more details. + Added HTTP/2 connection keepalive support to ClientTrafficPolicy and BackendTrafficPolicy. + Added RoutingType field for BackendTrafficPolicy. + Added support for configuring weights for locality zones. + Added support for gRPC-Web settings in ClientTrafficPolicy. + Added support for Envoy Dynamic Modules. + Added support for weight in BackendRef API to enable traffic splitting for non-x-route resources. + Added support for removing headers based on matching criteria (Exact, Prefix, Suffix, RegularExpression) in ClientTrafficPolicy EarlyRequestHeaders and LateResponseHeaders. + Added support for priorityClassName in KubernetesPodSpec for Envoy Proxy pods. + Added support for Global rate limit shadow mode. + Added support for specifying both text (body) and attributes in access log format by making the type field optional. + Set warning status condition for deprecated fields in xPolicy CRDs. + Added support for URLRewrite filter on individual backendRefs. + Added support for custom headers on OTLP exports (metrics, tracing, access logs). + Added support for custom TLS configuration when pulling WASM code via HTTP or OCI in EnvoyExtensionPolicy. + Added support for gRPC stats settings in EnvoyProxy. + Added the PostEndpointsModify extension hook, allowing extensions to modify EDS ClusterLoadAssignments generated by Envoy Gateway before they are sent to Envoy. + Added support for stream idle timeout in BackendTrafficPolicy. + Added `namespaceOverride` support to gateway-helm chart. + Added support for configuring statusOnError in ExtAuth settings. + Added support for GeoIP-based authorization on HTTPRoute and GRPCRoute via `SecurityPolicy.spec.authorization.rules[*].principal.clientIPGeoLocations`, backed by shared GeoIP provider settings in `EnvoyProxy.spec.geoIP`. + Added support for retry budget in BackendTrafficPolicy. + Added support for BackendUtilization load balancing policy in BackendTrafficPolicy. + Added support for upstream access logs via the `Upstream` access log type in EnvoyProxy. + Added support for invert match in CIDR match RateLimit API. + Added support for ignoring HTTP/1.1 Upgrade requests in ClientTrafficPolicy via `http1.ignoredUpgradeTypes`. + Added support for OpenTelemetry sampler configuration for tracing. + Added support for multiple ExtensionManagers with sequential chaining via a new `extensionManagers` field in `EnvoyGateway` configuration. + Added support for default EnvoyProxy settings on EnvoyGatewaySpec that can be overridden by GatewayClass or Gateway-level EnvoyProxy configurations. A new MergeType field allows choosing between Replace (default), StrategicMerge, or JSONMerge strategies for combining configurations. + Added support for sending Envoy Gateway route metadata to external authorization backends via `SecurityPolicy.spec.extAuth.includeRouteMetadata`. + Added support for cross-namespace policy attachment for ClientTrafficPolicy, BackendTrafficPolicy, EnvoyExtensionPolicy, and SecurityPolicy. + Added `source` field to `responseOverride` rules in BackendTrafficPolicy, allowing rules to target only Envoy-generated responses (`Local`), only upstream responses (`Backend`), or both (`All`, the default). This enables overriding Envoy responses (e.g. auth/rate-limit failures) without affecting legitimate upstream responses with the same status code. + Added support for path override in ExtAuth HTTP service. + Added support for bandwidth limiting in BackendTrafficPolicy. + Added support for defining Envoy Proxy image, pullPolicy, and pullSecrets via the helm chart. Note that to merge these helm-configured values with EnvoyProxy resources, the EnvoyProxy must include `mergeType: StrategicMerge` or `mergeType: JSONMerge`. + Added support for Envoy Admission Control to BackendTrafficPolicy, enabling client-side load shedding based on historical upstream success rates using Envoy's admission control filter. + +bug fixes: | + Fixed local rate limit rules with identical sourceCIDR client selectors producing conflicting descriptors. + Rejected ClientTrafficPolicy if invalid TLS cipher suites are configured. + Fixed ClientTrafficPolicy to disable HTTP/3 and surface a warning on the policy when downstream client TLS validation is configured, instead of generating a rejected QUIC listener. + Fixed validation of XListenerSet certificateRefs. + Fixed XListenerSet not allowing xRoutes from the same namespace when configured to allow them. + Fixed API key authentication dropping non-first client IDs when credential Secrets contain multiple keys. + Fixed `X-ENVOY-ORIGINAL-HOST` not being set when `headers.enableEnvoyHeaders` is enabled and hostname rewrite is configured for DynamicResolver type of Backends. + Fixed standalone mode emitting non-actionable error logs for missing secrets and unsupported ratelimit deletion on every startup. + Fixed local object reference resolution from parent policy in merged BackendTrafficPolicies. + Fixed xPolicy resources being processed from all namespaces when NamespaceSelector watch mode is configured in the Kubernetes provider. + Fixed route and policy status aggregation across multiple GatewayClasses managed by the same controller, so resources preserve status from all relevant parents and ancestors instead of being overwritten by the last processed GatewayClass. + Fixed route status parent aggregation when the number of parents exceeds the Gateway API cap of 32. + Made ConnectionLimit.Value optional so users can configure MaxConnectionDuration, MaxRequestsPerConnection, or MaxStreamDuration without setting a max connections value. + Fixed endpoint hostname not being respected during active health checks. + Fixed ratelimit deployment missing metrics container port (19001), which prevented PodMonitor/ServiceMonitor from targeting the metrics endpoint. + Fixed ratelimit ServiceAccount missing standard Kubernetes app labels. + Fixed GRPCRoute RequestMirror filter backend not being indexed, causing "service not found" errors for mirror targets that exist in the cluster. + Fixed GRPCRoute not detecting conflicting RequestMirror and DirectResponse filters, which caused the mirror to be silently dropped. + Fixed BackendTrafficPolicy `requestBuffer` coexisting with route upgrades by disabling the default WebSocket upgrade on buffered routes and rejecting explicit `requestBuffer` + `httpUpgrade` combinations. + Fixed per-endpoint hostname override not working due to the auto-generated wildcard hostname. + Fixed Basic Authentication failing when htpasswd secrets use CRLF line endings by normalizing to LF before passing to Envoy. + Fixed BackendTLSPolicy being ignored when configuring TLS for telemetry backends (access logs, tracing, metrics). + Fixed client certificate secret never being delivered when exclusively referenced by a SecurityPolicy `extAuth`/`jwt`/`oidc` Backend. + Fixed xRoutes being incorrectly marked unaccepted when a RequestMirror filter referenced a backend with no endpoints; the route now remains accepted with `BackendsAvailable=False`, per Gateway API conformance. + Fixed `ws` and `wss` Backend appProtocols to force HTTP/1.1 upstream connections instead of negotiating HTTP/2, avoiding compatibility issues with WebSocket backends that do not support RFC 8441 extended CONNECT. + Fixed gateway-helm RBAC in GatewayNamespace mode with explicit `watch.namespaces` list by adding controller-namespace secret read permissions to infra-manager. + Fixed a control plane panic caused by concurrent Status mutation racing with the watchable Map coalesce goroutine. + Fixed BackendTrafficPolicy rate limit `requests` values above uint32 max (4294967295) being silently truncated modulo 2^32 by the rate limit service and Envoy token bucket. The field now rejects such values at admission time with a clear schema validation error. + Fixed status conditions not being updated when a route is rejected due to multiple errors. + Fixed spurious development-mode panic log from the gatewayapi translator. + Fixed SecurityPolicy merge using the wrong policy as the owner for resource references and IR generation. + Fixed ListenerSet and its listeners incorrectly setting `Accepted: False` for InvalidCertificateRef and RefNotPermitted, inconsistent with Gateway behavior and the Gateway API spec. + Fixed active HTTP health checks to use Backend endpoint hostnames before falling back to the effective Route hostname. + Fixed HTTPS listeners with overlapping hostnames but disjoint certificate SANs to preserve HTTP/2 ALPN by default. + Removed the spurious cross-namespace policy-attachment warning condition when a ReferenceGrant is missing (#8901). + Fixed an invalid first listener winning hostname/protocol precedence and causing a later valid listener on the same hostname/port to be marked HostnameConflict (#8577). + Increased `RateLimitSelectCondition.headers` MaxItems from 16 to 64, matching the existing `HTTPHeaderFilter` pattern (#8906). + Fixed Gateway getting stuck at `Programmed=False` after its LoadBalancer Service IP was restored, by ignoring `LastTransitionTime` when comparing status conditions. + +# Enhancements that improve performance. +performance improvements: | + Reduced chances of listener drain due to Lua policy updates by migrating to LuaPerRoute. + Reduced Kubernetes API server calls by reusing the cached controller-runtime client from the controller manager for infrastructure reconciliation. In GatewayNamespaceMode, this may slightly increase memory usage due to keeping the infrastructure resources in the cache. + Enabled deferred stat creation to reduce CPU and memory overhead by creating only the subset of metrics that are actually used at runtime, instead of eagerly initializing all possible stats. More information can be found in the Envoy deferred stat creation [documentation](https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/bootstrap/v3/bootstrap.proto#config-bootstrap-v3-bootstrap-deferredstatoptions). + +# Deprecated features or APIs. +deprecations: | + +# Other notable changes not covered by the above sections. +Other changes: | + Moved Envoy Gateway CRDs into a sub-chart to avoid the Helm release secret exceeding the 1MB size limit when adding new API fields. Upgrade/Install behavior is unchanged for users. + The maximum number of rules in a RateLimit policy is increased from 128 to 256. + The maximum number of JWT providers allowed in `SecurityPolicy.spec.jwt.providers` is increased from 4 to 16. + Added `runner_event_total` metric to track update and delete events in infrastructure and gateway API runners for improved observability. + Added common Helm labels to Envoy Gateway RBAC resources. diff --git a/site/content/en/latest/api/extension_types.md b/site/content/en/latest/api/extension_types.md index 130bddae4d..d2235779eb 100644 --- a/site/content/en/latest/api/extension_types.md +++ b/site/content/en/latest/api/extension_types.md @@ -2942,7 +2942,7 @@ _Appears in:_ | Field | Type | Required | Default | Description | | --- | --- | --- | --- | --- | -| `hostname` | _string_ | false | | Hostname defines the HTTP host that will be requested during health checking.
Default: HTTPRoute or GRPCRoute hostname. | +| `hostname` | _string_ | false | | Hostname defines the HTTP Host header used for active HTTP health checks.
Host selection uses this order: this field, the associated Backend endpoint
hostname if available, then the effective Route hostname. | | `path` | _string_ | true | | Path defines the HTTP path that will be requested during health checking. | | `method` | _string_ | false | | Method defines the HTTP method used for health checking.
Defaults to GET | | `expectedStatuses` | _[HTTPStatus](#httpstatus) array_ | false | | ExpectedStatuses defines a list of HTTP response statuses considered healthy.
Defaults to 200 only | @@ -6197,7 +6197,7 @@ _Appears in:_ | --- | --- | --- | --- | --- | | `group` | _[Group](#group)_ | true | gateway.networking.k8s.io | Group is the group that this selector targets. Defaults to gateway.networking.k8s.io | | `kind` | _[Kind](#kind)_ | true | | Kind is the resource kind that this selector targets. | -| `namespaces` | _[TargetSelectorNamespaces](#targetselectornamespaces)_ | false | | Namespaces determines which namespaces are considered for target selection.
If unspecified, only targets in the same namespace as this policy are considered.
When specified, the effective set of namespaces is always constrained to the
namespaces watched by Envoy Gateway. | +| `namespaces` | _[TargetSelectorNamespaces](#targetselectornamespaces)_ | false | | Namespaces determines which namespaces are considered for target selection.
If unspecified, only targets in the same namespace as this policy are considered.
When specified, the effective set of namespaces is always constrained to the
namespaces watched by Envoy Gateway.
Selecting targets across namespaces requires a ReferenceGrant in the target
namespace that allows this policy kind to reference the selected target kind.
Cross-namespace targets without a matching ReferenceGrant are ignored. | | `matchLabels` | _object (keys:string, values:string)_ | false | | MatchLabels are the set of label selectors for identifying the targeted resource. | | `matchExpressions` | _[LabelSelectorRequirement](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.32/#labelselectorrequirement-v1-meta) array_ | false | | MatchExpressions is a list of label selector requirements. The requirements are ANDed. | diff --git a/site/content/en/latest/concepts/gateway_api_extensions/security-policy.md b/site/content/en/latest/concepts/gateway_api_extensions/security-policy.md index 8a2ccd710b..d1454f2f03 100644 --- a/site/content/en/latest/concepts/gateway_api_extensions/security-policy.md +++ b/site/content/en/latest/concepts/gateway_api_extensions/security-policy.md @@ -268,17 +268,7 @@ In this example, the route-level policy merges with the gateway-level policy, re - When `mergeType` is unset, no merging occurs - only the most specific policy takes effect - The merged configuration combines both policies, enabling layered security strategies - When the same security feature is configured in both parent and child policies (e.g., both define CORS), the child policy's configuration takes precedence for that specific feature - -### Important: Namespace Behavior with Secret References - -When policies are merged, secret references inherited from parent policies must be resolvable from the **route policy's namespace**. This is because the merged policy retains the identity (including namespace) of the route-level policy. - -**Example scenario:** -- Gateway policy in namespace `envoy-gateway` references `basic-auth-secret` -- Route policy in namespace `default` merges with the gateway policy -- The secret `basic-auth-secret` must exist in the `default` namespace for the merged policy to work - -**Best Practice:** When using policy merging with secret-based authentication (BasicAuth, OIDC, JWT, APIKeyAuth), ensure that required secrets are available in each route's namespace, or design your namespace strategy accordingly. +- Secret references and backend references are resolved against the namespace of the **policy that originally configured the field** (either route or parent). For example, if a Gateway policy defines BasicAuth, its secret is looked up in the Gateway policy's namespace even after merging. ## Related Resources - [API Key Authentication](../../tasks/security/apikey-auth.md) diff --git a/test/e2e/tests/backendtrafficpolicy_cross_namespace.go b/test/e2e/tests/backendtrafficpolicy_cross_namespace.go index 15214415af..2a01fe9ea6 100644 --- a/test/e2e/tests/backendtrafficpolicy_cross_namespace.go +++ b/test/e2e/tests/backendtrafficpolicy_cross_namespace.go @@ -57,12 +57,6 @@ var BackendTrafficPolicyCrossNamespaceTest = suite.ConformanceTest{ Namespace: gatewayapi.NamespacePtr(grantedGatewayNN.Namespace), Name: gwapiv1.ObjectName(grantedGatewayNN.Name), } - deniedAncestorRef := gwapiv1.ParentReference{ - Group: gatewayapi.GroupPtr(gwapiv1.GroupName), - Kind: gatewayapi.KindPtr(resource.KindGateway), - Namespace: gatewayapi.NamespacePtr(deniedGatewayNN.Namespace), - Name: gwapiv1.ObjectName(deniedGatewayNN.Name), - } BackendTrafficPolicyMustBeAccepted( t, @@ -72,15 +66,6 @@ var BackendTrafficPolicyCrossNamespaceTest = suite.ConformanceTest{ grantedAncestorRef, ) - BackendTrafficPolicyMustFail( - t, - suite.Client, - types.NamespacedName{Name: "cross-namespace-btp-denied", Namespace: policyNS}, - suite.ControllerName, - deniedAncestorRef, - "is not permitted by any ReferenceGrant", - ) - grantedResponse := http.ExpectedResponse{ Namespace: grantedNS, Request: http.Request{ diff --git a/test/helm/gateway-crds-helm/all.out.yaml b/test/helm/gateway-crds-helm/all.out.yaml index 00fbbaec7a..2fa7a96b96 100644 --- a/test/helm/gateway-crds-helm/all.out.yaml +++ b/test/helm/gateway-crds-helm/all.out.yaml @@ -23198,8 +23198,9 @@ spec: type: array hostname: description: |- - Hostname defines the HTTP host that will be requested during health checking. - Default: HTTPRoute or GRPCRoute hostname. + Hostname defines the HTTP Host header used for active HTTP health checks. + Host selection uses this order: this field, the associated Backend endpoint + hostname if available, then the effective Route hostname. maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ @@ -24033,7 +24034,7 @@ spec: required: - name type: object - maxItems: 16 + maxItems: 64 type: array methods: description: |- @@ -24417,7 +24418,7 @@ spec: required: - name type: object - maxItems: 16 + maxItems: 64 type: array methods: description: |- @@ -25451,6 +25452,10 @@ spec: When specified, the effective set of namespaces is always constrained to the namespaces watched by Envoy Gateway. + + Selecting targets across namespaces requires a ReferenceGrant in the target + namespace that allows this policy kind to reference the selected target kind. + Cross-namespace targets without a matching ReferenceGrant are ignored. properties: from: default: Same @@ -27308,6 +27313,10 @@ spec: When specified, the effective set of namespaces is always constrained to the namespaces watched by Envoy Gateway. + + Selecting targets across namespaces requires a ReferenceGrant in the target + namespace that allows this policy kind to reference the selected target kind. + Cross-namespace targets without a matching ReferenceGrant are ignored. properties: from: default: Same @@ -28831,8 +28840,9 @@ spec: type: array hostname: description: |- - Hostname defines the HTTP host that will be requested during health checking. - Default: HTTPRoute or GRPCRoute hostname. + Hostname defines the HTTP Host header used for active HTTP health checks. + Host selection uses this order: this field, the associated Backend endpoint + hostname if available, then the effective Route hostname. maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ @@ -30088,6 +30098,10 @@ spec: When specified, the effective set of namespaces is always constrained to the namespaces watched by Envoy Gateway. + + Selecting targets across namespaces requires a ReferenceGrant in the target + namespace that allows this policy kind to reference the selected target kind. + Cross-namespace targets without a matching ReferenceGrant are ignored. properties: from: default: Same @@ -43164,8 +43178,9 @@ spec: type: array hostname: description: |- - Hostname defines the HTTP host that will be requested during health checking. - Default: HTTPRoute or GRPCRoute hostname. + Hostname defines the HTTP Host header used for active HTTP health checks. + Host selection uses this order: this field, the associated Backend endpoint + hostname if available, then the effective Route hostname. maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ @@ -44695,8 +44710,9 @@ spec: type: array hostname: description: |- - Hostname defines the HTTP host that will be requested during health checking. - Default: HTTPRoute or GRPCRoute hostname. + Hostname defines the HTTP Host header used for active HTTP health checks. + Host selection uses this order: this field, the associated Backend endpoint + hostname if available, then the effective Route hostname. maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ @@ -46413,8 +46429,9 @@ spec: type: array hostname: description: |- - Hostname defines the HTTP host that will be requested during health checking. - Default: HTTPRoute or GRPCRoute hostname. + Hostname defines the HTTP Host header used for active HTTP health checks. + Host selection uses this order: this field, the associated Backend endpoint + hostname if available, then the effective Route hostname. maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ @@ -48021,8 +48038,9 @@ spec: type: array hostname: description: |- - Hostname defines the HTTP host that will be requested during health checking. - Default: HTTPRoute or GRPCRoute hostname. + Hostname defines the HTTP Host header used for active HTTP health checks. + Host selection uses this order: this field, the associated Backend endpoint + hostname if available, then the effective Route hostname. maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ @@ -51093,8 +51111,9 @@ spec: type: array hostname: description: |- - Hostname defines the HTTP host that will be requested during health checking. - Default: HTTPRoute or GRPCRoute hostname. + Hostname defines the HTTP Host header used for active HTTP health checks. + Host selection uses this order: this field, the associated Backend endpoint + hostname if available, then the effective Route hostname. maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ @@ -52496,8 +52515,9 @@ spec: type: array hostname: description: |- - Hostname defines the HTTP host that will be requested during health checking. - Default: HTTPRoute or GRPCRoute hostname. + Hostname defines the HTTP Host header used for active HTTP health checks. + Host selection uses this order: this field, the associated Backend endpoint + hostname if available, then the effective Route hostname. maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ @@ -54178,8 +54198,9 @@ spec: type: array hostname: description: |- - Hostname defines the HTTP host that will be requested during health checking. - Default: HTTPRoute or GRPCRoute hostname. + Hostname defines the HTTP Host header used for active HTTP health checks. + Host selection uses this order: this field, the associated Backend endpoint + hostname if available, then the effective Route hostname. maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ @@ -55892,8 +55913,9 @@ spec: type: array hostname: description: |- - Hostname defines the HTTP host that will be requested during health checking. - Default: HTTPRoute or GRPCRoute hostname. + Hostname defines the HTTP Host header used for active HTTP health checks. + Host selection uses this order: this field, the associated Backend endpoint + hostname if available, then the effective Route hostname. maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ @@ -57041,6 +57063,10 @@ spec: When specified, the effective set of namespaces is always constrained to the namespaces watched by Envoy Gateway. + + Selecting targets across namespaces requires a ReferenceGrant in the target + namespace that allows this policy kind to reference the selected target kind. + Cross-namespace targets without a matching ReferenceGrant are ignored. properties: from: default: Same diff --git a/test/helm/gateway-crds-helm/e2e.out.yaml b/test/helm/gateway-crds-helm/e2e.out.yaml index 9886bff5e0..49efed9ba9 100644 --- a/test/helm/gateway-crds-helm/e2e.out.yaml +++ b/test/helm/gateway-crds-helm/e2e.out.yaml @@ -1171,8 +1171,9 @@ spec: type: array hostname: description: |- - Hostname defines the HTTP host that will be requested during health checking. - Default: HTTPRoute or GRPCRoute hostname. + Hostname defines the HTTP Host header used for active HTTP health checks. + Host selection uses this order: this field, the associated Backend endpoint + hostname if available, then the effective Route hostname. maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ @@ -2006,7 +2007,7 @@ spec: required: - name type: object - maxItems: 16 + maxItems: 64 type: array methods: description: |- @@ -2390,7 +2391,7 @@ spec: required: - name type: object - maxItems: 16 + maxItems: 64 type: array methods: description: |- @@ -3424,6 +3425,10 @@ spec: When specified, the effective set of namespaces is always constrained to the namespaces watched by Envoy Gateway. + + Selecting targets across namespaces requires a ReferenceGrant in the target + namespace that allows this policy kind to reference the selected target kind. + Cross-namespace targets without a matching ReferenceGrant are ignored. properties: from: default: Same @@ -5281,6 +5286,10 @@ spec: When specified, the effective set of namespaces is always constrained to the namespaces watched by Envoy Gateway. + + Selecting targets across namespaces requires a ReferenceGrant in the target + namespace that allows this policy kind to reference the selected target kind. + Cross-namespace targets without a matching ReferenceGrant are ignored. properties: from: default: Same @@ -6804,8 +6813,9 @@ spec: type: array hostname: description: |- - Hostname defines the HTTP host that will be requested during health checking. - Default: HTTPRoute or GRPCRoute hostname. + Hostname defines the HTTP Host header used for active HTTP health checks. + Host selection uses this order: this field, the associated Backend endpoint + hostname if available, then the effective Route hostname. maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ @@ -8061,6 +8071,10 @@ spec: When specified, the effective set of namespaces is always constrained to the namespaces watched by Envoy Gateway. + + Selecting targets across namespaces requires a ReferenceGrant in the target + namespace that allows this policy kind to reference the selected target kind. + Cross-namespace targets without a matching ReferenceGrant are ignored. properties: from: default: Same @@ -21137,8 +21151,9 @@ spec: type: array hostname: description: |- - Hostname defines the HTTP host that will be requested during health checking. - Default: HTTPRoute or GRPCRoute hostname. + Hostname defines the HTTP Host header used for active HTTP health checks. + Host selection uses this order: this field, the associated Backend endpoint + hostname if available, then the effective Route hostname. maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ @@ -22668,8 +22683,9 @@ spec: type: array hostname: description: |- - Hostname defines the HTTP host that will be requested during health checking. - Default: HTTPRoute or GRPCRoute hostname. + Hostname defines the HTTP Host header used for active HTTP health checks. + Host selection uses this order: this field, the associated Backend endpoint + hostname if available, then the effective Route hostname. maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ @@ -24386,8 +24402,9 @@ spec: type: array hostname: description: |- - Hostname defines the HTTP host that will be requested during health checking. - Default: HTTPRoute or GRPCRoute hostname. + Hostname defines the HTTP Host header used for active HTTP health checks. + Host selection uses this order: this field, the associated Backend endpoint + hostname if available, then the effective Route hostname. maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ @@ -25994,8 +26011,9 @@ spec: type: array hostname: description: |- - Hostname defines the HTTP host that will be requested during health checking. - Default: HTTPRoute or GRPCRoute hostname. + Hostname defines the HTTP Host header used for active HTTP health checks. + Host selection uses this order: this field, the associated Backend endpoint + hostname if available, then the effective Route hostname. maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ @@ -29066,8 +29084,9 @@ spec: type: array hostname: description: |- - Hostname defines the HTTP host that will be requested during health checking. - Default: HTTPRoute or GRPCRoute hostname. + Hostname defines the HTTP Host header used for active HTTP health checks. + Host selection uses this order: this field, the associated Backend endpoint + hostname if available, then the effective Route hostname. maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ @@ -30469,8 +30488,9 @@ spec: type: array hostname: description: |- - Hostname defines the HTTP host that will be requested during health checking. - Default: HTTPRoute or GRPCRoute hostname. + Hostname defines the HTTP Host header used for active HTTP health checks. + Host selection uses this order: this field, the associated Backend endpoint + hostname if available, then the effective Route hostname. maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ @@ -32151,8 +32171,9 @@ spec: type: array hostname: description: |- - Hostname defines the HTTP host that will be requested during health checking. - Default: HTTPRoute or GRPCRoute hostname. + Hostname defines the HTTP Host header used for active HTTP health checks. + Host selection uses this order: this field, the associated Backend endpoint + hostname if available, then the effective Route hostname. maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ @@ -33865,8 +33886,9 @@ spec: type: array hostname: description: |- - Hostname defines the HTTP host that will be requested during health checking. - Default: HTTPRoute or GRPCRoute hostname. + Hostname defines the HTTP Host header used for active HTTP health checks. + Host selection uses this order: this field, the associated Backend endpoint + hostname if available, then the effective Route hostname. maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ @@ -35014,6 +35036,10 @@ spec: When specified, the effective set of namespaces is always constrained to the namespaces watched by Envoy Gateway. + + Selecting targets across namespaces requires a ReferenceGrant in the target + namespace that allows this policy kind to reference the selected target kind. + Cross-namespace targets without a matching ReferenceGrant are ignored. properties: from: default: Same diff --git a/test/helm/gateway-crds-helm/envoy-gateway-crds.out.yaml b/test/helm/gateway-crds-helm/envoy-gateway-crds.out.yaml index 4781857643..95e41cc841 100644 --- a/test/helm/gateway-crds-helm/envoy-gateway-crds.out.yaml +++ b/test/helm/gateway-crds-helm/envoy-gateway-crds.out.yaml @@ -1171,8 +1171,9 @@ spec: type: array hostname: description: |- - Hostname defines the HTTP host that will be requested during health checking. - Default: HTTPRoute or GRPCRoute hostname. + Hostname defines the HTTP Host header used for active HTTP health checks. + Host selection uses this order: this field, the associated Backend endpoint + hostname if available, then the effective Route hostname. maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ @@ -2006,7 +2007,7 @@ spec: required: - name type: object - maxItems: 16 + maxItems: 64 type: array methods: description: |- @@ -2390,7 +2391,7 @@ spec: required: - name type: object - maxItems: 16 + maxItems: 64 type: array methods: description: |- @@ -3424,6 +3425,10 @@ spec: When specified, the effective set of namespaces is always constrained to the namespaces watched by Envoy Gateway. + + Selecting targets across namespaces requires a ReferenceGrant in the target + namespace that allows this policy kind to reference the selected target kind. + Cross-namespace targets without a matching ReferenceGrant are ignored. properties: from: default: Same @@ -5281,6 +5286,10 @@ spec: When specified, the effective set of namespaces is always constrained to the namespaces watched by Envoy Gateway. + + Selecting targets across namespaces requires a ReferenceGrant in the target + namespace that allows this policy kind to reference the selected target kind. + Cross-namespace targets without a matching ReferenceGrant are ignored. properties: from: default: Same @@ -6804,8 +6813,9 @@ spec: type: array hostname: description: |- - Hostname defines the HTTP host that will be requested during health checking. - Default: HTTPRoute or GRPCRoute hostname. + Hostname defines the HTTP Host header used for active HTTP health checks. + Host selection uses this order: this field, the associated Backend endpoint + hostname if available, then the effective Route hostname. maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ @@ -8061,6 +8071,10 @@ spec: When specified, the effective set of namespaces is always constrained to the namespaces watched by Envoy Gateway. + + Selecting targets across namespaces requires a ReferenceGrant in the target + namespace that allows this policy kind to reference the selected target kind. + Cross-namespace targets without a matching ReferenceGrant are ignored. properties: from: default: Same @@ -21137,8 +21151,9 @@ spec: type: array hostname: description: |- - Hostname defines the HTTP host that will be requested during health checking. - Default: HTTPRoute or GRPCRoute hostname. + Hostname defines the HTTP Host header used for active HTTP health checks. + Host selection uses this order: this field, the associated Backend endpoint + hostname if available, then the effective Route hostname. maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ @@ -22668,8 +22683,9 @@ spec: type: array hostname: description: |- - Hostname defines the HTTP host that will be requested during health checking. - Default: HTTPRoute or GRPCRoute hostname. + Hostname defines the HTTP Host header used for active HTTP health checks. + Host selection uses this order: this field, the associated Backend endpoint + hostname if available, then the effective Route hostname. maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ @@ -24386,8 +24402,9 @@ spec: type: array hostname: description: |- - Hostname defines the HTTP host that will be requested during health checking. - Default: HTTPRoute or GRPCRoute hostname. + Hostname defines the HTTP Host header used for active HTTP health checks. + Host selection uses this order: this field, the associated Backend endpoint + hostname if available, then the effective Route hostname. maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ @@ -25994,8 +26011,9 @@ spec: type: array hostname: description: |- - Hostname defines the HTTP host that will be requested during health checking. - Default: HTTPRoute or GRPCRoute hostname. + Hostname defines the HTTP Host header used for active HTTP health checks. + Host selection uses this order: this field, the associated Backend endpoint + hostname if available, then the effective Route hostname. maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ @@ -29066,8 +29084,9 @@ spec: type: array hostname: description: |- - Hostname defines the HTTP host that will be requested during health checking. - Default: HTTPRoute or GRPCRoute hostname. + Hostname defines the HTTP Host header used for active HTTP health checks. + Host selection uses this order: this field, the associated Backend endpoint + hostname if available, then the effective Route hostname. maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ @@ -30469,8 +30488,9 @@ spec: type: array hostname: description: |- - Hostname defines the HTTP host that will be requested during health checking. - Default: HTTPRoute or GRPCRoute hostname. + Hostname defines the HTTP Host header used for active HTTP health checks. + Host selection uses this order: this field, the associated Backend endpoint + hostname if available, then the effective Route hostname. maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ @@ -32151,8 +32171,9 @@ spec: type: array hostname: description: |- - Hostname defines the HTTP host that will be requested during health checking. - Default: HTTPRoute or GRPCRoute hostname. + Hostname defines the HTTP Host header used for active HTTP health checks. + Host selection uses this order: this field, the associated Backend endpoint + hostname if available, then the effective Route hostname. maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ @@ -33865,8 +33886,9 @@ spec: type: array hostname: description: |- - Hostname defines the HTTP host that will be requested during health checking. - Default: HTTPRoute or GRPCRoute hostname. + Hostname defines the HTTP Host header used for active HTTP health checks. + Host selection uses this order: this field, the associated Backend endpoint + hostname if available, then the effective Route hostname. maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ @@ -35014,6 +35036,10 @@ spec: When specified, the effective set of namespaces is always constrained to the namespaces watched by Envoy Gateway. + + Selecting targets across namespaces requires a ReferenceGrant in the target + namespace that allows this policy kind to reference the selected target kind. + Cross-namespace targets without a matching ReferenceGrant are ignored. properties: from: default: Same diff --git a/test/helm/gateway-helm/certgen-annotations.out.yaml b/test/helm/gateway-helm/certgen-annotations.out.yaml index c28d3c040f..7d6c87a5d0 100644 --- a/test/helm/gateway-helm/certgen-annotations.out.yaml +++ b/test/helm/gateway-helm/certgen-annotations.out.yaml @@ -58,6 +58,12 @@ kind: ClusterRole metadata: creationTimestamp: null name: gateway-helm-envoy-gateway-role + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: gateway-helm + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm rules: - apiGroups: - "" @@ -191,6 +197,12 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: gateway-helm-envoy-gateway-rolebinding + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: gateway-helm + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole diff --git a/test/helm/gateway-helm/certgen-args.out.yaml b/test/helm/gateway-helm/certgen-args.out.yaml index e00da9d1d7..1b0c0b1dc1 100644 --- a/test/helm/gateway-helm/certgen-args.out.yaml +++ b/test/helm/gateway-helm/certgen-args.out.yaml @@ -58,6 +58,12 @@ kind: ClusterRole metadata: creationTimestamp: null name: gateway-helm-envoy-gateway-role + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: gateway-helm + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm rules: - apiGroups: - "" @@ -191,6 +197,12 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: gateway-helm-envoy-gateway-rolebinding + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: gateway-helm + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole diff --git a/test/helm/gateway-helm/certgen-labels.out.yaml b/test/helm/gateway-helm/certgen-labels.out.yaml index c0e896c124..b6e91d91a5 100644 --- a/test/helm/gateway-helm/certgen-labels.out.yaml +++ b/test/helm/gateway-helm/certgen-labels.out.yaml @@ -58,6 +58,12 @@ kind: ClusterRole metadata: creationTimestamp: null name: gateway-helm-envoy-gateway-role + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: gateway-helm + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm rules: - apiGroups: - "" @@ -191,6 +197,12 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: gateway-helm-envoy-gateway-rolebinding + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: gateway-helm + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole diff --git a/test/helm/gateway-helm/certjen-custom-scheduling.out.yaml b/test/helm/gateway-helm/certjen-custom-scheduling.out.yaml index afd724fd2e..205462a853 100644 --- a/test/helm/gateway-helm/certjen-custom-scheduling.out.yaml +++ b/test/helm/gateway-helm/certjen-custom-scheduling.out.yaml @@ -58,6 +58,12 @@ kind: ClusterRole metadata: creationTimestamp: null name: gateway-helm-envoy-gateway-role + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: gateway-helm + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm rules: - apiGroups: - "" @@ -191,6 +197,12 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: gateway-helm-envoy-gateway-rolebinding + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: gateway-helm + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole diff --git a/test/helm/gateway-helm/common-labels.out.yaml b/test/helm/gateway-helm/common-labels.out.yaml index de27b0aad1..4f99403632 100644 --- a/test/helm/gateway-helm/common-labels.out.yaml +++ b/test/helm/gateway-helm/common-labels.out.yaml @@ -66,6 +66,16 @@ kind: ClusterRole metadata: creationTimestamp: null name: gateway-helm-envoy-gateway-role + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: gateway-helm + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/instance: custom-instance-name + app.kubernetes.io/name: custom-gateway-name + my-commonlabel-1: example-1 + my-commonlabel-2: example-2 rules: - apiGroups: - "" @@ -199,6 +209,16 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: gateway-helm-envoy-gateway-rolebinding + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: gateway-helm + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/instance: custom-instance-name + app.kubernetes.io/name: custom-gateway-name + my-commonlabel-1: example-1 + my-commonlabel-2: example-2 roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole diff --git a/test/helm/gateway-helm/control-plane-with-pdb.out.yaml b/test/helm/gateway-helm/control-plane-with-pdb.out.yaml index 3fe1faed55..ae23c56b59 100644 --- a/test/helm/gateway-helm/control-plane-with-pdb.out.yaml +++ b/test/helm/gateway-helm/control-plane-with-pdb.out.yaml @@ -73,6 +73,12 @@ kind: ClusterRole metadata: creationTimestamp: null name: gateway-helm-envoy-gateway-role + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: gateway-helm + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm rules: - apiGroups: - "" @@ -206,6 +212,12 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: gateway-helm-envoy-gateway-rolebinding + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: gateway-helm + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole diff --git a/test/helm/gateway-helm/default-config.out.yaml b/test/helm/gateway-helm/default-config.out.yaml index f39a13e11b..31b4ced4b1 100644 --- a/test/helm/gateway-helm/default-config.out.yaml +++ b/test/helm/gateway-helm/default-config.out.yaml @@ -58,6 +58,12 @@ kind: ClusterRole metadata: creationTimestamp: null name: gateway-helm-envoy-gateway-role + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: gateway-helm + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm rules: - apiGroups: - "" @@ -191,6 +197,12 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: gateway-helm-envoy-gateway-rolebinding + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: gateway-helm + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole diff --git a/test/helm/gateway-helm/deployment-annotations.out.yaml b/test/helm/gateway-helm/deployment-annotations.out.yaml index 12502253f1..d05a496bd2 100644 --- a/test/helm/gateway-helm/deployment-annotations.out.yaml +++ b/test/helm/gateway-helm/deployment-annotations.out.yaml @@ -58,6 +58,12 @@ kind: ClusterRole metadata: creationTimestamp: null name: gateway-helm-envoy-gateway-role + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: gateway-helm + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm rules: - apiGroups: - "" @@ -191,6 +197,12 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: gateway-helm-envoy-gateway-rolebinding + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: gateway-helm + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole diff --git a/test/helm/gateway-helm/deployment-custom-topology.out.yaml b/test/helm/gateway-helm/deployment-custom-topology.out.yaml index d1602e92ef..bdf58960d8 100644 --- a/test/helm/gateway-helm/deployment-custom-topology.out.yaml +++ b/test/helm/gateway-helm/deployment-custom-topology.out.yaml @@ -58,6 +58,12 @@ kind: ClusterRole metadata: creationTimestamp: null name: gateway-helm-envoy-gateway-role + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: gateway-helm + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm rules: - apiGroups: - "" @@ -191,6 +197,12 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: gateway-helm-envoy-gateway-rolebinding + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: gateway-helm + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole diff --git a/test/helm/gateway-helm/deployment-extraenv.out.yaml b/test/helm/gateway-helm/deployment-extraenv.out.yaml index e4a9901942..aaa2950a04 100644 --- a/test/helm/gateway-helm/deployment-extraenv.out.yaml +++ b/test/helm/gateway-helm/deployment-extraenv.out.yaml @@ -58,6 +58,12 @@ kind: ClusterRole metadata: creationTimestamp: null name: gateway-helm-envoy-gateway-role + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: gateway-helm + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm rules: - apiGroups: - "" @@ -191,6 +197,12 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: gateway-helm-envoy-gateway-rolebinding + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: gateway-helm + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole diff --git a/test/helm/gateway-helm/deployment-images-config.out.yaml b/test/helm/gateway-helm/deployment-images-config.out.yaml index c9b12787dc..c52849af89 100644 --- a/test/helm/gateway-helm/deployment-images-config.out.yaml +++ b/test/helm/gateway-helm/deployment-images-config.out.yaml @@ -58,6 +58,12 @@ kind: ClusterRole metadata: creationTimestamp: null name: gateway-helm-envoy-gateway-role + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: gateway-helm + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm rules: - apiGroups: - "" @@ -191,6 +197,12 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: gateway-helm-envoy-gateway-rolebinding + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: gateway-helm + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole diff --git a/test/helm/gateway-helm/deployment-priorityclass.out.yaml b/test/helm/gateway-helm/deployment-priorityclass.out.yaml index 601da6bc2a..fb05c7e1a9 100644 --- a/test/helm/gateway-helm/deployment-priorityclass.out.yaml +++ b/test/helm/gateway-helm/deployment-priorityclass.out.yaml @@ -58,6 +58,12 @@ kind: ClusterRole metadata: creationTimestamp: null name: gateway-helm-envoy-gateway-role + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: gateway-helm + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm rules: - apiGroups: - "" @@ -191,6 +197,12 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: gateway-helm-envoy-gateway-rolebinding + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: gateway-helm + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole diff --git a/test/helm/gateway-helm/deployment-repo-no-registry.out.yaml b/test/helm/gateway-helm/deployment-repo-no-registry.out.yaml index 4c62ba99e6..ba3ad45d51 100644 --- a/test/helm/gateway-helm/deployment-repo-no-registry.out.yaml +++ b/test/helm/gateway-helm/deployment-repo-no-registry.out.yaml @@ -58,6 +58,12 @@ kind: ClusterRole metadata: creationTimestamp: null name: gateway-helm-envoy-gateway-role + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: gateway-helm + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm rules: - apiGroups: - "" @@ -191,6 +197,12 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: gateway-helm-envoy-gateway-rolebinding + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: gateway-helm + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole diff --git a/test/helm/gateway-helm/deployment-securitycontext.out.yaml b/test/helm/gateway-helm/deployment-securitycontext.out.yaml index 4f5185c430..f1d8103400 100644 --- a/test/helm/gateway-helm/deployment-securitycontext.out.yaml +++ b/test/helm/gateway-helm/deployment-securitycontext.out.yaml @@ -58,6 +58,12 @@ kind: ClusterRole metadata: creationTimestamp: null name: gateway-helm-envoy-gateway-role + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: gateway-helm + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm rules: - apiGroups: - "" @@ -191,6 +197,12 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: gateway-helm-envoy-gateway-rolebinding + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: gateway-helm + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole diff --git a/test/helm/gateway-helm/deployment-volume-mounts.out.yaml b/test/helm/gateway-helm/deployment-volume-mounts.out.yaml index 4affd2e979..dc51912586 100644 --- a/test/helm/gateway-helm/deployment-volume-mounts.out.yaml +++ b/test/helm/gateway-helm/deployment-volume-mounts.out.yaml @@ -58,6 +58,12 @@ kind: ClusterRole metadata: creationTimestamp: null name: gateway-helm-envoy-gateway-role + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: gateway-helm + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm rules: - apiGroups: - "" @@ -191,6 +197,12 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: gateway-helm-envoy-gateway-rolebinding + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: gateway-helm + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole diff --git a/test/helm/gateway-helm/envoy-gateway-config.out.yaml b/test/helm/gateway-helm/envoy-gateway-config.out.yaml index 5b6c8daa85..a81d1c8e75 100644 --- a/test/helm/gateway-helm/envoy-gateway-config.out.yaml +++ b/test/helm/gateway-helm/envoy-gateway-config.out.yaml @@ -60,6 +60,12 @@ kind: ClusterRole metadata: creationTimestamp: null name: gateway-helm-envoy-gateway-role + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: gateway-helm + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm rules: - apiGroups: - "" @@ -193,6 +199,12 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: gateway-helm-envoy-gateway-rolebinding + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: gateway-helm + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole diff --git a/test/helm/gateway-helm/envoy-gateway-gateway-namespace-config-watch.out.yaml b/test/helm/gateway-helm/envoy-gateway-gateway-namespace-config-watch.out.yaml index 48304360b1..3272081781 100644 --- a/test/helm/gateway-helm/envoy-gateway-gateway-namespace-config-watch.out.yaml +++ b/test/helm/gateway-helm/envoy-gateway-gateway-namespace-config-watch.out.yaml @@ -64,6 +64,12 @@ kind: ClusterRole metadata: creationTimestamp: null name: gateway-helm-envoy-gateway-role + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: gateway-helm + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm rules: - apiGroups: - "" @@ -123,6 +129,12 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: gateway-helm-envoy-gateway-rolebinding + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: gateway-helm + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole @@ -159,6 +171,12 @@ metadata: creationTimestamp: null name: gateway-helm-envoy-gateway-role namespace: "default" + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: gateway-helm + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm rules: - apiGroups: - "" @@ -261,6 +279,12 @@ metadata: creationTimestamp: null name: gateway-helm-envoy-gateway-role namespace: "app-ns" + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: gateway-helm + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm rules: - apiGroups: - "" @@ -606,6 +630,12 @@ kind: RoleBinding metadata: name: gateway-helm-envoy-gateway-rolebinding namespace: "default" + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: gateway-helm + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io kind: Role @@ -621,6 +651,12 @@ kind: RoleBinding metadata: name: gateway-helm-envoy-gateway-rolebinding namespace: "app-ns" + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: gateway-helm + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io kind: Role diff --git a/test/helm/gateway-helm/envoy-gateway-gateway-namespace-config.out.yaml b/test/helm/gateway-helm/envoy-gateway-gateway-namespace-config.out.yaml index b9c295f0ab..eeb532af32 100644 --- a/test/helm/gateway-helm/envoy-gateway-gateway-namespace-config.out.yaml +++ b/test/helm/gateway-helm/envoy-gateway-gateway-namespace-config.out.yaml @@ -60,6 +60,12 @@ kind: ClusterRole metadata: creationTimestamp: null name: gateway-helm-envoy-gateway-role + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: gateway-helm + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm rules: - apiGroups: - "" @@ -261,6 +267,12 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: gateway-helm-envoy-gateway-rolebinding + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: gateway-helm + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole diff --git a/test/helm/gateway-helm/envoy-gateway-gateway-namespace-namespaceselector.out.yaml b/test/helm/gateway-helm/envoy-gateway-gateway-namespace-namespaceselector.out.yaml index 3f6aaf4d27..ce321cf111 100644 --- a/test/helm/gateway-helm/envoy-gateway-gateway-namespace-namespaceselector.out.yaml +++ b/test/helm/gateway-helm/envoy-gateway-gateway-namespace-namespaceselector.out.yaml @@ -65,6 +65,12 @@ kind: ClusterRole metadata: creationTimestamp: null name: gateway-helm-envoy-gateway-role + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: gateway-helm + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm rules: - apiGroups: - "" @@ -285,6 +291,12 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: gateway-helm-envoy-gateway-rolebinding + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: gateway-helm + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole diff --git a/test/helm/gateway-helm/global-images-config.out.yaml b/test/helm/gateway-helm/global-images-config.out.yaml index 8d3d478756..7db956ec59 100644 --- a/test/helm/gateway-helm/global-images-config.out.yaml +++ b/test/helm/gateway-helm/global-images-config.out.yaml @@ -74,6 +74,12 @@ kind: ClusterRole metadata: creationTimestamp: null name: gateway-helm-envoy-gateway-role + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: gateway-helm + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm rules: - apiGroups: - "" @@ -207,6 +213,12 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: gateway-helm-envoy-gateway-rolebinding + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: gateway-helm + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole diff --git a/test/helm/gateway-helm/global-pullsecrets-override-deployment.out.yaml b/test/helm/gateway-helm/global-pullsecrets-override-deployment.out.yaml index 088d224f06..2be6ae3160 100644 --- a/test/helm/gateway-helm/global-pullsecrets-override-deployment.out.yaml +++ b/test/helm/gateway-helm/global-pullsecrets-override-deployment.out.yaml @@ -62,6 +62,12 @@ kind: ClusterRole metadata: creationTimestamp: null name: gateway-helm-envoy-gateway-role + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: gateway-helm + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm rules: - apiGroups: - "" @@ -195,6 +201,12 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: gateway-helm-envoy-gateway-rolebinding + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: gateway-helm + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole diff --git a/test/helm/gateway-helm/global-pullsecrets-override-global.out.yaml b/test/helm/gateway-helm/global-pullsecrets-override-global.out.yaml index 7f11308317..90a5a38c8a 100644 --- a/test/helm/gateway-helm/global-pullsecrets-override-global.out.yaml +++ b/test/helm/gateway-helm/global-pullsecrets-override-global.out.yaml @@ -62,6 +62,12 @@ kind: ClusterRole metadata: creationTimestamp: null name: gateway-helm-envoy-gateway-role + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: gateway-helm + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm rules: - apiGroups: - "" @@ -195,6 +201,12 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: gateway-helm-envoy-gateway-rolebinding + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: gateway-helm + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole diff --git a/test/helm/gateway-helm/global-registry-override-deployment.out.yaml b/test/helm/gateway-helm/global-registry-override-deployment.out.yaml index 03d028eed2..62ed64c696 100644 --- a/test/helm/gateway-helm/global-registry-override-deployment.out.yaml +++ b/test/helm/gateway-helm/global-registry-override-deployment.out.yaml @@ -58,6 +58,12 @@ kind: ClusterRole metadata: creationTimestamp: null name: gateway-helm-envoy-gateway-role + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: gateway-helm + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm rules: - apiGroups: - "" @@ -191,6 +197,12 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: gateway-helm-envoy-gateway-rolebinding + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: gateway-helm + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole diff --git a/test/helm/gateway-helm/global-registry-override-global.out.yaml b/test/helm/gateway-helm/global-registry-override-global.out.yaml index d68af2424b..825b1adf97 100644 --- a/test/helm/gateway-helm/global-registry-override-global.out.yaml +++ b/test/helm/gateway-helm/global-registry-override-global.out.yaml @@ -58,6 +58,12 @@ kind: ClusterRole metadata: creationTimestamp: null name: gateway-helm-envoy-gateway-role + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: gateway-helm + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm rules: - apiGroups: - "" @@ -191,6 +197,12 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: gateway-helm-envoy-gateway-rolebinding + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: gateway-helm + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole diff --git a/test/helm/gateway-helm/horizontal-pod-autoscaler-disabled.out.yaml b/test/helm/gateway-helm/horizontal-pod-autoscaler-disabled.out.yaml index 3c438579b4..6ace762a83 100644 --- a/test/helm/gateway-helm/horizontal-pod-autoscaler-disabled.out.yaml +++ b/test/helm/gateway-helm/horizontal-pod-autoscaler-disabled.out.yaml @@ -58,6 +58,12 @@ kind: ClusterRole metadata: creationTimestamp: null name: gateway-helm-envoy-gateway-role + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: gateway-helm + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm rules: - apiGroups: - "" @@ -191,6 +197,12 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: gateway-helm-envoy-gateway-rolebinding + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: gateway-helm + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole diff --git a/test/helm/gateway-helm/horizontal-pod-autoscaler.out.yaml b/test/helm/gateway-helm/horizontal-pod-autoscaler.out.yaml index 79cf7b5138..375e77318e 100644 --- a/test/helm/gateway-helm/horizontal-pod-autoscaler.out.yaml +++ b/test/helm/gateway-helm/horizontal-pod-autoscaler.out.yaml @@ -58,6 +58,12 @@ kind: ClusterRole metadata: creationTimestamp: null name: gateway-helm-envoy-gateway-role + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: gateway-helm + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm rules: - apiGroups: - "" @@ -191,6 +197,12 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: gateway-helm-envoy-gateway-rolebinding + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: gateway-helm + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole diff --git a/test/helm/gateway-helm/namespace-override.out.yaml b/test/helm/gateway-helm/namespace-override.out.yaml index 77e5f3b410..5ea015cdd8 100644 --- a/test/helm/gateway-helm/namespace-override.out.yaml +++ b/test/helm/gateway-helm/namespace-override.out.yaml @@ -58,6 +58,12 @@ kind: ClusterRole metadata: creationTimestamp: null name: gateway-helm-envoy-gateway-role + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: gateway-helm + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm rules: - apiGroups: - "" @@ -191,6 +197,12 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: gateway-helm-envoy-gateway-rolebinding + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: gateway-helm + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole diff --git a/test/helm/gateway-helm/service-customization.out.yaml b/test/helm/gateway-helm/service-customization.out.yaml index dae8a3256c..d4f8bc9923 100644 --- a/test/helm/gateway-helm/service-customization.out.yaml +++ b/test/helm/gateway-helm/service-customization.out.yaml @@ -58,6 +58,12 @@ kind: ClusterRole metadata: creationTimestamp: null name: gateway-helm-envoy-gateway-role + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: gateway-helm + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm rules: - apiGroups: - "" @@ -191,6 +197,12 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: gateway-helm-envoy-gateway-rolebinding + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: gateway-helm + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole diff --git a/test/helm/gateway-helm/webhook-disabled.out.yaml b/test/helm/gateway-helm/webhook-disabled.out.yaml index 9284757ac4..b96fa4d4d1 100644 --- a/test/helm/gateway-helm/webhook-disabled.out.yaml +++ b/test/helm/gateway-helm/webhook-disabled.out.yaml @@ -60,6 +60,12 @@ kind: ClusterRole metadata: creationTimestamp: null name: gateway-helm-envoy-gateway-role + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: gateway-helm + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm rules: - apiGroups: - "" @@ -182,6 +188,12 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: gateway-helm-envoy-gateway-rolebinding + labels: + helm.sh/chart: gateway-helm-v0.0.0-latest + app.kubernetes.io/name: gateway-helm + app.kubernetes.io/instance: gateway-helm + app.kubernetes.io/version: "latest" + app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole