From 8917449b70a11a29f3d57361b0f386b7f61439fc Mon Sep 17 00:00:00 2001 From: oddlama Date: Sat, 19 Aug 2023 18:29:46 +0200 Subject: [PATCH] feat: add kanidm secret manipulator --- .../meta/kanidm-secret-manipulator/Cargo.lock | 211 ++++++++++++++++++ .../meta/kanidm-secret-manipulator/Cargo.toml | 10 + .../kanidm-secret-manipulator/src/main.rs | 103 +++++++++ 3 files changed, 324 insertions(+) create mode 100644 modules/meta/kanidm-secret-manipulator/Cargo.lock create mode 100644 modules/meta/kanidm-secret-manipulator/Cargo.toml create mode 100644 modules/meta/kanidm-secret-manipulator/src/main.rs diff --git a/modules/meta/kanidm-secret-manipulator/Cargo.lock b/modules/meta/kanidm-secret-manipulator/Cargo.lock new file mode 100644 index 0000000..cc2d562 --- /dev/null +++ b/modules/meta/kanidm-secret-manipulator/Cargo.lock @@ -0,0 +1,211 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "ahash" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" +dependencies = [ + "cfg-if", + "once_cell", + "version_check", +] + +[[package]] +name = "allocator-api2" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" + +[[package]] +name = "anyhow" +version = "1.0.75" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" + +[[package]] +name = "bitflags" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "fallible-iterator" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" + +[[package]] +name = "fallible-streaming-iterator" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" + +[[package]] +name = "hashbrown" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" +dependencies = [ + "ahash", + "allocator-api2", +] + +[[package]] +name = "hashlink" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "312f66718a2d7789ffef4f4b7b213138ed9f1eb3aa1d0d82fc99f88fb3ffd26f" +dependencies = [ + "hashbrown", +] + +[[package]] +name = "itoa" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" + +[[package]] +name = "kanidm-secret-manipulator" +version = "1.0.0" +dependencies = [ + "anyhow", + "rusqlite", + "serde", + "serde_json", +] + +[[package]] +name = "libsqlite3-sys" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afc22eff61b133b115c6e8c74e818c628d6d5e7a502afea6f64dee076dd94326" +dependencies = [ + "pkg-config", + "vcpkg", +] + +[[package]] +name = "once_cell" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" + +[[package]] +name = "pkg-config" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" + +[[package]] +name = "proc-macro2" +version = "1.0.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rusqlite" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "549b9d036d571d42e6e85d1c1425e2ac83491075078ca9a15be021c56b1641f2" +dependencies = [ + "bitflags", + "fallible-iterator", + "fallible-streaming-iterator", + "hashlink", + "libsqlite3-sys", + "smallvec", +] + +[[package]] +name = "ryu" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" + +[[package]] +name = "serde" +version = "1.0.183" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32ac8da02677876d532745a130fc9d8e6edfa81a269b107c5b00829b91d8eb3c" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.183" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aafe972d60b0b9bee71a91b92fee2d4fb3c9d7e8f6b179aa99f27203d99a4816" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.105" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "693151e1ac27563d6dbcec9dee9fbd5da8539b20fa14ad3752b2e6d363ace360" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "smallvec" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" + +[[package]] +name = "syn" +version = "2.0.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c324c494eba9d92503e6f1ef2e6df781e78f6a7705a0202d9801b198807d518a" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" diff --git a/modules/meta/kanidm-secret-manipulator/Cargo.toml b/modules/meta/kanidm-secret-manipulator/Cargo.toml new file mode 100644 index 0000000..4a8d17a --- /dev/null +++ b/modules/meta/kanidm-secret-manipulator/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "kanidm-secret-manipulator" +version = "1.0.0" +edition = "2021" + +[dependencies] +anyhow = "1.0.75" +rusqlite = "0.29.0" +serde = { version = "1.0.183", features = ["derive"] } +serde_json = "1.0.105" diff --git a/modules/meta/kanidm-secret-manipulator/src/main.rs b/modules/meta/kanidm-secret-manipulator/src/main.rs new file mode 100644 index 0000000..387a489 --- /dev/null +++ b/modules/meta/kanidm-secret-manipulator/src/main.rs @@ -0,0 +1,103 @@ +use anyhow::{Context, Result}; +use rusqlite::{params, Connection}; +use serde::Deserialize; +use std::collections::HashMap; +use std::fs::File; + +#[derive(Debug, Deserialize)] +struct SecretMappings { + oauth2_basic_secrets: HashMap, +} + +fn main() -> Result<()> { + // Read command-line arguments + let args: Vec = std::env::args().collect(); + if args.len() != 3 { + eprintln!("Usage: kanidm-secret-manipulator "); + std::process::exit(1); + } + + // Open JSON mappings file + let mappings_file = File::open(&args[2]).context("Failed to open mappings file")?; + let mut secret_mappings: SecretMappings = + serde_json::from_reader(mappings_file).context("Failed to parse mappings file")?; + + // Open SQLite database + let db_path = &args[1]; + let conn = Connection::open(db_path) + .with_context(|| format!("Failed to open database: {}", db_path))?; + + // Prepare statement to update rows + let mut update_stmt = conn + .prepare("UPDATE id2entry SET data = ? WHERE id = ?") + .context("Failed to prepare update statement")?; + + // Iterate over rows and update secrets + let mut stmt = conn + .prepare("SELECT id, data FROM id2entry") + .context("Failed to prepare SELECT statement")?; + + let rows = stmt + .query_map([], |row| { + let id: i64 = row.get(0)?; + let data: Vec = row.get(1)?; + + Ok((id, data)) + }) + .context("Failed to execute SELECT statement")?; + + for row in rows { + let (id, data) = row?; + let mut json_data: serde_json::Value = serde_json::from_slice(&data)?; + + // Clone paths for updating + let oauth2_rs_name_path = json_data + .pointer("/ent/V2/attrs/oauth2_rs_name/N8/0") + .and_then(|value| value.as_str()) + .map(|value| value.to_string()); // Clone the value + let oauth2_rs_basic_secret_path = "/ent/V2/attrs/oauth2_rs_basic_secret/RU"; + + if let Some(oauth2_rs_name) = oauth2_rs_name_path { + if let Some(secret_path) = secret_mappings.oauth2_basic_secrets.remove(&oauth2_rs_name) + { + match std::fs::read_to_string(&secret_path) { + Ok(secret) => { + let secret = secret.trim(); + + // Update the cloned JSON data + if let Some(value) = json_data.pointer_mut(oauth2_rs_basic_secret_path) { + *value = serde_json::Value::String(secret.to_string()); + } + + // Update the row in the database + update_stmt + .execute(params![serde_json::to_vec(&json_data)?, id]) + .context( + "Failed to update oauth2 service '{oauth2_rs_name}' in database", + )?; + + println!("oauth2: Updated {oauth2_rs_name}"); + } + Err(e) => eprintln!( + "oauth2: Could not update {oauth2_rs_name} with {secret_path}: {e}" + ), + } + } + } + } + + // Print missing items + if !secret_mappings.oauth2_basic_secrets.is_empty() { + eprintln!( + "oauth2: Skipped update of missing services: {}", + secret_mappings + .oauth2_basic_secrets + .keys() + .cloned() + .collect::>() + .join(", ") + ); + } + + Ok(()) +}