Skip to content

Commit

Permalink
Add ACME/Let’s Encrypt integration tests
Browse files Browse the repository at this point in the history
Thx @gwallet for the help.
  • Loading branch information
trecloux committed Dec 22, 2016
1 parent e1ed8b7 commit 599c95e
Show file tree
Hide file tree
Showing 4 changed files with 182 additions and 0 deletions.
92 changes: 92 additions & 0 deletions integration/acme_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package main

import (
"crypto/tls"
"net/http"
"os"
"os/exec"
"time"

"github.com/go-check/check"

"errors"
"github.com/containous/traefik/integration/utils"
checker "github.com/vdemeester/shakers"
)

// ACME test suites (using libcompose)
type AcmeSuite struct {
BaseSuite
}

func (s *AcmeSuite) SetUpSuite(c *check.C) {
s.createComposeProject(c, "boulder")
s.composeProject.Start(c)

boulderHost := s.composeProject.Container(c, "boulder").NetworkSettings.IPAddress

// wait for boulder
err := utils.Try(120*time.Second, func() error {
resp, err := http.Get("http://" + boulderHost + ":4000/directory")
if err != nil {
return err
}
if resp.StatusCode != 200 {
return errors.New("Expected http 200 from boulder")
}
return nil
})

c.Assert(err, checker.IsNil)
}

func (s *AcmeSuite) TearDownSuite(c *check.C) {
// shutdown and delete compose project
if s.composeProject != nil {
s.composeProject.Stop(c)
}
}

func (s *AcmeSuite) TestRetrieveAcmeCertificate(c *check.C) {
boulderHost := s.composeProject.Container(c, "boulder").NetworkSettings.IPAddress
file := s.adaptFile(c, "fixtures/acme/acme.toml", struct{ BoulderHost string }{boulderHost})
defer os.Remove(file)
cmd := exec.Command(traefikBinary, "--configFile="+file)
err := cmd.Start()
c.Assert(err, checker.IsNil)
defer cmd.Process.Kill()

backend := startTestServer("9010", 200)
defer backend.Close()

tr := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
client := &http.Client{Transport: tr}

// wait for traefik (generating acme account take some seconds)
err = utils.Try(30*time.Second, func() error {
_, err := client.Get("https://127.0.0.1:5001")
if err != nil {
return err
}
return nil
})
c.Assert(err, checker.IsNil)

tr = &http.Transport{
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
ServerName: "traefik.acme.wtf",
},
}
client = &http.Client{Transport: tr}
req, _ := http.NewRequest("GET", "https://127.0.0.1:5001/", nil)
req.Host = "traefik.acme.wtf"
req.Header.Set("Host", "traefik.acme.wtf")
req.Header.Set("Accept", "*/*")
resp, err := client.Do(req)
c.Assert(err, checker.IsNil)
// Expected a 200
c.Assert(resp.StatusCode, checker.Equals, 200)
}
32 changes: 32 additions & 0 deletions integration/fixtures/acme/acme.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
logLevel = "DEBUG"

defaultEntryPoints = ["http", "https"]

[entryPoints]
[entryPoints.http]
address = ":8080"
[entryPoints.https]
address = ":5001"
[entryPoints.https.tls]


[acme]
email = "test@traefik.io"
storage = "/dev/null"
entryPoint = "https"
onDemand = true
caServer = "http://{{.BoulderHost}}:4000/directory"

[file]

[backends]
[backends.backend]
[backends.backend.servers.server1]
url = "http://127.0.0.1:9010"


[frontends]
[frontends.frontend]
backend = "backend"
[frontends.frontend.routes.test]
rule = "Host:traefik.acme.wtf"
14 changes: 14 additions & 0 deletions integration/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ package main
import (
"fmt"
"io/ioutil"
"net"
"os"
"os/exec"
"path/filepath"
Expand Down Expand Up @@ -34,6 +35,7 @@ func init() {
check.Suite(&ConstraintSuite{})
check.Suite(&MesosSuite{})
check.Suite(&EurekaSuite{})
check.Suite(&AcmeSuite{})
}

var traefikBinary = "../dist/traefik"
Expand All @@ -52,6 +54,18 @@ func (s *BaseSuite) TearDownSuite(c *check.C) {
func (s *BaseSuite) createComposeProject(c *check.C, name string) {
projectName := fmt.Sprintf("integration-test-%s", name)
composeFile := fmt.Sprintf("resources/compose/%s.yml", name)

addrs, err := net.InterfaceAddrs()
c.Assert(err, checker.IsNil)
for _, addr := range addrs {
ip, _, err := net.ParseCIDR(addr.String())
c.Assert(err, checker.IsNil)
if !ip.IsLoopback() && ip.To4() != nil {
os.Setenv("DOCKER_HOST_IP", ip.String())
break
}
}

s.composeProject = compose.CreateProject(c, projectName, composeFile)
}

Expand Down
44 changes: 44 additions & 0 deletions integration/resources/compose/boulder.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
boulder:
image: containous/boulder:release
environment:
FAKE_DNS: ${DOCKER_HOST_IP}
PKCS11_PROXY_SOCKET: tcp://boulder-hsm:5657
extra_hosts:
- le.wtf:127.0.0.1
- boulder:127.0.0.1
ports:
- 4000:4000 # ACME
- 4002:4002 # OCSP
- 4003:4003 # OCSP
- 4500:4500 # ct-test-srv
- 8000:8000 # debug ports
- 8001:8001
- 8002:8002
- 8003:8003
- 8004:8004
- 8055:8055 # dns-test-srv updates
- 9380:9380 # mail-test-srv
- 9381:9381 # mail-test-srv
links:
- bhsm:boulder-hsm
- bmysql:boulder-mysql
- brabbitmq:boulder-rabbitmq

bhsm:
# To minimize the fetching of various layers this should match
# the FROM image and tag in boulder/Dockerfile
image: letsencrypt/boulder-tools:2016-11-02
environment:
PKCS11_DAEMON_SOCKET: tcp://0.0.0.0:5657
command: /usr/local/bin/pkcs11-daemon /usr/lib/softhsm/libsofthsm.so
expose:
- 5657
bmysql:
image: mariadb:10.1
environment:
MYSQL_ALLOW_EMPTY_PASSWORD: "yes"
log_driver: none
brabbitmq:
image: rabbitmq:3
environment:
RABBITMQ_NODE_IP_ADDRESS: "0.0.0.0"

0 comments on commit 599c95e

Please sign in to comment.