SSL 配置
可用的 SSL 配置任务
Omnibus 提供几种 SSL 配置的常见用例。
- 允许使用
https
连接到极狐GitLab 实例服务。 - 为外部资源连接配置公共证书捆绑包。
Host Services
管理员可以通过任何极狐GitLab 服务支持的方法,启用安全的 http 服务。
服务 | 手动 SSL | Let’s Encrypt |
---|---|---|
Primary GitLab Instance Domain | Yes | Yes |
Container Registry | Yes | Yes |
Mattermost | Yes | Yes |
GitLab Pages | Yes | No |
集成 Let’s Encrypt
极狐GitLab 可以与 Let’s Encrypt 集成。
主 GitLab 实例
- 如果
external_url
设置为 https 协议且未配置证书时,默认启用。
/etc/gitlab/gitlab.rb
中设置 letsencrypt['enable'] = false
以禁用。将以下内容添加到 /etc/gitlab/gitlab.rb
以启用对主域名的 Let’s Encrypt 支持:
letsencrypt['enable'] = true # GitLab 10.5 and 10.6 require this option
external_url "https://gitlab.example.com" # Must use https protocol
letsencrypt['contact_emails'] = ['foo@email.com'] # Optional
contact_emails
设置会在到期日期临近时将到期警报发送到配置的地址。GitLab 组件
按照步骤启用基本的 Let’s Encrypt 集成并使用以下任何适用的内容修改 /etc/gitlab/gitlab.rb
:
registry_external_url "https://registry.example.com" # container registry, must use https protocol
mattermost_external_url "https://mattermost.example.com" # mattermost, must use https protocol
#registry_nginx['ssl_certificate'] = "path/to/cert" # Must be absent or commented out
Let’s Encrypt 证书是使用 GitLab 主实例作为证书上的主名称创建的。其他服务(例如 registry)作为备用名称添加到同一证书中。请注意,在上面的示例中,主域是名 gitlab.example.com
,registry 域名时registry.example.com
。 管理员无需担心设置通配符证书。
Let’s Encrypt 自动更新
/etc/gitlab/gitlab.rb
中设置 letsencrypt['enable'] = false
以禁用自动更新。 否则,gitlab-ctl reconfigure
可能会尝试更新证书,从而覆盖它们。
默认计划在每月 4 日午夜之后更新。分钟由 external_url
中的值决定,以帮助分配上游 Let's Encrypt
服务器上的负载。
通过将以下内容添加到 /etc/gitlab/gitlab.rb
来显式设置更新时间:
# This example renews every 7th day at 12:30
letsencrypt['auto_renew_hour'] = "12"
letsencrypt['auto_renew_minute'] = "30"
letsencrypt['auto_renew_day_of_month'] = "*/7"
在 /etc/gitlab/gitlab.rb
中使用以下内容禁用自动更新:
letsencrypt['auto_renew'] = false
Let’s Encrypt 手动更新
使用以下命令中的 一个 手动更新 Let’s Encrypt 证书:
sudo gitlab-ctl reconfigure
sudo gitlab-ctl renew-le-certs
/etc/gitlab/gitlab.rb
中设置 letsencrypt['enable'] = false
以禁用集成。 否则证书可能会因续订而被覆盖。
连接外部资源
某些环境连接到外部资源以执行各种任务。 Omnibus 允许这些连接使用安全的 http (https
)。
默认配置
Omnibus 附带了官方的 CAcert.org 可信根证书颁发机构集合,用于验证证书的真实性。
其它证书颁发机构
Omnibus 支持使用自签名证书连接到外部服务。
安装自定义公共证书
c_rehash
依赖需要一个 perl 解释器来正确地符号链接证书。Perl 目前未捆绑在 Omnibus GitLab 中。- 从您的私钥证书生成 PEM 或 DER 编码的公共证书。
- 仅将公共证书文件复制到
/etc/gitlab/trusted-certs
目录中。 - 执行
gitlab-ctl reconfigure
命令。
c_rehash
仅为第一个证书创建哈希,则必须将根证书和/或中间证书放入/etc/gitlab/trusted-certs
中的单独文件中。故障排查
有用的 OpenSSL 调试命令
有时,通过直接在源中查看 SSL 证书链,可以更好地了解它是有帮助的。这些命令是用于诊断和调试的标准 OpenSSL 工具库的一部分。
-
通过 HTTPS 执行与主机的测试连接。将
HOSTNAME
替换为您的 GitLab URL(不包括 HTTPS),并将port
替换为提供 HTTPS 连接的端口(通常为 443):echo | /opt/gitlab/embedded/bin/openssl s_client -connect HOSTNAME:port
echo
命令向服务器发送一个空请求,导致它关闭连接而不是等待额外的输入。您可以使用相同的命令来测试远程主机(例如,托管外部仓库的服务器),方法是将HOSTNAME:port
替换为远程主机的域名和端口号。此命令的输出显示证书链、服务器提供的任何公共证书,以及验证或连接可能发生的错误。这样可以快速检查 SSL 设置的任何直接问题。
-
使用
x509
以文本形式查看证书的详细信息。 请务必将/path/to/certificate.crt
替换为证书的路径:/opt/gitlab/embedded/bin/openssl x509 -in /path/to/certificate.crt -text -noout
例如,GitLab 会自动从 Let’s Encrypt 获取证书并将其放置在
/etc/gitlab/ssl/hostname.crt
。您可以使用带有该路径的x509
命令来快速显示证书的信息(例如,主机名、颁发者、有效期等)。如果证书存在问题,将会出现错误。
-
从服务器获取证书并对其进行解码。这结合了上述两个命令来获取服务器的 SSL 证书并将其解码为文本:
echo | /opt/gitlab/embedded/bin/openssl s_client -connect HOSTNAME:port | /opt/gitlab/embedded/bin/openssl x509 -text -noout
常见的 SSL 错误
-
SSL certificate problem: unable to get local issuer certificate
此错误表示客户端无法获取根 CA。要解决此问题,您可以尝试新人在客户端上连接的服务器的根 CA,或修改证书 使得在您尝试连接的服务器上显示完整的链式证书。
建议使用完整的证书链,以防止客户端连接时出现 SSL 错误。完整的证书链顺序应首先包含服务器证书,然后是所有中间证书,最后是根 CA。 -
unable to verify the first certificate
此错误表明服务器提供了不完整的证书链。要修复此错误,您需要用完整链式证书替换服务器的证书。 完整的证书链顺序应首先包含服务器证书,然后是所有中间证书,最后是根 CA。
-
certificate signed by unknown authority
此错误表明客户端不信任证书或 CA。要修复此错误,连接到服务器的客户端需要信任证书或 CA。
-
SSL certificate problem: self signed certificate in certificate chain
此错误表明客户端不信任证书或 CA。要修复此错误,连接到服务器的客户端需要信任证书或 CA。
golang 编写的 Git-LFS 等嵌入式服务报告未知机构签名的自定义证书
gitlab-workhorse
和其他用 golang 编写的服务使用来自 golang 的 crypto/tls 库而不是 OpenSSL。
在 /etc/gitlab/gitlab.rb
中添加以下条目以解决问题:
gitlab_workhorse['env'] = {
'SSL_CERT_DIR' => '/opt/gitlab/embedded/ssl/certs/'
}
/opt/gitlab/
之外的路径,请在您的操作环境中使用正确的路径修改上面的条目。证书导致重新配置失败
ERROR: Not a certificate: /opt/gitlab/embedded/ssl/certs/FILE. Move it from /opt/gitlab/embedded/ssl/certs to a different location and reconfigure again.
检查 /opt/gitlab/embedded/ssl/certs
并删除除 README.md
之外的任何不是有效 X.509 证书的文件。
gitlab-ctl reconfigure
构造从自定义公共证书的 subject 哈希命名的链接,并将它们放在 /opt/gitlab/embedded/ssl/certs/
中。/opt/gitlab/embedded/ssl/certs/
中损坏的链接将被自动删除。存储在 /opt/gitlab/embedded/ssl/certs/
中的 cacert.pem
和 README.md
以外的文件将被移动到 /etc/gitlab/trusted-certs/
中。丢失或跳过自定义证书
GitLab versions 8.9.0, 8.9.1, and 8.9.2 all mistakenly used the
/etc/gitlab/ssl/trusted-certs/
directory. This directory is safe to remove if it
is empty. If it still contains custom certificates then move them to /etc/gitlab/trusted-certs/
and run gitlab-ctl reconfigure
.
如果没有在 /opt/gitlab/embedded/ssl/certs/
中创建链接,你会看到运行gitlab-ctl reconfigure
后出现 “Skipping cert.pem
” 消息,这意味着可能存在以下四个问题之一:
-
/etc/gitlab/trusted-certs/
中的文件是链接 - 该文件不是有效的 PEM 或 DER 编码的证书
- Perl 未安装在 c_rehash 正确链接证书所需的操作系统上
- 证书包含字符串
TRUSTED
使用以下命令测试证书的有效性:
/opt/gitlab/embedded/bin/openssl x509 -in /etc/gitlab/trusted-certs/example.pem -text -noout
/opt/gitlab/embedded/bin/openssl x509 -inform DER -in /etc/gitlab/trusted-certs/example.der -text -noout
无效的证书文件会产生以下输出:
unable to load certificate
140663131141784:error:0906D06C:PEM routines:PEM_read_bio:no start line:pem_lib.c:701:Expecting: TRUSTED CERTIFICATE
测试 c_rehash
是否由于缺少 perl 解释器而没有链接证书:
$ /opt/gitlab/embedded/bin/c_rehash /etc/gitlab/trusted-certs
bash: /opt/gitlab/embedded/bin/c_rehash: /usr/bin/perl: bad interpreter: No such file or directory
如果您看到此消息,则需要使用发行版的包管理器安装 perl。
如果您检查证书本身,请查找字符串 TRUSTED
:
-----BEGIN TRUSTED CERTIFICATE-----
...
-----END TRUSTED CERTIFICATE-----
如果像上面的例子一样,然后尝试删除字符串 TRUSTED
并再次运行 gitlab-ctl reconfigure
。
未检测到自定义证书
如果在执行 gitlab-ctl reconfigure
命令后:
- 在
/opt/gitlab/embedded/ssl/certs/
中没有创建链接; - 您已将自定义证书放在
/etc/gitlab/trusted-certs/
中;并且 - 您未看到任何跳过的或链接的自定义证书消息
您可能会遇到 Omnibus 认为已添加自定义证书的问题。
要解决,请删除受信任的证书目录哈希:
rm /var/opt/gitlab/trusted-certs-directory-hash
然后再次运行gitlab-ctl reconfigure
。重新配置应现在检测并链接您的自定义证书。
Let’s Encrypt 证书由未知机构签署
Let’s Encrypt 集成的初始实现仅使用证书,而不是完整的证书链。
现在使用完整的证书链。对于已经在使用证书的安装,在续订逻辑指示证书即将到期之前不会发生切换。要尽快强制执行,请运行以下命令:
rm /etc/gitlab/ssl/HOSTNAME*
gitlab-ctl reconfigure
其中 HOSTNAME 是证书的主机名。
重新配置时 Let’s Encrypt 失败
重新配置时,Let’s Encrypt 可能会在以下常见情况下失败:
-
如果您的服务器无法访问 Let’s Encrypt 验证服务器,Let’s Encrypt 可能会失败,反之亦然:
letsencrypt_certificate[gitlab.domain.com] (letsencrypt::http_authorization line 3) had an error: RuntimeError: acme_certificate[staging] (/opt/gitlab/embedded/cookbooks/cache/cookbooks/letsencrypt/resources/certificate.rb line 20) had an error: RuntimeError: [gitlab.domain.com] Validation failed for domain gitlab.domain.com
如果您由于 Let’s Encrypt 而在重新配置 GitLab 时遇到问题确保您的端口 80 和 443 已打开并可访问。
-
您的域名的证书颁发机构授权 (CAA) 记录不允许 Let’s Encrypt 为您的域名颁发证书。在重新配置输出中查找以下错误:
letsencrypt_certificate[gitlab.domain.net] (letsencrypt::http_authorization line 5) had an error: RuntimeError: acme_certificate[staging] (/opt/gitlab/embedded/cookbooks/cache/cookbooks/letsencrypt/resources/certificate.rb line 25) had an error: RuntimeError: ruby_block[create certificate for gitlab.domain.net] (/opt/gitlab/embedded/cookbooks/cache/cookbooks/acme/resources/certificate.rb line 108) had an error: RuntimeError: [gitlab.domain.com] Validation failed, unable to request certificate
-
如果您使用的是例如
gitlab.example.com
之类的测试域名,但没有证书,您将看到上面显示的unable to request certificate
。在这种情况下,通过在/etc/gitlab/gitlab.rb
中设置letsencrypt['enable'] = false
来禁用 Let’s Encrypt。
您可以使用 Let’s Debug 诊断工具测试您的域名。它可以帮助您找出无法颁发 Let’s Encrypt 证书的原因。
GitLab 和 SSL 的工作实现细节
Omnibus 包含自己的 OpenSSL 库,并将所有已编译的程序(例如 Ruby、PostgreSQL 等)链接到该库。该库编译为在 /opt/gitlab/embedded/ssl/certs
中查找证书。
Omnibus 通过使用 c_rehash 将添加到 /etc/gitlab/trusted-certs/
的任何证书链接到 /opt/gitlab/embedded/ssl/certs
来管理自定义证书。例如,假设我们将 customcacert.pem
添加到 /etc/gitlab/trusted-certs/
:
$ sudo ls -al /opt/gitlab/embedded/ssl/certs
total 272
drwxr-xr-x 2 root root 4096 Jul 12 04:19 .
drwxr-xr-x 4 root root 4096 Jul 6 04:00 ..
lrwxrwxrwx 1 root root 42 Jul 12 04:19 7f279c95.0 -> /etc/gitlab/trusted-certs/customcacert.pem
-rw-r--r-- 1 root root 263781 Jul 5 17:52 cacert.pem
-rw-r--r-- 1 root root 147 Feb 6 20:48 README
证书的指纹为 7f279c95
,它链接到自定义证书。
当我们发出 HTTPS 请求时会发生什么?让我们以一个简单的 Ruby 程序为例:
#!/opt/gitlab/embedded/bin/ruby
require 'openssl'
require 'net/http'
Net::HTTP.get(URI('https://www.google.com'))
以下是屏幕后面发生的事情:
- “require
openssl
”行导致解释器加载/opt/gitlab/embedded/lib/ruby/2.3.0/x86_64-linux/openssl.so
。 -
Net::HTTP
调用然后尝试读取/opt/gitlab/embedded/ssl/certs/cacert.pem
中的默认证书包。 - SSL 协商。
- 服务器发送其 SSL 证书。
- 如果发送的证书包含在捆绑包中,则 SSL 将成功完成。
- 否则,OpenSSL 可能会通过在预定义的证书目录中,搜索与其指纹匹配的文件来验证其他证书。 例如,如果证书的指纹为“7f279c95”,OpenSSL 将尝试读取“/opt/gitlab/embedded/ssl/certs/7f279c95.0”。
请注意,OpenSSL 库支持 SSL_CERT_FILE
和 SSL_CERT_DIR
环境变量的定义。前者定义了要加载的默认证书包,而后者定义了一个用于搜索更多证书的目录。如果你已将证书添加到“trusted-certs”目录中,这些变量不是必需的。但是,如果由于某种原因需要设置它们,它们可以定义为环境变量。例如:
gitlab_rails['env'] = {"SSL_CERT_FILE" => "/usr/lib/ssl/private/customcacert.pem"}