Commit 844735c9 authored by Shuhei Matsumoto's avatar Shuhei Matsumoto Committed by Jim Harris
Browse files

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: default avatarShuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-on: https://review.gerrithub.io/420974


Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Chandler-Test-Pool: SPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
Reviewed-by: default avatarBen Walker <benjamin.walker@intel.com>
parent 6cd1714a
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -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:

+46 −0
Original line number Diff line number Diff line
@@ -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.
+69 −0
Original line number Diff line number Diff line
@@ -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)
+20 −0
Original line number Diff line number Diff line
@@ -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"
+3 −0
Original line number Diff line number Diff line
@@ -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);
Loading