From a01cc58c8dc4388eaf067e194ef1ee39191f86b5 Mon Sep 17 00:00:00 2001 From: Marcin Rataj Date: Fri, 1 Mar 2024 09:58:10 +0100 Subject: [PATCH] test: cleanup content blocking tests (#10360) --- test/cli/content_blocking_test.go | 80 +++++++++++++++++++++++++++---- 1 file changed, 71 insertions(+), 9 deletions(-) diff --git a/test/cli/content_blocking_test.go b/test/cli/content_blocking_test.go index ddb7c951e88..6598354d16e 100644 --- a/test/cli/content_blocking_test.go +++ b/test/cli/content_blocking_test.go @@ -12,7 +12,9 @@ import ( "strings" "testing" + "github.com/ipfs/go-cid" "github.com/ipfs/kubo/test/cli/harness" + carstore "github.com/ipld/go-car/v2/blockstore" "github.com/libp2p/go-libp2p" "github.com/libp2p/go-libp2p/core/peer" libp2phttp "github.com/libp2p/go-libp2p/p2p/http" @@ -34,8 +36,10 @@ func TestContentBlocking(t *testing.T) { node := h.NewNode().Init("--empty-repo", "--profile=test") // Create CIDs we use in test - h.WriteFile("blocked-dir/subdir/indirectly-blocked-file.txt", "indirectly blocked file content") - parentDirCID := node.IPFS("add", "--raw-leaves", "-Q", "-r", filepath.Join(h.Dir, "blocked-dir")).Stdout.Trimmed() + h.WriteFile("parent-dir/blocked-subdir/indirectly-blocked-file.txt", "indirectly blocked file content") + allowedParentDirCID := node.IPFS("add", "--raw-leaves", "-Q", "-r", "--pin=false", filepath.Join(h.Dir, "parent-dir")).Stdout.Trimmed() + blockedSubDirCID := node.IPFS("add", "--raw-leaves", "-Q", "-r", "--pin=false", filepath.Join(h.Dir, "parent-dir", "blocked-subdir")).Stdout.Trimmed() + node.IPFS("block", "rm", blockedSubDirCID) h.WriteFile("directly-blocked-file.txt", "directly blocked file content") blockedCID := node.IPFS("add", "--raw-leaves", "-Q", filepath.Join(h.Dir, "directly-blocked-file.txt")).Stdout.Trimmed() @@ -50,7 +54,7 @@ func TestContentBlocking(t *testing.T) { "//8526ba05eec55e28f8db5974cc891d0d92c8af69d386fc6464f1e9f372caf549\n" + // Legacy CID double-hash block: sha256(bafkqahtcnrxwg23fmqqgi33vmjwgk2dbonuca3dfm5qwg6jamnuwicq/) "//e5b7d2ce2594e2e09901596d8e1f29fa249b74c8c9e32ea01eda5111e4d33f07\n" + // Legacy Path double-hash block: sha256(bafyaagyscufaqalqaacauaqiaejao43vmjygc5didacauaqiae/subpath) "/ipfs/" + blockedCID + "\n" + // block specific CID - "/ipfs/" + parentDirCID + "/subdir*\n" + // block only specific subpath + "/ipfs/" + allowedParentDirCID + "/blocked-subdir*\n" + // block only specific subpath "/ipns/blocked-cid.example.com\n" + "/ipns/blocked-dnslink.example.com\n") @@ -94,22 +98,63 @@ func TestContentBlocking(t *testing.T) { // Confirm parent of blocked subpath is not blocked t.Run("Gateway Allows parent Path that is not blocked", func(t *testing.T) { t.Parallel() - resp := client.Get("/ipfs/" + parentDirCID) + resp := client.Get("/ipfs/" + allowedParentDirCID) assert.Equal(t, http.StatusOK, resp.StatusCode) }) + // Confirm CAR responses skip blocked subpaths + t.Run("Gateway returns CAR without blocked subpath", func(t *testing.T) { + resp := client.Get("/ipfs/" + allowedParentDirCID + "/subdir?format=car") + assert.Equal(t, http.StatusOK, resp.StatusCode) + + bs, err := carstore.NewReadOnly(strings.NewReader(resp.Body), nil) + assert.NoError(t, err) + + has, err := bs.Has(context.Background(), cid.MustParse(blockedSubDirCID)) + assert.NoError(t, err) + assert.False(t, has) + }) + + /* TODO: this was already broken in 0.26, but we should fix it + t.Run("Gateway returns CAR without directly blocked CID", func(t *testing.T) { + allowedDirWithDirectlyBlockedCID := node.IPFS("add", "--raw-leaves", "-Q", "-rw", filepath.Join(h.Dir, "directly-blocked-file.txt")).Stdout.Trimmed() + resp := client.Get("/ipfs/" + allowedDirWithDirectlyBlockedCID + "?format=car") + assert.Equal(t, http.StatusOK, resp.StatusCode) + + bs, err := carstore.NewReadOnly(strings.NewReader(resp.Body), nil) + assert.NoError(t, err) + + has, err := bs.Has(context.Background(), cid.MustParse(blockedCID)) + assert.NoError(t, err) + assert.False(t, has, "Returned CAR should not include blockedCID") + }) + */ + + // Confirm CAR responses skip blocked subpaths + t.Run("Gateway returns CAR without blocked subpath", func(t *testing.T) { + resp := client.Get("/ipfs/" + allowedParentDirCID + "/subdir?format=car") + assert.Equal(t, http.StatusOK, resp.StatusCode) + + bs, err := carstore.NewReadOnly(strings.NewReader(resp.Body), nil) + assert.NoError(t, err) + + has, err := bs.Has(context.Background(), cid.MustParse(blockedSubDirCID)) + assert.NoError(t, err) + assert.False(t, has, "Returned CAR should not include blockedSubDirCID") + }) + // Ok, now the full list of test cases we want to cover in both CLI and Gateway testCases := []struct { name string path string }{ { - name: "directly blocked CID", + name: "directly blocked file CID", path: "/ipfs/" + blockedCID, }, { name: "indirectly blocked file (on a blocked subpath)", - path: "/ipfs/" + parentDirCID + "/subdir/indirectly-blocked-file.txt", + path: "/ipfs/" + allowedParentDirCID + "/blocked-subdir/indirectly-blocked-file.txt", }, { name: "/ipns path that resolves to a blocked CID", @@ -161,9 +206,14 @@ func TestContentBlocking(t *testing.T) { t.Run(cliTestName, func(t *testing.T) { t.Parallel() args := append(cmd, testCase.path) - errMsg := node.RunIPFS(args...).Stderr.Trimmed() - if !strings.Contains(errMsg, expectedMsg) { - t.Errorf("Expected STDERR error message %q, but got: %q", expectedMsg, errMsg) + cmd := node.RunIPFS(args...) + stdout := cmd.Stdout.Trimmed() + stderr := cmd.Stderr.Trimmed() + if !strings.Contains(stderr, expectedMsg) { + t.Errorf("Expected STDERR error message %q, but got: %q", expectedMsg, stderr) + if stdout != "" { + t.Errorf("Expected STDOUT to be empty, but got: %q", stdout) + } } }) } @@ -299,5 +349,17 @@ func TestContentBlocking(t *testing.T) { assert.NotEqual(t, string(body), "directly blocked file content") assert.Contains(t, string(body), blockedMsg, bodyExpl) }) + + t.Run("Denies Blocked CID as CAR", func(t *testing.T) { + t.Parallel() + resp, err := libp2pClient.Get(fmt.Sprintf("/ipfs/%s?format=car", blockedCID)) + require.NoError(t, err) + defer resp.Body.Close() + assert.Equal(t, http.StatusGone, resp.StatusCode, statusExpl) + body, err := io.ReadAll(resp.Body) + require.NoError(t, err) + assert.NotContains(t, string(body), "directly blocked file content") + assert.Contains(t, string(body), blockedMsg, bodyExpl) + }) }) }