Table of Contents
- Supported Platforms
- Requirements
- Role Variables
- Dependencies
- Example Playbook
- License
- Author Information
Ansible role that installs, configures and runs OpenSSH: a remote login and operations tool based on the SSH protocol.
* Debian
* Redhat(CentOS/Fedora)
* Ubuntu
Pre-installation of a C-compiler (any C89 or better compiler should work) as well as working installations of both the zlib and libcrypto libraries (included within LibreSSl/OpenSSL) are required. A C compiler is generally available on supported platforms/linux distributions by default but can be downloaded using each platforms' native package manager if necessary. Reference for additional details.
Zlib version 1.1.4, 1.2.1.2 or greater is suggested (see https://zlib.net/fossils/ for released versions).
Also note that newer versions of OpenSSH require or strongly encourage a dedicated authentication account used by sshd
for privilege separation. This is automatically managed by this role and configurable via custom operator vars.
Variables are available and organized according to the following software & machine provisioning stages:
- install
- config
- launch
- uninstall
openssh
can be installed using OS package management systems provided by the supported platforms (e.g apt
, yum/dnf
).
The following variables can be customized to control various aspects of this installation process, ranging from the package version and user to run the SSH service as to the automatic setup of an SSH key caching agent (ssh-agent
):
service_package: <package-name-and-version>
(default: openssh[-latest])
- name and version of the openssh package to download and install. Reference or run something like
dnf --showduplicates list openssh
in a terminal to display a list of available packages for your platform
auto_enable_agent: <hash-of-accounts-to-enable>
(default: None)
- indicates user accounts to install and automatically enable a user-scoped instance of
ssh-agent
, managed by systemd. Hash containsrun_args
key for customization of agent launch
auto_enable_agent:
# users
example-1: {}
example-2:
# launch ssh-agent in debug mode with key TTL of 1 hour
run_args: "-d -t 3600"
Using this role, configuration of an openssh
installation is organized according to the following components:
- service (
sshd_config
) - client (
ssh_config
) - known hosts (
ssh_known_hosts #global
andknown_hosts #per-user
) - authorized keys (
authorized_keys
) - user identities (e.g.
id_rsa #private-key
andid_rsa.pub #public-key
)
The set of component configurations to manage can be controlled using the managed_configs
list var:
managed_configs: <list-of-component-configs>
(default: ALL see defaults/main.yml)
- list of SSH components' configuration to manage via this role
Each configuration can be expressed within a hash, keyed by user account where appropriate. The value of these user account keys are generally dicts representing config specifications (e.g. an entry in a user's authorized_keys file granting access to the local account for a particular key) containing a set of key-value pairs constituting associated settings for each component. The following provides an overview and example configuration of each for reference.
SSH daemon configuration values are defined under ssh_config.service
and describe a service config specification to be rendered at the appropriate location (i.e. /etc/ssh/sshd_config
):
[ssh_config:] service: <key: value,...>
(default: see defaults/main.yml
)
- a list of available configuration options can be found here
ssh_config:
service:
# disable password and challenge-response authentication methods and enable Public-Key auth *ONLY*
PasswordAuthentication: "no"
ChallengeResponseAuthentication: "no"
PubKeyAuthentication: "yes"
SSH client configuration values are defined under ssh_config.client
and describe client config specifications, from both a global and per-user scope, to be rendered at the appropriate locations (i.e. /etc/ssh/ssh_config # global
and ~/.ssh/config
# per-user).
Each specification contains a keyword attribute to describe whether the config is anchored on a Host (default)
or Match
basis:
[ssh_config: client : {global | user-account} : {entry} :] keyword: <Host | Match>
(default: Host)
- entry match basis (reference here for more details)
[ssh_config: client : {global | user-account} : {entry} :] options: <key: value,...>
(default: see defaults/main.yml
)
- a list of available configuration options can be found here
ssh_config:
client:
# system-wide settings
global:
'*':
options:
# disable auto add and forwarding of user keys by an `ssh-agent`
AddKeysToAgent: 'no'
ForwardAgent: 'no'
# custom settings for user-account-1
user-account-1:
# add and forward keys on connections to machines with the hostname matching dev-user.dev.net
'host "dev-user.dev.net"':
keyword: "Match"
options:
AddKeysToAgent: 'yes'
ForwardAgent: 'yes'
user-account-2:
# connect to hosts in test domain using designated test key and execute custom command on connection
'*.test.net':
keyword: "Host"
options:
LocalCommand: '~/test/show_test_results'
IdentityFile: '~/.ssh/test_rsa'
user-account-3:
# default keyword of 'Host'
# also silence ssh client logging and use designated production key
'*.prod.com':
options:
LogLevel: "QUIET"
IdentityFile: '~/.ssh/prod_rsa'
Like the SSH client configuration, SSH known hosts are configured based on both a global and per-user scope. Each type of config specification is defined under ssh_config.known_hosts
and will be rendered at the appropriate locations (i.e. /etc/ssh/ssh_known_hosts
# global and ~/.ssh/known_hosts
# per-user) accordingly.
Each specification contains several attributes detailing markers
and hostname
patterns associated with and accepted on behalf of the specified (host) key
. Reference for more details
[ssh_config: known_hosts : {global | user-account} : {entry} :] marker: <@cert-authority | @revoke>
(default: None)
- indicates that the line contains either a certification authority (@cert-authority) key or the key contained on the line is revoked and must not ever be accepted (@revoked)
[ssh_config: known_hosts : {global | user-account} : {entry} :] hostnames: <list of patterns>
(default: None)
- list of comma-separated patterns matched against hostnames to verify known identity
[ssh_config: known_hosts : {global | user-account} : {entry} :] key: <host-pub-key>
(default:None)
- cryptographic public host key representing proof of authenticity for host being connected to
Cryptographic keys included can be expressed in several formats:
- string - key definition containing: key-type, encoded key and additional comments
- file - local path on controller to file containing key definition
- hash - dict containing separate keys for key definition components ({type:...,encoding:...,comments:...})
ssh_config:
known_hosts:
# system-wide settings
global:
"Revoke ALL evil hosts":
hostnames:
- "*.evil.org"
# key expressed as string
key: "ssh-rsa @k3y..."
# mark for revocation
marker: "@revoked"
user-account-1:
# mark line contains a certification authority key
'Certified Authorities':
hostnames:
# host name stored in hash form
- "|1|JfKTdBh7rNbXkVAQCRp4OQoPfmI=|USECr3SWf1JUPsms5AqfD5QfxkM="
- "certified.net,*.mydomain.org,*.mydomain.com"
# host key read from file
key: "/etc/ssh/cert_auth_host_rsa.pub"
marker: "@cert-authority"
user-account-2:
'Organization network':
hostnames:
- "10.0.*.*"
- "*.example.org"
# negate access from known compromised subdomain
- "!*compromised.example.org"
key:
type: "ssh-rsa"
encoding: "th!s!s@HoSTk3y"
comments: "Known host key"
SSH authorized keys are configured on a per-user basis only. Each key specification is defined under ssh_config.authorized_keys
and rendered at the appropriate location under the specified user's local SSH directory (i.e. ~/.ssh/authorized_keys
).
Each entry contains several attributes detailing an(authorized_)key
and options
to associate with connection requests based on that key. Reference for more details
[ssh_config : authorized_keys : {user-account} : {entry}:] key: <pub-key>
(default: None)
- cryptographic public key representing proof of authenticity for client's connecting to the target user account
As with the known_hosts configuration above, authorized keys included can be expressed in several formats:
- string - key definition containing: key-type, encoded key and additional comments
- file - local path on controller to file containing keydefinition
- hash - dict containing separate keys for key definition components ({type:...,encoding:...,comments:...})
[ssh_config : authorized_keys : {user-account} : {entry} :] options : <list of options>
(default: None)
- list of options to apply to connections
ssh_config:
authorized_keys:
user-account-1:
"Basic Connection w/ no custom options":
key:
type: "ssh-rsa"
encoding: "th!s!s@k3y"
comments: "these are the key comments"
"Backup home directory":
options:
- "command='dump /home/user-account-1'"
- "no-pty"
- "no-port-forwarding"
key: "/home/user-account-1/.ssh/home_dump.pub"
Use the user_identities
configuration object to manage cryptographic public and private key pairs owned by various users. This functionality allows for copying of both public and private keys into their respective locations for user-host/account access across operated machines (i.e. ~/.ssh/
). Each identity specification is defined under ssh_config.user_identities
and expects keys and paths relative to the controller machine's filesystem.
Due to the sensitive and precise nature of handling user identities, keys are only copied from files as is to target machine. Reference for further reading
[ssh_config : user_identities : {user-account} :] src: <key-file-path>
(default: None)
- cryptographic key path located on local controller to be copied to target machine on behalf of designated user-account
[ssh_config : user_identities : {user-account} :] dest: <key-file-name>
(default: None)
- name of destination key-file to be copied to target machine
ssh_config:
user_identities:
user-account-1:
src: "/home/user-account-1/id_rsa"
dest: "my_rsa"
Execution of both the openssh
and ssh-agent
daemons is accomplished utilizing the systemd service management tool, standard on most Linux platforms. Both can be customized to adhere to system administrative policies by using the following launch arguments:
extra_run_args: <cli-options>
(default: None)
- list of
sshd
commandline arguments to pass to the executable at runtime for customizing launch. This variable enables the role to be customized according to the operator's specification; whether to activate a particular operational mode, force use of a specific type of IPv address family or pass additional runtime configuration values
A list of available command-line options can be found here.
# Launch the SSH daemon only accepting IPv4 addresses and also writing log output to a location besides the system log
extra_run_args: "-4 -E /var/log/sshd.log"
[auto_enable_agent : <account>] : run_args: <cli-options>
(default: None)
- list of
ssh-agent
commandline arguments to modify the default behavior of individual user's SSH authentication and key caching agent. Of note, a default value for the maximum lifetime of identities added to the agent may be specified. The lifetime may be expressed in seconds or in a time format
A list of available command-line options can be found here.
auto_enable_agent:
# user
example:
# automatically install a user-scoped ssh-agent for the *example* user and specify
# a maximum lifetime for cached identities of 86,400 seconds (or 1 day):
run_args: "-t 86400"
Remove customized user managed configs, returning the target host to its configured state prior to application of this role with the exception of managed global config settings (e.g. can be useful for recycling users and cleaning up stale settings).
The following variable(s) can be customized to manage this uninstall process:
perform_uninstall: <true | false>
(default: false
)
- whether to uninstall custom user configurations, based on defined role configuration at time of execution, on a target host (see:
handlers/main.yml
for details)
None
Basic setup with defaults:
- hosts: all
roles:
- role: 0x0I.openssh
Hardened production setup with heightened security configurations:
- hosts: prod
roles:
- role: 0x0I.openssh
vars:
ssh_config:
service:
# user authentication
AllowGroups: "devops security"
AuthenticationMethods: "publickey"
PermitRootLogin: "no"
PermitEmptyPasswords: "no"
AddKeysToAgent: "confirm"
# session privacy and data-integrity
Ciphers: "chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr"
MACs: "hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-512,hmac-sha2-256,umac-128@openssh.com"
IgnoreRhosts: "yes"
# session management
ClientAliveInterval: "60"
ClientAliveCountMax: "2"
X11Forwarding: "no"
Banner: "You are requesting access to a PRODUCTION environment. **Proceed with caution**"
client:
global:
'*':
options:
ForwardAgent: "no"
AddKeysToAgent: "confirm"
HashKnownHosts: "yes"
HostKeyAlgorithms: "ssh-ed25519-cert-v01@openssh.com,ssh-rsa-cert-v01@openssh.com,ssh-ed25519,ssh-rsa"
Only manage client/user configs and authorized keys:
- hosts: computer_lab
roles:
- role: 0x0I.openssh
vars:
managed_configs:
- client
- authorized_keys
ssh_config:
client:
.
.
.
authorized_keys:
.
.
.
Agile-development environment settings:
- hosts: dev
roles:
- role: 0x0I.openssh
vars:
ssh_config:
service:
AllowGroups: "ssh-user"
AllowAgentForwarding: "yes"
AddKeysToAgent: "yes"
client:
global:
'*.dev.net':
options:
ForwardAgent: "yes"
RemoteCommand: "/home/devops/launch_team_dashboard --user %r"
'*.test.net':
options:
ForwardAgent: "yes"
RemoteCommand: "/home/devops/launch_testenv_dashboard --user %r"
MIT
This role was created in 2019 by O1.IO.