Skip to content

Commit

Permalink
Modify D-Bus interface to support multiple token slots
Browse files Browse the repository at this point in the history
  • Loading branch information
jbaublitz committed Jan 6, 2025
1 parent 028ed95 commit 6288a2f
Show file tree
Hide file tree
Showing 25 changed files with 1,099 additions and 225 deletions.
39 changes: 37 additions & 2 deletions src/dbus_api/api/manager_3_8/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ use dbus_tree::{Access, EmitsChangedSignal, Factory, MTSync, Method, Property};

use crate::dbus_api::{
api::{
manager_3_8::{methods::start_pool, props::get_stopped_pools},
manager_3_8::{
methods::{create_pool, start_pool},
props::get_stopped_pools,
},
prop_conv::StoppedOrLockedPools,
},
consts,
Expand All @@ -17,7 +20,7 @@ pub fn start_pool_method(f: &Factory<MTSync<TData>, TData>) -> Method<MTSync<TDa
f.method("StartPool", (), start_pool)
.in_arg(("id", "s"))
.in_arg(("id_type", "s"))
.in_arg(("unlock_method", "(bs)"))
.in_arg(("unlock_method", "(b(bi))"))
.in_arg(("key_fd", "(bh)"))
// In order from left to right:
// b: true if the pool was newly started
Expand All @@ -31,6 +34,38 @@ pub fn start_pool_method(f: &Factory<MTSync<TData>, TData>) -> Method<MTSync<TDa
.out_arg(("return_string", "s"))
}

pub fn create_pool_method(f: &Factory<MTSync<TData>, TData>) -> Method<MTSync<TData>, TData> {
f.method("CreatePool", (), create_pool)
.in_arg(("name", "s"))
.in_arg(("devices", "as"))
// Optional key descriptions of key in the kernel keyring
// a: array of zero or more elements
// b: true if a token slot is specified
// i: token slot
// s: key description
//
// Rust representation: Vec<((bool, u32), String)>
.in_arg(("key_desc", "a((bi)s)"))
// Optional Clevis infos for binding on initialization.
// a: array of zero or more elements
// b: true if a token slot is specified
// i: token slot
// s: pin name
// s: JSON config for Clevis use
//
// Rust representation: Vec<((bool, u32), String, String)>
.in_arg(("clevis_info", "a((bi)ss)"))
// In order from left to right:
// b: true if a pool was created and object paths were returned
// o: Object path for Pool
// a(o): Array of object paths for block devices
//
// Rust representation: (bool, (dbus::Path, Vec<dbus::Path>))
.out_arg(("result", "(b(oao))"))
.out_arg(("return_code", "q"))
.out_arg(("return_string", "s"))
}

pub fn stopped_pools_property(f: &Factory<MTSync<TData>, TData>) -> Property<MTSync<TData>, TData> {
f.property::<StoppedOrLockedPools, _>(consts::STOPPED_POOLS_PROP, ())
.access(Access::Read)
Expand Down
156 changes: 134 additions & 22 deletions src/dbus_api/api/manager_3_8/methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,15 @@
// 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::{arg::OwnedFd, Message, Path};
use std::path::Path;

use dbus::{
arg::{Array, OwnedFd},
Message,
};
use dbus_tree::{MTSync, MethodInfo, MethodResult};
use futures::executor::block_on;
use serde_json::from_str;

use crate::{
dbus_api::{
Expand All @@ -14,19 +20,31 @@ use crate::{
types::{DbusErrorEnum, TData, OK_STRING},
util::{engine_to_dbus_err_tuple, get_next_arg, tuple_to_option},
},
engine::{Name, PoolIdentifier, PoolUuid, StartAction, TokenUnlockMethod, UnlockMethod},
engine::{
CreateAction, InputEncryptionInfo, KeyDescription, Name, PoolIdentifier, PoolUuid,
StartAction, TokenUnlockMethod,
},
stratis::StratisError,
};

type EncryptionInfos<'a> = (
Vec<((bool, u32), &'a str)>,
Vec<((bool, u32), (&'a str, &'a str))>,
);

pub fn start_pool(m: &MethodInfo<'_, MTSync<TData>, TData>) -> MethodResult {
let base_path = m.path.get_name();
let message: &Message = m.msg;
let mut iter = message.iter_init();
let dbus_context = m.tree.get_data();
let default_return: (
bool,
(Path<'static>, Vec<Path<'static>>, Vec<Path<'static>>),
) = (false, (Path::default(), Vec::new(), Vec::new()));
(
dbus::Path<'static>,
Vec<dbus::Path<'static>>,
Vec<dbus::Path<'static>>,
),
) = (false, (dbus::Path::default(), Vec::new(), Vec::new()));
let return_message = message.method_return();

let id_str: &str = get_next_arg(&mut iter, 0)?;
Expand All @@ -49,29 +67,15 @@ pub fn start_pool(m: &MethodInfo<'_, MTSync<TData>, TData>) -> MethodResult {
}
}
};
let unlock_method = {
let unlock_method_tup: (bool, &str) = get_next_arg(&mut iter, 2)?;
match tuple_to_option(unlock_method_tup) {
Some(unlock_method_str) => {
match UnlockMethod::try_from(unlock_method_str).map_err(|_| {
StratisError::Msg(format!("{unlock_method_str} is an invalid unlock method"))
}) {
Ok(um) => Some(um),
Err(e) => {
let (rc, rs) = engine_to_dbus_err_tuple(&e);
return Ok(vec![return_message.append3(default_return, rc, rs)]);
}
}
}
None => None,
}
};
let unlock_method_tup: (bool, (bool, u32)) = get_next_arg(&mut iter, 2)?;
let unlock_method =
TokenUnlockMethod::from_options(tuple_to_option(unlock_method_tup).map(tuple_to_option));
let fd_opt: (bool, OwnedFd) = get_next_arg(&mut iter, 3)?;
let fd = tuple_to_option(fd_opt);

let ret = match handle_action!(block_on(dbus_context.engine.start_pool(
id.clone(),
TokenUnlockMethod::from(unlock_method),
unlock_method,
fd.map(|f| f.into_fd()),
))) {
Ok(StartAction::Started(_)) => {
Expand Down Expand Up @@ -130,3 +134,111 @@ pub fn start_pool(m: &MethodInfo<'_, MTSync<TData>, TData>) -> MethodResult {
OK_STRING.to_string(),
)])
}

pub fn create_pool(m: &MethodInfo<'_, MTSync<TData>, TData>) -> MethodResult {
let base_path = m.path.get_name();
let message: &Message = m.msg;
let mut iter = message.iter_init();

let name: &str = get_next_arg(&mut iter, 0)?;
let devs: Array<'_, &str, _> = get_next_arg(&mut iter, 1)?;
let (key_desc_array, clevis_array): EncryptionInfos<'_> =
(get_next_arg(&mut iter, 2)?, get_next_arg(&mut iter, 3)?);

let return_message = message.method_return();

let default_return: (bool, (dbus::Path<'static>, Vec<dbus::Path<'static>>)) =
(false, (dbus::Path::default(), Vec::new()));

let key_descs =
match key_desc_array
.into_iter()
.try_fold(Vec::new(), |mut vec, (ts_opt, kd_str)| {
let token_slot = tuple_to_option(ts_opt);
let kd = KeyDescription::try_from(kd_str.to_string())?;
vec.push((token_slot, kd));
Ok(vec)
}) {
Ok(kds) => kds,
Err(e) => {
let (rc, rs) = engine_to_dbus_err_tuple(&e);
return Ok(vec![return_message.append3(default_return, rc, rs)]);
}
};

let clevis_infos =
match clevis_array
.into_iter()
.try_fold(Vec::new(), |mut vec, (ts_opt, (pin, json_str))| {
let token_slot = tuple_to_option(ts_opt);
let json = from_str(json_str)?;
vec.push((token_slot, (pin.to_owned(), json)));
Ok(vec)
}) {
Ok(cis) => cis,
Err(e) => {
let (rc, rs) = engine_to_dbus_err_tuple(&e);
return Ok(vec![return_message.append3(default_return, rc, rs)]);
}
};

let ei = match InputEncryptionInfo::new(key_descs, clevis_infos) {
Ok(opt) => opt,
Err(e) => {
let (rc, rs) = engine_to_dbus_err_tuple(&e);
return Ok(vec![return_message.append3(default_return, rc, rs)]);
}
};

let dbus_context = m.tree.get_data();
let create_result = handle_action!(block_on(dbus_context.engine.create_pool(
name,
&devs.map(Path::new).collect::<Vec<&Path>>(),
ei.as_ref()
)));
match create_result {
Ok(pool_uuid_action) => match pool_uuid_action {
CreateAction::Created(uuid) => {
let guard = match block_on(dbus_context.engine.get_pool(PoolIdentifier::Uuid(uuid)))
{
Some(g) => g,
None => {
let (rc, rs) = engine_to_dbus_err_tuple(&StratisError::Msg(
format!("Pool with UUID {uuid} was successfully started but appears to have been removed before it could be exposed on the D-Bus")
));
return Ok(vec![return_message.append3(default_return, rc, rs)]);
}
};

let (pool_name, pool_uuid, pool) = guard.as_tuple();
let pool_path =
create_dbus_pool(dbus_context, base_path.clone(), &pool_name, pool_uuid, pool);
let mut bd_paths = Vec::new();
for (bd_uuid, tier, bd) in pool.blockdevs() {
bd_paths.push(create_dbus_blockdev(
dbus_context,
pool_path.clone(),
bd_uuid,
tier,
bd,
));
}

Ok(vec![return_message.append3(
(true, (pool_path, bd_paths)),
DbusErrorEnum::OK as u16,
OK_STRING.to_string(),
)])
}
CreateAction::Identity => Ok(vec![return_message.append3(
default_return,
DbusErrorEnum::OK as u16,
OK_STRING.to_string(),
)]),
},
Err(x) => {
let (rc, rs) = engine_to_dbus_err_tuple(&x);
Ok(vec![return_message.append3(default_return, rc, rs)])
}
}
}
2 changes: 1 addition & 1 deletion src/dbus_api/api/manager_3_8/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ mod api;
mod methods;
mod props;

pub use api::{start_pool_method, stopped_pools_property};
pub use api::{create_pool_method, start_pool_method, stopped_pools_property};
2 changes: 1 addition & 1 deletion src/dbus_api/api/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ pub fn get_base_tree<'a>(
)
.add(
f.interface(consts::MANAGER_INTERFACE_NAME_3_8, ())
.add_m(manager_3_5::create_pool_method(&f))
.add_m(manager_3_8::create_pool_method(&f))
.add_m(manager_3_0::set_key_method(&f))
.add_m(manager_3_0::unset_key_method(&f))
.add_m(manager_3_0::list_keys_method(&f))
Expand Down
2 changes: 2 additions & 0 deletions src/dbus_api/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,11 @@ pub const POOL_HAS_CACHE_PROP: &str = "HasCache";
pub const POOL_ENCRYPTED_PROP: &str = "Encrypted";
pub const POOL_AVAIL_ACTIONS_PROP: &str = "AvailableActions";
pub const POOL_KEY_DESC_PROP: &str = "KeyDescription";
pub const POOL_KEY_DESCS_PROP: &str = "KeyDescriptions";
pub const POOL_TOTAL_SIZE_PROP: &str = "TotalPhysicalSize";
pub const POOL_TOTAL_USED_PROP: &str = "TotalPhysicalUsed";
pub const POOL_CLEVIS_INFO_PROP: &str = "ClevisInfo";
pub const POOL_CLEVIS_INFOS_PROP: &str = "ClevisInfos";
pub const POOL_ALLOC_SIZE_PROP: &str = "AllocatedSize";
pub const POOL_FS_LIMIT_PROP: &str = "FsLimit";
pub const POOL_OVERPROV_PROP: &str = "Overprovisioning";
Expand Down
19 changes: 10 additions & 9 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 @@ -281,14 +282,14 @@ pub fn create_dbus_pool<'a>(
.add_m(pool_3_7::destroy_filesystems_method(&f))
.add_m(pool_3_0::snapshot_filesystem_method(&f))
.add_m(pool_3_0::add_blockdevs_method(&f))
.add_m(pool_3_0::bind_clevis_method(&f))
.add_m(pool_3_0::unbind_clevis_method(&f))
.add_m(pool_3_8::bind_clevis_method(&f))
.add_m(pool_3_8::unbind_clevis_method(&f))
.add_m(pool_3_5::init_cache_method(&f))
.add_m(pool_3_0::add_cachedevs_method(&f))
.add_m(pool_3_0::bind_keyring_method(&f))
.add_m(pool_3_0::unbind_keyring_method(&f))
.add_m(pool_3_0::rebind_keyring_method(&f))
.add_m(pool_3_0::rebind_clevis_method(&f))
.add_m(pool_3_8::bind_keyring_method(&f))
.add_m(pool_3_8::unbind_keyring_method(&f))
.add_m(pool_3_8::rebind_keyring_method(&f))
.add_m(pool_3_8::rebind_clevis_method(&f))
.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))
Expand All @@ -297,8 +298,8 @@ pub fn create_dbus_pool<'a>(
.add_p(pool_3_0::uuid_property(&f))
.add_p(pool_3_0::encrypted_property(&f))
.add_p(pool_3_0::avail_actions_property(&f))
.add_p(pool_3_0::key_desc_property(&f))
.add_p(pool_3_0::clevis_info_property(&f))
.add_p(pool_3_8::key_descs_property(&f))
.add_p(pool_3_8::clevis_infos_property(&f))
.add_p(pool_3_0::has_cache_property(&f))
.add_p(pool_3_0::alloc_size_property(&f))
.add_p(pool_3_0::used_size_property(&f))
Expand Down Expand Up @@ -444,7 +445,7 @@ pub fn get_pool_properties(
consts::POOL_UUID_PROP => uuid_to_string!(pool_uuid),
consts::POOL_ENCRYPTED_PROP => shared::pool_enc_prop(pool),
consts::POOL_AVAIL_ACTIONS_PROP => shared::pool_avail_actions_prop(pool),
consts::POOL_KEY_DESC_PROP => shared::pool_key_desc_prop(pool),
consts::POOL_KEY_DESC_PROP => shared::pool_key_descs_prop(pool),
consts::POOL_CLEVIS_INFO_PROP => shared::pool_clevis_info_prop(pool),
consts::POOL_HAS_CACHE_PROP => shared::pool_has_cache_prop(pool),
consts::POOL_ALLOC_SIZE_PROP => shared::pool_allocated_size(pool),
Expand Down
Loading

0 comments on commit 6288a2f

Please sign in to comment.