Unverified Commit cb0acd6f authored by Adam C. Stephens's avatar Adam C. Stephens Committed by GitHub
Browse files

kanidm_1_5: mark EOL, kanidm_1_4: remove (#417915)

parents 27d7ead2 491f0239
Loading
Loading
Loading
Loading

pkgs/by-name/ka/kanidm/1_4.nix

deleted100644 → 0
+0 −7
Original line number Diff line number Diff line
import ./generic.nix {
  version = "1.4.6";
  hash = "sha256-pjJyq52wO5p34LN2Jmt0npgWBDcWin8gIX4skZ7Ff8E=";
  cargoHash = "sha256-33HRoH/vWPe/wOZJtQLWV9eBocbj0iR/XUu4zMehu8M=";
  patchDir = ./patches/1_4;
  unsupported = true;
}
+1 −0
Original line number Diff line number Diff line
@@ -3,4 +3,5 @@ import ./generic.nix {
  hash = "sha256-swrqyjA7Wgq17vd+753LDFcXrSFixVNLhTvj1bhG3DU=";
  cargoHash = "sha256-72IwS8Nk1y6xDH9y8JW2LpbhFWaq0tpORx7JQSCF5/M=";
  patchDir = ./patches/1_5;
  unsupported = true;
}
+4 −8
Original line number Diff line number Diff line
@@ -21,12 +21,7 @@ For example, when upgrading from 1.4 -> 1.5
1. Update `all-packages.nix` to add `kanidm_1_5` and `kanidmWithSecretProvisioning_1_5`, leave default
1. Create commit, `kanidm_1_5: init at 1.5.0` - this is the only commit that will be backported

### Mark previous version deprecated

1. Update `pkgs/by-name/ka/kanidm/1_4.nix` by adding `deprecated = true;`
1. Create commit `kanidm_1_4: update default to 1.5.0, deprecate 1.4.0`

### Update default and mark deprecation
### Update default

1. `sed -i 's/1_4/1_5/' pkgs/by-name/ka/kanidm/package.nix`
1. Update `all-packages.nix` and set `kanidmWithSecretProvisioning = kanidmWithSecretProvisioning_1_5;`
@@ -41,9 +36,10 @@ For example, when upgrading from 1.4 -> 1.5
Kanidm versions are supported for 30 days after the release of new versions. Following the example above, 1.5.x superseding 1.4.x in 30 days, do the following near the end of the 30 day window

1. Update `pkgs/by-name/ka/kanidm/1_4.nix` by adding `unsupported = true;`
1. Update `pkgs/top-level/release.nix` and add `kanidm_1_4-1.4.6` to `permittedInsecurePackages`
1. Update `pkgs/top-level/release.nix` and add `kanidm_1_4-1.4.6` and `kanidmWithSecretProvisioning_1_4-1.4.6` to `permittedInsecurePackages`
1. Create commit `kanidm_1_4: mark EOL`, this commit alone should be backported

1. Remove the third oldest release from `all-packages.nix`, e.g. 1.3.x continuing the example. Remove `kanidm_1_3` and `kanidmWithSecretProvisioning_1_3`
1. Update `pkgs/top-level/release.nix` and remove `kanidm_1_3-1.3.3` from `permittedInsecurePackages`
1. Update `pkgs/top-level/release.nix` and remove `kanidm_1_3*` from `permittedInsecurePackages`
1. Update `pkgs/top-level/aliases.nix` and add `kanidm_1_4` and `kanidmWithSecretProvisioning_1_4-1.4.6`
1. Remove `pkgs/by-name/ka/kanidm/1_3.nix`
+0 −303
Original line number Diff line number Diff line
From 44dfbc2b9dccce86c7d7e7b54db4c989344b8c56 Mon Sep 17 00:00:00 2001
From: oddlama <oddlama@oddlama.org>
Date: Mon, 12 Aug 2024 23:17:25 +0200
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/constants/acp.rs    |  6 +++++
 4 files changed, 82 insertions(+), 1 deletion(-)

diff --git a/server/core/src/actors/v1_write.rs b/server/core/src/actors/v1_write.rs
index e00a969fb..1cacc67b8 100644
--- a/server/core/src/actors/v1_write.rs
+++ b/server/core/src/actors/v1_write.rs
@@ -315,20 +315,62 @@ impl QueryServerWriteV1 {
         };
 
         trace!(?del, "Begin delete event");
 
         idms_prox_write
             .qs_write
             .delete(&del)
             .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,
         fields(uuid = ?eventid)
     )]
     pub async fn handle_reviverecycled(
         &self,
         client_auth_info: ClientAuthInfo,
         filter: Filter<FilterInvalid>,
         eventid: Uuid,
diff --git a/server/core/src/https/v1.rs b/server/core/src/https/v1.rs
index 8aba83bb2..f1f815026 100644
--- a/server/core/src/https/v1.rs
+++ b/server/core/src/https/v1.rs
@@ -1,17 +1,17 @@
 //! The V1 API things!
 
 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};
 use kanidm_proto::constants::uri::V1_AUTH_VALID;
 use std::net::IpAddr;
 use uuid::Uuid;
 
 use kanidm_proto::internal::{
     ApiToken, AppLink, CUIntentToken, CURequest, CUSessionToken, CUStatus, CreateRequest,
     CredentialStatus, DeleteRequest, IdentifyUserRequest, IdentifyUserResponse, ModifyRequest,
@@ -3119,20 +3119,24 @@ pub(crate) fn route_setup(state: ServerState) -> Router<ServerState> {
         )
         .route(
             "/v1/oauth2/:rs_name/_image",
             post(super::v1_oauth2::oauth2_id_image_post)
                 .delete(super::v1_oauth2::oauth2_id_image_delete),
         )
         .route(
             "/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)
                 .delete(super::v1_oauth2::oauth2_id_scopemap_delete),
         )
         .route(
             "/v1/oauth2/:rs_name/_sup_scopemap/:group",
             post(super::v1_oauth2::oauth2_id_sup_scopemap_post)
                 .delete(super::v1_oauth2::oauth2_id_sup_scopemap_delete),
         )
diff --git a/server/core/src/https/v1_oauth2.rs b/server/core/src/https/v1_oauth2.rs
index 5e481afab..a771aed04 100644
--- a/server/core/src/https/v1_oauth2.rs
+++ b/server/core/src/https/v1_oauth2.rs
@@ -144,20 +144,49 @@ pub(crate) async fn oauth2_id_get_basic_secret(
 ) -> Result<Json<Option<String>>, WebError> {
     let filter = oauth2_id(&rs_name);
     state
         .qe_r_ref
         .handle_oauth2_basic_secret_read(client_auth_info, filter, kopid.eventid)
         .await
         .map(Json::from)
         .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}",
     request_body=ProtoEntry,
     responses(
         DefaultApiResponse,
     ),
     security(("token_jwt" = [])),
     tag = "v1/oauth2",
     operation_id = "oauth2_id_patch"
diff --git a/server/lib/src/constants/acp.rs b/server/lib/src/constants/acp.rs
index f3409649d..42e407b7d 100644
--- a/server/lib/src/constants/acp.rs
+++ b/server/lib/src/constants/acp.rs
@@ -645,34 +645,36 @@ lazy_static! {
             Attribute::Image,
         ],
         modify_present_attrs: vec![
             Attribute::Description,
             Attribute::DisplayName,
             Attribute::OAuth2RsName,
             Attribute::OAuth2RsOrigin,
             Attribute::OAuth2RsOriginLanding,
             Attribute::OAuth2RsSupScopeMap,
             Attribute::OAuth2RsScopeMap,
+            Attribute::OAuth2RsBasicSecret,
             Attribute::OAuth2AllowInsecureClientDisablePkce,
             Attribute::OAuth2JwtLegacyCryptoEnable,
             Attribute::OAuth2PreferShortUsername,
             Attribute::Image,
         ],
         create_attrs: vec![
             Attribute::Class,
             Attribute::Description,
             Attribute::DisplayName,
             Attribute::OAuth2RsName,
             Attribute::OAuth2RsOrigin,
             Attribute::OAuth2RsOriginLanding,
             Attribute::OAuth2RsSupScopeMap,
             Attribute::OAuth2RsScopeMap,
+            Attribute::OAuth2RsBasicSecret,
             Attribute::OAuth2AllowInsecureClientDisablePkce,
             Attribute::OAuth2JwtLegacyCryptoEnable,
             Attribute::OAuth2PreferShortUsername,
             Attribute::Image,
         ],
         create_classes: vec![
             EntryClass::Object,
             EntryClass::OAuth2ResourceServer,
             EntryClass::OAuth2ResourceServerBasic,
             EntryClass::OAuth2ResourceServerPublic,
@@ -739,36 +741,38 @@ lazy_static! {
             Attribute::Image,
         ],
         modify_present_attrs: vec![
             Attribute::Description,
             Attribute::DisplayName,
             Attribute::OAuth2RsName,
             Attribute::OAuth2RsOrigin,
             Attribute::OAuth2RsOriginLanding,
             Attribute::OAuth2RsSupScopeMap,
             Attribute::OAuth2RsScopeMap,
+            Attribute::OAuth2RsBasicSecret,
             Attribute::OAuth2AllowInsecureClientDisablePkce,
             Attribute::OAuth2JwtLegacyCryptoEnable,
             Attribute::OAuth2PreferShortUsername,
             Attribute::OAuth2AllowLocalhostRedirect,
             Attribute::OAuth2RsClaimMap,
             Attribute::Image,
         ],
         create_attrs: vec![
             Attribute::Class,
             Attribute::Description,
             Attribute::DisplayName,
             Attribute::OAuth2RsName,
             Attribute::OAuth2RsOrigin,
             Attribute::OAuth2RsOriginLanding,
             Attribute::OAuth2RsSupScopeMap,
             Attribute::OAuth2RsScopeMap,
+            Attribute::OAuth2RsBasicSecret,
             Attribute::OAuth2AllowInsecureClientDisablePkce,
             Attribute::OAuth2JwtLegacyCryptoEnable,
             Attribute::OAuth2PreferShortUsername,
             Attribute::OAuth2AllowLocalhostRedirect,
             Attribute::OAuth2RsClaimMap,
             Attribute::Image,
         ],
         create_classes: vec![
             EntryClass::Object,
             EntryClass::OAuth2ResourceServer,
@@ -840,36 +844,38 @@ lazy_static! {
             Attribute::Image,
         ],
         modify_present_attrs: vec![
             Attribute::Description,
             Attribute::DisplayName,
             Attribute::Name,
             Attribute::OAuth2RsOrigin,
             Attribute::OAuth2RsOriginLanding,
             Attribute::OAuth2RsSupScopeMap,
             Attribute::OAuth2RsScopeMap,
+            Attribute::OAuth2RsBasicSecret,
             Attribute::OAuth2AllowInsecureClientDisablePkce,
             Attribute::OAuth2JwtLegacyCryptoEnable,
             Attribute::OAuth2PreferShortUsername,
             Attribute::OAuth2AllowLocalhostRedirect,
             Attribute::OAuth2RsClaimMap,
             Attribute::Image,
         ],
         create_attrs: vec![
             Attribute::Class,
             Attribute::Description,
             Attribute::Name,
             Attribute::OAuth2RsName,
             Attribute::OAuth2RsOrigin,
             Attribute::OAuth2RsOriginLanding,
             Attribute::OAuth2RsSupScopeMap,
             Attribute::OAuth2RsScopeMap,
+            Attribute::OAuth2RsBasicSecret,
             Attribute::OAuth2AllowInsecureClientDisablePkce,
             Attribute::OAuth2JwtLegacyCryptoEnable,
             Attribute::OAuth2PreferShortUsername,
             Attribute::OAuth2AllowLocalhostRedirect,
             Attribute::OAuth2RsClaimMap,
             Attribute::Image,
         ],
         create_classes: vec![
             EntryClass::Object,
             EntryClass::Account,
-- 
2.45.2
+0 −174
Original line number Diff line number Diff line
From cc8269489b56755714f07eee4671f8aa2659c014 Mon Sep 17 00:00:00 2001
From: oddlama <oddlama@oddlama.org>
Date: Mon, 12 Aug 2024 23:17:42 +0200
Subject: [PATCH 2/2] recover account

---
 server/core/src/actors/internal.rs |  3 ++-
 server/core/src/admin.rs           |  6 +++---
 server/daemon/src/main.rs          | 14 +++++++++++++-
 server/daemon/src/opt.rs           |  4 ++++
 4 files changed, 22 insertions(+), 5 deletions(-)

diff --git a/server/core/src/actors/internal.rs b/server/core/src/actors/internal.rs
index 40c18777f..40d553b40 100644
--- a/server/core/src/actors/internal.rs
+++ b/server/core/src/actors/internal.rs
@@ -153,25 +153,26 @@ 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)
     }
 
     #[instrument(
         level = "info",
         skip_all,
         fields(uuid = ?eventid)
     )]
     pub(crate) async fn handle_domain_raise(&self, eventid: Uuid) -> Result<u32, OperationError> {
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
@@ -17,21 +17,21 @@ use tokio_util::codec::{Decoder, Encoder, Framed};
 use tracing::{span, Instrument, Level};
 use uuid::Uuid;
 
 pub use kanidm_proto::internal::{
     DomainInfo as ProtoDomainInfo, DomainUpgradeCheckReport as ProtoDomainUpgradeCheckReport,
     DomainUpgradeCheckStatus as ProtoDomainUpgradeCheckStatus,
 };
 
 #[derive(Serialize, Deserialize, Debug)]
 pub enum AdminTaskRequest {
-    RecoverAccount { name: String },
+    RecoverAccount { name: String, password: Option<String> },
     ShowReplicationCertificate,
     RenewReplicationCertificate,
     RefreshReplicationConsumer,
     DomainShow,
     DomainUpgradeCheck,
     DomainRaise,
     DomainRemigrate { level: Option<u32> },
 }
 
 #[derive(Serialize, Deserialize, Debug)]
@@ -302,22 +302,22 @@ async fn handle_client(
     let mut reqs = Framed::new(sock, ServerCodec);
 
     trace!("Waiting for requests ...");
     while let Some(Ok(req)) = reqs.next().await {
         // Setup the logging span
         let eventid = Uuid::new_v4();
         let nspan = span!(Level::INFO, "handle_admin_client_request", uuid = ?eventid);
 
         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");
                             AdminTaskResponse::Error
                         }
                     }
                 }
                 AdminTaskRequest::ShowReplicationCertificate => match repl_ctrl_tx.as_mut() {
                     Some(ctrl_tx) => show_replication_certificate(ctrl_tx).await,
                     None => {
diff --git a/server/daemon/src/main.rs b/server/daemon/src/main.rs
index 577995615..a967928c9 100644
--- a/server/daemon/src/main.rs
+++ b/server/daemon/src/main.rs
@@ -894,27 +894,39 @@ async fn kanidm_main(
             } else {
                 let output_mode: ConsoleOutputMode = commonopts.output_mode.to_owned().into();
                 submit_admin_req(
                     config.adminbindpath.as_str(),
                     AdminTaskRequest::RefreshReplicationConsumer,
                     output_mode,
                 )
                 .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") {
+                    Ok(val) => Some(val),
+                    _ => {
+                        error!("Environment variable KANIDM_RECOVER_ACCOUNT_PASSWORD not set");
+                        return ExitCode::FAILURE;
+                    }
+                }
+            } else {
+                None
+            };
             submit_admin_req(
                 config.adminbindpath.as_str(),
                 AdminTaskRequest::RecoverAccount {
                     name: name.to_owned(),
+                    password,
                 },
                 output_mode,
             )
             .await;
         }
         KanidmdOpt::Database {
             commands: DbCommands::Reindex(_copt),
         } => {
             info!("Running in reindex mode ...");
             reindex_server_core(&config).await;
diff --git a/server/daemon/src/opt.rs b/server/daemon/src/opt.rs
index f1b45a5b3..9c013e32e 100644
--- a/server/daemon/src/opt.rs
+++ b/server/daemon/src/opt.rs
@@ -229,20 +229,24 @@ enum KanidmdOpt {
     /// Create a self-signed ca and tls certificate in the locations listed from the
     /// configuration. These certificates should *not* be used in production, they
     /// are for testing and evaluation only!
     CertGenerate(CommonOpt),
     #[clap(name = "recover-account")]
     /// Recover an account's password
     RecoverAccount {
         #[clap(value_parser)]
         /// The account name to recover credentials for.
         name: String,
+        /// Use the password given in the environment variable
+        /// `KANIDM_RECOVER_ACCOUNT_PASSWORD` instead of generating one.
+        #[clap(long = "from-environment")]
+        from_environment: bool,
         #[clap(flatten)]
         commonopts: CommonOpt,
     },
     /// Display this server's replication certificate
     ShowReplicationCertificate {
         #[clap(flatten)]
         commonopts: CommonOpt,
     },
     /// Renew this server's replication certificate
     RenewReplicationCertificate {
-- 
2.45.2
Loading