package aptrepo import ( "crypto/sha256" "fmt" "os" "path" "path/filepath" "reflect" "testing" "server-deploy/internal/installplan" ) func artifactFixture(t *testing.T) (string, installplan.Lock) { t.Helper() dir := t.TempDir() index := fixtureIndex() lock, err := Resolve(fixtureRelease(index), index, "resolute", "amd64", fixturePins(), fixtureNow) if err != nil { t.Fatal(err) } for i := range lock.Packages { p := &lock.Packages[i] data := []byte("artifact fixture " + p.Name) p.Size = uint64(len(data)) p.Digest = fmt.Sprintf("sha256:%x", sha256.Sum256(data)) if err := os.WriteFile(filepath.Join(dir, path.Base(p.Filename)), data, 0600); err != nil { t.Fatal(err) } } return dir, lock } func TestArtifactBytesAndIdentity(t *testing.T) { dir, lock := artifactFixture(t) before := lock before.Packages = append([]installplan.Package(nil), lock.Packages...) if err := verifyArtifacts(dir, lock); err != nil { t.Fatal(err) } if !reflect.DeepEqual(before, lock) { t.Fatal("lock mutated") } for _, p := range lock.Packages { data, err := os.ReadFile(filepath.Join(dir, path.Base(p.Filename))) if err != nil || string(data) != "artifact fixture "+p.Name { t.Fatal("artifact modified") } } } func TestArtifactRejectsTamperWithoutPartialSuccess(t *testing.T) { for _, kind := range []string{"same-size", "truncated", "extra-byte", "missing", "directory", "bad-lock", "relative-root", "extra-file"} { t.Run(kind, func(t *testing.T) { dir, lock := artifactFixture(t) p := lock.Packages[4] // The last artifact must fail the whole set. filename := filepath.Join(dir, path.Base(p.Filename)) switch kind { case "same-size": data := []byte("artifact fixture " + p.Name) data[0] = 'X' if err := os.WriteFile(filename, data, 0600); err != nil { t.Fatal(err) } case "truncated": if err := os.Truncate(filename, int64(p.Size)-1); err != nil { t.Fatal(err) } case "extra-byte": if err := os.Truncate(filename, int64(p.Size)+1); err != nil { t.Fatal(err) } case "missing": if err := os.Remove(filename); err != nil { t.Fatal(err) } case "directory": if err := os.Remove(filename); err != nil { t.Fatal(err) } if err := os.Mkdir(filename, 0700); err != nil { t.Fatal(err) } case "bad-lock": lock.Packages[0].Filename = "../../secret.deb" case "relative-root": dir = "relative" case "extra-file": if err := os.WriteFile(filepath.Join(dir, "unexpected.deb"), []byte("x"), 0600); err != nil { t.Fatal(err) } } if err := verifyArtifacts(dir, lock); err == nil { t.Fatal("invalid artifacts accepted") } }) } }