carlos / platform Public

Bound guard helpers and preserve unmanaged legacy routes

Paul Campbell pushed by paul@keymail.dev 6ea36465222fc6b88d1adc0d876158f7b507cefa parent 971960b
3 files changed, +60 −4
  • internal/maintenanceguard/guard.go +4 −3
  • internal/maintenanceguard/types.go +10 −1
  • internal/maintenanceguard/wire_test.go +46 −0
diff --git a/internal/maintenanceguard/guard.go b/internal/maintenanceguard/guard.go
index 1739addfe..0db0bc804 100644
--- a/internal/maintenanceguard/guard.go
+++ b/internal/maintenanceguard/guard.go
@@ -147,9 +147,10 @@ const (
// CheckServing is a denial check, not a lease or process-health permit. The
// caller supplies contracts from an already verified signed release manifest,
// verifies the current record identity, and repeats this check after lease
-// acquisition before starting or seeding anything.
+// acquisition before starting or seeding anything. Legacy unmanaged records may
+// omit Record: both barriers must be absent before that omission is accepted.
func (r *Repository) CheckServing(ctx context.Context, identity Identity, projection *Projection, verifiedContracts []string) (ServingDecision, error) {
- if !identity.valid() || !ValidContracts(verifiedContracts) {
+ if !identity.locationValid() || !ValidContracts(verifiedContracts) {
return Denied, ErrDenied
}
s, e := r.ReadGuard(ctx, identity.Host)
@@ -162,7 +163,7 @@ func (r *Repository) CheckServing(ctx context.Context, identity Identity, projec
}
return Denied, ErrDenied
}
- if projection == nil || !projection.valid() || s.value.Identity != identity || s.value.Phase != Resumed || !containsAll(verifiedContracts, s.value.RequiredContracts) {
+ if !identity.valid() || projection == nil || !projection.valid() || s.value.Identity != identity || s.value.Phase != Resumed || !containsAll(verifiedContracts, s.value.RequiredContracts) {
return Denied, ErrDenied
}
expected, e := s.Projection()
diff --git a/internal/maintenanceguard/types.go b/internal/maintenanceguard/types.go
index afe6e8fad..a8d6911fb 100644
--- a/internal/maintenanceguard/types.go
+++ b/internal/maintenanceguard/types.go
@@ -30,10 +30,16 @@ var (
)
func ValidID(s string) bool {
+ if len(s) != 43 {
+ return false
+ }
b, e := base64.RawURLEncoding.Strict().DecodeString(s)
return e == nil && len(b) == 32 && base64.RawURLEncoding.EncodeToString(b) == s
}
func ValidDigest(s string) bool {
+ if len(s) != 64 {
+ return false
+ }
b, e := hex.DecodeString(s)
return e == nil && len(b) == 32 && hex.EncodeToString(b) == s
}
@@ -89,7 +95,10 @@ type Identity struct {
}
func (i Identity) valid() bool {
- return controlname.ValidAccount(i.Account) && controlname.ValidApp(i.App) && controlname.ValidHostShape(i.Host) && ValidDigest(i.Record)
+ return i.locationValid() && ValidDigest(i.Record)
+}
+func (i Identity) locationValid() bool {
+ return controlname.ValidAccount(i.Account) && controlname.ValidApp(i.App) && controlname.ValidHostShape(i.Host)
}
type Reference struct {
diff --git a/internal/maintenanceguard/wire_test.go b/internal/maintenanceguard/wire_test.go
index dabb770fa..ca5f1a3ae 100644
--- a/internal/maintenanceguard/wire_test.go
+++ b/internal/maintenanceguard/wire_test.go
@@ -234,3 +234,49 @@ func TestPermanentReferenceDigestMismatchDenies(t *testing.T) {
replace(t, f, key, []byte(`{"metadata":"changed outside immutable writer"}`))
denied(t, f, &p, []string{"home.operator.v1"})
}
+
+func TestDirectHelpersBoundBeforeAllocation(t *testing.T) {
+ raw := strings.Repeat("a", 1<<20)
+ for name, fn := range map[string]func(string) bool{"id": guard.ValidID, "digest": guard.ValidDigest} {
+ t.Run(name, func(t *testing.T) {
+ if allocations := testing.AllocsPerRun(10, func() {
+ if fn(raw) {
+ panic("oversized helper input accepted")
+ }
+ }); allocations != 0 {
+ t.Fatalf("oversized direct input allocated before refusal: %v", allocations)
+ }
+ })
+ }
+}
+func TestLegacyUnmanagedIdentityNeedsNoCreationDigest(t *testing.T) {
+ f := setup(t)
+ legacy := f.identity
+ legacy.Record = ""
+ if d, e := f.repo.CheckServing(ctx, legacy, nil, nil); e != nil || d != guard.Unmanaged {
+ t.Fatalf("legacy route: %v %v", d, e)
+ }
+ bogus := legacy
+ bogus.Host = "../foreign"
+ if d, e := f.repo.CheckServing(ctx, bogus, nil, nil); e == nil || d != guard.Denied {
+ t.Fatal("invalid location accepted")
+ }
+ p := guard.Projection{Version: 1, Generation: 1, GuardDigest: hash("absent")}
+ if d, e := f.repo.CheckServing(ctx, legacy, &p, nil); e == nil || d != guard.Denied {
+ t.Fatal("projection alone accepted")
+ }
+ c := f.claim(t, 1)
+ s := f.create(t, c)
+ for _, phase := range []guard.Phase{guard.Quiescing, guard.Fenced, guard.ResumeRequested, guard.Resumed} {
+ s = f.step(t, c, s, phase)
+ }
+ p, e := s.Projection()
+ if e != nil {
+ t.Fatal(e)
+ }
+ for _, projection := range []*guard.Projection{nil, &p} {
+ if d, e := f.repo.CheckServing(ctx, legacy, projection, []string{"home.operator.v1"}); e == nil || d != guard.Denied {
+ t.Fatal("managed record lacking identity accepted")
+ }
+ }
+}