Securely controlling SSH access to your servers is critical. HashiCorp Vault can act as a central SSH Certificate Authority (CA), allowing you to issue signed user keys, enforce TTLs, and avoid distributing static SSH keys.
Enable the SSH engine at a chosen mount point:
vault secrets enable -path=ssh ssh
ssh
mount point manages Vault’s SSH CA and key signing.vault write ssh/config/ca generate_signing_key=true
vault read -field=public_key ssh/config/ca > vault-ca.pub
vault-ca.pub
file is distributed to your VMs.The last command outputs a public key that should go in the /etc/ssh directory of your Linux virtual machine. However, it wouldn’t be very convenient to load it manually on every device. I handle this through a snippet on the Proxmox hypervisor.
You can create a YAML config file and place it in the /var/lib/vz/snippets directory of your Proxmox host. If you already have a cloud image template, you can attach a snippet, and the public key will be loaded into each virtual machine at boot time.
Example Snippet
# user-data.yaml
users:
- name: user
passwd: mkpasswd --method=SHA-256 password
lock_passwd: false
ssh_authorized_keys:
- Paste SSH Public Key
sudo: ALL=(ALL) NOPASSWD:ALL
shell: /bin/bash
- name: ansible
ssh_authorized_keys:
- Paste SSH Public Key
sudo: ALL=(ALL) NOPASSWD:ALL
shell: /bin/bash
package_update: true
package_upgrade: true
write_files:
- path: /etc/ssh/vault-ca.pub
content: |
Paste Public Key here
permissions: '0644'
bootcmd:
- echo "TrustedUserCAKeys /etc/ssh/vault-ca.pub" >> /etc/ssh/sshd_config
runcmd:
- systemctl restart ssh
Assuming your cloud image template has an ID of 1000:
qm set 1000 --cicustom "user=local:snippets/user-data.yaml"
Note: This method doesn’t mesh well with Cloud-Init in the GUI. Either use snippets to configure your cloud images, or use the GUI and leave additional configurations to Ansible and other configuration tools.
Define an SSH role in Vault. This role controls which users can request signed certificates and sets the TTL (time-to-live) for the certificates:
Example:
vault write ssh/roles/dev-role \
key_type=ca \
allow_user_certificates=true \
allowed_users=”ansible,darnell” \
default_user=”ansible” \
ttl=”1h” \
max_ttl=”24h”
Generate an SSH Key Pair and Sign the Key
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_demo
Sign the key for the ansible
user:
vault write -field=signed_key ssh/sign/dev-role \
public_key=@/home/darnell/.ssh/id_ed25519_demo.pub \
username=ansible \
> /home/darnell/.ssh/id_ed25519_demo-cert.pub
Set the permissions:
chmod 600 ~/.ssh/id_ed25519_demo
chmod 644 ~/.ssh/id_ed25519_demo-cert.pub
Test SSH access using the signed certificate(s):
ssh -i ~/.ssh/id_ed25519_demo -i ~/.ssh/id_ed25519_demo-cert.pub ansible@IP/Hostname
© NAXS Labs All Rights Reserved