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