/ tests / e2e / test_git_signing.py
test_git_signing.py
  1  """E2E tests for git commit signing and verification."""
  2  
  3  import shutil
  4  from pathlib import Path
  5  
  6  import pytest
  7  
  8  from helpers.cli import run_auths, run_git
  9  from helpers.git import configure_signing, make_commit
 10  
 11  
 12  def _generate_allowed_signers(auths_bin, git_repo: Path, env: dict) -> Path:
 13      """Generate allowed-signers file inside the git repo's .auths/ dir."""
 14      auths_dir = git_repo / ".auths"
 15      auths_dir.mkdir(exist_ok=True)
 16      signers_file = auths_dir / "allowed_signers"
 17      run_auths(
 18          auths_bin,
 19          [
 20              "git",
 21              "allowed-signers",
 22              "--repo",
 23              env["AUTHS_HOME"],
 24              "--output",
 25              str(signers_file),
 26          ],
 27          env=env,
 28      ).assert_success()
 29      return signers_file
 30  
 31  
 32  @pytest.mark.requires_binary
 33  class TestGitSigning:
 34      @pytest.fixture(autouse=True)
 35      def _check_ssh_keygen(self):
 36          if not shutil.which("ssh-keygen"):
 37              pytest.skip("ssh-keygen not found")
 38  
 39      def test_sign_commit_roundtrip(
 40          self, auths_bin, auths_sign_bin, init_identity, git_repo
 41      ):
 42          configure_signing(git_repo, auths_sign_bin, init_identity)
 43          sha = make_commit(git_repo, "signed commit", init_identity)
 44          assert len(sha) == 40
 45  
 46          _generate_allowed_signers(auths_bin, git_repo, init_identity)
 47  
 48          result = run_auths(
 49              auths_bin, ["verify", sha], cwd=git_repo, env=init_identity
 50          )
 51          if result.returncode != 0:
 52              pytest.skip(f"verify not available: {result.stderr}")
 53          result.assert_success()
 54  
 55      def test_verify_unsigned_commit(self, auths_bin, init_identity, git_repo):
 56          sha = make_commit(git_repo, "unsigned commit", init_identity)
 57  
 58          _generate_allowed_signers(auths_bin, git_repo, init_identity)
 59  
 60          result = run_auths(
 61              auths_bin, ["verify", sha], cwd=git_repo, env=init_identity
 62          )
 63          # Unsigned commit should report as unverified
 64          if result.returncode == 0:
 65              pass
 66          else:
 67              result.assert_failure()
 68  
 69      def test_sign_and_verify_multiple_commits(
 70          self, auths_bin, auths_sign_bin, init_identity, git_repo
 71      ):
 72          configure_signing(git_repo, auths_sign_bin, init_identity)
 73  
 74          shas = []
 75          for i in range(3):
 76              sha = make_commit(git_repo, f"commit {i}", init_identity)
 77              shas.append(sha)
 78  
 79          _generate_allowed_signers(auths_bin, git_repo, init_identity)
 80  
 81          for sha in shas:
 82              result = run_auths(
 83                  auths_bin, ["verify", sha], cwd=git_repo, env=init_identity
 84              )
 85              if result.returncode != 0:
 86                  pytest.skip(f"verify not available: {result.stderr}")
 87  
 88      def test_auths_sign_binary_direct(
 89          self, auths_sign_bin, init_identity, tmp_path
 90      ):
 91          data_file = tmp_path / "message.txt"
 92          data_file.write_text("test message")
 93  
 94          result = run_auths(
 95              auths_sign_bin,
 96              ["-Y", "sign", "-n", "git", "-f", "auths:main", str(data_file)],
 97              env=init_identity,
 98          )
 99          if result.returncode != 0:
100              pytest.skip(f"auths-sign direct not available: {result.stderr}")
101  
102          # Should produce SSHSIG output
103          assert "SIGNATURE" in result.stdout or result.returncode == 0
104  
105      def test_allowed_signers_generation(
106          self, auths_bin, init_identity, git_repo, tmp_path
107      ):
108          signers_file = tmp_path / "signers.txt"
109          result = run_auths(
110              auths_bin,
111              [
112                  "git",
113                  "allowed-signers",
114                  "--repo",
115                  init_identity["AUTHS_HOME"],
116                  "--output",
117                  str(signers_file),
118              ],
119              env=init_identity,
120          )
121          if result.returncode != 0:
122              pytest.skip(f"allowed-signers not available: {result.stderr}")
123  
124          assert signers_file.exists()
125          content = signers_file.read_text()
126          assert len(content.strip()) > 0