68 lines
3.3 KiB
Go
68 lines
3.3 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
"github.com/novox/mesh-controller/internal/catalogue"
|
|
"github.com/novox/mesh-controller/internal/inventory"
|
|
)
|
|
|
|
// A covered account is handed to the vault when it is minted (novox/hq ADR 0374, issue 787).
|
|
//
|
|
// **Covered** are the bus accounts `module issue` mints for a core module (catalogue.CoreCredentialModules) or for a
|
|
// module marked moved; no other account is. Until the vault makes bus accounts (ADR 0113 clause 6, issue 774) the
|
|
// controller mints such an account and writes its hash to the bus's user list, as before, and then hands the whole
|
|
// value at once to the vault's `accept` with origin `issued`: sealed here to the key the vault made for that call, so
|
|
// the vault alone opens it (ADR 0349 clause 8). The vault keeps it as the module's own secret on that machine and
|
|
// raises `secret-changed`; a re-issue is the same hand with a new value, which replaces the old in place. An account
|
|
// not covered is minted and kept as it was and handed to nobody.
|
|
|
|
// vaultAskerForIssue is the vault as `module issue` asks it. A test replaces it.
|
|
var vaultAskerForIssue = func(ctx context.Context) vaultAsker { return theVault(ctx) }
|
|
|
|
// accountIsCovered says whether the bus accounts minted for m are the vault's to hold (ADR 0374 clause 1).
|
|
func accountIsCovered(m catalogue.Manifest) bool {
|
|
return catalogue.CarriesVaultSealed(m.Module) || m.Moved
|
|
}
|
|
|
|
// vaultInstalled says whether the vault is assigned to any machine. Until it is, as in genesis (ADR 0113 §15 to §18,
|
|
// mesh-host's bootstrap, which issues the bus's and the provisioner's accounts before the vault step), there is no
|
|
// vault to hand to: the value is kept in the controller's store as before, and the vault takes it afterwards by the
|
|
// move (move-in takes a value of the controller's store with origin made, accepted or issued, as it is). Only a
|
|
// vault that is installed and does not answer fails the issue.
|
|
func vaultInstalled(ctx context.Context, inv *inventory.Inventory) (bool, error) {
|
|
entries, err := inv.Catalogued(ctx)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
for _, e := range entries {
|
|
if e.Manifest.Module == "mesh-vault" && len(e.On) > 0 {
|
|
return true, nil
|
|
}
|
|
}
|
|
return false, nil
|
|
}
|
|
|
|
// handIssuedToVault hands the value just minted for module's own secret name on node to the vault, when the module's
|
|
// accounts are covered, and does nothing otherwise. Loud when the vault does not take it: the bus's user list
|
|
// already holds the new hash, so a vault that kept the old value would serve a password that no longer logs in.
|
|
func handIssuedToVault(ctx context.Context, inv *inventory.Inventory, m catalogue.Manifest, node, name, held string) error {
|
|
if !accountIsCovered(m) {
|
|
return nil
|
|
}
|
|
if installed, err := vaultInstalled(ctx, inv); err != nil {
|
|
return fmt.Errorf("whether the vault is installed cannot be read, so %s of %s was not handed to it: %w", name,
|
|
m.Module, err)
|
|
} else if !installed {
|
|
return nil
|
|
}
|
|
target := ownSecretArgs(node, m.Module, name)
|
|
target["origin"] = "issued"
|
|
if _, err := acceptIntoVault(vaultAskerForIssue(ctx), target, held, "module issue"); err != nil {
|
|
return fmt.Errorf("the credential is minted and kept here, and the bus's user list holds its hash, but the "+
|
|
"vault did not take %s of %s on %s: %w (`module issue` again hands a new one)", name, m.Module, node, err)
|
|
}
|
|
return nil
|
|
}
|