iscsi: Add set_iscsi_target_node_auth RPC to configure CHAP dynamically
An new RPC set_iscsi_target_node_auth enables users to configure CHAP authentication for the target node dynamically. New setting is used for new iSCSI sessions. For existing iSCSI sessions, new setting is not used until user logout and login again. Try to use descriptive message in the RPC when error occurs. Change-Id: I0bd40d92262d708c1f7de0effb208078bdf8cc41 Signed-off-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com> Reviewed-on: https://review.gerrithub.io/420974 Tested-by: SPDK CI Jenkins <sys_sgci@intel.com> Chandler-Test-Pool: SPDK Automated Test System <sys_sgsw@intel.com> Reviewed-by: Jim Harris <james.r.harris@intel.com> Reviewed-by: Ben Walker <benjamin.walker@intel.com>
This commit is contained in:
parent
6cd1714a99
commit
844735c928
@ -29,8 +29,9 @@ method for CHAP authentication in discovery sessions have been changed to
|
||||
align with `construct_target_node` RPC method. Old names are still usable
|
||||
but will be removed in future release.
|
||||
|
||||
`set_iscsi_discovery_auth` RPC method has been added to set CHAP authentication
|
||||
for discovery sessions dynamically.
|
||||
`set_iscsi_discovery_auth` and `set_iscsi_target_node_auth` RPC methods have
|
||||
been added to set CHAP authentication for discovery sessions and existing
|
||||
target nodes, respectively.
|
||||
|
||||
## v18.07:
|
||||
|
||||
|
@ -2184,6 +2184,8 @@ chap_group | Optional | number | Authentication group ID for t
|
||||
header_digest | Optional | boolean | Header Digest should be required for this target node
|
||||
data_digest | Optional | boolean | Data Digest should be required for this target node
|
||||
|
||||
Parameters `disable_chap` and `require_chap` are mutually exclusive.
|
||||
|
||||
### Example
|
||||
|
||||
Example request:
|
||||
@ -2231,6 +2233,50 @@ Example response:
|
||||
}
|
||||
~~~
|
||||
|
||||
## set_iscsi_target_node_auth method {#rpc_set_iscsi_target_node_auth}
|
||||
|
||||
Set CHAP authentication to an existing iSCSI target node.
|
||||
|
||||
### Parameters
|
||||
|
||||
Name | Optional | Type | Description
|
||||
--------------------------- | -------- | --------| -----------
|
||||
name | Required | string | Target node name (ASCII)
|
||||
disable_chap | Optional | boolean | CHAP authentication should be disabled for this target
|
||||
require_chap | Optional | boolean | CHAP authentication should be required for this target
|
||||
mutual_chap | Optional | boolean | CHAP authentication should be bidirectional (`true`) or unidirectional (`false`)
|
||||
chap_group | Optional | number | Authentication group ID for this target node
|
||||
|
||||
Parameters `disable_chap` and `require_chap` are mutually exclusive.
|
||||
|
||||
### Example
|
||||
|
||||
Example request:
|
||||
|
||||
~~~
|
||||
{
|
||||
"params": {
|
||||
"chap_group": 1,
|
||||
"require_chap": true,
|
||||
"name": "iqn.2016-06.io.spdk:target1",
|
||||
"mutual_chap": true
|
||||
},
|
||||
"jsonrpc": "2.0",
|
||||
"method": "set_iscsi_target_node_auth",
|
||||
"id": 1
|
||||
}
|
||||
~~~
|
||||
|
||||
Example response:
|
||||
|
||||
~~~
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"id": 1,
|
||||
"result": true
|
||||
}
|
||||
~~~
|
||||
|
||||
## add_pg_ig_maps method {#rpc_add_pg_ig_maps}
|
||||
|
||||
Add initiator group to portal group mappings to an existing iSCSI target node.
|
||||
|
@ -1035,6 +1035,75 @@ invalid:
|
||||
}
|
||||
SPDK_RPC_REGISTER("target_node_add_lun", spdk_rpc_target_node_add_lun, SPDK_RPC_RUNTIME)
|
||||
|
||||
struct rpc_target_auth {
|
||||
char *name;
|
||||
bool disable_chap;
|
||||
bool require_chap;
|
||||
bool mutual_chap;
|
||||
int32_t chap_group;
|
||||
};
|
||||
|
||||
static void
|
||||
free_rpc_target_auth(struct rpc_target_auth *req)
|
||||
{
|
||||
free(req->name);
|
||||
}
|
||||
|
||||
static const struct spdk_json_object_decoder rpc_target_auth_decoders[] = {
|
||||
{"name", offsetof(struct rpc_target_auth, name), spdk_json_decode_string},
|
||||
{"disable_chap", offsetof(struct rpc_target_auth, disable_chap), spdk_json_decode_bool, true},
|
||||
{"require_chap", offsetof(struct rpc_target_auth, require_chap), spdk_json_decode_bool, true},
|
||||
{"mutual_chap", offsetof(struct rpc_target_auth, mutual_chap), spdk_json_decode_bool, true},
|
||||
{"chap_group", offsetof(struct rpc_target_auth, chap_group), spdk_json_decode_int32, true},
|
||||
};
|
||||
|
||||
static void
|
||||
spdk_rpc_set_iscsi_target_node_auth(struct spdk_jsonrpc_request *request,
|
||||
const struct spdk_json_val *params)
|
||||
{
|
||||
struct rpc_target_auth req = {};
|
||||
struct spdk_json_write_ctx *w;
|
||||
struct spdk_iscsi_tgt_node *target;
|
||||
int rc;
|
||||
|
||||
if (spdk_json_decode_object(params, rpc_target_auth_decoders,
|
||||
SPDK_COUNTOF(rpc_target_auth_decoders), &req)) {
|
||||
SPDK_ERRLOG("spdk_json_decode_object failed\n");
|
||||
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
|
||||
"Invalid parameters");
|
||||
return;
|
||||
}
|
||||
|
||||
target = spdk_iscsi_find_tgt_node(req.name);
|
||||
if (target == NULL) {
|
||||
spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
|
||||
"Could not find target %s", req.name);
|
||||
free_rpc_target_auth(&req);
|
||||
return;
|
||||
}
|
||||
|
||||
rc = spdk_iscsi_tgt_node_set_chap_params(target, req.disable_chap, req.require_chap,
|
||||
req.mutual_chap, req.chap_group);
|
||||
if (rc < 0) {
|
||||
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
|
||||
"Invalid combination of CHAP params");
|
||||
free_rpc_target_auth(&req);
|
||||
return;
|
||||
}
|
||||
|
||||
free_rpc_target_auth(&req);
|
||||
|
||||
w = spdk_jsonrpc_begin_result(request);
|
||||
if (w == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
spdk_json_write_bool(w, true);
|
||||
spdk_jsonrpc_end_result(request, w);
|
||||
}
|
||||
SPDK_RPC_REGISTER("set_iscsi_target_node_auth", spdk_rpc_set_iscsi_target_node_auth,
|
||||
SPDK_RPC_RUNTIME)
|
||||
|
||||
static void
|
||||
spdk_rpc_get_iscsi_global_params(struct spdk_jsonrpc_request *request,
|
||||
const struct spdk_json_val *params)
|
||||
|
@ -1332,6 +1332,26 @@ spdk_iscsi_tgt_node_add_lun(struct spdk_iscsi_tgt_node *target,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
spdk_iscsi_tgt_node_set_chap_params(struct spdk_iscsi_tgt_node *target,
|
||||
bool disable_chap, bool require_chap,
|
||||
bool mutual_chap, int32_t chap_group)
|
||||
{
|
||||
if (!spdk_iscsi_check_chap_params(disable_chap, require_chap,
|
||||
mutual_chap, chap_group)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&target->mutex);
|
||||
target->disable_chap = disable_chap;
|
||||
target->require_chap = require_chap;
|
||||
target->mutual_chap = mutual_chap;
|
||||
target->chap_group = chap_group;
|
||||
pthread_mutex_unlock(&target->mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *target_nodes_section = \
|
||||
"\n"
|
||||
"# Users should change the TargetNode section(s) below to match the\n"
|
||||
|
@ -137,6 +137,9 @@ void spdk_iscsi_tgt_node_delete_map(struct spdk_iscsi_portal_grp *portal_group,
|
||||
struct spdk_iscsi_init_grp *initiator_group);
|
||||
int spdk_iscsi_tgt_node_add_lun(struct spdk_iscsi_tgt_node *target,
|
||||
const char *bdev_name, int lun_id);
|
||||
int spdk_iscsi_tgt_node_set_chap_params(struct spdk_iscsi_tgt_node *target,
|
||||
bool disable_chap, bool require_chap,
|
||||
bool mutual_chap, int32_t chap_group);
|
||||
void spdk_iscsi_tgt_nodes_config_text(FILE *fp);
|
||||
void spdk_iscsi_tgt_nodes_info_json(struct spdk_json_write_ctx *w);
|
||||
void spdk_iscsi_tgt_nodes_config_json(struct spdk_json_write_ctx *w);
|
||||
|
@ -644,6 +644,28 @@ if __name__ == "__main__":
|
||||
*** If LUN ID is omitted or -1, the lowest free one is assigned ***""", type=int, required=False)
|
||||
p.set_defaults(func=target_node_add_lun)
|
||||
|
||||
@call_cmd
|
||||
def set_iscsi_target_node_auth(args):
|
||||
rpc.iscsi.set_iscsi_target_node_auth(
|
||||
args.client,
|
||||
name=args.name,
|
||||
chap_group=args.chap_group,
|
||||
disable_chap=args.disable_chap,
|
||||
require_chap=args.require_chap,
|
||||
mutual_chap=args.mutual_chap)
|
||||
|
||||
p = subparsers.add_parser('set_iscsi_target_node_auth', help='Set CHAP authentication for the target node')
|
||||
p.add_argument('name', help='Target node name (ASCII)')
|
||||
p.add_argument('-g', '--chap-group', help="""Authentication group ID for this target node.
|
||||
*** Authentication group must be precreated ***""", type=int, default=0)
|
||||
p.add_argument('-d', '--disable-chap', help="""CHAP authentication should be disabled for this target node.
|
||||
*** Mutually exclusive with --require-chap ***""", action='store_true')
|
||||
p.add_argument('-r', '--require-chap', help="""CHAP authentication should be required for this target node.
|
||||
*** Mutually exclusive with --disable-chap ***""", action='store_true')
|
||||
p.add_argument('-m', '--mutual-chap', help='CHAP authentication should be mutual/bidirectional.',
|
||||
action='store_true')
|
||||
p.set_defaults(func=set_iscsi_target_node_auth)
|
||||
|
||||
@call_cmd
|
||||
def add_pg_ig_maps(args):
|
||||
pg_ig_maps = []
|
||||
|
@ -215,6 +215,40 @@ def target_node_add_lun(client, name, bdev_name, lun_id=None):
|
||||
return client.call('target_node_add_lun', params)
|
||||
|
||||
|
||||
def set_iscsi_target_node_auth(
|
||||
client,
|
||||
name,
|
||||
chap_group=None,
|
||||
disable_chap=None,
|
||||
require_chap=None,
|
||||
mutual_chap=None):
|
||||
"""Set CHAP authentication for the target node.
|
||||
|
||||
Args:
|
||||
name: Target node name (ASCII)
|
||||
chap_group: Authentication group ID for this target node
|
||||
disable_chap: CHAP authentication should be disabled for this target node
|
||||
require_chap: CHAP authentication should be required for this target node
|
||||
mutual_chap: CHAP authentication should be mutual/bidirectional
|
||||
|
||||
Returns:
|
||||
True or False
|
||||
"""
|
||||
params = {
|
||||
'name': name,
|
||||
}
|
||||
|
||||
if chap_group:
|
||||
params['chap_group'] = chap_group
|
||||
if disable_chap:
|
||||
params['disable_chap'] = disable_chap
|
||||
if require_chap:
|
||||
params['require_chap'] = require_chap
|
||||
if mutual_chap:
|
||||
params['mutual_chap'] = mutual_chap
|
||||
return client.call('set_iscsi_target_node_auth', params)
|
||||
|
||||
|
||||
def delete_pg_ig_maps(client, pg_ig_maps, name):
|
||||
"""Delete PG-IG maps from the target node.
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user