From e0bce55e569b30746c9c62fa8e9747074b733201 Mon Sep 17 00:00:00 2001
From: therealak12
Date: Mon, 9 Feb 2026 15:48:03 +0330
Subject: [PATCH 1/2] add support for http authz server
Signed-off-by: therealak12
---
apis/projectcontour/v1/httpproxy.go | 79 +++
.../v1/zz_generated.deepcopy.go | 45 ++
.../v1alpha1/extensionservice.go | 10 +-
.../unreleased/7418-therealak12-minor.md | 5 +
cmd/contour/serve.go | 28 ++
cmd/contour/servecontext.go | 5 +
examples/contour/01-crds.yaml | 255 +++++++++-
examples/render/contour-deployment.yaml | 255 +++++++++-
.../render/contour-gateway-provisioner.yaml | 255 +++++++++-
examples/render/contour-gateway.yaml | 255 +++++++++-
examples/render/contour.yaml | 255 +++++++++-
internal/dag/conditions.go | 38 ++
internal/dag/dag.go | 24 +
internal/dag/httpproxy_processor.go | 34 ++
internal/envoy/v3/cluster.go | 10 +-
internal/envoy/v3/listener.go | 91 +++-
.../featuretests/v3/authorization_test.go | 475 +++++++++++++++++-
internal/featuretests/v3/envoy.go | 14 +
.../featuretests/v3/extensionservice_test.go | 34 +-
.../v3/global_authorization_test.go | 6 +-
internal/xdscache/v3/listener.go | 16 +-
pkg/config/parameters.go | 10 +
.../docs/main/config/api-reference.html | 220 +++++++-
23 files changed, 2360 insertions(+), 59 deletions(-)
create mode 100644 changelogs/unreleased/7418-therealak12-minor.md
diff --git a/apis/projectcontour/v1/httpproxy.go b/apis/projectcontour/v1/httpproxy.go
index 8e407a02b7c..c30a8b243f8 100644
--- a/apis/projectcontour/v1/httpproxy.go
+++ b/apis/projectcontour/v1/httpproxy.go
@@ -239,6 +239,15 @@ type ExtensionServiceReference struct {
Name string `json:"name,omitempty" protobuf:"bytes,3,opt,name=name"`
}
+// AuthorizationServiceAPIType indicates the protocol
+// implemented by the external authorization server.
+type AuthorizationServiceAPIType string
+
+const (
+ AuthorizationGRPCService AuthorizationServiceAPIType = "grpc"
+ AuthorizationHTTPService AuthorizationServiceAPIType = "http"
+)
+
// AuthorizationServer configures an external server to authenticate
// client requests. The external server must implement the v3 Envoy
// external authorization GRPC protocol (https://www.envoyproxy.io/docs/envoy/latest/api-v3/service/auth/v3/external_auth.proto).
@@ -248,6 +257,19 @@ type AuthorizationServer struct {
// +optional
ExtensionServiceRef ExtensionServiceReference `json:"extensionRef,omitempty"`
+ // ServiceAPIType sets the protocol used to communicate with
+ // the external authorization server.
+ //
+ // +optional
+ // +kubebuilder:validation:Enum=http;grpc
+ // +kubebuilder:default=grpc
+ ServiceAPIType AuthorizationServiceAPIType `json:"serviceAPIType,omitempty"`
+
+ // HTTPAuthorizationServerSettings defines configurations for interacting with an external HTTP authorization server.
+ //
+ // +optional
+ HTTPServerSettings *HTTPAuthorizationServerSettings `json:"httpSettings,omitempty"`
+
// AuthPolicy sets a default authorization policy for client requests.
// This policy will be used unless overridden by individual routes.
//
@@ -276,6 +298,63 @@ type AuthorizationServer struct {
WithRequestBody *AuthorizationServerBufferSettings `json:"withRequestBody,omitempty"`
}
+// HTTPAuthorizationServerSettings defines configurations for interacting with an external HTTP authorization server.
+type HTTPAuthorizationServerSettings struct {
+ // PathPrefix Sets a prefix to the value of authorization request header Path.
+ //
+ // +optional
+ PathPrefix string `json:"pathPrefix,omitempty"`
+
+ // AllowedAuthorizationHeaders specifies client request headers that will be sent to the authorization server.
+ // Host, Method, Path, Content-Length, and Authorization headers are additionally included in the list.
+ //
+ // +optional
+ AllowedAuthorizationHeaders []HTTPAuthorizationServerAllowedHeaders `json:"allowedAuthorizationHeaders,omitempty"`
+
+ // AllowedUpstreamHeaders specifies authorization response headers that will be added to the original client request.
+ // Coexistent headers will be overridden.
+ //
+ // +optional
+ AllowedUpstreamHeaders []HTTPAuthorizationServerAllowedHeaders `json:"allowedUpstreamHeaders,omitempty"`
+}
+
+// HTTPAuthorizationServerAllowedHeaders specifies how to conditionally match against allowed headers
+// in the context of HTTP authorization. Regex support is intentionally excluded to simplify the user
+// experience and prevent potential issues. Only one of Prefix, Exact, Suffix or Contains must be provided.
+type HTTPAuthorizationServerAllowedHeaders struct {
+ // Exact specifies a string that the header name must be equal to.
+ //
+ // +optional
+ Exact string `json:"exact,omitempty"`
+
+ // Prefix defines a prefix match for the header name.
+ //
+ // +optional
+ Prefix string `json:"prefix,omitempty"`
+
+ // Suffix defines a suffix match for a header name.
+ //
+ // +optional
+ Suffix string `json:"suffix,omitempty"`
+
+ // To streamline user experience and mitigate potential issues, we do not support regex.
+ // Additionally, it's essential to ensure that any regex patterns adhere to the configured runtime key, re2.max_program_size.error_level
+ // by verifying that the program size is smaller than the specified value.
+ // This necessitates thorough validation of user input.
+ //
+ // Regex string `json:"regex,omitempty"`
+
+ // Contains specifies a substring that must be present in the header name.
+ //
+ // +optional
+ Contains string `json:"contains,omitempty"`
+
+ // IgnoreCase specifies whether string matching should be case-insensitive.
+ //
+ // +optional
+ IgnoreCase bool `json:"ignoreCase,omitempty"`
+}
+
// AuthorizationServerBufferSettings enables ExtAuthz filter to buffer client request data and send it as part of authorization request
type AuthorizationServerBufferSettings struct {
// MaxRequestBytes sets the maximum size of message body ExtAuthz filter will hold in-memory.
diff --git a/apis/projectcontour/v1/zz_generated.deepcopy.go b/apis/projectcontour/v1/zz_generated.deepcopy.go
index 30cd9f1cbea..67a09799161 100644
--- a/apis/projectcontour/v1/zz_generated.deepcopy.go
+++ b/apis/projectcontour/v1/zz_generated.deepcopy.go
@@ -50,6 +50,11 @@ func (in *AuthorizationPolicy) DeepCopy() *AuthorizationPolicy {
func (in *AuthorizationServer) DeepCopyInto(out *AuthorizationServer) {
*out = *in
out.ExtensionServiceRef = in.ExtensionServiceRef
+ if in.HTTPServerSettings != nil {
+ in, out := &in.HTTPServerSettings, &out.HTTPServerSettings
+ *out = new(HTTPAuthorizationServerSettings)
+ (*in).DeepCopyInto(*out)
+ }
if in.AuthPolicy != nil {
in, out := &in.AuthPolicy, &out.AuthPolicy
*out = new(AuthorizationPolicy)
@@ -324,6 +329,46 @@ func (in *GlobalRateLimitPolicy) DeepCopy() *GlobalRateLimitPolicy {
return out
}
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *HTTPAuthorizationServerAllowedHeaders) DeepCopyInto(out *HTTPAuthorizationServerAllowedHeaders) {
+ *out = *in
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPAuthorizationServerAllowedHeaders.
+func (in *HTTPAuthorizationServerAllowedHeaders) DeepCopy() *HTTPAuthorizationServerAllowedHeaders {
+ if in == nil {
+ return nil
+ }
+ out := new(HTTPAuthorizationServerAllowedHeaders)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *HTTPAuthorizationServerSettings) DeepCopyInto(out *HTTPAuthorizationServerSettings) {
+ *out = *in
+ if in.AllowedAuthorizationHeaders != nil {
+ in, out := &in.AllowedAuthorizationHeaders, &out.AllowedAuthorizationHeaders
+ *out = make([]HTTPAuthorizationServerAllowedHeaders, len(*in))
+ copy(*out, *in)
+ }
+ if in.AllowedUpstreamHeaders != nil {
+ in, out := &in.AllowedUpstreamHeaders, &out.AllowedUpstreamHeaders
+ *out = make([]HTTPAuthorizationServerAllowedHeaders, len(*in))
+ copy(*out, *in)
+ }
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPAuthorizationServerSettings.
+func (in *HTTPAuthorizationServerSettings) DeepCopy() *HTTPAuthorizationServerSettings {
+ if in == nil {
+ return nil
+ }
+ out := new(HTTPAuthorizationServerSettings)
+ in.DeepCopyInto(out)
+ return out
+}
+
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *HTTPDirectResponsePolicy) DeepCopyInto(out *HTTPDirectResponsePolicy) {
*out = *in
diff --git a/apis/projectcontour/v1alpha1/extensionservice.go b/apis/projectcontour/v1alpha1/extensionservice.go
index c074de546e7..c936f98c786 100644
--- a/apis/projectcontour/v1alpha1/extensionservice.go
+++ b/apis/projectcontour/v1alpha1/extensionservice.go
@@ -62,7 +62,7 @@ type ExtensionServiceTarget struct {
// ExtensionServiceSpec defines the desired state of an ExtensionService resource.
type ExtensionServiceSpec struct {
// Services specifies the set of Kubernetes Service resources that
- // receive GRPC extension API requests.
+ // receive extension API requests.
// If no weights are specified for any of the entries in
// this array, traffic will be spread evenly across all the
// services.
@@ -78,15 +78,15 @@ type ExtensionServiceSpec struct {
UpstreamValidation *contour_v1.UpstreamValidation `json:"validation,omitempty"`
// Protocol may be used to specify (or override) the protocol used to reach this Service.
- // Values may be h2 or h2c. If omitted, protocol-selection falls back on Service annotations.
+ // Values may be h2, h2c or http/1.1. If omitted, protocol-selection falls back on Service annotations.
//
// +optional
- // +kubebuilder:validation:Enum=h2;h2c
+ // +kubebuilder:validation:Enum=http/1.1;h2;h2c
Protocol *string `json:"protocol,omitempty"`
- // The policy for load balancing GRPC service requests. Note that the
+ // The policy for load balancing service requests. Note that the
// `Cookie` and `RequestHash` load balancing strategies cannot be used
- // here.
+ // here for GRPC service requests.
//
// +optional
LoadBalancerPolicy *contour_v1.LoadBalancerPolicy `json:"loadBalancerPolicy,omitempty"`
diff --git a/changelogs/unreleased/7418-therealak12-minor.md b/changelogs/unreleased/7418-therealak12-minor.md
new file mode 100644
index 00000000000..8b33df50489
--- /dev/null
+++ b/changelogs/unreleased/7418-therealak12-minor.md
@@ -0,0 +1,5 @@
+## Contour now supports HTTP external authorization services
+
+With this change, Contour supports HTTP external authorization services in addition to gRPC.
+This expands compatibility with a broader range of authorization providers and
+allows operators to choose the protocol that best fits their environment.
diff --git a/cmd/contour/serve.go b/cmd/contour/serve.go
index 16a00bdd283..9b291279a73 100644
--- a/cmd/contour/serve.go
+++ b/cmd/contour/serve.go
@@ -836,6 +836,34 @@ func (s *Server) setupGlobalExternalAuthentication(contourConfiguration contour_
Context: context,
}
+ switch contourConfiguration.GlobalExternalAuthorization.ServiceAPIType {
+ case contour_v1.AuthorizationGRPCService:
+ globalExternalAuthConfig.ServiceAPIType = contour_v1.AuthorizationGRPCService
+ case contour_v1.AuthorizationHTTPService:
+ globalExternalAuthConfig.ServiceAPIType = contour_v1.AuthorizationHTTPService
+ if contourConfiguration.GlobalExternalAuthorization.HTTPServerSettings != nil {
+ globalExternalAuthConfig.HTTPPathPrefix = contourConfiguration.GlobalExternalAuthorization.HTTPServerSettings.PathPrefix
+
+ // globalExternalAuthConfig.HttpServerURI = contourConfiguration.GlobalExternalAuthorization.HttpServerSettings.ServerURI
+
+ if len(contourConfiguration.GlobalExternalAuthorization.HTTPServerSettings.AllowedAuthorizationHeaders) > 0 {
+ if err := dag.ExternalAuthAllowedHeadersValid(contourConfiguration.GlobalExternalAuthorization.HTTPServerSettings.AllowedAuthorizationHeaders); err != nil {
+ return nil, err
+ }
+
+ globalExternalAuthConfig.HTTPAllowedAuthorizationHeaders = contourConfiguration.GlobalExternalAuthorization.HTTPServerSettings.AllowedAuthorizationHeaders
+ }
+
+ if len(contourConfiguration.GlobalExternalAuthorization.HTTPServerSettings.AllowedUpstreamHeaders) > 0 {
+ if err := dag.ExternalAuthAllowedHeadersValid(contourConfiguration.GlobalExternalAuthorization.HTTPServerSettings.AllowedUpstreamHeaders); err != nil {
+ return nil, err
+ }
+
+ globalExternalAuthConfig.HTTPAllowedUpstreamHeaders = contourConfiguration.GlobalExternalAuthorization.HTTPServerSettings.AllowedUpstreamHeaders
+ }
+ }
+ }
+
if contourConfiguration.GlobalExternalAuthorization.WithRequestBody != nil {
globalExternalAuthConfig.WithRequestBody = &dag.AuthorizationServerBufferSettings{
PackAsBytes: contourConfiguration.GlobalExternalAuthorization.WithRequestBody.PackAsBytes,
diff --git a/cmd/contour/servecontext.go b/cmd/contour/servecontext.go
index 8c4ee27d73b..9ddb8e4a5cf 100644
--- a/cmd/contour/servecontext.go
+++ b/cmd/contour/servecontext.go
@@ -457,10 +457,15 @@ func (ctx *serveContext) convertToContourConfigurationSpec() contour_v1alpha1.Co
Name: nsedName.Name,
Namespace: nsedName.Namespace,
},
+ ServiceAPIType: ctx.Config.GlobalExternalAuthorization.ServiceAPIType,
ResponseTimeout: ctx.Config.GlobalExternalAuthorization.ResponseTimeout,
FailOpen: ctx.Config.GlobalExternalAuthorization.FailOpen,
}
+ if ctx.Config.GlobalExternalAuthorization.HTTPServerSettings != nil {
+ globalExtAuth.HTTPServerSettings = ctx.Config.GlobalExternalAuthorization.HTTPServerSettings
+ }
+
if ctx.Config.GlobalExternalAuthorization.AuthPolicy != nil {
globalExtAuth.AuthPolicy = &contour_v1.AuthorizationPolicy{
Disabled: ctx.Config.GlobalExternalAuthorization.AuthPolicy.Disabled,
diff --git a/examples/contour/01-crds.yaml b/examples/contour/01-crds.yaml
index bd251103c8b..8348305dee8 100644
--- a/examples/contour/01-crds.yaml
+++ b/examples/contour/01-crds.yaml
@@ -727,6 +727,79 @@ spec:
set in most cases. It is intended for use only while migrating applications
from internal authorization to Contour external authorization.
type: boolean
+ httpSettings:
+ description: HTTPAuthorizationServerSettings defines configurations
+ for interacting with an external HTTP authorization server.
+ properties:
+ allowedAuthorizationHeaders:
+ description: |-
+ AllowedAuthorizationHeaders specifies client request headers that will be sent to the authorization server.
+ Host, Method, Path, Content-Length, and Authorization headers are additionally included in the list.
+ items:
+ description: |-
+ HTTPAuthorizationServerAllowedHeaders specifies how to conditionally match against allowed headers
+ in the context of HTTP authorization. Regex support is intentionally excluded to simplify the user
+ experience and prevent potential issues. Only one of Prefix, Exact, Suffix or Contains must be provided.
+ properties:
+ contains:
+ description: Contains specifies a substring that must
+ be present in the header name.
+ type: string
+ exact:
+ description: Exact specifies a string that the header
+ name must be equal to.
+ type: string
+ ignoreCase:
+ description: IgnoreCase specifies whether string matching
+ should be case-insensitive.
+ type: boolean
+ prefix:
+ description: Prefix defines a prefix match for the header
+ name.
+ type: string
+ suffix:
+ description: Suffix defines a suffix match for a header
+ name.
+ type: string
+ type: object
+ type: array
+ allowedUpstreamHeaders:
+ description: |-
+ AllowedUpstreamHeaders specifies authorization response headers that will be added to the original client request.
+ Coexistent headers will be overridden.
+ items:
+ description: |-
+ HTTPAuthorizationServerAllowedHeaders specifies how to conditionally match against allowed headers
+ in the context of HTTP authorization. Regex support is intentionally excluded to simplify the user
+ experience and prevent potential issues. Only one of Prefix, Exact, Suffix or Contains must be provided.
+ properties:
+ contains:
+ description: Contains specifies a substring that must
+ be present in the header name.
+ type: string
+ exact:
+ description: Exact specifies a string that the header
+ name must be equal to.
+ type: string
+ ignoreCase:
+ description: IgnoreCase specifies whether string matching
+ should be case-insensitive.
+ type: boolean
+ prefix:
+ description: Prefix defines a prefix match for the header
+ name.
+ type: string
+ suffix:
+ description: Suffix defines a suffix match for a header
+ name.
+ type: string
+ type: object
+ type: array
+ pathPrefix:
+ description: PathPrefix Sets a prefix to the value of authorization
+ request header Path.
+ type: string
+ type: object
responseTimeout:
description: |-
ResponseTimeout configures maximum time to wait for a check response from the authorization server.
@@ -735,6 +808,15 @@ spec:
The string "infinity" is also a valid input and specifies no timeout.
pattern: ^(((\d*(\.\d*)?h)|(\d*(\.\d*)?m)|(\d*(\.\d*)?s)|(\d*(\.\d*)?ms)|(\d*(\.\d*)?us)|(\d*(\.\d*)?µs)|(\d*(\.\d*)?ns))+|infinity|infinite)$
type: string
+ serviceAPIType:
+ default: grpc
+ description: |-
+ ServiceAPIType sets the protocol used to communicate with
+ the external authorization server.
+ enum:
+ - http
+ - grpc
+ type: string
withRequestBody:
description: WithRequestBody specifies configuration for sending
the client request's body to authorization server.
@@ -4675,6 +4757,79 @@ spec:
set in most cases. It is intended for use only while migrating applications
from internal authorization to Contour external authorization.
type: boolean
+ httpSettings:
+ description: HTTPAuthorizationServerSettings defines configurations
+ for interacting with an external HTTP authorization server.
+ properties:
+ allowedAuthorizationHeaders:
+ description: |-
+ AllowedAuthorizationHeaders specifies client request headers that will be sent to the authorization server.
+ Host, Method, Path, Content-Length, and Authorization headers are additionally included in the list.
+ items:
+ description: |-
+ HTTPAuthorizationServerAllowedHeaders specifies how to conditionally match against allowed headers
+ in the context of HTTP authorization. Regex support is intentionally excluded to simplify the user
+ experience and prevent potential issues. Only one of Prefix, Exact, Suffix or Contains must be provided.
+ properties:
+ contains:
+ description: Contains specifies a substring that
+ must be present in the header name.
+ type: string
+ exact:
+ description: Exact specifies a string that the header
+ name must be equal to.
+ type: string
+ ignoreCase:
+ description: IgnoreCase specifies whether string
+ matching should be case-insensitive.
+ type: boolean
+ prefix:
+ description: Prefix defines a prefix match for the
+ header name.
+ type: string
+ suffix:
+ description: Suffix defines a suffix match for a
+ header name.
+ type: string
+ type: object
+ type: array
+ allowedUpstreamHeaders:
+ description: |-
+ AllowedUpstreamHeaders specifies authorization response headers that will be added to the original client request.
+ Coexistent headers will be overridden.
+ items:
+ description: |-
+ HTTPAuthorizationServerAllowedHeaders specifies how to conditionally match against allowed headers
+ in the context of HTTP authorization. Regex support is intentionally excluded to simplify the user
+ experience and prevent potential issues. Only one of Prefix, Exact, Suffix or Contains must be provided.
+ properties:
+ contains:
+ description: Contains specifies a substring that
+ must be present in the header name.
+ type: string
+ exact:
+ description: Exact specifies a string that the header
+ name must be equal to.
+ type: string
+ ignoreCase:
+ description: IgnoreCase specifies whether string
+ matching should be case-insensitive.
+ type: boolean
+ prefix:
+ description: Prefix defines a prefix match for the
+ header name.
+ type: string
+ suffix:
+ description: Suffix defines a suffix match for a
+ header name.
+ type: string
+ type: object
+ type: array
+ pathPrefix:
+ description: PathPrefix Sets a prefix to the value of
+ authorization request header Path.
+ type: string
+ type: object
responseTimeout:
description: |-
ResponseTimeout configures maximum time to wait for a check response from the authorization server.
@@ -4683,6 +4838,15 @@ spec:
The string "infinity" is also a valid input and specifies no timeout.
pattern: ^(((\d*(\.\d*)?h)|(\d*(\.\d*)?m)|(\d*(\.\d*)?s)|(\d*(\.\d*)?ms)|(\d*(\.\d*)?us)|(\d*(\.\d*)?µs)|(\d*(\.\d*)?ns))+|infinity|infinite)$
type: string
+ serviceAPIType:
+ default: grpc
+ description: |-
+ ServiceAPIType sets the protocol used to communicate with
+ the external authorization server.
+ enum:
+ - http
+ - grpc
+ type: string
withRequestBody:
description: WithRequestBody specifies configuration for sending
the client request's body to authorization server.
@@ -5298,9 +5462,9 @@ spec:
type: object
loadBalancerPolicy:
description: |-
- The policy for load balancing GRPC service requests. Note that the
+ The policy for load balancing service requests. Note that the
`Cookie` and `RequestHash` load balancing strategies cannot be used
- here.
+ here for GRPC service requests.
properties:
requestHashPolicies:
description: |-
@@ -5374,8 +5538,9 @@ spec:
protocol:
description: |-
Protocol may be used to specify (or override) the protocol used to reach this Service.
- Values may be h2 or h2c. If omitted, protocol-selection falls back on Service annotations.
+ Values may be h2, h2c or http/1.1. If omitted, protocol-selection falls back on Service annotations.
enum:
+ - http/1.1
- h2
- h2c
type: string
@@ -5391,7 +5556,7 @@ spec:
services:
description: |-
Services specifies the set of Kubernetes Service resources that
- receive GRPC extension API requests.
+ receive extension API requests.
If no weights are specified for any of the entries in
this array, traffic will be spread evenly across all the
services.
@@ -7650,6 +7815,79 @@ spec:
set in most cases. It is intended for use only while migrating applications
from internal authorization to Contour external authorization.
type: boolean
+ httpSettings:
+ description: HTTPAuthorizationServerSettings defines configurations
+ for interacting with an external HTTP authorization server.
+ properties:
+ allowedAuthorizationHeaders:
+ description: |-
+ AllowedAuthorizationHeaders specifies client request headers that will be sent to the authorization server.
+ Host, Method, Path, Content-Length, and Authorization headers are additionally included in the list.
+ items:
+ description: |-
+ HTTPAuthorizationServerAllowedHeaders specifies how to conditionally match against allowed headers
+ in the context of HTTP authorization. Regex support is intentionally excluded to simplify the user
+ experience and prevent potential issues. Only one of Prefix, Exact, Suffix or Contains must be provided.
+ properties:
+ contains:
+ description: Contains specifies a substring that
+ must be present in the header name.
+ type: string
+ exact:
+ description: Exact specifies a string that the header
+ name must be equal to.
+ type: string
+ ignoreCase:
+ description: IgnoreCase specifies whether string
+ matching should be case-insensitive.
+ type: boolean
+ prefix:
+ description: Prefix defines a prefix match for the
+ header name.
+ type: string
+ suffix:
+ description: Suffix defines a suffix match for a
+ header name.
+ type: string
+ type: object
+ type: array
+ allowedUpstreamHeaders:
+ description: |-
+ AllowedUpstreamHeaders specifies authorization response headers that will be added to the original client request.
+ Coexistent headers will be overridden.
+ items:
+ description: |-
+ HTTPAuthorizationServerAllowedHeaders specifies how to conditionally match against allowed headers
+ in the context of HTTP authorization. Regex support is intentionally excluded to simplify the user
+ experience and prevent potential issues. Only one of Prefix, Exact, Suffix or Contains must be provided.
+ properties:
+ contains:
+ description: Contains specifies a substring that
+ must be present in the header name.
+ type: string
+ exact:
+ description: Exact specifies a string that the header
+ name must be equal to.
+ type: string
+ ignoreCase:
+ description: IgnoreCase specifies whether string
+ matching should be case-insensitive.
+ type: boolean
+ prefix:
+ description: Prefix defines a prefix match for the
+ header name.
+ type: string
+ suffix:
+ description: Suffix defines a suffix match for a
+ header name.
+ type: string
+ type: object
+ type: array
+ pathPrefix:
+ description: PathPrefix Sets a prefix to the value of
+ authorization request header Path.
+ type: string
+ type: object
responseTimeout:
description: |-
ResponseTimeout configures maximum time to wait for a check response from the authorization server.
@@ -7658,6 +7896,15 @@ spec:
The string "infinity" is also a valid input and specifies no timeout.
pattern: ^(((\d*(\.\d*)?h)|(\d*(\.\d*)?m)|(\d*(\.\d*)?s)|(\d*(\.\d*)?ms)|(\d*(\.\d*)?us)|(\d*(\.\d*)?µs)|(\d*(\.\d*)?ns))+|infinity|infinite)$
type: string
+ serviceAPIType:
+ default: grpc
+ description: |-
+ ServiceAPIType sets the protocol used to communicate with
+ the external authorization server.
+ enum:
+ - http
+ - grpc
+ type: string
withRequestBody:
description: WithRequestBody specifies configuration for sending
the client request's body to authorization server.
diff --git a/examples/render/contour-deployment.yaml b/examples/render/contour-deployment.yaml
index d89221430ae..b9c74917f28 100644
--- a/examples/render/contour-deployment.yaml
+++ b/examples/render/contour-deployment.yaml
@@ -946,6 +946,79 @@ spec:
set in most cases. It is intended for use only while migrating applications
from internal authorization to Contour external authorization.
type: boolean
+ httpSettings:
+ description: HTTPAuthorizationServerSettings defines configurations
+ for interacting with an external HTTP authorization server.
+ properties:
+ allowedAuthorizationHeaders:
+ description: |-
+ AllowedAuthorizationHeaders specifies client request headers that will be sent to the authorization server.
+ Host, Method, Path, Content-Length, and Authorization headers are additionally included in the list.
+ items:
+ description: |-
+ HTTPAuthorizationServerAllowedHeaders specifies how to conditionally match against allowed headers
+ in the context of HTTP authorization. Regex support is intentionally excluded to simplify the user
+ experience and prevent potential issues. Only one of Prefix, Exact, Suffix or Contains must be provided.
+ properties:
+ contains:
+ description: Contains specifies a substring that must
+ be present in the header name.
+ type: string
+ exact:
+ description: Exact specifies a string that the header
+ name must be equal to.
+ type: string
+ ignoreCase:
+ description: IgnoreCase specifies whether string matching
+ should be case-insensitive.
+ type: boolean
+ prefix:
+ description: Prefix defines a prefix match for the header
+ name.
+ type: string
+ suffix:
+ description: Suffix defines a suffix match for a header
+ name.
+ type: string
+ type: object
+ type: array
+ allowedUpstreamHeaders:
+ description: |-
+ AllowedUpstreamHeaders specifies authorization response headers that will be added to the original client request.
+ Coexistent headers will be overridden.
+ items:
+ description: |-
+ HTTPAuthorizationServerAllowedHeaders specifies how to conditionally match against allowed headers
+ in the context of HTTP authorization. Regex support is intentionally excluded to simplify the user
+ experience and prevent potential issues. Only one of Prefix, Exact, Suffix or Contains must be provided.
+ properties:
+ contains:
+ description: Contains specifies a substring that must
+ be present in the header name.
+ type: string
+ exact:
+ description: Exact specifies a string that the header
+ name must be equal to.
+ type: string
+ ignoreCase:
+ description: IgnoreCase specifies whether string matching
+ should be case-insensitive.
+ type: boolean
+ prefix:
+ description: Prefix defines a prefix match for the header
+ name.
+ type: string
+ suffix:
+ description: Suffix defines a suffix match for a header
+ name.
+ type: string
+ type: object
+ type: array
+ pathPrefix:
+ description: PathPrefix Sets a prefix to the value of authorization
+ request header Path.
+ type: string
+ type: object
responseTimeout:
description: |-
ResponseTimeout configures maximum time to wait for a check response from the authorization server.
@@ -954,6 +1027,15 @@ spec:
The string "infinity" is also a valid input and specifies no timeout.
pattern: ^(((\d*(\.\d*)?h)|(\d*(\.\d*)?m)|(\d*(\.\d*)?s)|(\d*(\.\d*)?ms)|(\d*(\.\d*)?us)|(\d*(\.\d*)?µs)|(\d*(\.\d*)?ns))+|infinity|infinite)$
type: string
+ serviceAPIType:
+ default: grpc
+ description: |-
+ ServiceAPIType sets the protocol used to communicate with
+ the external authorization server.
+ enum:
+ - http
+ - grpc
+ type: string
withRequestBody:
description: WithRequestBody specifies configuration for sending
the client request's body to authorization server.
@@ -4894,6 +4976,79 @@ spec:
set in most cases. It is intended for use only while migrating applications
from internal authorization to Contour external authorization.
type: boolean
+ httpSettings:
+ description: HTTPAuthorizationServerSettings defines configurations
+ for interacting with an external HTTP authorization server.
+ properties:
+ allowedAuthorizationHeaders:
+ description: |-
+ AllowedAuthorizationHeaders specifies client request headers that will be sent to the authorization server.
+ Host, Method, Path, Content-Length, and Authorization headers are additionally included in the list.
+ items:
+ description: |-
+ HTTPAuthorizationServerAllowedHeaders specifies how to conditionally match against allowed headers
+ in the context of HTTP authorization. Regex support is intentionally excluded to simplify the user
+ experience and prevent potential issues. Only one of Prefix, Exact, Suffix or Contains must be provided.
+ properties:
+ contains:
+ description: Contains specifies a substring that
+ must be present in the header name.
+ type: string
+ exact:
+ description: Exact specifies a string that the header
+ name must be equal to.
+ type: string
+ ignoreCase:
+ description: IgnoreCase specifies whether string
+ matching should be case-insensitive.
+ type: boolean
+ prefix:
+ description: Prefix defines a prefix match for the
+ header name.
+ type: string
+ suffix:
+ description: Suffix defines a suffix match for a
+ header name.
+ type: string
+ type: object
+ type: array
+ allowedUpstreamHeaders:
+ description: |-
+ AllowedUpstreamHeaders specifies authorization response headers that will be added to the original client request.
+ Coexistent headers will be overridden.
+ items:
+ description: |-
+ HTTPAuthorizationServerAllowedHeaders specifies how to conditionally match against allowed headers
+ in the context of HTTP authorization. Regex support is intentionally excluded to simplify the user
+ experience and prevent potential issues. Only one of Prefix, Exact, Suffix or Contains must be provided.
+ properties:
+ contains:
+ description: Contains specifies a substring that
+ must be present in the header name.
+ type: string
+ exact:
+ description: Exact specifies a string that the header
+ name must be equal to.
+ type: string
+ ignoreCase:
+ description: IgnoreCase specifies whether string
+ matching should be case-insensitive.
+ type: boolean
+ prefix:
+ description: Prefix defines a prefix match for the
+ header name.
+ type: string
+ suffix:
+ description: Suffix defines a suffix match for a
+ header name.
+ type: string
+ type: object
+ type: array
+ pathPrefix:
+ description: PathPrefix Sets a prefix to the value of
+ authorization request header Path.
+ type: string
+ type: object
responseTimeout:
description: |-
ResponseTimeout configures maximum time to wait for a check response from the authorization server.
@@ -4902,6 +5057,15 @@ spec:
The string "infinity" is also a valid input and specifies no timeout.
pattern: ^(((\d*(\.\d*)?h)|(\d*(\.\d*)?m)|(\d*(\.\d*)?s)|(\d*(\.\d*)?ms)|(\d*(\.\d*)?us)|(\d*(\.\d*)?µs)|(\d*(\.\d*)?ns))+|infinity|infinite)$
type: string
+ serviceAPIType:
+ default: grpc
+ description: |-
+ ServiceAPIType sets the protocol used to communicate with
+ the external authorization server.
+ enum:
+ - http
+ - grpc
+ type: string
withRequestBody:
description: WithRequestBody specifies configuration for sending
the client request's body to authorization server.
@@ -5517,9 +5681,9 @@ spec:
type: object
loadBalancerPolicy:
description: |-
- The policy for load balancing GRPC service requests. Note that the
+ The policy for load balancing service requests. Note that the
`Cookie` and `RequestHash` load balancing strategies cannot be used
- here.
+ here for GRPC service requests.
properties:
requestHashPolicies:
description: |-
@@ -5593,8 +5757,9 @@ spec:
protocol:
description: |-
Protocol may be used to specify (or override) the protocol used to reach this Service.
- Values may be h2 or h2c. If omitted, protocol-selection falls back on Service annotations.
+ Values may be h2, h2c or http/1.1. If omitted, protocol-selection falls back on Service annotations.
enum:
+ - http/1.1
- h2
- h2c
type: string
@@ -5610,7 +5775,7 @@ spec:
services:
description: |-
Services specifies the set of Kubernetes Service resources that
- receive GRPC extension API requests.
+ receive extension API requests.
If no weights are specified for any of the entries in
this array, traffic will be spread evenly across all the
services.
@@ -7869,6 +8034,79 @@ spec:
set in most cases. It is intended for use only while migrating applications
from internal authorization to Contour external authorization.
type: boolean
+ httpSettings:
+ description: HTTPAuthorizationServerSettings defines configurations
+ for interacting with an external HTTP authorization server.
+ properties:
+ allowedAuthorizationHeaders:
+ description: |-
+ AllowedAuthorizationHeaders specifies client request headers that will be sent to the authorization server.
+ Host, Method, Path, Content-Length, and Authorization headers are additionally included in the list.
+ items:
+ description: |-
+ HTTPAuthorizationServerAllowedHeaders specifies how to conditionally match against allowed headers
+ in the context of HTTP authorization. Regex support is intentionally excluded to simplify the user
+ experience and prevent potential issues. Only one of Prefix, Exact, Suffix or Contains must be provided.
+ properties:
+ contains:
+ description: Contains specifies a substring that
+ must be present in the header name.
+ type: string
+ exact:
+ description: Exact specifies a string that the header
+ name must be equal to.
+ type: string
+ ignoreCase:
+ description: IgnoreCase specifies whether string
+ matching should be case-insensitive.
+ type: boolean
+ prefix:
+ description: Prefix defines a prefix match for the
+ header name.
+ type: string
+ suffix:
+ description: Suffix defines a suffix match for a
+ header name.
+ type: string
+ type: object
+ type: array
+ allowedUpstreamHeaders:
+ description: |-
+ AllowedUpstreamHeaders specifies authorization response headers that will be added to the original client request.
+ Coexistent headers will be overridden.
+ items:
+ description: |-
+ HTTPAuthorizationServerAllowedHeaders specifies how to conditionally match against allowed headers
+ in the context of HTTP authorization. Regex support is intentionally excluded to simplify the user
+ experience and prevent potential issues. Only one of Prefix, Exact, Suffix or Contains must be provided.
+ properties:
+ contains:
+ description: Contains specifies a substring that
+ must be present in the header name.
+ type: string
+ exact:
+ description: Exact specifies a string that the header
+ name must be equal to.
+ type: string
+ ignoreCase:
+ description: IgnoreCase specifies whether string
+ matching should be case-insensitive.
+ type: boolean
+ prefix:
+ description: Prefix defines a prefix match for the
+ header name.
+ type: string
+ suffix:
+ description: Suffix defines a suffix match for a
+ header name.
+ type: string
+ type: object
+ type: array
+ pathPrefix:
+ description: PathPrefix Sets a prefix to the value of
+ authorization request header Path.
+ type: string
+ type: object
responseTimeout:
description: |-
ResponseTimeout configures maximum time to wait for a check response from the authorization server.
@@ -7877,6 +8115,15 @@ spec:
The string "infinity" is also a valid input and specifies no timeout.
pattern: ^(((\d*(\.\d*)?h)|(\d*(\.\d*)?m)|(\d*(\.\d*)?s)|(\d*(\.\d*)?ms)|(\d*(\.\d*)?us)|(\d*(\.\d*)?µs)|(\d*(\.\d*)?ns))+|infinity|infinite)$
type: string
+ serviceAPIType:
+ default: grpc
+ description: |-
+ ServiceAPIType sets the protocol used to communicate with
+ the external authorization server.
+ enum:
+ - http
+ - grpc
+ type: string
withRequestBody:
description: WithRequestBody specifies configuration for sending
the client request's body to authorization server.
diff --git a/examples/render/contour-gateway-provisioner.yaml b/examples/render/contour-gateway-provisioner.yaml
index 2496dac11ac..4e34ef1d20e 100644
--- a/examples/render/contour-gateway-provisioner.yaml
+++ b/examples/render/contour-gateway-provisioner.yaml
@@ -738,6 +738,79 @@ spec:
set in most cases. It is intended for use only while migrating applications
from internal authorization to Contour external authorization.
type: boolean
+ httpSettings:
+ description: HTTPAuthorizationServerSettings defines configurations
+ for interacting with an external HTTP authorization server.
+ properties:
+ allowedAuthorizationHeaders:
+ description: |-
+ AllowedAuthorizationHeaders specifies client request headers that will be sent to the authorization server.
+ Host, Method, Path, Content-Length, and Authorization headers are additionally included in the list.
+ items:
+ description: |-
+ HTTPAuthorizationServerAllowedHeaders specifies how to conditionally match against allowed headers
+ in the context of HTTP authorization. Regex support is intentionally excluded to simplify the user
+ experience and prevent potential issues. Only one of Prefix, Exact, Suffix or Contains must be provided.
+ properties:
+ contains:
+ description: Contains specifies a substring that must
+ be present in the header name.
+ type: string
+ exact:
+ description: Exact specifies a string that the header
+ name must be equal to.
+ type: string
+ ignoreCase:
+ description: IgnoreCase specifies whether string matching
+ should be case-insensitive.
+ type: boolean
+ prefix:
+ description: Prefix defines a prefix match for the header
+ name.
+ type: string
+ suffix:
+ description: Suffix defines a suffix match for a header
+ name.
+ type: string
+ type: object
+ type: array
+ allowedUpstreamHeaders:
+ description: |-
+ AllowedUpstreamHeaders specifies authorization response headers that will be added to the original client request.
+ Coexistent headers will be overridden.
+ items:
+ description: |-
+ HTTPAuthorizationServerAllowedHeaders specifies how to conditionally match against allowed headers
+ in the context of HTTP authorization. Regex support is intentionally excluded to simplify the user
+ experience and prevent potential issues. Only one of Prefix, Exact, Suffix or Contains must be provided.
+ properties:
+ contains:
+ description: Contains specifies a substring that must
+ be present in the header name.
+ type: string
+ exact:
+ description: Exact specifies a string that the header
+ name must be equal to.
+ type: string
+ ignoreCase:
+ description: IgnoreCase specifies whether string matching
+ should be case-insensitive.
+ type: boolean
+ prefix:
+ description: Prefix defines a prefix match for the header
+ name.
+ type: string
+ suffix:
+ description: Suffix defines a suffix match for a header
+ name.
+ type: string
+ type: object
+ type: array
+ pathPrefix:
+ description: PathPrefix Sets a prefix to the value of authorization
+ request header Path.
+ type: string
+ type: object
responseTimeout:
description: |-
ResponseTimeout configures maximum time to wait for a check response from the authorization server.
@@ -746,6 +819,15 @@ spec:
The string "infinity" is also a valid input and specifies no timeout.
pattern: ^(((\d*(\.\d*)?h)|(\d*(\.\d*)?m)|(\d*(\.\d*)?s)|(\d*(\.\d*)?ms)|(\d*(\.\d*)?us)|(\d*(\.\d*)?µs)|(\d*(\.\d*)?ns))+|infinity|infinite)$
type: string
+ serviceAPIType:
+ default: grpc
+ description: |-
+ ServiceAPIType sets the protocol used to communicate with
+ the external authorization server.
+ enum:
+ - http
+ - grpc
+ type: string
withRequestBody:
description: WithRequestBody specifies configuration for sending
the client request's body to authorization server.
@@ -4686,6 +4768,79 @@ spec:
set in most cases. It is intended for use only while migrating applications
from internal authorization to Contour external authorization.
type: boolean
+ httpSettings:
+ description: HTTPAuthorizationServerSettings defines configurations
+ for interacting with an external HTTP authorization server.
+ properties:
+ allowedAuthorizationHeaders:
+ description: |-
+ AllowedAuthorizationHeaders specifies client request headers that will be sent to the authorization server.
+ Host, Method, Path, Content-Length, and Authorization headers are additionally included in the list.
+ items:
+ description: |-
+ HTTPAuthorizationServerAllowedHeaders specifies how to conditionally match against allowed headers
+ in the context of HTTP authorization. Regex support is intentionally excluded to simplify the user
+ experience and prevent potential issues. Only one of Prefix, Exact, Suffix or Contains must be provided.
+ properties:
+ contains:
+ description: Contains specifies a substring that
+ must be present in the header name.
+ type: string
+ exact:
+ description: Exact specifies a string that the header
+ name must be equal to.
+ type: string
+ ignoreCase:
+ description: IgnoreCase specifies whether string
+ matching should be case-insensitive.
+ type: boolean
+ prefix:
+ description: Prefix defines a prefix match for the
+ header name.
+ type: string
+ suffix:
+ description: Suffix defines a suffix match for a
+ header name.
+ type: string
+ type: object
+ type: array
+ allowedUpstreamHeaders:
+ description: |-
+ AllowedUpstreamHeaders specifies authorization response headers that will be added to the original client request.
+ Coexistent headers will be overridden.
+ items:
+ description: |-
+ HTTPAuthorizationServerAllowedHeaders specifies how to conditionally match against allowed headers
+ in the context of HTTP authorization. Regex support is intentionally excluded to simplify the user
+ experience and prevent potential issues. Only one of Prefix, Exact, Suffix or Contains must be provided.
+ properties:
+ contains:
+ description: Contains specifies a substring that
+ must be present in the header name.
+ type: string
+ exact:
+ description: Exact specifies a string that the header
+ name must be equal to.
+ type: string
+ ignoreCase:
+ description: IgnoreCase specifies whether string
+ matching should be case-insensitive.
+ type: boolean
+ prefix:
+ description: Prefix defines a prefix match for the
+ header name.
+ type: string
+ suffix:
+ description: Suffix defines a suffix match for a
+ header name.
+ type: string
+ type: object
+ type: array
+ pathPrefix:
+ description: PathPrefix Sets a prefix to the value of
+ authorization request header Path.
+ type: string
+ type: object
responseTimeout:
description: |-
ResponseTimeout configures maximum time to wait for a check response from the authorization server.
@@ -4694,6 +4849,15 @@ spec:
The string "infinity" is also a valid input and specifies no timeout.
pattern: ^(((\d*(\.\d*)?h)|(\d*(\.\d*)?m)|(\d*(\.\d*)?s)|(\d*(\.\d*)?ms)|(\d*(\.\d*)?us)|(\d*(\.\d*)?µs)|(\d*(\.\d*)?ns))+|infinity|infinite)$
type: string
+ serviceAPIType:
+ default: grpc
+ description: |-
+ ServiceAPIType sets the protocol used to communicate with
+ the external authorization server.
+ enum:
+ - http
+ - grpc
+ type: string
withRequestBody:
description: WithRequestBody specifies configuration for sending
the client request's body to authorization server.
@@ -5309,9 +5473,9 @@ spec:
type: object
loadBalancerPolicy:
description: |-
- The policy for load balancing GRPC service requests. Note that the
+ The policy for load balancing service requests. Note that the
`Cookie` and `RequestHash` load balancing strategies cannot be used
- here.
+ here for GRPC service requests.
properties:
requestHashPolicies:
description: |-
@@ -5385,8 +5549,9 @@ spec:
protocol:
description: |-
Protocol may be used to specify (or override) the protocol used to reach this Service.
- Values may be h2 or h2c. If omitted, protocol-selection falls back on Service annotations.
+ Values may be h2, h2c or http/1.1. If omitted, protocol-selection falls back on Service annotations.
enum:
+ - http/1.1
- h2
- h2c
type: string
@@ -5402,7 +5567,7 @@ spec:
services:
description: |-
Services specifies the set of Kubernetes Service resources that
- receive GRPC extension API requests.
+ receive extension API requests.
If no weights are specified for any of the entries in
this array, traffic will be spread evenly across all the
services.
@@ -7661,6 +7826,79 @@ spec:
set in most cases. It is intended for use only while migrating applications
from internal authorization to Contour external authorization.
type: boolean
+ httpSettings:
+ description: HTTPAuthorizationServerSettings defines configurations
+ for interacting with an external HTTP authorization server.
+ properties:
+ allowedAuthorizationHeaders:
+ description: |-
+ AllowedAuthorizationHeaders specifies client request headers that will be sent to the authorization server.
+ Host, Method, Path, Content-Length, and Authorization headers are additionally included in the list.
+ items:
+ description: |-
+ HTTPAuthorizationServerAllowedHeaders specifies how to conditionally match against allowed headers
+ in the context of HTTP authorization. Regex support is intentionally excluded to simplify the user
+ experience and prevent potential issues. Only one of Prefix, Exact, Suffix or Contains must be provided.
+ properties:
+ contains:
+ description: Contains specifies a substring that
+ must be present in the header name.
+ type: string
+ exact:
+ description: Exact specifies a string that the header
+ name must be equal to.
+ type: string
+ ignoreCase:
+ description: IgnoreCase specifies whether string
+ matching should be case-insensitive.
+ type: boolean
+ prefix:
+ description: Prefix defines a prefix match for the
+ header name.
+ type: string
+ suffix:
+ description: Suffix defines a suffix match for a
+ header name.
+ type: string
+ type: object
+ type: array
+ allowedUpstreamHeaders:
+ description: |-
+ AllowedUpstreamHeaders specifies authorization response headers that will be added to the original client request.
+ Coexistent headers will be overridden.
+ items:
+ description: |-
+ HTTPAuthorizationServerAllowedHeaders specifies how to conditionally match against allowed headers
+ in the context of HTTP authorization. Regex support is intentionally excluded to simplify the user
+ experience and prevent potential issues. Only one of Prefix, Exact, Suffix or Contains must be provided.
+ properties:
+ contains:
+ description: Contains specifies a substring that
+ must be present in the header name.
+ type: string
+ exact:
+ description: Exact specifies a string that the header
+ name must be equal to.
+ type: string
+ ignoreCase:
+ description: IgnoreCase specifies whether string
+ matching should be case-insensitive.
+ type: boolean
+ prefix:
+ description: Prefix defines a prefix match for the
+ header name.
+ type: string
+ suffix:
+ description: Suffix defines a suffix match for a
+ header name.
+ type: string
+ type: object
+ type: array
+ pathPrefix:
+ description: PathPrefix Sets a prefix to the value of
+ authorization request header Path.
+ type: string
+ type: object
responseTimeout:
description: |-
ResponseTimeout configures maximum time to wait for a check response from the authorization server.
@@ -7669,6 +7907,15 @@ spec:
The string "infinity" is also a valid input and specifies no timeout.
pattern: ^(((\d*(\.\d*)?h)|(\d*(\.\d*)?m)|(\d*(\.\d*)?s)|(\d*(\.\d*)?ms)|(\d*(\.\d*)?us)|(\d*(\.\d*)?µs)|(\d*(\.\d*)?ns))+|infinity|infinite)$
type: string
+ serviceAPIType:
+ default: grpc
+ description: |-
+ ServiceAPIType sets the protocol used to communicate with
+ the external authorization server.
+ enum:
+ - http
+ - grpc
+ type: string
withRequestBody:
description: WithRequestBody specifies configuration for sending
the client request's body to authorization server.
diff --git a/examples/render/contour-gateway.yaml b/examples/render/contour-gateway.yaml
index 8c125a49e2c..b9d01fb463c 100644
--- a/examples/render/contour-gateway.yaml
+++ b/examples/render/contour-gateway.yaml
@@ -763,6 +763,79 @@ spec:
set in most cases. It is intended for use only while migrating applications
from internal authorization to Contour external authorization.
type: boolean
+ httpSettings:
+ description: HTTPAuthorizationServerSettings defines configurations
+ for interacting with an external HTTP authorization server.
+ properties:
+ allowedAuthorizationHeaders:
+ description: |-
+ AllowedAuthorizationHeaders specifies client request headers that will be sent to the authorization server.
+ Host, Method, Path, Content-Length, and Authorization headers are additionally included in the list.
+ items:
+ description: |-
+ HTTPAuthorizationServerAllowedHeaders specifies how to conditionally match against allowed headers
+ in the context of HTTP authorization. Regex support is intentionally excluded to simplify the user
+ experience and prevent potential issues. Only one of Prefix, Exact, Suffix or Contains must be provided.
+ properties:
+ contains:
+ description: Contains specifies a substring that must
+ be present in the header name.
+ type: string
+ exact:
+ description: Exact specifies a string that the header
+ name must be equal to.
+ type: string
+ ignoreCase:
+ description: IgnoreCase specifies whether string matching
+ should be case-insensitive.
+ type: boolean
+ prefix:
+ description: Prefix defines a prefix match for the header
+ name.
+ type: string
+ suffix:
+ description: Suffix defines a suffix match for a header
+ name.
+ type: string
+ type: object
+ type: array
+ allowedUpstreamHeaders:
+ description: |-
+ AllowedUpstreamHeaders specifies authorization response headers that will be added to the original client request.
+ Coexistent headers will be overridden.
+ items:
+ description: |-
+ HTTPAuthorizationServerAllowedHeaders specifies how to conditionally match against allowed headers
+ in the context of HTTP authorization. Regex support is intentionally excluded to simplify the user
+ experience and prevent potential issues. Only one of Prefix, Exact, Suffix or Contains must be provided.
+ properties:
+ contains:
+ description: Contains specifies a substring that must
+ be present in the header name.
+ type: string
+ exact:
+ description: Exact specifies a string that the header
+ name must be equal to.
+ type: string
+ ignoreCase:
+ description: IgnoreCase specifies whether string matching
+ should be case-insensitive.
+ type: boolean
+ prefix:
+ description: Prefix defines a prefix match for the header
+ name.
+ type: string
+ suffix:
+ description: Suffix defines a suffix match for a header
+ name.
+ type: string
+ type: object
+ type: array
+ pathPrefix:
+ description: PathPrefix Sets a prefix to the value of authorization
+ request header Path.
+ type: string
+ type: object
responseTimeout:
description: |-
ResponseTimeout configures maximum time to wait for a check response from the authorization server.
@@ -771,6 +844,15 @@ spec:
The string "infinity" is also a valid input and specifies no timeout.
pattern: ^(((\d*(\.\d*)?h)|(\d*(\.\d*)?m)|(\d*(\.\d*)?s)|(\d*(\.\d*)?ms)|(\d*(\.\d*)?us)|(\d*(\.\d*)?µs)|(\d*(\.\d*)?ns))+|infinity|infinite)$
type: string
+ serviceAPIType:
+ default: grpc
+ description: |-
+ ServiceAPIType sets the protocol used to communicate with
+ the external authorization server.
+ enum:
+ - http
+ - grpc
+ type: string
withRequestBody:
description: WithRequestBody specifies configuration for sending
the client request's body to authorization server.
@@ -4711,6 +4793,79 @@ spec:
set in most cases. It is intended for use only while migrating applications
from internal authorization to Contour external authorization.
type: boolean
+ httpSettings:
+ description: HTTPAuthorizationServerSettings defines configurations
+ for interacting with an external HTTP authorization server.
+ properties:
+ allowedAuthorizationHeaders:
+ description: |-
+ AllowedAuthorizationHeaders specifies client request headers that will be sent to the authorization server.
+ Host, Method, Path, Content-Length, and Authorization headers are additionally included in the list.
+ items:
+ description: |-
+ HTTPAuthorizationServerAllowedHeaders specifies how to conditionally match against allowed headers
+ in the context of HTTP authorization. Regex support is intentionally excluded to simplify the user
+ experience and prevent potential issues. Only one of Prefix, Exact, Suffix or Contains must be provided.
+ properties:
+ contains:
+ description: Contains specifies a substring that
+ must be present in the header name.
+ type: string
+ exact:
+ description: Exact specifies a string that the header
+ name must be equal to.
+ type: string
+ ignoreCase:
+ description: IgnoreCase specifies whether string
+ matching should be case-insensitive.
+ type: boolean
+ prefix:
+ description: Prefix defines a prefix match for the
+ header name.
+ type: string
+ suffix:
+ description: Suffix defines a suffix match for a
+ header name.
+ type: string
+ type: object
+ type: array
+ allowedUpstreamHeaders:
+ description: |-
+ AllowedUpstreamHeaders specifies authorization response headers that will be added to the original client request.
+ Coexistent headers will be overridden.
+ items:
+ description: |-
+ HTTPAuthorizationServerAllowedHeaders specifies how to conditionally match against allowed headers
+ in the context of HTTP authorization. Regex support is intentionally excluded to simplify the user
+ experience and prevent potential issues. Only one of Prefix, Exact, Suffix or Contains must be provided.
+ properties:
+ contains:
+ description: Contains specifies a substring that
+ must be present in the header name.
+ type: string
+ exact:
+ description: Exact specifies a string that the header
+ name must be equal to.
+ type: string
+ ignoreCase:
+ description: IgnoreCase specifies whether string
+ matching should be case-insensitive.
+ type: boolean
+ prefix:
+ description: Prefix defines a prefix match for the
+ header name.
+ type: string
+ suffix:
+ description: Suffix defines a suffix match for a
+ header name.
+ type: string
+ type: object
+ type: array
+ pathPrefix:
+ description: PathPrefix Sets a prefix to the value of
+ authorization request header Path.
+ type: string
+ type: object
responseTimeout:
description: |-
ResponseTimeout configures maximum time to wait for a check response from the authorization server.
@@ -4719,6 +4874,15 @@ spec:
The string "infinity" is also a valid input and specifies no timeout.
pattern: ^(((\d*(\.\d*)?h)|(\d*(\.\d*)?m)|(\d*(\.\d*)?s)|(\d*(\.\d*)?ms)|(\d*(\.\d*)?us)|(\d*(\.\d*)?µs)|(\d*(\.\d*)?ns))+|infinity|infinite)$
type: string
+ serviceAPIType:
+ default: grpc
+ description: |-
+ ServiceAPIType sets the protocol used to communicate with
+ the external authorization server.
+ enum:
+ - http
+ - grpc
+ type: string
withRequestBody:
description: WithRequestBody specifies configuration for sending
the client request's body to authorization server.
@@ -5334,9 +5498,9 @@ spec:
type: object
loadBalancerPolicy:
description: |-
- The policy for load balancing GRPC service requests. Note that the
+ The policy for load balancing service requests. Note that the
`Cookie` and `RequestHash` load balancing strategies cannot be used
- here.
+ here for GRPC service requests.
properties:
requestHashPolicies:
description: |-
@@ -5410,8 +5574,9 @@ spec:
protocol:
description: |-
Protocol may be used to specify (or override) the protocol used to reach this Service.
- Values may be h2 or h2c. If omitted, protocol-selection falls back on Service annotations.
+ Values may be h2, h2c or http/1.1. If omitted, protocol-selection falls back on Service annotations.
enum:
+ - http/1.1
- h2
- h2c
type: string
@@ -5427,7 +5592,7 @@ spec:
services:
description: |-
Services specifies the set of Kubernetes Service resources that
- receive GRPC extension API requests.
+ receive extension API requests.
If no weights are specified for any of the entries in
this array, traffic will be spread evenly across all the
services.
@@ -7686,6 +7851,79 @@ spec:
set in most cases. It is intended for use only while migrating applications
from internal authorization to Contour external authorization.
type: boolean
+ httpSettings:
+ description: HTTPAuthorizationServerSettings defines configurations
+ for interacting with an external HTTP authorization server.
+ properties:
+ allowedAuthorizationHeaders:
+ description: |-
+ AllowedAuthorizationHeaders specifies client request headers that will be sent to the authorization server.
+ Host, Method, Path, Content-Length, and Authorization headers are additionally included in the list.
+ items:
+ description: |-
+ HTTPAuthorizationServerAllowedHeaders specifies how to conditionally match against allowed headers
+ in the context of HTTP authorization. Regex support is intentionally excluded to simplify the user
+ experience and prevent potential issues. Only one of Prefix, Exact, Suffix or Contains must be provided.
+ properties:
+ contains:
+ description: Contains specifies a substring that
+ must be present in the header name.
+ type: string
+ exact:
+ description: Exact specifies a string that the header
+ name must be equal to.
+ type: string
+ ignoreCase:
+ description: IgnoreCase specifies whether string
+ matching should be case-insensitive.
+ type: boolean
+ prefix:
+ description: Prefix defines a prefix match for the
+ header name.
+ type: string
+ suffix:
+ description: Suffix defines a suffix match for a
+ header name.
+ type: string
+ type: object
+ type: array
+ allowedUpstreamHeaders:
+ description: |-
+ AllowedUpstreamHeaders specifies authorization response headers that will be added to the original client request.
+ Coexistent headers will be overridden.
+ items:
+ description: |-
+ HTTPAuthorizationServerAllowedHeaders specifies how to conditionally match against allowed headers
+ in the context of HTTP authorization. Regex support is intentionally excluded to simplify the user
+ experience and prevent potential issues. Only one of Prefix, Exact, Suffix or Contains must be provided.
+ properties:
+ contains:
+ description: Contains specifies a substring that
+ must be present in the header name.
+ type: string
+ exact:
+ description: Exact specifies a string that the header
+ name must be equal to.
+ type: string
+ ignoreCase:
+ description: IgnoreCase specifies whether string
+ matching should be case-insensitive.
+ type: boolean
+ prefix:
+ description: Prefix defines a prefix match for the
+ header name.
+ type: string
+ suffix:
+ description: Suffix defines a suffix match for a
+ header name.
+ type: string
+ type: object
+ type: array
+ pathPrefix:
+ description: PathPrefix Sets a prefix to the value of
+ authorization request header Path.
+ type: string
+ type: object
responseTimeout:
description: |-
ResponseTimeout configures maximum time to wait for a check response from the authorization server.
@@ -7694,6 +7932,15 @@ spec:
The string "infinity" is also a valid input and specifies no timeout.
pattern: ^(((\d*(\.\d*)?h)|(\d*(\.\d*)?m)|(\d*(\.\d*)?s)|(\d*(\.\d*)?ms)|(\d*(\.\d*)?us)|(\d*(\.\d*)?µs)|(\d*(\.\d*)?ns))+|infinity|infinite)$
type: string
+ serviceAPIType:
+ default: grpc
+ description: |-
+ ServiceAPIType sets the protocol used to communicate with
+ the external authorization server.
+ enum:
+ - http
+ - grpc
+ type: string
withRequestBody:
description: WithRequestBody specifies configuration for sending
the client request's body to authorization server.
diff --git a/examples/render/contour.yaml b/examples/render/contour.yaml
index 837cf752cef..15f3614f10c 100644
--- a/examples/render/contour.yaml
+++ b/examples/render/contour.yaml
@@ -946,6 +946,79 @@ spec:
set in most cases. It is intended for use only while migrating applications
from internal authorization to Contour external authorization.
type: boolean
+ httpSettings:
+ description: HTTPAuthorizationServerSettings defines configurations
+ for interacting with an external HTTP authorization server.
+ properties:
+ allowedAuthorizationHeaders:
+ description: |-
+ AllowedAuthorizationHeaders specifies client request headers that will be sent to the authorization server.
+ Host, Method, Path, Content-Length, and Authorization headers are additionally included in the list.
+ items:
+ description: |-
+ HTTPAuthorizationServerAllowedHeaders specifies how to conditionally match against allowed headers
+ in the context of HTTP authorization. Regex support is intentionally excluded to simplify the user
+ experience and prevent potential issues. Only one of Prefix, Exact, Suffix or Contains must be provided.
+ properties:
+ contains:
+ description: Contains specifies a substring that must
+ be present in the header name.
+ type: string
+ exact:
+ description: Exact specifies a string that the header
+ name must be equal to.
+ type: string
+ ignoreCase:
+ description: IgnoreCase specifies whether string matching
+ should be case-insensitive.
+ type: boolean
+ prefix:
+ description: Prefix defines a prefix match for the header
+ name.
+ type: string
+ suffix:
+ description: Suffix defines a suffix match for a header
+ name.
+ type: string
+ type: object
+ type: array
+ allowedUpstreamHeaders:
+ description: |-
+ AllowedUpstreamHeaders specifies authorization response headers that will be added to the original client request.
+ Coexistent headers will be overridden.
+ items:
+ description: |-
+ HTTPAuthorizationServerAllowedHeaders specifies how to conditionally match against allowed headers
+ in the context of HTTP authorization. Regex support is intentionally excluded to simplify the user
+ experience and prevent potential issues. Only one of Prefix, Exact, Suffix or Contains must be provided.
+ properties:
+ contains:
+ description: Contains specifies a substring that must
+ be present in the header name.
+ type: string
+ exact:
+ description: Exact specifies a string that the header
+ name must be equal to.
+ type: string
+ ignoreCase:
+ description: IgnoreCase specifies whether string matching
+ should be case-insensitive.
+ type: boolean
+ prefix:
+ description: Prefix defines a prefix match for the header
+ name.
+ type: string
+ suffix:
+ description: Suffix defines a suffix match for a header
+ name.
+ type: string
+ type: object
+ type: array
+ pathPrefix:
+ description: PathPrefix Sets a prefix to the value of authorization
+ request header Path.
+ type: string
+ type: object
responseTimeout:
description: |-
ResponseTimeout configures maximum time to wait for a check response from the authorization server.
@@ -954,6 +1027,15 @@ spec:
The string "infinity" is also a valid input and specifies no timeout.
pattern: ^(((\d*(\.\d*)?h)|(\d*(\.\d*)?m)|(\d*(\.\d*)?s)|(\d*(\.\d*)?ms)|(\d*(\.\d*)?us)|(\d*(\.\d*)?µs)|(\d*(\.\d*)?ns))+|infinity|infinite)$
type: string
+ serviceAPIType:
+ default: grpc
+ description: |-
+ ServiceAPIType sets the protocol used to communicate with
+ the external authorization server.
+ enum:
+ - http
+ - grpc
+ type: string
withRequestBody:
description: WithRequestBody specifies configuration for sending
the client request's body to authorization server.
@@ -4894,6 +4976,79 @@ spec:
set in most cases. It is intended for use only while migrating applications
from internal authorization to Contour external authorization.
type: boolean
+ httpSettings:
+ description: HTTPAuthorizationServerSettings defines configurations
+ for interacting with an external HTTP authorization server.
+ properties:
+ allowedAuthorizationHeaders:
+ description: |-
+ AllowedAuthorizationHeaders specifies client request headers that will be sent to the authorization server.
+ Host, Method, Path, Content-Length, and Authorization headers are additionally included in the list.
+ items:
+ description: |-
+ HTTPAuthorizationServerAllowedHeaders specifies how to conditionally match against allowed headers
+ in the context of HTTP authorization. Regex support is intentionally excluded to simplify the user
+ experience and prevent potential issues. Only one of Prefix, Exact, Suffix or Contains must be provided.
+ properties:
+ contains:
+ description: Contains specifies a substring that
+ must be present in the header name.
+ type: string
+ exact:
+ description: Exact specifies a string that the header
+ name must be equal to.
+ type: string
+ ignoreCase:
+ description: IgnoreCase specifies whether string
+ matching should be case-insensitive.
+ type: boolean
+ prefix:
+ description: Prefix defines a prefix match for the
+ header name.
+ type: string
+ suffix:
+ description: Suffix defines a suffix match for a
+ header name.
+ type: string
+ type: object
+ type: array
+ allowedUpstreamHeaders:
+ description: |-
+ AllowedUpstreamHeaders specifies authorization response headers that will be added to the original client request.
+ Coexistent headers will be overridden.
+ items:
+ description: |-
+ HTTPAuthorizationServerAllowedHeaders specifies how to conditionally match against allowed headers
+ in the context of HTTP authorization. Regex support is intentionally excluded to simplify the user
+ experience and prevent potential issues. Only one of Prefix, Exact, Suffix or Contains must be provided.
+ properties:
+ contains:
+ description: Contains specifies a substring that
+ must be present in the header name.
+ type: string
+ exact:
+ description: Exact specifies a string that the header
+ name must be equal to.
+ type: string
+ ignoreCase:
+ description: IgnoreCase specifies whether string
+ matching should be case-insensitive.
+ type: boolean
+ prefix:
+ description: Prefix defines a prefix match for the
+ header name.
+ type: string
+ suffix:
+ description: Suffix defines a suffix match for a
+ header name.
+ type: string
+ type: object
+ type: array
+ pathPrefix:
+ description: PathPrefix Sets a prefix to the value of
+ authorization request header Path.
+ type: string
+ type: object
responseTimeout:
description: |-
ResponseTimeout configures maximum time to wait for a check response from the authorization server.
@@ -4902,6 +5057,15 @@ spec:
The string "infinity" is also a valid input and specifies no timeout.
pattern: ^(((\d*(\.\d*)?h)|(\d*(\.\d*)?m)|(\d*(\.\d*)?s)|(\d*(\.\d*)?ms)|(\d*(\.\d*)?us)|(\d*(\.\d*)?µs)|(\d*(\.\d*)?ns))+|infinity|infinite)$
type: string
+ serviceAPIType:
+ default: grpc
+ description: |-
+ ServiceAPIType sets the protocol used to communicate with
+ the external authorization server.
+ enum:
+ - http
+ - grpc
+ type: string
withRequestBody:
description: WithRequestBody specifies configuration for sending
the client request's body to authorization server.
@@ -5517,9 +5681,9 @@ spec:
type: object
loadBalancerPolicy:
description: |-
- The policy for load balancing GRPC service requests. Note that the
+ The policy for load balancing service requests. Note that the
`Cookie` and `RequestHash` load balancing strategies cannot be used
- here.
+ here for GRPC service requests.
properties:
requestHashPolicies:
description: |-
@@ -5593,8 +5757,9 @@ spec:
protocol:
description: |-
Protocol may be used to specify (or override) the protocol used to reach this Service.
- Values may be h2 or h2c. If omitted, protocol-selection falls back on Service annotations.
+ Values may be h2, h2c or http/1.1. If omitted, protocol-selection falls back on Service annotations.
enum:
+ - http/1.1
- h2
- h2c
type: string
@@ -5610,7 +5775,7 @@ spec:
services:
description: |-
Services specifies the set of Kubernetes Service resources that
- receive GRPC extension API requests.
+ receive extension API requests.
If no weights are specified for any of the entries in
this array, traffic will be spread evenly across all the
services.
@@ -7869,6 +8034,79 @@ spec:
set in most cases. It is intended for use only while migrating applications
from internal authorization to Contour external authorization.
type: boolean
+ httpSettings:
+ description: HTTPAuthorizationServerSettings defines configurations
+ for interacting with an external HTTP authorization server.
+ properties:
+ allowedAuthorizationHeaders:
+ description: |-
+ AllowedAuthorizationHeaders specifies client request headers that will be sent to the authorization server.
+ Host, Method, Path, Content-Length, and Authorization headers are additionally included in the list.
+ items:
+ description: |-
+ HTTPAuthorizationServerAllowedHeaders specifies how to conditionally match against allowed headers
+ in the context of HTTP authorization. Regex support is intentionally excluded to simplify the user
+ experience and prevent potential issues. Only one of Prefix, Exact, Suffix or Contains must be provided.
+ properties:
+ contains:
+ description: Contains specifies a substring that
+ must be present in the header name.
+ type: string
+ exact:
+ description: Exact specifies a string that the header
+ name must be equal to.
+ type: string
+ ignoreCase:
+ description: IgnoreCase specifies whether string
+ matching should be case-insensitive.
+ type: boolean
+ prefix:
+ description: Prefix defines a prefix match for the
+ header name.
+ type: string
+ suffix:
+ description: Suffix defines a suffix match for a
+ header name.
+ type: string
+ type: object
+ type: array
+ allowedUpstreamHeaders:
+ description: |-
+ AllowedUpstreamHeaders specifies authorization response headers that will be added to the original client request.
+ Coexistent headers will be overridden.
+ items:
+ description: |-
+ HTTPAuthorizationServerAllowedHeaders specifies how to conditionally match against allowed headers
+ in the context of HTTP authorization. Regex support is intentionally excluded to simplify the user
+ experience and prevent potential issues. Only one of Prefix, Exact, Suffix or Contains must be provided.
+ properties:
+ contains:
+ description: Contains specifies a substring that
+ must be present in the header name.
+ type: string
+ exact:
+ description: Exact specifies a string that the header
+ name must be equal to.
+ type: string
+ ignoreCase:
+ description: IgnoreCase specifies whether string
+ matching should be case-insensitive.
+ type: boolean
+ prefix:
+ description: Prefix defines a prefix match for the
+ header name.
+ type: string
+ suffix:
+ description: Suffix defines a suffix match for a
+ header name.
+ type: string
+ type: object
+ type: array
+ pathPrefix:
+ description: PathPrefix Sets a prefix to the value of
+ authorization request header Path.
+ type: string
+ type: object
responseTimeout:
description: |-
ResponseTimeout configures maximum time to wait for a check response from the authorization server.
@@ -7877,6 +8115,15 @@ spec:
The string "infinity" is also a valid input and specifies no timeout.
pattern: ^(((\d*(\.\d*)?h)|(\d*(\.\d*)?m)|(\d*(\.\d*)?s)|(\d*(\.\d*)?ms)|(\d*(\.\d*)?us)|(\d*(\.\d*)?µs)|(\d*(\.\d*)?ns))+|infinity|infinite)$
type: string
+ serviceAPIType:
+ default: grpc
+ description: |-
+ ServiceAPIType sets the protocol used to communicate with
+ the external authorization server.
+ enum:
+ - http
+ - grpc
+ type: string
withRequestBody:
description: WithRequestBody specifies configuration for sending
the client request's body to authorization server.
diff --git a/internal/dag/conditions.go b/internal/dag/conditions.go
index 8b4f542ce9c..5fa207f0866 100644
--- a/internal/dag/conditions.go
+++ b/internal/dag/conditions.go
@@ -407,6 +407,44 @@ func queryParameterMatchConditionsValid(conditions []contour_v1.MatchCondition)
return nil
}
+// ExternalAuthAllowedHeadersValid validates that the allowed header conditions within a
+// slice of HTTPAuthorizationServerAllowedHeaders are valid. Specifically, it returns an error for
+// any of the following scenarios:
+// - no conditions are set
+// - more than one condition is set in the same allowed header condition branch
+// - invalid regular expression is specified for the Regex condition
+func ExternalAuthAllowedHeadersValid(allowedHeaders []contour_v1.HTTPAuthorizationServerAllowedHeaders) error {
+ for _, allowedHeader := range allowedHeaders {
+ sum := 0
+
+ if allowedHeader.Exact != "" {
+ sum++
+ }
+
+ if allowedHeader.Prefix != "" {
+ sum++
+ }
+
+ if allowedHeader.Suffix != "" {
+ sum++
+ }
+
+ if allowedHeader.Contains != "" {
+ sum++
+ }
+
+ if sum == 0 {
+ return errors.New("one of prefix, suffix, exact or contains is required for each allowedHeader")
+ }
+
+ if sum > 1 {
+ return errors.New("only one of prefix, suffix, exact, and contains should be set in the allowedHeader")
+ }
+ }
+
+ return nil
+}
+
// ValidateRegex returns an error if the supplied
// RE2 regex syntax is invalid.
func ValidateRegex(regex string) error {
diff --git a/internal/dag/dag.go b/internal/dag/dag.go
index 0e75755abfd..8d9134ffce5 100644
--- a/internal/dag/dag.go
+++ b/internal/dag/dag.go
@@ -27,6 +27,7 @@ import (
core_v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/types"
+ contour_v1 "github.com/projectcontour/contour/apis/projectcontour/v1"
"github.com/projectcontour/contour/internal/status"
"github.com/projectcontour/contour/internal/timeout"
)
@@ -861,6 +862,29 @@ type IPFilterRule struct {
// ExternalAuthorization contains the configuration for enabling
// the ExtAuthz filter.
type ExternalAuthorization struct {
+ // ServiceAPIType defines the external authorization service API type.
+ // It indicates the protocol implemented by the external server, specifying whether it's a raw HTTP authorization server
+ // or a gRPC authorization server.
+ ServiceAPIType contour_v1.AuthorizationServiceAPIType
+
+ // HTTPAllowedAuthorizationHeaders specifies client request headers that will be sent to the authorization server.
+ // Note that in addition to the the user’s supplied matchers, Host, Method, Path, Content-Length, and Authorization are additionally included in the list.
+ HTTPAllowedAuthorizationHeaders []contour_v1.HTTPAuthorizationServerAllowedHeaders
+
+ // HTTPAllowedUpstreamHeaders specifies authorization response headers that will be added to the original client request.
+ // Note that coexistent headers will be overridden.
+ HTTPAllowedUpstreamHeaders []contour_v1.HTTPAuthorizationServerAllowedHeaders
+
+ // HTTPPathPrefix Sets a prefix to the value of authorization request header Path.
+ HTTPPathPrefix string
+
+ // Note: This field is not used by Envoy
+ // https://github.com/envoyproxy/envoy/issues/5357
+ //
+ // HttpServerURI sets the URI of the external HTTP authorization server to which authorization requests must be sent.
+ // Only required for http services.
+ // HttpServerURI string
+
// AuthorizationService points to the extension that client
// requests are forwarded to for authorization. If nil, no
// authorization is enabled for this host.
diff --git a/internal/dag/httpproxy_processor.go b/internal/dag/httpproxy_processor.go
index 8a61bc5f132..9044ad568c0 100644
--- a/internal/dag/httpproxy_processor.go
+++ b/internal/dag/httpproxy_processor.go
@@ -1403,6 +1403,40 @@ func (p *HTTPProxyProcessor) computeVirtualHostAuthorization(auth *contour_v1.Au
AuthorizationResponseTimeout: *respTimeout,
}
+ switch auth.ServiceAPIType {
+ case contour_v1.AuthorizationGRPCService:
+ globalExternalAuthorization.ServiceAPIType = contour_v1.AuthorizationGRPCService
+ case contour_v1.AuthorizationHTTPService:
+ globalExternalAuthorization.ServiceAPIType = contour_v1.AuthorizationHTTPService
+ if auth.HTTPServerSettings != nil {
+ globalExternalAuthorization.HTTPPathPrefix = auth.HTTPServerSettings.PathPrefix
+
+ // globalExternalAuthorization.HttpServerURI = auth.HttpServerSettings.ServerURI
+
+ if len(auth.HTTPServerSettings.AllowedAuthorizationHeaders) > 0 {
+ if err := ExternalAuthAllowedHeadersValid(auth.HTTPServerSettings.AllowedAuthorizationHeaders); err != nil {
+ validCond.AddErrorf(contour_v1.ConditionTypeAuthError, "AuthBadAllowedHeader",
+ "Spec.Virtualhost.Authorization.HTTPServerSettings.AllowedAuthorizationHeaders is invalid: %s", err)
+
+ return nil
+ }
+
+ globalExternalAuthorization.HTTPAllowedAuthorizationHeaders = auth.HTTPServerSettings.AllowedAuthorizationHeaders
+ }
+
+ if len(auth.HTTPServerSettings.AllowedUpstreamHeaders) > 0 {
+ if err := ExternalAuthAllowedHeadersValid(auth.HTTPServerSettings.AllowedUpstreamHeaders); err != nil {
+ validCond.AddErrorf(contour_v1.ConditionTypeAuthError, "AuthBadAllowedHeader",
+ "Spec.Virtualhost.Authorization.HTTPServerSettings.AllowedUpstreamHeaders is invalid: %s", err)
+
+ return nil
+ }
+
+ globalExternalAuthorization.HTTPAllowedUpstreamHeaders = auth.HTTPServerSettings.AllowedUpstreamHeaders
+ }
+ }
+ }
+
if auth.WithRequestBody != nil {
maxRequestBytes := defaultMaxRequestBytes
if auth.WithRequestBody.MaxRequestBytes != 0 {
diff --git a/internal/envoy/v3/cluster.go b/internal/envoy/v3/cluster.go
index 4717b966f8b..c6b876a32b5 100644
--- a/internal/envoy/v3/cluster.go
+++ b/internal/envoy/v3/cluster.go
@@ -162,10 +162,10 @@ func (e *EnvoyGen) ExtensionCluster(ext *dag.ExtensionCluster) *envoy_config_clu
// TODO(jpeach): Externalname service support in https://github.com/projectcontour/contour/issues/2875
- http2Version := HTTPVersionAuto
+ httpVersion := HTTPVersionAuto
switch ext.Protocol {
case "h2":
- http2Version = HTTPVersion2
+ httpVersion = HTTPVersion2
cluster.TransportSocket = UpstreamTLSTransportSocket(
e.UpstreamTLSContext(
ext.UpstreamValidation,
@@ -176,13 +176,15 @@ func (e *EnvoyGen) ExtensionCluster(ext *dag.ExtensionCluster) *envoy_config_clu
),
)
case "h2c":
- http2Version = HTTPVersion2
+ httpVersion = HTTPVersion2
+ case "http/1.1":
+ httpVersion = HTTPVersion1
}
if ext.ClusterTimeoutPolicy.ConnectTimeout > time.Duration(0) {
cluster.ConnectTimeout = durationpb.New(ext.ClusterTimeoutPolicy.ConnectTimeout)
}
- cluster.TypedExtensionProtocolOptions = protocolOptions(http2Version, ext.ClusterTimeoutPolicy.IdleConnectionTimeout, nil)
+ cluster.TypedExtensionProtocolOptions = protocolOptions(httpVersion, ext.ClusterTimeoutPolicy.IdleConnectionTimeout, nil)
applyCircuitBreakers(cluster, ext.CircuitBreakers)
diff --git a/internal/envoy/v3/listener.go b/internal/envoy/v3/listener.go
index 51a8a53bebe..511edad2f3f 100644
--- a/internal/envoy/v3/listener.go
+++ b/internal/envoy/v3/listener.go
@@ -41,12 +41,14 @@ import (
envoy_filter_network_http_connection_manager_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/http_connection_manager/v3"
envoy_filter_network_tcp_proxy_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/tcp_proxy/v3"
envoy_transport_socket_tls_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/tls/v3"
+ envoy_matcher_v3 "github.com/envoyproxy/go-control-plane/envoy/type/matcher/v3"
envoy_type_v3 "github.com/envoyproxy/go-control-plane/envoy/type/v3"
"github.com/envoyproxy/go-control-plane/pkg/wellknown"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/types/known/durationpb"
"google.golang.org/protobuf/types/known/wrapperspb"
+ contour_v1 "github.com/projectcontour/contour/apis/projectcontour/v1"
contour_v1alpha1 "github.com/projectcontour/contour/apis/projectcontour/v1alpha1"
"github.com/projectcontour/contour/internal/dag"
"github.com/projectcontour/contour/internal/envoy"
@@ -64,7 +66,7 @@ const (
HTTPVersion3 HTTPVersionType = envoy_filter_network_http_connection_manager_v3.HttpConnectionManager_HTTP3
)
-// ProtoNamesForVersions returns the slice of ALPN protocol names for the give HTTP versions.
+// ProtoNamesForVersions returns the slice of ALPN protocol names for the given HTTP versions.
func ProtoNamesForVersions(versions ...HTTPVersionType) []string {
protocols := map[HTTPVersionType]string{
HTTPVersion1: "http/1.1",
@@ -837,6 +839,46 @@ end
}
}
+// ExternalAuthzAllowedHeaders returns the slice of StringMatcher for a given slice of HTTPAuthorizationServerAllowedHeaders.
+func ExternalAuthzAllowedHeaders(allowedHeaders []contour_v1.HTTPAuthorizationServerAllowedHeaders) []*envoy_matcher_v3.StringMatcher {
+ var allowedHeaderPatterns []*envoy_matcher_v3.StringMatcher
+
+ for _, allowedHeader := range allowedHeaders {
+ switch {
+ case allowedHeader.Exact != "":
+ allowedHeaderPatterns = append(allowedHeaderPatterns, &envoy_matcher_v3.StringMatcher{
+ MatchPattern: &envoy_matcher_v3.StringMatcher_Exact{
+ Exact: allowedHeader.Exact,
+ },
+ IgnoreCase: allowedHeader.IgnoreCase,
+ })
+ case allowedHeader.Prefix != "":
+ allowedHeaderPatterns = append(allowedHeaderPatterns, &envoy_matcher_v3.StringMatcher{
+ MatchPattern: &envoy_matcher_v3.StringMatcher_Prefix{
+ Prefix: allowedHeader.Prefix,
+ },
+ IgnoreCase: allowedHeader.IgnoreCase,
+ })
+ case allowedHeader.Suffix != "":
+ allowedHeaderPatterns = append(allowedHeaderPatterns, &envoy_matcher_v3.StringMatcher{
+ MatchPattern: &envoy_matcher_v3.StringMatcher_Suffix{
+ Suffix: allowedHeader.Suffix,
+ },
+ IgnoreCase: allowedHeader.IgnoreCase,
+ })
+ case allowedHeader.Contains != "":
+ allowedHeaderPatterns = append(allowedHeaderPatterns, &envoy_matcher_v3.StringMatcher{
+ MatchPattern: &envoy_matcher_v3.StringMatcher_Contains{
+ Contains: allowedHeader.Contains,
+ },
+ IgnoreCase: allowedHeader.IgnoreCase,
+ })
+ }
+ }
+
+ return allowedHeaderPatterns
+}
+
// FilterExternalAuthz returns an `ext_authz` filter configured with the
// requested parameters.
func FilterExternalAuthz(externalAuthorization *dag.ExternalAuthorization) *envoy_filter_network_http_connection_manager_v3.HttpFilter {
@@ -852,11 +894,52 @@ func FilterExternalAuthz(externalAuthorization *dag.ExternalAuthorization) *envo
StatusOnError: &envoy_type_v3.HttpStatus{
Code: envoy_type_v3.StatusCode_Forbidden,
},
- MetadataContextNamespaces: []string{},
- IncludePeerCertificate: true,
// TODO(jpeach): When we move to the Envoy v4 API, propagate the
// `transport_api_version` from ExtensionServiceSpec ProtocolVersion.
- TransportApiVersion: envoy_config_core_v3.ApiVersion_V3,
+ TransportApiVersion: envoy_config_core_v3.ApiVersion_V3,
+ IncludePeerCertificate: true,
+ }
+
+ switch externalAuthorization.ServiceAPIType {
+ case contour_v1.AuthorizationGRPCService:
+ authConfig.Services = &envoy_filter_http_ext_authz_v3.ExtAuthz_GrpcService{
+ GrpcService: grpcService(externalAuthorization.AuthorizationService.Name, externalAuthorization.AuthorizationService.SNI, externalAuthorization.AuthorizationResponseTimeout),
+ }
+ authConfig.MetadataContextNamespaces = []string{}
+
+ case contour_v1.AuthorizationHTTPService:
+ extAuthzService := &envoy_filter_http_ext_authz_v3.ExtAuthz_HttpService{
+ HttpService: &envoy_filter_http_ext_authz_v3.HttpService{
+ ServerUri: &envoy_config_core_v3.HttpUri{
+ // Uri: externalAuthorization.HttpServerURI,
+ Uri: "http://dummy/",
+ HttpUpstreamType: &envoy_config_core_v3.HttpUri_Cluster{
+ Cluster: externalAuthorization.AuthorizationService.Name,
+ },
+ Timeout: envoy.Timeout(externalAuthorization.AuthorizationResponseTimeout),
+ },
+ },
+ }
+
+ if pathPrefix := externalAuthorization.HTTPPathPrefix; pathPrefix != "" {
+ extAuthzService.HttpService.PathPrefix = pathPrefix
+ }
+
+ if len(externalAuthorization.HTTPAllowedAuthorizationHeaders) > 0 {
+ authConfig.AllowedHeaders = &envoy_matcher_v3.ListStringMatcher{
+ Patterns: ExternalAuthzAllowedHeaders(externalAuthorization.HTTPAllowedAuthorizationHeaders),
+ }
+ }
+
+ if len(externalAuthorization.HTTPAllowedUpstreamHeaders) > 0 {
+ extAuthzService.HttpService.AuthorizationResponse = &envoy_filter_http_ext_authz_v3.AuthorizationResponse{
+ AllowedUpstreamHeaders: &envoy_matcher_v3.ListStringMatcher{
+ Patterns: ExternalAuthzAllowedHeaders(externalAuthorization.HTTPAllowedUpstreamHeaders),
+ },
+ }
+ }
+
+ authConfig.Services = extAuthzService
}
if externalAuthorization.AuthorizationServerWithRequestBody != nil {
diff --git a/internal/featuretests/v3/authorization_test.go b/internal/featuretests/v3/authorization_test.go
index efbb9ae21e0..981da972ad1 100644
--- a/internal/featuretests/v3/authorization_test.go
+++ b/internal/featuretests/v3/authorization_test.go
@@ -24,6 +24,7 @@ import (
envoy_config_route_v3 "github.com/envoyproxy/go-control-plane/envoy/config/route/v3"
envoy_filter_http_ext_authz_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/ext_authz/v3"
envoy_service_discovery_v3 "github.com/envoyproxy/go-control-plane/envoy/service/discovery/v3"
+ envoy_matcher_v3 "github.com/envoyproxy/go-control-plane/envoy/type/matcher/v3"
envoy_type_v3 "github.com/envoyproxy/go-control-plane/envoy/type/v3"
"google.golang.org/protobuf/types/known/durationpb"
core_v1 "k8s.io/api/core/v1"
@@ -51,6 +52,20 @@ func grpcCluster(name string) *envoy_filter_http_ext_authz_v3.ExtAuthz_GrpcServi
}
}
+func httpCluster(name string) *envoy_filter_http_ext_authz_v3.ExtAuthz_HttpService {
+ return &envoy_filter_http_ext_authz_v3.ExtAuthz_HttpService{
+ HttpService: &envoy_filter_http_ext_authz_v3.HttpService{
+ ServerUri: &envoy_config_core_v3.HttpUri{
+ Uri: "http://dummy/",
+ HttpUpstreamType: &envoy_config_core_v3.HttpUri_Cluster{
+ Cluster: name,
+ },
+ Timeout: durationpb.New(defaultResponseTimeout),
+ },
+ },
+ }
+}
+
func authzResponseTimeout(t *testing.T, rh ResourceEventHandlerWrapper, c *Contour) {
const fqdn = "failopen.projectcontour.io"
@@ -62,6 +77,7 @@ func authzResponseTimeout(t *testing.T, rh ResourceEventHandlerWrapper, c *Conto
Namespace: "auth",
Name: "extension",
},
+ ServiceAPIType: contour_v1.AuthorizationGRPCService,
ResponseTimeout: "10m",
}).
WithSpec(contour_v1.HTTPProxySpec{
@@ -120,6 +136,7 @@ func authzInvalidResponseTimeout(t *testing.T, rh ResourceEventHandlerWrapper, c
Namespace: "auth",
Name: "extension",
},
+ ServiceAPIType: contour_v1.AuthorizationGRPCService,
ResponseTimeout: "invalid-timeout",
}).
WithSpec(contour_v1.HTTPProxySpec{
@@ -147,7 +164,8 @@ func authzFailOpen(t *testing.T, rh ResourceEventHandlerWrapper, c *Contour) {
Namespace: "auth",
Name: "extension",
},
- FailOpen: true,
+ ServiceAPIType: contour_v1.AuthorizationGRPCService,
+ FailOpen: true,
}).
WithSpec(contour_v1.HTTPProxySpec{
Routes: []contour_v1.Route{{
@@ -199,6 +217,7 @@ func authzFallbackIncompat(t *testing.T, rh ResourceEventHandlerWrapper, c *Cont
Namespace: "auth",
Name: "extension",
},
+ ServiceAPIType: contour_v1.AuthorizationGRPCService,
}).
WithSpec(contour_v1.HTTPProxySpec{
Routes: []contour_v1.Route{{
@@ -230,6 +249,7 @@ func authzOverrideDisabled(t *testing.T, rh ResourceEventHandlerWrapper, c *Cont
WithCertificate("certificate").
WithAuthServer(contour_v1.AuthorizationServer{
ExtensionServiceRef: extensionRef,
+ ServiceAPIType: contour_v1.AuthorizationGRPCService,
AuthPolicy: &contour_v1.AuthorizationPolicy{Disabled: false},
}).
WithSpec(contour_v1.HTTPProxySpec{
@@ -340,6 +360,7 @@ func authzMergeRouteContext(t *testing.T, rh ResourceEventHandlerWrapper, c *Con
Namespace: "auth",
Name: "extension",
},
+ ServiceAPIType: contour_v1.AuthorizationGRPCService,
AuthPolicy: &contour_v1.AuthorizationPolicy{
Context: map[string]string{
"root-element": "root",
@@ -419,7 +440,9 @@ func authzInvalidReference(t *testing.T, rh ResourceEventHandlerWrapper, c *Cont
invalid := fixture.NewProxy("proxy").
WithFQDN(fqdn).
WithCertificate("certificate").
- WithAuthServer(contour_v1.AuthorizationServer{}).
+ WithAuthServer(contour_v1.AuthorizationServer{
+ ServiceAPIType: contour_v1.AuthorizationGRPCService,
+ }).
WithSpec(contour_v1.HTTPProxySpec{
Routes: []contour_v1.Route{{
Services: []contour_v1.Service{{
@@ -509,7 +532,8 @@ func authzWithRequestBodyBufferSettings(t *testing.T, rh ResourceEventHandlerWra
Namespace: "auth",
Name: "extension",
},
- FailOpen: true,
+ ServiceAPIType: contour_v1.AuthorizationGRPCService,
+ FailOpen: true,
WithRequestBody: &contour_v1.AuthorizationServerBufferSettings{
MaxRequestBytes: 100,
AllowPartialMessage: true,
@@ -562,16 +586,445 @@ func authzWithRequestBodyBufferSettings(t *testing.T, rh ResourceEventHandlerWra
}).Status(p).IsValid()
}
+func AuthzTypeGRPC(t *testing.T, rh ResourceEventHandlerWrapper, c *Contour) {
+ const fqdn = "typegrpc.projectcontour.io"
+
+ p := fixture.NewProxy("proxy").
+ WithFQDN(fqdn).
+ WithCertificate("certificate").
+ WithAuthServer(contour_v1.AuthorizationServer{
+ ExtensionServiceRef: contour_v1.ExtensionServiceReference{
+ Namespace: "auth",
+ Name: "extension",
+ },
+ ServiceAPIType: contour_v1.AuthorizationGRPCService,
+ }).
+ WithSpec(contour_v1.HTTPProxySpec{
+ Routes: []contour_v1.Route{{
+ Services: []contour_v1.Service{{
+ Name: "app-server",
+ Port: 80,
+ }},
+ }},
+ })
+
+ rh.OnDelete(p)
+ rh.OnAdd(p)
+
+ c.Request(listenerType).Equals(&envoy_service_discovery_v3.DiscoveryResponse{
+ TypeUrl: listenerType,
+ Resources: resources(t,
+ defaultHTTPListener(),
+ &envoy_config_listener_v3.Listener{
+ Name: "ingress_https",
+ Address: envoy_v3.SocketAddress("0.0.0.0", 8443),
+ ListenerFilters: envoy_v3.ListenerFilters(
+ envoy_v3.TLSInspector(),
+ ),
+ FilterChains: []*envoy_config_listener_v3.FilterChain{
+ filterchaintls(fqdn,
+ featuretests.TLSSecret(t, "certificate", &featuretests.ServerCertificate),
+ authzFilterFor(
+ fqdn,
+ &envoy_filter_http_ext_authz_v3.ExtAuthz{
+ Services: grpcCluster("extension/auth/extension"),
+ ClearRouteCache: true,
+ FailureModeAllow: false,
+ IncludePeerCertificate: true,
+ StatusOnError: &envoy_type_v3.HttpStatus{
+ Code: envoy_type_v3.StatusCode_Forbidden,
+ },
+ TransportApiVersion: envoy_config_core_v3.ApiVersion_V3,
+ },
+ ),
+ nil, "h2", "http/1.1"),
+ },
+ SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(),
+ },
+ statsListener()),
+ }).Status(p).IsValid()
+}
+
+func authzTypeHTTP(t *testing.T, rh ResourceEventHandlerWrapper, c *Contour) {
+ const fqdn = "typehttp.projectcontour.io"
+
+ p := fixture.NewProxy("proxy").
+ WithFQDN(fqdn).
+ WithCertificate("certificate").
+ WithAuthServer(contour_v1.AuthorizationServer{
+ ExtensionServiceRef: contour_v1.ExtensionServiceReference{
+ Namespace: "auth",
+ Name: "extension",
+ },
+ ServiceAPIType: contour_v1.AuthorizationHTTPService,
+ }).
+ WithSpec(contour_v1.HTTPProxySpec{
+ Routes: []contour_v1.Route{{
+ Services: []contour_v1.Service{{
+ Name: "app-server",
+ Port: 80,
+ }},
+ }},
+ })
+
+ rh.OnDelete(p)
+ rh.OnAdd(p)
+
+ c.Request(listenerType).Equals(&envoy_service_discovery_v3.DiscoveryResponse{
+ TypeUrl: listenerType,
+ Resources: resources(t,
+ defaultHTTPListener(),
+ &envoy_config_listener_v3.Listener{
+ Name: "ingress_https",
+ Address: envoy_v3.SocketAddress("0.0.0.0", 8443),
+ ListenerFilters: envoy_v3.ListenerFilters(
+ envoy_v3.TLSInspector(),
+ ),
+ FilterChains: []*envoy_config_listener_v3.FilterChain{
+ filterchaintls(fqdn,
+ featuretests.TLSSecret(t, "certificate", &featuretests.ServerCertificate),
+ authzFilterFor(
+ fqdn,
+ &envoy_filter_http_ext_authz_v3.ExtAuthz{
+ Services: httpCluster("extension/auth/extension"),
+ ClearRouteCache: true,
+ FailureModeAllow: false,
+ IncludePeerCertificate: true,
+ StatusOnError: &envoy_type_v3.HttpStatus{
+ Code: envoy_type_v3.StatusCode_Forbidden,
+ },
+ TransportApiVersion: envoy_config_core_v3.ApiVersion_V3,
+ },
+ ),
+ nil, "h2", "http/1.1"),
+ },
+ SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(),
+ },
+ statsListener()),
+ }).Status(p).IsValid()
+}
+
+func AuthzTypeHTTPWithPathPrefix(t *testing.T, rh ResourceEventHandlerWrapper, c *Contour) {
+ const fqdn = "typehttp.projectcontour.io"
+
+ p := fixture.NewProxy("proxy").
+ WithFQDN(fqdn).
+ WithCertificate("certificate").
+ WithAuthServer(contour_v1.AuthorizationServer{
+ ExtensionServiceRef: contour_v1.ExtensionServiceReference{
+ Namespace: "auth",
+ Name: "extension",
+ },
+ ServiceAPIType: contour_v1.AuthorizationHTTPService,
+ HTTPServerSettings: &contour_v1.HTTPAuthorizationServerSettings{
+ PathPrefix: "/auth?",
+ },
+ }).
+ WithSpec(contour_v1.HTTPProxySpec{
+ Routes: []contour_v1.Route{{
+ Services: []contour_v1.Service{{
+ Name: "app-server",
+ Port: 80,
+ }},
+ }},
+ })
+
+ rh.OnDelete(p)
+ rh.OnAdd(p)
+
+ cluster := httpCluster("extension/auth/extension")
+ cluster.HttpService.PathPrefix = "/auth?"
+
+ c.Request(listenerType).Equals(&envoy_service_discovery_v3.DiscoveryResponse{
+ TypeUrl: listenerType,
+ Resources: resources(t,
+ defaultHTTPListener(),
+ &envoy_config_listener_v3.Listener{
+ Name: "ingress_https",
+ Address: envoy_v3.SocketAddress("0.0.0.0", 8443),
+ ListenerFilters: envoy_v3.ListenerFilters(
+ envoy_v3.TLSInspector(),
+ ),
+ FilterChains: []*envoy_config_listener_v3.FilterChain{
+ filterchaintls(fqdn,
+ featuretests.TLSSecret(t, "certificate", &featuretests.ServerCertificate),
+ authzFilterFor(
+ fqdn,
+ &envoy_filter_http_ext_authz_v3.ExtAuthz{
+ Services: cluster,
+ ClearRouteCache: true,
+ FailureModeAllow: false,
+ IncludePeerCertificate: true,
+ StatusOnError: &envoy_type_v3.HttpStatus{
+ Code: envoy_type_v3.StatusCode_Forbidden,
+ },
+ TransportApiVersion: envoy_config_core_v3.ApiVersion_V3,
+ },
+ ),
+ nil, "h2", "http/1.1"),
+ },
+ SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(),
+ },
+ statsListener()),
+ }).Status(p).IsValid()
+}
+
+func AuthzTypeHTTPWithAllowedAuthorizationHeaders(t *testing.T, rh ResourceEventHandlerWrapper, c *Contour) {
+ const fqdn = "typehttp.projectcontour.io"
+
+ p := fixture.NewProxy("proxy").
+ WithFQDN(fqdn).
+ WithCertificate("certificate").
+ WithAuthServer(contour_v1.AuthorizationServer{
+ ExtensionServiceRef: contour_v1.ExtensionServiceReference{
+ Namespace: "auth",
+ Name: "extension",
+ },
+ ServiceAPIType: contour_v1.AuthorizationHTTPService,
+ }).
+ WithSpec(contour_v1.HTTPProxySpec{
+ Routes: []contour_v1.Route{{
+ Services: []contour_v1.Service{{
+ Name: "app-server",
+ Port: 80,
+ }},
+ }},
+ })
+
+ p.Spec.VirtualHost.Authorization.HTTPServerSettings = &contour_v1.HTTPAuthorizationServerSettings{
+ AllowedAuthorizationHeaders: []contour_v1.HTTPAuthorizationServerAllowedHeaders{
+ {IgnoreCase: false},
+ },
+ }
+
+ rh.OnDelete(p)
+ rh.OnAdd(p)
+
+ c.Request(listenerType).Equals(&envoy_service_discovery_v3.DiscoveryResponse{
+ TypeUrl: listenerType,
+ Resources: resources(t, statsListener()),
+ }).Status(p).HasError(contour_v1.ConditionTypeAuthError, "AuthBadAllowedHeader", `Spec.Virtualhost.Authorization.HTTPServerSettings.AllowedAuthorizationHeaders is invalid: one of prefix, suffix, exact or contains is required for each allowedHeader`)
+
+ p.Spec.VirtualHost.Authorization.HTTPServerSettings = &contour_v1.HTTPAuthorizationServerSettings{
+ AllowedAuthorizationHeaders: []contour_v1.HTTPAuthorizationServerAllowedHeaders{
+ {Exact: "test", Prefix: "test", IgnoreCase: false},
+ },
+ }
+
+ rh.OnDelete(p)
+ rh.OnAdd(p)
+
+ c.Request(listenerType).Equals(&envoy_service_discovery_v3.DiscoveryResponse{
+ TypeUrl: listenerType,
+ Resources: resources(t, statsListener()),
+ }).Status(p).HasError(contour_v1.ConditionTypeAuthError, "AuthBadAllowedHeader", `Spec.Virtualhost.Authorization.HTTPServerSettings.AllowedAuthorizationHeaders is invalid: only one of prefix, suffix, exact, and contains should be set in the allowedHeader`)
+
+ p.Spec.VirtualHost.Authorization.HTTPServerSettings = &contour_v1.HTTPAuthorizationServerSettings{
+ AllowedAuthorizationHeaders: []contour_v1.HTTPAuthorizationServerAllowedHeaders{
+ {Prefix: "test1", IgnoreCase: false},
+ {Exact: "test2", IgnoreCase: true},
+ },
+ }
+
+ rh.OnDelete(p)
+ rh.OnAdd(p)
+
+ c.Request(listenerType).Equals(&envoy_service_discovery_v3.DiscoveryResponse{
+ TypeUrl: listenerType,
+ Resources: resources(t,
+ defaultHTTPListener(),
+ &envoy_config_listener_v3.Listener{
+ Name: "ingress_https",
+ Address: envoy_v3.SocketAddress("0.0.0.0", 8443),
+ ListenerFilters: envoy_v3.ListenerFilters(
+ envoy_v3.TLSInspector(),
+ ),
+ FilterChains: []*envoy_config_listener_v3.FilterChain{
+ filterchaintls(fqdn,
+ featuretests.TLSSecret(t, "certificate", &featuretests.ServerCertificate),
+ authzFilterFor(
+ fqdn,
+ &envoy_filter_http_ext_authz_v3.ExtAuthz{
+ Services: httpCluster("extension/auth/extension"),
+ AllowedHeaders: &envoy_matcher_v3.ListStringMatcher{
+ Patterns: []*envoy_matcher_v3.StringMatcher{
+ {MatchPattern: &envoy_matcher_v3.StringMatcher_Prefix{Prefix: "test1"}, IgnoreCase: false},
+ {MatchPattern: &envoy_matcher_v3.StringMatcher_Exact{Exact: "test2"}, IgnoreCase: true},
+ },
+ },
+ ClearRouteCache: true,
+ FailureModeAllow: false,
+ IncludePeerCertificate: true,
+ StatusOnError: &envoy_type_v3.HttpStatus{
+ Code: envoy_type_v3.StatusCode_Forbidden,
+ },
+ TransportApiVersion: envoy_config_core_v3.ApiVersion_V3,
+ },
+ ),
+ nil, "h2", "http/1.1"),
+ },
+ SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(),
+ },
+ statsListener()),
+ }).Status(p).IsValid()
+}
+
+func AuthzTypeHTTPWithAllowedUpstreamHeaders(t *testing.T, rh ResourceEventHandlerWrapper, c *Contour) {
+ const fqdn = "typehttp.projectcontour.io"
+
+ p := fixture.NewProxy("proxy").
+ WithFQDN(fqdn).
+ WithCertificate("certificate").
+ WithAuthServer(contour_v1.AuthorizationServer{
+ ExtensionServiceRef: contour_v1.ExtensionServiceReference{
+ Namespace: "auth",
+ Name: "extension",
+ },
+ ServiceAPIType: contour_v1.AuthorizationHTTPService,
+ }).
+ WithSpec(contour_v1.HTTPProxySpec{
+ Routes: []contour_v1.Route{{
+ Services: []contour_v1.Service{{
+ Name: "app-server",
+ Port: 80,
+ }},
+ }},
+ })
+
+ p.Spec.VirtualHost.Authorization.HTTPServerSettings = &contour_v1.HTTPAuthorizationServerSettings{
+ AllowedUpstreamHeaders: []contour_v1.HTTPAuthorizationServerAllowedHeaders{
+ {IgnoreCase: false},
+ },
+ }
+
+ rh.OnDelete(p)
+ rh.OnAdd(p)
+
+ c.Request(listenerType).Equals(&envoy_service_discovery_v3.DiscoveryResponse{
+ TypeUrl: listenerType,
+ Resources: resources(t, statsListener()),
+ }).Status(p).HasError(contour_v1.ConditionTypeAuthError, "AuthBadAllowedHeader", `Spec.Virtualhost.Authorization.HTTPServerSettings.AllowedUpstreamHeaders is invalid: one of prefix, suffix, exact or contains is required for each allowedHeader`)
+
+ p.Spec.VirtualHost.Authorization.HTTPServerSettings = &contour_v1.HTTPAuthorizationServerSettings{
+ AllowedUpstreamHeaders: []contour_v1.HTTPAuthorizationServerAllowedHeaders{
+ {Exact: "test", Prefix: "test", IgnoreCase: false},
+ },
+ }
+
+ rh.OnDelete(p)
+ rh.OnAdd(p)
+
+ c.Request(listenerType).Equals(&envoy_service_discovery_v3.DiscoveryResponse{
+ TypeUrl: listenerType,
+ Resources: resources(t, statsListener()),
+ }).Status(p).HasError(contour_v1.ConditionTypeAuthError, "AuthBadAllowedHeader", `Spec.Virtualhost.Authorization.HTTPServerSettings.AllowedUpstreamHeaders is invalid: only one of prefix, suffix, exact, and contains should be set in the allowedHeader`)
+
+ p.Spec.VirtualHost.Authorization.HTTPServerSettings = &contour_v1.HTTPAuthorizationServerSettings{
+ AllowedUpstreamHeaders: []contour_v1.HTTPAuthorizationServerAllowedHeaders{
+ {Prefix: "test1", IgnoreCase: false},
+ {Exact: "test2", IgnoreCase: true},
+ },
+ }
+
+ rh.OnDelete(p)
+ rh.OnAdd(p)
+
+ cluster := httpCluster("extension/auth/extension")
+ cluster.HttpService.AuthorizationResponse = &envoy_filter_http_ext_authz_v3.AuthorizationResponse{
+ AllowedUpstreamHeaders: &envoy_matcher_v3.ListStringMatcher{
+ Patterns: []*envoy_matcher_v3.StringMatcher{
+ {MatchPattern: &envoy_matcher_v3.StringMatcher_Prefix{Prefix: "test1"}, IgnoreCase: false},
+ {MatchPattern: &envoy_matcher_v3.StringMatcher_Exact{Exact: "test2"}, IgnoreCase: true},
+ },
+ },
+ }
+
+ c.Request(listenerType).Equals(&envoy_service_discovery_v3.DiscoveryResponse{
+ TypeUrl: listenerType,
+ Resources: resources(t,
+ defaultHTTPListener(),
+ &envoy_config_listener_v3.Listener{
+ Name: "ingress_https",
+ Address: envoy_v3.SocketAddress("0.0.0.0", 8443),
+ ListenerFilters: envoy_v3.ListenerFilters(
+ envoy_v3.TLSInspector(),
+ ),
+ FilterChains: []*envoy_config_listener_v3.FilterChain{
+ filterchaintls(fqdn,
+ featuretests.TLSSecret(t, "certificate", &featuretests.ServerCertificate),
+ authzFilterFor(
+ fqdn,
+ &envoy_filter_http_ext_authz_v3.ExtAuthz{
+ Services: cluster,
+ ClearRouteCache: true,
+ FailureModeAllow: false,
+ IncludePeerCertificate: true,
+ StatusOnError: &envoy_type_v3.HttpStatus{
+ Code: envoy_type_v3.StatusCode_Forbidden,
+ },
+ TransportApiVersion: envoy_config_core_v3.ApiVersion_V3,
+ },
+ ),
+ nil, "h2", "http/1.1"),
+ },
+ SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(),
+ },
+ statsListener()),
+ }).Status(p).IsValid()
+}
+
+func AuthzTypeHTTPWithContext(t *testing.T, rh ResourceEventHandlerWrapper, c *Contour) {
+ const fqdn = "typehttp.projectcontour.io"
+
+ p := fixture.NewProxy("proxy").
+ WithFQDN(fqdn).
+ WithCertificate("certificate").
+ WithAuthServer(contour_v1.AuthorizationServer{
+ ExtensionServiceRef: contour_v1.ExtensionServiceReference{
+ Namespace: "auth",
+ Name: "extension",
+ },
+ ServiceAPIType: contour_v1.AuthorizationHTTPService,
+ AuthPolicy: &contour_v1.AuthorizationPolicy{
+ Context: map[string]string{
+ "k1": "v1",
+ "k2": "v2",
+ },
+ },
+ }).
+ WithSpec(contour_v1.HTTPProxySpec{
+ Routes: []contour_v1.Route{{
+ Services: []contour_v1.Service{{
+ Name: "app-server",
+ Port: 80,
+ }},
+ }},
+ })
+
+ rh.OnDelete(p)
+ rh.OnAdd(p)
+
+ c.Request(listenerType).Equals(&envoy_service_discovery_v3.DiscoveryResponse{
+ TypeUrl: listenerType,
+ Resources: resources(t, statsListener()),
+ }).Status(p).HasError(contour_v1.ConditionTypeAuthError, "AuthContextForHTTP", `Spec.Virtualhost.Authorization.AuthPolicy.Context are only applied to grpc service type`)
+}
+
func TestAuthorization(t *testing.T) {
subtests := map[string]func(*testing.T, ResourceEventHandlerWrapper, *Contour){
- "MissingExtension": authzInvalidReference,
- "MergeRouteContext": authzMergeRouteContext,
- "OverrideDisabled": authzOverrideDisabled,
- "FallbackIncompat": authzFallbackIncompat,
- "FailOpen": authzFailOpen,
- "ResponseTimeout": authzResponseTimeout,
- "InvalidResponseTimeout": authzInvalidResponseTimeout,
- "AuthzWithRequestBodyBufferSettings": authzWithRequestBodyBufferSettings,
+ "MissingExtension": authzInvalidReference,
+ "MergeRouteContext": authzMergeRouteContext,
+ "OverrideDisabled": authzOverrideDisabled,
+ "FallbackIncompat": authzFallbackIncompat,
+ "FailOpen": authzFailOpen,
+ "ResponseTimeout": authzResponseTimeout,
+ "InvalidResponseTimeout": authzInvalidResponseTimeout,
+ "AuthzWithRequestBodyBufferSettings": authzWithRequestBodyBufferSettings,
+ "AuthzTypeGRPC": AuthzTypeGRPC,
+ "AuthzTypeHTTP": authzTypeHTTP,
+ "AuthzTypeHTTPWithPathPrefix": AuthzTypeHTTPWithPathPrefix,
+ "AuthzTypeHTTPWithAllowedAuthorizationHeaders": AuthzTypeHTTPWithAllowedAuthorizationHeaders,
+ "AuthzTypeHTTPWithAllowedUpstreamHeaders": AuthzTypeHTTPWithAllowedUpstreamHeaders,
}
for n, f := range subtests {
diff --git a/internal/featuretests/v3/envoy.go b/internal/featuretests/v3/envoy.go
index e9b8a5995e1..d434381f923 100644
--- a/internal/featuretests/v3/envoy.go
+++ b/internal/featuretests/v3/envoy.go
@@ -249,6 +249,20 @@ func h2cCluster(c *envoy_config_cluster_v3.Cluster) *envoy_config_cluster_v3.Clu
return c
}
+func http1Cluster(c *envoy_config_cluster_v3.Cluster) *envoy_config_cluster_v3.Cluster {
+ c.TypedExtensionProtocolOptions = map[string]*anypb.Any{
+ "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": protobuf.MustMarshalAny(
+ &envoy_upstream_http_v3.HttpProtocolOptions{
+ UpstreamProtocolOptions: &envoy_upstream_http_v3.HttpProtocolOptions_ExplicitHttpConfig_{
+ ExplicitHttpConfig: &envoy_upstream_http_v3.HttpProtocolOptions_ExplicitHttpConfig{
+ ProtocolConfig: &envoy_upstream_http_v3.HttpProtocolOptions_ExplicitHttpConfig_HttpProtocolOptions{},
+ },
+ },
+ }),
+ }
+ return c
+}
+
func withConnectionTimeout(c *envoy_config_cluster_v3.Cluster, timeout time.Duration, httpVersion envoy_v3.HTTPVersionType) *envoy_config_cluster_v3.Cluster {
var config *envoy_upstream_http_v3.HttpProtocolOptions_ExplicitHttpConfig
diff --git a/internal/featuretests/v3/extensionservice_test.go b/internal/featuretests/v3/extensionservice_test.go
index a82f1fd5726..94e3f4be64c 100644
--- a/internal/featuretests/v3/extensionservice_test.go
+++ b/internal/featuretests/v3/extensionservice_test.go
@@ -78,7 +78,7 @@ func extBasic(t *testing.T, rh ResourceEventHandlerWrapper, c *Contour) {
}
func extCleartext(t *testing.T, rh ResourceEventHandlerWrapper, c *Contour) {
- rh.OnAdd(&contour_v1alpha1.ExtensionService{
+ es := &contour_v1alpha1.ExtensionService{
ObjectMeta: fixture.ObjectMeta("ns/ext"),
Spec: contour_v1alpha1.ExtensionServiceSpec{
Protocol: ptr.To("h2c"),
@@ -87,7 +87,9 @@ func extCleartext(t *testing.T, rh ResourceEventHandlerWrapper, c *Contour) {
{Name: "svc2", Port: 8082},
},
},
- })
+ }
+
+ rh.OnAdd(es)
c.Request(clusterType).Equals(&envoy_service_discovery_v3.DiscoveryResponse{
TypeUrl: clusterType,
@@ -97,6 +99,20 @@ func extCleartext(t *testing.T, rh ResourceEventHandlerWrapper, c *Contour) {
),
),
})
+
+ es.Spec.Protocol = ptr.To("http/1.1")
+
+ rh.OnDelete(es)
+ rh.OnAdd(es)
+
+ c.Request(clusterType).Equals(&envoy_service_discovery_v3.DiscoveryResponse{
+ TypeUrl: clusterType,
+ Resources: resources(t,
+ DefaultCluster(
+ http1Cluster(cluster("extension/ns/ext", "extension/ns/ext", "extension_ns_ext")),
+ ),
+ ),
+ })
}
func extUpstreamValidation(t *testing.T, rh ResourceEventHandlerWrapper, c *Contour) {
@@ -313,7 +329,7 @@ func extInvalidTimeout(_ *testing.T, rh ResourceEventHandlerWrapper, c *Contour)
}
func extInconsistentProto(_ *testing.T, rh ResourceEventHandlerWrapper, c *Contour) {
- rh.OnAdd(&contour_v1alpha1.ExtensionService{
+ es := &contour_v1alpha1.ExtensionService{
ObjectMeta: fixture.ObjectMeta("ns/ext"),
Spec: contour_v1alpha1.ExtensionServiceSpec{
Services: []contour_v1alpha1.ExtensionServiceTarget{
@@ -325,8 +341,20 @@ func extInconsistentProto(_ *testing.T, rh ResourceEventHandlerWrapper, c *Conto
SubjectName: "ext.projectcontour.io",
},
},
+ }
+
+ rh.OnAdd(es)
+
+ // Should have no clusters because Protocol and UpstreamValidation is inconsistent.
+ c.Request(clusterType).Equals(&envoy_service_discovery_v3.DiscoveryResponse{
+ TypeUrl: clusterType,
})
+ es.Spec.Protocol = ptr.To("h1")
+
+ rh.OnDelete(es)
+ rh.OnAdd(es)
+
// Should have no clusters because Protocol and UpstreamValidation is inconsistent.
c.Request(clusterType).Equals(&envoy_service_discovery_v3.DiscoveryResponse{
TypeUrl: clusterType,
diff --git a/internal/featuretests/v3/global_authorization_test.go b/internal/featuretests/v3/global_authorization_test.go
index c2b35f58cae..4c134a6073d 100644
--- a/internal/featuretests/v3/global_authorization_test.go
+++ b/internal/featuretests/v3/global_authorization_test.go
@@ -47,6 +47,7 @@ var (
Name: "extension",
Namespace: "auth",
},
+ ServiceAPIType: contour_v1.AuthorizationGRPCService,
FailOpen: false,
ResponseTimeout: defaultResponseTimeout.String(),
AuthPolicy: &contour_v1.AuthorizationPolicy{
@@ -62,6 +63,7 @@ var (
Name: "extension",
Namespace: "auth",
},
+ ServiceAPIType: contour_v1.AuthorizationGRPCService,
FailOpen: false,
ResponseTimeout: defaultResponseTimeout.String(),
AuthPolicy: &contour_v1.AuthorizationPolicy{
@@ -580,6 +582,7 @@ func globalExternalAuthorizationWithTLSAuthOverride(t *testing.T, rh ResourceEve
Namespace: "auth",
Name: "extension",
},
+ ServiceAPIType: contour_v1.AuthorizationGRPCService,
ResponseTimeout: defaultResponseTimeout.String(),
FailOpen: true,
WithRequestBody: &contour_v1.AuthorizationServerBufferSettings{
@@ -800,7 +803,8 @@ func TestGlobalAuthorization(t *testing.T) {
ExtensionService: k8s.NamespacedNameFrom("auth/extension"),
Timeout: timeout.DurationSetting(defaultResponseTimeout),
},
- FailOpen: false,
+ ServiceAPIType: contour_v1.AuthorizationGRPCService,
+ FailOpen: false,
Context: map[string]string{
"header_type": "root_config",
"header_1": "message_1",
diff --git a/internal/xdscache/v3/listener.go b/internal/xdscache/v3/listener.go
index a0e62004d80..a9d68c347c5 100644
--- a/internal/xdscache/v3/listener.go
+++ b/internal/xdscache/v3/listener.go
@@ -25,6 +25,7 @@ import (
"google.golang.org/protobuf/proto"
"k8s.io/apimachinery/pkg/types"
+ contour_v1 "github.com/projectcontour/contour/apis/projectcontour/v1"
contour_v1alpha1 "github.com/projectcontour/contour/apis/projectcontour/v1alpha1"
"github.com/projectcontour/contour/internal/contourconfig"
"github.com/projectcontour/contour/internal/dag"
@@ -202,9 +203,14 @@ type RateLimitConfig struct {
type GlobalExternalAuthConfig struct {
ExtensionServiceConfig
- FailOpen bool
- Context map[string]string
- WithRequestBody *dag.AuthorizationServerBufferSettings
+ FailOpen bool
+ Context map[string]string
+ ServiceAPIType contour_v1.AuthorizationServiceAPIType
+ HTTPAllowedAuthorizationHeaders []contour_v1.HTTPAuthorizationServerAllowedHeaders
+ HTTPAllowedUpstreamHeaders []contour_v1.HTTPAuthorizationServerAllowedHeaders
+ HTTPPathPrefix string
+ WithRequestBody *dag.AuthorizationServerBufferSettings
+ // HttpServerURI string
}
// httpAccessLog returns the access log for the HTTP (non TLS)
@@ -604,6 +610,10 @@ func httpGlobalExternalAuthConfig(config *GlobalExternalAuthConfig) *envoy_filte
Name: dag.ExtensionClusterName(config.ExtensionService),
SNI: config.SNI,
},
+ ServiceAPIType: config.ServiceAPIType,
+ HTTPAllowedAuthorizationHeaders: config.HTTPAllowedAuthorizationHeaders,
+ HTTPAllowedUpstreamHeaders: config.HTTPAllowedUpstreamHeaders,
+ HTTPPathPrefix: config.HTTPPathPrefix,
AuthorizationFailOpen: config.FailOpen,
AuthorizationResponseTimeout: config.Timeout,
AuthorizationServerWithRequestBody: config.WithRequestBody,
diff --git a/pkg/config/parameters.go b/pkg/config/parameters.go
index 1e4c397d513..4af63ad86dc 100644
--- a/pkg/config/parameters.go
+++ b/pkg/config/parameters.go
@@ -761,6 +761,16 @@ type GlobalExternalAuthorization struct {
// ExtensionService identifies the extension service defining the RLS,
// formatted as /.
ExtensionService string `yaml:"extensionService,omitempty"`
+ // ServiceAPIType defines the external authorization service API type.
+ // It indicates the protocol implemented by the external server, specifying whether it's a raw HTTP authorization server
+ // or a gRPC authorization server.
+ //
+ // +optional
+ ServiceAPIType contour_v1.AuthorizationServiceAPIType `json:"serviceAPIType,omitempty"`
+ // HttpAuthorizationServerSettings defines configurations for interacting with an external HTTP authorization server.
+ //
+ // +optional
+ HTTPServerSettings *contour_v1.HTTPAuthorizationServerSettings `json:"httpSettings,omitempty"`
// AuthPolicy sets a default authorization policy for client requests.
// This policy will be used unless overridden by individual routes.
//
diff --git a/site/content/docs/main/config/api-reference.html b/site/content/docs/main/config/api-reference.html
index f985ae33037..2c024e8cf55 100644
--- a/site/content/docs/main/config/api-reference.html
+++ b/site/content/docs/main/config/api-reference.html
@@ -361,6 +361,37 @@ AuthorizationServer
+serviceAPIType
+
+
+
+AuthorizationServiceAPIType
+
+
+ |
+
+(Optional)
+ ServiceAPIType sets the protocol used to communicate with
+the external authorization server.
+ |
+
+
+
+httpSettings
+
+
+
+HTTPAuthorizationServerSettings
+
+
+ |
+
+(Optional)
+ HTTPAuthorizationServerSettings defines configurations for interacting with an external HTTP authorization server.
+ |
+
+
+
authPolicy
@@ -482,6 +513,29 @@ AuthorizationSer
|
+AuthorizationServiceAPIType
+(string alias)
+
+(Appears on:
+AuthorizationServer)
+
+
+
AuthorizationServiceAPIType indicates the protocol
+implemented by the external authorization server.
+
+
+
+
+| Value |
+Description |
+
+
+"grpc" |
+ |
+
"http" |
+ |
+
+
@@ -1281,6 +1335,156 @@
GlobalRateLimitPolicy
+
+
+(Appears on:
+HTTPAuthorizationServerSettings)
+
+
+
HTTPAuthorizationServerAllowedHeaders specifies how to conditionally match against allowed headers
+in the context of HTTP authorization. Regex support is intentionally excluded to simplify the user
+experience and prevent potential issues. Only one of Prefix, Exact, Suffix or Contains must be provided.
+
+
+
+
+| Field |
+Description |
+
+
+
+
+
+exact
+
+
+string
+
+ |
+
+(Optional)
+ Exact specifies a string that the header name must be equal to.
+ |
+
+
+
+prefix
+
+
+string
+
+ |
+
+(Optional)
+ Prefix defines a prefix match for the header name.
+ |
+
+
+
+suffix
+
+
+string
+
+ |
+
+(Optional)
+ Suffix defines a suffix match for a header name.
+ |
+
+
+
+contains
+
+
+string
+
+ |
+
+(Optional)
+ Contains specifies a substring that must be present in the header name.
+ |
+
+
+
+ignoreCase
+
+
+bool
+
+ |
+
+(Optional)
+ IgnoreCase specifies whether string matching should be case-insensitive.
+ |
+
+
+
+HTTPAuthorizationServerSettings
+
+
+(Appears on:
+AuthorizationServer)
+
+
+
HTTPAuthorizationServerSettings defines configurations for interacting with an external HTTP authorization server.
+
+
+
+
+| Field |
+Description |
+
+
+
+
+
+pathPrefix
+
+
+string
+
+ |
+
+(Optional)
+ PathPrefix Sets a prefix to the value of authorization request header Path.
+ |
+
+
+
+allowedAuthorizationHeaders
+
+
+
+[]HTTPAuthorizationServerAllowedHeaders
+
+
+ |
+
+(Optional)
+ AllowedAuthorizationHeaders specifies client request headers that will be sent to the authorization server.
+Host, Method, Path, Content-Length, and Authorization headers are additionally included in the list.
+ |
+
+
+
+allowedUpstreamHeaders
+
+
+
+[]HTTPAuthorizationServerAllowedHeaders
+
+
+ |
+
+(Optional)
+ AllowedUpstreamHeaders specifies authorization response headers that will be added to the original client request.
+Coexistent headers will be overridden.
+ |
+
+
+
HTTPDirectResponsePolicy
@@ -5437,7 +5641,7 @@
ExtensionService
|
Services specifies the set of Kubernetes Service resources that
-receive GRPC extension API requests.
+receive extension API requests.
If no weights are specified for any of the entries in
this array, traffic will be spread evenly across all the
services.
@@ -5471,7 +5675,7 @@ ExtensionService
|
(Optional)
Protocol may be used to specify (or override) the protocol used to reach this Service.
-Values may be h2 or h2c. If omitted, protocol-selection falls back on Service annotations.
+Values may be h2, h2c or http/1.1. If omitted, protocol-selection falls back on Service annotations.
|
@@ -5486,9 +5690,9 @@ ExtensionService
|
(Optional)
- The policy for load balancing GRPC service requests. Note that the
+ The policy for load balancing service requests. Note that the
Cookie and RequestHash load balancing strategies cannot be used
-here.
+here for GRPC service requests.
|
@@ -7662,7 +7866,7 @@ ExtensionServiceSpec
|
Services specifies the set of Kubernetes Service resources that
-receive GRPC extension API requests.
+receive extension API requests.
If no weights are specified for any of the entries in
this array, traffic will be spread evenly across all the
services.
@@ -7696,7 +7900,7 @@ ExtensionServiceSpec
|
(Optional)
Protocol may be used to specify (or override) the protocol used to reach this Service.
-Values may be h2 or h2c. If omitted, protocol-selection falls back on Service annotations.
+Values may be h2, h2c or http/1.1. If omitted, protocol-selection falls back on Service annotations.
|
|
@@ -7711,9 +7915,9 @@ ExtensionServiceSpec
|
(Optional)
- The policy for load balancing GRPC service requests. Note that the
+ The policy for load balancing service requests. Note that the
Cookie and RequestHash load balancing strategies cannot be used
-here.
+here for GRPC service requests.
|
From 0a50822f2145f6f334b6e142aa56d60f9cd0629f Mon Sep 17 00:00:00 2001
From: therealak12
Date: Sat, 11 Apr 2026 10:37:29 +0330
Subject: [PATCH 2/2] Apply Tero Saarni's suggestions
Signed-off-by: therealak12
---
apis/projectcontour/v1/httpproxy.go | 21 ++--
cmd/contour/serve.go | 49 ++------
cmd/contour/servecontext.go | 2 +-
examples/contour/01-crds.yaml | 69 +++++++++--
examples/render/contour-deployment.yaml | 69 +++++++++--
.../render/contour-gateway-provisioner.yaml | 69 +++++++++--
examples/render/contour-gateway.yaml | 69 +++++++++--
examples/render/contour.yaml | 69 +++++++++--
internal/dag/dag.go | 39 ++++++-
internal/dag/httpproxy_processor.go | 59 ++--------
internal/envoy/v3/listener.go | 44 ++++---
.../featuretests/v3/authorization_test.go | 110 ++++++++++++++----
.../v3/global_authorization_test.go | 10 +-
internal/xdscache/v3/listener.go | 15 +--
pkg/config/parameters.go | 6 +-
.../docs/main/config/api-reference.html | 19 +--
16 files changed, 481 insertions(+), 238 deletions(-)
diff --git a/apis/projectcontour/v1/httpproxy.go b/apis/projectcontour/v1/httpproxy.go
index c30a8b243f8..e0ca3f53b46 100644
--- a/apis/projectcontour/v1/httpproxy.go
+++ b/apis/projectcontour/v1/httpproxy.go
@@ -239,31 +239,33 @@ type ExtensionServiceReference struct {
Name string `json:"name,omitempty" protobuf:"bytes,3,opt,name=name"`
}
-// AuthorizationServiceAPIType indicates the protocol
+// AuthorizationServiceType indicates the protocol
// implemented by the external authorization server.
-type AuthorizationServiceAPIType string
+type AuthorizationServiceType string
const (
- AuthorizationGRPCService AuthorizationServiceAPIType = "grpc"
- AuthorizationHTTPService AuthorizationServiceAPIType = "http"
+ AuthorizationGRPCService AuthorizationServiceType = "grpc"
+ AuthorizationHTTPService AuthorizationServiceType = "http"
)
// AuthorizationServer configures an external server to authenticate
// client requests. The external server must implement the v3 Envoy
-// external authorization GRPC protocol (https://www.envoyproxy.io/docs/envoy/latest/api-v3/service/auth/v3/external_auth.proto).
+// external authorization GRPC protocol (https://www.envoyproxy.io/docs/envoy/latest/api-v3/service/auth/v3/external_auth.proto)
+// or the HTTP authorization server protocol.
+// +kubebuilder:validation:XValidation:message="httpSettings can only be set when serviceType is 'http'",rule="!has(self.httpSettings) || self.serviceType == 'http'"
type AuthorizationServer struct {
// ExtensionServiceRef specifies the extension resource that will authorize client requests.
//
// +optional
ExtensionServiceRef ExtensionServiceReference `json:"extensionRef,omitempty"`
- // ServiceAPIType sets the protocol used to communicate with
+ // ServiceType sets the protocol used to communicate with
// the external authorization server.
//
// +optional
// +kubebuilder:validation:Enum=http;grpc
// +kubebuilder:default=grpc
- ServiceAPIType AuthorizationServiceAPIType `json:"serviceAPIType,omitempty"`
+ ServiceType AuthorizationServiceType `json:"serviceType,omitempty"`
// HTTPAuthorizationServerSettings defines configurations for interacting with an external HTTP authorization server.
//
@@ -311,8 +313,8 @@ type HTTPAuthorizationServerSettings struct {
// +optional
AllowedAuthorizationHeaders []HTTPAuthorizationServerAllowedHeaders `json:"allowedAuthorizationHeaders,omitempty"`
- // AllowedUpstreamHeaders specifies authorization response headers that will be added to the original client request.
- // Coexistent headers will be overridden.
+ // AllowedUpstreamHeaders specifies response headers from the authorization server
+ // that may be added to the original client request before sending it to the upstream.
//
// +optional
AllowedUpstreamHeaders []HTTPAuthorizationServerAllowedHeaders `json:"allowedUpstreamHeaders,omitempty"`
@@ -321,6 +323,7 @@ type HTTPAuthorizationServerSettings struct {
// HTTPAuthorizationServerAllowedHeaders specifies how to conditionally match against allowed headers
// in the context of HTTP authorization. Regex support is intentionally excluded to simplify the user
// experience and prevent potential issues. Only one of Prefix, Exact, Suffix or Contains must be provided.
+// +kubebuilder:validation:XValidation:message="only one of prefix, suffix, exact, and contains should be set in the allowedHeader",rule="(has(self.exact) ? 1 : 0) + (has(self.prefix) ? 1 : 0) + (has(self.suffix) ? 1 : 0) + (has(self.contains) ? 1 : 0) == 1"
type HTTPAuthorizationServerAllowedHeaders struct {
// Exact specifies a string that the header name must be equal to.
//
diff --git a/cmd/contour/serve.go b/cmd/contour/serve.go
index 9b291279a73..1e449f0a9c1 100644
--- a/cmd/contour/serve.go
+++ b/cmd/contour/serve.go
@@ -830,48 +830,17 @@ func (s *Server) setupGlobalExternalAuthentication(contourConfiguration contour_
context = contourConfiguration.GlobalExternalAuthorization.AuthPolicy.Context
}
- globalExternalAuthConfig := &xdscache_v3.GlobalExternalAuthConfig{
- ExtensionServiceConfig: extensionSvcConfig,
- FailOpen: contourConfiguration.GlobalExternalAuthorization.FailOpen,
- Context: context,
+ var validCond contour_v1.DetailedCondition
+ extAuth := dag.NewExternalAuthorization(contourConfiguration.GlobalExternalAuthorization, &validCond)
+ if len(validCond.Errors) > 0 {
+ return nil, fmt.Errorf("%s", validCond.Errors[0].Message)
}
- switch contourConfiguration.GlobalExternalAuthorization.ServiceAPIType {
- case contour_v1.AuthorizationGRPCService:
- globalExternalAuthConfig.ServiceAPIType = contour_v1.AuthorizationGRPCService
- case contour_v1.AuthorizationHTTPService:
- globalExternalAuthConfig.ServiceAPIType = contour_v1.AuthorizationHTTPService
- if contourConfiguration.GlobalExternalAuthorization.HTTPServerSettings != nil {
- globalExternalAuthConfig.HTTPPathPrefix = contourConfiguration.GlobalExternalAuthorization.HTTPServerSettings.PathPrefix
-
- // globalExternalAuthConfig.HttpServerURI = contourConfiguration.GlobalExternalAuthorization.HttpServerSettings.ServerURI
-
- if len(contourConfiguration.GlobalExternalAuthorization.HTTPServerSettings.AllowedAuthorizationHeaders) > 0 {
- if err := dag.ExternalAuthAllowedHeadersValid(contourConfiguration.GlobalExternalAuthorization.HTTPServerSettings.AllowedAuthorizationHeaders); err != nil {
- return nil, err
- }
-
- globalExternalAuthConfig.HTTPAllowedAuthorizationHeaders = contourConfiguration.GlobalExternalAuthorization.HTTPServerSettings.AllowedAuthorizationHeaders
- }
-
- if len(contourConfiguration.GlobalExternalAuthorization.HTTPServerSettings.AllowedUpstreamHeaders) > 0 {
- if err := dag.ExternalAuthAllowedHeadersValid(contourConfiguration.GlobalExternalAuthorization.HTTPServerSettings.AllowedUpstreamHeaders); err != nil {
- return nil, err
- }
-
- globalExternalAuthConfig.HTTPAllowedUpstreamHeaders = contourConfiguration.GlobalExternalAuthorization.HTTPServerSettings.AllowedUpstreamHeaders
- }
- }
- }
-
- if contourConfiguration.GlobalExternalAuthorization.WithRequestBody != nil {
- globalExternalAuthConfig.WithRequestBody = &dag.AuthorizationServerBufferSettings{
- PackAsBytes: contourConfiguration.GlobalExternalAuthorization.WithRequestBody.PackAsBytes,
- AllowPartialMessage: contourConfiguration.GlobalExternalAuthorization.WithRequestBody.AllowPartialMessage,
- MaxRequestBytes: contourConfiguration.GlobalExternalAuthorization.WithRequestBody.MaxRequestBytes,
- }
- }
- return globalExternalAuthConfig, nil
+ return &xdscache_v3.GlobalExternalAuthConfig{
+ ExtensionServiceConfig: extensionSvcConfig,
+ ExternalAuthorization: *extAuth,
+ Context: context,
+ }, nil
}
func (s *Server) setupDebugService(debugConfig contour_v1alpha1.DebugConfig, builder *dag.Builder) error {
diff --git a/cmd/contour/servecontext.go b/cmd/contour/servecontext.go
index 9ddb8e4a5cf..d4f09ce5b4a 100644
--- a/cmd/contour/servecontext.go
+++ b/cmd/contour/servecontext.go
@@ -457,7 +457,7 @@ func (ctx *serveContext) convertToContourConfigurationSpec() contour_v1alpha1.Co
Name: nsedName.Name,
Namespace: nsedName.Namespace,
},
- ServiceAPIType: ctx.Config.GlobalExternalAuthorization.ServiceAPIType,
+ ServiceType: ctx.Config.GlobalExternalAuthorization.ServiceType,
ResponseTimeout: ctx.Config.GlobalExternalAuthorization.ResponseTimeout,
FailOpen: ctx.Config.GlobalExternalAuthorization.FailOpen,
}
diff --git a/examples/contour/01-crds.yaml b/examples/contour/01-crds.yaml
index 8348305dee8..c4c8f39fc9b 100644
--- a/examples/contour/01-crds.yaml
+++ b/examples/contour/01-crds.yaml
@@ -762,11 +762,17 @@ spec:
name.
type: string
type: object
+ x-kubernetes-validations:
+ - message: only one of prefix, suffix, exact, and contains
+ should be set in the allowedHeader
+ rule: '(has(self.exact) ? 1 : 0) + (has(self.prefix) ?
+ 1 : 0) + (has(self.suffix) ? 1 : 0) + (has(self.contains)
+ ? 1 : 0) == 1'
type: array
allowedUpstreamHeaders:
description: |-
- AllowedUpstreamHeaders specifies authorization response headers that will be added to the original client request.
- Coexistent headers will be overridden.
+ AllowedUpstreamHeaders specifies response headers from the authorization server
+ that may be added to the original client request before sending it to the upstream.
items:
description: |-
HTTPAuthorizationServerAllowedHeaders specifies how to conditionally match against allowed headers
@@ -794,6 +800,12 @@ spec:
name.
type: string
type: object
+ x-kubernetes-validations:
+ - message: only one of prefix, suffix, exact, and contains
+ should be set in the allowedHeader
+ rule: '(has(self.exact) ? 1 : 0) + (has(self.prefix) ?
+ 1 : 0) + (has(self.suffix) ? 1 : 0) + (has(self.contains)
+ ? 1 : 0) == 1'
type: array
pathPrefix:
description: PathPrefix Sets a prefix to the value of authorization
@@ -808,10 +820,10 @@ spec:
The string "infinity" is also a valid input and specifies no timeout.
pattern: ^(((\d*(\.\d*)?h)|(\d*(\.\d*)?m)|(\d*(\.\d*)?s)|(\d*(\.\d*)?ms)|(\d*(\.\d*)?us)|(\d*(\.\d*)?µs)|(\d*(\.\d*)?ns))+|infinity|infinite)$
type: string
- serviceAPIType:
+ serviceType:
default: grpc
description: |-
- ServiceAPIType sets the protocol used to communicate with
+ ServiceType sets the protocol used to communicate with
the external authorization server.
enum:
- http
@@ -838,6 +850,9 @@ spec:
type: boolean
type: object
type: object
+ x-kubernetes-validations:
+ - message: httpSettings can only be set when serviceType is 'http'
+ rule: '!has(self.httpSettings) || self.serviceType == ''http'''
health:
description: |-
Health defines the endpoints Contour uses to serve health checks.
@@ -4792,11 +4807,17 @@ spec:
header name.
type: string
type: object
+ x-kubernetes-validations:
+ - message: only one of prefix, suffix, exact, and contains
+ should be set in the allowedHeader
+ rule: '(has(self.exact) ? 1 : 0) + (has(self.prefix)
+ ? 1 : 0) + (has(self.suffix) ? 1 : 0) + (has(self.contains)
+ ? 1 : 0) == 1'
type: array
allowedUpstreamHeaders:
description: |-
- AllowedUpstreamHeaders specifies authorization response headers that will be added to the original client request.
- Coexistent headers will be overridden.
+ AllowedUpstreamHeaders specifies response headers from the authorization server
+ that may be added to the original client request before sending it to the upstream.
items:
description: |-
HTTPAuthorizationServerAllowedHeaders specifies how to conditionally match against allowed headers
@@ -4824,6 +4845,12 @@ spec:
header name.
type: string
type: object
+ x-kubernetes-validations:
+ - message: only one of prefix, suffix, exact, and contains
+ should be set in the allowedHeader
+ rule: '(has(self.exact) ? 1 : 0) + (has(self.prefix)
+ ? 1 : 0) + (has(self.suffix) ? 1 : 0) + (has(self.contains)
+ ? 1 : 0) == 1'
type: array
pathPrefix:
description: PathPrefix Sets a prefix to the value of
@@ -4838,10 +4865,10 @@ spec:
The string "infinity" is also a valid input and specifies no timeout.
pattern: ^(((\d*(\.\d*)?h)|(\d*(\.\d*)?m)|(\d*(\.\d*)?s)|(\d*(\.\d*)?ms)|(\d*(\.\d*)?us)|(\d*(\.\d*)?µs)|(\d*(\.\d*)?ns))+|infinity|infinite)$
type: string
- serviceAPIType:
+ serviceType:
default: grpc
description: |-
- ServiceAPIType sets the protocol used to communicate with
+ ServiceType sets the protocol used to communicate with
the external authorization server.
enum:
- http
@@ -4868,6 +4895,9 @@ spec:
type: boolean
type: object
type: object
+ x-kubernetes-validations:
+ - message: httpSettings can only be set when serviceType is 'http'
+ rule: '!has(self.httpSettings) || self.serviceType == ''http'''
health:
description: |-
Health defines the endpoints Contour uses to serve health checks.
@@ -7850,11 +7880,17 @@ spec:
header name.
type: string
type: object
+ x-kubernetes-validations:
+ - message: only one of prefix, suffix, exact, and contains
+ should be set in the allowedHeader
+ rule: '(has(self.exact) ? 1 : 0) + (has(self.prefix)
+ ? 1 : 0) + (has(self.suffix) ? 1 : 0) + (has(self.contains)
+ ? 1 : 0) == 1'
type: array
allowedUpstreamHeaders:
description: |-
- AllowedUpstreamHeaders specifies authorization response headers that will be added to the original client request.
- Coexistent headers will be overridden.
+ AllowedUpstreamHeaders specifies response headers from the authorization server
+ that may be added to the original client request before sending it to the upstream.
items:
description: |-
HTTPAuthorizationServerAllowedHeaders specifies how to conditionally match against allowed headers
@@ -7882,6 +7918,12 @@ spec:
header name.
type: string
type: object
+ x-kubernetes-validations:
+ - message: only one of prefix, suffix, exact, and contains
+ should be set in the allowedHeader
+ rule: '(has(self.exact) ? 1 : 0) + (has(self.prefix)
+ ? 1 : 0) + (has(self.suffix) ? 1 : 0) + (has(self.contains)
+ ? 1 : 0) == 1'
type: array
pathPrefix:
description: PathPrefix Sets a prefix to the value of
@@ -7896,10 +7938,10 @@ spec:
The string "infinity" is also a valid input and specifies no timeout.
pattern: ^(((\d*(\.\d*)?h)|(\d*(\.\d*)?m)|(\d*(\.\d*)?s)|(\d*(\.\d*)?ms)|(\d*(\.\d*)?us)|(\d*(\.\d*)?µs)|(\d*(\.\d*)?ns))+|infinity|infinite)$
type: string
- serviceAPIType:
+ serviceType:
default: grpc
description: |-
- ServiceAPIType sets the protocol used to communicate with
+ ServiceType sets the protocol used to communicate with
the external authorization server.
enum:
- http
@@ -7926,6 +7968,9 @@ spec:
type: boolean
type: object
type: object
+ x-kubernetes-validations:
+ - message: httpSettings can only be set when serviceType is 'http'
+ rule: '!has(self.httpSettings) || self.serviceType == ''http'''
corsPolicy:
description: Specifies the cross-origin policy to apply to the
VirtualHost.
diff --git a/examples/render/contour-deployment.yaml b/examples/render/contour-deployment.yaml
index b9c74917f28..264be05fbe3 100644
--- a/examples/render/contour-deployment.yaml
+++ b/examples/render/contour-deployment.yaml
@@ -981,11 +981,17 @@ spec:
name.
type: string
type: object
+ x-kubernetes-validations:
+ - message: only one of prefix, suffix, exact, and contains
+ should be set in the allowedHeader
+ rule: '(has(self.exact) ? 1 : 0) + (has(self.prefix) ?
+ 1 : 0) + (has(self.suffix) ? 1 : 0) + (has(self.contains)
+ ? 1 : 0) == 1'
type: array
allowedUpstreamHeaders:
description: |-
- AllowedUpstreamHeaders specifies authorization response headers that will be added to the original client request.
- Coexistent headers will be overridden.
+ AllowedUpstreamHeaders specifies response headers from the authorization server
+ that may be added to the original client request before sending it to the upstream.
items:
description: |-
HTTPAuthorizationServerAllowedHeaders specifies how to conditionally match against allowed headers
@@ -1013,6 +1019,12 @@ spec:
name.
type: string
type: object
+ x-kubernetes-validations:
+ - message: only one of prefix, suffix, exact, and contains
+ should be set in the allowedHeader
+ rule: '(has(self.exact) ? 1 : 0) + (has(self.prefix) ?
+ 1 : 0) + (has(self.suffix) ? 1 : 0) + (has(self.contains)
+ ? 1 : 0) == 1'
type: array
pathPrefix:
description: PathPrefix Sets a prefix to the value of authorization
@@ -1027,10 +1039,10 @@ spec:
The string "infinity" is also a valid input and specifies no timeout.
pattern: ^(((\d*(\.\d*)?h)|(\d*(\.\d*)?m)|(\d*(\.\d*)?s)|(\d*(\.\d*)?ms)|(\d*(\.\d*)?us)|(\d*(\.\d*)?µs)|(\d*(\.\d*)?ns))+|infinity|infinite)$
type: string
- serviceAPIType:
+ serviceType:
default: grpc
description: |-
- ServiceAPIType sets the protocol used to communicate with
+ ServiceType sets the protocol used to communicate with
the external authorization server.
enum:
- http
@@ -1057,6 +1069,9 @@ spec:
type: boolean
type: object
type: object
+ x-kubernetes-validations:
+ - message: httpSettings can only be set when serviceType is 'http'
+ rule: '!has(self.httpSettings) || self.serviceType == ''http'''
health:
description: |-
Health defines the endpoints Contour uses to serve health checks.
@@ -5011,11 +5026,17 @@ spec:
header name.
type: string
type: object
+ x-kubernetes-validations:
+ - message: only one of prefix, suffix, exact, and contains
+ should be set in the allowedHeader
+ rule: '(has(self.exact) ? 1 : 0) + (has(self.prefix)
+ ? 1 : 0) + (has(self.suffix) ? 1 : 0) + (has(self.contains)
+ ? 1 : 0) == 1'
type: array
allowedUpstreamHeaders:
description: |-
- AllowedUpstreamHeaders specifies authorization response headers that will be added to the original client request.
- Coexistent headers will be overridden.
+ AllowedUpstreamHeaders specifies response headers from the authorization server
+ that may be added to the original client request before sending it to the upstream.
items:
description: |-
HTTPAuthorizationServerAllowedHeaders specifies how to conditionally match against allowed headers
@@ -5043,6 +5064,12 @@ spec:
header name.
type: string
type: object
+ x-kubernetes-validations:
+ - message: only one of prefix, suffix, exact, and contains
+ should be set in the allowedHeader
+ rule: '(has(self.exact) ? 1 : 0) + (has(self.prefix)
+ ? 1 : 0) + (has(self.suffix) ? 1 : 0) + (has(self.contains)
+ ? 1 : 0) == 1'
type: array
pathPrefix:
description: PathPrefix Sets a prefix to the value of
@@ -5057,10 +5084,10 @@ spec:
The string "infinity" is also a valid input and specifies no timeout.
pattern: ^(((\d*(\.\d*)?h)|(\d*(\.\d*)?m)|(\d*(\.\d*)?s)|(\d*(\.\d*)?ms)|(\d*(\.\d*)?us)|(\d*(\.\d*)?µs)|(\d*(\.\d*)?ns))+|infinity|infinite)$
type: string
- serviceAPIType:
+ serviceType:
default: grpc
description: |-
- ServiceAPIType sets the protocol used to communicate with
+ ServiceType sets the protocol used to communicate with
the external authorization server.
enum:
- http
@@ -5087,6 +5114,9 @@ spec:
type: boolean
type: object
type: object
+ x-kubernetes-validations:
+ - message: httpSettings can only be set when serviceType is 'http'
+ rule: '!has(self.httpSettings) || self.serviceType == ''http'''
health:
description: |-
Health defines the endpoints Contour uses to serve health checks.
@@ -8069,11 +8099,17 @@ spec:
header name.
type: string
type: object
+ x-kubernetes-validations:
+ - message: only one of prefix, suffix, exact, and contains
+ should be set in the allowedHeader
+ rule: '(has(self.exact) ? 1 : 0) + (has(self.prefix)
+ ? 1 : 0) + (has(self.suffix) ? 1 : 0) + (has(self.contains)
+ ? 1 : 0) == 1'
type: array
allowedUpstreamHeaders:
description: |-
- AllowedUpstreamHeaders specifies authorization response headers that will be added to the original client request.
- Coexistent headers will be overridden.
+ AllowedUpstreamHeaders specifies response headers from the authorization server
+ that may be added to the original client request before sending it to the upstream.
items:
description: |-
HTTPAuthorizationServerAllowedHeaders specifies how to conditionally match against allowed headers
@@ -8101,6 +8137,12 @@ spec:
header name.
type: string
type: object
+ x-kubernetes-validations:
+ - message: only one of prefix, suffix, exact, and contains
+ should be set in the allowedHeader
+ rule: '(has(self.exact) ? 1 : 0) + (has(self.prefix)
+ ? 1 : 0) + (has(self.suffix) ? 1 : 0) + (has(self.contains)
+ ? 1 : 0) == 1'
type: array
pathPrefix:
description: PathPrefix Sets a prefix to the value of
@@ -8115,10 +8157,10 @@ spec:
The string "infinity" is also a valid input and specifies no timeout.
pattern: ^(((\d*(\.\d*)?h)|(\d*(\.\d*)?m)|(\d*(\.\d*)?s)|(\d*(\.\d*)?ms)|(\d*(\.\d*)?us)|(\d*(\.\d*)?µs)|(\d*(\.\d*)?ns))+|infinity|infinite)$
type: string
- serviceAPIType:
+ serviceType:
default: grpc
description: |-
- ServiceAPIType sets the protocol used to communicate with
+ ServiceType sets the protocol used to communicate with
the external authorization server.
enum:
- http
@@ -8145,6 +8187,9 @@ spec:
type: boolean
type: object
type: object
+ x-kubernetes-validations:
+ - message: httpSettings can only be set when serviceType is 'http'
+ rule: '!has(self.httpSettings) || self.serviceType == ''http'''
corsPolicy:
description: Specifies the cross-origin policy to apply to the
VirtualHost.
diff --git a/examples/render/contour-gateway-provisioner.yaml b/examples/render/contour-gateway-provisioner.yaml
index 4e34ef1d20e..3a175d8ca03 100644
--- a/examples/render/contour-gateway-provisioner.yaml
+++ b/examples/render/contour-gateway-provisioner.yaml
@@ -773,11 +773,17 @@ spec:
name.
type: string
type: object
+ x-kubernetes-validations:
+ - message: only one of prefix, suffix, exact, and contains
+ should be set in the allowedHeader
+ rule: '(has(self.exact) ? 1 : 0) + (has(self.prefix) ?
+ 1 : 0) + (has(self.suffix) ? 1 : 0) + (has(self.contains)
+ ? 1 : 0) == 1'
type: array
allowedUpstreamHeaders:
description: |-
- AllowedUpstreamHeaders specifies authorization response headers that will be added to the original client request.
- Coexistent headers will be overridden.
+ AllowedUpstreamHeaders specifies response headers from the authorization server
+ that may be added to the original client request before sending it to the upstream.
items:
description: |-
HTTPAuthorizationServerAllowedHeaders specifies how to conditionally match against allowed headers
@@ -805,6 +811,12 @@ spec:
name.
type: string
type: object
+ x-kubernetes-validations:
+ - message: only one of prefix, suffix, exact, and contains
+ should be set in the allowedHeader
+ rule: '(has(self.exact) ? 1 : 0) + (has(self.prefix) ?
+ 1 : 0) + (has(self.suffix) ? 1 : 0) + (has(self.contains)
+ ? 1 : 0) == 1'
type: array
pathPrefix:
description: PathPrefix Sets a prefix to the value of authorization
@@ -819,10 +831,10 @@ spec:
The string "infinity" is also a valid input and specifies no timeout.
pattern: ^(((\d*(\.\d*)?h)|(\d*(\.\d*)?m)|(\d*(\.\d*)?s)|(\d*(\.\d*)?ms)|(\d*(\.\d*)?us)|(\d*(\.\d*)?µs)|(\d*(\.\d*)?ns))+|infinity|infinite)$
type: string
- serviceAPIType:
+ serviceType:
default: grpc
description: |-
- ServiceAPIType sets the protocol used to communicate with
+ ServiceType sets the protocol used to communicate with
the external authorization server.
enum:
- http
@@ -849,6 +861,9 @@ spec:
type: boolean
type: object
type: object
+ x-kubernetes-validations:
+ - message: httpSettings can only be set when serviceType is 'http'
+ rule: '!has(self.httpSettings) || self.serviceType == ''http'''
health:
description: |-
Health defines the endpoints Contour uses to serve health checks.
@@ -4803,11 +4818,17 @@ spec:
header name.
type: string
type: object
+ x-kubernetes-validations:
+ - message: only one of prefix, suffix, exact, and contains
+ should be set in the allowedHeader
+ rule: '(has(self.exact) ? 1 : 0) + (has(self.prefix)
+ ? 1 : 0) + (has(self.suffix) ? 1 : 0) + (has(self.contains)
+ ? 1 : 0) == 1'
type: array
allowedUpstreamHeaders:
description: |-
- AllowedUpstreamHeaders specifies authorization response headers that will be added to the original client request.
- Coexistent headers will be overridden.
+ AllowedUpstreamHeaders specifies response headers from the authorization server
+ that may be added to the original client request before sending it to the upstream.
items:
description: |-
HTTPAuthorizationServerAllowedHeaders specifies how to conditionally match against allowed headers
@@ -4835,6 +4856,12 @@ spec:
header name.
type: string
type: object
+ x-kubernetes-validations:
+ - message: only one of prefix, suffix, exact, and contains
+ should be set in the allowedHeader
+ rule: '(has(self.exact) ? 1 : 0) + (has(self.prefix)
+ ? 1 : 0) + (has(self.suffix) ? 1 : 0) + (has(self.contains)
+ ? 1 : 0) == 1'
type: array
pathPrefix:
description: PathPrefix Sets a prefix to the value of
@@ -4849,10 +4876,10 @@ spec:
The string "infinity" is also a valid input and specifies no timeout.
pattern: ^(((\d*(\.\d*)?h)|(\d*(\.\d*)?m)|(\d*(\.\d*)?s)|(\d*(\.\d*)?ms)|(\d*(\.\d*)?us)|(\d*(\.\d*)?µs)|(\d*(\.\d*)?ns))+|infinity|infinite)$
type: string
- serviceAPIType:
+ serviceType:
default: grpc
description: |-
- ServiceAPIType sets the protocol used to communicate with
+ ServiceType sets the protocol used to communicate with
the external authorization server.
enum:
- http
@@ -4879,6 +4906,9 @@ spec:
type: boolean
type: object
type: object
+ x-kubernetes-validations:
+ - message: httpSettings can only be set when serviceType is 'http'
+ rule: '!has(self.httpSettings) || self.serviceType == ''http'''
health:
description: |-
Health defines the endpoints Contour uses to serve health checks.
@@ -7861,11 +7891,17 @@ spec:
header name.
type: string
type: object
+ x-kubernetes-validations:
+ - message: only one of prefix, suffix, exact, and contains
+ should be set in the allowedHeader
+ rule: '(has(self.exact) ? 1 : 0) + (has(self.prefix)
+ ? 1 : 0) + (has(self.suffix) ? 1 : 0) + (has(self.contains)
+ ? 1 : 0) == 1'
type: array
allowedUpstreamHeaders:
description: |-
- AllowedUpstreamHeaders specifies authorization response headers that will be added to the original client request.
- Coexistent headers will be overridden.
+ AllowedUpstreamHeaders specifies response headers from the authorization server
+ that may be added to the original client request before sending it to the upstream.
items:
description: |-
HTTPAuthorizationServerAllowedHeaders specifies how to conditionally match against allowed headers
@@ -7893,6 +7929,12 @@ spec:
header name.
type: string
type: object
+ x-kubernetes-validations:
+ - message: only one of prefix, suffix, exact, and contains
+ should be set in the allowedHeader
+ rule: '(has(self.exact) ? 1 : 0) + (has(self.prefix)
+ ? 1 : 0) + (has(self.suffix) ? 1 : 0) + (has(self.contains)
+ ? 1 : 0) == 1'
type: array
pathPrefix:
description: PathPrefix Sets a prefix to the value of
@@ -7907,10 +7949,10 @@ spec:
The string "infinity" is also a valid input and specifies no timeout.
pattern: ^(((\d*(\.\d*)?h)|(\d*(\.\d*)?m)|(\d*(\.\d*)?s)|(\d*(\.\d*)?ms)|(\d*(\.\d*)?us)|(\d*(\.\d*)?µs)|(\d*(\.\d*)?ns))+|infinity|infinite)$
type: string
- serviceAPIType:
+ serviceType:
default: grpc
description: |-
- ServiceAPIType sets the protocol used to communicate with
+ ServiceType sets the protocol used to communicate with
the external authorization server.
enum:
- http
@@ -7937,6 +7979,9 @@ spec:
type: boolean
type: object
type: object
+ x-kubernetes-validations:
+ - message: httpSettings can only be set when serviceType is 'http'
+ rule: '!has(self.httpSettings) || self.serviceType == ''http'''
corsPolicy:
description: Specifies the cross-origin policy to apply to the
VirtualHost.
diff --git a/examples/render/contour-gateway.yaml b/examples/render/contour-gateway.yaml
index b9d01fb463c..77142750f4c 100644
--- a/examples/render/contour-gateway.yaml
+++ b/examples/render/contour-gateway.yaml
@@ -798,11 +798,17 @@ spec:
name.
type: string
type: object
+ x-kubernetes-validations:
+ - message: only one of prefix, suffix, exact, and contains
+ should be set in the allowedHeader
+ rule: '(has(self.exact) ? 1 : 0) + (has(self.prefix) ?
+ 1 : 0) + (has(self.suffix) ? 1 : 0) + (has(self.contains)
+ ? 1 : 0) == 1'
type: array
allowedUpstreamHeaders:
description: |-
- AllowedUpstreamHeaders specifies authorization response headers that will be added to the original client request.
- Coexistent headers will be overridden.
+ AllowedUpstreamHeaders specifies response headers from the authorization server
+ that may be added to the original client request before sending it to the upstream.
items:
description: |-
HTTPAuthorizationServerAllowedHeaders specifies how to conditionally match against allowed headers
@@ -830,6 +836,12 @@ spec:
name.
type: string
type: object
+ x-kubernetes-validations:
+ - message: only one of prefix, suffix, exact, and contains
+ should be set in the allowedHeader
+ rule: '(has(self.exact) ? 1 : 0) + (has(self.prefix) ?
+ 1 : 0) + (has(self.suffix) ? 1 : 0) + (has(self.contains)
+ ? 1 : 0) == 1'
type: array
pathPrefix:
description: PathPrefix Sets a prefix to the value of authorization
@@ -844,10 +856,10 @@ spec:
The string "infinity" is also a valid input and specifies no timeout.
pattern: ^(((\d*(\.\d*)?h)|(\d*(\.\d*)?m)|(\d*(\.\d*)?s)|(\d*(\.\d*)?ms)|(\d*(\.\d*)?us)|(\d*(\.\d*)?µs)|(\d*(\.\d*)?ns))+|infinity|infinite)$
type: string
- serviceAPIType:
+ serviceType:
default: grpc
description: |-
- ServiceAPIType sets the protocol used to communicate with
+ ServiceType sets the protocol used to communicate with
the external authorization server.
enum:
- http
@@ -874,6 +886,9 @@ spec:
type: boolean
type: object
type: object
+ x-kubernetes-validations:
+ - message: httpSettings can only be set when serviceType is 'http'
+ rule: '!has(self.httpSettings) || self.serviceType == ''http'''
health:
description: |-
Health defines the endpoints Contour uses to serve health checks.
@@ -4828,11 +4843,17 @@ spec:
header name.
type: string
type: object
+ x-kubernetes-validations:
+ - message: only one of prefix, suffix, exact, and contains
+ should be set in the allowedHeader
+ rule: '(has(self.exact) ? 1 : 0) + (has(self.prefix)
+ ? 1 : 0) + (has(self.suffix) ? 1 : 0) + (has(self.contains)
+ ? 1 : 0) == 1'
type: array
allowedUpstreamHeaders:
description: |-
- AllowedUpstreamHeaders specifies authorization response headers that will be added to the original client request.
- Coexistent headers will be overridden.
+ AllowedUpstreamHeaders specifies response headers from the authorization server
+ that may be added to the original client request before sending it to the upstream.
items:
description: |-
HTTPAuthorizationServerAllowedHeaders specifies how to conditionally match against allowed headers
@@ -4860,6 +4881,12 @@ spec:
header name.
type: string
type: object
+ x-kubernetes-validations:
+ - message: only one of prefix, suffix, exact, and contains
+ should be set in the allowedHeader
+ rule: '(has(self.exact) ? 1 : 0) + (has(self.prefix)
+ ? 1 : 0) + (has(self.suffix) ? 1 : 0) + (has(self.contains)
+ ? 1 : 0) == 1'
type: array
pathPrefix:
description: PathPrefix Sets a prefix to the value of
@@ -4874,10 +4901,10 @@ spec:
The string "infinity" is also a valid input and specifies no timeout.
pattern: ^(((\d*(\.\d*)?h)|(\d*(\.\d*)?m)|(\d*(\.\d*)?s)|(\d*(\.\d*)?ms)|(\d*(\.\d*)?us)|(\d*(\.\d*)?µs)|(\d*(\.\d*)?ns))+|infinity|infinite)$
type: string
- serviceAPIType:
+ serviceType:
default: grpc
description: |-
- ServiceAPIType sets the protocol used to communicate with
+ ServiceType sets the protocol used to communicate with
the external authorization server.
enum:
- http
@@ -4904,6 +4931,9 @@ spec:
type: boolean
type: object
type: object
+ x-kubernetes-validations:
+ - message: httpSettings can only be set when serviceType is 'http'
+ rule: '!has(self.httpSettings) || self.serviceType == ''http'''
health:
description: |-
Health defines the endpoints Contour uses to serve health checks.
@@ -7886,11 +7916,17 @@ spec:
header name.
type: string
type: object
+ x-kubernetes-validations:
+ - message: only one of prefix, suffix, exact, and contains
+ should be set in the allowedHeader
+ rule: '(has(self.exact) ? 1 : 0) + (has(self.prefix)
+ ? 1 : 0) + (has(self.suffix) ? 1 : 0) + (has(self.contains)
+ ? 1 : 0) == 1'
type: array
allowedUpstreamHeaders:
description: |-
- AllowedUpstreamHeaders specifies authorization response headers that will be added to the original client request.
- Coexistent headers will be overridden.
+ AllowedUpstreamHeaders specifies response headers from the authorization server
+ that may be added to the original client request before sending it to the upstream.
items:
description: |-
HTTPAuthorizationServerAllowedHeaders specifies how to conditionally match against allowed headers
@@ -7918,6 +7954,12 @@ spec:
header name.
type: string
type: object
+ x-kubernetes-validations:
+ - message: only one of prefix, suffix, exact, and contains
+ should be set in the allowedHeader
+ rule: '(has(self.exact) ? 1 : 0) + (has(self.prefix)
+ ? 1 : 0) + (has(self.suffix) ? 1 : 0) + (has(self.contains)
+ ? 1 : 0) == 1'
type: array
pathPrefix:
description: PathPrefix Sets a prefix to the value of
@@ -7932,10 +7974,10 @@ spec:
The string "infinity" is also a valid input and specifies no timeout.
pattern: ^(((\d*(\.\d*)?h)|(\d*(\.\d*)?m)|(\d*(\.\d*)?s)|(\d*(\.\d*)?ms)|(\d*(\.\d*)?us)|(\d*(\.\d*)?µs)|(\d*(\.\d*)?ns))+|infinity|infinite)$
type: string
- serviceAPIType:
+ serviceType:
default: grpc
description: |-
- ServiceAPIType sets the protocol used to communicate with
+ ServiceType sets the protocol used to communicate with
the external authorization server.
enum:
- http
@@ -7962,6 +8004,9 @@ spec:
type: boolean
type: object
type: object
+ x-kubernetes-validations:
+ - message: httpSettings can only be set when serviceType is 'http'
+ rule: '!has(self.httpSettings) || self.serviceType == ''http'''
corsPolicy:
description: Specifies the cross-origin policy to apply to the
VirtualHost.
diff --git a/examples/render/contour.yaml b/examples/render/contour.yaml
index 15f3614f10c..60521a03de8 100644
--- a/examples/render/contour.yaml
+++ b/examples/render/contour.yaml
@@ -981,11 +981,17 @@ spec:
name.
type: string
type: object
+ x-kubernetes-validations:
+ - message: only one of prefix, suffix, exact, and contains
+ should be set in the allowedHeader
+ rule: '(has(self.exact) ? 1 : 0) + (has(self.prefix) ?
+ 1 : 0) + (has(self.suffix) ? 1 : 0) + (has(self.contains)
+ ? 1 : 0) == 1'
type: array
allowedUpstreamHeaders:
description: |-
- AllowedUpstreamHeaders specifies authorization response headers that will be added to the original client request.
- Coexistent headers will be overridden.
+ AllowedUpstreamHeaders specifies response headers from the authorization server
+ that may be added to the original client request before sending it to the upstream.
items:
description: |-
HTTPAuthorizationServerAllowedHeaders specifies how to conditionally match against allowed headers
@@ -1013,6 +1019,12 @@ spec:
name.
type: string
type: object
+ x-kubernetes-validations:
+ - message: only one of prefix, suffix, exact, and contains
+ should be set in the allowedHeader
+ rule: '(has(self.exact) ? 1 : 0) + (has(self.prefix) ?
+ 1 : 0) + (has(self.suffix) ? 1 : 0) + (has(self.contains)
+ ? 1 : 0) == 1'
type: array
pathPrefix:
description: PathPrefix Sets a prefix to the value of authorization
@@ -1027,10 +1039,10 @@ spec:
The string "infinity" is also a valid input and specifies no timeout.
pattern: ^(((\d*(\.\d*)?h)|(\d*(\.\d*)?m)|(\d*(\.\d*)?s)|(\d*(\.\d*)?ms)|(\d*(\.\d*)?us)|(\d*(\.\d*)?µs)|(\d*(\.\d*)?ns))+|infinity|infinite)$
type: string
- serviceAPIType:
+ serviceType:
default: grpc
description: |-
- ServiceAPIType sets the protocol used to communicate with
+ ServiceType sets the protocol used to communicate with
the external authorization server.
enum:
- http
@@ -1057,6 +1069,9 @@ spec:
type: boolean
type: object
type: object
+ x-kubernetes-validations:
+ - message: httpSettings can only be set when serviceType is 'http'
+ rule: '!has(self.httpSettings) || self.serviceType == ''http'''
health:
description: |-
Health defines the endpoints Contour uses to serve health checks.
@@ -5011,11 +5026,17 @@ spec:
header name.
type: string
type: object
+ x-kubernetes-validations:
+ - message: only one of prefix, suffix, exact, and contains
+ should be set in the allowedHeader
+ rule: '(has(self.exact) ? 1 : 0) + (has(self.prefix)
+ ? 1 : 0) + (has(self.suffix) ? 1 : 0) + (has(self.contains)
+ ? 1 : 0) == 1'
type: array
allowedUpstreamHeaders:
description: |-
- AllowedUpstreamHeaders specifies authorization response headers that will be added to the original client request.
- Coexistent headers will be overridden.
+ AllowedUpstreamHeaders specifies response headers from the authorization server
+ that may be added to the original client request before sending it to the upstream.
items:
description: |-
HTTPAuthorizationServerAllowedHeaders specifies how to conditionally match against allowed headers
@@ -5043,6 +5064,12 @@ spec:
header name.
type: string
type: object
+ x-kubernetes-validations:
+ - message: only one of prefix, suffix, exact, and contains
+ should be set in the allowedHeader
+ rule: '(has(self.exact) ? 1 : 0) + (has(self.prefix)
+ ? 1 : 0) + (has(self.suffix) ? 1 : 0) + (has(self.contains)
+ ? 1 : 0) == 1'
type: array
pathPrefix:
description: PathPrefix Sets a prefix to the value of
@@ -5057,10 +5084,10 @@ spec:
The string "infinity" is also a valid input and specifies no timeout.
pattern: ^(((\d*(\.\d*)?h)|(\d*(\.\d*)?m)|(\d*(\.\d*)?s)|(\d*(\.\d*)?ms)|(\d*(\.\d*)?us)|(\d*(\.\d*)?µs)|(\d*(\.\d*)?ns))+|infinity|infinite)$
type: string
- serviceAPIType:
+ serviceType:
default: grpc
description: |-
- ServiceAPIType sets the protocol used to communicate with
+ ServiceType sets the protocol used to communicate with
the external authorization server.
enum:
- http
@@ -5087,6 +5114,9 @@ spec:
type: boolean
type: object
type: object
+ x-kubernetes-validations:
+ - message: httpSettings can only be set when serviceType is 'http'
+ rule: '!has(self.httpSettings) || self.serviceType == ''http'''
health:
description: |-
Health defines the endpoints Contour uses to serve health checks.
@@ -8069,11 +8099,17 @@ spec:
header name.
type: string
type: object
+ x-kubernetes-validations:
+ - message: only one of prefix, suffix, exact, and contains
+ should be set in the allowedHeader
+ rule: '(has(self.exact) ? 1 : 0) + (has(self.prefix)
+ ? 1 : 0) + (has(self.suffix) ? 1 : 0) + (has(self.contains)
+ ? 1 : 0) == 1'
type: array
allowedUpstreamHeaders:
description: |-
- AllowedUpstreamHeaders specifies authorization response headers that will be added to the original client request.
- Coexistent headers will be overridden.
+ AllowedUpstreamHeaders specifies response headers from the authorization server
+ that may be added to the original client request before sending it to the upstream.
items:
description: |-
HTTPAuthorizationServerAllowedHeaders specifies how to conditionally match against allowed headers
@@ -8101,6 +8137,12 @@ spec:
header name.
type: string
type: object
+ x-kubernetes-validations:
+ - message: only one of prefix, suffix, exact, and contains
+ should be set in the allowedHeader
+ rule: '(has(self.exact) ? 1 : 0) + (has(self.prefix)
+ ? 1 : 0) + (has(self.suffix) ? 1 : 0) + (has(self.contains)
+ ? 1 : 0) == 1'
type: array
pathPrefix:
description: PathPrefix Sets a prefix to the value of
@@ -8115,10 +8157,10 @@ spec:
The string "infinity" is also a valid input and specifies no timeout.
pattern: ^(((\d*(\.\d*)?h)|(\d*(\.\d*)?m)|(\d*(\.\d*)?s)|(\d*(\.\d*)?ms)|(\d*(\.\d*)?us)|(\d*(\.\d*)?µs)|(\d*(\.\d*)?ns))+|infinity|infinite)$
type: string
- serviceAPIType:
+ serviceType:
default: grpc
description: |-
- ServiceAPIType sets the protocol used to communicate with
+ ServiceType sets the protocol used to communicate with
the external authorization server.
enum:
- http
@@ -8145,6 +8187,9 @@ spec:
type: boolean
type: object
type: object
+ x-kubernetes-validations:
+ - message: httpSettings can only be set when serviceType is 'http'
+ rule: '!has(self.httpSettings) || self.serviceType == ''http'''
corsPolicy:
description: Specifies the cross-origin policy to apply to the
VirtualHost.
diff --git a/internal/dag/dag.go b/internal/dag/dag.go
index 8d9134ffce5..5b1fed32f93 100644
--- a/internal/dag/dag.go
+++ b/internal/dag/dag.go
@@ -27,7 +27,6 @@ import (
core_v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/types"
- contour_v1 "github.com/projectcontour/contour/apis/projectcontour/v1"
"github.com/projectcontour/contour/internal/status"
"github.com/projectcontour/contour/internal/timeout"
)
@@ -163,6 +162,35 @@ func (hc *HeaderMatchCondition) String() string {
return "header: " + details
}
+// AuthorizationServiceType defines whether the external authorization server
+// uses HTTP or gRPC protocol.
+type AuthorizationServiceType int
+
+const (
+ // AuthorizationServiceGRPC indicates the server implements the gRPC ext_authz protocol.
+ AuthorizationServiceGRPC AuthorizationServiceType = iota
+ // AuthorizationServiceHTTP indicates the server implements the raw HTTP ext_authz protocol.
+ AuthorizationServiceHTTP
+)
+
+const (
+ // HeaderNameMatchTypeExact matches a header name exactly.
+ HeaderNameMatchTypeExact = "exact"
+ // HeaderNameMatchTypePrefix matches a header name by prefix.
+ HeaderNameMatchTypePrefix = "prefix"
+ // HeaderNameMatchTypeSuffix matches a header name by suffix.
+ HeaderNameMatchTypeSuffix = "suffix"
+ // HeaderNameMatchTypeContains matches a header name if it contains the provided value.
+ HeaderNameMatchTypeContains = "contains"
+)
+
+// HeaderNameMatchCondition matches an HTTP header name by MatchType.
+type HeaderNameMatchCondition struct {
+ MatchType string
+ Value string
+ IgnoreCase bool
+}
+
const (
// QueryParamMatchTypeExact matches a querystring parameter value exactly.
QueryParamMatchTypeExact = "exact"
@@ -865,15 +893,14 @@ type ExternalAuthorization struct {
// ServiceAPIType defines the external authorization service API type.
// It indicates the protocol implemented by the external server, specifying whether it's a raw HTTP authorization server
// or a gRPC authorization server.
- ServiceAPIType contour_v1.AuthorizationServiceAPIType
+ ServiceAPIType AuthorizationServiceType
- // HTTPAllowedAuthorizationHeaders specifies client request headers that will be sent to the authorization server.
- // Note that in addition to the the user’s supplied matchers, Host, Method, Path, Content-Length, and Authorization are additionally included in the list.
- HTTPAllowedAuthorizationHeaders []contour_v1.HTTPAuthorizationServerAllowedHeaders
+ // Note that in addition to the user’s supplied matchers, Host, Method, Path, Content-Length, and Authorization are additionally included in the list.
+ HTTPAllowedAuthorizationHeaders []HeaderNameMatchCondition
// HTTPAllowedUpstreamHeaders specifies authorization response headers that will be added to the original client request.
// Note that coexistent headers will be overridden.
- HTTPAllowedUpstreamHeaders []contour_v1.HTTPAuthorizationServerAllowedHeaders
+ HTTPAllowedUpstreamHeaders []HeaderNameMatchCondition
// HTTPPathPrefix Sets a prefix to the value of authorization request header Path.
HTTPPathPrefix string
diff --git a/internal/dag/httpproxy_processor.go b/internal/dag/httpproxy_processor.go
index 9044ad568c0..2d9c95f0248 100644
--- a/internal/dag/httpproxy_processor.go
+++ b/internal/dag/httpproxy_processor.go
@@ -1392,63 +1392,18 @@ func (p *HTTPProxyProcessor) computeVirtualHostAuthorization(auth *contour_v1.Au
return nil
}
- ok, respTimeout := determineExternalAuthTimeout(auth.ResponseTimeout, validCond, ext)
- if !ok {
+ extAuth := NewExternalAuthorization(auth, validCond)
+ if extAuth == nil {
return nil
}
- globalExternalAuthorization := &ExternalAuthorization{
- AuthorizationService: ext,
- AuthorizationFailOpen: auth.FailOpen,
- AuthorizationResponseTimeout: *respTimeout,
- }
-
- switch auth.ServiceAPIType {
- case contour_v1.AuthorizationGRPCService:
- globalExternalAuthorization.ServiceAPIType = contour_v1.AuthorizationGRPCService
- case contour_v1.AuthorizationHTTPService:
- globalExternalAuthorization.ServiceAPIType = contour_v1.AuthorizationHTTPService
- if auth.HTTPServerSettings != nil {
- globalExternalAuthorization.HTTPPathPrefix = auth.HTTPServerSettings.PathPrefix
-
- // globalExternalAuthorization.HttpServerURI = auth.HttpServerSettings.ServerURI
-
- if len(auth.HTTPServerSettings.AllowedAuthorizationHeaders) > 0 {
- if err := ExternalAuthAllowedHeadersValid(auth.HTTPServerSettings.AllowedAuthorizationHeaders); err != nil {
- validCond.AddErrorf(contour_v1.ConditionTypeAuthError, "AuthBadAllowedHeader",
- "Spec.Virtualhost.Authorization.HTTPServerSettings.AllowedAuthorizationHeaders is invalid: %s", err)
-
- return nil
- }
-
- globalExternalAuthorization.HTTPAllowedAuthorizationHeaders = auth.HTTPServerSettings.AllowedAuthorizationHeaders
- }
-
- if len(auth.HTTPServerSettings.AllowedUpstreamHeaders) > 0 {
- if err := ExternalAuthAllowedHeadersValid(auth.HTTPServerSettings.AllowedUpstreamHeaders); err != nil {
- validCond.AddErrorf(contour_v1.ConditionTypeAuthError, "AuthBadAllowedHeader",
- "Spec.Virtualhost.Authorization.HTTPServerSettings.AllowedUpstreamHeaders is invalid: %s", err)
-
- return nil
- }
-
- globalExternalAuthorization.HTTPAllowedUpstreamHeaders = auth.HTTPServerSettings.AllowedUpstreamHeaders
- }
- }
+ // If no explicit timeout was configured, fall back to the extension service's own timeout.
+ if extAuth.AuthorizationResponseTimeout.UseDefault() {
+ extAuth.AuthorizationResponseTimeout = ext.RouteTimeoutPolicy.ResponseTimeout
}
- if auth.WithRequestBody != nil {
- maxRequestBytes := defaultMaxRequestBytes
- if auth.WithRequestBody.MaxRequestBytes != 0 {
- maxRequestBytes = auth.WithRequestBody.MaxRequestBytes
- }
- globalExternalAuthorization.AuthorizationServerWithRequestBody = &AuthorizationServerBufferSettings{
- MaxRequestBytes: maxRequestBytes,
- AllowPartialMessage: auth.WithRequestBody.AllowPartialMessage,
- PackAsBytes: auth.WithRequestBody.PackAsBytes,
- }
- }
- return globalExternalAuthorization
+ extAuth.AuthorizationService = ext
+ return extAuth
}
func validateExternalAuthExtensionService(ref contour_v1.ExtensionServiceReference, validCond *contour_v1.DetailedCondition, httpproxy *contour_v1.HTTPProxy, getExtensionCluster func(name string) *ExtensionCluster) (bool, *ExtensionCluster) {
diff --git a/internal/envoy/v3/listener.go b/internal/envoy/v3/listener.go
index 511edad2f3f..ca3e83b0d83 100644
--- a/internal/envoy/v3/listener.go
+++ b/internal/envoy/v3/listener.go
@@ -48,7 +48,6 @@ import (
"google.golang.org/protobuf/types/known/durationpb"
"google.golang.org/protobuf/types/known/wrapperspb"
- contour_v1 "github.com/projectcontour/contour/apis/projectcontour/v1"
contour_v1alpha1 "github.com/projectcontour/contour/apis/projectcontour/v1alpha1"
"github.com/projectcontour/contour/internal/dag"
"github.com/projectcontour/contour/internal/envoy"
@@ -839,37 +838,37 @@ end
}
}
-// ExternalAuthzAllowedHeaders returns the slice of StringMatcher for a given slice of HTTPAuthorizationServerAllowedHeaders.
-func ExternalAuthzAllowedHeaders(allowedHeaders []contour_v1.HTTPAuthorizationServerAllowedHeaders) []*envoy_matcher_v3.StringMatcher {
+// ExternalAuthzAllowedHeaders returns the slice of StringMatcher for a given slice of HeaderNameMatchCondition.
+func ExternalAuthzAllowedHeaders(allowedHeaders []dag.HeaderNameMatchCondition) []*envoy_matcher_v3.StringMatcher {
var allowedHeaderPatterns []*envoy_matcher_v3.StringMatcher
for _, allowedHeader := range allowedHeaders {
- switch {
- case allowedHeader.Exact != "":
+ switch allowedHeader.MatchType {
+ case dag.HeaderNameMatchTypeExact:
allowedHeaderPatterns = append(allowedHeaderPatterns, &envoy_matcher_v3.StringMatcher{
MatchPattern: &envoy_matcher_v3.StringMatcher_Exact{
- Exact: allowedHeader.Exact,
+ Exact: allowedHeader.Value,
},
IgnoreCase: allowedHeader.IgnoreCase,
})
- case allowedHeader.Prefix != "":
+ case dag.HeaderNameMatchTypePrefix:
allowedHeaderPatterns = append(allowedHeaderPatterns, &envoy_matcher_v3.StringMatcher{
MatchPattern: &envoy_matcher_v3.StringMatcher_Prefix{
- Prefix: allowedHeader.Prefix,
+ Prefix: allowedHeader.Value,
},
IgnoreCase: allowedHeader.IgnoreCase,
})
- case allowedHeader.Suffix != "":
+ case dag.HeaderNameMatchTypeSuffix:
allowedHeaderPatterns = append(allowedHeaderPatterns, &envoy_matcher_v3.StringMatcher{
MatchPattern: &envoy_matcher_v3.StringMatcher_Suffix{
- Suffix: allowedHeader.Suffix,
+ Suffix: allowedHeader.Value,
},
IgnoreCase: allowedHeader.IgnoreCase,
})
- case allowedHeader.Contains != "":
+ case dag.HeaderNameMatchTypeContains:
allowedHeaderPatterns = append(allowedHeaderPatterns, &envoy_matcher_v3.StringMatcher{
MatchPattern: &envoy_matcher_v3.StringMatcher_Contains{
- Contains: allowedHeader.Contains,
+ Contains: allowedHeader.Value,
},
IgnoreCase: allowedHeader.IgnoreCase,
})
@@ -883,9 +882,6 @@ func ExternalAuthzAllowedHeaders(allowedHeaders []contour_v1.HTTPAuthorizationSe
// requested parameters.
func FilterExternalAuthz(externalAuthorization *dag.ExternalAuthorization) *envoy_filter_network_http_connection_manager_v3.HttpFilter {
authConfig := envoy_filter_http_ext_authz_v3.ExtAuthz{
- Services: &envoy_filter_http_ext_authz_v3.ExtAuthz_GrpcService{
- GrpcService: grpcService(externalAuthorization.AuthorizationService.Name, externalAuthorization.AuthorizationService.SNI, externalAuthorization.AuthorizationResponseTimeout),
- },
// Pretty sure we always want this. Why have an
// external auth service if it is not going to affect
// routing decisions?
@@ -901,22 +897,23 @@ func FilterExternalAuthz(externalAuthorization *dag.ExternalAuthorization) *envo
}
switch externalAuthorization.ServiceAPIType {
- case contour_v1.AuthorizationGRPCService:
+ case dag.AuthorizationServiceGRPC:
authConfig.Services = &envoy_filter_http_ext_authz_v3.ExtAuthz_GrpcService{
GrpcService: grpcService(externalAuthorization.AuthorizationService.Name, externalAuthorization.AuthorizationService.SNI, externalAuthorization.AuthorizationResponseTimeout),
}
authConfig.MetadataContextNamespaces = []string{}
- case contour_v1.AuthorizationHTTPService:
+ case dag.AuthorizationServiceHTTP:
extAuthzService := &envoy_filter_http_ext_authz_v3.ExtAuthz_HttpService{
HttpService: &envoy_filter_http_ext_authz_v3.HttpService{
ServerUri: &envoy_config_core_v3.HttpUri{
- // Uri: externalAuthorization.HttpServerURI,
+ // Uri is required by the Envoy API but routing is determined by the Cluster field,
+ // so we use a dummy value here.
Uri: "http://dummy/",
HttpUpstreamType: &envoy_config_core_v3.HttpUri_Cluster{
Cluster: externalAuthorization.AuthorizationService.Name,
},
- Timeout: envoy.Timeout(externalAuthorization.AuthorizationResponseTimeout),
+ Timeout: httpURITimeout(externalAuthorization.AuthorizationResponseTimeout),
},
},
}
@@ -1058,6 +1055,15 @@ func FilterChainTLSFallback(downstream *envoy_transport_socket_tls_v3.Downstream
return fc
}
+// httpURITimeout returns a duration for the HttpUri.Timeout field.
+// It returns 0 (infinite) if the timeout is not set.
+func httpURITimeout(d timeout.Setting) *durationpb.Duration {
+ if t := envoy.Timeout(d); t != nil {
+ return t
+ }
+ return durationpb.New(0)
+}
+
// grpcService returns a envoy_config_core_v3.GrpcService for the given parameters.
func grpcService(clusterName, sni string, timeout timeout.Setting) *envoy_config_core_v3.GrpcService {
authority := strings.ReplaceAll(clusterName, "/", ".")
diff --git a/internal/featuretests/v3/authorization_test.go b/internal/featuretests/v3/authorization_test.go
index 981da972ad1..4c98a3b121c 100644
--- a/internal/featuretests/v3/authorization_test.go
+++ b/internal/featuretests/v3/authorization_test.go
@@ -77,7 +77,7 @@ func authzResponseTimeout(t *testing.T, rh ResourceEventHandlerWrapper, c *Conto
Namespace: "auth",
Name: "extension",
},
- ServiceAPIType: contour_v1.AuthorizationGRPCService,
+ ServiceType: contour_v1.AuthorizationGRPCService,
ResponseTimeout: "10m",
}).
WithSpec(contour_v1.HTTPProxySpec{
@@ -136,7 +136,7 @@ func authzInvalidResponseTimeout(t *testing.T, rh ResourceEventHandlerWrapper, c
Namespace: "auth",
Name: "extension",
},
- ServiceAPIType: contour_v1.AuthorizationGRPCService,
+ ServiceType: contour_v1.AuthorizationGRPCService,
ResponseTimeout: "invalid-timeout",
}).
WithSpec(contour_v1.HTTPProxySpec{
@@ -164,8 +164,8 @@ func authzFailOpen(t *testing.T, rh ResourceEventHandlerWrapper, c *Contour) {
Namespace: "auth",
Name: "extension",
},
- ServiceAPIType: contour_v1.AuthorizationGRPCService,
- FailOpen: true,
+ ServiceType: contour_v1.AuthorizationGRPCService,
+ FailOpen: true,
}).
WithSpec(contour_v1.HTTPProxySpec{
Routes: []contour_v1.Route{{
@@ -217,7 +217,7 @@ func authzFallbackIncompat(t *testing.T, rh ResourceEventHandlerWrapper, c *Cont
Namespace: "auth",
Name: "extension",
},
- ServiceAPIType: contour_v1.AuthorizationGRPCService,
+ ServiceType: contour_v1.AuthorizationGRPCService,
}).
WithSpec(contour_v1.HTTPProxySpec{
Routes: []contour_v1.Route{{
@@ -249,7 +249,7 @@ func authzOverrideDisabled(t *testing.T, rh ResourceEventHandlerWrapper, c *Cont
WithCertificate("certificate").
WithAuthServer(contour_v1.AuthorizationServer{
ExtensionServiceRef: extensionRef,
- ServiceAPIType: contour_v1.AuthorizationGRPCService,
+ ServiceType: contour_v1.AuthorizationGRPCService,
AuthPolicy: &contour_v1.AuthorizationPolicy{Disabled: false},
}).
WithSpec(contour_v1.HTTPProxySpec{
@@ -360,7 +360,7 @@ func authzMergeRouteContext(t *testing.T, rh ResourceEventHandlerWrapper, c *Con
Namespace: "auth",
Name: "extension",
},
- ServiceAPIType: contour_v1.AuthorizationGRPCService,
+ ServiceType: contour_v1.AuthorizationGRPCService,
AuthPolicy: &contour_v1.AuthorizationPolicy{
Context: map[string]string{
"root-element": "root",
@@ -441,7 +441,7 @@ func authzInvalidReference(t *testing.T, rh ResourceEventHandlerWrapper, c *Cont
WithFQDN(fqdn).
WithCertificate("certificate").
WithAuthServer(contour_v1.AuthorizationServer{
- ServiceAPIType: contour_v1.AuthorizationGRPCService,
+ ServiceType: contour_v1.AuthorizationGRPCService,
}).
WithSpec(contour_v1.HTTPProxySpec{
Routes: []contour_v1.Route{{
@@ -532,8 +532,8 @@ func authzWithRequestBodyBufferSettings(t *testing.T, rh ResourceEventHandlerWra
Namespace: "auth",
Name: "extension",
},
- ServiceAPIType: contour_v1.AuthorizationGRPCService,
- FailOpen: true,
+ ServiceType: contour_v1.AuthorizationGRPCService,
+ FailOpen: true,
WithRequestBody: &contour_v1.AuthorizationServerBufferSettings{
MaxRequestBytes: 100,
AllowPartialMessage: true,
@@ -597,7 +597,7 @@ func AuthzTypeGRPC(t *testing.T, rh ResourceEventHandlerWrapper, c *Contour) {
Namespace: "auth",
Name: "extension",
},
- ServiceAPIType: contour_v1.AuthorizationGRPCService,
+ ServiceType: contour_v1.AuthorizationGRPCService,
}).
WithSpec(contour_v1.HTTPProxySpec{
Routes: []contour_v1.Route{{
@@ -656,7 +656,7 @@ func authzTypeHTTP(t *testing.T, rh ResourceEventHandlerWrapper, c *Contour) {
Namespace: "auth",
Name: "extension",
},
- ServiceAPIType: contour_v1.AuthorizationHTTPService,
+ ServiceType: contour_v1.AuthorizationHTTPService,
}).
WithSpec(contour_v1.HTTPProxySpec{
Routes: []contour_v1.Route{{
@@ -704,7 +704,7 @@ func authzTypeHTTP(t *testing.T, rh ResourceEventHandlerWrapper, c *Contour) {
}).Status(p).IsValid()
}
-func AuthzTypeHTTPWithPathPrefix(t *testing.T, rh ResourceEventHandlerWrapper, c *Contour) {
+func authzTypeHTTPWithPathPrefix(t *testing.T, rh ResourceEventHandlerWrapper, c *Contour) {
const fqdn = "typehttp.projectcontour.io"
p := fixture.NewProxy("proxy").
@@ -715,7 +715,7 @@ func AuthzTypeHTTPWithPathPrefix(t *testing.T, rh ResourceEventHandlerWrapper, c
Namespace: "auth",
Name: "extension",
},
- ServiceAPIType: contour_v1.AuthorizationHTTPService,
+ ServiceType: contour_v1.AuthorizationHTTPService,
HTTPServerSettings: &contour_v1.HTTPAuthorizationServerSettings{
PathPrefix: "/auth?",
},
@@ -769,7 +769,7 @@ func AuthzTypeHTTPWithPathPrefix(t *testing.T, rh ResourceEventHandlerWrapper, c
}).Status(p).IsValid()
}
-func AuthzTypeHTTPWithAllowedAuthorizationHeaders(t *testing.T, rh ResourceEventHandlerWrapper, c *Contour) {
+func authzTypeHTTPWithAllowedAuthorizationHeaders(t *testing.T, rh ResourceEventHandlerWrapper, c *Contour) {
const fqdn = "typehttp.projectcontour.io"
p := fixture.NewProxy("proxy").
@@ -780,7 +780,7 @@ func AuthzTypeHTTPWithAllowedAuthorizationHeaders(t *testing.T, rh ResourceEvent
Namespace: "auth",
Name: "extension",
},
- ServiceAPIType: contour_v1.AuthorizationHTTPService,
+ ServiceType: contour_v1.AuthorizationHTTPService,
}).
WithSpec(contour_v1.HTTPProxySpec{
Routes: []contour_v1.Route{{
@@ -869,7 +869,7 @@ func AuthzTypeHTTPWithAllowedAuthorizationHeaders(t *testing.T, rh ResourceEvent
}).Status(p).IsValid()
}
-func AuthzTypeHTTPWithAllowedUpstreamHeaders(t *testing.T, rh ResourceEventHandlerWrapper, c *Contour) {
+func authzTypeHTTPWithAllowedUpstreamHeaders(t *testing.T, rh ResourceEventHandlerWrapper, c *Contour) {
const fqdn = "typehttp.projectcontour.io"
p := fixture.NewProxy("proxy").
@@ -880,7 +880,7 @@ func AuthzTypeHTTPWithAllowedUpstreamHeaders(t *testing.T, rh ResourceEventHandl
Namespace: "auth",
Name: "extension",
},
- ServiceAPIType: contour_v1.AuthorizationHTTPService,
+ ServiceType: contour_v1.AuthorizationHTTPService,
}).
WithSpec(contour_v1.HTTPProxySpec{
Routes: []contour_v1.Route{{
@@ -973,7 +973,7 @@ func AuthzTypeHTTPWithAllowedUpstreamHeaders(t *testing.T, rh ResourceEventHandl
}).Status(p).IsValid()
}
-func AuthzTypeHTTPWithContext(t *testing.T, rh ResourceEventHandlerWrapper, c *Contour) {
+func authzTypeHTTPWithContext(t *testing.T, rh ResourceEventHandlerWrapper, c *Contour) {
const fqdn = "typehttp.projectcontour.io"
p := fixture.NewProxy("proxy").
@@ -984,7 +984,7 @@ func AuthzTypeHTTPWithContext(t *testing.T, rh ResourceEventHandlerWrapper, c *C
Namespace: "auth",
Name: "extension",
},
- ServiceAPIType: contour_v1.AuthorizationHTTPService,
+ ServiceType: contour_v1.AuthorizationHTTPService,
AuthPolicy: &contour_v1.AuthorizationPolicy{
Context: map[string]string{
"k1": "v1",
@@ -1010,6 +1010,68 @@ func AuthzTypeHTTPWithContext(t *testing.T, rh ResourceEventHandlerWrapper, c *C
}).Status(p).HasError(contour_v1.ConditionTypeAuthError, "AuthContextForHTTP", `Spec.Virtualhost.Authorization.AuthPolicy.Context are only applied to grpc service type`)
}
+// authzTypeUnset tests backwards compatibility: an HTTPProxy with no
+// serviceAPIType set (field absent in older stored objects, Go zero-value "")
+// must be treated as gRPC.
+func authzTypeUnset(t *testing.T, rh ResourceEventHandlerWrapper, c *Contour) {
+ const fqdn = "typegrpc.projectcontour.io"
+
+ p := fixture.NewProxy("proxy").
+ WithFQDN(fqdn).
+ WithCertificate("certificate").
+ WithAuthServer(contour_v1.AuthorizationServer{
+ ExtensionServiceRef: contour_v1.ExtensionServiceReference{
+ Namespace: "auth",
+ Name: "extension",
+ },
+ // ServiceAPIType intentionally absent to simulate upgrade from older version where this field didn't exist.
+ }).
+ WithSpec(contour_v1.HTTPProxySpec{
+ Routes: []contour_v1.Route{{
+ Services: []contour_v1.Service{{
+ Name: "app-server",
+ Port: 80,
+ }},
+ }},
+ })
+
+ rh.OnDelete(p)
+ rh.OnAdd(p)
+
+ c.Request(listenerType).Equals(&envoy_service_discovery_v3.DiscoveryResponse{
+ TypeUrl: listenerType,
+ Resources: resources(t,
+ defaultHTTPListener(),
+ &envoy_config_listener_v3.Listener{
+ Name: "ingress_https",
+ Address: envoy_v3.SocketAddress("0.0.0.0", 8443),
+ ListenerFilters: envoy_v3.ListenerFilters(
+ envoy_v3.TLSInspector(),
+ ),
+ FilterChains: []*envoy_config_listener_v3.FilterChain{
+ filterchaintls(fqdn,
+ featuretests.TLSSecret(t, "certificate", &featuretests.ServerCertificate),
+ authzFilterFor(
+ fqdn,
+ &envoy_filter_http_ext_authz_v3.ExtAuthz{
+ Services: grpcCluster("extension/auth/extension"),
+ ClearRouteCache: true,
+ FailureModeAllow: false,
+ IncludePeerCertificate: true,
+ StatusOnError: &envoy_type_v3.HttpStatus{
+ Code: envoy_type_v3.StatusCode_Forbidden,
+ },
+ TransportApiVersion: envoy_config_core_v3.ApiVersion_V3,
+ },
+ ),
+ nil, "h2", "http/1.1"),
+ },
+ SocketOptions: envoy_v3.NewSocketOptions().TCPKeepalive().Build(),
+ },
+ statsListener()),
+ }).Status(p).IsValid()
+}
+
func TestAuthorization(t *testing.T) {
subtests := map[string]func(*testing.T, ResourceEventHandlerWrapper, *Contour){
"MissingExtension": authzInvalidReference,
@@ -1022,9 +1084,11 @@ func TestAuthorization(t *testing.T) {
"AuthzWithRequestBodyBufferSettings": authzWithRequestBodyBufferSettings,
"AuthzTypeGRPC": AuthzTypeGRPC,
"AuthzTypeHTTP": authzTypeHTTP,
- "AuthzTypeHTTPWithPathPrefix": AuthzTypeHTTPWithPathPrefix,
- "AuthzTypeHTTPWithAllowedAuthorizationHeaders": AuthzTypeHTTPWithAllowedAuthorizationHeaders,
- "AuthzTypeHTTPWithAllowedUpstreamHeaders": AuthzTypeHTTPWithAllowedUpstreamHeaders,
+ "AuthzTypeHTTPWithPathPrefix": authzTypeHTTPWithPathPrefix,
+ "AuthzTypeHTTPWithAllowedAuthorizationHeaders": authzTypeHTTPWithAllowedAuthorizationHeaders,
+ "AuthzTypeHTTPWithAllowedUpstreamHeaders": authzTypeHTTPWithAllowedUpstreamHeaders,
+ "AuthzTypeHTTPWithContext": authzTypeHTTPWithContext,
+ "AuthzTypeUnset": authzTypeUnset,
}
for n, f := range subtests {
diff --git a/internal/featuretests/v3/global_authorization_test.go b/internal/featuretests/v3/global_authorization_test.go
index 4c134a6073d..1b1f6a16789 100644
--- a/internal/featuretests/v3/global_authorization_test.go
+++ b/internal/featuretests/v3/global_authorization_test.go
@@ -47,7 +47,7 @@ var (
Name: "extension",
Namespace: "auth",
},
- ServiceAPIType: contour_v1.AuthorizationGRPCService,
+ ServiceType: contour_v1.AuthorizationGRPCService,
FailOpen: false,
ResponseTimeout: defaultResponseTimeout.String(),
AuthPolicy: &contour_v1.AuthorizationPolicy{
@@ -63,7 +63,7 @@ var (
Name: "extension",
Namespace: "auth",
},
- ServiceAPIType: contour_v1.AuthorizationGRPCService,
+ ServiceType: contour_v1.AuthorizationGRPCService,
FailOpen: false,
ResponseTimeout: defaultResponseTimeout.String(),
AuthPolicy: &contour_v1.AuthorizationPolicy{
@@ -582,7 +582,7 @@ func globalExternalAuthorizationWithTLSAuthOverride(t *testing.T, rh ResourceEve
Namespace: "auth",
Name: "extension",
},
- ServiceAPIType: contour_v1.AuthorizationGRPCService,
+ ServiceType: contour_v1.AuthorizationGRPCService,
ResponseTimeout: defaultResponseTimeout.String(),
FailOpen: true,
WithRequestBody: &contour_v1.AuthorizationServerBufferSettings{
@@ -803,13 +803,13 @@ func TestGlobalAuthorization(t *testing.T) {
ExtensionService: k8s.NamespacedNameFrom("auth/extension"),
Timeout: timeout.DurationSetting(defaultResponseTimeout),
},
- ServiceAPIType: contour_v1.AuthorizationGRPCService,
- FailOpen: false,
Context: map[string]string{
"header_type": "root_config",
"header_1": "message_1",
},
}
+ cfg.GlobalExternalAuthConfig.ServiceAPIType = dag.AuthorizationServiceGRPC
+ cfg.GlobalExternalAuthConfig.AuthorizationFailOpen = false
},
func(b *dag.Builder) {
for _, processor := range b.Processors {
diff --git a/internal/xdscache/v3/listener.go b/internal/xdscache/v3/listener.go
index a9d68c347c5..b1cf42294c3 100644
--- a/internal/xdscache/v3/listener.go
+++ b/internal/xdscache/v3/listener.go
@@ -25,7 +25,6 @@ import (
"google.golang.org/protobuf/proto"
"k8s.io/apimachinery/pkg/types"
- contour_v1 "github.com/projectcontour/contour/apis/projectcontour/v1"
contour_v1alpha1 "github.com/projectcontour/contour/apis/projectcontour/v1alpha1"
"github.com/projectcontour/contour/internal/contourconfig"
"github.com/projectcontour/contour/internal/dag"
@@ -203,14 +202,8 @@ type RateLimitConfig struct {
type GlobalExternalAuthConfig struct {
ExtensionServiceConfig
- FailOpen bool
- Context map[string]string
- ServiceAPIType contour_v1.AuthorizationServiceAPIType
- HTTPAllowedAuthorizationHeaders []contour_v1.HTTPAuthorizationServerAllowedHeaders
- HTTPAllowedUpstreamHeaders []contour_v1.HTTPAuthorizationServerAllowedHeaders
- HTTPPathPrefix string
- WithRequestBody *dag.AuthorizationServerBufferSettings
- // HttpServerURI string
+ dag.ExternalAuthorization
+ Context map[string]string
}
// httpAccessLog returns the access log for the HTTP (non TLS)
@@ -614,9 +607,9 @@ func httpGlobalExternalAuthConfig(config *GlobalExternalAuthConfig) *envoy_filte
HTTPAllowedAuthorizationHeaders: config.HTTPAllowedAuthorizationHeaders,
HTTPAllowedUpstreamHeaders: config.HTTPAllowedUpstreamHeaders,
HTTPPathPrefix: config.HTTPPathPrefix,
- AuthorizationFailOpen: config.FailOpen,
+ AuthorizationFailOpen: config.AuthorizationFailOpen,
AuthorizationResponseTimeout: config.Timeout,
- AuthorizationServerWithRequestBody: config.WithRequestBody,
+ AuthorizationServerWithRequestBody: config.AuthorizationServerWithRequestBody,
})
}
diff --git a/pkg/config/parameters.go b/pkg/config/parameters.go
index 4af63ad86dc..645b33cf053 100644
--- a/pkg/config/parameters.go
+++ b/pkg/config/parameters.go
@@ -761,16 +761,16 @@ type GlobalExternalAuthorization struct {
// ExtensionService identifies the extension service defining the RLS,
// formatted as /.
ExtensionService string `yaml:"extensionService,omitempty"`
- // ServiceAPIType defines the external authorization service API type.
+ // ServiceType defines the external authorization service API type.
// It indicates the protocol implemented by the external server, specifying whether it's a raw HTTP authorization server
// or a gRPC authorization server.
//
// +optional
- ServiceAPIType contour_v1.AuthorizationServiceAPIType `json:"serviceAPIType,omitempty"`
+ ServiceType contour_v1.AuthorizationServiceType `yaml:"serviceType,omitempty"`
// HttpAuthorizationServerSettings defines configurations for interacting with an external HTTP authorization server.
//
// +optional
- HTTPServerSettings *contour_v1.HTTPAuthorizationServerSettings `json:"httpSettings,omitempty"`
+ HTTPServerSettings *contour_v1.HTTPAuthorizationServerSettings `yaml:"httpSettings,omitempty"`
// AuthPolicy sets a default authorization policy for client requests.
// This policy will be used unless overridden by individual routes.
//
diff --git a/site/content/docs/main/config/api-reference.html b/site/content/docs/main/config/api-reference.html
index 2c024e8cf55..7cc7b7a6c97 100644
--- a/site/content/docs/main/config/api-reference.html
+++ b/site/content/docs/main/config/api-reference.html
@@ -334,7 +334,8 @@ AuthorizationServer
AuthorizationServer configures an external server to authenticate
client requests. The external server must implement the v3 Envoy
-external authorization GRPC protocol (https://www.envoyproxy.io/docs/envoy/latest/api-v3/service/auth/v3/external_auth.proto).
+external authorization GRPC protocol (https://www.envoyproxy.io/docs/envoy/latest/api-v3/service/auth/v3/external_auth.proto)
+or the HTTP authorization server protocol.
@@ -361,17 +362,17 @@ AuthorizationServer
-serviceAPIType
+serviceType
-
-AuthorizationServiceAPIType
+
+AuthorizationServiceType
|
(Optional)
- ServiceAPIType sets the protocol used to communicate with
+ ServiceType sets the protocol used to communicate with
the external authorization server.
|
@@ -513,14 +514,14 @@ AuthorizationSer
-AuthorizationServiceAPIType
+AuthorizationServiceType
(string alias)
(Appears on:
AuthorizationServer)
- AuthorizationServiceAPIType indicates the protocol
+ AuthorizationServiceType indicates the protocol
implemented by the external authorization server.
@@ -1479,8 +1480,8 @@ HTTPAuthorizationS
|
(Optional)
- AllowedUpstreamHeaders specifies authorization response headers that will be added to the original client request.
-Coexistent headers will be overridden.
+AllowedUpstreamHeaders specifies response headers from the authorization server
+that may be added to the original client request before sending it to the upstream.
|
|