在 chart 组件之间使用 TLS
极狐GitLab chart 可以在各种组件之间使用传输层安全性 (TLS),这要求您为要启用的服务提供证书,并配置这些服务使用这些证书和签署它们的证书颁发机构(CA)。
准备
每个 chart 都有关于为该服务启用 TLS 的文档,以及确保适当配置所需的各种设置。
生成供内部使用的证书
出于本文档的目的,我们在下面提供了一个概念证明脚本,它利用 Cloudflare 的 CFSSL 生成自签名证书颁发机构,以及可用于所有服务的通配符证书。
该脚本将:
- 生成 CA 密钥对。
- 签署旨在为所有极狐GitLab 组件服务端点提供服务的证书。
- 创建两个 Kubernetes Secret 对象:
- 具有服务器证书和密钥对的
kuberetes.io/tls
类型的 secret。 -
Opaque
类型的 secret,仅包含 CA 的公共证书作为 NGINX Ingress 需要的ca.crt
。
- 具有服务器证书和密钥对的
先决条件:
- Bash,或兼容的 shell。
-
cfssl
可用于您的 shell,并且位于PATH
中。 -
kubectl
可用,并配置为指向稍后将安装极狐GitLab 的 Kubernetes 集群。- 在运行脚本之前,请务必创建您希望将这些证书安装到的命名空间。
您可以将此脚本的内容复制到您的计算机,并使生成的文件可执行。我们建议使用 poc-gitlab-internal-tls.sh
。
#!/bin/bash
set -e
#############
## make and change into a working directory
pushd $(mktemp -d)
#############
## setup environment
NAMESPACE=${NAMESPACE:-default}
RELEASE=${RELEASE:-gitlab}
## stop if variable is unset beyond this point
set -u
## known expected patterns for SAN
CERT_SANS="*.${NAMESPACE}.svc,${RELEASE}-metrics.${NAMESPACE}.svc,*.${RELEASE}-gitaly.${NAMESPACE}.svc"
#############
## generate default CA config
cfssl print-defaults config > ca-config.json
## generate a CA
echo '{"CN":"'${RELEASE}.${NAMESPACE}.internal.ca'","key":{"algo":"ecdsa","size":256}}' | \
cfssl gencert -initca - | \
cfssljson -bare ca -
## generate certificate
echo '{"CN":"'${RELEASE}.${NAMESPACE}.internal'","key":{"algo":"ecdsa","size":256}}' | \
cfssl gencert -config=ca-config.json -ca=ca.pem -ca-key=ca-key.pem -profile www -hostname="${CERT_SANS}" - |\
cfssljson -bare ${RELEASE}-services
#############
## load certificates into K8s
kubectl -n ${NAMESPACE} create secret tls ${RELEASE}-internal-tls \
--cert=${RELEASE}-services.pem \
--key=${RELEASE}-services-key.pem
kubectl -n ${NAMESPACE} create secret generic ${RELEASE}-internal-tls-ca \
--from-file=ca.crt=ca.pem
该脚本需要设置两个环境变量:
-
NAMESPACE
:您稍后将极狐GitLab 安装到的 Kubernetes 命名空间。与kubectl
一样,默认为default
。 -
RELEASE
:您稍后将用于安装极狐GitLab 的 Helm Release 名称。默认为gitlab
。
要运行此脚本,您可以“导出”这两个变量,或在脚本名称前加上它们的值。
export NAMESPACE=testing
export RELEASE=gitlab
./poc-gitlab-internal-tls.sh
脚本运行后,您会发现创建的两个密钥,临时工作目录包含所有证书及其密钥。
$ pwd
/tmp/tmp.swyMgf9mDs
$ kubectl -n ${NAMESPACE} get secret | grep internal-tls
testing-internal-tls kubernetes.io/tls 2 11s
testing-internal-tls-ca Opaque 1 10s
$ ls -1
ca-config.json
ca.csr
ca-key.pem
ca.pem
testing-services.csr
testing-services-key.pem
testing-services.pem
所需证书 CN 和 SAN
各种极狐GitLab 组件通过其服务的 DNS 名称相互通信。
当 tls.verify: true
(这是默认值)时,极狐GitLab chart 生成的 Ingress 对象必须提供 NGINX 要验证的名称。因此,每个极狐GitLab 组件都应收到带有 SAN 的证书,其中包括其服务名称或 Kubernetes 服务 DNS 条目可接受的通配符。
service-name.namespace.svc
*.namespace.svc
如果需要,您可以使用 helm template
来检索所有服务对象名称的完整列表。如果您的极狐GitLab 是在没有 TLS 的情况下部署的,您可以向 Kubernetes 查询这些名称:
kubectl -n ${NAMESPACE} get service -lrelease=${RELEASE}
配置
您可以在 examples/internal-tls 中找到配置示例。
出于本文档的目的,提供了 shared-cert-values.yaml
,在生成供内部使用的证书时,它将极狐GitLab 组件配置为使用上面脚本生成的证书。
要配置的关键项:
通过使用 YAML 的本地锚点功能,可以大大简化此过程。shared-cert-values.yaml
的截断片段如下:
.internal-ca: &internal-ca gitlab-internal-tls-ca
.internal-tls: &internal-tls gitlab-internal-tls
global:
certificates:
customCAs:
- secret: *internal-ca
workhorse:
tls:
enabled: true
gitlab:
webservice:
tls:
secretName: *internal-tls
workhorse:
tls:
verify: true # default
secretName: *internal-tls
caSecretName: *internal-ca
结果
当所有组件都配置为在其服务侦听器上提供 TLS 时,极狐GitLab 组件之间的所有通信都将通过 TLS 安全性遍历网络,包括从 NGINX Ingress 到每个极狐GitLab 组件的连接。
NGINX Ingress 将终止任何入站 TLS,确定将流量传递到哪里的适当服务,然后形成与极狐GitLab 组件的新 TLS 连接。当按此处所示配置时,它还将针对 CA 验证极狐GitLab 组件提供的证书。
这可以通过连接到 Toolbox pod 并查询各种组件服务来验证。连接到 NGINX Ingress 使用的 Webservice Pod 的主要服务端口,示例如下:
$ kubectl -n ${NAMESPACE} get pod -lapp=toolbox,release=${RELEASE}
NAME READY STATUS RESTARTS AGE
gitlab-toolbox-5c447bfdb4-pfmpc 1/1 Running 0 65m
$ kubectl exec -ti gitlab-toolbox-5c447bfdb4-pfmpc -c toolbox -- \
curl -Iv "https://gitlab-webservice-default.testing.svc:8181"
输出应类似于以下示例:
* Trying 10.60.0.237:8181...
* Connected to gitlab-webservice-default.testing.svc (10.60.0.237) port 8181 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
* CAfile: /etc/ssl/certs/ca-certificates.crt
* CApath: /etc/ssl/certs
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_128_GCM_SHA256
* ALPN, server did not agree to a protocol
* Server certificate:
* subject: CN=gitlab.testing.internal
* start date: Jul 18 19:15:00 2022 GMT
* expire date: Jul 18 19:15:00 2023 GMT
* subjectAltName: host "gitlab-webservice-default.testing.svc" matched cert's "*.testing.svc"
* issuer: CN=gitlab.testing.internal.ca
* SSL certificate verify ok.
> HEAD / HTTP/1.1
> Host: gitlab-webservice-default.testing.svc:8181
故障排除
如果您的极狐GitLab 实例似乎无法从浏览器访问,通过呈现 HTTP 503 错误,NGINX Ingress 可能在验证极狐GitLab 组件的证书时遇到问题。
您可以通过暂时将 gitlab.webservice.workhorse.tls.verify
设置为 false
来解决这个问题。
可以连接 NGINX Ingress 控制器,并将在 nginx.conf
中显示一条关于证书验证问题的消息。
无法访问 Secret 的示例内容:
# Location denied. Reason: "error obtaining certificate: local SSL certificate
testing/gitlab-internal-tls-ca was not found"
return 503;
导致这种情况的常见问题:
- CA 证书不在 Secret 中名为
ca.crt
的密钥中。 - Secret 未正确提供,或者命名空间中可能不存在。