Git钩子脚本如何检查证书策略

wen 实用脚本 1

Git 钩子脚本可以通过以下几种方式检查和强制执行证书策略(例如签名要求、证书有效性等):

Git钩子脚本如何检查证书策略

检查提交签名 (GPG 签名)

pre-receive 钩子 (服务端)

#!/bin/bash
# 检查所有推送的提交是否有有效 GPG 签名
while read oldrev newrev refname; do
    # 获取所有新提交的 SHA
    commits=$(git rev-list $oldrev..$newrev 2>/dev/null)
    for commit in $commits; do
        # 检查签名
        if ! git verify-commit $commit 2>/dev/null; then
            echo "错误: 提交 $commit 没有有效的 GPG 签名"
            exit 1
        fi
        # 可选:检查签名者是否在允许列表中
        signer=$(git log --format='%GG' $commit -1)
        if [[ ! "$signer" =~ "authorized@company.com" ]]; then
            echo "错误: 提交 $commit 的签名者未授权"
            exit 1
        fi
    done
done

commit-msg 钩子 (客户端 - 使用 commit --signoff)

#!/bin/bash
# 检查 commit 消息是否包含 Signed-off-by
if ! grep -q "^Signed-off-by:" "$1"; then
    echo "错误: 提交必须包含 Signed-off-by 行"
    echo "请使用 git commit -s 重新提交"
    exit 1
fi

检查 SSH 证书策略

pre-receive 钩子 (服务端)

#!/bin/bash
# 检查 SSH 证书是否有效
while read oldrev newrev refname; do
    # 获取推送者的 SSH 公钥指纹
    push_user=$(git log -1 --format='%ae' $newrev)
    # 检查 SSH 证书是否在授权列表中
    if ! grep -q "$push_user" /etc/git/authorized_users; then
        echo "错误: 用户 $push_user 未授权"
        exit 1
    fi
done

检查提交者邮箱与证书匹配

pre-receive 钩子

#!/bin/bash
# 验证提交者身份
while read oldrev newrev refname; do
    committer_email=$(git log -1 --format='%ce' $newrev)
    author_email=$(git log -1 --format='%ae' $newrev)
    # 获取推送者的证书信息
    user_cert=$(ssh-keygen -L -f ~/.ssh/id_rsa.pub 2>/dev/null)
    if [[ ! "$user_cert" =~ "$committer_email" ]]; then
        echo "错误: 提交者 $committer_email 与证书不匹配"
        exit 1
    fi
done

检查 TLS/HTTPS 证书

update 钩子 (针对 webhook 或远程仓库)

#!/bin/bash
# 检查仓库 URL 的 TLS 证书
remote_url=$(git config --get remote.origin.url)
if [[ "$remote_url" =~ ^https:// ]]; then
    # 使用 openssl 检查证书
    host=$(echo $remote_url | sed 's|https://\([^/]*\).*|\1|')
    port=443
    if ! openssl s_client -connect $host:$port -servername $host </dev/null 2>/dev/null | grep -q "Verify return code: 0"; then
        echo "错误: 仓库的 TLS 证书无效或已过期"
        exit 1
    fi
fi

综合策略检查脚本

完整的 pre-receive 钩子示例

#!/bin/bash
# 综合证书策略检查
POLICY_FAILURE=false
# 配置
SIGNED_COMMIT_REQUIRED=true
ALLOWED_SIGNERS=("authorized@company.com")
CERT_EXPIRY_DAYS=30
while read oldrev newrev refname; do
    if [ "$SIGNED_COMMIT_REQUIRED" = true ]; then
        # 检查签名
        for commit in $(git rev-list $oldrev..$newrev); do
            if ! git verify-commit $commit 2>/dev/null; then
                echo "❌ 提交 $commit 缺少有效的 GPG 签名"
                POLICY_FAILURE=true
            fi
            # 检查签名者
            signer_key=$(git log --format='%GK' $commit -1)
            signer_email=$(git log --format='%ae' $commit -1)
            if [[ ! " ${ALLOWED_SIGNERS[@]} " =~ " $signer_email " ]]; then
                echo "❌ 提交 $commit 的签名者 $signer_email 未授权"
                POLICY_FAILURE=true
            fi
            # 检查证书有效期
            if git log --format='%G?' $commit -1 | grep -q "E"; then
                echo "❌ 提交 $commit 的证书已过期"
                POLICY_FAILURE=true
            fi
        done
    fi
done
if [ "$POLICY_FAILURE" = true ]; then
    echo ""
    echo "❌ 推送被拒绝,违反证书策略"
    exit 1
fi
echo "✅ 所有证书策略检查通过"
exit 0

部署和测试建议

  1. 设置钩子权限

    chmod +x .git/hooks/pre-receive
  2. 测试脚本

    # 测试签名检查
    git tag v1.0 -s -m "测试签名"

测试推送被拒绝的场景

git push origin main


3. **日志记录**:
```bash
# 在钩子中添加日志
echo "$(date): 用户 $USER 推送被拒绝" >> /var/log/git-hooks.log
  1. 服务端部署
  • 将钩子放到 hooks/ 目录
  • 确保 git 用户有执行权限
  • 考虑使用 gitolitegitea 等工具管理

这些脚本可以根据实际需求组合使用,确保仓库的提交符合组织的安全策略。

抱歉,评论功能暂时关闭!