fix(submit): 审阅绑定上下文 sha256,批准须带摘要,构建只从内部 API 取上下文并校验字节

This commit is contained in:
Lemon-miaow committed 2026-09-24 22:24:50 +08:00
1 parent 13b65e19ec
commit e521cf5976
30 files changed
+910 -98

No files matched your search

+65
View File
@@ -4,6 +4,8 @@ import (
"archive/tar"
"bytes"
"compress/gzip"
"crypto/sha256"
"encoding/hex"
"io"
"net"
"net/http"
@@ -187,6 +189,69 @@ func TestCmdFetchContextFetchAndExtract(t *testing.T) {
}
}
// With --sha256 the fetch refuses any bytes but the approved ones, including
// a tarball that extracts cleanly: that is exactly the context an uploader
// swapped in after the review.
func TestCmdFetchContextChecksDigest(t *testing.T) {
body := tgzBody(t, tarEntry{name: "Dockerfile", body: "FROM scratch\n"})
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
_, _ = w.Write(body)
}))
defer srv.Close()
t.Setenv("FELIS_SERVICE_TOKEN", "test-token")
sum := sha256.Sum256(body)
good := hex.EncodeToString(sum[:])
args := func(digest string) []string {
return []string{"--url=" + srv.URL + "/sub-1/context", "--out=" + t.TempDir(), "--sha256=" + digest}
}
if code := cmdFetchContext(args(good), io.Discard, io.Discard); code != 0 {
t.Fatalf("matching digest exit = %d, want 0", code)
}
var stderr bytes.Buffer
other := strings.Repeat("0", 64)
if code := cmdFetchContext(args(other), io.Discard, &stderr); code != 1 || !strings.Contains(stderr.String(), "changed after approval") {
t.Fatalf("mismatched digest exit = %d, stderr %q; want 1 naming the change", code, stderr.String())
}
stderr.Reset()
if code := cmdFetchContext(args("ABC"), io.Discard, &stderr); code != 2 {
t.Fatalf("malformed digest exit = %d, want 2 (stderr %q)", code, stderr.String())
}
// Bytes after the tar end marker still count: appending to an approved blob
// must change what the fetch accepts.
padded := append(append([]byte{}, body...), "trailing"...)
srvPadded := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
_, _ = w.Write(padded)
}))
defer srvPadded.Close()
if code := cmdFetchContext([]string{"--url=" + srvPadded.URL + "/c", "--out=" + t.TempDir(), "--sha256=" + good}, io.Discard, io.Discard); code != 1 {
t.Fatalf("padded blob exit = %d, want 1", code)
}
}
// The request carries the service token, so a redirect is a failure: the token
// never follows it to another host (build-supply-chain-13).
func TestCmdFetchContextRefusesRedirects(t *testing.T) {
var leaked bool
elsewhere := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
leaked = true
}))
defer elsewhere.Close()
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, elsewhere.URL+"/steal", http.StatusFound)
}))
defer srv.Close()
t.Setenv("FELIS_SERVICE_TOKEN", "test-token")
var stderr bytes.Buffer
if code := cmdFetchContext([]string{"--url=" + srv.URL + "/c", "--out=" + t.TempDir()}, io.Discard, &stderr); code != 1 {
t.Fatalf("redirect exit = %d, want 1 (stderr %q)", code, stderr.String())
}
if leaked {
t.Fatal("the fetch followed the redirect")
}
}
// A body that is not a gzip tarball must fail the extraction rather than produce
// an empty (or partial) context Kaniko would then try to build.
func TestExtractTarGzRejectsNonGzip(t *testing.T) {