@@ -57,8 +57,11 @@ const MAX_CERT_CHAIN_LEN: usize = 10;
5757/// The ideal number of certs is 1, so this need not be large.
5858const MAX_CERTS : usize = 100 ;
5959
60- /// Maximum number of cached/revoked identities.
61- const MAX_IDENTITIES : usize = 1_000 ;
60+ /// Maximum number of cached identities.
61+ const MAX_CACHED_IDENTITIES : NonZeroUsize = NonZeroUsize :: new ( 1_000 ) . unwrap ( ) ;
62+
63+ /// Maximum number of revoked identities.
64+ const MAX_REVOKED_IDENTITIES : usize = 1_000 ;
6265
6366/// Maximum number of active jobs in a session.
6467const MAX_ACTIVE_JOBS : usize = 1_000 ;
@@ -82,7 +85,8 @@ type SessionGuard<'a> = MutexGuard<'a, Option<Session>>;
8285pub struct JobManager {
8386 log : Logger ,
8487 nonces : Arc < Mutex < LruCache < Nonce , DateTime < Utc > > > > ,
85- identities : Arc < Mutex < BTreeMap < KeyId , ( Identity , Credentials ) > > > ,
88+ identities : Arc < Mutex < LruCache < KeyId , ( Identity , Credentials ) > > > ,
89+ revoked_identities : Arc < Mutex < BTreeMap < KeyId , DateTime < Utc > > > > ,
8690 certs : Arc < Mutex < BTreeMap < KeyId , Certificate > > > ,
8791 session : Arc < Mutex < Option < Session > > > ,
8892 active_jobs : Arc < Mutex < BTreeMap < JobId , JobStatus > > > ,
@@ -124,7 +128,8 @@ impl JobManager {
124128 let new = Self {
125129 log : log. new ( o ! ( "component" => "manager" ) ) ,
126130 nonces : Arc :: new ( Mutex :: new ( LruCache :: new ( MAX_OUTSTANDING_NONCES ) ) ) ,
127- identities : Arc :: new ( Mutex :: new ( BTreeMap :: new ( ) ) ) ,
131+ identities : Arc :: new ( Mutex :: new ( LruCache :: new ( MAX_CACHED_IDENTITIES ) ) ) ,
132+ revoked_identities : Arc :: new ( Mutex :: new ( BTreeMap :: new ( ) ) ) ,
128133 certs : Arc :: new ( Mutex :: new ( BTreeMap :: new ( ) ) ) ,
129134 session : Arc :: new ( Mutex :: new ( None ) ) ,
130135 active_jobs,
@@ -259,11 +264,21 @@ impl JobManager {
259264 signature,
260265 } = credentials. clone ( ) ;
261266
267+ // Check for a revoked identity.
268+ if self
269+ . revoked_identities
270+ . lock ( )
271+ . unwrap ( )
272+ . contains_key ( & key_id)
273+ {
274+ unauthorized ! ( "identity revoked" ) ;
275+ }
276+
262277 // Check the cache.
263278 let mut identities = self . identities . lock ( ) . unwrap ( ) ;
264279 let now = Utc :: now ( ) ;
265- identities. retain ( |_k, ( i, _c) | i. is_still_valid ( & now) || i. time_revoked . is_some ( ) ) ;
266280 if let Some ( ( identity, cached_credentials) ) = identities. get ( & key_id) . cloned ( )
281+ && try_authn ! ( identity. is_still_valid( & now) , "identity expired" )
267282 && try_authn ! ( identity. time_revoked. is_none( ) , "identity revoked" )
268283 && cached_credentials. nonce == nonce
269284 && cached_credentials. cnonce == cnonce
@@ -294,10 +309,7 @@ impl JobManager {
294309
295310 // Authenticated! Try to cache the credentials.
296311 debug ! ( self . log, "authenticated credentials for new identity" ; "key_id" => %key_id) ;
297- if identities. len ( ) >= MAX_IDENTITIES {
298- return Err ( JobError :: TooManyIdentities ( MAX_IDENTITIES ) ) ;
299- }
300- identities. insert ( key_id. to_owned ( ) , ( identity. clone ( ) , credentials) ) ;
312+ identities. put ( key_id. to_owned ( ) , ( identity. clone ( ) , credentials) ) ;
301313 Ok ( identity)
302314 }
303315
@@ -312,15 +324,21 @@ impl JobManager {
312324 }
313325
314326 pub async fn revoke_identity ( & self , _authn : & Identity , key_id : KeyId ) -> Result < ( ) , JobError > {
315- let time_revoked = Utc :: now ( ) ;
316- if let Some ( ( identity, _credentials) ) = self . identities . lock ( ) . unwrap ( ) . get_mut ( & key_id) {
317- identity. time_revoked = Some ( time_revoked) ;
318- } else {
319- return Err ( JobError :: IdentityNotFound ( key_id) ) ;
327+ if let Some ( session) = {
328+ self . session
329+ . lock ( )
330+ . unwrap ( )
331+ . take_if ( |session| session. key_id ( ) == Some ( & key_id) )
332+ } {
333+ self . session_stop_inner ( session) . await ?;
334+ }
335+
336+ let mut revoked = self . revoked_identities . lock ( ) . unwrap ( ) ;
337+ if revoked. len ( ) >= MAX_REVOKED_IDENTITIES {
338+ return Err ( JobError :: TooManyRevocations ( MAX_REVOKED_IDENTITIES ) ) ;
320339 }
321- // for job_id in todo!("get interactive sessions") {
322- // self.monitor(MonitorRequest::Stop(job_id)).await?;
323- // }
340+ revoked. insert ( key_id. clone ( ) , Utc :: now ( ) ) ;
341+
324342 Ok ( ( ) )
325343 }
326344
@@ -347,11 +365,7 @@ impl JobManager {
347365 // Anyone is allowed to stop a session.
348366 let session = {
349367 let mut session_guard = self . session . lock ( ) . unwrap ( ) ;
350- if session_guard. as_ref ( ) . map ( |s| s. session_id ( ) ) == Some ( session_id) {
351- session_guard. take ( )
352- } else {
353- None
354- }
368+ session_guard. take_if ( |session| session. session_id ( ) == session_id)
355369 } ;
356370 if let Some ( session) = session {
357371 self . session_stop_inner ( session) . await
@@ -361,7 +375,18 @@ impl JobManager {
361375 }
362376
363377 async fn session_stop_inner ( & self , session : Session ) -> Result < ( ) , JobError > {
364- // TODO: send session stop event
378+ for job_id in {
379+ self . active_jobs
380+ . lock ( )
381+ . unwrap ( )
382+ . iter ( )
383+ . filter ( |( _id, status) | status. session_id ( ) == Some ( session. session_id ( ) ) )
384+ . map ( |( id, _status) | id. to_owned ( ) )
385+ . collect :: < Vec < JobId > > ( )
386+ } {
387+ self . monitor ( MonitorRequest :: Stop ( job_id. to_owned ( ) ) )
388+ . await ?;
389+ }
365390 info ! ( self . log, "session stopped" ; "session_id" => %session. session_id( ) ) ;
366391 Ok ( ( ) )
367392 }
@@ -455,6 +480,7 @@ impl JobManager {
455480 let Some ( job_session_id) = self
456481 . job_status_inner ( & mut session_guard, job_id) ?
457482 . session_id ( )
483+ . cloned ( )
458484 else {
459485 return Err ( JobError :: JobNotFound ( job_id. to_owned ( ) ) ) ;
460486 } ;
0 commit comments