Jul 26, 2020
Jul 27, 2020
N/A Views
MD
warning
この記事は2年以上前に更新されたものです。情報が古くなっている可能性があります。

Let's Encryptの証明書生成およびSecretの作成をcert-managerで行い、Spring Bootアプリに設定するメモです。
Azure DNSでDNS Challengeを使います。

目次

cert-managerのインストール

https://cert-manager.io/docs/installation/kubernetes の通りインストールします。

kubectl apply -f https://github.com/jetstack/cert-manager/releases/download/v0.16.0/cert-manager.yaml

Podを確認。

$ kubectl get pods -n cert-manager
NAME                                       READY   STATUS    RESTARTS   AGE
cert-manager-cainjector-6d444776dd-f7wxx   1/1     Running   0          2m58s
cert-manager-fbd8f9986-wbsmw               1/1     Running   0          2m58s
cert-manager-webhook-86689cb4c9-4tnwm      1/1     Running   0          2m58s

Azure CLIでService Principalを作成

https://cert-manager.io/docs/configuration/acme/dns01/azuredns の通り作成します。

Resource Group maki-lolとDNS Zone maki.lol は用意済み。

image

az login

でブラウザ経由でログイン。

AZURE_CERT_MANAGER_NEW_SP_NAME=cert-manager
AZURE_DNS_ZONE_RESOURCE_GROUP=maki-lol
AZURE_DNS_ZONE=maki.lol
DNS_SP=$(az ad sp create-for-rbac --name ${AZURE_CERT_MANAGER_NEW_SP_NAME})
AZURE_CERT_MANAGER_SP_APP_ID=$(echo ${DNS_SP} | jq -r '.appId')
AZURE_CERT_MANAGER_SP_PASSWORD=$(echo ${DNS_SP} | jq -r '.password')
AZURE_TENANT_ID=$(echo ${DNS_SP} | jq -r '.tenant')
AZURE_SUBSCRIPTION_ID=$(az account show | jq -r '.id')

Service PrincipalにはDNS Zone Contributor Roleのみ付けます。

az role assignment delete --assignee ${AZURE_CERT_MANAGER_SP_APP_ID} --role Contributor
DNS_ID=$(az network dns zone show --name ${AZURE_DNS_ZONE} --resource-group ${AZURE_DNS_ZONE_RESOURCE_GROUP} --query "id" --output tsv)
az role assignment create --assignee ${AZURE_CERT_MANAGER_SP_APP_ID} --role "DNS Zone Contributor" --scope ${DNS_ID}

Let's EncryptのIssuer作成

Let's EncryptのIssuerリソースを作ります。NamespaceレベルのIssuerとClusterレベルのClusterIssuerがありますが、
今回はClusterIssuerリソースを作成します。

Service PrincipalのClient Secret保存するSecretを作成します。

cat <<EOF > azuredns-config.yml
kind: Secret
apiVersion: v1
metadata:
  name: azuredns-config
  namespace: cert-manager
stringData:
  client-secret: ${AZURE_CERT_MANAGER_SP_PASSWORD}
EOF

Azure DNSを使ったClusterIssuerを作成します。

cat <<EOF > letsencrypt-cluster-issuer.yml
apiVersion: cert-manager.io/v1alpha2
kind: ClusterIssuer
metadata:
  name: letsencrypt
spec:
  acme:
    server: https://acme-v02.api.letsencrypt.org/directory
    email: makingx+cert-manager@gmail.com
    privateKeySecretRef:
      name: letsencrypt
    solvers:
    - dns01:
        azuredns:
          clientID: ${AZURE_CERT_MANAGER_SP_APP_ID}
          clientSecretSecretRef:
            name: azuredns-config
            key: client-secret
          subscriptionID: ${AZURE_SUBSCRIPTION_ID}
          tenantID: ${AZURE_TENANT_ID}
          resourceGroupName: ${AZURE_DNS_ZONE_RESOURCE_GROUP}
          hostedZoneName: ${AZURE_DNS_ZONE}
          environment: AzurePublicCloud
EOF

kubectl applyでこれらを適用します。

kubectl apply -f azuredns-config.yml -f letsencrypt-cluster-issuer.yml

ClusterIssuerリソースが作成され、READYであることを確認します。

$ kubectl get clusterissuer             
NAME          READY   AGE
letsencrypt   True    15s

Certificateの作成

次のこのIssuerからCertificateリソースを作成します。

*.demo.maki.loldemo.maki.lolに対する証明書を発行します。

cat <<EOF > demo-maki-lol.yml
apiVersion: cert-manager.io/v1alpha2
kind: Certificate
metadata:
  name: demo-maki-lol
  namespace: default
spec:
  secretName: demo-maki-lol-tls
  issuerRef:
    name: letsencrypt
    kind: ClusterIssuer
  dnsNames:
  - '*.demo.maki.lol'
  - demo.maki.lol
EOF

kubectl applyでこれらを適用します。

kubectl apply -f demo-maki-lol.yml

2~3分経つとCertificateリソースがREADYになります。

$ kubectl get certificate -n default     
NAME            READY   SECRET              AGE
demo-maki-lol   True    demo-maki-lol-tls   2m29s

TLSのSecretも作成されます。

$ kubectl get secret -n default   
NAME                  TYPE                                  DATA   AGE
...
demo-maki-lol-tls     kubernetes.io/tls                     2      7m6s
...

TLS証明書の中身を見てみます。

$ kubectl get secret demo-maki-lol-tls -o go-template='{{index .data "tls.crt" | base64decode}}' | openssl x509 -noout -text
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            03:1f:52:6c:2a:21:51:fa:07:37:2c:37:02:90:34:24:a0:a2
    Signature Algorithm: sha256WithRSAEncryption
        Issuer: C=US, O=Let's Encrypt, CN=Let's Encrypt Authority X3
        Validity
            Not Before: Jul 26 03:02:03 2020 GMT
            Not After : Oct 24 03:02:03 2020 GMT
        Subject: CN=*.demo.maki.lol
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    00:ab:c8:4f:a6:cf:92:12:1e:10:2e:6c:50:20:8d:
                    97:3e:ae:45:e5:37:5d:20:eb:36:88:36:53:01:ff:
                    cb:98:61:da:02:37:a2:70:b6:c6:3c:16:42:8d:02:
                    16:71:94:77:70:b3:6d:07:c0:8c:37:29:ad:e9:51:
                    37:eb:5c:4b:9d:33:fd:d1:e5:7c:f1:8f:35:5d:18:
                    b0:23:45:ee:37:ab:58:8f:ca:f9:41:e0:f4:d6:c6:
                    d1:00:f4:a7:92:13:3e:f0:8c:0b:c8:2e:15:33:37:
                    04:7c:26:e8:44:b6:9f:10:4f:c2:57:a0:fb:05:a3:
                    c7:a7:94:7b:2b:78:fc:15:71:08:91:1e:04:ce:7c:
                    46:82:82:09:94:e9:30:98:62:7b:d3:d7:67:d1:4a:
                    5b:89:b2:81:bf:70:44:db:8c:4c:e0:d3:41:38:1b:
                    8f:24:c9:b2:54:18:2d:b3:a6:64:52:45:7e:42:d3:
                    d6:7f:35:3f:eb:04:4a:dd:0b:62:c5:ba:d0:9d:8a:
                    ff:3c:6c:a2:7e:3a:2f:9b:c1:a6:92:95:67:64:8e:
                    d1:46:da:2d:19:ac:d9:16:dc:4f:fb:c7:6a:a6:d7:
                    4c:3f:7f:0f:cc:ed:6a:55:77:e8:29:95:8b:3e:83:
                    90:e0:77:0f:69:53:4b:60:87:09:e9:5e:34:7b:bd:
                    f1:0d
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Key Usage: critical
                Digital Signature, Key Encipherment
            X509v3 Extended Key Usage: 
                TLS Web Server Authentication, TLS Web Client Authentication
            X509v3 Basic Constraints: critical
                CA:FALSE
            X509v3 Subject Key Identifier: 
                21:E0:6A:FF:D0:43:73:09:CF:64:40:E0:7F:26:1B:C8:7A:BB:65:27
            X509v3 Authority Key Identifier: 
                keyid:A8:4A:6A:63:04:7D:DD:BA:E6:D1:39:B7:A6:45:65:EF:F3:A8:EC:A1

            Authority Information Access: 
                OCSP - URI:http://ocsp.int-x3.letsencrypt.org
                CA Issuers - URI:http://cert.int-x3.letsencrypt.org/

            X509v3 Subject Alternative Name: 
                DNS:*.demo.maki.lol, DNS:demo.maki.lol
            X509v3 Certificate Policies: 
                Policy: 2.23.140.1.2.1
                Policy: 1.3.6.1.4.1.44947.1.1.1
                  CPS: http://cps.letsencrypt.org

            1.3.6.1.4.1.11129.2.4.2: 
                ......v.^.s..V...6H}.I.2z.........u..qEX...s.H.......G0E.!...
.F.[>.K.(.....)[...9=.o....{ . =v..f...t>....i!.L..|..sV....w...u......... N.f.+..% gk..p..IS-...^...s.H.......F0D. o..T.~%..|U,E$.....J=$l.......... *....h.8"i.j/.U......s.i.."?..<.
    Signature Algorithm: sha256WithRSAEncryption
         5c:a0:d7:58:4d:ff:63:bc:6d:d7:71:1f:49:6b:e7:ae:e9:8a:
         00:e0:dc:b3:77:e1:7c:93:46:f7:29:fd:14:04:45:99:f9:d0:
         0b:de:e0:8d:43:65:db:76:6e:22:ef:e6:ea:71:5f:e0:44:1d:
         0d:b4:27:f1:8e:84:5b:24:e7:e3:9c:78:46:2e:6a:de:59:a6:
         72:fc:02:2b:81:05:d6:eb:a7:08:69:62:81:91:dd:f3:79:92:
         35:3a:51:0f:70:8e:80:53:0c:32:f1:24:a9:b7:9d:d1:e0:c4:
         82:b1:0f:aa:71:19:1b:26:48:ee:a0:3d:1a:06:f2:d9:5e:bb:
         67:70:71:99:72:24:ca:08:e9:b5:4f:e6:ac:98:c7:20:05:e6:
         3b:d8:d9:0a:64:31:e4:47:93:be:ac:69:b2:36:d1:ec:ac:96:
         81:5e:2f:63:73:66:5b:b9:bf:93:16:d5:2f:a5:31:e7:58:22:
         55:b1:58:28:8a:54:c1:86:31:7d:58:11:c0:b6:37:7b:23:9e:
         e6:fe:31:84:bc:02:d3:65:ca:c2:74:4e:d2:21:ab:34:d0:2d:
         60:7a:18:7b:1b:02:e6:f1:27:fa:cd:5d:eb:09:d3:5e:25:91:
         af:99:a7:f4:1f:1f:98:e3:80:37:4e:c0:27:f4:c4:66:a9:f7:
         94:57:49:81

IssuerがLet's Encryptで、Subject Alternative NameがDNS:*.demo.maki.lol, DNS:demo.maki.lolになっています。

発行したTLS証明書をSpring Bootアプリに設定

https://blog.ik.am/entries/488 の記事のようにPEM形式をJKS形式に変換し、Spring BootアプリをTLS対応させます。

cat <<'EOF' > hello-cnb.yml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello-cnb
spec:
  replicas: 1
  selector:
    matchLabels:
      app: hello-cnb
  template:
    metadata:
      labels:
        app: hello-cnb
    spec:
      initContainers:
      - image: openjdk:11-jdk-slim
        name: pem-to-keystore
        volumeMounts:
        - name: keystore-volume
          mountPath: /keystores
        - name: demo-maki-lol-tls
          mountPath: /demo-maki-lol-tls
        env:
        - name: SERVER_SSL_KEY_PASSWORD
          valueFrom:
            secretKeyRef:
              name: hello-cnb
              key: server.ssl.key-password
        command:          
        - sh
        - -ce
        - |
          openssl pkcs12 -export \
                  -name hello-cnb \
                  -in /demo-maki-lol-tls/tls.crt \
                  -inkey /demo-maki-lol-tls/tls.key \
                  -out /keystores/hello-cnb.p12 \
                  -password pass:foobar
          keytool -importkeystore \
                  -destkeystore /keystores/hello-cnb.jks \
                  -srckeystore /keystores/hello-cnb.p12 \
                  -deststoretype pkcs12 \
                  -srcstoretype pkcs12 \
                  -alias hello-cnb \
                  -deststorepass ${SERVER_SSL_KEY_PASSWORD} \
                  -destkeypass ${SERVER_SSL_KEY_PASSWORD} \
                  -srcstorepass foobar \
                  -srckeypass foobar \
                  -noprompt
      containers:
      - image: making/hello-cnb:latest
        name: hello-cnb
        ports:
        - containerPort: 8443
        volumeMounts:
        - name: keystore-volume
          mountPath: /keystores
          readOnly: true
        env:
        - name: INFO_MESSAGE
          value: Hello World!
        - name: JAVA_OPTS
          value: "-XX:ReservedCodeCacheSize=32M -Xss512k"
        - name: BPL_JVM_THREAD_COUNT
          value: "20"
        - name: BPL_JVM_HEAD_ROOM
          value: "5"
        - name: SERVER_PORT
          value: "8443"
        - name: SERVER_SSL_ENABLED
          value: "true"
        - name: SERVER_SSL_PROTOCOL
          value: TLSv1.2
        - name: SERVER_SSL_KEY_STORE
          value: file:///keystores/hello-cnb.jks
        - name: SERVER_SSL_KEY_STORE_TYPE
          value: PKCS12
        - name: SERVER_SSL_KEY_ALIAS
          value: hello-cnb
        - name: SERVER_SSL_KEY_PASSWORD
          valueFrom:
            secretKeyRef:
              name: hello-cnb
              key: server.ssl.key-password
        - name: SERVER_SSL_KEY_STORE_PASSWORD
          valueFrom:
            secretKeyRef:
              name: hello-cnb
              key: server.ssl.key-password
        - name: SERVER_HTTP2_ENABLED
          value: "true"
        resources:
          limits:
            memory: "256Mi"
          requests:
            memory: "256Mi"
        readinessProbe:
          httpGet:
            path: /actuator/health/readiness
            port: 8443
            scheme: HTTPS
          initialDelaySeconds: 10
          timeoutSeconds: 3
          failureThreshold: 3
          periodSeconds: 5
        livenessProbe:
          httpGet:
            path: /actuator/health/liveness
            port: 8443
            scheme: HTTPS
          initialDelaySeconds: 20
          timeoutSeconds: 1
          periodSeconds: 10
          failureThreshold: 1
      volumes:
      - name: keystore-volume
        emptyDir: {}
      - name: demo-maki-lol-tls
        secret:
          secretName: demo-maki-lol-tls
---
kind: Service
apiVersion: v1
metadata:
  name: hello-cnb
spec:
  type: LoadBalancer
  selector:
    app: hello-cnb
  ports:
  - protocol: TCP
    port: 443
    targetPort: 8443
EOF

kubectl applyでこれらを適用します。

kubectl create secret generic hello-cnb \
  --dry-run -o yaml \
  --from-literal server.ssl.key-password=thisisasecret \
  > hello-cnb-secret.yml

kubectl apply -f hello-cnb.yml -f hello-cnb-secret.yml 

/etc/hosts

<hello-cnb ServiceのExternal IP> hello-cnb.demo.maki.lol

を追加して、 https://hello-cnb.demo.maki.lol/actuator/info にアクセス。

image

Found a mistake? Update the entry.
Share this article: