diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 578bd7b4c..8763f6799 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -3,11 +3,11 @@ PLEASE READ THIS MESSAGE. Documentation fixes or enhancements: - for Traefik v1: use branch v1.7 -- for Traefik v2: use branch v2.6 +- for Traefik v2: use branch v2.7 Bug fixes: - for Traefik v1: use branch v1.7 -- for Traefik v2: use branch v2.6 +- for Traefik v2: use branch v2.7 Enhancements: - for Traefik v1: we only accept bug fixes diff --git a/.github/workflows/validate.yaml b/.github/workflows/validate.yaml index 15db3ed12..21aa83767 100644 --- a/.github/workflows/validate.yaml +++ b/.github/workflows/validate.yaml @@ -7,7 +7,7 @@ on: env: GO_VERSION: 1.17 - GOLANGCI_LINT_VERSION: v1.45.0 + GOLANGCI_LINT_VERSION: v1.46.2 MISSSPELL_VERSION: v0.3.4 IN_DOCKER: "" diff --git a/.golangci.toml b/.golangci.toml index 8e3e3d246..43f02ce28 100644 --- a/.golangci.toml +++ b/.golangci.toml @@ -119,6 +119,7 @@ "interfacer", # Deprecated "maligned", # Deprecated "golint", # Deprecated + "execinquery", # Not relevant (SQL) "sqlclosecheck", # Not relevant (SQL) "rowserrcheck", # Not relevant (SQL) "lll", # Not relevant @@ -142,6 +143,7 @@ "paralleltest", # Not relevant "exhaustive", # Not relevant "exhaustivestruct", # Not relevant + "exhaustruct", # duplicate of exhaustivestruct "goerr113", # Too strict "wrapcheck", # Too strict "noctx", # Too strict @@ -156,6 +158,7 @@ "contextcheck", # too many false-positive "containedctx", # too many false-positive "maintidx", # kind of duplicate of gocyclo + "nonamedreturns", # not relevant ] [issues] diff --git a/.semaphore/semaphore.yml b/.semaphore/semaphore.yml index b02513a4e..509aeafa8 100644 --- a/.semaphore/semaphore.yml +++ b/.semaphore/semaphore.yml @@ -25,7 +25,7 @@ global_job_config: - export "PATH=${GOPATH}/bin:${PATH}" - mkdir -vp "${SEMAPHORE_GIT_DIR}" "${GOPATH}/bin" - export GOPROXY=https://proxy.golang.org,direct - - curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b "${GOPATH}/bin" v1.45.0 + - curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b "${GOPATH}/bin" v1.46.2 - curl -sSfL https://gist.githubusercontent.com/traefiker/6d7ac019c11d011e4f131bb2cca8900e/raw/goreleaser.sh | bash -s -- -b "${GOPATH}/bin" - checkout - cache restore traefik-$(checksum go.sum) diff --git a/CHANGELOG.md b/CHANGELOG.md index d702c450f..de9b0b580 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,93 @@ +## [v2.7.0](https://github.com/traefik/traefik/tree/v2.7.0) (2022-05-24) +[All Commits](https://github.com/traefik/traefik/compare/v2.7.0-rc1...v2.7.0) + +**Enhancements:** +- **[consulcatalog]** Watch for Consul events to rebuild the dynamic configuration ([#8476](https://github.com/traefik/traefik/pull/8476) by [JasonWangA](https://github.com/JasonWangA)) +- **[healthcheck]** Add Failover service ([#8825](https://github.com/traefik/traefik/pull/8825) by [tomMoulard](https://github.com/tomMoulard)) +- **[http3]** Configure advertised port using h3 server option ([#8778](https://github.com/traefik/traefik/pull/8778) by [kevinpollet](https://github.com/kevinpollet)) +- **[http3]** Upgrade quic-go to v0.25.0 ([#8760](https://github.com/traefik/traefik/pull/8760) by [sylr](https://github.com/sylr)) +- **[hub]** Add Traefik Hub Integration (Experimental Feature) ([#8837](https://github.com/traefik/traefik/pull/8837) by [jbdoumenjou](https://github.com/jbdoumenjou)) +- **[k8s/crd,k8s]** Allow empty services in Kubernetes CRD ([#8802](https://github.com/traefik/traefik/pull/8802) by [tomMoulard](https://github.com/tomMoulard)) +- **[metrics]** Support InfluxDB v2 metrics backend ([#8250](https://github.com/traefik/traefik/pull/8250) by [sh7dm](https://github.com/sh7dm)) +- **[plugins]** Remove Pilot token setup constraint to use plugins ([#8869](https://github.com/traefik/traefik/pull/8869) by [ldez](https://github.com/ldez)) +- **[provider]** Refactor configuration reload/throttling ([#6633](https://github.com/traefik/traefik/pull/6633) by [rkojedzinszky](https://github.com/rkojedzinszky)) +- **[rules,tcp]** Add HostSNIRegexp rule matcher for TCP ([#8849](https://github.com/traefik/traefik/pull/8849) by [rtribotte](https://github.com/rtribotte)) +- **[tcp]** Add muxer for TCP Routers ([#8182](https://github.com/traefik/traefik/pull/8182) by [dtomcej](https://github.com/dtomcej)) +- **[webui,pilot]** Add Traefik Hub access and remove Pilot access ([#8848](https://github.com/traefik/traefik/pull/8848) by [tomMoulard](https://github.com/tomMoulard)) +- **[webui]** Add a link to service on router detail view ([#8821](https://github.com/traefik/traefik/pull/8821) by [Tchoupinax](https://github.com/Tchoupinax)) + +**Bug fixes:** +- **[hub]** Skip Provide when TLS is nil ([#9031](https://github.com/traefik/traefik/pull/9031) by [ldez](https://github.com/ldez)) +- **[tcp]** Fix TCP-TLS/HTTPS routing precedence ([#9024](https://github.com/traefik/traefik/pull/9024) by [rtribotte](https://github.com/rtribotte)) +- **[webui,hub]** Use dedicated entrypoint for the tunnels ([#9023](https://github.com/traefik/traefik/pull/9023) by [youkoulayley](https://github.com/youkoulayley)) + +**Documentation:** +- **[hub]** Fix Traefik Hub TLS documentation ([#8883](https://github.com/traefik/traefik/pull/8883) by [jbdoumenjou](https://github.com/jbdoumenjou)) +- Add a Feature Deprecation page ([#8868](https://github.com/traefik/traefik/pull/8868) by [ddtmachado](https://github.com/ddtmachado)) +- Prepare release v2.7.0-rc1 ([#8879](https://github.com/traefik/traefik/pull/8879) by [tomMoulard](https://github.com/tomMoulard)) +- Prepare release v2.7.0-rc2 ([#8900](https://github.com/traefik/traefik/pull/8900) by [rtribotte](https://github.com/rtribotte)) + +**Misc:** +- Merge current v2.6 into v2.7 ([#8984](https://github.com/traefik/traefik/pull/8984) by [kevinpollet](https://github.com/kevinpollet)) +- Merge current v2.6 into v2.7 ([#8958](https://github.com/traefik/traefik/pull/8958) by [tomMoulard](https://github.com/tomMoulard)) +- Merge current v2.6 into v2.7 ([#8899](https://github.com/traefik/traefik/pull/8899) by [rtribotte](https://github.com/rtribotte)) +- Merge current v2.6 into master ([#8877](https://github.com/traefik/traefik/pull/8877) by [rtribotte](https://github.com/rtribotte)) +- Merge current v2.6 into master ([#8865](https://github.com/traefik/traefik/pull/8865) by [tomMoulard](https://github.com/tomMoulard)) +- Merge current v2.6 into master ([#8832](https://github.com/traefik/traefik/pull/8832) by [tomMoulard](https://github.com/tomMoulard)) +- Merge current v2.6 into master ([#8793](https://github.com/traefik/traefik/pull/8793) by [tomMoulard](https://github.com/tomMoulard)) +- Merge current v2.6 into master ([#8777](https://github.com/traefik/traefik/pull/8777) by [tomMoulard](https://github.com/tomMoulard)) +- Merge current v2.6 into master ([#8757](https://github.com/traefik/traefik/pull/8757) by [tomMoulard](https://github.com/tomMoulard)) +- Merge current v2.6 into master ([#8754](https://github.com/traefik/traefik/pull/8754) by [tomMoulard](https://github.com/tomMoulard)) +- Merge current v2.6 into master ([#8736](https://github.com/traefik/traefik/pull/8736) by [kevinpollet](https://github.com/kevinpollet)) +- Merge current v2.6 into master ([#8689](https://github.com/traefik/traefik/pull/8689) by [tomMoulard](https://github.com/tomMoulard)) +- Merge current v2.6 into master ([#8666](https://github.com/traefik/traefik/pull/8666) by [tomMoulard](https://github.com/tomMoulard)) + +## [v2.6.7](https://github.com/traefik/traefik/tree/v2.6.7) (2022-05-23) +[All Commits](https://github.com/traefik/traefik/compare/v2.6.6...v2.6.7) + +**Bug fixes:** +- **[logs,k8s/crd]** Fix log statement for ExternalName misconfig ([#9014](https://github.com/traefik/traefik/pull/9014) by [kruton](https://github.com/kruton)) +- **[plugins]** Update Yaegi to v0.12.0 ([#9039](https://github.com/traefik/traefik/pull/9039) by [mpl](https://github.com/mpl)) +- **[tcp,service]** Fix initial tcp lookup when address is not available ([#9021](https://github.com/traefik/traefik/pull/9021) by [ddtmachado](https://github.com/ddtmachado)) +- **[tls]** Fix panic when getting certificates with non-existing store ([#9019](https://github.com/traefik/traefik/pull/9019) by [moutoum](https://github.com/moutoum)) +- **[tracing]** Update jaeger-client-go to v2.30.0 ([#9000](https://github.com/traefik/traefik/pull/9000) by [moutoum](https://github.com/moutoum)) + +**Documentation:** +- **[middleware]** Updated browserXssFilter key to camel case ([#9038](https://github.com/traefik/traefik/pull/9038) by [karlosmunjos](https://github.com/karlosmunjos)) +- Fix the default priority for the entrypoint redirection ([#9028](https://github.com/traefik/traefik/pull/9028) by [ldez](https://github.com/ldez)) +- Fix typo in maintainers guidelines ([#9011](https://github.com/traefik/traefik/pull/9011) by [eltociear](https://github.com/eltociear)) + +## [v2.6.6](https://github.com/traefik/traefik/tree/v2.6.6) (2022-05-03) +[All Commits](https://github.com/traefik/traefik/compare/v2.6.3...v2.6.6) + +**Bug fixes:** +- **[acme]** Fix RenewInterval computation in ACME provider ([#8969](https://github.com/traefik/traefik/pull/8969) by [smasset-orange](https://github.com/smasset-orange)) +- **[ecs,logs]** Remove duplicate error logs ([#8916](https://github.com/traefik/traefik/pull/8916) by [rtribotte](https://github.com/rtribotte)) +- **[ecs]** Filter out ECS anywhere instance IDs ([#8973](https://github.com/traefik/traefik/pull/8973) by [JohnPreston](https://github.com/JohnPreston)) +- **[middleware]** Re-add missing writeheader call in flush ([#8957](https://github.com/traefik/traefik/pull/8957) by [mpl](https://github.com/mpl)) +- **[middleware]** Fix bug for when custom page is large enough ([#8932](https://github.com/traefik/traefik/pull/8932) by [mpl](https://github.com/mpl)) +- **[middleware]** Fix regexp handling in redirect middleware ([#8920](https://github.com/traefik/traefik/pull/8920) by [tomMoulard](https://github.com/tomMoulard)) +- **[plugins]** Update Yaegi to v0.11.3 ([#8954](https://github.com/traefik/traefik/pull/8954) by [kevinpollet](https://github.com/kevinpollet)) + +**Documentation:** +- **[k8s/gatewayapi]** Fix certificateRefs in dynamic configuration ([#8940](https://github.com/traefik/traefik/pull/8940) by [kahirokunn](https://github.com/kahirokunn)) +- **[logs]** Move accessLog.fields example to TOML section ([#8944](https://github.com/traefik/traefik/pull/8944) by [major](https://github.com/major)) +- **[logs]** Add default mode for fields.names to access log ([#8933](https://github.com/traefik/traefik/pull/8933) by [aleksvujic](https://github.com/aleksvujic)) +- **[middleware]** Fix default for buffering middleware ([#8945](https://github.com/traefik/traefik/pull/8945) by [rtribotte](https://github.com/rtribotte)) +- **[middleware]** Preflight requests are not forwarded to services ([#8923](https://github.com/traefik/traefik/pull/8923) by [sizief](https://github.com/sizief)) +- Add title and description metadata to documentation pages ([#8941](https://github.com/traefik/traefik/pull/8941) by [ldez](https://github.com/ldez)) +- Update dynamic and static configuration references ([#8918](https://github.com/traefik/traefik/pull/8918) by [ldez](https://github.com/ldez)) + +## [v2.6.5](https://github.com/traefik/traefik/tree/v2.6.5) (2022-05-03) +[All Commits](https://github.com/traefik/traefik/compare/v2.6.3...v2.6.5) + +Release canceled. + +## [v2.6.4](https://github.com/traefik/traefik/tree/v2.6.4) (2022-05-03) +[All Commits](https://github.com/traefik/traefik/compare/v2.6.3...v2.6.4) + +Release canceled. + ## [v2.7.0-rc2](https://github.com/traefik/traefik/tree/v2.7.0-rc2) (2022-03-29) [All Commits](https://github.com/traefik/traefik/compare/v2.7.0-rc1...v2.7.0-rc2) diff --git a/Makefile b/Makefile index 4f454017a..ebccf5d01 100644 --- a/Makefile +++ b/Makefile @@ -65,7 +65,7 @@ build-webui-image: clean-webui: rm -r webui/static mkdir -p webui/static - echo 'For more information show `webui/readme.md`' > webui/static/DONT-EDIT-FILES-IN-THIS-DIRECTORY.md + printf 'For more information see `webui/readme.md`' > webui/static/DONT-EDIT-FILES-IN-THIS-DIRECTORY.md ## Generate WebUI webui/static/index.html: diff --git a/build.Dockerfile b/build.Dockerfile index 4424e3603..8d3159c8e 100644 --- a/build.Dockerfile +++ b/build.Dockerfile @@ -13,7 +13,7 @@ RUN mkdir -p /usr/local/bin \ | tar -xzC /usr/local/bin --transform 's#^.+/##x' # Download golangci-lint binary to bin folder in $GOPATH -RUN curl -sfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | bash -s -- -b $GOPATH/bin v1.45.0 +RUN curl -sfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | bash -s -- -b $GOPATH/bin v1.46.2 # Download misspell binary to bin folder in $GOPATH RUN curl -sfL https://raw.githubusercontent.com/client9/misspell/master/install-misspell.sh | bash -s -- -b $GOPATH/bin v0.3.4 diff --git a/cmd/traefik/traefik.go b/cmd/traefik/traefik.go index 875eff503..47f409a0b 100644 --- a/cmd/traefik/traefik.go +++ b/cmd/traefik/traefik.go @@ -34,6 +34,7 @@ import ( "github.com/traefik/traefik/v2/pkg/pilot" "github.com/traefik/traefik/v2/pkg/provider/acme" "github.com/traefik/traefik/v2/pkg/provider/aggregator" + "github.com/traefik/traefik/v2/pkg/provider/hub" "github.com/traefik/traefik/v2/pkg/provider/traefik" "github.com/traefik/traefik/v2/pkg/safe" "github.com/traefik/traefik/v2/pkg/server" @@ -215,8 +216,6 @@ func setupServer(staticConfiguration *static.Configuration) (*server.Server, err } if staticConfiguration.Pilot != nil { - log.WithoutContext().Warn("Traefik Pilot is deprecated and will be removed soon. Please check our Blog for migration instructions later this year") - version.PilotEnabled = staticConfiguration.Pilot.Dashboard } @@ -363,7 +362,7 @@ func getDefaultsEntrypoints(staticConfiguration *static.Configuration) []string var defaultEntryPoints []string for name, cfg := range staticConfiguration.EntryPoints { // Traefik Hub entryPoint should not be part of the set of default entryPoints. - if staticConfiguration.Hub != nil && staticConfiguration.Hub.EntryPoint == name { + if hub.APIEntrypoint == name || hub.TunnelEntrypoint == name { continue } diff --git a/docs/content/contributing/maintainers-guidelines.md b/docs/content/contributing/maintainers-guidelines.md index a22991807..b1d2a0432 100644 --- a/docs/content/contributing/maintainers-guidelines.md +++ b/docs/content/contributing/maintainers-guidelines.md @@ -60,7 +60,7 @@ but we can suggest you start with activities such as: The ability to set up a testing environment in a few minutes, using the official documentation, is a game changer. -- You will be listed on our Maintainers Github page +- You will be listed on our Maintainers GitHub page as well as on our website in the section [maintainers](maintainers.md). - We will be promoting you on social channels (mostly on Twitter). diff --git a/docs/content/getting-started/install-traefik.md b/docs/content/getting-started/install-traefik.md index eaaf88e65..8b67f5e22 100644 --- a/docs/content/getting-started/install-traefik.md +++ b/docs/content/getting-started/install-traefik.md @@ -16,8 +16,8 @@ You can install Traefik with the following flavors: Choose one of the [official Docker images](https://hub.docker.com/_/traefik) and run it with one sample configuration file: -* [YAML](https://raw.githubusercontent.com/traefik/traefik/v2.6/traefik.sample.yml) -* [TOML](https://raw.githubusercontent.com/traefik/traefik/v2.6/traefik.sample.toml) +* [YAML](https://raw.githubusercontent.com/traefik/traefik/v2.7/traefik.sample.yml) +* [TOML](https://raw.githubusercontent.com/traefik/traefik/v2.7/traefik.sample.toml) ```bash docker run -d -p 8080:8080 -p 80:80 \ diff --git a/docs/content/middlewares/http/headers.md b/docs/content/middlewares/http/headers.md index 95ea5c3dc..856a38c4a 100644 --- a/docs/content/middlewares/http/headers.md +++ b/docs/content/middlewares/http/headers.md @@ -165,7 +165,7 @@ metadata: spec: headers: frameDeny: true - browserxssfilter: true + browserXssFilter: true ``` ```yaml tab="Consul Catalog" @@ -192,14 +192,14 @@ http: testHeader: headers: frameDeny: true - browserxssfilter: true + browserXssFilter: true ``` ```toml tab="File (TOML)" [http.middlewares] [http.middlewares.testHeader.headers] frameDeny = true - browserxssfilter = true + browserXssFilter = true ``` ### CORS Headers diff --git a/docs/content/migration/v1-to-v2.md b/docs/content/migration/v1-to-v2.md index 873b95ae9..1e7bcdf91 100644 --- a/docs/content/migration/v1-to-v2.md +++ b/docs/content/migration/v1-to-v2.md @@ -109,7 +109,7 @@ Then any router can refer to an instance of the wanted middleware. ```yaml tab="K8s IngressRoute" # The definitions below require the definitions for the Middleware and IngressRoute kinds. - # https://doc.traefik.io/traefik/v2.6/reference/dynamic-configuration/kubernetes-crd/#definitions + # https://doc.traefik.io/traefik/v2.7/reference/dynamic-configuration/kubernetes-crd/#definitions apiVersion: traefik.containo.us/v1alpha1 kind: Middleware metadata: diff --git a/docs/content/migration/v2.md b/docs/content/migration/v2.md index 783d08cac..c32f28987 100644 --- a/docs/content/migration/v2.md +++ b/docs/content/migration/v2.md @@ -458,14 +458,9 @@ the value for the method label becomes `EXTENSION_METHOD`, instead of the reques 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`. -## v2.7 - -### Traefik Pilot - -In `v2.7`, the `pilot.token` and `pilot.dashboard` options are deprecated. -Please check the [feature deprecation page](../deprecation/features.md) and our Blog for migration instructions later this year. - ## v2.8 +### TLS client authentication + In `v2.8`, the `caOptional` option is deprecated as TLS client authentication is a server side option. This option available in the ForwardAuth middleware, as well as in the HTTP, Consul, Etcd, Redis, ZooKeeper, Marathon, Consul Catalog, and Docker providers has no effect and must not be used anymore. diff --git a/docs/content/plugins/index.md b/docs/content/plugins/index.md index 421044278..f5062b21f 100644 --- a/docs/content/plugins/index.md +++ b/docs/content/plugins/index.md @@ -5,11 +5,6 @@ description: "Learn how to connect Traefik Proxy with Pilot, a SaaS platform tha # Plugins and Traefik Pilot -!!! warning "Traefik Pilot Deprecation" - - Traefik Pilot is deprecated and will be removed soon. - Please check our Blog for migration instructions later this year. - Traefik Pilot is a software-as-a-service (SaaS) platform that connects to Traefik to extend its capabilities. It offers a number of features to enhance observability and control of Traefik through a global control plane and dashboard, including: diff --git a/docs/content/providers/kubernetes-ingress.md b/docs/content/providers/kubernetes-ingress.md index f80f54562..cf4ccf9bd 100644 --- a/docs/content/providers/kubernetes-ingress.md +++ b/docs/content/providers/kubernetes-ingress.md @@ -500,4 +500,4 @@ providers: ### Further To learn more about the various aspects of the Ingress specification that Traefik supports, -many examples of Ingresses definitions are located in the test [examples](https://github.com/traefik/traefik/tree/v2.6/pkg/provider/kubernetes/ingress/fixtures) of the Traefik repository. +many examples of Ingresses definitions are located in the test [examples](https://github.com/traefik/traefik/tree/v2.7/pkg/provider/kubernetes/ingress/fixtures) of the Traefik repository. diff --git a/docs/content/reference/static-configuration/cli-ref.md b/docs/content/reference/static-configuration/cli-ref.md index 84296d2cc..9dcc60921 100644 --- a/docs/content/reference/static-configuration/cli-ref.md +++ b/docs/content/reference/static-configuration/cli-ref.md @@ -225,9 +225,6 @@ The maximal depth of DNS recursive resolving (Default: ```5```) `--hub`: Traefik Hub configuration. (Default: ```false```) -`--hub.entrypoint`: -Entrypoint that exposes data for Traefik Hub. It should be a dedicated one, and not used by any router. (Default: ```traefik-hub```) - `--hub.tls.ca`: The certificate authority authenticates the Traefik Hub Agent certificate. diff --git a/docs/content/reference/static-configuration/env-ref.md b/docs/content/reference/static-configuration/env-ref.md index bd3d96f98..44a976c37 100644 --- a/docs/content/reference/static-configuration/env-ref.md +++ b/docs/content/reference/static-configuration/env-ref.md @@ -225,9 +225,6 @@ The maximal depth of DNS recursive resolving (Default: ```5```) `TRAEFIK_HUB`: Traefik Hub configuration. (Default: ```false```) -`TRAEFIK_HUB_ENTRYPOINT`: -Entrypoint that exposes data for Traefik Hub. It should be a dedicated one, and not used by any router. (Default: ```traefik-hub```) - `TRAEFIK_HUB_TLS_CA`: The certificate authority authenticates the Traefik Hub Agent certificate. diff --git a/docs/content/reference/static-configuration/file.toml b/docs/content/reference/static-configuration/file.toml index 6bc925709..aad84318d 100644 --- a/docs/content/reference/static-configuration/file.toml +++ b/docs/content/reference/static-configuration/file.toml @@ -432,7 +432,6 @@ dashboard = true [hub] - entrypoint = "foobar" [hub.tls] insecure = true ca = "foobar" diff --git a/docs/content/reference/static-configuration/file.yaml b/docs/content/reference/static-configuration/file.yaml index c0c2891ad..3887876e3 100644 --- a/docs/content/reference/static-configuration/file.yaml +++ b/docs/content/reference/static-configuration/file.yaml @@ -453,7 +453,6 @@ pilot: token: foobar dashboard: true hub: - entrypoint: foobar tls: insecure: true ca: foobar diff --git a/docs/content/routing/entrypoints.md b/docs/content/routing/entrypoints.md index 0f0f3338d..91509d3f1 100644 --- a/docs/content/routing/entrypoints.md +++ b/docs/content/routing/entrypoints.md @@ -805,7 +805,7 @@ This section is a convenience to enable (permanent) redirecting of all incoming ??? info "`entryPoint.priority`" - _Optional, Default=1_ + _Optional, Default=MaxInt32-1 (2147483646)_ Priority of the generated router. diff --git a/docs/content/traefik-hub/index.md b/docs/content/traefik-hub/index.md deleted file mode 100644 index d6fa92dfe..000000000 --- a/docs/content/traefik-hub/index.md +++ /dev/null @@ -1,295 +0,0 @@ -# Traefik Hub (Experimental) - -## Overview - -Once the Traefik Hub Experimental feature is enabled in Traefik, -Traefik and its local agent communicate together. -This agent can: - -* get the Traefik metrics to display them in the Traefik Hub UI -* secure the Traefik routers -* provide ACME certificates to Traefik -* transfer requests from the SaaS Platform to Traefik (and then avoid the users to expose directly their infrastructure on the internet) - -!!! warning "Traefik Hub EntryPoint" - - When the Traefik Hub feature is enabled, Traefik exposes some services meant for the Traefik Hub Agent on a dedicated entryPoint (on port `9900` by default). - Given their sensitive nature, those services should not be publicly exposed. - Also this dedicated entryPoint, regardless of how it is created (default, or user-defined), should not be used by anything other than the Hub Agent. - -!!! important "Learn More About Traefik Hub" - - This section is intended only as a brief overview for Traefik users who are not familiar with Traefik Hub. - To explore all that Traefik Hub has to offer, please consult the [Traefik Hub Documentation](https://doc.traefik.io/traefik-hub). - -!!! Note "Prerequisites" - - * Traefik Hub is compatible with Traefik Proxy 2.7 or later. - * The Traefik Hub Agent must be installed to connect to the Traefik Hub platform. - * Activate this feature in the experimental section of the static configuration. - -!!! example "Minimal Static Configuration to Activate Traefik Hub" - - ```yaml tab="File (YAML)" - experimental: - hub: true - - hub: - tls: - insecure: true - - metrics: - prometheus: {} - ``` - - ```toml tab="File (TOML)" - [experimental] - hub = true - - [hub] - [hub.tls] - insecure = true - - [metrics] - [metrics.prometheus] - ``` - - ```bash tab="CLI" - --experimental.hub - --hub.tls.insecure=true - --metrics.prometheus=true - ``` - -## Configuration - -### `entryPoint` - -_Optional, Default="traefik-hub"_ - -Defines the entryPoint that exposes data for Traefik Hub Agent. - -!!! info - - * If no entryPoint is defined, a default `traefik-hub` entryPoint is created (on port `9900`). - * If defined, the value must match an existing entryPoint name. - * This dedicated Traefik Hub entryPoint should not be used by anything other than Traefik Hub. - -```yaml tab="File (YAML)" -entryPoints: - hub-ep: ":8000" - -hub: - entryPoint: "hub-ep" -``` - -```toml tab="File (TOML)" -[entryPoints.hub-ep] - address = ":8000" - -[hub] - entryPoint = "hub-ep" -``` - -```bash tab="CLI" ---entrypoints.hub-ep.address=:8000 ---hub.entrypoint=hub-ep -``` - -### `tls` - -_Required, Default=None_ - -This section allows configuring mutual TLS connection between Traefik Proxy and the Traefik Hub Agent. -The key and the certificate are the credentials for Traefik Proxy as a TLS client. -The certificate authority authenticates the Traefik Hub Agent certificate. - -!!! note "Certificate Domain" - - The certificate must be valid for the `proxy.traefik` domain. - -!!! note "Certificates Definition" - - Certificates can be defined either by their content or their path. - -!!! note "Insecure Mode" - - The `insecure` option is mutually exclusive with any other option. - -```yaml tab="File (YAML)" -hub: - tls: - ca: /path/to/ca.pem - cert: /path/to/cert.pem - key: /path/to/key.pem -``` - -```toml tab="File (TOML)" -[hub.tls] - ca= "/path/to/ca.pem" - cert= "/path/to/cert.pem" - key= "/path/to/key.pem" -``` - -```bash tab="CLI" ---hub.tls.ca=/path/to/ca.pem ---hub.tls.cert=/path/to/cert.pem ---hub.tls.key=/path/to/key.pem -``` - -### `tls.ca` - -The certificate authority authenticates the Traefik Hub Agent certificate. - -```yaml tab="File (YAML)" -hub: - tls: - ca: |- - -----BEGIN CERTIFICATE----- - MIIBcjCCARegAwIBAgIQaewCzGdRz5iNnjAiEoO5AzAKBggqhkjOPQQDAjASMRAw - DgYDVQQKEwdBY21lIENvMCAXDTIyMDMyMTE2MTY0NFoYDzIxMjIwMjI1MTYxNjQ0 - WjASMRAwDgYDVQQKEwdBY21lIENvMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE - ZaKYPj2G8Hnmju6jbHt+vODwKqNDVQMH5nxhtAgSUZS61mLWwZvvUhIYLNPwHz8a - x8C7+cuihEC6Tzvn8DeGeKNNMEswDgYDVR0PAQH/BAQDAgeAMBMGA1UdJQQMMAoG - CCsGAQUFBwMBMAwGA1UdEwEB/wQCMAAwFgYDVR0RBA8wDYILZXhhbXBsZS5jb20w - CgYIKoZIzj0EAwIDSQAwRgIhAO8sucDGY+JOrNgQg1a9ZqqYvbxPFnYsSZr7F/vz - aUX2AiEAilZ+M5eX4RiMFc3nlm9qVs1LZhV3dZW/u80/mPQ/oaY= - -----END CERTIFICATE----- -``` - -```toml tab="File (TOML)" -[hub.tls] - ca = """-----BEGIN CERTIFICATE----- -MIIBcjCCARegAwIBAgIQaewCzGdRz5iNnjAiEoO5AzAKBggqhkjOPQQDAjASMRAw -DgYDVQQKEwdBY21lIENvMCAXDTIyMDMyMTE2MTY0NFoYDzIxMjIwMjI1MTYxNjQ0 -WjASMRAwDgYDVQQKEwdBY21lIENvMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE -ZaKYPj2G8Hnmju6jbHt+vODwKqNDVQMH5nxhtAgSUZS61mLWwZvvUhIYLNPwHz8a -x8C7+cuihEC6Tzvn8DeGeKNNMEswDgYDVR0PAQH/BAQDAgeAMBMGA1UdJQQMMAoG -CCsGAQUFBwMBMAwGA1UdEwEB/wQCMAAwFgYDVR0RBA8wDYILZXhhbXBsZS5jb20w -CgYIKoZIzj0EAwIDSQAwRgIhAO8sucDGY+JOrNgQg1a9ZqqYvbxPFnYsSZr7F/vz -aUX2AiEAilZ+M5eX4RiMFc3nlm9qVs1LZhV3dZW/u80/mPQ/oaY= ------END CERTIFICATE-----""" -``` - -```bash tab="CLI" ---hub.tls.ca=-----BEGIN CERTIFICATE----- -MIIBcjCCARegAwIBAgIQaewCzGdRz5iNnjAiEoO5AzAKBggqhkjOPQQDAjASMRAw -DgYDVQQKEwdBY21lIENvMCAXDTIyMDMyMTE2MTY0NFoYDzIxMjIwMjI1MTYxNjQ0 -WjASMRAwDgYDVQQKEwdBY21lIENvMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE -ZaKYPj2G8Hnmju6jbHt+vODwKqNDVQMH5nxhtAgSUZS61mLWwZvvUhIYLNPwHz8a -x8C7+cuihEC6Tzvn8DeGeKNNMEswDgYDVR0PAQH/BAQDAgeAMBMGA1UdJQQMMAoG -CCsGAQUFBwMBMAwGA1UdEwEB/wQCMAAwFgYDVR0RBA8wDYILZXhhbXBsZS5jb20w -CgYIKoZIzj0EAwIDSQAwRgIhAO8sucDGY+JOrNgQg1a9ZqqYvbxPFnYsSZr7F/vz -aUX2AiEAilZ+M5eX4RiMFc3nlm9qVs1LZhV3dZW/u80/mPQ/oaY= ------END CERTIFICATE----- -``` - -### `tls.cert` - -The TLS certificate for Traefik Proxy as a TLS client. - -!!! note "Certificate Domain" - - The certificate must be valid for the `proxy.traefik` domain. - -```yaml tab="File (YAML)" -hub: - tls: - cert: |- - -----BEGIN CERTIFICATE----- - MIIBcjCCARegAwIBAgIQaewCzGdRz5iNnjAiEoO5AzAKBggqhkjOPQQDAjASMRAw - DgYDVQQKEwdBY21lIENvMCAXDTIyMDMyMTE2MTY0NFoYDzIxMjIwMjI1MTYxNjQ0 - WjASMRAwDgYDVQQKEwdBY21lIENvMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE - ZaKYPj2G8Hnmju6jbHt+vODwKqNDVQMH5nxhtAgSUZS61mLWwZvvUhIYLNPwHz8a - x8C7+cuihEC6Tzvn8DeGeKNNMEswDgYDVR0PAQH/BAQDAgeAMBMGA1UdJQQMMAoG - CCsGAQUFBwMBMAwGA1UdEwEB/wQCMAAwFgYDVR0RBA8wDYILZXhhbXBsZS5jb20w - CgYIKoZIzj0EAwIDSQAwRgIhAO8sucDGY+JOrNgQg1a9ZqqYvbxPFnYsSZr7F/vz - aUX2AiEAilZ+M5eX4RiMFc3nlm9qVs1LZhV3dZW/u80/mPQ/oaY= - -----END CERTIFICATE----- -``` - -```toml tab="File (TOML)" -[hub.tls] - cert = """-----BEGIN CERTIFICATE----- -MIIBcjCCARegAwIBAgIQaewCzGdRz5iNnjAiEoO5AzAKBggqhkjOPQQDAjASMRAw -DgYDVQQKEwdBY21lIENvMCAXDTIyMDMyMTE2MTY0NFoYDzIxMjIwMjI1MTYxNjQ0 -WjASMRAwDgYDVQQKEwdBY21lIENvMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE -ZaKYPj2G8Hnmju6jbHt+vODwKqNDVQMH5nxhtAgSUZS61mLWwZvvUhIYLNPwHz8a -x8C7+cuihEC6Tzvn8DeGeKNNMEswDgYDVR0PAQH/BAQDAgeAMBMGA1UdJQQMMAoG -CCsGAQUFBwMBMAwGA1UdEwEB/wQCMAAwFgYDVR0RBA8wDYILZXhhbXBsZS5jb20w -CgYIKoZIzj0EAwIDSQAwRgIhAO8sucDGY+JOrNgQg1a9ZqqYvbxPFnYsSZr7F/vz -aUX2AiEAilZ+M5eX4RiMFc3nlm9qVs1LZhV3dZW/u80/mPQ/oaY= ------END CERTIFICATE-----""" -``` - -```bash tab="CLI" ---hub.tls.cert=-----BEGIN CERTIFICATE----- -MIIBcjCCARegAwIBAgIQaewCzGdRz5iNnjAiEoO5AzAKBggqhkjOPQQDAjASMRAw -DgYDVQQKEwdBY21lIENvMCAXDTIyMDMyMTE2MTY0NFoYDzIxMjIwMjI1MTYxNjQ0 -WjASMRAwDgYDVQQKEwdBY21lIENvMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE -ZaKYPj2G8Hnmju6jbHt+vODwKqNDVQMH5nxhtAgSUZS61mLWwZvvUhIYLNPwHz8a -x8C7+cuihEC6Tzvn8DeGeKNNMEswDgYDVR0PAQH/BAQDAgeAMBMGA1UdJQQMMAoG -CCsGAQUFBwMBMAwGA1UdEwEB/wQCMAAwFgYDVR0RBA8wDYILZXhhbXBsZS5jb20w -CgYIKoZIzj0EAwIDSQAwRgIhAO8sucDGY+JOrNgQg1a9ZqqYvbxPFnYsSZr7F/vz -aUX2AiEAilZ+M5eX4RiMFc3nlm9qVs1LZhV3dZW/u80/mPQ/oaY= ------END CERTIFICATE----- -``` - -### `tls.key` - -The TLS key for Traefik Proxy as a TLS client. - -```yaml tab="File (YAML)" -hub: - tls: - key: |- - -----BEGIN PRIVATE KEY----- - MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgm+XJ3LVrTbbirJea - O+Crj2ADVsVHjMuiyd72VE3lgxihRANCAARlopg+PYbweeaO7qNse3684PAqo0NV - AwfmfGG0CBJRlLrWYtbBm+9SEhgs0/AfPxrHwLv5y6KEQLpPO+fwN4Z4 - -----END PRIVATE KEY----- -``` - -```toml tab="File (TOML)" -[hub.tls] - key = """-----BEGIN PRIVATE KEY----- -MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgm+XJ3LVrTbbirJea -O+Crj2ADVsVHjMuiyd72VE3lgxihRANCAARlopg+PYbweeaO7qNse3684PAqo0NV -AwfmfGG0CBJRlLrWYtbBm+9SEhgs0/AfPxrHwLv5y6KEQLpPO+fwN4Z4 ------END PRIVATE KEY-----""" -``` - -```bash tab="CLI" ---hub.tls.key=-----BEGIN PRIVATE KEY----- -MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgm+XJ3LVrTbbirJea -O+Crj2ADVsVHjMuiyd72VE3lgxihRANCAARlopg+PYbweeaO7qNse3684PAqo0NV -AwfmfGG0CBJRlLrWYtbBm+9SEhgs0/AfPxrHwLv5y6KEQLpPO+fwN4Z4 ------END PRIVATE KEY----- -``` - -### `tls.insecure` - -_Optional, Default=false_ - -Enables an insecure TLS connection that uses default credentials, -and which has no peer authentication between Traefik Proxy and the Traefik Hub Agent. -The `insecure` option is mutually exclusive with any other option. - -!!! warning "Security Consideration" - - Do not use this setup in production. - This option implies sensitive data can be exposed to potential malicious third-party programs. - -```yaml tab="File (YAML)" -hub: - tls: - insecure: true -``` - -```toml tab="File (TOML)" -[hub.tls] - insecure = true -``` - -```bash tab="CLI" ---hub.tls.insecure=true -``` diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index a3a8a0497..08c78cae2 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -136,7 +136,6 @@ nav: - 'InFlightConn': 'middlewares/tcp/inflightconn.md' - 'IpWhitelist': 'middlewares/tcp/ipwhitelist.md' - 'Plugins & Traefik Pilot': 'plugins/index.md' - - 'Traefik Hub': 'traefik-hub/index.md' - 'Operations': - 'CLI': 'operations/cli.md' - 'Dashboard' : 'operations/dashboard.md' diff --git a/docs/scripts/verify.sh b/docs/scripts/verify.sh index 640572ec5..830fb448e 100755 --- a/docs/scripts/verify.sh +++ b/docs/scripts/verify.sh @@ -22,7 +22,7 @@ find "${PATH_TO_SITE}" -type f -not -path "/app/site/theme/*" \ --alt_ignore="/traefikproxy-vertical-logo-color.svg/" \ --http_status_ignore="0,500,501,503" \ --file_ignore="/404.html/" \ - --url_ignore="/https://groups.google.com/a/traefik.io/forum/#!forum/security/,/localhost:/,/127.0.0.1:/,/fonts.gstatic.com/,/.minikube/,/github.com\/traefik\/traefik\/*edit*/,/github.com\/traefik\/traefik/,/doc.traefik.io/,/github\.com\/golang\/oauth2\/blob\/36a7019397c4c86cf59eeab3bc0d188bac444277\/.+/,/www.akamai.com/,/pilot.traefik.io\/profile/,/traefik.io/,/doc.traefik.io\/traefik-mesh/,/www.mkdocs.org/,/squidfunk.github.io/,/ietf.org/,/www.namesilo.com/,/www.youtube.com/,/www.linode.com/,/www.alibabacloud.com/,/www.cloudxns.net/,/www.vultr.com/,/vscale.io/,/hetzner.com/,/docs.github.com/,/njal.la/" \ + --url_ignore="/https://groups.google.com/a/traefik.io/forum/#!forum/security/,/localhost:/,/127.0.0.1:/,/fonts.gstatic.com/,/.minikube/,/github.com\/traefik\/traefik\/*edit*/,/github.com\/traefik\/traefik/,/doc.traefik.io/,/github\.com\/golang\/oauth2\/blob\/36a7019397c4c86cf59eeab3bc0d188bac444277\/.+/,/www.akamai.com/,/pilot.traefik.io\/profile/,/traefik.io/,/doc.traefik.io\/traefik-mesh/,/www.mkdocs.org/,/squidfunk.github.io/,/ietf.org/,/www.namesilo.com/,/www.youtube.com/,/www.linode.com/,/www.alibabacloud.com/,/www.cloudxns.net/,/www.vultr.com/,/vscale.io/,/hetzner.com/,/docs.github.com/,/njal.la/,/www.wedos.com/" \ '{}' 1>/dev/null ## HTML-proofer options at https://github.com/gjtorikian/html-proofer#configuration diff --git a/go.mod b/go.mod index 3caf5bece..76697b647 100644 --- a/go.mod +++ b/go.mod @@ -1,18 +1,15 @@ module github.com/traefik/traefik/v2 -go 1.16 +go 1.17 -// github.com/docker/docker v17.12.0-ce-rc1.0.20200204220554-5f6d6f3f2203+incompatible => v19.03.6 require ( github.com/BurntSushi/toml v1.0.0 github.com/ExpediaDotCom/haystack-client-go v0.0.0-20190315171017-e7edbdf53a61 github.com/Masterminds/sprig/v3 v3.2.2 - github.com/Shopify/sarama v1.23.1 // indirect github.com/abbot/go-http-auth v0.0.0-00010101000000-000000000000 github.com/aws/aws-sdk-go v1.39.0 github.com/cenkalti/backoff/v4 v4.1.1 github.com/compose-spec/compose-go v1.0.3 - github.com/containerd/containerd v1.5.9 // indirect github.com/containous/alice v0.0.0-20181107144136-d83ebdd94cbd github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf github.com/davecgh/go-spew v1.1.1 @@ -20,7 +17,6 @@ require ( github.com/docker/compose/v2 v2.0.1 github.com/docker/docker v20.10.7+incompatible github.com/docker/go-connections v0.4.0 - github.com/donovanhide/eventsource v0.0.0-20170630084216-b8f31a59085e // indirect github.com/fatih/structs v1.1.0 github.com/gambol99/go-marathon v0.0.0-20180614232016-99a156b96fb2 github.com/go-acme/lego/v4 v4.6.0 @@ -29,7 +25,7 @@ require ( github.com/golang/protobuf v1.5.2 github.com/google/go-github/v28 v28.1.1 github.com/gorilla/mux v1.8.0 - github.com/gorilla/websocket v1.4.2 + github.com/gorilla/websocket v1.5.0 github.com/hashicorp/consul v1.10.4 github.com/hashicorp/consul/api v1.12.0 github.com/hashicorp/go-hclog v0.16.1 @@ -50,30 +46,27 @@ require ( github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5 github.com/openzipkin/zipkin-go v0.2.2 github.com/patrickmn/go-cache v2.1.0+incompatible - github.com/philhofer/fwd v1.0.0 // indirect github.com/pires/go-proxyproto v0.6.1 github.com/pmezard/go-difflib v1.0.0 github.com/prometheus/client_golang v1.11.0 github.com/prometheus/client_model v0.2.0 github.com/rancher/go-rancher-metadata v0.0.0-20200311180630-7f4c936a06ac github.com/sirupsen/logrus v1.8.1 - github.com/stretchr/testify v1.7.0 + github.com/stretchr/testify v1.7.1 github.com/stvp/go-udp-testing v0.0.0-20191102171040-06b61409b154 - github.com/tinylib/msgp v1.0.2 // indirect github.com/traefik/paerser v0.1.5 - github.com/traefik/yaegi v0.11.3 - github.com/uber/jaeger-client-go v2.29.1+incompatible + github.com/traefik/yaegi v0.12.0 + github.com/uber/jaeger-client-go v2.30.0+incompatible github.com/uber/jaeger-lib v2.2.0+incompatible github.com/unrolled/render v1.0.2 github.com/unrolled/secure v1.0.9 github.com/vdemeester/shakers v0.1.0 - github.com/vulcand/oxy v1.3.0 - github.com/vulcand/predicate v1.1.0 + github.com/vulcand/oxy v1.4.1 + github.com/vulcand/predicate v1.2.0 go.elastic.co/apm v1.13.1 go.elastic.co/apm/module/apmot v1.13.1 golang.org/x/mod v0.4.2 - golang.org/x/net v0.0.0-20211209124913-491a49abca63 - golang.org/x/sys v0.0.0-20210817190340-bfb29a6856f2 // indirect + golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4 golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2 google.golang.org/grpc v1.38.0 @@ -89,13 +82,252 @@ require ( sigs.k8s.io/gateway-api v0.4.0 ) +require ( + cloud.google.com/go v0.81.0 // indirect + github.com/AlecAivazis/survey/v2 v2.2.3 // indirect + github.com/Azure/azure-sdk-for-go v40.3.0+incompatible // indirect + github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect + github.com/Azure/go-autorest v14.2.0+incompatible // indirect + github.com/Azure/go-autorest/autorest v0.11.19 // indirect + github.com/Azure/go-autorest/autorest/adal v0.9.13 // indirect + github.com/Azure/go-autorest/autorest/azure/auth v0.5.8 // indirect + github.com/Azure/go-autorest/autorest/azure/cli v0.4.2 // indirect + github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect + github.com/Azure/go-autorest/autorest/to v0.4.0 // indirect + github.com/Azure/go-autorest/autorest/validation v0.3.1 // indirect + github.com/Azure/go-autorest/logger v0.2.1 // indirect + github.com/Azure/go-autorest/tracing v0.6.0 // indirect + github.com/DataDog/datadog-go v3.2.0+incompatible // indirect + github.com/HdrHistogram/hdrhistogram-go v1.1.2 // indirect + github.com/Masterminds/goutils v1.1.1 // indirect + github.com/Masterminds/semver/v3 v3.1.1 // indirect + github.com/Microsoft/go-winio v0.4.17 // indirect + github.com/Microsoft/hcsshim v0.8.23 // indirect + github.com/OpenDNS/vegadns2client v0.0.0-20180418235048-a3fa4a771d87 // indirect + github.com/Shopify/sarama v1.23.1 // indirect + github.com/VividCortex/gohistogram v1.0.0 // indirect + github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412 // indirect + github.com/akamai/AkamaiOPEN-edgegrid-golang v1.1.1 // indirect + github.com/aliyun/alibaba-cloud-sdk-go v1.61.1183 // indirect + github.com/armon/go-metrics v0.3.10 // indirect + github.com/armon/go-radix v1.0.0 // indirect + github.com/beorn7/perks v1.0.1 // indirect + github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc // indirect + github.com/buger/goterm v1.0.0 // indirect + github.com/cespare/xxhash/v2 v2.1.1 // indirect + github.com/cheekybits/genny v1.0.0 // indirect + github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible // indirect + github.com/circonus-labs/circonusllhist v0.1.3 // indirect + github.com/cloudflare/cloudflare-go v0.20.0 // indirect + github.com/compose-spec/godotenv v1.0.0 // indirect + github.com/containerd/cgroups v1.0.1 // indirect + github.com/containerd/console v1.0.2 // indirect + github.com/containerd/containerd v1.5.9 // indirect + github.com/containerd/continuity v0.1.0 // indirect + github.com/containerd/typeurl v1.0.2 // indirect + github.com/coreos/go-semver v0.3.0 // indirect + github.com/coreos/go-systemd/v22 v22.3.2 // indirect + github.com/cpu/goacmedns v0.1.1 // indirect + github.com/deepmap/oapi-codegen v1.8.2 // indirect + github.com/dimchansky/utfbom v1.1.1 // indirect + github.com/distribution/distribution/v3 v3.0.0-20210316161203-a01c71e2477e // indirect + github.com/dnsimple/dnsimple-go v0.70.1 // indirect + github.com/docker/buildx v0.5.2-0.20210422185057-908a856079fc // indirect + github.com/docker/distribution v2.7.1+incompatible // indirect + github.com/docker/docker-credential-helpers v0.6.4-0.20210125172408-38bea2ce277a // indirect + github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c // indirect + github.com/docker/go-metrics v0.0.1 // indirect + github.com/docker/go-units v0.4.0 // indirect + github.com/donovanhide/eventsource v0.0.0-20170630084216-b8f31a59085e // indirect + github.com/elastic/go-licenser v0.3.1 // indirect + github.com/elastic/go-sysinfo v1.1.1 // indirect + github.com/elastic/go-windows v1.0.0 // indirect + github.com/evanphx/json-patch v4.11.0+incompatible // indirect + github.com/exoscale/egoscale v0.67.0 // indirect + github.com/fatih/color v1.12.0 // indirect + github.com/form3tech-oss/jwt-go v3.2.3+incompatible // indirect + github.com/fsnotify/fsnotify v1.4.9 // indirect + github.com/fvbommel/sortorder v1.0.1 // indirect + github.com/go-errors/errors v1.0.1 // indirect + github.com/go-logfmt/logfmt v0.5.0 // indirect + github.com/go-logr/logr v0.4.0 // indirect + github.com/go-resty/resty/v2 v2.1.1-0.20191201195748-d7b97669fe48 // indirect + github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect + github.com/go-zookeeper/zk v1.0.2 // indirect + github.com/gofrs/flock v0.8.0 // indirect + github.com/gofrs/uuid v3.3.0+incompatible // indirect + github.com/gogo/googleapis v1.4.0 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect + github.com/golang/mock v1.6.0 // indirect + github.com/golang/snappy v0.0.3 // indirect + github.com/google/btree v1.0.1 // indirect + github.com/google/go-cmp v0.5.6 // indirect + github.com/google/go-querystring v1.1.0 // indirect + github.com/google/gofuzz v1.2.0 // indirect + github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect + github.com/google/uuid v1.2.0 // indirect + github.com/googleapis/gax-go/v2 v2.0.5 // indirect + github.com/googleapis/gnostic v0.5.5 // indirect + github.com/gophercloud/gophercloud v0.16.0 // indirect + github.com/gophercloud/utils v0.0.0-20210216074907-f6de111f2eae // indirect + github.com/gorilla/context v1.1.1 // indirect + github.com/gravitational/trace v1.1.16-0.20220114165159-14a9a7dd6aaf // indirect + github.com/grpc-ecosystem/go-grpc-middleware v1.2.0 // indirect + github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645 // indirect + github.com/hashicorp/consul/sdk v0.8.0 // indirect + github.com/hashicorp/errwrap v1.0.0 // indirect + github.com/hashicorp/go-cleanhttp v0.5.1 // indirect + github.com/hashicorp/go-immutable-radix v1.3.0 // indirect + github.com/hashicorp/go-msgpack v0.5.5 // indirect + github.com/hashicorp/go-retryablehttp v0.7.0 // indirect + github.com/hashicorp/go-rootcerts v1.0.2 // indirect + github.com/hashicorp/go-sockaddr v1.0.2 // indirect + github.com/hashicorp/go-uuid v1.0.2 // indirect + github.com/hashicorp/golang-lru v0.5.4 // indirect + github.com/hashicorp/hcl v1.0.0 // indirect + github.com/hashicorp/memberlist v0.3.0 // indirect + github.com/hashicorp/raft v1.3.2 // indirect + github.com/hashicorp/raft-autopilot v0.1.5 // indirect + github.com/hashicorp/serf v0.9.6 // indirect + github.com/hashicorp/yamux v0.0.0-20210826001029-26ff87cf9493 // indirect + github.com/huandu/xstrings v1.3.1 // indirect + github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df // indirect + github.com/imdario/mergo v0.3.12 // indirect + github.com/inconshreveable/mousetrap v1.0.0 // indirect + github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839 // indirect + github.com/infobloxopen/infoblox-go-client v1.1.1 // indirect + github.com/jaguilar/vt100 v0.0.0-20150826170717-2703a27b14ea // indirect + github.com/jarcoal/httpmock v1.0.6 // indirect + github.com/jcchavezs/porto v0.1.0 // indirect + github.com/jmespath/go-jmespath v0.4.0 // indirect + github.com/joeshaw/multierror v0.0.0-20140124173710-69b34d4ec901 // indirect + github.com/jonboulle/clockwork v0.2.2 // indirect + github.com/json-iterator/go v1.1.11 // indirect + github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213 // indirect + github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect + github.com/kolo/xmlrpc v0.0.0-20200310150728-e0350524596b // indirect + github.com/labbsr0x/bindman-dns-webhook v1.0.2 // indirect + github.com/labbsr0x/goh v1.0.1 // indirect + github.com/linode/linodego v0.31.1 // indirect + github.com/liquidweb/go-lwApi v0.0.5 // indirect + github.com/liquidweb/liquidweb-cli v0.6.9 // indirect + github.com/liquidweb/liquidweb-go v1.6.3 // indirect + github.com/looplab/fsm v0.1.0 // indirect + github.com/mailgun/minheap v0.0.0-20170619185613-3dbe6c6bf55f // indirect + github.com/mailgun/multibuf v0.1.2 // indirect + github.com/mailgun/timetools v0.0.0-20141028012446-7e6055773c51 // indirect + github.com/marten-seemann/qpack v0.2.1 // indirect + github.com/marten-seemann/qtls-go1-16 v0.1.5 // indirect + github.com/marten-seemann/qtls-go1-17 v0.1.1 // indirect + github.com/marten-seemann/qtls-go1-18 v0.1.1 // indirect + github.com/mattn/go-colorable v0.1.8 // indirect + github.com/mattn/go-isatty v0.0.12 // indirect + github.com/mattn/go-shellwords v1.0.12 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect + github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect + github.com/miekg/pkcs11 v1.0.3 // indirect + github.com/mitchellh/go-homedir v1.1.0 // indirect + github.com/mitchellh/go-testing-interface v1.14.0 // indirect + github.com/mitchellh/reflectwalk v1.0.1 // indirect + github.com/moby/buildkit v0.8.2-0.20210401015549-df49b648c8bf // indirect + github.com/moby/locker v1.0.1 // indirect + github.com/moby/sys/mount v0.2.0 // indirect + github.com/moby/sys/mountinfo v0.4.1 // indirect + github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.1 // indirect + github.com/morikuni/aec v1.0.0 // indirect + github.com/namedotcom/go v0.0.0-20180403034216-08470befbe04 // indirect + github.com/nrdcg/auroradns v1.0.1 // indirect + github.com/nrdcg/desec v0.6.0 // indirect + github.com/nrdcg/dnspod-go v0.4.0 // indirect + github.com/nrdcg/freemyip v0.2.0 // indirect + github.com/nrdcg/goinwx v0.8.1 // indirect + github.com/nrdcg/namesilo v0.2.1 // indirect + github.com/nrdcg/porkbun v0.1.1 // indirect + github.com/nxadm/tail v1.4.8 // indirect + github.com/onsi/ginkgo v1.16.4 // indirect + github.com/opencontainers/go-digest v1.0.0 // indirect + github.com/opencontainers/image-spec v1.0.2 // indirect + github.com/opencontainers/runc v1.0.2 // indirect + github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492 // indirect + github.com/oracle/oci-go-sdk v24.3.0+incompatible // indirect + github.com/ovh/go-ovh v1.1.0 // indirect + github.com/philhofer/fwd v1.0.0 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/pquerna/otp v1.3.0 // indirect + github.com/prometheus/common v0.26.0 // indirect + github.com/prometheus/procfs v0.6.0 // indirect + github.com/sacloud/libsacloud v1.36.2 // indirect + github.com/sanathkr/go-yaml v0.0.0-20170819195128-ed9d249f429b // indirect + github.com/santhosh-tekuri/jsonschema v1.2.4 // indirect + github.com/scaleway/scaleway-sdk-go v1.0.0-beta.7.0.20210127161313-bd30bebeac4f // indirect + github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 // indirect + github.com/segmentio/fasthash v1.0.3 // indirect + github.com/shopspring/decimal v1.2.0 // indirect + github.com/smartystreets/go-aws-auth v0.0.0-20180515143844-0c1422d1fdb9 // indirect + github.com/softlayer/softlayer-go v1.0.3 // indirect + github.com/softlayer/xmlrpc v0.0.0-20200409220501-5f089df7cb7e // indirect + github.com/spf13/cast v1.3.1 // indirect + github.com/spf13/cobra v1.2.1 // indirect + github.com/spf13/pflag v1.0.5 // indirect + github.com/stretchr/objx v0.3.0 // indirect + github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.287 // indirect + github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.287 // indirect + github.com/theupdateframework/notary v0.6.1 // indirect + github.com/tinylib/msgp v1.0.2 // indirect + github.com/tonistiigi/fsutil v0.0.0-20201103201449-0834f99b7b85 // indirect + github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea // indirect + github.com/transip/gotransip/v6 v6.6.1 // indirect + github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926 // indirect + github.com/vinyldns/go-vinyldns v0.9.16 // indirect + github.com/vultr/govultr/v2 v2.7.1 // indirect + github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect + github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect + github.com/xeipuuv/gojsonschema v1.2.0 // indirect + go.elastic.co/apm/module/apmhttp v1.13.1 // indirect + go.elastic.co/fastjson v1.1.0 // indirect + go.etcd.io/etcd/api/v3 v3.5.0 // indirect + go.etcd.io/etcd/client/pkg/v3 v3.5.0 // indirect + go.etcd.io/etcd/client/v3 v3.5.0 // indirect + go.opencensus.io v0.23.0 // indirect + go.uber.org/atomic v1.7.0 // indirect + go.uber.org/multierr v1.6.0 // indirect + go.uber.org/ratelimit v0.0.0-20180316092928-c15da0234277 // indirect + go.uber.org/zap v1.18.1 // indirect + golang.org/x/crypto v0.0.0-20220427172511-eb4f295cb31f // indirect + golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 // indirect + golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602 // indirect + golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect + golang.org/x/sys v0.0.0-20220307203707-22a9840ba4d7 // indirect + golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect + golang.org/x/text v0.3.7 // indirect + golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect + google.golang.org/api v0.44.0 // indirect + google.golang.org/appengine v1.6.7 // indirect + google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c // indirect + google.golang.org/protobuf v1.27.1 // indirect + gopkg.in/inf.v0 v0.9.1 // indirect + gopkg.in/ini.v1 v1.62.0 // indirect + gopkg.in/ns1/ns1-go.v2 v2.6.2 // indirect + gopkg.in/redis.v5 v5.2.9 // indirect + gopkg.in/square/go-jose.v2 v2.6.0 // indirect + gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect + howett.net/plist v0.0.0-20181124034731-591f970eefbb // indirect + k8s.io/klog/v2 v2.10.0 // indirect + k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e // indirect + sigs.k8s.io/structured-merge-diff/v4 v4.1.2 // indirect + sigs.k8s.io/yaml v1.2.0 // indirect +) + // Containous forks replace ( github.com/abbot/go-http-auth => github.com/containous/go-http-auth v0.4.1-0.20200324110947-a37a7636d23e github.com/go-check/check => github.com/containous/check v0.0.0-20170915194414-ca0bf163426a github.com/gorilla/mux => github.com/containous/mux v0.0.0-20220113180107-8ffa4f6d063c github.com/mailgun/minheap => github.com/containous/minheap v0.0.0-20190809180810-6e71eb837595 - github.com/mailgun/multibuf => github.com/containous/multibuf v0.0.0-20220419123348-2d0b12e116c6 ) // https://github.com/docker/compose/blob/e44222664abd07ce1d1fe6796d84d93cbc7468c3/go.mod#L131 diff --git a/go.sum b/go.sum index 9f3f80268..d6d978342 100644 --- a/go.sum +++ b/go.sum @@ -125,6 +125,8 @@ github.com/ExpediaDotCom/haystack-client-go v0.0.0-20190315171017-e7edbdf53a61 h github.com/ExpediaDotCom/haystack-client-go v0.0.0-20190315171017-e7edbdf53a61/go.mod h1:62qWSDaEI0BLykU+zQza5CAKgW0lOy9oBSz3/DvYz4w= github.com/GeertJohan/go.incremental v1.0.0/go.mod h1:6fAjUhbVuX1KcMD3c8TEgVUqmo4seqhv0i0kdATSkM0= github.com/GeertJohan/go.rice v1.0.0/go.mod h1:eH6gbSOAUv07dQuZVnBmoDP8mgsM1rtixis4Tib9if0= +github.com/HdrHistogram/hdrhistogram-go v1.1.2 h1:5IcZpTvzydCQeHzK4Ef/D5rrSqwxob0t8PQPMybUNFM= +github.com/HdrHistogram/hdrhistogram-go v1.1.2/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= @@ -184,6 +186,7 @@ github.com/agext/levenshtein v1.2.1/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412 h1:w1UutsfOrms1J05zt7ISrnJIXKzwaspym5BTKGx93EI= github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412/go.mod h1:WPjqKcmVOxf0XSf3YxCJs6N6AOSrOx3obionmG7T0y0= github.com/ahmetb/gen-crd-api-reference-docs v0.3.0/go.mod h1:TdjdkYhlOifCQWPs1UdTma97kQQMozf5h26hTuG70u8= +github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= github.com/akamai/AkamaiOPEN-edgegrid-golang v1.1.1 h1:bLzehmpyCwQiqCE1Qe9Ny6fbFqs7hPlmo9vKv2orUxs= github.com/akamai/AkamaiOPEN-edgegrid-golang v1.1.1/go.mod h1:kX6YddBkXqqywAe8c9LyvgTCyFuZCTMF4cRPQhc3Fy8= github.com/akavel/rsrc v0.8.0/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c= @@ -426,8 +429,6 @@ github.com/containous/go-http-auth v0.4.1-0.20200324110947-a37a7636d23e h1:D+uTE github.com/containous/go-http-auth v0.4.1-0.20200324110947-a37a7636d23e/go.mod h1:s8kLgBQolDbsJOPVIGCEEv9zGAKUUf/685Gi0Qqg8z8= github.com/containous/minheap v0.0.0-20190809180810-6e71eb837595 h1:aPspFRO6b94To3gl4yTDOEtpjFwXI7V2W+z0JcNljQ4= github.com/containous/minheap v0.0.0-20190809180810-6e71eb837595/go.mod h1:+lHFbEasIiQVGzhVDVw/cn0ZaOzde2OwNncp1NhXV4c= -github.com/containous/multibuf v0.0.0-20220419123348-2d0b12e116c6 h1:KzERnBo5Jn4RRKjo8hdDPS4llWjHlJtM6kfm4mRkIew= -github.com/containous/multibuf v0.0.0-20220419123348-2d0b12e116c6/go.mod h1:zkWcASFUJEst6QwCrxLdkuw1gvaKqmflEipm+iecV5M= github.com/containous/mux v0.0.0-20220113180107-8ffa4f6d063c h1:g6JvgTtfpS6AfhRjY87NZ0g39CrNDbdm8R+1CD85Cfo= github.com/containous/mux v0.0.0-20220113180107-8ffa4f6d063c/go.mod h1:z8WW7n06n8/1xF9Jl9WmuDeZuHAhfL+bwarNjsciwwg= github.com/coredns/coredns v1.1.2/go.mod h1:zASH/MVDgR6XZTbxvOnsZfffS+31vg6Ackf/wo1+AM0= @@ -599,6 +600,7 @@ github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= +github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= github.com/form3tech-oss/jwt-go v3.2.3+incompatible h1:7ZaBxOI7TMoYBfyA3cQHErNNyAWIKUMIwqxEtgHOs5c= github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= @@ -710,6 +712,7 @@ github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXP github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/goji/httpauth v0.0.0-20160601135302-2da839ab0f4d/go.mod h1:nnjvkQ9ptGaCkuDUx6wNykzzlUixGxvkme+H/lnzb+A= +github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -843,11 +846,12 @@ github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33/go.mod h1:Qkdc/uu github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q= github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= -github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gotestyourself/gotestyourself v2.2.0+incompatible/go.mod h1:zZKM6oeNM8k+FRljX1mnzVYeS8wiGgQyvST1/GafPbY= -github.com/gravitational/trace v0.0.0-20190726142706-a535a178675f h1:68WxnfBzJRYktZ30fmIjGQ74RsXYLoeH2/NITPktTMY= -github.com/gravitational/trace v0.0.0-20190726142706-a535a178675f/go.mod h1:RvdOUHE4SHqR3oXlFFKnGzms8a5dugHygGw1bqDstYI= +github.com/gravitational/trace v1.1.16-0.20220114165159-14a9a7dd6aaf h1:C1GPyPJrOlJlIrcaBBiBpDsqZena2Ks8spa5xZqr1XQ= +github.com/gravitational/trace v1.1.16-0.20220114165159-14a9a7dd6aaf/go.mod h1:zXqxTI6jXDdKnlf8s+nT+3c8LrwUEy3yNpO4XJL90lA= github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= @@ -1037,8 +1041,9 @@ github.com/jmhodges/clock v0.0.0-20160418191101-880ee4c33548/go.mod h1:hGT6jSUVz github.com/jmoiron/sqlx v0.0.0-20180124204410-05cef0741ade/go.mod h1:IiEW3SEiiErVyFdH8NTuWjSifiEQKUoyK3LNqr2kCHU= github.com/joeshaw/multierror v0.0.0-20140124173710-69b34d4ec901 h1:rp+c0RAYOWj8l6qbCUTSiRLG/iKnW3K3/QfPPuSsBt4= github.com/joeshaw/multierror v0.0.0-20140124173710-69b34d4ec901/go.mod h1:Z86h9688Y0wesXCyonoVr47MasHilkuLMqGhRZ4Hpak= -github.com/jonboulle/clockwork v0.1.0 h1:VKV+ZcuP6l3yW9doeqz6ziZGgcynBVQO+obU0+0hcPo= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ= +github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/joyent/triton-go v0.0.0-20180628001255-830d2b111e62/go.mod h1:U+RSyWxWd04xTqnuOQxnai7XGS2PrPY2cfGoDKtMHjA= github.com/joyent/triton-go v1.7.1-0.20200416154420-6801d15b779f/go.mod h1:KDSfL7qe5ZfQqvlDMkVjCztbmcpp/c8M77vhQP8ZPvk= @@ -1059,6 +1064,7 @@ github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7 github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= +github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213 h1:qGQQKEcAR99REcMpsXCp3lJ03zYT1PkRd3kQGPn9GVg= github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213/go.mod h1:vNUNkEQ1e29fT/6vq2aBdFsgNPmy8qMdSay1npru+Sw= github.com/kardianos/osext v0.0.0-20170510131534-ae77be60afb1/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8= @@ -1133,6 +1139,8 @@ github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czP github.com/magiconair/properties v1.8.4/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/magiconair/properties v1.8.5 h1:b6kJs+EmPFMYGkow9GiUyCyOvIwYetYJ3fSaWak/Gls= github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= +github.com/mailgun/multibuf v0.1.2 h1:QE9kE27lK6LFZB4aYNVtUPlWVHVCT0zpgUr2uoq/+jk= +github.com/mailgun/multibuf v0.1.2/go.mod h1:E+sUhIy69qgT6EM57kCPdUTlHnjTuxQBO/yf6af9Hes= github.com/mailgun/timetools v0.0.0-20141028012446-7e6055773c51 h1:Kg/NPZLLC3aAFr1YToMs98dbCdhootQ1hZIvZU28hAQ= github.com/mailgun/timetools v0.0.0-20141028012446-7e6055773c51/go.mod h1:RYmqHbhWwIz3z9eVmQ2rx82rulEMG0t+Q1bzfc9DYN4= github.com/mailgun/ttlmap v0.0.0-20170619185759-c1c17f74874f h1:ZZYhg16XocqSKPGNQAe0aeweNtFxuedbwwb4fSlg7h4= @@ -1627,8 +1635,9 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stvp/go-udp-testing v0.0.0-20191102171040-06b61409b154 h1:XGopsea1Dw7ecQ8JscCNQXDGYAKDiWjDeXnpN/+BY9g= github.com/stvp/go-udp-testing v0.0.0-20191102171040-06b61409b154/go.mod h1:7jxmlfBCDBXRzr0eAQJ48XC1hBu1np4CS5+cHEYfwpc= github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= @@ -1657,8 +1666,8 @@ github.com/tonistiigi/vt100 v0.0.0-20190402012908-ad4c4a574305 h1:y/1cL5AL2oRcfz github.com/tonistiigi/vt100 v0.0.0-20190402012908-ad4c4a574305/go.mod h1:gXOLibKqQTRAVuVZ9gX7G9Ykky8ll8yb4slxsEMoY0c= github.com/traefik/paerser v0.1.5 h1:crit7KzQ9PUWGCYu+H2acwyr7ZKb3RQDSn6iJCtxBhE= github.com/traefik/paerser v0.1.5/go.mod h1:Fuwl9DWJfGpZPPwZY6djYIF0vhvzhLmCizn6P66UeLY= -github.com/traefik/yaegi v0.11.3 h1:TuuIc0TC4oaWkVngjVAKkFd4fH35B0B95DmbS76uqs8= -github.com/traefik/yaegi v0.11.3/go.mod h1:RuCwD8/wsX7b6KoQHOaIFUfuH3gQIK4KWnFFmJMw5VA= +github.com/traefik/yaegi v0.12.0 h1:1gSdARfQ5JB/yEvwEyy9e0AOyLuJrocGiDfkTftQpEo= +github.com/traefik/yaegi v0.12.0/go.mod h1:RuCwD8/wsX7b6KoQHOaIFUfuH3gQIK4KWnFFmJMw5VA= github.com/transip/gotransip/v6 v6.6.1 h1:nsCU1ErZS5G0FeOpgGXc4FsWvBff9GPswSMggsC4564= github.com/transip/gotransip/v6 v6.6.1/go.mod h1:pQZ36hWWRahCUXkFWlx9Hs711gLd8J4qdgLdRzmtY+g= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926 h1:G3dpKMzFDjgEh2q1Z7zUUtKa8ViPtH+ocF0bE0g00O8= @@ -1666,8 +1675,8 @@ github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqri github.com/uber-go/atomic v1.3.2 h1:Azu9lPBWRNKzYXSIwRfgRuDuS0YKsK4NFhiQv98gkxo= github.com/uber-go/atomic v1.3.2/go.mod h1:/Ct5t2lcmbJ4OSe/waGBoaVvVqtO0bmtfVNex1PFV8g= github.com/uber/jaeger-client-go v2.25.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= -github.com/uber/jaeger-client-go v2.29.1+incompatible h1:R9ec3zO3sGpzs0abd43Y+fBZRJ9uiH6lXyR/+u6brW4= -github.com/uber/jaeger-client-go v2.29.1+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= +github.com/uber/jaeger-client-go v2.30.0+incompatible h1:D6wyKGCecFaSRUpo8lCVbaOOb6ThwMmTEbhRwtKR97o= +github.com/uber/jaeger-client-go v2.30.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= github.com/uber/jaeger-lib v2.2.0+incompatible h1:MxZXOiR2JuoANZ3J6DE/U0kSFv/eJ/GfSYVCjK7dyaw= github.com/uber/jaeger-lib v2.2.0+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= @@ -1703,10 +1712,10 @@ github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6Ac github.com/vmihailenco/msgpack/v4 v4.3.12/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4= github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI= github.com/vmware/govmomi v0.18.0/go.mod h1:URlwyTFZX72RmxtxuaFL2Uj3fD1JTvZdx59bHWk6aFU= -github.com/vulcand/oxy v1.3.0 h1:358BVHmJNLjhOrhbjq2EVJX5NQ3HxrP0d5OyHLRliX0= -github.com/vulcand/oxy v1.3.0/go.mod h1:hN/gw/jg+GH4A+bqvznsW26Izd4jNGV6h1z3s7drRzs= -github.com/vulcand/predicate v1.1.0 h1:Gq/uWopa4rx/tnZu2opOSBqHK63Yqlou/SzrbwdJiNg= -github.com/vulcand/predicate v1.1.0/go.mod h1:mlccC5IRBoc2cIFmCB8ZM62I3VDb6p2GXESMHa3CnZg= +github.com/vulcand/oxy v1.4.1 h1:8FUsbr5xhSJqNlSrpUBcw93WuZIEI9JUyvThB9YqqF8= +github.com/vulcand/oxy v1.4.1/go.mod h1:Yq8OBb0XWU/7nPSglwUH5LS2Pcp4yvad8SVayobZbSo= +github.com/vulcand/predicate v1.2.0 h1:uFsW1gcnnR7R+QTID+FVcs0sSYlIGntoGOTb3rQJt50= +github.com/vulcand/predicate v1.2.0/go.mod h1:VipoNYXny6c8N381zGUWkjuuNHiRbeAZhE7Qm9c+2GA= github.com/vultr/govultr/v2 v2.7.1 h1:uF9ERet++Gb+7Cqs3p1P6b6yebeaZqVd7t5P2uZCaJU= github.com/vultr/govultr/v2 v2.7.1/go.mod h1:BvOhVe6/ZpjwcoL6/unkdQshmbS9VGbowI4QT+3DGVU= github.com/weppos/publicsuffix-go v0.4.0/go.mod h1:z3LCPQ38eedDQSwmsSRW4Y7t2L8Ln16JPQ02lHAdn5k= @@ -1840,9 +1849,13 @@ golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWP golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= -golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e h1:gsTQYXdTw2Gq7RBsWvlQ91b+aEQ6bXFUngBGuR8sPpI= golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20220427172511-eb4f295cb31f h1:OeJjE6G4dgCY4PIXvIRQbE8+RX+uXZyGhUy/ksMGJoc= +golang.org/x/crypto v0.0.0-20220427172511-eb4f295cb31f/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= @@ -1851,7 +1864,9 @@ golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6 h1:QE6XYQK6naiK1EPAe1g/ILLxN5RBoH5xkJk3CqlMI/Y= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -1945,8 +1960,9 @@ golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210520170846-37e1c6afe023/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211209124913-491a49abca63 h1:iocB37TsdFuN6IBRZ+ry36wrkoV51/tl5vOWqkcPGvY= -golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4 h1:HVyaeDAYux4pnY+D/SiwmLOR36ewZ4iGQIIrtnuCjFA= +golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/oauth2 v0.0.0-20180724155351-3d292e4d0cdc/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -2093,12 +2109,14 @@ golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210817190340-bfb29a6856f2 h1:c8PlLMqBbOHoqtjteWm5/kbe6rNY2pbRfbIMVnepueo= -golang.org/x/sys v0.0.0-20210817190340-bfb29a6856f2/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220307203707-22a9840ba4d7 h1:8IVLkfbr2cLhv0a/vKq4UFUcJym8RmDoDboxCFWEjYE= +golang.org/x/sys v0.0.0-20220307203707-22a9840ba4d7/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d h1:SZxvLBoTP5yHO3Frd4z4vrF+DBX9vMVanchswa69toE= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -2107,8 +2125,9 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -2121,12 +2140,14 @@ golang.org/x/time v0.0.0-20210611083556-38a9dc6acbc6/go.mod h1:tRJNPiyCQ0inRvYxb golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac h1:7zkz7BUtwNFFqcowJ+RIgu2MaV/MapERkDIy+mwPyjs= golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= @@ -2198,6 +2219,11 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gomodules.xyz/jsonpatch/v2 v2.2.0/go.mod h1:WXp+iVDkoLQqPudfQ9GBlwB2eZ5DKOnjQZCYdOS8GPY= +gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= +gonum.org/v1/gonum v0.8.2 h1:CCXrcPKiGGotvnN6jfUsKk4rRqm7q09/YbKb5xCEvtM= +gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0= +gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= +gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc= google.golang.org/api v0.0.0-20160322025152-9bf6e6e569ff/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= @@ -2506,6 +2532,7 @@ launchpad.net/gocheck v0.0.0-20140225173054-000000000087/go.mod h1:hj7XX3B/0A+80 mvdan.cc/xurls/v2 v2.1.0 h1:KaMb5GLhlcSX+e+qhbRJODnUUBvlw01jt4yrjFIHAuA= mvdan.cc/xurls/v2 v2.1.0/go.mod h1:5GrSd9rOnKOpZaji1OZLYL/yeAAtGDlo/cFe+8K5n8E= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.14/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= diff --git a/integration/https_test.go b/integration/https_test.go index b10eb37f2..6ddda5e8e 100644 --- a/integration/https_test.go +++ b/integration/https_test.go @@ -1072,7 +1072,7 @@ func (s *HTTPSSuite) TestEntryPointHttpsRedirectAndPathModification(c *check.C) resp.Body.Close() location := resp.Header.Get("Location") - expected := fmt.Sprintf("https://%s:8443%s", host, test.path) + expected := "https://" + net.JoinHostPort(host, "8443") + test.path c.Assert(location, checker.Equals, expected) } diff --git a/integration/timeout_test.go b/integration/timeout_test.go index b5a68e7e9..68c5886ca 100644 --- a/integration/timeout_test.go +++ b/integration/timeout_test.go @@ -2,6 +2,7 @@ package integration import ( "fmt" + "net" "net/http" "os" "time" @@ -38,7 +39,8 @@ func (s *TimeoutSuite) TestForwardingTimeouts(c *check.C) { c.Assert(response.StatusCode, checker.Equals, http.StatusGatewayTimeout) // Check that timeout service is available - statusURL := fmt.Sprintf("http://%s:9000/statusTest?status=200", timeoutEndpointIP) + statusURL := fmt.Sprintf("http://%s/statusTest?status=200", + net.JoinHostPort(timeoutEndpointIP, "9000")) c.Assert(try.GetRequest(statusURL, 60*time.Second, try.StatusCodeIs(http.StatusOK)), checker.IsNil) // This simulates a ResponseHeaderTimeout. diff --git a/pkg/collector/collector.go b/pkg/collector/collector.go index 0fec4f061..50ce0666d 100644 --- a/pkg/collector/collector.go +++ b/pkg/collector/collector.go @@ -16,7 +16,7 @@ import ( "github.com/traefik/traefik/v2/pkg/version" ) -// collectorURL URL where the stats are send. +// collectorURL URL where the stats are sent. const collectorURL = "https://collect.traefik.io/9vxmmkcdmalbdi635d4jgc5p5rx0h7h8" // Collected data. @@ -30,16 +30,30 @@ type data struct { // Collect anonymous data. func Collect(staticConfiguration *static.Configuration) error { - anonConfig, err := redactor.Anonymize(staticConfiguration) + buf, err := createBody(staticConfiguration) if err != nil { return err } + resp, err := makeHTTPClient().Post(collectorURL, "application/json; charset=utf-8", buf) + if resp != nil { + _ = resp.Body.Close() + } + + return err +} + +func createBody(staticConfiguration *static.Configuration) (*bytes.Buffer, error) { + anonConfig, err := redactor.Anonymize(staticConfiguration) + if err != nil { + return nil, err + } + log.WithoutContext().Infof("Anonymous stats sent to %s: %s", collectorURL, anonConfig) hashConf, err := hashstructure.Hash(staticConfiguration, nil) if err != nil { - return err + return nil, err } data := &data{ @@ -53,15 +67,10 @@ func Collect(staticConfiguration *static.Configuration) error { buf := new(bytes.Buffer) err = json.NewEncoder(buf).Encode(data) if err != nil { - return err + return nil, err } - resp, err := makeHTTPClient().Post(collectorURL, "application/json; charset=utf-8", buf) - if resp != nil { - resp.Body.Close() - } - - return err + return buf, err } func makeHTTPClient() *http.Client { diff --git a/pkg/collector/collector_test.go b/pkg/collector/collector_test.go new file mode 100644 index 000000000..b091f0c4f --- /dev/null +++ b/pkg/collector/collector_test.go @@ -0,0 +1,21 @@ +package collector + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/traefik/traefik/v2/pkg/config/static" +) + +func Test_createBody(t *testing.T) { + var staticConfiguration static.Configuration + + err := hydrate(&staticConfiguration) + require.NoError(t, err) + + buffer, err := createBody(&staticConfiguration) + require.NoError(t, err) + + assert.NotEmpty(t, buffer) +} diff --git a/pkg/collector/hydration_test.go b/pkg/collector/hydration_test.go new file mode 100644 index 000000000..8814888a6 --- /dev/null +++ b/pkg/collector/hydration_test.go @@ -0,0 +1,166 @@ +package collector + +import ( + "fmt" + "reflect" + "time" + + "github.com/traefik/paerser/types" +) + +const ( + sliceItemNumber = 2 + mapItemNumber = 2 + defaultString = "foobar" + defaultNumber = 42 + defaultBool = true + defaultMapKeyPrefix = "name" +) + +func hydrate(element interface{}) error { + field := reflect.ValueOf(element) + return fill(field) +} + +func fill(field reflect.Value) error { + switch field.Kind() { + case reflect.Struct: + if err := setStruct(field); err != nil { + return err + } + case reflect.Ptr: + if err := setPointer(field); err != nil { + return err + } + case reflect.Slice: + if err := setSlice(field); err != nil { + return err + } + case reflect.Map: + if err := setMap(field); err != nil { + return err + } + case reflect.Interface: + if err := fill(field.Elem()); err != nil { + return err + } + case reflect.String: + setTyped(field, defaultString) + case reflect.Int: + setTyped(field, defaultNumber) + case reflect.Int8: + setTyped(field, int8(defaultNumber)) + case reflect.Int16: + setTyped(field, int16(defaultNumber)) + case reflect.Int32: + setTyped(field, int32(defaultNumber)) + case reflect.Int64: + switch field.Type() { + case reflect.TypeOf(types.Duration(time.Second)): + setTyped(field, int64(defaultNumber*int(time.Second))) + default: + setTyped(field, int64(defaultNumber)) + } + case reflect.Uint: + setTyped(field, uint(defaultNumber)) + case reflect.Uint8: + setTyped(field, uint8(defaultNumber)) + case reflect.Uint16: + setTyped(field, uint16(defaultNumber)) + case reflect.Uint32: + setTyped(field, uint32(defaultNumber)) + case reflect.Uint64: + setTyped(field, uint64(defaultNumber)) + case reflect.Bool: + setTyped(field, defaultBool) + case reflect.Float32: + setTyped(field, float32(defaultNumber)) + case reflect.Float64: + setTyped(field, float64(defaultNumber)) + } + + return nil +} + +func setTyped(field reflect.Value, i interface{}) { + baseValue := reflect.ValueOf(i) + if field.Kind().String() == field.Type().String() { + field.Set(baseValue) + } else { + field.Set(baseValue.Convert(field.Type())) + } +} + +func setMap(field reflect.Value) error { + field.Set(reflect.MakeMap(field.Type())) + + for i := 0; i < mapItemNumber; i++ { + baseKeyName := makeKeyName(field.Type().Elem()) + key := reflect.ValueOf(fmt.Sprintf("%s%d", baseKeyName, i)) + + // generate value + ptrType := reflect.PtrTo(field.Type().Elem()) + ptrValue := reflect.New(ptrType) + if err := fill(ptrValue); err != nil { + return err + } + value := ptrValue.Elem().Elem() + + field.SetMapIndex(key, value) + } + return nil +} + +func makeKeyName(typ reflect.Type) string { + switch typ.Kind() { + case reflect.Ptr: + return typ.Elem().Name() + case reflect.String, + reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, + reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, + reflect.Bool, reflect.Float32, reflect.Float64: + return defaultMapKeyPrefix + default: + return typ.Name() + } +} + +func setStruct(field reflect.Value) error { + for i := 0; i < field.NumField(); i++ { + fld := field.Field(i) + stFld := field.Type().Field(i) + + if !stFld.IsExported() || fld.Kind() == reflect.Func { + continue + } + + if err := fill(fld); err != nil { + return err + } + } + return nil +} + +func setSlice(field reflect.Value) error { + field.Set(reflect.MakeSlice(field.Type(), sliceItemNumber, sliceItemNumber)) + for j := 0; j < field.Len(); j++ { + if err := fill(field.Index(j)); err != nil { + return err + } + } + return nil +} + +func setPointer(field reflect.Value) error { + if field.IsNil() { + field.Set(reflect.New(field.Type().Elem())) + if err := fill(field.Elem()); err != nil { + return err + } + } else { + if err := fill(field.Elem()); err != nil { + return err + } + } + return nil +} diff --git a/pkg/config/static/hub.go b/pkg/config/static/hub.go new file mode 100644 index 000000000..ee78de975 --- /dev/null +++ b/pkg/config/static/hub.go @@ -0,0 +1,53 @@ +package static + +import ( + "errors" + + "github.com/traefik/traefik/v2/pkg/log" + "github.com/traefik/traefik/v2/pkg/provider/hub" +) + +func (c *Configuration) initHubProvider() error { + // Hub provider is an experimental feature. It requires the experimental flag to be enabled before continuing. + if c.Experimental == nil || !c.Experimental.Hub { + return errors.New("the experimental flag for Hub is not set") + } + + if _, ok := c.EntryPoints[hub.TunnelEntrypoint]; !ok { + var ep EntryPoint + ep.SetDefaults() + ep.Address = ":9901" + c.EntryPoints[hub.TunnelEntrypoint] = &ep + log.WithoutContext().Infof("The entryPoint %q is created on port 9901 to allow exposition of services.", hub.TunnelEntrypoint) + } + + if c.Hub.TLS == nil { + return nil + } + + if c.Hub.TLS.Insecure && (c.Hub.TLS.CA != "" || c.Hub.TLS.Cert != "" || c.Hub.TLS.Key != "") { + return errors.New("mTLS configuration for Hub and insecure TLS for Hub are mutually exclusive") + } + + if !c.Hub.TLS.Insecure && (c.Hub.TLS.CA == "" || c.Hub.TLS.Cert == "" || c.Hub.TLS.Key == "") { + return errors.New("incomplete mTLS configuration for Hub") + } + + if c.Hub.TLS.Insecure { + log.WithoutContext().Warn("Hub is in `insecure` mode. Do not run in production with this setup.") + } + + if _, ok := c.EntryPoints[hub.APIEntrypoint]; !ok { + var ep EntryPoint + ep.SetDefaults() + ep.Address = ":9900" + c.EntryPoints[hub.APIEntrypoint] = &ep + log.WithoutContext().Infof("The entryPoint %q is created on port 9900 to allow Traefik to communicate with the Hub Agent for Traefik.", hub.APIEntrypoint) + } + + c.EntryPoints[hub.APIEntrypoint].HTTP.TLS = &TLSConfig{ + Options: "traefik-hub", + } + + return nil +} diff --git a/pkg/config/static/pilot.go b/pkg/config/static/pilot.go index f3699a729..147c8917b 100644 --- a/pkg/config/static/pilot.go +++ b/pkg/config/static/pilot.go @@ -1,7 +1,6 @@ package static // Pilot Configuration related to Traefik Pilot. -// Deprecated. type Pilot struct { Token string `description:"Traefik Pilot token." json:"token,omitempty" toml:"token,omitempty" yaml:"token,omitempty" loggable:"false"` Dashboard bool `description:"Enable Traefik Pilot in the dashboard." json:"dashboard,omitempty" toml:"dashboard,omitempty" yaml:"dashboard,omitempty"` diff --git a/pkg/config/static/static_config.go b/pkg/config/static/static_config.go index 961786f94..b285996f8 100644 --- a/pkg/config/static/static_config.go +++ b/pkg/config/static/static_config.go @@ -1,7 +1,6 @@ package static import ( - "errors" "fmt" stdlog "log" "strings" @@ -78,7 +77,6 @@ type Configuration struct { CertificatesResolvers map[string]CertificateResolver `description:"Certificates resolvers configuration." json:"certificatesResolvers,omitempty" toml:"certificatesResolvers,omitempty" yaml:"certificatesResolvers,omitempty" export:"true"` - // Deprecated. Pilot *Pilot `description:"Traefik Pilot configuration." json:"pilot,omitempty" toml:"pilot,omitempty" yaml:"pilot,omitempty" export:"true"` Hub *hub.Provider `description:"Traefik Hub configuration." json:"hub,omitempty" toml:"hub,omitempty" yaml:"hub,omitempty" label:"allowEmpty" file:"allowEmpty" export:"true"` @@ -201,7 +199,7 @@ type Providers struct { // It also takes care of maintaining backwards compatibility. func (c *Configuration) SetEffectiveConfiguration() { // Creates the default entry point if needed - if len(c.EntryPoints) == 0 || (c.Hub != nil && len(c.EntryPoints) == 1 && c.EntryPoints[c.Hub.EntryPoint] != nil) { + if !c.hasUserDefinedEntrypoint() { ep := &EntryPoint{Address: ":80"} ep.SetDefaults() // TODO: double check this tomorrow @@ -287,6 +285,21 @@ func (c *Configuration) SetEffectiveConfiguration() { c.initACMEProvider() } +func (c *Configuration) hasUserDefinedEntrypoint() bool { + if len(c.EntryPoints) == 0 { + return false + } + + switch len(c.EntryPoints) { + case 1: + return c.EntryPoints[hub.TunnelEntrypoint] == nil + case 2: + return c.EntryPoints[hub.TunnelEntrypoint] == nil || c.EntryPoints[hub.APIEntrypoint] == nil + default: + return true + } +} + func (c *Configuration) initACMEProvider() { for _, resolver := range c.CertificatesResolvers { if resolver.ACME != nil { @@ -297,46 +310,6 @@ func (c *Configuration) initACMEProvider() { legolog.Logger = stdlog.New(log.WithoutContext().WriterLevel(logrus.DebugLevel), "legolog: ", 0) } -func (c *Configuration) initHubProvider() error { - // Hub provider is an experimental feature. Require the experimental flag to be enabled before continuing. - if c.Experimental == nil || !c.Experimental.Hub { - return errors.New("experimental flag for Hub not set") - } - - if c.Hub.TLS == nil { - return errors.New("no TLS configuration defined for Hub") - } - - if c.Hub.TLS.Insecure && (c.Hub.TLS.CA != "" || c.Hub.TLS.Cert != "" || c.Hub.TLS.Key != "") { - return errors.New("mTLS configuration for Hub and insecure TLS for Hub are mutually exclusive") - } - - if !c.Hub.TLS.Insecure && (c.Hub.TLS.CA == "" || c.Hub.TLS.Cert == "" || c.Hub.TLS.Key == "") { - return errors.New("incomplete mTLS configuration for Hub") - } - - if c.Hub.TLS.Insecure { - log.WithoutContext().Warn("Hub is in `insecure` mode. Do not run in production with this setup.") - } - - // Creates the internal Hub entry point if needed. - if c.Hub.EntryPoint == hub.DefaultEntryPointName { - if _, ok := c.EntryPoints[hub.DefaultEntryPointName]; !ok { - var ep EntryPoint - ep.SetDefaults() - ep.Address = ":9900" - c.EntryPoints[hub.DefaultEntryPointName] = &ep - log.WithoutContext().Infof("The entryPoint %q is created on port 9900 to allow Traefik to communicate with the Hub Agent for Traefik.", hub.DefaultEntryPointName) - } - } - - c.EntryPoints[c.Hub.EntryPoint].HTTP.TLS = &TLSConfig{ - Options: "traefik-hub", - } - - return nil -} - // ValidateConfiguration validate that configuration is coherent. func (c *Configuration) ValidateConfiguration() error { var acmeEmail string diff --git a/pkg/config/static/static_config_test.go b/pkg/config/static/static_config_test.go new file mode 100644 index 000000000..9680233dd --- /dev/null +++ b/pkg/config/static/static_config_test.go @@ -0,0 +1,88 @@ +package static + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/traefik/traefik/v2/pkg/provider/hub" +) + +func TestHasEntrypoint(t *testing.T) { + tests := []struct { + desc string + entryPoints map[string]*EntryPoint + assert assert.BoolAssertionFunc + }{ + { + desc: "no user defined entryPoints", + assert: assert.False, + }, + { + desc: "user defined entryPoints", + entryPoints: map[string]*EntryPoint{ + "foo": {}, + }, + assert: assert.True, + }, + { + desc: "user defined entryPoints + hub entryPoint (tunnel)", + entryPoints: map[string]*EntryPoint{ + "foo": {}, + hub.TunnelEntrypoint: {}, + }, + assert: assert.True, + }, + { + desc: "hub entryPoint (tunnel)", + entryPoints: map[string]*EntryPoint{ + hub.TunnelEntrypoint: {}, + }, + assert: assert.False, + }, + { + desc: "user defined entryPoints + hub entryPoint (api)", + entryPoints: map[string]*EntryPoint{ + "foo": {}, + hub.APIEntrypoint: {}, + }, + assert: assert.True, + }, + { + desc: "hub entryPoint (api)", + entryPoints: map[string]*EntryPoint{ + hub.APIEntrypoint: {}, + }, + assert: assert.True, + }, + { + desc: "user defined entryPoints + hub entryPoints (tunnel, api)", + entryPoints: map[string]*EntryPoint{ + "foo": {}, + hub.TunnelEntrypoint: {}, + hub.APIEntrypoint: {}, + }, + assert: assert.True, + }, + { + desc: "hub entryPoints (tunnel, api)", + entryPoints: map[string]*EntryPoint{ + hub.TunnelEntrypoint: {}, + hub.APIEntrypoint: {}, + }, + assert: assert.False, + }, + } + + for _, test := range tests { + test := test + t.Run(test.desc, func(t *testing.T) { + t.Parallel() + + cfg := &Configuration{ + EntryPoints: test.entryPoints, + } + + test.assert(t, cfg.hasUserDefinedEntrypoint()) + }) + } +} diff --git a/pkg/muxer/tcp/mux.go b/pkg/muxer/tcp/mux.go index b82675614..a70e5fd34 100644 --- a/pkg/muxer/tcp/mux.go +++ b/pkg/muxer/tcp/mux.go @@ -95,32 +95,21 @@ func NewMuxer() (*Muxer, error) { return &Muxer{parser: parser}, nil } -// Match returns the handler of the first route matching the connection metadata. -func (m Muxer) Match(meta ConnData) tcp.Handler { +// Match returns the handler of the first route matching the connection metadata, +// and whether the match is exactly from the rule HostSNI(*). +func (m Muxer) Match(meta ConnData) (tcp.Handler, bool) { for _, route := range m.routes { if route.matchers.match(meta) { - return route.handler + return route.handler, route.catchAll } } - return nil + return nil, false } // AddRoute adds a new route, associated to the given handler, at the given // priority, to the muxer. func (m *Muxer) AddRoute(rule string, priority int, handler tcp.Handler) error { - // Special case for when the catchAll fallback is present. - // When no user-defined priority is found, the lowest computable priority minus one is used, - // in order to make the fallback the last to be evaluated. - if priority == 0 && rule == "HostSNI(`*`)" { - priority = -1 - } - - // Default value, which means the user has not set it, so we'll compute it. - if priority == 0 { - priority = len(rule) - } - parse, err := m.parser.Parse(rule) if err != nil { return fmt.Errorf("error while parsing rule %s: %w", rule, err) @@ -131,16 +120,36 @@ func (m *Muxer) AddRoute(rule string, priority int, handler tcp.Handler) error { return fmt.Errorf("error while parsing rule %s", rule) } + ruleTree := buildTree() + var matchers matchersTree - err = addRule(&matchers, buildTree()) + err = addRule(&matchers, ruleTree) if err != nil { return err } + var catchAll bool + if ruleTree.RuleLeft == nil && ruleTree.RuleRight == nil && len(ruleTree.Value) == 1 { + catchAll = ruleTree.Value[0] == "*" && strings.EqualFold(ruleTree.Matcher, "HostSNI") + } + + // Special case for when the catchAll fallback is present. + // When no user-defined priority is found, the lowest computable priority minus one is used, + // in order to make the fallback the last to be evaluated. + if priority == 0 && catchAll { + priority = -1 + } + + // Default value, which means the user has not set it, so we'll compute it. + if priority == 0 { + priority = len(rule) + } + newRoute := &route{ handler: handler, - priority: priority, matchers: matchers, + catchAll: catchAll, + priority: priority, } m.routes = append(m.routes, newRoute) @@ -207,9 +216,10 @@ type route struct { matchers matchersTree // handler responsible for handling the route. handler tcp.Handler - - // Used to disambiguate between two (or more) rules that would both match for a - // given request. + // catchAll indicates whether the route rule has exactly the catchAll value (HostSNI(`*`)). + catchAll bool + // priority is used to disambiguate between two (or more) rules that would + // all match for a given request. // Computed from the matching rule length, if not user-set. priority int } diff --git a/pkg/muxer/tcp/mux_test.go b/pkg/muxer/tcp/mux_test.go index 65f3021b7..82119319e 100644 --- a/pkg/muxer/tcp/mux_test.go +++ b/pkg/muxer/tcp/mux_test.go @@ -474,7 +474,7 @@ func Test_addTCPRoute(t *testing.T) { connData, err := NewConnData(test.serverName, conn) require.NoError(t, err) - matchingHandler := router.Match(connData) + matchingHandler, _ := router.Match(connData) if test.matchErr { require.Nil(t, matchingHandler) return @@ -568,6 +568,54 @@ func TestParseHostSNI(t *testing.T) { } } +func Test_HostSNICatchAll(t *testing.T) { + testCases := []struct { + desc string + rule string + isCatchAll bool + }{ + { + desc: "HostSNI(`foobar`) is not catchAll", + rule: "HostSNI(`foobar`)", + }, + { + desc: "HostSNI(`*`) is catchAll", + rule: "HostSNI(`*`)", + isCatchAll: true, + }, + { + desc: "HOSTSNI(`*`) is catchAll", + rule: "HOSTSNI(`*`)", + isCatchAll: true, + }, + { + desc: `HostSNI("*") is catchAll`, + rule: `HostSNI("*")`, + isCatchAll: true, + }, + } + + for _, test := range testCases { + test := test + + t.Run(test.desc, func(t *testing.T) { + t.Parallel() + + muxer, err := NewMuxer() + require.NoError(t, err) + + err = muxer.AddRoute(test.rule, 0, tcp.HandlerFunc(func(conn tcp.WriteCloser) {})) + require.NoError(t, err) + + handler, catchAll := muxer.Match(ConnData{ + serverName: "foobar", + }) + require.NotNil(t, handler) + assert.Equal(t, test.isCatchAll, catchAll) + }) + } +} + func Test_HostSNI(t *testing.T) { testCases := []struct { desc string @@ -934,7 +982,7 @@ func Test_Priority(t *testing.T) { require.NoError(t, err) } - handler := muxer.Match(ConnData{ + handler, _ := muxer.Match(ConnData{ serverName: test.serverName, remoteIP: test.remoteIP, }) diff --git a/pkg/provider/acme/provider.go b/pkg/provider/acme/provider.go index df02a5a32..a403b94ba 100644 --- a/pkg/provider/acme/provider.go +++ b/pkg/provider/acme/provider.go @@ -538,7 +538,7 @@ func (p *Provider) addCertificateForDomain(domain types.Domain, certificate, key // The second (RenewInterval) is the interval between renew attempts. func getCertificateRenewDurations(certificatesDuration int) (time.Duration, time.Duration) { switch { - case certificatesDuration >= 265*24: // >= 1 year + case certificatesDuration >= 365*24: // >= 1 year return 4 * 30 * 24 * time.Hour, 7 * 24 * time.Hour // 4 month, 1 week case certificatesDuration >= 3*30*24: // >= 90 days return 30 * 24 * time.Hour, 24 * time.Hour // 30 days, 1 day diff --git a/pkg/provider/acme/provider_test.go b/pkg/provider/acme/provider_test.go index 64bcf1085..103eff59e 100644 --- a/pkg/provider/acme/provider_test.go +++ b/pkg/provider/acme/provider_test.go @@ -608,11 +608,17 @@ func Test_getCertificateRenewDurations(t *testing.T) { expectRenewInterval: time.Minute, }, { - desc: "1 Year certificates: 2 months renew period, 1 week renew interval", + desc: "1 Year certificates: 4 months renew period, 1 week renew interval", certificatesDurations: 24 * 365, expectRenewPeriod: time.Hour * 24 * 30 * 4, expectRenewInterval: time.Hour * 24 * 7, }, + { + desc: "265 Days certificates: 30 days renew period, 1 day renew interval", + certificatesDurations: 24 * 265, + expectRenewPeriod: time.Hour * 24 * 30, + expectRenewInterval: time.Hour * 24, + }, { desc: "90 Days certificates: 30 days renew period, 1 day renew interval", certificatesDurations: 24 * 90, diff --git a/pkg/provider/ecs/ecs.go b/pkg/provider/ecs/ecs.go index 13dafd8d8..0cde14508 100644 --- a/pkg/provider/ecs/ecs.go +++ b/pkg/provider/ecs/ecs.go @@ -392,6 +392,13 @@ func (p *Provider) lookupEc2Instances(ctx context.Context, client *awsClient, cl for _, container := range resp.ContainerInstances { instanceIds[aws.StringValue(container.Ec2InstanceId)] = aws.StringValue(container.ContainerInstanceArn) + // Disallow Instance IDs of the form mi-* + // This prevents considering external instances in ECS Anywhere setups + // and getting InvalidInstanceID.Malformed error when calling the describe-instances endpoint. + if strings.HasPrefix(aws.StringValue(container.Ec2InstanceId), "mi-") { + continue + } + instanceArns = append(instanceArns, container.Ec2InstanceId) } } diff --git a/pkg/provider/hub/handler.go b/pkg/provider/hub/handler.go index 328bf58b5..83d15dfb9 100644 --- a/pkg/provider/hub/handler.go +++ b/pkg/provider/hub/handler.go @@ -4,6 +4,7 @@ import ( "context" "encoding/json" "fmt" + "net" "net/http" "net/url" "sync/atomic" @@ -101,7 +102,7 @@ func (h *handler) handleDiscoverIP(rw http.ResponseWriter, req *http.Request) { } func (h *handler) doDiscoveryReq(ctx context.Context, ip, port, nonce string) error { - req, err := http.NewRequestWithContext(ctx, http.MethodGet, fmt.Sprintf("https://%s:%s", ip, port), http.NoBody) + req, err := http.NewRequestWithContext(ctx, http.MethodGet, fmt.Sprintf("https://%s", net.JoinHostPort(ip, port)), http.NoBody) if err != nil { return fmt.Errorf("creating request: %w", err) } diff --git a/pkg/provider/hub/hub.go b/pkg/provider/hub/hub.go index 1643a0980..106a097e2 100644 --- a/pkg/provider/hub/hub.go +++ b/pkg/provider/hub/hub.go @@ -17,13 +17,15 @@ import ( var _ provider.Provider = (*Provider)(nil) -// DefaultEntryPointName is the name of the default internal entry point. -const DefaultEntryPointName = "traefik-hub" +// Entrypoints created for Hub. +const ( + APIEntrypoint = "traefikhub-api" + TunnelEntrypoint = "traefikhub-tunl" +) // Provider holds configurations of the provider. type Provider struct { - EntryPoint string `description:"Entrypoint that exposes data for Traefik Hub. It should be a dedicated one, and not used by any router." json:"entryPoint,omitempty" toml:"entryPoint,omitempty" yaml:"entryPoint,omitempty" export:"true"` - TLS *TLS `description:"TLS configuration for mTLS communication between Traefik and Hub Agent." json:"tls,omitempty" toml:"tls,omitempty" yaml:"tls,omitempty" export:"true"` + TLS *TLS `description:"TLS configuration for mTLS communication between Traefik and Hub Agent." json:"tls,omitempty" toml:"tls,omitempty" yaml:"tls,omitempty" export:"true"` server *http.Server } @@ -36,11 +38,6 @@ type TLS struct { Key ttls.FileOrContent `description:"The TLS key for Traefik Proxy as a TLS client." json:"key,omitempty" toml:"key,omitempty" yaml:"key,omitempty" loggable:"false"` } -// SetDefaults sets the default values. -func (p *Provider) SetDefaults() { - p.EntryPoint = DefaultEntryPointName -} - // Init the provider. func (p *Provider) Init() error { return nil @@ -48,10 +45,15 @@ func (p *Provider) Init() error { // Provide allows the hub provider to provide configurations to traefik using the given configuration channel. func (p *Provider) Provide(configurationChan chan<- dynamic.Message, _ *safe.Pool) error { + if p.TLS == nil { + return nil + } + listener, err := net.Listen("tcp", "127.0.0.1:0") if err != nil { return fmt.Errorf("listener: %w", err) } + port := listener.Addr().(*net.TCPAddr).Port client, err := createAgentClient(p.TLS) @@ -59,7 +61,7 @@ func (p *Provider) Provide(configurationChan chan<- dynamic.Message, _ *safe.Poo return fmt.Errorf("creating Hub Agent HTTP client: %w", err) } - p.server = &http.Server{Handler: newHandler(p.EntryPoint, port, configurationChan, p.TLS, client)} + p.server = &http.Server{Handler: newHandler(APIEntrypoint, port, configurationChan, p.TLS, client)} // TODO: this is going to be leaky (because no context to make it terminate) // if/when Provide lifecycle differs with Traefik lifecycle. @@ -70,7 +72,7 @@ func (p *Provider) Provide(configurationChan chan<- dynamic.Message, _ *safe.Poo } }() - exposeAPIAndMetrics(configurationChan, p.EntryPoint, port, p.TLS) + exposeAPIAndMetrics(configurationChan, APIEntrypoint, port, p.TLS) return nil } diff --git a/pkg/provider/kubernetes/crd/kubernetes.go b/pkg/provider/kubernetes/crd/kubernetes.go index 74485b078..7270c37d8 100644 --- a/pkg/provider/kubernetes/crd/kubernetes.go +++ b/pkg/provider/kubernetes/crd/kubernetes.go @@ -413,7 +413,7 @@ func getServicePort(svc *corev1.Service, port intstr.IntOrString) (*corev1.Servi if hasValidPort { log.WithoutContext(). - Warning("The port %d from IngressRoute doesn't match with ports defined in the ExternalName service %s/%s.", port, svc.Namespace, svc.Name) + Warnf("The port %s from IngressRoute doesn't match with ports defined in the ExternalName service %s/%s.", port, svc.Namespace, svc.Name) } return &corev1.ServicePort{Port: port.IntVal}, nil diff --git a/pkg/server/router/tcp/router.go b/pkg/server/router/tcp/router.go index d9b5327c0..9b42b7ebe 100644 --- a/pkg/server/router/tcp/router.go +++ b/pkg/server/router/tcp/router.go @@ -93,7 +93,7 @@ func (r *Router) ServeTCP(conn tcp.WriteCloser) { return } - handler := r.muxerTCP.Match(connData) + handler, _ := r.muxerTCP.Match(connData) // If there is a handler matching the connection metadata, // we let it handle the connection. if handler != nil { @@ -133,7 +133,7 @@ func (r *Router) ServeTCP(conn tcp.WriteCloser) { } if !tls { - handler := r.muxerTCP.Match(connData) + handler, _ := r.muxerTCP.Match(connData) switch { case handler != nil: handler.ServeTCP(r.GetConn(conn, peeked)) @@ -145,20 +145,38 @@ func (r *Router) ServeTCP(conn tcp.WriteCloser) { return } - handler := r.muxerTCPTLS.Match(connData) - if handler != nil { - handler.ServeTCP(r.GetConn(conn, peeked)) + // For real, the handler eventually used for HTTPS is (almost) always the same: + // it is the httpsForwarder that is used for all HTTPS connections that match + // (which is also incidentally the same used in the last block below for 404s). + // The added value from doing Match is to find and use the specific TLS config + // (wrapped inside the returned handler) requested for the given HostSNI. + handlerHTTPS, catchAllHTTPS := r.muxerHTTPS.Match(connData) + if handlerHTTPS != nil && !catchAllHTTPS { + // In order not to depart from the behavior in 2.6, we only allow an HTTPS router + // to take precedence over a TCP-TLS router if it is _not_ an HostSNI(*) router (so + // basically any router that has a specific HostSNI based rule). + handlerHTTPS.ServeTCP(r.GetConn(conn, peeked)) return } - // for real, the handler returned here is (almost) always the same: - // it is the httpsForwarder that is used for all HTTPS connections that match - // (which is also incidentally the same used in the last block below for 404s). - // The added value from doing Match, is to find and use the specific TLS config - // requested for the given HostSNI. - handler = r.muxerHTTPS.Match(connData) - if handler != nil { - handler.ServeTCP(r.GetConn(conn, peeked)) + // Contains also TCP TLS passthrough routes. + handlerTCPTLS, catchAllTCPTLS := r.muxerTCPTLS.Match(connData) + if handlerTCPTLS != nil && !catchAllTCPTLS { + handlerTCPTLS.ServeTCP(r.GetConn(conn, peeked)) + return + } + + // Fallback on HTTPS catchAll. + // We end up here for e.g. an HTTPS router that only has a PathPrefix rule, + // which under the scenes is counted as an HostSNI(*) rule. + if handlerHTTPS != nil { + handlerHTTPS.ServeTCP(r.GetConn(conn, peeked)) + return + } + + // Fallback on TCP TLS catchAll. + if handlerTCPTLS != nil { + handlerTCPTLS.ServeTCP(r.GetConn(conn, peeked)) return } diff --git a/pkg/server/router/tcp/router_test.go b/pkg/server/router/tcp/router_test.go new file mode 100644 index 000000000..f9e9978cf --- /dev/null +++ b/pkg/server/router/tcp/router_test.go @@ -0,0 +1,919 @@ +package tcp + +import ( + "bytes" + "context" + "crypto/tls" + "errors" + "fmt" + "io" + "net" + "net/http" + "strings" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/traefik/traefik/v2/pkg/config/dynamic" + "github.com/traefik/traefik/v2/pkg/config/runtime" + tcpmiddleware "github.com/traefik/traefik/v2/pkg/server/middleware/tcp" + "github.com/traefik/traefik/v2/pkg/server/service/tcp" + tcp2 "github.com/traefik/traefik/v2/pkg/tcp" + traefiktls "github.com/traefik/traefik/v2/pkg/tls" +) + +type applyRouter func(conf *runtime.Configuration) + +type checkRouter func(addr string, timeout time.Duration) error + +type httpForwarder struct { + net.Listener + connChan chan net.Conn + errChan chan error +} + +func newHTTPForwarder(ln net.Listener) *httpForwarder { + return &httpForwarder{ + Listener: ln, + connChan: make(chan net.Conn), + errChan: make(chan error), + } +} + +// Close closes the Listener. +func (h *httpForwarder) Close() error { + h.errChan <- http.ErrServerClosed + + return nil +} + +// ServeTCP uses the connection to serve it later in "Accept". +func (h *httpForwarder) ServeTCP(conn tcp2.WriteCloser) { + h.connChan <- conn +} + +// Accept retrieves a served connection in ServeTCP. +func (h *httpForwarder) Accept() (net.Conn, error) { + select { + case conn := <-h.connChan: + return conn, nil + case err := <-h.errChan: + return nil, err + } +} + +// Test_Routing aims to settle the behavior between routers of different types on the same TCP entryPoint. +// It has been introduced as a regression test following a fix on the v2.7 TCP Muxer. +// +// The routing precedence is roughly as follows: +// - TCP over HTTP +// - HTTPS over TCP-TLS +// +// Discrepancies for server sending first bytes support: +// - On v2.6, it is possible as long as you have one and only one TCP Non-TLS HostSNI(`*`) router (so called CatchAllNoTLS) defined. +// - On v2.7, it is possible as long as you have zero TLS/HTTPS router defined. +// +// Discrepancies in routing precedence between TCP and HTTP routers: +// - TCP HostSNI(`*`) and HTTP Host(`foobar`) +// - On v2.6 and v2.7, the TCP one takes precedence. +// +// - TCP ClientIP(`[::]`) and HTTP Host(`foobar`) +// - On v2.6, ClientIP matcher doesn't exist. +// - On v2.7, the TCP one takes precedence. +// +// Routing precedence between TCP-TLS and HTTPS routers (considering a request/connection with the servername "foobar"): +// - TCP-TLS HostSNI(`*`) and HTTPS Host(`foobar`) +// - On v2.6 and v2.7, the HTTPS one takes precedence. +// +// - TCP-TLS HostSNI(`foobar`) and HTTPS Host(`foobar`) +// - On v2.6 and v2.7, the HTTPS one takes precedence (overriding the TCP-TLS one in v2.6). +// +// - TCP-TLS HostSNI(`*`) and HTTPS PathPrefix(`/`) +// - On v2.6 and v2.7, the HTTPS one takes precedence (overriding the TCP-TLS one in v2.6). +// +// - TCP-TLS HostSNI(`foobar`) and HTTPS PathPrefix(`/`) +// - On v2.6 and v2.7, the TCP-TLS one takes precedence. +// +func Test_Routing(t *testing.T) { + // This listener simulates the backend service. + // It is capable of switching into server first communication mode, + // if the client takes to long to send the first bytes. + tcpBackendListener, err := net.Listen("tcp", "127.0.0.1:0") + require.NoError(t, err) + // This allows the closing of the TCP backend listener to happen last. + t.Cleanup(func() { + tcpBackendListener.Close() + }) + + go func() { + for { + conn, err := tcpBackendListener.Accept() + if err != nil { + var netErr net.Error + if errors.As(err, &netErr) && netErr.Temporary() { + continue + } + + return + } + + err = conn.SetReadDeadline(time.Now().Add(200 * time.Millisecond)) + if err != nil { + return + } + + buf := make([]byte, 100) + _, err = conn.Read(buf) + + var opErr *net.OpError + if err == nil { + _, err = fmt.Fprint(conn, "TCP-CLIENT-FIRST") + require.NoError(t, err) + } else if errors.As(err, &opErr) && opErr.Timeout() { + _, err = fmt.Fprint(conn, "TCP-SERVER-FIRST") + require.NoError(t, err) + } + + err = conn.Close() + require.NoError(t, err) + } + }() + + // Configuration defining the TCP backend service, used by TCP routers later. + conf := &runtime.Configuration{ + TCPServices: map[string]*runtime.TCPServiceInfo{ + "tcp": { + TCPService: &dynamic.TCPService{ + LoadBalancer: &dynamic.TCPServersLoadBalancer{ + Servers: []dynamic.TCPServer{ + { + Address: tcpBackendListener.Addr().String(), + }, + }, + }, + }, + }, + }, + } + + serviceManager := tcp.NewManager(conf) + + // Creates the tlsManager and defines the TLS 1.0 and 1.2 TLSOptions. + tlsManager := traefiktls.NewManager() + tlsManager.UpdateConfigs( + context.Background(), + map[string]traefiktls.Store{}, + map[string]traefiktls.Options{ + "default": { + MaxVersion: "VersionTLS10", + }, + "tls10": { + MaxVersion: "VersionTLS10", + }, + "tls12": { + MinVersion: "VersionTLS12", + MaxVersion: "VersionTLS12", + }, + }, + []*traefiktls.CertAndStores{}) + + middlewaresBuilder := tcpmiddleware.NewBuilder(conf.TCPMiddlewares) + + manager := NewManager(conf, serviceManager, middlewaresBuilder, + nil, nil, tlsManager) + + type checkCase struct { + checkRouter + + desc string + expectedError string + timeout time.Duration + } + + testCases := []struct { + desc string + routers []applyRouter + checks []checkCase + }{ + { + desc: "No routers", + routers: []applyRouter{}, + checks: []checkCase{ + { + desc: "TCP with client sending first bytes should fail", + checkRouter: checkTCPClientFirst, + expectedError: "i/o timeout", + }, + { + desc: "TCP with server sending first bytes should fail", + checkRouter: checkTCPServerFirst, + expectedError: "i/o timeout", + }, + { + desc: "HTTP request should be handled by HTTP service (404)", + checkRouter: checkHTTP, + }, + { + desc: "TCP TLS 1.0 connection should fail", + checkRouter: checkTCPTLS10, + expectedError: "i/o timeout", + }, + { + desc: "TCP TLS 1.2 connection should fail", + checkRouter: checkTCPTLS12, + // The HTTPS forwarder catches the connection with the TLS 1.0 config, + // because no matching routes are defined with the custom TLS Config. + expectedError: "wrong TLS version", + }, + { + desc: "HTTPS TLS 1.0 request should be handled by HTTPS (HTTPS forwarder with tls 1.0 config) (404)", + checkRouter: checkHTTPSTLS10, + }, + { + desc: "HTTPS TLS 1.2 request should fail", + checkRouter: checkHTTPSTLS12, + expectedError: "wrong TLS version", + }, + }, + }, + { + desc: "Single TCP CatchAll router", + routers: []applyRouter{routerTCPCatchAll}, + checks: []checkCase{ + { + desc: "TCP with client sending first bytes should be handled by TCP service", + checkRouter: checkTCPClientFirst, + }, + { + desc: "TCP with server sending first bytes should be handled by TCP service", + checkRouter: checkTCPServerFirst, + }, + }, + }, + { + desc: "Single HTTP router", + routers: []applyRouter{routerHTTP}, + checks: []checkCase{ + { + desc: "HTTP request should be handled by HTTP service", + checkRouter: checkHTTP, + }, + }, + }, + { + desc: "Single TCP TLS router", + routers: []applyRouter{routerTCPTLS}, + checks: []checkCase{ + { + desc: "TCP TLS 1.0 connection should fail", + checkRouter: checkTCPTLS10, + expectedError: "wrong TLS version", + }, + { + desc: "TCP TLS 1.2 connection should be handled by TCP service", + checkRouter: checkTCPTLS12, + }, + }, + }, + { + desc: "Single TCP TLS CatchAll router", + routers: []applyRouter{routerTCPTLSCatchAll}, + checks: []checkCase{ + { + desc: "TCP TLS 1.0 connection should be handled by TCP service", + checkRouter: checkTCPTLS10, + }, + { + desc: "TCP TLS 1.2 connection should fail", + checkRouter: checkTCPTLS12, + expectedError: "wrong TLS version", + }, + }, + }, + { + desc: "Single HTTPS router", + routers: []applyRouter{routerHTTPS}, + checks: []checkCase{ + { + desc: "HTTPS TLS 1.0 request should fail", + checkRouter: checkHTTPSTLS10, + expectedError: "wrong TLS version", + }, + { + desc: "HTTPS TLS 1.2 request should be handled by HTTPS service", + checkRouter: checkHTTPSTLS12, + }, + }, + }, + { + desc: "Single HTTPS PathPrefix router", + routers: []applyRouter{routerHTTPSPathPrefix}, + checks: []checkCase{ + { + desc: "HTTPS TLS 1.0 request should be handled by HTTPS service", + checkRouter: checkHTTPSTLS10, + }, + { + desc: "HTTPS TLS 1.2 request should fail", + checkRouter: checkHTTPSTLS12, + expectedError: "wrong TLS version", + }, + }, + }, + { + desc: "TCP CatchAll router && HTTP router", + routers: []applyRouter{routerTCPCatchAll, routerHTTP}, + checks: []checkCase{ + { + desc: "TCP client sending first bytes should be handled by TCP service", + checkRouter: checkTCPClientFirst, + }, + { + desc: "TCP server sending first bytes should be handled by TCP service", + checkRouter: checkTCPServerFirst, + }, + { + desc: "HTTP request should fail, because handled by TCP service", + checkRouter: checkHTTP, + expectedError: "malformed HTTP response", + }, + }, + }, + { + desc: "TCP TLS CatchAll router && HTTP router", + routers: []applyRouter{routerTCPTLS, routerHTTP}, + checks: []checkCase{ + { + desc: "TCP TLS 1.0 connection should fail", + checkRouter: checkTCPTLS10, + expectedError: "wrong TLS version", + }, + { + desc: "TCP TLS 1.2 connection should be handled by TCP service", + checkRouter: checkTCPTLS12, + }, + { + desc: "HTTP request should be handled by HTTP service", + checkRouter: checkHTTP, + }, + }, + }, + { + desc: "TCP CatchAll router && HTTPS router", + routers: []applyRouter{routerTCPCatchAll, routerHTTPS}, + checks: []checkCase{ + { + desc: "TCP client sending first bytes should be handled by TCP service", + checkRouter: checkTCPClientFirst, + }, + { + desc: "TCP server sending first bytes should timeout on clientHello", + checkRouter: checkTCPServerFirst, + expectedError: "i/o timeout", + }, + { + desc: "HTTP request should fail, because handled by TCP service", + checkRouter: checkHTTP, + expectedError: "malformed HTTP response", + }, + { + desc: "HTTPS TLS 1.0 request should be handled by HTTPS service", + checkRouter: checkHTTPSTLS10, + expectedError: "wrong TLS version", + }, + { + desc: "HTTPS TLS 1.2 request should be handled by HTTPS service", + checkRouter: checkHTTPSTLS12, + }, + }, + }, + { + // We show that a not CatchAll HTTPS router takes priority over a TCP-TLS router. + desc: "TCP TLS router && HTTPS router", + routers: []applyRouter{routerTCPTLS, routerHTTPS}, + checks: []checkCase{ + { + desc: "TCP TLS 1.0 connection should fail", + checkRouter: checkTCPTLS10, + expectedError: "wrong TLS version", + }, + { + desc: "TCP TLS 1.2 connection should fail", + checkRouter: checkTCPTLS12, + // The connection is handled by the HTTPS router, + // which has the correct TLS config, + // but the HTTP server is detecting a malformed request which ends with a timeout. + expectedError: "i/o timeout", + }, + { + desc: "HTTPS TLS 1.0 request should fail", + checkRouter: checkHTTPSTLS10, + expectedError: "wrong TLS version", + }, + { + desc: "HTTPS TLS 1.2 request should be handled by HTTPS service", + checkRouter: checkHTTPSTLS12, + }, + }, + }, + { + // We show that a not CatchAll HTTPS router takes priority over a CatchAll TCP-TLS router. + desc: "TCP TLS CatchAll router && HTTPS router", + routers: []applyRouter{routerTCPCatchAll, routerHTTPS}, + checks: []checkCase{ + { + desc: "TCP TLS 1.0 connection should fail", + checkRouter: checkTCPTLS10, + expectedError: "wrong TLS version", + }, + { + desc: "TCP TLS 1.2 connection should fail", + checkRouter: checkTCPTLS12, + // The connection is handled by the HTTPS router, + // which has the correct TLS config, + // but the HTTP server is detecting a malformed request which ends with a timeout. + expectedError: "i/o timeout", + }, + { + desc: "HTTPS TLS 1.0 request should fail", + checkRouter: checkHTTPSTLS10, + expectedError: "wrong TLS version", + }, + { + desc: "HTTPS TLS 1.2 request should be handled by HTTPS service", + checkRouter: checkHTTPSTLS12, + }, + }, + }, + { + // We show that TCP-TLS router (not CatchAll) takes priority over non-Host rule HTTPS router (CatchAll). + desc: "TCP TLS router && HTTPS Path prefix router", + routers: []applyRouter{routerTCPTLS, routerHTTPSPathPrefix}, + checks: []checkCase{ + { + desc: "TCP TLS 1.0 connection should fail", + checkRouter: checkTCPTLS10, + expectedError: "wrong TLS version", + }, + { + desc: "TCP TLS 1.2 connection should be handled by TCP service", + checkRouter: checkTCPTLS12, + }, + { + desc: "HTTPS TLS 1.0 request should fail", + checkRouter: checkHTTPSTLS10, + expectedError: "malformed HTTP response", + }, + { + desc: "HTTPS TLS 1.2 should fail", + checkRouter: checkHTTPSTLS12, + expectedError: "malformed HTTP response", + }, + }, + }, + { + desc: "TCP TLS router && TCP TLS CatchAll router", + routers: []applyRouter{routerTCPTLS, routerTCPTLSCatchAll}, + checks: []checkCase{ + { + desc: "TCP TLS 1.0 connection should fail", + checkRouter: checkTCPTLS10, + expectedError: "wrong TLS version", + }, + { + desc: "TCP TLS 1.2 connection should be handled by TCP service", + checkRouter: checkTCPTLS12, + }, + }, + }, + { + desc: "All routers, all checks", + routers: []applyRouter{routerTCPCatchAll, routerHTTP, routerHTTPS, routerTCPTLS, routerTCPTLSCatchAll}, + checks: []checkCase{ + { + desc: "TCP client sending first bytes should be handled by TCP service", + checkRouter: checkTCPClientFirst, + }, + { + desc: "TCP server sending first bytes should timeout on clientHello", + checkRouter: checkTCPServerFirst, + expectedError: "i/o timeout", + }, + { + desc: "HTTP request should fail, because handled by TCP service", + checkRouter: checkHTTP, + expectedError: "malformed HTTP response", + }, + { + desc: "HTTPS TLS 1.0 request should fail", + checkRouter: checkHTTPSTLS10, + expectedError: "wrong TLS version", + }, + { + desc: "HTTPS TLS 1.2 request should be handled by HTTPS service", + checkRouter: checkHTTPSTLS12, + }, + { + desc: "TCP TLS 1.0 connection should fail", + checkRouter: checkTCPTLS10, + expectedError: "wrong TLS version", + }, + { + desc: "TCP TLS 1.2 connection should fail", + checkRouter: checkTCPTLS12, + // The connection is handled by the HTTPS router, + // witch have the correct TLS config, + // but the HTTP server is detecting a malformed request which ends with a timeout. + expectedError: "i/o timeout", + }, + }, + }, + } + + for _, test := range testCases { + test := test + + t.Run(test.desc, func(t *testing.T) { + t.Parallel() + + dynConf := &runtime.Configuration{ + Routers: map[string]*runtime.RouterInfo{}, + TCPRouters: map[string]*runtime.TCPRouterInfo{}, + } + + for _, router := range test.routers { + router(dynConf) + } + + router, err := manager.buildEntryPointHandler(context.Background(), dynConf.TCPRouters, dynConf.Routers, nil, nil) + require.NoError(t, err) + + epListener, err := net.Listen("tcp", "127.0.0.1:0") + require.NoError(t, err) + + // serverHTTP handler returns only the "HTTP" value as body for further checks. + serverHTTP := &http.Server{ + Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + _, err = fmt.Fprint(w, "HTTP") + require.NoError(t, err) + }), + } + + stoppedHTTP := make(chan struct{}) + forwarder := newHTTPForwarder(epListener) + go func() { + defer close(stoppedHTTP) + _ = serverHTTP.Serve(forwarder) + }() + + router.SetHTTPForwarder(forwarder) + + // serverHTTPS handler returns only the "HTTPS" value as body for further checks. + serverHTTPS := &http.Server{ + Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + _, err = fmt.Fprint(w, "HTTPS") + require.NoError(t, err) + }), + } + + stoppedHTTPS := make(chan struct{}) + httpsForwarder := newHTTPForwarder(epListener) + go func() { + defer close(stoppedHTTPS) + _ = serverHTTPS.Serve(httpsForwarder) + }() + + router.SetHTTPSForwarder(httpsForwarder) + + stoppedTCP := make(chan struct{}) + go func() { + defer close(stoppedTCP) + for { + conn, err := epListener.Accept() + if err != nil { + return + } + + tcpConn, ok := conn.(*net.TCPConn) + if !ok { + t.Error("not a write closer") + } + + router.ServeTCP(tcpConn) + } + }() + + for _, check := range test.checks { + timeout := 2 * time.Second + if check.timeout > 0 { + timeout = check.timeout + } + + err := check.checkRouter(epListener.Addr().String(), timeout) + + if check.expectedError != "" { + require.NotNil(t, err, check.desc) + assert.Contains(t, err.Error(), check.expectedError, check.desc) + continue + } + + assert.Nil(t, err, check.desc) + } + + epListener.Close() + + <-stoppedTCP + + serverHTTP.Close() + serverHTTPS.Close() + + <-stoppedHTTP + <-stoppedHTTPS + }) + } +} + +// routerTCPCatchAll configures a TCP CatchAll No TLS - HostSNI(`*`) router. +func routerTCPCatchAll(conf *runtime.Configuration) { + conf.TCPRouters["tcp-catchall"] = &runtime.TCPRouterInfo{ + TCPRouter: &dynamic.TCPRouter{ + EntryPoints: []string{"web"}, + Service: "tcp", + Rule: "HostSNI(`*`)", + }, + } +} + +// routerHTTP configures an HTTP - Host(`foo.bar`) router. +func routerHTTP(conf *runtime.Configuration) { + conf.Routers["http"] = &runtime.RouterInfo{ + Router: &dynamic.Router{ + EntryPoints: []string{"web"}, + Service: "http", + Rule: "Host(`foo.bar`)", + }, + } +} + +// routerTCPTLSCatchAll a TCP TLS CatchAll - HostSNI(`*`) router with TLS 1.0 config. +func routerTCPTLSCatchAll(conf *runtime.Configuration) { + conf.TCPRouters["tcp-tls-catchall"] = &runtime.TCPRouterInfo{ + TCPRouter: &dynamic.TCPRouter{ + EntryPoints: []string{"web"}, + Service: "tcp", + Rule: "HostSNI(`*`)", + TLS: &dynamic.RouterTCPTLSConfig{ + Options: "tls10", + }, + }, + } +} + +// routerTCPTLS configures a TCP TLS - HostSNI(`foo.bar`) router with TLS 1.2 config. +func routerTCPTLS(conf *runtime.Configuration) { + conf.TCPRouters["tcp-tls"] = &runtime.TCPRouterInfo{ + TCPRouter: &dynamic.TCPRouter{ + EntryPoints: []string{"web"}, + Service: "tcp", + Rule: "HostSNI(`foo.bar`)", + TLS: &dynamic.RouterTCPTLSConfig{ + Options: "tls12", + }, + }, + } +} + +// routerHTTPSPathPrefix configures an HTTPS - PathPrefix(`/`) router with TLS 1.0 config. +func routerHTTPSPathPrefix(conf *runtime.Configuration) { + conf.Routers["https"] = &runtime.RouterInfo{ + Router: &dynamic.Router{ + EntryPoints: []string{"web"}, + Service: "http", + Rule: "PathPrefix(`/`)", + TLS: &dynamic.RouterTLSConfig{ + Options: "tls10", + }, + }, + } +} + +// routerHTTPS configures an HTTPS - Host(`foo.bar`) router with TLS 1.2 config. +func routerHTTPS(conf *runtime.Configuration) { + conf.Routers["https-custom-tls"] = &runtime.RouterInfo{ + Router: &dynamic.Router{ + EntryPoints: []string{"web"}, + Service: "http", + Rule: "Host(`foo.bar`)", + TLS: &dynamic.RouterTLSConfig{ + Options: "tls12", + }, + }, + } +} + +// checkTCPClientFirst simulates a TCP client sending first bytes first. +// It returns an error if it doesn't receive the expected response. +func checkTCPClientFirst(addr string, timeout time.Duration) (err error) { + conn, err := net.Dial("tcp", addr) + if err != nil { + return err + } + defer func() { + closeErr := conn.Close() + if closeErr != nil && err == nil { + err = closeErr + } + }() + + fmt.Fprint(conn, "HELLO") + + err = conn.SetReadDeadline(time.Now().Add(timeout)) + if err != nil { + return + } + + var buf bytes.Buffer + _, err = io.Copy(&buf, conn) + if err != nil { + return err + } + + if !strings.HasPrefix(buf.String(), "TCP-CLIENT-FIRST") { + return fmt.Errorf("unexpected response: %s", buf.String()) + } + + return nil +} + +// checkTCPServerFirst simulates a TCP client waiting for the server first bytes. +// It returns an error if it doesn't receive the expected response. +func checkTCPServerFirst(addr string, timeout time.Duration) (err error) { + conn, err := net.Dial("tcp", addr) + if err != nil { + return err + } + defer func() { + closeErr := conn.Close() + if closeErr != nil && err == nil { + err = closeErr + } + }() + + err = conn.SetReadDeadline(time.Now().Add(timeout)) + if err != nil { + return + } + + var buf bytes.Buffer + _, err = io.Copy(&buf, conn) + if err != nil { + return err + } + + if !strings.HasPrefix(buf.String(), "TCP-SERVER-FIRST") { + return fmt.Errorf("unexpected response: %s", buf.String()) + } + + return nil +} + +// checkHTTP simulates an HTTP client. +// It returns an error if it doesn't receive the expected response. +func checkHTTP(addr string, timeout time.Duration) error { + httpClient := &http.Client{Timeout: timeout} + + req, err := http.NewRequest(http.MethodGet, "http://"+addr, nil) + if err != nil { + return err + } + req.Header.Set("Host", "foo.bar") + + resp, err := httpClient.Do(req) + if err != nil { + return err + } + + defer resp.Body.Close() + body, err := io.ReadAll(resp.Body) + if err != nil { + return err + } + + if !strings.Contains(string(body), "HTTP") { + return fmt.Errorf("unexpected response: %s", string(body)) + } + + return nil +} + +// checkTCPTLS simulates a TCP client connection. +// It returns an error if it doesn't receive the expected response. +func checkTCPTLS(addr string, timeout time.Duration, tlsVersion uint16) (err error) { + tlsConfig := &tls.Config{ + InsecureSkipVerify: true, + ServerName: "foo.bar", + MinVersion: tls.VersionTLS10, + MaxVersion: tls.VersionTLS12, + } + conn, err := tls.Dial("tcp", addr, tlsConfig) + if err != nil { + return err + } + defer func() { + closeErr := conn.Close() + if closeErr != nil && err == nil { + err = closeErr + } + }() + + if conn.ConnectionState().Version != tlsVersion { + return fmt.Errorf("wrong TLS version. wanted %X, got %X", tlsVersion, conn.ConnectionState().Version) + } + + fmt.Fprint(conn, "HELLO") + + err = conn.SetReadDeadline(time.Now().Add(timeout)) + if err != nil { + return + } + + var buf bytes.Buffer + _, err = io.Copy(&buf, conn) + if err != nil { + return err + } + + if !strings.HasPrefix(buf.String(), "TCP-CLIENT-FIRST") { + return fmt.Errorf("unexpected response: %s", buf.String()) + } + + return nil +} + +// checkTCPTLS10 simulates a TCP client connection with TLS 1.0. +// It returns an error if it doesn't receive the expected response. +func checkTCPTLS10(addr string, timeout time.Duration) error { + return checkTCPTLS(addr, timeout, tls.VersionTLS10) +} + +// checkTCPTLS12 simulates a TCP client connection with TLS 1.2. +// It returns an error if it doesn't receive the expected response. +func checkTCPTLS12(addr string, timeout time.Duration) error { + return checkTCPTLS(addr, timeout, tls.VersionTLS12) +} + +// checkHTTPS makes an HTTPS request and checks the given TLS. +// It returns an error if it doesn't receive the expected response. +func checkHTTPS(addr string, timeout time.Duration, tlsVersion uint16) error { + req, err := http.NewRequest(http.MethodGet, "https://"+addr, nil) + if err != nil { + return err + } + req.Header.Set("Host", "foo.bar") + + httpClient := &http.Client{ + Transport: &http.Transport{ + TLSClientConfig: &tls.Config{ + InsecureSkipVerify: true, + ServerName: "foo.bar", + MinVersion: tls.VersionTLS10, + MaxVersion: tls.VersionTLS12, + }, + }, + Timeout: timeout, + } + + resp, err := httpClient.Do(req) + if err != nil { + return err + } + + if resp.TLS.Version != tlsVersion { + return fmt.Errorf("wrong TLS version. wanted %X, got %X", tlsVersion, resp.TLS.Version) + } + + defer resp.Body.Close() + body, err := io.ReadAll(resp.Body) + if err != nil { + return err + } + + if !strings.Contains(string(body), "HTTPS") { + return fmt.Errorf("unexpected response: %s", string(body)) + } + + return nil +} + +// checkHTTPSTLS10 makes an HTTP request with TLS version 1.0. +// It returns an error if it doesn't receive the expected response. +func checkHTTPSTLS10(addr string, timeout time.Duration) error { + return checkHTTPS(addr, timeout, tls.VersionTLS10) +} + +// checkHTTPSTLS12 makes an HTTP request with TLS version 1.2. +// It returns an error if it doesn't receive the expected response. +func checkHTTPSTLS12(addr string, timeout time.Duration) error { + return checkHTTPS(addr, timeout, tls.VersionTLS12) +} diff --git a/pkg/tcp/proxy.go b/pkg/tcp/proxy.go index 038062c68..a9c5f1844 100644 --- a/pkg/tcp/proxy.go +++ b/pkg/tcp/proxy.go @@ -14,33 +14,31 @@ import ( // Proxy forwards a TCP request to a TCP service. type Proxy struct { address string - target *net.TCPAddr + tcpAddr *net.TCPAddr terminationDelay time.Duration proxyProtocol *dynamic.ProxyProtocol - refreshTarget bool } // NewProxy creates a new Proxy. func NewProxy(address string, terminationDelay time.Duration, proxyProtocol *dynamic.ProxyProtocol) (*Proxy, error) { - tcpAddr, err := net.ResolveTCPAddr("tcp", address) - if err != nil { - return nil, err - } - if proxyProtocol != nil && (proxyProtocol.Version < 1 || proxyProtocol.Version > 2) { return nil, fmt.Errorf("unknown proxyProtocol version: %d", proxyProtocol.Version) } - // enable the refresh of the target only if the address in not an IP - refreshTarget := false - if host, _, err := net.SplitHostPort(address); err == nil && net.ParseIP(host) == nil { - refreshTarget = true + // Creates the tcpAddr only for IP based addresses, + // because there is no need to resolve the name on every new connection, + // and building it should happen once. + var tcpAddr *net.TCPAddr + if host, _, err := net.SplitHostPort(address); err == nil && net.ParseIP(host) != nil { + tcpAddr, err = net.ResolveTCPAddr("tcp", address) + if err != nil { + return nil, err + } } return &Proxy{ address: address, - target: tcpAddr, - refreshTarget: refreshTarget, + tcpAddr: tcpAddr, terminationDelay: terminationDelay, proxyProtocol: proxyProtocol, }, nil @@ -83,10 +81,14 @@ func (p *Proxy) ServeTCP(conn WriteCloser) { } func (p Proxy) dialBackend() (*net.TCPConn, error) { - if !p.refreshTarget { - return net.DialTCP("tcp", nil, p.target) + // Dial using directly the TCPAddr for IP based addresses. + if p.tcpAddr != nil { + return net.DialTCP("tcp", nil, p.tcpAddr) } + log.WithoutContext().Debugf("Dial with lookup to address %s", p.address) + + // Dial with DNS lookup for host based addresses. conn, err := net.Dial("tcp", p.address) if err != nil { return nil, err diff --git a/pkg/tcp/proxy_test.go b/pkg/tcp/proxy_test.go index e70b36796..fb8cad1dd 100644 --- a/pkg/tcp/proxy_test.go +++ b/pkg/tcp/proxy_test.go @@ -176,16 +176,20 @@ func TestLookupAddress(t *testing.T) { testCases := []struct { desc string address string - expectRefresh bool + expectAddr assert.ComparisonAssertionFunc + expectRefresh assert.ValueAssertionFunc }{ { - desc: "IP doesn't need refresh", - address: "8.8.4.4:53", + desc: "IP doesn't need refresh", + address: "8.8.4.4:53", + expectAddr: assert.Equal, + expectRefresh: assert.NotNil, }, { desc: "Hostname needs refresh", address: "dns.google:53", - expectRefresh: true, + expectAddr: assert.NotEqual, + expectRefresh: assert.Nil, }, } @@ -197,16 +201,12 @@ func TestLookupAddress(t *testing.T) { proxy, err := NewProxy(test.address, 10*time.Millisecond, nil) require.NoError(t, err) - require.NotNil(t, proxy.target) + test.expectRefresh(t, proxy.tcpAddr) conn, err := proxy.dialBackend() require.NoError(t, err) - if test.expectRefresh { - assert.NotEqual(t, test.address, conn.RemoteAddr().String()) - } else { - assert.Equal(t, test.address, conn.RemoteAddr().String()) - } + test.expectAddr(t, test.address, conn.RemoteAddr().String()) }) } } diff --git a/pkg/tls/tlsmanager.go b/pkg/tls/tlsmanager.go index 50e809e8a..961b1d8e3 100644 --- a/pkg/tls/tlsmanager.go +++ b/pkg/tls/tlsmanager.go @@ -171,6 +171,13 @@ func (m *Manager) Get(storeName, configName string) (*tls.Config, error) { return nil, nil } + if store == nil { + log.WithoutContext().Errorf("TLS: No certificate store found with this name: %q, closing connection", storeName) + + // Same comment as above, as in the isACMETLS case. + return nil, nil + } + log.WithoutContext().Debugf("Serving default certificate for request: %q", domainToCheck) return store.DefaultCertificate, nil } diff --git a/pkg/tls/tlsmanager_test.go b/pkg/tls/tlsmanager_test.go index 63f13fe17..f06d0ab94 100644 --- a/pkg/tls/tlsmanager_test.go +++ b/pkg/tls/tlsmanager_test.go @@ -171,6 +171,36 @@ func TestManager_Get(t *testing.T) { } } +func TestManager_Get_GetCertificate(t *testing.T) { + testCases := []struct { + desc string + expectedGetConfigErr require.ErrorAssertionFunc + expectedCertificate assert.ValueAssertionFunc + }{ + { + desc: "Get a default certificate from non-existing store", + expectedGetConfigErr: require.Error, + expectedCertificate: assert.Nil, + }, + } + + tlsManager := NewManager() + + for _, test := range testCases { + test := test + t.Run(test.desc, func(t *testing.T) { + t.Parallel() + + config, err := tlsManager.Get("default", "foo") + test.expectedGetConfigErr(t, err) + + certificate, err := config.GetCertificate(&tls.ClientHelloInfo{}) + require.NoError(t, err) + test.expectedCertificate(t, certificate) + }) + } +} + func TestClientAuth(t *testing.T) { tlsConfigs := map[string]Options{ "eca": { diff --git a/script/gcg/traefik-bugfix.toml b/script/gcg/traefik-bugfix.toml index 7ce934ea3..e18143341 100644 --- a/script/gcg/traefik-bugfix.toml +++ b/script/gcg/traefik-bugfix.toml @@ -4,11 +4,11 @@ RepositoryName = "traefik" OutputType = "file" FileName = "traefik_changelog.md" -# example new bugfix v2.6.3 +# example new bugfix v2.6.7 CurrentRef = "v2.6" -PreviousRef = "v2.6.2" +PreviousRef = "v2.6.6" BaseBranch = "v2.6" -FutureCurrentRefName = "v2.6.3" +FutureCurrentRefName = "v2.6.7" ThresholdPreviousRef = 10 ThresholdCurrentRef = 10 diff --git a/script/gcg/traefik-final-release-part1.toml b/script/gcg/traefik-final-release-part1.toml index baa06defe..322e83805 100644 --- a/script/gcg/traefik-final-release-part1.toml +++ b/script/gcg/traefik-final-release-part1.toml @@ -4,11 +4,11 @@ RepositoryName = "traefik" OutputType = "file" FileName = "traefik_changelog.md" -# example final release of v2.6.0 -CurrentRef = "v2.6" -PreviousRef = "v2.6.0-rc1" -BaseBranch = "v2.6" -FutureCurrentRefName = "v2.6.0" +# example final release of v2.7.0 +CurrentRef = "v2.7" +PreviousRef = "v2.7.0-rc1" +BaseBranch = "v2.7" +FutureCurrentRefName = "v2.7.0" ThresholdPreviousRef = 10 ThresholdCurrentRef = 10 diff --git a/script/gcg/traefik-final-release-part2.toml b/script/gcg/traefik-final-release-part2.toml index 9f9ab1cce..23558aaf2 100644 --- a/script/gcg/traefik-final-release-part2.toml +++ b/script/gcg/traefik-final-release-part2.toml @@ -4,11 +4,11 @@ RepositoryName = "traefik" OutputType = "file" FileName = "traefik_changelog.md" -# example final release of v2.6.0 -CurrentRef = "v2.6.0-rc1" -PreviousRef = "v2.5.0-rc1" +# example final release of v2.7.0 +CurrentRef = "v2.7.0-rc1" +PreviousRef = "v2.6.0-rc1" BaseBranch = "master" -FutureCurrentRefName = "v2.6.0-rc1" +FutureCurrentRefName = "v2.7.0-rc1" ThresholdPreviousRef = 10 ThresholdCurrentRef = 10 diff --git a/webui/Dockerfile b/webui/Dockerfile index edb9593bc..643f12f8e 100644 --- a/webui/Dockerfile +++ b/webui/Dockerfile @@ -2,6 +2,8 @@ FROM node:14.16 # Current Active LTS release according to (https://nodejs.org/en/about/releases/) ENV WEBUI_DIR /src/webui +ARG ARG_PLATFORM_URL=https://pilot.traefik.io +ENV PLATFORM_URL=${ARG_PLATFORM_URL} RUN mkdir -p $WEBUI_DIR COPY package.json $WEBUI_DIR/ diff --git a/webui/dev/scripts/transfer.js b/webui/dev/scripts/transfer.js index ed812efff..eaa02bceb 100644 --- a/webui/dev/scripts/transfer.js +++ b/webui/dev/scripts/transfer.js @@ -5,7 +5,7 @@ const folder = process.argv[2] async function execute () { try { await fs.emptyDir('./static') - await fs.outputFile('./static/DONT-EDIT-FILES-IN-THIS-DIRECTORY.md', 'For more information show `webui/readme.md`') + await fs.outputFile('./static/DONT-EDIT-FILES-IN-THIS-DIRECTORY.md', 'For more information see `webui/readme.md`') console.log('Deleted static folder contents!') await fs.copy(`./dist/${folder}`, './static', { overwrite: true }) console.log('Installed new files in static folder!') diff --git a/webui/quasar.conf.js b/webui/quasar.conf.js index 07eec1a8d..c7dc90513 100644 --- a/webui/quasar.conf.js +++ b/webui/quasar.conf.js @@ -118,11 +118,13 @@ module.exports = function (ctx) { env: process.env.APP_ENV === 'development' ? { // staging: APP_ENV: JSON.stringify(process.env.APP_ENV), - APP_API: JSON.stringify(process.env.APP_API || '/api') + APP_API: JSON.stringify(process.env.APP_API || '/api'), + PLATFORM_URL: JSON.stringify(process.env.PLATFORM_URL || 'https://pilot.traefik.io') } : { // production: APP_ENV: JSON.stringify(process.env.APP_ENV), - APP_API: JSON.stringify(process.env.APP_API || '/api') + APP_API: JSON.stringify(process.env.APP_API || '/api'), + PLATFORM_URL: JSON.stringify(process.env.PLATFORM_URL || 'https://pilot.traefik.io') }, uglifyOptions: { compress: { diff --git a/webui/src/App.vue b/webui/src/App.vue index d655741b1..bb6e93e60 100644 --- a/webui/src/App.vue +++ b/webui/src/App.vue @@ -1,17 +1,26 @@ + + diff --git a/webui/src/components/platform/PlatformPanel.vue b/webui/src/components/platform/PlatformPanel.vue new file mode 100644 index 000000000..a24f2bb1a --- /dev/null +++ b/webui/src/components/platform/PlatformPanel.vue @@ -0,0 +1,112 @@ +