diff options
| -rwxr-xr-x | tests/basic/mount-nfs-auth.t | 40 | ||||
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-volgen.c | 13 | ||||
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-volume-set.c | 4 | ||||
| -rw-r--r-- | xlators/nfs/server/src/mount3.c | 27 | ||||
| -rw-r--r-- | xlators/nfs/server/src/nfs.c | 42 | ||||
| -rw-r--r-- | xlators/nfs/server/src/nfs3-helpers.c | 11 | ||||
| -rw-r--r-- | xlators/nfs/server/src/nfs3.c | 50 | ||||
| -rw-r--r-- | xlators/nfs/server/src/nfs3.h | 8 |
8 files changed, 167 insertions, 28 deletions
diff --git a/tests/basic/mount-nfs-auth.t b/tests/basic/mount-nfs-auth.t index 5c5e62e0d58..7f990c9aeb2 100755 --- a/tests/basic/mount-nfs-auth.t +++ b/tests/basic/mount-nfs-auth.t @@ -48,7 +48,7 @@ EXPORT_ALLOW_L1="/$V0L1 $H0(sec=sys,rw,anonuid=0) @ngtop(sec=sys,rw,anonuid=0)" EXPORT_WILDCARD="/$V0 *(sec=sys,rw,anonuid=0) @ngtop(sec=sys,rw,anonuid=0)" function build_dirs () { - mkdir -p $B0/b{0,1,2}/L1/L2/L3 + mkdir -p $B0/b{0,1,2,3,4,5}/L1/L2/L3 } function export_allow_this_host_ipv6 () { @@ -64,6 +64,9 @@ function export_allow_this_host_with_slash () { } function export_deny_this_host () { + if [[ "$1" && "$1" != "$V0" ]]; then + local EXPORT_DENY=$(echo $EXPORT_DENY | sed "s/$V0/$1/") + fi printf "$EXPORT_DENY\n" > ${NFSDIR}/exports } @@ -134,6 +137,10 @@ function check_mount_failure { fi } +function do_mount () { + mount_nfs $H0:/$1 $N0 nolock +} + function small_write () { dd if=/dev/zero of=$N0/test-small-write count=1 bs=1k 2>&1 if [ $? -ne 0 ]; then @@ -377,9 +384,40 @@ TEST $CLI vol set $V0 nfs.auth-refresh-interval-sec 20 ## Do a simple test to see if the volume option exists TEST $CLI vol set $V0 nfs.auth-cache-ttl-sec 400 +## Test authentication in 1 of 2 (sub)volumes +ME=$(hostname) +TEST $CLI vol create $V1 replica 3 $ME:$B0/b3 $ME:$B0/b4 $ME:$B0/b5 +TEST $CLI vol set $V1 cluster.self-heal-daemon off +TEST $CLI vol set $V1 nfs.disable off +TEST $CLI vol set $V1 cluster.choose-local off +TEST $CLI vol start $V1 +TEST $CLI volume info $V1; + +EXPECT_WITHIN $NFS_EXPORT_TIMEOUT "2" is_nfs_export_available $V0 +EXPECT_WITHIN $NFS_EXPORT_TIMEOUT "1" is_nfs_export_available $V1 +TEST $CLI vol set $V0 nfs.exports-auth-enable on +TEST $CLI vol set $V1 nfs.exports-auth-enable off +# Deny the hosts, but only effective on $V0 +TEST export_deny_this_host $V0 +TEST netgroup_deny_this_host +TEST export_deny_this_host $V1 + +sleep $AUTH_REFRESH_INTERVAL +TEST ! do_mount $V0 # Do a mount & test +TEST do_mount $V1 # Do a mount & test + +TEST touch /tmp/foo +TEST cp /tmp/foo $N0/ + +EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" umount_nfs $N0 + ## Finish up TEST $CLI volume stop $V0 TEST $CLI volume delete $V0; TEST ! $CLI volume info $V0; +TEST $CLI volume stop $V1 +TEST $CLI volume delete $V1; +TEST ! $CLI volume info $V1; + cleanup diff --git a/xlators/mgmt/glusterd/src/glusterd-volgen.c b/xlators/mgmt/glusterd/src/glusterd-volgen.c index 2344fd169f1..fdc9f46284a 100644 --- a/xlators/mgmt/glusterd/src/glusterd-volgen.c +++ b/xlators/mgmt/glusterd/src/glusterd-volgen.c @@ -4493,6 +4493,19 @@ nfs_option_handler (volgen_graph_t *graph, return -1; } + if (! strcmp (vme->option, "!nfs.*.exports-auth-enable")) { + ret = gf_asprintf (&aa, "nfs.%s.exports-auth-enable", + volinfo->volname); + + if (ret != -1) { + ret = xlator_set_option (xl, aa, vme->value); + GF_FREE (aa); + } + + if (ret) + return -1; + } + if ((strcmp (vme->voltype, "nfs/server") == 0) && (vme->option && vme->option[0]!='!') ) { ret = xlator_set_option (xl, vme->option, vme->value); diff --git a/xlators/mgmt/glusterd/src/glusterd-volume-set.c b/xlators/mgmt/glusterd/src/glusterd-volume-set.c index 82513338d92..0f098646b30 100644 --- a/xlators/mgmt/glusterd/src/glusterd-volume-set.c +++ b/xlators/mgmt/glusterd/src/glusterd-volume-set.c @@ -2434,8 +2434,8 @@ struct volopt_map_entry glusterd_volopt_map[] = { /* Cli options for Export authentication on nfs mount */ { .key = "nfs.exports-auth-enable", .voltype = "nfs/server", - .option = "nfs.exports-auth-enable", - .type = GLOBAL_DOC, + .option = "!nfs.*.exports-auth-enable", + //.type = GLOBAL_DOC, .op_version = GD_OP_VERSION_3_7_0 }, { .key = "nfs.auth-refresh-interval-sec", diff --git a/xlators/nfs/server/src/mount3.c b/xlators/nfs/server/src/mount3.c index 7e008b40c85..2dbbc0fbc3b 100644 --- a/xlators/nfs/server/src/mount3.c +++ b/xlators/nfs/server/src/mount3.c @@ -24,6 +24,7 @@ #include "iatt.h" #include "nfs-mem-types.h" #include "nfs.h" +#include "nfs3.h" #include "common-utils.h" #include "store.h" #include "glfs-internal.h" @@ -1169,7 +1170,8 @@ mnt3_resolve_subdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this, mres->exp->expname, mres->resolveloc.path); /* Check if this path is authorized to be mounted */ - authcode = mnt3_authenticate_request (ms, mres->req, NULL, NULL, + authcode = mnt3_authenticate_request (ms, mres->req, NULL, + mres->exp->vol->name, mres->exp->fullpath, &authorized_path, &authorized_host, @@ -2086,15 +2088,18 @@ mnt3_authenticate_request (struct mount3_state *ms, rpcsvc_request_t *req, const char *path, char **authorized_path, char **authorized_host, gf_boolean_t is_write_op) { - int auth_status_code = -EACCES; - char *parent_path = NULL; - const char *parent_old = NULL; + int auth_status_code = -EACCES; + char *parent_path = NULL; + const char *parent_old = NULL; + struct mnt3_export *exp = NULL; + struct nfs3_state *nfs3 = ms->nfs->nfs3state; GF_VALIDATE_OR_GOTO (GF_MNT, ms, out); GF_VALIDATE_OR_GOTO (GF_MNT, req, out); + GF_VALIDATE_OR_GOTO (GF_MNT, volname, out); /* If this option is not set, just allow it through */ - if (!ms->nfs->exports_auth) { + if (!nfs3->exports_auth || !nfs3_is_exports_auth(nfs3, volname)) { /* This function is called in a variety of use-cases (mount * + each fop) so path/authorized_path are not always present. * For the cases which it _is_ present we need to populate the @@ -2219,8 +2224,8 @@ mnt3svc_mnt (rpcsvc_request_t *req) /* The second authentication check is the exports/netgroups * check. */ - authcode = mnt3_authenticate_request (ms, req, NULL, NULL, path, NULL, - NULL, _gf_false); + authcode = mnt3_authenticate_request (ms, req, NULL, exp->vol->name, + path, NULL, NULL, FALSE); if (authcode != 0) { mntstat = MNT3ERR_ACCES; gf_msg_debug (GF_MNT, 0, "Client mount not allowed"); @@ -3726,6 +3731,9 @@ __mnt3_mounted_exports_walk (dict_t *dict, char *key, data_t *val, void *tmp) * and umounts them. * * @ms: The mountstate for this service that holds all the information we need + if (!nfs->nfs3state) + return NULL; + * */ void @@ -3812,6 +3820,9 @@ _mnt3_auth_param_refresh_thread (void *argv) /* Sleep before checking the file again */ sleep (mstate->nfs->auth_refresh_time_secs); + if (!mstate->nfs->nfs3state->exports_auth) + continue; + if (_mnt3_has_file_changed (exp_file_path, &exp_time)) { gf_msg (GF_MNT, GF_LOG_INFO, 0, NFS_MSG_UPDATING_EXP, "File %s changed, updating exports,", @@ -3990,7 +4001,7 @@ mnt3svc_init (xlator_t *nfsx) goto err; } - if (nfs->exports_auth) { + if (nfs->nfs3state->exports_auth) { ret = _mnt3_init_auth_params (mstate); if (ret < 0) goto err; diff --git a/xlators/nfs/server/src/nfs.c b/xlators/nfs/server/src/nfs.c index d5087f195ca..f2e202d0510 100644 --- a/xlators/nfs/server/src/nfs.c +++ b/xlators/nfs/server/src/nfs.c @@ -369,24 +369,24 @@ nfs_add_all_initiators (struct nfs_state *nfs) int ret = 0; /* Add the initializers for all versions. */ - ret = nfs_add_initer (&nfs->versions, mnt3svc_init, _gf_true); + ret = nfs_add_initer (&nfs->versions, mnt1svc_init, _gf_true); if (ret == -1) { gf_msg (GF_NFS, GF_LOG_ERROR, 0, NFS_MSG_PROT_INIT_ADD_FAIL, - "Failed to add MOUNT3 protocol initializer"); + "Failed to add MOUNT1 protocol initializer"); goto ret; } - ret = nfs_add_initer (&nfs->versions, mnt1svc_init, _gf_true); + ret = nfs_add_initer (&nfs->versions, nfs3svc_init, _gf_true); if (ret == -1) { gf_msg (GF_NFS, GF_LOG_ERROR, 0, NFS_MSG_PROT_INIT_ADD_FAIL, - "Failed to add MOUNT1 protocol initializer"); + "Failed to add NFS3 protocol initializer"); goto ret; } - ret = nfs_add_initer (&nfs->versions, nfs3svc_init, _gf_true); + ret = nfs_add_initer (&nfs->versions, mnt3svc_init, _gf_true); if (ret == -1) { gf_msg (GF_NFS, GF_LOG_ERROR, 0, NFS_MSG_PROT_INIT_ADD_FAIL, - "Failed to add NFS3 protocol initializer"); + "Failed to add MOUNT3 protocol initializer"); goto ret; } @@ -957,24 +957,22 @@ nfs_init_state (xlator_t *this) } nfs->exports_auth = GF_NFS_DEFAULT_EXPORT_AUTH; - if (dict_get(this->options, "nfs.exports-auth-enable")) { + if (dict_get (this->options, "nfs.exports-auth-enable")) { ret = dict_get_str (this->options, "nfs.exports-auth-enable", &optstr); if (ret == -1) { - gf_msg (GF_NFS, GF_LOG_ERROR, -ret, NFS_MSG_PARSE_FAIL, - "Failed to parse dict"); + gf_log (GF_NFS, GF_LOG_ERROR, "Failed to parse dict"); goto free_foppool; } ret = gf_string2boolean (optstr, &boolt); if (ret < 0) { - gf_msg (GF_NFS, GF_LOG_ERROR, errno, NFS_MSG_PARSE_FAIL, - "Failed to parse bool string"); + gf_log (GF_NFS, GF_LOG_ERROR, "Failed to parse bool " + "string"); goto free_foppool; } - if (boolt == _gf_true) - nfs->exports_auth = 1; + nfs->exports_auth = boolt; } nfs->auth_refresh_time_secs = GF_NFS_DEFAULT_AUTH_REFRESH_INTERVAL_SEC; @@ -1214,6 +1212,7 @@ nfs_reconfigure_state (xlator_t *this, dict_t *options) "nfs.transport-type", "nfs.mem-factor", NULL}; + char *exports_auth_enable = NULL; GF_VALIDATE_OR_GOTO (GF_NFS, this, out); GF_VALIDATE_OR_GOTO (GF_NFS, this->private, out); @@ -1293,6 +1292,21 @@ nfs_reconfigure_state (xlator_t *this, dict_t *options) "Reconfigured nfs.mount-rmtab path: %s", nfs->rmtab); } + /* reconfig nfs.exports-auth-enable */ + if (dict_get (options, "nfs.exports-auth-enable")) { + ret = dict_get_str (options, "nfs.exports-auth-enable", + &exports_auth_enable); + if (ret < 0) { + gf_log (GF_NFS, GF_LOG_ERROR, "Failed to read " + "reconfigured option: nfs.exports-auth-enable"); + goto out; + } + ret = gf_string2int (exports_auth_enable, &nfs->exports_auth); + if (ret < 0) { + goto out; + } + } + GF_OPTION_RECONF (OPT_SERVER_AUX_GIDS, optbool, options, bool, out); if (nfs->server_aux_gids != optbool) { @@ -2099,7 +2113,7 @@ struct volume_options options[] = { .description = "Sets the number of non-idempotent " "requests to cache in drc" }, - { .key = {"nfs.exports-auth-enable"}, + { .key = {"nfs.*.exports-auth-enable"}, .type = GF_OPTION_TYPE_BOOL, .description = "Set the option to 'on' to enable exports/netgroup " "authentication in the NFS server and mount daemon." diff --git a/xlators/nfs/server/src/nfs3-helpers.c b/xlators/nfs/server/src/nfs3-helpers.c index 0b977092fbb..1edc2ac4429 100644 --- a/xlators/nfs/server/src/nfs3-helpers.c +++ b/xlators/nfs/server/src/nfs3-helpers.c @@ -3975,11 +3975,18 @@ nfs3_fh_auth_nfsop (nfs3_call_state_t *cs, gf_boolean_t is_write_op) { struct nfs_state *nfs = NULL; struct mount3_state *ms = NULL; + int auth_status = -1; nfs = (struct nfs_state *)cs->nfsx->private; ms = (struct mount3_state *)nfs->mstate; - return mnt3_authenticate_request (ms, cs->req, &cs->resolvefh, NULL, - NULL, NULL, NULL, is_write_op); + auth_status = mnt3_authenticate_request (ms, cs->req, &cs->resolvefh, + cs->vol->name, NULL, NULL, + NULL, is_write_op); + + if (auth_status != 0) { + cs->resolve_errno = auth_status; + } + return auth_status; } int diff --git a/xlators/nfs/server/src/nfs3.c b/xlators/nfs/server/src/nfs3.c index 5aa9ea4e76e..d7eaca14b38 100644 --- a/xlators/nfs/server/src/nfs3.c +++ b/xlators/nfs/server/src/nfs3.c @@ -210,6 +210,25 @@ out: return ret; } +int +nfs3_is_exports_auth (struct nfs3_state *nfs3, const char *volname) +{ + int ret = 0; + struct nfs3_export *exp = NULL; + + GF_VALIDATE_OR_GOTO (GF_NFS3, nfs3, out); + + list_for_each_entry (exp, &nfs3->exports, explist) { + if (strcmp (exp->subvol->name, volname) == 0) { + ret = exp->exports_auth; + break; + } + } + +out: + return ret; +} + #define nfs3_map_fh_to_volume(nfs3state, handle, req, volume, status, label) \ do { \ @@ -5624,6 +5643,35 @@ no_dvm: (exp->trusted_sync == 0)?"no trusted_sync":"trusted_sync", (exp->trusted_write == 0)?"no trusted_write":"trusted_write"); ret = 0; + + ret = snprintf (searchkey, 1024, "nfs.%s.exports-auth-enable", name); + if (ret < 0) { + gf_log (GF_NFS, GF_LOG_ERROR, "snprintf failed"); + ret = -1; + goto err; + } + + if (dict_get (options, searchkey)) { + ret = dict_get_str (options, searchkey, &optstr); + if (ret == -1) { + gf_log (GF_NFS, GF_LOG_ERROR, "Failed to parse dict"); + goto err; + } + + ret = gf_string2boolean (optstr, &boolt); + if (ret < 0) { + gf_log (GF_NFS, GF_LOG_ERROR, "Failed to parse bool " + "string"); + goto err; + } + + exp->exports_auth = boolt ? TRUE : FALSE; + if (boolt) { + struct nfs_state *priv = nfsx->private; + priv->nfs3state->exports_auth = boolt; + } + } + err: return ret; } @@ -5730,6 +5778,7 @@ nfs3_init_state (xlator_t *nfsx) goto ret; } + nfs->nfs3state = nfs3; nfs3->nfsx = nfsx; nfs3->exportslist = nfsx->children; INIT_LIST_HEAD (&nfs3->exports); @@ -5752,7 +5801,6 @@ nfs3_init_state (xlator_t *nfsx) goto free_localpool; } - nfs->nfs3state = nfs3; ret = 0; free_localpool: diff --git a/xlators/nfs/server/src/nfs3.h b/xlators/nfs/server/src/nfs3.h index c6131222c2a..36d981c3eef 100644 --- a/xlators/nfs/server/src/nfs3.h +++ b/xlators/nfs/server/src/nfs3.h @@ -31,6 +31,7 @@ #define GF_NFS3_IOBPOOL_MULT GF_NFS_CONCURRENT_OPS_MULT #define GF_NFS3_CLTABLE_BUCKETS_MULT 2 #define GF_NFS3_FDTABLE_BUCKETS_MULT 2 +#define GF_NFS3_DEFAULT_EXPORT_AUTH _gf_false /* Static values used for FSINFO @@ -99,6 +100,7 @@ struct nfs3_export { int trusted_sync; int trusted_write; int rootlookedup; + int exports_auth; }; #define GF_NFS3_DEFAULT_VOLACCESS (GF_NFS3_VOLACCESS_RW) @@ -142,6 +144,9 @@ typedef struct nfs3_state { gf_lock_t fdlrulock; int fdcount; uint32_t occ_logger; + + /* Enable exports auth model */ + gf_boolean_t exports_auth; } nfs3_state_t; typedef enum nfs3_lookup_type { @@ -280,4 +285,7 @@ nfs3_reconfigure_state (xlator_t *nfsx, dict_t *options); extern uint64_t nfs3_request_xlator_deviceid (rpcsvc_request_t *req); +extern int +nfs3_is_exports_auth (struct nfs3_state *nfs3, const char *volname); + #endif |
