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