diff --git a/CHANGELOG.md b/CHANGELOG.md index ad45780..fae5c26 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,10 @@ generating a new salt. Please note that this changes nothing about the security posture of Userborn. If you provide a plaintext password to Userborn, there is nothing Userborn can do to protect it from leaking. +- You can now configure the path to the `nologin` binary via the compile-time + environment variable `USERBORN_NO_LOGIN_DEFAULT_PATH` and the runtime + variable `USERBORN_NO_LOGIN_PATH`. These values are used when no explicit + shell is provided in the user config. ## 0.2.0 diff --git a/README.md b/README.md index 66f1292..000fcfb 100644 --- a/README.md +++ b/README.md @@ -56,6 +56,33 @@ re-use is best illustrated by an example. Imagine the following scenario: - Userborn will discard entries in the shadow database that are not present in the passwd database. It will warn about these inconsistent entries. +## Configuration + +You can configure Userborn during runtime via the provided config file and via +environment variables. + +### Environment Variables + +- `USERBORN_NO_LOGIN_PATH`: Set this to the path of the `nologin` binary on + your system. This path is used when the user config doesn't specify a + `shell`. If this enviroment variable is set, its value overrides + `USERBORN_NO_LOGIN_DEFAULT_PATH`. + +## Building Userborn + +Runtime dependencies: + +- `libxcrypt` + +### Build-Time Parameters + +You can configure Userborn via compile-time environment variables: + +- `USERBORN_NO_LOGIN_DEFAULT_PATH`: Set this to the default path of the + `nologin` binary in your distro or system. If this is not set, the value + `/run/current-system/sw/bin/nologin` is used which will only make sense on + NixOS. + ## Comparison With Other Tools for Declarative User Management ### systemd-sysusers diff --git a/rust/userborn/src/main.rs b/rust/userborn/src/main.rs index 7f40ef6..5aed6df 100644 --- a/rust/userborn/src/main.rs +++ b/rust/userborn/src/main.rs @@ -17,8 +17,15 @@ use passwd::Passwd; use password::HashedPassword; use shadow::Shadow; -/// Path to the nologin binary. -const NO_LOGIN: &str = "/run/current-system/sw/bin/nologin"; +/// Fallback path to the nologin binary. +/// +/// This is used when `USERBORN_NO_LOGIN_PATH` is not set during runtime and +/// `USERBORN_NO_LOGIN_DEFAULT_PATH` hasn't been set during compilation. +const NO_LOGIN_FALLBACK: &str = "/run/current-system/sw/bin/nologin"; +/// Default path to the nolign binary. +/// +/// This can be configured via a compile-time environment variable. +const NO_LOGIN_DEFAULT: Option<&'static str> = option_env!("USERBORN_NO_LOGIN_DEFAULT_PATH"); const DEFAULT_DIRECTORY: &str = "/etc"; fn main() -> ExitCode { @@ -192,7 +199,10 @@ fn create_user( gid, user_config.description.clone().unwrap_or_default(), user_config.home.clone().unwrap_or_default(), - user_config.shell.clone().unwrap_or(NO_LOGIN.into()), + user_config.shell.clone().unwrap_or( + std::env::var("USERBORN_NO_LOGIN_PATH") + .unwrap_or(NO_LOGIN_DEFAULT.unwrap_or(NO_LOGIN_FALLBACK).into()), + ), ); let description = new_entry.describe(); @@ -391,6 +401,9 @@ mod tests { #[test] fn update_users_and_groups_across_generations() -> Result<()> { + // Explitly set this because the expected values depend on this. + std::env::set_var("USERBORN_NO_LOGIN_PATH", NO_LOGIN_FALLBACK); + let mut group_db = Group::default(); let mut passwd_db = Passwd::default(); let mut shadow_db = Shadow::default();