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