|
|
|
@@ -0,0 +1,57 @@
|
|
|
|
|
package catalogue
|
|
|
|
|
|
|
|
|
|
import "testing"
|
|
|
|
|
|
|
|
|
|
// A consumer's credential is read by the consumer's own code, and that stopped being root for every
|
|
|
|
|
// module whose code is a bundle the node's runtime runs (novox/hq issue 624, the consumer's side of
|
|
|
|
|
// issue 225). The lab requires the package registry and reads its bound credential to clone the forge;
|
|
|
|
|
// the credential file was composed with no owner, so root's and 0600, and the lab — running as the
|
|
|
|
|
// operator's account — cloned with no credential and was refused, "could not read Username".
|
|
|
|
|
|
|
|
|
|
// aConsumerWithABundle is the lab's shape: tools in a bundle, a requirement, its credential in a file.
|
|
|
|
|
func aConsumerWithABundle() Manifest {
|
|
|
|
|
return Manifest{
|
|
|
|
|
Module: "lab",
|
|
|
|
|
Requires: []string{"npm-package-registry"},
|
|
|
|
|
Secrets: map[string]string{"npm-package-registry": "/var/lib/lab/package-registry.secret"},
|
|
|
|
|
Bundles: []Bundle{{Name: "code", Language: "typescript"}},
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func consumerSecret(t *testing.T, m Manifest, account string) map[string]any {
|
|
|
|
|
t.Helper()
|
|
|
|
|
r := Resolution{Node: "shanks", Account: account, Modules: []Manifest{m},
|
|
|
|
|
Needs: []Needed{{Name: "npm-package-registry", For: m.Module, From: "novox", Sealed: "c2VhbGVk"}}}
|
|
|
|
|
out, err := r.Declaration(Rendering{})
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Fatal(err)
|
|
|
|
|
}
|
|
|
|
|
for _, res := range out {
|
|
|
|
|
if res["type"] == "file" && res["path"] == "/var/lib/lab/package-registry.secret" {
|
|
|
|
|
return res
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
t.Fatalf("no credential file was composed: %v", out)
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestABundlesBoundCredentialBelongsToTheAccountItsRuntimeRunsAs(t *testing.T) {
|
|
|
|
|
if got := consumerSecret(t, aConsumerWithABundle(), "jochen")["owner"]; got != "jochen" {
|
|
|
|
|
t.Fatalf("the lab's credential belongs to %v; its tools run as %q, and a root-owned 0600 file is one "+
|
|
|
|
|
"they cannot read", got, "jochen")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// A module that names its secrets' owner keeps it, and one with no bundle and no owner stays root's.
|
|
|
|
|
func TestAConsumersDeclaredSecretsOwnerStillWins(t *testing.T) {
|
|
|
|
|
m := aConsumerWithABundle()
|
|
|
|
|
m.SecretsOwner = "65534:65534"
|
|
|
|
|
if got := consumerSecret(t, m, "jochen")["owner"]; got != "65534:65534" {
|
|
|
|
|
t.Errorf("a declared owner was replaced by %v", got)
|
|
|
|
|
}
|
|
|
|
|
m = aConsumerWithABundle()
|
|
|
|
|
m.Bundles = nil
|
|
|
|
|
if got, has := consumerSecret(t, m, "jochen")["owner"]; has {
|
|
|
|
|
t.Errorf("a container consumer's credential was given the owner %v", got)
|
|
|
|
|
}
|
|
|
|
|
}
|