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