cloudflare/cloudflared

Public

mirrored fromhttps://github.com/cloudflare/cloudflaredAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
2020.6.1

Branches

Tags

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

Clone

HTTPS

Download ZIP

dbconnect/proxy_test.go

238lines · modecode

1package dbconnect
2
3import (
4 "context"
5 "fmt"
6 "io"
7 "io/ioutil"
8 "net"
9 "net/http"
10 "net/http/httptest"
11 "strings"
12 "testing"
13
14 "github.com/gorilla/mux"
15
16 "github.com/stretchr/testify/assert"
17)
18
19func TestNewInsecureProxy(t *testing.T) {
20 origins := []string{
21 "",
22 ":/",
23 "http://localhost",
24 "tcp://localhost:9000?debug=true",
25 "mongodb://127.0.0.1",
26 }
27
28 for _, origin := range origins {
29 proxy, err := NewInsecureProxy(context.Background(), origin)
30
31 assert.Error(t, err)
32 assert.Empty(t, proxy)
33 }
34}
35
36func TestProxyIsAllowed(t *testing.T) {
37 proxy := helperNewProxy(t)
38 req := httptest.NewRequest("GET", "https://1.1.1.1/ping", nil)
39 assert.True(t, proxy.IsAllowed(req))
40
41 proxy = helperNewProxy(t, true)
42 req.Header.Set("Cf-access-jwt-assertion", "xxx")
43 assert.False(t, proxy.IsAllowed(req))
44}
45
46func TestProxyStart(t *testing.T) {
47 proxy := helperNewProxy(t)
48 ctx := context.Background()
49 listenerC := make(chan net.Listener)
50
51 err := proxy.Start(ctx, "1.1.1.1:", listenerC)
52 assert.Error(t, err)
53
54 err = proxy.Start(ctx, "127.0.0.1:-1", listenerC)
55 assert.Error(t, err)
56
57 ctx, cancel := context.WithTimeout(ctx, 0)
58 defer cancel()
59
60 err = proxy.Start(ctx, "127.0.0.1:", listenerC)
61 assert.IsType(t, http.ErrServerClosed, err)
62}
63
64func TestProxyHTTPRouter(t *testing.T) {
65 proxy := helperNewProxy(t)
66 router := proxy.httpRouter()
67
68 tests := []struct {
69 path string
70 method string
71 valid bool
72 }{
73 {"", "GET", false},
74 {"/", "GET", false},
75 {"/ping", "GET", true},
76 {"/ping", "HEAD", true},
77 {"/ping", "POST", false},
78 {"/submit", "POST", true},
79 {"/submit", "GET", false},
80 {"/submit/extra", "POST", false},
81 }
82
83 for _, test := range tests {
84 match := &mux.RouteMatch{}
85 ok := router.Match(httptest.NewRequest(test.method, "https://1.1.1.1"+test.path, nil), match)
86
87 assert.True(t, ok == test.valid, test.path)
88 }
89}
90
91func TestProxyHTTPPing(t *testing.T) {
92 proxy := helperNewProxy(t)
93
94 server := httptest.NewServer(proxy.httpPing())
95 defer server.Close()
96 client := server.Client()
97
98 res, err := client.Get(server.URL)
99 assert.NoError(t, err)
100 assert.Equal(t, http.StatusOK, res.StatusCode)
101 assert.Equal(t, int64(2), res.ContentLength)
102
103 res, err = client.Head(server.URL)
104 assert.NoError(t, err)
105 assert.Equal(t, http.StatusOK, res.StatusCode)
106 assert.Equal(t, int64(-1), res.ContentLength)
107}
108
109func TestProxyHTTPSubmit(t *testing.T) {
110 proxy := helperNewProxy(t)
111
112 server := httptest.NewServer(proxy.httpSubmit())
113 defer server.Close()
114 client := server.Client()
115
116 tests := []struct {
117 input string
118 status int
119 output string
120 }{
121 {"", http.StatusBadRequest, "request body cannot be empty"},
122 {"{}", http.StatusBadRequest, "cannot provide an empty statement"},
123 {"{\"statement\":\"Ok\"}", http.StatusUnprocessableEntity, "cannot provide invalid sql mode: ''"},
124 {"{\"statement\":\"Ok\",\"mode\":\"query\"}", http.StatusUnprocessableEntity, "near \"Ok\": syntax error"},
125 {"{\"statement\":\"CREATE TABLE t (a INT);\",\"mode\":\"exec\"}", http.StatusOK, "{\"last_insert_id\":0,\"rows_affected\":0}\n"},
126 }
127
128 for _, test := range tests {
129 res, err := client.Post(server.URL, "application/json", strings.NewReader(test.input))
130
131 assert.NoError(t, err)
132 assert.Equal(t, test.status, res.StatusCode)
133 if res.StatusCode > http.StatusOK {
134 assert.Equal(t, "text/plain; charset=utf-8", res.Header.Get("Content-type"))
135 } else {
136 assert.Equal(t, "application/json", res.Header.Get("Content-type"))
137 }
138
139 data, err := ioutil.ReadAll(res.Body)
140 defer res.Body.Close()
141 str := string(data)
142
143 assert.NoError(t, err)
144 assert.Equal(t, test.output, str)
145 }
146}
147
148func TestProxyHTTPSubmitForbidden(t *testing.T) {
149 proxy := helperNewProxy(t, true)
150
151 server := httptest.NewServer(proxy.httpSubmit())
152 defer server.Close()
153 client := server.Client()
154
155 res, err := client.Get(server.URL)
156
157 assert.NoError(t, err)
158 assert.Equal(t, http.StatusForbidden, res.StatusCode)
159 assert.Zero(t, res.ContentLength)
160}
161
162func TestProxyHTTPRespond(t *testing.T) {
163 proxy := helperNewProxy(t)
164
165 server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
166 proxy.httpRespond(w, r, http.StatusAccepted, "Hello")
167 }))
168 defer server.Close()
169 client := server.Client()
170
171 res, err := client.Get(server.URL)
172 assert.NoError(t, err)
173 assert.Equal(t, http.StatusAccepted, res.StatusCode)
174 assert.Equal(t, int64(5), res.ContentLength)
175
176 data, err := ioutil.ReadAll(res.Body)
177 defer res.Body.Close()
178 assert.Equal(t, []byte("Hello"), data)
179}
180
181func TestProxyHTTPRespondForbidden(t *testing.T) {
182 proxy := helperNewProxy(t, true)
183
184 server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
185 proxy.httpRespond(w, r, http.StatusAccepted, "Hello")
186 }))
187 defer server.Close()
188 client := server.Client()
189
190 res, err := client.Get(server.URL)
191
192 assert.NoError(t, err)
193 assert.Equal(t, http.StatusAccepted, res.StatusCode)
194 assert.Equal(t, int64(0), res.ContentLength)
195}
196
197func TestHTTPError(t *testing.T) {
198 _, errTimeout := net.DialTimeout("tcp", "127.0.0.1", 0)
199 assert.Error(t, errTimeout)
200
201 tests := []struct {
202 input error
203 status int
204 output error
205 }{
206 {nil, http.StatusNotImplemented, fmt.Errorf("error expected but found none")},
207 {io.EOF, http.StatusBadRequest, fmt.Errorf("request body cannot be empty")},
208 {context.DeadlineExceeded, http.StatusRequestTimeout, nil},
209 {context.Canceled, 444, nil},
210 {errTimeout, http.StatusRequestTimeout, nil},
211 {fmt.Errorf(""), http.StatusInternalServerError, nil},
212 }
213
214 for _, test := range tests {
215 status, err := httpError(http.StatusInternalServerError, test.input)
216
217 assert.Error(t, err)
218 assert.Equal(t, test.status, status)
219 if test.output == nil {
220 test.output = test.input
221 }
222 assert.Equal(t, test.output, err)
223 }
224}
225
226func helperNewProxy(t *testing.T, secure ...bool) *Proxy {
227 t.Helper()
228
229 proxy, err := NewSecureProxy(context.Background(), "file::memory:?cache=shared", "test.cloudflareaccess.com", "")
230 assert.NoError(t, err)
231 assert.NotNil(t, proxy)
232
233 if len(secure) == 0 {
234 proxy.accessValidator = nil // Mark as insecure
235 }
236
237 return proxy
238}
239