From 61a4adc6d1c2caf08369ddb00f0f8fec9a1be6be Mon Sep 17 00:00:00 2001 From: Travis Glenn Hansen Date: Sat, 21 Nov 2020 17:15:22 -0700 Subject: [PATCH] support sudo setups, support apiKey with TrueNAS --- examples/freenas-iscsi.yaml | 7 +++ examples/freenas-nfs.yaml | 7 +++ examples/freenas-smb.yaml | 7 +++ examples/zfs-generic-iscsi.yaml | 1 + examples/zfs-generic-nfs.yaml | 1 + src/driver/controller-zfs-generic/index.js | 19 ++++--- src/driver/controller-zfs-ssh/index.js | 27 ++++++++++ src/driver/freenas/http/index.js | 62 ++++++++++++++-------- 8 files changed, 104 insertions(+), 27 deletions(-) diff --git a/examples/freenas-iscsi.yaml b/examples/freenas-iscsi.yaml index 33960bb..99a83fd 100644 --- a/examples/freenas-iscsi.yaml +++ b/examples/freenas-iscsi.yaml @@ -4,9 +4,15 @@ httpConnection: protocol: http host: server address port: 80 + # use only 1 of apiKey or username/password + # if both are present, apiKey is preferred + # apiKey is only available starting in TrueNAS-12 + #apiKey: username: root password: allowInsecure: true + # use apiVersion 2 for TrueNAS-12 and up (will work on 11.x in some scenarios as well) + #apiVersion: 2 sshConnection: host: server address port: 22 @@ -21,6 +27,7 @@ zfs: # can be used to override defaults if necessary # the example below is useful for TrueNAS 12 #cli: + # sudoEnabled: true # paths: # zfs: /usr/local/sbin/zfs # zpool: /usr/local/sbin/zpool diff --git a/examples/freenas-nfs.yaml b/examples/freenas-nfs.yaml index 6d915ab..141d305 100644 --- a/examples/freenas-nfs.yaml +++ b/examples/freenas-nfs.yaml @@ -4,9 +4,15 @@ httpConnection: protocol: http host: server address port: 80 + # use only 1 of apiKey or username/password + # if both are present, apiKey is preferred + # apiKey is only available starting in TrueNAS-12 + #apiKey: username: root password: allowInsecure: true + # use apiVersion 2 for TrueNAS-12 and up (will work on 11.x in some scenarios as well) + #apiVersion: 2 sshConnection: host: server address port: 22 @@ -21,6 +27,7 @@ zfs: # can be used to override defaults if necessary # the example below is useful for TrueNAS 12 #cli: + # sudoEnabled: true # paths: # zfs: /usr/local/sbin/zfs # zpool: /usr/local/sbin/zpool diff --git a/examples/freenas-smb.yaml b/examples/freenas-smb.yaml index 04a4be7..6704b11 100644 --- a/examples/freenas-smb.yaml +++ b/examples/freenas-smb.yaml @@ -4,9 +4,15 @@ httpConnection: protocol: http host: server address port: 80 + # use only 1 of apiKey or username/password + # if both are present, apiKey is preferred + # apiKey is only available starting in TrueNAS-12 + #apiKey: username: root password: allowInsecure: true + # use apiVersion 2 for TrueNAS-12 and up (will work on 11.x in some scenarios as well) + #apiVersion: 2 sshConnection: host: server address port: 22 @@ -21,6 +27,7 @@ zfs: # can be used to override defaults if necessary # the example below is useful for TrueNAS 12 #cli: + # sudoEnabled: true # paths: # zfs: /usr/local/sbin/zfs # zpool: /usr/local/sbin/zpool diff --git a/examples/zfs-generic-iscsi.yaml b/examples/zfs-generic-iscsi.yaml index eb65411..983d1d2 100644 --- a/examples/zfs-generic-iscsi.yaml +++ b/examples/zfs-generic-iscsi.yaml @@ -51,6 +51,7 @@ iscsi: # https://bugzilla.redhat.com/show_bug.cgi?id=1659195 # http://atodorov.org/blog/2015/04/07/how-to-configure-iscsi-target-on-red-hat-enterprise-linux-7/ shareStragetyTargetCli: + #sudoEnabled: true basename: "iqn.2003-01.org.linux-iscsi.ubuntu-19.x8664" tpg: attributes: diff --git a/examples/zfs-generic-nfs.yaml b/examples/zfs-generic-nfs.yaml index ed4f36b..ec660bc 100644 --- a/examples/zfs-generic-nfs.yaml +++ b/examples/zfs-generic-nfs.yaml @@ -17,6 +17,7 @@ zfs: # can be used to override defaults if necessary # the example below is useful for TrueNAS 12 #cli: + # sudoEnabled: true # paths: # zfs: /usr/local/sbin/zfs # zpool: /usr/local/sbin/zpool diff --git a/src/driver/controller-zfs-generic/index.js b/src/driver/controller-zfs-generic/index.js index eb1dc6d..d91bb23 100644 --- a/src/driver/controller-zfs-generic/index.js +++ b/src/driver/controller-zfs-generic/index.js @@ -260,14 +260,21 @@ delete ${iscsiName} const sshClient = this.getSshClient(); data = data.trim(); + let command = "sh"; let args = ["-c"]; - let command = []; - command.push(`echo "${data}"`.trim()); - command.push("|"); - command.push("targetcli"); + let taregetCliCommand = []; + taregetCliCommand.push(`echo "${data}"`.trim()); + taregetCliCommand.push("|"); + taregetCliCommand.push("targetcli"); - args.push("'" + command.join(" ") + "'"); - return sshClient.exec(sshClient.buildCommand("sh", args)); + if (this.options.iscsi.shareStragetyTargetCli.sudoEnabled) { + command = "sudo"; + args.unshift("sh"); + } + + args.push("'" + taregetCliCommand.join(" ") + "'"); + + return sshClient.exec(sshClient.buildCommand(command, args)); } } diff --git a/src/driver/controller-zfs-ssh/index.js b/src/driver/controller-zfs-ssh/index.js index 67c1eb1..d0fe409 100644 --- a/src/driver/controller-zfs-ssh/index.js +++ b/src/driver/controller-zfs-ssh/index.js @@ -135,9 +135,24 @@ class ControllerZfsSshBaseDriver extends CsiBaseDriver { options.paths = this.options.zfs.cli.paths; } + if ( + this.options.zfs.hasOwnProperty("cli") && + this.options.zfs.cli.hasOwnProperty("sudoEnabled") + ) { + options.sudo = this.getSudoEnabled(); + } + return new Zetabyte(options); } + getSudoEnabled() { + return this.options.zfs.cli.sudoEnabled === true; + } + + getSudoPath() { + return this.options.zfs.cli.paths.sudo || "/usr/bin/sudo"; + } + getDatasetParentName() { let datasetParentName = this.options.zfs.datasetParentName; datasetParentName = datasetParentName.replace(/\/$/, ""); @@ -671,6 +686,10 @@ class ControllerZfsSshBaseDriver extends CsiBaseDriver { this.options.zfs.datasetPermissionsMode, properties.mountpoint.value, ]); + if (this.getSudoEnabled()) { + command = this.getSudoPath() + " " + command; + } + driver.ctx.logger.verbose("set permission command: %s", command); response = await sshClient.exec(command); } @@ -690,6 +709,10 @@ class ControllerZfsSshBaseDriver extends CsiBaseDriver { : ""), properties.mountpoint.value, ]); + if (this.getSudoEnabled()) { + command = this.getSudoPath() + " " + command; + } + driver.ctx.logger.verbose("set ownership command: %s", command); response = await sshClient.exec(command); } @@ -703,6 +726,10 @@ class ControllerZfsSshBaseDriver extends CsiBaseDriver { acl, properties.mountpoint.value, ]); + if (this.getSudoEnabled()) { + command = this.getSudoPath() + " " + command; + } + driver.ctx.logger.verbose("set acl command: %s", command); response = await sshClient.exec(command); } diff --git a/src/driver/freenas/http/index.js b/src/driver/freenas/http/index.js index 62c0685..6823c4e 100644 --- a/src/driver/freenas/http/index.js +++ b/src/driver/freenas/http/index.js @@ -19,7 +19,7 @@ class Client { host: server.host, port: server.port, //userinfo: server.username + ":" + server.password, - path: server.apiVersion == 1 ? "/api/v1.0" : "/api/v2.0" + path: server.apiVersion == 1 ? "/api/v1.0" : "/api/v2.0", }; return URI.serialize(options); } @@ -55,22 +55,27 @@ class Client { headers: { Accept: "application/json", "User-Agent": USER_AGENT, - "Content-Type": "application/json" + "Content-Type": "application/json", }, json: true, qs: data, agentOptions: { - rejectUnauthorized: !!!client.options.allowInsecure - } + rejectUnauthorized: !!!client.options.allowInsecure, + }, }; - request(options, function(err, res, body) { + request(options, function (err, res, body) { client.log_repsonse(...arguments, options); if (err) { reject(err); } resolve(res); - }).auth(client.options.username, client.options.password); + }).auth( + client.options.username, + client.options.password, + true, + client.options.apiKey + ); }); } @@ -87,22 +92,27 @@ class Client { headers: { Accept: "application/json", "User-Agent": USER_AGENT, - "Content-Type": "application/json" + "Content-Type": "application/json", }, json: true, body: data, agentOptions: { - rejectUnauthorized: !!!client.options.allowInsecure - } + rejectUnauthorized: !!!client.options.allowInsecure, + }, }; - request(options, function(err, res, body) { + request(options, function (err, res, body) { client.log_repsonse(...arguments, options); if (err) { reject(err); } resolve(res); - }).auth(client.options.username, client.options.password); + }).auth( + client.options.username, + client.options.password, + true, + client.options.apiKey + ); }); } @@ -119,22 +129,27 @@ class Client { headers: { Accept: "application/json", "User-Agent": USER_AGENT, - "Content-Type": "application/json" + "Content-Type": "application/json", }, json: true, body: data, agentOptions: { - rejectUnauthorized: !!!client.options.allowInsecure - } + rejectUnauthorized: !!!client.options.allowInsecure, + }, }; - request(options, function(err, res, body) { + request(options, function (err, res, body) { client.log_repsonse(...arguments, options); if (err) { reject(err); } resolve(res); - }).auth(client.options.username, client.options.password); + }).auth( + client.options.username, + client.options.password, + true, + client.options.apiKey + ); }); } @@ -151,22 +166,27 @@ class Client { headers: { Accept: "application/json", "User-Agent": USER_AGENT, - "Content-Type": "application/json" + "Content-Type": "application/json", }, json: true, body: data, agentOptions: { - rejectUnauthorized: !!!client.options.allowInsecure - } + rejectUnauthorized: !!!client.options.allowInsecure, + }, }; - request(options, function(err, res, body) { + request(options, function (err, res, body) { client.log_repsonse(...arguments, options); if (err) { reject(err); } resolve(res); - }).auth(client.options.username, client.options.password); + }).auth( + client.options.username, + client.options.password, + true, + client.options.apiKey + ); }); } }