Compare commits

...

78 Commits

Author SHA1 Message Date
Ludovic Fernandez
df5f530058 Prepare release v1.7.15 2019-09-12 18:10:05 +02:00
mpl
753d173965 error pages: do not buffer response when it's not an error 2019-09-12 16:20:05 +02:00
Daniel Tomcej
ffd1f122de Add TLS minversion constraint 2019-09-12 14:48:05 +02:00
Piotr Majkrzak
f98b57fdf4 Fix wrong handling of insecure tls auth forward ingress annotation 2019-09-12 11:44:05 +02:00
Damien Duportal
2d37f08864 Improve Access Logs Documentation page 2019-09-11 18:14:03 +02:00
Nicholas Wiersma
a7dbcc282c Consider default cert domain in certificate store
Co-authored-by: Nicolas Mengin <nmengin.pro@gmail.com>
2019-09-11 17:46:04 +02:00
David Dymko
f4f62e7fb3 Update Acme doc - Vultr Wildcard & Root 2019-09-09 09:26:04 +02:00
mpl
4cae8bcb10 Finish kubernetes throttling refactoring 2019-08-31 05:10:04 -07:00
Ben Weissmann
bee370ec6b Throttle Kubernetes config refresh 2019-08-30 03:16:04 -07:00
pitan
f1d016b893 Typo in basic auth usersFile label consul-catalog 2019-08-21 01:36:03 -07:00
Erik Wegner
4defbbe848 Kubernetes support for Auth.HeaderField 2019-08-21 01:30:05 -07:00
Ludovic Fernandez
f397342f16 Prepare release v1.7.14 2019-08-14 02:06:03 -07:00
Ludovic Fernandez
989a59cc29 Update to go1.12.8 2019-08-14 01:52:05 -07:00
Julien Levesy
c5b71592c8 Make hijackConnectionTracker.Close thread safe 2019-08-12 02:34:04 -07:00
Ludovic Fernandez
9de3129a55 Prepare release v1.7.13 2019-08-08 09:04:03 -07:00
Douglas Wagner
40ab1f325c Wrr loadbalancer honors old weight on recovered servers 2019-08-07 08:14:04 -07:00
Daniel Becker
73e0561610 Update lego 2019-08-05 09:08:04 -07:00
Jean Prat
0a89cccdc0 warning should not be a fail status 2019-08-05 08:40:04 -07:00
Daniel Tomcej
b102e6de5a Add missing KeyUsages for default generated certificate 2019-08-05 06:20:05 -07:00
alvarezbruned
2064a6f805 Add example for CLI 2019-08-01 05:38:04 -07:00
Amir Keibi
72e2ddff98 Updating Service Fabric documentation 2019-07-26 02:30:05 -07:00
David Dymko
7db41967c6 Fixed doc link for AlibabaCloud 2019-07-16 16:02:04 +02:00
Jean-Baptiste Doumenjou
a8680a8719 Fixes the TLS Mutual Authentication documentation 2019-07-15 08:46:04 +02:00
Ludovic Fernandez
7e11fa1193 Update Docker version. 2019-07-15 07:04:02 +02:00
gurayyildirim
489b5a6150 Format YAML example on user guide 2019-07-08 10:40:03 +02:00
Daniel Tomcej
8027e8ee23 Check for multiport services on Global Backend Ingress 2019-06-27 09:42:03 +02:00
Damien Duportal
d35d5bd2e8 Update documentation to clarify the default format for logs 2019-06-26 14:28:04 +02:00
stffabi
8e47bdedc6 Clear TLS client headers if TLSMutualAuth is optional 2019-06-26 11:32:04 +02:00
Damien Duportal
51419a9235 Update Slack support channel references to Discourse community forum 2019-06-25 10:06:03 +02:00
Ludovic Fernandez
32fd52c698 Use dynamodbav tags to override json tags. 2019-06-24 09:14:03 +02:00
Ludovic Fernandez
468e4ebd98 Add remarks about Rancher 2 2019-06-21 19:04:04 +02:00
Damien Duportal
92a57384a4 Allows logs to use local time zone instead of UTC
Co-authored-by: Ludovic Fernandez <ldez@users.noreply.github.com>
2019-06-17 09:20:03 +02:00
Damien Duportal
2067a433cd Improve API / Dashboard wording in documentation 2019-06-04 00:42:05 +02:00
kolaente
16f1f851cc Use the latest stable version of traefik in the docs 2019-06-03 17:38:07 +02:00
Daniel Tomcej
8e992c7cfb Update docker api version 2019-06-03 11:28:06 +02:00
Ludovic Fernandez
9da0bcf3aa Prepare release v1.7.12 2019-05-29 20:42:06 +02:00
Ludovic Fernandez
51287d9316 Remove authentication hashes from API 2019-05-29 19:22:07 +02:00
Ludovic Fernandez
29307fe9fa fix: update-lego. 2019-05-28 17:32:05 +02:00
ravilr
52772c9642 fix kubernetes template for backend responseforwarding flushinterval setting 2019-05-23 18:14:05 +02:00
ravilr
8f135fdb0a Add missing callback on close of hijacked connections 2019-05-23 09:40:04 +02:00
Ludovic Fernandez
7722a41270 Adds a log fields documentation. 2019-05-21 17:02:11 +02:00
Alex Antonov
cd11b1aab4 Upgraded DataDog tracing library to 1.13.0 2019-05-15 18:04:06 +02:00
Ludovic Fernandez
e7564d4cf8 Enhance KV logs. 2019-05-15 17:20:08 +02:00
Wenxuan Zhao
cc130fb673 Allow SANs for wildcards domain. (#4821) 2019-05-03 18:08:37 +02:00
Greg Berns
4106cf647b Docs: Troubleshooting help for Docker Swarm labels 2019-05-03 10:28:05 +02:00
Ludovic Fernandez
8a1c3510ea Prepare release v1.7.11 2019-04-26 10:34:06 +02:00
Jean-Baptiste Doumenjou
787b0a3ac7 Enhance KV client error management
Co-authored-by: Ludovic Fernandez <ldez@users.noreply.github.com>
2019-04-26 09:36:03 +02:00
Ludovic Fernandez
a6d86cdddb fix: update lego. 2019-04-23 11:40:05 +02:00
mpl
9559a56011 Improve log message about redundant TLS certificate 2019-04-15 12:32:03 +02:00
ctas582
07e8042192 Forward all header values from forward auth response 2019-04-10 17:18:06 +02:00
Martin Hoefling
edd8e36dcc Documentation Update: Hosting.de wildcard support tested 2019-04-09 16:52:05 +02:00
Ludovic Fernandez
e291dcb8d1 Get Structor version from CI env var. 2019-04-08 08:44:03 +02:00
Ludovic Fernandez
de6e365b74 Update zipkin-go-opentracing. 2019-04-05 11:18:04 +02:00
Amir Aslaminejad
98a5e08553 Remove usage of github.com/satori/go.uuid 2019-04-05 08:44:03 +02:00
Brandon McNama
ba44619828 Update Wildcard Domain documentation 2019-04-01 17:42:04 +02:00
Ludovic Fernandez
86d700c845 Enhance k8s tests maintainability 2019-04-01 17:02:06 +02:00
Ludovic Fernandez
b2f11afcc2 Update certificates for some Docker images 2019-04-01 00:54:03 +02:00
Maxim Fominykh
cfb356c68e Keep consistent order 2019-03-29 16:40:03 +01:00
Ludovic Fernandez
266f5d18a8 Prepare release v1.7.10 2019-03-28 15:42:05 +01:00
Julien Salleyron
305af43fb9 Add entrypoints prefix in kubernetes frontend/backend id 2019-03-28 14:22:05 +01:00
Julien Salleyron
30545808d9 Remove thoas/stats fork 2019-03-28 13:46:04 +01:00
Michael
358f125a58 Migrate to dep 0.5 (#4684) 2019-03-28 12:58:57 +01:00
Andy Kipp
57ae9a80d5 Support external name service on global default backend 2019-03-27 17:48:04 +01:00
Alex Antonov
e32c021f16 Added support for configuring trace headers for DataDog tracing 2019-03-27 17:20:05 +01:00
Siyu
0db2a9aadd Exclude websocket connections from Average Response Time 2019-03-27 15:48:04 +01:00
tomberek
4f4dab3ca5 Reorder Auth and TLSClientHeaders middleware 2019-03-27 11:54:05 +01:00
Ludovic Fernandez
eaee39e534 fix: update lego. 2019-03-27 11:18:04 +01:00
Jonas Thelemann
d85eb0495c Add _FILE Environment Variable Documentation 2019-03-27 10:50:03 +01:00
Ludovic Fernandez
8aa618775d New build system for experimental Docker image. 2019-03-19 11:58:03 +01:00
Ludovic Fernandez
f6b7e333be Change deploy script. 2019-03-19 07:20:02 +01:00
Ludovic Fernandez
108d9dbb3f Update structor to restore permalink for the latest version 2019-03-18 11:32:03 +01:00
Emile Vauge
2a1fa32950 Add TraefikEE as security workaround 2019-03-15 18:54:05 +01:00
Ludovic Fernandez
ee7aa77833 Update structor 2019-03-15 16:04:04 +01:00
Ludovic Fernandez
fcc4cab614 Migrate to go-acme/lego. 2019-03-12 16:40:04 +01:00
Damien Duportal
1206cd52fc Travis: switch fallback dockerfile for structor 2019-02-27 18:56:04 +01:00
Daniel Tomcej
5cdba752a4 Loop through service ports for global backend 2019-02-26 17:18:04 +01:00
Damien Duportal
b48ea1e173 Update Structor to v1.4.0 2019-02-20 13:50:03 +01:00
Ludovic Fernandez
373040f552 Applies new goimports recommendations. 2019-02-18 07:50:03 +01:00
1400 changed files with 152375 additions and 27973 deletions

2
.gitattributes vendored
View File

@@ -1 +1 @@
# vendor/github.com/xenolf/lego/providers/dns/cloudxns/cloudxns.go eol=crlf
# vendor/github.com/go-acme/lego/providers/dns/cloudxns/cloudxns.go eol=crlf

18
.gitignore vendored
View File

@@ -1,15 +1,17 @@
/dist
/autogen/genstatic/gen.go
.idea/
.intellij/
*.iml
/traefik
/traefik.toml
/static/
/webui/.tmp/
.vscode/
.DS_Store
/static/
/autogen/genstatic/gen.go
/webui/.tmp/
/examples/acme/acme.json
/site/
/docs/site/
/traefik.toml
/dist
/traefik
*.log
*.exe
.DS_Store
/examples/acme/acme.json
cover.out

20
.semaphoreci/golang.sh Executable file
View File

@@ -0,0 +1,20 @@
#!/usr/bin/env bash
set -e
curl -O https://dl.google.com/go/go1.12.linux-amd64.tar.gz
tar -xvf go1.12.linux-amd64.tar.gz
rm -rf go1.12.linux-amd64.tar.gz
sudo mkdir -p /usr/local/golang/1.12/go
sudo mv go /usr/local/golang/1.12/
sudo rm /usr/local/bin/go
sudo chmod +x /usr/local/golang/1.12/go/bin/go
sudo ln -s /usr/local/golang/1.12/go/bin/go /usr/local/bin/go
export GOROOT="/usr/local/golang/1.12/go"
export GOTOOLDIR="/usr/local/golang/1.12/go/pkg/tool/linux_amd64"
go version

View File

@@ -1,7 +1,7 @@
#!/usr/bin/env bash
set -e
export DOCKER_VERSION=17.03.1
export DOCKER_VERSION=18.09.7
source .semaphoreci/vars

View File

@@ -30,9 +30,8 @@ before_deploy:
make -j${N_MAKE_JOBS} crossbinary-parallel;
tar cfz dist/traefik-${VERSION}.src.tar.gz --exclude-vcs --exclude dist .;
fi;
curl -sI https://github.com/containous/structor/releases/latest | grep -Fi Location | tr -d '\r' | sed "s/tag/download/g" | awk -F " " '{ print $2 "/structor_linux-amd64"}' | wget --output-document=$GOPATH/bin/structor -i -;
chmod +x $GOPATH/bin/structor;
structor -o containous -r traefik --dockerfile-url="https://raw.githubusercontent.com/containous/traefik/master/docs.Dockerfile" --menu.js-url="https://raw.githubusercontent.com/containous/structor/master/traefik-menu.js.gotmpl" --rqts-url="https://raw.githubusercontent.com/containous/structor/master/requirements-override.txt" --exp-branch=master --debug;
curl -sfL https://raw.githubusercontent.com/containous/structor/master/godownloader.sh | bash -s -- -b "${GOPATH}/bin" ${STRUCTOR_VERSION}
structor -o containous -r traefik --dockerfile-url="https://raw.githubusercontent.com/containous/traefik/v1.7/docs.Dockerfile" --menu.js-url="https://raw.githubusercontent.com/containous/structor/master/traefik-menu.js.gotmpl" --rqts-url="https://raw.githubusercontent.com/containous/structor/master/requirements-override.txt" --exp-branch=master --force-edit-url --debug;
fi
deploy:
- provider: releases
@@ -49,11 +48,6 @@ deploy:
on:
repo: containous/traefik
tags: true
- provider: script
script: sh script/deploy-docker.sh
skip_cleanup: true
on:
repo: containous/traefik
- provider: pages
edge: false
github_token: ${GITHUB_TOKEN}

View File

@@ -1,5 +1,107 @@
# Change Log
## [v1.7.15](https://github.com/containous/traefik/tree/v1.7.15) (2019-09-12)
[All Commits](https://github.com/containous/traefik/compare/v1.7.14...v1.7.15)
**Bug fixes:**
- **[authentication,k8s/ingress]** Kubernetes support for Auth.HeaderField ([#5235](https://github.com/containous/traefik/pull/5235) by [ErikWegner](https://github.com/ErikWegner))
- **[k8s,k8s/ingress]** Finish kubernetes throttling refactoring ([#5269](https://github.com/containous/traefik/pull/5269) by [mpl](https://github.com/mpl))
- **[k8s]** Throttle Kubernetes config refresh ([#4716](https://github.com/containous/traefik/pull/4716) by [benweissmann](https://github.com/benweissmann))
- **[k8s]** Fix wrong handling of insecure tls auth forward ingress annotation ([#5319](https://github.com/containous/traefik/pull/5319) by [majkrzak](https://github.com/majkrzak))
- **[middleware]** error pages: do not buffer response when it&#39;s not an error ([#5285](https://github.com/containous/traefik/pull/5285) by [mpl](https://github.com/mpl))
- **[tls]** Consider default cert domain in certificate store ([#5353](https://github.com/containous/traefik/pull/5353) by [nrwiersma](https://github.com/nrwiersma))
- **[tls]** Add TLS minversion constraint ([#5356](https://github.com/containous/traefik/pull/5356) by [dtomcej](https://github.com/dtomcej))
**Documentation:**
- **[acme]** Update Acme doc - Vultr Wildcard &amp; Root ([#5320](https://github.com/containous/traefik/pull/5320) by [ddymko](https://github.com/ddymko))
- **[consulcatalog]** Typo in basic auth usersFile label consul-catalog ([#5230](https://github.com/containous/traefik/pull/5230) by [pitan](https://github.com/pitan))
- **[logs]** Improve Access Logs Documentation page ([#5238](https://github.com/containous/traefik/pull/5238) by [dduportal](https://github.com/dduportal))
## [v1.7.14](https://github.com/containous/traefik/tree/v1.7.14) (2019-08-14)
[All Commits](https://github.com/containous/traefik/compare/v1.7.13...v1.7.14)
**Bug fixes:**
- Update to go1.12.8 ([#5201](https://github.com/containous/traefik/pull/5201) by [ldez](https://github.com/ldez)). HTTP/2 Denial of Service [CVE-2019-9512](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-9512) and [CVE-2019-9514](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-9514)
- **[server]** Make hijackConnectionTracker.Close thread safe ([#5194](https://github.com/containous/traefik/pull/5194) by [jlevesy](https://github.com/jlevesy))
## [v1.7.13](https://github.com/containous/traefik/tree/v1.7.13) (2019-08-07)
[All Commits](https://github.com/containous/traefik/compare/v1.7.12...v1.7.13)
**Bug fixes:**
- **[acme]** Update lego ([#5166](https://github.com/containous/traefik/pull/5166) by [dabeck](https://github.com/dabeck))
- **[consulcatalog]** warning should not be a fail status ([#4537](https://github.com/containous/traefik/pull/4537) by [saez0pub](https://github.com/saez0pub))
- **[docker]** Update docker api version ([#4909](https://github.com/containous/traefik/pull/4909) by [dtomcej](https://github.com/dtomcej))
- **[dynamodb]** Use dynamodbav tags to override json tags. ([#5002](https://github.com/containous/traefik/pull/5002) by [ldez](https://github.com/ldez))
- **[healthcheck]** Wrr loadbalancer honors old weight on recovered servers ([#5051](https://github.com/containous/traefik/pull/5051) by [DougWagner](https://github.com/DougWagner))
- **[k8s]** Check for multiport services on Global Backend Ingress ([#5021](https://github.com/containous/traefik/pull/5021) by [dtomcej](https://github.com/dtomcej))
- **[logs]** Allows logs to use local time zone instead of UTC ([#4954](https://github.com/containous/traefik/pull/4954) by [dduportal](https://github.com/dduportal))
- **[middleware]** Clear TLS client headers if TLSMutualAuth is optional ([#4963](https://github.com/containous/traefik/pull/4963) by [stffabi](https://github.com/stffabi))
- **[tls]** Add missing KeyUsages for default generated certificate ([#5150](https://github.com/containous/traefik/pull/5150) by [dtomcej](https://github.com/dtomcej))
**Documentation:**
- **[acme]** Fixed doc link for AlibabaCloud ([#5109](https://github.com/containous/traefik/pull/5109) by [ddymko](https://github.com/ddymko))
- **[docker]** Add example for CLI ([#5131](https://github.com/containous/traefik/pull/5131) by [alvarezbruned](https://github.com/alvarezbruned))
- **[docker]** Use the latest stable version of traefik in the docs ([#4927](https://github.com/containous/traefik/pull/4927) by [kolaente](https://github.com/kolaente))
- **[logs]** Update documentation to clarify the default format for logs ([#4953](https://github.com/containous/traefik/pull/4953) by [dduportal](https://github.com/dduportal))
- **[rancher]** Add remarks about Rancher 2 ([#4999](https://github.com/containous/traefik/pull/4999) by [ldez](https://github.com/ldez))
- **[tls]** Fixes the TLS Mutual Authentication documentation ([#5085](https://github.com/containous/traefik/pull/5085) by [jbdoumenjou](https://github.com/jbdoumenjou))
- Format YAML example on user guide ([#5067](https://github.com/containous/traefik/pull/5067) by [gurayyildirim](https://github.com/gurayyildirim))
- Update Slack support channel references to Discourse community forum ([#5014](https://github.com/containous/traefik/pull/5014) by [dduportal](https://github.com/dduportal))
- Updating Service Fabric documentation ([#5160](https://github.com/containous/traefik/pull/5160) by [gheibia](https://github.com/gheibia))
- Improve API / Dashboard wording in documentation ([#4929](https://github.com/containous/traefik/pull/4929) by [dduportal](https://github.com/dduportal))
## [v1.7.12](https://github.com/containous/traefik/tree/v1.7.12) (2019-05-29)
[All Commits](https://github.com/containous/traefik/compare/v1.7.11...v1.7.12)
**Bug fixes:**
- **[acme]** Allow SANs for wildcards domain. ([#4821](https://github.com/containous/traefik/pull/4821) by [vizv](https://github.com/vizv))
- **[acme]** fix: update lego. ([#4910](https://github.com/containous/traefik/pull/4910) by [ldez](https://github.com/ldez))
- **[api,authentication]** Remove authentication hashes from API ([#4918](https://github.com/containous/traefik/pull/4918) by [ldez](https://github.com/ldez))
- **[consul]** Enhance KV logs. ([#4877](https://github.com/containous/traefik/pull/4877) by [ldez](https://github.com/ldez))
- **[k8s]** Fix kubernetes template for backend responseforwarding flushinterval setting ([#4901](https://github.com/containous/traefik/pull/4901) by [ravilr](https://github.com/ravilr))
- **[metrics]** Upgraded DataDog tracing library to 1.13.0 ([#4878](https://github.com/containous/traefik/pull/4878) by [aantono](https://github.com/aantono))
- **[server]** Add missing callback on close of hijacked connections ([#4900](https://github.com/containous/traefik/pull/4900) by [ravilr](https://github.com/ravilr))
**Documentation:**
- **[docker]** Docs: Troubleshooting help for Docker Swarm labels ([#4751](https://github.com/containous/traefik/pull/4751) by [gregberns](https://github.com/gregberns))
- **[logs]** Adds a log fields documentation. ([#4890](https://github.com/containous/traefik/pull/4890) by [ldez](https://github.com/ldez))
## [v1.7.11](https://github.com/containous/traefik/tree/v1.7.11) (2019-04-26)
[All Commits](https://github.com/containous/traefik/compare/v1.7.10...v1.7.11)
**Enhancements:**
- **[k8s,k8s/ingress]** Enhance k8s tests maintainability ([#4696](https://github.com/containous/traefik/pull/4696) by [ldez](https://github.com/ldez))
**Bug fixes:**
- **[acme]** fix: update lego. ([#4800](https://github.com/containous/traefik/pull/4800) by [ldez](https://github.com/ldez))
- **[authentication,middleware]** Forward all header values from forward auth response ([#4515](https://github.com/containous/traefik/pull/4515) by [ctas582](https://github.com/ctas582))
- **[cluster]** Remove usage of github.com/satori/go.uuid ([#4722](https://github.com/containous/traefik/pull/4722) by [aaslamin](https://github.com/aaslamin))
- **[kv]** Enhance KV client error management ([#4819](https://github.com/containous/traefik/pull/4819) by [jbdoumenjou](https://github.com/jbdoumenjou))
- **[tls]** Improve log message about redundant TLS certificate ([#4765](https://github.com/containous/traefik/pull/4765) by [mpl](https://github.com/mpl))
- **[tracing]** Update zipkin-go-opentracing. ([#4720](https://github.com/containous/traefik/pull/4720) by [ldez](https://github.com/ldez))
**Documentation:**
- **[acme]** Documentation Update: Hosting.de wildcard support tested ([#4747](https://github.com/containous/traefik/pull/4747) by [martinhoefling](https://github.com/martinhoefling))
- **[acme]** Update Wildcard Domain documentation ([#4682](https://github.com/containous/traefik/pull/4682) by [DWSR](https://github.com/DWSR))
- **[middleware]** Keep consistent order ([#4690](https://github.com/containous/traefik/pull/4690) by [maxifom](https://github.com/maxifom))
## [v1.7.10](https://github.com/containous/traefik/tree/v1.7.10) (2019-03-28)
[All Commits](https://github.com/containous/traefik/compare/v1.7.9...v1.7.10)
**Bug fixes:**
- **[acme]** fix: update lego. ([#4670](https://github.com/containous/traefik/pull/4670) by [ldez](https://github.com/ldez))
- **[acme]** Migrate to go-acme/lego. ([#4577](https://github.com/containous/traefik/pull/4577) by [ldez](https://github.com/ldez))
- **[authentication,middleware]** Reorder Auth and TLSClientHeaders middleware ([#4557](https://github.com/containous/traefik/pull/4557) by [tomberek](https://github.com/tomberek))
- **[k8s/ingress]** Support external name service on global default backend ([#4564](https://github.com/containous/traefik/pull/4564) by [kippandrew](https://github.com/kippandrew))
- **[k8s/ingress]** Loop through service ports for global backend ([#4486](https://github.com/containous/traefik/pull/4486) by [dtomcej](https://github.com/dtomcej))
- **[k8s]** Add entrypoints prefix in kubernetes frontend/backend id ([#4679](https://github.com/containous/traefik/pull/4679) by [juliens](https://github.com/juliens))
- **[websocket]** Exclude websocket connections from Average Response Time ([#4313](https://github.com/containous/traefik/pull/4313) by [siyu6974](https://github.com/siyu6974))
- **[middleware]** Added support for configuring trace headers for DataDog tracing ([#4516](https://github.com/containous/traefik/pull/4516) by [aantono](https://github.com/aantono))
**Documentation:**
- **[acme]** Add _FILE Environment Variable Documentation ([#4643](https://github.com/containous/traefik/pull/4643) by [dargmuesli](https://github.com/dargmuesli))
- **[docker]** Add TraefikEE as security workaround ([#4606](https://github.com/containous/traefik/pull/4606) by [emilevauge](https://github.com/emilevauge))
## [v1.7.9](https://github.com/containous/traefik/tree/v1.7.9) (2019-02-11)
[All Commits](https://github.com/containous/traefik/compare/v1.7.8...v1.7.9)
@@ -1124,7 +1226,7 @@
- **[acme,tls]** Rename TLSConfigurations to TLS. ([#2744](https://github.com/containous/traefik/pull/2744) by [ldez](https://github.com/ldez))
- **[acme,provider,docker,tls]** Make the TLS certificates management dynamic. ([#2233](https://github.com/containous/traefik/pull/2233) by [nmengin](https://github.com/nmengin))
- **[acme]** Add Let&#39;s Encrypt HTTP Challenge ([#2701](https://github.com/containous/traefik/pull/2701) by [Juliens](https://github.com/Juliens))
- **[acme]** Update github.com/xenolf/lego to 0.4.1 ([#2304](https://github.com/containous/traefik/pull/2304) by [oldmantaiter](https://github.com/oldmantaiter))
- **[acme]** Update github.com/go-acme/lego to 0.4.1 ([#2304](https://github.com/containous/traefik/pull/2304) by [oldmantaiter](https://github.com/oldmantaiter))
- **[api,healthcheck,metrics,provider,webui]** Split Web into API/Dashboard, ping, metric and Rest Provider ([#2335](https://github.com/containous/traefik/pull/2335) by [Juliens](https://github.com/Juliens))
- **[authentication]** Pass through certain forward auth negative response headers ([#2127](https://github.com/containous/traefik/pull/2127) by [wheresmysocks](https://github.com/wheresmysocks))
- **[cluster,consul,file]** Add file to storeconfig ([#2419](https://github.com/containous/traefik/pull/2419) by [emilevauge](https://github.com/emilevauge))
@@ -1403,7 +1505,7 @@
**Enhancements:**
- **[acme,provider,docker,tls]** Make the TLS certificates management dynamic. ([#2233](https://github.com/containous/traefik/pull/2233) by [nmengin](https://github.com/nmengin))
- **[acme]** Update github.com/xenolf/lego to 0.4.1 ([#2304](https://github.com/containous/traefik/pull/2304) by [oldmantaiter](https://github.com/oldmantaiter))
- **[acme]** Update github.com/go-acme/lego to 0.4.1 ([#2304](https://github.com/containous/traefik/pull/2304) by [oldmantaiter](https://github.com/oldmantaiter))
- **[api,healthcheck,metrics,provider,webui]** Split Web into API/Dashboard, ping, metric and Rest Provider ([#2335](https://github.com/containous/traefik/pull/2335) by [Juliens](https://github.com/Juliens))
- **[authentication]** Pass through certain forward auth negative response headers ([#2127](https://github.com/containous/traefik/pull/2127) by [wheresmysocks](https://github.com/wheresmysocks))
- **[cluster,consul,file]** Add file to storeconfig ([#2419](https://github.com/containous/traefik/pull/2419) by [emilevauge](https://github.com/emilevauge))

View File

@@ -13,7 +13,7 @@ You need to run the `binary` target. This will create binaries for Linux platfor
$ make binary
docker build -t "traefik-dev:no-more-godep-ever" -f build.Dockerfile .
Sending build context to Docker daemon 295.3 MB
Step 0 : FROM golang:1.11-alpine
Step 0 : FROM golang:1.12-alpine
---> 8c6473912976
Step 1 : RUN go get github.com/golang/dep/cmd/dep
[...]
@@ -87,7 +87,7 @@ If you happen to update the provider templates (in `/templates`), you need to ru
[dep](https://github.com/golang/dep) is not required for building; however, it is necessary to modify dependencies (i.e., add, update, or remove third-party packages)
You need to use [dep](https://github.com/golang/dep) >= 0.4.1 and < 0.5.0.
You need to use [dep](https://github.com/golang/dep) >= 0.5.0.
If you want to add a dependency, use `dep ensure -add` to have [dep](https://github.com/golang/dep) put it into the vendor folder and update the dep manifest/lock files (`Gopkg.toml` and `Gopkg.lock`, respectively).
@@ -158,7 +158,7 @@ Integration tests must be run from the `integration/` directory and require the
## Documentation
The [documentation site](http://docs.traefik.io/) is built with [mkdocs](http://mkdocs.org/)
The [documentation site](https://docs.traefik.io/) is built with [mkdocs](https://mkdocs.org/)
### Building Documentation

2528
Gopkg.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -36,6 +36,10 @@
branch = "master"
name = "github.com/BurntSushi/ty"
[[constraint]]
name = "github.com/Masterminds/sprig"
version = "2.19.0"
[[constraint]]
branch = "master"
name = "github.com/NYTimes/gziphandler"
@@ -45,6 +49,11 @@
name = "github.com/abbot/go-http-auth"
source = "github.com/containous/go-http-auth"
[[constraint]]
name = "github.com/thoas/stats"
# related to https://github.com/thoas/stats/pull/32
revision = "4975baf6a358ed3ddaa42133996e1959f96c9300"
[[constraint]]
branch = "master"
name = "github.com/armon/go-proxyproto"
@@ -54,8 +63,8 @@
version = "1.13.11"
[[constraint]]
branch = "master"
name = "github.com/cenk/backoff"
version = "v2.1.1"
[[constraint]]
name = "github.com/containous/flaeg"
@@ -71,7 +80,7 @@
[[constraint]]
name = "github.com/containous/traefik-extra-service-fabric"
version = "1.4.0"
version = "v1.5.0"
[[constraint]]
name = "github.com/coreos/go-systemd"
@@ -117,8 +126,8 @@
version = "1.3.7"
[[constraint]]
branch = "master"
name = "github.com/jjcollinge/servicefabric"
revision = "8eebe170fa1ba25d3dfb928b3f86a7313b13b9fe"
[[constraint]]
branch = "master"
@@ -128,18 +137,6 @@
name = "github.com/mesosphere/mesos-dns"
source = "https://github.com/containous/mesos-dns.git"
[[constraint]]
branch = "master"
name = "github.com/mitchellh/copystructure"
[[constraint]]
branch = "master"
name = "github.com/mitchellh/hashstructure"
[[constraint]]
branch = "master"
name = "github.com/mitchellh/mapstructure"
[[constraint]]
name = "github.com/opentracing/opentracing-go"
version = "1.0.2"
@@ -153,10 +150,6 @@
branch = "master"
name = "github.com/ryanuber/go-glob"
[[constraint]]
name = "github.com/satori/go.uuid"
version = "1.1.0"
[[constraint]]
branch = "master"
name = "github.com/stvp/go-udp-testing"
@@ -186,9 +179,12 @@
name = "github.com/vulcand/oxy"
[[constraint]]
# branch = "master"
name = "github.com/xenolf/lego"
version = "2.0.1"
name = "github.com/go-acme/lego"
version = "2.7.2"
[[constraint]]
name = "github.com/golang/protobuf"
version = "v1.3.0"
[[constraint]]
name = "google.golang.org/grpc"
@@ -263,4 +259,8 @@
[[constraint]]
name = "gopkg.in/DataDog/dd-trace-go.v1"
version = "1.7.0"
version = "1.13.0"
[[constraint]]
name = "github.com/google/uuid"
version = "0.2.0"

View File

@@ -76,7 +76,7 @@ test-integration: build ## run the integration tests
TEST_HOST=1 ./script/make.sh test-integration
validate: build ## validate code, vendor and autogen
$(DOCKER_RUN_TRAEFIK) ./script/make.sh validate-gofmt validate-govet validate-golint validate-misspell validate-vendor validate-autogen
$(DOCKER_RUN_TRAEFIK) ./script/make.sh validate-gofmt validate-golint validate-misspell validate-vendor validate-autogen
build: dist
docker build $(DOCKER_BUILD_ARGS) -t "$(TRAEFIK_DEV_IMAGE)" -f build.Dockerfile .

View File

@@ -113,13 +113,13 @@ If you need commercial support, please contact [Containo.us](https://containo.us
## Download
- Grab the latest binary from the [releases](https://github.com/containous/traefik/releases) page and run it with the [sample configuration file](https://raw.githubusercontent.com/containous/traefik/master/traefik.sample.toml):
- Grab the latest binary from the [releases](https://github.com/containous/traefik/releases) page and run it with the [sample configuration file](https://raw.githubusercontent.com/containous/traefik/v1.7/traefik.sample.toml):
```shell
./traefik --configFile=traefik.toml
```
- Or use the official tiny Docker image and run it with the [sample configuration file](https://raw.githubusercontent.com/containous/traefik/master/traefik.sample.toml):
- Or use the official tiny Docker image and run it with the [sample configuration file](https://raw.githubusercontent.com/containous/traefik/v1.7/traefik.sample.toml):
```shell
docker run -d -p 8080:8080 -p 80:80 -v $PWD/traefik.toml:/etc/traefik/traefik.toml traefik

View File

@@ -17,8 +17,8 @@ import (
"github.com/containous/traefik/log"
acmeprovider "github.com/containous/traefik/provider/acme"
"github.com/containous/traefik/types"
"github.com/xenolf/lego/certcrypto"
"github.com/xenolf/lego/registration"
"github.com/go-acme/lego/certcrypto"
"github.com/go-acme/lego/registration"
)
// Account is used to store lets encrypt registration info

View File

@@ -27,19 +27,19 @@ import (
"github.com/containous/traefik/types"
"github.com/containous/traefik/version"
"github.com/eapache/channels"
"github.com/go-acme/lego/certificate"
"github.com/go-acme/lego/challenge"
"github.com/go-acme/lego/challenge/dns01"
"github.com/go-acme/lego/challenge/http01"
"github.com/go-acme/lego/lego"
legolog "github.com/go-acme/lego/log"
"github.com/go-acme/lego/providers/dns"
"github.com/go-acme/lego/registration"
"github.com/sirupsen/logrus"
"github.com/xenolf/lego/certificate"
"github.com/xenolf/lego/challenge"
"github.com/xenolf/lego/challenge/dns01"
"github.com/xenolf/lego/challenge/http01"
"github.com/xenolf/lego/lego"
legolog "github.com/xenolf/lego/log"
"github.com/xenolf/lego/providers/dns"
"github.com/xenolf/lego/registration"
)
var (
// OSCPMustStaple enables OSCP stapling as from https://github.com/xenolf/lego/issues/270
// OSCPMustStaple enables OSCP stapling as from https://github.com/go-acme/lego/issues/270
OSCPMustStaple = false
)
@@ -751,12 +751,6 @@ func (a *ACME) getValidDomains(domains []string, wildcardAllowed bool) ([]string
return nil, fmt.Errorf("unable to generate a wildcard certificate for domain %q : ACME does not allow '*.*' wildcard domain", strings.Join(domains, ","))
}
}
for _, san := range domains[1:] {
if strings.HasPrefix(san, "*") {
return nil, fmt.Errorf("unable to generate a certificate for domains %q: SANs can not be a wildcard domain", strings.Join(domains, ","))
}
}
domains = fun.Map(types.CanonicalDomain, domains).([]string)
return domains, nil

View File

@@ -419,12 +419,12 @@ func TestAcme_getValidDomain(t *testing.T) {
expectedDomains: []string{"*.traefik.wtf", "traefik.wtf"},
},
{
desc: "unexpected SANs",
desc: "wildcard SANs",
domains: []string{"*.traefik.wtf", "*.acme.wtf"},
dnsChallenge: &acmeprovider.DNSChallenge{},
wildcardAllowed: true,
expectedErr: "unable to generate a certificate for domains \"*.traefik.wtf,*.acme.wtf\": SANs can not be a wildcard domain",
expectedDomains: nil,
expectedErr: "",
expectedDomains: []string{"*.traefik.wtf", "*.acme.wtf"},
},
}
for _, test := range testCases {

View File

@@ -9,7 +9,7 @@ import (
"github.com/containous/traefik/cluster"
"github.com/containous/traefik/log"
"github.com/containous/traefik/safe"
"github.com/xenolf/lego/challenge"
"github.com/go-acme/lego/challenge"
)
var _ challenge.ProviderTimeout = (*challengeHTTPProvider)(nil)

View File

@@ -11,8 +11,8 @@ import (
"github.com/containous/traefik/cluster"
"github.com/containous/traefik/log"
"github.com/containous/traefik/safe"
"github.com/xenolf/lego/challenge"
"github.com/xenolf/lego/challenge/tlsalpn01"
"github.com/go-acme/lego/challenge"
"github.com/go-acme/lego/challenge/tlsalpn01"
)
var _ challenge.ProviderTimeout = (*challengeTLSProvider)(nil)

View File

@@ -31,7 +31,7 @@ import (
"github.com/containous/traefik/safe"
traefiktls "github.com/containous/traefik/tls"
"github.com/containous/traefik/types"
"github.com/elazarl/go-bindata-assetfs"
assetfs "github.com/elazarl/go-bindata-assetfs"
"github.com/thoas/stats"
)

View File

@@ -5,7 +5,7 @@ import (
"github.com/containous/mux"
"github.com/containous/traefik/log"
"github.com/elazarl/go-bindata-assetfs"
assetfs "github.com/elazarl/go-bindata-assetfs"
)
// DashboardHandler expose dashboard routes

View File

@@ -9,7 +9,7 @@ import (
"github.com/containous/traefik/safe"
"github.com/containous/traefik/types"
"github.com/containous/traefik/version"
"github.com/elazarl/go-bindata-assetfs"
assetfs "github.com/elazarl/go-bindata-assetfs"
thoas_stats "github.com/thoas/stats"
"github.com/unrolled/render"
)

View File

@@ -1316,7 +1316,7 @@ var _templatesKubernetesTmpl = []byte(`[backends]
{{if $backend.ResponseForwarding }}
[backends."{{ $backendName }}".responseForwarding]
flushInterval = "{{ $backend.responseForwarding.FlushInterval }}"
flushInterval = "{{ $backend.ResponseForwarding.FlushInterval }}"
{{end}}
[backends."{{ $backendName }}".loadBalancer]
@@ -1365,7 +1365,9 @@ var _templatesKubernetesTmpl = []byte(`[backends]
{{if $frontend.Auth }}
[frontends."{{ $frontendName }}".auth]
headerField = "X-WebAuth-User"
{{if $frontend.Auth.HeaderField }}
headerField = "{{ $frontend.Auth.HeaderField }}"
{{end}}
{{if $frontend.Auth.Basic }}
[frontends."{{ $frontendName }}".auth.basic]

View File

@@ -1,16 +1,16 @@
FROM golang:1.11-alpine
FROM golang:1.12-alpine
RUN apk --update upgrade \
&& apk --no-cache --no-progress add git mercurial bash gcc musl-dev curl tar \
&& rm -rf /var/cache/apk/*
&& apk --no-cache --no-progress add git mercurial bash gcc musl-dev curl tar ca-certificates tzdata \
&& update-ca-certificates \
&& rm -rf /var/cache/apk/*
RUN go get golang.org/x/lint/golint \
&& go get github.com/kisielk/errcheck \
&& go get github.com/client9/misspell/cmd/misspell
# Which docker version to test on
ARG DOCKER_VERSION=17.03.2
ARG DEP_VERSION=0.4.1
ARG DOCKER_VERSION=18.09.7
ARG DEP_VERSION=0.5.1
# Download go-bindata binary to bin folder in $GOPATH
RUN mkdir -p /usr/local/bin \
@@ -24,7 +24,7 @@ RUN mkdir -p /usr/local/bin \
# Download docker
RUN mkdir -p /usr/local/bin \
&& curl -fL https://download.docker.com/linux/static/stable/x86_64/docker-${DOCKER_VERSION}-ce.tgz \
&& curl -fL https://download.docker.com/linux/static/stable/x86_64/docker-${DOCKER_VERSION}.tgz \
| tar -xzC /usr/local/bin --transform 's#^.+/##x'
WORKDIR /go/src/github.com/containous/traefik

View File

@@ -13,7 +13,7 @@ import (
"github.com/containous/traefik/job"
"github.com/containous/traefik/log"
"github.com/containous/traefik/safe"
"github.com/satori/go.uuid"
"github.com/google/uuid"
)
// Metadata stores Object plus metadata
@@ -125,7 +125,7 @@ func (d *Datastore) reload() error {
// Begin creates a transaction with the KV store.
func (d *Datastore) Begin() (Transaction, Object, error) {
id := uuid.NewV4().String()
id := uuid.New().String()
log.Debugf("Transaction %s begins", id)
remoteLock, err := d.kv.NewLock(d.lockKey, &store.LockOptions{TTL: 20 * time.Second, Value: []byte(id)})
if err != nil {

View File

@@ -4,7 +4,7 @@ import (
"time"
"github.com/containous/flaeg"
"github.com/containous/traefik-extra-service-fabric"
servicefabric "github.com/containous/traefik-extra-service-fabric"
"github.com/containous/traefik/api"
"github.com/containous/traefik/configuration"
"github.com/containous/traefik/middlewares/accesslog"
@@ -111,6 +111,7 @@ func NewTraefikDefaultPointersConfiguration() *TraefikConfiguration {
defaultConsulCatalog.Prefix = "traefik"
defaultConsulCatalog.FrontEndRule = "Host:{{.ServiceName}}.{{.Domain}}"
defaultConsulCatalog.Stale = false
defaultConsulCatalog.StrictChecks = true
// default Etcd
var defaultEtcd etcd.Provider

View File

@@ -34,7 +34,7 @@ import (
"github.com/containous/traefik/types"
"github.com/containous/traefik/version"
"github.com/coreos/go-systemd/daemon"
"github.com/elazarl/go-bindata-assetfs"
assetfs "github.com/elazarl/go-bindata-assetfs"
"github.com/ogier/pflag"
"github.com/sirupsen/logrus"
"github.com/vulcand/oxy/roundrobin"

View File

@@ -6,7 +6,7 @@ import (
"time"
"github.com/containous/flaeg"
"github.com/containous/traefik-extra-service-fabric"
servicefabric "github.com/containous/traefik-extra-service-fabric"
"github.com/containous/traefik/acme"
"github.com/containous/traefik/api"
"github.com/containous/traefik/log"
@@ -33,9 +33,9 @@ import (
"github.com/containous/traefik/provider/zk"
"github.com/containous/traefik/tls"
"github.com/containous/traefik/types"
"github.com/go-acme/lego/challenge/dns01"
"github.com/pkg/errors"
jaegercli "github.com/uber/jaeger-client-go"
"github.com/xenolf/lego/challenge/dns01"
)
const (
@@ -212,6 +212,12 @@ func (gc *GlobalConfiguration) SetEffectiveConfiguration(configFile string) {
}
}
// Thanks to SSLv3 being enabled by mistake in golang 1.12,
// If no minVersion is set, apply TLS1.0 as the minimum.
if entryPoint.TLS != nil && len(entryPoint.TLS.MinVersion) == 0 {
entryPoint.TLS.MinVersion = "VersionTLS10"
}
if entryPoint.TLS != nil && entryPoint.TLS.DefaultCertificate == nil && len(entryPoint.TLS.Certificates) > 0 {
log.Infof("No tls.defaultCertificate given for %s: using the first item in tls.certificates as a fallback.", entryPointName)
entryPoint.TLS.DefaultCertificate = &entryPoint.TLS.Certificates[0]

View File

@@ -12,6 +12,7 @@ import (
"github.com/containous/traefik/provider"
acmeprovider "github.com/containous/traefik/provider/acme"
"github.com/containous/traefik/provider/file"
"github.com/containous/traefik/tls"
"github.com/stretchr/testify/assert"
)
@@ -269,3 +270,69 @@ func TestInitACMEProvider(t *testing.T) {
})
}
}
func TestSetEffectiveConfigurationTLSMinVersion(t *testing.T) {
testCases := []struct {
desc string
provided EntryPoint
expected EntryPoint
}{
{
desc: "Entrypoint with no TLS",
provided: EntryPoint{
Address: ":80",
},
expected: EntryPoint{
Address: ":80",
ForwardedHeaders: &ForwardedHeaders{Insecure: true},
},
},
{
desc: "Entrypoint with TLS Specifying MinVersion",
provided: EntryPoint{
Address: ":443",
TLS: &tls.TLS{
MinVersion: "VersionTLS12",
},
},
expected: EntryPoint{
Address: ":443",
ForwardedHeaders: &ForwardedHeaders{Insecure: true},
TLS: &tls.TLS{
MinVersion: "VersionTLS12",
},
},
},
{
desc: "Entrypoint with TLS without Specifying MinVersion",
provided: EntryPoint{
Address: ":443",
TLS: &tls.TLS{},
},
expected: EntryPoint{
Address: ":443",
ForwardedHeaders: &ForwardedHeaders{Insecure: true},
TLS: &tls.TLS{
MinVersion: "VersionTLS10",
},
},
},
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
gc := &GlobalConfiguration{
EntryPoints: map[string]*EntryPoint{
"foo": &test.provided,
},
}
gc.SetEffectiveConfiguration(defaultConfigFile)
assert.Equal(t, &test.expected, gc.EntryPoints["foo"])
})
}
}

View File

@@ -746,7 +746,7 @@ Once a day (the first call begins 10 minutes after the start of Traefik), we col
### Show me the code !
If you want to dig into more details, here is the source code of the collecting system: [collector.go](https://github.com/containous/traefik/blob/master/collector/collector.go)
If you want to dig into more details, here is the source code of the collecting system: [collector.go](https://github.com/containous/traefik/blob/v1.7/collector/collector.go)
By default we anonymize all configuration fields, except fields tagged with `export=true`.

View File

@@ -273,63 +273,73 @@ Useful if internal networks block external DNS queries.
Here is a list of supported `provider`s, that can automate the DNS verification, along with the required environment variables and their [wildcard & root domain support](/configuration/acme/#wildcard-domains) for each.
Do not hesitate to complete it.
Every lego environment variable can be overridden by their respective `_FILE` counterpart, which should have a filepath to a file that contains the secret as its value.
For example, `CF_API_EMAIL_FILE=/run/secrets/traefik_cf-api-email` could be used to provide a Cloudflare API email address as a Docker secret named `traefik_cf-api-email`.
| Provider Name | Provider Code | Environment Variables | Wildcard & Root Domain Support |
|-------------------------------------------------------------|----------------|-------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------|
| [ACME DNS](https://github.com/joohoi/acme-dns) | `acme-dns` | `ACME_DNS_API_BASE`, `ACME_DNS_STORAGE_PATH` | Not tested yet |
| [Alibaba Cloud](https://www.vultr.com) | `alidns` | `ALICLOUD_ACCESS_KEY`, `ALICLOUD_SECRET_KEY`, `ALICLOUD_REGION_ID` | Not tested yet |
| [Auroradns](https://www.pcextreme.com/aurora/dns) | `auroradns` | `AURORA_USER_ID`, `AURORA_KEY`, `AURORA_ENDPOINT` | Not tested yet |
| [Azure](https://azure.microsoft.com/services/dns/) | `azure` | `AZURE_CLIENT_ID`, `AZURE_CLIENT_SECRET`, `AZURE_SUBSCRIPTION_ID`, `AZURE_TENANT_ID`, `AZURE_RESOURCE_GROUP`, `[AZURE_METADATA_ENDPOINT]` | Not tested yet |
| [Blue Cat](https://www.bluecatnetworks.com/) | `bluecat` | `BLUECAT_SERVER_URL`, `BLUECAT_USER_NAME`, `BLUECAT_PASSWORD`, `BLUECAT_CONFIG_NAME`, `BLUECAT_DNS_VIEW` | Not tested yet |
| [Cloudflare](https://www.cloudflare.com) | `cloudflare` | `CF_API_EMAIL`, `CF_API_KEY` - The `Global API Key` needs to be used, not the `Origin CA Key` | YES |
| [CloudXNS](https://www.cloudxns.net) | `cloudxns` | `CLOUDXNS_API_KEY`, `CLOUDXNS_SECRET_KEY` | Not tested yet |
| [ConoHa](https://www.conoha.jp) | `conoha` | `CONOHA_TENANT_ID`, `CONOHA_API_USERNAME`, `CONOHA_API_PASSWORD` | YES |
| [DigitalOcean](https://www.digitalocean.com) | `digitalocean` | `DO_AUTH_TOKEN` | YES |
| [DNSimple](https://dnsimple.com) | `dnsimple` | `DNSIMPLE_OAUTH_TOKEN`, `DNSIMPLE_BASE_URL` | YES |
| [DNS Made Easy](https://dnsmadeeasy.com) | `dnsmadeeasy` | `DNSMADEEASY_API_KEY`, `DNSMADEEASY_API_SECRET`, `DNSMADEEASY_SANDBOX` | Not tested yet |
| [DNSPod](https://www.dnspod.com/) | `dnspod` | `DNSPOD_API_KEY` | Not tested yet |
| [DreamHost](https://www.dreamhost.com/) | `dreamhost` | `DREAMHOST_API_KEY` | YES |
| [Duck DNS](https://www.duckdns.org/) | `duckdns` | `DUCKDNS_TOKEN` | YES |
| [Dyn](https://dyn.com) | `dyn` | `DYN_CUSTOMER_NAME`, `DYN_USER_NAME`, `DYN_PASSWORD` | Not tested yet |
| External Program | `exec` | `EXEC_PATH` | YES |
| [Exoscale](https://www.exoscale.com) | `exoscale` | `EXOSCALE_API_KEY`, `EXOSCALE_API_SECRET`, `EXOSCALE_ENDPOINT` | YES |
| [Fast DNS](https://www.akamai.com/) | `fastdns` | `AKAMAI_CLIENT_TOKEN`, `AKAMAI_CLIENT_SECRET`, `AKAMAI_ACCESS_TOKEN` | YES |
| [Gandi](https://www.gandi.net) | `gandi` | `GANDI_API_KEY` | Not tested yet |
| [Gandi v5](http://doc.livedns.gandi.net) | `gandiv5` | `GANDIV5_API_KEY` | YES |
| [Glesys](https://glesys.com/) | `glesys` | `GLESYS_API_USER`, `GLESYS_API_KEY`, `GLESYS_DOMAIN` | Not tested yet |
| [GoDaddy](https://godaddy.com/domains) | `godaddy` | `GODADDY_API_KEY`, `GODADDY_API_SECRET` | Not tested yet |
| [Google Cloud DNS](https://cloud.google.com/dns/docs/) | `gcloud` | `GCE_PROJECT`, Application Default Credentials (2) (3), [`GCE_SERVICE_ACCOUNT_FILE`] | YES |
| [hosting.de](https://www.hosting.de) | `hostingde` | `HOSTINGDE_API_KEY`, `HOSTINGDE_ZONE_NAME` | Not tested yet |
| HTTP request | `httpreq` | `HTTPREQ_ENDPOINT`, `HTTPREQ_MODE`, `HTTPREQ_USERNAME`, `HTTPREQ_PASSWORD` (1) | YES |
| [IIJ](https://www.iij.ad.jp/) | `iij` | `IIJ_API_ACCESS_KEY`, `IIJ_API_SECRET_KEY`, `IIJ_DO_SERVICE_CODE` | Not tested yet |
| [INWX](https://www.inwx.de/en) | `inwx` | `INWX_USERNAME`, `INWX_PASSWORD` | YES |
| [Lightsail](https://aws.amazon.com/lightsail/) | `lightsail` | `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `DNS_ZONE` | Not tested yet |
| [Linode](https://www.linode.com) | `linode` | `LINODE_API_KEY` | Not tested yet |
| [Linode v4](https://www.linode.com) | `linodev4` | `LINODE_TOKEN` | Not tested yet |
| manual | - | none, but you need to run Traefik interactively, turn on `acmeLogging` to see instructions and press <kbd>Enter</kbd>. | YES |
| [MyDNS.jp](https://www.mydns.jp/) | `mydnsjp` | `MYDNSJP_MASTER_ID`, `MYDNSJP_PASSWORD` | YES |
| [Namecheap](https://www.namecheap.com) | `namecheap` | `NAMECHEAP_API_USER`, `NAMECHEAP_API_KEY` | YES |
| [name.com](https://www.name.com/) | `namedotcom` | `NAMECOM_USERNAME`, `NAMECOM_API_TOKEN`, `NAMECOM_SERVER` | Not tested yet |
| [Netcup](https://www.netcup.eu/) | `netcup` | `NETCUP_CUSTOMER_NUMBER`, `NETCUP_API_KEY`, `NETCUP_API_PASSWORD` | Not tested yet |
| [NIFCloud](https://cloud.nifty.com/service/dns.htm) | `nifcloud` | `NIFCLOUD_ACCESS_KEY_ID`, `NIFCLOUD_SECRET_ACCESS_KEY` | Not tested yet |
| [Ns1](https://ns1.com/) | `ns1` | `NS1_API_KEY` | Not tested yet |
| [Open Telekom Cloud](https://cloud.telekom.de) | `otc` | `OTC_DOMAIN_NAME`, `OTC_USER_NAME`, `OTC_PASSWORD`, `OTC_PROJECT_NAME`, `OTC_IDENTITY_ENDPOINT` | Not tested yet |
| [OVH](https://www.ovh.com) | `ovh` | `OVH_ENDPOINT`, `OVH_APPLICATION_KEY`, `OVH_APPLICATION_SECRET`, `OVH_CONSUMER_KEY` | YES |
| [Openstack Designate](https://docs.openstack.org/designate) | `designate` | `OS_AUTH_URL`, `OS_USERNAME`, `OS_PASSWORD`, `OS_TENANT_NAME`, `OS_REGION_NAME` | YES |
| [PowerDNS](https://www.powerdns.com) | `pdns` | `PDNS_API_KEY`, `PDNS_API_URL` | Not tested yet |
| [Rackspace](https://www.rackspace.com/cloud/dns) | `rackspace` | `RACKSPACE_USER`, `RACKSPACE_API_KEY` | Not tested yet |
| [RFC2136](https://tools.ietf.org/html/rfc2136) | `rfc2136` | `RFC2136_TSIG_KEY`, `RFC2136_TSIG_SECRET`, `RFC2136_TSIG_ALGORITHM`, `RFC2136_NAMESERVER` | Not tested yet |
| [Route 53](https://aws.amazon.com/route53/) | `route53` | `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `[AWS_REGION]`, `[AWS_HOSTED_ZONE_ID]` or a configured user/instance IAM profile. | YES |
| [Sakura Cloud](https://cloud.sakura.ad.jp/) | `sakuracloud` | `SAKURACLOUD_ACCESS_TOKEN`, `SAKURACLOUD_ACCESS_TOKEN_SECRET` | Not tested yet |
| [Selectel](https://selectel.ru/en/) | `selectel` | `SELECTEL_API_TOKEN` | YES |
| [Stackpath](https://www.stackpath.com/) | `stackpath` | `STACKPATH_CLIENT_ID`, `STACKPATH_CLIENT_SECRET`, `STACKPATH_STACK_ID` | Not tested yet |
| [TransIP](https://www.transip.nl/) | `transip` | `TRANSIP_ACCOUNT_NAME`, `TRANSIP_PRIVATE_KEY_PATH` | YES |
| [VegaDNS](https://github.com/shupp/VegaDNS-API) | `vegadns` | `SECRET_VEGADNS_KEY`, `SECRET_VEGADNS_SECRET`, `VEGADNS_URL` | Not tested yet |
| [Vscale](https://vscale.io/) | `vscale` | `VSCALE_API_TOKEN` | YES |
| [VULTR](https://www.vultr.com) | `vultr` | `VULTR_API_KEY` | Not tested yet |
| [Zone.ee](https://www.zone.ee) | `zoneee` | `ZONEEE_API_USER`, `ZONEEE_API_KEY` | YES |
| Provider Name | Provider Code | Environment Variables | Wildcard & Root Domain Support |
|-------------------------------------------------------------|----------------|---------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------|
| [ACME DNS](https://github.com/joohoi/acme-dns) | `acme-dns` | `ACME_DNS_API_BASE`, `ACME_DNS_STORAGE_PATH` | Not tested yet |
| [Alibaba Cloud](https://www.alibabacloud.com) | `alidns` | `ALICLOUD_ACCESS_KEY`, `ALICLOUD_SECRET_KEY`, `ALICLOUD_REGION_ID` | Not tested yet |
| [Auroradns](https://www.pcextreme.com/aurora/dns) | `auroradns` | `AURORA_USER_ID`, `AURORA_KEY`, `AURORA_ENDPOINT` | Not tested yet |
| [Azure](https://azure.microsoft.com/services/dns/) | `azure` | `AZURE_CLIENT_ID`, `AZURE_CLIENT_SECRET`, `AZURE_SUBSCRIPTION_ID`, `AZURE_TENANT_ID`, `AZURE_RESOURCE_GROUP`, `[AZURE_METADATA_ENDPOINT]` | Not tested yet |
| [Bindman](https://github.com/labbsr0x/bindman-dns-webhook) | `bindman` | `BINDMAN_MANAGER_ADDRESS` | YES |
| [Blue Cat](https://www.bluecatnetworks.com/) | `bluecat` | `BLUECAT_SERVER_URL`, `BLUECAT_USER_NAME`, `BLUECAT_PASSWORD`, `BLUECAT_CONFIG_NAME`, `BLUECAT_DNS_VIEW` | Not tested yet |
| [ClouDNS](https://www.cloudns.net/) | `cloudns` | `CLOUDNS_AUTH_ID`, `CLOUDNS_AUTH_PASSWORD` | YES |
| [Cloudflare](https://www.cloudflare.com) | `cloudflare` | `CF_API_EMAIL`, `CF_API_KEY` - The `Global API Key` needs to be used, not the `Origin CA Key` | YES |
| [CloudXNS](https://www.cloudxns.net) | `cloudxns` | `CLOUDXNS_API_KEY`, `CLOUDXNS_SECRET_KEY` | Not tested yet |
| [ConoHa](https://www.conoha.jp) | `conoha` | `CONOHA_TENANT_ID`, `CONOHA_API_USERNAME`, `CONOHA_API_PASSWORD` | YES |
| [DigitalOcean](https://www.digitalocean.com) | `digitalocean` | `DO_AUTH_TOKEN` | YES |
| [DNSimple](https://dnsimple.com) | `dnsimple` | `DNSIMPLE_OAUTH_TOKEN`, `DNSIMPLE_BASE_URL` | YES |
| [DNS Made Easy](https://dnsmadeeasy.com) | `dnsmadeeasy` | `DNSMADEEASY_API_KEY`, `DNSMADEEASY_API_SECRET`, `DNSMADEEASY_SANDBOX` | Not tested yet |
| [DNSPod](https://www.dnspod.com/) | `dnspod` | `DNSPOD_API_KEY` | Not tested yet |
| [Domain Offensive (do.de)](https://www.do.de/) | `dode` | `DODE_TOKEN` | YES |
| [DreamHost](https://www.dreamhost.com/) | `dreamhost` | `DREAMHOST_API_KEY` | YES |
| [Duck DNS](https://www.duckdns.org/) | `duckdns` | `DUCKDNS_TOKEN` | YES |
| [Dyn](https://dyn.com) | `dyn` | `DYN_CUSTOMER_NAME`, `DYN_USER_NAME`, `DYN_PASSWORD` | Not tested yet |
| [EasyDNS](https://easydns.com/) | `easydns` | `EASYDNS_TOKEN`, `EASYDNS_KEY` | YES |
| External Program | `exec` | `EXEC_PATH` | YES |
| [Exoscale](https://www.exoscale.com) | `exoscale` | `EXOSCALE_API_KEY`, `EXOSCALE_API_SECRET`, `EXOSCALE_ENDPOINT` | YES |
| [Fast DNS](https://www.akamai.com/) | `fastdns` | `AKAMAI_CLIENT_TOKEN`, `AKAMAI_CLIENT_SECRET`, `AKAMAI_ACCESS_TOKEN` | YES |
| [Gandi](https://www.gandi.net) | `gandi` | `GANDI_API_KEY` | Not tested yet |
| [Gandi v5](http://doc.livedns.gandi.net) | `gandiv5` | `GANDIV5_API_KEY` | YES |
| [Glesys](https://glesys.com/) | `glesys` | `GLESYS_API_USER`, `GLESYS_API_KEY`, `GLESYS_DOMAIN` | Not tested yet |
| [GoDaddy](https://godaddy.com/domains) | `godaddy` | `GODADDY_API_KEY`, `GODADDY_API_SECRET` | Not tested yet |
| [Google Cloud DNS](https://cloud.google.com/dns/docs/) | `gcloud` | `GCE_PROJECT`, Application Default Credentials (2) (3), [`GCE_SERVICE_ACCOUNT_FILE`] | YES |
| [hosting.de](https://www.hosting.de) | `hostingde` | `HOSTINGDE_API_KEY`, `HOSTINGDE_ZONE_NAME` | YES |
| HTTP request | `httpreq` | `HTTPREQ_ENDPOINT`, `HTTPREQ_MODE`, `HTTPREQ_USERNAME`, `HTTPREQ_PASSWORD` (1) | YES |
| [IIJ](https://www.iij.ad.jp/) | `iij` | `IIJ_API_ACCESS_KEY`, `IIJ_API_SECRET_KEY`, `IIJ_DO_SERVICE_CODE` | Not tested yet |
| [INWX](https://www.inwx.de/en) | `inwx` | `INWX_USERNAME`, `INWX_PASSWORD` | YES |
| [Joker.com](https://joker.com) | `joker` | `JOKER_API_KEY` or `JOKER_USERNAME`, `JOKER_PASSWORD` | YES |
| [Lightsail](https://aws.amazon.com/lightsail/) | `lightsail` | `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `DNS_ZONE` | Not tested yet |
| [Linode](https://www.linode.com) | `linode` | `LINODE_API_KEY` | Not tested yet |
| [Linode v4](https://www.linode.com) | `linodev4` | `LINODE_TOKEN` | Not tested yet |
| manual | - | none, but you need to run Traefik interactively, turn on `acmeLogging` to see instructions and press <kbd>Enter</kbd>. | YES |
| [MyDNS.jp](https://www.mydns.jp/) | `mydnsjp` | `MYDNSJP_MASTER_ID`, `MYDNSJP_PASSWORD` | YES |
| [Namecheap](https://www.namecheap.com) | `namecheap` | `NAMECHEAP_API_USER`, `NAMECHEAP_API_KEY` | YES |
| [Namesilo](https://www.namesilo.com/) | `namesilo` | `NAMESILO_API_KEY` | YES |
| [name.com](https://www.name.com/) | `namedotcom` | `NAMECOM_USERNAME`, `NAMECOM_API_TOKEN`, `NAMECOM_SERVER` | Not tested yet |
| [Netcup](https://www.netcup.eu/) | `netcup` | `NETCUP_CUSTOMER_NUMBER`, `NETCUP_API_KEY`, `NETCUP_API_PASSWORD` | Not tested yet |
| [NIFCloud](https://cloud.nifty.com/service/dns.htm) | `nifcloud` | `NIFCLOUD_ACCESS_KEY_ID`, `NIFCLOUD_SECRET_ACCESS_KEY` | Not tested yet |
| [Ns1](https://ns1.com/) | `ns1` | `NS1_API_KEY` | Not tested yet |
| [Open Telekom Cloud](https://cloud.telekom.de) | `otc` | `OTC_DOMAIN_NAME`, `OTC_USER_NAME`, `OTC_PASSWORD`, `OTC_PROJECT_NAME`, `OTC_IDENTITY_ENDPOINT` | Not tested yet |
| [OVH](https://www.ovh.com) | `ovh` | `OVH_ENDPOINT`, `OVH_APPLICATION_KEY`, `OVH_APPLICATION_SECRET`, `OVH_CONSUMER_KEY` | YES |
| [Openstack Designate](https://docs.openstack.org/designate) | `designate` | `OS_AUTH_URL`, `OS_USERNAME`, `OS_PASSWORD`, `OS_TENANT_NAME`, `OS_REGION_NAME` | YES |
| [Oracle Cloud](https://cloud.oracle.com/home) | `oraclecloud` | `OCI_COMPARTMENT_OCID`, `OCI_PRIVKEY_FILE`, `OCI_PRIVKEY_PASS`, `OCI_PUBKEY_FINGERPRINT`, `OCI_REGION`, `OCI_TENANCY_OCID`, `OCI_USER_OCID` | YES |
| [PowerDNS](https://www.powerdns.com) | `pdns` | `PDNS_API_KEY`, `PDNS_API_URL` | Not tested yet |
| [Rackspace](https://www.rackspace.com/cloud/dns) | `rackspace` | `RACKSPACE_USER`, `RACKSPACE_API_KEY` | Not tested yet |
| [RFC2136](https://tools.ietf.org/html/rfc2136) | `rfc2136` | `RFC2136_TSIG_KEY`, `RFC2136_TSIG_SECRET`, `RFC2136_TSIG_ALGORITHM`, `RFC2136_NAMESERVER` | Not tested yet |
| [Route 53](https://aws.amazon.com/route53/) | `route53` | `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `[AWS_REGION]`, `[AWS_HOSTED_ZONE_ID]` or a configured user/instance IAM profile. | YES |
| [Sakura Cloud](https://cloud.sakura.ad.jp/) | `sakuracloud` | `SAKURACLOUD_ACCESS_TOKEN`, `SAKURACLOUD_ACCESS_TOKEN_SECRET` | Not tested yet |
| [Selectel](https://selectel.ru/en/) | `selectel` | `SELECTEL_API_TOKEN` | YES |
| [Stackpath](https://www.stackpath.com/) | `stackpath` | `STACKPATH_CLIENT_ID`, `STACKPATH_CLIENT_SECRET`, `STACKPATH_STACK_ID` | Not tested yet |
| [TransIP](https://www.transip.nl/) | `transip` | `TRANSIP_ACCOUNT_NAME`, `TRANSIP_PRIVATE_KEY_PATH` | YES |
| [VegaDNS](https://github.com/shupp/VegaDNS-API) | `vegadns` | `SECRET_VEGADNS_KEY`, `SECRET_VEGADNS_SECRET`, `VEGADNS_URL` | Not tested yet |
| [Versio](https://www.versio.nl/domeinnamen) | `versio` | `VERSIO_USERNAME`, `VERSIO_PASSWORD` | YES |
| [Vscale](https://vscale.io/) | `vscale` | `VSCALE_API_TOKEN` | YES |
| [VULTR](https://www.vultr.com) | `vultr` | `VULTR_API_KEY` | YES |
| [Zone.ee](https://www.zone.ee) | `zoneee` | `ZONEEE_API_USER`, `ZONEEE_API_KEY` | YES |
- (1): more information about the HTTP message format can be found [here](https://github.com/xenolf/lego/blob/master/providers/dns/httpreq/readme.md)
- (1): more information about the HTTP message format can be found [here](https://go-acme.github.io/lego/dns/httpreq/)
- (2): https://cloud.google.com/docs/authentication/production#providing_credentials_to_your_application
- (3): https://github.com/golang/oauth2/blob/36a7019397c4c86cf59eeab3bc0d188bac444277/google/default.go#L61-L76
@@ -389,11 +399,10 @@ As described in [Let's Encrypt's post](https://community.letsencrypt.org/t/stagi
```
It is not possible to request a double wildcard certificate for a domain (for example `*.*.local.com`).
Due to ACME limitation it is not possible to define wildcards in SANs (alternative domains). Thus, the wildcard domain has to be defined as a main domain.
Most likely the root domain should receive a certificate too, so it needs to be specified as SAN and 2 `DNS-01` challenges are executed.
In this case the generated DNS TXT record for both domains is the same.
Even though this behaviour is [DNS RFC](https://community.letsencrypt.org/t/wildcard-issuance-two-txt-records-for-the-same-name/54528/2) compliant, it can lead to problems as all DNS providers keep DNS records cached for a certain time (TTL) and this TTL can be superior to the challenge timeout making the `DNS-01` challenge fail.
The Traefik ACME client library [LEGO](https://github.com/xenolf/lego) supports some but not all DNS providers to work around this issue.
The Traefik ACME client library [LEGO](https://github.com/go-acme/lego) supports some but not all DNS providers to work around this issue.
The [`provider` table](/configuration/acme/#provider) indicates if they allow generating certificates for a wildcard domain and its root domain.
### `onDemand` (Deprecated)

View File

@@ -35,7 +35,7 @@
For more customization, see [entry points](/configuration/entrypoints/) documentation and the examples below.
## Web UI
## Dashboard (Web UI)
![Web UI Providers](/img/web.frontend.png)
@@ -322,9 +322,12 @@ curl -s "http://localhost:8080/health" | jq .
}
```
## Metrics
## Dashboard Statistics
You can enable Traefik to export internal metrics to different monitoring systems.
You can control how the Traefik's internal metrics are shown in the Dashboard.
If you want to export internal metrics to different monitoring systems,
please check the page [Metrics](./metrics.md).
```toml
[api]

View File

@@ -37,6 +37,15 @@ stale = false
#
domain = "consul.localhost"
# Keep a Consul node only if all checks status are passing
# If true, only the Consul nodes with checks status 'passing' will be kept.
# if false, only the Consul nodes with checks status 'passing' or 'warning' will be kept.
#
# Optional
# Default: true
#
strictChecks = true
# Prefix for Consul catalog tags.
#
# Optional
@@ -121,10 +130,10 @@ Additional settings can be defined using Consul Catalog tags.
| `<prefix>.frontend.auth.basic=EXPR` | Sets basic authentication to this frontend in CSV format: `User:Hash,User:Hash` (DEPRECATED). |
| `<prefix>.frontend.auth.basic.removeHeader=true` | If set to `true`, removes the `Authorization` header. |
| `<prefix>.frontend.auth.basic.users=EXPR` | Sets basic authentication to this frontend in CSV format: `User:Hash,User:Hash`. |
| `<prefix>.frontend.auth.basic.usersfile=/path/.htpasswd` | Sets basic authentication with an external file; if users and usersFile are provided, both are merged, with external file contents having precedence. |
| `<prefix>.frontend.auth.basic.usersFile=/path/.htpasswd` | Sets basic authentication with an external file; if users and usersFile are provided, both are merged, with external file contents having precedence. |
| `<prefix>.frontend.auth.digest.removeHeader=true` | If set to `true`, removes the `Authorization` header. |
| `<prefix>.frontend.auth.digest.users=EXPR` | Sets digest authentication to this frontend in CSV format: `User:Realm:Hash,User:Realm:Hash`. |
| `<prefix>.frontend.auth.digest.usersfile=/path/.htdigest` | Sets digest authentication with an external file; if users and usersFile are provided, both are merged, with external file contents having precedence. |
| `<prefix>.frontend.auth.digest.usersFile=/path/.htdigest` | Sets digest authentication with an external file; if users and usersFile are provided, both are merged, with external file contents having precedence. |
| `<prefix>.frontend.auth.forward.address=https://example.com` | Sets the URL of the authentication server. |
| `<prefix>.frontend.auth.forward.authResponseHeaders=EXPR` | Sets the forward authentication authResponseHeaders in CSV format: `X-Auth-User,X-Auth-Header` |
| `<prefix>.frontend.auth.forward.tls.ca=/path/ca.pem` | Sets the Certificate Authority (CA) for the TLS connection with the authentication server. |

View File

@@ -213,9 +213,13 @@ More information about Docker's security:
- [A thread on Stack Overflow about sharing the `/var/run/docker.sock` file](https://news.ycombinator.com/item?id=17983623)
- [To Dind or not to DinD](https://blog.loof.fr/2018/01/to-dind-or-not-do-dind.html)
### Security Compensation
### Workarounds
The main security compensation is to expose the Docker socket over TCP, instead of the default Unix socket file.
!!! note "Improved Security"
[TraefikEE](https://containo.us/traefikee) solves this problem by separating the control plane (connected to Docker) and the data plane (handling the requests).
Another possible workaround is to expose the Docker socket over TCP, instead of the default Unix socket file.
It allows different implementation levels of the [AAA (Authentication, Authorization, Accounting) concepts](https://en.wikipedia.org/wiki/AAA_(computer_security)), depending on your security assessment:
- Authentication with Client Certificates as described in [the "Protect the Docker daemon socket" page of Docker's documentation](https://docs.docker.com/engine/security/https/)
@@ -253,6 +257,20 @@ services:
traefik.docker.network: traefik
```
Required labels:
- `traefik.frontend.rule`
- `traefik.port` - Without this the debug logs will show this service is deliberately filtered out.
- `traefik.docker.network` - Without this a 504 may occur.
#### Troubleshooting
If service doesn't show up in the dashboard, check the debug logs to see if the port is missing:
`Filtering container without port, <SERVICE_NAME>: port label is missing, ...')`
If `504 Gateway Timeout` occurs and there are networks used, ensure that `traefik.docker.network` is defined.
The complete name is required, meaning if the network is internal the name needs to be `<project_name>_<network_name>`.
### Using Docker Compose
If you are intending to use only Docker Compose commands (e.g. `docker-compose up --scale whoami=2 -d`), labels should be under your service, otherwise they will be ignored.

View File

@@ -73,6 +73,14 @@ See also [Kubernetes user guide](/user-guide/kubernetes).
#
# enablePassTLSCert = true
# Throttle how frequently we refresh our configuration from Ingresses when there
# are frequent changes.
#
# Optional
# Default: 0 (no throttling)
#
# throttleDuration = 10s
# Override default configuration template.
#
# Optional
@@ -210,7 +218,7 @@ infos:
serialnumber: true
```
If `pem` is set, it will add a `X-Forwarded-Tls-Client-Cert` header that contains the escaped pem as value.
If `pem` is set, it will add a `X-Forwarded-Tls-Client-Cert` header that contains the escaped pem as value.
If at least one flag of the `infos` part is set, it will add a `X-Forwarded-Tls-Client-Cert-Infos` header that contains an escaped string composed of the client certificate data selected by the infos flags.
This infos part is composed like the following example (not escaped):
```Subject="C=FR,ST=SomeState,L=Lyon,O=Cheese,CN=*.cheese.org",NB=1531900816,NA=1563436816,SAN=*.cheese.org,*.cheese.net,cheese.in,test@cheese.org,test@cheese.net,10.0.1.0,10.0.1.2```
@@ -231,7 +239,7 @@ rateset:
```
<5> `traefik.ingress.kubernetes.io/rule-type`
Note: `ReplacePath` is deprecated in this annotation, use the `traefik.ingress.kubernetes.io/request-modifier` annotation instead. Default: `PathPrefix`.
Note: `ReplacePath` is deprecated in this annotation, use the `traefik.ingress.kubernetes.io/request-modifier` annotation instead. Default: `PathPrefix`.
<6> `traefik.ingress.kubernetes.io/service-weights`:
Service weights enable to split traffic across multiple backing services in a fine-grained manner.

View File

@@ -2,6 +2,11 @@
Traefik can be configured to use Rancher as a provider.
!!! important
This provider is specific to Rancher 1.x.
Rancher 2.x requires Kubernetes and does not have a metadata endpoint of its own for Traefik to query.
As such, Rancher 2.x users should utilize the [Kubernetes provider](./kubernetes.md) directly.
## Global Configuration
```toml

View File

@@ -69,6 +69,8 @@ Here is an example of an extension setting Traefik labels:
</StatelessServiceType>
```
> **Note**: The `Label` tag and its `Key` attribute are case sensitive. That is, if you use `label` instead of `Label` or `key` instead of `Key`, they will be silently ignored.
#### Property Manager
Set Labels with the property manager API to overwrite and add labels, while your service is running.

View File

@@ -249,8 +249,8 @@ Multiple sets of rates can be added to each frontend, but the time periods must
```
In the above example, frontend1 is configured to limit requests by the client's ip address.
An average of 5 requests every 3 seconds is allowed and an average of 100 requests every 10 seconds.
These can "burst" up to 10 and 200 in each period respectively.
An average of 100 requests every 10 seconds is allowed and an average of 5 requests every 3 seconds.
These can "burst" up to 200 and 10 in each period respectively.
Valid values for `extractorfunc` are:
* `client.ip`

View File

@@ -235,8 +235,10 @@ If you need to add or remove TLS certificates while Traefik is started, Dynamic
## TLS Mutual Authentication
TLS Mutual Authentication can be `optional` or not.
If it's `optional`, Traefik will authorize connection with certificates not signed by a specified Certificate Authority (CA).
Otherwise, Traefik will only accept clients that present a certificate signed by a specified Certificate Authority (CA).
* If `optional = true`, if a certificate is provided, verifies if it is signed by a specified Certificate Authority (CA). Otherwise proceeds without any certificate.
* If `optional = false`, Traefik will only accept clients that present a certificate signed by a specified Certificate Authority (CA).
`ClientCAFiles` can be configured with multiple `CA:s` in the same file or use multiple files containing one or several `CA:s`.
The `CA:s` has to be in PEM format.

View File

@@ -39,7 +39,7 @@ logLevel = "INFO"
For more information about the CLI, see the documentation about [Traefik command](/basics/#traefik).
```shell
```bash
--logLevel="DEBUG"
--traefikLog.filePath="/path/to/traefik.log"
--traefikLog.format="json"
@@ -54,7 +54,6 @@ For more information about the CLI, see the documentation about [Traefik command
--accessLog.fields.headers.names="User-Agent=redact Authorization=drop Content-Type=keep"
```
## Traefik Logs
By default the Traefik log is written to stdout in text format.
@@ -66,7 +65,7 @@ To write the logs into a log file specify the `filePath`:
filePath = "/path/to/traefik.log"
```
To write JSON format logs, specify `json` as the format:
To switch to JSON format instead of standard format (`common`), specify `json` as the format:
```toml
[traefikLog]
@@ -74,7 +73,6 @@ To write JSON format logs, specify `json` as the format:
format = "json"
```
Deprecated way (before 1.4):
!!! danger "DEPRECATED"
@@ -105,13 +103,12 @@ To customize the log level:
logLevel = "ERROR"
```
## Access Logs
Access logs are written when `[accessLog]` is defined.
By default it will write to stdout and produce logs in the textual Common Log Format (CLF), extended with additional fields.
Access logs are written when the entry `[accessLog]` is defined (or the command line flag `--accesslog`).
By default it writes to stdout and produces logs in the textual [Common Log Format (CLF)](#clf-common-log-format), extended with additional fields.
To enable access logs using the default settings just add the `[accessLog]` entry:
To enable access logs using the default settings, add the `[accessLog]` entry in your `traefik.toml` configuration file:
```toml
[accessLog]
@@ -124,12 +121,12 @@ To write the logs into a log file specify the `filePath`:
filePath = "/path/to/access.log"
```
To write JSON format logs, specify `json` as the format:
To switch to JSON format instead of [Common Log Format (CLF)](#clf-common-log-format), specify `json` as the format:
```toml
[accessLog]
filePath = "/path/to/access.log"
format = "json"
format = "json" # Default: "common"
```
To write the logs in async, specify `bufferingSize` as the format (must be >0):
@@ -152,7 +149,7 @@ To filter logs you can specify a set of filters which are logically "OR-connecte
```toml
[accessLog]
filePath = "/path/to/access.log"
format = "json"
format = "json" # Default: "common"
[accessLog.filters]
@@ -178,22 +175,42 @@ format = "json"
minDuration = "10ms"
```
To customize logs format:
### CLF - Common Log Format
By default, Traefik use the CLF (`common`) as access log format.
```html
<remote_IP_address> - <client_user_name_if_available> [<timestamp>] "<request_method> <request_path> <request_protocol>" <origin_server_HTTP_status> <origin_server_content_size> "<request_referrer>" "<request_user_agent>" <number_of_requests_received_since_Traefik_started> "<Traefik_frontend_name>" "<Traefik_backend_URL>" <request_duration_in_ms>ms
```
### Customize Fields
You can customize the fields written in the access logs.
The list of available fields is found below: [List of All Available Fields](#list-of-all-available-fields).
Each field has a "mode" which defines if it is written or not in the access log lines.
The possible values for the mode are:
* `keep`: the field and its value are written on the access log line. This is the default behavior.
* `drop`: the field is not written at all on the access log.
To customize the fields, you must:
* Switch to the JSON format (mandatory)
* Define the "default mode" for all fields (default is `keep`)
* OR Define the fields which does not follow the default mode
```toml
[accessLog]
filePath = "/path/to/access.log"
# Access Log Format
#
# Optional
# Default: "common"
#
# Accepted values "common", "json"
#
format = "json"
[accessLog.filters]
# statusCodes keep only access logs with status codes in the specified range
#
# Optional
# Default: []
#
statusCodes = ["200", "300-302"]
[accessLog.fields]
# defaultMode
@@ -209,6 +226,43 @@ format = "json"
[accessLog.fields.names]
"ClientUsername" = "drop"
# ...
```
### Customize Headers
Access logs prints the headers of each request, as fields of the access log line.
You can customize which and how the headers are printed, likewise the other fields (see ["Customize Fields" section](#customize-fields)).
Each header has a "mode" which defines how it is written in the access log lines.
The possible values for the mode are:
* `keep`: the header and its value are written on the access log line. This is the default behavior.
* `drop`: the header is not written at all on the access log.
* `redacted`: the header is written, but its value is redacted to avoid leaking sensitive information.
To customize the headers, you must:
* Switch to the JSON format (mandatory)
* Define the "default mode" for all headers (default is `keep`)
* OR Define the headers which does not follow the default mode
!!! important
The headers are written with the prefix `request_` in the access log.
This prefix must not be included when specifying a header in the TOML configuration.
* Do: `"User-Agent" = "drop"`
* Don't: `"redacted_User-Agent" = "drop"`
```toml
[accessLog]
# Access Log Format
#
# Optional
# Default: "common"
#
# Accepted values "common", "json"
#
format = "json"
[accessLog.fields.headers]
# defaultMode
@@ -227,41 +281,42 @@ format = "json"
# ...
```
### List of All Available Fields
### List of all available fields
| Field | Description |
|-------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `StartUTC` | The time at which request processing started. |
| `StartLocal` | The local time at which request processing started. |
| `Duration` | The total time taken by processing the response, including the origin server's time but not the log writing time. |
| `FrontendName` | The name of the Traefik frontend. |
| `BackendName` | The name of the Traefik backend. |
| `BackendURL` | The URL of the Traefik backend. |
| `BackendAddr` | The IP:port of the Traefik backend (extracted from `BackendURL`) |
| `ClientAddr` | The remote address in its original form (usually IP:port). |
| `ClientHost` | The remote IP address from which the client request was received. |
| `ClientPort` | The remote TCP port from which the client request was received. |
| `ClientUsername` | The username provided in the URL, if present. |
| `RequestAddr` | The HTTP Host header (usually IP:port). This is treated as not a header by the Go API. |
| `RequestHost` | The HTTP Host server name (not including port). |
| `RequestPort` | The TCP port from the HTTP Host. |
| `RequestMethod` | The HTTP method. |
| `RequestPath` | The HTTP request URI, not including the scheme, host or port. |
| `RequestProtocol` | The version of HTTP requested. |
| `RequestLine` | `RequestMethod` + `RequestPath` + `RequestProtocol` |
| `RequestContentSize` | The number of bytes in the request entity (a.k.a. body) sent by the client. |
| `OriginDuration` | The time taken by the origin server ('upstream') to return its response. |
| `OriginContentSize` | The content length specified by the origin server, or 0 if unspecified. |
| `OriginStatus` | The HTTP status code returned by the origin server. If the request was handled by this Traefik instance (e.g. with a redirect), then this value will be absent. |
| `OriginStatusLine` | `OriginStatus` + Status code explanation |
| `DownstreamStatus` | The HTTP status code returned to the client. |
| `DownstreamStatusLine` | `DownstreamStatus` + Status code explanation |
| `DownstreamContentSize` | The number of bytes in the response entity returned to the client. This is in addition to the "Content-Length" header, which may be present in the origin response. |
| `RequestCount` | The number of requests received since the Traefik instance started. |
| `GzipRatio` | The response body compression ratio achieved. |
| `Overhead` | The processing time overhead caused by Traefik. |
| `RetryAttempts` | The amount of attempts the request was retried. |
```ini
StartUTC
StartLocal
Duration
FrontendName
BackendName
BackendURL
BackendAddr
ClientAddr
ClientHost
ClientPort
ClientUsername
RequestAddr
RequestHost
RequestPort
RequestMethod
RequestPath
RequestProtocol
RequestLine
RequestContentSize
OriginDuration
OriginContentSize
OriginStatus
OriginStatusLine
DownstreamStatus
DownstreamStatusLine
DownstreamContentSize
RequestCount
GzipRatio
Overhead
RetryAttempts
```
### Depreciation Notice
Deprecated way (before 1.4):
@@ -276,15 +331,6 @@ Deprecated way (before 1.4):
accessLogsFile = "log/access.log"
```
### CLF - Common Log Format
By default, Traefik use the CLF (`common`) as access log format.
```html
<remote_IP_address> - <client_user_name_if_available> [<timestamp>] "<request_method> <request_path> <request_protocol>" <origin_server_HTTP_status> <origin_server_content_size> "<request_referrer>" "<request_user_agent>" <number_of_requests_received_since_Traefik_started> "<Traefik_frontend_name>" "<Traefik_backend_URL>" <request_duration_in_ms>ms
```
## Log Rotation
Traefik will close and reopen its log files, assuming they're configured, on receipt of a USR1 signal.
@@ -292,3 +338,34 @@ This allows the logs to be rotated and processed by an external program, such as
!!! note
This does not work on Windows due to the lack of USR signals.
## Time Zones
The timestamp of each log line is in UTC time by default.
If you want to use local timezone, you need to ensure the 3 following elements:
1. Provide the timezone data into /usr/share/zoneinfo
2. Set the environement variable TZ to the timezone to be used
3. Specify the field StartLocal instead of StartUTC (works on default Common Log Format (CLF) as well as JSON)
Example using docker-compose:
```yml
version: '3'
services:
traefik:
image: containous/traefik:[latest stable version]
ports:
- "80:80"
environment:
- "TZ=US/Alaska"
command:
- --docker
- --accesslog
- --accesslog.fields.names="StartUTC=drop"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock"
- "/usr/share/zoneinfo:/usr/share/zoneinfo:ro"
```

View File

@@ -6,7 +6,7 @@
[![Docs](https://img.shields.io/badge/docs-current-brightgreen.svg)](/)
[![Go Report Card](https://goreportcard.com/badge/github.com/containous/traefik)](https://goreportcard.com/report/github.com/containous/traefik)
[![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/containous/traefik/blob/master/LICENSE.md)
[![Join the chat at https://slack.traefik.io](https://img.shields.io/badge/style-register-green.svg?style=social&label=Slack)](https://slack.traefik.io)
[![Join the community support forum at https://community.containo.us/](https://img.shields.io/badge/style-register-green.svg?style=social&label=Discourse)](https://community.containo.us/)
[![Twitter](https://img.shields.io/twitter/follow/traefik.svg?style=social)](https://twitter.com/intent/follow?screen_name=traefik)
@@ -66,7 +66,7 @@ _(But if you'd rather configure some of your routes manually, Traefik supports t
In this quickstart, we'll use [Docker compose](https://docs.docker.com/compose) to create our demo infrastructure.
To save some time, you can clone [Traefik's repository](https://github.com/containous/traefik) and use the quickstart files located in the [examples/quickstart](https://github.com/containous/traefik/tree/master/examples/quickstart/) directory.
To save some time, you can clone [Traefik's repository](https://github.com/containous/traefik) and use the quickstart files located in the [examples/quickstart](https://github.com/containous/traefik/tree/v1.7/examples/quickstart/) directory.
### 1 — Launch Traefik — Tell It to Listen to Docker
@@ -190,7 +190,7 @@ You will learn fundamental Traefik features and see some demos with Kubernetes.
### The Official Binary File
You can grab the latest binary from the [releases](https://github.com/containous/traefik/releases) page and just run it with the [sample configuration file](https://raw.githubusercontent.com/containous/traefik/master/traefik.sample.toml):
You can grab the latest binary from the [releases](https://github.com/containous/traefik/releases) page and just run it with the [sample configuration file](https://raw.githubusercontent.com/containous/traefik/v1.7/traefik.sample.toml):
```shell
./traefik -c traefik.toml

View File

@@ -88,9 +88,9 @@
</div>
{% endif %}
powered by
<a href="http://www.mkdocs.org" title="MkDocs">MkDocs</a>
<a href="https://www.mkdocs.org" title="MkDocs">MkDocs</a>
and
<a href="http://squidfunk.github.io/mkdocs-material/"
<a href="https://squidfunk.github.io/mkdocs-material/"
title="Material for MkDocs">
Material for MkDocs</a>
</div>

View File

@@ -91,7 +91,7 @@ To watch docker events, add `--docker.watch`.
version: "3"
services:
traefik:
image: traefik:1.5
image: traefik:<stable version from https://hub.docker.com/_/traefik>
command:
- "--api"
- "--entrypoints=Name:http Address::80 Redirect.EntryPoint:https"
@@ -156,7 +156,7 @@ The initializer in a docker-compose file will be:
```yaml
traefik_init:
image: traefik:1.5
image: traefik:<stable version from https://hub.docker.com/_/traefik>
command:
- "storeconfig"
- "--api"
@@ -177,7 +177,7 @@ And now, the Traefik part will only have the Consul configuration.
```yaml
traefik:
image: traefik:1.5
image: traefik:<stable version from https://hub.docker.com/_/traefik>
depends_on:
- traefik_init
- consul
@@ -200,7 +200,7 @@ The new configuration will be stored in Consul, and you need to restart the Trae
version: "3.4"
services:
traefik_init:
image: traefik:1.5
image: traefik:<stable version from https://hub.docker.com/_/traefik>
command:
- "storeconfig"
- "--api"
@@ -229,7 +229,7 @@ services:
depends_on:
- consul
traefik:
image: traefik:1.5
image: traefik:<stable version from https://hub.docker.com/_/traefik>
depends_on:
- traefik_init
- consul

View File

@@ -50,7 +50,7 @@ version: '2'
services:
traefik:
image: traefik:1.5.4
image: traefik:<stable version from https://hub.docker.com/_/traefik>
restart: always
ports:
- 80:80
@@ -108,6 +108,28 @@ onHostRule = true
entryPoint = "http"
```
Alternatively, the `TOML` file above can also be translated into command line switches.
This is the `command` value of the `traefik` service in the `docker-compose.yml` manifest:
```yaml
command:
- --debug=false
- --logLevel=ERROR
- --defaultentrypoints=https,http
- --entryPoints=Name:http Address::80 Redirect.EntryPoint:https
- --entryPoints=Name:https Address::443 TLS
- --retry
- --docker.endpoint=unix:///var/run/docker.sock
- --docker.domain=my-awesome-app.org
- --docker.watch=true
- --docker.exposedbydefault=false
- --acme.email=your-email-here@my-awesome-app.org
- --acme.storage=acme.json
- --acme.entryPoint=https
- --acme.onHostRule=true
- --acme.httpchallenge.entrypoint=http
```
This is the minimum configuration required to do the following:
- Log `ERROR`-level messages (or more severe) to the console, but silence `DEBUG`-level messages

View File

@@ -336,37 +336,37 @@ Pay attention to the **labels** section:
```
home:
image: abiosoft/caddy:0.10.14
networks:
- ntw_front
volumes:
- ./www/home/srv/:/srv/
deploy:
mode: replicated
replicas: 2
#placement:
# constraints: [node.role==manager]
restart_policy:
condition: on-failure
max_attempts: 5
resources:
limits:
cpus: '0.20'
memory: 9M
reservations:
cpus: '0.05'
memory: 9M
labels:
- "traefik.frontend.rule=PathPrefixStrip:/"
- "traefik.backend=home"
- "traefik.port=2015"
- "traefik.weight=10"
- "traefik.enable=true"
- "traefik.passHostHeader=true"
- "traefik.docker.network=ntw_front"
- "traefik.frontend.entryPoints=http"
- "traefik.backend.loadbalancer.swarm=true"
- "traefik.backend.loadbalancer.method=drr"
image: abiosoft/caddy:0.10.14
networks:
- ntw_front
volumes:
- ./www/home/srv/:/srv/
deploy:
mode: replicated
replicas: 2
#placement:
# constraints: [node.role==manager]
restart_policy:
condition: on-failure
max_attempts: 5
resources:
limits:
cpus: '0.20'
memory: 9M
reservations:
cpus: '0.05'
memory: 9M
labels:
- "traefik.frontend.rule=PathPrefixStrip:/"
- "traefik.backend=home"
- "traefik.port=2015"
- "traefik.weight=10"
- "traefik.enable=true"
- "traefik.passHostHeader=true"
- "traefik.docker.network=ntw_front"
- "traefik.frontend.entryPoints=http"
- "traefik.backend.loadbalancer.swarm=true"
- "traefik.backend.loadbalancer.method=drr"
```
Something more tricky using `regex`.
@@ -377,39 +377,39 @@ The double sign `$$` are variables managed by the docker compose file ([document
```
portainer:
image: portainer/portainer:1.16.5
networks:
- ntw_front
volumes:
- /var/run/docker.sock:/var/run/docker.sock
deploy:
mode: replicated
replicas: 1
placement:
constraints: [node.role==manager]
restart_policy:
condition: on-failure
max_attempts: 5
resources:
limits:
cpus: '0.33'
memory: 20M
reservations:
cpus: '0.05'
memory: 10M
labels:
- "traefik.frontend.rule=PathPrefixStrip:/portainer"
- "traefik.backend=portainer"
- "traefik.port=9000"
- "traefik.weight=10"
- "traefik.enable=true"
- "traefik.passHostHeader=true"
- "traefik.docker.network=ntw_front"
- "traefik.frontend.entryPoints=http"
- "traefik.backend.loadbalancer.swarm=true"
- "traefik.backend.loadbalancer.method=drr"
# https://github.com/containous/traefik/issues/563#issuecomment-421360934
- "traefik.frontend.redirect.regex=^(.*)/portainer$$"
- "traefik.frontend.redirect.replacement=$$1/portainer/"
- "traefik.frontend.rule=PathPrefix:/portainer;ReplacePathRegex: ^/portainer/(.*) /$$1"
image: portainer/portainer:1.16.5
networks:
- ntw_front
volumes:
- /var/run/docker.sock:/var/run/docker.sock
deploy:
mode: replicated
replicas: 1
placement:
constraints: [node.role==manager]
restart_policy:
condition: on-failure
max_attempts: 5
resources:
limits:
cpus: '0.33'
memory: 20M
reservations:
cpus: '0.05'
memory: 10M
labels:
- "traefik.frontend.rule=PathPrefixStrip:/portainer"
- "traefik.backend=portainer"
- "traefik.port=9000"
- "traefik.weight=10"
- "traefik.enable=true"
- "traefik.passHostHeader=true"
- "traefik.docker.network=ntw_front"
- "traefik.frontend.entryPoints=http"
- "traefik.backend.loadbalancer.swarm=true"
- "traefik.backend.loadbalancer.method=drr"
# https://github.com/containous/traefik/issues/563#issuecomment-421360934
- "traefik.frontend.redirect.regex=^(.*)/portainer$$"
- "traefik.frontend.redirect.replacement=$$1/portainer/"
- "traefik.frontend.rule=PathPrefix:/portainer;ReplacePathRegex: ^/portainer/(.*) /$$1"
```

View File

@@ -4,7 +4,7 @@ This guide explains how to use Traefik as an Ingress controller for a Kubernetes
If you are not familiar with Ingresses in Kubernetes you might want to read the [Kubernetes user guide](https://kubernetes.io/docs/concepts/services-networking/ingress/)
The config files used in this guide can be found in the [examples directory](https://github.com/containous/traefik/tree/master/examples/k8s)
The config files used in this guide can be found in the [examples directory](https://github.com/containous/traefik/tree/v1.7/examples/k8s)
## Prerequisites
@@ -68,10 +68,10 @@ subjects:
namespace: kube-system
```
[examples/k8s/traefik-rbac.yaml](https://github.com/containous/traefik/tree/master/examples/k8s/traefik-rbac.yaml)
[examples/k8s/traefik-rbac.yaml](https://github.com/containous/traefik/tree/v1.7/examples/k8s/traefik-rbac.yaml)
```shell
kubectl apply -f https://raw.githubusercontent.com/containous/traefik/master/examples/k8s/traefik-rbac.yaml
kubectl apply -f https://raw.githubusercontent.com/containous/traefik/v1.7/examples/k8s/traefik-rbac.yaml
```
For namespaced restrictions, one RoleBinding is required per watched namespace along with a corresponding configuration of Traefik's `kubernetes.namespaces` parameter.
@@ -148,7 +148,7 @@ spec:
type: NodePort
```
[examples/k8s/traefik-deployment.yaml](https://github.com/containous/traefik/tree/master/examples/k8s/traefik-deployment.yaml)
[examples/k8s/traefik-deployment.yaml](https://github.com/containous/traefik/tree/v1.7/examples/k8s/traefik-deployment.yaml)
!!! note
The Service will expose two NodePorts which allow access to the ingress and the web interface.
@@ -216,7 +216,7 @@ spec:
name: admin
```
[examples/k8s/traefik-ds.yaml](https://github.com/containous/traefik/tree/master/examples/k8s/traefik-ds.yaml)
[examples/k8s/traefik-ds.yaml](https://github.com/containous/traefik/tree/v1.7/examples/k8s/traefik-ds.yaml)
!!! note
This will create a Daemonset that uses privileged ports 80/8080 on the host. This may not work on all providers, but illustrates the static (non-NodePort) hostPort binding. The `traefik-ingress-service` can still be used inside the cluster to access the DaemonSet pods.
@@ -224,11 +224,11 @@ spec:
To deploy Traefik to your cluster start by submitting one of the YAML files to the cluster with `kubectl`:
```shell
kubectl apply -f https://raw.githubusercontent.com/containous/traefik/master/examples/k8s/traefik-deployment.yaml
kubectl apply -f https://raw.githubusercontent.com/containous/traefik/v1.7/examples/k8s/traefik-deployment.yaml
```
```shell
kubectl apply -f https://raw.githubusercontent.com/containous/traefik/master/examples/k8s/traefik-ds.yaml
kubectl apply -f https://raw.githubusercontent.com/containous/traefik/v1.7/examples/k8s/traefik-ds.yaml
```
There are some significant differences between using Deployments and DaemonSets:
@@ -352,10 +352,10 @@ spec:
servicePort: web
```
[examples/k8s/ui.yaml](https://github.com/containous/traefik/tree/master/examples/k8s/ui.yaml)
[examples/k8s/ui.yaml](https://github.com/containous/traefik/tree/v1.7/examples/k8s/ui.yaml)
```shell
kubectl apply -f https://raw.githubusercontent.com/containous/traefik/master/examples/k8s/ui.yaml
kubectl apply -f https://raw.githubusercontent.com/containous/traefik/v1.7/examples/k8s/ui.yaml
```
Now lets setup an entry in our `/etc/hosts` file to route `traefik-ui.minikube` to our cluster.
@@ -581,10 +581,10 @@ spec:
- containerPort: 80
```
[examples/k8s/cheese-deployments.yaml](https://github.com/containous/traefik/tree/master/examples/k8s/cheese-deployments.yaml)
[examples/k8s/cheese-deployments.yaml](https://github.com/containous/traefik/tree/v1.7/examples/k8s/cheese-deployments.yaml)
```shell
kubectl apply -f https://raw.githubusercontent.com/containous/traefik/master/examples/k8s/cheese-deployments.yaml
kubectl apply -f https://raw.githubusercontent.com/containous/traefik/v1.7/examples/k8s/cheese-deployments.yaml
```
Next we need to setup a Service for each of the cheese pods.
@@ -636,10 +636,10 @@ spec:
!!! note
We also set a [circuit breaker expression](/basics/#backends) for one of the backends by setting the `traefik.backend.circuitbreaker` annotation on the service.
[examples/k8s/cheese-services.yaml](https://github.com/containous/traefik/tree/master/examples/k8s/cheese-services.yaml)
[examples/k8s/cheese-services.yaml](https://github.com/containous/traefik/tree/v1.7/examples/k8s/cheese-services.yaml)
```shell
kubectl apply -f https://raw.githubusercontent.com/containous/traefik/master/examples/k8s/cheese-services.yaml
kubectl apply -f https://raw.githubusercontent.com/containous/traefik/v1.7/examples/k8s/cheese-services.yaml
```
Now we can submit an ingress for the cheese websites.
@@ -676,13 +676,13 @@ spec:
servicePort: http
```
[examples/k8s/cheese-ingress.yaml](https://github.com/containous/traefik/tree/master/examples/k8s/cheese-ingress.yaml)
[examples/k8s/cheese-ingress.yaml](https://github.com/containous/traefik/tree/v1.7/examples/k8s/cheese-ingress.yaml)
!!! note
We list each hostname, and add a backend service.
```shell
kubectl apply -f https://raw.githubusercontent.com/containous/traefik/master/examples/k8s/cheese-ingress.yaml
kubectl apply -f https://raw.githubusercontent.com/containous/traefik/v1.7/examples/k8s/cheese-ingress.yaml
```
Now visit the [Traefik dashboard](http://traefik-ui.minikube/) and you should see a frontend for each host.
@@ -731,13 +731,13 @@ spec:
servicePort: http
```
[examples/k8s/cheeses-ingress.yaml](https://github.com/containous/traefik/tree/master/examples/k8s/cheeses-ingress.yaml)
[examples/k8s/cheeses-ingress.yaml](https://github.com/containous/traefik/tree/v1.7/examples/k8s/cheeses-ingress.yaml)
!!! note
We are configuring Traefik to strip the prefix from the url path with the `traefik.frontend.rule.type` annotation so that we can use the containers from the previous example without modification.
```shell
kubectl apply -f https://raw.githubusercontent.com/containous/traefik/master/examples/k8s/cheeses-ingress.yaml
kubectl apply -f https://raw.githubusercontent.com/containous/traefik/v1.7/examples/k8s/cheeses-ingress.yaml
```
```shell

View File

@@ -139,7 +139,7 @@ Here is the [docker-compose file](https://docs.docker.com/compose/compose-file/)
```yaml
traefik:
image: traefik
image: traefik:<stable version from https://hub.docker.com/_/traefik>
command: --consul --consul.endpoint=127.0.0.1:8500
ports:
- "80:80"

View File

@@ -85,7 +85,7 @@ docker-machine ssh manager "docker service create \
--publish 80:80 --publish 8080:8080 \
--mount type=bind,source=/var/run/docker.sock,target=/var/run/docker.sock \
--network traefik-net \
traefik \
traefik:<stable version from https://hub.docker.com/_/traefik> \
--docker \
--docker.swarmMode \
--docker.domain=traefik \

View File

@@ -81,7 +81,7 @@ docker $(docker-machine config mhs-demo0) run \
-p 80:80 -p 8080:8080 \
--net=my-net \
-v /var/lib/boot2docker/:/ssl \
traefik \
traefik:<stable version from https://hub.docker.com/_/traefik> \
-l DEBUG \
-c /dev/null \
--docker \

View File

@@ -2,7 +2,7 @@
In this quickstart, we'll use [Docker compose](https://docs.docker.com/compose) to create our demo infrastructure.
To save some time, you can clone [Traefik's repository](https://github.com/containous/traefik) and use the quickstart files located in the [examples/quickstart](https://github.com/containous/traefik/tree/master/examples/quickstart/) directory.
To save some time, you can clone [Traefik's repository](https://github.com/containous/traefik) and use the quickstart files located in the [examples/quickstart](https://github.com/containous/traefik/tree/v1.7/examples/quickstart/) directory.
### 1 — Launch Traefik — Tell It to Listen to Docker

44
exp.Dockerfile Normal file
View File

@@ -0,0 +1,44 @@
# WEBUI
FROM node:8.15.0 as webui
ENV WEBUI_DIR /src/webui
RUN mkdir -p $WEBUI_DIR
COPY ./webui/ $WEBUI_DIR/
WORKDIR $WEBUI_DIR
RUN yarn install
RUN npm run build
# BUILD
FROM golang:1.12-alpine as gobuild
RUN apk --update upgrade \
&& apk --no-cache --no-progress add git mercurial bash gcc musl-dev curl tar ca-certificates tzdata \
&& update-ca-certificates \
&& rm -rf /var/cache/apk/*
RUN mkdir -p /usr/local/bin \
&& curl -fsSL -o /usr/local/bin/go-bindata https://github.com/containous/go-bindata/releases/download/v1.0.0/go-bindata \
&& chmod +x /usr/local/bin/go-bindata
WORKDIR /go/src/github.com/containous/traefik
COPY . /go/src/github.com/containous/traefik
RUN rm -rf /go/src/github.com/containous/traefik/static/
COPY --from=webui /src/static/ /go/src/github.com/containous/traefik/static/
RUN ./script/make.sh generate binary
## IMAGE
FROM scratch
COPY --from=gobuild /usr/share/zoneinfo /usr/share/zoneinfo
COPY --from=gobuild /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
COPY --from=gobuild /go/src/github.com/containous/traefik/dist/traefik /
EXPOSE 80
VOLUME ["/tmp"]
ENTRYPOINT ["/traefik"]

View File

@@ -49,11 +49,16 @@ func (opt Options) String() string {
return fmt.Sprintf("[Hostname: %s Headers: %v Path: %s Port: %d Interval: %s]", opt.Hostname, opt.Headers, opt.Path, opt.Port, opt.Interval)
}
type backendURL struct {
url *url.URL
weight int
}
// BackendConfig HealthCheck configuration for a backend
type BackendConfig struct {
Options
name string
disabledURLs []*url.URL
disabledURLs []backendURL
requestTimeout time.Duration
}
@@ -129,18 +134,18 @@ func (hc *HealthCheck) execute(ctx context.Context, backend *BackendConfig) {
func (hc *HealthCheck) checkBackend(backend *BackendConfig) {
enabledURLs := backend.LB.Servers()
var newDisabledURLs []*url.URL
for _, url := range backend.disabledURLs {
var newDisabledURLs []backendURL
for _, backendurl := range backend.disabledURLs {
serverUpMetricValue := float64(0)
if err := checkHealth(url, backend); err == nil {
log.Warnf("Health check up: Returning to server list. Backend: %q URL: %q", backend.name, url.String())
backend.LB.UpsertServer(url, roundrobin.Weight(1))
if err := checkHealth(backendurl.url, backend); err == nil {
log.Warnf("Health check up: Returning to server list. Backend: %q URL: %q Weight: %d", backend.name, backendurl.url.String(), backendurl.weight)
backend.LB.UpsertServer(backendurl.url, roundrobin.Weight(backendurl.weight))
serverUpMetricValue = 1
} else {
log.Warnf("Health check still failing. Backend: %q URL: %q Reason: %s", backend.name, url.String(), err)
newDisabledURLs = append(newDisabledURLs, url)
log.Warnf("Health check still failing. Backend: %q URL: %q Reason: %s", backend.name, backendurl.url.String(), err)
newDisabledURLs = append(newDisabledURLs, backendurl)
}
labelValues := []string{"backend", backend.name, "url", url.String()}
labelValues := []string{"backend", backend.name, "url", backendurl.url.String()}
hc.metrics.BackendServerUpGauge().With(labelValues...).Set(serverUpMetricValue)
}
backend.disabledURLs = newDisabledURLs
@@ -148,9 +153,18 @@ func (hc *HealthCheck) checkBackend(backend *BackendConfig) {
for _, url := range enabledURLs {
serverUpMetricValue := float64(1)
if err := checkHealth(url, backend); err != nil {
log.Warnf("Health check failed: Remove from server list. Backend: %q URL: %q Reason: %s", backend.name, url.String(), err)
weight := 1
rr, ok := backend.LB.(*roundrobin.RoundRobin)
if ok {
var gotWeight bool
weight, gotWeight = rr.ServerWeight(url)
if !gotWeight {
weight = 1
}
}
log.Warnf("Health check failed: Remove from server list. Backend: %q URL: %q Weight: %d Reason: %s", backend.name, url.String(), weight, err)
backend.LB.RemoveServer(url)
backend.disabledURLs = append(backend.disabledURLs, url)
backend.disabledURLs = append(backend.disabledURLs, backendURL{url, weight})
serverUpMetricValue = 0
}
labelValues := []string{"backend", backend.name, "url", url.String()}

View File

@@ -112,7 +112,7 @@ func TestSetBackendsConfiguration(t *testing.T) {
if test.startHealthy {
lb.servers = append(lb.servers, serverURL)
} else {
backend.disabledURLs = append(backend.disabledURLs, serverURL)
backend.disabledURLs = append(backend.disabledURLs, backendURL{serverURL, 1})
}
collectingMetrics := testhelpers.NewCollectingHealthCheckMetrics()

View File

@@ -10,7 +10,7 @@ import (
"github.com/abronan/valkeyrie"
"github.com/abronan/valkeyrie/store"
"github.com/abronan/valkeyrie/store/etcd/v3"
etcdv3 "github.com/abronan/valkeyrie/store/etcd/v3"
"github.com/containous/traefik/integration/try"
"github.com/go-check/check"

View File

@@ -1,5 +1,5 @@
pebble:
image: letsencrypt/pebble:2018-11-02
image: letsencrypt/pebble:v2.0.1
command: pebble --dnsserver ${DOCKER_HOST_IP}:5053
ports:
- 14000:14000

View File

@@ -1,7 +1,5 @@
zipkin:
# Fix zipkin version 2.4.2
# due to a bug in latest version https://github.com/openzipkin/zipkin/releases/tag/2.4.4
image: openzipkin/zipkin:2.4.2
image: openzipkin/zipkin:2.12.6
environment:
STORAGE_TYPE: mem
JAVA_OPTS: -Dlogging.level.zipkin=DEBUG

View File

@@ -24,6 +24,8 @@ func (f *CommonLogFormatter) Format(entry *logrus.Entry) ([]byte, error) {
var timestamp = defaultValue
if v, ok := entry.Data[StartUTC]; ok {
timestamp = v.(time.Time).Format(commonLogTimeFormat)
} else if v, ok := entry.Data[StartLocal]; ok {
timestamp = v.(time.Time).Local().Format(commonLogTimeFormat)
}
var elapsedMillis int64

View File

@@ -2,6 +2,7 @@ package accesslog
import (
"net/http"
"os"
"testing"
"time"
@@ -57,10 +58,34 @@ func TestCommonLogFormatter_Format(t *testing.T) {
BackendURL: "http://10.0.0.2/toto",
},
expectedLog: `10.0.0.1 - Client [10/Nov/2009:23:00:00 +0000] "GET /foo http" 123 132 "referer" "agent" - "foo" "http://10.0.0.2/toto" 123000ms
`,
},
{
name: "all data with local time",
data: map[string]interface{}{
StartLocal: time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC),
Duration: 123 * time.Second,
ClientHost: "10.0.0.1",
ClientUsername: "Client",
RequestMethod: http.MethodGet,
RequestPath: "/foo",
RequestProtocol: "http",
OriginStatus: 123,
OriginContentSize: 132,
RequestRefererHeader: "referer",
RequestUserAgentHeader: "agent",
RequestCount: nil,
FrontendName: "foo",
BackendURL: "http://10.0.0.2/toto",
},
expectedLog: `10.0.0.1 - Client [10/Nov/2009:14:00:00 -0900] "GET /foo http" 123 132 "referer" "agent" - "foo" "http://10.0.0.2/toto" 123000ms
`,
},
}
// Set timezone to Alaska to have a constant behavior
os.Setenv("TZ", "US/Alaska")
for _, test := range testCases {
test := test
t.Run(test.name, func(t *testing.T) {

View File

@@ -44,8 +44,9 @@ func TestLogRotation(t *testing.T) {
if err != nil {
t.Fatalf("Error setting up temporary directory: %s", err)
}
defer os.RemoveAll(tempDir)
fileName := tempDir + "traefik.log"
fileName := filepath.Join(tempDir, "traefik.log")
rotatedFileName := fileName + ".rotated"
config := &types.AccessLog{FilePath: fileName, Format: CommonFormat}
@@ -587,6 +588,7 @@ func captureStdout(t *testing.T) (out *os.File, restoreStdout func()) {
restoreStdout = func() {
os.Stdout = original
os.RemoveAll(file.Name())
}
return file, restoreStdout

View File

@@ -96,7 +96,11 @@ func Forward(config *types.Forward, w http.ResponseWriter, r *http.Request, next
}
for _, headerName := range config.AuthResponseHeaders {
r.Header.Set(headerName, forwardResponse.Header.Get(headerName))
headerKey := http.CanonicalHeaderKey(headerName)
r.Header.Del(headerKey)
if len(forwardResponse.Header[headerKey]) > 0 {
r.Header[headerKey] = append([]string(nil), forwardResponse.Header[headerKey]...)
}
}
r.RequestURI = r.URL.RequestURI()

View File

@@ -50,6 +50,8 @@ func TestForwardAuthFail(t *testing.T) {
func TestForwardAuthSuccess(t *testing.T) {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("X-Auth-User", "user@example.com")
w.Header().Add("X-Auth-Group", "group1")
w.Header().Add("X-Auth-Group", "group2")
w.Header().Set("X-Auth-Secret", "secret")
fmt.Fprintln(w, "Success")
}))
@@ -58,13 +60,14 @@ func TestForwardAuthSuccess(t *testing.T) {
middleware, err := NewAuthenticator(&types.Auth{
Forward: &types.Forward{
Address: server.URL,
AuthResponseHeaders: []string{"X-Auth-User"},
AuthResponseHeaders: []string{"X-Auth-User", "X-Auth-Group"},
},
}, &tracing.Tracing{})
assert.NoError(t, err, "there should be no error")
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
assert.Equal(t, "user@example.com", r.Header.Get("X-Auth-User"))
assert.Equal(t, []string{"group1", "group2"}, r.Header["X-Auth-Group"])
assert.Empty(t, r.Header.Get("X-Auth-Secret"))
fmt.Fprintln(w, "traefik")
})
@@ -74,6 +77,7 @@ func TestForwardAuthSuccess(t *testing.T) {
defer ts.Close()
req := testhelpers.MustNewRequest(http.MethodGet, ts.URL, nil)
req.Header.Set("X-Auth-Group", "admin_group")
res, err := http.DefaultClient.Do(req)
assert.NoError(t, err, "there should be no error")
assert.Equal(t, http.StatusOK, res.StatusCode, "they should be equal")

View File

@@ -74,25 +74,28 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, req *http.Request, next http.
return
}
recorder := newResponseRecorder(w)
next.ServeHTTP(recorder, req)
catcher := newCodeCatcher(w, h.httpCodeRanges)
next.ServeHTTP(catcher, req)
if !catcher.isError {
return
}
// check the recorder code against the configured http status code ranges
for _, block := range h.httpCodeRanges {
if recorder.GetCode() >= block[0] && recorder.GetCode() <= block[1] {
log.Errorf("Caught HTTP Status Code %d, returning error page", recorder.GetCode())
if catcher.code >= block[0] && catcher.code <= block[1] {
log.Errorf("Caught HTTP Status Code %d, returning error page", catcher.code)
var query string
if len(h.backendQuery) > 0 {
query = "/" + strings.TrimPrefix(h.backendQuery, "/")
query = strings.Replace(query, "{status}", strconv.Itoa(recorder.GetCode()), -1)
query = strings.Replace(query, "{status}", strconv.Itoa(catcher.code), -1)
}
pageReq, err := newRequest(h.backendURL + query)
if err != nil {
log.Error(err)
w.WriteHeader(recorder.GetCode())
fmt.Fprint(w, http.StatusText(recorder.GetCode()))
w.WriteHeader(catcher.code)
fmt.Fprint(w, http.StatusText(catcher.code))
return
}
@@ -102,16 +105,11 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, req *http.Request, next http.
h.backendHandler.ServeHTTP(recorderErrorPage, pageReq.WithContext(req.Context()))
utils.CopyHeaders(w.Header(), recorderErrorPage.Header())
w.WriteHeader(recorder.GetCode())
w.WriteHeader(catcher.code)
w.Write(recorderErrorPage.GetBody().Bytes())
return
}
}
// did not catch a configured status code so proceed with the request
utils.CopyHeaders(w.Header(), recorder.Header())
w.WriteHeader(recorder.GetCode())
w.Write(recorder.GetBody().Bytes())
}
func newRequest(baseURL string) (*http.Request, error) {
@@ -129,6 +127,73 @@ func newRequest(baseURL string) (*http.Request, error) {
return req, nil
}
// codeCatcher is a response writer that detects as soon as possible whether the
// response is a code within the ranges of codes it watches for. If it is, it
// simply drops the data from the response. Otherwise, it forwards it directly to
// the original client (its responseWriter) without any buffering.
type codeCatcher struct {
headerMap http.Header
code int
httpCodeRanges types.HTTPCodeRanges
firstWrite bool
isError bool
responseWriter http.ResponseWriter
err error
}
func newCodeCatcher(rw http.ResponseWriter, httpCodeRanges types.HTTPCodeRanges) *codeCatcher {
catcher := &codeCatcher{
headerMap: make(http.Header),
code: http.StatusOK, // If backend does not call WriteHeader on us, we consider it's a 200.
responseWriter: rw,
httpCodeRanges: httpCodeRanges,
firstWrite: true,
}
return catcher
}
func (cc *codeCatcher) Header() http.Header {
if cc.headerMap == nil {
cc.headerMap = make(http.Header)
}
return cc.headerMap
}
func (cc *codeCatcher) Write(buf []byte) (int, error) {
if cc.err != nil {
return 0, cc.err
}
if !cc.firstWrite {
if cc.isError {
// We don't care about the contents of the response,
// since we want to serve the ones from the error page,
// so we just drop them.
return len(buf), nil
}
return cc.responseWriter.Write(buf)
}
for _, block := range cc.httpCodeRanges {
if cc.code >= block[0] && cc.code <= block[1] {
cc.isError = true
break
}
}
cc.firstWrite = false
if !cc.isError {
utils.CopyHeaders(cc.responseWriter.Header(), cc.Header())
cc.responseWriter.WriteHeader(cc.code)
} else {
return len(buf), nil
}
return cc.responseWriter.Write(buf)
}
func (cc *codeCatcher) WriteHeader(code int) {
cc.code = code
}
type responseRecorder interface {
http.ResponseWriter
http.Flusher

View File

@@ -34,6 +34,18 @@ func TestHandler(t *testing.T) {
assert.Contains(t, recorder.Body.String(), http.StatusText(http.StatusOK))
},
},
{
desc: "no error, but not a 200",
errorPage: &types.ErrorPage{Backend: "error", Query: "/test", Status: []string{"500-501", "503-599"}},
backendCode: http.StatusPartialContent,
backendErrorHandler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "My error page.")
}),
validate: func(t *testing.T, recorder *httptest.ResponseRecorder) {
assert.Equal(t, http.StatusPartialContent, recorder.Code, "HTTP status")
assert.Contains(t, recorder.Body.String(), http.StatusText(http.StatusPartialContent))
},
},
{
desc: "in the range",
errorPage: &types.ErrorPage{Backend: "error", Query: "/test", Status: []string{"500-501", "503-599"}},

View File

@@ -5,6 +5,7 @@ import (
"net/http"
"net/http/httptest"
"net/http/httptrace"
"strconv"
"strings"
"testing"
@@ -35,7 +36,7 @@ func TestRetry(t *testing.T) {
desc: "no retry when max request attempts is one",
maxRequestAttempts: 1,
wantRetryAttempts: 0,
wantResponseStatus: http.StatusInternalServerError,
wantResponseStatus: http.StatusBadGateway,
amountFaultyEndpoints: 1,
},
{
@@ -56,7 +57,7 @@ func TestRetry(t *testing.T) {
desc: "max attempts exhausted delivers the 5xx response",
maxRequestAttempts: 3,
wantRetryAttempts: 2,
wantResponseStatus: http.StatusInternalServerError,
wantResponseStatus: http.StatusBadGateway,
amountFaultyEndpoints: 3,
},
}
@@ -82,17 +83,18 @@ func TestRetry(t *testing.T) {
t.Fatalf("Error creating load balancer: %s", err)
}
basePort := 33444
// out of range port
basePort := 1133444
for i := 0; i < test.amountFaultyEndpoints; i++ {
// 192.0.2.0 is a non-routable IP for testing purposes.
// See: https://stackoverflow.com/questions/528538/non-routable-ip-address/18436928#18436928
// We only use the port specification here because the URL is used as identifier
// in the load balancer and using the exact same URL would not add a new server.
loadBalancer.UpsertServer(testhelpers.MustParseURL("http://192.0.2.0:" + string(basePort+i)))
_ = loadBalancer.UpsertServer(testhelpers.MustParseURL("http://192.0.2.0:" + strconv.Itoa(basePort+i)))
}
// add the functioning server to the end of the load balancer list
loadBalancer.UpsertServer(testhelpers.MustParseURL(backendServer.URL))
_ = loadBalancer.UpsertServer(testhelpers.MustParseURL(backendServer.URL))
retryListener := &countingRetryListener{}
retry := NewRetry(test.maxRequestAttempts, loadBalancer, retryListener)
@@ -154,17 +156,18 @@ func TestRetryWebsocket(t *testing.T) {
t.Fatalf("Error creating load balancer: %s", err)
}
basePort := 33444
// out of range port
basePort := 1133444
for i := 0; i < test.amountFaultyEndpoints; i++ {
// 192.0.2.0 is a non-routable IP for testing purposes.
// See: https://stackoverflow.com/questions/528538/non-routable-ip-address/18436928#18436928
// We only use the port specification here because the URL is used as identifier
// in the load balancer and using the exact same URL would not add a new server.
loadBalancer.UpsertServer(testhelpers.MustParseURL("http://192.0.2.0:" + string(basePort+i)))
_ = loadBalancer.UpsertServer(testhelpers.MustParseURL("http://192.0.2.0:" + strconv.Itoa(basePort+i)))
}
// add the functioning server to the end of the load balancer list
loadBalancer.UpsertServer(testhelpers.MustParseURL(backendServer.URL))
_ = loadBalancer.UpsertServer(testhelpers.MustParseURL(backendServer.URL))
retryListener := &countingRetryListener{}
retry := NewRetry(test.maxRequestAttempts, loadBalancer, retryListener)

View File

@@ -44,7 +44,7 @@ type DistinguishedNameOptions struct {
// TLSClientHeaders is a middleware that helps setup a few tls info features.
type TLSClientHeaders struct {
Infos *TLSClientCertificateInfos // pass selected informations from the client certificate
Infos *TLSClientCertificateInfos // pass selected information from the client certificate
PEM bool // pass the sanitized pem to the backend in a specific header
}
@@ -79,23 +79,14 @@ func newTLSClientInfos(infos *types.TLSClientCertificateInfos) *TLSClientCertifi
}
// NewTLSClientHeaders constructs a new TLSClientHeaders instance from supplied frontend header struct.
func NewTLSClientHeaders(frontend *types.Frontend) *TLSClientHeaders {
if frontend == nil {
func NewTLSClientHeaders(passTLSClientCert *types.TLSClientHeaders) *TLSClientHeaders {
if passTLSClientCert == nil {
return nil
}
var addPEM bool
var infos *TLSClientCertificateInfos
if frontend.PassTLSClientCert != nil {
conf := frontend.PassTLSClientCert
addPEM = conf.PEM
infos = newTLSClientInfos(conf.Infos)
}
return &TLSClientHeaders{
Infos: infos,
PEM: addPEM,
Infos: newTLSClientInfos(passTLSClientCert.Infos),
PEM: passTLSClientCert.PEM,
}
}
@@ -221,7 +212,7 @@ func writePart(content *strings.Builder, entry string, prefix string) {
}
}
// getXForwardedTLSClientCertInfo Build a string with the wanted client certificates informations
// getXForwardedTLSClientCertInfo Build a string with the wanted client certificates information
// like Subject="DC=%s,C=%s,ST=%s,L=%s,O=%s,CN=%s",NB=%d,NA=%d,SAN=%s;
func (s *TLSClientHeaders) getXForwardedTLSClientCertInfo(certs []*x509.Certificate) string {
var headerValues []string
@@ -268,8 +259,9 @@ func (s *TLSClientHeaders) getXForwardedTLSClientCertInfo(certs []*x509.Certific
return strings.Join(headerValues, ";")
}
// ModifyRequestHeaders set the wanted headers with the certificates informations
// ModifyRequestHeaders set the wanted headers with the certificates information
func (s *TLSClientHeaders) ModifyRequestHeaders(r *http.Request) {
r.Header.Del(xForwardedTLSClientCert)
if s.PEM {
if r.TLS != nil && len(r.TLS.PeerCertificates) > 0 {
r.Header.Set(xForwardedTLSClientCert, getXForwardedTLSClientCert(r.TLS.PeerCertificates))
@@ -278,6 +270,7 @@ func (s *TLSClientHeaders) ModifyRequestHeaders(r *http.Request) {
}
}
r.Header.Del(xForwardedTLSClientCertInfos)
if s.Infos != nil {
if r.TLS != nil && len(r.TLS.PeerCertificates) > 0 {
headerContent := s.getXForwardedTLSClientCertInfo(r.TLS.PeerCertificates)

View File

@@ -240,26 +240,6 @@ mxcl71pV8i3NDU3kgVi2440JYpoMveTlXPCV2svHNCw0X238YHsSW4b93yGJO0gI
ML9n/4zmm1PMhzZHcEA72ZAq0tKCxpz10djg5v2qL5V+Oaz8TtTOZbPsxpiKMQ==
-----END CERTIFICATE-----
`
minimalCert = `-----BEGIN CERTIFICATE-----
MIIDGTCCAgECCQCqLd75YLi2kDANBgkqhkiG9w0BAQsFADBYMQswCQYDVQQGEwJG
UjETMBEGA1UECAwKU29tZS1TdGF0ZTERMA8GA1UEBwwIVG91bG91c2UxITAfBgNV
BAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0xODA3MTgwODI4MTZaFw0x
ODA4MTcwODI4MTZaMEUxCzAJBgNVBAYTAkZSMRMwEQYDVQQIDApTb21lLVN0YXRl
MSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggEiMA0GCSqGSIb3
DQEBAQUAA4IBDwAwggEKAoIBAQC/+frDMMTLQyXG34F68BPhQq0kzK4LIq9Y0/gl
FjySZNn1C0QDWA1ubVCAcA6yY204I9cxcQDPNrhC7JlS5QA8Y5rhIBrqQlzZizAi
Rj3NTrRjtGUtOScnHuJaWjLy03DWD+aMwb7q718xt5SEABmmUvLwQK+EjW2MeDwj
y8/UEIpvrRDmdhGaqv7IFpIDkcIF7FowJ/hwDvx3PMc+z/JWK0ovzpvgbx69AVbw
ZxCimeha65rOqVi+lEetD26le+WnOdYsdJ2IkmpPNTXGdfb15xuAc+gFXfMCh7Iw
3Ynl6dZtZM/Ok2kiA7/OsmVnRKkWrtBfGYkI9HcNGb3zrk6nAgMBAAEwDQYJKoZI
hvcNAQELBQADggEBAC/R+Yvhh1VUhcbK49olWsk/JKqfS3VIDQYZg1Eo+JCPbwgS
I1BSYVfMcGzuJTX6ua3m/AHzGF3Tap4GhF4tX12jeIx4R4utnjj7/YKkTvuEM2f4
xT56YqI7zalGScIB0iMeyNz1QcimRl+M/49au8ow9hNX8C2tcA2cwd/9OIj/6T8q
SBRHc6ojvbqZSJCO0jziGDT1L3D+EDgTjED4nd77v/NRdP+egb0q3P0s4dnQ/5AV
aQlQADUn61j3ScbGJ4NSeZFFvsl38jeRi/MEzp0bGgNBcPj6JHi7qbbauZcZfQ05
jECvgAY7Nfd9mZ1KtyNaW31is+kag7NsvjxU/kM=
-----END CERTIFICATE-----`
)
func getCleanCertContents(certContents []string) string {
@@ -303,10 +283,6 @@ func buildTLSWith(certContents []string) *tls.ConnectionState {
return &tls.ConnectionState{PeerCertificates: peerCertificates}
}
var myPassTLSClientCustomHandler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("bar"))
})
func getExpectedSanitized(s string) string {
return url.QueryEscape(strings.Replace(s, "\n", "", -1))
}
@@ -360,20 +336,13 @@ WqeUSNGYV//RunTeuRDAf5OxehERb1srzBXhRZ3cZdzXbgR/`),
}
func TestTlsClientheadersWithPEM(t *testing.T) {
func TestTlsClientHeadersWithPEM(t *testing.T) {
testCases := []struct {
desc string
certContents []string // set the request TLS attribute if defined
tlsClientCertHeaders *types.TLSClientHeaders
expectedHeader string
}{
{
desc: "No TLS, no option",
},
{
desc: "TLS, no option",
certContents: []string{minimalCheeseCrt},
},
{
desc: "No TLS, with pem option true",
tlsClientCertHeaders: &types.TLSClientHeaders{PEM: true},
@@ -399,20 +368,24 @@ func TestTlsClientheadersWithPEM(t *testing.T) {
}
for _, test := range testCases {
tlsClientHeaders := NewTLSClientHeaders(&types.Frontend{PassTLSClientCert: test.tlsClientCertHeaders})
res := httptest.NewRecorder()
req := testhelpers.MustNewRequest(http.MethodGet, "http://example.com/foo", nil)
if test.certContents != nil && len(test.certContents) > 0 {
req.TLS = buildTLSWith(test.certContents)
}
tlsClientHeaders.ServeHTTP(res, req, myPassTLSClientCustomHandler)
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
tlsClientHeaders := NewTLSClientHeaders(test.tlsClientCertHeaders)
res := httptest.NewRecorder()
req := testhelpers.MustNewRequest(http.MethodGet, "http://example.com/foo", nil)
if test.tlsClientCertHeaders != nil {
req.Header.Set(xForwardedTLSClientCert, "Unsanitized HEADER")
}
if test.certContents != nil && len(test.certContents) > 0 {
req.TLS = buildTLSWith(test.certContents)
}
tlsClientHeaders.ServeHTTP(res, req, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("bar"))
}))
require.Equal(t, http.StatusOK, res.Code, "Http Status should be OK")
require.Equal(t, "bar", res.Body.String(), "Should be the expected body")
@@ -477,7 +450,7 @@ func TestGetSans(t *testing.T) {
}
func TestTlsClientheadersWithCertInfos(t *testing.T) {
func TestTlsClientHeadersWithCertInfos(t *testing.T) {
minimalCheeseCertAllInfos := `Subject="C=FR,ST=Some-State,O=Cheese",Issuer="DC=org,DC=cheese,C=FR,C=US,ST=Signing State,ST=Signing State 2,L=TOULOUSE,L=LYON,O=Cheese,O=Cheese 2,CN=Simple Signing CA 2",NB=1544094636,NA=1632568236,SAN=`
completeCertAllInfos := `Subject="DC=org,DC=cheese,C=FR,C=US,ST=Cheese org state,ST=Cheese com state,L=TOULOUSE,L=LYON,O=Cheese,O=Cheese 2,CN=*.cheese.com",Issuer="DC=org,DC=cheese,C=FR,C=US,ST=Signing State,ST=Signing State 2,L=TOULOUSE,L=LYON,O=Cheese,O=Cheese 2,CN=Simple Signing CA 2",NB=1544094616,NA=1607166616,SAN=*.cheese.org,*.cheese.net,*.cheese.com,test@cheese.org,test@cheese.net,10.0.1.0,10.0.1.2`
@@ -487,13 +460,6 @@ func TestTlsClientheadersWithCertInfos(t *testing.T) {
tlsClientCertHeaders *types.TLSClientHeaders
expectedHeader string
}{
{
desc: "No TLS, no option",
},
{
desc: "TLS, no option",
certContents: []string{minimalCert},
},
{
desc: "No TLS, with pem option true",
tlsClientCertHeaders: &types.TLSClientHeaders{
@@ -627,20 +593,24 @@ func TestTlsClientheadersWithCertInfos(t *testing.T) {
},
}
for _, test := range testCases {
tlsClientHeaders := NewTLSClientHeaders(&types.Frontend{PassTLSClientCert: test.tlsClientCertHeaders})
res := httptest.NewRecorder()
req := testhelpers.MustNewRequest(http.MethodGet, "http://example.com/foo", nil)
if test.certContents != nil && len(test.certContents) > 0 {
req.TLS = buildTLSWith(test.certContents)
}
tlsClientHeaders.ServeHTTP(res, req, myPassTLSClientCustomHandler)
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
tlsClientHeaders := NewTLSClientHeaders(test.tlsClientCertHeaders)
res := httptest.NewRecorder()
req := testhelpers.MustNewRequest(http.MethodGet, "http://example.com/foo", nil)
if test.tlsClientCertHeaders != nil {
req.Header.Set(xForwardedTLSClientCertInfos, "Unsanitized HEADER")
}
if test.certContents != nil && len(test.certContents) > 0 {
req.TLS = buildTLSWith(test.certContents)
}
tlsClientHeaders.ServeHTTP(res, req, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("bar"))
}))
require.Equal(t, http.StatusOK, res.Code, "Http Status should be OK")
require.Equal(t, "bar", res.Body.String(), "Should be the expected body")
@@ -664,45 +634,31 @@ func TestTlsClientheadersWithCertInfos(t *testing.T) {
func TestNewTLSClientHeadersFromStruct(t *testing.T) {
testCases := []struct {
desc string
frontend *types.Frontend
expected *TLSClientHeaders
desc string
tlsClientHeaders *types.TLSClientHeaders
expected *TLSClientHeaders
}{
{
desc: "Without frontend",
},
{
desc: "frontend without the option",
frontend: &types.Frontend{},
expected: &TLSClientHeaders{},
},
{
desc: "frontend with the pem set false",
frontend: &types.Frontend{
PassTLSClientCert: &types.TLSClientHeaders{
PEM: false,
},
desc: "TLS client headers with the pem set false",
tlsClientHeaders: &types.TLSClientHeaders{
PEM: false,
},
expected: &TLSClientHeaders{PEM: false},
},
{
desc: "frontend with the pem set true",
frontend: &types.Frontend{
PassTLSClientCert: &types.TLSClientHeaders{
PEM: true,
},
desc: "TLS client headers with the pem set true",
tlsClientHeaders: &types.TLSClientHeaders{
PEM: true,
},
expected: &TLSClientHeaders{PEM: true},
},
{
desc: "frontend with the Infos with no flag",
frontend: &types.Frontend{
PassTLSClientCert: &types.TLSClientHeaders{
Infos: &types.TLSClientCertificateInfos{
NotAfter: false,
NotBefore: false,
Sans: false,
},
desc: "TLS client headers with the Infos with no flag",
tlsClientHeaders: &types.TLSClientHeaders{
Infos: &types.TLSClientCertificateInfos{
NotAfter: false,
NotBefore: false,
Sans: false,
},
},
expected: &TLSClientHeaders{
@@ -711,14 +667,12 @@ func TestNewTLSClientHeadersFromStruct(t *testing.T) {
},
},
{
desc: "frontend with the Infos basic",
frontend: &types.Frontend{
PassTLSClientCert: &types.TLSClientHeaders{
Infos: &types.TLSClientCertificateInfos{
NotAfter: true,
NotBefore: true,
Sans: true,
},
desc: "TLS client headers with the Infos basic",
tlsClientHeaders: &types.TLSClientHeaders{
Infos: &types.TLSClientCertificateInfos{
NotAfter: true,
NotBefore: true,
Sans: true,
},
},
expected: &TLSClientHeaders{
@@ -731,12 +685,10 @@ func TestNewTLSClientHeadersFromStruct(t *testing.T) {
},
},
{
desc: "frontend with the Infos NotAfter",
frontend: &types.Frontend{
PassTLSClientCert: &types.TLSClientHeaders{
Infos: &types.TLSClientCertificateInfos{
NotAfter: true,
},
desc: "TLS client headers with the Infos NotAfter",
tlsClientHeaders: &types.TLSClientHeaders{
Infos: &types.TLSClientCertificateInfos{
NotAfter: true,
},
},
expected: &TLSClientHeaders{
@@ -747,12 +699,10 @@ func TestNewTLSClientHeadersFromStruct(t *testing.T) {
},
},
{
desc: "frontend with the Infos NotBefore",
frontend: &types.Frontend{
PassTLSClientCert: &types.TLSClientHeaders{
Infos: &types.TLSClientCertificateInfos{
NotBefore: true,
},
desc: "TLS client headers with the Infos NotBefore",
tlsClientHeaders: &types.TLSClientHeaders{
Infos: &types.TLSClientCertificateInfos{
NotBefore: true,
},
},
expected: &TLSClientHeaders{
@@ -763,12 +713,10 @@ func TestNewTLSClientHeadersFromStruct(t *testing.T) {
},
},
{
desc: "frontend with the Infos Sans",
frontend: &types.Frontend{
PassTLSClientCert: &types.TLSClientHeaders{
Infos: &types.TLSClientCertificateInfos{
Sans: true,
},
desc: "TLS client headers with the Infos Sans",
tlsClientHeaders: &types.TLSClientHeaders{
Infos: &types.TLSClientCertificateInfos{
Sans: true,
},
},
expected: &TLSClientHeaders{
@@ -779,13 +727,11 @@ func TestNewTLSClientHeadersFromStruct(t *testing.T) {
},
},
{
desc: "frontend with the Infos Subject Organization",
frontend: &types.Frontend{
PassTLSClientCert: &types.TLSClientHeaders{
Infos: &types.TLSClientCertificateInfos{
Subject: &types.TLSCLientCertificateDNInfos{
Organization: true,
},
desc: "TLS client headers with the Infos Subject Organization",
tlsClientHeaders: &types.TLSClientHeaders{
Infos: &types.TLSClientCertificateInfos{
Subject: &types.TLSCLientCertificateDNInfos{
Organization: true,
},
},
},
@@ -799,13 +745,11 @@ func TestNewTLSClientHeadersFromStruct(t *testing.T) {
},
},
{
desc: "frontend with the Infos Subject Country",
frontend: &types.Frontend{
PassTLSClientCert: &types.TLSClientHeaders{
Infos: &types.TLSClientCertificateInfos{
Subject: &types.TLSCLientCertificateDNInfos{
Country: true,
},
desc: "TLS client headers with the Infos Subject Country",
tlsClientHeaders: &types.TLSClientHeaders{
Infos: &types.TLSClientCertificateInfos{
Subject: &types.TLSCLientCertificateDNInfos{
Country: true,
},
},
},
@@ -819,13 +763,11 @@ func TestNewTLSClientHeadersFromStruct(t *testing.T) {
},
},
{
desc: "frontend with the Infos Subject SerialNumber",
frontend: &types.Frontend{
PassTLSClientCert: &types.TLSClientHeaders{
Infos: &types.TLSClientCertificateInfos{
Subject: &types.TLSCLientCertificateDNInfos{
SerialNumber: true,
},
desc: "TLS client headers with the Infos Subject SerialNumber",
tlsClientHeaders: &types.TLSClientHeaders{
Infos: &types.TLSClientCertificateInfos{
Subject: &types.TLSCLientCertificateDNInfos{
SerialNumber: true,
},
},
},
@@ -839,13 +781,11 @@ func TestNewTLSClientHeadersFromStruct(t *testing.T) {
},
},
{
desc: "frontend with the Infos Subject Province",
frontend: &types.Frontend{
PassTLSClientCert: &types.TLSClientHeaders{
Infos: &types.TLSClientCertificateInfos{
Subject: &types.TLSCLientCertificateDNInfos{
Province: true,
},
desc: "TLS client headers with the Infos Subject Province",
tlsClientHeaders: &types.TLSClientHeaders{
Infos: &types.TLSClientCertificateInfos{
Subject: &types.TLSCLientCertificateDNInfos{
Province: true,
},
},
},
@@ -859,13 +799,11 @@ func TestNewTLSClientHeadersFromStruct(t *testing.T) {
},
},
{
desc: "frontend with the Infos Subject Locality",
frontend: &types.Frontend{
PassTLSClientCert: &types.TLSClientHeaders{
Infos: &types.TLSClientCertificateInfos{
Subject: &types.TLSCLientCertificateDNInfos{
Locality: true,
},
desc: "TLS client headers with the Infos Subject Locality",
tlsClientHeaders: &types.TLSClientHeaders{
Infos: &types.TLSClientCertificateInfos{
Subject: &types.TLSCLientCertificateDNInfos{
Locality: true,
},
},
},
@@ -879,13 +817,11 @@ func TestNewTLSClientHeadersFromStruct(t *testing.T) {
},
},
{
desc: "frontend with the Infos Subject CommonName",
frontend: &types.Frontend{
PassTLSClientCert: &types.TLSClientHeaders{
Infos: &types.TLSClientCertificateInfos{
Subject: &types.TLSCLientCertificateDNInfos{
CommonName: true,
},
desc: "TLS client headers with the Infos Subject CommonName",
tlsClientHeaders: &types.TLSClientHeaders{
Infos: &types.TLSClientCertificateInfos{
Subject: &types.TLSCLientCertificateDNInfos{
CommonName: true,
},
},
},
@@ -899,19 +835,17 @@ func TestNewTLSClientHeadersFromStruct(t *testing.T) {
},
},
{
desc: "frontend with the Infos Issuer",
frontend: &types.Frontend{
PassTLSClientCert: &types.TLSClientHeaders{
Infos: &types.TLSClientCertificateInfos{
Issuer: &types.TLSCLientCertificateDNInfos{
CommonName: true,
Country: true,
DomainComponent: true,
Locality: true,
Organization: true,
SerialNumber: true,
Province: true,
},
desc: "TLS client headers with the Infos Issuer",
tlsClientHeaders: &types.TLSClientHeaders{
Infos: &types.TLSClientCertificateInfos{
Issuer: &types.TLSCLientCertificateDNInfos{
CommonName: true,
Country: true,
DomainComponent: true,
Locality: true,
Organization: true,
SerialNumber: true,
Province: true,
},
},
},
@@ -931,12 +865,10 @@ func TestNewTLSClientHeadersFromStruct(t *testing.T) {
},
},
{
desc: "frontend with the Sans Infos",
frontend: &types.Frontend{
PassTLSClientCert: &types.TLSClientHeaders{
Infos: &types.TLSClientCertificateInfos{
Sans: true,
},
desc: "TLS client headers with the Sans Infos",
tlsClientHeaders: &types.TLSClientHeaders{
Infos: &types.TLSClientCertificateInfos{
Sans: true,
},
},
expected: &TLSClientHeaders{
@@ -947,30 +879,28 @@ func TestNewTLSClientHeadersFromStruct(t *testing.T) {
},
},
{
desc: "frontend with the Infos all",
frontend: &types.Frontend{
PassTLSClientCert: &types.TLSClientHeaders{
Infos: &types.TLSClientCertificateInfos{
NotAfter: true,
NotBefore: true,
Subject: &types.TLSCLientCertificateDNInfos{
CommonName: true,
Country: true,
Locality: true,
Organization: true,
Province: true,
SerialNumber: true,
},
Issuer: &types.TLSCLientCertificateDNInfos{
Country: true,
DomainComponent: true,
Locality: true,
Organization: true,
SerialNumber: true,
Province: true,
},
Sans: true,
desc: "TLS client headers with the Infos all",
tlsClientHeaders: &types.TLSClientHeaders{
Infos: &types.TLSClientCertificateInfos{
NotAfter: true,
NotBefore: true,
Subject: &types.TLSCLientCertificateDNInfos{
CommonName: true,
Country: true,
Locality: true,
Organization: true,
Province: true,
SerialNumber: true,
},
Issuer: &types.TLSCLientCertificateDNInfos{
Country: true,
DomainComponent: true,
Locality: true,
Organization: true,
SerialNumber: true,
Province: true,
},
Sans: true,
},
},
expected: &TLSClientHeaders{
@@ -1004,8 +934,7 @@ func TestNewTLSClientHeadersFromStruct(t *testing.T) {
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
require.Equal(t, test.expected, NewTLSClientHeaders(test.frontend))
require.Equal(t, test.expected, NewTLSClientHeaders(test.tlsClientHeaders))
})
}
}

View File

@@ -15,10 +15,14 @@ const Name = "datadog"
// Config provides configuration settings for a datadog tracer
type Config struct {
LocalAgentHostPort string `description:"Set datadog-agent's host:port that the reporter will used. Defaults to localhost:8126" export:"false"`
GlobalTag string `description:"Key:Value tag to be set on all the spans." export:"true"`
Debug bool `description:"Enable DataDog debug." export:"true"`
PrioritySampling bool `description:"Enable priority sampling. When using distributed tracing, this option must be enabled in order to get all the parts of a distributed trace sampled."`
LocalAgentHostPort string `description:"Set datadog-agent's host:port that the reporter will used. Defaults to localhost:8126" export:"false"`
GlobalTag string `description:"Key:Value tag to be set on all the spans." export:"true"`
Debug bool `description:"Enable DataDog debug." export:"true"`
PrioritySampling bool `description:"Enable priority sampling. When using distributed tracing, this option must be enabled in order to get all the parts of a distributed trace sampled."`
TraceIDHeaderName string `description:"Specifies the header name that will be used to store the trace ID." export:"true"`
ParentIDHeaderName string `description:"Specifies the header name that will be used to store the parent ID." export:"true"`
SamplingPriorityHeaderName string `description:"Specifies the header name that will be used to store the sampling priority." export:"true"`
BagagePrefixHeaderName string `description:"specifies the header name prefix that will be used to store baggage items in a map." export:"true"`
}
// Setup sets up the tracer
@@ -35,6 +39,12 @@ func (c *Config) Setup(serviceName string) (opentracing.Tracer, io.Closer, error
datadog.WithServiceName(serviceName),
datadog.WithGlobalTag(tag[0], value),
datadog.WithDebugMode(c.Debug),
datadog.WithPropagator(datadog.NewPropagator(&datadog.PropagatorConfig{
TraceHeader: c.TraceIDHeaderName,
ParentHeader: c.ParentIDHeaderName,
PriorityHeader: c.SamplingPriorityHeaderName,
BaggagePrefix: c.BagagePrefixHeaderName,
})),
}
if c.PrioritySampling {
opts = append(opts, datadog.WithPrioritySampling())

View File

@@ -5,7 +5,7 @@ import (
"github.com/containous/traefik/log"
"github.com/opentracing/opentracing-go"
zipkin "github.com/openzipkin/zipkin-go-opentracing"
zipkin "github.com/openzipkin-contrib/zipkin-go-opentracing"
)
// Name sets the name of this tracer

View File

@@ -6,6 +6,7 @@ dev_addr: 0.0.0.0:8000
repo_name: 'GitHub'
repo_url: 'https://github.com/containous/traefik'
edit_uri: 'edit/v1.7/docs/'
docs_dir: 'docs'

View File

@@ -7,8 +7,8 @@ import (
"crypto/x509"
"github.com/containous/traefik/log"
"github.com/xenolf/lego/certcrypto"
"github.com/xenolf/lego/registration"
"github.com/go-acme/lego/certcrypto"
"github.com/go-acme/lego/registration"
)
// Account is used to store lets encrypt registration info

View File

@@ -9,8 +9,8 @@ import (
"github.com/containous/mux"
"github.com/containous/traefik/log"
"github.com/containous/traefik/safe"
"github.com/xenolf/lego/challenge"
"github.com/xenolf/lego/challenge/http01"
"github.com/go-acme/lego/challenge"
"github.com/go-acme/lego/challenge/http01"
)
var _ challenge.ProviderTimeout = (*challengeHTTP)(nil)

View File

@@ -5,8 +5,8 @@ import (
"github.com/containous/traefik/log"
"github.com/containous/traefik/types"
"github.com/xenolf/lego/challenge"
"github.com/xenolf/lego/challenge/tlsalpn01"
"github.com/go-acme/lego/challenge"
"github.com/go-acme/lego/challenge/tlsalpn01"
)
var _ challenge.Provider = (*challengeTLSALPN)(nil)

View File

@@ -20,19 +20,19 @@ import (
traefiktls "github.com/containous/traefik/tls"
"github.com/containous/traefik/types"
"github.com/containous/traefik/version"
"github.com/go-acme/lego/certificate"
"github.com/go-acme/lego/challenge"
"github.com/go-acme/lego/challenge/dns01"
"github.com/go-acme/lego/lego"
legolog "github.com/go-acme/lego/log"
"github.com/go-acme/lego/providers/dns"
"github.com/go-acme/lego/registration"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/xenolf/lego/certificate"
"github.com/xenolf/lego/challenge"
"github.com/xenolf/lego/challenge/dns01"
"github.com/xenolf/lego/lego"
legolog "github.com/xenolf/lego/log"
"github.com/xenolf/lego/providers/dns"
"github.com/xenolf/lego/registration"
)
var (
// OSCPMustStaple enables OSCP stapling as from https://github.com/xenolf/lego/issues/270
// OSCPMustStaple enables OSCP stapling as from https://github.com/go-acme/lego/issues/270
OSCPMustStaple = false
)
@@ -49,7 +49,7 @@ type Configuration struct {
DNSChallenge *DNSChallenge `description:"Activate DNS-01 Challenge"`
HTTPChallenge *HTTPChallenge `description:"Activate HTTP-01 Challenge"`
TLSChallenge *TLSChallenge `description:"Activate TLS-ALPN-01 Challenge"`
Domains []types.Domain `description:"CN and SANs (alternative domains) to each main domain using format: --acme.domains='main.com,san1.com,san2.com' --acme.domains='*.main.net'. No SANs for wildcards domain. Wildcard domains only accepted with DNSChallenge"`
Domains []types.Domain `description:"CN and SANs (alternative domains) to each main domain using format: --acme.domains='main.com,san1.com,san2.com' --acme.domains='*.main.net'. Wildcard domains only accepted with DNSChallenge"`
}
// Provider holds configurations of the provider.
@@ -756,12 +756,6 @@ func (p *Provider) getValidDomains(domain types.Domain, wildcardAllowed bool) ([
}
}
for _, san := range domain.SANs {
if strings.HasPrefix(san, "*") {
return nil, fmt.Errorf("unable to generate a certificate in ACME provider for domains %q: SAN %q can not be a wildcard domain", strings.Join(domains, ","), san)
}
}
var cleanDomains []string
for _, domain := range domains {
canonicalDomain := types.CanonicalDomain(domain)

View File

@@ -7,8 +7,8 @@ import (
"github.com/containous/traefik/safe"
traefiktls "github.com/containous/traefik/tls"
"github.com/containous/traefik/types"
"github.com/go-acme/lego/certcrypto"
"github.com/stretchr/testify/assert"
"github.com/xenolf/lego/certcrypto"
)
func TestGetUncheckedCertificates(t *testing.T) {
@@ -267,12 +267,12 @@ func TestGetValidDomain(t *testing.T) {
expectedDomains: []string{"*.traefik.wtf", "traefik.wtf"},
},
{
desc: "unexpected SANs",
desc: "wildcard SANs",
domains: types.Domain{Main: "*.traefik.wtf", SANs: []string{"*.acme.wtf"}},
dnsChallenge: &DNSChallenge{},
wildcardAllowed: true,
expectedErr: "unable to generate a certificate in ACME provider for domains \"*.traefik.wtf,*.acme.wtf\": SAN \"*.acme.wtf\" can not be a wildcard domain",
expectedDomains: nil,
expectedErr: "",
expectedDomains: []string{"*.traefik.wtf", "*.acme.wtf"},
},
}

View File

@@ -34,6 +34,7 @@ type Provider struct {
Stale bool `description:"Use stale consistency for catalog reads" export:"true"`
ExposedByDefault bool `description:"Expose Consul services by default" export:"true"`
Prefix string `description:"Prefix used for Consul catalog tags" export:"true"`
StrictChecks bool `description:"Keep a Consul node only if all checks status are passing" export:"true"`
FrontEndRule string `description:"Frontend rule used for Consul services" export:"true"`
TLS *types.ClientTLS `description:"Enable TLS support" export:"true"`
client *api.Client
@@ -301,6 +302,8 @@ func (p *Provider) watchHealthState(stopCh <-chan struct{}, watchCh chan<- map[s
_, failing := currentFailing[key]
if healthy.Status == "passing" && !failing {
current[key] = append(current[key], healthy.Node)
} else if !p.StrictChecks && healthy.Status == "warning" && !failing {
current[key] = append(current[key], healthy.Node)
} else if strings.HasPrefix(healthy.CheckID, "_service_maintenance") || strings.HasPrefix(healthy.CheckID, "_node_maintenance") {
maintenance = append(maintenance, healthy.CheckID)
} else {
@@ -489,7 +492,8 @@ func getServiceAddresses(services []*api.CatalogService) []string {
func (p *Provider) healthyNodes(service string) (catalogUpdate, error) {
health := p.client.Health()
data, _, err := health.Service(service, "", true, &api.QueryOptions{AllowStale: p.Stale})
// You can't filter with assigning passingOnly here, nodeFilter will do this later
data, _, err := health.Service(service, "", false, &api.QueryOptions{AllowStale: p.Stale})
if err != nil {
log.WithError(err).Errorf("Failed to fetch details of %s", service)
return catalogUpdate{}, err
@@ -533,7 +537,8 @@ func (p *Provider) nodeFilter(service string, node *api.ServiceEntry) bool {
log.Debugf("Service %v pruned by '%v' constraint", service, failingConstraint.String())
return false
}
return true
return p.hasPassingChecks(node)
}
func (p *Provider) isServiceEnabled(node *api.ServiceEntry) bool {
@@ -567,6 +572,11 @@ func (p *Provider) getConstraintTags(tags []string) []string {
return values
}
func (p *Provider) hasPassingChecks(node *api.ServiceEntry) bool {
status := node.Checks.AggregatedStatus()
return status == "passing" || !p.StrictChecks && status == "warning"
}
func (p *Provider) generateFrontends(service *serviceUpdate) []*serviceUpdate {
frontends := make([]*serviceUpdate, 0)
// to support <prefix>.frontend.xxx

View File

@@ -28,7 +28,9 @@ import (
)
const (
// SwarmAPIVersion is a constant holding the version of the Provider API traefik will use
// DockerAPIVersion is a constant holding the version of the Provider API traefik will use
DockerAPIVersion = "1.24"
// SwarmAPIVersion is a constant holding the version of the Provider API traefik will use.
SwarmAPIVersion = "1.24"
)
@@ -110,11 +112,10 @@ func (p *Provider) createClient() (client.APIClient, error) {
"User-Agent": "Traefik " + version.Version,
}
var apiVersion string
apiVersion := DockerAPIVersion
if p.SwarmMode {
apiVersion = SwarmAPIVersion
} else {
apiVersion = DockerAPIVersion
}
return client.NewClient(p.Endpoint, apiVersion, httpClient, httpHeaders)

View File

@@ -1,8 +0,0 @@
// +build !windows
package docker
const (
// DockerAPIVersion is a constant holding the version of the Provider API traefik will use
DockerAPIVersion = "1.21"
)

View File

@@ -1,6 +0,0 @@
package docker
const (
// DockerAPIVersion is a constant holding the version of the Provider API traefik will use
DockerAPIVersion string = "1.24"
)

View File

@@ -5,7 +5,7 @@ import (
"github.com/abronan/valkeyrie/store"
"github.com/abronan/valkeyrie/store/etcd/v2"
"github.com/abronan/valkeyrie/store/etcd/v3"
etcdv3 "github.com/abronan/valkeyrie/store/etcd/v3"
"github.com/containous/traefik/log"
"github.com/containous/traefik/provider"
"github.com/containous/traefik/provider/kv"

View File

@@ -330,13 +330,13 @@ func createProvider(t *testing.T, test ProvideTestCase, watch bool) (*Provider,
}
return provider, func() {
os.Remove(tempDir)
os.RemoveAll(tempDir)
}
}
func TestTLSContent(t *testing.T) {
tempDir := createTempDir(t, "testdir")
defer os.Remove(tempDir)
defer os.RemoveAll(tempDir)
fileTLS := createRandomFile(t, tempDir, "CONTENT")
fileConfig := createRandomFile(t, tempDir, `

View File

@@ -230,9 +230,25 @@ func auth(opt func(*types.Auth)) func(*types.Frontend) {
}
}
func basicAuth(users ...string) func(*types.Auth) {
func basicAuth(opts ...func(*types.Basic)) func(*types.Auth) {
return func(a *types.Auth) {
a.Basic = &types.Basic{Users: users}
basic := &types.Basic{}
for _, opt := range opts {
opt(basic)
}
a.Basic = basic
}
}
func baUsers(users ...string) func(*types.Basic) {
return func(b *types.Basic) {
b.Users = users
}
}
func baRemoveHeaders() func(*types.Basic) {
return func(b *types.Basic) {
b.RemoveHeader = true
}
}

View File

@@ -61,13 +61,6 @@ func eAddress(ip string) func(*corev1.EndpointAddress) {
}
}
func eAddressWithTargetRef(targetRef, ip string) func(*corev1.EndpointAddress) {
return func(address *corev1.EndpointAddress) {
address.TargetRef = &corev1.ObjectReference{Name: targetRef}
address.IP = ip
}
}
func ePorts(opts ...func(port *corev1.EndpointPort)) func(*corev1.EndpointSubset) {
return func(spec *corev1.EndpointSubset) {
for _, opt := range opts {

View File

@@ -35,15 +35,6 @@ func sUID(value types.UID) func(*corev1.Service) {
}
}
func sAnnotation(name string, value string) func(*corev1.Service) {
return func(s *corev1.Service) {
if s.Annotations == nil {
s.Annotations = make(map[string]string)
}
s.Annotations[name] = value
}
}
func sSpec(opts ...func(*corev1.ServiceSpec)) func(*corev1.Service) {
return func(s *corev1.Service) {
spec := &corev1.ServiceSpec{}
@@ -54,30 +45,6 @@ func sSpec(opts ...func(*corev1.ServiceSpec)) func(*corev1.Service) {
}
}
func sLoadBalancerStatus(opts ...func(*corev1.LoadBalancerStatus)) func(service *corev1.Service) {
return func(s *corev1.Service) {
loadBalancer := &corev1.LoadBalancerStatus{}
for _, opt := range opts {
if opt != nil {
opt(loadBalancer)
}
}
s.Status = corev1.ServiceStatus{
LoadBalancer: *loadBalancer,
}
}
}
func sLoadBalancerIngress(ip string, hostname string) func(*corev1.LoadBalancerStatus) {
return func(status *corev1.LoadBalancerStatus) {
ingress := corev1.LoadBalancerIngress{
IP: ip,
Hostname: hostname,
}
status.Ingress = append(status.Ingress, ingress)
}
}
func clusterIP(ip string) func(*corev1.ServiceSpec) {
return func(spec *corev1.ServiceSpec) {
spec.ClusterIP = ip

View File

@@ -1,21 +1,57 @@
package kubernetes
import (
"fmt"
"io/ioutil"
corev1 "k8s.io/api/core/v1"
extensionsv1beta1 "k8s.io/api/extensions/v1beta1"
v1beta12 "k8s.io/api/extensions/v1beta1"
)
var _ Client = (*clientMock)(nil)
type clientMock struct {
ingresses []*extensionsv1beta1.Ingress
services []*corev1.Service
secrets []*corev1.Secret
endpoints []*corev1.Endpoints
watchChan chan interface{}
apiServiceError error
apiSecretError error
apiEndpointsError error
apiIngressStatusError error
watchChan chan interface{}
}
func newClientMock(paths ...string) clientMock {
var c clientMock
for _, path := range paths {
yamlContent, err := ioutil.ReadFile(path)
if err != nil {
panic(err)
}
k8sObjects := MustDecodeYaml(yamlContent)
for _, obj := range k8sObjects {
switch o := obj.(type) {
case *corev1.Service:
c.services = append(c.services, o)
case *corev1.Secret:
c.secrets = append(c.secrets, o)
case *corev1.Endpoints:
c.endpoints = append(c.endpoints, o)
case *v1beta12.Ingress:
c.ingresses = append(c.ingresses, o)
default:
panic(fmt.Sprintf("Unknown runtime object %+v %T", o, o))
}
}
}
return c
}
func (c clientMock) GetIngresses() []*extensionsv1beta1.Ingress {

View File

@@ -0,0 +1,21 @@
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
ingress.kubernetes.io/service-weights: |2
service1: 10%
namespace: testing
spec:
rules:
- host: foo.test
http:
paths:
- backend:
serviceName: service1
servicePort: 8080
path: /foo
- backend:
serviceName: service2
servicePort: 8080
path: /foo

View File

@@ -0,0 +1,31 @@
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
ingress.kubernetes.io/service-weights: |2
service1: 20%
service2: 40%
service3: 40%
namespace: testing
spec:
rules:
- host: foo.test
http:
paths:
- backend:
serviceName: service1
servicePort: 8080
path: /foo
- backend:
serviceName: service2
servicePort: 8080
path: /foo
- backend:
serviceName: service3
servicePort: 8080
path: /foo
- backend:
serviceName: service4
servicePort: 8080
path: /foo

View File

@@ -0,0 +1,29 @@
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
ingress.kubernetes.io/service-weights: |2
service1: 60%
namespace: testing
spec:
rules:
- host: foo.test
http:
paths:
- backend:
serviceName: service1
servicePort: 8080
path: /foo
- backend:
serviceName: service2
servicePort: 8080
path: /foo
- backend:
serviceName: service1
servicePort: 8080
path: /bar
- backend:
serviceName: service3
servicePort: 8080
path: /bar

View File

@@ -0,0 +1,30 @@
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
ingress.kubernetes.io/service-weights: |2
service1: 20%
service3: 20%
namespace: testing
spec:
rules:
- host: foo.test
http:
paths:
- backend:
serviceName: service1
servicePort: 8080
path: /foo
- backend:
serviceName: service2
servicePort: 8080
path: /foo
- backend:
serviceName: service2
servicePort: 8080
path: /bar
- backend:
serviceName: service3
servicePort: 8080
path: /bar

View File

@@ -0,0 +1,23 @@
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
ingress.kubernetes.io/service-weights: |2
service1: 20%
service2: 40%
service3: 40%
namespace: testing
spec:
rules:
- host: foo.test
http:
paths:
- backend:
serviceName: noservice
servicePort: 8080
path: /foo
- backend:
serviceName: noservice
servicePort: 8080
path: /bar

View File

@@ -0,0 +1,22 @@
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
ingress.kubernetes.io/service-weights: |2
service1: 70%
service2: 80%
namespace: testing
spec:
rules:
- host: foo.test
http:
paths:
- backend:
serviceName: service1
servicePort: 8080
path: /foo
- backend:
serviceName: service2
servicePort: 8080
path: /foo

View File

@@ -0,0 +1,19 @@
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
ingress.kubernetes.io/service-weights: ""
namespace: testing
spec:
rules:
- host: foo.test
http:
paths:
- backend:
serviceName: service1
servicePort: 8080
path: /foo
- backend:
serviceName: service2
servicePort: 8080
path: /bar

View File

@@ -0,0 +1,62 @@
apiVersion: v1
kind: Endpoints
metadata:
name: service1
namespace: testing
subsets:
- addresses:
- ip: 10.10.0.1
ports:
- port: 8080
- addresses:
- ip: 10.21.0.2
ports:
- port: 8080
---
apiVersion: v1
kind: Endpoints
metadata:
name: service2
namespace: testing
subsets:
- addresses:
- ip: 10.10.0.3
ports:
- port: 8080
---
apiVersion: v1
kind: Endpoints
metadata:
name: service3
namespace: testing
subsets:
- addresses:
- ip: 10.10.0.4
ports:
- port: 8080
- addresses:
- ip: 10.21.0.5
ports:
- port: 8080
- addresses:
- ip: 10.21.0.6
ports:
- port: 8080
- addresses:
- ip: 10.21.0.7
ports:
- port: 8080
---
apiVersion: v1
kind: Endpoints
metadata:
name: service4
namespace: testing
subsets:
- addresses:
- ip: 10.10.0.7
ports:
- port: 8080

View File

@@ -0,0 +1,26 @@
apiVersion: v1
kind: Service
metadata:
name: service1
namespace: testing
---
apiVersion: v1
kind: Service
metadata:
name: service2
namespace: testing
---
apiVersion: v1
kind: Service
metadata:
name: service3
namespace: testing
---
apiVersion: v1
kind: Service
metadata:
name: service4
namespace: testing

View File

@@ -0,0 +1,16 @@
apiVersion: v1
kind: Endpoints
metadata:
name: service1
namespace: testing
subsets:
- addresses:
- ip: 10.10.0.1
ports:
- name: http
port: 80
- addresses:
- ip: 10.10.0.2
ports:
- name: http
port: 80

View File

@@ -0,0 +1,26 @@
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
namespace: testing
spec:
rules:
- host: host-a
http:
paths:
- backend:
serviceName: service1
servicePort: "80"
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
namespace: testing
spec:
rules:
- host: host-a
http:
paths:
- backend:
serviceName: missing
servicePort: "80"

View File

@@ -0,0 +1,10 @@
apiVersion: v1
kind: Service
metadata:
name: service1
namespace: testing
spec:
clusterIP: 10.0.0.1
ports:
- name: http
port: 80

View File

@@ -0,0 +1,13 @@
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
namespace: awesome
spec:
rules:
- host: foo
http:
paths:
- backend:
serviceName: service1
servicePort: 801
path: /bar

View File

@@ -0,0 +1,9 @@
apiVersion: v1
kind: Service
metadata:
name: service1
namespace: awesome
spec:
ports:
- name: http
port: 801

View File

@@ -0,0 +1,13 @@
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
namespace: awesome
spec:
rules:
- host: foo
http:
paths:
- backend:
serviceName: service1
servicePort: 80
path: /bar

View File

@@ -0,0 +1,9 @@
apiVersion: v1
kind: Service
metadata:
name: service1
namespace: awesome
spec:
ports:
- name: http
port: 801

View File

@@ -0,0 +1,12 @@
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
namespace: awesome
spec:
rules:
- http:
paths:
- backend:
serviceName: service1
servicePort: 801
path: /bar

View File

@@ -0,0 +1,10 @@
apiVersion: v1
kind: Service
metadata:
name: service1
namespace: awesome
spec:
clusterIP: 10.0.0.1
ports:
- name: http
port: 801

View File

@@ -0,0 +1,431 @@
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
ingress.kubernetes.io/preserve-host: "false"
namespace: testing
spec:
rules:
- host: foo
http:
paths:
- backend:
serviceName: service1
servicePort: 80
path: /bar
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
ingress.kubernetes.io/preserve-host: "true"
kubernetes.io/ingress.class: traefik
namespace: testing
spec:
rules:
- host: other
http:
paths:
- backend:
serviceName: service1
servicePort: 80
path: /stuff
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
ingress.kubernetes.io/pass-client-tls-cert: |2
pem: true
infos:
notafter: true
notbefore: true
sans: true
subject:
country: true
province: true
locality: true
organization: true
commonname: true
serialnumber: true
domaincomponent: true
issuer:
country: true
province: true
locality: true
organization: true
commonname: true
serialnumber: true
domaincomponent: true
ingress.kubernetes.io/pass-tls-cert: "true"
kubernetes.io/ingress.class: traefik
namespace: testing
spec:
rules:
- host: other
http:
paths:
- backend:
serviceName: service1
servicePort: 80
path: /sslstuff
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
ingress.kubernetes.io/frontend-entry-points: http,https
kubernetes.io/ingress.class: traefik
namespace: testing
spec:
rules:
- host: other
http:
paths:
- backend:
serviceName: service1
servicePort: 80
path: /
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
ingress.kubernetes.io/auth-secret: mySecret
ingress.kubernetes.io/auth-type: basic
namespace: testing
spec:
rules:
- host: basic
http:
paths:
- backend:
serviceName: service1
servicePort: 80
path: /auth
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: traefik-other
namespace: testing
spec:
rules:
- host: herp
http:
paths:
- backend:
serviceName: service2
servicePort: 80
path: /derp
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
ingress.kubernetes.io/whitelist-source-range: 1.1.1.1/24, 1234:abcd::42/32
ingress.kubernetes.io/whitelist-x-forwarded-for: "true"
namespace: testing
spec:
rules:
- host: test
http:
paths:
- backend:
serviceName: service1
servicePort: 80
path: /whitelist-source-range
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
ingress.kubernetes.io/rewrite-target: /
namespace: testing
spec:
rules:
- host: rewrite
http:
paths:
- backend:
serviceName: service1
servicePort: 80
path: /api
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
ingress.kubernetes.io/auth-realm: customized
namespace: testing
spec:
rules:
- host: auth-realm-customized
http:
paths:
- backend:
serviceName: service1
servicePort: 80
path: /auth-realm-customized
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
ingress.kubernetes.io/redirect-entry-point: https
namespace: testing
spec:
rules:
- host: redirect
http:
paths:
- backend:
serviceName: service1
servicePort: 80
path: /https
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
ingress.kubernetes.io/error-pages: |2
foo:
status:
- "123"
- "456"
backend: bar
query: /bar
kubernetes.io/ingress.class: traefik
namespace: testing
spec:
rules:
- host: error-pages
http:
paths:
- backend:
serviceName: service1
servicePort: 80
path: /errorpages
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
ingress.kubernetes.io/rate-limit: |2
extractorfunc: client.ip
rateset:
bar:
period: 3s
average: 6
burst: 9
foo:
period: 6s
average: 12
burst: 18
kubernetes.io/ingress.class: traefik
namespace: testing
spec:
rules:
- host: rate-limit
http:
paths:
- backend:
serviceName: service1
servicePort: 80
path: /ratelimit
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
ingress.kubernetes.io/app-root: /root
namespace: testing
spec:
rules:
- host: root
http:
paths:
- backend:
serviceName: service1
servicePort: 80
path: /
- backend:
serviceName: service1
servicePort: 80
path: /root1
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
ingress.kubernetes.io/app-root: /root2
ingress.kubernetes.io/rewrite-target: /abc
namespace: testing
spec:
rules:
- host: root2
http:
paths:
- backend:
serviceName: service2
servicePort: 80
path: /
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
ingress.kubernetes.io/rewrite-target: /abc
ingress.kubernetes.io/rule-type: ReplacePath
namespace: testing
spec:
rules:
- host: root2
http:
paths:
- backend:
serviceName: service2
servicePort: 80
path: /
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
ingress.kubernetes.io/app-root: /root
namespace: testing
spec:
rules:
- host: root3
http:
paths:
- backend:
serviceName: service1
servicePort: 80
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
ingress.kubernetes.io/allowed-hosts: foo, fii, fuu
ingress.kubernetes.io/browser-xss-filter: "true"
ingress.kubernetes.io/content-security-policy: foo
ingress.kubernetes.io/content-type-nosniff: "true"
ingress.kubernetes.io/custom-browser-xss-value: foo
ingress.kubernetes.io/custom-frame-options-value: foo
ingress.kubernetes.io/custom-request-headers: 'Access-Control-Allow-Methods:POST,GET,OPTIONS
|| Content-type: application/json; charset=utf-8'
ingress.kubernetes.io/custom-response-headers: 'Access-Control-Allow-Methods:POST,GET,OPTIONS
|| Content-type: application/json; charset=utf-8'
ingress.kubernetes.io/force-hsts: "true"
ingress.kubernetes.io/frame-deny: "true"
ingress.kubernetes.io/hsts-include-subdomains: "true"
ingress.kubernetes.io/hsts-max-age: "666"
ingress.kubernetes.io/hsts-preload: "true"
ingress.kubernetes.io/is-development: "true"
ingress.kubernetes.io/proxy-headers: foo, fii, fuu
ingress.kubernetes.io/public-key: foo
ingress.kubernetes.io/referrer-policy: foo
ingress.kubernetes.io/ssl-force-host: "true"
ingress.kubernetes.io/ssl-host: foo
ingress.kubernetes.io/ssl-proxy-headers: 'Access-Control-Allow-Methods:POST,GET,OPTIONS
|| Content-type: application/json; charset=utf-8'
ingress.kubernetes.io/ssl-redirect: "true"
ingress.kubernetes.io/ssl-temporary-redirect: "true"
kubernetes.io/ingress.class: traefik
namespace: testing
spec:
rules:
- host: custom-headers
http:
paths:
- backend:
serviceName: service1
servicePort: 80
path: /customheaders
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
ingress.kubernetes.io/protocol: h2c
namespace: testing
spec:
rules:
- host: protocol
http:
paths:
- backend:
serviceName: service1
servicePort: 80
path: /valid
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
ingress.kubernetes.io/protocol: foobar
namespace: testing
spec:
rules:
- host: protocol
http:
paths:
- backend:
serviceName: service1
servicePort: 80
path: /notvalid
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
ingress.kubernetes.io/protocol: http
namespace: testing
spec:
rules:
- host: protocol
http:
paths:
- backend:
serviceName: serviceHTTPS
servicePort: 443
path: /missmatch
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
namespace: testing
spec:
rules:
- host: protocol
http:
paths:
- backend:
serviceName: serviceHTTPS
servicePort: 443
path: /noAnnotation

Some files were not shown because too many files have changed in this diff Show More