diff --git a/CHANGELOG.md b/CHANGELOG.md index 9e44c4a3e7..c8de918256 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -67,6 +67,10 @@ Added `spdk_nvme_ns_cmd_write_uncorrectable`. Portals may no longer be associated with a cpumask. The scheduling of connections is moving to a more dynamic model. +An new RPC `iscsi_portal_group_set_auth` has been added to set CHAP authentication +for discovery sessions specific for the existing iSCSI portal group. This RPC overwrites +the setting by the global parameters for the iSCSI portal group. + ### delay bdev The `bdev_delay_update_latency` has been added to allow users to update diff --git a/doc/jsonrpc.md b/doc/jsonrpc.md index 6217edddc1..930fc4ffc6 100644 --- a/doc/jsonrpc.md +++ b/doc/jsonrpc.md @@ -3559,6 +3559,51 @@ Example response: } ~~~ +### iscsi_portal_group_set_auth method {#rpc_iscsi_portal_group_set_auth} + +Set CHAP authentication for discovery sessions specific for the existing iSCSI portal group. +This RPC overwrites the setting by the global parameters for the iSCSI portal group. + +### Parameters + +Name | Optional | Type | Description +--------------------------- | -------- | --------| ----------- +disable_chap | Optional | boolean | CHAP for discovery session should be disabled (default: `false`) +require_chap | Optional | boolean | CHAP for discovery session should be required (default: `false`) +mutual_chap | Optional | boolean | CHAP for discovery session should be unidirectional (`false`) or bidirectional (`true`) (default: `false`) +chap_group | Optional | number | CHAP group ID for discovery session (default: 0) + +Parameters `disable_chap` and `require_chap` are mutually exclusive. + +### Example + +Example request: + +~~~ +request: +{ + "params": { + "tag": 1, + "chap_group": 1, + "require_chap": true, + "mutual_chap": true + }, + "jsonrpc": "2.0", + "method": "iscsi_portal_group_set_auth", + "id": 1 +} +~~~ + +Example response: + +~~~ +{ + "jsonrpc": "2.0", + "id": 1, + "result": true +} +~~~ + ## iscsi_get_connections method {#rpc_iscsi_get_connections} Show information about all active connections. diff --git a/lib/iscsi/iscsi_rpc.c b/lib/iscsi/iscsi_rpc.c index 51f29d6351..e2d0d22566 100644 --- a/lib/iscsi/iscsi_rpc.c +++ b/lib/iscsi/iscsi_rpc.c @@ -897,6 +897,70 @@ invalid: SPDK_RPC_REGISTER("iscsi_delete_portal_group", spdk_rpc_iscsi_delete_portal_group, SPDK_RPC_RUNTIME) SPDK_RPC_REGISTER_ALIAS_DEPRECATED(iscsi_delete_portal_group, delete_portal_group) +struct rpc_portal_group_auth { + int32_t tag; + bool disable_chap; + bool require_chap; + bool mutual_chap; + int32_t chap_group; +}; + +static const struct spdk_json_object_decoder rpc_portal_group_auth_decoders[] = { + {"tag", offsetof(struct rpc_portal_group_auth, tag), spdk_json_decode_int32}, + {"disable_chap", offsetof(struct rpc_portal_group_auth, disable_chap), spdk_json_decode_bool, true}, + {"require_chap", offsetof(struct rpc_portal_group_auth, require_chap), spdk_json_decode_bool, true}, + {"mutual_chap", offsetof(struct rpc_portal_group_auth, mutual_chap), spdk_json_decode_bool, true}, + {"chap_group", offsetof(struct rpc_portal_group_auth, chap_group), spdk_json_decode_int32, true}, +}; + +static void +spdk_rpc_iscsi_portal_group_set_auth(struct spdk_jsonrpc_request *request, + const struct spdk_json_val *params) +{ + struct rpc_portal_group_auth req = {}; + struct spdk_json_write_ctx *w; + struct spdk_iscsi_portal_grp *pg; + int rc; + + if (spdk_json_decode_object(params, rpc_portal_group_auth_decoders, + SPDK_COUNTOF(rpc_portal_group_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; + } + + pthread_mutex_lock(&g_spdk_iscsi.mutex); + + pg = spdk_iscsi_portal_grp_find_by_tag(req.tag); + if (pg == NULL) { + spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, + "Could not find portal group %d", req.tag); + goto exit; + } + + rc = spdk_iscsi_portal_grp_set_chap_params(pg, 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 auth params"); + goto exit; + } + + pthread_mutex_unlock(&g_spdk_iscsi.mutex); + + w = spdk_jsonrpc_begin_result(request); + spdk_json_write_bool(w, true); + spdk_jsonrpc_end_result(request, w); + + return; + +exit: + pthread_mutex_unlock(&g_spdk_iscsi.mutex); +} +SPDK_RPC_REGISTER("iscsi_portal_group_set_auth", spdk_rpc_iscsi_portal_group_set_auth, + SPDK_RPC_RUNTIME) + struct rpc_iscsi_get_connections_ctx { struct spdk_jsonrpc_request *request; struct spdk_json_write_ctx *w; diff --git a/lib/iscsi/portal_grp.c b/lib/iscsi/portal_grp.c index 31bbddc41d..19432da2b6 100644 --- a/lib/iscsi/portal_grp.c +++ b/lib/iscsi/portal_grp.c @@ -44,6 +44,7 @@ #include "iscsi/iscsi.h" #include "iscsi/conn.h" #include "iscsi/portal_grp.h" +#include "iscsi/tgt_node.h" #define PORTNUMSTRLEN 32 #define ACCEPT_TIMEOUT_US 1000 /* 1ms */ @@ -423,6 +424,24 @@ spdk_iscsi_portal_grp_add_portal(struct spdk_iscsi_portal_grp *pg, TAILQ_INSERT_TAIL(&pg->head, p, per_pg_tailq); } +int +spdk_iscsi_portal_grp_set_chap_params(struct spdk_iscsi_portal_grp *pg, + 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; + } + + pg->disable_chap = disable_chap; + pg->require_chap = require_chap; + pg->mutual_chap = mutual_chap; + pg->chap_group = chap_group; + + return 0; +} + static int iscsi_parse_portal_grp(struct spdk_conf_section *sp) { diff --git a/lib/iscsi/portal_grp.h b/lib/iscsi/portal_grp.h index 726277ea59..fe32421259 100644 --- a/lib/iscsi/portal_grp.h +++ b/lib/iscsi/portal_grp.h @@ -79,6 +79,9 @@ int spdk_iscsi_portal_grp_register(struct spdk_iscsi_portal_grp *pg); struct spdk_iscsi_portal_grp *spdk_iscsi_portal_grp_unregister(int tag); struct spdk_iscsi_portal_grp *spdk_iscsi_portal_grp_find_by_tag(int tag); int spdk_iscsi_portal_grp_open(struct spdk_iscsi_portal_grp *pg); +int spdk_iscsi_portal_grp_set_chap_params(struct spdk_iscsi_portal_grp *pg, + bool disable_chap, bool require_chap, + bool mutual_chap, int32_t chap_group); void spdk_iscsi_portal_grp_close_all(void); void spdk_iscsi_portal_grps_config_text(FILE *fp); diff --git a/scripts/rpc.py b/scripts/rpc.py index 868af3f645..dc5752754b 100755 --- a/scripts/rpc.py +++ b/scripts/rpc.py @@ -1101,6 +1101,28 @@ Format: 'user:u1 secret:s1 muser:mu1 msecret:ms1,user:u2 secret:s2 muser:mu2 mse 'tag', help='Initiator group tag (unique, integer > 0)', type=int) p.set_defaults(func=iscsi_delete_initiator_group) + def iscsi_portal_group_set_auth(args): + rpc.iscsi.iscsi_portal_group_set_auth( + args.client, + tag=args.tag, + chap_group=args.chap_group, + disable_chap=args.disable_chap, + require_chap=args.require_chap, + mutual_chap=args.mutual_chap) + + p = subparsers.add_parser('iscsi_portal_group_set_auth', + help='Set CHAP authentication for discovery sessions specific for the portal group') + p.add_argument('tag', help='Portal group tag (unique, integer > 0)', type=int) + p.add_argument('-g', '--chap-group', help="""Authentication group ID for this portal group. + *** Authentication group must be precreated ***""", type=int, default=0) + p.add_argument('-d', '--disable-chap', help="""CHAP authentication should be disabled for this portal group. + *** Mutually exclusive with --require-chap ***""", action='store_true') + p.add_argument('-r', '--require-chap', help="""CHAP authentication should be required for this portal group. + *** 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=iscsi_portal_group_set_auth) + def iscsi_get_connections(args): print_dict(rpc.iscsi.iscsi_get_connections(args.client)) diff --git a/scripts/rpc/iscsi.py b/scripts/rpc/iscsi.py index 9d129db940..e4779e1a06 100644 --- a/scripts/rpc/iscsi.py +++ b/scripts/rpc/iscsi.py @@ -493,6 +493,40 @@ def iscsi_delete_initiator_group(client, tag): return client.call('iscsi_delete_initiator_group', params) +def iscsi_portal_group_set_auth( + client, + tag, + chap_group=None, + disable_chap=None, + require_chap=None, + mutual_chap=None): + """Set CHAP authentication for discovery sessions specific for the portal group. + + Args: + tag: Portal group tag (unique, integer > 0) + chap_group: Authentication group ID for this portal group + disable_chap: CHAP authentication should be disabled for this portal group + require_chap: CHAP authentication should be required for this portal group + mutual_chap: CHAP authentication should be mutual/bidirectional + + Returns: + True or False + """ + params = { + 'tag': tag, + } + + 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('iscsi_portal_group_set_auth', params) + + @deprecated_alias('get_iscsi_connections') def iscsi_get_connections(client): """Display iSCSI connections.