X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/ce4285dd9a6310a799b861237918273329390316..6e08460da8e0d19c8152863eda05b868fa1a8d55:/services/keepstore/proxy_remote_test.go diff --git a/services/keepstore/proxy_remote_test.go b/services/keepstore/proxy_remote_test.go index 4c50513808..00161bf236 100644 --- a/services/keepstore/proxy_remote_test.go +++ b/services/keepstore/proxy_remote_test.go @@ -5,6 +5,7 @@ package main import ( + "context" "crypto/md5" "encoding/json" "fmt" @@ -16,10 +17,11 @@ import ( "sync/atomic" "time" - "git.curoverse.com/arvados.git/sdk/go/arvados" - "git.curoverse.com/arvados.git/sdk/go/arvadostest" - "git.curoverse.com/arvados.git/sdk/go/auth" - "git.curoverse.com/arvados.git/sdk/go/keepclient" + "git.arvados.org/arvados.git/sdk/go/arvados" + "git.arvados.org/arvados.git/sdk/go/arvadostest" + "git.arvados.org/arvados.git/sdk/go/auth" + "git.arvados.org/arvados.git/sdk/go/keepclient" + "github.com/prometheus/client_golang/prometheus" check "gopkg.in/check.v1" ) @@ -27,8 +29,7 @@ var _ = check.Suite(&ProxyRemoteSuite{}) type ProxyRemoteSuite struct { cluster *arvados.Cluster - vm VolumeManager - rtr http.Handler + handler *handler remoteClusterID string remoteBlobSigningKey []byte @@ -86,28 +87,23 @@ func (s *ProxyRemoteSuite) SetUpTest(c *check.C) { s.remoteKeepproxy = httptest.NewServer(http.HandlerFunc(s.remoteKeepproxyHandler)) s.remoteAPI = httptest.NewUnstartedServer(http.HandlerFunc(s.remoteAPIHandler)) s.remoteAPI.StartTLS() - s.cluster = arvados.IntegrationTestCluster() + s.cluster = testCluster(c) + s.cluster.Collections.BlobSigningKey = knownKey + s.cluster.SystemRootToken = arvadostest.SystemRootToken s.cluster.RemoteClusters = map[string]arvados.RemoteCluster{ - s.remoteClusterID: arvados.RemoteCluster{ + s.remoteClusterID: { Host: strings.Split(s.remoteAPI.URL, "//")[1], Proxy: true, Scheme: "http", Insecure: true, }, } - s.vm = MakeTestVolumeManager(2) - KeepVM = s.vm - theConfig = DefaultConfig() - theConfig.systemAuthToken = arvadostest.DataManagerToken - theConfig.Start() - s.rtr = MakeRESTRouter(s.cluster) + s.cluster.Volumes = map[string]arvados.Volume{"zzzzz-nyw5e-000000000000000": {Driver: "mock"}} + s.handler = &handler{} + c.Assert(s.handler.setup(context.Background(), s.cluster, "", prometheus.NewRegistry(), testServiceURL), check.IsNil) } func (s *ProxyRemoteSuite) TearDownTest(c *check.C) { - s.vm.Close() - KeepVM = nil - theConfig = DefaultConfig() - theConfig.Start() s.remoteAPI.Close() s.remoteKeepproxy.Close() } @@ -120,30 +116,101 @@ func (s *ProxyRemoteSuite) TestProxyRemote(c *check.C) { path := "/" + strings.Replace(s.remoteKeepLocator, "+A", "+R"+s.remoteClusterID+"-", 1) - var req *http.Request - var resp *httptest.ResponseRecorder - tryWithToken := func(token string) { - req = httptest.NewRequest("GET", path, nil) - req.Header.Set("Authorization", "Bearer "+token) + for _, trial := range []struct { + label string + method string + token string + xKeepSignature string + expectRemoteReqs int64 + expectCode int + expectSignature bool + }{ + { + label: "GET only", + method: "GET", + token: arvadostest.ActiveTokenV2, + expectRemoteReqs: 1, + expectCode: http.StatusOK, + }, + { + label: "obsolete token", + method: "GET", + token: arvadostest.ActiveToken, + expectRemoteReqs: 0, + expectCode: http.StatusBadRequest, + }, + { + label: "bad token", + method: "GET", + token: arvadostest.ActiveTokenV2[:len(arvadostest.ActiveTokenV2)-3] + "xxx", + expectRemoteReqs: 1, + expectCode: http.StatusNotFound, + }, + { + label: "HEAD only", + method: "HEAD", + token: arvadostest.ActiveTokenV2, + expectRemoteReqs: 1, + expectCode: http.StatusOK, + }, + { + label: "HEAD with local signature", + method: "HEAD", + xKeepSignature: "local, time=" + time.Now().Format(time.RFC3339), + token: arvadostest.ActiveTokenV2, + expectRemoteReqs: 1, + expectCode: http.StatusOK, + expectSignature: true, + }, + { + label: "GET with local signature", + method: "GET", + xKeepSignature: "local, time=" + time.Now().Format(time.RFC3339), + token: arvadostest.ActiveTokenV2, + expectRemoteReqs: 1, + expectCode: http.StatusOK, + expectSignature: true, + }, + } { + c.Logf("trial: %s", trial.label) + + s.remoteKeepRequests = 0 + + var req *http.Request + var resp *httptest.ResponseRecorder + req = httptest.NewRequest(trial.method, path, nil) + req.Header.Set("Authorization", "Bearer "+trial.token) + if trial.xKeepSignature != "" { + req.Header.Set("X-Keep-Signature", trial.xKeepSignature) + } resp = httptest.NewRecorder() - s.rtr.ServeHTTP(resp, req) + s.handler.ServeHTTP(resp, req) + c.Check(s.remoteKeepRequests, check.Equals, trial.expectRemoteReqs) + c.Check(resp.Code, check.Equals, trial.expectCode) + if resp.Code == http.StatusOK { + c.Check(resp.Body.String(), check.Equals, string(data)) + } else { + c.Check(resp.Body.String(), check.Not(check.Equals), string(data)) + } + + c.Check(resp.Header().Get("Vary"), check.Matches, `(.*, )?X-Keep-Signature(, .*)?`) + + locHdr := resp.Header().Get("X-Keep-Locator") + if !trial.expectSignature { + c.Check(locHdr, check.Equals, "") + continue + } + + c.Check(locHdr, check.Not(check.Equals), "") + c.Check(locHdr, check.Not(check.Matches), `.*\+R.*`) + c.Check(VerifySignature(s.cluster, locHdr, trial.token), check.IsNil) + + // Ensure block can be requested using new signature + req = httptest.NewRequest("GET", "/"+locHdr, nil) + req.Header.Set("Authorization", "Bearer "+trial.token) + resp = httptest.NewRecorder() + s.handler.ServeHTTP(resp, req) + c.Check(resp.Code, check.Equals, http.StatusOK) + c.Check(s.remoteKeepRequests, check.Equals, trial.expectRemoteReqs) } - - // Happy path - tryWithToken(arvadostest.ActiveTokenV2) - c.Check(s.remoteKeepRequests, check.Equals, int64(1)) - c.Check(resp.Code, check.Equals, http.StatusOK) - c.Check(resp.Body.String(), check.Equals, string(data)) - - // Obsolete token - tryWithToken(arvadostest.ActiveToken) - c.Check(s.remoteKeepRequests, check.Equals, int64(1)) - c.Check(resp.Code, check.Equals, http.StatusBadRequest) - c.Check(resp.Body.String(), check.Not(check.Equals), string(data)) - - // Bad token - tryWithToken(arvadostest.ActiveTokenV2[:len(arvadostest.ActiveTokenV2)-3] + "xxx") - c.Check(s.remoteKeepRequests, check.Equals, int64(2)) - c.Check(resp.Code, check.Equals, http.StatusNotFound) - c.Check(resp.Body.String(), check.Not(check.Equals), string(data)) }