#!/usr/bin/env nu def main [ --workspace: string = "" --key-type: string = "" --new-key-path: string = "" --ops-vm-host: string = "" --dry-run ]: nothing -> nothing { let ws = if ($workspace | is-not-empty) { $workspace } else { $env.PLAYBOOK_PARAM_WORKSPACE? | default "" } let ktype = if ($key_type | is-not-empty) { $key_type } else { $env.PLAYBOOK_PARAM_KEY_TYPE? | default "" } let key_path = if ($new_key_path | is-not-empty) { $new_key_path } else { $env.PLAYBOOK_PARAM_NEW_KEY_PATH? | default "" } let vm_host = if ($ops_vm_host | is-not-empty) { $ops_vm_host } else { $env.PLAYBOOK_PARAM_OPS_VM_HOST? | default "" } if ($ws | is-empty) { error make { msg: "workspace is required" } } if ($ktype | is-empty) { error make { msg: "key-type is required" } } if ($key_path | is-empty) { error make { msg: "new-key-path is required" } } if $dry_run { print $"[dry-run] would activate ($ktype) key from ($key_path) for workspace ($ws)" return } match $ktype { "ops-controller" => { let secret_name = $"ops-controller-key-($ws)" let key_b64 = open $key_path | ^base64 | str trim let patch_json = $"{\"data\":{\"private-key\":\"($key_b64)\"}}" let patch_r = do { ^kubectl patch secret $secret_name --namespace "ops-system" --patch $patch_json } | complete if $patch_r.exit_code != 0 { error make { msg: $"kubectl patch secret failed: ($patch_r.stderr | str trim)" } } let restart_r = do { ^kubectl rollout restart deployment/ops-controller --namespace "ops-system" } | complete if $restart_r.exit_code != 0 { error make { msg: $"ops-controller restart failed: ($restart_r.stderr | str trim)" } } print $"ops-controller restarted with new key — rollout in progress" } "keeper" => { if ($vm_host | is-empty) { error make { msg: "ops-vm-host is required for keeper key rotation" } } let upload_r = do { ^scp $key_path $"($vm_host):/etc/keeper/signing.key.tmp" } | complete if $upload_r.exit_code != 0 { error make { msg: $"Failed to upload new keeper key: ($upload_r.stderr | str trim)" } } let move_r = do { ^ssh $vm_host "mv /etc/keeper/signing.key.tmp /etc/keeper/signing.key && chmod 600 /etc/keeper/signing.key" } | complete if $move_r.exit_code != 0 { error make { msg: $"Failed to move key into place on ($vm_host): ($move_r.stderr | str trim)" } } let restart_r = do { ^ssh $vm_host "systemctl restart keeper-daemon" } | complete if $restart_r.exit_code != 0 { error make { msg: $"keeper-daemon restart failed: ($restart_r.stderr | str trim)" } } print $"keeper-daemon restarted on ($vm_host) with new signing key" } "operator" => { print "operator key rotation: new NATS JWT must be issued separately via onboard_operator playbook" print "This step marks the new operator pubkey as active in the delegation set" } _ => { error make { msg: $"Unknown key-type: ($ktype)" } } } }