diff --git a/Cargo.lock b/Cargo.lock index 068e6e26..d810df42 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2855,6 +2855,7 @@ dependencies = [ "sass-rs", "serde", "serde_json", + "time", "toml", ] diff --git a/Cargo.toml b/Cargo.toml index 60fd92d5..bcb9ed02 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,3 +15,6 @@ toml = "0.8" serde_json = "1.0" rust_team_data = { git = "https://github.com/rust-lang/team" } percent-encoding = "2.1.0" + +[dev-dependencies] +time = { version = "0.3.36", features = ["parsing"] } diff --git a/src/main.rs b/src/main.rs index 50fd2f7f..e72a1d7b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -233,6 +233,11 @@ fn redirect_bare_en_us() -> Redirect { Redirect::permanent("/") } +#[get("/.well-known/security.txt")] +fn well_known_security() -> &'static str { + include_str!("../static/text/well_known_security.txt") +} + #[catch(404)] #[allow(clippy::result_large_err)] fn not_found(req: &Request) -> Result { @@ -459,6 +464,7 @@ async fn rocket() -> _ { team_locale, subject_locale, redirect_bare_en_us, + well_known_security, ], ) .register( diff --git a/static/text/well_known_security.txt b/static/text/well_known_security.txt new file mode 100644 index 00000000..5b873bfd --- /dev/null +++ b/static/text/well_known_security.txt @@ -0,0 +1,2 @@ +Contact: https://www.rust-lang.org/policies/security +Expires: 2025-05-15T00:00:00.000Z diff --git a/tests/well_known_security.rs b/tests/well_known_security.rs new file mode 100644 index 00000000..fc11d39c --- /dev/null +++ b/tests/well_known_security.rs @@ -0,0 +1,37 @@ +use time::{format_description::well_known::Rfc3339, OffsetDateTime}; + +static TEXT: &str = include_str!("../static/text/well_known_security.txt"); + +#[test] +fn well_known_security_is_not_about_to_expire() { + let expires = TEXT.split("Expires:").nth(1).unwrap().trim(); + let expires = OffsetDateTime::parse(expires, &Rfc3339).unwrap(); + let one_month_from_now = OffsetDateTime::now_utc() + time::Duration::days(30); + assert!( + one_month_from_now < expires, + " + ┌────────────────────────────────────────────────────────────────┐ + │ │ + │ I looks like the expiration date of the security policy needs │ + │ updating. Before blindly updating it, please make sure the │ + │ pointed-to URL still refers to the source of truth of the │ + │ security policy of the Rust project. If all is well, you can │ + │ update the expiration date in the relevant file: │ + │ │ + │ static/text/well_known_security.txt │ + │ │ + └────────────────────────────────────────────────────────────────┘ + " + ); +} + +#[test] +fn well_known_security_expires_within_a_year() { + let expires = TEXT.split("Expires:").nth(1).unwrap().trim(); + let expires = OffsetDateTime::parse(expires, &Rfc3339).unwrap(); + let one_year_from_now = OffsetDateTime::now_utc() + time::Duration::days(370); + assert!( + expires < one_year_from_now, + "The security policy should be checked once a year, please reduce the expiration date." + ); +}