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"
|
"time"
|
||||||
|
|
||||||
"git.novox.be/novox/mesh-sdk/go/announce"
|
"git.novox.be/novox/mesh-sdk/go/announce"
|
||||||
|
"git.novox.be/novox/mesh-sdk/go/delivery"
|
||||||
"github.com/nats-io/nats.go/jetstream"
|
"github.com/nats-io/nats.go/jetstream"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@@ -415,6 +416,11 @@ func TestTheCopiedComposerComposesAsTheControllers(t *testing.T) {
|
|||||||
if on, why := LeaseHandedAway([]byte(row.raw), row.found, row.err); on != row.on || why == "" {
|
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)
|
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")}
|
announced := map[string]announce.States{ControllerSeat: ControllerAnnouncement("novox")}
|
||||||
for reader, want := range map[string]bool{VaultSeat: true, GrantsModule: true, "mesh-delivery-view": false} {
|
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 {
|
if _, err := EncodeControllerGrant(ControllerGrant{Accounts: []string{""}}); err == nil {
|
||||||
t.Errorf("a grant naming an empty account was accepted")
|
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"}}
|
g := ControllerGrant{Accounts: []string{"ace.mesh-build-go", "shanks.mesh-mail.reader"}}
|
||||||
for _, c := range []struct {
|
for _, c := range []struct {
|
||||||
g ControllerGrant
|
g ControllerGrant
|
||||||
|
|||||||
@@ -90,3 +90,39 @@ func (g ControllerGrant) NamesNode(node, module string) bool {
|
|||||||
}
|
}
|
||||||
return false
|
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