diff --git a/src/dbus_api/pool/mod.rs b/src/dbus_api/pool/mod.rs index c643560229..876878814e 100644 --- a/src/dbus_api/pool/mod.rs +++ b/src/dbus_api/pool/mod.rs @@ -19,6 +19,7 @@ mod pool_3_3; mod pool_3_5; mod pool_3_6; mod pool_3_7; +mod pool_3_8; pub mod prop_conv; mod shared; @@ -293,6 +294,7 @@ pub fn create_dbus_pool<'a>( .add_m(pool_3_0::rename_method(&f)) .add_m(pool_3_3::grow_physical_device_method(&f)) .add_m(pool_3_7::get_metadata_method(&f)) + .add_m(pool_3_8::encrypt_pool_method(&f)) .add_p(pool_3_0::name_property(&f)) .add_p(pool_3_0::uuid_property(&f)) .add_p(pool_3_0::encrypted_property(&f)) diff --git a/src/dbus_api/pool/pool_3_8/api.rs b/src/dbus_api/pool/pool_3_8/api.rs new file mode 100644 index 0000000000..b8f9488c29 --- /dev/null +++ b/src/dbus_api/pool/pool_3_8/api.rs @@ -0,0 +1,32 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +use dbus_tree::{Factory, MTSync, Method}; + +use crate::dbus_api::{pool::pool_3_8::methods::encrypt_pool, types::TData}; + +pub fn encrypt_pool_method(f: &Factory, TData>) -> Method, TData> { + f.method("EncryptPool", (), encrypt_pool) + // Optional key description of key in the kernel keyring + // b: true if the pool should be encrypted and able to be + // unlocked with a passphrase associated with this key description. + // s: key description + // + // Rust representation: (bool, String) + .in_arg(("key_desc", "(bs)")) + // Optional Clevis information for binding on initialization. + // b: true if the pool should be encrypted and able to be unlocked + // using Clevis. + // s: pin name + // s: JSON config for Clevis use + // + // Rust representation: (bool, (String, String)) + .in_arg(("clevis_info", "(b(ss))")) + // b: true if pool was newly encrypted + // + // Rust representation: bool + .out_arg(("results", "b")) + .out_arg(("return_code", "q")) + .out_arg(("return_string", "s")) +} diff --git a/src/dbus_api/pool/pool_3_8/methods.rs b/src/dbus_api/pool/pool_3_8/methods.rs new file mode 100644 index 0000000000..fc11eee697 --- /dev/null +++ b/src/dbus_api/pool/pool_3_8/methods.rs @@ -0,0 +1,99 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +use std::iter::once; + +use dbus::Message; +use dbus_tree::{MTSync, MethodInfo, MethodResult}; + +use crate::{ + dbus_api::{ + types::{DbusErrorEnum, TData, OK_STRING}, + util::{engine_to_dbus_err_tuple, get_next_arg, tuple_to_option}, + }, + engine::{CreateAction, EncryptionInfo, KeyDescription, PoolEncryptionInfo}, + stratis::StratisError, +}; + +pub fn encrypt_pool(m: &MethodInfo<'_, MTSync, TData>) -> MethodResult { + let message: &Message = m.msg; + let mut iter = message.iter_init(); + + let key_desc_tuple: (bool, String) = get_next_arg(&mut iter, 0)?; + let clevis_tuple: (bool, (String, String)) = get_next_arg(&mut iter, 0)?; + + let dbus_context = m.tree.get_data(); + let object_path = m.path.get_name(); + let return_message = message.method_return(); + let default_return: (bool, Vec) = (false, Vec::new()); + + let key_desc = match tuple_to_option(key_desc_tuple) { + Some(kds) => match KeyDescription::try_from(kds) { + Ok(kd) => Some(kd), + Err(e) => { + let (rc, rs) = engine_to_dbus_err_tuple(&e); + return Ok(vec![return_message.append3(default_return, rc, rs)]); + } + }, + None => None, + }; + let clevis_info = match tuple_to_option(clevis_tuple) { + Some((pin, json_string)) => match serde_json::from_str(json_string.as_str()) { + Ok(j) => Some((pin, j)), + Err(e) => { + let (rc, rs) = engine_to_dbus_err_tuple(&StratisError::Serde(e)); + return Ok(vec![return_message.append3(default_return, rc, rs)]); + } + }, + None => None, + }; + let encryption_info = match EncryptionInfo::from_options((key_desc, clevis_info)) { + Some(enc) => enc, + None => { + let (rc, rs) = ( + DbusErrorEnum::ERROR as u16, + "Either a key description or Clevis info is required for this method".to_string(), + ); + return Ok(vec![return_message.append3(default_return, rc, rs)]); + } + }; + + let pool_path = m + .tree + .get(object_path) + .expect("implicit argument must be in tree"); + let pool_uuid = typed_uuid!( + get_data!(pool_path; default_return; return_message).uuid; + Pool; + default_return; + return_message + ); + + let mut guard = get_mut_pool!(dbus_context.engine; pool_uuid; default_return; return_message); + let (_, _, pool) = guard.as_mut_tuple(); + + let result = handle_action!( + pool.encrypt_pool(pool_uuid, &encryption_info), + dbus_context, + pool_path.get_name() + ); + let msg = match result { + Ok(CreateAction::Created(_)) => { + let pool_enc_info = PoolEncryptionInfo::from(once(&encryption_info)); + dbus_context + .push_pool_key_desc_change(pool_path.get_name(), Some(pool_enc_info.clone())); + dbus_context.push_pool_clevis_info_change(pool_path.get_name(), Some(pool_enc_info)); + dbus_context.push_pool_encryption_status_change(pool_path.get_name(), true); + return_message.append3(true, DbusErrorEnum::OK as u16, OK_STRING.to_string()) + } + Ok(CreateAction::Identity) => { + return_message.append3(false, DbusErrorEnum::OK as u16, OK_STRING.to_string()) + } + Err(err) => { + let (rc, rs) = engine_to_dbus_err_tuple(&err); + return_message.append3(default_return, rc, rs) + } + }; + Ok(vec![msg]) +} diff --git a/src/dbus_api/pool/pool_3_8/mod.rs b/src/dbus_api/pool/pool_3_8/mod.rs new file mode 100644 index 0000000000..b487bccef5 --- /dev/null +++ b/src/dbus_api/pool/pool_3_8/mod.rs @@ -0,0 +1,8 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +mod api; +mod methods; + +pub use api::encrypt_pool_method; diff --git a/src/dbus_api/tree.rs b/src/dbus_api/tree.rs index 42b51f610c..e0269a63da 100644 --- a/src/dbus_api/tree.rs +++ b/src/dbus_api/tree.rs @@ -1055,6 +1055,65 @@ impl DbusTreeHandler { } } + /// Send a signal indicating that the pool encryption status has changed. + fn handle_pool_encryption_change(&self, path: Path<'static>, new_encryption: bool) { + if let Err(e) = self.property_changed_invalidated_signal( + &path, + prop_hashmap!( + consts::POOL_INTERFACE_NAME_3_0 => { + Vec::new(), + consts::POOL_ENCRYPTED_PROP.to_string() => + box_variant!(new_encryption) + }, + consts::POOL_INTERFACE_NAME_3_1 => { + Vec::new(), + consts::POOL_ENCRYPTED_PROP.to_string() => + box_variant!(new_encryption) + }, + consts::POOL_INTERFACE_NAME_3_2 => { + Vec::new(), + consts::POOL_ENCRYPTED_PROP.to_string() => + box_variant!(new_encryption) + }, + consts::POOL_INTERFACE_NAME_3_3 => { + Vec::new(), + consts::POOL_ENCRYPTED_PROP.to_string() => + box_variant!(new_encryption) + }, + consts::POOL_INTERFACE_NAME_3_4 => { + Vec::new(), + consts::POOL_ENCRYPTED_PROP.to_string() => + box_variant!(new_encryption) + }, + consts::POOL_INTERFACE_NAME_3_5 => { + Vec::new(), + consts::POOL_ENCRYPTED_PROP.to_string() => + box_variant!(new_encryption) + }, + consts::POOL_INTERFACE_NAME_3_6 => { + Vec::new(), + consts::POOL_ENCRYPTED_PROP.to_string() => + box_variant!(new_encryption) + }, + consts::POOL_INTERFACE_NAME_3_7 => { + Vec::new(), + consts::POOL_ENCRYPTED_PROP.to_string() => + box_variant!(new_encryption) + }, + consts::POOL_INTERFACE_NAME_3_8 => { + Vec::new(), + consts::POOL_ENCRYPTED_PROP.to_string() => + box_variant!(new_encryption) + } + ), + ) { + warn!( + "Failed to send a signal over D-Bus indicating blockdev total physical size change: {}", + e + ); + } + } + /// Send a signal indicating that the pool overprovisioning mode has changed. fn handle_pool_overprov_mode_change(&self, path: Path<'static>, new_mode: bool) { if let Err(e) = self.property_changed_invalidated_signal( @@ -1379,6 +1438,10 @@ impl DbusTreeHandler { self.handle_blockdev_total_physical_size_change(path, new_total_physical_size); Ok(true) } + DbusAction::PoolEncryptionChange(path, encryption_change) => { + self.handle_pool_encryption_change(path, encryption_change); + Ok(true) + } DbusAction::PoolForegroundChange(item, new_used, new_alloc, new_size, new_no_space) => { self.handle_pool_foreground_change( item, diff --git a/src/dbus_api/types.rs b/src/dbus_api/types.rs index af345c152c..20d47ab949 100644 --- a/src/dbus_api/types.rs +++ b/src/dbus_api/types.rs @@ -108,6 +108,7 @@ pub enum DbusAction { BlockdevTotalPhysicalSizeChange(Path<'static>, Sectors), FsOriginChange(Path<'static>), FsSizeLimitChange(Path<'static>, Option), + PoolEncryptionChange(Path<'static>, bool), FsBackgroundChange( FilesystemUuid, SignalChange>, @@ -465,6 +466,19 @@ impl DbusContext { } } + /// Send changed signal for changed encryption status of pool. + pub fn push_pool_encryption_status_change(&self, path: &Path<'static>, encrypted: bool) { + if let Err(e) = self + .sender + .send(DbusAction::PoolEncryptionChange(path.clone(), encrypted)) + { + warn!( + "Encryption status change event could not be sent to the processing thread; no signal will be sent out for the encryption status state change: {}", + e, + ) + } + } + /// Send changed signal for changed pool properties when blockdevs are /// added. pub fn push_pool_foreground_change(