feat(cli): orca node key-reset <node> — local known_hosts reset (T02.8, REQ-059)
---ci--- project: orca phase: 2 milestone: v0.8 status: execute ---/ci---
This commit is contained in:
@@ -346,6 +346,64 @@ func renderNodeTable(nodes []*model.Node) string {
|
||||
return out
|
||||
}
|
||||
|
||||
var nodeKeyResetCmd = &cobra.Command{
|
||||
Use: "key-reset <node>",
|
||||
Short: "Reset the SSH known_hosts entry for a node",
|
||||
Long: `Remove the pinned SSH host key for <node> from the local known_hosts
|
||||
file. The next connect re-pins the key via TOFU or --host-key-fingerprint.
|
||||
|
||||
LOCAL ONLY (D-046): does not touch the remote host's authorized_keys.
|
||||
|
||||
<node> is the node name (for proxmox nodes, this is the host address).`,
|
||||
Args: cobra.ExactArgs(1),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
nodeArg := args[0]
|
||||
|
||||
registry, closer, err := nodeRegistry()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer closer()
|
||||
|
||||
ctx, cancel := context.WithTimeout(cmd.Context(), 5*time.Second)
|
||||
defer cancel()
|
||||
|
||||
nodes, err := registry.List(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("list nodes: %w", err)
|
||||
}
|
||||
var node *model.Node
|
||||
for _, n := range nodes {
|
||||
if n.Name == nodeArg || n.ID == nodeArg {
|
||||
node = n
|
||||
break
|
||||
}
|
||||
}
|
||||
if node == nil {
|
||||
return fmt.Errorf("node %q not found in the registry", nodeArg)
|
||||
}
|
||||
host := node.Name
|
||||
|
||||
if err := proxmox.ResetHostKey(host); err != nil {
|
||||
return fmt.Errorf("reset host key: %w", err)
|
||||
}
|
||||
|
||||
// Audit-log the reset (REQ-059): actor=cli, action=node.key_reset.
|
||||
db, dbCloser, dbErr := openDB()
|
||||
if dbErr == nil {
|
||||
defer dbCloser()
|
||||
audit := engine.NewAudit(store.NewAuditRepo(db), newLogger())
|
||||
audit.Record(ctx, "cli", "node.key_reset", node.ID, "success", nil, map[string]any{
|
||||
"node": node.Name,
|
||||
"host": host,
|
||||
})
|
||||
}
|
||||
|
||||
fmt.Fprintf(cmd.OutOrStdout(), "✓ Host key reset for %s (next connect will re-pin via TOFU or --host-key-fingerprint)\n", node.Name)
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
nodeJoinCmd.Flags().StringVar(&joinName, "name", "", "node name (required for --type localhost)")
|
||||
nodeJoinCmd.Flags().StringVar(&joinAddr, "addr", "", "node address (default localhost:8443)")
|
||||
@@ -364,5 +422,6 @@ func init() {
|
||||
nodeCmd.AddCommand(nodeJoinCmd)
|
||||
nodeCmd.AddCommand(nodeLeaveCmd)
|
||||
nodeCmd.AddCommand(nodeListCmd)
|
||||
nodeCmd.AddCommand(nodeKeyResetCmd)
|
||||
rootCmd.AddCommand(nodeCmd)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user