The url was skipped by the installation check, so an installation's host or an address passed; it is judged whole now, the vendor's host declared in the artifact's names-on-purpose, and an address or a reserved name as the host is refused. Only the version's dotted-quad reading is skipped. The unpack caps its entries, drains xz before waiting for it, reads a pax global header and a nested within's parents, and a redirect off https is not followed.
102 lines
5.0 KiB
Go
102 lines
5.0 KiB
Go
package catalogue
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
// An archive pinned by URL and sha256 (novox/hq ADR 0316 §2, §6): the vendor's file, mirrored by the build
|
|
// seat, never a copy in the repository.
|
|
|
|
const pinnedSum = "38dd24890a66b4cf9a45bc24e15192e00c26b929e1bb8df7974c16a4539129e2"
|
|
|
|
func upstreamManifest(artifact string) string {
|
|
return `{"module":"a","version":"1","build":{"artifacts":[` + artifact + `]}}`
|
|
}
|
|
|
|
func TestAnArchivePinnedByURLAndSha256IsAccepted(t *testing.T) {
|
|
for _, a := range []string{
|
|
`{"name":"archive","kind":"archive","url":"https://vendor.example.org/release-1.tar.xz","sha256":"` + pinnedSum +
|
|
`","version":"1.0","within":"release"}`,
|
|
`{"name":"addon","kind":"archive","url":"https://vendor.example.org/addon.xpi","sha256":"` + pinnedSum +
|
|
`","version":"1.5.6.1","file":"addon.xpi"}`,
|
|
} {
|
|
if _, err := ParseManifest([]byte(upstreamManifest(a))); err != nil {
|
|
t.Errorf("%s was refused: %v", a, err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestAnUpstreamFileThatIsNotPinnedIsRefused(t *testing.T) {
|
|
cases := map[string]string{
|
|
// No digest: what the address serves changes under the mesh.
|
|
`{"name":"x","kind":"archive","url":"https://vendor.invalid/r.tar.xz","version":"1"}`: "without a pinned sha256",
|
|
`{"name":"x","kind":"archive","url":"https://vendor.invalid/r.tar.xz","sha256":"ABC","version":"1"}`: "without a pinned sha256",
|
|
// No version: a person reading the pin cannot tell which release.
|
|
`{"name":"x","kind":"archive","url":"https://vendor.invalid/r.tar.xz","sha256":"` + pinnedSum + `"}`: "says no version",
|
|
// Not https.
|
|
`{"name":"x","kind":"archive","url":"http://vendor.invalid/r.tar.xz","sha256":"` + pinnedSum + `","version":"1"}`: "over https",
|
|
// Both a directory of the repository and a URL.
|
|
`{"name":"x","kind":"archive","from":"files","url":"https://vendor.invalid/r.tar.xz","sha256":"` + pinnedSum +
|
|
`","version":"1"}`: "one or the other",
|
|
// A pin without a URL.
|
|
`{"name":"x","kind":"archive","from":"files","sha256":"` + pinnedSum + `"}`: "no url",
|
|
// Only an archive is mirrored from a file.
|
|
`{"name":"x","kind":"image","from":"Dockerfile","url":"https://vendor.invalid/r.tar.xz","sha256":"` + pinnedSum +
|
|
`","version":"1"}`: "only an archive",
|
|
// A file name that is a path, a directory within that leaves the archive, and both at once.
|
|
`{"name":"x","kind":"archive","url":"https://vendor.invalid/a.xpi","sha256":"` + pinnedSum +
|
|
`","version":"1","file":"../a.xpi"}`: "not a plain relative file name",
|
|
`{"name":"x","kind":"archive","url":"https://vendor.invalid/r.tar.xz","sha256":"` + pinnedSum +
|
|
`","version":"1","within":"../up"}`: "not a plain relative directory",
|
|
`{"name":"x","kind":"archive","url":"https://vendor.invalid/r.tar.xz","sha256":"` + pinnedSum +
|
|
`","version":"1","within":"r","file":"r.tar.xz"}`: "a file is kept whole",
|
|
}
|
|
for artifact, want := range cases {
|
|
_, err := ParseManifest([]byte(upstreamManifest(artifact)))
|
|
if err == nil {
|
|
t.Errorf("%s was accepted", artifact)
|
|
continue
|
|
}
|
|
if !strings.Contains(err.Error(), want) {
|
|
t.Errorf("%s was refused for another reason than %q: %v", artifact, want, err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestAnUpstreamFilesVendorIsNamedOnPurposeAndAnInstallationsIsRefused(t *testing.T) {
|
|
// The vendor's host is judged like any name, and passes through names-on-purpose; a version of four dotted
|
|
// numbers is not an address, and a name in it is still judged.
|
|
m, err := ParseManifest([]byte(upstreamManifest(`{"name":"owl","kind":"archive","url":"https://vendor.be/owl/owl.xpi","sha256":"` +
|
|
pinnedSum + `","version":"1.5.6.1","file":"owl.xpi","names-on-purpose":{"vendor.be":"Owl's vendor publishes it there"}}`)))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if problems := InstallationProblems(m); len(problems) != 0 {
|
|
t.Fatalf("the declared vendor and the version were taken for an installation: %v", problems)
|
|
}
|
|
m.Build.Artifacts[0].NamesOnPurpose = nil
|
|
if problems := InstallationProblems(m); len(problems) != 1 || !strings.Contains(problems[0], "vendor.be") {
|
|
t.Fatalf("an undeclared vendor host is judged: %v", problems)
|
|
}
|
|
m.Build.Artifacts[0].Version = "git.novox.be 10.0.0.1"
|
|
if problems := InstallationProblems(m); len(problems) != 2 {
|
|
t.Fatalf("a name in the version is judged: %v", problems)
|
|
}
|
|
m.Build.Artifacts[0].URL, m.Build.Artifacts[0].Version = "https://mail.novox.be/owl.xpi", "1"
|
|
if problems := InstallationProblems(m); len(problems) != 1 || !strings.Contains(problems[0], "mail.novox.be") {
|
|
t.Fatalf("an installation's host in the url is judged: %v", problems)
|
|
}
|
|
}
|
|
|
|
func TestAnUpstreamFileFromAnAddressOrAReservedNameIsRefused(t *testing.T) {
|
|
for _, u := range []string{"https://git.novox.internal/r.tar.xz", "https://10.1.2.3/r.tar.xz",
|
|
"https://203.0.113.9/r.tar.xz", "https://[2001:db8::1]/r.tar.xz", "https://nas.lan/r.tar.xz", "https://vendor/r.tar.xz"} {
|
|
_, err := ParseManifest([]byte(upstreamManifest(`{"name":"x","kind":"archive","url":"` + u + `","sha256":"` +
|
|
pinnedSum + `","version":"1"}`)))
|
|
if err == nil || !strings.Contains(err.Error(), "published under a public name") {
|
|
t.Errorf("%s: %v", u, err)
|
|
}
|
|
}
|
|
}
|