Skip to content
Snippets Groups Projects
Verified Commit 891dcbf9 authored by David Runge's avatar David Runge :chipmunk:
Browse files

feat: Rely on `signstar-common` crate for default locations


Signed-off-by: default avatarDavid Runge <dvzrv@archlinux.org>
parent c28d3f0e
No related branches found
No related tags found
1 merge request!181feat: Add `signstar-common` crate to provide common facilities
Pipeline #122529 passed
......@@ -3148,6 +3148,7 @@ dependencies = [
"clap",
"nethsm-config",
"nix",
"signstar-common",
"strum 0.27.1",
"sysinfo 0.33.0",
"thiserror 2.0.11",
......
......@@ -13,6 +13,7 @@ version = "0.1.2"
clap = { workspace = true, features = ["cargo", "derive", "env"] }
nethsm-config.workspace = true
nix = { version = "0.29.0", features = ["user"] }
signstar-common.workspace = true
strum.workspace = true
sysinfo = "0.33.0"
thiserror.workspace = true
use clap::{Parser, crate_name};
use signstar_common::{
config::{
get_default_config_file_path,
get_etc_override_config_file_path,
get_run_override_config_file_path,
get_usr_local_override_config_file_path,
},
ssh::{get_ssh_authorized_key_base_dir, get_sshd_config_dropin_dir},
system_user::get_home_base_dir_path,
};
use strum::VariantNames;
use crate::{
ConfigPath,
DEFAULT_CONFIG_FILE,
ETC_OVERRIDE_CONFIG_FILE,
HOME_BASE_DIR,
RUN_OVERRIDE_CONFIG_FILE,
SSH_AUTHORIZED_KEY_BASE_DIR,
SSHD_DROPIN_CONFIG_DIR,
SshForceCommand,
USR_LOCAL_OVERRIDE_CONFIG_FILE,
};
use crate::{ConfigPath, SshForceCommand};
pub const BIN_NAME: &str = crate_name!();
const SSH_FORCE_COMMAND_VARIANTS: &[&str] = SshForceCommand::VARIANTS;
......@@ -30,25 +30,32 @@ It creates system users and their integration based on a central configuration f
By default, one of the following configuration files is used if it exists, in the following order:
- \"{USR_LOCAL_OVERRIDE_CONFIG_FILE}\"
- {:?}
- \"{RUN_OVERRIDE_CONFIG_FILE}\"
- {:?}
- \"{ETC_OVERRIDE_CONFIG_FILE}\"
- {:?}
If none of the above are found, the default location \"{DEFAULT_CONFIG_FILE}\" is used.
If none of the above are found, the default location {:?} is used.
Alternatively a custom configuration file location can be specified using the \"--config\"/ \"-c\" option.
System users, if they don't exist already, are created with the help of `useradd`.
The users are created without a passphrase and setup with a home below \"{HOME_BASE_DIR}\".
The users are created without a passphrase and setup with a home below {:?}.
However, their home directory is not created automatically.
The system user accounts are then unlocked with the help of `usermod`.
For each system user a tmpfiles.d integration is provided below \"/usr/lib/tmpfiles.d\", to allow automatic creation of their home directory.
If the used configuration file associates the system user with SSH public keys, a dedicated \"authorized_keys\" file containing the SSH public keys for the user is created below \"{SSH_AUTHORIZED_KEY_BASE_DIR}\".
Additionally, an \"sshd_config\" drop-in configuration is created below \"{SSHD_DROPIN_CONFIG_DIR}\".
If the used configuration file associates the system user with SSH public keys, a dedicated \"authorized_keys\" file containing the SSH public keys for the user is created below {:?}.
Additionally, an \"sshd_config\" drop-in configuration is created below {:?}.
This \"sshd_config\" drop-in configuration enforces the use of the user's \"authorized_keys\" and the use of a specific command (i.e. one of {SSH_FORCE_COMMAND_VARIANTS:?}) depending on the user's role.",
),
get_usr_local_override_config_file_path(),
get_run_override_config_file_path(),
get_etc_override_config_file_path(),
get_default_config_file_path(),
get_home_base_dir_path(),
get_ssh_authorized_key_base_dir(),
get_sshd_config_dropin_dir(),
)
)]
pub struct Cli {
#[arg(
......@@ -61,14 +68,18 @@ If specified, the custom configuration file is used instead of the default confi
If unspecified, one of the following configuration files is used if it exists, in the following order:
- \"{USR_LOCAL_OVERRIDE_CONFIG_FILE}\"
- {:?}
- \"{RUN_OVERRIDE_CONFIG_FILE}\"
- {:?}
- \"{ETC_OVERRIDE_CONFIG_FILE}\"
- {:?}
If none of the above are found, the default location \"{DEFAULT_CONFIG_FILE}\" is used.
"),
If none of the above are found, the default location {:?} is used.",
get_usr_local_override_config_file_path(),
get_run_override_config_file_path(),
get_etc_override_config_file_path(),
get_default_config_file_path(),
),
long,
short
)]
......
......@@ -8,18 +8,15 @@ use std::{
use nethsm_config::{HermeticParallelConfig, SystemUserId, UserMapping};
use nix::unistd::User;
use signstar_common::{
config::get_config_file_or_default,
ssh::{get_ssh_authorized_key_base_dir, get_sshd_config_dropin_dir},
system_user::get_home_base_dir_path,
};
use sysinfo::{Pid, System};
pub mod cli;
pub static ETC_OVERRIDE_CONFIG_FILE: &str = "/etc/signstar/config.toml";
pub static RUN_OVERRIDE_CONFIG_FILE: &str = "/run/signstar/config.toml";
pub static USR_LOCAL_OVERRIDE_CONFIG_FILE: &str = "/usr/local/share/signstar/config.toml";
pub static DEFAULT_CONFIG_FILE: &str = "/usr/share/signstar/config.toml";
pub static SSH_AUTHORIZED_KEY_BASE_DIR: &str = "/etc/ssh";
pub static SSHD_DROPIN_CONFIG_DIR: &str = "/etc/ssh/sshd_config.d";
pub static HOME_BASE_DIR: &str = "/var/lib/signstar/home";
#[derive(Debug, thiserror::Error)]
pub enum Error {
/// A config error
......@@ -64,6 +61,16 @@ pub enum Error {
#[error("The string {0} could not be converted to a \"sysinfo::Uid\"")]
SysUidFromStr(String),
/// A `Path` value for a tmpfiles.d integration is not valid.
#[error(
"The Path value {path} for the tmpfiles.d integration for {user} is not valid:\n{reason}"
)]
TmpfilesDPath {
path: String,
user: SystemUserId,
reason: &'static str,
},
/// Adding a user failed
#[error("Adding user {user} failed:\n{source}")]
UserAdd {
......@@ -109,12 +116,7 @@ pub enum Error {
/// The configuration file path for the application.
///
/// If the path exists and is a file, one of the following configuration file locations is used:
/// - [`ETC_OVERRIDE_CONFIG_FILE`]
/// - [`RUN_OVERRIDE_CONFIG_FILE`]
/// - [`USR_LOCAL_OVERRIDE_CONFIG_FILE`]
///
/// If none of the above is found, [`DEFAULT_CONFIG_FILE`] is used (even if it doesn't exist!).
/// The configuration file location is defined by the behavior of [`get_config_file_or_default`].
#[derive(Clone, Debug)]
pub struct ConfigPath(PathBuf);
......@@ -133,25 +135,10 @@ impl AsRef<Path> for ConfigPath {
impl Default for ConfigPath {
/// Returns the default [`ConfigPath`].
///
/// If the path exists and is a file, one of the following configuration file locations is used:
/// - [`ETC_OVERRIDE_CONFIG_FILE`]
/// - [`RUN_OVERRIDE_CONFIG_FILE`]
/// - [`USR_LOCAL_OVERRIDE_CONFIG_FILE`]
///
/// If none of the above is found, [`DEFAULT_CONFIG_FILE`] is used (even if it doesn't exist!).
/// Uses [`get_config_file_or_default`] to find the first usable configuration file path, or the
/// default if none is found.
fn default() -> Self {
for config_file in [
ETC_OVERRIDE_CONFIG_FILE,
RUN_OVERRIDE_CONFIG_FILE,
USR_LOCAL_OVERRIDE_CONFIG_FILE,
] {
let config = PathBuf::from(config_file);
if config.is_file() {
return Self(config);
}
}
Self(PathBuf::from(DEFAULT_CONFIG_FILE))
Self(get_config_file_or_default())
}
}
......@@ -308,8 +295,8 @@ pub fn ensure_root() -> Result<(), Error> {
///
/// Works on the [`UserMapping`]s of the provided `config` and creates system users for all
/// mappings, that define system users, if they don't exist on the system yet.
/// System users are created unlocked, without passphrase, with their homes located in
/// [`HOME_BASE_DIR`].
/// System users are created unlocked, without passphrase, with their homes located in the directory
/// returned by [`get_home_base_dir_path`].
/// The home directories of users are not created upon user creation, but instead a [tmpfiles.d]
/// configuration is added for them to automate their creation upon system boot.
///
......@@ -354,17 +341,17 @@ pub fn create_system_users(config: &HermeticParallelConfig) -> Result<(), Error>
continue;
}
let home_base_dir = get_home_base_dir_path();
// add user, but do not create its home
print!("Creating user \"{user}\"...");
let user_add = Command::new("useradd")
.args([
"--base-dir",
HOME_BASE_DIR,
"--user-group",
"--shell",
"/usr/bin/bash",
user.as_ref(),
])
.arg("--base-dir")
.arg(home_base_dir.as_path())
.arg("--user-group")
.arg("--shell")
.arg("/usr/bin/bash")
.arg(user.as_ref())
.output()
.map_err(|error| Error::UserAdd {
user: user.clone(),
......@@ -407,8 +394,25 @@ pub fn create_system_users(config: &HermeticParallelConfig) -> Result<(), Error>
user: user.clone(),
source,
})?;
// ensure that the `Path` component in the tmpfiles.d file
// - has whitespace replaced with a c-style escape
// - does not contain specifiers
let home_dir = {
let home_dir =
format!("{}/{user}", home_base_dir.to_string_lossy()).replace(" ", "\\x20");
if home_dir.contains("%") {
return Err(Error::TmpfilesDPath {
path: home_dir.clone(),
user: user.clone(),
reason: "Specifiers (%) are not supported at this point.",
});
}
home_dir
};
buffer
.write_all(format!("d {HOME_BASE_DIR}/{user} 700 {user} {user}\n").as_bytes())
.write_all(format!("d {home_dir} 700 {user} {user}\n",).as_bytes())
.map_err(|source| Error::WriteTmpfilesD {
user: user.clone(),
source,
......@@ -422,14 +426,14 @@ pub fn create_system_users(config: &HermeticParallelConfig) -> Result<(), Error>
// add SSH authorized keys file user in system-wide location
print!("Adding SSH authorized_keys file for user \"{user}\"...");
{
let filename = format!(
"{SSH_AUTHORIZED_KEY_BASE_DIR}/signstar-user-{user}.authorized_keys"
);
let mut buffer =
File::create(filename).map_err(|source| Error::WriteAuthorizedKeys {
user: user.clone(),
source,
})?;
let mut buffer = File::create(
get_ssh_authorized_key_base_dir()
.join(format!("signstar-user-{user}.authorized_keys")),
)
.map_err(|source| Error::WriteAuthorizedKeys {
user: user.clone(),
source,
})?;
buffer
.write_all(
(authorized_keys
......@@ -450,9 +454,9 @@ pub fn create_system_users(config: &HermeticParallelConfig) -> Result<(), Error>
// add sshd_config drop-in configuration for user
print!("Adding sshd_config drop-in configuration for user \"{user}\"...");
{
let mut buffer = File::create(format!(
"{SSHD_DROPIN_CONFIG_DIR}/10-signstar-user-{user}.conf"
))
let mut buffer = File::create(
get_sshd_config_dropin_dir().join(format!("10-signstar-user-{user}.conf")),
)
.map_err(|source| Error::WriteSshdConfig {
user: user.clone(),
source,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment