delivery: the grants part's grant keys and the source the assigner reads (a1; issue 774)
Why: the grants part writes grants.<module>.<fp> in shadow beside the controller's; the assigner switches source only when the lease is handed away.
This commit is contained in:
@@ -6,6 +6,7 @@ import (
|
||||
"time"
|
||||
|
||||
"git.novox.be/novox/mesh-sdk/go/announce"
|
||||
"git.novox.be/novox/mesh-sdk/go/delivery"
|
||||
"github.com/nats-io/nats.go/jetstream"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@@ -431,6 +432,11 @@ func TestTheCopiedComposerComposesAsTheControllers(t *testing.T) {
|
||||
if on, why := LeaseHandedAway([]byte(row.raw), row.found, row.err); on != row.on || why == "" {
|
||||
t.Errorf("%s: on %v (%s), want %v", row.name, on, why, row.on)
|
||||
}
|
||||
// The assigner's grants source follows it: the grants part's bucket only for a handed-away lease (issue 774).
|
||||
on, _ := LeaseHandedAway([]byte(row.raw), row.found, row.err)
|
||||
if bucket, _ := delivery.GrantSource(on); (bucket == delivery.PartGrantsBucket) != row.on {
|
||||
t.Errorf("%s: the grants source is %s", row.name, bucket)
|
||||
}
|
||||
}
|
||||
announced := map[string]announce.States{ControllerSeat: ControllerAnnouncement("novox")}
|
||||
for reader, want := range map[string]bool{VaultSeat: true, GrantsModule: true, "mesh-delivery-view": false} {
|
||||
|
||||
@@ -298,6 +298,25 @@ func TestControllerGrant(t *testing.T) {
|
||||
if _, err := EncodeControllerGrant(ControllerGrant{Accounts: []string{""}}); err == nil {
|
||||
t.Errorf("a grant naming an empty account was accepted")
|
||||
}
|
||||
// The grants part's keys are the controller's: the same key round-trips; the source is the part's bucket only for a
|
||||
// handed-away lease (issue 774).
|
||||
if pk, err := PartGrantKey("mesh-delivery-assigner", fp); err != nil || pk != key {
|
||||
t.Errorf("PartGrantKey = %q, %v, want the controller's %q", pk, err, key)
|
||||
}
|
||||
if m, f, err := ParsePartGrantKey(key); err != nil || m != "mesh-delivery-assigner" || f != fp {
|
||||
t.Errorf("ParsePartGrantKey = %q, %q, %v", m, f, err)
|
||||
}
|
||||
for _, c := range []struct {
|
||||
away bool
|
||||
bucket, read string
|
||||
}{
|
||||
{false, "mesh-controller_grants", "mesh-controller.grants"},
|
||||
{true, "mesh-grants_grants", "mesh-grants.grants"},
|
||||
} {
|
||||
if b, r := GrantSource(c.away); b != c.bucket || r != c.read {
|
||||
t.Errorf("GrantSource(%v) = %q, %q, want %q, %q", c.away, b, r, c.bucket, c.read)
|
||||
}
|
||||
}
|
||||
g := ControllerGrant{Accounts: []string{"ace.mesh-build-go", "shanks.mesh-mail.reader"}}
|
||||
for _, c := range []struct {
|
||||
g ControllerGrant
|
||||
|
||||
@@ -90,3 +90,39 @@ func (g ControllerGrant) NamesNode(node, module string) bool {
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// **The grants part's grants** (novox/hq ADR 0547 §4, §5, ADR 0561 §2, §6; issue 774). The grants part writes the same
|
||||
// keys, with the same value, into its own state `grants` (the bucket PartGrantsBucket), beside the controller's: first in
|
||||
// shadow, which nobody reads, so a tool can compare the two before anything switches. The assigner reads the part's keys
|
||||
// only once the controller's lease is handed away (GrantSource), and the controller's until then.
|
||||
const (
|
||||
// PartGrantsState is the grants part's state of issued credentials by fingerprint, as its manifest names it.
|
||||
PartGrantsState = "grants"
|
||||
// PartGrantsBucket is that state's bucket, `<owner module>_<name>`.
|
||||
PartGrantsBucket = "mesh-grants_" + PartGrantsState
|
||||
// PartGrantsRead is that state as a reader names it in `reads`.
|
||||
PartGrantsRead = "mesh-grants." + PartGrantsState
|
||||
// PartGrantsHistory is the revisions the bucket keeps per key.
|
||||
PartGrantsHistory = ControllerGrantsHistory
|
||||
)
|
||||
|
||||
// PartGrantKey is the key, in PartGrantsBucket, of a module's credential issued for a fingerprint: the layout of the
|
||||
// controller's key (ControllerGrantKey), so a key of one is the key of the other and a compare is by key.
|
||||
func PartGrantKey(module, fingerprint string) (string, error) {
|
||||
return ControllerGrantKey(module, fingerprint)
|
||||
}
|
||||
|
||||
// ParsePartGrantKey is the inverse of PartGrantKey.
|
||||
func ParsePartGrantKey(key string) (module, fingerprint string, err error) {
|
||||
return ParseControllerGrantKey(key)
|
||||
}
|
||||
|
||||
// GrantSource names the bucket the assigner reads grants from, and the `reads` name that grants it: the grants part's
|
||||
// once the controller's lease is handed away (buscompose.LeaseHandedAway, which refuses every other value of the lease,
|
||||
// an unreadable one included), the controller's in every other case.
|
||||
func GrantSource(leaseHandedAway bool) (bucket, read string) {
|
||||
if leaseHandedAway {
|
||||
return PartGrantsBucket, PartGrantsRead
|
||||
}
|
||||
return ControllerGrantsBucket, "mesh-controller.grants"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user