Distribute ssh keys
This example shows a simple ssh key distribution implementation.
The policy was designed to work with the services_autorun
feature in
the Masterfiles Policy Framework. The
services_autorun
feature can be enabled from the augments_file. If
you do not have a def.json
in the root of your masterfiles directory
simply create it with the following content.
{
"classes": {
"services_autorun": [ "any" ]
}
}
In the following example we will manage the authorized_keys
file for
bob
, frank
, and kelly
.
For each listed user the ssh_key_distribution
bundle is activated if
the user exists on the system. Once activated the
ssh_key_distribution
bundle ensures that proper permissions are set
on the users .ssh
directory (home is assumed to be in
/home/username
) and ensures that the users .ssh/authorized_keys
is
a copy of the users authorized_keys
file as found on the server as
defined in the ssh_key_info
bundle.
Let's assume we collected all users' public keys into a single directory on the server and that users exist on the clients (and have corresponding home directory).
Note: special variable $(sys.policy_hub)
contains the hostname of
the policy server.
To deploy this policy simply place it in the services/autorun
directory of your masterfiles.
body common control
{
bundlesequence => { "autorun_ssh_key_distribution" };
inputs => { "$(sys.libdir)/stdlib.cf" };
}
bundle common ssh_key_info
{
meta:
"description"
string => "This bundle defines common ssh key information, like which
directory and server keys should be sourced from.";
vars:
"key_server" string => "$(sys.policy_hub)";
# We set the path to the repo in a common bundle so that we can reference
# the same path when defining access rules and when copying files.
# This directory is expected to contain one file for each users authorized
# keys, named for the username. For example: /srv/ssh_authorized_keys/kelly
"repo_path" string => "/srv/ssh_authorized_keys";
}
bundle agent autorun_ssh_key_distribution
{
meta:
# Here we simply tag the bundle for use with the `services_autorun`
# feature.
"tags" slist => { "autorun" };
vars:
"users" slist => { "bob", "frank", "kelly" };
methods:
"Distribute SSH Keys"
usebundle => ssh_key_distribution( $(users) ),
if => userexists( $(users) ),
comment => "It's important that we make sure each of these users
ssh_authorized_keys file has the correct content and
permissions so that they can successfully log in, if
the user exists on the executing agents host.";
}
bundle agent ssh_key_distribution(users)
{
meta:
"description"
string => "Ensure that specified users are able to log in using their ssh
keys";
vars:
# We get the users UID so that we can set permission appropriately
"uid[$(users)]" int => getuid( $(users) );
files:
"/home/$(users)/.ssh/."
create => "true",
perms => mo( 700, "$(uid[$(users)])"),
comment => "It is important to set the proper restrictive permissions and
ownership so that the ssh authorized_keys feature works
correctly.";
"/home/$(users)/.ssh/authorized_keys"
perms => mo( 600, "$(uid[$(users)])" ),
copy_from => remote_dcp( "$(ssh_key_info.repo_path)/$(users)",
$(ssh_key_info.key_server) ),
comment => "We centrally manage and users authorized keys. We source each
users complete authorized_keys file from the central server.";
}
bundle server ssh_key_access_rules
{
meta:
"description"
string => "This bundle handles sharing the directory where ssh keys
are distributed from.";
access:
# Only hosts with class `policy_server` should share the path to ssh
# authorized_keys
policy_server::
"$(ssh_key_info.repo_path)"
admit => { @(def.acl) },
comment => "We share the ssh authorized keys with all authorized
hosts.";
}
This policy can be found in
/var/cfengine/share/doc/examples/simple_ssh_key_distribution.cf
and downloaded directly from
github.
Example Run:
First make sure the users exist on your system.
root@host001:~# useradd bob
root@host001:~# useradd frank
root@host001:~# useradd kelly
Then update the policy and run it:
root@host001:~# cf-agent -Kf update.cf; cf-agent -KI
info: Installing cfe_internal_non_existing_package...
info: Created directory '/home/bob/.ssh/.'
info: Owner of '/home/bob/.ssh' was 0, setting to 1002
info: Object '/home/bob/.ssh' had permission 0755, changed it to 0700
info: Copying from '192.168.56.2:/srv/ssh_authorized_keys/bob'
info: Owner of '/home/bob/.ssh/authorized_keys' was 0, setting to 1002
info: Created directory '/home/frank/.ssh/.'
info: Owner of '/home/frank/.ssh' was 0, setting to 1003
info: Object '/home/frank/.ssh' had permission 0755, changed it to 0700
info: Copying from '192.168.56.2:/srv/ssh_authorized_keys/frank'
info: Owner of '/home/frank/.ssh/authorized_keys' was 0, setting to 1003
info: Created directory '/home/kelly/.ssh/.'
info: Owner of '/home/kelly/.ssh' was 0, setting to 1004
info: Object '/home/kelly/.ssh' had permission 0755, changed it to 0700
info: Copying from '192.168.56.2:/srv/ssh_authorized_keys/kelly'
info: Owner of '/home/kelly/.ssh/authorized_keys' was 0, setting to 1004