package static_test import ( "bufio" "crypto/sha256" "encoding/hex" "os" "strings" "testing" "github.com/stretchr/testify/require" "sneak.berlin/go/webhooker/static" ) const manifestPath = "vendor.sha256" // fetchHint is appended to every failure here: the assets the manifest // covers are fetched by the build, not committed, so a fresh clone that // has not run script/fetch-assets fails this test and should be told why. const fetchHint = "run `script/fetch-assets` (or `make assets`) to install " + "the pinned third-party assets" // TestVendoredAssetsMatchManifest asserts that every asset listed in // static/vendor.sha256 is embedded in the binary with exactly the pinned // bytes. script/fetch-assets verifies the same hashes at download time; // this test verifies them again on what actually ships, so a build that // skipped, cached, or subverted the fetch cannot produce a binary serving // unpinned third-party JavaScript. func TestVendoredAssetsMatchManifest(t *testing.T) { t.Parallel() entries := readManifest(t) require.NotEmpty(t, entries, "%s lists no assets", manifestPath) for path, want := range entries { t.Run(path, func(t *testing.T) { t.Parallel() data, err := static.Static.ReadFile(path) require.NoErrorf( t, err, "%s is listed in %s but is not embedded; %s", path, manifestPath, fetchHint, ) sum := sha256.Sum256(data) got := hex.EncodeToString(sum[:]) require.Equalf( t, want, got, "embedded %s does not match its pinned sha256 in %s; %s", path, manifestPath, fetchHint, ) }) } } // readManifest parses static/vendor.sha256, which is in sha256sum(1) // format with paths relative to static/. func readManifest(t *testing.T) map[string]string { t.Helper() f, err := os.Open(manifestPath) require.NoError(t, err, "opening %s", manifestPath) defer func() { require.NoError(t, f.Close()) }() entries := make(map[string]string) scanner := bufio.NewScanner(f) for scanner.Scan() { line := strings.TrimSpace(scanner.Text()) if line == "" || strings.HasPrefix(line, "#") { continue } fields := strings.Fields(line) require.Lenf( t, fields, 2, "%s: malformed entry %q, want \" \"", manifestPath, line, ) sum, path := fields[0], fields[1] require.Lenf(t, sum, 64, "%s: %q is not a sha256", manifestPath, sum) entries[path] = sum } require.NoError(t, scanner.Err(), "reading %s", manifestPath) return entries }