From abfe84ca1bf183ef33ee25ac66820a2e256cb520 Mon Sep 17 00:00:00 2001 From: Clinton Ebadi Date: Fri, 11 Jan 2013 03:06:18 -0500 Subject: [PATCH] "Factored" create-user, and script to create shared service users Converted create-user script into a set of procedures, grouped by logical step in the user creation process. Things were regrouped only as much as was needed to get `create-service-user' script for creating principles for non-humans and `create-user` working with minimal duplication. This still needs a lot of work (and destroy-user even more). --- create-service-user | 43 ++++++ create-user-new | 52 ++++++++ lib/create-user-lib.sh | 295 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 390 insertions(+) create mode 100755 create-service-user create mode 100755 create-user-new create mode 100644 lib/create-user-lib.sh diff --git a/create-service-user b/create-service-user new file mode 100755 index 0000000..a3144c4 --- /dev/null +++ b/create-service-user @@ -0,0 +1,43 @@ +#!/bin/bash -ex + +# create a shared service user, that is not able to use mod_waklog. + +# MUST be executed: +# - on fritz +# - as a user with an /etc/sudoers line +# - member of "wheel" unix group on deleuze (FIXME: TRUE?) +# - while holding tickets for a user who can 'ssh -K' to mire +# - and is a member of "wheel" on mire +# - while holding tokens for a user who is: +# - a member of system:administrator +# - listed in 'bos listusers fritz' +# - and who has been set up with Domtool admin privileges by: +# - running 'domtool-adduser $USER' while holding AFS admin tokens as +# someone who is already a Domtool admin +# - running 'domtool-admin grant $USER priv all' as someone who is already a +# Domtool admin +# (To bootstrap yourself into admindom: +# 1. Run '/etc/init.d/domtool-server stop' on deleuze. +# 2. Run '/etc/init.d/domtool-slave stop' on all Domtool slave machines +# (e.g., mire). +# 3. Edit ~domtool/acl, following the example of adamc_admin to grant +# yourself 'priv all'. +# 4. Run '/etc/init.d/domtool-server start' on deleuze. +# 5. Run '/etc/init.d/domtool-slave start' on all Domtool slave +# machines. +# 6. Run 'domtool-adduser' as above.) + +NEWUSER=$1 + +if test -z "$NEWUSER"; then + echo "Invoke as create-user " + exit 1 +fi + +source /afs/hcoop.net/common/etc/scripts/lib/create-user-lib.sh + +create_pts_user + +create_home_volume + +ensure_afs_servers_synced \ No newline at end of file diff --git a/create-user-new b/create-user-new new file mode 100755 index 0000000..b35f935 --- /dev/null +++ b/create-user-new @@ -0,0 +1,52 @@ +#!/bin/bash -ex + +# MUST be executed: +# - on fritz +# - as a user with an /etc/sudoers line +# - member of "wheel" unix group on deleuze (FIXME: TRUE?) +# - while holding tickets for a user who can 'ssh -K' to mire +# - and is a member of "wheel" on mire +# - while holding tokens for a user who is: +# - a member of system:administrator +# - listed in 'bos listusers fritz' +# - and who has been set up with Domtool admin privileges by: +# - running 'domtool-adduser $USER' while holding AFS admin tokens as +# someone who is already a Domtool admin +# - running 'domtool-admin grant $USER priv all' as someone who is already a +# Domtool admin +# (To bootstrap yourself into admindom: +# 1. Run '/etc/init.d/domtool-server stop' on deleuze. +# 2. Run '/etc/init.d/domtool-slave stop' on all Domtool slave machines +# (e.g., mire). +# 3. Edit ~domtool/acl, following the example of adamc_admin to grant +# yourself 'priv all'. +# 4. Run '/etc/init.d/domtool-server start' on deleuze. +# 5. Run '/etc/init.d/domtool-slave start' on all Domtool slave +# machines. +# 6. Run 'domtool-adduser' as above.) + +NEWUSER=$1 + +if test -z "$NEWUSER"; then + echo "Invoke as create-user " + exit 1 +fi + +source /afs/hcoop.net/common/etc/scripts/lib/create-user-lib.sh + +create_pts_user +create_pts_user_daemon +export_user_keytabs + +create_home_volume +create_mail_volume + +ensure_afs_servers_synced + +seed_user_hcoop_directories +setup_user_databases +create_dav_locks + +enable_domtool + +subscribe_to_lists \ No newline at end of file diff --git a/lib/create-user-lib.sh b/lib/create-user-lib.sh new file mode 100644 index 0000000..51834ef --- /dev/null +++ b/lib/create-user-lib.sh @@ -0,0 +1,295 @@ +# -*- sh-mode -*- + +# Library functions for create-user scripts +# Export the $NEWUSER variable before sourcing! + +# Functionality is split so that the scripts for creating real users, +# service users, and web service users can share as much code as +# possible. + +# This has probably grown to the point where it shouldn't be a shell +# script any more. + +# ALWAYS REMEMBER: THIS MUST BE IDEMPOTENT! re creating a user is +# something that should be perfectly permissible, and is something +# that we do somewhat regularly (to bring old accounts up to date). + +export PATH=$PATH:/afs/hcoop.net/common/bin/ + +if test -z "$NEWUSER"; then + echo "NEWUSER not set before sourcing create user library" + exit 1 +fi + +# +# Construct various paths for later perusal. +# + +# (If it's not clear, for user fred, PATHBITS = f/fr/fred) +PATHBITS=`echo $NEWUSER | head -c 1`/`echo $NEWUSER | head -c 2`/$NEWUSER +HOMEPATH=/afs/hcoop.net/user/$PATHBITS +MAILPATH=/afs/hcoop.net/common/email/$PATHBITS + +# +# Helper functions +# + +function execute_on_web_nodes () { + ssh -K deleuze $* + ssh -K mire $* + ssh -K navajos $* +} + +function execute_on_domtool_server () { + ssh -K deleuze.hcoop.net $* +} + + +function execute_on_all_machines () { + $* + ssh -K mire.hcoop.net $* + ssh -K hopper.hcoop.net $* + ssh -K deleuze.hcoop.net $* + ssh -K navajos.hcoop.net $* + ssh -K bog.hcoop.net $* +} + +# +# User credentials +# + +function create_pts_user () { + # Create primary user kerberos principle and afs pts user + + # We use -randkey for user's main principal as well, to make sure + # that the creation process does not continue without having a + # main principal. (But you who want to set password for a user, + # don't worry - we'll invoke cpw later, so that it has the same + # effect as setting password right now - while it is more error + # tolerant). + + sudo kadmin.local -p root/admin -q "ank -policy user -randkey +requires_preauth $NEWUSER@HCOOP.NET" + sudo kadmin.local -p root/admin -q "modprinc -maxlife 1day $NEWUSER@HCOOP.NET" + + pts cu $NEWUSER || true +} + +function create_pts_user_daemon () { + + # Create additional kerberos principles ($user.daemon for now, in + # theory also $user.mail, $user.cgi) and pts users for any used to + # gain afs access ($user.daemon only) + sudo kadmin.local -p root/admin -q "ank -policy daemon -randkey +requires_preauth $NEWUSER/daemon@HCOOP.NET" + pts cu $NEWUSER.daemon || true +} + +function export_user_keytabs () { + + # Export .mailfilter and .cgi keys to a keytab file + + # This is suboptimal, we need to generate keytabs for + # cgi/mail/etc. separately, and only sync to the nodes that + # perform the services in question + + # create a daemon keytab (used by /etc/exim4/get-token) + # *only* if it does not exist! + test -e /etc/keytabs/user.daemon/$NEWUSER || \ + sudo kadmin.local -p root/admin -q "ktadd -k /etc/keytabs/user.daemon/$NEWUSER $NEWUSER/daemon@HCOOP.NET" + + # Properly chown/mod keytab files (must be $NEWUSER:www-data) + sudo chown $NEWUSER:www-data /etc/keytabs/user.daemon/$NEWUSER + sudo chmod 440 /etc/keytabs/user.daemon/$NEWUSER + + # rsync keytabs + (cd /etc/keytabs + sudo tar clpf - user.daemon/$NEWUSER | \ + ssh mire.hcoop.net cd /etc/keytabs\; sudo tar xlpf -) + (cd /etc/keytabs + sudo tar clpf - user.daemon/$NEWUSER | \ + ssh hopper.hcoop.net cd /etc/keytabs\; sudo tar xlpf -) + (cd /etc/keytabs + sudo tar clpf - user.daemon/$NEWUSER | \ + ssh deleuze.hcoop.net cd /etc/keytabs\; sudo tar xlpf -) + (cd /etc/keytabs + sudo tar clpf - user.daemon/$NEWUSER | \ + ssh navajos.hcoop.net cd /etc/keytabs\; sudo tar xlpf -) + (cd /etc/keytabs + sudo tar clpf - user.daemon/$NEWUSER | \ + ssh bog.hcoop.net cd /etc/keytabs\; sudo tar xlpf -) +} + + +# +# Create/mount/set-perms on user's volumes (home, mail, databases, logs) +# + +# Each function that creates an afs volume should ensure that the +# backup volume is created and mounted for users. + +function create_home_volume () { + + if vos examine user.$NEWUSER.d 2>/dev/null; then + echo "Reactivating old volume (user.$NEWUSER.d)" + vos rename user.$NEWUSER.d user.$NEWUSER + fi + vos examine user.$NEWUSER 2>/dev/null || \ + vos create fritz.hcoop.net /vicepa user.$NEWUSER -maxquota 400000 + + mkdir -p `dirname $HOMEPATH` + fs ls $HOMEPATH || test -L $HOMEPATH || fs mkm $HOMEPATH user.$NEWUSER + chown $NEWUSER:nogroup $HOMEPATH + fs sa $HOMEPATH $NEWUSER all + fs sa $HOMEPATH system:anyuser l + # cleanliness / needed to keep suphp happy + chown root:root $HOMEPATH/../../ + chown root:root $HOMEPATH/../ + + # backup volume + mkdir -p `dirname /afs/hcoop.net/.old/user/$PATHBITS` + fs ls /afs/hcoop.net/.old/user/$PATHBITS || \ + fs mkm /afs/hcoop.net/.old/user/$PATHBITS user.$NEWUSER.backup +} + + +function create_mail_volume () { + + if vos examine mail.$NEWUSER.d 2>/dev/null; then + echo "Reactivating old volume (mail.$NEWUSER.d)" + vos rename mail.$NEWUSER.d mail.$NEWUSER + fi + vos examine mail.$NEWUSER 2>/dev/null || \ + vos create fritz.hcoop.net /vicepa mail.$NEWUSER -maxquota 400000 + + mkdir -p `dirname $MAILPATH` + fs ls $MAILPATH || fs mkm $MAILPATH mail.$NEWUSER + fs ls $HOMEPATH/Maildir || fs mkm $HOMEPATH/Maildir mail.$NEWUSER + chown $NEWUSER:nogroup $MAILPATH + chown $NEWUSER:nogroup $HOMEPATH/Maildir + fs sa $MAILPATH $NEWUSER all + fs sa $MAILPATH $NEWUSER.daemon all + + if test ! -e $MAILPATH/new; then + mkdir -p $MAILPATH/cur $MAILPATH/new $MAILPATH/tmp + echo -e "This email account is provided as a service for HCoop members." \ + "\n\nTo learn how to use it, please visit the page" \ + "\n on our website."| \ + mail -s "Welcome to your HCoop email store" \ + -e -a "From: postmaster@hcoop.net" \ + real-$NEWUSER + fi + + chown $NEWUSER:nogroup $MAILPATH/cur $MAILPATH/new $MAILPATH/tmp + + # Set up shared SpamAssassin folder + if test -f $HOMEPATH/Maildir/shared-maildirs; then + # Deal with case where user rsync'd their Maildir from fyodor + # Not an issue now, but harmless and can be adapted when we + # move the spamd dirs into afs where they belong later. + pattern='^SpamAssassin /home/spamd' + file=$HOMEPATH/Maildir/shared-maildirs + if grep $pattern $file; then + sed -i -r -e \ + 's!^(SpamAssassin )/home/spamd!\1/var/local/lib/spamd!1' \ + $file + fi + else + maildirmake --add SpamAssassin=/var/local/lib/spamd/Maildir \ + $HOMEPATH/Maildir + fi + + mkdir -p `dirname /afs/hcoop.net/.old/mail/$PATHBITS` + fs ls /afs/hcoop.net/.old/mail/$PATHBITS || \ + fs mkm /afs/hcoop.net/.old/mail/$PATHBITS mail.$NEWUSER.backup + vos release old +} + +function seed_user_hcoop_directories () { + # Additional standard directories. Some of these should probably + # be on their own volumes, and access via a canonical path instead + # to give users more control over their home dir without risking + # breaking system services. + + # Apache logs + mkdir -p $HOMEPATH/.logs + chown $NEWUSER:nogroup $HOMEPATH/.logs + mkdir -p $HOMEPATH/.logs/apache + chown $NEWUSER:nogroup $HOMEPATH/.logs/apache + fs sa $HOMEPATH/.logs/apache $NEWUSER.daemon rlwidk + mkdir -p $HOMEPATH/.logs/mail + fs sa $HOMEPATH/.logs/mail $NEWUSER.daemon rlwidk + chown $NEWUSER:nogroup $HOMEPATH/.logs/mail + + # public_html + test -e $HOMEPATH/public_html || \ + (mkdir -p $HOMEPATH/public_html; \ + chown $NEWUSER:nogroup $HOMEPATH/public_html; \ + fs sa $HOMEPATH/public_html system:anyuser none; \ + fs sa $HOMEPATH/public_html $NEWUSER.daemon rl) + + # .procmail.d + mkdir -p $HOMEPATH/.procmail.d + chown $NEWUSER:nogroup $HOMEPATH/.procmail.d + fs sa $HOMEPATH/.procmail.d system:anyuser rl + + # .public + mkdir -p $HOMEPATH/.public/ + chown $NEWUSER:nogroup $HOMEPATH/.public + fs sa $HOMEPATH/.public system:anyuser rl + + # .domtool + mkdir -p $HOMEPATH/.public/.domtool + chown $NEWUSER:nogroup $HOMEPATH/.public/.domtool + test -e $HOMEPATH/.domtool || \ + test -L $HOMEPATH/.domtool || \ + execute_on_domtool_server sudo -u $NEWUSER ln -s $HOMEPATH/.public/.domtool $HOMEPATH/.domtool + # ^^ work around sudo env_reset crap without having to + # actually figure out how to make it work cleanly -- clinton, + # 2011-11-30 + + # Gitweb hosting + test -L /var/cache/git/$NEWUSER || \ + sudo ln -s $HOMEPATH/.hcoop-git /var/cache/git/$NEWUSER + +} + +# +# Non-AFS files and directories +# + +function create_dav_locks () { + # Make per-user apache DAV lock directory -- the directory must be + # both user and group-writable, which is silly. + execute_on_web_nodes sudo mkdir -p /var/lock/apache2/dav/$NEWUSER + execute_on_web_nodes sudo chown $NEWUSER:www-data /var/lock/apache2/dav/$NEWUSER + execute_on_web_nodes sudo chmod ug=rwx,o= /var/lock/apache2/dav/$NEWUSER +} + +function setup_user_databases () { + sudo /afs/hcoop.net/common/etc/scripts/create-user-database $NEWUSER +} + +# +# etc +# + +function enable_domtool () { + execute_on_domtool_server domtool-adduser $NEWUSER +} + +function subscribe_to_lists () { + # Subscribe user to our mailing lists. + + echo $NEWUSER@hcoop.net | ssh -K deleuze sudo -u list \ + /var/lib/mailman/bin/add_members -r - hcoop-announce +} + +function ensure_afs_servers_synced () { + vos release old + + # technically this might not be necessary, but for good measure... + vos syncserv fritz + vos syncvldb fritz + + # refresh volume location cache (takes ~2hrs otherwise) + execute_on_all_machines fs checkvolumes +} \ No newline at end of file -- 2.20.1