SUPER-G.EEK.JP

twitter: @hum_op_dev
github: ophum

[k8s] cert-managerで管理している証明書を外部マシンで利用する

目次

k8s の cert-manager で管理している証明書を k8s 外の マシン(WSL2) で利用してみました。

構成

Docker Desktop で稼働している k8s に cert-manager をインストールし自己署名証明書を作成します。
WSL2 状に nginx をインストールしその自己署名証明書で HTTPS で Listen させます。

ophum/k8s-secret-fs

cert-manager で管理している証明書を、k8s 外の VM で利用するためには「secret から証明書のデータを取得しコピーする」という方法が考えられます。
しかし以下のような課題があります。

そこで、secret のデータをファイルとしてマウントできるophum/k8s-secret-fsを実装しました。

使ってみる

cert-manager のインストール

kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.9.1/cert-manager.yaml

cert-manager Kubectl apply

自己署名証明書

CA の作成

 1apiVersion: cert-manager.io/v1
 2kind: ClusterIssuer
 3metadata:
 4  name: selfsigned-issuer
 5spec:
 6  selfSigned: {}
 7---
 8apiVersion: cert-manager.io/v1
 9kind: Certificate
10metadata:
11  name: my-selfsigned-ca
12spec:
13  isCA: true
14  commonName: my-selfsigned-ca
15  secretName: root-secret
16  privateKey:
17    algorithm: ECDSA
18    size: 256
19  issuerRef:
20    name: selfsigned-issuer
21    kind: ClusterIssuer
22    group: cert-manager.io
23---
24apiVersion: cert-manager.io/v1
25kind: Issuer
26metadata:
27  name: my-ca-issuer
28spec:
29  ca:
30    secretName: root-secret

cert-manager SelfSigned

自己署名証明書発行

 1apiVersion: cert-manager.io/v1
 2kind: Certificate
 3metadata:
 4  name: selfsigned.example.com
 5spec:
 6  subject:
 7    organizations:
 8      - MyOrg
 9    countries:
10      - Japan
11    organizationalUnits:
12      - MyUnit
13    localities:
14      - Osaka
15    provinces:
16      - Osaka
17  commonName: selfsigned.example.com
18  duration: 8760h
19  dnsNames:
20    - selfsigned.example.com
21  secretName: selfsigned.example.com
22  issuerRef:
23    name: my-ca-issuer
24    kind: Issuer
25    group: cert-manager.io
26  privateKey:
27    algorithm: RSA
28    size: 2048

selfsigned.example.com という名前で作成します。

apply すると以下のように証明書が作成され READY が True になります。

1hum@ryzen5pc:~/cert$ kubectl get cert
2NAME                     READY   SECRET                   AGE
3my-selfsigned-ca         True    root-secret              117s
4selfsigned.example.com   True    selfsigned.example.com   2s

ついでに hosts に登録しておきます

1echo "127.0.0.1 selfsigned.example.com" | sudo tee -a /etc/hosts

k8s-secret-fs を起動する

k8s-secret-fs のバイナリをダウンロードします。

1wget https://github.com/ophum/k8s-secret-fs/releases/download/v0.2.0/k8s-secret-fs_0.2.0_linux_amd64.tar.gz -O - | tar xvz

設定ファイルを作成します。

1cat <<EOF > config.yaml
2kubeconfig: ${HOME}/.kube/config
3namespace: default
4secretName: selfsigned.example.com
5mountPoint: /mnt/k8s-secret-fs/
6EOF

マウントポイントを作成します。

1sudo mkdir -p /mnt/k8s-secret-fs

起動します。

1sudo ./k8s-secret-fs -config config.yaml &

マウントポイントを ls で見てみると以下のように証明書ファイルが出来ていることが分かります。

1sudo ls /mnt/k8s-secret-fs
2ca.crt  tls.crt  tls.key

nginx で利用してみる

WSL2 上にマウントできたので、このファイルを nginx で利用してみます。

まずは nginx をインストールします。

1sudo apt install nginx

設定ファイルを作成します。

 1cat <<EOF | sudo tee /etc/nginx/sites-available/ssl.conf
 2server {
 3        listen 443 ssl default_server;
 4        listen [::]:443 ssl default_server;
 5
 6        server_name selfsigned.example.com;
 7        root /var/www/html;
 8        index index.html index.htm index.nginx-debian.html;
 9
10        ssl_certificate /mnt/k8s-secret-fs/tls.crt;
11        ssl_certificate_key /mnt/k8s-secret-fs/tls.key;
12
13        location / {
14                try_files  $uri $uri/ =404;
15        }
16}
17EOF
18sudo ln -s /etc/nginx/sites-available/ssl.conf /etc/nginx/sites-enabled/ssl.conf

nginx を起動します。(WSL2 では systemd が動作していないため直接起動)

1sudo nginx

curl してみる

https://selfsigned.example.comに ca ファイルを指定して curl してみます。

 1 sudo curl https://selfsigned.example.com/ -v --cacert /mnt/k8s-secret-fs/ca.crt
 2*   Trying 127.0.0.1:443...
 3* TCP_NODELAY set
 4* Connected to selfsigned.example.com (127.0.0.1) port 443 (#0)
 5* ALPN, offering h2
 6* ALPN, offering http/1.1
 7* successfully set certificate verify locations:
 8*   CAfile: /mnt/k8s-secret-fs/ca.crt
 9  CApath: /etc/ssl/certs
10* TLSv1.3 (OUT), TLS handshake, Client hello (1):
11* TLSv1.3 (IN), TLS handshake, Server hello (2):
12* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
13* TLSv1.3 (IN), TLS handshake, Certificate (11):
14* TLSv1.3 (IN), TLS handshake, CERT verify (15):
15* TLSv1.3 (IN), TLS handshake, Finished (20):
16* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
17* TLSv1.3 (OUT), TLS handshake, Finished (20):
18* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
19* ALPN, server accepted to use http/1.1
20* Server certificate:
21*  subject: C=Japan; ST=Osaka; L=Osaka; O=MyOrg; OU=MyUnit; CN=selfsigned.example.com
22*  start date: Aug  6 19:52:08 2022 GMT
23*  expire date: Aug  6 19:52:08 2023 GMT
24*  subjectAltName: host "selfsigned.example.com" matched cert's "selfsigned.example.com"
25*  issuer: CN=my-selfsigned-ca
26*  SSL certificate verify ok.
27> GET / HTTP/1.1
28> Host: selfsigned.example.com
29> User-Agent: curl/7.68.0
30> Accept: */*
31>
32* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
33* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
34* old SSL session ID is stale, removing
35* Mark bundle as not supporting multiuse
36< HTTP/1.1 200 OK
37< Server: nginx/1.18.0 (Ubuntu)
38< Date: Sat, 06 Aug 2022 20:31:58 GMT
39< Content-Type: text/html
40< Content-Length: 612
41< Last-Modified: Sat, 06 Aug 2022 20:25:14 GMT
42< Connection: keep-alive
43< ETag: "62eece2a-264"
44< Accept-Ranges: bytes
45<
46<!DOCTYPE html>
47<html>
48<head>
49<title>Welcome to nginx!</title>
50<style>
51    body {
52        width: 35em;
53        margin: 0 auto;
54        font-family: Tahoma, Verdana, Arial, sans-serif;
55    }
56</style>
57</head>
58<body>
59<h1>Welcome to nginx!</h1>
60<p>If you see this page, the nginx web server is successfully installed and
61working. Further configuration is required.</p>
62
63<p>For online documentation and support please refer to
64<a href="http://nginx.org/">nginx.org</a>.<br/>
65Commercial support is available at
66<a href="http://nginx.com/">nginx.com</a>.</p>
67
68<p><em>Thank you for using nginx.</em></p>
69</body>
70</html>
71* Connection #0 to host selfsigned.example.com left intact

Windows 側の hosts にも selfsigned.example.com を登録することでブラウザでも証明書が反映されていることが確認できました。

さいごに

k8s-secret-fs を利用して cert-manager で作成した証明書を k8s 外のマシンで使うことができました。
これにより以下の課題を解決できました。

証明書更新時は、証明書を利用しているソフトウェアの再起動(or 設定の再読み込み)で対応することができます。

また、証明書を cert-manager で一元管理できるというメリットが大きいと思います。

Tags: