verify-commit Git Command Guide
The git verify-commit command validates GPG signatures on commits to ensure they were created by the claimed author and haven’t been tampered with. It’s crucial for maintaining the integrity and authenticity of commit history in security-conscious environments.
git verify-commit Syntax:
Section titled “git verify-commit Syntax:”git verify-commit [--raw] [-v | --verbose] [-q | --quiet] [--keyid-format=<format>] [--gpg-program=<gpg-program>] [--gpg-default-key=<key>] [--gpg-home-dir=<dir>] [--gpg-ssh-allowed-signers=<file>] [--gpg-ssh-default-key=<key>] [--gpg-ssh-program=<program>] <commit>...Verification Options:
Section titled “Verification Options:”| Option | Description |
|---|---|
--raw | Print raw GPG status output |
-v, --verbose | Verbose output |
-q, --quiet | Suppress output |
--keyid-format=<format> | Key ID display format (short, long, etc.) |
GPG Configuration Options:
Section titled “GPG Configuration Options:”| Option | Description |
|---|---|
--gpg-program=<program> | Use custom GPG program |
--gpg-default-key=<key> | Default GPG key |
--gpg-home-dir=<dir> | GPG home directory |
--gpg-ssh-allowed-signers=<file> | SSH allowed signers file |
--gpg-ssh-default-key=<key> | Default SSH key |
--gpg-ssh-program=<program> | SSH signing program |
Parameters:
Section titled “Parameters:”| Parameter | Description |
|---|---|
<commit> | Commit(s) to verify (SHA-1, branch, etc.) |
Understanding Commit Verification:
Section titled “Understanding Commit Verification:”GPG Signature Process:
Section titled “GPG Signature Process:”Commit Signing and Verification:├── Commit Creation: Author creates commit with content├── GPG Signing: Commit SHA-1 signed with private key├── Signature Storage: Signature embedded in commit object├── Verification: Public key used to verify signature├── Trust Validation: Key trustworthiness confirmed└── Integrity Check: Commit content matches signed hashSignature Components:
Section titled “Signature Components:”GPG Commit Signature Structure:├── Commit Data: Tree, parent, author, committer, message├── Content Hash: SHA-1 of commit data├── Digital Signature: Hash signed with private key├── Public Key: Used for verification├── Key Trust: Web of trust or keyserver validation├── Timestamp: When signature was created└── Validity Period: Key expiration and revocation statusVerification States:
Section titled “Verification States:”Signature Verification Results:├── GOOD: Valid signature from trusted key├── BAD: Invalid signature or tampered content├── EXPIRED: Key or signature has expired├── REVOKED: Signing key has been revoked├── UNKNOWN: Key not in keyring or untrusted└── NO_PUBKEY: Public key not availableBasic Verify-Commit Operations:
Section titled “Basic Verify-Commit Operations:”Verify Single Commit:
Section titled “Verify Single Commit:”# Verify specific commitgit verify-commit abc123def456
# Verify current HEADgit verify-commit HEAD
# Verify multiple commitsgit verify-commit HEAD~3 HEAD~2 HEAD~1Verify Branch Commits:
Section titled “Verify Branch Commits:”# Verify all commits in branchgit verify-commit main
# Verify commits in rangegit verify-commit main..feature-branch
# Verify recent commitsgit log --oneline -10 | cut -d' ' -f1 | xargs git verify-commitDetailed Verification Output:
Section titled “Detailed Verification Output:”# Verbose verification with detailsgit verify-commit -v HEAD
# Raw GPG output for debugginggit verify-commit --raw HEAD
# Quiet verification (exit code only)git verify-commit -q HEADAdvanced Verify-Commit Scenarios:
Section titled “Advanced Verify-Commit Scenarios:”Batch Verification:
Section titled “Batch Verification:”# Verify all commits with status reportingverify_all_commits() { echo "Verifying all commits in repository..."
git tag | while read -r tag; do if git verify-commit -q "$tag" 2>/dev/null; then echo "✓ $tag" else echo "✗ $tag" fi done}
# Verify commits by authorverify_author_commits() { local author="$1"
echo "Verifying commits by $author..."
git log --author="$author" --pretty=format:%H | while read -r commit; do if git verify-commit -q "$commit" 2>/dev/null; then echo "✓ $commit" else echo "✗ $commit" fi done}
# Usageverify_author_commits "John Doe"Signature Analysis:
Section titled “Signature Analysis:”# Analyze signature detailsanalyze_signatures() { echo "Analyzing commit signatures..."
git log --show-signature --pretty=format:"%H %G? %GS %GK" | while read -r commit status signer key; do echo "Commit: $commit" echo "Status: $status" echo "Signer: $signer" echo "Key: $key"
case "$status" in G) echo "✓ Good signature" ;; B) echo "✗ Bad signature" ;; X) echo "⚠ Expired signature" ;; Y) echo "⚠ Expired key" ;; R) echo "✗ Revoked key" ;; N) echo "⚠ No signature" ;; *) echo "? Unknown status: $status" ;; esac echo done}
# Check signature freshnesscheck_signature_freshness() { echo "Checking signature freshness..."
git log --show-signature --pretty=format:"%H %ct %G?" | while read -r commit timestamp status; do current_time=$(date +%s) signature_age=$((current_time - timestamp)) days_old=$((signature_age / 86400))
if [ "$status" = "G" ] && [ "$days_old" -gt 365 ]; then echo "⚠ Old signature: $commit ($days_old days)" fi done}Key Management Integration:
Section titled “Key Management Integration:”# Verify commits with specific keyverify_with_key() { local key_id="$1"
echo "Verifying commits signed with key: $key_id"
git log --show-signature --pretty=format:"%H %G? %GK" | while read -r commit status key; do if [ "$key" = "$key_id" ]; then echo "Commit: $commit" echo "Status: $status" echo "Key: $key" echo fi done}
# Check key validitycheck_key_validity() { local key_id="$1"
echo "Checking validity of key: $key_id"
# Check if key exists if gpg --list-keys "$key_id" >/dev/null 2>&1; then echo "✓ Key exists in keyring"
# Check expiration if gpg --list-keys --with-colons "$key_id" | grep -q "^pub:e:"; then echo "✗ Key has expired" else echo "✓ Key is valid" fi else echo "✗ Key not found in keyring" fi}
# Usageverify_with_key "ABC123DEF456"check_key_validity "ABC123DEF456"Configuration and Best Practices:
Section titled “Configuration and Best Practices:”Git Configuration for Verification:
Section titled “Git Configuration for Verification:”# Configure GPG for commit signinggit config --global user.signingkey "ABC123DEF456"git config --global commit.gpgsign truegit config --global tag.gpgsign true
# Configure GPG programgit config --global gpg.program "gpg"git config --global gpg.ssh.program "ssh-keygen"
# Configure key display formatgit config --global verify.keyidformat "long"
# Configure SSH signinggit config --global gpg.ssh.allowedSignersFile "~/.ssh/allowed_signers"git config --global gpg.ssh.defaultKeyCommand "ssh-add -L"GPG Key Setup for Commits:
Section titled “GPG Key Setup for Commits:”# Generate GPG key for commit signinggenerate_gpg_key() { echo "Generating GPG key for commit signing..."
# Generate key (interactive) gpg --full-generate-key
# List keys gpg --list-secret-keys --keyid-format LONG
# Export public key echo "Export your public key:" echo "gpg --armor --export YOUR_KEY_ID" echo "Share with team members for commit verification"}
# Setup SSH signing for commitssetup_ssh_signing() { echo "Setting up SSH signing for commits..."
# Generate SSH key for signing ssh-keygen -t ed25519 -C "git-commit-signing" -f ~/.ssh/commit_signing_key
# Configure allowed signers echo "$(git config user.email) $(cat ~/.ssh/commit_signing_key.pub)" >> ~/.ssh/allowed_signers
# Configure Git to use SSH signing git config --global gpg.ssh.defaultKeyCommand "ssh-add -L ~/.ssh/commit_signing_key" git config --global gpg.format ssh git config --global commit.gpgsign true}
# Import team member keyssetup_team_keys() { echo "Setting up team GPG keys for commit verification..."
# Import keys from keyserver gpg --keyserver hkps://keys.openpgp.org --recv-keys KEY_ID_1 KEY_ID_2
# Import from files gpg --import team-member-1.asc team-member-2.asc
# Sign imported keys (establish trust) gpg --sign-key KEY_ID_1 gpg --sign-key KEY_ID_2
echo "Team keys imported and signed"}Safe Verification Operations:
Section titled “Safe Verification Operations:”# Safe commit verification with error handlingsafe_verify_commit() { local commit="$1"
echo "Verifying commit: $commit"
# Check if commit exists if ! git cat-file -e "$commit" 2>/dev/null; then echo "Error: Commit $commit does not exist" return 1 fi
# Attempt verification if git verify-commit -q "$commit" 2>/dev/null; then echo "✓ Commit signature is valid" return 0 else echo "✗ Commit signature verification failed" return 1 fi}
# Batch verification with progressbatch_verify_commits() { local commit_count commit_count=$(git rev-list --count HEAD) local current=0
echo "Batch verifying $commit_count commits..."
git rev-list HEAD | while read -r commit; do ((current++)) echo -n "[$current/$commit_count] Verifying $commit... "
if safe_verify_commit "$commit" >/dev/null 2>&1; then echo "✓" else echo "✗" fi done
echo "Batch verification complete"}
# Usagebatch_verify_commitsIntegration with Development Workflows:
Section titled “Integration with Development Workflows:”CI/CD Pipeline Integration:
Section titled “CI/CD Pipeline Integration:”# Verify commits in CI/CD pipelinesci_commit_verification() { echo "=== CI/CD Commit Verification ==="
# Verify all commits in PR verify_pr_commits() { echo "Verifying commits in pull request..."
# Get commits in PR (simplified - would use actual CI variables) git log --oneline "${CI_MERGE_REQUEST_TARGET_BRANCH_NAME}..${CI_COMMIT_SHA}" | while read -r line; do commit=$(echo "$line" | cut -d' ' -f1) message=$(echo "$line" | cut -d' ' -f2-)
echo "Verifying commit $commit: $message"
if git verify-commit -q "$commit" 2>/dev/null; then echo "✓ Signature valid" else echo "✗ Signature invalid - rejecting PR" exit 1 fi done
echo "All commits in PR are properly signed" }
# Setup commit signing requirement setup_commit_signing() { echo "Setting up commit signing requirements..."
# Configure Git to require signing git config --global commit.gpgsign true git config --global tag.gpgsign true
# Setup pre-commit hook cat > .git/hooks/pre-commit << 'EOF'#!/bin/bash# Require commit signing
if [ "$(git config --bool commit.gpgsign)" = "true" ]; then echo "Commit signing is required" echo "Please ensure you have GPG/SSH signing configured"else echo "Warning: Commit signing not required"fiEOF
chmod +x .git/hooks/pre-commit
echo "Commit signing requirement configured" }
# Generate signing status report generate_signing_report() { echo "Generating commit signing status report..."
cat > commit-signing-report.md << EOF# Commit Signing Status Report
Generated: $(date)Repository: $(basename "$(pwd)")Branch: $(git branch --show-current)
## Signing StatisticsEOF
total_commits=$(git rev-list --count HEAD) signed_commits=$(git log --show-signature | grep -c "gpg:") unsigned_commits=$((total_commits - signed_commits))
echo "- Total commits: $total_commits" >> commit-signing-report.md echo "- Signed commits: $signed_commits" >> commit-signing-report.md echo "- Unsigned commits: $unsigned_commits" >> commit-signing-report.md echo "- Signing rate: $((signed_commits * 100 / total_commits))%" >> commit-signing-report.md
cat >> commit-signing-report.md << EOF
## Recent Commit Signing Status$(git log --oneline -10 --show-signature | while read -r line; do if echo "$line" | grep -q "gpg:"; then echo "- ✓ $(echo "$line" | head -1)" else echo "- ✗ $(echo "$line" | head -1)" fidone)
## RecommendationsEOF
if [ "$unsigned_commits" -gt 0 ]; then echo "- Enable commit signing: \`git config commit.gpgsign true\`" >> commit-signing-report.md echo "- Setup GPG key for signing" >> commit-signing-report.md fi
echo "Commit signing report generated: commit-signing-report.md" }
# Run CI/CD verification verify_pr_commits generate_signing_report}
# Usage in CIci_commit_verificationRepository Security Auditing:
Section titled “Repository Security Auditing:”# Audit repository for signed commitsaudit_commit_signing() { echo "=== Repository Commit Signing Audit ==="
# Analyze signing coverage analyze_signing_coverage() { echo "Analyzing commit signing coverage..."
declare -A signer_stats
git log --show-signature --pretty=format:"%H %ae %G?" | while read -r commit email status; do if [ "$status" = "G" ]; then signer_stats["$email"]=$((signer_stats["$email"] + 1)) fi done
echo "Signing coverage by author:" for email in "${!signer_stats[@]}"; do echo " $email: ${signer_stats[$email]} signed commits" done }
# Find unsigned commits find_unsigned_commits() { echo "Finding unsigned commits..."
git log --pretty=format:"%H %s" | while read -r commit subject; do if ! git verify-commit -q "$commit" 2>/dev/null; then echo "Unsigned: $commit - $subject" fi done }
# Check signing key rotation check_key_rotation() { echo "Checking signing key rotation..."
git log --show-signature --pretty=format:"%H %ct %GK" | while read -r commit timestamp key; do if [ -n "$key" ]; then echo "Commit $commit signed with key $key at $(date -d "@$timestamp")" fi done | sort -k4 | uniq -c | sort -nr }
# Generate security report generate_security_report() { echo "Generating repository security report..."
cat > security-audit-report.md << EOF# Repository Security Audit Report
Generated: $(date)Repository: $(basename "$(pwd)")
## Commit Signing AnalysisEOF
total_commits=$(git rev-list --count HEAD) signed_commits=$(git log --show-signature | grep -c "Good signature") unsigned_commits=$((total_commits - signed_commits))
echo "### Overall Statistics" >> security-audit-report.md echo "- Total commits: $total_commits" >> security-audit-report.md echo "- Signed commits: $signed_commits" >> security-audit-report.md echo "- Unsigned commits: $unsigned_commits" >> security-audit-report.md echo "- Signing compliance: $((signed_commits * 100 / total_commits))%" >> security-audit-report.md
echo >> security-audit-report.md echo "### Recent Unsigned Commits" >> security-audit-report.md git log --oneline -20 | while read -r line; do commit=$(echo "$line" | cut -d' ' -f1) if ! git verify-commit -q "$commit" 2>/dev/null; then echo "- $line" >> security-audit-report.md fi done
echo >> security-audit-report.md echo "### Security Recommendations" >> security-audit-report.md if [ "$unsigned_commits" -gt 0 ]; then echo "- **HIGH**: $unsigned_commits commits are unsigned" >> security-audit-report.md echo "- Enable mandatory commit signing" >> security-audit-report.md echo "- Configure CI/CD to reject unsigned commits" >> security-audit-report.md fi
echo "Security audit report generated: security-audit-report.md" }
# Run audit analyze_signing_coverage echo find_unsigned_commits echo check_key_rotation echo generate_security_report}
# Usageaudit_commit_signingDevelopment Team Workflows:
Section titled “Development Team Workflows:”# Team commit signing workflowteam_signing_workflow() { echo "=== Team Commit Signing Workflow ==="
# Setup team signing policy setup_team_policy() { echo "Setting up team signing policy..."
cat > team-signing-policy.md << EOF# Team Commit Signing Policy
## Policy OverviewAll commits must be signed with a valid GPG or SSH key.
## Requirements- Use GPG key with at least 4096-bit RSA or Ed25519- SSH keys must be added to allowed_signers file- Keys must be rotated annually- Public keys must be shared with the team
## Verification- CI/CD pipelines will reject unsigned commits- Code reviews will check signing status- Regular audits will verify compliance
## Setup Instructions1. Generate GPG key: \`gpg --full-generate-key\`2. Configure Git: \`git config commit.gpgsign true\`3. Export public key and share with team4. Add to allowed signers if using SSHEOF
echo "Team signing policy created: team-signing-policy.md" }
# Setup developer signing setup_developer_signing() { local developer="$1"
echo "Setting up signing for developer: $developer"
# Create developer config mkdir -p "developer-configs/$developer"
cat > "developer-configs/$developer/signing-setup.sh" << EOF#!/bin/bash# Signing setup for $developer
echo "Setting up commit signing..."
# Configure Gitgit config --global user.name "$developer"git config --global user.email "$developer@company.com"git config --global commit.gpgsign true
# Generate GPG key (interactive)echo "Run: gpg --full-generate-key"echo "Then configure: git config --global user.signingkey YOUR_KEY_ID"
echo "Setup complete for $developer"EOF
chmod +x "developer-configs/$developer/signing-setup.sh"
echo "Developer signing setup created" }
# Monitor team compliance monitor_team_compliance() { echo "Monitoring team signing compliance..."
# This would integrate with team management system echo "Team members and their signing status:"
# Example team members team_members=("alice" "bob" "charlie")
for member in "${team_members[@]}"; do # Check recent commits by member recent_commits=$(git log --author="$member" --oneline -5 2>/dev/null | wc -l)
if [ "$recent_commits" -gt 0 ]; then signed_commits=$(git log --author="$member" --show-signature -5 2>/dev/null | grep -c "Good signature") compliance=$((signed_commits * 100 / recent_commits)) echo " $member: ${compliance}% compliance ($signed_commits/$recent_commits signed)" else echo " $member: No recent commits" fi done }
# Interactive team workflow echo "Team Signing Workflow Options:" echo "1. Setup team policy" echo "2. Setup developer signing" echo "3. Monitor team compliance"
read -p "Select option (1-3): " option
case "$option" in 1) setup_team_policy ;; 2) read -p "Developer name: " dev setup_developer_signing "$dev" ;; 3) monitor_team_compliance ;; esac}
# Usageteam_signing_workflowTroubleshooting Common Issues:
Section titled “Troubleshooting Common Issues:”Signature Verification Issues:
Section titled “Signature Verification Issues:”# Diagnose signature verification problemsdiagnose_signature_issues() { echo "Diagnosing signature verification issues..."
# Test basic verification if git verify-commit -q HEAD 2>/dev/null; then echo "✓ Basic signature verification works" else echo "✗ Signature verification failed"
# Check for common issues if ! command -v gpg >/dev/null 2>&1 && ! command -v ssh-keygen >/dev/null 2>&1; then echo " No GPG or SSH signing tools found" fi
# Check commit signature if ! git show --show-signature HEAD | grep -q "gpg:"; then echo " Commit is not signed" fi fi
# Check GPG keyring if command -v gpg >/dev/null 2>&1; then key_count=$(gpg --list-keys 2>/dev/null | grep -c "^pub") echo "GPG keys in keyring: $key_count"
if [ "$key_count" -eq 0 ]; then echo " No GPG keys found - import signer keys" fi fi
# Check SSH allowed signers if [ -f ~/.ssh/allowed_signers ]; then signer_count=$(wc -l < ~/.ssh/allowed_signers) echo "SSH allowed signers: $signer_count" else echo "SSH allowed signers file not found" fi}
# Fix signature issuesfix_signature_issues() { echo "Attempting to fix signature issues..."
# Import missing keys echo "Attempting to import missing keys..."
# Get failed commit failed_commit=$(git verify-commit HEAD 2>&1 | grep -o "gpg:.*key.*not.*found" | sed 's/.*key \([A-F0-9]*\).*/\1/')
if [ -n "$failed_commit" ]; then echo "Missing key: $failed_commit" echo "Attempting to fetch from keyserver..."
if gpg --keyserver hkps://keys.openpgp.org --recv-keys "$failed_commit" 2>/dev/null; then echo "✓ Key imported successfully" else echo "✗ Could not import key" fi fi
# Check SSH configuration if [ ! -f ~/.ssh/allowed_signers ]; then echo "Creating SSH allowed signers file..." touch ~/.ssh/allowed_signers fi
# Test verification again if git verify-commit -q HEAD 2>/dev/null; then echo "✓ Signature verification now works" else echo "✗ Signature verification still failing" fi}
# Usagediagnose_signature_issuesfix_signature_issuesKey Management Issues:
Section titled “Key Management Issues:”# Troubleshoot key management problemstroubleshoot_key_management() { echo "Troubleshooting key management issues..."
# Check key validity check_key_status() { local key_id="$1"
echo "Checking status of key: $key_id"
# Check if key exists if ! gpg --list-keys "$key_id" >/dev/null 2>&1; then echo "✗ Key not found in keyring" return 1 fi
# Check expiration if gpg --list-keys --with-colons "$key_id" | grep -q "^pub:e:"; then echo "✗ Key has expired" return 1 fi
# Check revocation if gpg --list-keys --with-colons "$key_id" | grep -q "^pub:r:"; then echo "✗ Key has been revoked" return 1 fi
echo "✓ Key is valid" return 0 }
# Find commits with invalid signatures find_invalid_signatures() { echo "Finding commits with invalid signatures..."
git log --oneline --all | while read -r line; do commit=$(echo "$line" | cut -d' ' -f1)
if ! git verify-commit -q "$commit" 2>/dev/null; then echo "Invalid signature: $line" fi done }
# Update keyring update_keyring() { echo "Updating GPG keyring..."
# Update from keyservers gpg --keyserver hkps://keys.openpgp.org --refresh-keys
# Update trust database gpg --check-trustdb
echo "Keyring update complete" }
# Interactive troubleshooting echo "Key Management Troubleshooting:" echo "1. Check key status" echo "2. Find invalid signatures" echo "3. Update keyring"
read -p "Select option (1-3): " option
case "$option" in 1) read -p "Key ID: " key_id check_key_status "$key_id" ;; 2) find_invalid_signatures ;; 3) update_keyring ;; esac}
# Usagetroubleshoot_key_managementConfiguration Issues:
Section titled “Configuration Issues:”# Troubleshoot configuration problemstroubleshoot_config_issues() { echo "Troubleshooting configuration issues..."
# Check Git configuration echo "Git signing configuration:" git config --list | grep -E "(gpgsign|gpg|signingkey)" | while read -r config; do echo " $config" done
# Check if signing is enabled if [ "$(git config --bool commit.gpgsign)" != "true" ]; then echo "⚠ Commit signing is not enabled" echo " Enable with: git config commit.gpgsign true" fi
# Check signing key signing_key=$(git config user.signingkey) if [ -z "$signing_key" ]; then echo "⚠ No signing key configured" echo " Configure with: git config user.signingkey YOUR_KEY_ID" else echo "✓ Signing key configured: $signing_key" fi
# Check GPG program gpg_program=$(git config gpg.program) if [ -n "$gpg_program" ]; then if ! command -v "$gpg_program" >/dev/null 2>&1; then echo "✗ Configured GPG program not found: $gpg_program" else echo "✓ GPG program available: $gpg_program" fi fi
# Check SSH signing if [ "$(git config gpg.format)" = "ssh" ]; then echo "SSH signing is configured"
allowed_signers=$(git config gpg.ssh.allowedSignersFile) if [ -n "$allowed_signers" ] && [ -f "$allowed_signers" ]; then echo "✓ SSH allowed signers file exists: $allowed_signers" else echo "✗ SSH allowed signers file missing or not configured" fi fi}
# Fix configuration issuesfix_config_issues() { echo "Attempting to fix configuration issues..."
# Enable commit signing git config commit.gpgsign true echo "✓ Enabled commit signing"
# Find and set signing key secret_keys=$(gpg --list-secret-keys --keyid-format short | grep "^sec" | head -1 | awk '{print $2}' | cut -d'/' -f2)
if [ -n "$secret_keys" ]; then git config user.signingkey "$secret_keys" echo "✓ Configured signing key: $secret_keys" else echo "⚠ No GPG secret keys found" echo " Generate with: gpg --full-generate-key" fi
# Test configuration if git verify-commit -q HEAD 2>/dev/null; then echo "✓ Configuration is working" else echo "⚠ Configuration may still need adjustment" fi}
# Usagetroubleshoot_config_issuesfix_config_issuesReal-World Usage Examples:
Section titled “Real-World Usage Examples:”Enterprise Security Compliance:
Section titled “Enterprise Security Compliance:”#!/bin/bash# Enterprise commit signing compliance system
enterprise_compliance() { echo "=== Enterprise Commit Signing Compliance ==="
# Setup compliance requirements setup_compliance_requirements() { echo "Setting up enterprise compliance requirements..."
cat > compliance-requirements.md << EOF# Enterprise Commit Signing Requirements
## Policy OverviewAll commits to production branches must be signed with approved keys.
## Requirements- GPG keys: RSA 4096-bit or Ed25519, valid for 2 years max- SSH keys: Ed25519, added to organizational allowed_signers- Key rotation: Annual mandatory rotation- Signing requirement: All commits to main/master branches
## Approved Signers- All employees with active GPG/SSH keys- CI/CD systems with organizational keys- Contractors with temporary approved keys
## Enforcement- Pre-receive hooks reject unsigned commits- CI/CD pipelines verify signatures- Regular audits check compliance- Automated reporting to security teamEOF
echo "Compliance requirements documented: compliance-requirements.md" }
# Setup organizational key management setup_org_key_management() { echo "Setting up organizational key management..."
# Create key management directory mkdir -p org-keys/{gpg,ssh,revoked}
# Setup organizational allowed signers touch org-keys/ssh/allowed_signers
# Create key approval workflow cat > org-keys/key-approval-process.md << EOF# Key Approval Process
## For New Employees1. Generate GPG/SSH key pair2. Submit public key to IT security3. IT verifies key meets requirements4. Key added to organizational allowed_signers5. Employee configures Git signing
## For Contractors1. Generate key pair with organizational oversight2. Submit public key for approval3. Temporary addition to allowed_signers4. Automatic removal after contract end
## Key Rotation1. Annual reminder sent to all users2. Generate new key pair3. Submit for approval4. Update organizational records5. Revoke old keyEOF
echo "Organizational key management setup complete" }
# Implement pre-receive hook for signing enforcement setup_pre_receive_hook() { echo "Setting up pre-receive hook for signing enforcement..."
cat > .git/hooks/pre-receive << 'EOF'#!/bin/bash# Enforce commit signing for protected branches
zero_commit="0000000000000000000000000000000000000000"
while read -r oldrev newrev refname; do # Only enforce on protected branches case "$refname" in refs/heads/main|refs/heads/master|refs/heads/release/*) echo "Verifying signatures for $refname..."
# Check all commits in push for commit in $(git rev-list "$oldrev..$newrev"); do if ! git verify-commit -q "$commit" 2>/dev/null; then echo "ERROR: Unsigned commit detected: $commit" echo "All commits to $refname must be signed." echo "Please sign your commits and try again." exit 1 fi done
echo "✓ All commits in $refname are properly signed" ;; *) echo "Signature check skipped for $refname" ;; esacdone
echo "Pre-receive hook validation complete"EOF
chmod +x .git/hooks/pre-receive
echo "Pre-receive hook configured for signing enforcement" }
# Generate compliance reports generate_compliance_reports() { echo "Generating compliance reports..."
cat > compliance-report-$(date +%Y%m%d).md << EOF# Enterprise Compliance Report
Generated: $(date)Period: Last 30 days
## Overall StatisticsEOF
# Calculate compliance metrics total_commits=$(git log --since="30 days ago" --oneline | wc -l) signed_commits=$(git log --since="30 days ago" --show-signature | grep -c "Good signature")
compliance_rate=0 if [ "$total_commits" -gt 0 ]; then compliance_rate=$((signed_commits * 100 / total_commits)) fi
echo "- Total commits: $total_commits" >> compliance-report-$(date +%Y%m%d).md echo "- Signed commits: $signed_commits" >> compliance-report-$(date +%Y%m%d).md echo "- Compliance rate: ${compliance_rate}%" >> compliance-report-$(date +%Y%m%d).md
cat >> compliance-report-$(date +%Y%m%d).md << EOF
## Branch ComplianceEOF
# Check compliance by branch for branch in main master develop; do if git show-ref --verify "refs/heads/$branch" >/dev/null 2>&1; then branch_commits=$(git log --oneline "$branch" --since="30 days ago" | wc -l) branch_signed=$(git log "$branch" --since="30 days ago" --show-signature | grep -c "Good signature")
if [ "$branch_commits" -gt 0 ]; then branch_rate=$((branch_signed * 100 / branch_commits)) echo "- $branch: ${branch_rate}% ($branch_signed/$branch_commits)" >> compliance-report-$(date +%Y%m%d).md fi fi done
cat >> compliance-report-$(date +%Y%m%d).md << EOF
## Non-Compliant CommitsEOF
# List recent unsigned commits git log --oneline --since="30 days ago" | while read -r line; do commit=$(echo "$line" | cut -d' ' -f1) if ! git verify-commit -q "$commit" 2>/dev/null; then echo "- $line" >> compliance-report-$(date +%Y%m%d).md fi done
echo "Compliance report generated: compliance-report-$(date +%Y%m%d).md" }
# Run enterprise compliance setup setup_compliance_requirements setup_org_key_management setup_pre_receive_hook generate_compliance_reports
echo "Enterprise compliance system setup complete!"}
enterprise_complianceSecurity Auditing and Forensics:
Section titled “Security Auditing and Forensics:”# Advanced security auditing with commit verificationsecurity_auditing() { echo "=== Advanced Security Auditing ==="
# Audit signing key usage audit_key_usage() { echo "Auditing signing key usage..."
declare -A key_usage
git log --show-signature --pretty=format:"%H %ae %GK" | while read -r commit email key; do if [ -n "$key" ]; then key_usage["$key"]="${key_usage[$key]:-0}" key_usage["$key"]=$((key_usage["$key"] + 1)) fi done
echo "Signing key usage statistics:" for key in "${!key_usage[@]}"; do echo " $key: ${key_usage[$key]} commits"
# Check key validity if gpg --list-keys "$key" >/dev/null 2>&1; then echo " ✓ Key exists" else echo " ✗ Key not found" fi done }
# Detect signature anomalies detect_signature_anomalies() { echo "Detecting signature anomalies..."
# Check for commits signed with expired keys git log --show-signature --pretty=format:"%H %ct %GK" | while read -r commit timestamp key; do if [ -n "$key" ]; then # Check if key was valid at commit time if gpg --list-keys --with-colons "$key" 2>/dev/null | grep -q "^pub:e:"; then key_expiry=$(gpg --list-keys --with-colons "$key" 2>/dev/null | grep "^pub:e:" | cut -d: -f7)
if [ "$timestamp" -gt "$key_expiry" ]; then echo "⚠ Commit $commit signed with expired key $key" echo " Commit date: $(date -d "@$timestamp")" echo " Key expired: $(date -d "@$key_expiry")" fi fi fi done
# Check for unusual signing patterns echo "Checking for unusual signing patterns..."
# Find commits signed by multiple different keys author_keys=$(git log --show-signature --pretty=format:"%ae %GK" | sort | uniq)
echo "Author-key combinations:" echo "$author_keys" | while read -r author key; do if [ -n "$key" ]; then echo " $author -> $key" fi done }
# Forensic commit analysis forensic_commit_analysis() { echo "Performing forensic commit analysis..."
# Analyze commit timing and signatures echo "Commit timing and signature analysis:"
git log --show-signature --pretty=format:"%H %ct %ae %G?" | while read -r commit timestamp email status; do commit_date=$(date -d "@$timestamp" "+%Y-%m-%d %H:%M:%S")
case "$status" in "G") sig_status="✓ Good" ;; "B") sig_status="✗ Bad" ;; "X") sig_status="⚠ Expired sig" ;; "Y") sig_status="⚠ Expired key" ;; "R") sig_status="✗ Revoked key" ;; "N") sig_status="⚠ No signature" ;; *) sig_status="? Unknown: $status" ;; esac
echo "$commit_date - $commit - $email - $sig_status" done }
# Generate security audit report generate_security_audit() { echo "Generating comprehensive security audit report..."
cat > security-audit-$(date +%Y%m%d).md << EOF# Comprehensive Security Audit Report
Generated: $(date)Repository: $(basename "$(pwd)")Auditor: $(whoami)
## Executive SummaryThis report contains a comprehensive security audit of commit signing practices.
## Key FindingsEOF
# Overall statistics total_commits=$(git rev-list --count HEAD) signed_commits=$(git log --show-signature | grep -c "Good signature") unsigned_commits=$((total_commits - signed_commits))
echo "- Total commits analyzed: $total_commits" >> security-audit-$(date +%Y%m%d).md echo "- Properly signed commits: $signed_commits" >> security-audit-$(date +%Y%m%d).md echo "- Unsigned commits: $unsigned_commits" >> security-audit-$(date +%Y%m%d).md echo "- Signing compliance: $((signed_commits * 100 / total_commits))%" >> security-audit-$(date +%Y%m%d).md
cat >> security-audit-$(date +%Y%m%d).md << EOF
## Detailed Findings
### Signature Status BreakdownEOF
# Signature status breakdown git log --show-signature --pretty=format:"%G?" | sort | uniq -c | while read -r count status; do case "$status" in "G") desc="Good signatures" ;; "B") desc="Bad signatures" ;; "X") desc="Expired signatures" ;; "Y") desc="Expired keys" ;; "R") desc="Revoked keys" ;; "N") desc="No signature" ;; *) desc="Unknown status: $status" ;; esac echo "- $count $desc" >> security-audit-$(date +%Y%m%d).md done
cat >> security-audit-$(date +%Y%m%d).md << EOF
### Risk AssessmentEOF
# Risk assessment if [ "$unsigned_commits" -gt 0 ]; then echo "**HIGH RISK**: $unsigned_commits commits are unsigned and cannot be verified." >> security-audit-$(date +%Y%m%d).md fi
expired_sigs=$(git log --show-signature --pretty=format:"%G?" | grep -c "X") if [ "$expired_sigs" -gt 0 ]; then echo "**MEDIUM RISK**: $expired_sigs commits have expired signatures." >> security-audit-$(date +%Y%m%d).md fi
cat >> security-audit-$(date +%Y%m%d).md << EOF
### Recommendations1. **URGENT**: Enable mandatory commit signing2. **HIGH**: Implement CI/CD signature verification3. **MEDIUM**: Rotate expired keys4. **LOW**: Regular security audits
## ConclusionCommit signing is essential for repository integrity and security.EOF
echo "Security audit report generated: security-audit-$(date +%Y%m%d).md" }
# Run comprehensive audit audit_key_usage echo detect_signature_anomalies echo forensic_commit_analysis echo generate_security_audit}
# Usagesecurity_auditingAutomated Compliance Monitoring:
Section titled “Automated Compliance Monitoring:”# Automated compliance monitoring systemautomated_compliance_monitoring() { echo "=== Automated Compliance Monitoring ==="
# Setup monitoring infrastructure setup_monitoring_infrastructure() { echo "Setting up compliance monitoring infrastructure..."
# Create monitoring directories mkdir -p compliance-monitoring/{logs,reports,alerts}
# Setup monitoring script cat > compliance-monitoring/monitor-compliance.sh << 'EOF'#!/bin/bash# Automated compliance monitoring
LOG_FILE="compliance-monitoring/logs/compliance-$(date +%Y%m%d).log"ALERT_FILE="compliance-monitoring/alerts/alerts-$(date +%Y%m%d).txt"
echo "$(date): Starting compliance check" >> "$LOG_FILE"
# Check signing compliancetotal_commits=$(git rev-list --count HEAD)signed_commits=$(git log --show-signature | grep -c "Good signature")compliance_rate=$((signed_commits * 100 / total_commits))
echo "Compliance rate: ${compliance_rate}%" >> "$LOG_FILE"
# Alert thresholdsif [ "$compliance_rate" -lt 95 ]; then echo "$(date): WARNING - Compliance below 95%: ${compliance_rate}%" >> "$ALERT_FILE"fi
# Check for unsigned commits in last 24 hoursrecent_unsigned=$(git log --since="24 hours ago" --oneline | while read -r line; do commit=$(echo "$line" | cut -d' ' -f1) if ! git verify-commit -q "$commit" 2>/dev/null; then echo "$line" fidone | wc -l)
if [ "$recent_unsigned" -gt 0 ]; then echo "$(date): ALERT - $recent_unsigned unsigned commits in last 24 hours" >> "$ALERT_FILE"fi
echo "$(date): Compliance check complete" >> "$LOG_FILE"EOF
chmod +x compliance-monitoring/monitor-compliance.sh
# Setup cron monitoring (crontab -l ; echo "0 */4 * * * $(