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