Skip to content

Commit

Permalink
Add D-Bus method for pool encrypt
Browse files Browse the repository at this point in the history
  • Loading branch information
jbaublitz committed Aug 9, 2024
1 parent 1794d77 commit 60a1363
Show file tree
Hide file tree
Showing 6 changed files with 218 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/dbus_api/pool/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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))
Expand Down
32 changes: 32 additions & 0 deletions src/dbus_api/pool/pool_3_8/api.rs
Original file line number Diff line number Diff line change
@@ -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<MTSync<TData>, TData>) -> Method<MTSync<TData>, 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"))
}
99 changes: 99 additions & 0 deletions src/dbus_api/pool/pool_3_8/methods.rs
Original file line number Diff line number Diff line change
@@ -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>, 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<String>) = (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])
}
8 changes: 8 additions & 0 deletions src/dbus_api/pool/pool_3_8/mod.rs
Original file line number Diff line number Diff line change
@@ -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;
63 changes: 63 additions & 0 deletions src/dbus_api/tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down Expand Up @@ -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,
Expand Down
14 changes: 14 additions & 0 deletions src/dbus_api/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ pub enum DbusAction {
BlockdevTotalPhysicalSizeChange(Path<'static>, Sectors),
FsOriginChange(Path<'static>),
FsSizeLimitChange(Path<'static>, Option<Sectors>),
PoolEncryptionChange(Path<'static>, bool),
FsBackgroundChange(
FilesystemUuid,
SignalChange<Option<Bytes>>,
Expand Down Expand Up @@ -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(
Expand Down

0 comments on commit 60a1363

Please sign in to comment.