From 106b4ca4b36491aab217c3b5bdbc3c0685177c41 Mon Sep 17 00:00:00 2001 From: Jordan Doyle Date: Mon, 3 Jul 2023 22:04:43 +0100 Subject: [PATCH] Add expires_at field for impersonation_tokens POST request --- Cargo.lock | 2 ++ Cargo.toml | 1 + src/config.rs | 10 ++++++++++ src/git_command_handlers/ls_refs.rs | 4 ++-- src/main.rs | 4 ++-- src/providers/gitlab.rs | 12 +++++++++--- src/util.rs | 2 +- 7 files changed, 27 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e8909ef..3a00ad9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -556,6 +556,7 @@ dependencies = [ "shlex", "thrussh", "thrussh-keys", + "time", "tokio", "tokio-util", "toml", @@ -1522,6 +1523,7 @@ checksum = "d634a985c4d4238ec39cacaed2e7ae552fbd3c476b552c1deac3021b7d7eaf0c" dependencies = [ "libc", "num_threads", + "serde", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 48b08ca..75999a5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,6 +31,7 @@ serde = { version = "1.0", features = ["derive"] } serde_json = "1" sha1 = "0.10" shlex = "1.1" +time = { version = "0.3", features = ["serde"] } tracing = "0.1" tracing-subscriber = "0.3" thrussh = "0.33" diff --git a/src/config.rs b/src/config.rs index 5518d2d..a4abd98 100644 --- a/src/config.rs +++ b/src/config.rs @@ -3,6 +3,7 @@ use clap::Parser; use serde::{de::DeserializeOwned, Deserialize}; use std::{net::SocketAddr, path::PathBuf}; +use time::Duration; use url::Url; #[derive(Parser)] @@ -25,6 +26,15 @@ pub struct Config { pub struct GitlabConfig { pub uri: Url, pub admin_token: String, + #[serde(default = "GitlabConfig::default_token_expiry")] + pub token_expiry: Duration, +} + +impl GitlabConfig { + #[must_use] + const fn default_token_expiry() -> Duration { + Duration::days(30) + } } pub fn from_toml_path(path: &str) -> Result { diff --git a/src/git_command_handlers/ls_refs.rs b/src/git_command_handlers/ls_refs.rs index 914bf7e..81a68ae 100644 --- a/src/git_command_handlers/ls_refs.rs +++ b/src/git_command_handlers/ls_refs.rs @@ -19,10 +19,10 @@ pub fn handle( _metadata: &[Bytes], commit_hash: &HashOutput, ) -> Result<(), anyhow::Error> { - let commit_hash = hex::encode(&commit_hash); + let commit_hash = hex::encode(commit_hash); handle.write(PktLine::Data( - format!("{} HEAD symref-target:refs/heads/master", commit_hash).as_bytes(), + format!("{commit_hash} HEAD symref-target:refs/heads/master").as_bytes(), ))?; handle.write(PktLine::Flush)?; handle.flush(session, channel); diff --git a/src/main.rs b/src/main.rs index 18c2eca..70b99d6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -84,7 +84,7 @@ async fn main() -> anyhow::Result<()> { .ok_or_else(|| anyhow!("failed to generate server private key"))?; let thrussh_keys::key::KeyPair::Ed25519(key) = key; - std::fs::write(server_private_key, &key.key)?; + std::fs::write(server_private_key, key.key)?; thrussh_keys::key::KeyPair::Ed25519(key) }; @@ -350,7 +350,7 @@ type AsyncHandlerFut = dyn Future as thrussh::server::Handler>::Error>> + Send; #[allow(clippy::type_complexity)] -impl<'a, U: UserProvider + PackageProvider + Send + Sync + 'static> thrussh::server::Handler +impl thrussh::server::Handler for Handler { type Error = anyhow::Error; diff --git a/src/providers/gitlab.rs b/src/providers/gitlab.rs index 790315a..d7c1f23 100644 --- a/src/providers/gitlab.rs +++ b/src/providers/gitlab.rs @@ -8,12 +8,14 @@ use percent_encoding::{utf8_percent_encode, NON_ALPHANUMERIC}; use reqwest::header; use serde::{Deserialize, Serialize}; use std::{borrow::Cow, sync::Arc}; +use time::{Duration, OffsetDateTime}; use tracing::{info_span, instrument, Instrument}; use url::Url; pub struct Gitlab { client: reqwest::Client, base_url: Url, + token_expiry: Duration, } impl Gitlab { @@ -29,6 +31,7 @@ impl Gitlab { .default_headers(headers) .build()?, base_url: config.uri.join("api/v4/")?, + token_expiry: config.token_expiry, }) } } @@ -41,9 +44,8 @@ impl super::UserProvider for Gitlab { username_password: &str, ) -> anyhow::Result> { let mut splitter = username_password.splitn(2, ':'); - let (username, password) = match (splitter.next(), splitter.next()) { - (Some(username), Some(password)) => (username, password), - _ => return Ok(None), + let (Some(username), Some(password)) = (splitter.next(), splitter.next()) else { + return Ok(None); }; if username == "gitlab-ci-token" { @@ -95,6 +97,9 @@ impl super::UserProvider for Gitlab { ) .json(&GitlabImpersonationTokenRequest { name: env!("CARGO_PKG_NAME"), + expires_at: (OffsetDateTime::now_utc() + self.token_expiry) + .date() + .to_string(), scopes: vec!["api"], }) .send() @@ -273,6 +278,7 @@ impl GitlabCratePath { #[derive(Serialize)] pub struct GitlabImpersonationTokenRequest { name: &'static str, + expires_at: String, scopes: Vec<&'static str>, } diff --git a/src/util.rs b/src/util.rs index aeec7ef..847094f 100644 --- a/src/util.rs +++ b/src/util.rs @@ -9,7 +9,7 @@ use ustr::ustr; #[must_use] pub fn format_fingerprint(fingerprint: &str) -> String { - format!("SHA256:{}", fingerprint) + format!("SHA256:{fingerprint}") } /// Crates with a total of 1, 2 characters in the same are written out to directories named -- libgit2 1.7.2