The Static Key Sprawl Problem
I recently audited a mid-sized Indian fintech firm where I discovered over 4,500 unique entries in various authorized_keys files across their production fleet. Many of these keys belonged to former employees or third-party consultants who had left the project months prior. This is the "N+1" problem of SSH management: for every new user or server, the complexity of key distribution grows exponentially. Without hardening SSH and terminal access, managing this via configuration management tools like Ansible or Terraform often results in race conditions or, worse, orphaned keys that provide permanent backdoors into the infrastructure.
We observed that static SSH keys are essentially "infinite" credentials. Unless someone manually removes the public key from the target server, that key remains valid forever. In the context of the DPDP Act 2023, this lack of lifecycle management represents a significant compliance risk for Indian data fiduciaries. SSH certificate-based authentication solves this by moving from a decentralized trust model to a centralized, identity-driven system where access is inherently ephemeral.
What is SSH Certificate-Based Authentication?
Unlike standard SSH key-based authentication where the server must pre-possess your public key, certificate-based authentication relies on a Trusted Certificate Authority (CA). The server does not need to know who you are beforehand; it only needs to trust the CA that signed your key. This is conceptually similar to how HTTPS works with TLS certificates, but it is implemented specifically within the OpenSSH protocol (specifically protocol version 2).
When a user attempts to connect, they present a "certificate"—which is their public key bundled with metadata like identity, permissions, and an expiration timestamp—all signed by the CA's private key. The server verifies the signature using the CA's public key. If the signature is valid and the certificate hasn't expired, access is granted. This eliminates the need to manage ~/.ssh/authorized_keys files entirely.
Key Terminology: CA, User Certificates, and Host Certificates
- Certificate Authority (CA): A dedicated SSH key pair (usually Ed25519) kept in a highly secure environment. The private key signs certificates, while the public key is distributed to all servers.
- User Certificates: These are issued to developers or sysadmins. They contain the user's identity (principals) and a strictly defined validity period (e.g., 8 hours).
- Host Certificates: These allow servers to prove their identity to users. This eliminates the "Host key verification failed" or "Unknown host" warnings that users typically ignore by typing "yes", which is a common vector for Man-in-the-Middle (MITM) attacks.
- Principals: These are the usernames (e.g.,
ubuntu,root,ec2-user) that the certificate holder is allowed to log in as.
SSH Key-Based Authentication vs. Password vs. Certificates
Passwords are the weakest link. In our monitoring of cloud-facing Indian infrastructure, we see automated brute-force attempts within seconds of a public IP being assigned. CERT-In frequently highlights credential stuffing as a primary entry point for ransomware. While standard SSH keys mitigate brute-force risks, they fail at scale. If a developer's laptop is stolen, every server they have access to must be manually updated to revoke their public key.
The Limitations of Standard SSH Keys in Large Environments
In a standard setup, the authorized_keys file acts as a static database. We've seen this lead to several operational failures:
- Key Rotation Failure: Most organizations never rotate SSH keys because the risk of locking themselves out of 1,000 servers is higher than the perceived risk of a compromised key.
- Lack of Expiry: A key generated in 2018 is still valid in 2024 unless explicitly deleted.
- No Context: A public key is just a string of characters. It doesn't tell you who owns it or why they have access.
The Advantages of SSH Cert-Based Authentication for Scalability
Certificates introduce "Trust at Scale." By placing a single CA public key on every server (a one-time configuration), you gain the ability to issue thousands of unique, short-lived access tokens without ever touching the servers again. This aligns with secure SSH access for teams and the "Zero Trust" architecture guidelines emphasized by MeitY, where trust is never permanent and must be re-validated frequently.
Setting Up SSH Certificate-Based Authentication on Linux
We will use a dedicated Ubuntu 22.04 LTS instance as our "CA Server." In a production environment, this server should be air-gapped or protected by heavy MFA and hardware security modules (HSMs). For this guide, we will perform the operations via the command line to demonstrate the underlying mechanics.
Step 1: Creating the Trusted Certificate Authority (CA)
First, log into your CA server and generate the CA key pair. We use Ed25519 for its superior security profile and smaller key size compared to RSA.
# Generate the CA key pair
Use a strong passphrase for the CA key
ssh-keygen -t ed25519 -f /etc/ssh/ssh_ca_key -C "SSH Certificate Authority"
Set restrictive permissions
chmod 600 /etc/ssh/ssh_ca_key chmod 644 /etc/ssh/ssh_ca_key.pub
Step 2: Configuring the Target Servers (Host Configuration)
Every server in your infrastructure must be told to trust certificates signed by this CA. You need to copy the ssh_ca_key.pub (the public part only) to every target server. We usually place this in /etc/ssh/trusted-user-ca-keys.pem.
# On the target server:
1. Paste the content of ssh_ca_key.pub into /etc/ssh/trusted-user-ca-keys.pem
2. Update /etc/ssh/sshd_config
echo "TrustedUserCAKeys /etc/ssh/trusted-user-ca-keys.pem" >> /etc/ssh/sshd_config
Restart the SSH service to apply changes
systemctl restart ssh
Step 3: Signing a User Key
When a user needs access, they generate a standard SSH key pair on their local machine and send the public key to the CA. The CA then signs it. I recommend a short validity period—for example, 1 working day (+24h) or even just a few hours.
# On the CA Server:
Sign the user's public key (id_ed25519.pub)
-I: Identity (used for logging)
-n: Principals (usernames allowed)
-V: Validity (start time to end time)
ssh-keygen -s /etc/ssh/ssh_ca_key \ -I "dev-user-01" \ -n "ubuntu,ec2-user" \ -V +1d \ id_ed25519.pub
This command generates a new file named id_ed25519-cert.pub. The user must place this file in the same directory as their private key (~/.ssh/). When they run ssh user@server, the SSH client automatically presents this certificate to the server.
Implementing SSH Authentication for Specific Use Cases
The flexibility of certificates allows for granular control that static keys cannot match. We can restrict what a user can do even after they have successfully authenticated. This is critical for meeting the "Purpose Limitation" requirements of modern data protection laws.
Configuring SSH Certificate-Based Authentication for SFTP
If you have third-party vendors in India or abroad who need to upload files via SFTP, you can issue certificates that are restricted to SFTP only. This prevents them from gaining a shell environment if their credentials are compromised.
# Sign a key restricted to SFTP only
We use the -O option to force a command
ssh-keygen -s /etc/ssh/ssh_ca_key \ -I "vendor-transfer-01" \ -n "sftpuser" \ -V +52w \ -O force-command="/usr/lib/openssh/sftp-server" \ vendor_key.pub
Managing SSH Certificates on Windows Systems
Windows 10/11 and Windows Server 2019+ now include OpenSSH by default. The process for using certificates is identical to Linux, but the file paths differ. We observed that many Windows users struggle because the SSH agent doesn't automatically pick up the -cert.pub file unless it's explicitly added.
# On Windows PowerShell
Add the private key to the agent
ssh-add C:\Users\Admin\.ssh\id_ed25519
Verify the certificate is recognized
ssh-add -L
Automating Certificate Issuance for Linux Servers
Manual signing is a bottleneck. In high-velocity environments, we use tools like HashiCorp Vault's SSH Secrets Engine. It acts as the CA and integrates with your existing Identity Provider (like Okta, Azure AD, or Google Workspace). A developer authenticates with their corporate ID, and Vault issues a 5-minute certificate directly to their SSH agent.
# Example workflow with Vault
vault login -method=oidc vault write -field=signed_key ssh-client-signer/sign/developer-role \ public_key=@$HOME/.ssh/id_ed25519.pub > $HOME/.ssh/id_ed25519-cert.pub
Best Practices for SSH Certificate Management
Implementing certificates is only half the battle. Without proper lifecycle management, you've simply moved the problem from the servers to the CA. We follow a strict set of operational procedures to ensure the integrity of the CA.
Setting Expiration Dates for Enhanced Security
Never issue "forever" certificates. Even for automated service accounts, we recommend a maximum validity of 30 to 90 days. For human users, 8 to 12 hours is the gold standard. This ensures that if a laptop is compromised at 6:00 PM, the attacker's access automatically expires by the next morning without any manual intervention.
Handling Certificate Revocation Lists (CRL)
What if you need to revoke access immediately? OpenSSH supports a RevokedKeys directive in sshd_config. This points to a file containing a list of revoked public keys or certificate blobs. We recommend automating the distribution of this file via a cron job or configuration management tool.
# To revoke a key, add it to a file and update sshd_config
/etc/ssh/sshd_config
RevokedKeys /etc/ssh/revoked-keys
To generate the revocation list from a certificate:
ssh-keygen -k -f /etc/ssh/revoked-keys id_ed25519-cert.pub
Monitoring and Auditing SSH Access Logs
Certificates provide much richer logs than standard keys. Because we use the -I (Identity) flag during signing, the server's auth logs will show exactly which certificate was used, including its unique ID. This is vital for forensic investigations and comprehensive log monitoring and threat detection in the event of an incident.
# Example log output in /var/log/auth.log
$ tail -f /var/log/auth.log | grep "Accepted certificate"
Output: Accepted certificate ID "dev-user-01" (serial 0) signed by CA ED25519 ...
Validating the Certificate Metadata
Before deploying a certificate, I always verify its contents. The ssh-keygen -L command is your primary tool for inspecting what permissions have actually been granted. This prevents "principal confusion" where a user might accidentally be granted root access when they only needed access to a specific application user.
# Inspecting a certificate
$ ssh-keygen -L -f ~/.ssh/id_ed25519-cert.pub
Expected Output:
Type: [email protected] user certificate
Public key: ED25519-CERT SHA256:xxxx...
Signing CA: ED25519 SHA256:yyyy...
Key ID: "dev-user-01"
Serial: 0
Valid: from 2023-10-27T10:00:00 to 2023-10-28T10:00:00
Principals:
ubuntu
ec2-user
Critical Options: (none)
Extensions:
permit-X11-forwarding
permit-agent-forwarding
permit-port-forwarding
permit-pty
permit-user-rc
If you see (none) under Principals, it means the certificate is valid for any user on the server, which is a massive security hole. Always specify principals. In Indian enterprise environments, we often map principals to specific JIRA ticket IDs or employee codes for auditability.
Hardening the SSH Daemon for Certificate-Only Access
Once your certificate infrastructure is stable, the final step is to disable all other forms of authentication. This forces all users through the CA, ensuring that no "shadow" keys or weak passwords exist. We've seen this significantly reduce the attack surface for servers exposed to the public internet.
# /etc/ssh/sshd_config hardening
Only allow CA-based authentication
PasswordAuthentication no PubkeyAuthentication yes AuthorizedKeysFile /dev/null TrustedUserCAKeys /etc/ssh/trusted-user-ca-keys.pem
Mitigate CVE-2024-6387 (regreSSHion) by setting LoginGraceTime
Note: Ensure you are on a patched OpenSSH version (9.8p1+)
LoginGraceTime 0
By setting AuthorizedKeysFile to /dev/null, you effectively ignore any keys that might have been manually added to ~/.ssh/authorized_keys, forcing a clean slate across the entire environment. This is a bold move and should only be done after verifying that your CA distribution is 100% reliable.
Addressing CVE-2024-6387 (regreSSHion)
While certificate-based authentication doesn't directly patch the signal handler race condition in sshd known as regreSSHion, it is a key component of a hardened SSH strategy. Most organizations that move to certificates also implement automated patching and infrastructure-as-code. In our testing, servers that are configured with certificates and have LoginGraceTime set to 0 are significantly harder to exploit because the attack window for the race condition is minimized or eliminated, as documented in the NIST NVD.
Furthermore, the use of certificates allows for easier "Emergency Rotation." If a vulnerability is found in the specific key type you are using (e.g., a theoretical flaw in Ed25519), you only need to update the CA and issue new certificates, rather than touching every single server to replace thousands of individual keys.
Migrating from Static Keys to Certificates
The migration shouldn't happen overnight. We recommend a phased approach that minimizes the risk of lockout for your engineering teams. Start by enabling the CA alongside existing keys, then slowly phase out the static keys as teams adopt the new workflow.
- Phase 1: Deploy the CA public key to all servers. Keep
AuthorizedKeysFileactive. - Phase 2: Issue long-lived certificates (e.g., 1 month) to a pilot group of senior sysadmins.
- Phase 3: Implement a self-service portal (like Smallstep or Vault) for short-lived certificates.
- Phase 4: Monitor logs for any remaining usage of static keys. Contact those users and migrate them.
- Phase 5: Disable
AuthorizedKeysFileand enforce certificate-only access.
In terms of cost, moving to an open-source certificate model saves significant INR compared to commercial "privileged access management" (PAM) suites that charge per-user or per-node. The primary investment is the engineering time required to set up the automation and the CA security controls.
The technical overhead of managing authorized_keys is a debt that eventually comes due, usually in the form of a security breach or a failed compliance audit. By switching to SSH certificates, you treat access as a dynamic, verifiable attribute rather than a static piece of data. This is the only way to maintain a secure remote access posture as your infrastructure grows from tens to thousands of nodes.
Next Command: Run ssh-keygen -L -f ~/.ssh/id_ed25519-cert.pub on your current work machine to see if your organization is already using certificates or still relying on legacy static keys.
