1 // Copyright (C) The Arvados Authors. All rights reserved.
3 // SPDX-License-Identifier: AGPL-3.0
18 "git.arvados.org/arvados.git/sdk/go/arvados"
19 "git.arvados.org/arvados.git/sdk/go/arvadostest"
20 check "gopkg.in/check.v1"
23 func (s *IntegrationSuite) TestCadaverHTTPAuth(c *check.C) {
24 s.testCadaver(c, arvadostest.ActiveToken, func(newCollection arvados.Collection) (string, string, string) {
25 r := "/c=" + arvadostest.FooAndBarFilesInDirUUID + "/"
26 w := "/c=" + newCollection.UUID + "/"
27 pdh := "/c=" + strings.Replace(arvadostest.FooAndBarFilesInDirPDH, "+", "-", -1) + "/"
32 func (s *IntegrationSuite) TestCadaverPathAuth(c *check.C) {
33 s.testCadaver(c, "", func(newCollection arvados.Collection) (string, string, string) {
34 r := "/c=" + arvadostest.FooAndBarFilesInDirUUID + "/t=" + arvadostest.ActiveToken + "/"
35 w := "/c=" + newCollection.UUID + "/t=" + arvadostest.ActiveToken + "/"
36 pdh := "/c=" + strings.Replace(arvadostest.FooAndBarFilesInDirPDH, "+", "-", -1) + "/t=" + arvadostest.ActiveToken + "/"
41 func (s *IntegrationSuite) TestCadaverUserProject(c *check.C) {
42 rpath := "/users/active/foo_file_in_dir/"
43 s.testCadaver(c, arvadostest.ActiveToken, func(newCollection arvados.Collection) (string, string, string) {
44 wpath := "/users/active/" + newCollection.Name
45 pdh := "/c=" + strings.Replace(arvadostest.FooAndBarFilesInDirPDH, "+", "-", -1) + "/"
46 return rpath, wpath, pdh
47 }, func(path string) bool {
48 // Skip tests that rely on writes, because /users/
50 return !strings.HasPrefix(path, rpath) || strings.HasPrefix(path, rpath+"_/")
54 func (s *IntegrationSuite) testCadaver(c *check.C, password string, pathFunc func(arvados.Collection) (string, string, string), skip func(string) bool) {
55 s.testServer.Config.cluster.Users.AnonymousUserToken = arvadostest.AnonymousToken
57 testdata := []byte("the human tragedy consists in the necessity of living with the consequences of actions performed under the pressure of compulsions we do not understand")
59 tempdir, err := ioutil.TempDir("", "keep-web-test-")
60 c.Assert(err, check.IsNil)
61 defer os.RemoveAll(tempdir)
63 localfile, err := ioutil.TempFile(tempdir, "localfile")
64 c.Assert(err, check.IsNil)
65 localfile.Write(testdata)
67 emptyfile, err := ioutil.TempFile(tempdir, "emptyfile")
68 c.Assert(err, check.IsNil)
70 checkfile, err := ioutil.TempFile(tempdir, "checkfile")
71 c.Assert(err, check.IsNil)
73 var newCollection arvados.Collection
74 arv := arvados.NewClientFromEnv()
75 arv.AuthToken = arvadostest.ActiveToken
76 err = arv.RequestAndDecode(&newCollection, "POST", "arvados/v1/collections", nil, map[string]interface{}{"collection": map[string]interface{}{}})
77 c.Assert(err, check.IsNil)
79 readPath, writePath, pdhPath := pathFunc(newCollection)
81 matchToday := time.Now().Format("Jan +2")
83 type testcase struct {
89 for _, trial := range []testcase{
93 match: `(?ms).*dir1 *0 .*`,
98 match: `(?ms).*bar *3.*foo *3 .*`,
101 path: readPath + "_/dir1",
103 match: `(?ms).*bar *3.*foo *3 .*`,
106 path: readPath + "dir1/",
108 match: `(?ms).*bar *3.*foo +3 +Feb +\d+ +2014.*`,
112 cmd: "get emptyfile '" + checkfile.Name() + "'\n",
113 match: `(?ms).*Not Found.*`,
117 cmd: "put '" + emptyfile.Name() + "' emptyfile\n",
118 match: `(?ms).*Uploading .* succeeded.*`,
122 cmd: "get emptyfile '" + checkfile.Name() + "'\n",
123 match: `(?ms).*Downloading .* succeeded.*`,
128 cmd: "put '" + localfile.Name() + "' testfile\n",
129 match: `(?ms).*Uploading .* succeeded.*`,
133 cmd: "get testfile '" + checkfile.Name() + "'\n",
134 match: `(?ms).*succeeded.*`,
139 cmd: "move testfile \"test &#!%20 file\"\n",
140 match: `(?ms).*Moving .* succeeded.*`,
144 cmd: "move \"test &#!%20 file\" testfile\n",
145 match: `(?ms).*Moving .* succeeded.*`,
149 cmd: "move testfile newdir0/\n",
150 match: `(?ms).*Moving .* succeeded.*`,
154 cmd: "move testfile newdir0/\n",
155 match: `(?ms).*Moving .* failed.*`,
159 cmd: "lock newdir0/testfile\n",
160 match: `(?ms).*Locking .* succeeded.*`,
164 cmd: "unlock newdir0/testfile\nasdf\n",
165 match: `(?ms).*Unlocking .* succeeded.*`,
170 match: `(?ms).*newdir0.* 0 +` + matchToday + ` \d+:\d+\n.*`,
174 cmd: "move newdir0/testfile emptyfile/bogus/\n",
175 match: `(?ms).*Moving .* failed.*`,
179 cmd: "mkcol newdir1\n",
180 match: `(?ms).*Creating .* succeeded.*`,
184 cmd: "move newdir1/ newdir1x/\n",
185 match: `(?ms).*Moving .* succeeded.*`,
189 cmd: "move newdir1x newdir1\n",
190 match: `(?ms).*Moving .* succeeded.*`,
194 cmd: "move newdir0/testfile newdir1/\n",
195 match: `(?ms).*Moving .* succeeded.*`,
199 cmd: "move newdir1 newdir1/\n",
200 match: `(?ms).*Moving .* failed.*`,
204 cmd: "get newdir1/testfile '" + checkfile.Name() + "'\n",
205 match: `(?ms).*succeeded.*`,
210 cmd: "put '" + localfile.Name() + "' newdir1/testfile1\n",
211 match: `(?ms).*Uploading .* succeeded.*`,
215 cmd: "mkcol newdir2\n",
216 match: `(?ms).*Creating .* succeeded.*`,
220 cmd: "put '" + localfile.Name() + "' newdir2/testfile2\n",
221 match: `(?ms).*Uploading .* succeeded.*`,
225 cmd: "copy newdir2/testfile2 testfile3\n",
226 match: `(?ms).*succeeded.*`,
230 cmd: "get testfile3 '" + checkfile.Name() + "'\n",
231 match: `(?ms).*succeeded.*`,
236 cmd: "get newdir2/testfile2 '" + checkfile.Name() + "'\n",
237 match: `(?ms).*succeeded.*`,
242 cmd: "rmcol newdir2\n",
243 match: `(?ms).*Deleting collection .* succeeded.*`,
247 cmd: "get newdir2/testfile2 '" + checkfile.Name() + "'\n",
248 match: `(?ms).*Downloading .* failed.*`,
251 path: "/c=" + arvadostest.UserAgreementCollection + "/t=" + arv.AuthToken + "/",
252 cmd: "put '" + localfile.Name() + "' foo\n",
253 match: `(?ms).*Uploading .* failed:.*403 Forbidden.*`,
257 cmd: "put '" + localfile.Name() + "' foo\n",
258 match: `(?ms).*Uploading .* failed:.*405 Method Not Allowed.*`,
262 cmd: "move foo bar\n",
263 match: `(?ms).*Moving .* failed:.*405 Method Not Allowed.*`,
267 cmd: "copy foo bar\n",
268 match: `(?ms).*Copying .* failed:.*405 Method Not Allowed.*`,
273 match: `(?ms).*Deleting .* failed:.*405 Method Not Allowed.*`,
278 match: `(?ms).*Locking .* failed:.*405 Method Not Allowed.*`,
281 c.Logf("%s %+v", "http://"+s.testServer.Addr, trial)
282 if skip != nil && skip(trial.path) {
287 os.Remove(checkfile.Name())
289 stdout := s.runCadaver(c, password, trial.path, trial.cmd)
290 c.Check(stdout, check.Matches, trial.match)
292 if trial.data == nil {
295 checkfile, err = os.Open(checkfile.Name())
296 c.Assert(err, check.IsNil)
297 checkfile.Seek(0, os.SEEK_SET)
298 got, err := ioutil.ReadAll(checkfile)
299 c.Check(got, check.DeepEquals, trial.data)
300 c.Check(err, check.IsNil)
304 func (s *IntegrationSuite) TestCadaverByID(c *check.C) {
305 for _, path := range []string{"/by_id", "/by_id/"} {
306 stdout := s.runCadaver(c, arvadostest.ActiveToken, path, "ls")
307 c.Check(stdout, check.Matches, `(?ms).*collection is empty.*`)
309 for _, path := range []string{
310 "/by_id/" + arvadostest.FooCollectionPDH,
311 "/by_id/" + arvadostest.FooCollectionPDH + "/",
312 "/by_id/" + arvadostest.FooCollection,
313 "/by_id/" + arvadostest.FooCollection + "/",
315 stdout := s.runCadaver(c, arvadostest.ActiveToken, path, "ls")
316 c.Check(stdout, check.Matches, `(?ms).*\s+foo\s+3 .*`)
320 func (s *IntegrationSuite) TestCadaverUsersDir(c *check.C) {
321 for _, path := range []string{"/"} {
322 stdout := s.runCadaver(c, arvadostest.ActiveToken, path, "ls")
323 c.Check(stdout, check.Matches, `(?ms).*Coll:\s+by_id\s+0 .*`)
324 c.Check(stdout, check.Matches, `(?ms).*Coll:\s+users\s+0 .*`)
326 for _, path := range []string{"/users", "/users/"} {
327 stdout := s.runCadaver(c, arvadostest.ActiveToken, path, "ls")
328 c.Check(stdout, check.Matches, `(?ms).*Coll:\s+active.*`)
330 for _, path := range []string{"/users/active", "/users/active/"} {
331 stdout := s.runCadaver(c, arvadostest.ActiveToken, path, "ls")
332 c.Check(stdout, check.Matches, `(?ms).*Coll:\s+A Project\s+0 .*`)
333 c.Check(stdout, check.Matches, `(?ms).*Coll:\s+bar_file\s+0 .*`)
335 for _, path := range []string{"/users/admin", "/users/doesnotexist", "/users/doesnotexist/"} {
336 stdout := s.runCadaver(c, arvadostest.ActiveToken, path, "ls")
337 c.Check(stdout, check.Matches, `(?ms).*404 Not Found.*`)
341 func (s *IntegrationSuite) runCadaver(c *check.C, password, path, stdin string) string {
342 tempdir, err := ioutil.TempDir("", "keep-web-test-")
343 c.Assert(err, check.IsNil)
344 defer os.RemoveAll(tempdir)
346 cmd := exec.Command("cadaver", "http://"+s.testServer.Addr+path)
348 // cadaver won't try username/password authentication
349 // unless the server responds 401 to an
350 // unauthenticated request, which it only does in
351 // AttachmentOnlyHost, TrustAllContent, and
352 // per-collection vhost cases.
353 s.testServer.Config.cluster.Services.WebDAVDownload.ExternalURL.Host = s.testServer.Addr
355 cmd.Env = append(os.Environ(), "HOME="+tempdir)
356 f, err := os.OpenFile(filepath.Join(tempdir, ".netrc"), os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0600)
357 c.Assert(err, check.IsNil)
358 _, err = fmt.Fprintf(f, "default login none password %s\n", password)
359 c.Assert(err, check.IsNil)
360 c.Assert(f.Close(), check.IsNil)
362 cmd.Stdin = bytes.NewBufferString(stdin)
363 stdout, err := cmd.StdoutPipe()
364 c.Assert(err, check.Equals, nil)
365 cmd.Stderr = cmd.Stdout
369 _, err = io.Copy(&buf, stdout)
370 c.Check(err, check.Equals, nil)
372 c.Check(err, check.Equals, nil)