Implement SSH identity authentication

This commit is contained in:
2026-08-25 19:52:47 +02:00
parent f636f3b551
commit 5dbda4bbd2
14 changed files with 1964 additions and 60 deletions

View File

@@ -11,9 +11,9 @@ use std::{
};
use ironstorage::{
config::{ConfigLoader, GitRemote},
config::{ConfigLoader, GitRemote, SshFingerprint},
crypto::{CryptoError, KeyInfo, KeyStore, SecretProvider as _, SecretProviderError},
git::{GitCredentialProvider as _, GitError},
git::{GitCredentialProvider as _, GitError, SshPassphraseProvider as _},
repository::{EncryptedEntry, SecretBytes},
secret_store::{
OpenPgpPassphrasePrompt, OpenPgpPassphrasePromptError, SecretCachePolicy, SecretLocator,
@@ -274,6 +274,41 @@ fn denied_cancelled_unavailable_and_corrupted_are_typed_and_redacted() -> TestRe
Ok(())
}
#[test]
fn ssh_passphrases_are_retrieved_by_fingerprint_with_typed_access_failures() -> TestResult {
let backend = MemoryBackend::default();
let store = store(backend.clone());
store.unlock()?;
let fingerprint = SshFingerprint::parse("SHA256:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA")?;
let reference = SecretReference::ssh_key_passphrase(fingerprint.clone());
store.create(
&reference,
SecretBytes::new(b"protected-passphrase".to_vec()),
)?;
assert_eq!(
store.ssh_key_passphrase(&fingerprint)?.expose(),
b"protected-passphrase"
);
backend.fail_next(SecretStoreError::Denied);
assert!(matches!(
store.ssh_key_passphrase(&fingerprint),
Err(GitError::SshKeyPassphraseDenied { fingerprint: denied }) if denied == fingerprint
));
backend.fail_next(SecretStoreError::Cancelled);
assert!(matches!(
store.ssh_key_passphrase(&fingerprint),
Err(GitError::SshKeyPassphraseCancelled { fingerprint: cancelled })
if cancelled == fingerprint
));
let missing = SshFingerprint::parse("SHA256:AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQE")?;
assert!(matches!(
store.ssh_key_passphrase(&missing),
Err(GitError::SshKeyPassphraseUnavailable { fingerprint }) if fingerprint == missing
));
assert!(!format!("{reference:?}").contains("protected-passphrase"));
Ok(())
}
#[test]
fn bounded_cache_is_cleared_by_lock_and_never_aliases_git_accounts() -> TestResult {
let backend = MemoryBackend::default();