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