Skip to content

verify-tag Git Command Guide

The git verify-tag command validates GPG signatures on Git tags to ensure they were created by the claimed author and haven’t been tampered with. It’s essential for maintaining the integrity and authenticity of release tags and version markers in security-conscious environments.

Terminal window
git verify-tag [--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>]
<tag>...
OptionDescription
--rawPrint raw GPG status output
-v, --verboseVerbose output
-q, --quietSuppress output
--keyid-format=<format>Key ID display format (short, long, etc.)
OptionDescription
--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
ParameterDescription
<tag>Tag(s) to verify (name, SHA-1, etc.)
Tag Signing and Verification:
├── Tag Creation: Developer creates annotated tag with message
├── GPG Signing: Tag SHA-1 signed with private key
├── Signature Storage: Signature embedded in tag object
├── Verification: Public key used to verify signature
├── Trust Validation: Key trustworthiness confirmed
└── Integrity Check: Tag content matches signed hash
Tag Object Structure:
├── Lightweight Tags: Simple refs to commits (no signature)
├── Annotated Tags: Full objects with metadata and signatures
├── Signed Tags: Annotated tags with GPG/SSH signatures
├── Verification Scope: Message, timestamp, tagger, target commit
└── Trust Chain: Key validity, signature validity, content integrity
Tag Signature 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 available
Terminal window
# Verify specific tag
git verify-tag v1.0
# Verify latest tag
git verify-tag $(git describe --tags --abbrev=0)
# Verify multiple tags
git verify-tag v1.0 v2.0 v3.0
# Verify tag by SHA-1
git verify-tag abc123def456
Terminal window
# Verify all tags in repository
git tag | xargs git verify-tag
# Verify recent tags only
git tag --sort=-version:refname | head -5 | xargs git verify-tag
# Verify tags from specific pattern
git tag | grep "^v[0-9]" | xargs git verify-tag
Terminal window
# Verbose verification with details
git verify-tag -v v1.0
# Raw GPG output for debugging
git verify-tag --raw v1.0
# Quiet verification (exit code only)
git verify-tag -q v1.0
Terminal window
# Verify all tags with status reporting
verify_all_tags() {
echo "Verifying all tags in repository..."
git tag | while read -r tag; do
if git verify-tag -q "$tag" 2>/dev/null; then
echo "$tag"
else
echo "$tag"
fi
done
}
# Verify tags by contributor
verify_contributor_tags() {
local contributor="$1"
echo "Verifying tags created by $contributor..."
git tag --format="%(refname:short) %(creator)" | while read -r tag creator; do
if [[ "$creator" == *"$contributor"* ]]; then
if git verify-tag -q "$tag" 2>/dev/null; then
echo "$tag"
else
echo "$tag"
fi
fi
done
}
# Usage
verify_contributor_tags "John Doe"
Terminal window
# Verify tag chronological chain
verify_tag_chain() {
echo "Verifying tag chronological chain..."
# Get tags sorted by creation date
git tag --sort=creatordate --format="%(refname:short) %(creatordate)" | while read -r tag date; do
echo "Verifying $tag (created: $date)..."
if git verify-tag -q "$tag" 2>/dev/null; then
echo " ✓ Signature valid"
# Check if tag points to valid commit
commit=$(git rev-parse "$tag^{commit}")
if git cat-file -e "$commit" 2>/dev/null; then
echo " ✓ Points to valid commit: $commit"
else
echo " ✗ Points to invalid commit: $commit"
fi
else
echo " ✗ Signature invalid"
fi
echo
done
}
# Verify release tag sequence
verify_release_sequence() {
echo "Verifying release tag sequence..."
git tag --sort=version:refname | grep "^v" | while read -r tag; do
echo "Checking $tag..."
# Verify signature
if ! git verify-tag -q "$tag" 2>/dev/null; then
echo " ✗ Invalid signature"
continue
fi
# Check version ordering
version=$(echo "$tag" | sed 's/^v//')
# Additional version validation logic here
echo " ✓ Valid release tag"
done
}
Terminal window
# Verify tags with specific key requirements
verify_with_key_policy() {
local required_key="$1"
echo "Verifying tags with key policy: $required_key"
git tag | while read -r tag; do
echo "Checking $tag..."
# Get signature details
sig_info=$(git verify-tag --raw "$tag" 2>&1 | grep -E "(VALIDSIG|ERRSIG)")
if [[ "$sig_info" == *"$required_key"* ]]; then
echo " ✓ Signed with required key"
else
echo " ✗ Not signed with required key"
echo " Required: $required_key"
echo " Found: $sig_info"
fi
done
}
# Check key validity for tag signers
check_signer_key_validity() {
echo "Checking validity of keys used for tag signing..."
git tag | while read -r tag; do
# Extract signing key from raw output
key_id=$(git verify-tag --raw "$tag" 2>&1 | grep "VALIDSIG" | awk '{print $3}')
if [ -n "$key_id" ]; then
echo "Tag $tag signed with key: $key_id"
# Check key validity
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
else
echo "Tag $tag is not signed"
fi
echo
done
}
# Usage
verify_with_key_policy "ABC123DEF456"
check_signer_key_validity
Terminal window
# Configure GPG for tag signing
git config --global user.signingkey "ABC123DEF456"
git config --global tag.gpgsign true
# Configure GPG program
git config --global gpg.program "gpg"
git config --global gpg.ssh.program "ssh-keygen"
# Configure key display format
git config --global verify.keyidformat "long"
# Configure SSH signing
git config --global gpg.ssh.allowedSignersFile "~/.ssh/allowed_signers"
git config --global gpg.ssh.defaultKeyCommand "ssh-add -L"
Terminal window
# Generate GPG key for tag signing
generate_gpg_key() {
echo "Generating GPG key for tag 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 tag verification"
}
# Setup SSH signing for tags
setup_ssh_signing() {
echo "Setting up SSH signing for tags..."
# Generate SSH key for signing
ssh-keygen -t ed25519 -C "git-tag-signing" -f ~/.ssh/tag_signing_key
# Configure allowed signers
echo "$(git config user.email) $(cat ~/.ssh/tag_signing_key.pub)" >> ~/.ssh/allowed_signers
# Configure Git to use SSH signing
git config --global gpg.ssh.defaultKeyCommand "ssh-add -L ~/.ssh/tag_signing_key"
git config --global gpg.format ssh
git config --global tag.gpgsign true
}
# Import team member keys
setup_team_keys() {
echo "Setting up team GPG keys for tag 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"
}
Terminal window
# Safe tag verification with error handling
safe_verify_tag() {
local tag="$1"
echo "Verifying tag: $tag"
# Check if tag exists
if ! git show-ref --verify "refs/tags/$tag" >/dev/null 2>&1; then
echo "Error: Tag $tag does not exist"
return 1
fi
# Attempt verification
if git verify-tag -q "$tag" 2>/dev/null; then
echo "✓ Tag signature is valid"
return 0
else
echo "✗ Tag signature verification failed"
return 1
fi
}
# Batch verification with progress
batch_verify_tags() {
local tag_count
tag_count=$(git tag | wc -l)
local current=0
echo "Batch verifying $tag_count tags..."
git tag | while read -r tag; do
((current++))
echo -n "[$current/$tag_count] Verifying $tag... "
if safe_verify_tag "$tag" >/dev/null 2>&1; then
echo ""
else
echo ""
fi
done
echo "Batch verification complete"
}
# Usage
batch_verify_tags
Terminal window
# Verify tags in CI/CD pipelines
ci_tag_verification() {
echo "=== CI/CD Tag Verification ==="
# Verify release tags
verify_release_tags() {
echo "Verifying release tags..."
# Get release tags from current branch
git tag --merged HEAD | grep "^v[0-9]" | while read -r tag; do
echo "Verifying release tag $tag"
if git verify-tag -q "$tag" 2>/dev/null; then
echo "✓ Signature valid"
# Additional validation
tag_commit=$(git rev-parse "$tag^{commit}")
echo " Points to commit: $tag_commit"
# Check tag message
tag_message=$(git tag -l --format="%(contents)" "$tag")
if [ -n "$tag_message" ]; then
echo " ✓ Has annotation"
else
echo " ⚠ Lightweight tag"
fi
else
echo "✗ Signature invalid - rejecting release"
exit 1
fi
done
echo "All release tags verified"
}
# Setup tag signing requirement
setup_tag_signing() {
echo "Setting up tag signing requirements..."
# Configure Git to require signing
git config --global tag.gpgsign true
# Setup pre-push hook
cat > .git/hooks/pre-push << 'EOF'
#!/bin/bash
# Require tag signing for pushes
zero_commit="0000000000000000000000000000000000000000"
while read -r local_ref local_sha remote_ref remote_sha; do
# Check if pushing tags
if [[ "$local_ref" == refs/tags/* ]]; then
tag_name="${local_ref#refs/tags/}"
echo "Verifying tag signature for $tag_name..."
if ! git verify-tag -q "$tag_name" 2>/dev/null; then
echo "ERROR: Tag $tag_name is not signed"
echo "Please sign your tags before pushing."
exit 1
fi
echo "✓ Tag $tag_name is properly signed"
fi
done
echo "Pre-push tag verification complete"
EOF
chmod +x .git/hooks/pre-push
echo "Tag signing requirement configured"
}
# Generate tag verification report
generate_tag_report() {
echo "Generating tag verification status report..."
cat > tag-verification-report.md << EOF
# Tag Verification Status Report
Generated: $(date)
Repository: $(basename "$(pwd)")
Branch: $(git branch --show-current)
## Tag Statistics
EOF
total_tags=$(git tag | wc -l)
signed_tags=$(git tag | while read -r tag; do git verify-tag -q "$tag" 2>/dev/null && echo "$tag"; done | wc -l)
unsigned_tags=$((total_tags - signed_tags))
echo "- Total tags: $total_tags" >> tag-verification-report.md
echo "- Signed tags: $signed_tags" >> tag-verification-report.md
echo "- Unsigned tags: $unsigned_tags" >> tag-verification-report.md
echo "- Signing rate: $((signed_tags * 100 / total_tags))%" >> tag-verification-report.md
cat >> tag-verification-report.md << EOF
## Recent Tag Signing Status
$(git tag --sort=-creatordate | head -10 | while read -r tag; do
if git verify-tag -q "$tag" 2>/dev/null; then
echo "- ✓ $tag"
else
echo "- ✗ $tag"
fi
done)
## Recommendations
EOF
if [ "$unsigned_tags" -gt 0 ]; then
echo "- Enable tag signing: \`git config tag.gpgsign true\`" >> tag-verification-report.md
echo "- Setup GPG key for signing" >> tag-verification-report.md
fi
echo "Tag verification report generated: tag-verification-report.md"
}
# Run CI/CD verification
verify_release_tags
generate_tag_report
}
# Usage in CI
ci_tag_verification
Terminal window
# Audit repository for signed tags
audit_tag_signing() {
echo "=== Repository Tag Signing Audit ==="
# Analyze signing coverage
analyze_signing_coverage() {
echo "Analyzing tag signing coverage..."
declare -A signer_stats
git tag --format="%(refname:short) %(creator)" | while read -r tag creator; do
if git verify-tag -q "$tag" 2>/dev/null; then
signer_stats["$creator"]=$((signer_stats["$creator"] + 1))
fi
done
echo "Signing coverage by creator:"
for creator in "${!signer_stats[@]}"; do
echo " $creator: ${signer_stats[$creator]} signed tags"
done
}
# Find unsigned tags
find_unsigned_tags() {
echo "Finding unsigned tags..."
git tag | while read -r tag; do
if ! git verify-tag -q "$tag" 2>/dev/null; then
echo "Unsigned tag: $tag"
# Show tag details
git tag -l "$tag"
echo
fi
done
}
# Check tag signing key rotation
check_key_rotation() {
echo "Checking tag signing key rotation..."
git tag --sort=creatordate --format="%(refname:short) %(creatordate)" | while read -r tag date; do
if git verify-tag -q "$tag" 2>/dev/null; then
# Extract key info (simplified)
key_info=$(git verify-tag --raw "$tag" 2>&1 | grep "VALIDSIG" | awk '{print $3}')
echo "$date - $tag - $key_info"
fi
done | sort | uniq -c | sort -nr
}
# Generate security report
generate_security_report() {
echo "Generating tag security report..."
cat > tag-security-audit-report.md << EOF
# Tag Security Audit Report
Generated: $(date)
Repository: $(basename "$(pwd)")
## Tag Signing Analysis
EOF
total_tags=$(git tag | wc -l)
signed_tags=$(git tag | while read -r tag; do git verify-tag -q "$tag" 2>/dev/null && echo "$tag"; done | wc -l)
unsigned_tags=$((total_tags - signed_tags))
echo "### Overall Statistics" >> tag-security-audit-report.md
echo "- Total tags: $total_tags" >> tag-security-audit-report.md
echo "- Signed tags: $signed_tags" >> tag-security-audit-report.md
echo "- Unsigned tags: $unsigned_tags" >> tag-security-audit-report.md
echo "- Signing compliance: $((signed_tags * 100 / total_tags))%" >> tag-security-audit-report.md
echo >> tag-security-audit-report.md
echo "### Unsigned Tags" >> tag-security-audit-report.md
git tag | while read -r tag; do
if ! git verify-tag -q "$tag" 2>/dev/null; then
echo "- $tag" >> tag-security-audit-report.md
fi
done
echo >> tag-security-audit-report.md
echo "### Security Recommendations" >> tag-security-audit-report.md
if [ "$unsigned_tags" -gt 0 ]; then
echo "- **HIGH**: $unsigned_tags tags are unsigned" >> tag-security-audit-report.md
echo "- Enable mandatory tag signing" >> tag-security-audit-report.md
echo "- Implement CI/CD tag verification" >> tag-security-audit-report.md
fi
echo "Tag security audit report generated: tag-security-audit-report.md"
}
# Run audit
analyze_signing_coverage
echo
find_unsigned_tags
echo
check_key_rotation
echo
generate_security_report
}
# Usage
audit_tag_signing
Terminal window
# Team tag signing workflow
team_tag_workflow() {
echo "=== Team Tag Signing Workflow ==="
# Setup team signing policy
setup_team_policy() {
echo "Setting up team tag signing policy..."
cat > team-tag-policy.md << EOF
# Team Tag Signing Policy
## Policy Overview
All release tags must be signed with approved keys.
## Requirements
- Release tags (v*) must be signed
- Development tags may be unsigned
- Keys must be approved by security team
- Annual key rotation mandatory
## Process
1. Create annotated tag with release notes
2. Sign tag with approved key
3. Push tag to protected branch
4. CI/CD verifies signature before deployment
## Verification
- CI/CD pipelines reject unsigned release tags
- Security audits check compliance monthly
- Key rotation reminders sent quarterly
EOF
echo "Team tag policy created: team-tag-policy.md"
}
# Setup developer tag signing
setup_developer_signing() {
local developer="$1"
echo "Setting up tag signing for developer: $developer"
# Create developer config
mkdir -p "developer-configs/$developer"
cat > "developer-configs/$developer/tag-signing-setup.sh" << EOF
#!/bin/bash
# Tag signing setup for $developer
echo "Setting up tag signing..."
# Configure Git
git config --global user.name "$developer"
git config --global user.email "$developer@company.com"
git config --global tag.gpgsign true
# Generate GPG key (interactive)
echo "Run: gpg --full-generate-key"
echo "Then configure: git config --global user.signingkey YOUR_KEY_ID"
echo "Tag signing setup complete for $developer"
EOF
chmod +x "developer-configs/$developer/tag-signing-setup.sh"
echo "Developer tag signing setup created"
}
# Monitor team compliance
monitor_team_compliance() {
echo "Monitoring team tag signing compliance..."
# Check release tags
release_tags=$(git tag | grep "^v[0-9]" | wc -l)
signed_release_tags=$(git tag | grep "^v[0-9]" | while read -r tag; do
git verify-tag -q "$tag" 2>/dev/null && echo "$tag"
done | wc -l)
if [ "$release_tags" -gt 0 ]; then
compliance=$((signed_release_tags * 100 / release_tags))
echo "Release tag compliance: ${compliance}% ($signed_release_tags/$release_tags signed)"
fi
# Check recent tags
echo "Recent tag signing status:"
git tag --sort=-creatordate | head -5 | while read -r tag; do
if git verify-tag -q "$tag" 2>/dev/null; then
echo "$tag"
else
echo "$tag"
fi
done
}
# Interactive team workflow
echo "Team Tag 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
}
# Usage
team_tag_workflow
Terminal window
# Diagnose tag signature verification problems
diagnose_tag_signature_issues() {
echo "Diagnosing tag signature verification issues..."
# Test basic verification
if git verify-tag -q v1.0 2>/dev/null; then
echo "✓ Basic tag signature verification works"
else
echo "✗ Tag 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 if tag is signed
if ! git show --show-signature v1.0 | grep -q "gpg:"; then
echo " Tag 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 tag signature issues
fix_tag_signature_issues() {
echo "Attempting to fix tag signature issues..."
# Import missing keys
echo "Attempting to import missing keys..."
# Get failed tag
failed_key=$(git verify-tag v1.0 2>&1 | grep -o "gpg:.*key.*not.*found" | sed 's/.*key \([A-F0-9]*\).*/\1/')
if [ -n "$failed_key" ]; then
echo "Missing key: $failed_key"
echo "Attempting to fetch from keyserver..."
if gpg --keyserver hkps://keys.openpgp.org --recv-keys "$failed_key" 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-tag -q v1.0 2>/dev/null; then
echo "✓ Tag signature verification now works"
else
echo "✗ Tag signature verification still failing"
fi
}
# Usage
diagnose_tag_signature_issues
fix_tag_signature_issues
Terminal window
# Troubleshoot tag key management problems
troubleshoot_tag_key_management() {
echo "Troubleshooting tag key management issues..."
# Check key validity
check_tag_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 tags with invalid signatures
find_invalid_tag_signatures() {
echo "Finding tags with invalid signatures..."
git tag | while read -r tag; do
if ! git verify-tag -q "$tag" 2>/dev/null; then
echo "Invalid signature: $tag"
fi
done
}
# Update keyring
update_tag_keyring() {
echo "Updating GPG keyring for tag verification..."
# Update from keyservers
gpg --keyserver hkps://keys.openpgp.org --refresh-keys
# Update trust database
gpg --check-trustdb
echo "Tag keyring update complete"
}
# Interactive troubleshooting
echo "Tag 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_tag_key_status "$key_id"
;;
2) find_invalid_tag_signatures ;;
3) update_tag_keyring ;;
esac
}
# Usage
troubleshoot_tag_key_management
Terminal window
# Troubleshoot tag configuration problems
troubleshoot_tag_config_issues() {
echo "Troubleshooting tag configuration issues..."
# Check Git configuration
echo "Git tag signing configuration:"
git config --list | grep -E "(gpgsign|tag\.gpgsign)" | while read -r config; do
echo " $config"
done
# Check if tag signing is enabled
if [ "$(git config --bool tag.gpgsign)" != "true" ]; then
echo "⚠ Tag signing is not enabled"
echo " Enable with: git config tag.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 tag configuration issues
fix_tag_config_issues() {
echo "Attempting to fix tag configuration issues..."
# Enable tag signing
git config tag.gpgsign true
echo "✓ Enabled tag 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-tag -q $(git tag | head -1) 2>/dev/null; then
echo "✓ Tag configuration is working"
else
echo "⚠ Tag configuration may still need adjustment"
fi
}
# Usage
troubleshoot_tag_config_issues
fix_tag_config_issues
#!/bin/bash
# Enterprise tag-based release management
enterprise_release_management() {
echo "=== Enterprise Release Management ==="
# Setup release signing requirements
setup_release_signing() {
echo "Setting up enterprise release signing requirements..."
cat > release-signing-requirements.md << EOF
# Enterprise Release Signing Requirements
## Overview
All release tags must be cryptographically signed and verified.
## Requirements
- Release tags (vX.Y.Z) must be annotated and signed
- Signatures must use approved GPG keys
- Keys must be valid and not expired
- CI/CD must verify signatures before deployment
## Process
1. Create release branch from main
2. Test and validate release
3. Create signed annotated tag
4. Push tag to trigger deployment
5. CI/CD verifies signature and deploys
## Security Controls
- Pre-push hooks prevent unsigned tag pushes
- CI/CD rejects deployments from unsigned tags
- Regular key rotation audits
- Automated signature verification
EOF
echo "Release signing requirements documented: release-signing-requirements.md"
}
# Create signed release tag
create_signed_release() {
local version="$1"
local message="$2"
echo "Creating signed release tag v$version..."
# Validate version format
if [[ ! "$version" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "Invalid version format: $version"
echo "Expected: X.Y.Z"
return 1
fi
# Check if tag already exists
if git tag | grep -q "^v$version$"; then
echo "Tag v$version already exists"
return 1
fi
# Create annotated signed tag
git tag -a -s "v$version" -m "Release $version
$message
Signed-by: $(git config user.name) <$(git config user.email)>
Created: $(date -u '+%Y-%m-%d %H:%M:%S UTC')"
# Verify the tag was created and signed
if git verify-tag -q "v$version" 2>/dev/null; then
echo "✓ Signed release tag v$version created successfully"
# Show tag details
git tag -l "v$version"
else
echo "✗ Failed to create signed tag"
return 1
fi
}
# Verify release deployment readiness
verify_release_readiness() {
local tag="$1"
echo "Verifying release readiness for $tag..."
# Verify tag exists and is signed
if ! git verify-tag -q "$tag" 2>/dev/null; then
echo "✗ Tag $tag is not signed"
return 1
fi
# Check tag format
if [[ ! "$tag" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "⚠ Tag $tag does not follow release format vX.Y.Z"
fi
# Verify tag points to valid commit
commit=$(git rev-parse "$tag^{commit}")
if ! git cat-file -e "$commit" 2>/dev/null; then
echo "✗ Tag $tag points to invalid commit"
return 1
fi
# Check if commit is in main branch
if ! git branch --contains "$commit" | grep -q " main$\| master$"; then
echo "⚠ Tag $tag points to commit not in main branch"
fi
echo "✓ Release $tag is ready for deployment"
}
# Setup automated release verification
setup_release_verification() {
echo "Setting up automated release verification..."
# Create release verification script
cat > verify-release.sh << 'EOF'
#!/bin/bash
# Automated release verification
TAG="$1"
if [ -z "$TAG" ]; then
echo "Usage: $0 <tag>"
exit 1
fi
echo "Verifying release $TAG..."
# Verify signature
if ! git verify-tag -q "$TAG" 2>/dev/null; then
echo "❌ RELEASE REJECTED: Tag $TAG is not signed"
exit 1
fi
# Verify tag format
if [[ ! "$TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "❌ RELEASE REJECTED: Invalid tag format: $TAG"
exit 1
fi
# Additional checks can be added here
# - Security scans
# - Test results
# - Compliance checks
echo "✅ RELEASE APPROVED: $TAG passed all verification checks"
EOF
chmod +x verify-release.sh
echo "Release verification script created: verify-release.sh"
}
# Interactive enterprise release management
echo "Enterprise Release Management Options:"
echo "1. Setup release signing requirements"
echo "2. Create signed release tag"
echo "3. Verify release readiness"
echo "4. Setup automated verification"
read -p "Select option (1-4): " option
case "$option" in
1) setup_release_signing ;;
2)
read -p "Version (X.Y.Z): " version
read -p "Release message: " message
create_signed_release "$version" "$message"
;;
3)
read -p "Tag to verify: " tag
verify_release_readiness "$tag"
;;
4) setup_release_verification ;;
esac
}
enterprise_release_management
Terminal window
# Advanced tag security auditing
tag_security_auditing() {
echo "=== Advanced Tag Security Auditing ==="
# Audit tag signing compliance
audit_tag_compliance() {
echo "Auditing tag signing compliance..."
total_tags=$(git tag | wc -l)
signed_tags=0
unsigned_tags=0
declare -A signer_keys
git tag | while read -r tag; do
if git verify-tag -q "$tag" 2>/dev/null; then
((signed_tags++))
# Extract key info
key=$(git verify-tag --raw "$tag" 2>&1 | grep "VALIDSIG" | awk '{print $3}')
signer_keys["$key"]=$((signer_keys["$key"] + 1))
else
((unsigned_tags++))
fi
done
echo "Compliance Summary:"
echo " Total tags: $total_tags"
echo " Signed tags: $signed_tags"
echo " Unsigned tags: $unsigned_tags"
echo " Compliance rate: $((signed_tags * 100 / total_tags))%"
echo "Signing keys used:"
for key in "${!signer_keys[@]}"; do
echo " $key: ${signer_keys[$key]} tags"
done
}
# Detect tag signing anomalies
detect_tag_anomalies() {
echo "Detecting tag signing anomalies..."
# Check for expired signatures
git tag | while read -r tag; do
if git verify-tag -q "$tag" 2>/dev/null; then
# Check signature age
tag_date=$(git tag --format="%(creatordate:unix)" "$tag")
current_time=$(date +%s)
age_days=$(( (current_time - tag_date) / 86400 ))
if [ "$age_days" -gt 365 ]; then
echo "⚠ Old signature: $tag ($age_days days old)"
fi
fi
done
# Check for unusual signing patterns
echo "Checking for unusual signing patterns..."
# Find tags signed by multiple keys
declare -A tag_signers
git tag | while read -r tag; do
if git verify-tag -q "$tag" 2>/dev/null; then
key=$(git verify-tag --raw "$tag" 2>&1 | grep "VALIDSIG" | awk '{print $3}')
tag_signers["$tag"]="$key"
fi
done
# Report findings
unique_keys=$(echo "${tag_signers[@]}" | tr ' ' '\n' | sort | uniq | wc -l)
total_signed_tags=$(echo "${!tag_signers[@]}" | wc -w)
echo "Signing pattern analysis:"
echo " Unique signing keys: $unique_keys"
echo " Signed tags: $total_signed_tags"
}
# Generate compliance report
generate_compliance_report() {
echo "Generating tag compliance report..."
cat > tag-compliance-report-$(date +%Y%m%d).md << EOF
# Tag Compliance Report
Generated: $(date)
Repository: $(basename "$(pwd)")
Audit Period: All time
## Executive Summary
This report analyzes tag signing compliance and security posture.
## Compliance Metrics
EOF
# Calculate metrics
total_tags=$(git tag | wc -l)
signed_tags=$(git tag | while read -r tag; do git verify-tag -q "$tag" 2>/dev/null && echo "$tag"; done | wc -l)
unsigned_tags=$((total_tags - signed_tags))
compliance_rate=0
if [ "$total_tags" -gt 0 ]; then
compliance_rate=$((signed_tags * 100 / total_tags))
fi
echo "### Overall Compliance" >> tag-compliance-report-$(date +%Y%m%d).md
echo "- Total tags: $total_tags" >> tag-compliance-report-$(date +%Y%m%d).md
echo "- Signed tags: $signed_tags" >> tag-compliance-report-$(date +%Y%m%d).md
echo "- Unsigned tags: $unsigned_tags" >> tag-compliance-report-$(date +%Y%m%d).md
echo "- Compliance rate: ${compliance_rate}%" >> tag-compliance-report-$(date +%Y%m%d).md
cat >> tag-compliance-report-$(date +%Y%m%d).md << EOF
## Risk Assessment
EOF
if [ "$compliance_rate" -lt 80 ]; then
echo "**CRITICAL RISK**: Compliance below 80%" >> tag-compliance-report-$(date +%Y%m%d).md
elif [ "$compliance_rate" -lt 95 ]; then
echo "**HIGH RISK**: Compliance below 95%" >> tag-compliance-report-$(date +%Y%m%d).md
else
echo "**ACCEPTABLE**: Good compliance level" >> tag-compliance-report-$(date +%Y%m%d).md
fi
cat >> tag-compliance-report-$(date +%Y%m%d).md << EOF
## Recommendations
1. **IMMEDIATE**: Enable mandatory tag signing
2. **HIGH**: Implement CI/CD signature verification
3. **MEDIUM**: Rotate signing keys annually
4. **LOW**: Regular compliance audits
## Unsigned Tags (First 10)
EOF
git tag | while read -r tag; do
if ! git verify-tag -q "$tag" 2>/dev/null; then
echo "- $tag" >> tag-compliance-report-$(date +%Y%m%d).md
fi
done | head -10 >> tag-compliance-report-$(date +%Y%m%d).md
echo "Compliance report generated: tag-compliance-report-$(date +%Y%m%d).md"
}
# Run comprehensive audit
audit_tag_compliance
echo
detect_tag_anomalies
echo
generate_compliance_report
}
# Usage
tag_security_auditing
Terminal window
# Automated deployment with tag verification
secure_deployment_system() {
echo "=== Secure Deployment System ==="
# Setup deployment security
setup_deployment_security() {
echo "Setting up deployment security controls..."
cat > deployment-security-policy.md << EOF
# Deployment Security Policy
## Overview
Deployments are only allowed from properly signed and verified tags.
## Security Controls
- All deployments must originate from signed tags
- Tags must be verified before deployment starts
- Deployment keys must be approved and rotated regularly
- Audit logs must capture all deployment activities
## Process
1. Developer creates signed release tag
2. CI/CD verifies tag signature
3. Security scan runs on tagged commit
4. Manual approval required for production
5. Automated deployment with full audit trail
## Monitoring
- All deployment attempts logged
- Signature verification failures alerted
- Regular security audits performed
- Compliance reports generated monthly
EOF
echo "Deployment security policy created: deployment-security-policy.md"
}
# Verify deployment readiness
verify_deployment_readiness() {
local tag="$1"
local environment="$2"
echo "Verifying deployment readiness for $tag to $environment..."
# Verify tag signature
if ! git verify-tag -q "$tag" 2>/dev/null; then
echo "❌ DEPLOYMENT BLOCKED: Tag $tag signature verification failed"
return 1
fi
# Verify tag format for production
if [ "$environment" = "production" ]; then
if [[ ! "$tag" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "❌ DEPLOYMENT BLOCKED: Invalid production tag format: $tag"
return 1
fi
fi
# Additional security checks
commit=$(git rev-parse "$tag^{commit}")
# Check commit is in protected branch
protected_branches=("main" "master" "release/*")
in_protected_branch=false
for branch in "${protected_branches[@]}"; do
if git branch --contains "$commit" | grep -q "$branch"; then
in_protected_branch=true
break
fi
done
if [ "$in_protected_branch" = false ]; then
echo "❌ DEPLOYMENT BLOCKED: Commit not in protected branch"
return 1
fi
# Check for recent security scans (placeholder)
echo "✓ Security checks passed"
echo "✅ DEPLOYMENT APPROVED: $tag ready for $environment deployment"
return 0
}
# Execute secure deployment
execute_secure