{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://projectcontour.io/schemas/httpproxy.json", "title": "Contour HTTPProxy", "description": "Schema for the Contour HTTPProxy custom resource definition. HTTPProxy extends Kubernetes ingress with multi-team support, TLS delegation, weighted load balancing, and cross-namespace route inclusion.", "type": "object", "required": ["apiVersion", "kind", "metadata", "spec"], "properties": { "apiVersion": { "type": "string", "description": "API version of the HTTPProxy resource.", "const": "projectcontour.io/v1" }, "kind": { "type": "string", "description": "Resource kind.", "const": "HTTPProxy" }, "metadata": { "$ref": "#/$defs/ObjectMeta" }, "spec": { "$ref": "#/$defs/HTTPProxySpec" }, "status": { "$ref": "#/$defs/HTTPProxyStatus" } }, "$defs": { "HTTPProxySpec": { "type": "object", "description": "Specification of the HTTPProxy defining routing behavior and virtual host configuration.", "properties": { "virtualhost": { "$ref": "#/$defs/VirtualHost" }, "includes": { "type": "array", "description": "List of child HTTPProxy resources to include as sub-routes. Enables multi-team delegation of routing configuration.", "items": { "$ref": "#/$defs/Include" } }, "routes": { "type": "array", "description": "List of routing rules mapping request conditions to backend services.", "items": { "$ref": "#/$defs/Route" } }, "tcpproxy": { "$ref": "#/$defs/TCPProxy" }, "ingressClassName": { "type": "string", "description": "Name of the IngressClass resource to use for this HTTPProxy." } } }, "VirtualHost": { "type": "object", "description": "Defines the virtual host for a root HTTPProxy, including its FQDN and TLS settings.", "required": ["fqdn"], "properties": { "fqdn": { "type": "string", "description": "Fully qualified domain name of the virtual host.", "pattern": "^[a-zA-Z0-9*][a-zA-Z0-9.-]*$", "examples": ["app.example.com", "*.example.com"] }, "tls": { "$ref": "#/$defs/TLS" }, "rateLimitPolicy": { "$ref": "#/$defs/RateLimitPolicy" }, "corsPolicy": { "$ref": "#/$defs/CORSPolicy" }, "authorization": { "$ref": "#/$defs/AuthorizationServer" } } }, "TLS": { "type": "object", "description": "TLS configuration for a virtual host including certificate reference and protocol settings.", "properties": { "secretName": { "type": "string", "description": "Name of the Kubernetes Secret containing the TLS certificate and key. May reference a Secret in another namespace using 'namespace/name' format if TLSCertificateDelegation grants access." }, "minimumProtocolVersion": { "type": "string", "description": "Minimum TLS protocol version the virtual host will negotiate.", "enum": ["1.2", "1.3"] }, "passthrough": { "type": "boolean", "description": "If true, TLS termination is performed by the backend service rather than by Envoy." }, "enableFallbackCertificate": { "type": "boolean", "description": "If true, Contour will serve a fallback certificate for SNI names that don't match any configured virtual host." }, "clientValidation": { "type": "object", "description": "Configuration for mTLS client certificate validation.", "properties": { "caSecret": { "type": "string", "description": "Name of the Secret containing the CA certificate for client validation." }, "skipClientCertValidation": { "type": "boolean", "description": "If true, client certificates are requested but not required to be valid." } } } } }, "Include": { "type": "object", "description": "A reference to another HTTPProxy to include as child routes, enabling cross-namespace routing delegation.", "required": ["name"], "properties": { "name": { "type": "string", "description": "Name of the HTTPProxy resource to include." }, "namespace": { "type": "string", "description": "Namespace of the included HTTPProxy. If omitted, defaults to the current namespace." }, "conditions": { "type": "array", "description": "Conditions that requests must match for this inclusion to apply.", "items": { "$ref": "#/$defs/MatchCondition" } } } }, "Route": { "type": "object", "description": "A routing rule that maps matched HTTP requests to backend services.", "properties": { "conditions": { "type": "array", "description": "Match conditions for this route. All conditions must match for the route to apply.", "items": { "$ref": "#/$defs/MatchCondition" } }, "services": { "type": "array", "description": "Backend services to route matching traffic to. Multiple services enable weighted load balancing.", "items": { "$ref": "#/$defs/Service" } }, "enableWebsockets": { "type": "boolean", "description": "If true, Contour will upgrade HTTP connections to WebSocket connections for this route." }, "permitInsecure": { "type": "boolean", "description": "If true, allows the route to serve non-TLS requests when the parent virtual host has TLS configured." }, "retryPolicy": { "$ref": "#/$defs/RetryPolicy" }, "timeoutPolicy": { "$ref": "#/$defs/TimeoutPolicy" }, "rateLimitPolicy": { "$ref": "#/$defs/RateLimitPolicy" }, "requestHeadersPolicy": { "$ref": "#/$defs/HeadersPolicy" }, "responseHeadersPolicy": { "$ref": "#/$defs/HeadersPolicy" }, "pathRewritePolicy": { "type": "object", "description": "Policy for rewriting the URL path before forwarding to backends.", "properties": { "replacePrefix": { "type": "array", "items": { "type": "object", "properties": { "prefix": { "type": "string", "description": "The path prefix to replace." }, "replacement": { "type": "string", "description": "The replacement prefix." } } } } } } } }, "MatchCondition": { "type": "object", "description": "A condition that must be satisfied for a route or include to apply.", "properties": { "prefix": { "type": "string", "description": "URL path prefix that incoming requests must start with.", "examples": ["/api", "/static"] }, "exact": { "type": "string", "description": "Exact URL path that incoming requests must match." }, "regex": { "type": "string", "description": "Regular expression that the URL path must match." }, "header": { "$ref": "#/$defs/HeaderMatchCondition" }, "queryParameter": { "$ref": "#/$defs/QueryParameterMatchCondition" } } }, "HeaderMatchCondition": { "type": "object", "description": "A condition matching on an HTTP request header value.", "required": ["name"], "properties": { "name": { "type": "string", "description": "Name of the HTTP header to match." }, "present": { "type": "boolean", "description": "If true, matches requests where the header is present." }, "notpresent": { "type": "boolean", "description": "If true, matches requests where the header is absent." }, "contains": { "type": "string", "description": "Matches if the header value contains this substring." }, "notcontains": { "type": "string", "description": "Matches if the header value does not contain this substring." }, "exact": { "type": "string", "description": "Matches if the header value equals this string exactly." }, "notexact": { "type": "string", "description": "Matches if the header value does not equal this string." }, "regex": { "type": "string", "description": "Matches if the header value matches this regular expression." } } }, "QueryParameterMatchCondition": { "type": "object", "description": "A condition matching on an HTTP request query parameter.", "required": ["name"], "properties": { "name": { "type": "string", "description": "Name of the query parameter to match." }, "exact": { "type": "string", "description": "Matches if the query parameter equals this value." }, "prefix": { "type": "string", "description": "Matches if the query parameter starts with this value." }, "suffix": { "type": "string", "description": "Matches if the query parameter ends with this value." }, "contains": { "type": "string", "description": "Matches if the query parameter contains this substring." }, "present": { "type": "boolean", "description": "If true, matches requests where the query parameter is present." }, "regex": { "type": "string", "description": "Matches if the query parameter value matches this regular expression." } } }, "Service": { "type": "object", "description": "A backend Kubernetes Service to route traffic to.", "required": ["name", "port"], "properties": { "name": { "type": "string", "description": "Name of the Kubernetes Service in the same namespace." }, "port": { "type": "integer", "description": "Port number on the Kubernetes Service.", "minimum": 1, "maximum": 65535 }, "weight": { "type": "integer", "description": "Relative traffic weight. When multiple services are specified, traffic is distributed proportionally by weight.", "minimum": 0 }, "protocol": { "type": "string", "description": "Protocol to use when connecting to the upstream service.", "enum": ["h2", "h2c", "tls"] }, "healthPort": { "type": "integer", "description": "Port to use for health checking if different from the service port.", "minimum": 1, "maximum": 65535 } } }, "TCPProxy": { "type": "object", "description": "TCP proxy configuration for TLS passthrough or raw TCP routing.", "properties": { "services": { "type": "array", "description": "Backend services for TCP proxying.", "items": { "$ref": "#/$defs/Service" } }, "include": { "$ref": "#/$defs/Include" } } }, "RetryPolicy": { "type": "object", "description": "Configuration for retrying failed upstream requests.", "properties": { "count": { "type": "integer", "description": "Number of retry attempts before returning an error to the client.", "minimum": 0 }, "perTryTimeout": { "type": "string", "description": "Timeout per retry attempt as a duration string (e.g. '10s', '1m')." }, "retriableStatusCodes": { "type": "array", "description": "HTTP status codes from the backend that trigger a retry.", "items": { "type": "integer", "minimum": 400, "maximum": 599 } } } }, "TimeoutPolicy": { "type": "object", "description": "Timeout configuration for requests on this route.", "properties": { "response": { "type": "string", "description": "Timeout for the entire response from the backend, as a duration string.", "examples": ["15s", "1m", "infinity"] }, "idle": { "type": "string", "description": "Timeout for idle connections on this route." }, "idleConnection": { "type": "string", "description": "Timeout for idle backend connections in the connection pool." } } }, "RateLimitPolicy": { "type": "object", "description": "Rate limiting configuration applied to this route or virtual host.", "properties": { "local": { "type": "object", "description": "Local rate limiting using Envoy's built-in token bucket algorithm, enforced per Envoy pod.", "properties": { "requests": { "type": "integer", "description": "Maximum number of requests allowed per time unit.", "minimum": 1 }, "unit": { "type": "string", "description": "Time unit for measuring request rate.", "enum": ["second", "minute", "hour"] }, "burst": { "type": "integer", "description": "Maximum burst above the rate limit that is momentarily allowed.", "minimum": 0 }, "responseHeadersToAdd": { "type": "array", "description": "Headers to add to rate-limited responses.", "items": { "$ref": "#/$defs/HeaderValue" } } }, "required": ["requests", "unit"] }, "global": { "type": "object", "description": "Global rate limiting via an external rate limit service shared across all Envoy pods.", "properties": { "descriptors": { "type": "array", "description": "Rate limit descriptors sent to the global rate limit service.", "items": { "type": "object" } } } } } }, "CORSPolicy": { "type": "object", "description": "Cross-Origin Resource Sharing (CORS) policy for the virtual host.", "required": ["allowOrigin", "allowMethods"], "properties": { "allowCredentials": { "type": "boolean", "description": "Whether to include credentials in CORS responses." }, "allowOrigin": { "type": "array", "description": "List of origins allowed to make cross-site requests. Use '*' to allow all origins.", "items": { "type": "string" } }, "allowMethods": { "type": "array", "description": "HTTP methods allowed in cross-origin requests.", "items": { "type": "string", "enum": ["GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS"] } }, "allowHeaders": { "type": "array", "description": "Request headers that are allowed in cross-origin requests.", "items": { "type": "string" } }, "exposeHeaders": { "type": "array", "description": "Response headers that the browser is allowed to access.", "items": { "type": "string" } }, "maxAge": { "type": "string", "description": "Duration to cache CORS preflight responses, as a duration string.", "examples": ["600s", "1h"] } } }, "AuthorizationServer": { "type": "object", "description": "External authorization server configuration for validating requests to the virtual host.", "properties": { "extensionRef": { "type": "object", "description": "Reference to an ExtensionService providing the external authorization server.", "required": ["name"], "properties": { "name": { "type": "string", "description": "Name of the ExtensionService resource." }, "namespace": { "type": "string", "description": "Namespace of the ExtensionService resource." } } }, "authPolicy": { "type": "object", "description": "Policy settings for the authorization check.", "properties": { "disabled": { "type": "boolean", "description": "If true, disables authorization for this virtual host or route." }, "context": { "type": "object", "description": "Additional context key-value pairs to include in authorization requests.", "additionalProperties": { "type": "string" } } } }, "failOpen": { "type": "boolean", "description": "If true, requests proceed even if the authorization service is unavailable." } } }, "HeadersPolicy": { "type": "object", "description": "Policy for adding, setting, or removing HTTP headers on requests or responses.", "properties": { "set": { "type": "array", "description": "Headers to set, overriding any existing value.", "items": { "$ref": "#/$defs/HeaderValue" } }, "remove": { "type": "array", "description": "Header names to remove before forwarding.", "items": { "type": "string" } } } }, "HeaderValue": { "type": "object", "description": "A header name-value pair.", "required": ["name", "value"], "properties": { "name": { "type": "string", "description": "HTTP header name." }, "value": { "type": "string", "description": "HTTP header value. May reference request metadata using dynamic values." } } }, "HTTPProxyStatus": { "type": "object", "description": "Observed status of an HTTPProxy as reported by the Contour controller.", "properties": { "currentStatus": { "type": "string", "description": "High-level processing status of the HTTPProxy.", "enum": ["valid", "invalid", "orphaned"] }, "description": { "type": "string", "description": "Human-readable explanation of the current status." }, "conditions": { "type": "array", "description": "Detailed conditions describing the state of the HTTPProxy.", "items": { "$ref": "#/$defs/DetailedCondition" } } } }, "DetailedCondition": { "type": "object", "description": "A detailed condition providing structured status information.", "required": ["type", "status"], "properties": { "type": { "type": "string", "description": "Type of condition, e.g. 'Valid'." }, "status": { "type": "string", "description": "Status of the condition.", "enum": ["True", "False", "Unknown"] }, "observedGeneration": { "type": "integer", "format": "int64", "description": "Resource generation when this condition was last evaluated." }, "lastTransitionTime": { "type": "string", "format": "date-time", "description": "Time when this condition last transitioned." }, "reason": { "type": "string", "description": "Short, machine-readable reason for the condition." }, "message": { "type": "string", "description": "Human-readable details about the condition." }, "errors": { "type": "array", "description": "Sub-conditions representing specific errors.", "items": { "$ref": "#/$defs/SubCondition" } }, "warnings": { "type": "array", "description": "Sub-conditions representing warnings.", "items": { "$ref": "#/$defs/SubCondition" } } } }, "SubCondition": { "type": "object", "description": "A sub-condition providing granular detail about an error or warning.", "required": ["type", "status"], "properties": { "type": { "type": "string", "description": "Type of sub-condition." }, "status": { "type": "string", "description": "Status of the sub-condition.", "enum": ["True", "False", "Unknown"] }, "reason": { "type": "string", "description": "Short, machine-readable reason." }, "message": { "type": "string", "description": "Human-readable details." } } }, "ObjectMeta": { "type": "object", "description": "Standard Kubernetes object metadata.", "required": ["name"], "properties": { "name": { "type": "string", "description": "Name of the resource, unique within its namespace.", "maxLength": 253, "pattern": "^[a-z0-9][a-z0-9.-]*[a-z0-9]$" }, "namespace": { "type": "string", "description": "Namespace the resource belongs to." }, "labels": { "type": "object", "description": "Labels for organizing and selecting the resource.", "additionalProperties": { "type": "string" } }, "annotations": { "type": "object", "description": "Non-identifying metadata for the resource.", "additionalProperties": { "type": "string" } } } } }, "examples": [ { "apiVersion": "projectcontour.io/v1", "kind": "HTTPProxy", "metadata": { "name": "example-proxy", "namespace": "default" }, "spec": { "virtualhost": { "fqdn": "app.example.com", "tls": { "secretName": "example-tls", "minimumProtocolVersion": "1.2" } }, "routes": [ { "conditions": [ { "prefix": "/api" } ], "services": [ { "name": "api-service", "port": 8080, "weight": 100 } ], "timeoutPolicy": { "response": "15s" } } ] } } ] }