mirror of
https://github.com/philmmanjaro/alma.git
synced 2025-07-26 23:19:29 +02:00
Encryption (fix #3)
This commit is contained in:
parent
db9fdb29c6
commit
8c41b390a3
@ -17,6 +17,7 @@ This tool should be ran from an exiting Arch Linux installations. It depends on
|
|||||||
* Arch install scripts
|
* Arch install scripts
|
||||||
* mkfs.fat
|
* mkfs.fat
|
||||||
* mkfs.btrfs
|
* mkfs.btrfs
|
||||||
|
* *Optional*: cryptsetup
|
||||||
|
|
||||||
Dependencies will be handled for you if you install alma from AUR.
|
Dependencies will be handled for you if you install alma from AUR.
|
||||||
|
|
||||||
@ -42,6 +43,7 @@ sudo alma chroot /dev/disk/by-id/usb-Generic_USB_Flash_Disk-0:0
|
|||||||
### Flags
|
### Flags
|
||||||
* `-p / --extra-packages` - Specify extra packages to install. For example: `-p htop tmux`
|
* `-p / --extra-packages` - Specify extra packages to install. For example: `-p htop tmux`
|
||||||
* `-i / --interactive` - Drop you into interactive chroot to perform further customization
|
* `-i / --interactive` - Drop you into interactive chroot to perform further customization
|
||||||
|
* `-e / --encrypted-root` - Encrypt the root filesystem.
|
||||||
|
|
||||||
## What exactly does it do?
|
## What exactly does it do?
|
||||||
|
|
||||||
|
32
src/alma.rs
32
src/alma.rs
@ -1,31 +1,39 @@
|
|||||||
use super::block::BlockDevice;
|
use super::block::BlockDevice;
|
||||||
|
use super::cryptsetup::EncryptedDevice;
|
||||||
use super::error::{Error, ErrorKind};
|
use super::error::{Error, ErrorKind};
|
||||||
use super::mountstack::{Filesystem, MountStack};
|
use super::mountstack::{Filesystem, MountStack};
|
||||||
use failure::ResultExt;
|
use failure::ResultExt;
|
||||||
use log::info;
|
use log::{debug, info};
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
pub struct ALMA {
|
pub struct ALMA<'a> {
|
||||||
block: BlockDevice,
|
block: BlockDevice,
|
||||||
|
encrypted_root: Option<EncryptedDevice<'a>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ALMA {
|
impl<'a> ALMA<'a> {
|
||||||
pub fn new(block: BlockDevice) -> Self {
|
pub fn new(block: BlockDevice, encrypted_root: Option<EncryptedDevice<'a>>) -> Self {
|
||||||
Self { block }
|
Self {
|
||||||
|
block,
|
||||||
|
encrypted_root,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mount<'a>(&self, path: &'a Path) -> Result<MountStack<'a>, Error> {
|
pub fn mount<'b>(&self, path: &'b Path) -> Result<MountStack<'b>, Error> {
|
||||||
let mut mount_stack = MountStack::new();
|
let mut mount_stack = MountStack::new();
|
||||||
|
|
||||||
|
let root_device = if let Some(encrypted_root) = &self.encrypted_root {
|
||||||
|
PathBuf::from(encrypted_root.path())
|
||||||
|
} else {
|
||||||
|
self.block.partition_device_path(3)?
|
||||||
|
};
|
||||||
|
debug!("Root partition: {}", root_device.display());
|
||||||
|
|
||||||
info!("Mounting filesystems to {}", path.display());
|
info!("Mounting filesystems to {}", path.display());
|
||||||
mount_stack
|
mount_stack
|
||||||
.mount(
|
.mount(&root_device, path, Filesystem::Btrfs, None)
|
||||||
&PathBuf::from(&self.block.partition_device_path(3)?),
|
.context(ErrorKind::Mounting)?;
|
||||||
path,
|
|
||||||
Filesystem::Btrfs,
|
|
||||||
None,
|
|
||||||
).context(ErrorKind::Mounting)?;
|
|
||||||
|
|
||||||
let boot_point = path.join("boot");
|
let boot_point = path.join("boot");
|
||||||
if !boot_point.exists() {
|
if !boot_point.exists() {
|
||||||
|
68
src/cryptsetup.rs
Normal file
68
src/cryptsetup.rs
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
use super::error::{Error, ErrorKind};
|
||||||
|
use super::process::CommandExt;
|
||||||
|
use super::tool::Tool;
|
||||||
|
use log::{debug, warn};
|
||||||
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
|
pub struct EncryptedDevice<'a> {
|
||||||
|
cryptsetup: &'a Tool,
|
||||||
|
name: &'a str,
|
||||||
|
path: PathBuf,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> EncryptedDevice<'a> {
|
||||||
|
pub fn prepare(cryptsetup: &Tool, device: &Path) -> Result<(), Error> {
|
||||||
|
debug!("Preparing encrypted device in {}", device.display());
|
||||||
|
cryptsetup
|
||||||
|
.execute()
|
||||||
|
.arg("luksFormat")
|
||||||
|
.arg("-q")
|
||||||
|
.arg(device)
|
||||||
|
.run(ErrorKind::LuksSetup)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn open(
|
||||||
|
cryptsetup: &'a Tool,
|
||||||
|
device: &Path,
|
||||||
|
name: &'a str,
|
||||||
|
) -> Result<EncryptedDevice<'a>, Error> {
|
||||||
|
debug!("Opening encrypted device {} as {}", device.display(), name);
|
||||||
|
cryptsetup
|
||||||
|
.execute()
|
||||||
|
.arg("open")
|
||||||
|
.arg(device)
|
||||||
|
.arg(name)
|
||||||
|
.run(ErrorKind::LuksOpen)?;
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
cryptsetup,
|
||||||
|
name,
|
||||||
|
path: PathBuf::from("/dev/mapper").join(name),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn _close(&mut self) -> Result<(), Error> {
|
||||||
|
debug!("Closing encrypted device {}", self.name);
|
||||||
|
self.cryptsetup
|
||||||
|
.execute()
|
||||||
|
.arg("close")
|
||||||
|
.arg(self.name)
|
||||||
|
.run(ErrorKind::LuksClose)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn path(&self) -> &Path {
|
||||||
|
&self.path
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Drop for EncryptedDevice<'a> {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
if self._close().is_err() {
|
||||||
|
warn!("Error closing {}", self.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -58,6 +58,15 @@ pub enum ErrorKind {
|
|||||||
|
|
||||||
#[fail(display = "Failed umounting filesystems")]
|
#[fail(display = "Failed umounting filesystems")]
|
||||||
UmountFailure,
|
UmountFailure,
|
||||||
|
|
||||||
|
#[fail(display = "Error setting up an encrypted device")]
|
||||||
|
LuksSetup,
|
||||||
|
|
||||||
|
#[fail(display = "Error opening the encrypted device")]
|
||||||
|
LuksOpen,
|
||||||
|
|
||||||
|
#[fail(display = "Error closing the encrypted device")]
|
||||||
|
LuksClose,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Fail for Error {
|
impl Fail for Error {
|
||||||
|
95
src/main.rs
95
src/main.rs
@ -9,18 +9,21 @@ use nix::sys::signal;
|
|||||||
|
|
||||||
mod alma;
|
mod alma;
|
||||||
mod block;
|
mod block;
|
||||||
|
mod cryptsetup;
|
||||||
mod error;
|
mod error;
|
||||||
mod mountstack;
|
mod mountstack;
|
||||||
mod process;
|
mod process;
|
||||||
mod tool;
|
mod tool;
|
||||||
|
|
||||||
use alma::ALMA;
|
use alma::ALMA;
|
||||||
|
use cryptsetup::EncryptedDevice;
|
||||||
use error::*;
|
use error::*;
|
||||||
use failure::{Fail, ResultExt};
|
use failure::{Fail, ResultExt};
|
||||||
use log::{debug, error, info, warn};
|
use log::{debug, error, info, warn};
|
||||||
use process::CommandExt;
|
use process::CommandExt;
|
||||||
use simplelog::*;
|
use simplelog::*;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
|
use std::io::Write;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::process::exit;
|
use std::process::exit;
|
||||||
use std::thread;
|
use std::thread;
|
||||||
@ -32,7 +35,7 @@ use tool::Tool;
|
|||||||
static MKINITCPIO: &'static str = "MODULES=()
|
static MKINITCPIO: &'static str = "MODULES=()
|
||||||
BINARIES=()
|
BINARIES=()
|
||||||
FILES=()
|
FILES=()
|
||||||
HOOKS=(base udev block filesystems keyboard fsck)";
|
HOOKS=(base udev keyboard consolefont block encrypt filesystems keyboard fsck)";
|
||||||
|
|
||||||
static JOURNALD_CONF: &'static str = "
|
static JOURNALD_CONF: &'static str = "
|
||||||
[Journal]
|
[Journal]
|
||||||
@ -43,7 +46,8 @@ SystemMaxUse=16M
|
|||||||
#[derive(StructOpt)]
|
#[derive(StructOpt)]
|
||||||
#[structopt(name = "alma", about = "Arch Linux Mobile Appliance")]
|
#[structopt(name = "alma", about = "Arch Linux Mobile Appliance")]
|
||||||
struct App {
|
struct App {
|
||||||
#[structopt(short = "v", long = "verbose", help = "Verbose output")]
|
/// Verbose output
|
||||||
|
#[structopt(short = "v", long = "verbose")]
|
||||||
verbose: bool,
|
verbose: bool,
|
||||||
|
|
||||||
#[structopt(subcommand)]
|
#[structopt(subcommand)]
|
||||||
@ -72,6 +76,10 @@ struct CreateCommand {
|
|||||||
/// Enter interactive chroot before unmounting the drive
|
/// Enter interactive chroot before unmounting the drive
|
||||||
#[structopt(short = "i", long = "interactive")]
|
#[structopt(short = "i", long = "interactive")]
|
||||||
interactive: bool,
|
interactive: bool,
|
||||||
|
|
||||||
|
/// Encrypt the root partition
|
||||||
|
#[structopt(short = "e", long = "encrypted-root")]
|
||||||
|
encrypted_root: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(StructOpt)]
|
#[derive(StructOpt)]
|
||||||
@ -79,6 +87,10 @@ struct ChrootCommand {
|
|||||||
/// Path starting with /dev/disk/by-id for the USB drive
|
/// Path starting with /dev/disk/by-id for the USB drive
|
||||||
#[structopt(parse(from_os_str),)]
|
#[structopt(parse(from_os_str),)]
|
||||||
block_device: PathBuf,
|
block_device: PathBuf,
|
||||||
|
|
||||||
|
/// Open an encrypted root partition
|
||||||
|
#[structopt(short = "e", long = "encrypted-root")]
|
||||||
|
encrypted_root: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fix_fstab(fstab: &str) -> String {
|
fn fix_fstab(fstab: &str) -> String {
|
||||||
@ -96,6 +108,16 @@ fn create(command: CreateCommand) -> Result<(), Error> {
|
|||||||
let genfstab = Tool::find("genfstab")?;
|
let genfstab = Tool::find("genfstab")?;
|
||||||
let mkfat = Tool::find("mkfs.fat")?;
|
let mkfat = Tool::find("mkfs.fat")?;
|
||||||
let mkbtrfs = Tool::find("mkfs.btrfs")?;
|
let mkbtrfs = Tool::find("mkfs.btrfs")?;
|
||||||
|
let cryptsetup = if command.encrypted_root {
|
||||||
|
Some(Tool::find("cryptsetup")?)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
let blkid = if command.encrypted_root {
|
||||||
|
Some(Tool::find("blkid")?)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
let block_device = block::BlockDevice::from_path(command.block_device)?;
|
let block_device = block::BlockDevice::from_path(command.block_device)?;
|
||||||
|
|
||||||
@ -130,14 +152,28 @@ fn create(command: CreateCommand) -> Result<(), Error> {
|
|||||||
.run(ErrorKind::Formatting)?;
|
.run(ErrorKind::Formatting)?;
|
||||||
|
|
||||||
let root_partition = block_device.partition_device_path(3)?;
|
let root_partition = block_device.partition_device_path(3)?;
|
||||||
|
let encrypted_root = if let Some(cryptsetup) = &cryptsetup {
|
||||||
|
EncryptedDevice::prepare(&cryptsetup, &root_partition)?;
|
||||||
|
Some(EncryptedDevice::open(
|
||||||
|
cryptsetup,
|
||||||
|
&root_partition,
|
||||||
|
"alma_root",
|
||||||
|
)?)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
mkbtrfs
|
mkbtrfs
|
||||||
.execute()
|
.execute()
|
||||||
.arg("-f")
|
.arg("-f")
|
||||||
.arg(&root_partition)
|
.arg(if let Some(device) = &encrypted_root {
|
||||||
.run(ErrorKind::Formatting)?;
|
device.path()
|
||||||
|
} else {
|
||||||
|
&root_partition
|
||||||
|
}).run(ErrorKind::Formatting)?;
|
||||||
|
|
||||||
let alma = ALMA::new(block_device);
|
let alma = ALMA::new(block_device, encrypted_root);
|
||||||
let mut mount_stack = alma.mount(mount_point.path())?;
|
let mount_stack = alma.mount(mount_point.path())?;
|
||||||
|
|
||||||
info!("Bootstrapping system");
|
info!("Bootstrapping system");
|
||||||
pacstrap
|
pacstrap
|
||||||
@ -186,6 +222,30 @@ fn create(command: CreateCommand) -> Result<(), Error> {
|
|||||||
.args(&["mkinitcpio", "-p", "linux"])
|
.args(&["mkinitcpio", "-p", "linux"])
|
||||||
.run(ErrorKind::Initramfs)?;
|
.run(ErrorKind::Initramfs)?;
|
||||||
|
|
||||||
|
if cryptsetup.is_some() {
|
||||||
|
debug!("Setting up GRUB for an encrypted root partition");
|
||||||
|
|
||||||
|
let uuid = blkid
|
||||||
|
.unwrap()
|
||||||
|
.execute()
|
||||||
|
.arg(root_partition)
|
||||||
|
.args(&["-o", "value", "-s", "UUID"])
|
||||||
|
.run_text_output(ErrorKind::Partitioning)?;
|
||||||
|
let trimmed = uuid.trim();
|
||||||
|
debug!("Root partition UUID: {}", trimmed);
|
||||||
|
|
||||||
|
let mut grub_file = fs::OpenOptions::new()
|
||||||
|
.append(true)
|
||||||
|
.open(mount_point.path().join("etc/default/grub"))
|
||||||
|
.context(ErrorKind::Bootloader)?;
|
||||||
|
|
||||||
|
write!(
|
||||||
|
&mut grub_file,
|
||||||
|
"GRUB_CMDLINE_LINUX=\"cryptdevice=UUID={}:luks_root\"",
|
||||||
|
trimmed
|
||||||
|
).context(ErrorKind::Bootloader)?;
|
||||||
|
}
|
||||||
|
|
||||||
info!("Installing the Bootloader");
|
info!("Installing the Bootloader");
|
||||||
arch_chroot
|
arch_chroot
|
||||||
.execute()
|
.execute()
|
||||||
@ -205,18 +265,33 @@ fn create(command: CreateCommand) -> Result<(), Error> {
|
|||||||
info!("Unmounting filesystems");
|
info!("Unmounting filesystems");
|
||||||
mount_stack.umount()?;
|
mount_stack.umount()?;
|
||||||
|
|
||||||
info!("Installation succeeded. It is now safe to unplug your device.");
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn chroot(command: ChrootCommand) -> Result<(), Error> {
|
fn chroot(command: ChrootCommand) -> Result<(), Error> {
|
||||||
let arch_chroot = Tool::find("arch-chroot")?;
|
let arch_chroot = Tool::find("arch-chroot")?;
|
||||||
|
let cryptsetup = if command.encrypted_root {
|
||||||
|
Some(Tool::find("cryptsetup")?)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
let block_device = block::BlockDevice::from_path(command.block_device)?;
|
let block_device = block::BlockDevice::from_path(command.block_device)?;
|
||||||
|
|
||||||
let mount_point = tempdir().context(ErrorKind::TmpDirError)?;
|
let mount_point = tempdir().context(ErrorKind::TmpDirError)?;
|
||||||
let alma = ALMA::new(block_device);
|
let root_partition = block_device.partition_device_path(3)?;
|
||||||
let mut mount_stack = alma.mount(mount_point.path())?;
|
let encrypted_root = if let Some(cryptsetup) = &cryptsetup {
|
||||||
|
Some(EncryptedDevice::open(
|
||||||
|
cryptsetup,
|
||||||
|
&root_partition,
|
||||||
|
"alma_root",
|
||||||
|
)?)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
let alma = ALMA::new(block_device, encrypted_root);
|
||||||
|
let mount_stack = alma.mount(mount_point.path())?;
|
||||||
|
|
||||||
arch_chroot
|
arch_chroot
|
||||||
.execute()
|
.execute()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user