User Management and ACL Examples
- Manage users
- Add users
- Add users to passwd and group
- ACL file example
- ACL generic example
- ACL secret example
- Active directory example
- Active list users directory example
- Active directory show users example
- Get a list of users
- LDAP interactions
Manage users
There are many approaches to managing users. You can edit system files like /etc/passwd directly, or you can use commands on some systems like ‘useradd’ or ‘adduser’. In all cases it is desirable to make this a data-driven process.
Add users
Remove users
Add users
A simple approach which adds new users to the password file, and to a group called ‘users’ in the group file. Is shown below. This example does not edit the shadow file. A simple pattern that can be modified for use is shown below.
Note that, although this is a simple minded approach, it is the most efficient of the approaches shown here as all operations can be carried out in a single operation for each file.
bundle agent addusers
{
vars:
# Add some users
"pw[mark]" string => "mark:x:1000:100:Mark Burgess:/home/mark:/bin/bash";
"pw[fred]" string => "fred:x:1001:100:Right Said:/home/fred:/bin/bash";
"pw[jane]" string => "jane:x:1002:100:Jane Doe:/home/jane:/bin/bash";
"users" slist => getindices("pw");
files:
"/etc/passwd"
edit_line => append_users_starting("addusers.pw");
# "/etc/shadow"
# edit_line => append_users_starting("$(users):defaultpasswd:::::::");
"/etc/group"
edit_line => append_user_field("users","4","@(addusers.users)");
"/home/$(users)/."
create => "true",
perms => mog("755","$(users)","users");
# equivalent to ALL of the above in 3.6 (see documentation)
users:
"$(users)" policy => "present", shell => "/bin/bash";
}
A second approach is to use the shell commands supplied by some operating systems; this assumes that suitable defaults have been set up manually. Also the result is not repairable in a simple convergent manner. The command needs to edit multiple files for each user, and is quite inefficient.
bundle agent addusers
{
vars:
# Add some users
"pw[mark]" string => "mark:x:1000:100:Mark Burgess:/home/mark:/bin/bash";
"pw[fred]" string => "fred:x:1001:100:Right Said:/home/fred:/bin/bash";
"pw[jane]" string => "jane:x:1002:100:Jane Doe:/home/jane:/bin/bash";
"users" slist => getindices("pw");
methods:
"any" usebundle => user_add("$(users)","$(pw[$(users)])");
}
bundle agent user_add(x,pw)
{
files:
"/etc/passwd"
edit_line => append_users_starting("addusers.pw");
# "/etc/shadow"
# edit_line => append_users_starting("$(users):defaultpasswd:::::::");
"/etc/group"
edit_line => append_user_field("users","4","@(addusers.users)");
"/home/$(users)/."
create => "true",
perms => mog("755","$(users)","users");
}
An alternative approach is to use a method to wrap around the handling of a user. Although this looks nice, it is less efficient than the first method because it must edit the files multiple times.
bundle agent addusers
{
vars:
# Add some users
"pw[mark]" string => "mark:x:1000:100:Mark Burgess:/home/mark:/bin/bash";
"pw[fred]" string => "fred:x:1001:100:Right Said:/home/fred:/bin/bash";
"pw[jane]" string => "jane:x:1002:100:Jane Doe:/home/jane:/bin/bash";
"users" slist => getindices("pw");
methods:
"any" usebundle => user_add("$(users)","$(pw[$(users)])");
}
bundle agent user_add(x,pw)
{
files:
"/etc/passwd"
edit_line => append_users_starting("addusers.pw");
# "/etc/shadow"
# edit_line => append_users_starting("$(users):defaultpasswd:::::::");
"/etc/group"
edit_line => append_user_field("users","4","@(addusers.users)");
"/home/$(users)/."
create => "true",
perms => mog("755","$(users)","users");
}
Add users to passwd and group
Add lines to the password file, and users to group if they are not already there.
body common control
{
bundlesequence => { "addpasswd" };
inputs => { "cf_std_library.cf" };
}
bundle agent addpasswd
{
vars:
# want to set these values by the names of their array keys
"pwd[mark]" string => "mark:x:1000:100:Mark Burgess:/home/mark:/bin/bash";
"pwd[fred]" string => "fred:x:1001:100:Right Said:/home/fred:/bin/bash";
"pwd[jane]" string => "jane:x:1002:100:Jane Doe:/home/jane:/bin/bash";
"users" slist => getindices("pwd");
files:
"/etc/passwd"
create => "true",
edit_line => append_users_starting("addpasswd.pwd");
"/etc/group"
edit_line => append_user_field("users","4","@(addpasswd.users)");
}
ACL file example
body common control
{
bundlesequence => { "acls" };
}
bundle agent acls
{
files:
"/media/flash/acl/test_dir"
depth_search => include_base,
acl => template;
}
body acl template
{
acl_method => "overwrite";
acl_type => "posix";
acl_directory_inherit => "parent";
aces => { "user:*:r(wwx),-r:allow", "group:*:+rw:allow", "mask:x:allow", "all:r"};
}
body acl win
{
acl_method => "overwrite";
acl_type => "ntfs";
acl_directory_inherit => "nochange";
aces => { "user:Administrator:rw", "group:Bad:rwx(Dpo):deny" };
}
body depth_search include_base
{
include_basedir => "true";
}
ACL generic example
body common control
{
bundlesequence => { "acls" };
}
bundle agent acls
{
files:
"/media/flash/acl/test_dir"
depth_search => include_base,
acl => test;
}
body acl test
{
acl_type => "generic";
aces => {"user:bob:rwx", "group:staff:rx", "all:r"};
}
body depth_search include_base
{
include_basedir => "true";
}
ACL secret example
body common control
{
bundlesequence => { "acls" };
}
bundle agent acls
{
files:
windows::
"c:\Secret"
acl => win,
depth_search => include_base,
comment => "Secure the secret directory from unauthorized access";
}
body acl win
{
acl_method => "overwrite";
aces => { "user:Administrator:rwx" };
}
body depth_search include_base
{
include_basedir => "true";
}
Active directory example
bundle agent active_directory
{
vars:
# NOTE: Edit this to your domain, e.g. "corp", may also need more DC's after it
"domain_name" string => "cftesting";
"user_name" string => "Guest";
# NOTE: We can also extract data from remote Domain Controllers
dummy.DomainController::
"domain_controller" string => "localhost";
"userlist" slist => ldaplist(
"ldap://$(domain_controller)",
"CN=Users,DC=$(domain_name),DC=com",
"(objectClass=user)",
"sAMAccountName",
"subtree",
"none");
classes:
dummy.DomainController::
"gotuser" expression => ldaparray(
"userinfo",
"ldap://$(domain_controller)",
"CN=$(user_name),CN=Users,DC=$(domain_name),DC=com",
"(name=*)",
"subtree",
"none");
reports:
dummy.DomainController::
'Username is "$(userlist)"';
dummy.gotuser::
"Got user data; $(userinfo[name]) has logged on $(userinfo[logonCount]) times";
}
Active list users directory example
bundle agent ldap
{
vars:
"userlist" slist => ldaplist(
"ldap://cf-win2003",
"CN=Users,DC=domain,DC=cf-win2003",
"(objectClass=user)",
"sAMAccountName",
"subtree",
"none");
reports:
'Username: "$(userlist)"';
}
Active directory show users example
bundle agent ldap
{
classes:
"gotdata" expression => ldaparray(
"myarray",
"ldap://cf-win2003",
"CN=Test Pilot,CN=Users,DC=domain,DC=cf-win2003",
"(name=*)",
"subtree",
"none");
reports:
gotdata::
"Got user data";
!gotdata::
"Did not get user data";
}
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)";
}
LDAP interactions
body common control
{
bundlesequence => { "ldap" , "followup"};
}
bundle agent ldap
{
vars:
# Get the first matching value for "uid"
"value" string => ldapvalue("ldap://eternity.iu.hio.no","dc=cfengine,dc=com","(sn=User)","uid","subtree","none");
# Get all matching values for "uid" - should be a single record match
"list" slist => ldaplist("ldap://eternity.iu.hio.no","dc=cfengine,dc=com","(sn=User)","uid","subtree","none");
classes:
"gotdata" expression => ldaparray("myarray","ldap://eternity.iu.hio.no","dc=cfengine,dc=com","(uid=mark)","subtree","none");
"found" expression => regldap("ldap://eternity.iu.hio.no","dc=cfengine,dc=com","(sn=User)","uid","subtree","jon.*","none");
reports:
linux::
"LDAP VALUE $(value) found";
"LDAP LIST VALUE $(list)";
gotdata::
"Found specific entry data ...$(ldap.myarray[uid]),$(ldap.myarray[gecos]), etc";
found::
"Matched regex";
}
bundle agent followup
{
reports:
linux::
"Different bundle ...$(ldap.myarray[uid]),$(ldap.myarray[gecos]),...";
}