When integrating LDAP authentication with SSH via pam_ldap, administrators face a common workflow bottleneck: while authentication works seamlessly, local account creation remains a manual step. After adding a user to LDAP, you still need to run useradd
or adduser
on each target server.
The solution lies in PAM's capabilities through the pam_mkhomedir.so
module. This module can automatically create home directories upon first login, but with some configuration tweaks, we can extend this to full account creation.
# /etc/pam.d/sshd configuration
session required pam_mkhomedir.so skel=/etc/skel/ umask=0022
For full automation, combine these components:
- Configure PAM to create home directories
- Use SSSD (System Security Services Daemon) for better LDAP integration
- Implement name service switches to handle user resolution
Here's a complete configuration example:
# /etc/sssd/sssd.conf
[sssd]
services = nss, pam
domains = yourdomain.com
[domain/yourdomain.com]
id_provider = ldap
auth_provider = ldap
ldap_uri = ldap://server1.yourdomain.com
ldap_search_base = dc=yourdomain,dc=com
ldap_user_home_directory = /home/%u
cache_credentials = True
For production environments, consider these enhancements:
# Ensure proper permissions for auto-created homes
session required pam_umask.so umask=0077
# Log creation events for auditing
session optional pam_exec.so /usr/local/bin/log_home_creation.sh
For more control, the pam_script module allows executing custom scripts during authentication:
# /etc/pam.d/sshd addition
session optional pam_script.so onerr=fail
# Sample script (/etc/pam_script)
#!/bin/bash
if [ "$PAM_TYPE" = "open_session" ]; then
if ! id -u "$PAM_USER" >/dev/null 2>&1; then
useradd -m -s /bin/bash "$PAM_USER"
fi
fi
Always ensure:
- Home directory permissions are restrictive
- UID/GID numbering doesn't conflict with system accounts
- Process is logged for audit purposes
When implementing LDAP authentication for SSH access, we often face a chicken-and-egg problem: users exist in LDAP but don't have local accounts on the target server. While pam_ldap
handles authentication, we still need local accounts for proper home directories and system permissions.
The simplest approach uses PAM's pam_mkhomedir.so
module. Add this line to your /etc/pam.d/sshd
file:
session required pam_mkhomedir.so skel=/etc/skel umask=0022
This automatically creates home directories when users first log in. However, it doesn't handle other system account requirements.
For complete account creation, we can use pam_exec
to trigger a script:
auth required pam_exec.so /usr/local/bin/ldap_user_sync.sh
Here's a sample sync script:
#!/bin/bash
# /usr/local/bin/ldap_user_sync.sh
LDAP_USER="$1"
if ! id "$LDAP_USER" >/dev/null 2>&1; then
# User doesn't exist locally
USER_ENTRY=$(ldapsearch -x "uid=$LDAP_USER" | grep -A 5 '^dn:')
UID_NUMBER=$(echo "$USER_ENTRY" | grep 'uidNumber:' | awk '{print $2}')
GID_NUMBER=$(echo "$USER_ENTRY" | grep 'gidNumber:' | awk '{print $2}')
useradd -m -u "$UID_NUMBER" -g "$GID_NUMBER" "$LDAP_USER"
mkdir -p "/home/$LDAP_USER/.ssh"
chmod 700 "/home/$LDAP_USER/.ssh"
fi
exit 0
System Security Services Daemon (SSSD) provides more elegant LDAP integration:
# /etc/sssd/sssd.conf
[sssd]
services = nss, pam
domains = example.com
[domain/example.com]
id_provider = ldap
auth_provider = ldap
ldap_uri = ldap://ldap.example.com
ldap_search_base = dc=example,dc=com
ldap_id_use_start_tls = True
ldap_tls_reqcert = allow
cache_credentials = True
entry_cache_timeout = 600
ldap_network_timeout = 3
When implementing automatic account creation:
- Set proper umask values (022 or 027)
- Restrict SSH access to specific LDAP groups
- Implement rate limiting to prevent brute force attacks
- Consider using SELinux or AppArmor for additional protection
If things don't work as expected:
tail -f /var/log/auth.log
journalctl -f -u sshd
pam_tally2 --user username
getent passwd username