80 lines
3.4 KiB
Go
80 lines
3.4 KiB
Go
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")
|
|
}
|
|
}
|