fluidattacks-core-git 0.60.0

Fluid Attacks Core Git
Documentation
use anyhow::Result;
use std::path::Path;
use tokio::process::Command;

use super::{build_clone_args, reason, redirect_config, CloneOpts};
use crate::aws;
use crate::types::CredentialKind;

pub async fn clone_codecommit(opts: &CloneOpts, dest: &Path) -> Result<()> {
    let (arn, external_id, via) = match &opts.credentials.as_ref().map(|c| &c.kind) {
        Some(CredentialKind::AwsRole {
            arn,
            external_id,
            via,
        }) => (arn.as_str(), external_id.as_str(), via.as_deref()),
        _ => anyhow::bail!("expected AwsRole credentials for CodeCommit clone"),
    };

    let creds = aws::assume_role(arn, external_id, &opts.repo_url, via).await?;

    reason::run(
        Command::new("git")
            .args(clone_args(opts, dest))
            .env("AWS_ACCESS_KEY_ID", &creds.access_key)
            .env("AWS_SECRET_ACCESS_KEY", &creds.secret_key)
            .env("AWS_SESSION_TOKEN", &creds.session_token)
            .env("AWS_DEFAULT_REGION", &creds.region),
        &[],
    )
    .await?;

    Ok(())
}

fn clone_args(opts: &CloneOpts, dest: &Path) -> Vec<std::ffi::OsString> {
    build_clone_args(
        opts,
        &opts.repo_url,
        dest,
        &redirect_config(opts.follow_redirects),
    )
}

#[cfg(test)]
mod tests {
    use std::path::Path;

    use super::clone_args;
    use crate::clone::tests::opts;
    use crate::clone::{CloneOpts, CloneShape};

    #[test]
    fn a_redirect_is_followed_only_when_the_root_asks_for_one() {
        for follow_redirects in [false, true] {
            let opts = CloneOpts {
                follow_redirects,
                ..opts(CloneShape::SingleBranch)
            };

            let args = clone_args(&opts, Path::new("/tmp/a_root"));

            let config = format!("http.followRedirects={follow_redirects}");
            assert!(args.windows(2).any(|pair| pair == ["-c", config.as_str()]));
        }
    }
}