Skip to content

Commit

Permalink
feat: [#978] add a config option to disable cheking keys' expiration
Browse files Browse the repository at this point in the history
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")]

Check warning on line 37 in packages/configuration/src/v2/core.rs

View check run for this annotation

Codecov / codecov/patch

packages/configuration/src/v2/core.rs#L37

Added line #L37 was not covered by tests
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())

Check warning on line 96 in packages/configuration/src/v2/core.rs

View check run for this annotation

Codecov / codecov/patch

packages/configuration/src/v2/core.rs#L96

Added line #L96 was not covered by tests
} 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)]

Check warning on line 111 in packages/configuration/src/v2/core.rs

View check run for this annotation

Codecov / codecov/patch

packages/configuration/src/v2/core.rs#L111

Added line #L111 was not covered by tests
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,

Check warning on line 118 in packages/configuration/src/v2/core.rs

View check run for this annotation

Codecov / codecov/patch

packages/configuration/src/v2/core.rs#L117-L118

Added lines #L117 - L118 were not covered by tests
}

impl Default for PrivateMode {
fn default() -> Self {

Check warning on line 122 in packages/configuration/src/v2/core.rs

View check run for this annotation

Codecov / codecov/patch

packages/configuration/src/v2/core.rs#L122

Added line #L122 was not covered by tests
Self {
check_keys_expiration: Self::default_check_keys_expiration(),

Check warning on line 124 in packages/configuration/src/v2/core.rs

View check run for this annotation

Codecov / codecov/patch

packages/configuration/src/v2/core.rs#L124

Added line #L124 was not covered by tests
}
}

Check warning on line 126 in packages/configuration/src/v2/core.rs

View check run for this annotation

Codecov / codecov/patch

packages/configuration/src/v2/core.rs#L126

Added line #L126 was not covered by tests
}

impl PrivateMode {
fn default_check_keys_expiration() -> bool {

Check warning on line 130 in packages/configuration/src/v2/core.rs

View check run for this annotation

Codecov / codecov/patch

packages/configuration/src/v2/core.rs#L130

Added line #L130 was not covered by tests
true
}

Check warning on line 132 in packages/configuration/src/v2/core.rs

View check run for this annotation

Codecov / codecov/patch

packages/configuration/src/v2/core.rs#L132

Added line #L132 was not covered by tests
}
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);

Check warning on line 1002 in src/core/mod.rs

View check run for this annotation

Codecov / codecov/patch

src/core/mod.rs#L1002

Added line #L1002 was not covered by tests
}

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.