| Crates.io | ssh-auth-common |
| lib.rs | ssh-auth-common |
| version | 0.1.0 |
| created_at | 2025-06-09 11:40:02.029913+00 |
| updated_at | 2025-06-09 11:40:02.029913+00 |
| description | Common types and utilities for ssh-auth-cmd suite |
| homepage | https://github.com/epiphyte2/ssh-auth-cmd |
| repository | https://github.com/epiphyte2/ssh-auth-cmd |
| max_upload_size | |
| id | 1705812 |
| size | 27,642 |
ssh-auth-cmd is a Rust application designed to chain multiple SSH AuthorizedKeysCommand configurations, since OpenSSH only supports configuring a single one. The new version supports individual configuration files, user switching, comprehensive OpenSSH placeholder support, and automatic installation.
cargo build --release
sudo cp target/release/ssh-auth-cmd /usr/local/bin/
sudo chmod +x /usr/local/bin/ssh-auth-cmd
sudo /usr/local/bin/ssh-auth-cmd install
Or with a specific user:
sudo /usr/local/bin/ssh-auth-cmd install --user nobody
Commands are now configured in individual TOML files in /etc/ssh/auth_cmd.d/:
/etc/ssh/auth_cmd.d/
├── 01-local-keys.toml
├── 02-ldap-keys.toml
├── 03-database-keys.toml
└── 99-emergency-keys.toml
Files are processed in alphabetical order, so you can use prefixes to control execution order.
Each configuration file contains a single command definition:
/etc/ssh/auth_cmd.d/01-local-keys.tomlname = "local_keys"
command = "cat"
args = ["/home/%u/.ssh/authorized_keys"]
enabled = true
timeout = 30
user = "nobody"
readonly = false
/etc/ssh/auth_cmd.d/02-ldap-keys.tomlname = "ldap_keys"
command = "/usr/local/bin/ldap-ssh-keys"
args = ["--user", "%u", "--hostname", "%h", "--connection", "%C"]
enabled = true
timeout = 60
user = "ldap-user"
readonly = false
/etc/ssh/auth_cmd.d/03-audit-only.tomlname = "audit_logger"
command = "/usr/local/bin/ssh-audit-log"
args = ["--user", "%u", "--key-type", "%t", "--fingerprint", "%f"]
enabled = true
timeout = 10
user = "audit"
readonly = true # Don't include output in authorized keys
name: A descriptive name for the commandcommand: The command/script to executeargs: Array of arguments to pass to the commandenabled: Whether this command is enabled (default: true)timeout: Timeout in seconds for command execution (default: 30)user: UNIX user to run the command as (only when ssh-auth-cmd runs as root)readonly: If true, discard stdout output (useful for logging/auditing)The following OpenSSH placeholders are supported in the args array:
%C: Connection specification (user, client IP, client port, server IP, server port)%D: Routing domain%f: Key fingerprint%h: Hostname%t: Key type%U: Original username (before any transformations)%u: Username being authenticated%%: Literal % charactername = "comprehensive_auth"
command = "/usr/local/bin/auth-checker"
args = [
"--user", "%u",
"--original-user", "%U",
"--hostname", "%h",
"--connection", "%C",
"--key-type", "%t",
"--fingerprint", "%f",
"--key", "%k",
"--domain", "%D",
"--literal-percent", "%%"
]
When using the install command, ssh-auth-cmd configures OpenSSH as:
AuthorizedKeysCommand /usr/local/bin/ssh-auth-cmd key-cmd -c %C -D %D -f %f -h %h -k %k -t %t -U %U -u %u
AuthorizedKeysCommandUser root
This exhaustively uses all OpenSSH substitution variables currently defined.
When ssh-auth-cmd runs as root (recommended), you can specify different users for each command:
user is specified in a command config, that command runs as the specified useruser is not specified, the command runs as the same user as ssh-auth-cmdssh-auth-cmd is not running as root, the user field is ignoredThis allows for principle of least privilege - each command can run with only the permissions it needs.
ssh-auth-cmd key-cmd -c %C -D %D -f %f -h %h -k %k -t %t -U %U -u %u
This is the mode OpenSSH calls. It processes all enabled configurations and outputs authorized keys.
sudo ssh-auth-cmd config-check
Validates:
# Install with default settings (AuthorizedKeysCommandUser root)
sudo ssh-auth-cmd install
# Install with specific user
sudo ssh-auth-cmd install --user nobody
# Install with custom sshd_config location
sudo ssh-auth-cmd install --config /etc/ssh/sshd_config.custom
The install command:
AuthorizedKeysCommand to a config file in /etc/ssh/auth_cmd.d/AuthorizedKeysCommandUser settings when migrating/etc/ssh/auth_cmd.d/All configuration files and the configuration directory must have secure permissions:
# Set proper permissions
sudo chown -R root:root /etc/ssh/auth_cmd.d/
sudo chmod 755 /etc/ssh/auth_cmd.d/
sudo chmod 600 /etc/ssh/auth_cmd.d/*.toml
The config-check command verifies these permissions automatically.
user (or the user running ssh-auth-cmd)readonly flag for commands that should only log/audit without providing keysDifferent commands can run as different users for security isolation:
ldap-auth userdb-auth usernobodyaudit user/etc/ssh/auth_cmd.d/01-local.toml:
name = "local_keys"
command = "cat"
args = ["/home/%u/.ssh/authorized_keys"]
enabled = true
timeout = 30
user = "nobody"
/etc/ssh/auth_cmd.d/02-ldap.toml:
name = "ldap_lookup"
command = "/usr/local/bin/ldap-ssh-keys"
args = ["--user", "%u", "--hostname", "%h"]
enabled = true
timeout = 60
user = "ldap-auth"
/etc/ssh/auth_cmd.d/01-audit.toml:
name = "connection_audit"
command = "/usr/local/bin/log-ssh-attempt"
args = [
"--user", "%u",
"--original-user", "%U",
"--connection", "%C",
"--hostname", "%h",
"--key-fingerprint", "%f",
"--key-type", "%t"
]
enabled = true
timeout = 10
user = "audit"
readonly = true # Just for logging, don't provide keys
/etc/ssh/auth_cmd.d/02-corporate-keys.toml:
name = "corporate_ldap"
command = "/usr/local/bin/corporate-auth"
args = ["--user", "%u", "--domain", "corp.example.com"]
enabled = true
timeout = 60
user = "corp-auth"
/etc/ssh/auth_cmd.d/03-emergency.toml:
name = "emergency_access"
command = "/usr/local/bin/emergency-keys"
args = ["--user", "%u", "--validate-emergency"]
enabled = true
timeout = 30
user = "emergency-auth"
/etc/ssh/auth_cmd.d/01-local.toml:
name = "local_keys"
command = "cat"
args = ["/home/%u/.ssh/authorized_keys"]
enabled = true
timeout = 30
/etc/ssh/auth_cmd.d/02-shared-dev.toml:
name = "shared_dev_keys"
command = "cat"
args = ["/etc/ssh/shared_dev_keys"]
enabled = true
timeout = 10
If you're migrating from the original single-file configuration:
sudo ssh-auth-cmd install
The installer will:
AuthorizedKeysCommand to a config fileVerify the migration:
sudo ssh-auth-cmd config-check
# Check all configurations
sudo ssh-auth-cmd config-check
# Test manually for a specific user
sudo ssh-auth-cmd key-cmd -u testuser
# Test with full OpenSSH context
sudo ssh-auth-cmd key-cmd -c "testuser,192.168.1.100,22,10.0.0.1,22" -u testuser -h hostname.example.com
# Fix directory permissions
sudo chown -R root:root /etc/ssh/auth_cmd.d/
sudo chmod 755 /etc/ssh/auth_cmd.d/
sudo chmod 600 /etc/ssh/auth_cmd.d/*.toml
# Check command permissions
ls -la /usr/local/bin/your-auth-command
Enable SSH debug logging to see what's happening:
# In /etc/ssh/sshd_config
LogLevel DEBUG
# Then check logs
sudo tail -f /var/log/auth.log
"Configuration directory is writable by group or others"
sudo chmod 755 /etc/ssh/auth_cmd.d/"Configuration file is writable by group or others"
sudo chmod 600 /etc/ssh/auth_cmd.d/*.toml"Command is not owned by root"
sudo chown root:root /path/to/command"Invalid placeholder"
"User not found"
user field exists on the systemreadonly = true for audit/logging commands that don't provide keysconfig-check before deploymentname = "vault_ssh_ca"
command = "/usr/local/bin/vault-ssh-helper"
args = ["-mode", "ca", "-username", "%u"]
enabled = true
timeout = 45
user = "vault-ssh"
name = "ipa_keys"
command = "/usr/bin/sss_ssh_authorizedkeys"
args = ["%u"]
enabled = true
timeout = 30
user = "sssd"
name = "db_keys"
command = "/usr/local/bin/db-ssh-keys"
args = [
"--user", "%u",
"--client-ip", "%C",
"--hostname", "%h"
]
enabled = true
timeout = 60
user = "db-auth"
This comprehensive setup provides a secure, flexible, and maintainable way to chain multiple SSH authentication sources while maintaining full OpenSSH compatibility and security best practices.