Enforcing SSH Public Key Authentication for Specific Users While Maintaining Password Login for Others


43 views

In enterprise environments, we often face the challenge of balancing security and usability for SSH access. While public key authentication with passphrases provides stronger security than password-only authentication, forcing all users to use key-based authentication might create unnecessary friction for regular users.

The sshd_config file doesn't directly expose user-specific authentication policies, but we can achieve this through several clever techniques:

# Basic SSH authentication configuration
PubkeyAuthentication yes
PasswordAuthentication yes

The most elegant solution involves using Match User or Match Group directives:

# Allow password authentication for everyone by default
PasswordAuthentication yes

# Force public key for sudoers
Match User admin1,admin2
    PasswordAuthentication no
    AuthenticationMethods publickey

Match Group sudo
    PasswordAuthentication no
    AuthenticationMethods publickey

For more dynamic control, combine with a custom script:

Match Group sudo
    AuthorizedKeysCommand /usr/local/bin/check_sudoer_keys
    AuthorizedKeysCommandUser nobody
    PasswordAuthentication no

Sample script (/usr/local/bin/check_sudoer_keys):

#!/bin/bash
if [[ "$1" == "admin" ]]; then
    cat /home/admin/.ssh/authorized_keys
else
    exit 1
fi

For complex environments, consider PAM modules:

# In /etc/pam.d/sshd
auth [success=1 default=ignore] pam_succeed_if.so user ingroup sudo
auth required pam_deny.so

Always test changes thoroughly:

sudo sshd -t
sudo systemctl restart sshd
ssh -v user@localhost

Remember to:

  • Set proper permissions for authorized_keys files (600)
  • Use strong passphrases for keys
  • Consider implementing 2FA for privileged users
  • Regularly rotate keys

When hardening SSH server security, administrators often face a dilemma: public key authentication provides stronger security (especially when combined with passphrases), but forcing all users to use it might create unnecessary complexity for non-privileged accounts. The ideal solution would be implementing different authentication requirements based on user roles.

The OpenSSH server provides several mechanisms to achieve selective authentication enforcement. Here's the most reliable method using Match blocks in /etc/ssh/sshd_config:

# Default: allow password authentication for regular users
PasswordAuthentication yes

# Special rules for sudoers group
Match Group sudoers
    PasswordAuthentication no
    AuthenticationMethods publickey
    PubkeyAuthentication yes

For more granular control when you need to target specific users rather than groups:

Match User admin1,admin2,deploy-user
    PasswordAuthentication no
    AuthenticationMethods publickey

SSH allows combining multiple matching criteria for complex scenarios:

Match Group admins User !backup-admin Address 192.168.1.*
    PasswordAuthentication no
    AuthenticationMethods publickey

After modifying sshd_config, always test your configuration before restarting the service:

sudo sshd -t
sudo systemctl restart sshd
  • Ensure target users have their public keys in ~/.ssh/authorized_keys
  • Check file permissions (600 for authorized_keys, 700 for ~/.ssh)
  • Verify SELinux/AppArmor isn't blocking key access
  • Inspect auth logs (/var/log/auth.log or /var/log/secure) for errors

For more advanced scenarios, you can integrate with PAM:

auth [success=1 default=ignore] pam_ssh_user_auth.so
auth required pam_deny.so

This approach requires additional setup but offers more flexibility in complex environments.