feat: add deployment foundation and cross-device handoff
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
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")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user