# 使用自签名证书设置 Harbor

我之前为镜像设置了 docker-registry，并为 Helm chart 仓库设置了一个简单的 httpd 服务。大多数时候它都按预期工作，直到我们发现分层（又名前缀）chart 不起作用。解决方案是用 Harbor (2.0+) 替换上述两个服务。Harbor 是兼容 OCI 的注册表，能够提供包括 Helm chart 在内的符合 OCI 的工件（需要 Helm 3.0+）。

一般设置应该与其他 Ingress 控制器（如 Nginx/nginx-ingress）一起使用。

### 设置基本的 k3s 集群

```shell
export https_proxy=http://proxy.com:8000        # optional
curl -sfL https://get.k3s.io | sh -s - --node-name=nsp-k8s-deployer --disable=traefik --disable=metrics-server
```

### 安装 Helm 客户端

如果您想从远程客户端安装 chart，则本地 Helm 客户端是可选的。

```shell
curl https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 | bash
```

### 安装 Traefik

```shell
kubectl create namespace traefik
helm install --repo https://repo.chartcenter.io --version 9.1.1 --namespace traefik traefik traefik/traefik
```

### 生成自签名证书

参考自：https://goharbor.io/docs/2.1.0/install-config/configure-https/

1. 生成 CA 证书私钥 `openssl genrsa -out ca.key 4096`
2. 生成 CA 证书

```shell
openssl req -x509 -new -nodes -sha512 -days 3650 -subj "/C=CN/ST=Beijing/L=Beijing/O=example/OU=Personal/CN=yourdomain.com" -key ca.key -out ca.crt
```

注意：使用交互式界面进行精确设置。

3. 生成 x509 v3 扩展文件。

无论您是使用 FQDN 还是 IP 地址连接到 Harbor 主机，都必须创建此文件，以便您可以为符合使用者备用名称 (SAN) 和 x509 v3 扩展要求的 Harbor 主机生成证书。替换 DNS 条目以反映您的域。

```
cat > v3.ext <<-EOF
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names

[alt_names]
DNS.1=yourdomain.com
DNS.2=yourdomain
DNS.3=hostname
EOF
```

4. 使用 `v3.ext` 文件为您的 Harbor 主机生成证书。

将 CSR 和 CRT 文件名中的 `yourdomain.com` 替换为 Harbor 主机名。

```shell
openssl x509 -req -sha512 -days 3650 -extfile v3.ext -CA ca.crt -CAkey ca.key -CAcreateserial -in yourdomain.com.csr -out yourdomain.com.crt
```

5. 将 `yourdomain.com.crt` 转换为 `yourdomain.com.cert`，供 Docker 使用。（此步骤可能不需要）。

Docker 守护进程将 `.crt` 文件解释为 CA 证书，将 `.cert` 文件解释为客户端证书。

```shell
openssl x509 -inform PEM -in yourdomain.com.crt -out yourdomain.com.cert
```

注意：Docker 只需要：

```
ls /etc/docker/certs.d/registry.nspos.nokia.local/ 

Registry.nspos.nokia.local.crt 
```

6. 对于 Red Hat/CentOS 错误：`x509: certificate signed by unknown authority`

解决方案：(RHEL) 复制证书到 `/etc/pki/ca-trust/source/anchors/`

```shell
update-ca-trust force-enable 
update-ca-trust extract # (可能不需要) 
```

### 创建 TLS Secret

在与您的应用程序相同的命名空间中：

```shell
kubectl create secret tls traefiktest-cert --cert registry.nspos.nokia.local.crt --key registry.nspos.nokia.local.key -n nsp-k8s-deployer
```

### 安装 Harbor

```bash
helm install harbor center/harbor/harbor -n nsp-k8s-deployer --set externalURL=https://registry.nspos.nokia.local --set expose.tls.certSource=none --set chartmuseum.enabled=false --set clair.enabled=false --set trivy.enabled=false --set trivy.enabled=false --set notary.enabled=false  --set expose.ingress.hosts.core=registry.nspos.nokia.local --set persistence.persistentVolumeClaim.registry.size=10G --set harborAdminPassword=Harbor12235 
```

`ingress.hosts.core` 的设置可能不需要，需要验证。

### 应用 Ingress 路由

```yaml
# harbor-ingress.yml

kind: IngressRoute 
metadata: 
  name: harbor-ingressroute 
  namespace: nsp-k8s-deployer 

spec: 
  entryPoints: 
    - websecure 

  routes: 
  - match: Host(`registry.nspos.nokia.local`) 
    kind: Rule
    services: 
    - name: harbor-harbor-portal 
      port: 80 
  - match: Host(`registry.nspos.nokia.local`) && PathPrefix(`/api/`, `/service/`, `/v2/`, `/chartrepo/`, `/c/`) 
    kind: Rule 
    services: 
    - name: harbor-harbor-core 
      port: 80 
  tls: 
    certResolver: default 
    domains: 
    - main: 'registry.nspos.nokia.local' 
    secretName: traefik-cert 
```

参考：
1. https://github.com/goharbor/harbor-helm/issues/582
2. https://traefik.io/blog/install-and-configure-traefik-with-helm/

### 总结

最重要的一步是 Harbor 特定的 IngressRoute 设置。详细信息应来自 Harbor 和/或 harbor-helm 项目。

