[ARVADOS] updated: 014975cc7957bc25fb3b3d7be3ef2af0bae2bab7
git at public.curoverse.com
git at public.curoverse.com
Mon Sep 7 03:46:12 EDT 2015
Summary of changes:
services/keepdl/doc.go | 27 ++++++++++----------
services/keepdl/handler.go | 30 +++++++++++++++++++---
services/keepdl/handler_test.go | 56 +++++++++++++++++++++++++++++++++++++++--
3 files changed, 95 insertions(+), 18 deletions(-)
via 014975cc7957bc25fb3b3d7be3ef2af0bae2bab7 (commit)
via 647f476080b0b49a90cc5b7c7d24d54ce8cf631b (commit)
from d96f0405962b9ea907e700b662b4aee444455c1b (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
commit 014975cc7957bc25fb3b3d7be3ef2af0bae2bab7
Author: Tom Clegg <tom at curoverse.com>
Date: Mon Sep 7 03:43:59 2015 -0400
5824: Add -attachment-only-host feature.
diff --git a/services/keepdl/doc.go b/services/keepdl/doc.go
index 401b917..088f7a8 100644
--- a/services/keepdl/doc.go
+++ b/services/keepdl/doc.go
@@ -173,6 +173,19 @@
// (``https://dl.example.com/'') and upload it to some other site
// chosen by the author of collection X.
//
+// Attachment-Only host
+//
+// It is possible to serve untrusted content and accept user
+// credentials at the same origin as long as the content is only
+// downloaded, never executed by browsers. A single origin (hostname
+// and port) can be designated as an "attachment-only" origin: cookies
+// will be accepted and all responses will have a
+// "Content-Disposition: attachment" header. This behavior is invoked
+// only when the designated origin matches exactly the Host header
+// provided by the client or upstream proxy.
+//
+// keepdl -attachment-only-host domain.example:9999
+//
// Trust All Content mode
//
// In "trust all content" mode, Keepdl will accept credentials (API
diff --git a/services/keepdl/handler.go b/services/keepdl/handler.go
index bdcb9cf..d2b8ba6 100644
--- a/services/keepdl/handler.go
+++ b/services/keepdl/handler.go
@@ -23,11 +23,14 @@ type handler struct{}
var (
clientPool = arvadosclient.MakeClientPool()
trustAllContent = false
+ attachmentOnlyHost = ""
)
func init() {
flag.BoolVar(&trustAllContent, "trust-all-content", false,
"Serve non-public content from a single origin. Dangerous: read docs before using!")
+ flag.StringVar(&attachmentOnlyHost, "attachment-only-host", "",
+ "Accept credentials, and add \"Content-Disposition: attachment\" response headers, for requests at this hostname:port. Prohibiting inline display makes it possible to serve untrusted and non-public content from a single origin, i.e., without wildcard DNS or SSL.")
}
// return a UUID or PDH if s begins with a UUID or URL-encoded PDH;
@@ -110,8 +113,16 @@ func (h *handler) ServeHTTP(wOrig http.ResponseWriter, r *http.Request) {
var tokens []string
var reqTokens []string
var pathToken bool
+ var attachment bool
credentialsOK := trustAllContent
+ if r.Host != "" && r.Host == attachmentOnlyHost {
+ credentialsOK = true
+ attachment = true
+ } else if r.FormValue("disposition") == "attachment" {
+ attachment = true
+ }
+
if targetId = parseCollectionIdFromDNSName(r.Host); targetId != "" {
// http://ID.dl.example/PATH...
credentialsOK = true
@@ -292,6 +303,9 @@ func (h *handler) ServeHTTP(wOrig http.ResponseWriter, r *http.Request) {
}
}
w.Header().Set("Content-Length", fmt.Sprintf("%d", rdr.Len()))
+ if attachment {
+ w.Header().Set("Content-Disposition", "attachment")
+ }
w.WriteHeader(http.StatusOK)
_, err = io.Copy(w, rdr)
diff --git a/services/keepdl/handler_test.go b/services/keepdl/handler_test.go
index a6b5eb2..0590dd0 100644
--- a/services/keepdl/handler_test.go
+++ b/services/keepdl/handler_test.go
@@ -201,6 +201,30 @@ func (s *IntegrationSuite) TestVhostRedirectQueryTokenTrustAllContent(c *check.C
)
}
+func (s *IntegrationSuite) TestVhostRedirectQueryTokenAttachmentOnlyHost(c *check.C) {
+ defer func(orig string) {
+ attachmentOnlyHost = orig
+ }(attachmentOnlyHost)
+ attachmentOnlyHost = "example.com:1234"
+
+ s.testVhostRedirectTokenToCookie(c, "GET",
+ "example.com/c=" + arvadostest.FooCollection + "/foo",
+ "?api_token=" + arvadostest.ActiveToken,
+ "text/plain",
+ "",
+ http.StatusBadRequest,
+ )
+
+ resp := s.testVhostRedirectTokenToCookie(c, "GET",
+ "example.com:1234/c=" + arvadostest.FooCollection + "/foo",
+ "?api_token=" + arvadostest.ActiveToken,
+ "text/plain",
+ "",
+ http.StatusOK,
+ )
+ c.Check(resp.Header().Get("Content-Disposition"), check.Equals, "attachment")
+}
+
func (s *IntegrationSuite) TestVhostRedirectPOSTFormTokenToCookie(c *check.C) {
s.testVhostRedirectTokenToCookie(c, "POST",
arvadostest.FooCollection + ".example.com/foo",
@@ -221,7 +245,7 @@ func (s *IntegrationSuite) TestVhostRedirectPOSTFormTokenToCookie404(c *check.C)
)
}
-func (s *IntegrationSuite) testVhostRedirectTokenToCookie(c *check.C, method, hostPath, queryString, contentType, body string, expectStatus int) {
+func (s *IntegrationSuite) testVhostRedirectTokenToCookie(c *check.C, method, hostPath, queryString, contentType, body string, expectStatus int) *httptest.ResponseRecorder {
u, _ := url.Parse(`http://` + hostPath + queryString)
req := &http.Request{
Method: method,
@@ -235,7 +259,7 @@ func (s *IntegrationSuite) testVhostRedirectTokenToCookie(c *check.C, method, ho
(&handler{}).ServeHTTP(resp, req)
if resp.Code != http.StatusSeeOther {
c.Assert(resp.Code, check.Equals, expectStatus)
- return
+ return resp
}
c.Check(resp.Body.String(), check.Matches, `.*href="//` + regexp.QuoteMeta(html.EscapeString(hostPath)) + `".*`)
cookies := (&http.Response{Header: resp.Header()}).Cookies()
@@ -258,4 +282,5 @@ func (s *IntegrationSuite) testVhostRedirectTokenToCookie(c *check.C, method, ho
if expectStatus == http.StatusOK {
c.Check(resp.Body.String(), check.Equals, "foo")
}
+ return resp
}
commit 647f476080b0b49a90cc5b7c7d24d54ce8cf631b
Author: Tom Clegg <tom at curoverse.com>
Date: Mon Sep 7 02:39:10 2015 -0400
5824: Implement "trust all content" mode.
diff --git a/services/keepdl/doc.go b/services/keepdl/doc.go
index 6b7242f..401b917 100644
--- a/services/keepdl/doc.go
+++ b/services/keepdl/doc.go
@@ -49,7 +49,7 @@
// The following "same origin" URL patterns are supported for public
// collections (i.e., collections which can be served by keepdl
// without making use of any credentials supplied by the client). See
-// "Same-origin mode" below.
+// "Same-origin URLs" below.
//
// http://dl.example.com/c=uuid_or_pdh/path/file.txt
// http://dl.example.com/c=uuid_or_pdh/t=TOKEN/path/file.txt
@@ -163,7 +163,7 @@
// the local network -- the upstream proxy should configured to return
// 401 for all paths beginning with "/c=".
//
-// Same-origin mode
+// Same-origin URLs
//
// Without the same-origin protection outlined above, a web page
// stored in collection X could execute JavaScript code that uses the
@@ -173,19 +173,7 @@
// (``https://dl.example.com/'') and upload it to some other site
// chosen by the author of collection X.
//
-package main
-
-// TODO(TC): Implement?
-//
-// Trusted content
-//
-// Normally, Keepdl is installed using a wildcard DNS entry and a
-// wildcard HTTPS certificate, serving data from collection X at
-// ``https://X--dl.example.com/path/file.ext''.
-//
-// It will also serve publicly accessible data at
-// ``https://dl.example.com/collections/X/path/file.txt'', but it does not
-// accept any kind of credentials at paths like these.
+// Trust All Content mode
//
// In "trust all content" mode, Keepdl will accept credentials (API
// tokens) and serve any collection X at
@@ -198,4 +186,4 @@ package main
//
// keepdl -trust-all-content [...]
//
-// In the general case, this should not be enabled:
+package main
diff --git a/services/keepdl/handler.go b/services/keepdl/handler.go
index 3c38728..bdcb9cf 100644
--- a/services/keepdl/handler.go
+++ b/services/keepdl/handler.go
@@ -1,6 +1,7 @@
package main
import (
+ "flag"
"fmt"
"html"
"io"
@@ -19,7 +20,15 @@ import (
type handler struct{}
-var clientPool = arvadosclient.MakeClientPool()
+var (
+ clientPool = arvadosclient.MakeClientPool()
+ trustAllContent = false
+)
+
+func init() {
+ flag.BoolVar(&trustAllContent, "trust-all-content", false,
+ "Serve non-public content from a single origin. Dangerous: read docs before using!")
+}
// return a UUID or PDH if s begins with a UUID or URL-encoded PDH;
// otherwise return "".
@@ -101,7 +110,7 @@ func (h *handler) ServeHTTP(wOrig http.ResponseWriter, r *http.Request) {
var tokens []string
var reqTokens []string
var pathToken bool
- var credentialsOK bool
+ credentialsOK := trustAllContent
if targetId = parseCollectionIdFromDNSName(r.Host); targetId != "" {
// http://ID.dl.example/PATH...
@@ -138,7 +147,8 @@ func (h *handler) ServeHTTP(wOrig http.ResponseWriter, r *http.Request) {
if !credentialsOK {
// It is not safe to copy the provided token
// into a cookie unless the current vhost
- // (origin) serves only a single collection.
+ // (origin) serves only a single collection or
+ // we are in trustAllContent mode.
statusCode = http.StatusBadRequest
return
}
diff --git a/services/keepdl/handler_test.go b/services/keepdl/handler_test.go
index 69dff4f..a6b5eb2 100644
--- a/services/keepdl/handler_test.go
+++ b/services/keepdl/handler_test.go
@@ -177,6 +177,30 @@ func (s *IntegrationSuite) TestVhostRedirectQueryTokenToCookie(c *check.C) {
)
}
+func (s *IntegrationSuite) TestVhostRedirectQueryTokenSingleOriginError(c *check.C) {
+ s.testVhostRedirectTokenToCookie(c, "GET",
+ "example.com/c=" + arvadostest.FooCollection + "/foo",
+ "?api_token=" + arvadostest.ActiveToken,
+ "text/plain",
+ "",
+ http.StatusBadRequest,
+ )
+}
+
+func (s *IntegrationSuite) TestVhostRedirectQueryTokenTrustAllContent(c *check.C) {
+ defer func(orig bool) {
+ trustAllContent = orig
+ }(trustAllContent)
+ trustAllContent = true
+ s.testVhostRedirectTokenToCookie(c, "GET",
+ "example.com/c=" + arvadostest.FooCollection + "/foo",
+ "?api_token=" + arvadostest.ActiveToken,
+ "text/plain",
+ "",
+ http.StatusOK,
+ )
+}
+
func (s *IntegrationSuite) TestVhostRedirectPOSTFormTokenToCookie(c *check.C) {
s.testVhostRedirectTokenToCookie(c, "POST",
arvadostest.FooCollection + ".example.com/foo",
@@ -209,7 +233,10 @@ func (s *IntegrationSuite) testVhostRedirectTokenToCookie(c *check.C, method, ho
resp := httptest.NewRecorder()
(&handler{}).ServeHTTP(resp, req)
- c.Assert(resp.Code, check.Equals, http.StatusSeeOther)
+ if resp.Code != http.StatusSeeOther {
+ c.Assert(resp.Code, check.Equals, expectStatus)
+ return
+ }
c.Check(resp.Body.String(), check.Matches, `.*href="//` + regexp.QuoteMeta(html.EscapeString(hostPath)) + `".*`)
cookies := (&http.Response{Header: resp.Header()}).Cookies()
-----------------------------------------------------------------------
hooks/post-receive
--
More information about the arvados-commits
mailing list