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 7, 2025
1 parent c0a1a70 commit b6dd766
Show file tree
Hide file tree
Showing 23 changed files with 983 additions and 247 deletions.
24 changes: 13 additions & 11 deletions src/dbus_api/api/manager_3_8/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,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 @@ -38,21 +38,23 @@ pub fn create_pool_method(f: &Factory<MTSync<TData>, TData>) -> Method<MTSync<TD
f.method("CreatePool", (), create_pool)
.in_arg(("name", "s"))
.in_arg(("devices", "as"))
// 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.
// 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: (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.
// 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: (bool, (String, String))
.in_arg(("clevis_info", "(b(ss))"))
// Rust representation: Vec<((bool, u32), String, String)>
.in_arg(("clevis_info", "a((bi)ss)"))
// Optional journal size for integrity metadata reservation.
// b: true if the size should be specified.
// false if the default should be used.
Expand Down
81 changes: 44 additions & 37 deletions src/dbus_api/api/manager_3_8/methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ use dbus::{
};
use dbus_tree::{MTSync, MethodInfo, MethodResult};
use futures::executor::block_on;
use serde_json::from_str;

use devicemapper::Bytes;

use crate::{
dbus_api::{
api::shared::EncryptionParams,
blockdev::create_dbus_blockdev,
filesystem::create_dbus_filesystem,
pool::create_dbus_pool,
Expand All @@ -24,11 +24,16 @@ use crate::{
},
engine::{
CreateAction, InputEncryptionInfo, IntegritySpec, IntegrityTagSpec, KeyDescription, Name,
PoolIdentifier, PoolUuid, StartAction, TokenUnlockMethod, UnlockMethod,
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;
Expand Down Expand Up @@ -64,29 +69,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 @@ -153,10 +144,8 @@ pub fn create_pool(m: &MethodInfo<'_, MTSync<TData>, TData>) -> MethodResult {

let name: &str = get_next_arg(&mut iter, 0)?;
let devs: Array<'_, &str, _> = get_next_arg(&mut iter, 1)?;
let (key_desc_tuple, clevis_tuple): EncryptionParams = (
Some(get_next_arg(&mut iter, 2)?),
Some(get_next_arg(&mut iter, 3)?),
);
let (key_desc_array, clevis_array): EncryptionInfos<'_> =
(get_next_arg(&mut iter, 2)?, get_next_arg(&mut iter, 3)?);
let journal_size_tuple: (bool, u64) = get_next_arg(&mut iter, 4)?;
let tag_spec_tuple: (bool, String) = get_next_arg(&mut iter, 5)?;
let allocate_superblock_tuple: (bool, bool) = get_next_arg(&mut iter, 6)?;
Expand All @@ -166,26 +155,44 @@ pub fn create_pool(m: &MethodInfo<'_, MTSync<TData>, TData>) -> MethodResult {
let default_return: (bool, (dbus::Path<'static>, Vec<dbus::Path<'static>>)) =
(false, (dbus::Path::default(), Vec::new()));

let key_desc = match key_desc_tuple.and_then(tuple_to_option) {
Some(kds) => match KeyDescription::try_from(kds) {
Ok(kd) => Some(kd),
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)]);
}
},
None => None,
};
};

let clevis_info = match clevis_tuple.and_then(tuple_to_option) {
Some((pin, json_string)) => match serde_json::from_str(json_string.as_str()) {
Ok(j) => Some((pin, j)),
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(&StratisError::Serde(e));
let (rc, rs) = engine_to_dbus_err_tuple(&e);
return Ok(vec![return_message.append3(default_return, rc, rs)]);
}
},
None => None,
};

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 journal_size = tuple_to_option(journal_size_tuple).map(Bytes::from);
Expand All @@ -208,7 +215,7 @@ pub fn create_pool(m: &MethodInfo<'_, MTSync<TData>, TData>) -> MethodResult {
let create_result = handle_action!(block_on(dbus_context.engine.create_pool(
name,
&devs.map(Path::new).collect::<Vec<&Path>>(),
InputEncryptionInfo::new_legacy(key_desc, clevis_info).as_ref(),
ei.as_ref(),
IntegritySpec {
journal_size,
tag_spec,
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
42 changes: 30 additions & 12 deletions src/dbus_api/pool/pool_3_0/methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -384,8 +384,11 @@ pub fn bind_clevis(m: &MethodInfo<'_, MTSync<TData>, TData>) -> MethodResult {
return_message.append3(false, DbusErrorEnum::OK as u16, OK_STRING.to_string())
}
Ok(CreateAction::Created(_)) => {
dbus_context
.push_pool_clevis_info_change(pool_path.get_name(), pool.encryption_info_legacy());
dbus_context.push_pool_clevis_info_change(
pool_path.get_name(),
pool.encryption_info()
.map(|either| either.map_left(|ei| (true, ei))),
);
return_message.append3(true, DbusErrorEnum::OK as u16, OK_STRING.to_string())
}
Err(e) => {
Expand Down Expand Up @@ -422,8 +425,11 @@ pub fn unbind_clevis(m: &MethodInfo<'_, MTSync<TData>, TData>) -> MethodResult {
return_message.append3(false, DbusErrorEnum::OK as u16, OK_STRING.to_string())
}
Ok(DeleteAction::Deleted(_)) => {
dbus_context
.push_pool_clevis_info_change(pool_path.get_name(), pool.encryption_info_legacy());
dbus_context.push_pool_clevis_info_change(
pool_path.get_name(),
pool.encryption_info()
.map(|either| either.map_left(|ei| (true, ei))),
);
return_message.append3(true, DbusErrorEnum::OK as u16, OK_STRING.to_string())
}
Err(e) => {
Expand Down Expand Up @@ -474,8 +480,11 @@ pub fn bind_keyring(m: &MethodInfo<'_, MTSync<TData>, TData>) -> MethodResult {
return_message.append3(false, DbusErrorEnum::OK as u16, OK_STRING.to_string())
}
Ok(CreateAction::Created(_)) => {
dbus_context
.push_pool_key_desc_change(pool_path.get_name(), pool.encryption_info_legacy());
dbus_context.push_pool_key_desc_change(
pool_path.get_name(),
pool.encryption_info()
.map(|either| either.map_left(|ei| (true, ei))),
);
return_message.append3(true, DbusErrorEnum::OK as u16, OK_STRING.to_string())
}
Err(e) => {
Expand Down Expand Up @@ -516,8 +525,11 @@ pub fn unbind_keyring(m: &MethodInfo<'_, MTSync<TData>, TData>) -> MethodResult
return_message.append3(false, DbusErrorEnum::OK as u16, OK_STRING.to_string())
}
Ok(DeleteAction::Deleted(_)) => {
dbus_context
.push_pool_key_desc_change(pool_path.get_name(), pool.encryption_info_legacy());
dbus_context.push_pool_key_desc_change(
pool_path.get_name(),
pool.encryption_info()
.map(|either| either.map_left(|ei| (true, ei))),
);
return_message.append3(true, DbusErrorEnum::OK as u16, OK_STRING.to_string())
}
Err(e) => {
Expand Down Expand Up @@ -568,8 +580,11 @@ pub fn rebind_keyring(m: &MethodInfo<'_, MTSync<TData>, TData>) -> MethodResult
return_message.append3(false, DbusErrorEnum::OK as u16, OK_STRING.to_string())
}
Ok(RenameAction::Renamed(_)) => {
dbus_context
.push_pool_key_desc_change(pool_path.get_name(), pool.encryption_info_legacy());
dbus_context.push_pool_key_desc_change(
pool_path.get_name(),
pool.encryption_info()
.map(|either| either.map_left(|ei| (true, ei))),
);
return_message.append3(true, DbusErrorEnum::OK as u16, OK_STRING.to_string())
}
Ok(RenameAction::NoSource) => {
Expand Down Expand Up @@ -610,8 +625,11 @@ pub fn rebind_clevis(m: &MethodInfo<'_, MTSync<TData>, TData>) -> MethodResult {

let msg = match handle_action!(pool.rebind_clevis(None), dbus_context, pool_path.get_name()) {
Ok(_) => {
dbus_context
.push_pool_clevis_info_change(pool_path.get_name(), pool.encryption_info_legacy());
dbus_context.push_pool_clevis_info_change(
pool_path.get_name(),
pool.encryption_info()
.map(|either| either.map_left(|ei| (true, ei))),
);
return_message.append3(true, DbusErrorEnum::OK as u16, OK_STRING.to_string())
}
Err(e) => {
Expand Down
Loading

0 comments on commit b6dd766

Please sign in to comment.