Replace a value given by hand like one the mesh made (hq ADR 0228)
A given own secret the module reads at start is held by nobody but that module, so the mesh need not read it to replace it: secret rotate now works on it, and a value given through secret accept is replaced on its own after the module's first good start under the mesh. Only a value an outside party issues (own-secrets "issued-by": "outside") or one the module applies stays as given, refused with the reason.
This commit is contained in:
@@ -93,18 +93,31 @@ func secretCommand(ctx context.Context, args []string) error {
|
||||
fmt.Printf(" run `push %s` and `push %s` to send it\n", *provider, node)
|
||||
return nil
|
||||
}
|
||||
if err := open.inventory.AcceptSecretForModule(ctx, node, module, name, value); err != nil {
|
||||
untilStart, err := open.inventory.AcceptGivenSecret(ctx, node, module, name, value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Not printed back, and there is nowhere it could be printed from: it is sealed to that
|
||||
// machine and the mesh cannot read it again.
|
||||
fmt.Printf("%s on %s now holds %q, sealed to that machine.\n", module, node, name)
|
||||
fmt.Printf(" the mesh cannot read it back, and will not replace it with one of its own\n")
|
||||
if untilStart {
|
||||
// Accepted, and said what it is for (novox/hq ADR 0228): a value given by hand adopts
|
||||
// something that already holds it, and lives only until the module has started on it.
|
||||
fmt.Printf(" it lives until %s next starts well under the mesh on it, and is then replaced with a value\n"+
|
||||
" the mesh makes, sealed and sent (ADR 0228): a value given by hand is for adopting something\n"+
|
||||
" already running that holds it\n", module)
|
||||
if record, err := open.inventory.NodeByName(ctx, node); err == nil && !record.Adopted {
|
||||
fmt.Printf(" %s is not an adopted machine: if %s is installed fresh there, it needs no given value —\n"+
|
||||
" the mesh makes one at the first push\n", node, module)
|
||||
}
|
||||
} else {
|
||||
fmt.Printf(" the mesh cannot read it back, and will not replace it with one of its own\n")
|
||||
}
|
||||
fmt.Printf(" run `push %s` to send it\n", node)
|
||||
return nil
|
||||
}
|
||||
|
||||
const secretUsage = "secret rotate <node> <module> <name>\n" +
|
||||
const secretUsage = "secret rotate <node> <module> <name> [--why <text> [--cause <word>]]\n" +
|
||||
"secret accept <node> <module> <name> [--from <file>] [--provider <node> [--local <name>]]\n" +
|
||||
"secret recover <node> <module> <name> --key <operator-key> [--out <file>] [--from-export <file>] [--provider <node>]\n" +
|
||||
"secret export [--out <file>]"
|
||||
@@ -367,9 +380,20 @@ func valueFor(node, module, name, from string) (string, error) {
|
||||
// secretRotate makes a module's own secret anew and sends the machine, so the module starts again on
|
||||
// the new value (novox/hq ADR 0114, issue 180). A pair credential rotates with `rotate <provision>`;
|
||||
// this is the secret with one party. Said in the log with who asked and when, never the value.
|
||||
//
|
||||
// **A value given to the mesh rotates the same way** (novox/hq ADR 0228): what a module reads at start
|
||||
// is held by nobody else, so the old value is not needed to replace it. Refused for a value an
|
||||
// outside party issued, which no value of the mesh's would replace. Why it was rotated is recorded in
|
||||
// the hand-act log when given — a rotation asked by a person is an act by hand, and a leak is a cause
|
||||
// worth counting.
|
||||
func secretRotate(ctx context.Context, args []string) error {
|
||||
rest, _ := split(args)
|
||||
if len(rest) != 3 {
|
||||
rest, flags := split(args)
|
||||
set := flag.NewFlagSet("secret rotate", flag.ContinueOnError)
|
||||
why := addHandActFlags(set)
|
||||
if err := set.Parse(flags); err != nil {
|
||||
return err
|
||||
}
|
||||
if len(rest) != 3 || set.NArg() != 0 {
|
||||
return errors.New(secretUsage)
|
||||
}
|
||||
node, module, name := rest[0], rest[1], rest[2]
|
||||
@@ -378,6 +402,10 @@ func secretRotate(ctx context.Context, args []string) error {
|
||||
return err
|
||||
}
|
||||
defer open.Close()
|
||||
origin, given, err := open.inventory.OwnSecretOrigin(ctx, node, module, name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := open.inventory.RotateModuleSecret(ctx, node, module, name); err != nil {
|
||||
var refused inventory.ErrNotRotatable
|
||||
if errors.As(err, &refused) {
|
||||
@@ -385,8 +413,13 @@ func secretRotate(ctx context.Context, args []string) error {
|
||||
}
|
||||
return err
|
||||
}
|
||||
why.record(ctx, "secret rotate", []string{node, module, name})
|
||||
fmt.Printf("rotated %q of %s on %s at %s, asked by %s; the value is sealed and not shown\n",
|
||||
name, module, node, time.Now().UTC().Format(time.RFC3339), whoAsked())
|
||||
if origin == inventory.OriginAccepted {
|
||||
fmt.Printf(" it replaces the value given to the mesh on %s: the mesh made this one, so `secret rotate` "+
|
||||
"replaces it again whenever asked (ADR 0228)\n", given.UTC().Format("2006-01-02"))
|
||||
}
|
||||
// A shared credential (ADR 0158) has as many holders as the provision has consumers, and all
|
||||
// of them are sent in one act, so no machine is left reading a value the provider no longer takes.
|
||||
machines, err := open.inventory.SharedHolders(ctx, node, module, name)
|
||||
|
||||
Reference in New Issue
Block a user