package builder import ( "crypto/sha256" "encoding/hex" "encoding/json" "net/http" "net/http/httptest" "net/url" "strings" "testing" "time" "github.com/novox/mesh-controller/internal/facts" ) // **A check's container never sees the forge credential** (novox/hq issue 462): the toolchain container // mounts the workspace as HOME, so a credential kept there — or a clone's .git/config carrying one — is // readable by any pull request's merge-check.sh, and printed, kept on the bus for days. const ( forgeSecret = "sw0rdfi5h-forge" forgeURL = "http://mesh_novox_builder:" + forgeSecret + "@forge.invalid:20000" besideSecret = "b3side-t0ken" npmSecret = "npm-s3cret-t0ken" ) // aFactsRegistry is an artifact store holding the facts snapshot, and nothing else. func aFactsRegistry(t *testing.T) string { t.Helper() body, err := json.Marshal(facts.Facts{Format: facts.Format, Taken: time.Now().UTC(), Versions: facts.Versions{Bus: "2.11.17", Store: "17.11"}, Machines: []facts.Machine{{Name: "abcdef", Length: 6}}}) if err != nil { t.Fatal(err) } sum := sha256.Sum256(body) digest := "sha256:" + hex.EncodeToString(sum[:]) manifest, _ := json.Marshal(map[string]any{"schemaVersion": 2, "layers": []map[string]any{ {"mediaType": facts.MediaType, "digest": digest, "size": len(body)}}}) srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { switch { case strings.Contains(r.URL.Path, "/manifests/"): w.Write(manifest) case strings.HasSuffix(r.URL.Path, "/blobs/"+digest): w.Write(body) default: http.NotFound(w, r) } })) t.Cleanup(srv.Close) return strings.TrimPrefix(srv.URL, "http://") } // bareURL is a URL with its userinfo left out. func bareURL(t *testing.T, raw string) string { u, err := url.Parse(raw) if err != nil { t.Fatal(err) } u.User = nil return u.String() } // Every line a repository's own check prints is published to the build's log redacted. func TestTheRedactorHidesTheForgeCredentialAndShapes(t *testing.T) { r := redactorFor(GitCredential{URL: forgeURL}) for in, want := range map[string]string{ "the secret alone: " + forgeSecret: "the secret alone: [redacted: the forge credential]", "go test ./... ok": "go test ./... ok", "--password hunter22 and done": "--password [redacted: the word after --password] and done", "commit 3b6b54a0c1d2e3f4a5b6c7d8e9f0": "commit 3b6b54a0c1d2e3f4a5b6c7d8e9f0", } { if got := r.redact(in); got != want { t.Errorf("%q redacted as %q, want %q", in, got, want) } } } // A build's clone of a URL carrying userinfo records it without, so no build leaves a credential in // workspace/source/.git/config while it runs either (novox/hq issue 462); the tree itself is gone when the // build ends.