Skip to content

Commit

Permalink
feat: [torrust#978] add a config option to disable cheking keys' expi…
Browse files Browse the repository at this point in the history
…ration

When the tracker is running in private mode you can disable checking
keys' expiration in the configuration with:

```toml
[core]
private = false

[core.private_mode]
check_keys_expiration = true
```

All keys will be valid as long as they exist in the database.
  • Loading branch information
josecelano committed Aug 1, 2024
1 parent 680f642 commit e8e935c
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 7 deletions.
39 changes: 39 additions & 0 deletions packages/configuration/src/v2/core.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use derive_more::{Constructor, Display};
use serde::{Deserialize, Serialize};

use super::network::Network;
Expand Down Expand Up @@ -32,6 +33,10 @@ pub struct Core {
#[serde(default = "Core::default_private")]
pub private: bool,

// Configuration specific when the tracker is running in private mode.
#[serde(default = "Core::default_private_mode")]
pub private_mode: Option<PrivateMode>,

// Tracker policy configuration.
#[serde(default = "Core::default_tracker_policy")]
pub tracker_policy: TrackerPolicy,
Expand All @@ -54,6 +59,7 @@ impl Default for Core {
listed: Self::default_listed(),
net: Self::default_network(),
private: Self::default_private(),
private_mode: Self::default_private_mode(),
tracker_policy: Self::default_tracker_policy(),
tracker_usage_statistics: Self::default_tracker_usage_statistics(),
}
Expand Down Expand Up @@ -85,10 +91,43 @@ impl Core {
false
}

fn default_private_mode() -> Option<PrivateMode> {
if Self::default_private() {
Some(PrivateMode::default())
} else {
None
}
}

fn default_tracker_policy() -> TrackerPolicy {
TrackerPolicy::default()
}
fn default_tracker_usage_statistics() -> bool {
true
}
}

/// Configuration specific when the tracker is running in private mode.
#[derive(Serialize, Deserialize, PartialEq, Eq, Debug, Clone, Copy, Constructor, Display)]
pub struct PrivateMode {
/// A flag to disable expiration date for peer keys.
///
/// When true, if the keys is not permanent the expiration date will be
/// ignored. The key will be accepted even if it has expired.
#[serde(default = "PrivateMode::default_check_keys_expiration")]
pub check_keys_expiration: bool,
}

impl Default for PrivateMode {
fn default() -> Self {
Self {
check_keys_expiration: Self::default_check_keys_expiration(),
}
}
}

impl PrivateMode {
fn default_check_keys_expiration() -> bool {
true
}
}
10 changes: 5 additions & 5 deletions src/core/auth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
//!
//! // And you can later verify it with:
//!
//! assert!(auth::verify_key(&expiring_key).is_ok());
//! assert!(auth::verify_key_expiration(&expiring_key).is_ok());
//! ```
use std::panic::Location;
Expand Down Expand Up @@ -106,7 +106,7 @@ pub fn generate_key(lifetime: Option<Duration>) -> PeerKey {
///
/// - `Error::KeyExpired` if `auth_key.valid_until` is past the `current_time`.
/// - `Error::KeyInvalid` if `auth_key.valid_until` is past the `None`.
pub fn verify_key(auth_key: &PeerKey) -> Result<(), Error> {
pub fn verify_key_expiration(auth_key: &PeerKey) -> Result<(), Error> {
let current_time: DurationSinceUnixEpoch = CurrentClock::now();

match auth_key.valid_until {
Expand Down Expand Up @@ -322,7 +322,7 @@ mod tests {
fn should_be_generated_with_a_expiration_time() {
let expiring_key = auth::generate_key(Some(Duration::new(9999, 0)));

assert!(auth::verify_key(&expiring_key).is_ok());
assert!(auth::verify_key_expiration(&expiring_key).is_ok());
}

#[test]
Expand All @@ -336,12 +336,12 @@ mod tests {
// Mock the time has passed 10 sec.
clock::Stopped::local_add(&Duration::from_secs(10)).unwrap();

assert!(auth::verify_key(&expiring_key).is_ok());
assert!(auth::verify_key_expiration(&expiring_key).is_ok());

// Mock the time has passed another 10 sec.
clock::Stopped::local_add(&Duration::from_secs(10)).unwrap();

assert!(auth::verify_key(&expiring_key).is_err());
assert!(auth::verify_key_expiration(&expiring_key).is_err());
}
}
}
32 changes: 30 additions & 2 deletions src/core/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -996,7 +996,16 @@ impl Tracker {
location: Location::caller(),
key: Box::new(key.clone()),
}),
Some(key) => auth::verify_key(key),
Some(key) => match self.config.private_mode {
Some(private_mode) => {
if private_mode.check_keys_expiration {
return auth::verify_key_expiration(key);
}

Ok(())
}
None => auth::verify_key_expiration(key),
},
}
}

Expand Down Expand Up @@ -1779,8 +1788,9 @@ mod tests {
use std::time::Duration;

use torrust_tracker_clock::clock::Time;
use torrust_tracker_configuration::v2::core::PrivateMode;

use crate::core::auth;
use crate::core::auth::{self, Key};
use crate::core::tests::the_tracker::private_tracker;
use crate::CurrentClock;

Expand Down Expand Up @@ -1829,6 +1839,24 @@ mod tests {
assert!(tracker.verify_auth_key(&expiring_key.key()).await.is_ok());
}

#[tokio::test]
async fn it_should_accept_an_expired_key_when_checking_expiration_is_disabled_in_configuration() {
let mut tracker = private_tracker();

tracker.config.private_mode = Some(PrivateMode {
check_keys_expiration: false,
});

let past_time = Some(Duration::ZERO);

let expiring_key = tracker
.add_auth_key(Key::new("YZSl4lMZupRuOpSRC3krIKR5BPB14nrJ").unwrap(), past_time)
.await
.unwrap();

assert!(tracker.authenticate(&expiring_key.key()).await.is_ok());
}

#[tokio::test]
async fn it_should_fail_verifying_an_unregistered_authentication_key() {
let tracker = private_tracker();
Expand Down

0 comments on commit e8e935c

Please sign in to comment.