Skip to content

Commit 6aed0d5

Browse files
committed
Add revoke JWT endpoint
1 parent cc628fc commit 6aed0d5

4 files changed

Lines changed: 36 additions & 10 deletions

File tree

crates/common/src/commit/constants.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@ pub const REQUEST_SIGNATURE_PATH: &str = "/signer/v1/request_signature";
33
pub const GENERATE_PROXY_KEY_PATH: &str = "/signer/v1/generate_proxy_key";
44
pub const STATUS_PATH: &str = "/status";
55
pub const RELOAD_PATH: &str = "/reload";
6+
pub const REVOKE_JWT: &str = "/revoke_jwt";

crates/common/src/commit/request.rs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,11 @@ use tree_hash::TreeHash;
1414
use tree_hash_derive::TreeHash;
1515

1616
use crate::{
17-
constants::COMMIT_BOOST_DOMAIN, error::BlstErrorWrapper, signature::verify_signed_message,
18-
signer::BlsPublicKey, types::Chain,
17+
constants::COMMIT_BOOST_DOMAIN,
18+
error::BlstErrorWrapper,
19+
signature::verify_signed_message,
20+
signer::BlsPublicKey,
21+
types::{Chain, ModuleId},
1922
};
2023

2124
pub trait ProxyId: AsRef<[u8]> + Debug + Clone + Copy + TreeHash + Display {}
@@ -198,6 +201,11 @@ pub struct GetPubkeysResponse {
198201
pub keys: Vec<ConsensusProxyMap>,
199202
}
200203

204+
#[derive(Debug, Clone, Serialize, Deserialize)]
205+
pub struct RevokeJWTRequest {
206+
pub module_id: ModuleId,
207+
}
208+
201209
/// Map of consensus pubkeys to proxies
202210
#[derive(Debug, Clone, Deserialize, Serialize)]
203211
pub struct ConsensusProxyMap {
@@ -288,7 +296,7 @@ mod tests {
288296

289297
let _: SignedProxyDelegationBls = serde_json::from_str(data).unwrap();
290298

291-
let data = r#"{
299+
let data = r#"{
292300
"message": {
293301
"delegator": "0xa3366b54f28e4bf1461926a3c70cdb0ec432b5c92554ecaae3742d33fb33873990cbed1761c68020e6d3c14d30a22050",
294302
"proxy": "0x4ca9939a8311a7cab3dde201b70157285fa81a9d"

crates/signer/src/error.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ pub enum SignerModuleError {
2525
#[error("Dirk signer does not support this operation")]
2626
DirkNotSupported,
2727

28+
#[error("module id not found")]
29+
ModuleIdNotFound,
30+
2831
#[error("internal error: {0}")]
2932
Internal(String),
3033
}
@@ -45,6 +48,7 @@ impl IntoResponse for SignerModuleError {
4548
(StatusCode::INTERNAL_SERVER_ERROR, "internal error".to_string())
4649
}
4750
SignerModuleError::SignerError(err) => (StatusCode::BAD_REQUEST, err.to_string()),
51+
SignerModuleError::ModuleIdNotFound => (StatusCode::NOT_FOUND, self.to_string()),
4852
}
4953
.into_response()
5054
}

crates/signer/src/service.rs

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,11 @@ use cb_common::{
1313
commit::{
1414
constants::{
1515
GENERATE_PROXY_KEY_PATH, GET_PUBKEYS_PATH, RELOAD_PATH, REQUEST_SIGNATURE_PATH,
16-
STATUS_PATH,
16+
REVOKE_JWT, STATUS_PATH,
1717
},
1818
request::{
19-
EncryptionScheme, GenerateProxyRequest, GetPubkeysResponse, SignConsensusRequest,
20-
SignProxyRequest, SignRequest,
19+
EncryptionScheme, GenerateProxyRequest, GetPubkeysResponse, RevokeJWTRequest,
20+
SignConsensusRequest, SignProxyRequest, SignRequest,
2121
},
2222
},
2323
config::StartSignerConfig,
@@ -47,7 +47,7 @@ struct SigningState {
4747
manager: Arc<RwLock<SigningManager>>,
4848
/// Map of modules ids to JWT secrets. This also acts as registry of all
4949
/// modules running
50-
jwts: Arc<HashMap<ModuleId, String>>,
50+
jwts: Arc<RwLock<HashMap<ModuleId, String>>>,
5151
}
5252

5353
impl SigningService {
@@ -61,7 +61,7 @@ impl SigningService {
6161

6262
let state = SigningState {
6363
manager: Arc::new(RwLock::new(start_manager(config.clone()).await?)),
64-
jwts: config.jwts.into(),
64+
jwts: Arc::new(RwLock::new(config.jwts)),
6565
};
6666

6767
let loaded_consensus = state.manager.read().await.available_consensus_signers();
@@ -77,6 +77,7 @@ impl SigningService {
7777
.route(GENERATE_PROXY_KEY_PATH, post(handle_generate_proxy))
7878
.route_layer(middleware::from_fn_with_state(state.clone(), jwt_auth))
7979
.route(RELOAD_PATH, post(handle_reload))
80+
.route(REVOKE_JWT, post(handle_revoke_jwt))
8081
.with_state(state.clone())
8182
.route_layer(middleware::from_fn(log_request))
8283
.route(STATUS_PATH, get(handle_status));
@@ -108,7 +109,8 @@ async fn jwt_auth(
108109
SignerModuleError::Unauthorized
109110
})?;
110111

111-
let jwt_secret = state.jwts.get(&module_id).ok_or_else(|| {
112+
let guard = state.jwts.read().await;
113+
let jwt_secret = guard.get(&module_id).ok_or_else(|| {
112114
error!("Unauthorized request. Was the module started correctly?");
113115
SignerModuleError::Unauthorized
114116
})?;
@@ -270,7 +272,7 @@ async fn handle_reload(
270272
}
271273
};
272274

273-
state.jwts = config.jwts.clone().into();
275+
state.jwts = Arc::new(RwLock::new(config.jwts.clone()));
274276

275277
let new_manager = match start_manager(config).await {
276278
Ok(manager) => manager,
@@ -285,6 +287,17 @@ async fn handle_reload(
285287
Ok(StatusCode::OK)
286288
}
287289

290+
async fn handle_revoke_jwt(
291+
State(state): State<SigningState>,
292+
Json(request): Json<RevokeJWTRequest>,
293+
) -> Result<impl IntoResponse, SignerModuleError> {
294+
let mut guard = state.jwts.write().await;
295+
guard
296+
.remove(&request.module_id)
297+
.ok_or(SignerModuleError::ModuleIdNotFound)
298+
.map(|_| StatusCode::OK)
299+
}
300+
288301
async fn start_manager(config: StartSignerConfig) -> eyre::Result<SigningManager> {
289302
let proxy_store = if let Some(store) = config.store.clone() {
290303
Some(store.init_from_env()?)

0 commit comments

Comments
 (0)