Fix pass Git config and lazy OTP commits

This commit is contained in:
Hermes Agent
2026-08-10 09:42:53 +00:00
parent 6ea184cbc1
commit c86ea9eb0e
8 changed files with 231 additions and 22 deletions

View File

@@ -2,12 +2,13 @@
mod support;
use std::collections::BTreeMap;
use std::{collections::BTreeMap, fs, io::Write as _};
use data_encoding::BASE32_NOPAD;
use ironstorage::{
command::{OtpAppendRequest, OtpInputSource, OtpInsertRequest},
crypto::{KeyInfo, KeyStore, SecretProvider, SecretProviderError},
git::{GitIdentity, GitRepository},
otp::{OtpAlgorithm, OtpError, OtpInput, OtpKind, OtpService, OtpUri},
recipient::RecipientPolicyManager,
repository::{EntryPath, Repository, SecretBytes},
@@ -454,6 +455,84 @@ fn malformed_ambiguous_declined_and_commit_failures_never_mutate() -> TestResult
Ok(())
}
#[test]
fn automatic_code_supports_pass_diff_config_and_opens_git_only_for_hotp() -> TestResult {
let fixture = FixtureSet::load()?;
let store = fixture.materialize_store("basic")?;
let repository = Repository::open(store.path())?;
let identity = GitIdentity::ironstorage();
let git = GitRepository::init(&repository, identity.clone())?;
let initial_commits = git.log(None)?.len();
drop(git);
let config_path = store.path().join(".git/config");
let mut config = fs::OpenOptions::new().append(true).open(&config_path)?;
config.write_all(&fixture.read("pass-git-config.ini")?)?;
drop(config);
let original_config = fs::read(&config_path)?;
let keys = KeyStore::load(fixture.path("keys"))?;
let service = OtpService::new(&repository, &keys);
let mut provider = FixtureSecrets::all(&fixture);
let totp_path = EntryPath::parse("otp/totp")?;
let totp_before = repository.read_entry(&totp_path)?;
let totp = service.code_automatic("otp/totp", 59, None, &mut provider)?;
assert_eq!(totp.counter(), None);
assert_eq!(repository.read_entry(&totp_path)?, totp_before);
let git = GitRepository::open(&repository, identity.clone())?;
assert_eq!(git.log(None)?.len(), initial_commits);
drop(git);
let hotp = service.code_automatic("otp/hotp", 0, None, &mut provider)?;
assert_eq!(hotp.counter(), Some(1));
assert_eq!(service.uri("otp/hotp", &mut provider)?.counter(), Some(1));
let git = GitRepository::open(&repository, identity)?;
assert_eq!(git.log(None)?.len(), initial_commits + 1);
assert_eq!(
git.log(Some(1))?[0].message(),
"Increment HOTP counter for otp/hotp."
);
assert_eq!(fs::read(config_path)?, original_config);
Ok(())
}
#[test]
fn read_only_totp_ignores_git_that_mutations_correctly_reject() -> TestResult {
let fixture = FixtureSet::load()?;
let store = fixture.materialize_store("basic")?;
let repository = Repository::open(store.path())?;
GitRepository::init(&repository, GitIdentity::ironstorage())?;
let config_path = store.path().join(".git/config");
let mut config = fs::OpenOptions::new().append(true).open(&config_path)?;
config.write_all(b"[filter \"unsafe\"]\n\tclean = external-helper\n")?;
drop(config);
let keys = KeyStore::load(fixture.path("keys"))?;
let service = OtpService::new(&repository, &keys);
let mut provider = FixtureSecrets::all(&fixture);
let totp_path = EntryPath::parse("otp/totp")?;
let totp_before = repository.read_entry(&totp_path)?;
assert!(
service
.code_automatic("otp/totp", 59, None, &mut provider)
.is_ok()
);
assert_eq!(repository.read_entry(&totp_path)?, totp_before);
let hotp_path = EntryPath::parse("otp/hotp")?;
let hotp_before = repository.read_entry(&hotp_path)?;
let head_before = fs::read(store.path().join(".git/refs/heads/main"))?;
assert!(matches!(
service.code_automatic("otp/hotp", 0, None, &mut provider),
Err(OtpError::Git(_))
));
assert_eq!(repository.read_entry(&hotp_path)?, hotp_before);
assert_eq!(
fs::read(store.path().join(".git/refs/heads/main"))?,
head_before
);
Ok(())
}
fn token(secret: &[u8], algorithm: &str) -> Result<OtpUri, OtpError> {
OtpUri::parse_str(&format!(
"otpauth://totp/RFC6238?secret={}&algorithm={algorithm}&digits=8&period=30",