Skip to content

Commit

Permalink
Merge branch 'master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
rohitsakala committed Feb 7, 2022
2 parents d2a06a6 + 5780dc2 commit 70e734b
Show file tree
Hide file tree
Showing 15 changed files with 855 additions and 225 deletions.
4 changes: 1 addition & 3 deletions cmd/traefik/traefik.go
Original file line number Diff line number Diff line change
Expand Up @@ -180,8 +180,7 @@ func setupServer(staticConfiguration *static.Configuration) (*server.Server, err
tlsManager := traefiktls.NewManager()
httpChallengeProvider := acme.NewChallengeHTTP()

// we need to wait at least 2 times the ProvidersThrottleDuration to be sure to handle the challenge.
tlsChallengeProvider := acme.NewChallengeTLSALPN(time.Duration(staticConfiguration.Providers.ProvidersThrottleDuration) * 2)
tlsChallengeProvider := acme.NewChallengeTLSALPN()
err = providerAggregator.AddProvider(tlsChallengeProvider)
if err != nil {
return nil, err
Expand Down Expand Up @@ -265,7 +264,6 @@ func setupServer(staticConfiguration *static.Configuration) (*server.Server, err
watcher := server.NewConfigurationWatcher(
routinesPool,
providerAggregator,
time.Duration(staticConfiguration.Providers.ProvidersThrottleDuration),
getDefaultsEntrypoints(staticConfiguration),
"internal",
)
Expand Down
1 change: 0 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ require (
github.com/docker/docker v20.10.7+incompatible
github.com/docker/go-connections v0.4.0
github.com/donovanhide/eventsource v0.0.0-20170630084216-b8f31a59085e // indirect
github.com/eapache/channels v1.1.0
github.com/fatih/structs v1.1.0
github.com/gambol99/go-marathon v0.0.0-20180614232016-99a156b96fb2
github.com/go-acme/lego/v4 v4.6.0
Expand Down
2 changes: 0 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -550,8 +550,6 @@ github.com/donovanhide/eventsource v0.0.0-20170630084216-b8f31a59085e h1:rMOGp6H
github.com/donovanhide/eventsource v0.0.0-20170630084216-b8f31a59085e/go.mod h1:56wL82FO0bfMU5RvfXoIwSOP2ggqqxT+tAfNEIyxuHw=
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/eapache/channels v1.1.0 h1:F1taHcn7/F0i8DYqKXJnyhJcVpp2kgFcNePxXtnyu4k=
github.com/eapache/channels v1.1.0/go.mod h1:jMm2qB5Ubtg9zLd+inMZd2/NUvXgzmWXsDaLyQIGfH0=
github.com/eapache/go-resiliency v1.1.0 h1:1NtRmCAqadE2FN4ZcN6g90TP3uk8cg9rn9eNK2197aU=
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21 h1:YEetp8/yCZMuEPMUDHG0CW/brkkEp8mzqk2+ODEitlw=
Expand Down
30 changes: 14 additions & 16 deletions integration/acme_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -446,26 +446,28 @@ func (s *AcmeSuite) retrieveAcmeCertificate(c *check.C, testCase acmeTestCase) {
backend := startTestServer("9010", http.StatusOK, "")
defer backend.Close()

for _, sub := range testCase.subCases {
client := &http.Client{
Transport: &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
},
}
client := &http.Client{
Transport: &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
},
}

// wait for traefik (generating acme account take some seconds)
err = try.Do(60*time.Second, func() error {
_, errGet := client.Get("https://127.0.0.1:5001")
return errGet
})
c.Assert(err, checker.IsNil)
// wait for traefik (generating acme account take some seconds)
err = try.Do(60*time.Second, func() error {
_, errGet := client.Get("https://127.0.0.1:5001")
return errGet
})
c.Assert(err, checker.IsNil)

for _, sub := range testCase.subCases {
client = &http.Client{
Transport: &http.Transport{
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
ServerName: sub.host,
},
// Needed so that each subcase redoes the SSL handshake
DisableKeepAlives: true,
},
}

Expand All @@ -479,10 +481,6 @@ func (s *AcmeSuite) retrieveAcmeCertificate(c *check.C, testCase acmeTestCase) {
// Retry to send a Request which uses the LE generated certificate
err = try.Do(60*time.Second, func() error {
resp, err = client.Do(req)

// /!\ If connection is not closed, SSLHandshake will only be done during the first trial /!\
req.Close = true

if err != nil {
return err
}
Expand Down
105 changes: 105 additions & 0 deletions integration/conf_throttling_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
package integration

import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"regexp"
"strconv"
"time"

"github.com/go-check/check"
"github.com/traefik/traefik/v2/integration/try"
"github.com/traefik/traefik/v2/pkg/config/dynamic"
checker "github.com/vdemeester/shakers"
)

type ThrottlingSuite struct{ BaseSuite }

func (s *ThrottlingSuite) SetUpSuite(c *check.C) {
s.createComposeProject(c, "rest")
s.composeUp(c)
}

func (s *ThrottlingSuite) TestThrottleConfReload(c *check.C) {
cmd, display := s.traefikCmd(withConfigFile("fixtures/throttling/simple.toml"))

defer display(c)
err := cmd.Start()
c.Assert(err, checker.IsNil)
defer s.killCmd(cmd)

// wait for Traefik
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 1000*time.Millisecond, try.BodyContains("rest@internal"))
c.Assert(err, checker.IsNil)

// Expected a 404 as we did not configure anything.
err = try.GetRequest("http://127.0.0.1:8000/", 1000*time.Millisecond, try.StatusCodeIs(http.StatusNotFound))
c.Assert(err, checker.IsNil)

config := &dynamic.Configuration{
HTTP: &dynamic.HTTPConfiguration{
Routers: map[string]*dynamic.Router{},
Services: map[string]*dynamic.Service{
"serviceHTTP": {
LoadBalancer: &dynamic.ServersLoadBalancer{
Servers: []dynamic.Server{
{
URL: "http://" + s.getComposeServiceIP(c, "whoami1") + ":80",
},
},
},
},
},
},
}

router := &dynamic.Router{
EntryPoints: []string{"web"},
Middlewares: []string{},
Service: "serviceHTTP",
Rule: "PathPrefix(`/`)",
}

confChanges := 10

for i := 0; i < confChanges; i++ {
config.HTTP.Routers[fmt.Sprintf("routerHTTP%d", i)] = router
data, err := json.Marshal(config)
c.Assert(err, checker.IsNil)

request, err := http.NewRequest(http.MethodPut, "http://127.0.0.1:8080/api/providers/rest", bytes.NewReader(data))
c.Assert(err, checker.IsNil)

response, err := http.DefaultClient.Do(request)
c.Assert(err, checker.IsNil)
c.Assert(response.StatusCode, checker.Equals, http.StatusOK)
time.Sleep(200 * time.Millisecond)
}

reloadsRegexp := regexp.MustCompile(`traefik_config_reloads_total (\d*)\n`)

resp, err := http.Get("http://127.0.0.1:8080/metrics")
c.Assert(err, checker.IsNil)
defer resp.Body.Close()

body, err := io.ReadAll(resp.Body)
c.Assert(err, checker.IsNil)

fields := reloadsRegexp.FindStringSubmatch(string(body))
c.Assert(len(fields), checker.Equals, 2)

reloads, err := strconv.Atoi(fields[1])
if err != nil {
panic(err)
}

// The test tries to trigger a config reload with the REST API every 200ms,
// 10 times (so for 2s in total).
// Therefore the throttling (set at 400ms for this test) should only let
// (2s / 400 ms =) 5 config reloads happen in theory.
// In addition, we have to take into account the extra config reload from the internal provider (5 + 1).
c.Assert(reloads, checker.LessOrEqualThan, 6)
}
22 changes: 22 additions & 0 deletions integration/fixtures/throttling/simple.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
[global]
checkNewVersion = false
sendAnonymousUsage = false

[log]
level = "DEBUG"

[entryPoints]
[entryPoints.web]
address = ":8000"

[api]
insecure = true

[providers]
providersThrottleDuration = "400ms"
[providers.rest]
insecure = true

[metrics]
[metrics.prometheus]
buckets = [0.1,0.3,1.2,5.0]
1 change: 1 addition & 0 deletions integration/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ func Test(t *testing.T) {
check.Suite(&SimpleSuite{})
check.Suite(&TCPSuite{})
check.Suite(&TimeoutSuite{})
check.Suite(&ThrottlingSuite{})
check.Suite(&TLSClientHeadersSuite{})
check.Suite(&TracingSuite{})
check.Suite(&UDPSuite{})
Expand Down
21 changes: 12 additions & 9 deletions pkg/provider/acme/challenge_tls.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@ const providerNameALPN = "tlsalpn.acme"

// ChallengeTLSALPN TLSALPN challenge provider implements challenge.Provider.
type ChallengeTLSALPN struct {
Timeout time.Duration

chans map[string]chan struct{}
muChans sync.Mutex

Expand All @@ -29,11 +27,10 @@ type ChallengeTLSALPN struct {
}

// NewChallengeTLSALPN creates a new ChallengeTLSALPN.
func NewChallengeTLSALPN(timeout time.Duration) *ChallengeTLSALPN {
func NewChallengeTLSALPN() *ChallengeTLSALPN {
return &ChallengeTLSALPN{
Timeout: timeout,
chans: make(map[string]chan struct{}),
certs: make(map[string]*Certificate),
chans: make(map[string]chan struct{}),
certs: make(map[string]*Certificate),
}
}

Expand Down Expand Up @@ -61,12 +58,13 @@ func (c *ChallengeTLSALPN) Present(domain, _, keyAuth string) error {

c.configurationChan <- conf

timer := time.NewTimer(c.Timeout)
// Present should return when its dynamic configuration has been received and applied by Traefik.
// The timer exists in case the above does not happen, to ensure the challenge cleanup.
timer := time.NewTimer(time.Minute)
defer timer.Stop()

select {
case t := <-timer.C:
timer.Stop()

c.muChans.Lock()
c.cleanChan(string(certPEMBlock))
c.muChans.Unlock()
Expand Down Expand Up @@ -103,6 +101,11 @@ func (c *ChallengeTLSALPN) Init() error {
return nil
}

// ThrottleDuration returns the throttle duration.
func (c *ChallengeTLSALPN) ThrottleDuration() time.Duration {
return 0
}

// Provide allows the provider to provide configurations to traefik using the given configuration channel.
func (c *ChallengeTLSALPN) Provide(configurationChan chan<- dynamic.Message, _ *safe.Pool) error {
c.configurationChan = configurationChan
Expand Down
5 changes: 5 additions & 0 deletions pkg/provider/acme/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,11 @@ func isAccountMatchingCaServer(ctx context.Context, accountURI, serverURI string
return cau.Hostname() == aru.Hostname()
}

// ThrottleDuration returns the throttle duration.
func (p *Provider) ThrottleDuration() time.Duration {
return 0
}

// Provide allows the file provider to provide configurations to traefik
// using the given Configuration channel.
func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe.Pool) error {
Expand Down

0 comments on commit 70e734b

Please sign in to comment.