Adding a user to lots of systems.
Posted by Steve on Thu 6 Apr 2006 at 09:14
In many small and medium sized companies there are a number of servers which have organically grown, with no directory management. I'm curious to know how people would handle adding users in this scenario.
Imagine a situation where you have 50 machines which are running Debian Sarge, and you wish to do two things to each system:
- Add a new user account.
- Setup that user such that sudo is available for them.
Doing this one one or two machines is trivial; just ask somebody with an account to ssh into each server and run useradd to add the user, then edit the /etc/sudoers file.
But what if you want to do the same thing for a lot of machines?
Assuming you have no SSH keys which will allow remote root logins from a trusted internal host how would you handle this situation?
I can think of a several different approaches:
- Use NIS
NIS is insecure across the internet. Internally on a trusted LAN it is simple, secure enough and and well understood.
It would be possible to designate a single host as a master, then login to each host and set it up to fetch non-system accounts + passwords from the master.
This doesn't help much right now since you still have to login to each host, but it will make things easier in the future if the situation repeats itself.
It also doesn't help modify the sudoer setup.
- Setup CFEngine
We've covered using cfengine previously, and like NIS this has pros and cons.
On the downside installing and configuring each host to be a CFEngine "slave" or "node" would require logging into each host. But on the plus side it would allow the subsequent addition of users and configuring sudo to be a trivial operation.
- Use rsync
Rsyncing a password + shadow file, and sudoers file too, could be done. But this seems to be fraught with danger if hosts have different system-users available. (e.g. some packages create a local user; and if those packages are installed on only some hosts then issues will arise).
- Use a Debian Package
As a long shot .. if each host is setup to automatically download new packages from a central location it would be trivial to add a new-employee.deb package to that repository and ensure it was downloaded by modifying a standard package to depend upon it.
(This is similar to the custom packages I use to configure shell setup, etc on my local machines.)
The postinst section of the package could add a user and setup sudo - although this is not a Debian policy-compliant action.
Each of these approaches has pros and cons, and there are likely to be approaches I've missed.
So my question is : How would you handle this situation?
Personally I would be happy to login to each host once to do some minimal configuration but only if that were never required again. Automation is a wonderful thing and jobs like this do have a habit of recurring more often than you'd like ..
[ Send Message | View Steve's Scratchpad | View Weblogs ]
I'm happy enough using NIS on a trusted LAN even without the use of IPSec.
Although this still doesn't solve the problem of adding the user to the sudoers file ...
[ Parent | Reply to this comment ]
http://aqua.subnet.at/%7Emax/ldap/
http://people.debian.org/%7Etorsten/ldapnss.html
[ Parent | Reply to this comment ]
[ Parent | Reply to this comment ]
It's able to operate over SSL, or if you don't like LDAP-SSL, you can set up a VPN for LDAP (openvpn for example). You can distribute a lot of parameters, like host entries, groups, firewall rules with LDAP, you don't have strict to distribution of users only.
Combined with pam_mkhomedir and extended with cfengine, it would give you infinite power of administration.
Customizing with debian packages is a good idea, for example, I'd do the security related configuration with the help of an own package.
asdmin at gmail dot com
[ Parent | Reply to this comment ]
What about LDAP and PAM ? over secure communications. One LDAP server and a LDAP backup server (replica). Creating classes of computers etc. We have something like that but I am not sure how it is setup. I was involved a bit but at the end a someone else set it up.
Had big problems setting up the LDAP/PAM client on my side under Debian, while the SuSE guys almost just checked LDAP in Yast and it was running. No documentation about Debian online for mixed server clients, but at the end I got it working. RedHat server, Debian client.
I have installed LDAP at home to start to do something similar on my small 4 computer network just for kicks but I have not gotten further then apt-get install ldap :)
If anyone has any hints please place a comment :)
I am not sure if LDAP/PAM can be used by sudoers though, but I guess so.
[ Parent | Reply to this comment ]
[ Parent | Reply to this comment ]
According to me LDAP is the solution. If you have more than one server, use slurpd(replication deamon).
If you want to use your server for centralized authentication(more the 10000 user's, around the world). You can use LDAP with SASL + Referal + slurpd + Pam + nss ldap + nscd + . You can also get the sudo support for the LDAP [1].
This is my admin LDIF, with qmail, samba and sudo spport.
dn: uid=admin,ou=People,dc=foo,dc=com
objectClass: top
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: qmailUser
objectClass: sambaSamAccount
objectClass: sudoRole
cn: admin
uid: admin
uidNumber: 1000
gidNumber: 1000
userPassword: {SSHA}XXXXXXXXXXXXXXXXXXXXXXXXXXX
sudoUser: admin
sudoHost: ALL
sudoCommand: ALL
sudoCommand: !/bin/sh
homeDirectory: /home/admin
loginShell: /bin/bash
mail: admin@foo.com
mailMessageStore: /home/admin/Maildir/
qmailUID: 1000
qmailGID: 1000
deliveryMode: noforward
accountStatus: active
mailQuotaSize: 0
mailSizeMax: 0
sambaLMPassword: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
sambaNTPassword: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
sambaAcctFlags: [U ]
sambaPwdLastSet: 11XXXXXX734
sambaPwdCanChange: 11XXXXXX34
sambaPwdMustChange: 2147483647
sambaSID: S-1-5-21-62781671-XXXXXXXXX-XXXXXXX-3000
sambaPrimaryGroupSID: S-1-5-21-XXXXXXXXX-XXXXXX-3380384210-3001
displayName: foo Server Administrator
gecos: foo Server Administrator
description: foo Server Administrator
sn: admin
[1] http://www.courtesan.com/sudo/readme_ldap.html
Hardik Dalwadi
DeepRoot Linux
[ Parent | Reply to this comment ]
[ Send Message | View Steve's Scratchpad | View Weblogs ]
Thanks for that. I'd been deliberately ignoring LDAP as a "heavyweight" solution (although I should have included it in the list).
But now you've shown that LDAP can be used for managing Sudo it is looking more attractive.
[ Parent | Reply to this comment ]
-=Hardik=-
[ Parent | Reply to this comment ]
--
Dániel Vásárhelyi
[ Parent | Reply to this comment ]
[ Parent | Reply to this comment ]
[ Send Message | View Steve's Scratchpad | View Weblogs ]
An article would certainly be appreciated.
(That goes for pretty much any relevant topic to be honest!)
[ Parent | Reply to this comment ]
[ Parent | Reply to this comment ]
http://www.tom.sfc.keio.ac.jp/~torry/ldap/ldap_en.html
ok, you actually need no tags, the system is smart :)
[ Parent | Reply to this comment ]
All the examples use ldap-utils and the like.
Are they all using customer scripts, or is there some supercool LDAP admin tool that stops it looking like complete voodoo.
All I've ever used OpenLDAP for was a shared address books, and I had to debug the Perl CGI script for updating that.
[ Parent | Reply to this comment ]
* smbldap-tools
* jxplore
* phpldapadmin
* cpu
* or just make your own with perl+ldap, once you understand how a directory works, it really is not very hard (I should know, I am no programmer).
[ Parent | Reply to this comment ]
[ Parent | Reply to this comment ]
(http://www.lichteblau.com/ldapvi.html)!
It's the best for quick modifications (correcting typos etc).
It executes a query, the result is opened in your text editor, you make the changes, after exiting from the editor it produces an ldif from the changes and offers several choices what to do with this ldif (execute on the db, view, save, discard).
Good for experts (quick and straightforward), good for beginners (easy to understand how to produce an ldif) and very useful for the most cases. Of course apt-get install ldapvi is avaible.
--
Dániel Vásárhelyi
[ Parent | Reply to this comment ]
[ Send Message | View dkg's Scratchpad | View Weblogs ]
[ Parent | Reply to this comment ]
[ Send Message | View Serge's Scratchpad | View Weblogs ]
Or you could script an ssh adduser command.
--
Serge van Ginderachter
[ Parent | Reply to this comment ]
[ Send Message | View Steve's Scratchpad | View Weblogs ]
[ Parent | Reply to this comment ]
but i also use ldap. what i am looking for is:
sudo+ldap where user foo can login to machine
bar1 and bar2 but only on machine bar1 he/she can run sudo commands
i already have hostgroups so i only add the user to an other host and then he can also login on the second host
Daniel
[ Parent | Reply to this comment ]
1 shell, many machines executing your commands.
I do this in setups like you describe.
New build systems, or systems where I am allowed to spend some time get converted to ldap
[ Parent | Reply to this comment ]
[ Parent | Reply to this comment ]
[ Parent | Reply to this comment ]
Whilst people are quite correct in suggesting LDAP as a centralised authentication soruce, there are plenty of scenarios where it's not really suitable, for example when you need people to be able to log into the machine locally in a situation where the network is inaccessible.
My solution to adding one user to many machines is to use ClusterSSH. If you've got keys set up on all the machines you're connecting to (and why wouldn't you?) it makes things pretty simple. Sam Bashton
Bashton Ltd - Linux Consultancy
[ Parent | Reply to this comment ]
http://www.csm.ornl.gov/torc/C3/
It is very useful when dealing with many machines.
Has push and exec functionality. One can specify ranges of machines.
Unfortunatly I do not think there is a Debian package.
[ Parent | Reply to this comment ]
[ Parent | Reply to this comment ]
And for LDAP management, it looks simple at first, but the best GUI tool I've come across so far is LDAP Browser/Editor (LBE) - http://www-unix.mcs.anl.gov/~gawor/ldap/installation.html
[ Parent | Reply to this comment ]
Daniel
--
Dániel Vásárhelyi
[ Parent | Reply to this comment ]
[ Parent | Reply to this comment ]
-- Asheesh.
--
/usr/games/fortune|
[ Parent | Reply to this comment ]
The Admin machine was really an internal webserver, that served up user modification pages to the admin staff and stored all user info in a DB. A cron "client" would run every 15 minuets that would send all changes out to the servers.
In practice this completely hand written system worked well, however security wise, maybe not the best of plans. The comunications were encrypted, and the server only responded to admin requests coming from a specific IP, but in retrospect I can think of many cracks that could have been used against this system.
After 2 years use, the company abandoned this system and went with Active Directory, replaceing all their unix machines with windows...
[ Parent | Reply to this comment ]
Lindsey Rockwell
lindseyrockwell@yahoo.se
[ Parent | Reply to this comment ]
On a related tack, why isn't there a web-based auth mechanism? HTTP is the transport of choice these days, why use a specialized protocol like LDAP instead of a simple protocol on top of HTTP?
[ Parent | Reply to this comment ]
--
Lead System Administrator
Aero-Graphics, Inc
http://dataw0lf.org
[ Parent | Reply to this comment ]
[ Parent | Reply to this comment ]
I wrote some code a long time ago to address the issue of running remote commands on a large collection of hosts, as any user.
The script calls "ssh", handles the password prompting, then performs
the specified "Cmd"; which could be anything... like useradd, or passwd,
whatever...
Here's a basic "expect function" (read TCL), that performs a "remote command"...
PS. please pardon the formatting, my cut-n-paste didn't preserve leading tabs...
================================================================= ==
# procedure to execute a command remotely
# SYNTAX: RemoteCommand "Command" HostName UserName UserPassword
# RETURN: error|ok
# ERRORS: failed login (bad passwrod,bad username)
# bad command.
proc RemoteCommand { Cmd Host User Psw } {
global ERR_IGN
global GLOBAL_TIMEOUT
# set timeout value to GLOBAL_TIMEOUT
set timeout $GLOBAL_TIMEOUT
# turn off user display logging
log_user 0
#log_user 1
# clear BAD password flag
set BAD 0
# start the ssh activity
spawn -noecho ssh -l $User $Host $Cmd
# expect...
expect {
# got a password prompt, send password &
# clear BAD flag, then continue in expect loop.
assword: { send "${Psw}\r"
set BAD 0
log_user 1
exp_continue
}
# got a password-bad message, set BAD flag
# and continue in expect loop (retries).
denied { puts stderr "access denied"
set BAD 1
exp_continue
}
# remote side timed out on us.
timeout { puts stderr "timeout"
}
continue { send "yes\r"
exp_continue
}
# we probably sent a bad hostname
"service not known" { puts stderr "bad host ($Host)"
if { $ERR_IGN == 1 } {
return -code ok
} else {
return -code error
}
}
"Received disconnect" { puts stderr "command error ($Cmd)"
if { $ERR_IGN == 1 } {
return -code ok
} else {
return -code error
}
}
# we probably sent a command that wasn't on
# our PATH.
"command not found" { puts stderr "bad command ($Cmd)"
if { $ERR_IGN == 1 } {
return -code ok
} else {
return -code error
}
}
# we got a shell prompt, must be done...
"$ " { log_user 0
return -code ok
}
# we got an "eof" from the spawned process
# so check our BAD flag to let the caller know
# if we got logged in or not.
eof { #puts stdout "connection closed"
if { $BAD == 0 } {
return -code ok
} else {
if { $ERR_IGN == 1 } {
return -code ok
} else {
return -code error
}
}
}
# do some general cleanup here, always a good SYNC
# method to send a CR or 2.
send "\r"
expect "$ "
return -code ok
}
-===============================================
This should give you a "basic" idea of how it works.
Good Luck!
- Tom
[ Parent | Reply to this comment ]
If it's a pretty uniform and relatively safe environment (let's say, a classroom with 'mature' users and identical clients), just running NIS/NFS might do the trick too... perhaps a bit less work initially.
Or have your passwd in CVS. :)
[ Parent | Reply to this comment ]
its great for executing multiple commands on different systems at once
[ Parent | Reply to this comment ]
LDAP seems to have emerged as the recommendation. I am in this
situation as well and LDAP does seem way overkill. My reading led me to
Hesiod which seems able to do the job a just a thin layer over DNS.
But I haven't done the switch, because what I'd really like is to
synchronize the system user IDs as well (and group IDs of course). I
just hate seeing random numeric IDs when I do ls -l on a net-mounted
directory. So the challenge is not really (or not as much) how to do
the distribution of IDs to multiple machines, but mostly how to stop the
debian package maintainer scripts from doing stupid things:
1. installing the same system user / group with different IDs, and
(especially!)
2. removing system users / groups once installed. Ever. AT ALL!!
My existing approach has been:
1. replace {user,group}add scripts with variants that warn me loudly
about what is happening.
2. keep /etc/{passwd,group} under version control, in a single
repository with a branch for each host, and when the warning in 1 above
is triggered, cherry-pick the diff to the other hosts.
3. replace {user,group}del scripts with variants that do NOTHING. :-)
(The original scripts are still available under a different name so
removing a user manually is not a problem.)
But it is still a chore. Suggestions?
All this because we still don't have a network file system that is
higher-level than NFS but not hopeless overkill like Gluster etc.
[ Parent | Reply to this comment ]
[ Parent | Reply to this comment ]