]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rbd, rbd-nbd: accept "luks", "luks1" and "luks2" formats
authorIlya Dryomov <idryomov@gmail.com>
Sat, 19 Nov 2022 12:30:55 +0000 (13:30 +0100)
committerIlya Dryomov <idryomov@gmail.com>
Sun, 4 Dec 2022 17:19:19 +0000 (18:19 +0100)
Since RBD_ENCRYPTION_FORMAT_LUKS1, RBD_ENCRYPTION_FORMAT_LUKS2
and RBD_ENCRYPTION_FORMAT_LUKS aren't treated the same when loading
encryption anymore, "luks1" and "luks2" formats need to be accepted
in addition to "luks" format.

Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
doc/man/8/rbd-nbd.rst
qa/workunits/rbd/luks-encryption.sh
src/test/cli/rbd/help.t
src/tools/rbd/ArgumentTypes.cc
src/tools/rbd/Utils.cc
src/tools/rbd/Utils.h
src/tools/rbd_nbd/rbd-nbd.cc

index a7bf15332e5ab8f5c0380d74c154a76839d068a1..5ec7ce40f440840e311dfea79c252cd4b227dd6c 100644 (file)
@@ -54,7 +54,7 @@ Options
 .. option:: --encryption-format
 
    Image encryption format.
-   Possible values: *luks*
+   Possible values: *luks*, *luks1*, *luks2*
 
 .. option:: --encryption-passphrase-file
 
index 52105a6cc367cea56b0308bde91de461f6cc4a86..91e8758e26725595eda68b9d59940d943ca6d18c 100755 (executable)
@@ -94,7 +94,8 @@ function test_clone_encryption() {
   sudo rbd device unmap -t nbd $LIBRBD_DEV
 
   # flatten
-  rbd flatten testimg2 --encryption-format luks --encryption-format luks --encryption-passphrase-file /tmp/passphrase2 --encryption-passphrase-file /tmp/passphrase
+  expect_false rbd flatten testimg2 --encryption-format luks1 --encryption-format luks2 --encryption-passphrase-file /tmp/passphrase2 --encryption-passphrase-file /tmp/passphrase
+  rbd flatten testimg2 --encryption-format luks2 --encryption-format luks1 --encryption-passphrase-file /tmp/passphrase2 --encryption-passphrase-file /tmp/passphrase
 
   # verify with cryptsetup
   RAW_FLAT_DEV=$(_sudo rbd -p rbd map testimg2 -t nbd)
index 5c2a38031a5fb3093e45319b0d4dc1e4e560ade8..c70d76f4cd7091fc15a9f0af18f4e4fe616b9737 100644 (file)
     --namespace arg                  namespace name
     --image arg                      image name
     --no-progress                    disable progress output
-    --encryption-format arg          encryption formats [possible values: luks]
+    --encryption-format arg          encryption format (luks, luks1, luks2)
     --encryption-passphrase-file arg path to file containing passphrase for
                                      unlocking the image
   
     -s [ --size ] arg                image size (in M/G/T) [default: M]
     --allow-shrink                   permit shrinking
     --no-progress                    disable progress output
-    --encryption-format arg          encryption formats [possible values: luks]
+    --encryption-format arg          encryption format (luks, luks1, luks2)
     --encryption-passphrase-file arg path to file containing passphrase for
                                      unlocking the image
   
index 5d75d02abb34e41599f5193189b457c7b6bdc938..231264e57b2df5f89f8f5a0e3b41c14da4569409 100644 (file)
@@ -331,9 +331,9 @@ void add_snap_create_options(po::options_description *opt) {
 
 void add_encryption_options(boost::program_options::options_description *opt) {
   opt->add_options()
-  (ENCRYPTION_FORMAT.c_str(),
-   po::value<std::vector<EncryptionFormat>>(),
-   "encryption formats [possible values: luks]");
+    (ENCRYPTION_FORMAT.c_str(),
+     po::value<std::vector<EncryptionFormat>>(),
+     "encryption format (luks, luks1, luks2)");
 
   opt->add_options()
     (ENCRYPTION_PASSPHRASE_FILE.c_str(),
@@ -538,14 +538,15 @@ void validate(boost::any& v, const std::vector<std::string>& values,
               EncryptionFormat *target_type, int) {
   po::validators::check_first_occurrence(v);
   const std::string &s = po::validators::get_single_string(values);
-  EncryptionFormat format;
   if (s == "luks") {
-    format.format = RBD_ENCRYPTION_FORMAT_LUKS;
+    v = boost::any(EncryptionFormat{RBD_ENCRYPTION_FORMAT_LUKS});
+  } else if (s == "luks1") {
+    v = boost::any(EncryptionFormat{RBD_ENCRYPTION_FORMAT_LUKS1});
+  } else if (s == "luks2") {
+    v = boost::any(EncryptionFormat{RBD_ENCRYPTION_FORMAT_LUKS2});
   } else {
     throw po::validation_error(po::validation_error::invalid_option_value);
   }
-
-  v = boost::any(format);
 }
 
 void validate(boost::any& v, const std::vector<std::string>& values,
index e3a1f6c8cedb523932f6a0331b8a542d046f470c..47203dcba1cc061ec1174f5fc5bbff09fa70f57e 100644 (file)
@@ -721,20 +721,16 @@ int get_snap_create_flags(const po::variables_map &vm, uint32_t *flags) {
 }
 
 int get_encryption_options(const boost::program_options::variables_map &vm,
-                           EncryptionOptions* opts) {
+                           EncryptionOptions* result) {
   std::vector<std::string> passphrase_files;
   if (vm.count(at::ENCRYPTION_PASSPHRASE_FILE)) {
     passphrase_files =
             vm[at::ENCRYPTION_PASSPHRASE_FILE].as<std::vector<std::string>>();
   }
 
-  std::vector<librbd::encryption_format_t> formats;
+  std::vector<at::EncryptionFormat> formats;
   if (vm.count(at::ENCRYPTION_FORMAT)) {
-    auto& format_structs =
-            vm[at::ENCRYPTION_FORMAT].as<std::vector<at::EncryptionFormat>>();
-    for (auto& format_struct : format_structs) {
-      formats.push_back((librbd::encryption_format_t)format_struct.format);
-    }
+    formats = vm[at::ENCRYPTION_FORMAT].as<decltype(formats)>();
   }
 
   if (formats.size() != passphrase_files.size()) {
@@ -743,45 +739,45 @@ int get_encryption_options(const boost::program_options::variables_map &vm,
     return -EINVAL;
   }
 
-  auto spec_count = formats.size();
-  if (spec_count == 0) {
-    return 0;
-  }
-
-  opts->luks_opts.reserve(spec_count);
-
-  auto& specs = opts->specs;
-  specs.resize(spec_count);
-  for (size_t i = 0; i < spec_count; ++i) {
+  result->specs.clear();
+  result->specs.reserve(formats.size());
+  for (size_t i = 0; i < formats.size(); ++i) {
     std::ifstream file(passphrase_files[i], std::ios::in | std::ios::binary);
-    auto sg = make_scope_guard([&] { file.close(); });
-
-    specs[i].format = formats[i];
-    std::string* passphrase;
-    switch (specs[i].format) {
-      case RBD_ENCRYPTION_FORMAT_LUKS: {
-        auto& luks_opts = opts->luks_opts;
-        luks_opts.emplace_back();
-        specs[i].opts = &luks_opts.back();
-        specs[i].opts_size = sizeof(luks_opts.back());
-        passphrase = &luks_opts.back().passphrase;
-        break;
-      }
-      default:
-        std::cerr << "rbd: unsupported encryption format: " << specs[i].format
-                  << std::endl;
-        return -ENOTSUP;
-    }
-
-    passphrase->assign((std::istreambuf_iterator<char>(file)),
-                       (std::istreambuf_iterator<char>()));
-
     if (file.fail()) {
       std::cerr << "rbd: unable to open passphrase file '"
                 << passphrase_files[i] << "': " << cpp_strerror(errno)
                 << std::endl;
       return -errno;
     }
+    std::string passphrase((std::istreambuf_iterator<char>(file)),
+                           std::istreambuf_iterator<char>());
+    file.close();
+
+    switch (formats[i].format) {
+    case RBD_ENCRYPTION_FORMAT_LUKS: {
+      auto opts = new librbd::encryption_luks_format_options_t{
+          std::move(passphrase)};
+      result->specs.push_back(
+          {RBD_ENCRYPTION_FORMAT_LUKS, opts, sizeof(*opts)});
+      break;
+    }
+    case RBD_ENCRYPTION_FORMAT_LUKS1: {
+      auto opts = new librbd::encryption_luks1_format_options_t{
+          .passphrase = std::move(passphrase)};
+      result->specs.push_back(
+          {RBD_ENCRYPTION_FORMAT_LUKS1, opts, sizeof(*opts)});
+      break;
+    }
+    case RBD_ENCRYPTION_FORMAT_LUKS2: {
+      auto opts = new librbd::encryption_luks2_format_options_t{
+          .passphrase = std::move(passphrase)};
+      result->specs.push_back(
+          {RBD_ENCRYPTION_FORMAT_LUKS2, opts, sizeof(*opts)});
+      break;
+    }
+    default:
+      ceph_abort();
+    }
   }
 
   return 0;
index 5bfdeae06592d53dc6cff771a8b8f487de85559b..5076fd7fe9ce54f5b215bc93b09ae41a57d2f75c 100644 (file)
@@ -86,15 +86,40 @@ struct ProgressContext : public librbd::ProgressContext {
 int get_percentage(uint64_t part, uint64_t whole);
 
 struct EncryptionOptions {
-    std::vector<librbd::encryption_spec_t> specs;
-    std::vector<librbd::encryption_luks_format_options_t> luks_opts;
-
-    ~EncryptionOptions() {
-      for (auto& opts : luks_opts) {
-        auto& passphrase = opts.passphrase;
-        ceph_memzero_s(&passphrase[0], passphrase.size(), passphrase.size());
+  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();
       }
     }
+  }
 };
 
 template <typename T, void(T::*MF)(int)>
@@ -176,7 +201,7 @@ int get_snap_create_flags(const boost::program_options::variables_map &vm,
                           uint32_t *flags);
 
 int get_encryption_options(const boost::program_options::variables_map &vm,
-                           EncryptionOptions* opts);
+                           EncryptionOptions* result);
 
 void init_context();
 
index b5af8b5fd119f945948294373fa63e96dca34f4a..cc42491ca081d8c3a6802703981a09262a1b35ae 100644 (file)
@@ -119,8 +119,8 @@ struct Config {
   std::string format;
   bool pretty_format = false;
 
-  std::vector<librbd::encryption_format_t> encryption_format;
-  std::vector<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: luks)\n"
+            << "  --encryption-format luks|luks1|luks2\n"
+            << "                                Image encryption format\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;
@@ -1588,7 +1625,6 @@ static int do_map(int argc, const char *argv[], Config *cfg, bool reconnect)
   unsigned long size;
   unsigned long blksize = RBD_NBD_BLKSIZE;
   bool use_netlink;
-  auto encryption_format_count = cfg->encryption_format.size();
 
   int fd[2];
 
@@ -1679,55 +1715,53 @@ static int do_map(int argc, const char *argv[], Config *cfg, bool reconnect)
     }
   }
 
-  if (encryption_format_count > 0) {
-    std::vector<librbd::encryption_spec_t> specs(encryption_format_count);
-    std::vector<librbd::encryption_luks_format_options_t> luks_opts;
-
-    luks_opts.reserve(encryption_format_count);
+  if (!cfg->encryption_formats.empty()) {
+    EncryptionOptions encryption_options;
+    encryption_options.specs.reserve(cfg->encryption_formats.size());
 
-    auto sg = make_scope_guard([&] {
-      for (auto& opts : luks_opts) {
-        auto& passphrase = opts.passphrase;
-        ceph_memzero_s(&passphrase[0], passphrase.size(), passphrase.size());
-      }
-    });
-
-    for (size_t i = 0; i < encryption_format_count; ++i) {
-      std::ifstream file(cfg->encryption_passphrase_file[i],
+    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);
-      auto sg2 = make_scope_guard([&] { file.close(); });
-
-      specs[i].format = cfg->encryption_format[i];
-      std::string* passphrase;
-      switch (specs[i].format) {
-        case RBD_ENCRYPTION_FORMAT_LUKS: {
-          luks_opts.emplace_back();
-          specs[i].opts = &luks_opts.back();
-          specs[i].opts_size = sizeof(luks_opts.back());
-          passphrase = &luks_opts.back().passphrase;
-          break;
-        }
-        default:
-          r = -ENOTSUP;
-          cerr << "rbd-nbd: unsupported encryption format: " << specs[i].format
-               << std::endl;
-          goto close_fd;
-      }
-
-      passphrase->assign((std::istreambuf_iterator<char>(file)),
-                         (std::istreambuf_iterator<char>()));
-
       if (file.fail()) {
         r = -errno;
         std::cerr << "rbd-nbd: unable to open passphrase file '"
-                  << cfg->encryption_passphrase_file[i] << "': "
-                  << cpp_strerror(errno) << std::endl;
+                  << 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: {
+        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: {
+        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:
+        ceph_abort();
+      }
     }
 
-    r = image.encryption_load2(&specs[0], encryption_format_count);
-
+    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;
@@ -2142,15 +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.push_back(RBD_ENCRYPTION_FORMAT_LUKS);
-        *err_msg << "rbd-nbd: specifying luks1 when loading encryption "
-                    "is deprecated, use luks";
+        cfg->encryption_formats.push_back(RBD_ENCRYPTION_FORMAT_LUKS1);
       } else if (arg_value == "luks2") {
-        cfg->encryption_format.push_back(RBD_ENCRYPTION_FORMAT_LUKS);
-        *err_msg << "rbd-nbd: specifying luks2 when loading encryption "
-                    "is deprecated, use luks";
+        cfg->encryption_formats.push_back(RBD_ENCRYPTION_FORMAT_LUKS2);
       } else if (arg_value == "luks") {
-        cfg->encryption_format.push_back(RBD_ENCRYPTION_FORMAT_LUKS);
+        cfg->encryption_formats.push_back(RBD_ENCRYPTION_FORMAT_LUKS);
       } else {
         *err_msg << "rbd-nbd: Invalid encryption format";
         return -EINVAL;
@@ -2158,13 +2188,13 @@ 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.push_back(arg_value);
+      cfg->encryption_passphrase_files.push_back(arg_value);
     } else {
       ++i;
     }
   }
 
-  if (cfg->encryption_format.size() != cfg->encryption_passphrase_file.size()) {
+  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;