refactor: remove dead updater and simplify ISO launcher
This commit is contained in:
@@ -1,59 +0,0 @@
|
|||||||
// Package updater handles binary self-update with Ed25519 signature verification.
|
|
||||||
// See bible/rules/patterns/release-signing/contract.md for the full contract.
|
|
||||||
package updater
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/ed25519"
|
|
||||||
"encoding/base64"
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// trustedKeysRaw is injected at release build time via:
|
|
||||||
//
|
|
||||||
// -ldflags "-X bee/audit/internal/updater.trustedKeysRaw=base64key1:base64key2"
|
|
||||||
//
|
|
||||||
// Empty in dev builds — updates are disabled when empty.
|
|
||||||
var trustedKeysRaw string
|
|
||||||
|
|
||||||
// TrustedKeys decodes the embedded public keys.
|
|
||||||
// Returns an error if the binary was built without key injection (dev build).
|
|
||||||
func TrustedKeys() ([]ed25519.PublicKey, error) {
|
|
||||||
if strings.TrimSpace(trustedKeysRaw) == "" {
|
|
||||||
return nil, fmt.Errorf("dev build: trusted keys not embedded, updates disabled")
|
|
||||||
}
|
|
||||||
var keys []ed25519.PublicKey
|
|
||||||
for _, enc := range strings.Split(trustedKeysRaw, ":") {
|
|
||||||
enc = strings.TrimSpace(enc)
|
|
||||||
if enc == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
b, err := base64.StdEncoding.DecodeString(enc)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("decode trusted key: %w", err)
|
|
||||||
}
|
|
||||||
if len(b) != ed25519.PublicKeySize {
|
|
||||||
return nil, fmt.Errorf("trusted key has wrong size: got %d, want %d", len(b), ed25519.PublicKeySize)
|
|
||||||
}
|
|
||||||
keys = append(keys, ed25519.PublicKey(b))
|
|
||||||
}
|
|
||||||
if len(keys) == 0 {
|
|
||||||
return nil, fmt.Errorf("no valid trusted keys found in build")
|
|
||||||
}
|
|
||||||
return keys, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// VerifySignature returns nil if sig was produced by any trusted key over data.
|
|
||||||
// Returns an error (never panics) on any failure — caller logs and continues.
|
|
||||||
func VerifySignature(data, sig []byte) error {
|
|
||||||
keys, err := TrustedKeys()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
for _, key := range keys {
|
|
||||||
if ed25519.Verify(key, data, sig) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return fmt.Errorf("signature verification failed: no trusted key matched")
|
|
||||||
}
|
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
package updater
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/ed25519"
|
|
||||||
"crypto/rand"
|
|
||||||
"encoding/base64"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestVerifySignature_valid(t *testing.T) {
|
|
||||||
pub, priv, err := ed25519.GenerateKey(rand.Reader)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
data := []byte("release binary content")
|
|
||||||
sig := ed25519.Sign(priv, data)
|
|
||||||
|
|
||||||
trustedKeysRaw = base64.StdEncoding.EncodeToString(pub)
|
|
||||||
t.Cleanup(func() { trustedKeysRaw = "" })
|
|
||||||
|
|
||||||
if err := VerifySignature(data, sig); err != nil {
|
|
||||||
t.Fatalf("expected valid signature to pass: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestVerifySignature_tampered(t *testing.T) {
|
|
||||||
pub, priv, err := ed25519.GenerateKey(rand.Reader)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
_ = pub
|
|
||||||
|
|
||||||
data := []byte("original content")
|
|
||||||
sig := ed25519.Sign(priv, data)
|
|
||||||
|
|
||||||
// different key embedded
|
|
||||||
pub2, _, _ := ed25519.GenerateKey(rand.Reader)
|
|
||||||
trustedKeysRaw = base64.StdEncoding.EncodeToString(pub2)
|
|
||||||
t.Cleanup(func() { trustedKeysRaw = "" })
|
|
||||||
|
|
||||||
if err := VerifySignature(data, sig); err == nil {
|
|
||||||
t.Fatal("expected tampered signature to fail")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestVerifySignature_multiKey_anyMatches(t *testing.T) {
|
|
||||||
pub1, _, _ := ed25519.GenerateKey(rand.Reader)
|
|
||||||
pub2, priv2, _ := ed25519.GenerateKey(rand.Reader)
|
|
||||||
|
|
||||||
data := []byte("signed by developer 2")
|
|
||||||
sig := ed25519.Sign(priv2, data)
|
|
||||||
|
|
||||||
trustedKeysRaw = base64.StdEncoding.EncodeToString(pub1) + ":" +
|
|
||||||
base64.StdEncoding.EncodeToString(pub2)
|
|
||||||
t.Cleanup(func() { trustedKeysRaw = "" })
|
|
||||||
|
|
||||||
if err := VerifySignature(data, sig); err != nil {
|
|
||||||
t.Fatalf("expected any-key match to pass: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestVerifySignature_devBuild(t *testing.T) {
|
|
||||||
trustedKeysRaw = ""
|
|
||||||
_, priv, _ := ed25519.GenerateKey(rand.Reader)
|
|
||||||
data := []byte("content")
|
|
||||||
sig := ed25519.Sign(priv, data)
|
|
||||||
|
|
||||||
if err := VerifySignature(data, sig); err == nil {
|
|
||||||
t.Fatal("expected dev build (no keys) to fail")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -124,66 +124,41 @@ else
|
|||||||
echo "=== using existing builder image ${IMAGE_REF} (${BUILDER_PLATFORM}) ==="
|
echo "=== using existing builder image ${IMAGE_REF} (${BUILDER_PLATFORM}) ==="
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Build base docker run args (without --authorized-keys)
|
run_variant() {
|
||||||
build_run_args() {
|
_v="$1"
|
||||||
_variant="$1"
|
echo "=== building variant: ${_v} ==="
|
||||||
_auth_arg=""
|
|
||||||
if [ -n "$AUTH_KEYS" ]; then
|
set -- \
|
||||||
_auth_arg="--authorized-keys /tmp/bee-authkeys/${AUTH_KEYS_BASE}"
|
--rm \
|
||||||
fi
|
--privileged \
|
||||||
echo "run --rm --privileged \
|
--platform "${BUILDER_PLATFORM}" \
|
||||||
--platform ${BUILDER_PLATFORM} \
|
-v "${REPO_ROOT}:/work" \
|
||||||
-v ${REPO_ROOT}:/work \
|
-v "${CACHE_DIR}:/cache" \
|
||||||
-v ${CACHE_DIR}:/cache \
|
|
||||||
${AUTH_KEYS:+-v ${AUTH_KEYS_DIR}:/tmp/bee-authkeys:ro} \
|
|
||||||
-e BEE_CONTAINER_BUILD=1 \
|
-e BEE_CONTAINER_BUILD=1 \
|
||||||
-e GOCACHE=/cache/go-build \
|
-e GOCACHE=/cache/go-build \
|
||||||
-e GOMODCACHE=/cache/go-mod \
|
-e GOMODCACHE=/cache/go-mod \
|
||||||
-e TMPDIR=/cache/tmp \
|
-e TMPDIR=/cache/tmp \
|
||||||
-e BEE_CACHE_DIR=/cache/bee \
|
-e BEE_CACHE_DIR=/cache/bee \
|
||||||
-w /work \
|
-e BEE_REQUIRE_MEMTEST=1
|
||||||
${IMAGE_REF} \
|
|
||||||
sh /work/iso/builder/build.sh --variant ${_variant} ${_auth_arg}"
|
|
||||||
}
|
|
||||||
|
|
||||||
run_variant() {
|
|
||||||
_v="$1"
|
|
||||||
echo "=== building variant: ${_v} ==="
|
|
||||||
if [ -n "$AUTH_KEYS" ]; then
|
if [ -n "$AUTH_KEYS" ]; then
|
||||||
"$CONTAINER_TOOL" run --rm --privileged \
|
set -- "$@" -v "${AUTH_KEYS_DIR}:/tmp/bee-authkeys:ro"
|
||||||
--platform "${BUILDER_PLATFORM}" \
|
|
||||||
-v "${REPO_ROOT}:/work" \
|
|
||||||
-v "${CACHE_DIR}:/cache" \
|
|
||||||
-v "${AUTH_KEYS_DIR}:/tmp/bee-authkeys:ro" \
|
|
||||||
-e BEE_CONTAINER_BUILD=1 \
|
|
||||||
-e GOCACHE=/cache/go-build \
|
|
||||||
-e GOMODCACHE=/cache/go-mod \
|
|
||||||
-e TMPDIR=/cache/tmp \
|
|
||||||
-e BEE_CACHE_DIR=/cache/bee \
|
|
||||||
-e BEE_REQUIRE_MEMTEST=1 \
|
|
||||||
${MIRROR:+-e "BEE_MIRROR=${MIRROR}"} \
|
|
||||||
-w /work \
|
|
||||||
"${IMAGE_REF}" \
|
|
||||||
sh /work/iso/builder/build.sh --variant "${_v}" \
|
|
||||||
--authorized-keys "/tmp/bee-authkeys/${AUTH_KEYS_BASE}" \
|
|
||||||
${MIRROR:+--mirror "${MIRROR}"}
|
|
||||||
else
|
|
||||||
"$CONTAINER_TOOL" run --rm --privileged \
|
|
||||||
--platform "${BUILDER_PLATFORM}" \
|
|
||||||
-v "${REPO_ROOT}:/work" \
|
|
||||||
-v "${CACHE_DIR}:/cache" \
|
|
||||||
-e BEE_CONTAINER_BUILD=1 \
|
|
||||||
-e GOCACHE=/cache/go-build \
|
|
||||||
-e GOMODCACHE=/cache/go-mod \
|
|
||||||
-e TMPDIR=/cache/tmp \
|
|
||||||
-e BEE_CACHE_DIR=/cache/bee \
|
|
||||||
-e BEE_REQUIRE_MEMTEST=1 \
|
|
||||||
${MIRROR:+-e "BEE_MIRROR=${MIRROR}"} \
|
|
||||||
-w /work \
|
|
||||||
"${IMAGE_REF}" \
|
|
||||||
sh /work/iso/builder/build.sh --variant "${_v}" \
|
|
||||||
${MIRROR:+--mirror "${MIRROR}"}
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [ -n "$MIRROR" ]; then
|
||||||
|
set -- "$@" -e "BEE_MIRROR=${MIRROR}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
set -- "$@" -w /work "${IMAGE_REF}" \
|
||||||
|
sh /work/iso/builder/build.sh --variant "${_v}"
|
||||||
|
if [ -n "$AUTH_KEYS" ]; then
|
||||||
|
set -- "$@" --authorized-keys "/tmp/bee-authkeys/${AUTH_KEYS_BASE}"
|
||||||
|
fi
|
||||||
|
if [ -n "$MIRROR" ]; then
|
||||||
|
set -- "$@" --mirror "${MIRROR}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
"$CONTAINER_TOOL" run "$@"
|
||||||
}
|
}
|
||||||
|
|
||||||
case "$VARIANT" in
|
case "$VARIANT" in
|
||||||
|
|||||||
@@ -16,6 +16,11 @@ for tool in mksquashfs unsquashfs rsync; do
|
|||||||
}
|
}
|
||||||
done
|
done
|
||||||
|
|
||||||
|
find . -maxdepth 0 -printf '' >/dev/null 2>&1 || {
|
||||||
|
echo "test-squashfs-layers: GNU find not available, skipping"
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
T="$(mktemp -d)"
|
T="$(mktemp -d)"
|
||||||
trap 'rm -rf "$T"' EXIT INT TERM HUP
|
trap 'rm -rf "$T"' EXIT INT TERM HUP
|
||||||
ROOT="$T/root"
|
ROOT="$T/root"
|
||||||
|
|||||||
Reference in New Issue
Block a user