1 // Tests for Keep HTTP handlers:
7 // The HTTP handlers are responsible for enforcing permission policy,
8 // so these tests must exercise all possible permission permutations.
21 func TestGetHandler(t *testing.T) {
24 // Prepare two test Keep volumes. Our block is stored on the second volume.
25 KeepVM = MakeTestVolumeManager(2)
26 defer func() { KeepVM.Quit() }()
28 vols := KeepVM.Volumes()
29 if err := vols[0].Put(TEST_HASH, TEST_BLOCK); err != nil {
33 // Set up a REST router for testing the handlers.
34 rest := NewRESTRouter()
36 // Test an unsigned GET request.
37 test_url := "http://localhost:25107/" + TEST_HASH
38 req, _ := http.NewRequest("GET", test_url, nil)
39 resp := httptest.NewRecorder()
40 rest.ServeHTTP(resp, req)
43 t.Errorf("bad response code: %v", resp)
45 if bytes.Compare(resp.Body.Bytes(), TEST_BLOCK) != 0 {
46 t.Errorf("bad response body: %v", resp)
49 // Enable permissions.
50 enforce_permissions = true
51 PermissionSecret = []byte(known_key)
53 expiry := time.Now().Add(time.Duration(permission_ttl) * time.Second)
55 // Test GET with a signed locator.
56 test_url = "http://localhost:25107/" + SignLocator(TEST_HASH, known_token, expiry)
57 resp = httptest.NewRecorder()
58 req, _ = http.NewRequest("GET", test_url, nil)
59 req.Header.Set("Authorization", "OAuth "+known_token)
60 rest.ServeHTTP(resp, req)
63 t.Errorf("signed request: bad response code: %v", resp)
65 if bytes.Compare(resp.Body.Bytes(), TEST_BLOCK) != 0 {
66 t.Errorf("signed request: bad response body: %v", resp)
69 // Test GET with an unsigned locator.
70 test_url = "http://localhost:25107/" + TEST_HASH
71 resp = httptest.NewRecorder()
72 req, _ = http.NewRequest("GET", test_url, nil)
73 req.Header.Set("Authorization", "OAuth "+known_token)
74 rest.ServeHTTP(resp, req)
76 if resp.Code != PermissionError.HTTPCode {
77 t.Errorf("unsigned request: bad response code: %v", resp)
80 // Test GET with a signed locator and an unauthenticated request.
81 test_url = "http://localhost:25107/" + SignLocator(TEST_HASH, known_token, expiry)
82 resp = httptest.NewRecorder()
83 req, _ = http.NewRequest("GET", test_url, nil)
84 rest.ServeHTTP(resp, req)
86 if resp.Code != PermissionError.HTTPCode {
87 t.Errorf("signed locator, unauthenticated request: bad response code: %v", resp)
90 // Test GET with an expired, signed locator.
91 expired_ts := time.Now().Add(-time.Hour)
92 test_url = "http://localhost:25107/" + SignLocator(TEST_HASH, known_token, expired_ts)
93 resp = httptest.NewRecorder()
94 req, _ = http.NewRequest("GET", test_url, nil)
95 req.Header.Set("Authorization", "OAuth "+known_token)
96 rest.ServeHTTP(resp, req)
98 if resp.Code != ExpiredError.HTTPCode {
99 t.Errorf("expired signature: bad response code: %v", resp)
103 func TestPutHandler(t *testing.T) {
106 // Prepare two test Keep volumes.
107 KeepVM = MakeTestVolumeManager(2)
108 defer func() { KeepVM.Quit() }()
110 // Set up a REST router for testing the handlers.
111 rest := NewRESTRouter()
113 // Execute a PUT request.
114 test_url := "http://localhost:25107/" + TEST_HASH
115 test_body := bytes.NewReader(TEST_BLOCK)
116 req, _ := http.NewRequest("PUT", test_url, test_body)
117 resp := httptest.NewRecorder()
118 rest.ServeHTTP(resp, req)
120 if resp.Code != 200 {
121 t.Errorf("bad response code: %v", resp)
123 if resp.Body.String() != TEST_HASH {
124 t.Errorf("bad response body: %v", resp)
127 // Add a permission key.
128 // When a permission key is available, the locator returned
129 // from a PUT request will be signed.
130 PermissionSecret = []byte(known_key)
132 // An authenticated PUT request returns a signed locator.
133 test_url = "http://localhost:25107/" + TEST_HASH
134 test_body = bytes.NewReader(TEST_BLOCK)
135 req, _ = http.NewRequest("PUT", test_url, test_body)
136 req.Header.Set("Authorization", "OAuth "+known_token)
137 resp = httptest.NewRecorder()
138 rest.ServeHTTP(resp, req)
140 if resp.Code != 200 {
141 t.Errorf("bad response code: %v", resp)
143 if !VerifySignature(resp.Body.String(), known_token) {
144 t.Errorf("bad response body: %v", resp)
147 // An unauthenticated PUT request returns an unsigned locator
148 // even when a permission key is available.
149 test_url = "http://localhost:25107/" + TEST_HASH
150 test_body = bytes.NewReader(TEST_BLOCK)
151 req, _ = http.NewRequest("PUT", test_url, test_body)
152 resp = httptest.NewRecorder()
153 rest.ServeHTTP(resp, req)
155 if resp.Code != 200 {
156 t.Errorf("bad response code: %v", resp)
158 if resp.Body.String() != TEST_HASH {
159 t.Errorf("bad response body: %v", resp)
163 func TestIndexHandler(t *testing.T) {
166 // Set up Keep volumes and populate them.
167 // Include multiple blocks on different volumes, and
168 // some metadata files.
169 KeepVM = MakeTestVolumeManager(2)
170 defer func() { KeepVM.Quit() }()
172 vols := KeepVM.Volumes()
173 vols[0].Put(TEST_HASH, TEST_BLOCK)
174 vols[1].Put(TEST_HASH_2, TEST_BLOCK_2)
176 // Set up a REST router for testing the handlers.
177 rest := NewRESTRouter()
179 // Requests for /index with a prefix are okay even if unauthenticated.
180 test_url := "http://localhost:25107/index/" + TEST_HASH[0:5]
181 req, _ := http.NewRequest("GET", test_url, nil)
182 resp := httptest.NewRecorder()
183 rest.ServeHTTP(resp, req)
185 expected := `^` + TEST_HASH + `\+\d+ \d+\n$`
186 match, _ := regexp.MatchString(expected, resp.Body.String())
188 t.Errorf("IndexHandler returned:\n%s", resp.Body.String())
191 // Unauthenticated /index requests: fail.
192 test_url = "http://localhost:25107/index"
193 req, _ = http.NewRequest("GET", test_url, nil)
194 resp = httptest.NewRecorder()
195 rest.ServeHTTP(resp, req)
197 if resp.Code != PermissionError.HTTPCode {
198 t.Errorf("unauthenticated /index: %+v", resp)
201 // Authenticated /index requests by a non-superuser: also fail.
202 test_url = "http://localhost:25107/index"
203 req, _ = http.NewRequest("GET", test_url, nil)
204 req.Header.Set("Authorization", "OAuth "+known_token)
205 resp = httptest.NewRecorder()
206 rest.ServeHTTP(resp, req)
208 if resp.Code != PermissionError.HTTPCode {
209 t.Errorf("authenticated /index: %+v", resp)
212 // Even superuser /index requests fail if enforce_permissions is off!
213 enforce_permissions = false
214 data_manager_token = "DATA MANAGER TOKEN"
215 test_url = "http://localhost:25107/index"
216 req, _ = http.NewRequest("GET", test_url, nil)
217 req.Header.Set("Authorization", "OAuth "+data_manager_token)
218 resp = httptest.NewRecorder()
219 rest.ServeHTTP(resp, req)
221 if resp.Code != PermissionError.HTTPCode {
222 t.Errorf("superuser /index (permissions off): %+v", resp)
225 // Superuser /index requests with enforce_permissions set: succeed!
226 enforce_permissions = true
227 data_manager_token = "DATA MANAGER TOKEN"
228 test_url = "http://localhost:25107/index"
229 req, _ = http.NewRequest("GET", test_url, nil)
230 req.Header.Set("Authorization", "OAuth "+data_manager_token)
231 resp = httptest.NewRecorder()
232 rest.ServeHTTP(resp, req)
234 if resp.Code != http.StatusOK {
235 t.Errorf("superuser /index: %+v", resp)
237 expected = `^` + TEST_HASH + `\+\d+ \d+\n` +
238 TEST_HASH_2 + `\+\d+ \d+\n$`
239 match, _ = regexp.MatchString(expected, resp.Body.String())
241 t.Errorf("superuser /index:\n%s", resp.Body.String())