跳到主要内容
ecdsa.com
git over HTTPS with libcurl-gnutls (Debian, Ubuntu)Git

错误信息

fatal: unable to access 'https://git.example.com/team/app.git/': server verification failed: certificate signer not trusted. (CAfile: /etc/ssl/certs/ca-certificates.crt CRLfile: none)

也可能输出为

  • server verification failed: certificate signer not trusted. (CAfile: /etc/ssl/certs/ca-certificates.crt CRLfile: none)
  • server certificate verification failed. CAfile: none CRLfile: none

消息中的 URL 是你的远程仓库地址。较旧的 Debian 和 Ubuntu 版本(libcurl 7.x)会打印更短的“server certificate verification failed. CAfile: none CRLfile: none”,其中“CAfile: none”只表示没有显式配置 CA 文件,使用的是系统证书包。

含义

git 的 HTTPS 传输层(在 Debian 和 Ubuntu 上是基于 GnuTLS 构建的 libcurl)无法验证 Git 服务器的证书:证书链中没有任何一张证书能通向它所读取的证书包中的 CA。“certificate signer not trusted”是 GnuTLS 表示颁发者未知的说法;此时还根本没有检查你的凭证或仓库。

原因

修复方法

  1. 1.

    查看 Git 服务器发送了哪些证书

    如果只出现了叶子证书,就修复服务器。如果证书链终止于公司根证书或代理根证书,就在客户端上安装该根证书。

    bash
    openssl s_client -connect git.example.com:443 -servername git.example.com -showcerts </dev/null 2>/dev/null \
      | grep -E '^ *[0-9]+ s:|^ *i:'
  2. 2.

    只为某一个 Git 服务器信任 CA

    http.<url>.sslCAInfo 把自定义 CA 限定在一个主机上,因此公共远程仓库继续使用系统证书包。GIT_SSL_CAINFO 则对单条命令或单个 CI 作业起同样的作用。

    bash
    # Trust the company CA for this server only; other remotes keep the system bundle
    git config --global http."https://git.example.com/".sslCAInfo /etc/ssl/private-ca/corp-root-ca.pem
    git ls-remote https://git.example.com/team/app.git
  3. 3.

    把根证书添加到系统证书包

    通过 update-ca-certificates 安装根证书,可以一步修复 git、curl、wget 和包管理器。在 Docker 镜像中,在 Dockerfile 里完成这一步;在 CI 中,则在运行器镜像里完成。

    bash
    sudo cp corp-root-ca.pem /usr/local/share/ca-certificates/corp-root-ca.crt
    sudo update-ca-certificates     # git, curl and wget read /etc/ssl/certs/ca-certificates.crt
  4. 4.

    服务器所有者:配置完整证书链

    Git 服务器的 Web 前端使用的证书文件必须先包含叶子证书,后面依次跟上所有中间证书。

    text
    # GitLab Omnibus (/etc/gitlab/gitlab.rb): the .crt file must contain leaf + intermediates
    nginx['ssl_certificate'] = "/etc/gitlab/ssl/git.example.com.crt"
    # then: sudo gitlab-ctl reconfigure
  5. 5.

    临时诊断:只对一条命令跳过验证

    只对单条命令使用 -c http.sslVerify=false,可以确认问题只出在信任上。如果全局设置它,你的凭证和代码就会发送给任何能够拦截该连接的人。

    bash
    # Diagnostic only, for one command: never set http.sslVerify=false globally
    git -c http.sslVerify=false ls-remote https://git.example.com/team/app.git

相关错误

浏览完整的签名错误库