🏡 index : ~doyle/gitlab-cargo-shim.git

author Jordan Doyle <jordan@doyle.la> 2023-07-03 22:04:43.0 +01:00:00
committer Jordan Doyle <jordan@doyle.la> 2023-07-03 22:04:43.0 +01:00:00
commit
106b4ca4b36491aab217c3b5bdbc3c0685177c41 [patch]
tree
f6a25f762bffa06d8397e847c2c211d3b7a65a9b
parent
3e8a188c41e07f4bcb2be8e39c8633e1c4d0f52b
download
106b4ca4b36491aab217c3b5bdbc3c0685177c41.tar.gz

Add expires_at field for impersonation_tokens POST request



Diff

 Cargo.lock                          |  2 ++
 Cargo.toml                          |  1 +
 src/config.rs                       | 10 ++++++++++
 src/main.rs                         |  4 ++--
 src/util.rs                         |  2 +-
 src/git_command_handlers/ls_refs.rs |  4 ++--
 src/providers/gitlab.rs             | 12 +++++++++++-
 7 files changed, 27 insertions(+), 8 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index e8909ef..3a00ad9 100644
--- a/Cargo.lock
+++ a/Cargo.lock
@@ -556,6 +556,7 @@
 "shlex",
 "thrussh",
 "thrussh-keys",
 "time",
 "tokio",
 "tokio-util",
 "toml",
@@ -1522,6 +1523,7 @@
dependencies = [
 "libc",
 "num_threads",
 "serde",
]

[[package]]
diff --git a/Cargo.toml b/Cargo.toml
index 48b08ca..75999a5 100644
--- a/Cargo.toml
+++ a/Cargo.toml
@@ -31,6 +31,7 @@
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
+++ a/src/config.rs
@@ -1,8 +1,9 @@
#![allow(clippy::module_name_repetitions)]

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 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<T: DeserializeOwned>(path: &str) -> Result<T, std::io::Error> {
diff --git a/src/main.rs b/src/main.rs
index 18c2eca..70b99d6 100644
--- a/src/main.rs
+++ a/src/main.rs
@@ -84,7 +84,7 @@
            .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 @@
    dyn Future<Output = Result<T, <Handler<U> as thrussh::server::Handler>::Error>> + Send;

#[allow(clippy::type_complexity)]
impl<'a, U: UserProvider + PackageProvider + Send + Sync + 'static> thrussh::server::Handler
impl<U: UserProvider + PackageProvider + Send + Sync + 'static> thrussh::server::Handler
    for Handler<U>
{
    type Error = anyhow::Error;
diff --git a/src/util.rs b/src/util.rs
index aeec7ef..847094f 100644
--- a/src/util.rs
+++ a/src/util.rs
@@ -9,7 +9,7 @@

#[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

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
+++ a/src/git_command_handlers/ls_refs.rs
@@ -19,10 +19,10 @@
    _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/providers/gitlab.rs b/src/providers/gitlab.rs
index 790315a..d7c1f23 100644
--- a/src/providers/gitlab.rs
+++ a/src/providers/gitlab.rs
@@ -8,12 +8,14 @@
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 @@
                .default_headers(headers)
                .build()?,
            base_url: config.uri.join("api/v4/")?,
            token_expiry: config.token_expiry,
        })
    }
}
@@ -41,9 +44,8 @@
        username_password: &str,
    ) -> anyhow::Result<Option<User>> {
        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 @@
                )
                .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 @@
#[derive(Serialize)]
pub struct GitlabImpersonationTokenRequest {
    name: &'static str,
    expires_at: String,
    scopes: Vec<&'static str>,
}