User management examples
Local user management
There are many approaches to managing users. You can edit system files
like /etc/passwd
directly, you can use commands on some systems like
useradd
. However the easiest, and preferred way is to use
CFEngine's native users
type promise.
Ensuring a local user has a specific password
This example shows ensuring that the local users root
is managed if
there is a specific password hash defined.
body file control
{
# This policy uses parts of the standard library.
inputs => { "$(sys.libdir)/users.cf" };
}
bundle agent main
{
vars:
# This is the hashed password for 'vagrant'
debian_8::
"root_hash"
string => "$6$1nRTeNoE$DpBSe.eDsuZaME0EydXBEf.DAwuzpSoIJhkhiIAPgRqVKlmI55EONfvjZorkxNQvK2VFfMm9txx93r2bma/4h/";
users:
linux::
"root"
policy => "present",
password => hashed_password( $(root_hash) ),
if => isvariable("root_hash");
}
This policy can be found in
/var/cfengine/share/doc/examples/local_user_password.cf
and downloaded directly from
github.
root@debian-jessie:/core/examples# grep root /etc/shadow
root:!:16791:0:99999:7:::
root@debian-jessie:/core/examples# cf-agent -KIf ./local_user_password.cf
info: User promise repaired
root@debian-jessie:/core/examples# grep root /etc/shadow
root:$6$1nRTeNoE$DpBSe.eDsuZaME0EydXBEf.DAwuzpSoIJhkhiIAPgRqVKlmI55EONfvjZorkxNQvK2VFfMm9txx93r2bma/4h/:16791:0:99999:7:::
Ensuring local users are present
This example shows ensuring that the local users jack
and jill
are
present on all linux systems using the native users
type promise.
body file control
{
# This policy uses parts of the standard library.
inputs => { "$(sys.libdir)/files.cf" };
}
bundle agent main
{
vars:
"users" slist => { "jack", "jill" };
"skel" string => "/etc/skel";
users:
linux::
"$(users)"
home_dir => "/home/$(users)",
policy => "present",
home_bundle => home_skel( $(users), $(skel) );
}
bundle agent home_skel(user, skel)
{
files:
"/home/$(user)/."
create => "true",
copy_from => seed_cp( $(skel) ),
depth_search => recurse( "inf" );
}
This policy can be found in
/var/cfengine/share/doc/examples/local_users_present.cf
and downloaded directly from
github.
Lets check the environment to see that the users do not currently exist.
root@debian-jessie:/CFEngine/core/examples# egrep "jack|jill" /etc/passwd
root@debian-jessie:/core/examples# ls -al /home/{jack,jill}
ls: cannot access /home/jack: No such file or directory
ls: cannot access /home/jill: No such file or directory
Let's run the policy and inspect the state of the system afterwards.
root@debian-jessie:/core/examples# cf-agent -KIf ./users_present.cf
info: Created directory '/home/jack/.'
info: Copying from 'localhost:/etc/skel/.bashrc'
info: Copying from 'localhost:/etc/skel/.profile'
info: Copying from 'localhost:/etc/skel/.bash_logout'
info: User promise repaired
info: Created directory '/home/jill/.'
info: Copying from 'localhost:/etc/skel/.bashrc'
info: Copying from 'localhost:/etc/skel/.profile'
info: Copying from 'localhost:/etc/skel/.bash_logout'
info: User promise repaired
root@debian-jessie:/core/examples# egrep "jack|jill" /etc/passwd
jack:x:1001:1001::/home/jack:/bin/sh
jill:x:1002:1002::/home/jill:/bin/sh
root@debian-jessie:/core/examples# ls -al /home/{jack,jill}
/home/jack:
total 20
drwxr-xr-x 2 root root 4096 Dec 22 16:37 .
drwxr-xr-x 5 root root 4096 Dec 22 16:37 ..
-rw-r--r-- 1 root root 220 Dec 22 16:37 .bash_logout
-rw-r--r-- 1 root root 3515 Dec 22 16:37 .bashrc
-rw-r--r-- 1 root root 675 Dec 22 16:37 .profile
/home/jill:
total 20
drwxr-xr-x 2 root root 4096 Dec 22 16:37 .
drwxr-xr-x 5 root root 4096 Dec 22 16:37 ..
-rw-r--r-- 1 root root 220 Dec 22 16:37 .bash_logout
-rw-r--r-- 1 root root 3515 Dec 22 16:37 .bashrc
-rw-r--r-- 1 root root 675 Dec 22 16:37 .profile
Ensuring local users are locked
This example shows ensuring that the local users jack
and jill
are
locked if they are present on linux systems using the native users
type promise.
bundle agent main
{
vars:
"users" slist => { "jack", "jill" };
users:
linux::
"$(users)"
policy => "locked";
}
This policy can be found in
/var/cfengine/share/doc/examples/local_users_locked.cf
and downloaded directly from
github.
This output shows the state of the /etc/shadow
file before running
the example policy:
root@debian-jessie:/core/examples# egrep "jack|jill" /etc/shadow
jack:x:16791:0:99999:7:::
jill:x:16791:0:99999:7:::
root@debian-jessie:/core/examples# cf-agent -KIf ./local_users_locked.cf
info: User promise repaired
info: User promise repaired
root@debian-jessie:/core/examples# egrep "jack|jill" /etc/shadow
jack:!x:16791:0:99999:7::1:
jill:!x:16791:0:99999:7::1:
Ensuring local users are absent
This example shows ensuring that the local users jack
and jill
are
absent on linux systems using the native users
type promise.
bundle agent main
{
vars:
"users" slist => { "jack", "jill" };
users:
linux::
"$(users)"
policy => "absent";
}
This policy can be found in
/var/cfengine/share/doc/examples/local_users_absent.cf
and downloaded directly from
github.
Before activating the example policy, lets inspect the current state of the system.
root@debian-jessie:/core/examples# egrep "jack|jill" /etc/passwd
jack:x:1001:1001::/home/jack:/bin/sh
jill:x:1002:1002::/home/jill:/bin/sh
root@debian-jessie:/core/examples# ls -al /home/{jack,jill}
/home/jack:
total 20
drwxr-xr-x 2 root root 4096 Dec 22 16:37 .
drwxr-xr-x 5 root root 4096 Dec 22 16:37 ..
-rw-r--r-- 1 root root 220 Dec 22 16:37 .bash_logout
-rw-r--r-- 1 root root 3515 Dec 22 16:37 .bashrc
-rw-r--r-- 1 root root 675 Dec 22 16:37 .profile
/home/jill:
total 20
drwxr-xr-x 2 root root 4096 Dec 22 16:37 .
drwxr-xr-x 5 root root 4096 Dec 22 16:37 ..
-rw-r--r-- 1 root root 220 Dec 22 16:37 .bash_logout
-rw-r--r-- 1 root root 3515 Dec 22 16:37 .bashrc
-rw-r--r-- 1 root root 675 Dec 22 16:37 .profile
From the above output we can see that the local users jack
and
jill
are present, and that they both have home directories.
Now lets activate the example policy and insepect the result.
root@debian-jessie:/core/examples# cf-agent -KIf ./local_users_absent.cf
info: User promise repaired
info: User promise repaired
root@debian-jessie:/core/examples# egrep "jack|jill" /etc/passwd
root@debian-jessie:/core/examples# ls -al /home/{jack,jill}
/home/jack:
total 20
drwxr-xr-x 2 root root 4096 Dec 22 16:37 .
drwxr-xr-x 5 root root 4096 Dec 22 16:37 ..
-rw-r--r-- 1 root root 220 Dec 22 16:37 .bash_logout
-rw-r--r-- 1 root root 3515 Dec 22 16:37 .bashrc
-rw-r--r-- 1 root root 675 Dec 22 16:37 .profile
/home/jill:
total 20
drwxr-xr-x 2 root root 4096 Dec 22 16:37 .
drwxr-xr-x 5 root root 4096 Dec 22 16:37 ..
-rw-r--r-- 1 root root 220 Dec 22 16:37 .bash_logout
-rw-r--r-- 1 root root 3515 Dec 22 16:37 .bashrc
-rw-r--r-- 1 root root 675 Dec 22 16:37 .profile
From the above output we can see that the local users jack
and
jill
were removed from the system as desired. Note that their home
directories remain, and if we wanted them to be purged we would have
to have a separate promise to perform that cleanup.
Local group management
CFEngine does not currently have a native groups
type promise so you
will need to either edit the necessary files using files
type
promises, or arrange for the proper commands to be run in order to
create or delete groups.
Ensure a local group is present
Add lines to the password file, and users to group if they are not already there.
This example uses the native operating system commands to show ensuring that a group is present.
body file control
{
# This policy uses parts of the standard library.
inputs => { "$(sys.libdir)/paths.cf" };
}
bundle agent main
{
classes:
"group_cfengineers_absent"
not => groupexists("cfengineers");
commands:
linux.group_cfengineers_absent::
"$(paths.groupadd)"
args => "cfengineers";
}
This policy can be found in
/var/cfengine/share/doc/examples/local_group_present.cf
and downloaded directly from
github.
First lets inspect the current state of the system.
root@debian-jessie:/core/examples# grep cfengineers /etc/group
Now lets activate the example policy and check the resulting state of the system.
root@debian-jessie:/core/examples# cf-agent -KIf ./local_group_present.cf
info: Executing 'no timeout' ... '/usr/sbin/groupadd cfengineers'
info: Completed execution of '/usr/sbin/groupadd cfengineers'
root@debian-jessie:/CFEngine/core2.git/examples# grep cfengineers /etc/group
cfengineers:x:1001:
Ensureing a user is a member of a secondary group
This example shows using the native users
type promise to ensure
that a user is a member of a particular group.
bundle agent main
{
users:
linux::
"jill"
policy => "present",
groups_secondary => { "cfengineers" };
}
This policy can be found in
/var/cfengine/share/doc/examples/local_user_secondary_group_member.cf
and downloaded directly from
github.
First lets inspect the current state of the system
root@debian-jessie:/core/examples# grep jill /etc/passwd
root@debian-jessie:/core/examples# grep jill /etc/group
Now lets actiavte the example policy and inspect the resulting state.
root@debian-jessie:/core/examples# cf-agent -KIf ./local_user_secondary_group_member.cf
info: User promise repaired
root@debian-jessie:/core/examples# grep jill /etc/passwd
jill:x:1001:1002::/home/jill:/bin/sh
root@debian-jessie:/core/examples# grep jill /etc/group
cfengineers:x:1001:jill
jill:x:1002:
It's important to remember we made no promise about the presence of
the cfengineers
group in the above example. We can see what would
happen when the cfengineers
group was not present.
root@debian-jessie:/core/examples# grep cfengineers /etc/group
root@debian-jessie:/core/examples# cf-agent -KIf ./local_user_secondary_group_member.cf
usermod: group 'cfengineers' does not exist
error: Command returned error while modifying user 'jill'. (Command line: '/usr/sbin/usermod -G "cfengineers" jill')
info: User promise not kept
Get a list of users
body common control
{
bundlesequence => { test };
}
bundle agent test
{
vars:
"allusers" slist => getusers("zenoss,mysql,at","12,0");
reports:
linux::
"Found user $(allusers)";
}