---
# System prepended metadata

title: 自簽 Root-CA 提供給 Cert-manager 再去簽發服務 server certificate
tags: [工具]

---

# 自簽 Root-CA 提供給 Cert-manager 再去簽發服務 server certificate


## 環境準備

### 1. 本次範例服務對外使用 istio
```
$ kubectl -n istio-system get pod
NAME                                    READY   STATUS    RESTARTS   AGE
istio-cni-node-5kmfh                    1/1     Running   0          18h
istio-cni-node-975fn                    1/1     Running   0          18h
istio-cni-node-9jqsq                    1/1     Running   0          18h
istio-cni-node-9n8s6                    1/1     Running   0          18h
istio-cni-node-d5d4z                    1/1     Running   0          18h
istio-ingressgateway-5b6548c6d6-n6x64   1/1     Running   0          18h
istiod-d498fb64c-d9w5x                  1/1     Running   0          18h
jaeger-76444674f-s2nqj                  1/1     Running   0          18h
kiali-6d774d8bb8-6n6zj                  1/1     Running   0          18h
ztunnel-dc56s                           1/1     Running   0          18h
ztunnel-f4t5s                           1/1     Running   0          18h
ztunnel-mfxxn                           1/1     Running   0          18h
ztunnel-vrbs2                           1/1     Running   0          18h
ztunnel-w4xkp                           1/1     Running   0          18h
```
### 2. 部署 nignix 範例

* 在 demo namespace 設定 `istio.io/dataplane-mode=ambient` label
```
$ kubectl create ns demo

$ kubectl label namespace demo istio.io/dataplane-mode=ambient
```
* 建立 Nginx deployment
```
$ kubectl -n demo create deploy web --image=nginx --port=80

$ kubectl -n demo expose deploy web --name=svc-web --target-port=80 --port=80
```

## 建立 Root-CA 自簽憑證
```
$ git clone https://github.com/cooloo9871/SelfSigned-RootCA.git;cd SelfSigned-RootCA/

# ip 為 istio ingressgateway svc ip
$ ./mk create nginx.k8sexample.com 10.10.7.87

# 需要有 dns server 做名稱解析
$ host nginx.k8sexample.com
nginx.k8sexample.com has address 10.10.7.87
```

* 建立 `root-ca-secret` secret，在 `cert-manager` namespace 上產生，提供給 cert-manager 使用

```
$ kubectl create secret tls my-root-ca-secret \
  --cert=ca.pem \
  --key=ca-key-decrypted.pem \
  -n cert-manager
```

## 設定 cert-manager 建立 ClusterIssuer
* 將自簽的 `root-ca-secret` 提供給 cert-manager 做出 `ClusterIssuer`
```
$ nano cert.yaml
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: root-ca-clusterissuer
spec:
  ca:
    secretName: my-root-ca-secret
```

* 部署以及檢查資源
```
$ kubectl apply -f cert.yaml

$ kubectl get ClusterIssuer
NAME                     READY   AGE
root-ca-clusterissuer    True    25s
```

## 建立 HTTPS 憑證
* 使用 `root-ca-clusterissuer` 這個 ClusterIssuer 來簽發憑證，憑證簽發後會把 公鑰和私鑰放在 `nginx-cert-tls` secret。
* `dnsNames:` 就是 憑證的 主體名稱（SANs），也是服務對外的 domain，也需要將名稱解析到 istio ingressgateway 的 svc ip。

```
$ nano nginx-cert.yaml
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: nginx-cert
  namespace: istio-system
spec:
  duration: 8760h             # 1 year
  renewBefore: 720h           # 30d
  secretName: nginx-cert-tls
  dnsNames:
    - nginx.k8sexample.com
  issuerRef:
    name: root-ca-clusterissuer
    kind: ClusterIssuer

$ kubectl apply -f nginx-cert.yaml

$ kubectl -n istio-system get Certificate nginx-cert
NAME         READY   SECRET           AGE
nginx-cert   True    nginx-cert-tls   4s

$ kubectl -n istio-system get secret nginx-cert-tls
NAME             TYPE                DATA   AGE
nginx-cert-tls   kubernetes.io/tls   3      16s
```

## 建立 Istio Gateway 與 VirtualService


* 設定 Istio 的流量路由，目標是讓外部流量透過 HTTPS 進入 Istio Ingress Gateway，然後轉發到內部 Nginx Service。
```
$ nano istio.yaml
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
  name: nginx-gateway
  namespace: istio-system
spec:
  selector:
    istio: ingressgateway
  servers:
  - port:
      number: 443
      name: https
      protocol: HTTPS
    tls:
      mode: SIMPLE
      credentialName: nginx-cert-tls  # 對應憑證 Secret
    hosts:
    - nginx.k8sexample.com
---
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: nginx-vs
  namespace: demo
spec:
  hosts:
  - nginx.k8sexample.com
  gateways:
  - istio-system/nginx-gateway
  http:
  - route:
    - destination:
        host: svc-web.demo.svc.cluster.local
        port:
          number: 80
```

* 部署以及檢查資源
```
$ kubectl apply -f istio.yaml

$ kubectl -n istio-system get gateway.networking
NAME             AGE
nginx-gateway    21s

$ kubectl -n demo get virtualservice
NAME       GATEWAYS                         HOSTS                      AGE
nginx-vs   ["istio-system/nginx-gateway"]   ["nginx.k8sexample.com"]   45s
```

## 將 ca.pem 匯入到每一個 client 上


* 以下為 ubuntu 24.04 匯入自簽憑證設定
```
$ sudo cp ca.pem /usr/local/share/ca-certificates/ca.crt

$ sudo update-ca-certificates
```

* 就可以直接訪問 https
```
$ curl https://nginx.k8sexample.com
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
```
## 檢查憑證 issuer 與到期時間
```
$ sudo openssl x509 -in /usr/local/share/ca-certificates/ca.crt -noout -subject -issuer -dates
subject=C = TW, ST = Taipei, L = Taipei, O = test, OU = lab, CN = example
issuer=C = TW, ST = Taipei, L = Taipei, O = test, OU = lab, CN = example
notBefore=Aug 27 01:56:39 2025 GMT
notAfter=Aug 27 01:56:39 2026 GMT
```