nixpkgs mirror (for testing) github.com/NixOS/nixpkgs
nix

kanidm_1_7: init at 1.7.1 (#430205)

authored by

Adam C. Stephens and committed by
GitHub
da4f70e2 b8d3005a

+376 -72
+2
nixos/modules/services/security/kanidm.nix
··· 671 671 }; 672 672 673 673 config = mkIf (cfg.enableClient || cfg.enableServer || cfg.enablePam) { 674 + warnings = lib.optionals (cfg.package.eolMessage != "") [ cfg.package.eolMessage ]; 675 + 674 676 assertions = 675 677 let 676 678 entityList =
+12 -2
nixos/tests/all-tests.nix
··· 772 772 k3s = handleTest ./k3s { }; 773 773 kafka = handleTest ./kafka { }; 774 774 kanboard = runTest ./web-apps/kanboard.nix; 775 - kanidm = runTest ./kanidm.nix; 776 - kanidm-provisioning = runTest ./kanidm-provisioning.nix; 775 + kanidm = 776 + kanidmVersion: 777 + runTest { 778 + imports = [ ./kanidm.nix ]; 779 + _module.args = { inherit kanidmVersion; }; 780 + }; 781 + kanidm-provisioning = 782 + kanidmVersion: 783 + runTest { 784 + imports = [ ./kanidm-provisioning.nix ]; 785 + _module.args = { inherit kanidmVersion; }; 786 + }; 777 787 karma = runTest ./karma.nix; 778 788 kavita = runTest ./kavita.nix; 779 789 kbd-setfont-decompress = runTest ./kbd-setfont-decompress.nix;
+9 -7
nixos/tests/kanidm-provisioning.nix
··· 1 - { pkgs, ... }: 1 + { kanidmVersion, pkgs, ... }: 2 2 let 3 3 certs = import ./common/acme/server/snakeoil-certs.nix; 4 4 serverDomain = certs.domain; ··· 13 13 provisionAdminPassword = "very-strong-password-for-admin"; 14 14 provisionIdmAdminPassword = "very-strong-password-for-idm-admin"; 15 15 provisionIdmAdminPassword2 = "very-strong-alternative-password-for-idm-admin"; 16 + 17 + kanidmPackage = pkgs."kanidmWithSecretProvisioning_${kanidmVersion}"; 16 18 in 17 19 { 18 20 name = "kanidm-provisioning"; ··· 24 22 { pkgs, lib, ... }: 25 23 { 26 24 services.kanidm = { 27 - package = pkgs.kanidmWithSecretProvisioning_1_6; 25 + package = kanidmPackage; 28 26 enableServer = true; 29 27 serverSettings = { 30 28 origin = "https://${serverDomain}"; ··· 275 273 276 274 users.users.kanidm.shell = pkgs.bashInteractive; 277 275 278 - environment.systemPackages = with pkgs; [ 279 - kanidm 280 - openldap 281 - ripgrep 282 - jq 276 + environment.systemPackages = [ 277 + kanidmPackage 278 + pkgs.openldap 279 + pkgs.ripgrep 280 + pkgs.jq 283 281 ]; 284 282 }; 285 283
+9 -7
nixos/tests/kanidm.nix
··· 1 - { pkgs, ... }: 1 + { kanidmVersion, pkgs, ... }: 2 2 let 3 3 certs = import ./common/acme/server/snakeoil-certs.nix; 4 4 serverDomain = certs.domain; ··· 13 13 cp ${certs."${serverDomain}".cert} $out/snakeoil.crt 14 14 cp ${certs."${serverDomain}".key} $out/snakeoil.key 15 15 ''; 16 + 17 + kanidmPackage = pkgs."kanidm_${kanidmVersion}"; 16 18 in 17 19 { 18 20 name = "kanidm"; ··· 27 25 { pkgs, ... }: 28 26 { 29 27 services.kanidm = { 30 - package = pkgs.kanidm_1_6; 28 + package = kanidmPackage; 31 29 enableServer = true; 32 30 serverSettings = { 33 31 origin = "https://${serverDomain}"; ··· 46 44 47 45 users.users.kanidm.shell = pkgs.bashInteractive; 48 46 49 - environment.systemPackages = with pkgs; [ 50 - kanidm 51 - openldap 52 - ripgrep 47 + environment.systemPackages = [ 48 + kanidmPackage 49 + pkgs.openldap 50 + pkgs.ripgrep 53 51 ]; 54 52 }; 55 53 ··· 57 55 { nodes, ... }: 58 56 { 59 57 services.kanidm = { 60 - package = pkgs.kanidm_1_6; 58 + package = kanidmPackage; 61 59 enableClient = true; 62 60 clientSettings = { 63 61 uri = "https://${serverDomain}";
-1
pkgs/by-name/ka/kanidm/1_5.nix
··· 2 2 version = "1.5.0"; 3 3 hash = "sha256-swrqyjA7Wgq17vd+753LDFcXrSFixVNLhTvj1bhG3DU="; 4 4 cargoHash = "sha256-72IwS8Nk1y6xDH9y8JW2LpbhFWaq0tpORx7JQSCF5/M="; 5 - patchDir = ./patches/1_5; 6 5 unsupported = true; 7 6 }
+1 -1
pkgs/by-name/ka/kanidm/1_6.nix
··· 2 2 version = "1.6.4"; 3 3 hash = "sha256-ui3w1HDHXHARsjQ3WtJfZbM7Xgg3ODnUneXJMQwaOMw="; 4 4 cargoHash = "sha256-KJGELBzScwsLd6g3GR9Vk0nfDU2EjZBfXwlXJ+bZb1k="; 5 - patchDir = ./patches/1_6; 5 + eolDate = "2025-09-01"; 6 6 }
+5
pkgs/by-name/ka/kanidm/1_7.nix
··· 1 + import ./generic.nix { 2 + version = "1.7.1"; 3 + hash = "sha256-CG4s6fYxTM2I/kFjD905g8/DSFkyB+0pnGVXgyRXtlE="; 4 + cargoHash = "sha256-9bE3hSCFBJF8f3Lm5SzEuDtEpJBbCBijUDfqGiPnRsc="; 5 + }
+1
pkgs/by-name/ka/kanidm/README.md
··· 19 19 1. `cp -r pkgs/by-name/ka/kanidm/patches/1_4 pkgs/by-name/ka/kanidm/patches/1_5` 20 20 1. Update `1_5.nix` hashes/paths, and as needed for upstream changes, `generic.nix` 21 21 1. Update `all-packages.nix` to add `kanidm_1_5` and `kanidmWithSecretProvisioning_1_5`, leave default 22 + 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. 22 23 1. Create commit, `kanidm_1_5: init at 1.5.0` - this is the only commit that will be backported 23 24 24 25 ### Update default
+51 -54
pkgs/by-name/ka/kanidm/generic.nix
··· 2 2 version, 3 3 hash, 4 4 cargoHash, 5 - patchDir, 6 - extraMeta ? { }, 7 5 unsupported ? false, 6 + eolDate ? null, 8 7 }: 9 8 10 9 { ··· 34 35 35 36 let 36 37 arch = if stdenv.hostPlatform.isx86_64 then "x86_64" else "generic"; 38 + 39 + versionUnderscored = builtins.replaceStrings [ "." ] [ "_" ] ( 40 + lib.versions.majorMinor kanidm.version 41 + ); 42 + 43 + provisionPatches = [ 44 + (./. + "/provision-patches/${versionUnderscored}/oauth2-basic-secret-modify.patch") 45 + (./. + "/provision-patches/${versionUnderscored}/recover-account.patch") 46 + ]; 47 + 48 + upgradeNote = '' 49 + Please upgrade by verifying `kanidmd domain upgrade-check` and choosing the 50 + next version with `services.kanidm.package = pkgs.kanidm_1_x;` 51 + 52 + See upgrade guide at https://kanidm.github.io/kanidm/master/server_updates.html 53 + ''; 37 54 in 38 - rustPlatform.buildRustPackage rec { 55 + rustPlatform.buildRustPackage (finalAttrs: { 39 56 pname = "kanidm" + (lib.optionalString enableSecretProvisioning "-with-secret-provisioning"); 40 57 inherit version cargoHash; 41 58 ··· 64 49 inherit hash; 65 50 }; 66 51 67 - KANIDM_BUILD_PROFILE = "release_nixpkgs_${arch}"; 52 + env.KANIDM_BUILD_PROFILE = "release_nixpkgs_${arch}"; 68 53 69 - patches = lib.optionals enableSecretProvisioning [ 70 - "${patchDir}/oauth2-basic-secret-modify.patch" 71 - "${patchDir}/recover-account.patch" 72 - ]; 54 + patches = lib.optionals enableSecretProvisioning provisionPatches; 73 55 74 56 postPatch = 75 57 let 76 - format = (formats.toml { }).generate "${KANIDM_BUILD_PROFILE}.toml"; 58 + format = (formats.toml { }).generate "${finalAttrs.env.KANIDM_BUILD_PROFILE}.toml"; 77 59 socket_path = if stdenv.hostPlatform.isLinux then "/run/kanidmd/sock" else "/var/run/kanidm.socket"; 78 60 profile = { 79 61 cpu_flags = if stdenv.hostPlatform.isx86_64 then "x86_64_legacy" else "none"; ··· 82 70 server_admin_bind_path = socket_path; 83 71 server_config_path = "/etc/kanidm/server.toml"; 84 72 server_ui_pkg_path = "@htmx_ui_pkg_path@"; 85 - } 86 - // lib.optionalAttrs (lib.versionOlder version "1.5") { 87 - admin_bind_path = socket_path; 88 - default_config_path = "/etc/kanidm/server.toml"; 89 - default_unix_shell_path = "${lib.getBin bashInteractive}/bin/bash"; 90 - htmx_ui_pkg_path = "@htmx_ui_pkg_path@"; 91 - } 92 - // lib.optionalAttrs (lib.versions.majorMinor version == "1.3") { 93 - web_ui_pkg_path = "@web_ui_pkg_path@"; 94 73 }; 95 74 in 96 75 '' 97 - cp ${format profile} libs/profiles/${KANIDM_BUILD_PROFILE}.toml 98 - substituteInPlace libs/profiles/${KANIDM_BUILD_PROFILE}.toml --replace-fail '@htmx_ui_pkg_path@' "$out/ui/hpkg" 99 - '' 100 - + lib.optionalString (lib.versions.majorMinor version == "1.3") '' 101 - substituteInPlace libs/profiles/${KANIDM_BUILD_PROFILE}.toml --replace-fail '@web_ui_pkg_path@' "$out/ui/pkg" 76 + cp ${format profile} libs/profiles/${finalAttrs.env.KANIDM_BUILD_PROFILE}.toml 77 + substituteInPlace libs/profiles/${finalAttrs.env.KANIDM_BUILD_PROFILE}.toml --replace-fail '@htmx_ui_pkg_path@' "$out/ui/hpkg" 102 78 ''; 103 79 104 80 nativeBuildInputs = [ ··· 108 108 postBuild = '' 109 109 mkdir -p $out/ui 110 110 cp -r server/core/static $out/ui/hpkg 111 - '' 112 - + lib.optionalString (lib.versions.majorMinor version == "1.3") '' 113 - cp -r server/web_ui/pkg $out/ui/pkg 114 111 ''; 115 112 116 113 # Upstream runs with the Rust equivalent of -Werror, ··· 136 139 137 140 passthru = { 138 141 tests = { 139 - inherit (nixosTests) kanidm kanidm-provisioning; 142 + kanidm = nixosTests.kanidm versionUnderscored; 143 + kanidm-provisioning = nixosTests.kanidm-provisioning versionUnderscored; 140 144 }; 141 145 142 146 updateScript = lib.optionals (!enableSecretProvisioning) (nix-update-script { 143 - # avoid spurious releases and tags such as "debs" 144 147 extraArgs = [ 145 148 "-vr" 146 - "v([0-9\\.]*)" 149 + "v(${lib.versions.major kanidm.version}\\.${lib.versions.minor kanidm.version}\\.[0-9]*)" 147 150 "--override-filename" 148 - "pkgs/by-name/ka/kanidm/${ 149 - builtins.replaceStrings [ "." ] [ "_" ] (lib.versions.majorMinor kanidm.version) 150 - }.nix" 151 + "pkgs/by-name/ka/kanidm/${versionUnderscored}.nix" 151 152 ]; 152 153 }); 153 154 154 155 inherit enableSecretProvisioning; 155 156 withSecretProvisioning = kanidm.override { enableSecretProvisioning = true; }; 157 + 158 + eolMessage = lib.optionalString (eolDate != null) '' 159 + kanidm ${lib.versions.majorMinor version} is deprecated and will reach end-of-life on ${eolDate} 160 + 161 + ${upgradeNote} 162 + ''; 156 163 }; 157 164 158 165 # can take over 4 hours on 2 cores and needs 16GB+ RAM 159 166 requiredSystemFeatures = [ "big-parallel" ]; 160 167 161 - meta = 162 - with lib; 163 - { 164 - changelog = "https://github.com/kanidm/kanidm/releases/tag/v${version}"; 165 - description = "Simple, secure and fast identity management platform"; 166 - homepage = "https://github.com/kanidm/kanidm"; 167 - license = licenses.mpl20; 168 - platforms = platforms.linux ++ platforms.darwin; 169 - maintainers = with maintainers; [ 170 - adamcstephens 171 - Flakebi 172 - ]; 173 - knownVulnerabilities = lib.optionals unsupported [ 174 - '' 175 - kanidm ${version} has reached EOL. 168 + meta = { 169 + changelog = "https://github.com/kanidm/kanidm/releases/tag/v${version}"; 170 + description = "Simple, secure and fast identity management platform"; 171 + homepage = "https://github.com/kanidm/kanidm"; 172 + license = lib.licenses.mpl20; 173 + platforms = lib.platforms.linux ++ lib.platforms.darwin; 174 + maintainers = with lib.maintainers; [ 175 + adamcstephens 176 + Flakebi 177 + ]; 178 + knownVulnerabilities = lib.optionals unsupported [ 179 + '' 180 + kanidm ${lib.versions.majorMinor version} has reached end-of-life. 176 181 177 - Please upgrade by verifying `kanidmd domain upgrade-check` and choosing the next version with `services.kanidm.package = pkgs.kanidm_1_x;` 178 - See upgrade guide at https://kanidm.github.io/kanidm/master/server_updates.html 179 - '' 180 - ]; 181 - } 182 - // extraMeta; 183 - } 182 + ${upgradeNote} 183 + '' 184 + ]; 185 + }; 186 + })
pkgs/by-name/ka/kanidm/patches/1_5/oauth2-basic-secret-modify.patch pkgs/by-name/ka/kanidm/provision-patches/1_5/oauth2-basic-secret-modify.patch
pkgs/by-name/ka/kanidm/patches/1_5/recover-account.patch pkgs/by-name/ka/kanidm/provision-patches/1_5/recover-account.patch
pkgs/by-name/ka/kanidm/patches/1_6/oauth2-basic-secret-modify.patch pkgs/by-name/ka/kanidm/provision-patches/1_6/oauth2-basic-secret-modify.patch
pkgs/by-name/ka/kanidm/patches/1_6/recover-account.patch pkgs/by-name/ka/kanidm/provision-patches/1_6/recover-account.patch
+159
pkgs/by-name/ka/kanidm/provision-patches/1_7/oauth2-basic-secret-modify.patch
··· 1 + From fc26fe5ac9e9cd65af82609c5a4966c8f756ea0f Mon Sep 17 00:00:00 2001 2 + From: oddlama <oddlama@oddlama.org> 3 + Date: Fri, 21 Mar 2025 16:07:54 +0100 4 + Subject: [PATCH 1/2] oauth2 basic secret modify 5 + 6 + --- 7 + server/core/src/actors/v1_write.rs | 42 +++++++++++++++++++++++++++++ 8 + server/core/src/https/v1.rs | 6 ++++- 9 + server/core/src/https/v1_oauth2.rs | 29 ++++++++++++++++++++ 10 + server/lib/src/server/migrations.rs | 16 +++++++++++ 11 + 4 files changed, 92 insertions(+), 1 deletion(-) 12 + 13 + diff --git a/server/core/src/actors/v1_write.rs b/server/core/src/actors/v1_write.rs 14 + index 732e826c8..a2b8e503f 100644 15 + --- a/server/core/src/actors/v1_write.rs 16 + +++ b/server/core/src/actors/v1_write.rs 17 + @@ -324,6 +324,48 @@ impl QueryServerWriteV1 { 18 + .and_then(|_| idms_prox_write.commit().map(|_| ())) 19 + } 20 + 21 + + #[instrument( 22 + + level = "info", 23 + + skip_all, 24 + + fields(uuid = ?eventid) 25 + + )] 26 + + pub async fn handle_oauth2_basic_secret_write( 27 + + &self, 28 + + client_auth_info: ClientAuthInfo, 29 + + filter: Filter<FilterInvalid>, 30 + + new_secret: String, 31 + + eventid: Uuid, 32 + + ) -> Result<(), OperationError> { 33 + + // Given a protoEntry, turn this into a modification set. 34 + + let ct = duration_from_epoch_now(); 35 + + let mut idms_prox_write = self.idms.proxy_write(ct).await?; 36 + + let ident = idms_prox_write 37 + + .validate_client_auth_info_to_ident(client_auth_info, ct) 38 + + .map_err(|e| { 39 + + admin_error!(err = ?e, "Invalid identity"); 40 + + e 41 + + })?; 42 + + 43 + + let modlist = ModifyList::new_purge_and_set( 44 + + Attribute::OAuth2RsBasicSecret, 45 + + Value::SecretValue(new_secret), 46 + + ); 47 + + 48 + + let mdf = 49 + + ModifyEvent::from_internal_parts(ident, &modlist, &filter, &idms_prox_write.qs_write) 50 + + .map_err(|e| { 51 + + admin_error!(err = ?e, "Failed to begin modify during handle_oauth2_basic_secret_write"); 52 + + e 53 + + })?; 54 + + 55 + + trace!(?mdf, "Begin modify event"); 56 + + 57 + + idms_prox_write 58 + + .qs_write 59 + + .modify(&mdf) 60 + + .and_then(|_| idms_prox_write.commit()) 61 + + } 62 + + 63 + #[instrument( 64 + level = "info", 65 + skip_all, 66 + diff --git a/server/core/src/https/v1.rs b/server/core/src/https/v1.rs 67 + index 30de387b8..a11aa8ecd 100644 68 + --- a/server/core/src/https/v1.rs 69 + +++ b/server/core/src/https/v1.rs 70 + @@ -4,7 +4,7 @@ use axum::extract::{Path, State}; 71 + use axum::http::{HeaderMap, HeaderValue}; 72 + use axum::middleware::from_fn; 73 + use axum::response::{IntoResponse, Response}; 74 + -use axum::routing::{delete, get, post, put}; 75 + +use axum::routing::{delete, get, post, put, patch}; 76 + use axum::{Extension, Json, Router}; 77 + use axum_extra::extract::cookie::{Cookie, CookieJar, SameSite}; 78 + use compact_jwt::{Jwk, Jws, JwsSigner}; 79 + @@ -3129,6 +3129,10 @@ pub(crate) fn route_setup(state: ServerState) -> Router<ServerState> { 80 + "/v1/oauth2/:rs_name/_basic_secret", 81 + get(super::v1_oauth2::oauth2_id_get_basic_secret), 82 + ) 83 + + .route( 84 + + "/v1/oauth2/:rs_name/_basic_secret", 85 + + patch(super::v1_oauth2::oauth2_id_patch_basic_secret), 86 + + ) 87 + .route( 88 + "/v1/oauth2/:rs_name/_scopemap/:group", 89 + post(super::v1_oauth2::oauth2_id_scopemap_post) 90 + diff --git a/server/core/src/https/v1_oauth2.rs b/server/core/src/https/v1_oauth2.rs 91 + index f399539bc..ffad9921e 100644 92 + --- a/server/core/src/https/v1_oauth2.rs 93 + +++ b/server/core/src/https/v1_oauth2.rs 94 + @@ -151,6 +151,35 @@ pub(crate) async fn oauth2_id_get_basic_secret( 95 + .map_err(WebError::from) 96 + } 97 + 98 + +#[utoipa::path( 99 + + patch, 100 + + path = "/v1/oauth2/{rs_name}/_basic_secret", 101 + + request_body=ProtoEntry, 102 + + responses( 103 + + DefaultApiResponse, 104 + + ), 105 + + security(("token_jwt" = [])), 106 + + tag = "v1/oauth2", 107 + + operation_id = "oauth2_id_patch_basic_secret" 108 + +)] 109 + +/// Overwrite the basic secret for a given OAuth2 Resource Server. 110 + +#[instrument(level = "info", skip(state, new_secret))] 111 + +pub(crate) async fn oauth2_id_patch_basic_secret( 112 + + State(state): State<ServerState>, 113 + + Extension(kopid): Extension<KOpId>, 114 + + VerifiedClientInformation(client_auth_info): VerifiedClientInformation, 115 + + Path(rs_name): Path<String>, 116 + + Json(new_secret): Json<String>, 117 + +) -> Result<Json<()>, WebError> { 118 + + let filter = oauth2_id(&rs_name); 119 + + state 120 + + .qe_w_ref 121 + + .handle_oauth2_basic_secret_write(client_auth_info, filter, new_secret, kopid.eventid) 122 + + .await 123 + + .map(Json::from) 124 + + .map_err(WebError::from) 125 + +} 126 + + 127 + #[utoipa::path( 128 + patch, 129 + path = "/v1/oauth2/{rs_name}", 130 + diff --git a/server/lib/src/server/migrations.rs b/server/lib/src/server/migrations.rs 131 + index fd0bca8db..8621714f2 100644 132 + --- a/server/lib/src/server/migrations.rs 133 + +++ b/server/lib/src/server/migrations.rs 134 + @@ -171,6 +171,22 @@ impl QueryServer { 135 + reload_required = true; 136 + }; 137 + 138 + + // secret provisioning: allow idm_admin to modify OAuth2RsBasicSecret. 139 + + write_txn.internal_modify_uuid( 140 + + UUID_IDM_ACP_OAUTH2_MANAGE_V1, 141 + + &ModifyList::new_append( 142 + + Attribute::AcpCreateAttr, 143 + + Attribute::OAuth2RsBasicSecret.into(), 144 + + ), 145 + + )?; 146 + + write_txn.internal_modify_uuid( 147 + + UUID_IDM_ACP_OAUTH2_MANAGE_V1, 148 + + &ModifyList::new_append( 149 + + Attribute::AcpModifyPresentAttr, 150 + + Attribute::OAuth2RsBasicSecret.into(), 151 + + ), 152 + + )?; 153 + + 154 + // Execute whatever operations we have batched up and ready to go. This is needed 155 + // to preserve ordering of the operations - if we reloaded after a remigrate then 156 + // we would have skipped the patch level fix which needs to have occurred *first*. 157 + -- 158 + 2.49.0 159 +
+122
pkgs/by-name/ka/kanidm/provision-patches/1_7/recover-account.patch
··· 1 + From 229165abe5be596fc2be8e285884813a1b5a38c8 Mon Sep 17 00:00:00 2001 2 + From: oddlama <oddlama@oddlama.org> 3 + Date: Fri, 21 Mar 2025 16:08:15 +0100 4 + Subject: [PATCH 2/2] recover account 5 + 6 + --- 7 + server/core/src/actors/internal.rs | 5 +++-- 8 + server/core/src/admin.rs | 6 +++--- 9 + server/daemon/src/main.rs | 23 ++++++++++++++++++++++- 10 + server/daemon/src/opt.rs | 7 +++++++ 11 + 4 files changed, 35 insertions(+), 6 deletions(-) 12 + 13 + diff --git a/server/core/src/actors/internal.rs b/server/core/src/actors/internal.rs 14 + index 420e72c6c..e252bca51 100644 15 + --- a/server/core/src/actors/internal.rs 16 + +++ b/server/core/src/actors/internal.rs 17 + @@ -172,17 +172,18 @@ impl QueryServerWriteV1 { 18 + 19 + #[instrument( 20 + level = "info", 21 + - skip(self, eventid), 22 + + skip(self, password, eventid), 23 + fields(uuid = ?eventid) 24 + )] 25 + pub(crate) async fn handle_admin_recover_account( 26 + &self, 27 + name: String, 28 + + password: Option<String>, 29 + eventid: Uuid, 30 + ) -> Result<String, OperationError> { 31 + let ct = duration_from_epoch_now(); 32 + let mut idms_prox_write = self.idms.proxy_write(ct).await?; 33 + - let pw = idms_prox_write.recover_account(name.as_str(), None)?; 34 + + let pw = idms_prox_write.recover_account(name.as_str(), password.as_deref())?; 35 + 36 + idms_prox_write.commit().map(|()| pw) 37 + } 38 + diff --git a/server/core/src/admin.rs b/server/core/src/admin.rs 39 + index 90ccb1927..85e31ddef 100644 40 + --- a/server/core/src/admin.rs 41 + +++ b/server/core/src/admin.rs 42 + @@ -24,7 +24,7 @@ pub use kanidm_proto::internal::{ 43 + 44 + #[derive(Serialize, Deserialize, Debug)] 45 + pub enum AdminTaskRequest { 46 + - RecoverAccount { name: String }, 47 + + RecoverAccount { name: String, password: Option<String> }, 48 + ShowReplicationCertificate, 49 + RenewReplicationCertificate, 50 + RefreshReplicationConsumer, 51 + @@ -309,8 +309,8 @@ async fn handle_client( 52 + 53 + let resp = async { 54 + match req { 55 + - AdminTaskRequest::RecoverAccount { name } => { 56 + - match server_rw.handle_admin_recover_account(name, eventid).await { 57 + + AdminTaskRequest::RecoverAccount { name, password } => { 58 + + match server_rw.handle_admin_recover_account(name, password, eventid).await { 59 + Ok(password) => AdminTaskResponse::RecoverAccount { password }, 60 + Err(e) => { 61 + error!(err = ?e, "error during recover-account"); 62 + diff --git a/server/daemon/src/main.rs b/server/daemon/src/main.rs 63 + index c3b40faa0..2a57a307c 100644 64 + --- a/server/daemon/src/main.rs 65 + +++ b/server/daemon/src/main.rs 66 + @@ -923,13 +923,34 @@ async fn kanidm_main(config: Configuration, opt: KanidmdParser) -> ExitCode { 67 + .await; 68 + } 69 + } 70 + - KanidmdOpt::RecoverAccount { name, commonopts } => { 71 + + KanidmdOpt::RecoverAccount { name, from_environment, commonopts } => { 72 + info!("Running account recovery ..."); 73 + let output_mode: ConsoleOutputMode = commonopts.output_mode.to_owned().into(); 74 + + let password = if *from_environment { 75 + + match std::env::var("KANIDM_RECOVER_ACCOUNT_PASSWORD_FILE") { 76 + + Ok(path) => match tokio::fs::read_to_string(&path).await { 77 + + Ok(contents) => Some(contents), 78 + + Err(e) => { 79 + + error!("Failed to read password file '{}': {}", path, e); 80 + + return ExitCode::FAILURE; 81 + + } 82 + + }, 83 + + Err(_) => match std::env::var("KANIDM_RECOVER_ACCOUNT_PASSWORD") { 84 + + Ok(val) => Some(val), 85 + + Err(_) => { 86 + + error!("Neither KANIDM_RECOVER_ACCOUNT_PASSWORD_FILE nor KANIDM_RECOVER_ACCOUNT_PASSWORD was set"); 87 + + return ExitCode::FAILURE; 88 + + } 89 + + } 90 + + } 91 + + } else { 92 + + None 93 + + }; 94 + submit_admin_req( 95 + config.adminbindpath.as_str(), 96 + AdminTaskRequest::RecoverAccount { 97 + name: name.to_owned(), 98 + + password, 99 + }, 100 + output_mode, 101 + ) 102 + diff --git a/server/daemon/src/opt.rs b/server/daemon/src/opt.rs 103 + index f1b45a5b3..ca19fb6a5 100644 104 + --- a/server/daemon/src/opt.rs 105 + +++ b/server/daemon/src/opt.rs 106 + @@ -236,6 +236,13 @@ enum KanidmdOpt { 107 + #[clap(value_parser)] 108 + /// The account name to recover credentials for. 109 + name: String, 110 + + /// Use a password given via an environment variable. 111 + + /// - `KANIDM_RECOVER_ACCOUNT_PASSWORD_FILE` takes precedence and reads the desired 112 + + /// password from the given file 113 + + /// - `KANIDM_RECOVER_ACCOUNT_PASSWORD` directly takes a 114 + + /// password - beware that this will leave the password in the environment 115 + + #[clap(long = "from-environment")] 116 + + from_environment: bool, 117 + #[clap(flatten)] 118 + commonopts: CommonOpt, 119 + }, 120 + -- 121 + 2.49.0 122 +
+5
pkgs/top-level/all-packages.nix
··· 10136 10136 10137 10137 kanidm_1_5 = callPackage ../by-name/ka/kanidm/1_5.nix { kanidm = kanidm_1_5; }; 10138 10138 kanidm_1_6 = callPackage ../by-name/ka/kanidm/1_6.nix { kanidm = kanidm_1_6; }; 10139 + kanidm_1_7 = callPackage ../by-name/ka/kanidm/1_7.nix { kanidm = kanidm_1_7; }; 10139 10140 10140 10141 kanidmWithSecretProvisioning = kanidmWithSecretProvisioning_1_6; 10141 10142 ··· 10145 10144 }; 10146 10145 10147 10146 kanidmWithSecretProvisioning_1_6 = callPackage ../by-name/ka/kanidm/1_6.nix { 10147 + enableSecretProvisioning = true; 10148 + }; 10149 + 10150 + kanidmWithSecretProvisioning_1_7 = callPackage ../by-name/ka/kanidm/1_7.nix { 10148 10151 enableSecretProvisioning = true; 10149 10152 }; 10150 10153