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