]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/tools/rbd_nbd/rbd-nbd.cc
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / tools / rbd_nbd / rbd-nbd.cc
index 55ef9d1595d299105b799ec2070912e4e012ddd0..3130e8bc750e28cf9147b0eedda132d66cac6e99 100644 (file)
@@ -119,8 +119,8 @@ struct Config {
   std::string format;
   bool pretty_format = false;
 
-  std::optional<librbd::encryption_format_t> encryption_format;
-  std::optional<std::string> encryption_passphrase_file;
+  std::vector<librbd::encryption_format_t> encryption_formats;
+  std::vector<std::string> encryption_passphrase_files;
 
   Command command = None;
   int pid = 0;
@@ -152,8 +152,8 @@ static void usage()
             << "               [options] list-mapped                 List mapped nbd devices\n"
             << "Map and attach options:\n"
             << "  --device <device path>        Specify nbd device path (/dev/nbd{num})\n"
-            << "  --encryption-format           Image encryption format\n"
-            << "                                (possible values: luks1, luks2)\n"
+            << "  --encryption-format luks|luks1|luks2\n"
+            << "                                Image encryption format (default: luks)\n"
             << "  --encryption-passphrase-file  Path of file containing passphrase for unlocking image encryption\n"
             << "  --exclusive                   Forbid writes by other clients\n"
             << "  --notrim                      Turn off trim/discard\n"
@@ -943,6 +943,43 @@ private:
   }
 };
 
+struct EncryptionOptions {
+  std::vector<librbd::encryption_spec_t> specs;
+
+  ~EncryptionOptions() {
+    for (auto& spec : specs) {
+      switch (spec.format) {
+      case RBD_ENCRYPTION_FORMAT_LUKS: {
+        auto opts =
+            static_cast<librbd::encryption_luks_format_options_t*>(spec.opts);
+        ceph_memzero_s(opts->passphrase.data(), opts->passphrase.size(),
+                       opts->passphrase.size());
+        delete opts;
+        break;
+      }
+      case RBD_ENCRYPTION_FORMAT_LUKS1: {
+        auto opts =
+            static_cast<librbd::encryption_luks1_format_options_t*>(spec.opts);
+        ceph_memzero_s(opts->passphrase.data(), opts->passphrase.size(),
+                       opts->passphrase.size());
+        delete opts;
+        break;
+      }
+      case RBD_ENCRYPTION_FORMAT_LUKS2: {
+        auto opts =
+            static_cast<librbd::encryption_luks2_format_options_t*>(spec.opts);
+        ceph_memzero_s(opts->passphrase.data(), opts->passphrase.size(),
+                       opts->passphrase.size());
+        delete opts;
+        break;
+      }
+      default:
+        ceph_abort();
+      }
+    }
+  }
+};
+
 static std::string get_cookie(const std::string &devpath)
 {
   std::string cookie;
@@ -1678,55 +1715,62 @@ static int do_map(int argc, const char *argv[], Config *cfg, bool reconnect)
     }
   }
 
-  if (cfg->encryption_format.has_value()) {
-    if (!cfg->encryption_passphrase_file.has_value()) {
-      r = -EINVAL;
-      cerr << "rbd-nbd: missing encryption-passphrase-file" << std::endl;
-      goto close_fd;
-    }
-    std::ifstream file(cfg->encryption_passphrase_file.value().c_str());
-    if (file.fail()) {
-      r = -errno;
-      std::cerr << "rbd-nbd: unable to open passphrase file:"
-                << cpp_strerror(errno) << std::endl;
-      goto close_fd;
-    }
-    std::string passphrase((std::istreambuf_iterator<char>(file)),
-                           (std::istreambuf_iterator<char>()));
-    auto sg = make_scope_guard([&] {
-      ceph_memzero_s(&passphrase[0], passphrase.size(), passphrase.size()); });
-    file.close();
-    if (!passphrase.empty() && passphrase[passphrase.length() - 1] == '\n') {
-      passphrase.erase(passphrase.length() - 1);
-    }
+  if (!cfg->encryption_formats.empty()) {
+    EncryptionOptions encryption_options;
+    encryption_options.specs.reserve(cfg->encryption_formats.size());
 
-    switch (cfg->encryption_format.value()) {
+    for (size_t i = 0; i < cfg->encryption_formats.size(); ++i) {
+      std::ifstream file(cfg->encryption_passphrase_files[i],
+                         std::ios::in | std::ios::binary);
+      if (file.fail()) {
+        r = -errno;
+        std::cerr << "rbd-nbd: unable to open passphrase file '"
+                  << cfg->encryption_passphrase_files[i] << "': "
+                  << cpp_strerror(r) << std::endl;
+        goto close_fd;
+      }
+      std::string passphrase((std::istreambuf_iterator<char>(file)),
+                             std::istreambuf_iterator<char>());
+      file.close();
+
+      switch (cfg->encryption_formats[i]) {
+      case RBD_ENCRYPTION_FORMAT_LUKS: {
+        auto opts = new librbd::encryption_luks_format_options_t{
+            std::move(passphrase)};
+        encryption_options.specs.push_back(
+            {RBD_ENCRYPTION_FORMAT_LUKS, opts, sizeof(*opts)});
+        break;
+      }
       case RBD_ENCRYPTION_FORMAT_LUKS1: {
-        librbd::encryption_luks1_format_options_t opts = {};
-        opts.passphrase = passphrase;
-        r = image.encryption_load(
-                RBD_ENCRYPTION_FORMAT_LUKS1, &opts, sizeof(opts));
+        auto opts = new librbd::encryption_luks1_format_options_t{
+            .passphrase = std::move(passphrase)};
+        encryption_options.specs.push_back(
+            {RBD_ENCRYPTION_FORMAT_LUKS1, opts, sizeof(*opts)});
         break;
       }
       case RBD_ENCRYPTION_FORMAT_LUKS2: {
-        librbd::encryption_luks2_format_options_t opts = {};
-        opts.passphrase = passphrase;
-        r = image.encryption_load(
-                RBD_ENCRYPTION_FORMAT_LUKS2, &opts, sizeof(opts));
-        blksize = 4096;
+        auto opts = new librbd::encryption_luks2_format_options_t{
+            .passphrase = std::move(passphrase)};
+        encryption_options.specs.push_back(
+            {RBD_ENCRYPTION_FORMAT_LUKS2, opts, sizeof(*opts)});
         break;
       }
       default:
-        r = -ENOTSUP;
-        cerr << "rbd-nbd: unsupported encryption format" << std::endl;
-        goto close_fd;
+        ceph_abort();
+      }
     }
 
+    r = image.encryption_load2(encryption_options.specs.data(),
+                               encryption_options.specs.size());
     if (r != 0) {
       cerr << "rbd-nbd: failed to load encryption: " << cpp_strerror(r)
            << std::endl;
       goto close_fd;
     }
+
+    // luks2 block size can vary upto 4096, while luks1 always uses 512
+    // currently we don't have an rbd API for querying the loaded encryption
+    blksize = 4096;
   }
 
   r = image.stat(info, sizeof(info));
@@ -2132,11 +2176,11 @@ static int parse_args(vector<const char*>& args, std::ostream *err_msg,
     } else if (ceph_argparse_witharg(args, i, &arg_value,
                                      "--encryption-format", (char *)NULL)) {
       if (arg_value == "luks1") {
-        cfg->encryption_format =
-                std::make_optional(RBD_ENCRYPTION_FORMAT_LUKS1);
+        cfg->encryption_formats.push_back(RBD_ENCRYPTION_FORMAT_LUKS1);
       } else if (arg_value == "luks2") {
-        cfg->encryption_format =
-                std::make_optional(RBD_ENCRYPTION_FORMAT_LUKS2);
+        cfg->encryption_formats.push_back(RBD_ENCRYPTION_FORMAT_LUKS2);
+      } else if (arg_value == "luks") {
+        cfg->encryption_formats.push_back(RBD_ENCRYPTION_FORMAT_LUKS);
       } else {
         *err_msg << "rbd-nbd: Invalid encryption format";
         return -EINVAL;
@@ -2144,12 +2188,24 @@ static int parse_args(vector<const char*>& args, std::ostream *err_msg,
     } else if (ceph_argparse_witharg(args, i, &arg_value,
                                      "--encryption-passphrase-file",
                                      (char *)NULL)) {
-      cfg->encryption_passphrase_file = std::make_optional(arg_value);
+      cfg->encryption_passphrase_files.push_back(arg_value);
     } else {
       ++i;
     }
   }
 
+  if (cfg->encryption_formats.empty() &&
+      !cfg->encryption_passphrase_files.empty()) {
+    cfg->encryption_formats.resize(cfg->encryption_passphrase_files.size(),
+                                   RBD_ENCRYPTION_FORMAT_LUKS);
+  }
+
+  if (cfg->encryption_formats.size() != cfg->encryption_passphrase_files.size()) {
+    *err_msg << "rbd-nbd: Encryption formats count does not match "
+             << "passphrase files count";
+    return -EINVAL;
+  }
+
   Command cmd = None;
   if (args.begin() != args.end()) {
     if (strcmp(*args.begin(), "map") == 0) {