char uc_jobid[LUSTRE_JOBID_SIZE];
lnet_nid_t uc_nid;
bool uc_enable_audit;
+ int uc_rbac_file_perms:1;
+ int uc_rbac_dne_ops:1;
+ int uc_rbac_quota_ops:1;
+ int uc_rbac_byfid_ops:1;
+ int uc_rbac_chlg_ops:1;
};
struct lu_ucred *lu_ucred(const struct lu_env *env);
RETURN(0);
if (is_project_state_change(oattr, la)) {
- if (!cap_raised(uc->uc_cap, CAP_SYS_RESOURCE) &&
- !lustre_in_group_p(uc, ma->ma_enable_chprojid_gid) &&
- !(ma->ma_enable_chprojid_gid == -1 &&
- mdd_permission_internal(env, obj, oattr, MAY_WRITE)))
+ /* we want rbac roles to have precedence over any other
+ * permission or capability checks
+ */
+ if (!uc->uc_rbac_file_perms ||
+ (!cap_raised(uc->uc_cap, CAP_SYS_RESOURCE) &&
+ !lustre_in_group_p(uc, ma->ma_enable_chprojid_gid) &&
+ !(ma->ma_enable_chprojid_gid == -1 &&
+ mdd_permission_internal(env, obj, oattr, MAY_WRITE))))
RETURN(-EPERM);
}
/* Make sure a caller can chmod. */
if (la->la_valid & LA_MODE) {
- if (!(flags & MDS_PERM_BYPASS) &&
- (uc->uc_fsuid != oattr->la_uid) &&
- !cap_raised(uc->uc_cap, CAP_FOWNER))
+ /* we want rbac roles to have precedence over any other
+ * permission or capability checks
+ */
+ if (!uc->uc_rbac_file_perms ||
+ (!(flags & MDS_PERM_BYPASS) &&
+ (uc->uc_fsuid != oattr->la_uid) &&
+ !cap_raised(uc->uc_cap, CAP_FOWNER)))
RETURN(-EPERM);
if (la->la_mode == (umode_t) -1)
if (la->la_valid & LA_UID) {
if (la->la_uid == (uid_t) -1)
la->la_uid = oattr->la_uid;
- if (((uc->uc_fsuid != oattr->la_uid) ||
- (la->la_uid != oattr->la_uid)) &&
- !cap_raised(uc->uc_cap, CAP_CHOWN))
+ /* we want rbac roles to have precedence over any other
+ * permission or capability checks
+ */
+ if (!uc->uc_rbac_file_perms ||
+ ((uc->uc_fsuid != oattr->la_uid ||
+ la->la_uid != oattr->la_uid) &&
+ !cap_raised(uc->uc_cap, CAP_CHOWN)))
RETURN(-EPERM);
/* If the user or group of a non-directory has been
if (la->la_valid & LA_GID) {
if (la->la_gid == (gid_t) -1)
la->la_gid = oattr->la_gid;
- if (((uc->uc_fsuid != oattr->la_uid) ||
- ((la->la_gid != oattr->la_gid) &&
- !lustre_in_group_p(uc, la->la_gid))) &&
- !cap_raised(uc->uc_cap, CAP_CHOWN))
+ /* we want rbac roles to have precedence over any other
+ * permission or capability checks
+ */
+ if (!uc->uc_rbac_file_perms ||
+ ((uc->uc_fsuid != oattr->la_uid ||
+ (la->la_gid != oattr->la_gid &&
+ !lustre_in_group_p(uc, la->la_gid))) &&
+ !cap_raised(uc->uc_cap, CAP_CHOWN)))
RETURN(-EPERM);
/* Likewise, if the user or group of a non-directory
uc->uc_identity = NULL;
/* always record internal HSM activity if also enabled globally */
uc->uc_enable_audit = 1;
+ /* do not let rbac interfere with HSM internal processing */
+ uc->uc_rbac_file_perms = 1;
+ uc->uc_rbac_dne_ops = 1;
+ uc->uc_rbac_quota_ops = 1;
+ uc->uc_rbac_byfid_ops = 1;
+ uc->uc_rbac_chlg_ops = 1;
RETURN(0);
}
if (la->la_flags & LUSTRE_IMMUTABLE_FL)
rc = -EACCES;
+ /* we want rbac roles to have precedence over any other
+ * permission or capability checks
+ */
+ if (!uc->uc_rbac_byfid_ops)
+ RETURN(-EPERM);
if (cap_raised(uc->uc_cap, CAP_DAC_OVERRIDE))
RETURN(0);
if (uc->uc_fsuid == la->la_uid) {
__swab32s(&cs->cs_id);
}
- if (!mdt_is_rootadmin(tsi2mdt_info(tsi)))
+ if (!mdt_changelog_allow(tsi2mdt_info(tsi)))
RETURN(-EACCES);
rc = mdt_iocontrol(OBD_IOC_CHANGELOG_CLEAR, req->rq_export,
vallen, val, NULL);
{
ENTRY;
- if (!mdt_is_rootadmin(tsi2mdt_info(tsi)))
+ if (!mdt_changelog_allow(tsi2mdt_info(tsi)))
RETURN(err_serious(-EACCES));
RETURN(tgt_llog_open(tsi));
lu_context_enter(&ses);
mdt_ucred(info)->uc_valid = UCRED_OLD;
+ /* do not let rbac interfere with dirty flag internal system event */
+ mdt_ucred(info)->uc_rbac_file_perms = 1;
+ mdt_ucred(info)->uc_rbac_dne_ops = 1;
+ mdt_ucred(info)->uc_rbac_quota_ops = 1;
+ mdt_ucred(info)->uc_rbac_byfid_ops = 1;
+ mdt_ucred(info)->uc_rbac_chlg_ops = 1;
rc = mdt_add_dirty_flag(info, mfd->mfd_object, &info->mti_attr);
lu_context_exit(&ses);
u64 want, bool conservative);
extern struct kmem_cache *ldlm_glimpse_work_kmem;
-static inline bool mdt_is_rootadmin(struct mdt_thread_info *info)
+static inline bool mdt_changelog_allow(struct mdt_thread_info *info)
{
struct lu_ucred *uc = NULL;
bool is_admin;
uc = mdt_ucred(info);
is_admin = (uc->uc_uid == 0 && uc->uc_gid == 0 &&
- cap_raised(uc->uc_cap, CAP_SYS_ADMIN));
+ cap_raised(uc->uc_cap, CAP_SYS_ADMIN) &&
+ uc->uc_rbac_chlg_ops);
mdt_exit_ucred(info);
uc->uc_enable_audit = audit;
}
+static void ucred_set_rbac_roles(struct mdt_thread_info *info,
+ struct lu_ucred *uc)
+{
+ struct lu_nodemap *nodemap = NULL;
+ enum nodemap_rbac_roles rbac = NODEMAP_RBAC_ALL;
+
+ if (info && info->mti_exp) {
+ nodemap = nodemap_get_from_exp(info->mti_exp);
+ if (!IS_ERR_OR_NULL(nodemap)) {
+ rbac = nodemap->nmf_rbac;
+ nodemap_putref(nodemap);
+ }
+ }
+
+ uc->uc_rbac_file_perms = !!(rbac & NODEMAP_RBAC_FILE_PERMS);
+ uc->uc_rbac_dne_ops = !!(rbac & NODEMAP_RBAC_DNE_OPS);
+ uc->uc_rbac_quota_ops = !!(rbac & NODEMAP_RBAC_QUOTA_OPS);
+ uc->uc_rbac_byfid_ops = !!(rbac & NODEMAP_RBAC_BYFID_OPS);
+ uc->uc_rbac_chlg_ops = !!(rbac & NODEMAP_RBAC_CHLG_OPS);
+}
+
static int new_init_ucred(struct mdt_thread_info *info, ucred_init_type_t type,
void *buf)
{
ucred_set_jobid(info, ucred);
ucred_set_nid(info, ucred);
ucred_set_audit_enabled(info, ucred);
+ ucred_set_rbac_roles(info, ucred);
EXIT;
ucred_set_jobid(info, uc);
ucred_set_nid(info, uc);
ucred_set_audit_enabled(info, uc);
+ ucred_set_rbac_roles(info, uc);
EXIT;
struct ldlm_reply *ldlm_rep;
struct mdt_body *repbody;
struct lu_fid *child_fid = &info->mti_tmp_fid1;
+ struct lu_ucred *uc = mdt_ucred(info);
struct md_attr *ma = &info->mti_attr;
u64 open_flags = info->mti_spec.sp_cr_flags;
u64 ibits = 0;
PFID(rr->rr_fid1), PNAME(&rr->rr_name), PFID(rr->rr_fid2),
open_flags, ma->ma_attr.la_mode, msg_flags);
+ /* Prevent by-fid operation if parent fid is .lustre/fid.
+ * Also, we want rbac roles to have precedence over any other
+ * permission or capability checks
+ */
+ if (lu_fid_eq(rr->rr_fid1, &LU_OBF_FID) && !uc->uc_rbac_byfid_ops)
+ GOTO(out, result = -EPERM);
+
if (info->mti_cross_ref) {
/* This is cross-ref open */
mdt_set_disposition(info, ldlm_rep,
struct lu_fid *fid = &info->mti_tmp_fid2;
struct ldlm_enqueue_info *einfo = &info->mti_einfo[0];
struct lmv_user_md *lum = spec->u.sp_ea.eadata;
+ struct lu_ucred *uc = mdt_ucred(info);
struct lmv_mds_md_v1 *lmv;
struct mdt_object *child;
struct mdt_lock_handle *lhp;
int rc;
ENTRY;
- if (!mdt->mdt_enable_dir_restripe)
+
+ /* we want rbac roles to have precedence over any other
+ * permission or capability checks
+ */
+ if (!mdt->mdt_enable_dir_restripe && !uc->uc_rbac_dne_ops)
RETURN(-EPERM);
LASSERT(lum);
LMV_HASH_TYPE_CRUSH)
RETURN(-EPROTO);
- if (!cap_raised(uc->uc_cap, CAP_SYS_ADMIN) &&
- uc->uc_gid != mdt->mdt_enable_remote_dir_gid &&
- mdt->mdt_enable_remote_dir_gid != -1)
+ /* we want rbac roles to have precedence over any other
+ * permission or capability checks
+ */
+ if (!uc->uc_rbac_dne_ops ||
+ (!cap_raised(uc->uc_cap, CAP_SYS_ADMIN) &&
+ uc->uc_gid != mdt->mdt_enable_remote_dir_gid &&
+ mdt->mdt_enable_remote_dir_gid != -1))
RETURN(-EPERM);
/* restripe if later found dir exists, MDS_OPEN_CREAT means
!mdt->mdt_enable_striped_dir)
GOTO(out_put, rc = -EPERM);
- if (!cap_raised(uc->uc_cap, CAP_SYS_ADMIN) &&
- uc->uc_gid != mdt->mdt_enable_remote_dir_gid &&
- mdt->mdt_enable_remote_dir_gid != -1)
+ /* we want rbac roles to have precedence over any other
+ * permission or capability checks
+ */
+ if (!uc->uc_rbac_dne_ops ||
+ (!cap_raised(uc->uc_cap, CAP_SYS_ADMIN) &&
+ uc->uc_gid != mdt->mdt_enable_remote_dir_gid &&
+ mdt->mdt_enable_remote_dir_gid != -1))
GOTO(out_put, rc = -EPERM);
}
if (!mdt->mdt_enable_remote_dir || !mdt->mdt_enable_dir_migration)
RETURN(-EPERM);
- if (uc && !cap_raised(uc->uc_cap, CAP_SYS_ADMIN) &&
- uc->uc_gid != mdt->mdt_enable_remote_dir_gid &&
- mdt->mdt_enable_remote_dir_gid != -1)
+ /* we want rbac roles to have precedence over any other
+ * permission or capability checks
+ */
+ if (uc && (!uc->uc_rbac_dne_ops ||
+ (!cap_raised(uc->uc_cap, CAP_SYS_ADMIN) &&
+ uc->uc_gid != mdt->mdt_enable_remote_dir_gid &&
+ mdt->mdt_enable_remote_dir_gid != -1)))
RETURN(-EPERM);
/*
uc->uc_umask = 0644;
uc->uc_ginfo = NULL;
uc->uc_identity = NULL;
+ /* do not let rbac interfere with restriper internal processing */
+ uc->uc_rbac_file_perms = 1;
+ uc->uc_rbac_dne_ops = 1;
+ uc->uc_rbac_quota_ops = 1;
+ uc->uc_rbac_byfid_ops = 1;
+ uc->uc_rbac_chlg_ops = 1;
task = kthread_create(mdt_restriper_main, info, "mdt_restriper_%03d",
mdt_seq_site(mdt)->ss_node_id);
if (!mdt->mdt_enable_dir_migration)
RETURN(-EPERM);
- if (!cap_raised(uc->uc_cap, CAP_SYS_ADMIN) &&
- uc->uc_gid != mdt->mdt_enable_remote_dir_gid &&
- mdt->mdt_enable_remote_dir_gid != -1)
+ /* we want rbac roles to have precedence over any other
+ * permission or capability checks
+ */
+ if (!uc->uc_rbac_dne_ops ||
+ (!cap_raised(uc->uc_cap, CAP_SYS_ADMIN) &&
+ uc->uc_gid != mdt->mdt_enable_remote_dir_gid &&
+ mdt->mdt_enable_remote_dir_gid != -1))
RETURN(-EPERM);
obj = mdt_object_find(env, mdt, rr->rr_fid1);
}
ucred->uc_cap = kcap;
ucred->uc_valid = UCRED_NEW;
+ /* do not let rbac interfere with obdecho */
+ ucred->uc_rbac_file_perms = 1;
+ ucred->uc_rbac_dne_ops = 1;
+ ucred->uc_rbac_quota_ops = 1;
+ ucred->uc_rbac_byfid_ops = 1;
+ ucred->uc_rbac_chlg_ops = 1;
}
static void echo_ucred_fini(struct lu_env *env)
if (!nodemap_active)
return true;
- if (!nodemap || !nodemap->nmf_allow_root_access)
+ if (!nodemap || !nodemap->nmf_allow_root_access ||
+ !(nodemap->nmf_rbac & NODEMAP_RBAC_QUOTA_OPS))
return false;
if (qc_type == PRJQUOTA) {
}
run_test 63 "fid2path with encrypted files"
+setup_64() {
+ do_facet mgs $LCTL nodemap_activate 1
+ wait_nm_sync active
+
+ do_facet mgs $LCTL nodemap_del c0 || true
+ wait_nm_sync c0 id ''
+
+ do_facet mgs $LCTL nodemap_modify --name default \
+ --property admin --value 1
+ do_facet mgs $LCTL nodemap_modify --name default \
+ --property trusted --value 1
+ wait_nm_sync default admin_nodemap
+ wait_nm_sync default trusted_nodemap
+
+ client_ip=$(host_nids_address $HOSTNAME $NETTYPE)
+ client_nid=$(h2nettype $client_ip)
+ do_facet mgs $LCTL nodemap_add c0
+ do_facet mgs $LCTL nodemap_add_range \
+ --name c0 --range $client_nid
+ do_facet mgs $LCTL nodemap_modify --name c0 \
+ --property admin --value 1
+ do_facet mgs $LCTL nodemap_modify --name c0 \
+ --property trusted --value 1
+ wait_nm_sync c0 admin_nodemap
+ wait_nm_sync c0 trusted_nodemap
+}
+
+cleanup_64() {
+ do_facet mgs $LCTL nodemap_del c0
+ do_facet mgs $LCTL nodemap_modify --name default \
+ --property admin --value 0
+ do_facet mgs $LCTL nodemap_modify --name default \
+ --property trusted --value 0
+ wait_nm_sync default admin_nodemap
+ wait_nm_sync default trusted_nodemap
+
+ do_facet mgs $LCTL nodemap_activate 0
+ wait_nm_sync active 0
+}
+
+test_64a() {
+ local testfile=$DIR/$tdir/$tfile
+ local rbac
+
+ (( MDS1_VERSION >= $(version_code 2.15.54) )) ||
+ skip "Need MDS >= 2.15.54 for role-based controls"
+
+ stack_trap cleanup_64 EXIT
+ mkdir -p $DIR/$tdir || error "mkdir $DIR/$tdir failed"
+ setup_64
+
+ # check default value for rbac is all
+ rbac=$(do_facet mds $LCTL get_param -n nodemap.c0.rbac)
+ for role in file_perms \
+ dne_ops \
+ quota_ops \
+ byfid_ops \
+ chlg_ops \
+ ;
+ do
+ [[ "$rbac" =~ "$role" ]] ||
+ error "role '$role' not in default '$rbac'"
+ done
+
+ do_facet mgs $LCTL nodemap_modify --name c0 \
+ --property rbac --value file_perms
+ wait_nm_sync c0 rbac
+ touch $testfile
+ stack_trap "set +vx"
+ set -vx
+ chmod 777 $testfile || error "chmod failed"
+ chown $TSTUSR:$TSTUSR $testfile || error "chown failed"
+ chgrp $TSTUSR $testfile || error "chgrp failed"
+ $LFS project -p 1000 $testfile || error "setting project failed"
+ set +vx
+ rm -f $testfile
+ do_facet mgs $LCTL nodemap_modify --name c0 --property rbac --value none
+ wait_nm_sync c0 rbac
+ touch $testfile
+ set -vx
+ chmod 777 $testfile && error "chmod should fail"
+ chown $TSTUSR:$TSTUSR $testfile && error "chown should fail"
+ chgrp $TSTUSR $testfile && error "chgrp should fail"
+ $LFS project -p 1000 $testfile && error "setting project should fail"
+ set +vx
+}
+run_test 64a "Nodemap enforces file_perms RBAC roles"
+
+test_64b() {
+ local testdir=$DIR/$tdir/${tfile}.d
+ local dir_restripe
+
+ (( MDS1_VERSION >= $(version_code 2.15.54) )) ||
+ skip "Need MDS >= 2.15.54 for role-based controls"
+
+ (( MDSCOUNT >= 2 )) || skip "mdt count $MDSCOUNT, skipping dne_ops role"
+
+ stack_trap cleanup_64 EXIT
+ mkdir -p $DIR/$tdir || error "mkdir $DIR/$tdir failed"
+ setup_64
+
+ dir_restripe=$(do_node $mds1_HOST \
+ "$LCTL get_param -n mdt.*MDT0000.enable_dir_restripe")
+ [ -n "$dir_restripe" ] || dir_restripe=0
+ do_nodes $(comma_list $(all_mdts_nodes)) \
+ $LCTL set_param mdt.*.enable_dir_restripe=1 ||
+ error "enabling dir_restripe failed"
+ stack_trap "do_nodes $(comma_list $(all_mdts_nodes)) \
+ $LCTL set_param mdt.*.enable_dir_restripe=$dir_restripe" EXIT
+ do_facet mgs $LCTL nodemap_modify --name c0 --property rbac \
+ --value dne_ops
+ wait_nm_sync c0 rbac
+ $LFS mkdir -i 0 ${testdir}_for_migr ||
+ error "$LFS mkdir ${testdir}_for_migr failed (1)"
+ touch ${testdir}_for_migr/file001 ||
+ error "touch ${testdir}_for_migr/file001 failed (1)"
+ $LFS mkdir -i 0 ${testdir}_mdt0 ||
+ error "$LFS mkdir ${testdir}_mdt0 failed (1)"
+ $LFS mkdir -i 1 ${testdir}_mdt1 ||
+ error "$LFS mkdir ${testdir}_mdt1 failed (1)"
+ set -vx
+ $LFS mkdir -i 1 $testdir || error "$LFS mkdir failed (1)"
+ rmdir $testdir
+ $LFS mkdir -c 2 $testdir || error "$LFS mkdir failed (2)"
+ rmdir $testdir
+ mkdir $testdir
+ $LFS setdirstripe -c 2 $testdir || error "$LFS setdirstripe failed"
+ rmdir $testdir
+ $LFS migrate -m 1 ${testdir}_for_migr || error "$LFS migrate failed"
+ touch ${testdir}_mdt0/fileA || error "touch fileA failed (1)"
+ mv ${testdir}_mdt0/fileA ${testdir}_mdt1/ || error "mv failed (1)"
+ set +vx
+ rm -rf ${testdir}*
+ $LFS mkdir -i 0 ${testdir}_for_migr ||
+ error "$LFS mkdir ${testdir}_for_migr failed (2)"
+ touch ${testdir}_for_migr/file001 ||
+ error "touch ${testdir}_for_migr/file001 failed (2)"
+ $LFS mkdir -i 0 ${testdir}_mdt0 ||
+ error "$LFS mkdir ${testdir}_mdt0 failed (2)"
+ $LFS mkdir -i 1 ${testdir}_mdt1 ||
+ error "$LFS mkdir ${testdir}_mdt1 failed (2)"
+
+ do_facet mgs $LCTL nodemap_modify --name c0 --property rbac --value none
+ wait_nm_sync c0 rbac
+ set -vx
+ $LFS mkdir -i 1 $testdir && error "$LFS mkdir should fail (1)"
+ $LFS mkdir -c 2 $testdir && error "$LFS mkdir should fail (2)"
+ mkdir $testdir
+ $LFS setdirstripe -c 2 $testdir && error "$LFS setdirstripe should fail"
+ rmdir $testdir
+ $LFS migrate -m 1 ${testdir}_for_migr &&
+ error "$LFS migrate should fail"
+ touch ${testdir}_mdt0/fileA || error "touch fileA failed (2)"
+ mv ${testdir}_mdt0/fileA ${testdir}_mdt1/ || error "mv failed (2)"
+ set +vx
+}
+run_test 64b "Nodemap enforces dne_ops RBAC roles"
+
+test_64c() {
+ (( MDS1_VERSION >= $(version_code 2.15.54) )) ||
+ skip "Need MDS >= 2.15.54 for role-based controls"
+
+ stack_trap cleanup_64 EXIT
+ mkdir -p $DIR/$tdir || error "mkdir $DIR/$tdir failed"
+ setup_64
+
+ do_facet mgs $LCTL nodemap_modify --name c0 \
+ --property rbac --value quota_ops
+ wait_nm_sync c0 rbac
+ set -vx
+ $LFS setquota -u $USER0 -b 307200 -B 309200 -i 10000 -I 11000 $MOUNT ||
+ error "lfs setquota -u failed"
+ $LFS setquota -u $USER0 --delete $MOUNT
+ $LFS setquota -g $USER0 -b 307200 -B 309200 -i 10000 -I 11000 $MOUNT ||
+ error "lfs setquota -g failed"
+ $LFS setquota -g $USER0 --delete $MOUNT
+ $LFS setquota -p 1000 -b 307200 -B 309200 -i 10000 -I 11000 $MOUNT ||
+ error "lfs setquota -p failed"
+ $LFS setquota -p 1000 --delete $MOUNT
+
+ $LFS setquota -U -b 10G -B 11G -i 100K -I 105K $MOUNT ||
+ error "lfs setquota -U failed"
+ $LFS setquota -U -b 0 -B 0 -i 0 -I 0 $MOUNT
+ $LFS setquota -G -b 10G -B 11G -i 100K -I 105K $MOUNT ||
+ error "lfs setquota -G failed"
+ $LFS setquota -G -b 0 -B 0 -i 0 -I 0 $MOUNT
+ $LFS setquota -P -b 10G -B 11G -i 100K -I 105K $MOUNT ||
+ error "lfs setquota -P failed"
+ $LFS setquota -P -b 0 -B 0 -i 0 -I 0 $MOUNT
+ $LFS setquota -u $USER0 -D $MOUNT ||
+ error "lfs setquota -u -D failed"
+ $LFS setquota -u $USER0 --delete $MOUNT
+ $LFS setquota -g $USER0 -D $MOUNT ||
+ error "lfs setquota -g -D failed"
+ $LFS setquota -g $USER0 --delete $MOUNT
+ $LFS setquota -p 1000 -D $MOUNT ||
+ error "lfs setquota -p -D failed"
+ $LFS setquota -p 1000 --delete $MOUNT
+ set +vx
+
+ do_facet mgs $LCTL nodemap_modify --name c0 --property rbac --value none
+ wait_nm_sync c0 rbac
+
+ set -vx
+ $LFS setquota -u $USER0 -b 307200 -B 309200 -i 10000 -I 11000 $MOUNT &&
+ error "lfs setquota -u should fail"
+ $LFS setquota -u $USER0 --delete $MOUNT
+ $LFS setquota -g $USER0 -b 307200 -B 309200 -i 10000 -I 11000 $MOUNT &&
+ error "lfs setquota -g should fail"
+ $LFS setquota -g $USER0 --delete $MOUNT
+ $LFS setquota -p 1000 -b 307200 -B 309200 -i 10000 -I 11000 $MOUNT &&
+ error "lfs setquota -p should fail"
+ $LFS setquota -p 1000 --delete $MOUNT
+
+ $LFS setquota -U -b 10G -B 11G -i 100K -I 105K $MOUNT &&
+ error "lfs setquota -U should fail"
+ $LFS setquota -G -b 10G -B 11G -i 100K -I 105K $MOUNT &&
+ error "lfs setquota -G should fail"
+ $LFS setquota -P -b 10G -B 11G -i 100K -I 105K $MOUNT &&
+ error "lfs setquota -P should fail"
+ $LFS setquota -u $USER0 -D $MOUNT &&
+ error "lfs setquota -u -D should fail"
+ $LFS setquota -u $USER0 --delete $MOUNT
+ $LFS setquota -g $USER0 -D $MOUNT &&
+ error "lfs setquota -g -D should fail"
+ $LFS setquota -g $USER0 --delete $MOUNT
+ $LFS setquota -p 1000 -D $MOUNT &&
+ error "lfs setquota -p -D should fail"
+ $LFS setquota -p 1000 --delete $MOUNT
+ set +vx
+}
+run_test 64c "Nodemap enforces quota_ops RBAC roles"
+
+test_64d() {
+ local testfile=$DIR/$tdir/$tfile
+ local fid
+
+ (( MDS1_VERSION >= $(version_code 2.15.54) )) ||
+ skip "Need MDS >= 2.15.54 for role-based controls"
+
+ stack_trap cleanup_64 EXIT
+ mkdir -p $DIR/$tdir || error "mkdir $DIR/$tdir failed"
+ setup_64
+
+ do_facet mgs $LCTL nodemap_modify --name c0 \
+ --property rbac --value byfid_ops
+ wait_nm_sync c0 rbac
+
+ touch $testfile
+ fid=$(lfs path2fid $testfile)
+ set -vx
+ $LFS fid2path $MOUNT $fid || error "fid2path $fid failed (1)"
+ cat $MOUNT/.lustre/fid/$fid || error "cat by fid failed"
+ lfs rmfid $MOUNT $fid || error "lfs rmfid failed"
+ set +vx
+
+ do_facet mgs $LCTL nodemap_modify --name c0 --property rbac --value none
+ wait_nm_sync c0 rbac
+
+ touch $testfile
+ fid=$(lfs path2fid $testfile)
+ set -vx
+ $LFS fid2path $MOUNT $fid || error "fid2path $fid failed (2)"
+ cat $MOUNT/.lustre/fid/$fid && error "cat by fid should fail"
+ lfs rmfid $MOUNT $fid && error "lfs rmfid should fail"
+ set +vx
+ rm -f $testfile
+}
+run_test 64d "Nodemap enforces byfid_ops RBAC roles"
+
+test_64e() {
+ local testfile=$DIR/$tdir/$tfile
+ local testdir=$DIR/$tdir/${tfile}.d
+
+ (( MDS1_VERSION >= $(version_code 2.15.54) )) ||
+ skip "Need MDS >= 2.15.54 for role-based controls"
+
+ stack_trap cleanup_64 EXIT
+ mkdir -p $DIR/$tdir || error "mkdir $DIR/$tdir failed"
+ setup_64
+
+ # activate changelogs
+ changelog_register || error "changelog_register failed"
+ local cl_user="${CL_USERS[$SINGLEMDS]%% *}"
+ changelog_users $SINGLEMDS | grep -q $cl_user ||
+ error "User $cl_user not found in changelog_users"
+ changelog_chmask ALL
+
+ # do some IOs
+ mkdir $testdir || error "failed to mkdir $testdir"
+ touch $testfile || error "failed to touch $testfile"
+
+ do_facet mgs $LCTL nodemap_modify --name c0 \
+ --property rbac --value chlg_ops
+ wait_nm_sync c0 rbac
+
+ # access changelogs
+ echo "changelogs dump"
+ changelog_dump || error "failed to dump changelogs"
+ echo "changelogs clear"
+ changelog_clear 0 || error "failed to clear changelogs"
+
+ rm -rf $testdir $testfile || error "rm -rf $testdir $testfile failed"
+
+ do_facet mgs $LCTL nodemap_modify --name c0 --property rbac --value none
+ wait_nm_sync c0 rbac
+
+ # do some IOs
+ mkdir $testdir || error "failed to mkdir $testdir"
+ touch $testfile || error "failed to touch $testfile"
+
+ # access changelogs
+ echo "changelogs dump"
+ changelog_dump && error "dump changelogs should fail"
+ echo "changelogs clear"
+ changelog_clear 0 && error "clear changelogs should fail"
+ rm -rf $testdir $testfile
+
+ do_facet mgs $LCTL nodemap_modify --name c0 --property rbac --value all
+ wait_nm_sync c0 rbac
+}
+run_test 64e "Nodemap enforces chlg_ops RBAC roles"
+
log "cleanup: ======================================================"
sec_unsetup() {