feat: add deployment foundation and cross-device handoff
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
package installplan
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func lockFixture() Lock {
|
||||
l := Lock{ProtocolVersion: 1, Repository: "https://download.docker.com/linux/ubuntu", Suite: "resolute", Architecture: "amd64", ReleaseDigest: "sha256:" + strings.Repeat("b", 64), Packages: []Package{}}
|
||||
for _, name := range []string{"docker-ce", "docker-ce-cli", "containerd.io", "docker-buildx-plugin", "docker-compose-plugin"} {
|
||||
l.Packages = append(l.Packages, Package{Name: name, Version: "1.2.3-1", Filename: "dists/resolute/pool/stable/amd64/" + name + "_1.2.3-1_amd64.deb", Digest: "sha256:" + strings.Repeat("a", 64), Size: 123})
|
||||
}
|
||||
return l
|
||||
}
|
||||
func TestValidLockAndStableDigest(t *testing.T) {
|
||||
l := lockFixture()
|
||||
digest, err := Validate(l, "resolute", "amd64")
|
||||
if err != nil || !strings.HasPrefix(digest, "sha256:") {
|
||||
t.Fatal("valid lock rejected", err)
|
||||
}
|
||||
l.Packages[0].Size++
|
||||
changed, err := Validate(l, "resolute", "amd64")
|
||||
if err != nil || changed == digest {
|
||||
t.Fatal("lock digest does not bind size")
|
||||
}
|
||||
}
|
||||
func TestRejectUnsafeLock(t *testing.T) {
|
||||
for name, mutate := range map[string]func(*Lock){
|
||||
"protocol": func(l *Lock) { l.ProtocolVersion = 2 },
|
||||
"repository": func(l *Lock) { l.Repository = "https://attacker.example/linux/ubuntu" },
|
||||
"credentials": func(l *Lock) { l.Repository = "https://user:secret@download.docker.com/linux/ubuntu" },
|
||||
"suite": func(l *Lock) { l.Suite = "noble" },
|
||||
"architecture": func(l *Lock) { l.Architecture = "arm64" },
|
||||
"release": func(l *Lock) { l.ReleaseDigest = "" },
|
||||
"missing": func(l *Lock) { l.Packages = l.Packages[:4] },
|
||||
"extra": func(l *Lock) { l.Packages = append(l.Packages, l.Packages[0]) },
|
||||
"duplicate": func(l *Lock) { l.Packages[1] = l.Packages[0] },
|
||||
"latest": func(l *Lock) { l.Packages[0].Version = "latest" },
|
||||
"shell": func(l *Lock) { l.Packages[0].Version = "1;reboot" },
|
||||
"wrong file": func(l *Lock) { l.Packages[0].Filename = "dists/resolute/pool/stable/amd64/other.deb" },
|
||||
"traversal": func(l *Lock) { l.Packages[0].Filename = "../docker.deb" },
|
||||
"encoded path": func(l *Lock) { l.Packages[0].Filename = "dists/resolute/pool/stable/amd64/%2e%2e.deb" },
|
||||
"digest": func(l *Lock) { l.Packages[0].Digest = "bad" },
|
||||
"size": func(l *Lock) { l.Packages[0].Size = 0 },
|
||||
"engine mismatch": func(l *Lock) {
|
||||
l.Packages[1].Version = "2.3.4-1"
|
||||
l.Packages[1].Filename = "dists/resolute/pool/stable/amd64/docker-ce-cli_2.3.4-1_amd64.deb"
|
||||
},
|
||||
} {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
l := lockFixture()
|
||||
mutate(&l)
|
||||
if _, err := Validate(l, "resolute", "amd64"); err == nil {
|
||||
t.Fatal("unsafe lock accepted")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestDockerEpochAndTargetArchitecture(t *testing.T) {
|
||||
l := lockFixture()
|
||||
for i := range l.Packages {
|
||||
p := &l.Packages[i]
|
||||
if p.Name == "docker-ce" || p.Name == "docker-ce-cli" {
|
||||
p.Version = "5:29.1.0-1~ubuntu.26.04~resolute"
|
||||
p.Filename = "dists/resolute/pool/stable/amd64/" + p.Name + "_29.1.0-1~ubuntu.26.04~resolute_amd64.deb"
|
||||
}
|
||||
}
|
||||
if _, err := Validate(l, "resolute", "amd64"); err != nil {
|
||||
t.Fatal("epoch version rejected", err)
|
||||
}
|
||||
if _, err := Validate(l, "resolute", "arm64"); err == nil {
|
||||
t.Fatal("architecture mismatch accepted")
|
||||
}
|
||||
l.Packages[0].Filename = strings.Replace(l.Packages[0].Filename, "_29.", "_5:29.", 1)
|
||||
if _, err := Validate(l, "resolute", "amd64"); err == nil {
|
||||
t.Fatal("epoch in repository filename accepted")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user