Add exclusive process lock to Kanidm to prevent accidental duplicate commands. (#1575)

This commit is contained in:
Firstyear 2023-04-26 21:09:18 +10:00 committed by GitHub
parent 2f4687765c
commit c670069db1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 39 additions and 2 deletions

11
Cargo.lock generated
View file

@ -1151,6 +1151,7 @@ version = "1.1.0-alpha.12-dev"
dependencies = [ dependencies = [
"clap", "clap",
"clap_complete", "clap_complete",
"fs2",
"kanidm_lib_file_permissions", "kanidm_lib_file_permissions",
"kanidm_proto", "kanidm_proto",
"kanidmd_core", "kanidmd_core",
@ -1519,6 +1520,16 @@ dependencies = [
"percent-encoding", "percent-encoding",
] ]
[[package]]
name = "fs2"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213"
dependencies = [
"libc",
"winapi",
]
[[package]] [[package]]
name = "futures" name = "futures"
version = "0.3.28" version = "0.3.28"

View file

@ -59,6 +59,7 @@ dialoguer = "0.10.4"
dyn-clone = "^1.0.11" dyn-clone = "^1.0.11"
fernet = "^0.2.1" fernet = "^0.2.1"
filetime = "^0.2.21" filetime = "^0.2.21"
fs2 = "^0.4.3"
futures = "^0.3.28" futures = "^0.3.28"
futures-concurrency = "^3.1.0" futures-concurrency = "^3.1.0"
futures-util = { version = "^0.3.21", features = ["sink"] } futures-util = { version = "^0.3.21", features = ["sink"] }

View file

@ -22,6 +22,7 @@ kanidm_proto.workspace = true
kanidmd_core.workspace = true kanidmd_core.workspace = true
kanidm_lib_file_permissions.workspace = true kanidm_lib_file_permissions.workspace = true
sketching.workspace = true sketching.workspace = true
fs2.workspace = true
clap = { workspace = true, features = ["env"] } clap = { workspace = true, features = ["env"] }
reqwest = { workspace = true } reqwest = { workspace = true }

View file

@ -14,7 +14,9 @@
#[global_allocator] #[global_allocator]
static ALLOC: tikv_jemallocator::Jemalloc = tikv_jemallocator::Jemalloc; static ALLOC: tikv_jemallocator::Jemalloc = tikv_jemallocator::Jemalloc;
use std::fs::metadata; use std::fs::{metadata, File};
// This works on both unix and windows.
use fs2::FileExt;
#[cfg(target_family = "unix")] #[cfg(target_family = "unix")]
use std::os::unix::fs::MetadataExt; use std::os::unix::fs::MetadataExt;
use std::path::PathBuf; use std::path::PathBuf;
@ -235,6 +237,25 @@ async fn main() -> ExitCode {
config.update_output_mode(opt.commands.commonopt().output_mode.to_owned().into()); config.update_output_mode(opt.commands.commonopt().output_mode.to_owned().into());
config.update_trust_x_forward_for(sconfig.trust_x_forward_for); config.update_trust_x_forward_for(sconfig.trust_x_forward_for);
// Okay - Lets now create our lock and go.
let klock_path = format!("{}.klock" ,sconfig.db_path.as_str());
let flock = match File::create(&klock_path) {
Ok(flock) => flock,
Err(e) => {
error!("ERROR: Refusing to start - unable to create kanidm exclusive lock at {} - {:?}", klock_path, e);
return ExitCode::FAILURE
}
};
match flock.try_lock_exclusive() {
Ok(()) => debug!("Acquired kanidm exclusive lock"),
Err(e) => {
error!("ERROR: Refusing to start - unable to lock kanidm exclusive lock at {} - {:?}", klock_path, e);
error!("Is another kanidm process running?");
return ExitCode::FAILURE
}
};
/* /*
// Apply any cli overrides, normally debug level. // Apply any cli overrides, normally debug level.
if opt.commands.commonopt().debug.as_ref() { if opt.commands.commonopt().debug.as_ref() {

View file

@ -1440,7 +1440,10 @@ impl IdlSqlite {
// Enable WAL mode, which is just faster and better for our needs. // Enable WAL mode, which is just faster and better for our needs.
let mut flags = OpenFlags::default(); let mut flags = OpenFlags::default();
// Open with multi thread flags and locking options. // Open with multi thread flags and locking options.
if cfg!(test) {
flags.insert(OpenFlags::SQLITE_OPEN_NO_MUTEX); flags.insert(OpenFlags::SQLITE_OPEN_NO_MUTEX);
};
// We need to run vacuum in the setup else we hit sqlite lock conditions. // We need to run vacuum in the setup else we hit sqlite lock conditions.
if vacuum { if vacuum {