diff --git a/modules/mesh-vault/cmd/mesh-vault/enrolment.go b/modules/mesh-vault/cmd/mesh-vault/enrolment.go index c88187ea..b9c92d03 100644 --- a/modules/mesh-vault/cmd/mesh-vault/enrolment.go +++ b/modules/mesh-vault/cmd/mesh-vault/enrolment.go @@ -24,6 +24,7 @@ import ( "time" stdio "git.novox.be/novox/mesh-sdk/go" + "git.novox.be/novox/mesh-sdk/go/delivery" "git.novox.be/novox/mesh-sdk/go/seal" "golang.org/x/crypto/bcrypt" ) @@ -31,9 +32,9 @@ import ( // The names enrolment gives: the module that holds the seat mesh-enrolment, the prefix of a token's bus user, and the // vault's state of each node's logins. const ( - EnrolmentModule = "mesh-enrolment" - EnrolUserPrefix = "enrol." - NodeLoginsState = "node-logins" + EnrolmentModule = delivery.EnrolmentModule + EnrolUserPrefix = delivery.EnrolmentUserPrefix + NodeLoginsState = delivery.NodeLoginsState // MeshHostModule is the module a node's own login secret is kept under (`own//mesh-host/`, ADR 0583 ยง3). MeshHostModule = "mesh-host" ) @@ -130,41 +131,9 @@ func (v *Vault) fromEnrolment(caller, verb string) error { // TokenBase is what a token states beside its secret: where the bus is and the certificate to expect there, and the // machine's first tunnel when the token carries one. type TokenBase struct { - Broker string `json:"broker"` - Fingerprint string `json:"fingerprint"` - Tunnel *TokenTunnel `json:"tunnel,omitempty"` -} - -// TokenTunnel is the joining machine's side of its first tunnel, in the wire format the node-engine parses. -type TokenTunnel struct { - Key string `json:"key"` - Address string `json:"address"` - Range string `json:"range"` - HubKey string `json:"hub_key"` - HubEndpoint string `json:"hub_endpoint"` -} - -// EnrolToken is the token a person carries to a joining machine, in the wire format of the node-engine's parser -// (mesh-host internal/identity.Token): version, node, the bus's address and certificate fingerprint, the vault's public -// signing key, the one-time secret, and the tunnel when there is one. -type EnrolToken struct { - Version int `json:"v"` - Node string `json:"node,omitempty"` - Broker string `json:"broker,omitempty"` - Fingerprint string `json:"fingerprint,omitempty"` - Signer []byte `json:"signer,omitempty"` - Secret string `json:"secret"` - Adopted bool `json:"adopted,omitempty"` - Tunnel *TokenTunnel `json:"tunnel,omitempty"` -} - -// Text is the token as a person types it: base64url of its JSON. -func (t EnrolToken) Text() (string, error) { - raw, err := json.Marshal(t) - if err != nil { - return "", err - } - return base64.RawURLEncoding.EncodeToString(raw), nil + Broker string `json:"broker"` + Fingerprint string `json:"fingerprint"` + Tunnel *delivery.TokenTunnel `json:"tunnel,omitempty"` } // EnrolmentTokenArgs are `enrolment-token`'s arguments: the node, when it expires (the seat's word, echoed), and which @@ -268,8 +237,8 @@ func (v *Vault) showEnrolmentToken(caller, node string) (EnrolmentTokenAnswer, e if err != nil { return EnrolmentTokenAnswer{}, fmt.Errorf("the token carries the vault's signing key, which is not held yet: %w", err) } - text, err := EnrolToken{Version: 1, Node: node, Broker: base.Broker, Fingerprint: base.Fingerprint, - Signer: []byte(keys.key.Public().(ed25519.PublicKey)), Secret: secret, Tunnel: base.Tunnel}.Text() + text, err := delivery.Token{Version: 1, Node: node, Broker: base.Broker, Fingerprint: base.Fingerprint, + Signer: []byte(keys.key.Public().(ed25519.PublicKey)), Secret: secret, Tunnel: base.Tunnel}.Encode() if err != nil { return EnrolmentTokenAnswer{}, err } diff --git a/modules/mesh-vault/cmd/mesh-vault/enrolment_test.go b/modules/mesh-vault/cmd/mesh-vault/enrolment_test.go index 16d32e5d..1f52a26e 100644 --- a/modules/mesh-vault/cmd/mesh-vault/enrolment_test.go +++ b/modules/mesh-vault/cmd/mesh-vault/enrolment_test.go @@ -35,7 +35,10 @@ func (l *loginsState) Get(node string) (*NodeLogin, error) { func (l *loginsState) Put(n NodeLogin) error { l.mu.Lock() defer l.mu.Unlock() - raw, _ := json.Marshal(n) + raw, err := delivery.EncodeNodeLogin(n) + if err != nil { + return err + } if field := credentialField(raw); field != "" { return fmt.Errorf("%s carries a field %q, which names a credential", n.Node, field) } @@ -152,7 +155,7 @@ func TestTheVaultMakesAnEnrolmentsTokenAccountAndSignature(t *testing.T) { t.Fatalf("show answered %+v, %v", shown, err) } text := openOperator(t, e.operatorPublic, e.operatorPrivate, shown.Sealed) - var tok EnrolToken + var tok delivery.Token body, _ := base64.RawURLEncoding.DecodeString(text) signer, _ := e.keys() if err := json.Unmarshal(body, &tok); err != nil || tok.Version != 1 || tok.Secret != secret || tok.Node != "new1" || diff --git a/modules/mesh-vault/cmd/mesh-vault/noderotation.go b/modules/mesh-vault/cmd/mesh-vault/noderotation.go index 2c4ab333..8666ceb5 100644 --- a/modules/mesh-vault/cmd/mesh-vault/noderotation.go +++ b/modules/mesh-vault/cmd/mesh-vault/noderotation.go @@ -29,35 +29,28 @@ import ( "time" stdio "git.novox.be/novox/mesh-sdk/go" + "git.novox.be/novox/mesh-sdk/go/delivery" "golang.org/x/crypto/bcrypt" ) -// The events a rotation says, and the stages of a node's key. +// The events a rotation says and the stages of a node's key are mesh-sdk's (delivery/node_logins.go); a rotation warranted +// by a hand act is warranted for a day. const ( - RotationBegunEvent = "rotation-begun" - NodeAccountReadyEvent = "node-account-ready" - RotationDoneEvent = "rotation-done" + RotationBegunEvent = delivery.RotationBegunEvent + NodeAccountReadyEvent = delivery.NodeAccountReadyEvent + RotationDoneEvent = delivery.RotationDoneEvent - StageBegun = "begun" - StageReady = "ready" - StageConfirmed = "confirmed" + StageBegun = delivery.RotationBegun + StageReady = delivery.RotationReady + StageConfirmed = delivery.RotationConfirmed // HandActWithin is how recent a hand act is that warrants a rotation. HandActWithin = 24 * time.Hour ) -// NodeLogin is one key of the vault's state `node-logins`: the login the node's node-engine dials as, and, while a -// rotation runs, the other login and how far it has come. Never a value or a hash. -type NodeLogin struct { - Node string `json:"node"` - Login string `json:"login"` - // Rotating is the other login while a rotation runs; empty reads as none. - Rotating string `json:"rotating,omitempty"` - Stage string `json:"stage,omitempty"` - Since time.Time `json:"since,omitzero"` - // ListRevision is the revision of the loaded user list the rotation began at. - ListRevision uint64 `json:"list-revision,omitempty"` -} +// NodeLogin is one key of the vault's state node-logins (mesh-sdk's contract): the login the node's node-engine dials as, +// and while a rotation runs the other login with its stage. Never a value or a hash. +type NodeLogin = delivery.NodeLogin // NodeLoginStore is the vault's state `node-logins`, by node. type NodeLoginStore interface { @@ -75,15 +68,19 @@ func (busNodeLogins) Get(node string) (*NodeLogin, error) { if err != nil || e == nil { return nil, err } - var n NodeLogin - if err := json.Unmarshal(e.Value, &n); err != nil { + n, err := delivery.DecodeNodeLogin(e.Value) + if err != nil { return nil, fmt.Errorf("%s %s is not a node's login: %w", NodeLoginsState, node, err) } return &n, nil } func (busNodeLogins) Put(n NodeLogin) error { - _, err := stdio.State(NodeLoginsState).Put(n.Node, n) + raw, err := delivery.EncodeNodeLogin(n) + if err != nil { + return err + } + _, err = stdio.State(NodeLoginsState).Put(n.Node, json.RawMessage(raw)) return err }