From e8633d17e8f600a053564123831d77470719328c Mon Sep 17 00:00:00 2001 From: Emile Vauge Date: Mon, 30 Oct 2017 10:02:03 +0100 Subject: [PATCH] Add proxy protocol tests --- Makefile | 3 +- integration/fixtures/proxy-protocol/with.toml | 24 ++++++++ .../fixtures/proxy-protocol/without.toml | 24 ++++++++ integration/integration_test.go | 51 +++++++++------- integration/proxy_protocol_test.go | 59 +++++++++++++++++++ .../resources/compose/proxy-protocol.yml | 7 +++ integration/resources/haproxy/haproxy.cfg | 21 +++++++ script/test-integration | 11 +++- 8 files changed, 177 insertions(+), 23 deletions(-) create mode 100644 integration/fixtures/proxy-protocol/with.toml create mode 100644 integration/fixtures/proxy-protocol/without.toml create mode 100644 integration/proxy_protocol_test.go create mode 100644 integration/resources/compose/proxy-protocol.yml create mode 100644 integration/resources/haproxy/haproxy.cfg diff --git a/Makefile b/Makefile index c5480376a..8a8835e76 100644 --- a/Makefile +++ b/Makefile @@ -20,7 +20,7 @@ GIT_BRANCH := $(subst heads/,,$(shell git rev-parse --abbrev-ref HEAD 2>/dev/nul TRAEFIK_DEV_IMAGE := traefik-dev$(if $(GIT_BRANCH),:$(subst /,-,$(GIT_BRANCH))) REPONAME := $(shell echo $(REPO) | tr '[:upper:]' '[:lower:]') TRAEFIK_IMAGE := $(if $(REPONAME),$(REPONAME),"containous/traefik") -INTEGRATION_OPTS := $(if $(MAKE_DOCKER_HOST),-e "DOCKER_HOST=$(MAKE_DOCKER_HOST)", -v "/var/run/docker.sock:/var/run/docker.sock") +INTEGRATION_OPTS := $(if $(MAKE_DOCKER_HOST),-e "DOCKER_HOST=$(MAKE_DOCKER_HOST)", -e "TEST_CONTAINER=1" -v "/var/run/docker.sock:/var/run/docker.sock") TRAEFIK_DOC_IMAGE := traefik-docs DOCKER_BUILD_ARGS := $(if $(DOCKER_VERSION), "--build-arg=DOCKER_VERSION=$(DOCKER_VERSION)",) @@ -71,6 +71,7 @@ test-unit: build ## run the unit tests test-integration: build ## run the integration tests $(DOCKER_RUN_TRAEFIK) ./script/make.sh generate binary test-integration + TEST_HOST=1 ./script/make.sh test-integration validate: build ## validate gofmt, golint and go vet $(DOCKER_RUN_TRAEFIK) ./script/make.sh validate-glide validate-gofmt validate-govet validate-golint validate-misspell validate-vendor diff --git a/integration/fixtures/proxy-protocol/with.toml b/integration/fixtures/proxy-protocol/with.toml new file mode 100644 index 000000000..68f813994 --- /dev/null +++ b/integration/fixtures/proxy-protocol/with.toml @@ -0,0 +1,24 @@ +logLevel = "DEBUG" +defaultEntryPoints = ["http"] + +[entryPoints] +[entryPoints.http] +address = ":8000" +[entryPoints.http.proxyProtocol] +trustedIPs = ["{{.HaproxyIP}}"] + +[web] +address = ":8080" + +[file] + +[backends] +[backends.backend1] +[backends.backend1.servers.server1] +url = "http://{{.WhoamiIP}}" + +[frontends] +[frontends.frontend1] +backend = "backend1" +[frontends.frontend1.routes.test_1] +rule = "Path:/whoami" diff --git a/integration/fixtures/proxy-protocol/without.toml b/integration/fixtures/proxy-protocol/without.toml new file mode 100644 index 000000000..3188c64f7 --- /dev/null +++ b/integration/fixtures/proxy-protocol/without.toml @@ -0,0 +1,24 @@ +logLevel = "DEBUG" +defaultEntryPoints = ["http"] + +[entryPoints] +[entryPoints.http] +address = ":8000" +[entryPoints.http.proxyProtocol] +trustedIPs = ["1.2.3.4"] + +[web] +address = ":8080" + +[file] + +[backends] +[backends.backend1] +[backends.backend1.servers.server1] +url = "http://{{.WhoamiIP}}" + +[frontends] +[frontends.frontend1] +backend = "backend1" +[frontends.frontend1.routes.test_1] +rule = "Path:/whoami" diff --git a/integration/integration_test.go b/integration/integration_test.go index 3fe1f0bda..9773a93ce 100644 --- a/integration/integration_test.go +++ b/integration/integration_test.go @@ -20,6 +20,8 @@ import ( ) var integration = flag.Bool("integration", false, "run integration tests") +var container = flag.Bool("container", false, "run container integration tests") +var host = flag.Bool("host", false, "run host integration tests") func Test(t *testing.T) { check.TestingT(t) @@ -32,27 +34,34 @@ func init() { return } - check.Suite(&AccessLogSuite{}) - check.Suite(&AcmeSuite{}) - check.Suite(&ConstraintSuite{}) - check.Suite(&ConsulCatalogSuite{}) - check.Suite(&ConsulSuite{}) - check.Suite(&DockerSuite{}) - check.Suite(&DynamoDBSuite{}) - check.Suite(&ErrorPagesSuite{}) - check.Suite(&EtcdSuite{}) - check.Suite(&EurekaSuite{}) - check.Suite(&FileSuite{}) - check.Suite(&GRPCSuite{}) - check.Suite(&HealthCheckSuite{}) - check.Suite(&HTTPSSuite{}) - check.Suite(&LogRotationSuite{}) - check.Suite(&MarathonSuite{}) - check.Suite(&MesosSuite{}) - check.Suite(&RateLimitSuite{}) - check.Suite(&SimpleSuite{}) - check.Suite(&TimeoutSuite{}) - check.Suite(&WebsocketSuite{}) + if *container { + // tests launched from a container + check.Suite(&AccessLogSuite{}) + check.Suite(&AcmeSuite{}) + check.Suite(&ConstraintSuite{}) + check.Suite(&ConsulCatalogSuite{}) + check.Suite(&ConsulSuite{}) + check.Suite(&DockerSuite{}) + check.Suite(&DynamoDBSuite{}) + check.Suite(&ErrorPagesSuite{}) + check.Suite(&EtcdSuite{}) + check.Suite(&EurekaSuite{}) + check.Suite(&FileSuite{}) + check.Suite(&GRPCSuite{}) + check.Suite(&HealthCheckSuite{}) + check.Suite(&HTTPSSuite{}) + check.Suite(&LogRotationSuite{}) + check.Suite(&MarathonSuite{}) + check.Suite(&MesosSuite{}) + check.Suite(&RateLimitSuite{}) + check.Suite(&SimpleSuite{}) + check.Suite(&TimeoutSuite{}) + check.Suite(&WebsocketSuite{}) + } + if *host { + // tests launched from the host + check.Suite(&ProxyProtocolSuite{}) + } } var traefikBinary = "../dist/traefik" diff --git a/integration/proxy_protocol_test.go b/integration/proxy_protocol_test.go new file mode 100644 index 000000000..66d5c93c5 --- /dev/null +++ b/integration/proxy_protocol_test.go @@ -0,0 +1,59 @@ +package integration + +import ( + "net/http" + "os" + "time" + + "github.com/containous/traefik/integration/try" + "github.com/go-check/check" + checker "github.com/vdemeester/shakers" +) + +type ProxyProtocolSuite struct{ BaseSuite } + +func (s *ProxyProtocolSuite) SetUpSuite(c *check.C) { + s.createComposeProject(c, "proxy-protocol") + s.composeProject.Start(c) +} + +func (s *ProxyProtocolSuite) TestProxyProtocolTrusted(c *check.C) { + gatewayIP := s.composeProject.Container(c, "haproxy").NetworkSettings.Gateway + haproxyIP := s.composeProject.Container(c, "haproxy").NetworkSettings.IPAddress + whoamiIP := s.composeProject.Container(c, "whoami").NetworkSettings.IPAddress + file := s.adaptFile(c, "fixtures/proxy-protocol/with.toml", struct { + HaproxyIP string + WhoamiIP string + }{haproxyIP, whoamiIP}) + defer os.Remove(file) + + cmd, display := s.traefikCmd(withConfigFile(file)) + defer display(c) + err := cmd.Start() + c.Assert(err, checker.IsNil) + defer cmd.Process.Kill() + + err = try.GetRequest("http://"+haproxyIP+"/whoami", 500*time.Millisecond, try.StatusCodeIs(http.StatusOK), try.BodyContains("X-Forwarded-For: "+gatewayIP)) + display(c) + c.Assert(err, checker.IsNil) +} + +func (s *ProxyProtocolSuite) TestProxyProtocolNotTrusted(c *check.C) { + haproxyIP := s.composeProject.Container(c, "haproxy").NetworkSettings.IPAddress + whoamiIP := s.composeProject.Container(c, "whoami").NetworkSettings.IPAddress + file := s.adaptFile(c, "fixtures/proxy-protocol/without.toml", struct { + HaproxyIP string + WhoamiIP string + }{haproxyIP, whoamiIP}) + defer os.Remove(file) + + cmd, display := s.traefikCmd(withConfigFile(file)) + defer display(c) + err := cmd.Start() + c.Assert(err, checker.IsNil) + defer cmd.Process.Kill() + + err = try.GetRequest("http://"+haproxyIP+"/whoami", 500*time.Millisecond, try.StatusCodeIs(http.StatusOK), try.BodyContains("X-Forwarded-For: "+haproxyIP)) + display(c) + c.Assert(err, checker.IsNil) +} diff --git a/integration/resources/compose/proxy-protocol.yml b/integration/resources/compose/proxy-protocol.yml new file mode 100644 index 000000000..de8cca8bb --- /dev/null +++ b/integration/resources/compose/proxy-protocol.yml @@ -0,0 +1,7 @@ +haproxy: + image: haproxy + volumes: + - ../haproxy/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg + +whoami: + image: emilevauge/whoami diff --git a/integration/resources/haproxy/haproxy.cfg b/integration/resources/haproxy/haproxy.cfg new file mode 100644 index 000000000..de649591c --- /dev/null +++ b/integration/resources/haproxy/haproxy.cfg @@ -0,0 +1,21 @@ +global + maxconn 4096 + +defaults + log global + mode http + retries 3 + option redispatch + maxconn 2000 + timeout connect 5000 + timeout client 50000 + timeout server 50000 + +frontend TestServerTest + bind 0.0.0.0:80 + mode tcp + default_backend TestServerNodes + +backend TestServerNodes + mode tcp + server TestServer01 172.17.0.1:8000 send-proxy \ No newline at end of file diff --git a/script/test-integration b/script/test-integration index 8245c821f..95d32af32 100755 --- a/script/test-integration +++ b/script/test-integration @@ -13,4 +13,13 @@ fi cd integration echo "Testing against…" docker version -CGO_ENABLED=0 go test -integration $TESTFLAGS + +if [ -n "$TEST_CONTAINER" ]; then +echo "Testing from container…" +CGO_ENABLED=0 go test -integration -container $TESTFLAGS +fi + +if [ -n "$TEST_HOST" ]; then +echo "Testing from host…" +CGO_ENABLED=0 go test -integration -host $TESTFLAGS +fi \ No newline at end of file