Although the XML for CHAP authentication with plain "password"
was introduced long ago, the function was never implemented. This
patch replaces the login/password mechanism by following the
'ceph' (or RBD) model of using a 'username' with a 'secret' which
has the authentication information.
This patch performs the authentication during startPool() processing
of pools with an authType of VIR_STORAGE_POOL_AUTH_CHAP specified
for iSCSI pools.
There are two types of CHAP configurations supported for iSCSI
authentication:
* Initiator Authentication
Forward, one-way; The initiator is authenticated by the target.
* Target Authentication
Reverse, Bi-directional, mutual, two-way; The target is authenticated
by the initiator; This method also requires Initiator Authentication
This only supports the "Initiator Authentication". (I don't have any
enterprise iSCSI env for testing, only have a iSCSI target setup with
tgtd, which doesn't support "Target Authentication").
"Discovery authentication" is not supported by tgt yet too. So this only
setup the session authentication by executing 3 iscsiadm commands, E.g:
% iscsiadm -m node --target "iqn.2013-05.test:iscsi.foo" --name \
"node.session.auth.authmethod" -v "CHAP" --op update
% iscsiadm -m node --target "iqn.2013-05.test:iscsi.foo" --name \
"node.session.auth.username" -v "Jim" --op update
% iscsiadm -m node --target "iqn.2013-05.test:iscsi.foo" --name \
"node.session.auth.password" -v "Jimsecret" --op update
---
src/storage/storage_backend_iscsi.c | 111 +++++++++++++++++++++++++++++++++++-
1 file changed, 110 insertions(+), 1 deletion(-)
diff --git a/src/storage/storage_backend_iscsi.c b/src/storage/storage_backend_iscsi.c
index 54bcd14..388d6ed 100644
--- a/src/storage/storage_backend_iscsi.c
+++ b/src/storage/storage_backend_iscsi.c
@@ -32,6 +32,8 @@
#include <unistd.h>
#include <sys/stat.h>
+#include "datatypes.h"
+#include "driver.h"
#include "virerror.h"
#include "storage_backend_scsi.h"
#include "storage_backend_iscsi.h"
@@ -39,6 +41,7 @@
#include "virlog.h"
#include "virfile.h"
#include "vircommand.h"
+#include "virobject.h"
#include "virrandom.h"
#include "virstring.h"
@@ -658,9 +661,112 @@ virStorageBackendISCSICheckPool(virConnectPtr conn
ATTRIBUTE_UNUSED,
return ret;
}
+static int
+virStorageBackendISCSINodeUpdate(const char *portal,
+ const char *target,
+ const char *name,
+ const char *value)
+{
+ virCommandPtr cmd = NULL;
+ int status;
+ int ret = -1;
+
+ cmd = virCommandNewArgList(ISCSIADM,
+ "--mode", "node",
+ "--portal", portal,
+ "--target", target,
+ "--op", "update",
+ "--name", name,
+ "--value", value,
+ NULL);
+
+ if (virCommandRun(cmd, &status) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Failed to update '%s' of node mode for target
'%s'"),
+ name, target);
+ goto cleanup;
+ }
+
+ ret = 0;
+cleanup:
+ virCommandFree(cmd);
+ return ret;
+}
static int
-virStorageBackendISCSIStartPool(virConnectPtr conn ATTRIBUTE_UNUSED,
+virStorageBackendISCSISetAuth(const char *portal,
+ virConnectPtr conn,
+ virStoragePoolDefPtr def)
+{
+ virSecretPtr secret = NULL;
+ unsigned char *secret_value = NULL;
+ virStoragePoolAuthChap chap;
+ int ret = -1;
+
+ if (def->source.authType == VIR_STORAGE_POOL_AUTH_NONE)
+ return 0;
+
+ if (def->source.authType != VIR_STORAGE_POOL_AUTH_CHAP) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("iscsi pool only supports 'chap' auth
type"));
+ return -1;
+ }
+
+ if (!conn) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("iscsi 'chap' authentication requires
connection"));
+ return -1;
+ }
+
+ chap = def->source.auth.chap;
+ if (chap.secret.uuidUsable)
+ secret = virSecretLookupByUUID(conn, chap.secret.uuid);
+ else
+ secret = virSecretLookupByUsage(conn, VIR_SECRET_USAGE_TYPE_ISCSI,
+ chap.secret.usage);
+
+ if (secret) {
+ size_t secret_size;
+ secret_value =
+ conn->secretDriver->secretGetValue(secret, &secret_size, 0,
+ VIR_SECRET_GET_VALUE_INTERNAL_CALL);
+ if (!secret_value) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("could not get the value of the secret "
+ "for username %s"), chap.username);
+ goto cleanup;
+ }
+ } else {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("username '%s' specified but secret not
found"),
+ chap.username);
+ goto cleanup;
+ }
+
+ if (virStorageBackendISCSINodeUpdate(portal,
+ def->source.devices[0].path,
+ "node.session.auth.authmethod",
+ "CHAP") < 0 ||
+ virStorageBackendISCSINodeUpdate(portal,
+ def->source.devices[0].path,
+ "node.session.auth.username",
+ chap.username) < 0 ||
+ virStorageBackendISCSINodeUpdate(portal,
+ def->source.devices[0].path,
+ "node.session.auth.password",
+ (const char *)secret_value) < 0)
+ goto cleanup;
+
+ ret = 0;
+
+cleanup:
+ virObjectUnref(secret);
+ VIR_FREE(secret_value);
+ return ret;
+}
+
+static int
+virStorageBackendISCSIStartPool(virConnectPtr conn,
virStoragePoolObjPtr pool)
{
char *portal = NULL;
@@ -699,6 +805,9 @@ virStorageBackendISCSIStartPool(virConnectPtr conn ATTRIBUTE_UNUSED,
NULL, NULL) < 0)
goto cleanup;
+ if (virStorageBackendISCSISetAuth(portal, conn, pool->def) < 0)
+ goto cleanup;
+
if (virStorageBackendISCSIConnection(portal,
pool->def->source.initiator.iqn,
pool->def->source.devices[0].path,
--
1.8.1.4