The module:authkey script provides Secure Shell (SSH) public key management, associating user accounts with public keys and CFEngine class information. This simplifies configuration of SSH trust relationships, for example those used by role accounts. Currently, the module only supports OpenSSH authorized_keys files.
The global ssh_known_hosts file can be managed under CFEngine.
The module:users module can install users before module:authkey runs, and module:groups manage groups for use in keymap.ini statements.
Code running as root must not edit user authorized_keys files. A malicious user could link their file to some other critical system file. module:authkey avoids this problem via a fork
and a POSIX module setuid change to the user before touching the authorized_keys file.
With the no_modify class set in the CFALLCLASSES environment variable, module:authkey will only display what changes would be made to the system. This simplifies rollouts to previously unmanaged systems.
The source code for module:authkey is only available by request.
Configuration
The main.ini, keymap.ini, and rules contain all configuration for module:authkey. Public keys must be saved into files under a different directory structure. module:authkey uses the mapping information in keymap.ini to associate particular public keys with various user accounts on systems belonging to particular CFEngine classes. The public key directories and preferences files should be saved under a version control repository.
main.ini
Contains global options for module:authkey. The module can optionally disable deprecated ~/.ssh/authorized_keys2 files, and optionally disable authorized_keys files it knows nothing about.
[defaults]
# only OpenSSH supported (required)
implementations = app_openssh
# where to read public keys from (required)
key_source = /var/cfengine/etc/ssh/pubkeys/%{keylist}/%{keyname}.pub
# disable unknown authorized_keys files (recommended)
manage_all = true
# auto-create ~/.ssh directories if needed
openssh_create_dotssh = true
# disable deprecated ~/.ssh/authorized_keys2 files (recommended)
openssh_ak2_disable = true
Keep the *.ini options files used by module:authkey tidy with the initidy script.
keymap.ini
Details the mappings between public keys (referenced by key_source in main.ini) and what accounts on which classes of systems.
# SiteScope public key for monitoring access
[sitescope-monitor]
classes = role_sitescope_client
keylist = roles
keyname = sitescope
account = healthcheck
# enforce sshd(8) access limitation to the key to restrict usage
options = from="monitor01.example.org,monitor02.example.org"
# Ensure sysadmins can login even if LDAP dead
# 1:1 map between accounts in the wheel group (minus root) and the
# public key for the user under the users keylist directory
[admins]
classes = any
keylist = users
account = @wheel -root
rules
Rulesets allow customization of the from="" and similar options detailed in sshd(8). For example, systems administrators could have access to all systems, except that production systems must be accessed through a particular bastion host:
test: name eq admins
{
test: cf.classes contains realm_prod
actions: options=from="gateway.example.org"
}
With the above from="" limitation, keys in authorized_keys will be created with the following prefix:
from="gateway.example.org" ssh-rsa AAAAB…
keygen.ini
The keygen.ini contains rules to generate passphrase-free public keys, for use by role accounts. Use passphrase-free keys should be restricted on the remote servers via from="" and command="" option limitations, if possible. The following entry would ensure all systems have id_rsa and identity key pairs generated under the home directory for the root user.
[default-root-keys]
classes = any
account = root
type = rsa rsa1
Public Key Repository
The public keys must be stored under a directory tree, broken down into different trees: users to store user-specific public keys, and roles for role based public keys. These files must contain one or more public keys, copied from where the key pair was generated (usually ~/.ssh/id_rsa.pub for a rsa key pair under OpenSSH).
$ ls
CVS roles users
$ ls roles
CVS sitescope.pub
$ ls users
CVS jmates.pub
module:authkey references these files via the key_source entry in the main.ini configuration file. CFEngine must copy the module preferences and public keys down to each client system.
Problems
Problems encountered writing this module:
- Addresses and Domain Name System (DNS) lookups
- Users with the same home directory
When adding from="" limitations for hostnames, reverse DNS must resolve to something in the allowed list. If not, the address (or subnet) must be listed. Some systems now reference addresses using the IPv6 format ::ffff:192.0.2.10 instead of 192.0.2.10. This means to allow connections from all hosts on the 192.0.2/24 subnet, both address forms may need to be accounted for:
from="*.example.org,192.0.2.*,::ffff:192.0.2.*" ssh-rsa AAAAB…
Check the logs for sshd to determine whether a reverse lookup or address matching problem prevents logins. On RedHat Linux, the logs will appear in /var/log/secure by default:
Jan 30 09:30:23 server sshd[1147]: Authentication tried for user with↵
correct key but not from a permitted host (host=client.example.org,↵
ip=::ffff:192.0.2.111).
Many Unix role accounts share the same home directory, such as /var/empty or worse, /root. One solution: change the conflicting home directories. Be aware that a home directory change may break something else. For example, software might require a home directory shared between two role accounts, or improperly use the literal home directory path instead of a getpwent(3) call. Currently, module:authkey emits a warning should a home directory be shared between two or more users:
warning: shared home directory detected: accounts=jabber:mysql,↵
homedir=/var/empty