SSH CA setup
# DRHECK SSH CERTIFICATE IMPLEMENTATION PLAN
### ARCHITECTURE & SECURITY OVERVIEW
* **Authentication Flow:** Incoming SSH clients authenticate using an OpenSSH user certificate signed by the trusted DrHeck User Certificate Authority (CA).
* **LDAP & Authentik Integration:** Host **ul** derives user accounts from Authentik via LDAP (managed via SSSD). When a client presents an SSH certificate, `sshd` validates the certificate signature against the trusted DrHeck CA public key and checks that one of the certificate's valid principals matches the requested LDAP login username. No per-user `~/.ssh/authorized_keys` file is required.
* **Key Storage & Backup:**
* The User CA private key (`drheck_ca_user_key`) and Host CA private key (`drheck_ca_host_key`) must **never** reside on client machines or internet-facing servers (such as **ul**).
* Store the offline CA private keys and passphrases securely in Vaultwarden.
* Deploy only the CA public keys (`drheck_ca_user_key.pub` and `drheck_ca_host_key.pub`) to host **ul** and client machines.
---
### PHASE 1: CA GENERATION & VAULTWARDEN BACKUP
Generate CA Keypairs on a secure offline or admin workstation:
*When prompted by `ssh-keygen`, enter a strong, unique passphrase to encrypt each CA private key.*
```bash
# Generate the User CA keypair
ssh-keygen -t ed25519 -f drheck_ca_user_key -C "drheck-user-ca"
# Generate the Host CA keypair
ssh-keygen -t ed25519 -f drheck_ca_host_key -C "drheck-host-ca"
```
#### Secure Storage in Vaultwarden:
1. Create a secure note or attachment in Vaultwarden containing the private keys (`drheck_ca_user_key`, `drheck_ca_host_key`) and their passphrases.
2. Remove the private CA keys from the unencrypted local storage of your workstation after verifying the backup.
---
### PHASE 2: MAIN SERVER CONFIGURATION (ul)
#### 1. Deploy Trusted User CA Public Key
* Copy the public CA file `drheck_ca_user_key.pub` to host **ul** at `/etc/ssh/drheck_ca_user_key.pub`.
* Set secure permissions:
```bash
sudo chmod 644 /etc/ssh/drheck_ca_user_key.pub
sudo chown root:root /etc/ssh/drheck_ca_user_key.pub
```
#### 2. Configure Host Certificate (Signed by Host CA)
*To keep the private `drheck_ca_host_key` offline, the host key must be signed on your secure workstation:*
1. Copy **ul**'s public host key `/etc/ssh/ssh_host_ed25519_key.pub` to your secure workstation.
2. On your workstation, sign the host key (valid for 52 weeks):
```bash
ssh-keygen -s drheck_ca_host_key -I "drheck-ul-host-cert" -h -n ul,ul.drheck.dev -V +52w ssh_host_ed25519_key.pub
```
3. Copy the resulting certificate `ssh_host_ed25519_key-cert.pub` back to **ul** at `/etc/ssh/ssh_host_ed25519_key-cert.pub`.
4. Set secure permissions on **ul**:
```bash
sudo chmod 644 /etc/ssh/ssh_host_ed25519_key-cert.pub
sudo chown root:root /etc/ssh/ssh_host_ed25519_key-cert.pub
```
#### 3. Configure OpenSSH Daemon on ul
* Create the config file `/etc/ssh/sshd_config.d/10-drheck-certs.conf`:
```bash
sudo vim /etc/ssh/sshd_config.d/10-drheck-certs.conf
```
* Add the following directives to trust incoming User CA certificates and deploy the host certificate:
```text
TrustedUserCAKeys /etc/ssh/drheck_ca_user_key.pub
HostCertificate /etc/ssh/ssh_host_ed25519_key-cert.pub
```
#### 4. Validate and Reload SSHD on ul
* Validate the configuration syntax before reloading:
```bash
sudo sshd -t
```
* If no errors are returned, reload the daemon:
```bash
sudo systemctl reload sshd
```
---
### PHASE 3: CLIENT MACHINE ONBOARDING & SIGNING
#### 1. Client Key Generation
* On the Linux client machine, generate a standard SSH keypair if one doesn't exist:
```bash
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519 -C "client key label"
```
#### 2. Certificate Signing Request
* Transfer **only** the public key (`~/.ssh/id_ed25519.pub`) and the target LDAP username to the DrHeck CA administrator.
#### 3. Sign the Client Public Key
* On the secure workstation, sign the client public key using the vaulted `drheck_ca_user_key` (defining the exact LDAP username as the principal):
```bash
ssh-keygen -s drheck_ca_user_key -I "client-hostname-YYYYMMDD" -n <ldap_username> -V +52w id_ed25519.pub
```
* **`-I`**: Certificate identity string printed in the server's authentication logs.
* **`-n`**: Valid principals; **must** exactly match the target LDAP username on **ul**.
* **`-V +52w`**: Certificate validity duration (e.g., 52 weeks or shorter).
#### 4. Deploy the Client Certificate
* Transfer the generated certificate `id_ed25519-cert.pub` back to the client machine and place it in `~/.ssh/id_ed25519-cert.pub` (alongside the private key).
* Set file permissions on the client:
```bash
chmod 644 ~/.ssh/id_ed25519-cert.pub
```
#### 5. Client SSH Configuration (~/.ssh/config)
* Configure the host entry on the client machine to use the cert automatically:
```text
Host ul
HostName <ul_fqdn_or_ipv6>
User <ldap_username>
IdentityFile ~/.ssh/id_ed25519
```
*(Note: OpenSSH automatically detects and presents `id_ed25519-cert.pub` when utilizing `id_ed25519` if they are in the same folder).*
* **Trusting the Host CA:** Add this line to `/etc/ssh/ssh_known_hosts` (system-wide) or `~/.ssh/known_hosts` on your client machines. This tells the clients to trust **ul**'s host certificate automatically without prompting about finger-prints:
```text
@cert-authority * ssh-ed25519 <drheck_ca_host_key.pub_content>
```
---
### PHASE 4: VERIFICATION & MIGRATION
#### 1. Test Certificate Authentication
* Connect from the client machine with verbose debug output:
```bash
ssh -v ul
```
* Confirm that the client authenticates using the certificate signature:
```text
Server accepts key: pkalg ssh-ed25519-cert-v01@openssh.com
```
#### 2. Migration Strategy
* Keep `PubkeyAuthentication yes` active on **ul** to allow standard `.ssh/authorized_keys` logins during client onboarding.
* Once all clients are verified and migrated, disable legacy `.ssh/authorized_keys` file lookups system-wide by adding the following line to `/etc/ssh/sshd_config.d/10-drheck-certs.conf`:
```text
AuthorizedKeysFile /dev/null
```
*(This keeps standard certificate authentication fully active, but prevents users from logging in via traditional uncertified public keys).*