disable encryption for new raspi setups (#2348)

* disable encryption for new raspi setups

* use config instead of OS_ARCH

* fixes from testing
This commit is contained in:
Aiden McClelland
2023-07-14 12:30:52 -06:00
committed by GitHub
parent 59d6795d9e
commit 90a9db3a91
6 changed files with 123 additions and 89 deletions

View File

@@ -125,7 +125,11 @@ async fn setup_or_init(cfg_path: Option<PathBuf>) -> Result<(), Error> {
} else {
RepairStrategy::Preen
},
DEFAULT_PASSWORD,
if guid.ends_with("_UNENC") {
None
} else {
Some(DEFAULT_PASSWORD)
},
)
.await?;
if tokio::fs::metadata(REPAIR_DISK_PATH).await.is_ok() {

View File

@@ -45,6 +45,8 @@ pub struct SetupContextConfig {
pub migration_batch_rows: Option<usize>,
pub migration_prefetch_rows: Option<usize>,
pub datadir: Option<PathBuf>,
#[serde(default)]
pub disable_encryption: bool,
}
impl SetupContextConfig {
#[instrument(skip_all)]
@@ -75,6 +77,7 @@ pub struct SetupContextSeed {
pub config_path: Option<PathBuf>,
pub migration_batch_rows: usize,
pub migration_prefetch_rows: usize,
pub disable_encryption: bool,
pub shutdown: Sender<()>,
pub datadir: PathBuf,
pub selected_v2_drive: RwLock<Option<PathBuf>>,
@@ -102,6 +105,7 @@ impl SetupContext {
config_path: path.as_ref().map(|p| p.as_ref().to_owned()),
migration_batch_rows: cfg.migration_batch_rows.unwrap_or(25000),
migration_prefetch_rows: cfg.migration_prefetch_rows.unwrap_or(100_000),
disable_encryption: cfg.disable_encryption,
shutdown,
datadir,
selected_v2_drive: RwLock::new(None),

View File

@@ -13,7 +13,7 @@ use crate::disk::mount::util::unmount;
use crate::util::Invoke;
use crate::{Error, ErrorKind, ResultExt};
pub const PASSWORD_PATH: &'static str = "/etc/embassy/password";
pub const PASSWORD_PATH: &'static str = "/run/embassy/password";
pub const DEFAULT_PASSWORD: &'static str = "password";
pub const MAIN_FS_SIZE: FsSize = FsSize::Gigabytes(8);
@@ -22,13 +22,13 @@ pub async fn create<I, P>(
disks: &I,
pvscan: &BTreeMap<PathBuf, Option<String>>,
datadir: impl AsRef<Path>,
password: &str,
password: Option<&str>,
) -> Result<String, Error>
where
for<'a> &'a I: IntoIterator<Item = &'a P>,
P: AsRef<Path>,
{
let guid = create_pool(disks, pvscan).await?;
let guid = create_pool(disks, pvscan, password.is_some()).await?;
create_all_fs(&guid, &datadir, password).await?;
export(&guid, datadir).await?;
Ok(guid)
@@ -38,6 +38,7 @@ where
pub async fn create_pool<I, P>(
disks: &I,
pvscan: &BTreeMap<PathBuf, Option<String>>,
encrypted: bool,
) -> Result<String, Error>
where
for<'a> &'a I: IntoIterator<Item = &'a P>,
@@ -62,13 +63,16 @@ where
.invoke(crate::ErrorKind::DiskManagement)
.await?;
}
let guid = format!(
let mut guid = format!(
"EMBASSY_{}",
base32::encode(
base32::Alphabet::RFC4648 { padding: false },
&rand::random::<[u8; 32]>(),
)
);
if !encrypted {
guid += "_UNENC";
}
let mut cmd = Command::new("vgcreate");
cmd.arg("-y").arg(&guid);
for disk in disks {
@@ -90,11 +94,8 @@ pub async fn create_fs<P: AsRef<Path>>(
datadir: P,
name: &str,
size: FsSize,
password: &str,
password: Option<&str>,
) -> Result<(), Error> {
tokio::fs::write(PASSWORD_PATH, password)
.await
.with_ctx(|_| (crate::ErrorKind::Filesystem, PASSWORD_PATH))?;
let mut cmd = Command::new("lvcreate");
match size {
FsSize::Gigabytes(a) => cmd.arg("-L").arg(format!("{}G", a)),
@@ -106,37 +107,38 @@ pub async fn create_fs<P: AsRef<Path>>(
.arg(guid)
.invoke(crate::ErrorKind::DiskManagement)
.await?;
let crypt_path = Path::new("/dev").join(guid).join(name);
Command::new("cryptsetup")
.arg("-q")
.arg("luksFormat")
.arg(format!("--key-file={}", PASSWORD_PATH))
.arg(format!("--keyfile-size={}", password.len()))
.arg(&crypt_path)
.invoke(crate::ErrorKind::DiskManagement)
.await?;
Command::new("cryptsetup")
.arg("-q")
.arg("luksOpen")
.arg(format!("--key-file={}", PASSWORD_PATH))
.arg(format!("--keyfile-size={}", password.len()))
.arg(&crypt_path)
.arg(format!("{}_{}", guid, name))
.invoke(crate::ErrorKind::DiskManagement)
.await?;
let mut blockdev_path = Path::new("/dev").join(guid).join(name);
if let Some(password) = password {
tokio::fs::write(PASSWORD_PATH, password)
.await
.with_ctx(|_| (crate::ErrorKind::Filesystem, PASSWORD_PATH))?;
Command::new("cryptsetup")
.arg("-q")
.arg("luksFormat")
.arg(format!("--key-file={}", PASSWORD_PATH))
.arg(format!("--keyfile-size={}", password.len()))
.arg(&blockdev_path)
.invoke(crate::ErrorKind::DiskManagement)
.await?;
Command::new("cryptsetup")
.arg("-q")
.arg("luksOpen")
.arg(format!("--key-file={}", PASSWORD_PATH))
.arg(format!("--keyfile-size={}", password.len()))
.arg(&blockdev_path)
.arg(format!("{}_{}", guid, name))
.invoke(crate::ErrorKind::DiskManagement)
.await?;
tokio::fs::remove_file(PASSWORD_PATH)
.await
.with_ctx(|_| (crate::ErrorKind::Filesystem, PASSWORD_PATH))?;
blockdev_path = Path::new("/dev/mapper").join(format!("{}_{}", guid, name));
}
Command::new("mkfs.btrfs")
.arg(Path::new("/dev/mapper").join(format!("{}_{}", guid, name)))
.arg(&blockdev_path)
.invoke(crate::ErrorKind::DiskManagement)
.await?;
mount(
Path::new("/dev/mapper").join(format!("{}_{}", guid, name)),
datadir.as_ref().join(name),
ReadWrite,
)
.await?;
tokio::fs::remove_file(PASSWORD_PATH)
.await
.with_ctx(|_| (crate::ErrorKind::Filesystem, PASSWORD_PATH))?;
mount(&blockdev_path, datadir.as_ref().join(name), ReadWrite).await?;
Ok(())
}
@@ -144,7 +146,7 @@ pub async fn create_fs<P: AsRef<Path>>(
pub async fn create_all_fs<P: AsRef<Path>>(
guid: &str,
datadir: P,
password: &str,
password: Option<&str>,
) -> Result<(), Error> {
create_fs(guid, &datadir, "main", MAIN_FS_SIZE, password).await?;
create_fs(
@@ -161,12 +163,14 @@ pub async fn create_all_fs<P: AsRef<Path>>(
#[instrument(skip_all)]
pub async fn unmount_fs<P: AsRef<Path>>(guid: &str, datadir: P, name: &str) -> Result<(), Error> {
unmount(datadir.as_ref().join(name)).await?;
Command::new("cryptsetup")
.arg("-q")
.arg("luksClose")
.arg(format!("{}_{}", guid, name))
.invoke(crate::ErrorKind::DiskManagement)
.await?;
if !guid.ends_with("_UNENC") {
Command::new("cryptsetup")
.arg("-q")
.arg("luksClose")
.arg(format!("{}_{}", guid, name))
.invoke(crate::ErrorKind::DiskManagement)
.await?;
}
Ok(())
}
@@ -203,7 +207,7 @@ pub async fn import<P: AsRef<Path>>(
guid: &str,
datadir: P,
repair: RepairStrategy,
password: &str,
mut password: Option<&str>,
) -> Result<RequiresReboot, Error> {
let scan = pvscan().await?;
if scan
@@ -261,46 +265,56 @@ pub async fn mount_fs<P: AsRef<Path>>(
datadir: P,
name: &str,
repair: RepairStrategy,
password: &str,
password: Option<&str>,
) -> Result<RequiresReboot, Error> {
tokio::fs::write(PASSWORD_PATH, password)
.await
.with_ctx(|_| (crate::ErrorKind::Filesystem, PASSWORD_PATH))?;
let crypt_path = Path::new("/dev").join(guid).join(name);
let orig_path = Path::new("/dev").join(guid).join(name);
let mut blockdev_path = orig_path.clone();
let full_name = format!("{}_{}", guid, name);
Command::new("cryptsetup")
.arg("-q")
.arg("luksOpen")
.arg(format!("--key-file={}", PASSWORD_PATH))
.arg(format!("--keyfile-size={}", password.len()))
.arg(&crypt_path)
.arg(&full_name)
.invoke(crate::ErrorKind::DiskManagement)
.await?;
let mapper_path = Path::new("/dev/mapper").join(&full_name);
let reboot = repair.fsck(&mapper_path).await?;
// Backup LUKS header if e2fsck succeeded
let luks_folder = Path::new("/media/embassy/config/luks");
tokio::fs::create_dir_all(luks_folder).await?;
let tmp_luks_bak = luks_folder.join(format!(".{full_name}.luks.bak.tmp"));
if tokio::fs::metadata(&tmp_luks_bak).await.is_ok() {
tokio::fs::remove_file(&tmp_luks_bak).await?;
if !guid.ends_with("_UNENC") {
let password = password.unwrap_or(DEFAULT_PASSWORD);
if let Some(parent) = Path::new(PASSWORD_PATH).parent() {
tokio::fs::create_dir_all(parent).await?;
}
tokio::fs::write(PASSWORD_PATH, password)
.await
.with_ctx(|_| (crate::ErrorKind::Filesystem, PASSWORD_PATH))?;
Command::new("cryptsetup")
.arg("-q")
.arg("luksOpen")
.arg(format!("--key-file={}", PASSWORD_PATH))
.arg(format!("--keyfile-size={}", password.len()))
.arg(&blockdev_path)
.arg(&full_name)
.invoke(crate::ErrorKind::DiskManagement)
.await?;
tokio::fs::remove_file(PASSWORD_PATH)
.await
.with_ctx(|_| (crate::ErrorKind::Filesystem, PASSWORD_PATH))?;
blockdev_path = Path::new("/dev/mapper").join(&full_name);
}
let luks_bak = luks_folder.join(format!("{full_name}.luks.bak"));
Command::new("cryptsetup")
.arg("-q")
.arg("luksHeaderBackup")
.arg("--header-backup-file")
.arg(&tmp_luks_bak)
.arg(&crypt_path)
.invoke(crate::ErrorKind::DiskManagement)
.await?;
tokio::fs::rename(&tmp_luks_bak, &luks_bak).await?;
mount(&mapper_path, datadir.as_ref().join(name), ReadWrite).await?;
let reboot = repair.fsck(&blockdev_path).await?;
tokio::fs::remove_file(PASSWORD_PATH)
.await
.with_ctx(|_| (crate::ErrorKind::Filesystem, PASSWORD_PATH))?;
if !guid.ends_with("_UNENC") {
// Backup LUKS header if e2fsck succeeded
let luks_folder = Path::new("/media/embassy/config/luks");
tokio::fs::create_dir_all(luks_folder).await?;
let tmp_luks_bak = luks_folder.join(format!(".{full_name}.luks.bak.tmp"));
if tokio::fs::metadata(&tmp_luks_bak).await.is_ok() {
tokio::fs::remove_file(&tmp_luks_bak).await?;
}
let luks_bak = luks_folder.join(format!("{full_name}.luks.bak"));
Command::new("cryptsetup")
.arg("-q")
.arg("luksHeaderBackup")
.arg("--header-backup-file")
.arg(&tmp_luks_bak)
.arg(&orig_path)
.invoke(crate::ErrorKind::DiskManagement)
.await?;
tokio::fs::rename(&tmp_luks_bak, &luks_bak).await?;
}
mount(&blockdev_path, datadir.as_ref().join(name), ReadWrite).await?;
Ok(reboot)
}
@@ -310,7 +324,7 @@ pub async fn mount_all_fs<P: AsRef<Path>>(
guid: &str,
datadir: P,
repair: RepairStrategy,
password: &str,
password: Option<&str>,
) -> Result<RequiresReboot, Error> {
let mut reboot = RequiresReboot(false);
reboot |= mount_fs(guid, &datadir, "main", repair, password).await?;

View File

@@ -324,11 +324,13 @@ pub async fn list(os: &OsPartitionInfo) -> Result<Vec<DiskInfo>, Error> {
if index.internal {
for part in index.parts {
let mut disk_info = disk_info(disk.clone()).await;
disk_info.logicalname = part;
let part_info = part_info(part).await;
disk_info.logicalname = part_info.logicalname.clone();
disk_info.capacity = part_info.capacity;
if let Some(g) = disk_guids.get(&disk_info.logicalname) {
disk_info.guid = g.clone();
} else {
disk_info.partitions = vec![part_info(disk_info.logicalname.clone()).await];
disk_info.partitions = vec![part_info];
}
res.push(disk_info);
}

View File

@@ -125,7 +125,7 @@ pub async fn attach(
} else {
RepairStrategy::Preen
},
DEFAULT_PASSWORD,
if guid.ends_with("_UNENC") { None } else { Some(DEFAULT_PASSWORD) },
)
.await?;
if tokio::fs::metadata(REPAIR_DISK_PATH).await.is_ok() {
@@ -337,12 +337,17 @@ pub async fn execute_inner(
recovery_source: Option<RecoverySource>,
recovery_password: Option<String>,
) -> Result<(Arc<String>, Hostname, OnionAddressV3, X509), Error> {
let encryption_password = if ctx.disable_encryption {
None
} else {
Some(DEFAULT_PASSWORD)
};
let guid = Arc::new(
crate::disk::main::create(
&[embassy_logicalname],
&pvscan().await?,
&ctx.datadir,
DEFAULT_PASSWORD,
encryption_password,
)
.await?,
);
@@ -350,7 +355,7 @@ pub async fn execute_inner(
&*guid,
&ctx.datadir,
RepairStrategy::Preen,
DEFAULT_PASSWORD,
encryption_password,
)
.await?;
@@ -418,7 +423,11 @@ async fn migrate(
&old_guid,
"/media/embassy/migrate",
RepairStrategy::Preen,
DEFAULT_PASSWORD,
if guid.ends_with("_UNENC") {
None
} else {
Some(DEFAULT_PASSWORD)
},
)
.await?;

View File

@@ -3,3 +3,4 @@ os-partitions:
root: /dev/mmcblk0p2
ethernet-interface: end0
wifi-interface: wlan0
disable-encryption: true