Skip to content

Commit a5be7b5

Browse files
Implementing GEP-1767 CORS Filter for HTTPRoute (#3637)
* WiP * Validation and CRD Gen for CORS Filter * Fixing CRD generation to allow experimental validation at this level * Shrinking spec for CORS to avoid exceeding CRD size limit --------- Co-authored-by: Marcin Kosieradzki <[email protected]>
1 parent d851d24 commit a5be7b5

File tree

10 files changed

+1762
-73
lines changed

10 files changed

+1762
-73
lines changed

apis/v1/httproute_types.go

Lines changed: 237 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -701,6 +701,9 @@ type HTTPQueryParamMatch struct {
701701
// +kubebuilder:validation:Enum=GET;HEAD;POST;PUT;DELETE;CONNECT;OPTIONS;TRACE;PATCH
702702
type HTTPMethod string
703703

704+
// +kubebuilder:validation:Enum=GET;HEAD;POST;PUT;DELETE;CONNECT;OPTIONS;TRACE;PATCH;*
705+
type HTTPMethodWithWildcard string
706+
704707
const (
705708
HTTPMethodGet HTTPMethod = "GET"
706709
HTTPMethodHead HTTPMethod = "HEAD"
@@ -787,6 +790,8 @@ type HTTPRouteMatch struct {
787790
// +kubebuilder:validation:XValidation:message="filter.requestRedirect must be specified for RequestRedirect filter.type",rule="!(!has(self.requestRedirect) && self.type == 'RequestRedirect')"
788791
// +kubebuilder:validation:XValidation:message="filter.urlRewrite must be nil if the filter.type is not URLRewrite",rule="!(has(self.urlRewrite) && self.type != 'URLRewrite')"
789792
// +kubebuilder:validation:XValidation:message="filter.urlRewrite must be specified for URLRewrite filter.type",rule="!(!has(self.urlRewrite) && self.type == 'URLRewrite')"
793+
// <gateway:experimental:validation:XValidation:message="filter.cors must be nil if the filter.type is not CORS",rule="!(has(self.cors) && self.type != 'CORS')">
794+
// <gateway:experimental:validation:XValidation:message="filter.cors must be specified for CORS filter.type",rule="!(!has(self.cors) && self.type == 'CORS')">
790795
// +kubebuilder:validation:XValidation:message="filter.extensionRef must be nil if the filter.type is not ExtensionRef",rule="!(has(self.extensionRef) && self.type != 'ExtensionRef')"
791796
// +kubebuilder:validation:XValidation:message="filter.extensionRef must be specified for ExtensionRef filter.type",rule="!(!has(self.extensionRef) && self.type == 'ExtensionRef')"
792797
type HTTPRouteFilter struct {
@@ -873,6 +878,15 @@ type HTTPRouteFilter struct {
873878
// +optional
874879
URLRewrite *HTTPURLRewriteFilter `json:"urlRewrite,omitempty"`
875880

881+
// CORS defines a schema for a filter that responds to the
882+
// cross-origin request based on HTTP response header.
883+
//
884+
// Support: Extended
885+
//
886+
// +optional
887+
// <gateway:experimental>
888+
CORS *HTTPCORSFilter `json:"cors,omitempty"`
889+
876890
// ExtensionRef is an optional, implementation-specific extension to the
877891
// "filter" behavior. For example, resource "myroutefilter" in group
878892
// "networking.example.net"). ExtensionRef MUST NOT be used for core and
@@ -935,6 +949,15 @@ const (
935949
// Support in HTTPBackendRef: Extended
936950
HTTPRouteFilterRequestMirror HTTPRouteFilterType = "RequestMirror"
937951

952+
// HTTPRouteFilterCORS can be used to add CORS headers to an
953+
// HTTP response before it is sent to the client.
954+
//
955+
// Support in HTTPRouteRule: Extended
956+
//
957+
// Support in HTTPBackendRef: Extended
958+
// <gateway:experimental>
959+
HTTPRouteFilterCORS HTTPRouteFilterType = "CORS"
960+
938961
// HTTPRouteFilterExtensionRef should be used for configuring custom
939962
// HTTP filters.
940963
//
@@ -1277,6 +1300,220 @@ type HTTPRequestMirrorFilter struct {
12771300
Fraction *Fraction `json:"fraction,omitempty"`
12781301
}
12791302

1303+
// HTTPCORSFilter defines a filter that that configures Cross-Origin Request
1304+
// Sharing (CORS).
1305+
type HTTPCORSFilter struct {
1306+
// AllowOrigins indicates whether the response can be shared with requested
1307+
// resource from the given `Origin`.
1308+
//
1309+
// The `Origin` consists of a scheme and a host, with an optional port, and
1310+
// takes the form `<scheme>://<host>(:<port>)`.
1311+
//
1312+
// Valid values for scheme are: `http` and `https`.
1313+
//
1314+
// Valid values for port are any integer between 1 and 65535 (the list of
1315+
// available TCP/UDP ports). Note that, if not included, port `80` is
1316+
// assumed for `http` scheme origins, and port `443` is assumed for `https`
1317+
// origins. This may affect origin matching.
1318+
//
1319+
// The host part of the origin may contain the wildcard character `*`. These
1320+
// wildcard characters behave as follows:
1321+
//
1322+
// * `*` is a greedy match to the _left_, including any number of
1323+
// DNS labels to the left of its position. This also means that
1324+
// `*` will include any number of period `.` characters to the
1325+
// left of its position.
1326+
// * A wildcard by itself matches all hosts.
1327+
//
1328+
// An origin value that includes _only_ the `*` character indicates requests
1329+
// from all `Origin`s are allowed.
1330+
//
1331+
// When the `AllowOrigins` field is configured with multiple origins, it
1332+
// means the server supports clients from multiple origins. If the request
1333+
// `Origin` matches the configured allowed origins, the gateway must return
1334+
// the given `Origin` and sets value of the header
1335+
// `Access-Control-Allow-Origin` same as the `Origin` header provided by the
1336+
// client.
1337+
//
1338+
// The status code of a successful response to a "preflight" request is
1339+
// always an OK status (i.e., 204 or 200).
1340+
//
1341+
// If the request `Origin` does not match the configured allowed origins,
1342+
// the gateway returns 204/200 response but doesn't set the relevant
1343+
// cross-origin response headers. Alternatively, the gateway responds with
1344+
// 403 status to the "preflight" request is denied, coupled with omitting
1345+
// the CORS headers. The cross-origin request fails on the client side.
1346+
// Therefore, the client doesn't attempt the actual cross-origin request.
1347+
//
1348+
// The `Access-Control-Allow-Origin` response header can only use `*`
1349+
// wildcard as value when the `AllowCredentials` field is unspecified.
1350+
//
1351+
// When the `AllowCredentials` field is specified and `AllowOrigins` field
1352+
// specified with the `*` wildcard, the gateway must return a single origin
1353+
// in the value of the `Access-Control-Allow-Origin` response header,
1354+
// instead of specifying the `*` wildcard. The value of the header
1355+
// `Access-Control-Allow-Origin` is same as the `Origin` header provided by
1356+
// the client.
1357+
//
1358+
// Support: Extended
1359+
// +listType=set
1360+
// +kubebuilder:validation:MaxItems=64
1361+
AllowOrigins []AbsoluteURI `json:"allowOrigins,omitempty"`
1362+
1363+
// AllowCredentials indicates whether the actual cross-origin request allows
1364+
// to include credentials.
1365+
//
1366+
// The only valid value for the `Access-Control-Allow-Credentials` response
1367+
// header is true (case-sensitive).
1368+
//
1369+
// If the credentials are not allowed in cross-origin requests, the gateway
1370+
// will omit the header `Access-Control-Allow-Credentials` entirely rather
1371+
// than setting its value to false.
1372+
//
1373+
// Support: Extended
1374+
//
1375+
// +optional
1376+
AllowCredentials *LowercaseTrue `json:"allowCredentials,omitempty"`
1377+
1378+
// AllowMethods indicates which HTTP methods are supported for accessing the
1379+
// requested resource.
1380+
//
1381+
// Valid values are any method defined by RFC9110, along with the special
1382+
// value `*`, which represents all HTTP methods are allowed.
1383+
//
1384+
// Method names are case sensitive, so these values are also case-sensitive.
1385+
// (See https://www.rfc-editor.org/rfc/rfc2616#section-5.1.1)
1386+
//
1387+
// Multiple method names in the value of the `Access-Control-Allow-Methods`
1388+
// response header are separated by a comma (",").
1389+
//
1390+
// A CORS-safelisted method is a method that is `GET`, `HEAD`, or `POST`.
1391+
// (See https://fetch.spec.whatwg.org/#cors-safelisted-method) The
1392+
// CORS-safelisted methods are always allowed, regardless of whether they
1393+
// are specified in the `AllowMethods` field.
1394+
//
1395+
// When the `AllowMethods` field is configured with one or more methods, the
1396+
// gateway must return the `Access-Control-Allow-Methods` response header
1397+
// which value is present in the `AllowMethods` field.
1398+
//
1399+
// If the HTTP method of the `Access-Control-Request-Method` request header
1400+
// is not included in the list of methods specified by the response header
1401+
// `Access-Control-Allow-Methods`, it will present an error on the client
1402+
// side.
1403+
//
1404+
// The `Access-Control-Allow-Methods` response header can only use `*`
1405+
// wildcard as value when the `AllowCredentials` field is unspecified.
1406+
//
1407+
// When the `AllowCredentials` field is specified and `AllowMethods` field
1408+
// specified with the `*` wildcard, the gateway must specify one HTTP method
1409+
// in the value of the Access-Control-Allow-Methods response header. The
1410+
// value of the header `Access-Control-Allow-Methods` is same as the
1411+
// `Access-Control-Request-Method` header provided by the client. If the
1412+
// header `Access-Control-Request-Method` is not included in the request,
1413+
// the gateway will omit the `Access-Control-Allow-Methods` response header,
1414+
// instead of specifying the `*` wildcard. A Gateway implementation may
1415+
// choose to add implementation-specific default methods.
1416+
//
1417+
// Support: Extended
1418+
//
1419+
// +listType=set
1420+
// +kubebuilder:validation:MaxItems=9
1421+
AllowMethods []HTTPMethodWithWildcard `json:"allowMethods,omitempty"`
1422+
1423+
// AllowHeaders indicates which HTTP request headers are supported for
1424+
// accessing the requested resource.
1425+
//
1426+
// Header names are not case sensitive.
1427+
//
1428+
// Multiple header names in the value of the `Access-Control-Allow-Headers`
1429+
// response header are separated by a comma (",").
1430+
//
1431+
// When the `AllowHeaders` field is configured with one or more headers, the
1432+
// gateway must return the `Access-Control-Allow-Headers` response header
1433+
// which value is present in the `AllowHeaders` field.
1434+
//
1435+
// If any header name in the `Access-Control-Request-Headers` request header
1436+
// is not included in the list of header names specified by the response
1437+
// header `Access-Control-Allow-Headers`, it will present an error on the
1438+
// client side.
1439+
//
1440+
// If any header name in the `Access-Control-Allow-Headers` response header
1441+
// does not recognize by the client, it will also occur an error on the
1442+
// client side.
1443+
//
1444+
// A wildcard indicates that the requests with all HTTP headers are allowed.
1445+
// The `Access-Control-Allow-Headers` response header can only use `*`
1446+
// wildcard as value when the `AllowCredentials` field is unspecified.
1447+
//
1448+
// When the `AllowCredentials` field is specified and `AllowHeaders` field
1449+
// specified with the `*` wildcard, the gateway must specify one or more
1450+
// HTTP headers in the value of the `Access-Control-Allow-Headers` response
1451+
// header. The value of the header `Access-Control-Allow-Headers` is same as
1452+
// the `Access-Control-Request-Headers` header provided by the client. If
1453+
// the header `Access-Control-Request-Headers` is not included in the
1454+
// request, the gateway will omit the `Access-Control-Allow-Headers`
1455+
// response header, instead of specifying the `*` wildcard. A Gateway
1456+
// implementation may choose to add implementation-specific default headers.
1457+
//
1458+
// Support: Extended
1459+
//
1460+
// +listType=set
1461+
// +kubebuilder:validation:MaxItems=64
1462+
AllowHeaders []HTTPHeaderName `json:"allowHeaders,omitempty"`
1463+
1464+
// ExposeHeaders indicates which HTTP response headers can be exposed
1465+
// to client-side scripts in response to a cross-origin request.
1466+
//
1467+
// A CORS-safelisted response header is an HTTP header in a CORS response
1468+
// that it is considered safe to expose to the client scripts.
1469+
// The CORS-safelisted response headers include the following headers:
1470+
// `Cache-Control`
1471+
// `Content-Language`
1472+
// `Content-Length`
1473+
// `Content-Type`
1474+
// `Expires`
1475+
// `Last-Modified`
1476+
// `Pragma`
1477+
// (See https://fetch.spec.whatwg.org/#cors-safelisted-response-header-name)
1478+
// The CORS-safelisted response headers are exposed to client by default.
1479+
//
1480+
// When an HTTP header name is specified using the `ExposeHeaders` field,
1481+
// this additional header will be exposed as part of the response to the
1482+
// client.
1483+
//
1484+
// Header names are not case sensitive.
1485+
//
1486+
// Multiple header names in the value of the `Access-Control-Expose-Headers`
1487+
// response header are separated by a comma (",").
1488+
//
1489+
// A wildcard indicates that the responses with all HTTP headers are exposed
1490+
// to clients. The `Access-Control-Expose-Headers` response header can only
1491+
// use `*` wildcard as value when the `AllowCredentials` field is
1492+
// unspecified.
1493+
//
1494+
// Support: Extended
1495+
//
1496+
// +optional
1497+
// +listType=set
1498+
// +kubebuilder:validation:MaxItems=64
1499+
ExposeHeaders []HTTPHeaderName `json:"exposeHeaders,omitempty"`
1500+
1501+
// MaxAge indicates the duration (in seconds) for the client to cache the
1502+
// results of a "preflight" request.
1503+
//
1504+
// The information provided by the `Access-Control-Allow-Methods` and
1505+
// `Access-Control-Allow-Headers` response headers can be cached by the
1506+
// client until the time specified by `Access-Control-Max-Age` elapses.
1507+
//
1508+
// The default value of `Access-Control-Max-Age` response header is 5
1509+
// (seconds).
1510+
//
1511+
// +optional
1512+
// +kubebuilder:default=5
1513+
// +kubebuilder:validation:Minimum=1
1514+
MaxAge int32 `json:"maxAge,omitempty"`
1515+
}
1516+
12801517
// HTTPBackendRef defines how a HTTPRoute forwards a HTTP request.
12811518
//
12821519
// Note that when a namespace different than the local namespace is specified, a

apis/v1/shared_types.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -764,6 +764,12 @@ type HeaderName string
764764
// +kubebuilder:validation:Pattern=`^([0-9]{1,5}(h|m|s|ms)){1,4}$`
765765
type Duration string
766766

767+
// LowercaseTrue is a string value that can only be set to "true" (case
768+
// sensitive).
769+
//
770+
// +kubebuilder:validation:Enum=true
771+
type LowercaseTrue string
772+
767773
const (
768774
// A textual representation of a numeric IP address. IPv4
769775
// addresses must be in dotted-decimal form. IPv6 addresses

apis/v1/zz_generated.deepcopy.go

Lines changed: 45 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)