Redirects specify how URLs may need to be rewritten. Each Redirect has a name, a regex that matches the requested URL, a to indicating how the url should be rewritten, and a flag to indicate how the redirect will be handled by the proxying layer.
nameCommon name for this redirect, e.g. "force-https".
fromRegex pattern to match against incoming request URLs. Capture groups set here can be used in the field.
toNew URL of the redirect. Can be direct string (") or reference capture groups from the field ("").
redirect_typeOne of "permanent" or "temporary". Selection "permanent" will set the response code to 301, "temporary" will be 302.
header_constraintsArray of that must match for the redirect to take effect.
{
"name": "force-https",
"from": "(.*)",
"to": "https://$1",
"redirect_type": "permanent"
}Grey Matter supports the configuration of cross-origin resource sharing on a sidecar. CORS can be configured to allow an application to access resources at a different origin (domain, protocol, or port) than its own.
For more information on CORS, see this CORS reference.
Simple requests are classified as requests that don't require a . This distinction is made between requests that might be dangerous (i.e. modifies server resources) and those that are most likely benign. A request is considered simple when all of the following criteria is true:
The method is GET, HEAD, or POST
Only are present
The Content Type header is set to one of application/x-www-form-urlencoded
A more comprehensive list and explanation can be found .
As an example, say an app running at http://localhost:8080 is trying to call a backend service with a Grey Matter sidecar at http://localhost:10808. Without a CORS configuration, this request would fail, because the app localhost:8080 is trying to access resources from a server at a different origin, localhost:10808. To solve this, the following CORS config is set on its domain:
With this configuration, if a simple request comes in to the sidecar from the app, it will have an Origin header value of http://localhost:8080, and this request will succeed. The server will attach a header Access-Control-Allow-Origin: http://localhost:8080 to the response, which signals to the browser that this request is allowed.
are initiated by the browser using the OPTIONS HTTP method before sending a request in order to determine if the real request is safe to send. The response to this kind of request contains information about what is allowed from a request, and the server determines whether or not to send the actual request based on this information.
This response information is in the form of three HTTP headers, access-control-request-method, access-control-request-headers, and the origin header. These correspond to of the cors_config - thus these configurations can be specified to determine how the Grey Matter sidecar will respond to preflight requests. If a preflight request comes in to the Grey Matter Sidecar that does not meet the specification for one of these configured fields, the sidecar will send back a response to not initiate the request.
Based on the same , say the app running at http://localhost:8080 wants to send requests to the backend service at http://localhost:10808 with a content-type of application/json;charset=UTF-8. This particular content-type is outside of those allowed by CORS for simple requests, and thus would result in sending a preflight request to determine if the request can be sent. In order for the CORS configuration to indicate that the request can be sent, it would need to allow the content-type header by configuring the field:
In the above configuration, CORS will allow requests with Origin header value http://localhost:8080 only and indicate that the content-type header can be set according to the request.
To set up CORS, set the cors_config field on a domain object with the desired configuration, see the below.
For an existing domain, run
and add the desired cors_config object.
allowed_originsThis field specifies an array of string patterns that match allowed origins. The proxy will use these matchers to set the header. This header will be set on any cross-origin response that matches one of the allowed_origins.
Available matchers include:
exact
prefix
suffix
Example:
A wildcard value * is allowed except when using the regex matcher.
allow_credentialsSpecifies the content for the header that the proxy will set on any cross-origin request that matches one of the allowed_origins. This header specifies whether or not the upstream service allows credentials.
exposed_headersSpecifies the content for the header that the proxy will set on any cross-origin request that matches one of the allowed_origins. This header specifies an array of headers that are allowed on the response.
max_ageSpecifies the content for the header that the proxy will set on the preflight response. This header is an integer value specifying how long a preflight request can be cached by the browser.
allowed_methodsSpecifies the content for the header that the proxy will set on the preflight response. This header specifies an array of methods allowed by the upstream service.
allowed_headersSpecifies the content for the header that the proxy will set on the preflight response. This header specifies an array of headers allowed by the upstream service.
By default, the proxy will use the upstream service's CORS policy on the gateway and on the upstream service. The gateway policy is ignored.
Because CORS is a browser construct, curl can always make a request to the server, with or without CORS. However, it can be used to mimic a browser and verify how the proxy will react to CORS requests:
multipart/form-datatext/plainregex{
"zone_key": "zone-default-zone",
"domain_key": "domain-backend-service",
"name": "*",
"port": 10808,
"cors_config": {
"allowed_origins": [
{ "match_type": "exact", "value": "http://localhost:8080" }
],
"allowed_headers": [],
"allowed_methods": [],
"exposed_headers": [],
"max_age": 60
}
}{
"zone_key": "zone-default-zone",
"domain_key": "domain-backend-service",
"name": "*",
"port": 10808,
"cors_config": {
"allowed_origins": [
{ "match_type": "exact", "value": "http://localhost:8080" }
],
"allowed_headers": ["content-type"],
"allowed_methods": [],
"exposed_headers": [],
"max_age": 60
}
}greymatter edit domain <domain-name> "cors_config": {
"allowed_origins": [],
"allowed_headers": [],
"allowed_methods": [],
"exposed_headers": [],
"max_age": 0,
"allow_credentials": true
} "allowed_origins": [
{ "match_type": "exact", "value": "http://localhost:8080" }
]$ curl -v 'http://localhost:9080/services/catalog/latest/' \
-X OPTIONS \
-H 'Access-Control-Request-Method: POST' \
-H 'Access-Control-Request-Headers: content-type' \
-H 'Origin: http://localhost:8080'
* Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 9080 (#0)
> OPTIONS /services/catalog/latest/ HTTP/1.1
> Host: localhost:9080
> User-Agent: curl/7.64.1
> Accept: */*
> Access-Control-Request-Method: POST
> Access-Control-Request-Headers: content-type
> Origin: http://localhost:8080
>
< HTTP/1.1 200 OK
< access-control-allow-origin: http://localhost:8080
< access-control-max-age: 60
< date: Tue, 12 May 2020 20:11:13 GMT
< server: envoy
< content-length: 0
<
* Connection #0 to host localhost left intact
* Closing connection 0cipher_filter. If specified, only the listed ciphers will be accepted. Only valid with TLSv1-TLSv1.2, but has no affect with TLSv1.3.
Examples include the values below, but full options should be found in the link above.
[ECDHE-ECDSA-AES128-GCM-SHA256|ECDHE-ECDSA-CHACHA20-POLY1305]
[ECDHE-RSA-AES128-GCM-SHA256|ECDHE-RSA-CHACHA20-POLY1305]
ECDHE-ECDSA-AES128-SHA
ECDHE-RSA-AES128-SHA
protocolsArray of SSL protocols to accept: "TLSv1, TLSv1.1, TLSv1.2, TLSv1.3"
cert_key_pairsArray of (cert, key) pairs to use when receiving requests on this . Each cert or key must point to files on disk.
require_client_certsIf true, client cert verification will be performed. false will disable this check and not require client certificates to be presented when connecting to this listener.
trust_fileString representing the path on disk to the SSL trust file to use when receiving requests on this . If omitted, then no trust verification will be performed.
sniString representing how this listener will identify itself during SSL SNI.
{
"cipher_filter": "",
"protocols": [
"TLSv1.1",
"TLSv1.2"
],
"cert_key_pairs": [
{
"certificate_path": "/etc/proxy/tls/sidecar/server.crt",
"key_path": "/etc/proxy/tls/sidecar/server.key"
}
],
"require_client_certs": true,
"trust_file": "/etc/proxy/tls/sidecar/ca.crt",
"sni": null
}AES128-GCM-SHA256
AES128-SHA
ECDHE-ECDSA-AES256-GCM-SHA384
ECDHE-RSA-AES256-GCM-SHA384
ECDHE-ECDSA-AES256-SHA
ECDHE-RSA-AES256-SHA
AES256-GCM-SHA384
AES256-SHA
Each domain controls requests for a specific host:port. This permits different handling of requests to domains like localhost:8080 or catalog:8080 if desired. If uniform handling is required, wildcards are understood to apply to all domains. A domain set to match *:8080 will match both of the above domains.
NOTEThe domain port should, in most cases, match the port of the exposed on the proxy. If they do not match, users will need to supply HOST: header keywords to all requests to match the virtual domain.
Virtual host:port matching and redirecting
GZIP of requests
CORS
Setting custom headers for downstream requests
NOTE Do not set an ssl_config on any domain object whose service you want to use SPIFFE/SPIRE. If a domain ssl_config is set, it will override the secret set on the corresponding listener and the mesh configuration will be wrong.
The domain object has an optional ssl_config field, which can be used to set up TLS and specify it's configuration. The Domain SSL Config Object appears as follows:
The Domain SSL Configuration is used to populate a for the Envoy Listener.
The sni field for a domain accepts a list of strings and configures the Envoy Listener to detect the requested Server Name Indication.
To specify a minimum and maximum TLS protocol version, set the protocols field to one of the following: "TLSv1_0", "TLSv1_1", "TLSv1_2", "TLSv1_3". If one protocol is specified, it will be set as both the minimum and maximum protocol versions in Envoy. If more than one protocol version is specified in the list, the lowest will set the minimum TLS protocol version and the highest will set the maximum TLS protocol version. If this field is left empty, Envoy will choose the default TLS version.
The cipher_filter field takes a colon : delimited string to populate the cipher_suites cipher list in envoy for TLS.
redirectsThis field can be used to configure redirect routes for the domain. See for details.
Fields:
name
the name of the redirect
from
domain_keyA unique key used to identify this particular domain configuration. This key is used in proxy, listener, and route objects.
zone_keyThe zone in which this object will live. It will only be able to be referenced by objects or sent to Sidecars that live in the same zone.
nameThe name of this virtual domain, e.g. localhost, www.greymatter.io, or catalog.svc.local. Only requests coming in to the named host will be matched and handled by attached . Is used in conjunction with the field.
This field can be set to a wildcard (*) which will match against all hostnames.
portSet the specific port of the virtual host to match. Is used in conjunction with the field.
E.g. port: 8080 and name: * will setup a virtual domain matching any request made to port 8080 regardless of the host.
ssl_config for this cluster. Setting the SSL Config at the domain level set this same config on all that are directly linked to this domain.
redirectsArray of URL
gzip_enabledDEPRECATION: This field has been deprecated and will be removed in the next major version release.
This field has no effect.
cors_configA to attach to this domain.
aliasesAn array of additional hostnames that should be matched in this domain. E.g. name: "www.greymatter.io" with aliases: ["greymatter.io", "localhost"]
force_httpsIf true, listeners attached to this domain will only accept HTTPS connections. In this case, one of the or fields should be set. If false, attached listeners will only accept plaintext HTTP connections.
custom_headersAn array of header key, value pairs to set on all requests that pass through this domain.
E.g.
checksumAn API calculated checksum. Can be used to verify that the API contains the expected object before performing a write.
SSL Config for incoming requests
regex value that the incoming request :path will be regex matched to
to
the new URL that an incoming request matching from will route to
if set to "$host", will redirect to the name of the domain
redirect_type
determines the response code of the redirect
must be one of: "permanent" (for a 301 code), "temporary" (for a 307 code)
header_constraints
a list of header constraint objects
each header constraint has the following fields:
name
the header key to be compared to the incoming requests headers
will be compared without case sensitivity
value
must be a valid regex
the value to be compared to the value of the incoming request header with matching name
case_sensitive
boolean indicating whether the value will be compared to the value of the header with matching name with case sensitivity
invert
boolean value
{
"domain_key": "catalog",
"zone_key": "default",
"name": "*",
"port": 9080,
"ssl_config": {
"cipher_filter": "",
"protocols": [
"TLSv1.1",
"TLSv1.2"
],
"cert_key_pairs": [
{
"certificate_path": "/etc/proxy/tls/sidecar/server.crt",
"key_path": "/etc/proxy/tls/sidecar/server.key"
}
],
"require_client_certs": true,
"trust_file": "/etc/proxy/tls/sidecar/ca.crt",
"sni": null
},
"redirects": null,
"gzip_enabled": false,
"cors_config": null,
"aliases": null,
"force_https": true,
"custom_headers": null,
"checksum": "b633fd4b535932fc1da31fbb7c6d4c39517871d112e9bce2d5ffe004e6d09735"
}"ssl_config": {
"cipher_filter": "",
"protocols": [],
"cert_key_pairs": null,
"require_client_certs": false,
"trust_file": "",
"sni": null
}"custom_headers" : [
{
"key": "x-forwarded-proto",
"value": "https"
}
]nameHeader key to match on. Supports regex expressions.
valueHeader value to match on. Supports regex expressions.
case_sensitiveIf true, then the regex matching will be case sensitive. Defaults to false.
invertIf true, invert the regex match. This allows easier "not" expressions.
For example, to match only X-Forwarded-Proto: "http":
But to match anything NOT "https":
{
"name": "X-Forwarded-Proto",
"value": "http"
}{
"name": "X-Forwarded-Proto",
"value": "http"
}{
"name": "X-Forwarded-Proto",
"value": "https",
"invert": true
}