cloudflare/cloudflared

Public

mirrored from https://github.com/cloudflare/cloudflaredAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
d50fee4fa0ea358952a83798af3400c5757dff21

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

origin/supervisor_test.go

165lines · modecode

1package origin
2
3import (
4 "context"
5 "errors"
6 "fmt"
7 "testing"
8 "time"
9
10 "github.com/google/uuid"
11 "github.com/prometheus/client_golang/prometheus"
12 "github.com/sirupsen/logrus"
13 "github.com/stretchr/testify/assert"
14
15 tunnelpogs "github.com/cloudflare/cloudflared/tunnelrpc/pogs"
16)
17
18func testConfig(logger *logrus.Logger) *TunnelConfig {
19 metrics := TunnelMetrics{}
20
21 metrics.authSuccess = prometheus.NewCounter(
22 prometheus.CounterOpts{
23 Namespace: metricsNamespace,
24 Subsystem: tunnelSubsystem,
25 Name: "tunnel_authenticate_success",
26 Help: "Count of successful tunnel authenticate",
27 },
28 )
29
30 metrics.authFail = prometheus.NewCounterVec(
31 prometheus.CounterOpts{
32 Namespace: metricsNamespace,
33 Subsystem: tunnelSubsystem,
34 Name: "tunnel_authenticate_fail",
35 Help: "Count of tunnel authenticate errors by type",
36 },
37 []string{"error"},
38 )
39 return &TunnelConfig{Logger: logger, Metrics: &metrics}
40}
41
42func TestRefreshAuthBackoff(t *testing.T) {
43 logger := logrus.New()
44 logger.Level = logrus.ErrorLevel
45
46 var wait time.Duration
47 timeAfter = func(d time.Duration) <-chan time.Time {
48 wait = d
49 return time.After(d)
50 }
51
52 s, err := NewSupervisor(testConfig(logger), uuid.New())
53 if !assert.NoError(t, err) {
54 t.FailNow()
55 }
56 backoff := &BackoffHandler{MaxRetries: 3}
57 auth := func(ctx context.Context, n int) (tunnelpogs.AuthOutcome, error) {
58 return nil, fmt.Errorf("authentication failure")
59 }
60
61 // authentication failures should consume the backoff
62 for i := uint(0); i < backoff.MaxRetries; i++ {
63 retryChan, err := s.refreshAuth(context.Background(), backoff, auth)
64 assert.NoError(t, err)
65 assert.NotNil(t, retryChan)
66 assert.Equal(t, (1<<i)*time.Second, wait)
67 }
68 retryChan, err := s.refreshAuth(context.Background(), backoff, auth)
69 assert.Error(t, err)
70 assert.Nil(t, retryChan)
71
72 // now we actually make contact with the remote server
73 _, _ = s.refreshAuth(context.Background(), backoff, func(ctx context.Context, n int) (tunnelpogs.AuthOutcome, error) {
74 return tunnelpogs.NewAuthUnknown(errors.New("auth unknown"), 19), nil
75 })
76
77 // The backoff timer should have been reset. To confirm this, make timeNow
78 // return a value after the backoff timer's grace period
79 timeNow = func() time.Time {
80 expectedGracePeriod := time.Duration(time.Second * 2 << backoff.MaxRetries)
81 return time.Now().Add(expectedGracePeriod * 2)
82 }
83 _, ok := backoff.GetBackoffDuration(context.Background())
84 assert.True(t, ok)
85}
86
87func TestRefreshAuthSuccess(t *testing.T) {
88 logger := logrus.New()
89 logger.Level = logrus.ErrorLevel
90
91 var wait time.Duration
92 timeAfter = func(d time.Duration) <-chan time.Time {
93 wait = d
94 return time.After(d)
95 }
96
97 s, err := NewSupervisor(testConfig(logger), uuid.New())
98 if !assert.NoError(t, err) {
99 t.FailNow()
100 }
101 backoff := &BackoffHandler{MaxRetries: 3}
102 auth := func(ctx context.Context, n int) (tunnelpogs.AuthOutcome, error) {
103 return tunnelpogs.NewAuthSuccess([]byte("jwt"), 19), nil
104 }
105
106 retryChan, err := s.refreshAuth(context.Background(), backoff, auth)
107 assert.NoError(t, err)
108 assert.NotNil(t, retryChan)
109 assert.Equal(t, 19*time.Hour, wait)
110
111 token, err := s.ReconnectToken()
112 assert.NoError(t, err)
113 assert.Equal(t, []byte("jwt"), token)
114}
115
116func TestRefreshAuthUnknown(t *testing.T) {
117 logger := logrus.New()
118 logger.Level = logrus.ErrorLevel
119
120 var wait time.Duration
121 timeAfter = func(d time.Duration) <-chan time.Time {
122 wait = d
123 return time.After(d)
124 }
125
126 s, err := NewSupervisor(testConfig(logger), uuid.New())
127 if !assert.NoError(t, err) {
128 t.FailNow()
129 }
130 backoff := &BackoffHandler{MaxRetries: 3}
131 auth := func(ctx context.Context, n int) (tunnelpogs.AuthOutcome, error) {
132 return tunnelpogs.NewAuthUnknown(errors.New("auth unknown"), 19), nil
133 }
134
135 retryChan, err := s.refreshAuth(context.Background(), backoff, auth)
136 assert.NoError(t, err)
137 assert.NotNil(t, retryChan)
138 assert.Equal(t, 19*time.Hour, wait)
139
140 token, err := s.ReconnectToken()
141 assert.Equal(t, errJWTUnset, err)
142 assert.Nil(t, token)
143}
144
145func TestRefreshAuthFail(t *testing.T) {
146 logger := logrus.New()
147 logger.Level = logrus.ErrorLevel
148
149 s, err := NewSupervisor(testConfig(logger), uuid.New())
150 if !assert.NoError(t, err) {
151 t.FailNow()
152 }
153 backoff := &BackoffHandler{MaxRetries: 3}
154 auth := func(ctx context.Context, n int) (tunnelpogs.AuthOutcome, error) {
155 return tunnelpogs.NewAuthFail(errors.New("auth fail")), nil
156 }
157
158 retryChan, err := s.refreshAuth(context.Background(), backoff, auth)
159 assert.Error(t, err)
160 assert.Nil(t, retryChan)
161
162 token, err := s.ReconnectToken()
163 assert.Equal(t, errJWTUnset, err)
164 assert.Nil(t, token)
165}
166