Skip to main content

ENFORCE AUTHORIZED_KEYS ACROSS HOSTS WITH SWAMP

This guide shows you how to make sure a list of approved SSH public keys is installed on every host, and how to remove a retired key wherever it still appears, using @hivemq/ssh/authorized-keys.

Prerequisites

  • swamp auth login completed
  • A private key that can log in to every host, stored in a Swamp vault (see Storing Secrets). This guide uses a vault named ssh-keys with the key BASTION_KEY.

Pull the extension

swamp extension pull @hivemq/ssh/authorized-keys

You will see output like:

INF extension·pull: Pulling "@swamp/ssh"@"2026.10.13.1"
INF extension·pull: Identity verified: "@swamp/ssh"@"2026.10.13.1"
INF extension·pull: Pulled "@swamp/ssh"@"2026.10.13.1"
INF extension·pull: Extracted 14 files:

Declare the hosts and keys

Create a behavior of type @hivemq/ssh/authorized-keys named bastion-keys (see Create and Run a Behavior). Set state: present on keys that must be installed and state: absent on keys that must be removed. searchPaths sets which directories are scanned for authorized_keys files.

globalArguments:
  privateKey: "${{ vault.get('ssh-keys', 'BASTION_KEY') }}"
  defaultUser: root
  searchPaths:
    - /root/.ssh
    - /home
  hosts:
    - name: bastion-1
      address: 203.0.113.10
    - name: bastion-2
      address: 203.0.113.11
  keys:
    - name: alice
      publicKey: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAliceExampleKey alice@example.com"
      state: present
    - name: bob-old
      publicKey: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBobRetiredKey bob@example.com"
      state: absent

Reference the private key through vault.get() and never write the key body into the definition. If a host needs a different key or user, set privateKey or user on that host entry.

Check compliance

swamp behavior run bastion-keys verify

This command reads every authorized_keys file under searchPaths on every host and changes nothing. It writes a verify resource per host that reports whether each present key is in every file and whether any absent key still appears.

Add the approved keys

swamp behavior run bastion-keys add

This command appends each state: present key to every authorized_keys file that lacks it and writes an addResult resource per host. Keys are matched on algorithm and key body, and the comment is ignored, so running it again adds nothing.

Remove the retired keys

swamp behavior run bastion-keys strip

This command removes each state: absent key from every authorized_keys file and writes a stripResult resource per host. Each file is replaced atomically, so it keeps its ownership and mode.

If you want each file to contain only the present keys, and any key not on the list to be deleted, run the seal method instead of strip. seal is destructive. Run audit first and review the audit resource it writes.

Confirm the result

swamp behavior run bastion-keys verify

This command writes a new verify resource for each host. Every host should now report that it complies.

To limit any of these methods to some of the hosts, pass --input filter=<value>. See the extensions reference for every method and argument.