User and group management has been a very difficult task for sysadmins, especially when one user account has to be created across 10 machines, or even a 100. Similarly, disabling or deleting the accounts on 10s or 100s of machines, when employees leave the team or company, is not for the faint-hearted. You would be right in asking, “Why? Doesn’t LDAP solve the problem?” Believe me, I agree with you!
I feel, after struggling with LDAP for about two years, that:
- Puppet has made the task much simpler for me.
- Communications are encrypted by default, without me having to setup SSL separately, which makes it very secure to set even passwords.
- The configurations on the client end are very minimal, or nil, compared to LDAP.
Groups
We need to create groups first, because a user, when added, needs to be part of a group. Management of privileges by a group is always better than individual user management. Put all the users into a group, and assign the group privileges as per the member users’ requirements in this group. This is very useful, even when giving sudo privileges.
Enter the following lines in the /etc/puppet/manifests/site.pp
file — the comma at the end of a line is significant; so don’t omit it.
group { "lfyforum": ensure => present, gid => 1001 }
Make sure that a group with the ID 1001 doesn’t already exist.
root@puppet-client:~# grep 1001 /etc/group | wc -l 0
On running the command puppetd --server=puppet -t --onetime
as the root use, you should get the following
result, telling you that the group lfyforum has been created successfully, with the ID 1001.
notice: /Stage[main]//Group[lfyforum]/ensure: created root@puppet-client:~# grep 1001 /etc/group lfyforum:x:1001:
You can add a -d
(debug) flag to the above command if you need to troubleshoot any errors.
Users
You can create users with a basic method. site.pp
would be the file to use for both users and groups in this example. Add the following lines to site.pp
:
user { "lfy": ensure => "present", uid => "1001", gid => "1001", comment => "LinuxForU User", home => "/home/lfy", shell => "/bin/bash" }
Of course, here also please make sure that a user with the ID 1001 doesn’t already exist:
root@puppet-client:~# grep 1001 /etc/passwd | wc -l 0
On running the puppetd
command as the root, you should get the following output:
notice: /Stage[main]//User[lfy]/ensure: created root@puppet-client:~# grep 1001 /etc/passwd lfy:x:1001:1001:LinuxForU User:/home/lfy:/bin/bash
Now, can these two be clubbed, instead of having them as two different statements? Yes. We can make the user statement depend on the group by adding the following line:
require => Group[“lfyforum”]
You now have the output given below:
notice: /Stage[main]//Group[lfyforum]/ensure: created notice: /Stage[main]//User[lfy]/ensure: created
Files and folders
Although everything (including directories) is considered a file in UNIX, but not in Puppet. You have to exclusively mention the word directory to have a folder created.
A home directory does not get created, by default; and if it does, default permissions for the home would be 755. In this special case, adding the managehome
line to the user stanza should take care of creating the home folder and the skeleton of the folder as well.
user { "lfy": ensure => "present", uid => "1001", gid => "1001", comment => "LinuxForU User", home => "/home/lfy", shell => "/bin/bash", managehome => true }
These are the default file permissions:
root@puppet-client:~# ls -l /home/ | grep lfy drwxr-xr-x 8 lfy lfyforum 4096 2010-10-27 22:08 lfy
How do you set directory permissions? Adding these lines to the same file should help:
file { "/home/lfy": mode => 700, require => User["lfy"] }
Why did we use the attribute require
? It’s so that there are no errors when Puppet tries to apply permissions to a non-existent folder. Here, it will only run when Puppet confirms that the user has been created first. This should give an output as shown below:
notice: /Stage[main]//File[/home/lfy]/mode: mode changed '755' to '700' root@puppet-client:~# ls -l /home/ | grep lfy drwx------ 8 lfy lfyforum 4096 2010-10-27 22:08 lfy
Run an id
on the user lfy, to see if the user was created properly:
root@puppet-client:~# id lfy uid=1001(lfy) gid=1001(lfyforum) groups=1001(lfyforum)
Pretty simple, right? Just imagine thousands of machines doing this at the same time without any intervention from your side! As far as Puppet is concerned, it’s the maximum use of the client’s resources. The server only comes into the picture when configurations are to be pulled.
I hope you haven’t forgotten about putting puppetd
in cron, as discussed in the last article in this series.
User deletion
What about user deletion? Just reverse a few entries in the user and file stanzas:
user { "lfy": ensure => "absent" } file { "/home/lfy": ensure => absent, force => true, require => User["lfy"] }
Why did we use force
? Because, by default, Puppet plays safe and does not use rm -rf
on the home folder. The force attribute does just that.
Now tell me… a user/admin has left the organisation and you need to remove his/her home folder. Can you remove/delete the home folder through any LDAP service? Hope now you have got the solution to that as well.
I hope you enjoyed creating users, groups and files/folders with Puppet. In the next article, we will look at something even more interesting: the management of passwords, sudo users, and a little bit about setting up Puppet on a machine during installation itself.