Whamcloud - gitweb
b=23588 conf-sanity.sh:test_50g - wait for new OST addition propagation to a client
[fs/lustre-release.git] / lustre / tests / setup_kerberos.sh
1 #!/bin/bash
2 # vim:expandtab:shiftwidth=4:softtabstop=4:tabstop=4:
3
4 #
5 # setup_kerberos.sh - setup the Kerberos environment on Lustre cluster
6 #
7 # Notes:
8 #  * Only one KDC involved, no slave KDC.
9 #  * Only one Kerberos realm involved, no multiple Kerberos realms.
10 #
11 ###############################################################################
12
13 # usage
14 my_usage() {
15     cat <<EOF
16 Usage: $(basename $0) <KDC_distro> <KDC_node> <MGS_node> <MDS_node>[:MDS_node:...]
17                       <OSS_node>[:OSS_node:...] <CLIENT_node>[:CLIENT_node:...]
18
19     This script is used to setup the Kerberos environment on Lustre cluster.
20
21     KDC_distro      distribution on the KDC node (rhel5 or sles10)
22     KDC_node        KDC node name
23     MGS_node        Lustre MGS node name
24     MDS_node        Lustre MDS node name
25     OSS_node        Lustre OSS node name
26     CLIENT_node     Lustre client node name
27
28     e.g.: $(basename $0) rhel5 scsi2 scsi2 sata2 sata3 client5
29     e.g.: $(basename $0) sles10 scsi2 scsi2 scsi2 sata3:sata5 client2:client3
30     e.g.: $(basename $0) rhel5 scsi2 scsi2 scsi2 scsi2 scsi2
31
32     Notes:
33     1) The script will destroy all the old Kerberos settings by default. If you
34     want to reserve the original krb5.conf and KDC configuration, please set
35     "RESET_KDC=false".
36
37     2) The script will create principals for some runas users and add them into
38     the Kerberos database by default. The UIDs of the runas users specified in 
39     "LOCAL_UIDS" variable need exist on KDC, MDS and Client nodes. If you do not
40     need runas users, please set "CFG_RUNAS=false".
41
42     3) The script will create idmap.conf and perm.conf under /etc/lustre dir on
43     MDS node for remote ACL by default. If you do not need remote ACL, please
44     set "CFG_IDMAP=false".
45
46 EOF
47 }
48
49 # ************************ Parameters and Variables ************************ #
50 MY_KDC_DISTRO=$1
51 MY_KDCNODE=$2
52 MY_MGSNODE=$3
53 MY_MDSNODES=$4
54 MY_OSSNODES=$5
55 MY_CLIENTNODES=$6
56
57 # translate to lower case letters
58 MY_KDC_DISTRO=$(echo $MY_KDC_DISTRO | tr '[A-Z]' '[a-z]')
59
60 if [ -z "$MY_KDC_DISTRO" -o -z "$MY_KDCNODE" -o -z "$MY_MDSNODES" -o \
61     -z "$MY_OSSNODES" -o -z "$MY_CLIENTNODES" -o -z "$MY_MGSNODE" ]; then
62     my_usage
63     exit 1
64 fi
65
66 LUSTRE=${LUSTRE:-$(cd $(dirname $0)/..; echo $PWD)}
67 . $LUSTRE/tests/test-framework.sh
68 init_test_env
69 . ${CONFIG:=$LUSTRE/tests/cfg/$NAME.sh}
70
71 SCP=${SCP:-"scp -q"}
72 ACCEPTOR_PORT=${ACCEPTOR_PORT:-988}
73
74 # check and configure runas users
75 CFG_RUNAS=${CFG_RUNAS:-true}
76 # uids for local and remote users
77 LOCAL_UIDS=${LOCAL_UIDS:-"500 501"}
78 REMOTE_UIDS=${REMOTE_UIDS:-"500 501"}   # for remote ACL testing
79
80 # remove the original Kerberos and KDC settings
81 RESET_KDC=${RESET_KDC:-true}
82
83 # generate unique keytab for each client node
84 SPLIT_KEYTAB=${SPLIT_KEYTAB:-true}
85
86 # encryption types for generating keytab
87 MDS_ENCTYPE=${MDS_ENCTYPE:-"aes128-cts"}
88 MGS_ENCTYPE=${MGS_ENCTYPE:-"$MDS_ENCTYPE"}
89 OSS_ENCTYPE=${OSS_ENCTYPE:-"aes128-cts"}
90 CLIENT_ENCTYPE=${CLIENT_ENCTYPE:-"aes128-cts"}
91
92 # configuration file for Kerberos
93 KRB5_CONF=${KRB5_CONF:-"/etc/krb5.conf"}
94 KRB5_KEYTAB=${KRB5_KEYTAB:-"/etc/krb5.keytab"}
95 KRB5_TICKET_LIFETIME=${KRB5_TICKET_LIFETIME:-"24h"}
96
97 # configuration files for libgssapi and keyutils
98 GSSAPI_MECH_CONF=${GSSAPI_MECH_CONF:-"/etc/gssapi_mech.conf"}
99 REQUEST_KEY_CONF=${REQUEST_KEY_CONF:-"/etc/request-key.conf"}
100
101 # create configuration files for remote ACL testing
102 CFG_IDMAP=${CFG_IDMAP:-true}
103 LUSTRE_CONF_DIR=${LUSTRE_CONF_DIR:-"/etc/lustre"}
104 IDMAP_CONF=$LUSTRE_CONF_DIR/idmap.conf
105 PERM_CONF=$LUSTRE_CONF_DIR/perm.conf
106
107 # krb5 realm & domain
108 KRB5_REALM=${KRB5_REALM:-"CO.CFS"}
109 KRB5_DOMAIN=$(echo $KRB5_REALM | tr '[A-Z]' '[a-z]')
110
111 MY_MDSNODES=${MY_MDSNODES//:/ }
112 MY_OSSNODES=${MY_OSSNODES//:/ }
113 MY_CLIENTNODES=${MY_CLIENTNODES//:/ }
114
115 # set vars according to the KDC distribution
116 KRB5PKG_SVR="krb5-server"
117 KRB5PKG_DEV="krb5-devel"
118 case $MY_KDC_DISTRO in
119     rhel5)
120         KRB5PKG_CLI="krb5-workstation"
121         KRB5PKG_LIB="krb5-libs"
122         KDC_CONF_DIR="/var/kerberos/krb5kdc"
123         ;;
124     sles10)
125         KRB5PKG_CLI="krb5-client"
126         KRB5PKG_LIB="krb5"
127         KDC_CONF_DIR="/var/lib/kerberos/krb5kdc"
128         ;;
129     *)
130         echo "Unsupported KDC distro: $MY_KDC_DISTRO!"
131         exit 1
132 esac
133 KDC_CONF="$KDC_CONF_DIR/kdc.conf"
134 KDC_ACL="$KDC_CONF_DIR/kadm5.acl"
135
136 # ******************************** Functions ******************************** #
137 is_part_of() {
138     local name="$1"
139     shift
140     local list="$@"
141
142     if [ -z "$name" -o -z "$list" ]; then
143         false
144         return
145     fi
146
147     if [[ " $list " == *\ $name\ * ]]; then
148         true
149     else
150         false
151     fi
152
153     return
154 }
155
156 my_do_node() {
157     local node=$1
158     shift
159     local nodename=${node%.$KRB5_DOMAIN}
160     do_node $node "PATH=\$PATH:/usr/kerberos/sbin:/usr/kerberos/bin:\
161 /usr/lib/mit/sbin:/usr/lib/mit/bin $@" | sed "s/^${nodename}: //"
162     return ${PIPESTATUS[0]}
163 }
164
165 do_node_mute() {
166     local output
167     output=$(my_do_node "$@" 2>&1)
168     return ${PIPESTATUS[0]}
169 }
170
171 do_kdc() {
172     my_do_node $MY_KDCNODE "$@"
173     return ${PIPESTATUS[0]}
174 }
175
176 do_kdc_mute() {
177     do_node_mute $MY_KDCNODE "$@"
178     return ${PIPESTATUS[0]}
179 }
180
181 #
182 # convert a space-delimited node name list to a canonical name list
183 #
184 get_fqdn() {
185     local nodename_list="$@"
186     local fqdn_list=""
187     local name
188     local fqdn
189     local rc
190
191     for name in $nodename_list; do
192         fqdn=$(do_kdc "gethostip -n $name 2>&1")
193         rc=${PIPESTATUS[0]}
194         if [ $rc -ne 0 ]; then
195             echo "Can not get the FQDN of node $name: $fqdn"
196             return $rc
197         fi
198         [ -z "$fqdn_list" ] && fqdn_list="$fqdn" \
199         || fqdn_list="$fqdn_list $fqdn"
200
201     done
202
203     echo "$fqdn_list"
204     return 0
205 }
206
207 #
208 # convert MDS/OSS nodes to their canonical name, it required by
209 # kerberos. we also convert kdc and client too in order to make
210 # node name comparison easier
211 #
212 normalize_names() {
213     local rc
214
215     # KDC
216     MY_KDCNODE=$(get_fqdn $MY_KDCNODE)
217     rc=${PIPESTATUS[0]}
218     if [ $rc -ne 0 ]; then
219         echo $MY_KDCNODE
220         return $rc
221     fi
222
223     # MGS node
224     MY_MGSNODE=$(get_fqdn $MY_MGSNODE)
225     rc=${PIPESTATUS[0]}
226     if [ $rc -ne 0 ]; then
227         echo $MY_MGSNODE
228         return $rc
229     fi
230
231     # MDS nodes
232     MY_MDSNODES=$(get_fqdn $MY_MDSNODES)
233     rc=${PIPESTATUS[0]}
234     if [ $rc -ne 0 ]; then
235         echo $MY_MDSNODES
236         return $rc
237     fi
238
239     # OSS nodes
240     MY_OSSNODES=$(get_fqdn $MY_OSSNODES)
241     rc=${PIPESTATUS[0]}
242     if [ $rc -ne 0 ]; then
243         echo $MY_OSSNODES
244         return $rc
245     fi
246
247     # client nodes
248     MY_CLIENTNODES=$(get_fqdn $MY_CLIENTNODES)
249     rc=${PIPESTATUS[0]}
250     if [ $rc -ne 0 ]; then
251         echo $MY_CLIENTNODES
252         return $rc
253     fi
254
255     return 0
256 }
257
258 #
259 # verify remote shell works on all nodes
260 #
261 check_rsh() {
262     local checked=""
263     local node
264
265     echo "+++ Checking remote shell"
266
267     for node in $MY_KDCNODE $MY_MGSNODE $MY_OSSNODES $MY_MDSNODES $MY_CLIENTNODES
268     do
269         is_part_of $node $checked && continue
270
271         echo -n "Checking remote shell on $node..."
272         do_node_mute $node true || return ${PIPESTATUS[0]}
273         echo "OK!"
274
275         checked="$checked $node"
276     done
277 }
278
279 #
280 # verify the entropy (random numbers) on the KDC node, which is
281 # used by kdb5_util to create Kerberos database
282 #
283 check_entropy() {
284     local limit=170
285     local avail
286
287     echo "+++ Checking the entropy on the KDC"
288
289     echo -n "Checking $MY_KDCNODE..."
290     avail=$(do_kdc "sysctl -n kernel.random.entropy_avail")
291     local rc=${PIPESTATUS[0]}
292     if [ $rc -eq 0 ]; then
293         if [ $avail -lt $limit ]; then
294             echo -e "\nWarning: The entropy on the KDC node is only $avail, \
295 which is not enough for kdb5_util to create Kerberos database! \
296 Let's use /dev/urandom!"
297             do_kdc "rm -f /dev/random.bak && mv /dev/random{,.bak} && \
298 mknod /dev/random c 1 9"
299             return ${PIPESTATUS[0]}
300         fi
301     else
302         echo "Can not get the entropy on the KDC node!"
303         return $rc
304     fi
305     echo "OK!"
306 }
307
308 #
309 # verify runas users and groups
310 #
311 check_users() {
312     local checked=""
313     local node
314     local id
315     local user
316
317     echo "+++ Checking users and groups"
318
319     for node in $MY_KDCNODE $MY_MGSNODE $MY_MDSNODES $MY_CLIENTNODES; do
320         is_part_of $node $checked && continue
321
322         for id in $LOCAL_UIDS; do
323             echo -n "Checking uid/gid $id/$id on $node..."
324             user=$(my_do_node $node getent passwd | grep :$id:$id: | cut -d: -f1)
325             if [ -z "$user" ]; then
326                 echo -e "\nPlease set LOCAL_UIDS and REMOTE_UIDS to some users \
327 which exist on KDC, MDS and client or add user/group $id/$id on these nodes."
328                 return 1
329             fi
330             echo "OK!"
331         done
332         checked="$checked $node"
333     done
334 }
335
336 cfg_mount() {
337     local node=$1
338     local dev=$2
339     local dir=$3
340
341     echo -n "Checking $dev mount on $node..."
342     if do_node_mute $node "grep -q $dir' ' /proc/mounts"; then
343         echo "OK!"
344         return 0
345     fi
346
347     if ! do_node_mute $node "grep -q ^$dev /etc/fstab"; then
348         my_do_node $node "echo '$dev $dir $dev defaults 0 0' >> /etc/fstab" || \
349             return ${PIPESTATUS[0]}
350     fi
351     my_do_node $node "mkdir -p $dir && mount $dir" || true
352
353     if ! do_node_mute $node "grep -q $dir' ' /proc/mounts"; then
354         echo "Failed to mount fs $dev at $dir!"
355         return 1
356     fi
357     echo "OK!"
358 }
359
360 #
361 # configure nfsd mount on MDS and OSS nodes
362 #
363 cfg_nfs_mount() {
364     local checked=""
365     local node
366
367     echo "+++ Configuring nfsd mount"
368
369     for node in $MY_MGSNODE $MY_OSSNODES $MY_MDSNODES; do
370         is_part_of $node $checked && continue
371         cfg_mount $node nfsd /proc/fs/nfsd || return ${PIPESTATUS[0]}
372         checked="$checked $node"
373     done
374 }
375
376 get_pkgname() {
377     local node=$1
378     local pkg=$2
379
380     my_do_node $node "rpm -q $pkg 2>&1" | tail -n1
381     return ${PIPESTATUS[0]}
382 }
383
384 get_krb5pkgname() {
385     local node=$1
386     local flavor=$2
387
388     my_do_node $node cat /etc/SuSE-release 2>/dev/null | \
389     grep -q 'Enterprise Server 10'
390     if [ ${PIPESTATUS[1]} -eq 0 ]; then
391         case $flavor in
392             cli) echo "krb5-client";;
393             lib) echo "krb5";;
394         esac
395     else
396         case $flavor in
397             cli) echo "krb5-workstation";;
398             lib) echo "krb5-libs";;
399         esac
400     fi
401 }
402
403 check_kdc() {
404     local pkg
405     local rc
406
407     echo "+++ Checking KDC installation"
408
409     echo -n "Checking $MY_KDCNODE..."
410     pkg=$(get_pkgname $MY_KDCNODE $KRB5PKG_SVR)
411     rc=${PIPESTATUS[0]}
412     if [ $rc -ne 0 ]; then
413         echo -e "\nCan not find $KRB5PKG_SVR package on $MY_KDCNODE: $pkg"
414         return $rc
415     fi
416     echo "OK!"
417 }
418
419 check_krb5() {
420     local checked=""
421     local pkg
422     local rc
423     local krb5pkg_cli
424
425     echo "+++ Checking Kerberos 5 installation"
426     for node in $MY_MGSNODE $MY_OSSNODES $MY_MDSNODES $MY_CLIENTNODES; do
427         is_part_of $node $checked && continue
428
429         echo -n "Checking $node..."
430         krb5pkg_cli=$(get_krb5pkgname $node cli)
431
432         pkg=$(get_pkgname $node $krb5pkg_cli)
433         rc=${PIPESTATUS[0]}
434         if [ $rc -ne 0 ]; then
435             echo -e "\nCan not find $krb5pkg_cli package on $node: $pkg"
436             return $rc
437         fi
438         echo "OK!"
439         checked="$checked $node"
440     done
441 }
442
443 check_libgssapi() {
444     local checked=""
445     local node
446     local pkg
447     local rc
448
449     echo "+++ Checking libgssapi installation"
450
451     LIBGSSAPI=$(get_pkgname $MY_KDCNODE libgssapi)
452     rc=${PIPESTATUS[0]}
453     if [ $rc -ne 0 ]; then
454         echo "Can not find libgssapi package on $MY_KDCNODE: $LIBGSSAPI"
455         return $rc
456     fi
457
458     for node in $MY_MGSNODE $MY_OSSNODES $MY_MDSNODES $MY_CLIENTNODES; do
459         is_part_of $node $checked && continue
460
461         echo -n "Checking $node..."
462         pkg=$(get_pkgname $node libgssapi)
463         rc=${PIPESTATUS[0]}
464         if [ $rc -ne 0 ]; then
465             echo -e "\nCan not find libgssapi package on $node: $pkg"
466             return $rc
467         fi
468         echo "OK!"
469         checked="$checked $node"
470     done
471 }
472
473 #
474 # check and update the /etc/gssapi_mech.conf file on each node
475 # We only support MIT Kerberos 5 GSS-API mechanism.
476 #
477 cfg_libgssapi() {
478     local checked=""
479     local node
480     local pkg
481     local rc
482     local krb5pkg_lib
483     local krb5_lib 
484
485     echo "+++ Updating $GSSAPI_MECH_CONF"
486
487     for node in $MY_KDCNODE $MY_MGSNODE $MY_OSSNODES $MY_MDSNODES $MY_CLIENTNODES
488     do
489         is_part_of $node $checked && continue
490
491         krb5pkg_lib=$(get_krb5pkgname $node lib)
492         pkg=$(get_pkgname $node $krb5pkg_lib)
493         rc=${PIPESTATUS[0]}
494         if [ $rc -ne 0 ]; then
495             echo -e "\nCan not find $krb5pkg_lib package on $node: $pkg"
496             return $rc
497         fi
498
499         krb5_lib=$(my_do_node $node "rpm -ql $pkg" | \
500                     grep libgssapi_krb5.so | head -n1)
501
502         if ! do_node_mute $node \
503 "egrep -q \\\"^$krb5_lib|^$(basename $krb5_lib)\\\" $GSSAPI_MECH_CONF"; then
504             do_node_mute $node \
505 "echo '$krb5_lib mechglue_internal_krb5_init' >> $GSSAPI_MECH_CONF"
506         fi
507         checked="$checked $node"
508     done
509     echo "OK!"
510 }
511
512 #
513 # check and update the /etc/request-key.conf file on each MDS and client node
514 #
515 cfg_keyutils() {
516     local checked=""
517     local node
518     local lgss_keyring
519
520     echo "+++ Updating $REQUEST_KEY_CONF"
521
522     for node in $MY_MGSNODE $MY_MDSNODES $MY_CLIENTNODES; do
523         is_part_of $node $checked && continue
524         lgss_keyring=$(my_do_node $node "which lgss_keyring") || \
525             return ${PIPESTATUS[0]}
526
527         if ! do_node_mute $node \
528 "grep -q \\\"^create.*$lgss_keyring\\\" $REQUEST_KEY_CONF"; then
529             do_node_mute $node \
530 "echo 'create lgssc * * $lgss_keyring %o %k %t %d %c %u %g %T %P %S' \
531 >> $REQUEST_KEY_CONF"
532         fi
533         checked="$checked $node"
534     done
535     echo "OK!"
536 }
537
538 add_svc_princ() {
539     local fqdn=$1
540     local type=$2
541
542     echo -n "Creating service principal lustre_$type/$fqdn@$KRB5_REALM..."
543     do_kdc_mute "kadmin.local -r $KRB5_REALM <<EOF
544 addprinc -randkey lustre_$type/$fqdn@$KRB5_REALM
545 EOF"
546     local rc=${PIPESTATUS[0]}
547     [ $rc -ne 0 ] && echo "Failed!" || echo "OK!"
548
549     return $rc
550 }
551
552 add_svc_princ_root() {
553     echo -n "Creating service principal lustre_root@$KRB5_REALM..."
554     do_kdc_mute "kadmin.local -r $KRB5_REALM <<EOF
555 addprinc -randkey lustre_root@$KRB5_REALM
556 EOF"
557     local rc=${PIPESTATUS[0]}
558     [ $rc -ne 0 ] && echo "Failed!" || echo "OK!"
559
560     return $rc
561 }
562
563 add_user_princ() {
564     local user=$1
565
566     echo -n "Creating user principal $user@$KRB5_REALM..."
567     do_kdc_mute "kadmin.local -r $KRB5_REALM <<EOF
568 addprinc -pw $user $user@$KRB5_REALM
569 EOF"
570     local rc=${PIPESTATUS[0]}
571     [ $rc -ne 0 ] && echo "Failed!" || echo "OK!"
572
573     return $rc
574 }
575
576 add_test_princ_id() {
577     local id=$1
578     local user
579
580     user=$(do_kdc getent passwd $id | cut -d: -f1)
581     if [ -z "$user" ]; then
582         echo "Can not find the user with uid $id on the KDC!"
583         return 1
584     fi
585
586     add_user_princ $user || return ${PIPESTATUS[0]}
587 }
588
589 #
590 # create principals for the client, MDS, OSS, runas users and add them to 
591 # the Kerberos database
592 #
593 cfg_kdc_princs() {
594     local node
595
596     add_svc_princ $MY_MGSNODE mgs || return ${PIPESTATUS[0]}
597
598     for node in $MY_MDSNODES; do
599         add_svc_princ $node mds || return ${PIPESTATUS[0]}
600     done
601
602     for node in $MY_OSSNODES; do
603         add_svc_princ $node oss || return ${PIPESTATUS[0]}
604     done
605
606     for node in $MY_CLIENTNODES; do
607         if $SPLIT_KEYTAB; then
608             add_svc_princ $node root || return ${PIPESTATUS[0]}
609         else
610             add_svc_princ_root || return ${PIPESTATUS[0]}
611         fi
612     done
613
614     if ! $SPLIT_KEYTAB; then 
615         add_user_princ lustre_root || return ${PIPESTATUS[0]}
616     fi
617     add_user_princ bin || return ${PIPESTATUS[0]}
618     add_user_princ daemon || return ${PIPESTATUS[0]}
619     add_user_princ games || return ${PIPESTATUS[0]}
620
621     if $CFG_RUNAS; then
622         for uid in $LOCAL_UIDS; do
623             add_test_princ_id $uid || return ${PIPESTATUS[0]}
624         done
625     fi
626 }
627
628 #
629 # create and install the KDC configuration file kdc.conf on the KDC, which 
630 # will destroy the old KDC setting
631 #
632 cfg_kdc() {
633     local tmpdir="$TMP/krb5_cfg_tmp_$UID"
634     local tmpcfg=$tmpdir/kdc.conf
635     local tmpacl=$tmpdir/kadm5.acl
636
637     echo "+++ Configuring KDC on $MY_KDCNODE"
638     echo "Warning: old KDC setting on $MY_KDCNODE will be destroied!!!"
639
640     echo -n "Checking the existence of KDC config dir..."
641     do_kdc_mute "[ -d $KDC_CONF_DIR ]"
642     if [ ${PIPESTATUS[0]} -ne 0 ]; then
643         echo -e "\nUnrecognized krb5 distribution!"
644         return 1
645     else
646         echo "OK!"
647     fi
648
649     # stop KDC daemon
650     do_kdc_mute "/etc/init.d/krb5kdc stop < /dev/null" || true
651
652     echo -n "Removing old KDC configurations..."
653     do_kdc_mute "rm -f $KDC_CONF_DIR/*"
654     echo "OK!"
655
656     # create kdc.conf locally
657     rm -rf $tmpdir
658     mkdir -p $tmpdir || return ${PIPESTATUS[0]}
659     cat <<EOF > $tmpcfg
660 [kdcdefaults]
661  acl_file = $KDC_ACL
662
663 [realms]
664  $KRB5_REALM = {
665   master_key_type = aes128-cts
666   supported_enctypes = des3-hmac-sha1:normal aes128-cts:normal aes256-cts:normal des-cbc-md5:normal
667  }
668 EOF
669
670     # install kdc.conf remotely
671     echo -n "Installing kdc.conf on $MY_KDCNODE..."
672     $SCP $tmpcfg root@$MY_KDCNODE:$KDC_CONF || return ${PIPESTATUS[0]}
673     echo "OK!"
674
675     # initialize KDC database
676     echo -n "Creating Kerberos database on $MY_KDCNODE..."
677     do_kdc_mute "kdb5_util create -r $KRB5_REALM -s -P 111111"
678     local rc=${PIPESTATUS[0]}
679     if [ $rc -ne 0 ]; then
680         echo "Failed!"
681         return $rc
682     else
683         echo "OK!"
684     fi
685
686     # create ACL file locally & install remotely
687     cat <<EOF > $tmpacl
688 */admin@$KRB5_REALM   *
689 root@$KRB5_REALM      *
690 EOF
691     echo -n "Installing kadm5.acl on $MY_KDCNODE..."
692     $SCP $tmpacl root@$MY_KDCNODE:$KDC_ACL || return ${PIPESTATUS[0]}
693     echo "OK!"
694     rm -rf $tmpdir || true
695
696     # start KDC daemon
697     do_kdc "/etc/init.d/krb5kdc restart < /dev/null" || return ${PIPESTATUS[0]}
698 }
699
700 #
701 # create and install the Kerberos configuration file krb5.conf on the KDC, 
702 # client, MDS and OSS
703 #
704 cfg_krb5_conf() {
705     local tmpdir="$TMP/krb5_cfg_tmp_$UID"
706     local tmpcfg="$tmpdir/krb5.conf"
707     local checked=""
708
709     echo "+++ Installing krb5.conf on all nodes"
710
711     # create krb5.conf locally
712     rm -rf $tmpdir
713     mkdir -p $tmpdir || return ${PIPESTATUS[0]}
714     cat <<EOF > $tmpcfg
715 [libdefaults]
716  default_realm = $KRB5_REALM
717  dns_lookup_realm = false
718  dns_lookup_kdc = false
719  ticket_lifetime = $KRB5_TICKET_LIFETIME
720  forwardable = yes
721
722 [realms]
723  $KRB5_REALM = {
724   kdc = $MY_KDCNODE:88
725   admin_server = $MY_KDCNODE:749
726   default_domain = $KRB5_DOMAIN
727  }
728
729 [domain_realm]
730  .$KRB5_DOMAIN = $KRB5_REALM
731  $KRB5_DOMAIN = $KRB5_REALM
732
733 [kdc]
734  profile = $KDC_CONF
735
736 [appdefaults]
737  pam = {
738   debug = false
739   forwardable = true
740   krb4_convert = false
741  }
742 EOF
743
744     # install krb5.conf remotely
745     for node in $MY_KDCNODE $MY_MGSNODE $MY_OSSNODES $MY_MDSNODES $MY_CLIENTNODES
746     do
747         is_part_of $node $checked && continue
748
749         echo -n "Installing krb5.conf on $node..."
750         $SCP $tmpcfg root@$node:$KRB5_CONF || return ${PIPESTATUS[0]}
751         echo "OK!"
752
753         checked="$checked $node"
754     done
755     rm -rf $tmpdir || true
756 }
757
758 add_keytab() {
759     local tab=$1
760     local princ=$2
761     local enctype=$3
762
763     do_kdc_mute "kadmin.local -r $KRB5_REALM <<EOF
764 ktadd -k $tab -e $enctype:normal $princ@$KRB5_REALM
765 EOF"
766 }
767
768 add_keytab_svc() {
769     local tab=$1
770     local fqdn=$2
771     local type=$3
772     local enctype=$4
773
774     add_keytab $tab lustre_$type/$fqdn $enctype
775 }
776
777 add_keytab_root() {
778     local tab=$1
779     local enctype=$2
780
781     add_keytab $tab lustre_root $enctype
782 }
783
784 merge_keytab() {
785     local tab=$1
786     local node=$2
787
788     $SCP $tab root@$node:$tab || return ${PIPESTATUS[0]}
789     do_node_mute $node "ktutil <<EOF
790 rkt $tab
791 wkt $KRB5_KEYTAB
792 EOF" || return ${PIPESTATUS[0]}
793 }
794
795 #
796 # create and install the keytab file krb5.keytab on the client, MDS and OSS
797 #
798 cfg_keytab() {
799     local tmptab="$TMP/keytab.tmp"
800     local node
801
802     echo "+++ Generating keytabs"
803
804     # remove old keytabs
805     echo -n "Deleting old keytabs on all nodes..."
806     for node in $MY_MGSNODE $MY_OSSNODES $MY_MDSNODES $MY_CLIENTNODES; do
807         do_node_mute $node "rm -f $KRB5_KEYTAB $TMP/krb5cc*"
808     done
809     echo "OK!"
810
811     # install for MDS nodes
812     for node in $MY_MDSNODES; do
813         echo -n "Preparing for MDS $node..."
814         do_kdc_mute "rm -f $tmptab"
815         add_keytab_svc $tmptab $node mds $MDS_ENCTYPE || return ${PIPESTATUS[0]}
816
817         if is_part_of $node $MY_MGSNODE; then
818             echo -n "also be an MGS..."
819             add_keytab_svc $tmptab $node mgs $MGS_ENCTYPE || \
820                 return ${PIPESTATUS[0]}
821         fi
822
823         if is_part_of $node $MY_OSSNODES; then
824             echo -n "also be an OSS..."
825             add_keytab_svc $tmptab $node oss $OSS_ENCTYPE || \
826                 return ${PIPESTATUS[0]}
827         fi
828         echo "OK!"
829
830         echo -n "Installing krb5.keytab on $node..."
831         $SCP root@$MY_KDCNODE:$tmptab $tmptab || return ${PIPESTATUS[0]}
832         $SCP $tmptab root@$node:$KRB5_KEYTAB || return ${PIPESTATUS[0]}
833         echo "OK!"
834         rm -f $tmptab
835     done
836
837     # install for MGS node
838     echo -n "Preparing for MGS $MY_MGSNODE..."
839     if ! is_part_of $MY_MGSNODE $MY_MDSNODES; then
840         do_kdc_mute "rm -f $tmptab"
841         add_keytab_svc $tmptab $MY_MGSNODE mgs $MGS_ENCTYPE || \
842             return ${PIPESTATUS[0]}
843
844         if is_part_of $MY_MGSNODE $MY_OSSNODES; then
845             echo -n "also be an OSS..."
846             add_keytab_svc $tmptab $MY_MGSNODE oss $OSS_ENCTYPE || \
847                 return ${PIPESTATUS[0]}
848         fi
849         echo "OK!"
850
851         echo -n "Installing krb5.keytab on $MY_MGSNODE..."
852         $SCP root@$MY_KDCNODE:$tmptab $tmptab || return ${PIPESTATUS[0]}
853         $SCP $tmptab root@$MY_MGSNODE:$KRB5_KEYTAB || return ${PIPESTATUS[0]}
854         echo "OK!"
855         rm -f $tmptab
856     else
857         echo "also be an MDS, already done, skip"
858     fi
859
860     # install for OSS nodes
861     for node in $MY_OSSNODES; do
862         echo -n "Preparing for OSS $node..."
863         if is_part_of $node $MY_MDSNODES; then
864             echo "also be an MDS, already done, skip"
865         elif is_part_of $node $MY_MGSNODE; then
866             echo "also be an MGS, already done, skip"
867         else
868             do_kdc_mute "rm -f $tmptab"
869             add_keytab_svc $tmptab $node oss $OSS_ENCTYPE || \
870                 return ${PIPESTATUS[0]}
871             echo "OK!"
872
873             echo -n "Installing krb5.keytab on $node..."
874             $SCP root@$MY_KDCNODE:$tmptab $tmptab || return ${PIPESTATUS[0]}
875             $SCP $tmptab root@$node:$KRB5_KEYTAB || return ${PIPESTATUS[0]}
876             echo "OK!"
877             rm -f $tmptab
878         fi
879     done
880
881     # install for client nodes
882     do_kdc_mute "rm -f $tmptab"
883     if ! $SPLIT_KEYTAB; then
884         echo -n "Preparing for client..."
885         add_keytab_root $tmptab $CLIENT_ENCTYPE || return ${PIPESTATUS[0]}
886         $SCP root@$MY_KDCNODE:$tmptab $tmptab || return ${PIPESTATUS[0]}
887         echo "OK!"
888     else
889         for node in $MY_CLIENTNODES; do
890             echo -n "Preparing for client $node..."
891             # don't generate keytabs if it's also an MDS
892             if is_part_of $node $MY_MDSNODES; then
893                 echo "also be an MDS, already done, skip"
894                 continue
895             fi
896
897             add_keytab_svc $tmptab $node root $CLIENT_ENCTYPE || \
898                 return ${PIPESTATUS[0]}
899             $SCP root@$MY_KDCNODE:$tmptab $tmptab || return ${PIPESTATUS[0]}
900             echo "OK!"
901         done
902     fi
903     for node in $MY_CLIENTNODES; do
904         echo -n "Installing krb5.keytab on client $node..."
905
906         # don't install if it's also an MDS
907         if is_part_of $node $MY_MDSNODES; then
908             echo "also be an MDS, already done, skip"
909             continue
910         fi
911
912         # merge keytab if it's also an MGS
913         if is_part_of $node $MY_MGSNODE; then
914             echo -n "also be an MGS, merging keytab..."
915             merge_keytab $tmptab $node || return ${PIPESTATUS[0]}
916             echo "OK!"
917             continue 
918         fi
919
920         # merge keytab if it's also an OSS
921         if is_part_of $node $MY_OSSNODES; then
922             echo -n "also be an OSS, merging keytab..."
923             merge_keytab $tmptab $node || return ${PIPESTATUS[0]}
924             echo "OK!"
925             continue 
926         fi
927
928         # simply install otherwise
929         $SCP $tmptab root@$node:$KRB5_KEYTAB || return ${PIPESTATUS[0]}
930         echo "OK!"
931     done
932     rm -f $tmptab || true
933 }
934
935 check_acceptor_port() {
936     local node=$1
937     local port=$2
938
939     if [ -z "$port" ]; then
940         echo "Missing acceptor port!"
941         return 1
942     fi
943
944     local WAIT=0
945     local MAX_WAIT=300
946     while [ $WAIT -lt $MAX_WAIT ]; do
947         sleep 5
948         my_do_node $node "netstat -tpan" | grep -q ":$port .*TIME_WAIT"
949         if [ ${PIPESTATUS[1]} -ne 0 ]; then
950             return 0
951         fi
952         WAIT=$((WAIT + 5))
953     done
954
955     echo "LNET acceptor port $port is in use on node $node!"
956     return 2
957 }
958
959 get_client_nids() {
960     local client_nids=""
961     local node
962     local nid
963     local local_fqdn
964     local rc
965
966     # get the fqdn of the local host
967     local_fqdn=$(get_fqdn $HOSTNAME)
968     rc=${PIPESTATUS[0]}
969     if [ $rc -ne 0 ]; then
970         echo $local_fqdn
971         return $rc
972     fi
973
974     for node in $MY_CLIENTNODES; do
975         my_do_node $node lsmod | grep -q lnet || \
976         my_do_node $node "modprobe lnet" || {
977             if [ "$node" = "$local_fqdn" ]; then
978                 lsmod | grep -q lnet || load_modules
979             else
980                 echo "Failed to load lnet module on node $node!"
981                 return 1
982             fi
983         }
984
985         check_acceptor_port $node $ACCEPTOR_PORT || return ${PIPESTATUS[0]}
986
987         nid=$(set +x; my_do_node $node \
988 "$LCTL net up 1>/dev/null && $LCTL list_nids" 2>&1 | head -n1
989 exit ${PIPESTATUS[0]})
990         rc=${PIPESTATUS[0]}
991         if [ $rc -ne 0 ]; then
992             echo "Failed to get the nid for node $node: $nid"
993             return $rc
994         fi
995         [ -z "$client_nids" ] && client_nids="$nid" \
996         || client_nids="$client_nids $nid"
997
998         my_do_node $node "$LCTL net down 1>/dev/null" || true
999     done
1000
1001     echo "$client_nids"
1002     return 0
1003 }
1004
1005 #
1006 # create and install idmap.conf on the MDS
1007 #
1008 cfg_idmap_conf() {
1009     local tmpcfg="$TMP/idmap.conf"
1010     local fqdn 
1011     local user
1012     local uid
1013     local client_nids client_nid
1014     local rc
1015
1016     echo "+++ Installing idmap.conf on MDS"
1017     echo "Getting Client NID..."
1018     client_nids=$(get_client_nids)
1019     rc=${PIPESTATUS[0]}
1020     if [ $rc -ne 0 ]; then
1021         echo $client_nids
1022         return $rc
1023     fi
1024
1025     rm -f $tmpcfg
1026     if $SPLIT_KEYTAB; then
1027         for fqdn in $MY_CLIENTNODES; do
1028             echo "lustre_root/$fqdn@$KRB5_REALM * 0" >> $tmpcfg
1029         done
1030     else
1031         echo "lustre_root@$KRB5_REALM * 0" >> $tmpcfg
1032     fi
1033     cat <<EOF >> $tmpcfg
1034 bin@$KRB5_REALM * 1
1035 daemon@$KRB5_REALM * 2
1036 games@$KRB5_REALM * 12
1037 EOF
1038
1039     for node in $MY_MDSNODES; do
1040         for uid in $LOCAL_UIDS; do
1041             user=$(my_do_node $node getent passwd $uid | cut -d: -f1)
1042             for client_nid in $client_nids; do
1043                 echo "$user@$KRB5_REALM $client_nid $uid" >> $tmpcfg
1044             done
1045         done
1046     done
1047
1048     for node in $MY_MDSNODES; do
1049         my_do_node $node "mkdir -p $LUSTRE_CONF_DIR" || return ${PIPESTATUS[0]}
1050         $SCP $tmpcfg root@$node:$IDMAP_CONF || return ${PIPESTATUS[0]}
1051     done
1052     rm -f $tmpcfg
1053     echo "OK!"
1054 }
1055
1056 #
1057 # create and install perm.conf on the MDS for remote ACL testing
1058 #
1059 cfg_perm_conf() {
1060     local tmpcfg="$TMP/perm.conf"
1061     local uid
1062
1063     echo "+++ Installing perm.conf on MDS"
1064
1065     rm -f $tmpcfg
1066     for node in $MY_MDSNODES; do
1067         my_do_node $node "mkdir -p $LUSTRE_CONF_DIR" || return ${PIPESTATUS[0]}
1068
1069         for uid in $LOCAL_UIDS $REMOTE_UIDS; do
1070             if ! grep -q " $uid " $tmpcfg 2>/dev/null; then
1071                 echo "* $uid rmtacl" >> $tmpcfg
1072             fi
1073         done
1074
1075         echo "* 0 setgid" >> $tmpcfg
1076
1077         $SCP $tmpcfg root@$node:$PERM_CONF || return ${PIPESTATUS[0]}
1078     done
1079     rm -f $tmpcfg
1080     echo "OK!"
1081 }
1082
1083 # ******************************** Main Flow ******************************** #
1084 normalize_names || exit ${PIPESTATUS[0]}
1085 check_rsh || exit ${PIPESTATUS[0]}
1086 check_entropy || exit ${PIPESTATUS[0]}
1087
1088 if $CFG_RUNAS; then
1089     check_users || exit ${PIPESTATUS[0]}
1090 elif $CFG_IDMAP; then
1091     echo "Remote ACL operations need local and remote users!"
1092     exit 1
1093 fi
1094
1095 check_kdc || exit ${PIPESTATUS[0]}
1096 check_krb5 || exit ${PIPESTATUS[0]}
1097 check_libgssapi || exit ${PIPESTATUS[0]}
1098
1099 echo "===================================================================="
1100 echo " Configure Kerberos testing environment for Lustre"
1101 echo " KDC: $MY_KDCNODE"
1102 echo " realm: $KRB5_REALM, domain: $KRB5_DOMAIN"
1103 echo " Using gssapi package: $LIBGSSAPI"
1104 echo " MGS node:"
1105 echo "     $MY_MGSNODE"
1106 echo " OSS nodes:"
1107 for i in $MY_OSSNODES; do echo "     $i"; done
1108 echo " MDS nodes:"
1109 for i in $MY_MDSNODES; do echo "     $i"; done
1110 echo " CLIENT nodes:"
1111 for i in $MY_CLIENTNODES; do echo "     $i"; done
1112 echo "===================================================================="
1113
1114 cfg_nfs_mount || exit ${PIPESTATUS[0]}
1115 cfg_libgssapi || exit ${PIPESTATUS[0]}
1116 cfg_keyutils || exit ${PIPESTATUS[0]}
1117
1118 if $RESET_KDC; then
1119     cfg_krb5_conf || exit ${PIPESTATUS[0]}
1120     cfg_kdc || exit ${PIPESTATUS[0]}
1121 fi
1122
1123 cfg_kdc_princs || exit ${PIPESTATUS[0]}
1124 cfg_keytab || exit ${PIPESTATUS[0]}
1125
1126 if $CFG_IDMAP; then
1127     cfg_idmap_conf || exit ${PIPESTATUS[0]}
1128     cfg_perm_conf || exit ${PIPESTATUS[0]}
1129 fi
1130
1131 echo "Complete successfully!"