Files
llmgw/internal/release/release_test.go
T
Ilker ManapandClaude Opus 5.5 0bd5305e9a Install only releases signed with the key built in; fetch a node's release on the control plane
trusted.pub now holds the release signing key, so self-upgrade, agent
upgrade and node onboarding refuse a release whose checksums are not signed
with it. Onboarding fetched the release on the node and compared it with a
checksum from the same server; the control plane now fetches it for the
node's architecture with release.Fetch, checks signature and checksum, and
hands the bytes over. Release addresses must be https (loopback excepted).
LLMGW_RELEASE_KEY overrides the key only in development builds. The CI
release job fails instead of publishing an unsigned release while a key is
built in.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-04 09:48:03 +02:00

107 lines
3.5 KiB
Go

package release
import (
"crypto/sha256"
"encoding/hex"
"net/http"
"net/http/httptest"
"os"
"path/filepath"
"testing"
)
func releaseServer(t *testing.T, version, asset string, body []byte, sum string) *httptest.Server {
t.Helper()
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
switch r.URL.Path {
case "/" + version + "/checksums.txt":
_, _ = w.Write([]byte(sum + " " + asset + "\n"))
case "/" + version + "/" + asset:
_, _ = w.Write(body)
default:
http.NotFound(w, r)
}
}))
t.Cleanup(srv.Close)
return srv
}
// unsigned has this build trust no key for the test: the checksum alone.
func unsigned(t *testing.T) {
t.Helper()
was := trustedPub
trustedPub = ""
t.Setenv("LLMGW_RELEASE_KEY", "")
t.Cleanup(func() { trustedPub = was })
}
func TestABinaryIsReplacedOnlyWithWhatTheReleasePublished(t *testing.T) {
unsigned(t)
dir := t.TempDir()
target := filepath.Join(dir, "llmgw")
_ = os.WriteFile(target, []byte("old"), 0o755)
body := []byte("new binary")
sum := sha256.Sum256(body)
asset := AssetName("v1.2.3", "linux", "amd64")
srv := releaseServer(t, "v1.2.3", asset, body, hex.EncodeToString(sum[:]))
backup, err := Install(t.Context(), srv.Client(), srv.URL, "v1.2.3", "linux", "amd64", target)
if err != nil {
t.Fatal(err)
}
if b, _ := os.ReadFile(target); string(b) != "new binary" {
t.Errorf("target holds %q", b)
}
if b, _ := os.ReadFile(backup); string(b) != "old" {
t.Errorf("the old binary was not kept: %q", b)
}
// A download that does not match its checksum changes nothing.
bad := releaseServer(t, "v1.2.4", AssetName("v1.2.4", "linux", "amd64"), []byte("tampered"),
hex.EncodeToString(sum[:]))
if _, err := Install(t.Context(), bad.Client(), bad.URL, "v1.2.4", "linux", "amd64", target); err == nil {
t.Fatal("a binary not matching its checksum was installed")
}
if b, _ := os.ReadFile(target); string(b) != "new binary" {
t.Errorf("a failed install touched the binary: %q", b)
}
if _, err := Install(t.Context(), nil, srv.URL, "../../x", "linux", "amd64", target); err == nil {
t.Error("a version that is not one was fetched")
}
}
func TestReleasesAreFetchedOverHTTPSOrFromThisMachine(t *testing.T) {
for base, ok := range map[string]bool{
"https://gitea.example/releases/download": true,
"http://127.0.0.1:8080/r": true,
"http://localhost/r": true,
"http://gitea.example/releases/download": false,
"http://10.0.0.5/r": false,
"ftp://x/r": false,
"not a url": false,
} {
if err := CheckBase(base); (err == nil) != ok {
t.Errorf("%s: %v", base, err)
}
}
if _, err := Install(t.Context(), nil, "http://gitea.example/r", "v1.2.3", "linux", "amd64", "/nonexistent"); err == nil {
t.Error("a release over plain http was installed")
}
}
func TestFetchGivesOnlyACheckedBinary(t *testing.T) {
unsigned(t)
body := []byte("for another machine")
sum := sha256.Sum256(body)
asset := AssetName("v1.2.3", "linux", "arm64")
srv := releaseServer(t, "v1.2.3", asset, body, hex.EncodeToString(sum[:]))
got, err := Fetch(t.Context(), srv.Client(), srv.URL, "v1.2.3", "linux", "arm64")
if err != nil || string(got) != string(body) {
t.Fatalf("%q %v", got, err)
}
bad := releaseServer(t, "v1.2.3", asset, []byte("swapped"), hex.EncodeToString(sum[:]))
if _, err := Fetch(t.Context(), bad.Client(), bad.URL, "v1.2.3", "linux", "arm64"); err == nil {
t.Error("a binary not matching its checksum was given")
}
}