Whamcloud - gitweb
b=14471
[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 PERM_CONF=/etc/lustre/perm.conf
25 SANITYSECLOG=${TESTSUITELOG:-$TMP/$(basename $0 .sh).log}
26 FAIL_ON_ERROR=false
27
28 ID0=${ID0:-500}
29 ID1=${ID1:-501}
30 USER0=`cat /etc/passwd|grep :$ID0:$ID0:|cut -d: -f1`
31 USER1=`cat /etc/passwd|grep :$ID1:$ID1:|cut -d: -f1`
32
33 [ -z "$USER0" ] && \
34         echo "Please add user0 (uid=$ID0 gid=$ID0)! Skip sanity-sec" && exit 0
35
36 [ -z "$USER1" ] && \
37         echo "Please add user1 (uid=$ID1 gid=$ID1)! Skip sanity-sec" && exit 0
38
39 check_and_setup_lustre
40
41 DIR=${DIR:-$MOUNT}
42 [ -z "`echo $DIR | grep $MOUNT`" ] && \
43         error "$DIR not in $MOUNT" && sec_cleanup && exit 1
44
45 [ `echo $MOUNT | wc -w` -gt 1 ] && \
46         echo "NAME=$MOUNT mounted more than once" && sec_cleanup && exit 0
47
48 [ $MDSCOUNT -gt 1 ] && \
49         echo "skip multi-MDS test" && sec_cleanup && exit 0
50
51 # for GSS_SUP
52 GSS_REF=$(lsmod | grep ^ptlrpc_gss | awk '{print $3}')
53 if [ ! -z "$GSS_REF" -a "$GSS_REF" != "0" ]; then
54         GSS_SUP=1
55         echo "with GSS support"
56 else
57         GSS_SUP=0
58         echo "without GSS support"
59 fi
60
61 MDT="`do_facet $SINGLEMDS "lctl get_param -N mdt.\*MDT\*/stats | cut -d"." -f2" || true`"
62 if [ ! -z "$MDT" ]; then
63         IDENTITY_FLUSH=mdt.$MDT.identity_flush
64         MDSCAPA=mdt.$MDT.capa
65         CAPA_TIMEOUT=mdt.$MDT.capa_timeout
66 fi
67
68 # for CLIENT_TYPE
69 if [ -z "$(lctl get_param -n llite.*.client_type | grep remote 2>/dev/null)" ]; then
70         CLIENT_TYPE="local"
71         echo "local client"
72 else
73         CLIENT_TYPE="remote"
74         echo "remote client"
75 fi
76
77 SAVE_PWD=$PWD
78
79 build_test_filter
80
81 sec_login() {
82         local user=$1
83         local group=$2
84
85         if ! $RUNAS -u $user krb5_login.sh; then
86                 error "$user login kerberos failed."
87                 exit 1
88         fi
89
90         if ! $RUNAS -u $user -g $group ls $DIR > /dev/null 2>&1; then
91                 $RUNAS -u $user lfs flushctx -k
92                 $RUNAS -u $user krb5_login.sh
93                 if ! $RUNAS -u $user -g $group ls $DIR > /dev/null 2>&1; then
94                         error "init $user $group failed."
95                         exit 2
96                 fi
97         fi
98 }
99
100 declare -a identity_old
101
102 sec_setup() {
103         for num in `seq $MDSCOUNT`; do
104                 switch_identity $num true || identity_old[$num]=$?
105         done
106
107         if ! $RUNAS -u $ID0 ls $DIR > /dev/null 2>&1; then
108                 sec_login $USER0 $USER0
109         fi
110
111         if ! $RUNAS -u $ID1 ls $DIR > /dev/null 2>&1; then
112                 sec_login $USER1 $USER1
113         fi
114 }
115 sec_setup
116
117 # run as different user
118 test_0() {
119         rm -rf $DIR/d0
120         mkdir $DIR/d0
121
122         chown $USER0 $DIR/d0 || error "chown (1)"
123         $RUNAS -u $ID0 ls $DIR || error "ls (2)"
124         $RUNAS -u $ID0 touch $DIR/f0 && error "touch (3)"
125         $RUNAS -u $ID0 touch $DIR/d0/f1 || error "touch (4)"
126         $RUNAS -u $ID1 touch $DIR/d0/f2 && error "touch (5)"
127         touch $DIR/d0/f3 || error "touch (6)"
128         chown root $DIR/d0 || error "chown (7)"
129         chgrp $USER0 $DIR/d0 || error "chgrp (8)"
130         chmod 775 $DIR/d0 || error "chmod (9)"
131         $RUNAS -u $ID0 touch $DIR/d0/f4 || error "touch (10)"
132         $RUNAS -u $ID1 touch $DIR/d0/f5 && error "touch (11)"
133         touch $DIR/d0/f6 || error "touch (12)"
134
135         rm -rf $DIR/d0
136 }
137 run_test 0 "uid permission ============================="
138
139 # setuid/gid
140 test_1() {
141         [ $GSS_SUP = 0 ] && skip "without GSS support." && return
142         [ -z "$MDT" ] && skip "do not support do_facet operations." && return
143         [ "$CLIENT_TYPE" = "remote" ] && \
144                 skip "test_1 for local client only" && return
145
146         do_facet $SINGLEMDS "rm -f $PERM_CONF"
147         do_facet $SINGLEMDS "lctl set_param -n $IDENTITY_FLUSH=-1"
148
149         rm -rf $DIR/d1
150         mkdir $DIR/d1
151
152         chown $USER0 $DIR/d1 || error "chown (1)"
153         $RUNAS -u $ID1 -v $ID0 touch $DIR/d1/f0 && error "touch (2)"
154         do_facet $SINGLEMDS "echo '* $ID1 setuid' > $PERM_CONF"
155         echo "enable uid $ID1 setuid"
156         do_facet $SINGLEMDS "lctl set_param -n $IDENTITY_FLUSH=-1"
157         $RUNAS -u $ID1 -v $ID0 touch $DIR/d1/f1 || error "touch (3)"
158
159         chown root $DIR/d1 || error "chown (4)"
160         chgrp $USER0 $DIR/d1 || error "chgrp (5)"
161         chmod 770 $DIR/d1 || error "chmod (6)"
162         $RUNAS -u $ID1 -g $ID1 touch $DIR/d1/f2 && error "touch (7)"
163         $RUNAS -u $ID1 -g $ID1 -j $ID0 touch $DIR/d1/f3 && error "touch (8)"
164         do_facet $SINGLEMDS "echo '* $ID1 setuid,setgid' > $PERM_CONF"
165         echo "enable uid $ID1 setuid,setgid"
166         do_facet $SINGLEMDS "lctl set_param -n $IDENTITY_FLUSH=-1"
167         $RUNAS -u $ID1 -g $ID1 -j $ID0 touch $DIR/d1/f4 || error "touch (9)"
168         $RUNAS -u $ID1 -v $ID0 -g $ID1 -j $ID0 touch $DIR/d1/f5 || error "touch (10)"
169
170         rm -rf $DIR/d1
171
172         do_facet $SINGLEMDS "rm -f $PERM_CONF"
173         do_facet $SINGLEMDS "lctl set_param -n $IDENTITY_FLUSH=-1"
174 }
175 run_test 1 "setuid/gid ============================="
176
177 run_rmtacl_subtest() {
178     $SAVE_PWD/rmtacl/run $SAVE_PWD/rmtacl/$1.test
179     return $?
180 }
181
182 # remote_acl
183 # for remote client only
184 test_2 () {
185         [ "$CLIENT_TYPE" = "local" ] && \
186                 skip "remote_acl for remote client only" && return
187         [ -z "$(lctl get_param -n mdc.*-mdc-*.connect_flags | grep ^acl)" ] && \
188                 skip "must have acl enabled" && return
189         [ -z "$(which setfacl 2>/dev/null)" ] && \
190                 skip "could not find setfacl" && return
191         [ "$UID" != 0 ] && skip "must run as root" && return
192
193         sec_login root root
194         sec_login bin bin
195         sec_login daemon daemon
196         sec_login games users
197
198         SAVE_UMASK=`umask`
199         umask 0022
200         cd $DIR
201
202         if [ ! -z "$MDT" ]; then
203                 do_facet $SINGLEMDS "echo '* 0 rmtacl' > $PERM_CONF"
204                 do_facet $SINGLEMDS "lctl set_param -n $IDENTITY_FLUSH=-1"
205         fi
206
207         if lfs rgetfacl $DIR; then
208                 echo "performing cp ..."
209                 run_rmtacl_subtest cp || error "cp"
210         else
211                 echo "server doesn't permit current user 'lfs r{s,g}etfacl', skip cp test."
212         fi
213         echo "performing getfacl-noacl..."
214         run_rmtacl_subtest getfacl-noacl || error "getfacl-noacl"
215         echo "performing misc..."
216         run_rmtacl_subtest misc || error "misc"
217         echo "performing permissions..."
218         run_rmtacl_subtest permissions || error "permissions"
219         echo "performing setfacl..."
220         run_rmtacl_subtest setfacl || error "setfacl"
221
222         # inheritance test got from HP
223         echo "performing inheritance..."
224         cp $SAVE_PWD/rmtacl/make-tree .
225         chmod +x make-tree
226         run_rmtacl_subtest inheritance || error "inheritance"
227         rm -f make-tree
228
229         if [ ! -z "$MDT" ]; then
230                 do_facet $SINGLEMDS "rm -f $PERM_CONF"
231                 do_facet $SINGLEMDS "lctl set_param -n $IDENTITY_FLUSH=-1"
232         fi
233
234         cd $SAVE_PWD
235         umask $SAVE_UMASK
236 }
237 run_test 2 "rmtacl ============================="
238
239 # rootsquash
240 # root_squash will be redesigned in Lustre 1.7
241 test_3() {
242         skip "root_squash will be redesigned in Lustre 1.7" && return
243 }
244 run_test 3 "rootsquash ============================="
245
246 # bug 3285 - supplementary group should always succeed.
247 # NB: the supplementary groups are set for local client only,
248 # as for remote client, the groups of the specified uid on MDT
249 # will be obtained by upcall /sbin/l_getidentity and used.
250 test_4() {
251         rm -rf $DIR/d4
252         mkdir $DIR/d4
253         chmod 771 $DIR/d4
254         chgrp $ID0 $DIR/d4
255         $RUNAS -u $ID0 ls $DIR/d4 || error "setgroups (1)"
256         if [ "$CLIENT_TYPE" != "remote" ]; then
257                 if [ ! -z "$MDT" ]; then
258                         do_facet $SINGLEMDS "echo '* $ID1 setgrp' > $PERM_CONF"
259                         do_facet $SINGLEMDS "lctl set_param -n $IDENTITY_FLUSH=-1"
260                 fi
261                 $RUNAS -u $ID1 -G1,2,$ID0 ls $DIR/d4 || error "setgroups (2)"
262                 if [ ! -z "$MDT" ]; then
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"