feat: add private repository support with SSH key and HTTPS token auth
Some checks failed
CI / Clippy (push) Failing after 2m39s
CI / Security Audit (push) Has been skipped
CI / Tests (push) Has been skipped
CI / Format (pull_request) Failing after 3s
CI / Clippy (pull_request) Failing after 2m33s
CI / Security Audit (pull_request) Has been skipped
CI / Tests (pull_request) Has been skipped
CI / Detect Changes (push) Has been skipped
CI / Detect Changes (pull_request) Has been skipped
CI / Deploy Agent (push) Has been skipped
CI / Deploy Dashboard (push) Has been skipped
CI / Deploy Docs (push) Has been skipped
CI / Format (push) Failing after 4s
CI / Deploy MCP (pull_request) Has been skipped
CI / Deploy MCP (push) Has been skipped
CI / Deploy Agent (pull_request) Has been skipped
CI / Deploy Dashboard (pull_request) Has been skipped
CI / Deploy Docs (pull_request) Has been skipped
Some checks failed
CI / Clippy (push) Failing after 2m39s
CI / Security Audit (push) Has been skipped
CI / Tests (push) Has been skipped
CI / Format (pull_request) Failing after 3s
CI / Clippy (pull_request) Failing after 2m33s
CI / Security Audit (pull_request) Has been skipped
CI / Tests (pull_request) Has been skipped
CI / Detect Changes (push) Has been skipped
CI / Detect Changes (pull_request) Has been skipped
CI / Deploy Agent (push) Has been skipped
CI / Deploy Dashboard (push) Has been skipped
CI / Deploy Docs (push) Has been skipped
CI / Format (push) Failing after 4s
CI / Deploy MCP (pull_request) Has been skipped
CI / Deploy MCP (push) Has been skipped
CI / Deploy Agent (pull_request) Has been skipped
CI / Deploy Dashboard (pull_request) Has been skipped
CI / Deploy Docs (pull_request) Has been skipped
- Generate SSH ed25519 key pair on agent startup for cloning private repos via SSH - Add GET /api/v1/settings/ssh-public-key endpoint to expose deploy key - Add auth_token and auth_username fields to TrackedRepository model - Wire git2 credential callbacks for both SSH and HTTPS authentication - Validate repository access before saving (test-connect on add) - Update dashboard add form with optional auth section showing deploy key and token fields - Show error toast if private repo cannot be accessed Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
57
compliance-agent/src/ssh.rs
Normal file
57
compliance-agent/src/ssh.rs
Normal file
@@ -0,0 +1,57 @@
|
||||
use std::path::Path;
|
||||
|
||||
use crate::error::AgentError;
|
||||
|
||||
/// Ensure the SSH key pair exists at the given path, generating it if missing.
|
||||
/// Returns the public key contents.
|
||||
pub fn ensure_ssh_key(key_path: &str) -> Result<String, AgentError> {
|
||||
let private_path = Path::new(key_path);
|
||||
let public_path = private_path.with_extension("pub");
|
||||
|
||||
if private_path.exists() && public_path.exists() {
|
||||
return std::fs::read_to_string(&public_path).map_err(|e| {
|
||||
AgentError::Config(format!("Failed to read SSH public key: {e}"))
|
||||
});
|
||||
}
|
||||
|
||||
// Create parent directory
|
||||
if let Some(parent) = private_path.parent() {
|
||||
std::fs::create_dir_all(parent)?;
|
||||
}
|
||||
|
||||
// Generate ed25519 key pair using ssh-keygen
|
||||
let output = std::process::Command::new("ssh-keygen")
|
||||
.args([
|
||||
"-t",
|
||||
"ed25519",
|
||||
"-f",
|
||||
key_path,
|
||||
"-N",
|
||||
"", // no passphrase
|
||||
"-C",
|
||||
"compliance-scanner-agent",
|
||||
])
|
||||
.output()
|
||||
.map_err(|e| AgentError::Config(format!("Failed to run ssh-keygen: {e}")))?;
|
||||
|
||||
if !output.status.success() {
|
||||
let stderr = String::from_utf8_lossy(&output.stderr);
|
||||
return Err(AgentError::Config(format!(
|
||||
"ssh-keygen failed: {stderr}"
|
||||
)));
|
||||
}
|
||||
|
||||
// Set correct permissions
|
||||
#[cfg(unix)]
|
||||
{
|
||||
use std::os::unix::fs::PermissionsExt;
|
||||
std::fs::set_permissions(private_path, std::fs::Permissions::from_mode(0o600))?;
|
||||
}
|
||||
|
||||
let public_key = std::fs::read_to_string(&public_path).map_err(|e| {
|
||||
AgentError::Config(format!("Failed to read generated SSH public key: {e}"))
|
||||
})?;
|
||||
|
||||
tracing::info!("Generated new SSH key pair at {key_path}");
|
||||
Ok(public_key)
|
||||
}
|
||||
Reference in New Issue
Block a user