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