Whamcloud - gitweb
LU-3527 nodemap: add nodemap kernel module
[fs/lustre-release.git] / lustre / tests / sanity-sec.sh
1 #!/bin/bash
2 #
3 # Run select tests by setting ONLY, or as arguments to the script.
4 # Skip specific tests by setting EXCEPT.
5 #
6
7 set -e
8
9 ONLY=${ONLY:-"$*"}
10 # bug number for skipped test: 19430 19967 19967
11 ALWAYS_EXCEPT="                2     5     6    $SANITY_SEC_EXCEPT"
12 # UPDATE THE COMMENT ABOVE WITH BUG NUMBERS WHEN CHANGING ALWAYS_EXCEPT!
13
14 [ "$ALWAYS_EXCEPT$EXCEPT" ] && \
15     echo "Skipping tests: $ALWAYS_EXCEPT $EXCEPT"
16
17 SRCDIR=`dirname $0`
18 export PATH=$PWD/$SRCDIR:$SRCDIR:$PWD/$SRCDIR/../utils:$PATH:/sbin
19 export NAME=${NAME:-local}
20
21 LUSTRE=${LUSTRE:-`dirname $0`/..} 
22 . $LUSTRE/tests/test-framework.sh
23 init_test_env $@
24 . ${CONFIG:=$LUSTRE/tests/cfg/$NAME.sh}
25 init_logging
26
27 RUNAS="runas"
28
29 WTL=${WTL:-"$LUSTRE/tests/write_time_limit"}
30
31 CONFDIR=/etc/lustre
32 PERM_CONF=$CONFDIR/perm.conf
33 FAIL_ON_ERROR=false
34
35 HN=$(hostname | sum | awk '{ print $1 }')
36 NODEMAP_COUNT=10
37 NODEMAP_RANGE_COUNT=3
38 NODEMAP_IPADDR_COUNT=30
39 NODEMAP_ID_COUNT=200
40
41 require_dsh_mds || exit 0
42 require_dsh_ost || exit 0
43
44 ID0=${ID0:-500}
45 ID1=${ID1:-501}
46 USER0=`cat /etc/passwd|grep :$ID0:$ID0:|cut -d: -f1`
47 USER1=`cat /etc/passwd|grep :$ID1:$ID1:|cut -d: -f1`
48
49 [ -z "$USER0" ] && \
50         echo "Please add user0 (uid=$ID0 gid=$ID0)! Skip sanity-sec" && exit 0
51
52 [ -z "$USER1" ] && \
53         echo "Please add user1 (uid=$ID1 gid=$ID1)! Skip sanity-sec" && exit 0
54
55 check_and_setup_lustre
56
57 sec_cleanup() {
58         if [ "$I_MOUNTED" = "yes" ]; then
59                 cleanupall -f || error "sec_cleanup"
60         fi
61 }
62
63 DIR=${DIR:-$MOUNT}
64 [ -z "`echo $DIR | grep $MOUNT`" ] && \
65         error "$DIR not in $MOUNT" && sec_cleanup && exit 1
66
67 [ `echo $MOUNT | wc -w` -gt 1 ] && \
68         echo "NAME=$MOUNT mounted more than once" && sec_cleanup && exit 0
69
70 [ $MDSCOUNT -gt 1 ] && \
71         echo "skip multi-MDS test" && sec_cleanup && exit 0
72
73 # for GSS_SUP
74 GSS_REF=$(lsmod | grep ^ptlrpc_gss | awk '{print $3}')
75 if [ ! -z "$GSS_REF" -a "$GSS_REF" != "0" ]; then
76         GSS_SUP=1
77         echo "with GSS support"
78 else
79         GSS_SUP=0
80         echo "without GSS support"
81 fi
82
83 MDT=$(do_facet $SINGLEMDS lctl get_param -N "mdt.\*MDT0000" |
84         cut -d. -f2 || true)
85 [ -z "$MDT" ] && error "fail to get MDT device" && exit 1
86 do_facet $SINGLEMDS "mkdir -p $CONFDIR"
87 IDENTITY_FLUSH=mdt.$MDT.identity_flush
88 MDSCAPA=mdt.$MDT.capa
89 CAPA_TIMEOUT=mdt.$MDT.capa_timeout
90 MDSSECLEVEL=mdt.$MDT.sec_level
91
92 # for CLIENT_TYPE
93 if [ -z "$(lctl get_param -n llite.*.client_type | grep remote 2>/dev/null)" ]; then
94         CLIENT_TYPE="local"
95         echo "local client"
96 else
97         CLIENT_TYPE="remote"
98         echo "remote client"
99 fi
100
101 SAVE_PWD=$PWD
102
103 build_test_filter
104
105 sec_login() {
106         local user=$1
107         local group=$2
108
109         if ! $RUNAS -u $user krb5_login.sh; then
110                 error "$user login kerberos failed."
111                 exit 1
112         fi
113
114         if ! $RUNAS -u $user -g $group ls $DIR > /dev/null 2>&1; then
115                 $RUNAS -u $user lfs flushctx -k
116                 $RUNAS -u $user krb5_login.sh
117                 if ! $RUNAS -u $user -g $group ls $DIR > /dev/null 2>&1; then
118                         error "init $user $group failed."
119                         exit 2
120                 fi
121         fi
122 }
123
124 declare -a identity_old
125
126 sec_setup() {
127         for num in `seq $MDSCOUNT`; do
128                 switch_identity $num true || identity_old[$num]=$?
129         done
130
131         if ! $RUNAS -u $ID0 ls $DIR > /dev/null 2>&1; then
132                 sec_login $USER0 $USER0
133         fi
134
135         if ! $RUNAS -u $ID1 ls $DIR > /dev/null 2>&1; then
136                 sec_login $USER1 $USER1
137         fi
138 }
139 sec_setup
140
141 # run as different user
142 test_0() {
143         umask 0022
144
145         chmod 0755 $DIR || error "chmod (1)"
146         rm -rf $DIR/$tdir || error "rm (1)"
147         mkdir -p $DIR/$tdir || error "mkdir (1)"
148
149         if [ "$CLIENT_TYPE" = "remote" ]; then
150                 do_facet $SINGLEMDS "echo '* 0 normtown' > $PERM_CONF"
151                 do_facet $SINGLEMDS "lctl set_param -n $IDENTITY_FLUSH=-1"
152                 chown $USER0 $DIR/$tdir && error "chown (1)"
153                 do_facet $SINGLEMDS "echo '* 0 rmtown' > $PERM_CONF"
154                 do_facet $SINGLEMDS "lctl set_param -n $IDENTITY_FLUSH=-1"
155         else
156                 chown $USER0 $DIR/$tdir || error "chown (2)"
157         fi
158
159         $RUNAS -u $ID0 ls $DIR || error "ls (1)"
160         rm -f $DIR/f0 || error "rm (2)"
161         $RUNAS -u $ID0 touch $DIR/f0 && error "touch (1)"
162         $RUNAS -u $ID0 touch $DIR/$tdir/f1 || error "touch (2)"
163         $RUNAS -u $ID1 touch $DIR/$tdir/f2 && error "touch (3)"
164         touch $DIR/$tdir/f3 || error "touch (4)"
165         chown root $DIR/$tdir || error "chown (3)"
166         chgrp $USER0 $DIR/$tdir || error "chgrp (1)"
167         chmod 0775 $DIR/$tdir || error "chmod (2)"
168         $RUNAS -u $ID0 touch $DIR/$tdir/f4 || error "touch (5)"
169         $RUNAS -u $ID1 touch $DIR/$tdir/f5 && error "touch (6)"
170         touch $DIR/$tdir/f6 || error "touch (7)"
171         rm -rf $DIR/$tdir || error "rm (3)"
172
173         if [ "$CLIENT_TYPE" = "remote" ]; then
174                 do_facet $SINGLEMDS "rm -f $PERM_CONF"
175                 do_facet $SINGLEMDS "lctl set_param -n $IDENTITY_FLUSH=-1"
176         fi
177 }
178 run_test 0 "uid permission ============================="
179
180 # setuid/gid
181 test_1() {
182         [ $GSS_SUP = 0 ] && skip "without GSS support." && return
183
184         if [ "$CLIENT_TYPE" = "remote" ]; then
185                 do_facet $SINGLEMDS "echo '* 0 rmtown' > $PERM_CONF"
186                 do_facet $SINGLEMDS "lctl set_param -n $IDENTITY_FLUSH=-1"
187         fi
188
189         rm -rf $DIR/$tdir
190         mkdir -p $DIR/$tdir
191
192         chown $USER0 $DIR/$tdir || error "chown (1)"
193         $RUNAS -u $ID1 -v $ID0 touch $DIR/$tdir/f0 && error "touch (2)"
194         echo "enable uid $ID1 setuid"
195         do_facet $SINGLEMDS "echo '* $ID1 setuid' >> $PERM_CONF"
196         do_facet $SINGLEMDS "lctl set_param -n $IDENTITY_FLUSH=-1"
197         $RUNAS -u $ID1 -v $ID0 touch $DIR/$tdir/f1 || error "touch (3)"
198
199         chown root $DIR/$tdir || error "chown (4)"
200         chgrp $USER0 $DIR/$tdir || error "chgrp (5)"
201         chmod 0770 $DIR/$tdir || error "chmod (6)"
202         $RUNAS -u $ID1 -g $ID1 touch $DIR/$tdir/f2 && error "touch (7)"
203         $RUNAS -u $ID1 -g $ID1 -j $ID0 touch $DIR/$tdir/f3 && error "touch (8)"
204         echo "enable uid $ID1 setuid,setgid"
205         do_facet $SINGLEMDS "echo '* $ID1 setuid,setgid' > $PERM_CONF"
206         do_facet $SINGLEMDS "lctl set_param -n $IDENTITY_FLUSH=-1"
207         $RUNAS -u $ID1 -g $ID1 -j $ID0 touch $DIR/$tdir/f4 || error "touch (9)"
208         $RUNAS -u $ID1 -v $ID0 -g $ID1 -j $ID0 touch $DIR/$tdir/f5 || error "touch (10)"
209
210         rm -rf $DIR/$tdir
211
212         do_facet $SINGLEMDS "rm -f $PERM_CONF"
213         do_facet $SINGLEMDS "lctl set_param -n $IDENTITY_FLUSH=-1"
214 }
215 run_test 1 "setuid/gid ============================="
216
217 run_rmtacl_subtest() {
218     $SAVE_PWD/rmtacl/run $SAVE_PWD/rmtacl/$1.test
219     return $?
220 }
221
222 # remote_acl
223 # for remote client only
224 test_2 () {
225         [ "$CLIENT_TYPE" = "local" ] && \
226                 skip "remote_acl for remote client only" && return
227         [ -z "$(lctl get_param -n mdc.*-mdc-*.connect_flags | grep ^acl)" ] && \
228                 skip "must have acl enabled" && return
229         [ -z "$(which setfacl 2>/dev/null)" ] && \
230                 skip "could not find setfacl" && return
231         [ "$UID" != 0 ] && skip "must run as root" && return
232
233         do_facet $SINGLEMDS "echo '* 0 rmtacl,rmtown' > $PERM_CONF"
234         do_facet $SINGLEMDS "lctl set_param -n $IDENTITY_FLUSH=-1"
235
236         sec_login root root
237         sec_login bin bin
238         sec_login daemon daemon
239         sec_login games users
240
241         SAVE_UMASK=`umask`
242         umask 0022
243         cd $DIR
244
245         echo "performing cp ..."
246         run_rmtacl_subtest cp || error "cp"
247         echo "performing getfacl-noacl..."
248         run_rmtacl_subtest getfacl-noacl || error "getfacl-noacl"
249         echo "performing misc..."
250         run_rmtacl_subtest misc || error "misc"
251         echo "performing permissions..."
252         run_rmtacl_subtest permissions || error "permissions"
253         echo "performing setfacl..."
254         run_rmtacl_subtest setfacl || error "setfacl"
255
256         # inheritance test got from HP
257         echo "performing inheritance..."
258         cp $SAVE_PWD/rmtacl/make-tree .
259         chmod +x make-tree
260         run_rmtacl_subtest inheritance || error "inheritance"
261         rm -f make-tree
262
263         cd $SAVE_PWD
264         umask $SAVE_UMASK
265
266         do_facet $SINGLEMDS "rm -f $PERM_CONF"
267         do_facet $SINGLEMDS "lctl set_param -n $IDENTITY_FLUSH=-1"
268 }
269 run_test 2 "rmtacl ============================="
270
271 # rootsquash
272 # root_squash will be redesigned in Lustre 1.7
273 test_3() {
274         skip "root_squash will be redesigned in Lustre 1.7" && return
275 }
276 run_test 3 "rootsquash ============================="
277
278 # bug 3285 - supplementary group should always succeed.
279 # NB: the supplementary groups are set for local client only,
280 # as for remote client, the groups of the specified uid on MDT
281 # will be obtained by upcall /sbin/l_getidentity and used.
282 test_4() {
283         if [ "$CLIENT_TYPE" = "remote" ]; then
284                 do_facet $SINGLEMDS "echo '* 0 rmtown' > $PERM_CONF"
285                 do_facet $SINGLEMDS "lctl set_param -n $IDENTITY_FLUSH=-1"
286         fi
287
288         rm -rf $DIR/$tdir
289         mkdir -p $DIR/$tdir
290         chmod 0771 $DIR/$tdir
291         chgrp $ID0 $DIR/$tdir
292         $RUNAS -u $ID0 ls $DIR/$tdir || error "setgroups (1)"
293         if [ "$CLIENT_TYPE" = "local" ]; then
294                 do_facet $SINGLEMDS "echo '* $ID1 setgrp' > $PERM_CONF"
295                 do_facet $SINGLEMDS "lctl set_param -n $IDENTITY_FLUSH=-1"
296                 $RUNAS -u $ID1 -G1,2,$ID0 ls $DIR/$tdir || error "setgroups (2)"
297         fi
298         $RUNAS -u $ID1 -G1,2 ls $DIR/$tdir && error "setgroups (3)"
299         rm -rf $DIR/$tdir
300
301         do_facet $SINGLEMDS "rm -f $PERM_CONF"
302         do_facet $SINGLEMDS "lctl set_param -n $IDENTITY_FLUSH=-1"
303 }
304 run_test 4 "set supplementary group ==============="
305
306 mds_capability_timeout() {
307         [ $# -lt 1 ] && echo "Miss mds capability timeout value" && return 1
308
309         echo "Set mds capability timeout as $1 seconds"
310         do_facet $SINGLEMDS "lctl set_param -n $CAPA_TIMEOUT=$1"
311         return 0
312 }
313
314 mds_sec_level_switch() {
315         [ $# -lt 1 ] && echo "Miss mds sec level switch value" && return 1
316
317         case $1 in
318                 0) echo "Disable capa for all clients";;
319                 1) echo "Enable capa for remote client";;
320                 3) echo "Enable capa for all clients";;
321                 *) echo "Invalid mds sec level switch value" && return 2;;
322         esac
323
324         do_facet $SINGLEMDS "lctl set_param -n $MDSSECLEVEL=$1"
325         return 0
326 }
327
328 oss_sec_level_switch() {
329         [ $# -lt 1 ] && echo "Miss oss sec level switch value" && return 1
330
331         case $1 in
332                 0) echo "Disable capa for all clients";;
333                 1) echo "Enable capa for remote client";;
334                 3) echo "Enable capa for all clients";;
335                 *) echo "Invalid oss sec level switch value" && return 2;;
336         esac
337
338         for i in `seq $OSTCOUNT`; do
339                 local j=`expr $i - 1`
340                 local OST="`do_facet ost$i "lctl get_param -N obdfilter.\*OST\*$j/stats 2>/dev/null | cut -d"." -f2" || true`"
341                 [ -z "$OST" ] && return 3
342                 do_facet ost$i "lctl set_param -n obdfilter.$OST.sec_level=$1"
343         done
344         return 0
345 }
346
347 mds_capability_switch() {
348         [ $# -lt 1 ] && echo "Miss mds capability switch value" && return 1
349
350         case $1 in
351                 0) echo "Turn off mds capability";;
352                 3) echo "Turn on mds capability";;
353                 *) echo "Invalid mds capability switch value" && return 2;;
354         esac
355
356         do_facet $SINGLEMDS "lctl set_param -n $MDSCAPA=$1"
357         return 0
358 }
359
360 oss_capability_switch() {
361         [ $# -lt 1 ] && echo "Miss oss capability switch value" && return 1
362
363         case $1 in
364                 0) echo "Turn off oss capability";;
365                 1) echo "Turn on oss capability";;
366                 *) echo "Invalid oss capability switch value" && return 2;;
367         esac
368
369         for i in `seq $OSTCOUNT`; do
370                 local j=`expr $i - 1`
371                 local OST="`do_facet ost$i "lctl get_param -N obdfilter.\*OST\*$j/stats 2>/dev/null | cut -d"." -f2" || true`"
372                 [ -z "$OST" ] && return 3
373                 do_facet ost$i "lctl set_param -n obdfilter.$OST.capa=$1"
374         done
375         return 0
376 }
377
378 turn_mds_capa_on() {
379         mds_capability_switch 3 || return 1
380         mds_sec_level_switch 3  || return 2
381         return 0
382 }
383
384 turn_oss_capa_on() {
385         oss_capability_switch 1 || return 1
386         oss_sec_level_switch 3  || return 2
387         return 0
388 }
389
390 turn_capability_on() {
391         local capa_timeout=${1:-"1800"}
392
393         # To turn on fid capability for the system,
394         # there is a requirement that fid capability
395         # is turned on on all MDS/OSS servers before
396         # client mount.
397
398         turn_mds_capa_on || return 1
399         turn_oss_capa_on || return 2
400         mds_capability_timeout $capa_timeout || return 3
401         remount_client $MOUNT || return 4
402         return 0
403 }
404
405 turn_mds_capa_off() {
406         mds_sec_level_switch 0  || return 1
407         mds_capability_switch 0 || return 2
408         return 0
409 }
410
411 turn_oss_capa_off() {
412         oss_sec_level_switch 0  || return 1
413         oss_capability_switch 0 || return 2
414         return 0
415 }
416
417 turn_capability_off() {
418         # to turn off fid capability, you can just do
419         # it in a live system. But, please turn off
420         # capability of all OSS servers before MDS servers.
421
422         turn_oss_capa_off || return 1
423         turn_mds_capa_off || return 2
424         return 0
425 }
426
427 # We demonstrate that access to the objects in the filesystem are not
428 # accessible without supplying secrets from the MDS by disabling a
429 # proc variable on the mds so that it does not supply secrets. We then
430 # try and access objects which result in failure.
431 test_5() {
432         local file=$DIR/f5
433
434         [ $GSS_SUP = 0 ] && skip "without GSS support." && return
435         if ! remote_mds; then
436                 skip "client should be separated from server."
437                 return
438         fi
439
440         rm -f $file
441
442         turn_capability_off
443         if [ $? != 0 ]; then
444                 error "turn_capability_off"
445                 return 1
446         fi
447
448         turn_oss_capa_on
449         if [ $? != 0 ]; then
450                 error "turn_oss_capa_on"
451                 return 2
452         fi
453
454         if [ "$CLIENT_TYPE" = "remote" ]; then
455                 remount_client $MOUNT && return 3
456                 turn_oss_capa_off
457                 return 0
458         else
459                 remount_client $MOUNT || return 4
460         fi
461
462         # proc variable disabled -- access to the objects in the filesystem
463         # is not allowed 
464         echo "Should get Write error here : (proc variable are disabled "\
465              "-- access to the objects in the filesystem is denied."
466         $WTL $file 30
467         if [ $? == 0 ]; then
468                 error "Write worked well even though secrets not supplied."
469                 return 5
470         fi
471
472         turn_capability_on
473         if [ $? != 0 ]; then
474                 error "turn_capability_on"
475                 return 6
476         fi
477
478         sleep 5
479
480         # proc variable enabled, secrets supplied -- write should work now
481         echo "Should not fail here : (proc variable enabled, secrets supplied "\
482              "-- write should work now)."
483         $WTL $file 30
484         if [ $? != 0 ]; then
485                 error "Write failed even though secrets supplied."
486                 return 7
487         fi
488
489         turn_capability_off
490         if [ $? != 0 ]; then
491                 error "turn_capability_off"
492                 return 8
493         fi
494         rm -f $file
495 }
496 run_test 5 "capa secrets ========================="
497
498 # Expiry: A test program is performing I/O on a file. It has credential
499 # with an expiry half a minute later. While the program is running the
500 # credentials expire and no automatic extensions or renewals are
501 # enabled. The program will demonstrate an I/O failure.
502 test_6() {
503         local file=$DIR/f6
504
505         [ $GSS_SUP = 0 ] && skip "without GSS support." && return
506         if ! remote_mds; then
507                 skip "client should be separated from server."
508                 return
509         fi
510
511         turn_capability_off
512         if [ $? != 0 ]; then
513                 error "turn_capability_off"
514                 return 1
515         fi
516
517         rm -f $file
518
519         turn_capability_on 30
520         if [ $? != 0 ]; then
521                 error "turn_capability_on 30"
522                 return 2
523         fi
524
525         # Token expiry
526         $WTL $file 60
527         if [ $? != 0 ]; then
528                 error "$WTL $file 60"
529                 return 3
530         fi
531
532         # Reset MDS capability timeout
533         mds_capability_timeout 30
534         if [ $? != 0 ]; then
535                 error "mds_capability_timeout 30"
536                 return 4
537         fi
538
539         $WTL $file 60 &
540         local PID=$!
541         sleep 5
542
543         # To disable automatic renew, only need turn capa off on MDS.
544         turn_mds_capa_off
545         if [ $? != 0 ]; then
546                 error "turn_mds_capa_off"
547                 return 5
548         fi
549
550         echo "We expect I/O failure."
551         wait $PID
552         if [ $? == 0 ]; then
553                 echo "no I/O failure got."
554                 return 6
555         fi
556
557         turn_capability_off
558         if [ $? != 0 ]; then
559                 error "turn_capability_off"
560                 return 7
561         fi
562         rm -f $file
563 }
564 run_test 6 "capa expiry ========================="
565
566 create_nodemaps() {
567         local i
568         local out
569         local rc
570
571         for (( i = 0; i < NODEMAP_COUNT; i++ )); do
572                 if ! do_facet mgs $LCTL nodemap_add ${HN}_${i}; then
573                         return 1
574                 fi
575                 out=$(do_facet mgs $LCTL get_param nodemap.${HN}_${i}.id)
576                 ## This needs to return zero if the following statement is 1
577                 rc=$(echo $out | grep -c ${HN}_${i})
578                 [[ $rc == 0 ]] && return 1
579         done
580         return 0
581 }
582
583 delete_nodemaps() {
584         local i
585         local out
586         local rc
587
588         for ((i = 0; i < NODEMAP_COUNT; i++)); do
589                 if ! do_facet mgs $LCTL nodemap_del ${HN}_${i}; then
590                         error "nodemap_del ${HN}_${i} failed with $rc"
591                         return 3
592                 fi
593                 out=$(do_facet mgs $LCTL get_param nodemap.${HN}_${i}.id)
594                 rc=$(echo $out | grep -c ${HN}_${i})
595                 [[ $rc != 0 ]] && return 1
596         done
597         return 0
598 }
599
600 test_7() {
601         local rc
602
603         create_nodemaps
604         rc=$?
605         [[ $rc != 0 ]] && error "nodemap_add failed with $rc" && return 1
606
607         delete_nodemaps
608         rc=$?
609         [[ $rc != 0 ]] && error "nodemap_add failed with $rc" && return 2
610
611         return 0
612 }
613 run_test 7 "nodemap create and delete"
614
615 test_8() {
616         local rc
617
618         # Set up nodemaps
619
620         create_nodemaps
621         rc=$?
622         [[ $rc != 0 ]] && error "nodemap_add failed with $rc" && return 1
623
624         # Try duplicates
625
626         create_nodemaps
627         rc=$?
628         [[ $rc == 0 ]] && error "duplicate nodemap_add allowed with $rc" &&
629         return 2
630
631         # Clean up
632         delete_nodemaps
633         rc=$?
634         [[ $rc != 0 ]] && error "nodemap_add failed with $rc" && return 3
635
636         return 0
637 }
638 run_test 8 "nodemap reject duplicates"
639
640 log "cleanup: ======================================================"
641
642 sec_unsetup() {
643         for num in `seq $MDSCOUNT`; do
644                 if [ "${identity_old[$num]}" = 1 ]; then
645                         switch_identity $num false || identity_old[$num]=$?
646                 fi
647         done
648
649         $RUNAS -u $ID0 ls $DIR
650         $RUNAS -u $ID1 ls $DIR
651 }
652 sec_unsetup
653
654 sec_cleanup
655
656 complete $SECONDS
657 exit_status