From 9d13bcdc33647e9c6274fc6ae603d4ed185ef860 Mon Sep 17 00:00:00 2001 From: Tobias Bieniek Date: Sat, 25 Dec 2021 14:11:55 +0100 Subject: [PATCH 1/4] git: Extract `write_temporary_ssh_key()` function --- src/git.rs | 20 ++++++++++++++++++++ src/worker/git.rs | 23 +++-------------------- 2 files changed, 23 insertions(+), 20 deletions(-) diff --git a/src/git.rs b/src/git.rs index 8eada5c9b11..12b14088aa8 100644 --- a/src/git.rs +++ b/src/git.rs @@ -1,4 +1,5 @@ use std::collections::HashMap; +use std::io::Write; use std::path::{Path, PathBuf}; use swirl::PerformError; @@ -48,6 +49,25 @@ impl Credentials { } } } + + pub fn write_temporary_ssh_key(&self) -> Result { + let key = match self { + Credentials::Ssh { key } => key, + _ => return Err("SSH key not available".into()), + }; + + // When running on production, ensure the file is created in tmpfs and not persisted to disk + #[cfg(target_os = "linux")] + let mut temp_key_file = tempfile::Builder::new().tempfile_in("/dev/shm")?; + + // For other platforms, default to std::env::tempdir() + #[cfg(not(target_os = "linux"))] + let mut temp_key_file = tempfile::Builder::new().tempfile()?; + + temp_key_file.write_all(key.as_bytes())?; + + Ok(temp_key_file.into_temp_path()) + } } #[derive(Serialize, Deserialize, Debug)] diff --git a/src/worker/git.rs b/src/worker/git.rs index f4ac6253932..b2d1cdd8928 100644 --- a/src/worker/git.rs +++ b/src/worker/git.rs @@ -1,11 +1,10 @@ use crate::background_jobs::Environment; -use crate::git::{Crate, Credentials}; +use crate::git::Crate; use crate::schema; use anyhow::Context; use chrono::Utc; use diesel::prelude::*; use std::fs::{self, OpenOptions}; -use std::io::prelude::*; use swirl::PerformError; #[swirl::background_job] @@ -99,23 +98,7 @@ pub fn squash_index(env: &Environment) -> Result<(), PerformError> { // Shell out to git because libgit2 does not currently support push leases - let key = match &repo.credentials { - Credentials::Ssh { key } => key, - Credentials::Http { .. } => { - return Err(String::from("squash_index: Password auth not supported").into()) - } - _ => return Err(String::from("squash_index: Could not determine credentials").into()), - }; - - // When running on production, ensure the file is created in tmpfs and not persisted to disk - #[cfg(target_os = "linux")] - let mut temp_key_file = tempfile::Builder::new().tempfile_in("/dev/shm")?; - - // For other platforms, default to std::env::tempdir() - #[cfg(not(target_os = "linux"))] - let mut temp_key_file = tempfile::Builder::new().tempfile()?; - - temp_key_file.write_all(key.as_bytes())?; + let temp_key_path = repo.credentials.write_temporary_ssh_key()?; let checkout_path = repo.checkout_path.path(); let output = std::process::Command::new("git") @@ -124,7 +107,7 @@ pub fn squash_index(env: &Environment) -> Result<(), PerformError> { "GIT_SSH_COMMAND", format!( "ssh -o StrictHostKeyChecking=accept-new -i {}", - temp_key_file.path().display() + temp_key_path.display() ), ) .args(&[ From cd68ccccd52caf5967a52d25a528faa48fdf7a10 Mon Sep 17 00:00:00 2001 From: Tobias Bieniek Date: Sun, 26 Dec 2021 10:57:23 +0100 Subject: [PATCH 2/4] git: Add doc comment to `write_temporary_ssh_key()` --- src/git.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/git.rs b/src/git.rs index 12b14088aa8..653e13d5053 100644 --- a/src/git.rs +++ b/src/git.rs @@ -50,6 +50,20 @@ impl Credentials { } } + /// Write the SSH key to a temporary file and return the path. The file is + /// deleted once the returned path is dropped. + /// + /// This function can be used when running `git push` instead of using the + /// `git2` crate for pushing commits to remote git servers. + /// + /// Note: On Linux this function creates the temporary file in `/dev/shm` to + /// avoid writing it to disk. + /// + /// # Errors + /// + /// - If non-SSH credentials are use, `Err` is returned. + /// - If creation of the temporary file fails, `Err` is returned. + /// pub fn write_temporary_ssh_key(&self) -> Result { let key = match self { Credentials::Ssh { key } => key, From 63af6d1ae5157fbfd628c803c4ebf36fb61fc819 Mon Sep 17 00:00:00 2001 From: Tobias Bieniek Date: Sat, 25 Dec 2021 14:15:24 +0100 Subject: [PATCH 3/4] git: Use `cfg!()` to simplify `tempfile` code --- src/git.rs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/git.rs b/src/git.rs index 653e13d5053..ed942d2afaf 100644 --- a/src/git.rs +++ b/src/git.rs @@ -70,14 +70,15 @@ impl Credentials { _ => return Err("SSH key not available".into()), }; - // When running on production, ensure the file is created in tmpfs and not persisted to disk - #[cfg(target_os = "linux")] - let mut temp_key_file = tempfile::Builder::new().tempfile_in("/dev/shm")?; - - // For other platforms, default to std::env::tempdir() - #[cfg(not(target_os = "linux"))] - let mut temp_key_file = tempfile::Builder::new().tempfile()?; + let dir = if cfg!(target_os = "linux") { + // When running on production, ensure the file is created in tmpfs and not persisted to disk + "/dev/shm".into() + } else { + // For other platforms, default to std::env::tempdir() + std::env::temp_dir() + }; + let mut temp_key_file = tempfile::Builder::new().tempfile_in(dir)?; temp_key_file.write_all(key.as_bytes())?; Ok(temp_key_file.into_temp_path()) From abdaa2082a0543961b4488088cbe96bc2c70ff06 Mon Sep 17 00:00:00 2001 From: Tobias Bieniek Date: Sun, 26 Dec 2021 11:07:22 +0100 Subject: [PATCH 4/4] git: Use `anyhow` errors in `write_temporary_ssh_key()` --- src/git.rs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/git.rs b/src/git.rs index ed942d2afaf..8b96d12c1f7 100644 --- a/src/git.rs +++ b/src/git.rs @@ -1,3 +1,4 @@ +use anyhow::{anyhow, Context}; use std::collections::HashMap; use std::io::Write; use std::path::{Path, PathBuf}; @@ -64,10 +65,10 @@ impl Credentials { /// - If non-SSH credentials are use, `Err` is returned. /// - If creation of the temporary file fails, `Err` is returned. /// - pub fn write_temporary_ssh_key(&self) -> Result { + pub fn write_temporary_ssh_key(&self) -> anyhow::Result { let key = match self { Credentials::Ssh { key } => key, - _ => return Err("SSH key not available".into()), + _ => return Err(anyhow!("SSH key not available")), }; let dir = if cfg!(target_os = "linux") { @@ -78,8 +79,13 @@ impl Credentials { std::env::temp_dir() }; - let mut temp_key_file = tempfile::Builder::new().tempfile_in(dir)?; - temp_key_file.write_all(key.as_bytes())?; + let mut temp_key_file = tempfile::Builder::new() + .tempfile_in(dir) + .context("Failed to create temporary file")?; + + temp_key_file + .write_all(key.as_bytes()) + .context("Failed to write SSH key to temporary file")?; Ok(temp_key_file.into_temp_path()) }