Skip to content

Commit

Permalink
cdh: Add secure mount interface for block device
Browse files Browse the repository at this point in the history
Add secure mount interface for block device.

Fixed: confidential-containers#540 -- part II

Signed-off-by: ChengyuZhu6 <[email protected]>
  • Loading branch information
ChengyuZhu6 committed Jul 18, 2024
1 parent 3cbdf1b commit 63f0f1b
Show file tree
Hide file tree
Showing 6 changed files with 149 additions and 1 deletion.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions confidential-data-hub/storage/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ anyhow.workspace = true
async-trait.workspace = true
base64.workspace = true
log.workspace = true
kms = { path = "../kms", default-features = false }
rand = { workspace = true, optional = true }
secret = { path = "../secret" }
serde.workspace = true
Expand Down
3 changes: 3 additions & 0 deletions confidential-data-hub/storage/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ pub enum Error {
#[error("Error when mounting Aliyun OSS")]
AliyunOssError(#[from] volume_type::aliyun::error::AliyunError),

#[error("Error when mounting Block device")]
BlockDeviceError(#[from] volume_type::blockdevice::error::BlockDeviceError),

#[error("Failed to recognize the storage type")]
StorageTypeNotRecognized(#[from] strum::ParseError),
}
29 changes: 29 additions & 0 deletions confidential-data-hub/storage/src/volume_type/blockdevice/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Copyright (c) 2024 Intel
//
// SPDX-License-Identifier: Apache-2.0
//

use thiserror::Error;

pub type Result<T> = std::result::Result<T, BlockDeviceError>;

#[derive(Error, Debug)]
pub enum BlockDeviceError {
#[error("Error when getting encrypt/decrypt keys")]
GetKeysFailure(#[from] anyhow::Error),

#[error("LUKS decryption mount failed")]
LUKSfsMountFailed,

#[error("I/O error")]
IOError(#[from] std::io::Error),

#[error("Failed to mount block device")]
BlockDeviceMountFailed,

#[error("Serialize/Deserialize failed")]
SerdeError(#[from] serde_json::Error),

#[error("Failed to recognize the storage type")]
StorageTypeNotRecognized(#[from] strum::ParseError),
}
107 changes: 107 additions & 0 deletions confidential-data-hub/storage/src/volume_type/blockdevice/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
// Copyright (c) 2024 Intel
//
// SPDX-License-Identifier: Apache-2.0
//
pub mod error;

use super::SecureMount;
use anyhow::Context;
use async_trait::async_trait;
use error::{BlockDeviceError, Result};
use kms::{Annotations, ProviderSettings};
use log::{debug, error};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use strum::{Display, EnumString};

#[derive(EnumString, Serialize, Deserialize, Display, Debug, PartialEq, Eq)]
pub enum BlockDeviceEncryptType {
#[strum(serialize = "luks")]
LUKS,
}

#[derive(Serialize, Deserialize, PartialEq, Debug)]
pub struct BlockDeviceParameters {
/// The device number, formatted as "MAJ:MIN".
#[serde(rename = "deviceId")]
pub device_id: String,

/// The encryption type. Currently, only LUKS is supported.
#[serde(rename = "encryptType")]
pub encryption_type: BlockDeviceEncryptType,

/// Encryption key. If not set, generate a random 4096-byte key
#[serde(rename = "encryptKey")]
pub encryption_key: Option<String>,

/// Indicates whether to enable dm-integrity.
#[serde(rename = "dataIntegrity")]
pub data_integrity: String,
}
pub(crate) struct BlockDevice;

#[async_trait]
pub trait Encryptor {
async fn encrypt_and_mount(
&self,
parameters: BlockDeviceParameters,
mount_point: &str,
) -> Result<()>;
}

async fn get_plaintext_key(resource: &str) -> anyhow::Result<Vec<u8>> {
if resource.starts_with("sealed.") {
debug!("detected sealed secret");
let unsealed = secret::unseal_secret(resource.as_bytes()).await?;
return Ok(unsealed);
}

if resource.starts_with("kbs://") {
let secret = kms::new_getter("kbs", ProviderSettings::default())
.await?
.get_secret(resource, &Annotations::default())
.await
.map_err(|e| {
error!("get keys from kbs failed: {e}");
BlockDeviceError::GetKeysFailure(e.into())
})?;
return Ok(secret);
}

Err(BlockDeviceError::GetKeysFailure(anyhow::anyhow!("unknown resource scheme")).into())
}

impl BlockDevice {
async fn real_mount(
&self,
options: &HashMap<String, String>,
_flags: &[String],
mount_point: &str,
) -> Result<()> {
// construct BlockDeviceParameters
let parameters = serde_json::to_string(options)?;
let bd_parameter: BlockDeviceParameters = serde_json::from_str(&parameters)?;

Ok(())
}
}

#[async_trait]
impl SecureMount for BlockDevice {
/// Mount the block device to the given `mount_point``.
///
/// If `bd.encrypt_type` is set to `LUKS`, the device will be formated as a LUKS-encrypted device.
/// Then use cryptsetup open the device and mount it to `mount_point` as plaintext.
///
/// This is a wrapper for inner function to convert error type.
async fn mount(
&self,
options: &HashMap<String, String>,
flags: &[String],
mount_point: &str,
) -> super::Result<()> {
self.real_mount(options, flags, mount_point)
.await
.map_err(|e| e.into())
}
}
9 changes: 8 additions & 1 deletion confidential-data-hub/storage/src/volume_type/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

#[cfg(feature = "aliyun")]
pub mod aliyun;

pub mod blockdevice;
use std::{collections::HashMap, str::FromStr};

use crate::Result;
Expand All @@ -20,6 +20,7 @@ pub enum Volume {
#[cfg(feature = "aliyun")]
#[strum(serialize = "alibaba-cloud-oss")]
AliOss,
BlockDevice,
}

/// Indicating a mount point and its parameters.
Expand Down Expand Up @@ -61,6 +62,12 @@ impl Storage {
.await?;
Ok(self.mount_point.clone())
}
Volume::BlockDevice => {
let bd = blockdevice::BlockDevice {};
bd.mount(&self.options, &self.flags, &self.mount_point)
.await?;
Ok(self.mount_point.clone())
}
}
}
}

0 comments on commit 63f0f1b

Please sign in to comment.