Merge current v2.6 into master
This commit is contained in:
commit
a79868fadc
22 changed files with 566 additions and 221 deletions
17
CHANGELOG.md
17
CHANGELOG.md
|
@ -1,3 +1,20 @@
|
|||
## [v2.6.1](https://github.com/traefik/traefik/tree/v2.6.1) (2022-02-14)
|
||||
[All Commits](https://github.com/traefik/traefik/compare/v2.6.0...v2.6.1)
|
||||
|
||||
**Bug fixes:**
|
||||
- **[acme]** Add domain to HTTP challenge errors ([#8740](https://github.com/traefik/traefik/pull/8740) by [ldez](https://github.com/ldez))
|
||||
- **[metrics]** Fix metrics bucket key high cardinality ([#8761](https://github.com/traefik/traefik/pull/8761) by [tomMoulard](https://github.com/tomMoulard))
|
||||
- **[middleware,tls]** Use CNAME for SNI check on host header ([#8773](https://github.com/traefik/traefik/pull/8773) by [ldez](https://github.com/ldez))
|
||||
- **[middleware,tracing]** Rename Datadog span tags ([#8323](https://github.com/traefik/traefik/pull/8323) by [luckielordie](https://github.com/luckielordie))
|
||||
- **[tls]** Apply the same approach as the rules system on the TLS configuration choice ([#8764](https://github.com/traefik/traefik/pull/8764) by [ldez](https://github.com/ldez))
|
||||
|
||||
**Documentation:**
|
||||
- **[acme]** Add Hurricane Electric to acme documentation ([#8746](https://github.com/traefik/traefik/pull/8746) by [vladshub](https://github.com/vladshub))
|
||||
- **[acme]** Clarify that ACME challenge is mandatory ([#8739](https://github.com/traefik/traefik/pull/8739) by [mpl](https://github.com/mpl))
|
||||
- **[http3]** Explain a bit more around enabling HTTP3 ([#8731](https://github.com/traefik/traefik/pull/8731) by [SantoDE](https://github.com/SantoDE))
|
||||
- **[metrics]** Fix mixups in metrics documentation ([#8752](https://github.com/traefik/traefik/pull/8752) by [tomMoulard](https://github.com/tomMoulard))
|
||||
- **[middleware,k8s/crd]** Fix Kubernetes TCP examples ([#8759](https://github.com/traefik/traefik/pull/8759) by [sylr](https://github.com/sylr))
|
||||
|
||||
## [v2.6.0](https://github.com/traefik/traefik/tree/v2.6.0) (2022-01-24)
|
||||
[All Commits](https://github.com/traefik/traefik/compare/v2.5.0-rc1...v2.6.0)
|
||||
|
||||
|
|
|
@ -190,7 +190,7 @@ func setupServer(staticConfiguration *static.Configuration) (*server.Server, err
|
|||
|
||||
// Entrypoints
|
||||
|
||||
serverEntryPointsTCP, err := server.NewTCPEntryPoints(staticConfiguration.EntryPoints)
|
||||
serverEntryPointsTCP, err := server.NewTCPEntryPoints(staticConfiguration.EntryPoints, staticConfiguration.HostResolver)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ labels:
|
|||
|
||||
```yaml tab="Kubernetes"
|
||||
apiVersion: traefik.containo.us/v1alpha1
|
||||
kind: Middleware
|
||||
kind: MiddlewareTCP
|
||||
metadata:
|
||||
name: test-inflightconn
|
||||
spec:
|
||||
|
|
|
@ -36,7 +36,7 @@ spec:
|
|||
|
||||
---
|
||||
apiVersion: traefik.containo.us/v1alpha1
|
||||
kind: Middleware
|
||||
kind: MiddlewareTCP
|
||||
metadata:
|
||||
name: foo-ip-whitelist
|
||||
spec:
|
||||
|
@ -47,7 +47,7 @@ spec:
|
|||
|
||||
---
|
||||
apiVersion: traefik.containo.us/v1alpha1
|
||||
kind: IngressRoute
|
||||
kind: IngressRouteTCP
|
||||
metadata:
|
||||
name: ingressroute
|
||||
spec:
|
||||
|
|
|
@ -438,3 +438,17 @@ To enable HTTP/3 on an EntryPoint, please check out the [HTTP/3 configuration](.
|
|||
In `v2.6`, the [Kubernetes Gateway API provider](../providers/kubernetes-gateway.md) now only supports the version [v1alpha2](https://gateway-api.sigs.k8s.io/v1alpha2/guides/getting-started/) of the specification and
|
||||
[route namespaces](https://gateway-api.sigs.k8s.io/v1alpha2/references/spec/#gateway.networking.k8s.io/v1alpha2.RouteNamespaces) selectors, which requires Traefik to fetch and watch the cluster namespaces.
|
||||
Therefore, the [RBAC](../reference/dynamic-configuration/kubernetes-gateway.md#rbac) and [CRD](../reference/dynamic-configuration/kubernetes-gateway.md#definitions) definitions must be updated.
|
||||
|
||||
## v2.6.0 to v2.6.1
|
||||
|
||||
### Metrics
|
||||
|
||||
In `v2.6.1`, the metrics system does not support any more custom HTTP method verbs to prevent potential metrics cardinality overhead.
|
||||
In consequence, for metrics having the method label,
|
||||
if the HTTP method verb of a request is not one defined in the set of common methods for [`HTTP/1.1`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods)
|
||||
or the [`PRI`](https://datatracker.ietf.org/doc/html/rfc7540#section-11.6) verb (for `HTTP/2`),
|
||||
the value for the method label becomes `EXTENSION_METHOD`, instead of the request's one.
|
||||
|
||||
### Tracing
|
||||
|
||||
In `v2.6.1`, the Datadog tags added to a span changed from `service.name` to `traefik.service.name` and from `router.name` to `traefik.router.name`.
|
||||
|
|
|
@ -62,7 +62,7 @@ traefik_config_last_reload_success
|
|||
|
||||
The expiration date of certificates.
|
||||
|
||||
Available labels: `cn`, `sans`, `serial`.
|
||||
[Labels](#labels): `cn`, `sans`, `serial`.
|
||||
|
||||
```dd tab="Datadog"
|
||||
tls.certs.notAfterTimestamp
|
||||
|
@ -94,7 +94,7 @@ traefik_tls_certs_not_after
|
|||
|
||||
The total count of HTTP requests received by an entrypoint.
|
||||
|
||||
Available labels: `code`, `method`, `protocol`, `entrypoint`.
|
||||
[Labels](#labels): `code`, `method`, `protocol`, `entrypoint`.
|
||||
|
||||
```dd tab="Datadog"
|
||||
entrypoint.request.total
|
||||
|
@ -117,7 +117,7 @@ traefik_entrypoint_requests_total
|
|||
|
||||
The total count of HTTPS requests received by an entrypoint.
|
||||
|
||||
Available labels: `tls_version`, `tls_cipher`, `entrypoint`.
|
||||
[Labels](#labels): `tls_version`, `tls_cipher`, `entrypoint`.
|
||||
|
||||
```dd tab="Datadog"
|
||||
entrypoint.request.tls.total
|
||||
|
@ -140,7 +140,7 @@ traefik_entrypoint_requests_tls_total
|
|||
|
||||
Request processing duration histogram on an entrypoint.
|
||||
|
||||
Available labels: `code`, `method`, `protocol`, `entrypoint`.
|
||||
[Labels](#labels): `code`, `method`, `protocol`, `entrypoint`.
|
||||
|
||||
```dd tab="Datadog"
|
||||
entrypoint.request.duration
|
||||
|
@ -163,7 +163,7 @@ traefik_entrypoint_request_duration_seconds
|
|||
|
||||
The current count of open connections on an entrypoint.
|
||||
|
||||
Available labels: `method`, `protocol`, `entrypoint`.
|
||||
[Labels](#labels): `method`, `protocol`, `entrypoint`.
|
||||
|
||||
```dd tab="Datadog"
|
||||
entrypoint.connections.open
|
||||
|
@ -195,7 +195,7 @@ traefik_entrypoint_open_connections
|
|||
|
||||
The total count of HTTP requests handled by a router.
|
||||
|
||||
Available labels: `code`, `method`, `protocol`, `router`, `service`.
|
||||
[Labels](#labels): `code`, `method`, `protocol`, `router`, `service`.
|
||||
|
||||
```dd tab="Datadog"
|
||||
router.request.total
|
||||
|
@ -218,7 +218,7 @@ traefik_router_requests_total
|
|||
|
||||
The total count of HTTPS requests handled by a router.
|
||||
|
||||
Available labels: `tls_version`, `tls_cipher`, `router`, `service`.
|
||||
[Labels](#labels): `tls_version`, `tls_cipher`, `router`, `service`.
|
||||
|
||||
```dd tab="Datadog"
|
||||
router.request.tls.total
|
||||
|
@ -241,7 +241,7 @@ traefik_router_requests_tls_total
|
|||
|
||||
Request processing duration histogram on a router.
|
||||
|
||||
Available labels: `code`, `method`, `protocol`, `router`, `service`.
|
||||
[Labels](#labels): `code`, `method`, `protocol`, `router`, `service`.
|
||||
|
||||
```dd tab="Datadog"
|
||||
router.request.duration
|
||||
|
@ -264,7 +264,7 @@ traefik_router_request_duration_seconds
|
|||
|
||||
The current count of open connections on a router.
|
||||
|
||||
Available labels: `method`, `protocol`, `router`, `service`.
|
||||
[Labels](#labels): `method`, `protocol`, `router`, `service`.
|
||||
|
||||
```dd tab="Datadog"
|
||||
router.connections.open
|
||||
|
@ -298,7 +298,7 @@ traefik_router_open_connections
|
|||
|
||||
The total count of HTTP requests processed on a service.
|
||||
|
||||
Available labels: `code`, `method`, `protocol`, `service`.
|
||||
[Labels](#labels): `code`, `method`, `protocol`, `service`.
|
||||
|
||||
```dd tab="Datadog"
|
||||
service.request.total
|
||||
|
@ -321,7 +321,7 @@ traefik_service_requests_total
|
|||
|
||||
The total count of HTTPS requests processed on a service.
|
||||
|
||||
Available labels: `tls_version`, `tls_cipher`, `service`.
|
||||
[Labels](#labels): `tls_version`, `tls_cipher`, `service`.
|
||||
|
||||
```dd tab="Datadog"
|
||||
router.service.tls.total
|
||||
|
@ -344,7 +344,7 @@ traefik_service_requests_tls_total
|
|||
|
||||
Request processing duration histogram on a service.
|
||||
|
||||
Available labels: `code`, `method`, `protocol`, `service`.
|
||||
[Labels](#labels): `code`, `method`, `protocol`, `service`.
|
||||
|
||||
```dd tab="Datadog"
|
||||
service.request.duration
|
||||
|
@ -367,7 +367,7 @@ traefik_service_request_duration_seconds
|
|||
|
||||
The current count of open connections on a service.
|
||||
|
||||
Available labels: `method`, `protocol`, `service`.
|
||||
[Labels](#labels): `method`, `protocol`, `service`.
|
||||
|
||||
```dd tab="Datadog"
|
||||
service.connections.open
|
||||
|
@ -390,7 +390,7 @@ traefik_service_open_connections
|
|||
|
||||
The count of requests retries on a service.
|
||||
|
||||
Available labels: `service`.
|
||||
[Labels](#labels): `service`.
|
||||
|
||||
```dd tab="Datadog"
|
||||
service.retries.total
|
||||
|
@ -413,7 +413,7 @@ traefik_service_retries_total
|
|||
|
||||
Current service's server status, described by a gauge with a value of 0 for a down server or a value of 1 for an up server.
|
||||
|
||||
Available labels: `service`, `url`.
|
||||
[Labels](#labels): `service`, `url`.
|
||||
|
||||
```dd tab="Datadog"
|
||||
service.server.up
|
||||
|
@ -431,3 +431,28 @@ traefik_service_server_up
|
|||
# Default prefix: "traefik"
|
||||
{prefix}.service.server.up
|
||||
```
|
||||
|
||||
## Labels
|
||||
|
||||
Here is a comprehensive list of labels that are provided by the metrics:
|
||||
|
||||
| Label | Description | example |
|
||||
|---------------|---------------------------------------|----------------------------|
|
||||
| `cn` | Certificate Common Name | "example.com" |
|
||||
| `code` | Request code | "200" |
|
||||
| `entrypoint` | Entrypoint that handled the request | "example_entrypoint" |
|
||||
| `method` | Request Method | "GET" |
|
||||
| `protocol` | Request protocol | "http" |
|
||||
| `router` | Router that handled the request | "example_router" |
|
||||
| `sans` | Certificate Subject Alternative NameS | "example.com" |
|
||||
| `serial` | Certificate Serial Number | "123..." |
|
||||
| `service` | Service that handled the request | "example_service@provider" |
|
||||
| `tls_cipher` | TLS cipher used for the request | "TLS_FALLBACK_SCSV" |
|
||||
| `tls_version` | TLS version used for the request | "1.0" |
|
||||
| `url` | Service server url | "http://example.com" |
|
||||
|
||||
!!! info "`method` label value"
|
||||
|
||||
If the HTTP method verb on a request is not one defined in the set of common methods for [`HTTP/1.1`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods)
|
||||
or the [`PRI`](https://datatracker.ietf.org/doc/html/rfc7540#section-11.6) verb (for `HTTP/2`),
|
||||
then the value for the method label becomes `EXTENSION_METHOD`.
|
||||
|
|
|
@ -9,18 +9,24 @@
|
|||
# Use certificate in net/internal/testcert.go
|
||||
rootCAs = [ """
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIICEzCCAXygAwIBAgIQMIMChMLGrR+QvmQvpwAU6zANBgkqhkiG9w0BAQsFADAS
|
||||
MIIDOTCCAiGgAwIBAgIQSRJrEpBGFc7tNb1fb5pKFzANBgkqhkiG9w0BAQsFADAS
|
||||
MRAwDgYDVQQKEwdBY21lIENvMCAXDTcwMDEwMTAwMDAwMFoYDzIwODQwMTI5MTYw
|
||||
MDAwWjASMRAwDgYDVQQKEwdBY21lIENvMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB
|
||||
iQKBgQDuLnQAI3mDgey3VBzWnB2L39JUU4txjeVE6myuDqkM/uGlfjb9SjY1bIw4
|
||||
iA5sBBZzHi3z0h1YV8QPuxEbi4nW91IJm2gsvvZhIrCHS3l6afab4pZBl2+XsDul
|
||||
rKBxKKtD1rGxlG4LjncdabFn9gvLZad2bSysqz/qTAUStTvqJQIDAQABo2gwZjAO
|
||||
BgNVHQ8BAf8EBAMCAqQwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDwYDVR0TAQH/BAUw
|
||||
AwEB/zAuBgNVHREEJzAlggtleGFtcGxlLmNvbYcEfwAAAYcQAAAAAAAAAAAAAAAA
|
||||
AAAAATANBgkqhkiG9w0BAQsFAAOBgQCEcetwO59EWk7WiJsG4x8SY+UIAA+flUI9
|
||||
tyC4lNhbcF2Idq9greZwbYCqTTTr2XiRNSMLCOjKyI7ukPoPjo16ocHj+P3vZGfs
|
||||
h1fIw3cSS2OolhloGw/XM6RWPWtPAlGykKLciQrBru5NAPvCMsb/I1DAceTiotQM
|
||||
fblo6RBxUQ==
|
||||
MDAwWjASMRAwDgYDVQQKEwdBY21lIENvMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
|
||||
MIIBCgKCAQEA6Gba5tHV1dAKouAaXO3/ebDUU4rvwCUg/CNaJ2PT5xLD4N1Vcb8r
|
||||
bFSW2HXKq+MPfVdwIKR/1DczEoAGf/JWQTW7EgzlXrCd3rlajEX2D73faWJekD0U
|
||||
aUgz5vtrTXZ90BQL7WvRICd7FlEZ6FPOcPlumiyNmzUqtwGhO+9ad1W5BqJaRI6P
|
||||
YfouNkwR6Na4TzSj5BrqUfP0FwDizKSJ0XXmh8g8G9mtwxOSN3Ru1QFc61Xyeluk
|
||||
POGKBV/q6RBNklTNe0gI8usUMlYyoC7ytppNMW7X2vodAelSu25jgx2anj9fDVZu
|
||||
h7AXF5+4nJS4AAt0n1lNY7nGSsdZas8PbQIDAQABo4GIMIGFMA4GA1UdDwEB/wQE
|
||||
AwICpDATBgNVHSUEDDAKBggrBgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud
|
||||
DgQWBBStsdjh3/JCXXYlQryOrL4Sh7BW5TAuBgNVHREEJzAlggtleGFtcGxlLmNv
|
||||
bYcEfwAAAYcQAAAAAAAAAAAAAAAAAAAAATANBgkqhkiG9w0BAQsFAAOCAQEAxWGI
|
||||
5NhpF3nwwy/4yB4i/CwwSpLrWUa70NyhvprUBC50PxiXav1TeDzwzLx/o5HyNwsv
|
||||
cxv3HdkLW59i/0SlJSrNnWdfZ19oTcS+6PtLoVyISgtyN6DpkKpdG1cOkW3Cy2P2
|
||||
+tK/tKHRP1Y/Ra0RiDpOAmqn0gCOFGz8+lqDIor/T7MTpibL3IxqWfPrvfVRHL3B
|
||||
grw/ZQTTIVjjh4JBSW3WyWgNo/ikC1lrVxzl4iPUGptxT36Cr7Zk2Bsg0XqwbOvK
|
||||
5d+NTDREkSnUbie4GeutujmX3Dsx88UiV6UY/4lHJa6I5leHUNOHahRbpbWeOfs/
|
||||
WkBKOclmOV2xlTVuPw==
|
||||
-----END CERTIFICATE-----
|
||||
"""]
|
||||
|
||||
|
|
|
@ -1,14 +1,20 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIICEzCCAXygAwIBAgIQMIMChMLGrR+QvmQvpwAU6zANBgkqhkiG9w0BAQsFADAS
|
||||
MIIDOTCCAiGgAwIBAgIQSRJrEpBGFc7tNb1fb5pKFzANBgkqhkiG9w0BAQsFADAS
|
||||
MRAwDgYDVQQKEwdBY21lIENvMCAXDTcwMDEwMTAwMDAwMFoYDzIwODQwMTI5MTYw
|
||||
MDAwWjASMRAwDgYDVQQKEwdBY21lIENvMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB
|
||||
iQKBgQDuLnQAI3mDgey3VBzWnB2L39JUU4txjeVE6myuDqkM/uGlfjb9SjY1bIw4
|
||||
iA5sBBZzHi3z0h1YV8QPuxEbi4nW91IJm2gsvvZhIrCHS3l6afab4pZBl2+XsDul
|
||||
rKBxKKtD1rGxlG4LjncdabFn9gvLZad2bSysqz/qTAUStTvqJQIDAQABo2gwZjAO
|
||||
BgNVHQ8BAf8EBAMCAqQwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDwYDVR0TAQH/BAUw
|
||||
AwEB/zAuBgNVHREEJzAlggtleGFtcGxlLmNvbYcEfwAAAYcQAAAAAAAAAAAAAAAA
|
||||
AAAAATANBgkqhkiG9w0BAQsFAAOBgQCEcetwO59EWk7WiJsG4x8SY+UIAA+flUI9
|
||||
tyC4lNhbcF2Idq9greZwbYCqTTTr2XiRNSMLCOjKyI7ukPoPjo16ocHj+P3vZGfs
|
||||
h1fIw3cSS2OolhloGw/XM6RWPWtPAlGykKLciQrBru5NAPvCMsb/I1DAceTiotQM
|
||||
fblo6RBxUQ==
|
||||
MDAwWjASMRAwDgYDVQQKEwdBY21lIENvMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
|
||||
MIIBCgKCAQEA6Gba5tHV1dAKouAaXO3/ebDUU4rvwCUg/CNaJ2PT5xLD4N1Vcb8r
|
||||
bFSW2HXKq+MPfVdwIKR/1DczEoAGf/JWQTW7EgzlXrCd3rlajEX2D73faWJekD0U
|
||||
aUgz5vtrTXZ90BQL7WvRICd7FlEZ6FPOcPlumiyNmzUqtwGhO+9ad1W5BqJaRI6P
|
||||
YfouNkwR6Na4TzSj5BrqUfP0FwDizKSJ0XXmh8g8G9mtwxOSN3Ru1QFc61Xyeluk
|
||||
POGKBV/q6RBNklTNe0gI8usUMlYyoC7ytppNMW7X2vodAelSu25jgx2anj9fDVZu
|
||||
h7AXF5+4nJS4AAt0n1lNY7nGSsdZas8PbQIDAQABo4GIMIGFMA4GA1UdDwEB/wQE
|
||||
AwICpDATBgNVHSUEDDAKBggrBgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud
|
||||
DgQWBBStsdjh3/JCXXYlQryOrL4Sh7BW5TAuBgNVHREEJzAlggtleGFtcGxlLmNv
|
||||
bYcEfwAAAYcQAAAAAAAAAAAAAAAAAAAAATANBgkqhkiG9w0BAQsFAAOCAQEAxWGI
|
||||
5NhpF3nwwy/4yB4i/CwwSpLrWUa70NyhvprUBC50PxiXav1TeDzwzLx/o5HyNwsv
|
||||
cxv3HdkLW59i/0SlJSrNnWdfZ19oTcS+6PtLoVyISgtyN6DpkKpdG1cOkW3Cy2P2
|
||||
+tK/tKHRP1Y/Ra0RiDpOAmqn0gCOFGz8+lqDIor/T7MTpibL3IxqWfPrvfVRHL3B
|
||||
grw/ZQTTIVjjh4JBSW3WyWgNo/ikC1lrVxzl4iPUGptxT36Cr7Zk2Bsg0XqwbOvK
|
||||
5d+NTDREkSnUbie4GeutujmX3Dsx88UiV6UY/4lHJa6I5leHUNOHahRbpbWeOfs/
|
||||
WkBKOclmOV2xlTVuPw==
|
||||
-----END CERTIFICATE-----
|
||||
|
|
|
@ -159,12 +159,27 @@ func containsHeader(req *http.Request, name, value string) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
// getMethod returns the request's method.
|
||||
// It checks whether the method is a valid UTF-8 string.
|
||||
// To restrict the (potentially infinite) number of accepted values for the method,
|
||||
// and avoid unbounded memory issues,
|
||||
// values that are not part of the set of HTTP verbs are replaced with EXTENSION_METHOD.
|
||||
// See https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods
|
||||
// https://datatracker.ietf.org/doc/html/rfc2616/#section-5.1.1.
|
||||
func getMethod(r *http.Request) string {
|
||||
if !utf8.ValidString(r.Method) {
|
||||
log.Warnf("Invalid HTTP method encoding: %s", r.Method)
|
||||
log.WithoutContext().Warnf("Invalid HTTP method encoding: %s", r.Method)
|
||||
return "NON_UTF8_HTTP_METHOD"
|
||||
}
|
||||
return r.Method
|
||||
|
||||
switch r.Method {
|
||||
case "HEAD", "GET", "POST", "PUT", "DELETE", "CONNECT", "OPTIONS", "TRACE", // https://datatracker.ietf.org/doc/html/rfc7231#section-4
|
||||
"PATCH", // https://datatracker.ietf.org/doc/html/rfc5789#section-2
|
||||
"PRI": // https://datatracker.ietf.org/doc/html/rfc7540#section-11.6
|
||||
return r.Method
|
||||
default:
|
||||
return "EXTENSION_METHOD"
|
||||
}
|
||||
}
|
||||
|
||||
type retryMetrics interface {
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"net/http"
|
||||
"net/http/httptest"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/go-kit/kit/metrics"
|
||||
|
@ -98,3 +99,33 @@ func TestCloseNotifier(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_getMethod(t *testing.T) {
|
||||
testCases := []struct {
|
||||
method string
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
method: http.MethodGet,
|
||||
expected: http.MethodGet,
|
||||
},
|
||||
{
|
||||
method: strings.ToLower(http.MethodGet),
|
||||
expected: "EXTENSION_METHOD",
|
||||
},
|
||||
{
|
||||
method: "THIS_IS_NOT_A_VALID_METHOD",
|
||||
expected: "EXTENSION_METHOD",
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.method, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
request := httptest.NewRequest(test.method, "http://example.com", nil)
|
||||
assert.Equal(t, test.expected, getMethod(request))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
107
pkg/middlewares/snicheck/snicheck.go
Normal file
107
pkg/middlewares/snicheck/snicheck.go
Normal file
|
@ -0,0 +1,107 @@
|
|||
package snicheck
|
||||
|
||||
import (
|
||||
"net"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/traefik/traefik/v2/pkg/log"
|
||||
"github.com/traefik/traefik/v2/pkg/middlewares/requestdecorator"
|
||||
traefiktls "github.com/traefik/traefik/v2/pkg/tls"
|
||||
)
|
||||
|
||||
// SNICheck is an HTTP handler that checks whether the TLS configuration for the server name is the same as for the host header.
|
||||
type SNICheck struct {
|
||||
next http.Handler
|
||||
tlsOptionsForHost map[string]string
|
||||
}
|
||||
|
||||
// New creates a new SNICheck.
|
||||
func New(tlsOptionsForHost map[string]string, next http.Handler) *SNICheck {
|
||||
return &SNICheck{next: next, tlsOptionsForHost: tlsOptionsForHost}
|
||||
}
|
||||
|
||||
func (s SNICheck) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
||||
if req.TLS == nil {
|
||||
s.next.ServeHTTP(rw, req)
|
||||
return
|
||||
}
|
||||
|
||||
host := getHost(req)
|
||||
serverName := strings.TrimSpace(req.TLS.ServerName)
|
||||
|
||||
// Domain Fronting
|
||||
if !strings.EqualFold(host, serverName) {
|
||||
tlsOptionHeader := findTLSOptionName(s.tlsOptionsForHost, host, true)
|
||||
tlsOptionSNI := findTLSOptionName(s.tlsOptionsForHost, serverName, false)
|
||||
|
||||
if tlsOptionHeader != tlsOptionSNI {
|
||||
log.WithoutContext().
|
||||
WithField("host", host).
|
||||
WithField("req.Host", req.Host).
|
||||
WithField("req.TLS.ServerName", req.TLS.ServerName).
|
||||
Debugf("TLS options difference: SNI:%s, Header:%s", tlsOptionSNI, tlsOptionHeader)
|
||||
http.Error(rw, http.StatusText(http.StatusMisdirectedRequest), http.StatusMisdirectedRequest)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
s.next.ServeHTTP(rw, req)
|
||||
}
|
||||
|
||||
func getHost(req *http.Request) string {
|
||||
h := requestdecorator.GetCNAMEFlatten(req.Context())
|
||||
if h != "" {
|
||||
return h
|
||||
}
|
||||
|
||||
h = requestdecorator.GetCanonizedHost(req.Context())
|
||||
if h != "" {
|
||||
return h
|
||||
}
|
||||
|
||||
host, _, err := net.SplitHostPort(req.Host)
|
||||
if err != nil {
|
||||
host = req.Host
|
||||
}
|
||||
|
||||
return strings.TrimSpace(host)
|
||||
}
|
||||
|
||||
func findTLSOptionName(tlsOptionsForHost map[string]string, host string, fqdn bool) string {
|
||||
name := findTLSOptName(tlsOptionsForHost, host, fqdn)
|
||||
if name != "" {
|
||||
return name
|
||||
}
|
||||
|
||||
name = findTLSOptName(tlsOptionsForHost, strings.ToLower(host), fqdn)
|
||||
if name != "" {
|
||||
return name
|
||||
}
|
||||
|
||||
return traefiktls.DefaultTLSConfigName
|
||||
}
|
||||
|
||||
func findTLSOptName(tlsOptionsForHost map[string]string, host string, fqdn bool) string {
|
||||
if tlsOptions, ok := tlsOptionsForHost[host]; ok {
|
||||
return tlsOptions
|
||||
}
|
||||
|
||||
if !fqdn {
|
||||
return ""
|
||||
}
|
||||
|
||||
if last := len(host) - 1; last >= 0 && host[last] == '.' {
|
||||
if tlsOptions, ok := tlsOptionsForHost[host[:last]]; ok {
|
||||
return tlsOptions
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
if tlsOptions, ok := tlsOptionsForHost[host+"."]; ok {
|
||||
return tlsOptions
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
60
pkg/middlewares/snicheck/snicheck_test.go
Normal file
60
pkg/middlewares/snicheck/snicheck_test.go
Normal file
|
@ -0,0 +1,60 @@
|
|||
package snicheck
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestSNICheck_ServeHTTP(t *testing.T) {
|
||||
testCases := []struct {
|
||||
desc string
|
||||
tlsOptionsForHost map[string]string
|
||||
host string
|
||||
expected int
|
||||
}{
|
||||
{
|
||||
desc: "no TLS options",
|
||||
expected: http.StatusOK,
|
||||
},
|
||||
{
|
||||
desc: "with TLS options",
|
||||
tlsOptionsForHost: map[string]string{
|
||||
"example.com": "foo",
|
||||
},
|
||||
expected: http.StatusOK,
|
||||
},
|
||||
{
|
||||
desc: "server name and host doesn't have the same TLS configuration",
|
||||
tlsOptionsForHost: map[string]string{
|
||||
"example.com": "foo",
|
||||
},
|
||||
host: "example.com",
|
||||
expected: http.StatusMisdirectedRequest,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
next := http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {})
|
||||
|
||||
sniCheck := New(test.tlsOptionsForHost, next)
|
||||
|
||||
req := httptest.NewRequest(http.MethodGet, "https://localhost", nil)
|
||||
if test.host != "" {
|
||||
req.Host = test.host
|
||||
}
|
||||
|
||||
recorder := httptest.NewRecorder()
|
||||
|
||||
sniCheck.ServeHTTP(recorder, req)
|
||||
|
||||
assert.Equal(t, test.expected, recorder.Code)
|
||||
})
|
||||
}
|
||||
}
|
|
@ -43,8 +43,8 @@ func (f *forwarderMiddleware) ServeHTTP(rw http.ResponseWriter, req *http.Reques
|
|||
span, req, finish := tr.StartSpanf(req, ext.SpanKindRPCClientEnum, "forward", opParts, "/")
|
||||
defer finish()
|
||||
|
||||
span.SetTag("service.name", f.service)
|
||||
span.SetTag("router.name", f.router)
|
||||
span.SetTag("traefik.service.name", f.service)
|
||||
span.SetTag("traefik.router.name", f.router)
|
||||
ext.HTTPMethod.Set(span, req.Method)
|
||||
ext.HTTPUrl.Set(span, req.URL.String())
|
||||
span.SetTag("http.host", req.Host)
|
||||
|
|
|
@ -36,12 +36,12 @@ func TestNewForwarder(t *testing.T) {
|
|||
router: "some-service.domain.tld",
|
||||
expected: expected{
|
||||
Tags: map[string]interface{}{
|
||||
"http.host": "www.test.com",
|
||||
"http.method": "GET",
|
||||
"http.url": "http://www.test.com/toto",
|
||||
"service.name": "some-service.domain.tld",
|
||||
"router.name": "some-service.domain.tld",
|
||||
"span.kind": ext.SpanKindRPCClientEnum,
|
||||
"http.host": "www.test.com",
|
||||
"http.method": "GET",
|
||||
"http.url": "http://www.test.com/toto",
|
||||
"traefik.service.name": "some-service.domain.tld",
|
||||
"traefik.router.name": "some-service.domain.tld",
|
||||
"span.kind": ext.SpanKindRPCClientEnum,
|
||||
},
|
||||
OperationName: "forward some-service.domain.tld/some-service.domain.tld",
|
||||
},
|
||||
|
@ -56,12 +56,12 @@ func TestNewForwarder(t *testing.T) {
|
|||
router: "some-service-100.slug.namespace.environment.domain.tld",
|
||||
expected: expected{
|
||||
Tags: map[string]interface{}{
|
||||
"http.host": "www.test.com",
|
||||
"http.method": "GET",
|
||||
"http.url": "http://www.test.com/toto",
|
||||
"service.name": "some-service-100.slug.namespace.environment.domain.tld",
|
||||
"router.name": "some-service-100.slug.namespace.environment.domain.tld",
|
||||
"span.kind": ext.SpanKindRPCClientEnum,
|
||||
"http.host": "www.test.com",
|
||||
"http.method": "GET",
|
||||
"http.url": "http://www.test.com/toto",
|
||||
"traefik.service.name": "some-service-100.slug.namespace.environment.domain.tld",
|
||||
"traefik.router.name": "some-service-100.slug.namespace.environment.domain.tld",
|
||||
"span.kind": ext.SpanKindRPCClientEnum,
|
||||
},
|
||||
OperationName: "forward some-service-100.slug.namespace.enviro.../some-service-100.slug.namespace.enviro.../bc4a0d48",
|
||||
},
|
||||
|
@ -76,12 +76,12 @@ func TestNewForwarder(t *testing.T) {
|
|||
router: "some-service1.namespace.environment.domain.tld",
|
||||
expected: expected{
|
||||
Tags: map[string]interface{}{
|
||||
"http.host": "www.test.com",
|
||||
"http.method": "GET",
|
||||
"http.url": "http://www.test.com/toto",
|
||||
"service.name": "some-service1.namespace.environment.domain.tld",
|
||||
"router.name": "some-service1.namespace.environment.domain.tld",
|
||||
"span.kind": ext.SpanKindRPCClientEnum,
|
||||
"http.host": "www.test.com",
|
||||
"http.method": "GET",
|
||||
"http.url": "http://www.test.com/toto",
|
||||
"traefik.service.name": "some-service1.namespace.environment.domain.tld",
|
||||
"traefik.router.name": "some-service1.namespace.environment.domain.tld",
|
||||
"span.kind": ext.SpanKindRPCClientEnum,
|
||||
},
|
||||
OperationName: "forward some-service1.namespace.environment.domain.tld/some-service1.namespace.environment.domain.tld",
|
||||
},
|
||||
|
@ -96,12 +96,12 @@ func TestNewForwarder(t *testing.T) {
|
|||
router: "some-service1.backend.namespace.environment.domain.tld",
|
||||
expected: expected{
|
||||
Tags: map[string]interface{}{
|
||||
"http.host": "www.test.com",
|
||||
"http.method": "GET",
|
||||
"http.url": "http://www.test.com/toto",
|
||||
"service.name": "some-service1.frontend.namespace.environment.domain.tld",
|
||||
"router.name": "some-service1.backend.namespace.environment.domain.tld",
|
||||
"span.kind": ext.SpanKindRPCClientEnum,
|
||||
"http.host": "www.test.com",
|
||||
"http.method": "GET",
|
||||
"http.url": "http://www.test.com/toto",
|
||||
"traefik.service.name": "some-service1.frontend.namespace.environment.domain.tld",
|
||||
"traefik.router.name": "some-service1.backend.namespace.environment.domain.tld",
|
||||
"span.kind": ext.SpanKindRPCClientEnum,
|
||||
},
|
||||
OperationName: "forward some-service1.frontend.namespace.envir.../some-service1.backend.namespace.enviro.../fa49dd23",
|
||||
},
|
||||
|
|
|
@ -9,7 +9,6 @@ import (
|
|||
"github.com/traefik/traefik/v2/pkg/metrics"
|
||||
"github.com/traefik/traefik/v2/pkg/middlewares/accesslog"
|
||||
metricsmiddleware "github.com/traefik/traefik/v2/pkg/middlewares/metrics"
|
||||
"github.com/traefik/traefik/v2/pkg/middlewares/requestdecorator"
|
||||
mTracing "github.com/traefik/traefik/v2/pkg/middlewares/tracing"
|
||||
"github.com/traefik/traefik/v2/pkg/tracing"
|
||||
"github.com/traefik/traefik/v2/pkg/tracing/jaeger"
|
||||
|
@ -20,7 +19,6 @@ type ChainBuilder struct {
|
|||
metricsRegistry metrics.Registry
|
||||
accessLoggerMiddleware *accesslog.Handler
|
||||
tracer *tracing.Tracing
|
||||
requestDecorator *requestdecorator.RequestDecorator
|
||||
}
|
||||
|
||||
// NewChainBuilder Creates a new ChainBuilder.
|
||||
|
@ -29,7 +27,6 @@ func NewChainBuilder(staticConfiguration static.Configuration, metricsRegistry m
|
|||
metricsRegistry: metricsRegistry,
|
||||
accessLoggerMiddleware: accessLoggerMiddleware,
|
||||
tracer: setupTracing(staticConfiguration.Tracing),
|
||||
requestDecorator: requestdecorator.New(staticConfiguration.HostResolver),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -49,7 +46,7 @@ func (c *ChainBuilder) Build(ctx context.Context, entryPointName string) alice.C
|
|||
chain = chain.Append(metricsmiddleware.WrapEntryPointHandler(ctx, c.metricsRegistry, entryPointName))
|
||||
}
|
||||
|
||||
return chain.Append(requestdecorator.WrapHandler(c.requestDecorator))
|
||||
return chain
|
||||
}
|
||||
|
||||
// Close accessLogger and tracer.
|
||||
|
|
|
@ -5,12 +5,11 @@ import (
|
|||
"crypto/tls"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/traefik/traefik/v2/pkg/config/runtime"
|
||||
"github.com/traefik/traefik/v2/pkg/log"
|
||||
"github.com/traefik/traefik/v2/pkg/middlewares/snicheck"
|
||||
"github.com/traefik/traefik/v2/pkg/rules"
|
||||
"github.com/traefik/traefik/v2/pkg/server/provider"
|
||||
tcpservice "github.com/traefik/traefik/v2/pkg/server/service/tcp"
|
||||
|
@ -161,38 +160,7 @@ func (m *Manager) buildEntryPointHandler(ctx context.Context, configs map[string
|
|||
}
|
||||
}
|
||||
|
||||
sniCheck := http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
||||
if req.TLS == nil {
|
||||
handlerHTTPS.ServeHTTP(rw, req)
|
||||
return
|
||||
}
|
||||
|
||||
host, _, err := net.SplitHostPort(req.Host)
|
||||
if err != nil {
|
||||
host = req.Host
|
||||
}
|
||||
|
||||
host = strings.TrimSpace(host)
|
||||
serverName := strings.TrimSpace(req.TLS.ServerName)
|
||||
|
||||
// Domain Fronting
|
||||
if !strings.EqualFold(host, serverName) {
|
||||
tlsOptionSNI := findTLSOptionName(tlsOptionsForHost, serverName)
|
||||
tlsOptionHeader := findTLSOptionName(tlsOptionsForHost, host)
|
||||
|
||||
if tlsOptionHeader != tlsOptionSNI {
|
||||
log.WithoutContext().
|
||||
WithField("host", host).
|
||||
WithField("req.Host", req.Host).
|
||||
WithField("req.TLS.ServerName", req.TLS.ServerName).
|
||||
Debugf("TLS options difference: SNI=%s, Header:%s", tlsOptionSNI, tlsOptionHeader)
|
||||
http.Error(rw, http.StatusText(http.StatusMisdirectedRequest), http.StatusMisdirectedRequest)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
handlerHTTPS.ServeHTTP(rw, req)
|
||||
})
|
||||
sniCheck := snicheck.New(tlsOptionsForHost, handlerHTTPS)
|
||||
|
||||
router.HTTPSHandler(sniCheck, defaultTLSConf)
|
||||
|
||||
|
@ -321,17 +289,3 @@ func (m *Manager) buildTCPHandler(ctx context.Context, router *runtime.TCPRouter
|
|||
|
||||
return tcp.NewChain().Extend(*mHandler).Then(sHandler)
|
||||
}
|
||||
|
||||
func findTLSOptionName(tlsOptionsForHost map[string]string, host string) string {
|
||||
tlsOptions, ok := tlsOptionsForHost[host]
|
||||
if ok {
|
||||
return tlsOptions
|
||||
}
|
||||
|
||||
tlsOptions, ok = tlsOptionsForHost[strings.ToLower(host)]
|
||||
if ok {
|
||||
return tlsOptions
|
||||
}
|
||||
|
||||
return traefiktls.DefaultTLSConfigName
|
||||
}
|
||||
|
|
|
@ -59,7 +59,6 @@ func TestRuntimeConfiguration(t *testing.T) {
|
|||
},
|
||||
"bar": {
|
||||
TCPRouter: &dynamic.TCPRouter{
|
||||
|
||||
EntryPoints: []string{"web"},
|
||||
Service: "foo-service",
|
||||
Rule: "HostSNI(`foo.bar`)",
|
||||
|
@ -136,7 +135,6 @@ func TestRuntimeConfiguration(t *testing.T) {
|
|||
},
|
||||
"bar": {
|
||||
Router: &dynamic.Router{
|
||||
|
||||
EntryPoints: []string{"web"},
|
||||
Service: "foo-service",
|
||||
Rule: "Host(`bar.foo`) && PathPrefix(`/path`)",
|
||||
|
@ -240,7 +238,6 @@ func TestRuntimeConfiguration(t *testing.T) {
|
|||
},
|
||||
"bar": {
|
||||
TCPRouter: &dynamic.TCPRouter{
|
||||
|
||||
EntryPoints: []string{"web"},
|
||||
Service: "foo-service",
|
||||
Rule: "HostSNI(`foo.bar`)",
|
||||
|
@ -340,9 +337,26 @@ func TestRuntimeConfiguration(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestDomainFronting(t *testing.T) {
|
||||
tlsOptionsBase := map[string]traefiktls.Options{
|
||||
"default": {
|
||||
MinVersion: "VersionTLS10",
|
||||
},
|
||||
"host1@file": {
|
||||
MinVersion: "VersionTLS12",
|
||||
},
|
||||
"host1@crd": {
|
||||
MinVersion: "VersionTLS12",
|
||||
},
|
||||
}
|
||||
|
||||
entryPoints := []string{"web"}
|
||||
|
||||
tests := []struct {
|
||||
desc string
|
||||
routers map[string]*runtime.RouterInfo
|
||||
tlsOptions map[string]traefiktls.Options
|
||||
host string
|
||||
ServerName string
|
||||
expectedStatus int
|
||||
}{
|
||||
{
|
||||
|
@ -350,7 +364,7 @@ func TestDomainFronting(t *testing.T) {
|
|||
routers: map[string]*runtime.RouterInfo{
|
||||
"router-1@file": {
|
||||
Router: &dynamic.Router{
|
||||
EntryPoints: []string{"web"},
|
||||
EntryPoints: entryPoints,
|
||||
Rule: "Host(`host1.local`)",
|
||||
TLS: &dynamic.RouterTLSConfig{
|
||||
Options: "host1",
|
||||
|
@ -359,12 +373,15 @@ func TestDomainFronting(t *testing.T) {
|
|||
},
|
||||
"router-2@file": {
|
||||
Router: &dynamic.Router{
|
||||
EntryPoints: []string{"web"},
|
||||
EntryPoints: entryPoints,
|
||||
Rule: "Host(`host2.local`)",
|
||||
TLS: &dynamic.RouterTLSConfig{},
|
||||
},
|
||||
},
|
||||
},
|
||||
tlsOptions: tlsOptionsBase,
|
||||
host: "host1.local",
|
||||
ServerName: "host2.local",
|
||||
expectedStatus: http.StatusMisdirectedRequest,
|
||||
},
|
||||
{
|
||||
|
@ -372,7 +389,7 @@ func TestDomainFronting(t *testing.T) {
|
|||
routers: map[string]*runtime.RouterInfo{
|
||||
"router-1@file": {
|
||||
Router: &dynamic.Router{
|
||||
EntryPoints: []string{"web"},
|
||||
EntryPoints: entryPoints,
|
||||
Rule: "Host(`host1.local`)",
|
||||
TLS: &dynamic.RouterTLSConfig{
|
||||
Options: "host1",
|
||||
|
@ -381,7 +398,7 @@ func TestDomainFronting(t *testing.T) {
|
|||
},
|
||||
"router-2@file": {
|
||||
Router: &dynamic.Router{
|
||||
EntryPoints: []string{"web"},
|
||||
EntryPoints: entryPoints,
|
||||
Rule: "Host(`host2.local`)",
|
||||
TLS: &dynamic.RouterTLSConfig{
|
||||
Options: "host1",
|
||||
|
@ -389,6 +406,9 @@ func TestDomainFronting(t *testing.T) {
|
|||
},
|
||||
},
|
||||
},
|
||||
tlsOptions: tlsOptionsBase,
|
||||
host: "host1.local",
|
||||
ServerName: "host2.local",
|
||||
expectedStatus: http.StatusOK,
|
||||
},
|
||||
{
|
||||
|
@ -396,7 +416,7 @@ func TestDomainFronting(t *testing.T) {
|
|||
routers: map[string]*runtime.RouterInfo{
|
||||
"router-1@file": {
|
||||
Router: &dynamic.Router{
|
||||
EntryPoints: []string{"web"},
|
||||
EntryPoints: entryPoints,
|
||||
Rule: "Host(`host1.local`)",
|
||||
TLS: &dynamic.RouterTLSConfig{
|
||||
Options: "host1",
|
||||
|
@ -405,7 +425,7 @@ func TestDomainFronting(t *testing.T) {
|
|||
},
|
||||
"router-2@file": {
|
||||
Router: &dynamic.Router{
|
||||
EntryPoints: []string{"web"},
|
||||
EntryPoints: entryPoints,
|
||||
Rule: "Host(`host1.local`) && PathPrefix(`/foo`)",
|
||||
TLS: &dynamic.RouterTLSConfig{
|
||||
Options: "default",
|
||||
|
@ -414,7 +434,7 @@ func TestDomainFronting(t *testing.T) {
|
|||
},
|
||||
"router-3@file": {
|
||||
Router: &dynamic.Router{
|
||||
EntryPoints: []string{"web"},
|
||||
EntryPoints: entryPoints,
|
||||
Rule: "Host(`host2.local`)",
|
||||
TLS: &dynamic.RouterTLSConfig{
|
||||
Options: "host1",
|
||||
|
@ -422,6 +442,9 @@ func TestDomainFronting(t *testing.T) {
|
|||
},
|
||||
},
|
||||
},
|
||||
tlsOptions: tlsOptionsBase,
|
||||
host: "host1.local",
|
||||
ServerName: "host2.local",
|
||||
expectedStatus: http.StatusMisdirectedRequest,
|
||||
},
|
||||
{
|
||||
|
@ -429,7 +452,7 @@ func TestDomainFronting(t *testing.T) {
|
|||
routers: map[string]*runtime.RouterInfo{
|
||||
"router-1@file": {
|
||||
Router: &dynamic.Router{
|
||||
EntryPoints: []string{"web"},
|
||||
EntryPoints: entryPoints,
|
||||
Rule: "Host(`host1.local`)",
|
||||
TLS: &dynamic.RouterTLSConfig{
|
||||
Options: "host1",
|
||||
|
@ -438,7 +461,7 @@ func TestDomainFronting(t *testing.T) {
|
|||
},
|
||||
"router-2@file": {
|
||||
Router: &dynamic.Router{
|
||||
EntryPoints: []string{"web"},
|
||||
EntryPoints: entryPoints,
|
||||
Rule: "Host(`host1.local`) && PathPrefix(`/bar`)",
|
||||
TLS: &dynamic.RouterTLSConfig{
|
||||
Options: "host1",
|
||||
|
@ -447,7 +470,7 @@ func TestDomainFronting(t *testing.T) {
|
|||
},
|
||||
"router-3@file": {
|
||||
Router: &dynamic.Router{
|
||||
EntryPoints: []string{"web"},
|
||||
EntryPoints: entryPoints,
|
||||
Rule: "Host(`host2.local`)",
|
||||
TLS: &dynamic.RouterTLSConfig{
|
||||
Options: "host1",
|
||||
|
@ -455,6 +478,9 @@ func TestDomainFronting(t *testing.T) {
|
|||
},
|
||||
},
|
||||
},
|
||||
tlsOptions: tlsOptionsBase,
|
||||
host: "host1.local",
|
||||
ServerName: "host2.local",
|
||||
expectedStatus: http.StatusOK,
|
||||
},
|
||||
{
|
||||
|
@ -462,7 +488,7 @@ func TestDomainFronting(t *testing.T) {
|
|||
routers: map[string]*runtime.RouterInfo{
|
||||
"router-1@file": {
|
||||
Router: &dynamic.Router{
|
||||
EntryPoints: []string{"web"},
|
||||
EntryPoints: entryPoints,
|
||||
Rule: "Host(`host1.local`)",
|
||||
TLS: &dynamic.RouterTLSConfig{
|
||||
Options: "host1",
|
||||
|
@ -471,7 +497,7 @@ func TestDomainFronting(t *testing.T) {
|
|||
},
|
||||
"router-2@crd": {
|
||||
Router: &dynamic.Router{
|
||||
EntryPoints: []string{"web"},
|
||||
EntryPoints: entryPoints,
|
||||
Rule: "Host(`host2.local`)",
|
||||
TLS: &dynamic.RouterTLSConfig{
|
||||
Options: "host1",
|
||||
|
@ -479,6 +505,9 @@ func TestDomainFronting(t *testing.T) {
|
|||
},
|
||||
},
|
||||
},
|
||||
tlsOptions: tlsOptionsBase,
|
||||
host: "host1.local",
|
||||
ServerName: "host2.local",
|
||||
expectedStatus: http.StatusMisdirectedRequest,
|
||||
},
|
||||
{
|
||||
|
@ -486,7 +515,7 @@ func TestDomainFronting(t *testing.T) {
|
|||
routers: map[string]*runtime.RouterInfo{
|
||||
"router-1@file": {
|
||||
Router: &dynamic.Router{
|
||||
EntryPoints: []string{"web"},
|
||||
EntryPoints: entryPoints,
|
||||
Rule: "Host(`host1.local`)",
|
||||
TLS: &dynamic.RouterTLSConfig{
|
||||
Options: "host1@crd",
|
||||
|
@ -495,7 +524,7 @@ func TestDomainFronting(t *testing.T) {
|
|||
},
|
||||
"router-2@crd": {
|
||||
Router: &dynamic.Router{
|
||||
EntryPoints: []string{"web"},
|
||||
EntryPoints: entryPoints,
|
||||
Rule: "Host(`host2.local`)",
|
||||
TLS: &dynamic.RouterTLSConfig{
|
||||
Options: "host1@crd",
|
||||
|
@ -503,25 +532,63 @@ func TestDomainFronting(t *testing.T) {
|
|||
},
|
||||
},
|
||||
},
|
||||
tlsOptions: tlsOptionsBase,
|
||||
host: "host1.local",
|
||||
ServerName: "host2.local",
|
||||
expectedStatus: http.StatusOK,
|
||||
},
|
||||
{
|
||||
desc: "Request is misdirected when server name is empty and the host name is an FQDN, but router's rule is not",
|
||||
routers: map[string]*runtime.RouterInfo{
|
||||
"router-1@file": {
|
||||
Router: &dynamic.Router{
|
||||
EntryPoints: entryPoints,
|
||||
Rule: "Host(`host1.local`)",
|
||||
TLS: &dynamic.RouterTLSConfig{
|
||||
Options: "host1@file",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
tlsOptions: map[string]traefiktls.Options{
|
||||
"default": {
|
||||
MinVersion: "VersionTLS13",
|
||||
},
|
||||
"host1@file": {
|
||||
MinVersion: "VersionTLS12",
|
||||
},
|
||||
},
|
||||
host: "host1.local.",
|
||||
expectedStatus: http.StatusMisdirectedRequest,
|
||||
},
|
||||
{
|
||||
desc: "Request is misdirected when server name is empty and the host name is not FQDN, but router's rule is",
|
||||
routers: map[string]*runtime.RouterInfo{
|
||||
"router-1@file": {
|
||||
Router: &dynamic.Router{
|
||||
EntryPoints: entryPoints,
|
||||
Rule: "Host(`host1.local.`)",
|
||||
TLS: &dynamic.RouterTLSConfig{
|
||||
Options: "host1@file",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
tlsOptions: map[string]traefiktls.Options{
|
||||
"default": {
|
||||
MinVersion: "VersionTLS13",
|
||||
},
|
||||
"host1@file": {
|
||||
MinVersion: "VersionTLS12",
|
||||
},
|
||||
},
|
||||
host: "host1.local",
|
||||
expectedStatus: http.StatusMisdirectedRequest,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
entryPoints := []string{"web"}
|
||||
tlsOptions := map[string]traefiktls.Options{
|
||||
"default": {
|
||||
MinVersion: "VersionTLS10",
|
||||
},
|
||||
"host1@file": {
|
||||
MinVersion: "VersionTLS12",
|
||||
},
|
||||
"host1@crd": {
|
||||
MinVersion: "VersionTLS12",
|
||||
},
|
||||
}
|
||||
|
||||
conf := &runtime.Configuration{
|
||||
Routers: test.routers,
|
||||
}
|
||||
|
@ -529,7 +596,7 @@ func TestDomainFronting(t *testing.T) {
|
|||
serviceManager := tcp.NewManager(conf)
|
||||
|
||||
tlsManager := traefiktls.NewManager()
|
||||
tlsManager.UpdateConfigs(context.Background(), map[string]traefiktls.Store{}, tlsOptions, []*traefiktls.CertAndStores{})
|
||||
tlsManager.UpdateConfigs(context.Background(), map[string]traefiktls.Store{}, test.tlsOptions, []*traefiktls.CertAndStores{})
|
||||
|
||||
httpsHandler := map[string]http.Handler{
|
||||
"web": http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {}),
|
||||
|
@ -545,9 +612,9 @@ func TestDomainFronting(t *testing.T) {
|
|||
require.True(t, ok)
|
||||
|
||||
req := httptest.NewRequest(http.MethodGet, "/", nil)
|
||||
req.Host = "host1.local"
|
||||
req.Host = test.host
|
||||
req.TLS = &tls.ConnectionState{
|
||||
ServerName: "host2.local",
|
||||
ServerName: test.ServerName,
|
||||
}
|
||||
|
||||
rw := httptest.NewRecorder()
|
||||
|
|
|
@ -11,6 +11,7 @@ import (
|
|||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/containous/alice"
|
||||
"github.com/pires/go-proxyproto"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/traefik/traefik/v2/pkg/config/static"
|
||||
|
@ -18,9 +19,11 @@ import (
|
|||
"github.com/traefik/traefik/v2/pkg/log"
|
||||
"github.com/traefik/traefik/v2/pkg/middlewares"
|
||||
"github.com/traefik/traefik/v2/pkg/middlewares/forwardedheaders"
|
||||
"github.com/traefik/traefik/v2/pkg/middlewares/requestdecorator"
|
||||
"github.com/traefik/traefik/v2/pkg/safe"
|
||||
"github.com/traefik/traefik/v2/pkg/server/router"
|
||||
"github.com/traefik/traefik/v2/pkg/tcp"
|
||||
"github.com/traefik/traefik/v2/pkg/types"
|
||||
"golang.org/x/net/http2"
|
||||
"golang.org/x/net/http2/h2c"
|
||||
)
|
||||
|
@ -60,7 +63,7 @@ func (h *httpForwarder) Accept() (net.Conn, error) {
|
|||
type TCPEntryPoints map[string]*TCPEntryPoint
|
||||
|
||||
// NewTCPEntryPoints creates a new TCPEntryPoints.
|
||||
func NewTCPEntryPoints(entryPointsConfig static.EntryPoints) (TCPEntryPoints, error) {
|
||||
func NewTCPEntryPoints(entryPointsConfig static.EntryPoints, hostResolverConfig *types.HostResolverConfig) (TCPEntryPoints, error) {
|
||||
serverEntryPointsTCP := make(TCPEntryPoints)
|
||||
for entryPointName, config := range entryPointsConfig {
|
||||
protocol, err := config.GetProtocol()
|
||||
|
@ -74,7 +77,7 @@ func NewTCPEntryPoints(entryPointsConfig static.EntryPoints) (TCPEntryPoints, er
|
|||
|
||||
ctx := log.With(context.Background(), log.Str(log.EntryPointName, entryPointName))
|
||||
|
||||
serverEntryPointsTCP[entryPointName], err = NewTCPEntryPoint(ctx, config)
|
||||
serverEntryPointsTCP[entryPointName], err = NewTCPEntryPoint(ctx, config, hostResolverConfig)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error while building entryPoint %s: %w", entryPointName, err)
|
||||
}
|
||||
|
@ -130,7 +133,7 @@ type TCPEntryPoint struct {
|
|||
}
|
||||
|
||||
// NewTCPEntryPoint creates a new TCPEntryPoint.
|
||||
func NewTCPEntryPoint(ctx context.Context, configuration *static.EntryPoint) (*TCPEntryPoint, error) {
|
||||
func NewTCPEntryPoint(ctx context.Context, configuration *static.EntryPoint, hostResolverConfig *types.HostResolverConfig) (*TCPEntryPoint, error) {
|
||||
tracker := newConnectionTracker()
|
||||
|
||||
listener, err := buildListener(ctx, configuration)
|
||||
|
@ -140,14 +143,16 @@ func NewTCPEntryPoint(ctx context.Context, configuration *static.EntryPoint) (*T
|
|||
|
||||
rt := &tcp.Router{}
|
||||
|
||||
httpServer, err := createHTTPServer(ctx, listener, configuration, true)
|
||||
reqDecorator := requestdecorator.New(hostResolverConfig)
|
||||
|
||||
httpServer, err := createHTTPServer(ctx, listener, configuration, true, reqDecorator)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error preparing httpServer: %w", err)
|
||||
}
|
||||
|
||||
rt.HTTPForwarder(httpServer.Forwarder)
|
||||
|
||||
httpsServer, err := createHTTPServer(ctx, listener, configuration, false)
|
||||
httpsServer, err := createHTTPServer(ctx, listener, configuration, false, reqDecorator)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error preparing httpsServer: %w", err)
|
||||
}
|
||||
|
@ -500,16 +505,19 @@ type httpServer struct {
|
|||
Switcher *middlewares.HTTPHandlerSwitcher
|
||||
}
|
||||
|
||||
func createHTTPServer(ctx context.Context, ln net.Listener, configuration *static.EntryPoint, withH2c bool) (*httpServer, error) {
|
||||
func createHTTPServer(ctx context.Context, ln net.Listener, configuration *static.EntryPoint, withH2c bool, reqDecorator *requestdecorator.RequestDecorator) (*httpServer, error) {
|
||||
httpSwitcher := middlewares.NewHandlerSwitcher(router.BuildDefaultHTTPRouter())
|
||||
|
||||
next, err := alice.New(requestdecorator.WrapHandler(reqDecorator)).Then(httpSwitcher)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var handler http.Handler
|
||||
var err error
|
||||
handler, err = forwardedheaders.NewXForwarded(
|
||||
configuration.ForwardedHeaders.Insecure,
|
||||
configuration.ForwardedHeaders.TrustedIPs,
|
||||
httpSwitcher)
|
||||
|
||||
next)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -17,38 +17,57 @@ import (
|
|||
// LocalhostCert is a PEM-encoded TLS cert with SAN IPs
|
||||
// "127.0.0.1" and "[::1]", expiring at Jan 29 16:00:00 2084 GMT.
|
||||
// generated from src/crypto/tls:
|
||||
// go run generate_cert.go --rsa-bits 1024 --host 127.0.0.1,::1,example.com --ca --start-date "Jan 1 00:00:00 1970" --duration=1000000h
|
||||
// go run generate_cert.go --rsa-bits 2048 --host 127.0.0.1,::1,example.com --ca --start-date "Jan 1 00:00:00 1970" --duration=1000000h
|
||||
var (
|
||||
localhostCert = traefiktls.FileOrContent(`-----BEGIN CERTIFICATE-----
|
||||
MIICEzCCAXygAwIBAgIQMIMChMLGrR+QvmQvpwAU6zANBgkqhkiG9w0BAQsFADAS
|
||||
MIIDOTCCAiGgAwIBAgIQSRJrEpBGFc7tNb1fb5pKFzANBgkqhkiG9w0BAQsFADAS
|
||||
MRAwDgYDVQQKEwdBY21lIENvMCAXDTcwMDEwMTAwMDAwMFoYDzIwODQwMTI5MTYw
|
||||
MDAwWjASMRAwDgYDVQQKEwdBY21lIENvMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB
|
||||
iQKBgQDuLnQAI3mDgey3VBzWnB2L39JUU4txjeVE6myuDqkM/uGlfjb9SjY1bIw4
|
||||
iA5sBBZzHi3z0h1YV8QPuxEbi4nW91IJm2gsvvZhIrCHS3l6afab4pZBl2+XsDul
|
||||
rKBxKKtD1rGxlG4LjncdabFn9gvLZad2bSysqz/qTAUStTvqJQIDAQABo2gwZjAO
|
||||
BgNVHQ8BAf8EBAMCAqQwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDwYDVR0TAQH/BAUw
|
||||
AwEB/zAuBgNVHREEJzAlggtleGFtcGxlLmNvbYcEfwAAAYcQAAAAAAAAAAAAAAAA
|
||||
AAAAATANBgkqhkiG9w0BAQsFAAOBgQCEcetwO59EWk7WiJsG4x8SY+UIAA+flUI9
|
||||
tyC4lNhbcF2Idq9greZwbYCqTTTr2XiRNSMLCOjKyI7ukPoPjo16ocHj+P3vZGfs
|
||||
h1fIw3cSS2OolhloGw/XM6RWPWtPAlGykKLciQrBru5NAPvCMsb/I1DAceTiotQM
|
||||
fblo6RBxUQ==
|
||||
MDAwWjASMRAwDgYDVQQKEwdBY21lIENvMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
|
||||
MIIBCgKCAQEA6Gba5tHV1dAKouAaXO3/ebDUU4rvwCUg/CNaJ2PT5xLD4N1Vcb8r
|
||||
bFSW2HXKq+MPfVdwIKR/1DczEoAGf/JWQTW7EgzlXrCd3rlajEX2D73faWJekD0U
|
||||
aUgz5vtrTXZ90BQL7WvRICd7FlEZ6FPOcPlumiyNmzUqtwGhO+9ad1W5BqJaRI6P
|
||||
YfouNkwR6Na4TzSj5BrqUfP0FwDizKSJ0XXmh8g8G9mtwxOSN3Ru1QFc61Xyeluk
|
||||
POGKBV/q6RBNklTNe0gI8usUMlYyoC7ytppNMW7X2vodAelSu25jgx2anj9fDVZu
|
||||
h7AXF5+4nJS4AAt0n1lNY7nGSsdZas8PbQIDAQABo4GIMIGFMA4GA1UdDwEB/wQE
|
||||
AwICpDATBgNVHSUEDDAKBggrBgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud
|
||||
DgQWBBStsdjh3/JCXXYlQryOrL4Sh7BW5TAuBgNVHREEJzAlggtleGFtcGxlLmNv
|
||||
bYcEfwAAAYcQAAAAAAAAAAAAAAAAAAAAATANBgkqhkiG9w0BAQsFAAOCAQEAxWGI
|
||||
5NhpF3nwwy/4yB4i/CwwSpLrWUa70NyhvprUBC50PxiXav1TeDzwzLx/o5HyNwsv
|
||||
cxv3HdkLW59i/0SlJSrNnWdfZ19oTcS+6PtLoVyISgtyN6DpkKpdG1cOkW3Cy2P2
|
||||
+tK/tKHRP1Y/Ra0RiDpOAmqn0gCOFGz8+lqDIor/T7MTpibL3IxqWfPrvfVRHL3B
|
||||
grw/ZQTTIVjjh4JBSW3WyWgNo/ikC1lrVxzl4iPUGptxT36Cr7Zk2Bsg0XqwbOvK
|
||||
5d+NTDREkSnUbie4GeutujmX3Dsx88UiV6UY/4lHJa6I5leHUNOHahRbpbWeOfs/
|
||||
WkBKOclmOV2xlTVuPw==
|
||||
-----END CERTIFICATE-----`)
|
||||
|
||||
// LocalhostKey is the private key for localhostCert.
|
||||
localhostKey = traefiktls.FileOrContent(`-----BEGIN RSA PRIVATE KEY-----
|
||||
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
|
||||
ZboOWVe3icTy64BT3OQhmg==
|
||||
-----END RSA PRIVATE KEY-----`)
|
||||
)
|
||||
|
||||
|
@ -72,7 +91,7 @@ func TestHTTP3AdvertisedPort(t *testing.T) {
|
|||
HTTP3: &static.HTTP3Config{
|
||||
AdvertisedPort: 8080,
|
||||
},
|
||||
})
|
||||
}, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
router := &tcp.Router{}
|
||||
|
|
|
@ -79,7 +79,7 @@ func testShutdown(t *testing.T, router *tcp.Router) {
|
|||
Address: "127.0.0.1:0",
|
||||
Transport: epConfig,
|
||||
ForwardedHeaders: &static.ForwardedHeaders{},
|
||||
})
|
||||
}, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
conn, err := startEntrypoint(entryPoint, router)
|
||||
|
@ -162,7 +162,7 @@ func TestReadTimeoutWithoutFirstByte(t *testing.T) {
|
|||
Address: ":0",
|
||||
Transport: epConfig,
|
||||
ForwardedHeaders: &static.ForwardedHeaders{},
|
||||
})
|
||||
}, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
router := &tcp.Router{}
|
||||
|
@ -198,7 +198,7 @@ func TestReadTimeoutWithFirstByte(t *testing.T) {
|
|||
Address: ":0",
|
||||
Transport: epConfig,
|
||||
ForwardedHeaders: &static.ForwardedHeaders{},
|
||||
})
|
||||
}, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
router := &tcp.Router{}
|
||||
|
|
|
@ -17,35 +17,54 @@ import (
|
|||
// go run generate_cert.go --rsa-bits 1024 --host 127.0.0.1,::1,example.com --ca --start-date "Jan 1 00:00:00 1970" --duration=1000000h
|
||||
var (
|
||||
localhostCert = FileOrContent(`-----BEGIN CERTIFICATE-----
|
||||
MIICEzCCAXygAwIBAgIQMIMChMLGrR+QvmQvpwAU6zANBgkqhkiG9w0BAQsFADAS
|
||||
MIIDOTCCAiGgAwIBAgIQSRJrEpBGFc7tNb1fb5pKFzANBgkqhkiG9w0BAQsFADAS
|
||||
MRAwDgYDVQQKEwdBY21lIENvMCAXDTcwMDEwMTAwMDAwMFoYDzIwODQwMTI5MTYw
|
||||
MDAwWjASMRAwDgYDVQQKEwdBY21lIENvMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB
|
||||
iQKBgQDuLnQAI3mDgey3VBzWnB2L39JUU4txjeVE6myuDqkM/uGlfjb9SjY1bIw4
|
||||
iA5sBBZzHi3z0h1YV8QPuxEbi4nW91IJm2gsvvZhIrCHS3l6afab4pZBl2+XsDul
|
||||
rKBxKKtD1rGxlG4LjncdabFn9gvLZad2bSysqz/qTAUStTvqJQIDAQABo2gwZjAO
|
||||
BgNVHQ8BAf8EBAMCAqQwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDwYDVR0TAQH/BAUw
|
||||
AwEB/zAuBgNVHREEJzAlggtleGFtcGxlLmNvbYcEfwAAAYcQAAAAAAAAAAAAAAAA
|
||||
AAAAATANBgkqhkiG9w0BAQsFAAOBgQCEcetwO59EWk7WiJsG4x8SY+UIAA+flUI9
|
||||
tyC4lNhbcF2Idq9greZwbYCqTTTr2XiRNSMLCOjKyI7ukPoPjo16ocHj+P3vZGfs
|
||||
h1fIw3cSS2OolhloGw/XM6RWPWtPAlGykKLciQrBru5NAPvCMsb/I1DAceTiotQM
|
||||
fblo6RBxUQ==
|
||||
MDAwWjASMRAwDgYDVQQKEwdBY21lIENvMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
|
||||
MIIBCgKCAQEA6Gba5tHV1dAKouAaXO3/ebDUU4rvwCUg/CNaJ2PT5xLD4N1Vcb8r
|
||||
bFSW2HXKq+MPfVdwIKR/1DczEoAGf/JWQTW7EgzlXrCd3rlajEX2D73faWJekD0U
|
||||
aUgz5vtrTXZ90BQL7WvRICd7FlEZ6FPOcPlumiyNmzUqtwGhO+9ad1W5BqJaRI6P
|
||||
YfouNkwR6Na4TzSj5BrqUfP0FwDizKSJ0XXmh8g8G9mtwxOSN3Ru1QFc61Xyeluk
|
||||
POGKBV/q6RBNklTNe0gI8usUMlYyoC7ytppNMW7X2vodAelSu25jgx2anj9fDVZu
|
||||
h7AXF5+4nJS4AAt0n1lNY7nGSsdZas8PbQIDAQABo4GIMIGFMA4GA1UdDwEB/wQE
|
||||
AwICpDATBgNVHSUEDDAKBggrBgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud
|
||||
DgQWBBStsdjh3/JCXXYlQryOrL4Sh7BW5TAuBgNVHREEJzAlggtleGFtcGxlLmNv
|
||||
bYcEfwAAAYcQAAAAAAAAAAAAAAAAAAAAATANBgkqhkiG9w0BAQsFAAOCAQEAxWGI
|
||||
5NhpF3nwwy/4yB4i/CwwSpLrWUa70NyhvprUBC50PxiXav1TeDzwzLx/o5HyNwsv
|
||||
cxv3HdkLW59i/0SlJSrNnWdfZ19oTcS+6PtLoVyISgtyN6DpkKpdG1cOkW3Cy2P2
|
||||
+tK/tKHRP1Y/Ra0RiDpOAmqn0gCOFGz8+lqDIor/T7MTpibL3IxqWfPrvfVRHL3B
|
||||
grw/ZQTTIVjjh4JBSW3WyWgNo/ikC1lrVxzl4iPUGptxT36Cr7Zk2Bsg0XqwbOvK
|
||||
5d+NTDREkSnUbie4GeutujmX3Dsx88UiV6UY/4lHJa6I5leHUNOHahRbpbWeOfs/
|
||||
WkBKOclmOV2xlTVuPw==
|
||||
-----END CERTIFICATE-----`)
|
||||
|
||||
// LocalhostKey is the private key for localhostCert.
|
||||
localhostKey = FileOrContent(`-----BEGIN RSA PRIVATE KEY-----
|
||||
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
|
||||
ZboOWVe3icTy64BT3OQhmg==
|
||||
-----END RSA PRIVATE KEY-----`)
|
||||
)
|
||||
|
||||
|
|
|
@ -4,11 +4,11 @@ RepositoryName = "traefik"
|
|||
OutputType = "file"
|
||||
FileName = "traefik_changelog.md"
|
||||
|
||||
# example new bugfix v2.5.7
|
||||
CurrentRef = "v2.5"
|
||||
PreviousRef = "v2.5.6"
|
||||
BaseBranch = "v2.5"
|
||||
FutureCurrentRefName = "v2.5.7"
|
||||
# example new bugfix v2.6.1
|
||||
CurrentRef = "v2.6"
|
||||
PreviousRef = "v2.6.0"
|
||||
BaseBranch = "v2.6"
|
||||
FutureCurrentRefName = "v2.6.1"
|
||||
|
||||
ThresholdPreviousRef = 10
|
||||
ThresholdCurrentRef = 10
|
||||
|
|
Loading…
Reference in a new issue