|
| 1 | +From fc26fe5ac9e9cd65af82609c5a4966c8f756ea0f Mon Sep 17 00:00:00 2001 |
| 2 | + |
| 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 | + |
0 commit comments