Loading pkgs/by-name/ka/kanidm/1_6.nix 0 → 100644 +6 −0 Original line number Diff line number Diff line import ./generic.nix { version = "1.6.2"; hash = "sha256-rfQNx6yAj1mDW7UL8mz01TqMAET9D5fL02JhHeN5zV4="; cargoHash = "sha256-3XUAwuRKtdnMNhH92lgwgeN2rMmzgqir1+OZNaTGmks="; patchDir = ./patches/1_6; } pkgs/by-name/ka/kanidm/package.nix +1 −1 Original line number Diff line number Diff line import ./1_5.nix import ./1_6.nix pkgs/by-name/ka/kanidm/patches/1_6/oauth2-basic-secret-modify.patch 0 → 100644 +159 −0 Original line number Diff line number Diff line From fc26fe5ac9e9cd65af82609c5a4966c8f756ea0f Mon Sep 17 00:00:00 2001 From: oddlama <oddlama@oddlama.org> 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<FilterInvalid>, + 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<ServerState> { "/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<ServerState>, + Extension(kopid): Extension<KOpId>, + VerifiedClientInformation(client_auth_info): VerifiedClientInformation, + Path(rs_name): Path<String>, + Json(new_secret): Json<String>, +) -> Result<Json<()>, 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 pkgs/by-name/ka/kanidm/patches/1_6/recover-account.patch 0 → 100644 +122 −0 Original line number Diff line number Diff line From 229165abe5be596fc2be8e285884813a1b5a38c8 Mon Sep 17 00:00:00 2001 From: oddlama <oddlama@oddlama.org> 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<String>, eventid: Uuid, ) -> Result<String, OperationError> { 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<String> }, 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 pkgs/top-level/all-packages.nix +6 −1 Original line number Diff line number Diff line Loading @@ -10455,8 +10455,9 @@ with pkgs; kanidm_1_4 = callPackage ../by-name/ka/kanidm/1_4.nix { kanidm = kanidm_1_4; }; 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; }; kanidmWithSecretProvisioning = kanidmWithSecretProvisioning_1_5; kanidmWithSecretProvisioning = kanidmWithSecretProvisioning_1_6; kanidmWithSecretProvisioning_1_4 = callPackage ../by-name/ka/kanidm/1_4.nix { enableSecretProvisioning = true; Loading @@ -10466,6 +10467,10 @@ with pkgs; enableSecretProvisioning = true; }; kanidmWithSecretProvisioning_1_6 = callPackage ../by-name/ka/kanidm/1_6.nix { enableSecretProvisioning = true; }; knot-resolver = callPackage ../servers/dns/knot-resolver { systemd = systemdMinimal; # in closure already anyway }; Loading Loading
pkgs/by-name/ka/kanidm/1_6.nix 0 → 100644 +6 −0 Original line number Diff line number Diff line import ./generic.nix { version = "1.6.2"; hash = "sha256-rfQNx6yAj1mDW7UL8mz01TqMAET9D5fL02JhHeN5zV4="; cargoHash = "sha256-3XUAwuRKtdnMNhH92lgwgeN2rMmzgqir1+OZNaTGmks="; patchDir = ./patches/1_6; }
pkgs/by-name/ka/kanidm/package.nix +1 −1 Original line number Diff line number Diff line import ./1_5.nix import ./1_6.nix
pkgs/by-name/ka/kanidm/patches/1_6/oauth2-basic-secret-modify.patch 0 → 100644 +159 −0 Original line number Diff line number Diff line From fc26fe5ac9e9cd65af82609c5a4966c8f756ea0f Mon Sep 17 00:00:00 2001 From: oddlama <oddlama@oddlama.org> 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<FilterInvalid>, + 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<ServerState> { "/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<ServerState>, + Extension(kopid): Extension<KOpId>, + VerifiedClientInformation(client_auth_info): VerifiedClientInformation, + Path(rs_name): Path<String>, + Json(new_secret): Json<String>, +) -> Result<Json<()>, 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
pkgs/by-name/ka/kanidm/patches/1_6/recover-account.patch 0 → 100644 +122 −0 Original line number Diff line number Diff line From 229165abe5be596fc2be8e285884813a1b5a38c8 Mon Sep 17 00:00:00 2001 From: oddlama <oddlama@oddlama.org> 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<String>, eventid: Uuid, ) -> Result<String, OperationError> { 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<String> }, 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
pkgs/top-level/all-packages.nix +6 −1 Original line number Diff line number Diff line Loading @@ -10455,8 +10455,9 @@ with pkgs; kanidm_1_4 = callPackage ../by-name/ka/kanidm/1_4.nix { kanidm = kanidm_1_4; }; 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; }; kanidmWithSecretProvisioning = kanidmWithSecretProvisioning_1_5; kanidmWithSecretProvisioning = kanidmWithSecretProvisioning_1_6; kanidmWithSecretProvisioning_1_4 = callPackage ../by-name/ka/kanidm/1_4.nix { enableSecretProvisioning = true; Loading @@ -10466,6 +10467,10 @@ with pkgs; enableSecretProvisioning = true; }; kanidmWithSecretProvisioning_1_6 = callPackage ../by-name/ka/kanidm/1_6.nix { enableSecretProvisioning = true; }; knot-resolver = callPackage ../servers/dns/knot-resolver { systemd = systemdMinimal; # in closure already anyway }; Loading