I have created following middleware for API endpoint
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: cors-api
namespace: api-staging
spec:
headers:
accessControlAllowMethods:
- "GET"
- "OPTIONS"
- "PUT"
- "POST"
- "DELETE"
accessControlAllowHeaders:
- "*"
accessControlAllowOriginList:
- "https://*.example.com"
accessControlMaxAge: 100
addVaryHeader: true
& attached it to IngressRoute
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: api-external-0
namespace: api-staging
spec:
entryPoints:
- web
- websecure
routes:
- kind: Rule
match: Host(`api.staging.example.com`)
services:
- name: nginx
port: 80
strategy: RoundRobin
sticky:
cookie:
httpOnly: true
middlewares:
- name: cors-api
namespace: api-staging
tls:
secretName: staging-cert
But following request is going through
% curl -v --request OPTIONS 'https://api.staging.example.com' -H 'Origin: http://fake.origin.com' -H 'Access-Control-Request-Method: GET'
* Trying x.x.x.x:443...
* Connected to api.staging.example.com (x.x.x.x) port 443
* ALPN: curl offers h2,http/1.1
* (304) (OUT), TLS handshake, Client hello (1):
* CAfile: /etc/ssl/cert.pem
* CApath: none
* (304) (IN), TLS handshake, Server hello (2):
* (304) (IN), TLS handshake, Unknown (8):
* (304) (IN), TLS handshake, Certificate (11):
* (304) (IN), TLS handshake, CERT verify (15):
* (304) (IN), TLS handshake, Finished (20):
* (304) (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / AEAD-AES128-GCM-SHA256
* ALPN: server accepted h2
* Server certificate:
* subject: CN=*.staging.example.com
* start date: Jan 11 02:15:45 2024 GMT
* expire date: Apr 10 02:15:44 2024 GMT
* subjectAltName: host "api.staging.example.com" matched cert's "*.staging.example.com"
* issuer: C=US; O=Let's Encrypt; CN=R3
* SSL certificate verify ok.
* using HTTP/2
* [HTTP/2] [1] OPENED stream for https://api.staging.example.com/
* [HTTP/2] [1] [:method: OPTIONS]
* [HTTP/2] [1] [:scheme: https]
* [HTTP/2] [1] [:authority: api.staging.example.com]
* [HTTP/2] [1] [:path: /]
* [HTTP/2] [1] [user-agent: curl/8.4.0]
* [HTTP/2] [1] [accept: */*]
* [HTTP/2] [1] [origin: http://fake.origin.com]
* [HTTP/2] [1] [access-control-request-method: GET]
> OPTIONS / HTTP/2
> Host: api.staging.example.com
> User-Agent: curl/8.4.0
> Accept: */*
> Origin: http://fake.origin.com
> Access-Control-Request-Method: GET
>
< HTTP/2 200
< access-control-allow-headers: *
< access-control-allow-methods: GET,OPTIONS,PUT,POST,DELETE
< access-control-max-age: 100
< content-length: 0
< date: Mon, 19 Feb 2024 17:54:27 GMT
<
* Connection #0 to host api.staging.example.com left intact
I also tried accessControlAllowOriginListRegex
still no luck
spec:
headers:
accessControlAllowMethods:
- "GET"
- "OPTIONS"
- "PUT"
- "POST"
- "DELETE"
accessControlAllowHeaders:
- "*"
accessControlAllowOriginListRegex:
- "(.*?)\.example\.com"
accessControlMaxAge: 100
addVaryHeader: true
Any thoughts on what is happening here ?
2
Answers
Never used Traefik, but I googled
accessControlAllowOriginList
and the documentation strongly suggests that the asterisk is only allowed by itself to match any origin, but not in the middle of a origin.It also appears a second
accessControlAllowOriginListRegex
setting is available to set up patterns.Traefik documentation is notoriously vague on how to actually use the configuration options. Luckily, we can learn something from its source code.
In these unit tests there are some examples of accessControlAllowOriginListRegex usage, and according to them your regex should be formatted like this:
these are other examples of valid regex:
From a quick glance at the source code instead it’s clear that wildcards are not supported in
accessControlAllowOriginList