From 9d78192fbfa58a939898db27dfcd9d6941393099 Mon Sep 17 00:00:00 2001 From: "Adam C. Stephens" Date: Fri, 1 Aug 2025 15:07:31 -0400 Subject: [PATCH 1/4] kanidm_1_7: init at 1.7.0 https://github.com/kanidm/kanidm/releases/tag/v1.7.0 --- pkgs/by-name/ka/kanidm/1_5.nix | 1 - pkgs/by-name/ka/kanidm/1_6.nix | 1 - pkgs/by-name/ka/kanidm/1_7.nix | 5 + pkgs/by-name/ka/kanidm/generic.nix | 86 ++++------ .../1_5/oauth2-basic-secret-modify.patch | 0 .../1_5/recover-account.patch | 0 .../1_6/oauth2-basic-secret-modify.patch | 0 .../1_6/recover-account.patch | 0 .../1_7/oauth2-basic-secret-modify.patch | 159 ++++++++++++++++++ .../1_7/recover-account.patch | 122 ++++++++++++++ pkgs/top-level/all-packages.nix | 5 + 11 files changed, 326 insertions(+), 53 deletions(-) create mode 100644 pkgs/by-name/ka/kanidm/1_7.nix rename pkgs/by-name/ka/kanidm/{patches => provision-patches}/1_5/oauth2-basic-secret-modify.patch (100%) rename pkgs/by-name/ka/kanidm/{patches => provision-patches}/1_5/recover-account.patch (100%) rename pkgs/by-name/ka/kanidm/{patches => provision-patches}/1_6/oauth2-basic-secret-modify.patch (100%) rename pkgs/by-name/ka/kanidm/{patches => provision-patches}/1_6/recover-account.patch (100%) create mode 100644 pkgs/by-name/ka/kanidm/provision-patches/1_7/oauth2-basic-secret-modify.patch create mode 100644 pkgs/by-name/ka/kanidm/provision-patches/1_7/recover-account.patch diff --git a/pkgs/by-name/ka/kanidm/1_5.nix b/pkgs/by-name/ka/kanidm/1_5.nix index 3d45f6b1e923..7b549c0b5186 100644 --- a/pkgs/by-name/ka/kanidm/1_5.nix +++ b/pkgs/by-name/ka/kanidm/1_5.nix @@ -2,6 +2,5 @@ import ./generic.nix { version = "1.5.0"; hash = "sha256-swrqyjA7Wgq17vd+753LDFcXrSFixVNLhTvj1bhG3DU="; cargoHash = "sha256-72IwS8Nk1y6xDH9y8JW2LpbhFWaq0tpORx7JQSCF5/M="; - patchDir = ./patches/1_5; unsupported = true; } diff --git a/pkgs/by-name/ka/kanidm/1_6.nix b/pkgs/by-name/ka/kanidm/1_6.nix index b7ebd14a9d2c..4253cebff2a0 100644 --- a/pkgs/by-name/ka/kanidm/1_6.nix +++ b/pkgs/by-name/ka/kanidm/1_6.nix @@ -2,5 +2,4 @@ import ./generic.nix { version = "1.6.4"; hash = "sha256-ui3w1HDHXHARsjQ3WtJfZbM7Xgg3ODnUneXJMQwaOMw="; cargoHash = "sha256-KJGELBzScwsLd6g3GR9Vk0nfDU2EjZBfXwlXJ+bZb1k="; - patchDir = ./patches/1_6; } diff --git a/pkgs/by-name/ka/kanidm/1_7.nix b/pkgs/by-name/ka/kanidm/1_7.nix new file mode 100644 index 000000000000..47d68762b764 --- /dev/null +++ b/pkgs/by-name/ka/kanidm/1_7.nix @@ -0,0 +1,5 @@ +import ./generic.nix { + version = "1.7.0"; + hash = "sha256-JM5C0tCvo4Lq06bqil8M35YnFMoQFjzA/J30gZOs4fU="; + cargoHash = "sha256-MvBjj/6ph+i29dZGtaysHHgRk03P8sMePXdIm+v2tpw="; +} diff --git a/pkgs/by-name/ka/kanidm/generic.nix b/pkgs/by-name/ka/kanidm/generic.nix index cf33675556ee..926452422080 100644 --- a/pkgs/by-name/ka/kanidm/generic.nix +++ b/pkgs/by-name/ka/kanidm/generic.nix @@ -2,8 +2,6 @@ version, hash, cargoHash, - patchDir, - extraMeta ? { }, unsupported ? false, }: @@ -35,8 +33,17 @@ let arch = if stdenv.hostPlatform.isx86_64 then "x86_64" else "generic"; + + versionUnderscored = builtins.replaceStrings [ "." ] [ "_" ] ( + lib.versions.majorMinor kanidm.version + ); + + provisionPatches = [ + (./. + "/provision-patches/${versionUnderscored}/oauth2-basic-secret-modify.patch") + (./. + "/provision-patches/${versionUnderscored}/recover-account.patch") + ]; in -rustPlatform.buildRustPackage rec { +rustPlatform.buildRustPackage (finalAttrs: { pname = "kanidm" + (lib.optionalString enableSecretProvisioning "-with-secret-provisioning"); inherit version cargoHash; @@ -49,16 +56,13 @@ rustPlatform.buildRustPackage rec { inherit hash; }; - KANIDM_BUILD_PROFILE = "release_nixpkgs_${arch}"; + env.KANIDM_BUILD_PROFILE = "release_nixpkgs_${arch}"; - patches = lib.optionals enableSecretProvisioning [ - "${patchDir}/oauth2-basic-secret-modify.patch" - "${patchDir}/recover-account.patch" - ]; + patches = lib.optionals enableSecretProvisioning provisionPatches; postPatch = let - format = (formats.toml { }).generate "${KANIDM_BUILD_PROFILE}.toml"; + format = (formats.toml { }).generate "${finalAttrs.env.KANIDM_BUILD_PROFILE}.toml"; socket_path = if stdenv.hostPlatform.isLinux then "/run/kanidmd/sock" else "/var/run/kanidm.socket"; profile = { cpu_flags = if stdenv.hostPlatform.isx86_64 then "x86_64_legacy" else "none"; @@ -70,23 +74,11 @@ rustPlatform.buildRustPackage rec { server_admin_bind_path = socket_path; server_config_path = "/etc/kanidm/server.toml"; server_ui_pkg_path = "@htmx_ui_pkg_path@"; - } - // lib.optionalAttrs (lib.versionOlder version "1.5") { - admin_bind_path = socket_path; - default_config_path = "/etc/kanidm/server.toml"; - default_unix_shell_path = "${lib.getBin bashInteractive}/bin/bash"; - htmx_ui_pkg_path = "@htmx_ui_pkg_path@"; - } - // lib.optionalAttrs (lib.versions.majorMinor version == "1.3") { - web_ui_pkg_path = "@web_ui_pkg_path@"; }; in '' - cp ${format profile} libs/profiles/${KANIDM_BUILD_PROFILE}.toml - substituteInPlace libs/profiles/${KANIDM_BUILD_PROFILE}.toml --replace-fail '@htmx_ui_pkg_path@' "$out/ui/hpkg" - '' - + lib.optionalString (lib.versions.majorMinor version == "1.3") '' - substituteInPlace libs/profiles/${KANIDM_BUILD_PROFILE}.toml --replace-fail '@web_ui_pkg_path@' "$out/ui/pkg" + cp ${format profile} libs/profiles/${finalAttrs.env.KANIDM_BUILD_PROFILE}.toml + substituteInPlace libs/profiles/${finalAttrs.env.KANIDM_BUILD_PROFILE}.toml --replace-fail '@htmx_ui_pkg_path@' "$out/ui/hpkg" ''; nativeBuildInputs = [ @@ -108,9 +100,6 @@ rustPlatform.buildRustPackage rec { postBuild = '' mkdir -p $out/ui cp -r server/core/static $out/ui/hpkg - '' - + lib.optionalString (lib.versions.majorMinor version == "1.3") '' - cp -r server/web_ui/pkg $out/ui/pkg ''; # Upstream runs with the Rust equivalent of -Werror, @@ -148,9 +137,7 @@ rustPlatform.buildRustPackage rec { "-vr" "v([0-9\\.]*)" "--override-filename" - "pkgs/by-name/ka/kanidm/${ - builtins.replaceStrings [ "." ] [ "_" ] (lib.versions.majorMinor kanidm.version) - }.nix" + "pkgs/by-name/ka/kanidm/${versionUnderscored}.nix" ]; }); @@ -161,26 +148,23 @@ rustPlatform.buildRustPackage rec { # can take over 4 hours on 2 cores and needs 16GB+ RAM requiredSystemFeatures = [ "big-parallel" ]; - meta = - with lib; - { - changelog = "https://github.com/kanidm/kanidm/releases/tag/v${version}"; - description = "Simple, secure and fast identity management platform"; - homepage = "https://github.com/kanidm/kanidm"; - license = licenses.mpl20; - platforms = platforms.linux ++ platforms.darwin; - maintainers = with maintainers; [ - adamcstephens - Flakebi - ]; - knownVulnerabilities = lib.optionals unsupported [ - '' - kanidm ${version} has reached EOL. + meta = with lib; { + changelog = "https://github.com/kanidm/kanidm/releases/tag/v${version}"; + description = "Simple, secure and fast identity management platform"; + homepage = "https://github.com/kanidm/kanidm"; + license = licenses.mpl20; + platforms = platforms.linux ++ platforms.darwin; + maintainers = with maintainers; [ + adamcstephens + Flakebi + ]; + knownVulnerabilities = lib.optionals unsupported [ + '' + kanidm ${version} has reached EOL. - Please upgrade by verifying `kanidmd domain upgrade-check` and choosing the next version with `services.kanidm.package = pkgs.kanidm_1_x;` - See upgrade guide at https://kanidm.github.io/kanidm/master/server_updates.html - '' - ]; - } - // extraMeta; -} + Please upgrade by verifying `kanidmd domain upgrade-check` and choosing the next version with `services.kanidm.package = pkgs.kanidm_1_x;` + See upgrade guide at https://kanidm.github.io/kanidm/master/server_updates.html + '' + ]; + }; +}) diff --git a/pkgs/by-name/ka/kanidm/patches/1_5/oauth2-basic-secret-modify.patch b/pkgs/by-name/ka/kanidm/provision-patches/1_5/oauth2-basic-secret-modify.patch similarity index 100% rename from pkgs/by-name/ka/kanidm/patches/1_5/oauth2-basic-secret-modify.patch rename to pkgs/by-name/ka/kanidm/provision-patches/1_5/oauth2-basic-secret-modify.patch diff --git a/pkgs/by-name/ka/kanidm/patches/1_5/recover-account.patch b/pkgs/by-name/ka/kanidm/provision-patches/1_5/recover-account.patch similarity index 100% rename from pkgs/by-name/ka/kanidm/patches/1_5/recover-account.patch rename to pkgs/by-name/ka/kanidm/provision-patches/1_5/recover-account.patch diff --git a/pkgs/by-name/ka/kanidm/patches/1_6/oauth2-basic-secret-modify.patch b/pkgs/by-name/ka/kanidm/provision-patches/1_6/oauth2-basic-secret-modify.patch similarity index 100% rename from pkgs/by-name/ka/kanidm/patches/1_6/oauth2-basic-secret-modify.patch rename to pkgs/by-name/ka/kanidm/provision-patches/1_6/oauth2-basic-secret-modify.patch diff --git a/pkgs/by-name/ka/kanidm/patches/1_6/recover-account.patch b/pkgs/by-name/ka/kanidm/provision-patches/1_6/recover-account.patch similarity index 100% rename from pkgs/by-name/ka/kanidm/patches/1_6/recover-account.patch rename to pkgs/by-name/ka/kanidm/provision-patches/1_6/recover-account.patch diff --git a/pkgs/by-name/ka/kanidm/provision-patches/1_7/oauth2-basic-secret-modify.patch b/pkgs/by-name/ka/kanidm/provision-patches/1_7/oauth2-basic-secret-modify.patch new file mode 100644 index 000000000000..191f06626f0f --- /dev/null +++ b/pkgs/by-name/ka/kanidm/provision-patches/1_7/oauth2-basic-secret-modify.patch @@ -0,0 +1,159 @@ +From fc26fe5ac9e9cd65af82609c5a4966c8f756ea0f Mon Sep 17 00:00:00 2001 +From: oddlama +Date: Fri, 21 Mar 2025 16:07:54 +0100 +Subject: [PATCH 1/2] oauth2 basic secret modify + +--- + server/core/src/actors/v1_write.rs | 42 +++++++++++++++++++++++++++++ + server/core/src/https/v1.rs | 6 ++++- + server/core/src/https/v1_oauth2.rs | 29 ++++++++++++++++++++ + server/lib/src/server/migrations.rs | 16 +++++++++++ + 4 files changed, 92 insertions(+), 1 deletion(-) + +diff --git a/server/core/src/actors/v1_write.rs b/server/core/src/actors/v1_write.rs +index 732e826c8..a2b8e503f 100644 +--- a/server/core/src/actors/v1_write.rs ++++ b/server/core/src/actors/v1_write.rs +@@ -324,6 +324,48 @@ impl QueryServerWriteV1 { + .and_then(|_| idms_prox_write.commit().map(|_| ())) + } + ++ #[instrument( ++ level = "info", ++ skip_all, ++ fields(uuid = ?eventid) ++ )] ++ pub async fn handle_oauth2_basic_secret_write( ++ &self, ++ client_auth_info: ClientAuthInfo, ++ filter: Filter, ++ new_secret: String, ++ eventid: Uuid, ++ ) -> Result<(), OperationError> { ++ // Given a protoEntry, turn this into a modification set. ++ let ct = duration_from_epoch_now(); ++ let mut idms_prox_write = self.idms.proxy_write(ct).await?; ++ let ident = idms_prox_write ++ .validate_client_auth_info_to_ident(client_auth_info, ct) ++ .map_err(|e| { ++ admin_error!(err = ?e, "Invalid identity"); ++ e ++ })?; ++ ++ let modlist = ModifyList::new_purge_and_set( ++ Attribute::OAuth2RsBasicSecret, ++ Value::SecretValue(new_secret), ++ ); ++ ++ let mdf = ++ ModifyEvent::from_internal_parts(ident, &modlist, &filter, &idms_prox_write.qs_write) ++ .map_err(|e| { ++ admin_error!(err = ?e, "Failed to begin modify during handle_oauth2_basic_secret_write"); ++ e ++ })?; ++ ++ trace!(?mdf, "Begin modify event"); ++ ++ idms_prox_write ++ .qs_write ++ .modify(&mdf) ++ .and_then(|_| idms_prox_write.commit()) ++ } ++ + #[instrument( + level = "info", + skip_all, +diff --git a/server/core/src/https/v1.rs b/server/core/src/https/v1.rs +index 30de387b8..a11aa8ecd 100644 +--- a/server/core/src/https/v1.rs ++++ b/server/core/src/https/v1.rs +@@ -4,7 +4,7 @@ use axum::extract::{Path, State}; + use axum::http::{HeaderMap, HeaderValue}; + use axum::middleware::from_fn; + use axum::response::{IntoResponse, Response}; +-use axum::routing::{delete, get, post, put}; ++use axum::routing::{delete, get, post, put, patch}; + use axum::{Extension, Json, Router}; + use axum_extra::extract::cookie::{Cookie, CookieJar, SameSite}; + use compact_jwt::{Jwk, Jws, JwsSigner}; +@@ -3129,6 +3129,10 @@ pub(crate) fn route_setup(state: ServerState) -> Router { + "/v1/oauth2/:rs_name/_basic_secret", + get(super::v1_oauth2::oauth2_id_get_basic_secret), + ) ++ .route( ++ "/v1/oauth2/:rs_name/_basic_secret", ++ patch(super::v1_oauth2::oauth2_id_patch_basic_secret), ++ ) + .route( + "/v1/oauth2/:rs_name/_scopemap/:group", + post(super::v1_oauth2::oauth2_id_scopemap_post) +diff --git a/server/core/src/https/v1_oauth2.rs b/server/core/src/https/v1_oauth2.rs +index f399539bc..ffad9921e 100644 +--- a/server/core/src/https/v1_oauth2.rs ++++ b/server/core/src/https/v1_oauth2.rs +@@ -151,6 +151,35 @@ pub(crate) async fn oauth2_id_get_basic_secret( + .map_err(WebError::from) + } + ++#[utoipa::path( ++ patch, ++ path = "/v1/oauth2/{rs_name}/_basic_secret", ++ request_body=ProtoEntry, ++ responses( ++ DefaultApiResponse, ++ ), ++ security(("token_jwt" = [])), ++ tag = "v1/oauth2", ++ operation_id = "oauth2_id_patch_basic_secret" ++)] ++/// Overwrite the basic secret for a given OAuth2 Resource Server. ++#[instrument(level = "info", skip(state, new_secret))] ++pub(crate) async fn oauth2_id_patch_basic_secret( ++ State(state): State, ++ Extension(kopid): Extension, ++ VerifiedClientInformation(client_auth_info): VerifiedClientInformation, ++ Path(rs_name): Path, ++ Json(new_secret): Json, ++) -> Result, WebError> { ++ let filter = oauth2_id(&rs_name); ++ state ++ .qe_w_ref ++ .handle_oauth2_basic_secret_write(client_auth_info, filter, new_secret, kopid.eventid) ++ .await ++ .map(Json::from) ++ .map_err(WebError::from) ++} ++ + #[utoipa::path( + patch, + path = "/v1/oauth2/{rs_name}", +diff --git a/server/lib/src/server/migrations.rs b/server/lib/src/server/migrations.rs +index fd0bca8db..8621714f2 100644 +--- a/server/lib/src/server/migrations.rs ++++ b/server/lib/src/server/migrations.rs +@@ -171,6 +171,22 @@ impl QueryServer { + reload_required = true; + }; + ++ // secret provisioning: allow idm_admin to modify OAuth2RsBasicSecret. ++ write_txn.internal_modify_uuid( ++ UUID_IDM_ACP_OAUTH2_MANAGE_V1, ++ &ModifyList::new_append( ++ Attribute::AcpCreateAttr, ++ Attribute::OAuth2RsBasicSecret.into(), ++ ), ++ )?; ++ write_txn.internal_modify_uuid( ++ UUID_IDM_ACP_OAUTH2_MANAGE_V1, ++ &ModifyList::new_append( ++ Attribute::AcpModifyPresentAttr, ++ Attribute::OAuth2RsBasicSecret.into(), ++ ), ++ )?; ++ + // Execute whatever operations we have batched up and ready to go. This is needed + // to preserve ordering of the operations - if we reloaded after a remigrate then + // we would have skipped the patch level fix which needs to have occurred *first*. +-- +2.49.0 + diff --git a/pkgs/by-name/ka/kanidm/provision-patches/1_7/recover-account.patch b/pkgs/by-name/ka/kanidm/provision-patches/1_7/recover-account.patch new file mode 100644 index 000000000000..1892cdf63a19 --- /dev/null +++ b/pkgs/by-name/ka/kanidm/provision-patches/1_7/recover-account.patch @@ -0,0 +1,122 @@ +From 229165abe5be596fc2be8e285884813a1b5a38c8 Mon Sep 17 00:00:00 2001 +From: oddlama +Date: Fri, 21 Mar 2025 16:08:15 +0100 +Subject: [PATCH 2/2] recover account + +--- + server/core/src/actors/internal.rs | 5 +++-- + server/core/src/admin.rs | 6 +++--- + server/daemon/src/main.rs | 23 ++++++++++++++++++++++- + server/daemon/src/opt.rs | 7 +++++++ + 4 files changed, 35 insertions(+), 6 deletions(-) + +diff --git a/server/core/src/actors/internal.rs b/server/core/src/actors/internal.rs +index 420e72c6c..e252bca51 100644 +--- a/server/core/src/actors/internal.rs ++++ b/server/core/src/actors/internal.rs +@@ -172,17 +172,18 @@ impl QueryServerWriteV1 { + + #[instrument( + level = "info", +- skip(self, eventid), ++ skip(self, password, eventid), + fields(uuid = ?eventid) + )] + pub(crate) async fn handle_admin_recover_account( + &self, + name: String, ++ password: Option, + eventid: Uuid, + ) -> Result { + let ct = duration_from_epoch_now(); + let mut idms_prox_write = self.idms.proxy_write(ct).await?; +- let pw = idms_prox_write.recover_account(name.as_str(), None)?; ++ let pw = idms_prox_write.recover_account(name.as_str(), password.as_deref())?; + + idms_prox_write.commit().map(|()| pw) + } +diff --git a/server/core/src/admin.rs b/server/core/src/admin.rs +index 90ccb1927..85e31ddef 100644 +--- a/server/core/src/admin.rs ++++ b/server/core/src/admin.rs +@@ -24,7 +24,7 @@ pub use kanidm_proto::internal::{ + + #[derive(Serialize, Deserialize, Debug)] + pub enum AdminTaskRequest { +- RecoverAccount { name: String }, ++ RecoverAccount { name: String, password: Option }, + ShowReplicationCertificate, + RenewReplicationCertificate, + RefreshReplicationConsumer, +@@ -309,8 +309,8 @@ async fn handle_client( + + let resp = async { + match req { +- AdminTaskRequest::RecoverAccount { name } => { +- match server_rw.handle_admin_recover_account(name, eventid).await { ++ AdminTaskRequest::RecoverAccount { name, password } => { ++ match server_rw.handle_admin_recover_account(name, password, eventid).await { + Ok(password) => AdminTaskResponse::RecoverAccount { password }, + Err(e) => { + error!(err = ?e, "error during recover-account"); +diff --git a/server/daemon/src/main.rs b/server/daemon/src/main.rs +index c3b40faa0..2a57a307c 100644 +--- a/server/daemon/src/main.rs ++++ b/server/daemon/src/main.rs +@@ -923,13 +923,34 @@ async fn kanidm_main(config: Configuration, opt: KanidmdParser) -> ExitCode { + .await; + } + } +- KanidmdOpt::RecoverAccount { name, commonopts } => { ++ KanidmdOpt::RecoverAccount { name, from_environment, commonopts } => { + info!("Running account recovery ..."); + let output_mode: ConsoleOutputMode = commonopts.output_mode.to_owned().into(); ++ let password = if *from_environment { ++ match std::env::var("KANIDM_RECOVER_ACCOUNT_PASSWORD_FILE") { ++ Ok(path) => match tokio::fs::read_to_string(&path).await { ++ Ok(contents) => Some(contents), ++ Err(e) => { ++ error!("Failed to read password file '{}': {}", path, e); ++ return ExitCode::FAILURE; ++ } ++ }, ++ Err(_) => match std::env::var("KANIDM_RECOVER_ACCOUNT_PASSWORD") { ++ Ok(val) => Some(val), ++ Err(_) => { ++ error!("Neither KANIDM_RECOVER_ACCOUNT_PASSWORD_FILE nor KANIDM_RECOVER_ACCOUNT_PASSWORD was set"); ++ return ExitCode::FAILURE; ++ } ++ } ++ } ++ } else { ++ None ++ }; + submit_admin_req( + config.adminbindpath.as_str(), + AdminTaskRequest::RecoverAccount { + name: name.to_owned(), ++ password, + }, + output_mode, + ) +diff --git a/server/daemon/src/opt.rs b/server/daemon/src/opt.rs +index f1b45a5b3..ca19fb6a5 100644 +--- a/server/daemon/src/opt.rs ++++ b/server/daemon/src/opt.rs +@@ -236,6 +236,13 @@ enum KanidmdOpt { + #[clap(value_parser)] + /// The account name to recover credentials for. + name: String, ++ /// Use a password given via an environment variable. ++ /// - `KANIDM_RECOVER_ACCOUNT_PASSWORD_FILE` takes precedence and reads the desired ++ /// password from the given file ++ /// - `KANIDM_RECOVER_ACCOUNT_PASSWORD` directly takes a ++ /// password - beware that this will leave the password in the environment ++ #[clap(long = "from-environment")] ++ from_environment: bool, + #[clap(flatten)] + commonopts: CommonOpt, + }, +-- +2.49.0 + diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index 15b7b79653f4..b6d7143405b9 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -10221,6 +10221,7 @@ with pkgs; kanidm_1_5 = callPackage ../by-name/ka/kanidm/1_5.nix { kanidm = kanidm_1_5; }; kanidm_1_6 = callPackage ../by-name/ka/kanidm/1_6.nix { kanidm = kanidm_1_6; }; + kanidm_1_7 = callPackage ../by-name/ka/kanidm/1_7.nix { kanidm = kanidm_1_7; }; kanidmWithSecretProvisioning = kanidmWithSecretProvisioning_1_6; @@ -10232,6 +10233,10 @@ with pkgs; enableSecretProvisioning = true; }; + kanidmWithSecretProvisioning_1_7 = callPackage ../by-name/ka/kanidm/1_7.nix { + enableSecretProvisioning = true; + }; + knot-resolver = callPackage ../servers/dns/knot-resolver { systemd = systemdMinimal; # in closure already anyway }; From 8dca13f41473c44054ad10965331424fe8d7d290 Mon Sep 17 00:00:00 2001 From: "Adam C. Stephens" Date: Fri, 1 Aug 2025 15:19:16 -0400 Subject: [PATCH 2/4] kanidm: add EOL notice and set for 1.6 --- nixos/modules/services/security/kanidm.nix | 2 ++ pkgs/by-name/ka/kanidm/1_6.nix | 1 + pkgs/by-name/ka/kanidm/README.md | 1 + pkgs/by-name/ka/kanidm/generic.nix | 30 +++++++++++++++------- 4 files changed, 25 insertions(+), 9 deletions(-) diff --git a/nixos/modules/services/security/kanidm.nix b/nixos/modules/services/security/kanidm.nix index 77aa6bafebab..e371f3f40275 100644 --- a/nixos/modules/services/security/kanidm.nix +++ b/nixos/modules/services/security/kanidm.nix @@ -671,6 +671,8 @@ in }; config = mkIf (cfg.enableClient || cfg.enableServer || cfg.enablePam) { + warnings = lib.optionals (cfg.package.eolMessage != "") [ cfg.package.eolMessage ]; + assertions = let entityList = diff --git a/pkgs/by-name/ka/kanidm/1_6.nix b/pkgs/by-name/ka/kanidm/1_6.nix index 4253cebff2a0..894accceda72 100644 --- a/pkgs/by-name/ka/kanidm/1_6.nix +++ b/pkgs/by-name/ka/kanidm/1_6.nix @@ -2,4 +2,5 @@ import ./generic.nix { version = "1.6.4"; hash = "sha256-ui3w1HDHXHARsjQ3WtJfZbM7Xgg3ODnUneXJMQwaOMw="; cargoHash = "sha256-KJGELBzScwsLd6g3GR9Vk0nfDU2EjZBfXwlXJ+bZb1k="; + eolDate = "2025-09-01"; } diff --git a/pkgs/by-name/ka/kanidm/README.md b/pkgs/by-name/ka/kanidm/README.md index c87b4dd4bca7..c4bcd62467e2 100644 --- a/pkgs/by-name/ka/kanidm/README.md +++ b/pkgs/by-name/ka/kanidm/README.md @@ -19,6 +19,7 @@ For example, when upgrading from 1.4 -> 1.5 1. `cp -r pkgs/by-name/ka/kanidm/patches/1_4 pkgs/by-name/ka/kanidm/patches/1_5` 1. Update `1_5.nix` hashes/paths, and as needed for upstream changes, `generic.nix` 1. Update `all-packages.nix` to add `kanidm_1_5` and `kanidmWithSecretProvisioning_1_5`, leave default +1. Update the previous release, e.g. `1_4.nix` and set `eolDate = "YYYY-MM-DD"` where the date is 30 days from release of 1.5. 1. Create commit, `kanidm_1_5: init at 1.5.0` - this is the only commit that will be backported ### Update default diff --git a/pkgs/by-name/ka/kanidm/generic.nix b/pkgs/by-name/ka/kanidm/generic.nix index 926452422080..4ba7bd113250 100644 --- a/pkgs/by-name/ka/kanidm/generic.nix +++ b/pkgs/by-name/ka/kanidm/generic.nix @@ -3,6 +3,7 @@ hash, cargoHash, unsupported ? false, + eolDate ? null, }: { @@ -42,6 +43,13 @@ let (./. + "/provision-patches/${versionUnderscored}/oauth2-basic-secret-modify.patch") (./. + "/provision-patches/${versionUnderscored}/recover-account.patch") ]; + + upgradeNote = '' + Please upgrade by verifying `kanidmd domain upgrade-check` and choosing the + next version with `services.kanidm.package = pkgs.kanidm_1_x;` + + See upgrade guide at https://kanidm.github.io/kanidm/master/server_updates.html + ''; in rustPlatform.buildRustPackage (finalAttrs: { pname = "kanidm" + (lib.optionalString enableSecretProvisioning "-with-secret-provisioning"); @@ -132,10 +140,9 @@ rustPlatform.buildRustPackage (finalAttrs: { }; updateScript = lib.optionals (!enableSecretProvisioning) (nix-update-script { - # avoid spurious releases and tags such as "debs" extraArgs = [ "-vr" - "v([0-9\\.]*)" + "v(${lib.versions.major kanidm.version}\\.${lib.versions.minor kanidm.version}\\.[0-9]*)" "--override-filename" "pkgs/by-name/ka/kanidm/${versionUnderscored}.nix" ]; @@ -143,27 +150,32 @@ rustPlatform.buildRustPackage (finalAttrs: { inherit enableSecretProvisioning; withSecretProvisioning = kanidm.override { enableSecretProvisioning = true; }; + + eolMessage = lib.optionalString (eolDate != null) '' + kanidm ${lib.versions.majorMinor version} is deprecated and will reach end-of-life on ${eolDate} + + ${upgradeNote} + ''; }; # can take over 4 hours on 2 cores and needs 16GB+ RAM requiredSystemFeatures = [ "big-parallel" ]; - meta = with lib; { + meta = { changelog = "https://github.com/kanidm/kanidm/releases/tag/v${version}"; description = "Simple, secure and fast identity management platform"; homepage = "https://github.com/kanidm/kanidm"; - license = licenses.mpl20; - platforms = platforms.linux ++ platforms.darwin; - maintainers = with maintainers; [ + license = lib.licenses.mpl20; + platforms = lib.platforms.linux ++ lib.platforms.darwin; + maintainers = with lib.maintainers; [ adamcstephens Flakebi ]; knownVulnerabilities = lib.optionals unsupported [ '' - kanidm ${version} has reached EOL. + kanidm ${lib.versions.majorMinor version} has reached end-of-life. - Please upgrade by verifying `kanidmd domain upgrade-check` and choosing the next version with `services.kanidm.package = pkgs.kanidm_1_x;` - See upgrade guide at https://kanidm.github.io/kanidm/master/server_updates.html + ${upgradeNote} '' ]; }; From 9b6cad46ea7f139329bc067a1abfc7772b841557 Mon Sep 17 00:00:00 2001 From: "Adam C. Stephens" Date: Fri, 1 Aug 2025 15:58:39 -0400 Subject: [PATCH 3/4] kanidm: use package version in tests --- nixos/tests/all-tests.nix | 14 ++++++++++++-- nixos/tests/kanidm-provisioning.nix | 16 +++++++++------- nixos/tests/kanidm.nix | 16 +++++++++------- pkgs/by-name/ka/kanidm/generic.nix | 3 ++- 4 files changed, 32 insertions(+), 17 deletions(-) diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix index 76867b74b49d..1279ec80ddc4 100644 --- a/nixos/tests/all-tests.nix +++ b/nixos/tests/all-tests.nix @@ -765,8 +765,18 @@ in k3s = handleTest ./k3s { }; kafka = handleTest ./kafka { }; kanboard = runTest ./web-apps/kanboard.nix; - kanidm = runTest ./kanidm.nix; - kanidm-provisioning = runTest ./kanidm-provisioning.nix; + kanidm = + kanidmVersion: + runTest { + imports = [ ./kanidm.nix ]; + _module.args = { inherit kanidmVersion; }; + }; + kanidm-provisioning = + kanidmVersion: + runTest { + imports = [ ./kanidm-provisioning.nix ]; + _module.args = { inherit kanidmVersion; }; + }; karma = runTest ./karma.nix; kavita = runTest ./kavita.nix; kbd-setfont-decompress = runTest ./kbd-setfont-decompress.nix; diff --git a/nixos/tests/kanidm-provisioning.nix b/nixos/tests/kanidm-provisioning.nix index b04fb4d65e4a..f51c34eae245 100644 --- a/nixos/tests/kanidm-provisioning.nix +++ b/nixos/tests/kanidm-provisioning.nix @@ -1,4 +1,4 @@ -{ pkgs, ... }: +{ kanidmVersion, pkgs, ... }: let certs = import ./common/acme/server/snakeoil-certs.nix; serverDomain = certs.domain; @@ -13,6 +13,8 @@ let provisionAdminPassword = "very-strong-password-for-admin"; provisionIdmAdminPassword = "very-strong-password-for-idm-admin"; provisionIdmAdminPassword2 = "very-strong-alternative-password-for-idm-admin"; + + kanidmPackage = pkgs."kanidmWithSecretProvisioning_${kanidmVersion}"; in { name = "kanidm-provisioning"; @@ -22,7 +24,7 @@ in { pkgs, lib, ... }: { services.kanidm = { - package = pkgs.kanidmWithSecretProvisioning_1_6; + package = kanidmPackage; enableServer = true; serverSettings = { origin = "https://${serverDomain}"; @@ -273,11 +275,11 @@ in users.users.kanidm.shell = pkgs.bashInteractive; - environment.systemPackages = with pkgs; [ - kanidm - openldap - ripgrep - jq + environment.systemPackages = [ + kanidmPackage + pkgs.openldap + pkgs.ripgrep + pkgs.jq ]; }; diff --git a/nixos/tests/kanidm.nix b/nixos/tests/kanidm.nix index f2f4981da276..be91be64d2f0 100644 --- a/nixos/tests/kanidm.nix +++ b/nixos/tests/kanidm.nix @@ -1,4 +1,4 @@ -{ pkgs, ... }: +{ kanidmVersion, pkgs, ... }: let certs = import ./common/acme/server/snakeoil-certs.nix; serverDomain = certs.domain; @@ -13,6 +13,8 @@ let cp ${certs."${serverDomain}".cert} $out/snakeoil.crt cp ${certs."${serverDomain}".key} $out/snakeoil.key ''; + + kanidmPackage = pkgs."kanidm_${kanidmVersion}"; in { name = "kanidm"; @@ -25,7 +27,7 @@ in { pkgs, ... }: { services.kanidm = { - package = pkgs.kanidm_1_6; + package = kanidmPackage; enableServer = true; serverSettings = { origin = "https://${serverDomain}"; @@ -44,10 +46,10 @@ in users.users.kanidm.shell = pkgs.bashInteractive; - environment.systemPackages = with pkgs; [ - kanidm - openldap - ripgrep + environment.systemPackages = [ + kanidmPackage + pkgs.openldap + pkgs.ripgrep ]; }; @@ -55,7 +57,7 @@ in { nodes, ... }: { services.kanidm = { - package = pkgs.kanidm_1_6; + package = kanidmPackage; enableClient = true; clientSettings = { uri = "https://${serverDomain}"; diff --git a/pkgs/by-name/ka/kanidm/generic.nix b/pkgs/by-name/ka/kanidm/generic.nix index 4ba7bd113250..0810710fc854 100644 --- a/pkgs/by-name/ka/kanidm/generic.nix +++ b/pkgs/by-name/ka/kanidm/generic.nix @@ -136,7 +136,8 @@ rustPlatform.buildRustPackage (finalAttrs: { passthru = { tests = { - inherit (nixosTests) kanidm kanidm-provisioning; + kanidm = nixosTests.kanidm versionUnderscored; + kanidm-provisioning = nixosTests.kanidm-provisioning versionUnderscored; }; updateScript = lib.optionals (!enableSecretProvisioning) (nix-update-script { From 48aeb444ad8f37ed1f303519e37a29aa72cc0063 Mon Sep 17 00:00:00 2001 From: "Adam C. Stephens" Date: Wed, 6 Aug 2025 17:15:06 +0000 Subject: [PATCH 4/4] kanidm_1_7: 1.7.0 -> 1.7.1 https://github.com/kanidm/kanidm/releases/tag/v1.7.1 --- pkgs/by-name/ka/kanidm/1_7.nix | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkgs/by-name/ka/kanidm/1_7.nix b/pkgs/by-name/ka/kanidm/1_7.nix index 47d68762b764..718975bfcc14 100644 --- a/pkgs/by-name/ka/kanidm/1_7.nix +++ b/pkgs/by-name/ka/kanidm/1_7.nix @@ -1,5 +1,5 @@ import ./generic.nix { - version = "1.7.0"; - hash = "sha256-JM5C0tCvo4Lq06bqil8M35YnFMoQFjzA/J30gZOs4fU="; - cargoHash = "sha256-MvBjj/6ph+i29dZGtaysHHgRk03P8sMePXdIm+v2tpw="; + version = "1.7.1"; + hash = "sha256-CG4s6fYxTM2I/kFjD905g8/DSFkyB+0pnGVXgyRXtlE="; + cargoHash = "sha256-9bE3hSCFBJF8f3Lm5SzEuDtEpJBbCBijUDfqGiPnRsc="; }