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