diff --git a/Makefile b/Makefile index 6ba45be3ad0..81255feef62 100644 --- a/Makefile +++ b/Makefile @@ -156,7 +156,6 @@ container: ## Build the Contour container image --build-arg "BUILD_GOEXPERIMENT=$(BUILD_GOEXPERIMENT)" \ $(DOCKER_BUILD_LABELS) \ $(shell pwd) \ - --platform linux/amd64 \ --tag $(IMAGE):$(VERSION) push: ## Push the Contour container image to the Docker registry diff --git a/apis/projectcontour/v1/httpproxy.go b/apis/projectcontour/v1/httpproxy.go index 464728463ca..4bbf9144010 100644 --- a/apis/projectcontour/v1/httpproxy.go +++ b/apis/projectcontour/v1/httpproxy.go @@ -254,10 +254,10 @@ type AuthorizationServer struct { // +kubebuilder:default=grpc ServiceAPIType AuthorizationServiceAPIType `json:"serviceAPIType,omitempty"` - // HttpAuthorizationServerSettings defines configurations for interacting with an external HTTP authorization server. + // HTTPServerSettings defines configurations for interacting with an external HTTP authorization server. // // +optional - HttpServerSettings *HttpAuthorizationServerSettings `json:"httpSettings,omitempty"` + HTTPServerSettings *HTTPAuthorizationServerSettings `json:"httpSettings,omitempty"` // AuthPolicy sets a default authorization policy for client requests. // This policy will be used unless overridden by individual routes. @@ -287,8 +287,8 @@ type AuthorizationServer struct { WithRequestBody *AuthorizationServerBufferSettings `json:"withRequestBody,omitempty"` } -// HttpAuthorizationServerSettings defines configurations for interacting with an external HTTP authorization server. -type HttpAuthorizationServerSettings struct { +// 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 @@ -307,21 +307,21 @@ type HttpAuthorizationServerSettings struct { // Note that in addition to the the user’s supplied matchers, Host, Method, Path, Content-Length, and Authorization are additionally included in the list. // // +optional - AllowedAuthorizationHeaders []HttpAuthorizationServerAllowedHeaders `json:"allowedAuthorizationHeaders,omitempty"` + AllowedAuthorizationHeaders []HTTPAuthorizationServerAllowedHeaders `json:"allowedAuthorizationHeaders,omitempty"` // AllowedUpstreamHeaders specifies authorization response headers that will be added to the original client request. // Note that coexistent headers will be overridden. // // +optional - AllowedUpstreamHeaders []HttpAuthorizationServerAllowedHeaders `json:"allowedUpstreamHeaders,omitempty"` + AllowedUpstreamHeaders []HTTPAuthorizationServerAllowedHeaders `json:"allowedUpstreamHeaders,omitempty"` } -// HttpAuthorizationServerAllowedHeaders specifies how to conditionally match against allowed headers +// HTTPAuthorizationServerAllowedHeaders specifies how to conditionally match against allowed headers // in the context of HTTP authorization. It includes options such as Exact, Prefix, Suffix, // Contains, and IgnoreCase to customize header matching criteria. However, regex support // is intentionally excluded to simplify the user experience and prevent potential issues. // One of Prefix, Exact, Suffix or Contains must be provided. -type HttpAuthorizationServerAllowedHeaders struct { +type HTTPAuthorizationServerAllowedHeaders struct { // Exact specifies a string that the header name must be equal to. // // +optional diff --git a/apis/projectcontour/v1/zz_generated.deepcopy.go b/apis/projectcontour/v1/zz_generated.deepcopy.go index bbfd123d334..776c46e0264 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) @@ -320,6 +325,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 f2b041e83e1..b34ccab8e25 100644 --- a/apis/projectcontour/v1alpha1/extensionservice.go +++ b/apis/projectcontour/v1alpha1/extensionservice.go @@ -61,7 +61,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. @@ -77,15 +77,15 @@ type ExtensionServiceSpec struct { UpstreamValidation *contour_api_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=h1;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_api_v1.LoadBalancerPolicy `json:"loadBalancerPolicy,omitempty"` diff --git a/cmd/contour/serve.go b/cmd/contour/serve.go index 97b07b9654d..fe8f6bacf48 100644 --- a/cmd/contour/serve.go +++ b/cmd/contour/serve.go @@ -861,10 +861,6 @@ func (s *Server) setupGlobalExternalAuthentication(contourConfiguration contour_ context = contourConfiguration.GlobalExternalAuthorization.AuthPolicy.Context } - if contourConfiguration.GlobalExternalAuthorization.ServiceAPIType == contour_api_v1.AuthorizationHTTPService && contourConfiguration.GlobalExternalAuthorization.HttpServerSettings == nil { - return nil, fmt.Errorf("Spec.globalExtAuth.HttpServerSettings is not set and it is required for http type") - } - // Not required due to Kubernetes API server validation. // // if auth.ServiceAPIType == contour_api_v1.AuthorizationHTTPService && auth.HttpServerSettings.ServerURI == "" { @@ -885,24 +881,28 @@ func (s *Server) setupGlobalExternalAuthentication(contourConfiguration contour_ globalExternalAuthConfig.ServiceAPIType = contour_api_v1.AuthorizationGRPCService case contour_api_v1.AuthorizationHTTPService: globalExternalAuthConfig.ServiceAPIType = contour_api_v1.AuthorizationHTTPService - globalExternalAuthConfig.HttpPathPrefix = contourConfiguration.GlobalExternalAuthorization.HttpServerSettings.PathPrefix - // globalExternalAuthConfig.HttpServerURI = contourConfiguration.GlobalExternalAuthorization.HttpServerSettings.ServerURI - if contourConfiguration.GlobalExternalAuthorization.HttpServerSettings.AllowedAuthorizationHeaders != nil { - if err := dag.ExternalAuthAllowedHeadersValid(contourConfiguration.GlobalExternalAuthorization.HttpServerSettings.AllowedAuthorizationHeaders); err != nil { - return nil, err - } + if contourConfiguration.GlobalExternalAuthorization.HTTPServerSettings != nil { + globalExternalAuthConfig.HTTPPathPrefix = contourConfiguration.GlobalExternalAuthorization.HTTPServerSettings.PathPrefix - globalExternalAuthConfig.HttpAllowedAuthorizationHeaders = contourConfiguration.GlobalExternalAuthorization.HttpServerSettings.AllowedAuthorizationHeaders - } + // globalExternalAuthConfig.HttpServerURI = contourConfiguration.GlobalExternalAuthorization.HttpServerSettings.ServerURI - if contourConfiguration.GlobalExternalAuthorization.HttpServerSettings.AllowedUpstreamHeaders != nil { - if err := dag.ExternalAuthAllowedHeadersValid(contourConfiguration.GlobalExternalAuthorization.HttpServerSettings.AllowedUpstreamHeaders); err != nil { + if len(contourConfiguration.GlobalExternalAuthorization.HTTPServerSettings.AllowedAuthorizationHeaders) > 0 { + if err := dag.ExternalAuthAllowedHeadersValid(contourConfiguration.GlobalExternalAuthorization.HTTPServerSettings.AllowedAuthorizationHeaders); err != nil { + return nil, err + } - return nil, err + globalExternalAuthConfig.HTTPAllowedAuthorizationHeaders = contourConfiguration.GlobalExternalAuthorization.HTTPServerSettings.AllowedAuthorizationHeaders } - globalExternalAuthConfig.HttpAllowedUpstreamHeaders = contourConfiguration.GlobalExternalAuthorization.HttpServerSettings.AllowedUpstreamHeaders + 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 + } } } diff --git a/cmd/contour/servecontext.go b/cmd/contour/servecontext.go index c6b71d0791a..72b384fc1c3 100644 --- a/cmd/contour/servecontext.go +++ b/cmd/contour/servecontext.go @@ -440,10 +440,15 @@ func (ctx *serveContext) convertToContourConfigurationSpec() contour_api_v1alpha 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_api_v1.AuthorizationPolicy{ Disabled: ctx.Config.GlobalExternalAuthorization.AuthPolicy.Disabled, diff --git a/examples/contour/01-crds.yaml b/examples/contour/01-crds.yaml index 876bef985e1..7381782771f 100644 --- a/examples/contour/01-crds.yaml +++ b/examples/contour/01-crds.yaml @@ -632,8 +632,8 @@ spec: authorization to Contour external authorization. type: boolean httpSettings: - description: HttpAuthorizationServerSettings defines configurations - for interacting with an external HTTP authorization server. + description: HTTPServerSettings defines configurations for interacting + with an external HTTP authorization server. properties: allowedAuthorizationHeaders: description: AllowedAuthorizationHeaders specifies client @@ -642,7 +642,7 @@ spec: Host, Method, Path, Content-Length, and Authorization are additionally included in the list. items: - description: HttpAuthorizationServerAllowedHeaders specifies + description: HTTPAuthorizationServerAllowedHeaders specifies how to conditionally match against allowed headers in the context of HTTP authorization. It includes options such as Exact, Prefix, Suffix, Contains, and IgnoreCase @@ -679,7 +679,7 @@ spec: response headers that will be added to the original client request. Note that coexistent headers will be overridden. items: - description: HttpAuthorizationServerAllowedHeaders specifies + description: HTTPAuthorizationServerAllowedHeaders specifies how to conditionally match against allowed headers in the context of HTTP authorization. It includes options such as Exact, Prefix, Suffix, Contains, and IgnoreCase @@ -4387,8 +4387,8 @@ spec: from internal authorization to Contour external authorization. type: boolean httpSettings: - description: HttpAuthorizationServerSettings defines configurations - for interacting with an external HTTP authorization server. + description: HTTPServerSettings defines configurations for + interacting with an external HTTP authorization server. properties: allowedAuthorizationHeaders: description: AllowedAuthorizationHeaders specifies client @@ -4397,7 +4397,7 @@ spec: matchers, Host, Method, Path, Content-Length, and Authorization are additionally included in the list. items: - description: HttpAuthorizationServerAllowedHeaders specifies + description: HTTPAuthorizationServerAllowedHeaders specifies how to conditionally match against allowed headers in the context of HTTP authorization. It includes options such as Exact, Prefix, Suffix, Contains, and @@ -4436,7 +4436,7 @@ spec: client request. Note that coexistent headers will be overridden. items: - description: HttpAuthorizationServerAllowedHeaders specifies + description: HTTPAuthorizationServerAllowedHeaders specifies how to conditionally match against allowed headers in the context of HTTP authorization. It includes options such as Exact, Prefix, Suffix, Contains, and @@ -5083,9 +5083,9 @@ spec: resource. properties: loadBalancerPolicy: - description: The policy for load balancing GRPC service requests. - Note that the `Cookie` and `RequestHash` load balancing strategies - cannot be used here. + description: The policy for load balancing service requests. Note + that the `Cookie` and `RequestHash` load balancing strategies cannot + be used here for GRPC service requests. properties: requestHashPolicies: description: RequestHashPolicies contains a list of hash policies @@ -5151,10 +5151,10 @@ spec: type: object 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. + used to reach this Service. Values may be h2, h2c or http/1.1. If + omitted, protocol-selection falls back on Service annotations. enum: - - h1 + - http/1.1 - h2 - h2c type: string @@ -5168,7 +5168,7 @@ spec: type: string services: description: Services specifies the set of Kubernetes Service resources - that receive GRPC extension API requests. If no weights are specified + that 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. Otherwise, traffic is balanced proportionally to the Weight field in each entry. @@ -7410,8 +7410,8 @@ spec: from internal authorization to Contour external authorization. type: boolean httpSettings: - description: HttpAuthorizationServerSettings defines configurations - for interacting with an external HTTP authorization server. + description: HTTPServerSettings defines configurations for + interacting with an external HTTP authorization server. properties: allowedAuthorizationHeaders: description: AllowedAuthorizationHeaders specifies client @@ -7420,7 +7420,7 @@ spec: matchers, Host, Method, Path, Content-Length, and Authorization are additionally included in the list. items: - description: HttpAuthorizationServerAllowedHeaders specifies + description: HTTPAuthorizationServerAllowedHeaders specifies how to conditionally match against allowed headers in the context of HTTP authorization. It includes options such as Exact, Prefix, Suffix, Contains, and @@ -7459,7 +7459,7 @@ spec: client request. Note that coexistent headers will be overridden. items: - description: HttpAuthorizationServerAllowedHeaders specifies + description: HTTPAuthorizationServerAllowedHeaders specifies how to conditionally match against allowed headers in the context of HTTP authorization. It includes options such as Exact, Prefix, Suffix, Contains, and diff --git a/examples/render/contour-deployment.yaml b/examples/render/contour-deployment.yaml index 602043ecd31..55722d8fbd8 100644 --- a/examples/render/contour-deployment.yaml +++ b/examples/render/contour-deployment.yaml @@ -850,6 +850,91 @@ spec: intended for use only while migrating applications from internal authorization to Contour external authorization. type: boolean + httpSettings: + description: HTTPServerSettings 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. + Note that in addition to the the user’s supplied matchers, + Host, Method, Path, Content-Length, and Authorization are + additionally included in the list. + items: + description: HTTPAuthorizationServerAllowedHeaders specifies + how to conditionally match against allowed headers in + the context of HTTP authorization. It includes options + such as Exact, Prefix, Suffix, Contains, and IgnoreCase + to customize header matching criteria. However, regex + support is intentionally excluded to simplify the user + experience and prevent potential issues. 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 that string matching + should be case insensitive. Note that this has no + effect on the Regex parameter. + 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. Note that coexistent headers will be overridden. + items: + description: HTTPAuthorizationServerAllowedHeaders specifies + how to conditionally match against allowed headers in + the context of HTTP authorization. It includes options + such as Exact, Prefix, Suffix, Contains, and IgnoreCase + to customize header matching criteria. However, regex + support is intentionally excluded to simplify the user + experience and prevent potential issues. 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 that string matching + should be case insensitive. Note that this has no + effect on the Regex parameter. + 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. Timeout durations @@ -859,6 +944,16 @@ spec: 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 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. + enum: + - http + - grpc + type: string withRequestBody: description: WithRequestBody specifies configuration for sending the client request's body to authorization server. @@ -4510,6 +4605,94 @@ spec: It is intended for use only while migrating applications from internal authorization to Contour external authorization. type: boolean + httpSettings: + description: HTTPServerSettings 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. Note that in addition to the the user’s supplied + matchers, Host, Method, Path, Content-Length, and Authorization + are additionally included in the list. + items: + description: HTTPAuthorizationServerAllowedHeaders specifies + how to conditionally match against allowed headers + in the context of HTTP authorization. It includes + options such as Exact, Prefix, Suffix, Contains, and + IgnoreCase to customize header matching criteria. + However, regex support is intentionally excluded to + simplify the user experience and prevent potential + issues. 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 that string matching + should be case insensitive. Note that this has + no effect on the Regex parameter. + 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. Note that coexistent headers will be + overridden. + items: + description: HTTPAuthorizationServerAllowedHeaders specifies + how to conditionally match against allowed headers + in the context of HTTP authorization. It includes + options such as Exact, Prefix, Suffix, Contains, and + IgnoreCase to customize header matching criteria. + However, regex support is intentionally excluded to + simplify the user experience and prevent potential + issues. 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 that string matching + should be case insensitive. Note that this has + no effect on the Regex parameter. + 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. Timeout @@ -4519,6 +4702,16 @@ spec: 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 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. + enum: + - http + - grpc + type: string withRequestBody: description: WithRequestBody specifies configuration for sending the client request's body to authorization server. @@ -5109,9 +5302,9 @@ spec: resource. properties: loadBalancerPolicy: - description: The policy for load balancing GRPC service requests. - Note that the `Cookie` and `RequestHash` load balancing strategies - cannot be used here. + description: The policy for load balancing service requests. Note + that the `Cookie` and `RequestHash` load balancing strategies cannot + be used here for GRPC service requests. properties: requestHashPolicies: description: RequestHashPolicies contains a list of hash policies @@ -5177,9 +5370,10 @@ spec: type: object 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. + used to reach this Service. 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 @@ -5193,7 +5387,7 @@ spec: type: string services: description: Services specifies the set of Kubernetes Service resources - that receive GRPC extension API requests. If no weights are specified + that 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. Otherwise, traffic is balanced proportionally to the Weight field in each entry. @@ -7434,6 +7628,94 @@ spec: It is intended for use only while migrating applications from internal authorization to Contour external authorization. type: boolean + httpSettings: + description: HTTPServerSettings 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. Note that in addition to the the user’s supplied + matchers, Host, Method, Path, Content-Length, and Authorization + are additionally included in the list. + items: + description: HTTPAuthorizationServerAllowedHeaders specifies + how to conditionally match against allowed headers + in the context of HTTP authorization. It includes + options such as Exact, Prefix, Suffix, Contains, and + IgnoreCase to customize header matching criteria. + However, regex support is intentionally excluded to + simplify the user experience and prevent potential + issues. 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 that string matching + should be case insensitive. Note that this has + no effect on the Regex parameter. + 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. Note that coexistent headers will be + overridden. + items: + description: HTTPAuthorizationServerAllowedHeaders specifies + how to conditionally match against allowed headers + in the context of HTTP authorization. It includes + options such as Exact, Prefix, Suffix, Contains, and + IgnoreCase to customize header matching criteria. + However, regex support is intentionally excluded to + simplify the user experience and prevent potential + issues. 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 that string matching + should be case insensitive. Note that this has + no effect on the Regex parameter. + 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. Timeout @@ -7443,6 +7725,16 @@ spec: 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 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. + 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 9d1fa385dd9..6e1b6b1e562 100644 --- a/examples/render/contour-gateway-provisioner.yaml +++ b/examples/render/contour-gateway-provisioner.yaml @@ -642,6 +642,91 @@ spec: intended for use only while migrating applications from internal authorization to Contour external authorization. type: boolean + httpSettings: + description: HTTPServerSettings 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. + Note that in addition to the the user’s supplied matchers, + Host, Method, Path, Content-Length, and Authorization are + additionally included in the list. + items: + description: HTTPAuthorizationServerAllowedHeaders specifies + how to conditionally match against allowed headers in + the context of HTTP authorization. It includes options + such as Exact, Prefix, Suffix, Contains, and IgnoreCase + to customize header matching criteria. However, regex + support is intentionally excluded to simplify the user + experience and prevent potential issues. 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 that string matching + should be case insensitive. Note that this has no + effect on the Regex parameter. + 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. Note that coexistent headers will be overridden. + items: + description: HTTPAuthorizationServerAllowedHeaders specifies + how to conditionally match against allowed headers in + the context of HTTP authorization. It includes options + such as Exact, Prefix, Suffix, Contains, and IgnoreCase + to customize header matching criteria. However, regex + support is intentionally excluded to simplify the user + experience and prevent potential issues. 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 that string matching + should be case insensitive. Note that this has no + effect on the Regex parameter. + 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. Timeout durations @@ -651,6 +736,16 @@ spec: 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 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. + enum: + - http + - grpc + type: string withRequestBody: description: WithRequestBody specifies configuration for sending the client request's body to authorization server. @@ -4302,6 +4397,94 @@ spec: It is intended for use only while migrating applications from internal authorization to Contour external authorization. type: boolean + httpSettings: + description: HTTPServerSettings 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. Note that in addition to the the user’s supplied + matchers, Host, Method, Path, Content-Length, and Authorization + are additionally included in the list. + items: + description: HTTPAuthorizationServerAllowedHeaders specifies + how to conditionally match against allowed headers + in the context of HTTP authorization. It includes + options such as Exact, Prefix, Suffix, Contains, and + IgnoreCase to customize header matching criteria. + However, regex support is intentionally excluded to + simplify the user experience and prevent potential + issues. 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 that string matching + should be case insensitive. Note that this has + no effect on the Regex parameter. + 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. Note that coexistent headers will be + overridden. + items: + description: HTTPAuthorizationServerAllowedHeaders specifies + how to conditionally match against allowed headers + in the context of HTTP authorization. It includes + options such as Exact, Prefix, Suffix, Contains, and + IgnoreCase to customize header matching criteria. + However, regex support is intentionally excluded to + simplify the user experience and prevent potential + issues. 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 that string matching + should be case insensitive. Note that this has + no effect on the Regex parameter. + 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. Timeout @@ -4311,6 +4494,16 @@ spec: 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 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. + enum: + - http + - grpc + type: string withRequestBody: description: WithRequestBody specifies configuration for sending the client request's body to authorization server. @@ -4901,9 +5094,9 @@ spec: resource. properties: loadBalancerPolicy: - description: The policy for load balancing GRPC service requests. - Note that the `Cookie` and `RequestHash` load balancing strategies - cannot be used here. + description: The policy for load balancing service requests. Note + that the `Cookie` and `RequestHash` load balancing strategies cannot + be used here for GRPC service requests. properties: requestHashPolicies: description: RequestHashPolicies contains a list of hash policies @@ -4969,9 +5162,10 @@ spec: type: object 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. + used to reach this Service. 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 @@ -4985,7 +5179,7 @@ spec: type: string services: description: Services specifies the set of Kubernetes Service resources - that receive GRPC extension API requests. If no weights are specified + that 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. Otherwise, traffic is balanced proportionally to the Weight field in each entry. @@ -7226,6 +7420,94 @@ spec: It is intended for use only while migrating applications from internal authorization to Contour external authorization. type: boolean + httpSettings: + description: HTTPServerSettings 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. Note that in addition to the the user’s supplied + matchers, Host, Method, Path, Content-Length, and Authorization + are additionally included in the list. + items: + description: HTTPAuthorizationServerAllowedHeaders specifies + how to conditionally match against allowed headers + in the context of HTTP authorization. It includes + options such as Exact, Prefix, Suffix, Contains, and + IgnoreCase to customize header matching criteria. + However, regex support is intentionally excluded to + simplify the user experience and prevent potential + issues. 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 that string matching + should be case insensitive. Note that this has + no effect on the Regex parameter. + 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. Note that coexistent headers will be + overridden. + items: + description: HTTPAuthorizationServerAllowedHeaders specifies + how to conditionally match against allowed headers + in the context of HTTP authorization. It includes + options such as Exact, Prefix, Suffix, Contains, and + IgnoreCase to customize header matching criteria. + However, regex support is intentionally excluded to + simplify the user experience and prevent potential + issues. 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 that string matching + should be case insensitive. Note that this has + no effect on the Regex parameter. + 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. Timeout @@ -7235,6 +7517,16 @@ spec: 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 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. + 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 3ee6966b820..f64276cb687 100644 --- a/examples/render/contour-gateway.yaml +++ b/examples/render/contour-gateway.yaml @@ -853,6 +853,91 @@ spec: intended for use only while migrating applications from internal authorization to Contour external authorization. type: boolean + httpSettings: + description: HTTPServerSettings 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. + Note that in addition to the the user’s supplied matchers, + Host, Method, Path, Content-Length, and Authorization are + additionally included in the list. + items: + description: HTTPAuthorizationServerAllowedHeaders specifies + how to conditionally match against allowed headers in + the context of HTTP authorization. It includes options + such as Exact, Prefix, Suffix, Contains, and IgnoreCase + to customize header matching criteria. However, regex + support is intentionally excluded to simplify the user + experience and prevent potential issues. 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 that string matching + should be case insensitive. Note that this has no + effect on the Regex parameter. + 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. Note that coexistent headers will be overridden. + items: + description: HTTPAuthorizationServerAllowedHeaders specifies + how to conditionally match against allowed headers in + the context of HTTP authorization. It includes options + such as Exact, Prefix, Suffix, Contains, and IgnoreCase + to customize header matching criteria. However, regex + support is intentionally excluded to simplify the user + experience and prevent potential issues. 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 that string matching + should be case insensitive. Note that this has no + effect on the Regex parameter. + 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. Timeout durations @@ -862,6 +947,16 @@ spec: 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 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. + enum: + - http + - grpc + type: string withRequestBody: description: WithRequestBody specifies configuration for sending the client request's body to authorization server. @@ -4513,6 +4608,94 @@ spec: It is intended for use only while migrating applications from internal authorization to Contour external authorization. type: boolean + httpSettings: + description: HTTPServerSettings 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. Note that in addition to the the user’s supplied + matchers, Host, Method, Path, Content-Length, and Authorization + are additionally included in the list. + items: + description: HTTPAuthorizationServerAllowedHeaders specifies + how to conditionally match against allowed headers + in the context of HTTP authorization. It includes + options such as Exact, Prefix, Suffix, Contains, and + IgnoreCase to customize header matching criteria. + However, regex support is intentionally excluded to + simplify the user experience and prevent potential + issues. 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 that string matching + should be case insensitive. Note that this has + no effect on the Regex parameter. + 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. Note that coexistent headers will be + overridden. + items: + description: HTTPAuthorizationServerAllowedHeaders specifies + how to conditionally match against allowed headers + in the context of HTTP authorization. It includes + options such as Exact, Prefix, Suffix, Contains, and + IgnoreCase to customize header matching criteria. + However, regex support is intentionally excluded to + simplify the user experience and prevent potential + issues. 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 that string matching + should be case insensitive. Note that this has + no effect on the Regex parameter. + 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. Timeout @@ -4522,6 +4705,16 @@ spec: 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 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. + enum: + - http + - grpc + type: string withRequestBody: description: WithRequestBody specifies configuration for sending the client request's body to authorization server. @@ -5112,9 +5305,9 @@ spec: resource. properties: loadBalancerPolicy: - description: The policy for load balancing GRPC service requests. - Note that the `Cookie` and `RequestHash` load balancing strategies - cannot be used here. + description: The policy for load balancing service requests. Note + that the `Cookie` and `RequestHash` load balancing strategies cannot + be used here for GRPC service requests. properties: requestHashPolicies: description: RequestHashPolicies contains a list of hash policies @@ -5180,9 +5373,10 @@ spec: type: object 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. + used to reach this Service. 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 @@ -5196,7 +5390,7 @@ spec: type: string services: description: Services specifies the set of Kubernetes Service resources - that receive GRPC extension API requests. If no weights are specified + that 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. Otherwise, traffic is balanced proportionally to the Weight field in each entry. @@ -7437,6 +7631,94 @@ spec: It is intended for use only while migrating applications from internal authorization to Contour external authorization. type: boolean + httpSettings: + description: HTTPServerSettings 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. Note that in addition to the the user’s supplied + matchers, Host, Method, Path, Content-Length, and Authorization + are additionally included in the list. + items: + description: HTTPAuthorizationServerAllowedHeaders specifies + how to conditionally match against allowed headers + in the context of HTTP authorization. It includes + options such as Exact, Prefix, Suffix, Contains, and + IgnoreCase to customize header matching criteria. + However, regex support is intentionally excluded to + simplify the user experience and prevent potential + issues. 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 that string matching + should be case insensitive. Note that this has + no effect on the Regex parameter. + 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. Note that coexistent headers will be + overridden. + items: + description: HTTPAuthorizationServerAllowedHeaders specifies + how to conditionally match against allowed headers + in the context of HTTP authorization. It includes + options such as Exact, Prefix, Suffix, Contains, and + IgnoreCase to customize header matching criteria. + However, regex support is intentionally excluded to + simplify the user experience and prevent potential + issues. 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 that string matching + should be case insensitive. Note that this has + no effect on the Regex parameter. + 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. Timeout @@ -7446,6 +7728,16 @@ spec: 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 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. + 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 dcde8ac9e5e..01d4a3f3993 100644 --- a/examples/render/contour.yaml +++ b/examples/render/contour.yaml @@ -850,6 +850,91 @@ spec: intended for use only while migrating applications from internal authorization to Contour external authorization. type: boolean + httpSettings: + description: HTTPServerSettings 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. + Note that in addition to the the user’s supplied matchers, + Host, Method, Path, Content-Length, and Authorization are + additionally included in the list. + items: + description: HTTPAuthorizationServerAllowedHeaders specifies + how to conditionally match against allowed headers in + the context of HTTP authorization. It includes options + such as Exact, Prefix, Suffix, Contains, and IgnoreCase + to customize header matching criteria. However, regex + support is intentionally excluded to simplify the user + experience and prevent potential issues. 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 that string matching + should be case insensitive. Note that this has no + effect on the Regex parameter. + 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. Note that coexistent headers will be overridden. + items: + description: HTTPAuthorizationServerAllowedHeaders specifies + how to conditionally match against allowed headers in + the context of HTTP authorization. It includes options + such as Exact, Prefix, Suffix, Contains, and IgnoreCase + to customize header matching criteria. However, regex + support is intentionally excluded to simplify the user + experience and prevent potential issues. 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 that string matching + should be case insensitive. Note that this has no + effect on the Regex parameter. + 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. Timeout durations @@ -859,6 +944,16 @@ spec: 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 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. + enum: + - http + - grpc + type: string withRequestBody: description: WithRequestBody specifies configuration for sending the client request's body to authorization server. @@ -4510,6 +4605,94 @@ spec: It is intended for use only while migrating applications from internal authorization to Contour external authorization. type: boolean + httpSettings: + description: HTTPServerSettings 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. Note that in addition to the the user’s supplied + matchers, Host, Method, Path, Content-Length, and Authorization + are additionally included in the list. + items: + description: HTTPAuthorizationServerAllowedHeaders specifies + how to conditionally match against allowed headers + in the context of HTTP authorization. It includes + options such as Exact, Prefix, Suffix, Contains, and + IgnoreCase to customize header matching criteria. + However, regex support is intentionally excluded to + simplify the user experience and prevent potential + issues. 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 that string matching + should be case insensitive. Note that this has + no effect on the Regex parameter. + 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. Note that coexistent headers will be + overridden. + items: + description: HTTPAuthorizationServerAllowedHeaders specifies + how to conditionally match against allowed headers + in the context of HTTP authorization. It includes + options such as Exact, Prefix, Suffix, Contains, and + IgnoreCase to customize header matching criteria. + However, regex support is intentionally excluded to + simplify the user experience and prevent potential + issues. 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 that string matching + should be case insensitive. Note that this has + no effect on the Regex parameter. + 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. Timeout @@ -4519,6 +4702,16 @@ spec: 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 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. + enum: + - http + - grpc + type: string withRequestBody: description: WithRequestBody specifies configuration for sending the client request's body to authorization server. @@ -5109,9 +5302,9 @@ spec: resource. properties: loadBalancerPolicy: - description: The policy for load balancing GRPC service requests. - Note that the `Cookie` and `RequestHash` load balancing strategies - cannot be used here. + description: The policy for load balancing service requests. Note + that the `Cookie` and `RequestHash` load balancing strategies cannot + be used here for GRPC service requests. properties: requestHashPolicies: description: RequestHashPolicies contains a list of hash policies @@ -5177,9 +5370,10 @@ spec: type: object 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. + used to reach this Service. 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 @@ -5193,7 +5387,7 @@ spec: type: string services: description: Services specifies the set of Kubernetes Service resources - that receive GRPC extension API requests. If no weights are specified + that 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. Otherwise, traffic is balanced proportionally to the Weight field in each entry. @@ -7434,6 +7628,94 @@ spec: It is intended for use only while migrating applications from internal authorization to Contour external authorization. type: boolean + httpSettings: + description: HTTPServerSettings 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. Note that in addition to the the user’s supplied + matchers, Host, Method, Path, Content-Length, and Authorization + are additionally included in the list. + items: + description: HTTPAuthorizationServerAllowedHeaders specifies + how to conditionally match against allowed headers + in the context of HTTP authorization. It includes + options such as Exact, Prefix, Suffix, Contains, and + IgnoreCase to customize header matching criteria. + However, regex support is intentionally excluded to + simplify the user experience and prevent potential + issues. 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 that string matching + should be case insensitive. Note that this has + no effect on the Regex parameter. + 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. Note that coexistent headers will be + overridden. + items: + description: HTTPAuthorizationServerAllowedHeaders specifies + how to conditionally match against allowed headers + in the context of HTTP authorization. It includes + options such as Exact, Prefix, Suffix, Contains, and + IgnoreCase to customize header matching criteria. + However, regex support is intentionally excluded to + simplify the user experience and prevent potential + issues. 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 that string matching + should be case insensitive. Note that this has + no effect on the Regex parameter. + 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. Timeout @@ -7443,6 +7725,16 @@ spec: 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 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. + 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 fce6c942987..1384ae32405 100644 --- a/internal/dag/conditions.go +++ b/internal/dag/conditions.go @@ -413,7 +413,7 @@ func queryParameterMatchConditionsValid(conditions []contour_api_v1.MatchConditi // - 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_api_v1.HttpAuthorizationServerAllowedHeaders) error { +func ExternalAuthAllowedHeadersValid(allowedHeaders []contour_api_v1.HTTPAuthorizationServerAllowedHeaders) error { for _, allowedHeader := range allowedHeaders { sum := 0 diff --git a/internal/dag/dag.go b/internal/dag/dag.go index f8bc1052089..95fb8bbff0f 100644 --- a/internal/dag/dag.go +++ b/internal/dag/dag.go @@ -859,16 +859,16 @@ type ExternalAuthorization struct { // or a gRPC authorization server. ServiceAPIType contour_api_v1.AuthorizationServiceAPIType - // HttpAllowedAuthorizationHeaders specifies client request headers that will be sent to the authorization server. + // 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_api_v1.HttpAuthorizationServerAllowedHeaders + HTTPAllowedAuthorizationHeaders []contour_api_v1.HTTPAuthorizationServerAllowedHeaders - // HttpAllowedUpstreamHeaders specifies authorization response headers that will be added to the original client request. + // HTTPAllowedUpstreamHeaders specifies authorization response headers that will be added to the original client request. // Note that coexistent headers will be overridden. - HttpAllowedUpstreamHeaders []contour_api_v1.HttpAuthorizationServerAllowedHeaders + HTTPAllowedUpstreamHeaders []contour_api_v1.HTTPAuthorizationServerAllowedHeaders - // HttpPathPrefix Sets a prefix to the value of authorization request header Path. - HttpPathPrefix string + // 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 diff --git a/internal/dag/httpproxy_processor.go b/internal/dag/httpproxy_processor.go index 4ed9e8e5188..bd6b9fb6334 100644 --- a/internal/dag/httpproxy_processor.go +++ b/internal/dag/httpproxy_processor.go @@ -1375,13 +1375,6 @@ func (p *HTTPProxyProcessor) computeVirtualHostAuthorization(auth *contour_api_v return nil } - if auth.ServiceAPIType == contour_api_v1.AuthorizationHTTPService && auth.HttpServerSettings == nil { - validCond.AddErrorf(contour_api_v1.ConditionTypeAuthError, "AuthNilHttpSettings", - "Spec.Virtualhost.Authorization.HttpServerSettings is not set and it is required for http type") - - return nil - } - // Not required due to Kubernetes API server validation. // // if auth.ServiceAPIType == contour_api_v1.AuthorizationHTTPService && auth.HttpServerSettings.ServerURI == "" { @@ -1402,29 +1395,33 @@ func (p *HTTPProxyProcessor) computeVirtualHostAuthorization(auth *contour_api_v globalExternalAuthorization.ServiceAPIType = contour_api_v1.AuthorizationGRPCService case contour_api_v1.AuthorizationHTTPService: globalExternalAuthorization.ServiceAPIType = contour_api_v1.AuthorizationHTTPService - globalExternalAuthorization.HttpPathPrefix = auth.HttpServerSettings.PathPrefix - // globalExternalAuthorization.HttpServerURI = auth.HttpServerSettings.ServerURI - if auth.HttpServerSettings.AllowedAuthorizationHeaders != nil { - if err := ExternalAuthAllowedHeadersValid(auth.HttpServerSettings.AllowedAuthorizationHeaders); err != nil { - validCond.AddErrorf(contour_api_v1.ConditionTypeAuthError, "AuthBadAllowedHeader", - err.Error()) + if auth.HTTPServerSettings != nil { + globalExternalAuthorization.HTTPPathPrefix = auth.HTTPServerSettings.PathPrefix - return nil - } + // globalExternalAuthorization.HttpServerURI = auth.HttpServerSettings.ServerURI - globalExternalAuthorization.HttpAllowedAuthorizationHeaders = auth.HttpServerSettings.AllowedAuthorizationHeaders - } + if len(auth.HTTPServerSettings.AllowedAuthorizationHeaders) > 0 { + if err := ExternalAuthAllowedHeadersValid(auth.HTTPServerSettings.AllowedAuthorizationHeaders); err != nil { + validCond.AddErrorf(contour_api_v1.ConditionTypeAuthError, "AuthBadAllowedHeader", + err.Error()) - if auth.HttpServerSettings.AllowedUpstreamHeaders != nil { - if err := ExternalAuthAllowedHeadersValid(auth.HttpServerSettings.AllowedUpstreamHeaders); err != nil { - validCond.AddErrorf(contour_api_v1.ConditionTypeAuthError, "AuthBadAllowedHeader", - err.Error()) + return nil + } - return nil + globalExternalAuthorization.HTTPAllowedAuthorizationHeaders = auth.HTTPServerSettings.AllowedAuthorizationHeaders } - globalExternalAuthorization.HttpAllowedUpstreamHeaders = auth.HttpServerSettings.AllowedUpstreamHeaders + if len(auth.HTTPServerSettings.AllowedUpstreamHeaders) > 0 { + if err := ExternalAuthAllowedHeadersValid(auth.HTTPServerSettings.AllowedUpstreamHeaders); err != nil { + validCond.AddErrorf(contour_api_v1.ConditionTypeAuthError, "AuthBadAllowedHeader", + err.Error()) + + return nil + } + + globalExternalAuthorization.HTTPAllowedUpstreamHeaders = auth.HTTPServerSettings.AllowedUpstreamHeaders + } } } diff --git a/internal/envoy/v3/cluster.go b/internal/envoy/v3/cluster.go index 49811ba4c1d..36968f1397c 100644 --- a/internal/envoy/v3/cluster.go +++ b/internal/envoy/v3/cluster.go @@ -173,10 +173,10 @@ func ExtensionCluster(ext *dag.ExtensionCluster) *envoy_cluster_v3.Cluster { // 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( UpstreamTLSContext( ext.UpstreamValidation, @@ -187,13 +187,15 @@ func ExtensionCluster(ext *dag.ExtensionCluster) *envoy_cluster_v3.Cluster { ), ) 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) return cluster } diff --git a/internal/envoy/v3/listener.go b/internal/envoy/v3/listener.go index 66258803f9e..6319baa6ad1 100644 --- a/internal/envoy/v3/listener.go +++ b/internal/envoy/v3/listener.go @@ -779,7 +779,7 @@ end } // ExternalAuthzAllowedHeaders returns the slice of StringMatcher for a given slice of HttpAuthorizationServerAllowedHeaders. -func ExternalAuthzAllowedHeaders(allowedHeaders []contour_api_v1.HttpAuthorizationServerAllowedHeaders) []*envoy_matcher.StringMatcher { +func ExternalAuthzAllowedHeaders(allowedHeaders []contour_api_v1.HTTPAuthorizationServerAllowedHeaders) []*envoy_matcher.StringMatcher { var allowedHeaderPatterns []*envoy_matcher.StringMatcher for _, allowedHeader := range allowedHeaders { @@ -868,20 +868,20 @@ func FilterExternalAuthz(externalAuthorization *dag.ExternalAuthorization) *http }, } - if pathPrefix := externalAuthorization.HttpPathPrefix; pathPrefix != "" { - extAuthzService.HttpService.PathPrefix = pathPrefix + if externalAuthorization.HTTPPathPrefix != "" { + extAuthzService.HttpService.PathPrefix = externalAuthorization.HTTPPathPrefix } - if len(externalAuthorization.HttpAllowedAuthorizationHeaders) > 0 { + if len(externalAuthorization.HTTPAllowedAuthorizationHeaders) > 0 { authConfig.AllowedHeaders = &envoy_matcher.ListStringMatcher{ - Patterns: ExternalAuthzAllowedHeaders(externalAuthorization.HttpAllowedAuthorizationHeaders), + Patterns: ExternalAuthzAllowedHeaders(externalAuthorization.HTTPAllowedAuthorizationHeaders), } } - if len(externalAuthorization.HttpAllowedUpstreamHeaders) > 0 { + if len(externalAuthorization.HTTPAllowedUpstreamHeaders) > 0 { extAuthzService.HttpService.AuthorizationResponse = &envoy_config_filter_http_ext_authz_v3.AuthorizationResponse{ AllowedUpstreamHeaders: &envoy_matcher.ListStringMatcher{ - Patterns: ExternalAuthzAllowedHeaders(externalAuthorization.HttpAllowedUpstreamHeaders), + Patterns: ExternalAuthzAllowedHeaders(externalAuthorization.HTTPAllowedUpstreamHeaders), }, } } diff --git a/internal/featuretests/v3/authorization_test.go b/internal/featuretests/v3/authorization_test.go index 3e51070cba2..0fc809b8aa0 100644 --- a/internal/featuretests/v3/authorization_test.go +++ b/internal/featuretests/v3/authorization_test.go @@ -24,6 +24,7 @@ import ( envoy_route_v3 "github.com/envoyproxy/go-control-plane/envoy/config/route/v3" envoy_config_filter_http_ext_authz_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/ext_authz/v3" envoy_discovery_v3 "github.com/envoyproxy/go-control-plane/envoy/service/discovery/v3" + matcherv3 "github.com/envoyproxy/go-control-plane/envoy/type/matcher/v3" envoy_type "github.com/envoyproxy/go-control-plane/envoy/type/v3" contour_api_v1 "github.com/projectcontour/contour/apis/projectcontour/v1" "github.com/projectcontour/contour/apis/projectcontour/v1alpha1" @@ -50,6 +51,20 @@ func grpcCluster(name string) *envoy_config_filter_http_ext_authz_v3.ExtAuthz_Gr } } +func httpCluster(name string) *envoy_config_filter_http_ext_authz_v3.ExtAuthz_HttpService { + return &envoy_config_filter_http_ext_authz_v3.ExtAuthz_HttpService{ + HttpService: &envoy_config_filter_http_ext_authz_v3.HttpService{ + ServerUri: &envoy_core_v3.HttpUri{ + Uri: "http://dummy/", + HttpUpstreamType: &envoy_core_v3.HttpUri_Cluster{ + Cluster: name, + }, + Timeout: durationpb.New(defaultResponseTimeout), + }, + }, + } +} + func authzResponseTimeout(t *testing.T, rh ResourceEventHandlerWrapper, c *Contour) { const fqdn = "failopen.projectcontour.io" @@ -61,6 +76,7 @@ func authzResponseTimeout(t *testing.T, rh ResourceEventHandlerWrapper, c *Conto Namespace: "auth", Name: "extension", }, + ServiceAPIType: contour_api_v1.AuthorizationGRPCService, ResponseTimeout: "10m", }). WithSpec(contour_api_v1.HTTPProxySpec{ @@ -124,6 +140,7 @@ func authzInvalidResponseTimeout(t *testing.T, rh ResourceEventHandlerWrapper, c Namespace: "auth", Name: "extension", }, + ServiceAPIType: contour_api_v1.AuthorizationGRPCService, ResponseTimeout: "invalid-timeout", }). WithSpec(contour_api_v1.HTTPProxySpec{ @@ -151,7 +168,8 @@ func authzFailOpen(t *testing.T, rh ResourceEventHandlerWrapper, c *Contour) { Namespace: "auth", Name: "extension", }, - FailOpen: true, + ServiceAPIType: contour_api_v1.AuthorizationGRPCService, + FailOpen: true, }). WithSpec(contour_api_v1.HTTPProxySpec{ Routes: []contour_api_v1.Route{{ @@ -208,6 +226,7 @@ func authzFallbackIncompat(t *testing.T, rh ResourceEventHandlerWrapper, c *Cont Namespace: "auth", Name: "extension", }, + ServiceAPIType: contour_api_v1.AuthorizationGRPCService, }). WithSpec(contour_api_v1.HTTPProxySpec{ Routes: []contour_api_v1.Route{{ @@ -239,6 +258,7 @@ func authzOverrideDisabled(t *testing.T, rh ResourceEventHandlerWrapper, c *Cont WithCertificate("certificate"). WithAuthServer(contour_api_v1.AuthorizationServer{ ExtensionServiceRef: extensionRef, + ServiceAPIType: contour_api_v1.AuthorizationGRPCService, AuthPolicy: &contour_api_v1.AuthorizationPolicy{Disabled: false}, }). WithSpec(contour_api_v1.HTTPProxySpec{ @@ -258,6 +278,7 @@ func authzOverrideDisabled(t *testing.T, rh ResourceEventHandlerWrapper, c *Cont WithCertificate("certificate"). WithAuthServer(contour_api_v1.AuthorizationServer{ ExtensionServiceRef: extensionRef, + ServiceAPIType: contour_api_v1.AuthorizationGRPCService, AuthPolicy: &contour_api_v1.AuthorizationPolicy{Disabled: true}, }). WithSpec(contour_api_v1.HTTPProxySpec{ @@ -352,6 +373,7 @@ func authzMergeRouteContext(t *testing.T, rh ResourceEventHandlerWrapper, c *Con Namespace: "auth", Name: "extension", }, + ServiceAPIType: contour_api_v1.AuthorizationGRPCService, AuthPolicy: &contour_api_v1.AuthorizationPolicy{ Context: map[string]string{ "root-element": "root", @@ -430,7 +452,9 @@ func authzInvalidReference(t *testing.T, rh ResourceEventHandlerWrapper, c *Cont invalid := fixture.NewProxy("proxy"). WithFQDN(fqdn). WithCertificate("certificate"). - WithAuthServer(contour_api_v1.AuthorizationServer{}). + WithAuthServer(contour_api_v1.AuthorizationServer{ + ServiceAPIType: contour_api_v1.AuthorizationGRPCService, + }). WithSpec(contour_api_v1.HTTPProxySpec{ Routes: []contour_api_v1.Route{{ Services: []contour_api_v1.Service{{ @@ -525,7 +549,8 @@ func authzWithRequestBodyBufferSettings(t *testing.T, rh ResourceEventHandlerWra Namespace: "auth", Name: "extension", }, - FailOpen: true, + ServiceAPIType: contour_api_v1.AuthorizationGRPCService, + FailOpen: true, WithRequestBody: &contour_api_v1.AuthorizationServerBufferSettings{ MaxRequestBytes: 100, AllowPartialMessage: true, @@ -583,16 +608,465 @@ 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_api_v1.AuthorizationServer{ + ExtensionServiceRef: contour_api_v1.ExtensionServiceReference{ + Namespace: "auth", + Name: "extension", + }, + ServiceAPIType: contour_api_v1.AuthorizationGRPCService, + }). + WithSpec(contour_api_v1.HTTPProxySpec{ + Routes: []contour_api_v1.Route{{ + Services: []contour_api_v1.Service{{ + Name: "app-server", + Port: 80, + }}, + }}, + }) + + rh.OnDelete(p) + rh.OnAdd(p) + + c.Request(listenerType).Equals(&envoy_discovery_v3.DiscoveryResponse{ + TypeUrl: listenerType, + Resources: resources(t, + defaultHTTPListener(), + &envoy_listener_v3.Listener{ + Name: "ingress_https", + Address: envoy_v3.SocketAddress("0.0.0.0", 8443), + ListenerFilters: envoy_v3.ListenerFilters( + envoy_v3.TLSInspector(), + ), + FilterChains: []*envoy_listener_v3.FilterChain{ + filterchaintls(fqdn, + &corev1.Secret{ + ObjectMeta: fixture.ObjectMeta("certificate"), + Type: "kubernetes.io/tls", + Data: featuretests.Secretdata(featuretests.CERTIFICATE, featuretests.RSA_PRIVATE_KEY), + }, + authzFilterFor( + fqdn, + &envoy_config_filter_http_ext_authz_v3.ExtAuthz{ + Services: grpcCluster("extension/auth/extension"), + ClearRouteCache: true, + FailureModeAllow: false, + IncludePeerCertificate: true, + StatusOnError: &envoy_type.HttpStatus{ + Code: envoy_type.StatusCode_Forbidden, + }, + TransportApiVersion: envoy_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_api_v1.AuthorizationServer{ + ExtensionServiceRef: contour_api_v1.ExtensionServiceReference{ + Namespace: "auth", + Name: "extension", + }, + ServiceAPIType: contour_api_v1.AuthorizationHTTPService, + }). + WithSpec(contour_api_v1.HTTPProxySpec{ + Routes: []contour_api_v1.Route{{ + Services: []contour_api_v1.Service{{ + Name: "app-server", + Port: 80, + }}, + }}, + }) + + rh.OnDelete(p) + rh.OnAdd(p) + + c.Request(listenerType).Equals(&envoy_discovery_v3.DiscoveryResponse{ + TypeUrl: listenerType, + Resources: resources(t, + defaultHTTPListener(), + &envoy_listener_v3.Listener{ + Name: "ingress_https", + Address: envoy_v3.SocketAddress("0.0.0.0", 8443), + ListenerFilters: envoy_v3.ListenerFilters( + envoy_v3.TLSInspector(), + ), + FilterChains: []*envoy_listener_v3.FilterChain{ + filterchaintls(fqdn, + &corev1.Secret{ + ObjectMeta: fixture.ObjectMeta("certificate"), + Type: "kubernetes.io/tls", + Data: featuretests.Secretdata(featuretests.CERTIFICATE, featuretests.RSA_PRIVATE_KEY), + }, + authzFilterFor( + fqdn, + &envoy_config_filter_http_ext_authz_v3.ExtAuthz{ + Services: httpCluster("extension/auth/extension"), + ClearRouteCache: true, + FailureModeAllow: false, + IncludePeerCertificate: true, + StatusOnError: &envoy_type.HttpStatus{ + Code: envoy_type.StatusCode_Forbidden, + }, + TransportApiVersion: envoy_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_api_v1.AuthorizationServer{ + ExtensionServiceRef: contour_api_v1.ExtensionServiceReference{ + Namespace: "auth", + Name: "extension", + }, + ServiceAPIType: contour_api_v1.AuthorizationHTTPService, + HTTPServerSettings: &contour_api_v1.HTTPAuthorizationServerSettings{ + PathPrefix: "/auth?", + }, + }). + WithSpec(contour_api_v1.HTTPProxySpec{ + Routes: []contour_api_v1.Route{{ + Services: []contour_api_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_discovery_v3.DiscoveryResponse{ + TypeUrl: listenerType, + Resources: resources(t, + defaultHTTPListener(), + &envoy_listener_v3.Listener{ + Name: "ingress_https", + Address: envoy_v3.SocketAddress("0.0.0.0", 8443), + ListenerFilters: envoy_v3.ListenerFilters( + envoy_v3.TLSInspector(), + ), + FilterChains: []*envoy_listener_v3.FilterChain{ + filterchaintls(fqdn, + &corev1.Secret{ + ObjectMeta: fixture.ObjectMeta("certificate"), + Type: "kubernetes.io/tls", + Data: featuretests.Secretdata(featuretests.CERTIFICATE, featuretests.RSA_PRIVATE_KEY), + }, + authzFilterFor( + fqdn, + &envoy_config_filter_http_ext_authz_v3.ExtAuthz{ + Services: cluster, + ClearRouteCache: true, + FailureModeAllow: false, + IncludePeerCertificate: true, + StatusOnError: &envoy_type.HttpStatus{ + Code: envoy_type.StatusCode_Forbidden, + }, + TransportApiVersion: envoy_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_api_v1.AuthorizationServer{ + ExtensionServiceRef: contour_api_v1.ExtensionServiceReference{ + Namespace: "auth", + Name: "extension", + }, + ServiceAPIType: contour_api_v1.AuthorizationHTTPService, + }). + WithSpec(contour_api_v1.HTTPProxySpec{ + Routes: []contour_api_v1.Route{{ + Services: []contour_api_v1.Service{{ + Name: "app-server", + Port: 80, + }}, + }}, + }) + + p.Spec.VirtualHost.Authorization.HTTPServerSettings = &contour_api_v1.HTTPAuthorizationServerSettings{ + AllowedAuthorizationHeaders: []contour_api_v1.HTTPAuthorizationServerAllowedHeaders{ + {IgnoreCase: false}, + }, + } + + rh.OnDelete(p) + rh.OnAdd(p) + + c.Request(listenerType).Equals(&envoy_discovery_v3.DiscoveryResponse{ + TypeUrl: listenerType, + Resources: resources(t, statsListener()), + }).Status(p).HasError(contour_api_v1.ConditionTypeAuthError, "AuthBadAllowedHeader", `one of prefix, suffix, exact or contains is required for each allowedHeader`) + + p.Spec.VirtualHost.Authorization.HTTPServerSettings = &contour_api_v1.HTTPAuthorizationServerSettings{ + AllowedAuthorizationHeaders: []contour_api_v1.HTTPAuthorizationServerAllowedHeaders{ + {Exact: "test", Prefix: "test", IgnoreCase: false}, + }, + } + + rh.OnDelete(p) + rh.OnAdd(p) + + c.Request(listenerType).Equals(&envoy_discovery_v3.DiscoveryResponse{ + TypeUrl: listenerType, + Resources: resources(t, statsListener()), + }).Status(p).HasError(contour_api_v1.ConditionTypeAuthError, "AuthBadAllowedHeader", `more than one prefix, suffix, exact or contains is not allowed in an allowedHeader`) + + p.Spec.VirtualHost.Authorization.HTTPServerSettings = &contour_api_v1.HTTPAuthorizationServerSettings{ + AllowedAuthorizationHeaders: []contour_api_v1.HTTPAuthorizationServerAllowedHeaders{ + {Prefix: "test1", IgnoreCase: false}, + {Exact: "test2", IgnoreCase: true}, + }, + } + + rh.OnDelete(p) + rh.OnAdd(p) + + c.Request(listenerType).Equals(&envoy_discovery_v3.DiscoveryResponse{ + TypeUrl: listenerType, + Resources: resources(t, + defaultHTTPListener(), + &envoy_listener_v3.Listener{ + Name: "ingress_https", + Address: envoy_v3.SocketAddress("0.0.0.0", 8443), + ListenerFilters: envoy_v3.ListenerFilters( + envoy_v3.TLSInspector(), + ), + FilterChains: []*envoy_listener_v3.FilterChain{ + filterchaintls(fqdn, + &corev1.Secret{ + ObjectMeta: fixture.ObjectMeta("certificate"), + Type: "kubernetes.io/tls", + Data: featuretests.Secretdata(featuretests.CERTIFICATE, featuretests.RSA_PRIVATE_KEY), + }, + authzFilterFor( + fqdn, + &envoy_config_filter_http_ext_authz_v3.ExtAuthz{ + Services: httpCluster("extension/auth/extension"), + AllowedHeaders: &matcherv3.ListStringMatcher{ + Patterns: []*matcherv3.StringMatcher{ + {MatchPattern: &matcherv3.StringMatcher_Prefix{Prefix: "test1"}, IgnoreCase: false}, + {MatchPattern: &matcherv3.StringMatcher_Exact{Exact: "test2"}, IgnoreCase: true}, + }, + }, + ClearRouteCache: true, + FailureModeAllow: false, + IncludePeerCertificate: true, + StatusOnError: &envoy_type.HttpStatus{ + Code: envoy_type.StatusCode_Forbidden, + }, + TransportApiVersion: envoy_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_api_v1.AuthorizationServer{ + ExtensionServiceRef: contour_api_v1.ExtensionServiceReference{ + Namespace: "auth", + Name: "extension", + }, + ServiceAPIType: contour_api_v1.AuthorizationHTTPService, + }). + WithSpec(contour_api_v1.HTTPProxySpec{ + Routes: []contour_api_v1.Route{{ + Services: []contour_api_v1.Service{{ + Name: "app-server", + Port: 80, + }}, + }}, + }) + + p.Spec.VirtualHost.Authorization.HTTPServerSettings = &contour_api_v1.HTTPAuthorizationServerSettings{ + AllowedUpstreamHeaders: []contour_api_v1.HTTPAuthorizationServerAllowedHeaders{ + {IgnoreCase: false}, + }, + } + + rh.OnDelete(p) + rh.OnAdd(p) + + c.Request(listenerType).Equals(&envoy_discovery_v3.DiscoveryResponse{ + TypeUrl: listenerType, + Resources: resources(t, statsListener()), + }).Status(p).HasError(contour_api_v1.ConditionTypeAuthError, "AuthBadAllowedHeader", `one of prefix, suffix, exact or contains is required for each allowedHeader`) + + p.Spec.VirtualHost.Authorization.HTTPServerSettings = &contour_api_v1.HTTPAuthorizationServerSettings{ + AllowedUpstreamHeaders: []contour_api_v1.HTTPAuthorizationServerAllowedHeaders{ + {Exact: "test", Prefix: "test", IgnoreCase: false}, + }, + } + + rh.OnDelete(p) + rh.OnAdd(p) + + c.Request(listenerType).Equals(&envoy_discovery_v3.DiscoveryResponse{ + TypeUrl: listenerType, + Resources: resources(t, statsListener()), + }).Status(p).HasError(contour_api_v1.ConditionTypeAuthError, "AuthBadAllowedHeader", `more than one prefix, suffix, exact or contains is not allowed in an allowedHeader`) + + p.Spec.VirtualHost.Authorization.HTTPServerSettings = &contour_api_v1.HTTPAuthorizationServerSettings{ + AllowedUpstreamHeaders: []contour_api_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_config_filter_http_ext_authz_v3.AuthorizationResponse{ + AllowedUpstreamHeaders: &matcherv3.ListStringMatcher{ + Patterns: []*matcherv3.StringMatcher{ + {MatchPattern: &matcherv3.StringMatcher_Prefix{Prefix: "test1"}, IgnoreCase: false}, + {MatchPattern: &matcherv3.StringMatcher_Exact{Exact: "test2"}, IgnoreCase: true}, + }, + }, + } + + c.Request(listenerType).Equals(&envoy_discovery_v3.DiscoveryResponse{ + TypeUrl: listenerType, + Resources: resources(t, + defaultHTTPListener(), + &envoy_listener_v3.Listener{ + Name: "ingress_https", + Address: envoy_v3.SocketAddress("0.0.0.0", 8443), + ListenerFilters: envoy_v3.ListenerFilters( + envoy_v3.TLSInspector(), + ), + FilterChains: []*envoy_listener_v3.FilterChain{ + filterchaintls(fqdn, + &corev1.Secret{ + ObjectMeta: fixture.ObjectMeta("certificate"), + Type: "kubernetes.io/tls", + Data: featuretests.Secretdata(featuretests.CERTIFICATE, featuretests.RSA_PRIVATE_KEY), + }, + authzFilterFor( + fqdn, + &envoy_config_filter_http_ext_authz_v3.ExtAuthz{ + Services: cluster, + ClearRouteCache: true, + FailureModeAllow: false, + IncludePeerCertificate: true, + StatusOnError: &envoy_type.HttpStatus{ + Code: envoy_type.StatusCode_Forbidden, + }, + TransportApiVersion: envoy_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_api_v1.AuthorizationServer{ + ExtensionServiceRef: contour_api_v1.ExtensionServiceReference{ + Namespace: "auth", + Name: "extension", + }, + ServiceAPIType: contour_api_v1.AuthorizationHTTPService, + AuthPolicy: &contour_api_v1.AuthorizationPolicy{ + Context: map[string]string{ + "k1": "v1", + "k2": "v2", + }, + }, + }). + WithSpec(contour_api_v1.HTTPProxySpec{ + Routes: []contour_api_v1.Route{{ + Services: []contour_api_v1.Service{{ + Name: "app-server", + Port: 80, + }}, + }}, + }) + + rh.OnDelete(p) + rh.OnAdd(p) + + c.Request(listenerType).Equals(&envoy_discovery_v3.DiscoveryResponse{ + TypeUrl: listenerType, + Resources: resources(t, statsListener()), + }).Status(p).HasError(contour_api_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 139a8c18803..a8f59c009f6 100644 --- a/internal/featuretests/v3/envoy.go +++ b/internal/featuretests/v3/envoy.go @@ -243,6 +243,20 @@ func h2cCluster(c *envoy_cluster_v3.Cluster) *envoy_cluster_v3.Cluster { return c } +func http1Cluster(c *envoy_cluster_v3.Cluster) *envoy_cluster_v3.Cluster { + c.TypedExtensionProtocolOptions = map[string]*anypb.Any{ + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": protobuf.MustMarshalAny( + &envoy_extensions_upstream_http_v3.HttpProtocolOptions{ + UpstreamProtocolOptions: &envoy_extensions_upstream_http_v3.HttpProtocolOptions_ExplicitHttpConfig_{ + ExplicitHttpConfig: &envoy_extensions_upstream_http_v3.HttpProtocolOptions_ExplicitHttpConfig{ + ProtocolConfig: &envoy_extensions_upstream_http_v3.HttpProtocolOptions_ExplicitHttpConfig_HttpProtocolOptions{}, + }, + }, + }), + } + return c +} + func withConnectionTimeout(c *envoy_cluster_v3.Cluster, timeout time.Duration, httpVersion envoy_v3.HTTPVersionType) *envoy_cluster_v3.Cluster { var config *envoy_extensions_upstream_http_v3.HttpProtocolOptions_ExplicitHttpConfig diff --git a/internal/featuretests/v3/extensionservice_test.go b/internal/featuretests/v3/extensionservice_test.go index 43642ca7652..b2e3109f705 100644 --- a/internal/featuretests/v3/extensionservice_test.go +++ b/internal/featuretests/v3/extensionservice_test.go @@ -76,7 +76,7 @@ func extBasic(t *testing.T, rh ResourceEventHandlerWrapper, c *Contour) { } func extCleartext(t *testing.T, rh ResourceEventHandlerWrapper, c *Contour) { - rh.OnAdd(&v1alpha1.ExtensionService{ + es := &v1alpha1.ExtensionService{ ObjectMeta: fixture.ObjectMeta("ns/ext"), Spec: v1alpha1.ExtensionServiceSpec{ Protocol: ref.To("h2c"), @@ -85,7 +85,9 @@ func extCleartext(t *testing.T, rh ResourceEventHandlerWrapper, c *Contour) { {Name: "svc2", Port: 8082}, }, }, - }) + } + + rh.OnAdd(es) c.Request(clusterType).Equals(&envoy_discovery_v3.DiscoveryResponse{ TypeUrl: clusterType, @@ -95,6 +97,21 @@ func extCleartext(t *testing.T, rh ResourceEventHandlerWrapper, c *Contour) { ), ), }) + + es.Spec.Protocol = ref.To("http/1.1") + + rh.OnDelete(es) + rh.OnAdd(es) + + c.Request(clusterType).Equals(&envoy_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) { @@ -317,7 +334,7 @@ func extInvalidTimeout(_ *testing.T, rh ResourceEventHandlerWrapper, c *Contour) } func extInconsistentProto(_ *testing.T, rh ResourceEventHandlerWrapper, c *Contour) { - rh.OnAdd(&v1alpha1.ExtensionService{ + es := &v1alpha1.ExtensionService{ ObjectMeta: fixture.ObjectMeta("ns/ext"), Spec: v1alpha1.ExtensionServiceSpec{ Services: []v1alpha1.ExtensionServiceTarget{ @@ -329,8 +346,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_discovery_v3.DiscoveryResponse{ + TypeUrl: clusterType, }) + es.Spec.Protocol = ref.To("h1") + + rh.OnDelete(es) + rh.OnAdd(es) + // Should have no clusters because Protocol and UpstreamValidation is inconsistent. c.Request(clusterType).Equals(&envoy_discovery_v3.DiscoveryResponse{ TypeUrl: clusterType, diff --git a/internal/featuretests/v3/global_authorization_test.go b/internal/featuretests/v3/global_authorization_test.go index d928bc2057e..499c14013bf 100644 --- a/internal/featuretests/v3/global_authorization_test.go +++ b/internal/featuretests/v3/global_authorization_test.go @@ -411,6 +411,7 @@ func globalExternalAuthorizationWithTLSAuthOverride(t *testing.T, rh ResourceEve Namespace: "auth", Name: "extension", }, + ServiceAPIType: contour_api_v1.AuthorizationGRPCService, ResponseTimeout: defaultResponseTimeout.String(), FailOpen: true, WithRequestBody: &contour_api_v1.AuthorizationServerBufferSettings{ @@ -511,7 +512,8 @@ func TestGlobalAuthorization(t *testing.T) { ExtensionService: k8s.NamespacedNameFrom("auth/extension"), Timeout: timeout.DurationSetting(defaultResponseTimeout), }, - FailOpen: false, + ServiceAPIType: contour_api_v1.AuthorizationGRPCService, + FailOpen: false, Context: map[string]string{ "header_type": "root_config", "header_1": "message_1", @@ -526,6 +528,7 @@ func TestGlobalAuthorization(t *testing.T) { Name: "extension", Namespace: "auth", }, + ServiceAPIType: contour_api_v1.AuthorizationGRPCService, FailOpen: false, ResponseTimeout: defaultResponseTimeout.String(), AuthPolicy: &contour_api_v1.AuthorizationPolicy{ diff --git a/internal/xdscache/v3/listener.go b/internal/xdscache/v3/listener.go index 6060256dc4c..13aee02d28b 100644 --- a/internal/xdscache/v3/listener.go +++ b/internal/xdscache/v3/listener.go @@ -199,9 +199,9 @@ type GlobalExternalAuthConfig struct { FailOpen bool Context map[string]string ServiceAPIType contour_api_v1.AuthorizationServiceAPIType - HttpAllowedAuthorizationHeaders []contour_api_v1.HttpAuthorizationServerAllowedHeaders - HttpAllowedUpstreamHeaders []contour_api_v1.HttpAuthorizationServerAllowedHeaders - HttpPathPrefix string + HTTPAllowedAuthorizationHeaders []contour_api_v1.HTTPAuthorizationServerAllowedHeaders + HTTPAllowedUpstreamHeaders []contour_api_v1.HTTPAuthorizationServerAllowedHeaders + HTTPPathPrefix string WithRequestBody *dag.AuthorizationServerBufferSettings // HttpServerURI string } @@ -633,9 +633,9 @@ func httpGlobalExternalAuthConfig(config *GlobalExternalAuthConfig) *http.HttpFi SNI: config.ExtensionServiceConfig.SNI, }, ServiceAPIType: config.ServiceAPIType, - HttpAllowedAuthorizationHeaders: config.HttpAllowedAuthorizationHeaders, - HttpAllowedUpstreamHeaders: config.HttpAllowedUpstreamHeaders, - HttpPathPrefix: config.HttpPathPrefix, + HTTPAllowedAuthorizationHeaders: config.HTTPAllowedAuthorizationHeaders, + HTTPAllowedUpstreamHeaders: config.HTTPAllowedUpstreamHeaders, + HTTPPathPrefix: config.HTTPPathPrefix, AuthorizationFailOpen: config.FailOpen, AuthorizationResponseTimeout: config.ExtensionServiceConfig.Timeout, AuthorizationServerWithRequestBody: config.WithRequestBody, diff --git a/pkg/config/parameters.go b/pkg/config/parameters.go index 87574eac345..57d3e2af3a4 100644 --- a/pkg/config/parameters.go +++ b/pkg/config/parameters.go @@ -760,6 +760,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_api_v1.AuthorizationServiceAPIType `json:"serviceAPIType,omitempty"` + // HttpAuthorizationServerSettings defines configurations for interacting with an external HTTP authorization server. + // + // +optional + HTTPServerSettings *contour_api_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 77974849583..bf47f593e3a 100644 --- a/site/content/docs/main/config/api-reference.html +++ b/site/content/docs/main/config/api-reference.html @@ -377,6 +377,38 @@

AuthorizationServer +serviceAPIType +
+ + +AuthorizationServiceAPIType + + + + +(Optional) +

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.

+ + + + +httpSettings +
+ + +HTTPAuthorizationServerSettings + + + + +(Optional) +

HTTPServerSettings defines configurations for interacting with an external HTTP authorization server.

+ + + + authPolicy
@@ -498,6 +530,28 @@

AuthorizationSer +

AuthorizationServiceAPIType +(string alias)

+

+(Appears on: +AuthorizationServer) +

+

+

AuthorizationServiceType is an alias to enforce validation

+

+ + + + + + + + + + + + +
ValueDescription

"grpc"

"http"

CORSHeaderValue (string alias)

@@ -1289,6 +1343,159 @@

GlobalRateLimitPolicy +

HTTPAuthorizationServerAllowedHeaders +

+

+(Appears on: +HTTPAuthorizationServerSettings) +

+

+

HTTPAuthorizationServerAllowedHeaders specifies how to conditionally match against allowed headers +in the context of HTTP authorization. It includes options such as Exact, Prefix, Suffix, +Contains, and IgnoreCase to customize header matching criteria. However, regex support +is intentionally excluded to simplify the user experience and prevent potential issues. +One of Prefix, Exact, Suffix or Contains must be provided.

+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldDescription
+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 that string matching should be case insensitive. +Note that this has no effect on the Regex parameter.

+
+

HTTPAuthorizationServerSettings +

+

+(Appears on: +AuthorizationServer) +

+

+

HTTPAuthorizationServerSettings defines configurations for interacting with an external HTTP authorization server.

+

+ + + + + + + + + + + + + + + + + + + + + +
FieldDescription
+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. +Note that in addition to the the user’s supplied matchers, Host, Method, Path, Content-Length, and Authorization are additionally included in the list.

+
+allowedUpstreamHeaders +
+ + +[]HTTPAuthorizationServerAllowedHeaders + + +
+(Optional) +

AllowedUpstreamHeaders specifies authorization response headers that will be added to the original client request. +Note that coexistent headers will be overridden.

+

HTTPDirectResponsePolicy

@@ -5447,7 +5654,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. @@ -5481,7 +5688,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.

@@ -5496,9 +5703,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.

@@ -7421,7 +7628,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. @@ -7455,7 +7662,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.

@@ -7470,9 +7677,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.