tl;dr
docker run -v $PWD/lego:/.lego -it goacme/lego --email="your@email.com" --domains="*.morifuji-is.ninja" --dns manual -k rsa2048 run
概要
自前k8sに自前のドメインをぶら下げたく調べると、GKEのマネージド証明書が使えるらしいと聞いて喜んでいたら、どうにもワイルドカード証明書は無理らしい。しかも1Ingressに1マネージド証明書なので、 ingress1つで複数の証明書をぶら下げることはできないらしい。
ということで 自前で証明書を作ることにした。
Let’sEncryptの環境を用意するのがめんどくセーなーと思ってたら、 lego というものがあるらしい。
Dockerイメージも用意されているのでさくっと使ってみた。
参考
- https://cloud.google.com/kubernetes-engine/docs/how-to/ingress-multi-ssl?hl=ja
- https://go-acme.github.io/lego/
- https://github.com/go-acme/lego/blob/master/Dockerfile
1.起動確認
$ docker run -it goacme/lego help
NAME:
lego - Let's Encrypt client written in Go
USAGE:
lego [global options] command [command options] [arguments...]
VERSION:
v3.2.0
COMMANDS:
run Register an account, then create and install a certificate
revoke Revoke a certificate
renew Renew a certificate
dnshelp Shows additional help for the '--dns' global option
list Display certificates and accounts information.
help, h Shows a list of commands or help for one command
GLOBAL OPTIONS:
--domains value, -d value Add a domain to the process. Can be specified multiple times.
--server value, -s value CA hostname (and optionally :port). The server certificate must be trusted in order to avoid further modifications to the client. (default: "https://acme-v02.api.letsencrypt.org/directory")
--accept-tos, -a By setting this flag to true you indicate that you accept the current Let's Encrypt terms of service.
--email value, -m value Email used for registration and recovery contact.
--csr value, -c value Certificate signing request filename, if an external CSR is to be used.
--eab Use External Account Binding for account registration. Requires --kid and --hmac.
--kid value Key identifier from External CA. Used for External Account Binding.
--hmac value MAC key from External CA. Should be in Base64 URL Encoding without padding format. Used for External Account Binding.
--key-type value, -k value Key type to use for private keys. Supported: rsa2048, rsa4096, rsa8192, ec256, ec384. (default: "ec384")
--filename value (deprecated) Filename of the generated certificate.
--path value Directory to use for storing the data. (default: "/.lego")
--http Use the HTTP challenge to solve challenges. Can be mixed with other types of challenges.
--http.port value Set the port and interface to use for HTTP based challenges to listen on.Supported: interface:port or :port. (default: ":80")
--http.proxy-header value Validate against this HTTP header when solving HTTP based challenges behind a reverse proxy. (default: "Host")
--http.webroot value Set the webroot folder to use for HTTP based challenges to write directly in a file in .well-known/acme-challenge.
--http.memcached-host value Set the memcached host(s) to use for HTTP based challenges. Challenges will be written to all specified hosts.
--tls Use the TLS challenge to solve challenges. Can be mixed with other types of challenges.
--tls.port value Set the port and interface to use for TLS based challenges to listen on. Supported: interface:port or :port. (default: ":443")
--dns value Solve a DNS challenge using the specified provider. Can be mixed with other types of challenges. Run 'lego dnshelp' for help on usage.
--dns.disable-cp By setting this flag to true, disables the need to wait the propagation of the TXT record to all authoritative name servers.
--dns.resolvers value Set the resolvers to use for performing recursive DNS queries. Supported: host:port. The default is to use the system resolvers, or Google's DNS resolvers if the system's cannot be determined.
--http-timeout value Set the HTTP timeout value to a specific value in seconds. (default: 0)
--dns-timeout value Set the DNS timeout value to a specific value in seconds. Used only when performing authoritative name servers queries. (default: 10)
--pem Generate a .pem file by concatenating the .key and .crt files together.
--cert.timeout value Set the certificate timeout value to a specific value in seconds. Only used when obtaining certificates. (default: 30)
--help, -h show help
--version, -v print the version
2.証明書作成
複数あるチャレンジ方法のうち今回はDNS-01
を使います。 ec2とかだったらHTTP-01
を選んでnginxのコンテナ立てて終わらせるんですが、k8sにいちいちあげるのが面倒だと思ったので。
DNS-01
を使う場合、ドメインの管理にGoDaddyとか Route53とかを使っていた場合は、 コマンドにSECRET_KEYを渡すと自動でチャレンジをしてくれるみたいなんですが、 GoogleDomainは未対応でしたw
なので泥臭く --dns manual
で行なっています。また、 今回はワイルドカード証明書が欲しいので --domains="morifuji-is.ninja" --domains="*.morifuji-is.ninja"
を指定しました。
また、チャレンジ成功後、 証明書がコンテナないの /.lego
配下に出力されるので -v $PWD/lego:/.lego -it goacme/lego
を指定しています。
$ docker run -v $PWD/lego:/.lego -it goacme/lego --email="your@email.com" --domains="morifuji-is.ninja" --domains="*.morifuji-is.ninja" --dns manual run
2019/12/12 13:26:11 No key found for account info@morifuji-is.ninja. Generating a P384 key.
2019/12/12 13:26:11 Saved key to /.lego/accounts/acme-v02.api.letsencrypt.org/info@morifuji-is.ninja/keys/info@morifuji-is.ninja.key
2019/12/12 13:26:12 Please review the TOS at https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf
Do you accept the TOS? Y/n
Y
2019/12/12 13:26:16 [INFO] acme: Registering account for info@morifuji-is.ninja
!!!! HEADS UP !!!!
Your account credentials have been saved in your Let's Encrypt
configuration directory at "/.lego/accounts".
You should make a secure backup of this folder now. This
configuration directory will also contain certificates and
private keys obtained from Let's Encrypt so making regular
backups of this folder is ideal.2019/12/12 13:26:16 [INFO] [morifuji-is.ninja, *.morifuji-is.ninja] acme: Obtaining bundled SAN certificate
2019/12/12 13:26:17 [INFO] [*.morifuji-is.ninja] AuthURL: https://acme-v02.api.letsencrypt.org/acme/authz-v3/1690246363
2019/12/12 13:26:17 [INFO] [morifuji-is.ninja] AuthURL: https://acme-v02.api.letsencrypt.org/acme/authz-v3/1690246364
2019/12/12 13:26:17 [INFO] [*.morifuji-is.ninja] acme: use dns-01 solver
2019/12/12 13:26:17 [INFO] [morifuji-is.ninja] acme: Could not find solver for: tls-alpn-01
2019/12/12 13:26:17 [INFO] [morifuji-is.ninja] acme: Could not find solver for: http-01
2019/12/12 13:26:17 [INFO] [morifuji-is.ninja] acme: use dns-01 solver
2019/12/12 13:26:17 [INFO] [*.morifuji-is.ninja] acme: Preparing to solve DNS-01
lego: Please create the following TXT record in your morifuji-is.ninja. zone:
_acme-challenge.morifuji-is.ninja. 120 IN TXT "zWA4q-FFTRqrzaY_SkNw0p2rJ7iD08_CR6go63Kav-c"
lego: Press 'Enter' when you are done
2019/12/12 13:27:50 [INFO] [*.morifuji-is.ninja] acme: Trying to solve DNS-01
2019/12/12 13:27:50 [INFO] [*.morifuji-is.ninja] acme: Checking DNS record propagation using [192.168.65.1:53]
2019/12/12 13:27:50 [INFO] Wait for propagation [timeout: 1m0s, interval: 2s]
2019/12/12 13:27:52 [INFO] [*.morifuji-is.ninja] The server validated our request
2019/12/12 13:27:52 [INFO] [*.morifuji-is.ninja] acme: Cleaning DNS-01 challenge
lego: You can now remove this TXT record from your morifuji-is.ninja. zone:
_acme-challenge.morifuji-is.ninja. 120 IN TXT "..."
2019/12/12 13:27:52 [INFO] sequence: wait for 1m0s
2019/12/12 13:28:52 [INFO] [morifuji-is.ninja] acme: Preparing to solve DNS-01
lego: Please create the following TXT record in your morifuji-is.ninja. zone:
_acme-challenge.morifuji-is.ninja. 120 IN TXT "uxRURNmRMQMpmK4nlerPXPA6cVrpaw3rXWDk0ctIor0"
lego: Press 'Enter' when you are done
2019/12/12 13:30:12 [INFO] [morifuji-is.ninja] acme: Trying to solve DNS-01
2019/12/12 13:30:12 [INFO] [morifuji-is.ninja] acme: Checking DNS record propagation using [192.168.65.1:53]
2019/12/12 13:30:12 [INFO] Wait for propagation [timeout: 1m0s, interval: 2s]
2019/12/12 13:30:17 [INFO] [morifuji-is.ninja] The server validated our request
2019/12/12 13:30:17 [INFO] [morifuji-is.ninja] acme: Cleaning DNS-01 challenge
lego: You can now remove this TXT record from your morifuji-is.ninja. zone:
_acme-challenge.morifuji-is.ninja. 120 IN TXT "..."
2019/12/12 13:30:17 [INFO] [morifuji-is.ninja, *.morifuji-is.ninja] acme: Validations succeeded; requesting certificates
2019/12/12 13:30:18 [INFO] [morifuji-is.ninja] Server responded with a certificate.
manualの場合、コマンド実行して表示されるvalueを、自分でTXTレコードを作成して反映されてからEnterを押して手動で検証を始める必要があります。僕の場合は ゲームしながらだらだら dig _acme-challenge.morifuji-is.ninja TXT
を打ちました。
今回は2種類のドメインなので、それを2回やります。あとは./lego/certificates/lego/certificates/morifuji-is.ninja.crt
と ./lego/certificates/lego/certificates/morifuji-is.ninja.key
を好きに調理して下さい。僕はingressに紐付けます。
3.リソース作成&ingressに紐付け
$ kubectl create secret tls all-cert --cert ./morifuji-is.ninja.crt --key ./morifuji-is.ninja.key -o yaml > all-cert.yaml
# リソース確認
$ k get secret
NAME TYPE DATA AGE
all-cert kubernetes.io/tls 2 26m
ingressに紐付けます
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: k8slab-ingress
spec:
tls:
- secretName: all-cert # この部分を追記
rules:
- http:
paths:
- path: /handler
backend:
serviceName: k8slab-service
servicePort: 80
- host: aaaaaa.morifuji-is.ninja
http:
paths:
- path: "/*"
backend:
serviceName: nextcloud-service
servicePort: 80
- host: bbbbbb.morifuji-is.ninja
http:
paths:
- path: "/*"
backend:
serviceName: blog-service
servicePort: 80
backend:
serviceName: k8slab-service
servicePort: 80
あとは待つだけ。
4.ECDSA非対応&RSA4096非対応
Warning Sync 6m10s (x24 over 45m) loadbalancer-controller Error during sync: error running load balancer syncing routine: loadbalancer default-k8slab-ingress--c82b4489f3148701 does not exist: Cert creation failures - k8s-ssl-03778049d335f6d5-7832ce86f8261bed--c82b4489f3148701 Error:googleapi: Error 400: The ECDSA curve is not supported., sslCertificateUnsupportedCurve
The ECDSA curve is not supported.
嘘やろ、、、泣く泣くECDSAからRSA4096に変更した。
$ docker run -v $PWD/lego:/.lego -it goacme/lego --email="your@email.com" --domains="morifuji-is.ninja" --domains="*.morifuji-is.ninja" --dns manual -k rsa4096 run
今度こそ,,
Warning Sync 8s loadbalancer-controller Error during sync: error running load balancer syncing routine: loadbalancer default-k8slab-ingress--c82b4489f3148701 does not exist: Cert creation failures - k8s-ssl-03778049d335f6d5-40b15ffdb67098e2--c82b4489f3148701 Error:googleapi: Error 400: The SSL key size is unsupported. The loadbalancer supports RSA-2048 and ECDSA P-256 certificates., sslCertificateUnsupportedKeySize
The SSL key size is unsupported. The loadbalancer supports RSA-2048 and ECDSA P-256 certificates.
クソやんけ!!!!泣く泣くRSA4096からRSA2048に変更した。
$ docker run -v $PWD/lego:/.lego -it goacme/lego --email="your@email.com" --domains="morifuji-is.ninja" --domains="*.morifuji-is.ninja" --dns manual -k rsa2048 run