Automatic Certificate Management Environment (ACME) は、X.509 証明書の発行を自動化するためのプロトコルです。ACME プロトコルを使用すると、認証局 (CA) は証明書の申請者がドメインを所有していることを自動的に検証し、申請者に証明書を発行します。Let's Encrypt は、ACME プロトコルを使用して、ほとんどのブラウザで信頼されている証明書を発行する非営利の公開 CA です。このトピックでは、cert-manager と Let's Encrypt を併用して、Service Mesh (ASM) イングレスゲートウェイのブラウザ信頼 HTTPS 証明書を発行する方法について説明します。
前提条件
Kubernetes 用 Container Service (ACK) クラスタが、V1.16 以降の ASM インスタンスに追加されています。詳細については、「ASM インスタンスへのクラスタの追加」および「ASM インスタンスの更新」をご参照ください。
イングレスゲートウェイがデプロイされ、ポート 80 と 443 が公開されています。詳細については、「イングレスゲートウェイの作成」をご参照ください。
HTTPBin アプリケーションが、ASM インスタンスに追加された ACK クラスタにデプロイされています。詳細については、「HTTPBin アプリケーションのデプロイ」をご参照ください。
cert-manager がインストールされています。詳細については、「クラスタへの cert-manager のインストール」をご参照ください。
ASM イングレスゲートウェイに対して Ingress API アクセスが有効になっています。詳細については、「手順 1:ASM ゲートウェイで Ingress を有効にする」をご参照ください。
cert-manager の ACME
cert-manager を使用すると、ACME Issuer は ACME プロトコルをサポートする CA サーバーにアカウントを登録します。ACME Issuer リソースを作成すると、cert-manager は秘密鍵を生成します。この秘密鍵は、ACME CA サーバーとの安全な通信に使用されます。Let's Encrypt などの公開 CA によって発行された証明書は、通常、クライアントの Web ブラウザで信頼されています。これは、ユーザーがブラウザを介して Web サイトにアクセスすると、ブラウザが Web サイトの Secure Sockets Layer (SSL) および Transport Layer Security (TLS) 証明書を自動的に信頼することを意味します。公開 CA によって発行された証明書の主な目的は、現在のサーバーがドメインの正当なサービスプロバイダーであることをブラウザに証明することです。このため、公開 CA は、証明書を申請するサーバーが実際にドメインを所有していることを検証してから、証明書を発行する必要があります。ACME プロトコルの詳細については、「Automatic Certificate Management Environment」をご参照ください。
チャレンジの解決
チャレンジは、証明書の申請者が証明書のドメインを所有していることを検証するために ACME プロトコルで使用される重要なメカニズムです。証明書の申請プロセスでは、ACME CA サーバーは、クライアント (証明書の申請者) が特定のチャレンジを完了して、ドメインの正当な所有者のみが対応する証明書を正常に申請できるようにすることを要求します。これにより、ネットワークセキュリティが向上し、ドメインのなりすましのリスクが防止されます。 cert-manager は、次の主要なチャレンジタイプをサポートしています。HTTP-01 チャレンジと DNS-01 チャレンジ。
HTTP-01 チャレンジは、計算されたキーを提示することで完了します。キーは HTTP URL エンドポイントに存在し、インターネット経由でルーティング可能です。この URL は、証明書に要求されたドメインを使用します。ACME サーバーがこのキーをインターネット経由でこの URL から取得できるようになると、ACME サーバーは申請者がこのドメインの所有者であることを検証できます。HTTP-01 チャレンジが作成されると、cert-manager は、この URL のトラフィックをこのキーを提示する小さな Web サーバーにルーティングするようにクラスタイングレスを自動的に構成します。小さな Web サーバーは、このキーを返すことによって、ACME サーバーによって開始されたチャレンジ検証リクエストに応答します。
DNS-01 チャレンジは、ドメインネームシステム (DNS) TXT レコードに存在する計算されたキーを提供することで完了します。この TXT レコードがインターネット全体に伝播された後、ACME サーバーは DNS ルックアップを介してこのキーを正常に取得し、申請者が要求された証明書のドメインを所有していることを検証できます。適切な権限があれば、cert-manager は DNS プロバイダーのこの TXT レコードを自動的に提示します。
実際の使用シナリオでは、現在の CA が ACME プロトコルをサポートしているかどうかを確認する必要があります。CA が ACME プロトコルをサポートしている場合、ASM イングレスゲートウェイは cert-manager を使用して CA から証明書を自動的に取得できます。たとえば、Sectigo は ACME プロトコルをサポートしています。Sectigo の動作方法は、このトピックで説明されている方法と似ています。
手順 1:パブリックドメインを準備する
Let's Encrypt を使用してドメインの証明書を発行するには、パブリックドメインを用意し、そのパブリックドメインを使用する ASM イングレスゲートウェイにポイントする必要があります。詳細については、DNS プロバイダーのドキュメントをご参照ください。Alibaba Cloud DNS を使用している場合は、「DNS レコードの追加」をご参照ください。Let's Encrypt の詳細については、「Getting Started」をご参照ください。
手順 2:Issuer リソースを作成して cert-manager を Let's Encrypt に接続する
ASM インスタンスに追加したデータプレーン上の ACK クラスタの kubeconfig ファイルを使用して、次のコードブロックに示されているリソースを作成します。
apiVersion: cert-manager.io/v1 kind: Issuer metadata: name: letsencrypt-prod-issuer namespace: istio-system spec: acme: email: 'te**@mail.com' # このフィールドはオプションですが、指定することをお勧めします。ACME サーバーは、このメールアドレスを介して証明書関連の重要な通知を送信する場合があります。 privateKeySecretRef: name: letsencrypt-prod server: https://acme-v02.api.letsencrypt.org/directory solvers: - http01: ingress: ingressClassName: istio上記の Issuer リソースは、
http01タイプのソルバーを指定します。Ingress API アクセスが有効になっており、ingressClassNameフィールドの値はistioです。次の手順では、このソルバーがどのように有効になるかを説明します。説明cert-manager は、Ingress API と Gateway API の 2 つのタイプのソルバーをサポートしています。ASM もこれらの 2 つの API をサポートしています。この例では、Ingress API が使用されています。
Issuer リソースの準備ができるまで待ちます。次のコマンドを実行して、Issuer リソースのステータスを確認します。
kubectl -n istio-system get issuer letsencrypt-prod-issuer予期される出力:
NAME READY AGE letsencrypt-prod-issuer True 8m3s
手順 3:ASM イングレスゲートウェイの証明書を発行する
ASM インスタンスに追加したデータプレーン上の ACK クラスタの kubeconfig ファイルを使用して、次のコードブロックに示されているリソースを作成します。
apiVersion: cert-manager.io/v1 kind: Certificate metadata: name: istio-ingressgateway-certs namespace: istio-system spec: dnsNames: - ${テストドメイン} # test.com issuerRef: group: cert-manager.io kind: Issuer name: letsencrypt-prod-issuer secretName: istio-ingressgateway-certsCertificate リソースの準備ができるまで待ちます。次のコマンドを実行して、Certificate リソースのステータスを確認します。
kubectl -n istio-system get certificate istio-ingressgateway-certs予期される出力:
NAME READY SECRET AGE istio-ingressgateway-certs True istio-ingressgateway-certs 59m
証明書の発行プロセス
Certificate リソースを作成すると、cert-manager は作成された Issuer リソースを使用して、Certificate リソースで指定したドメインの証明書を発行します。このプロセス中に、構成されたソルバーが有効になります。
Let's Encrypt は、現在のサーバーが証明書で指定したドメインの所有者であることを検証するために HTTP-01 チャレンジを開始します。これを行うために、Let's Encrypt はこのドメインに HTTP リクエストを送信します。ドメインの所有権を検証する前に、有効なレスポンスを取得する必要があります。この例では、ASM イングレスゲートウェイには HTTPBin ルーティングルールのみが構成されています。ASM イングレスゲートウェイには、チャレンジ関連の構成は構成されていません。Let's Encrypt はチャレンジ検証リクエストを送信しましたか?リクエストはどのように応答されますか?
次のコマンドを実行して、ASM イングレスゲートウェイのアクセスログを表示できます。次に、Let's Encrypt が ASM イングレスゲートウェイにチャレンジ検証リクエストを送信したかどうかを判断できます。
kubectl -n istio-system logs ${ASM イングレスゲートウェイ Pod の名前} | grep letsencrypt | tail -1出力は、Let's Encrypt が ASM イングレスゲートウェイにチャレンジ検証リクエストを送信し、リクエストが正常にレスポンスされたことを示しています。Issuer リソースでは、ingressClassName フィールドが istio に設定されています。したがって、cert-manager は ingressClassName が istio である Ingress リソースを自動的に作成し、チャレンジ検証リクエストを cert-manager のソルバーに転送してドメイン所有権の検証を完了します。
Certificate リソースの準備ができた後、kubectl -n istio-system get ingress コマンドを実行しても、関連する Ingress リソースを表示することはできません。理由は、証明書が発行された後、cert-manager は Ingress、Service、Deployment リソースなどのソルバー関連のリソースを自動的に削除するためです。
手順 4:Let's Encrypt によって発行された証明書を確認する
次のコードブロックに示されている Istio ゲートウェイを作成します。手順 3 で生成された証明書を ASM イングレスゲートウェイのポート 443 に構成します。詳細については、「Istio ゲートウェイの管理」をご参照ください。
apiVersion: networking.istio.io/v1beta1 kind: Gateway metadata: name: httpbin-https namespace: default spec: selector: istio: ingressgateway servers: - hosts: - ${テストドメイン} port: name: https number: 443 protocol: HTTPS tls: credentialName: istio-ingressgateway-certs mode: SIMPLE元の httpbin-vs 仮想サービスを、次のコードブロックに示されている内容に変更します。詳細については、「仮想サービスの管理」をご参照ください。
apiVersion: networking.istio.io/v1beta1 kind: VirtualService metadata: name: httpbin-vs namespace: default spec: gateways: - httpbin -httpbin-https # この行を追加します。 hosts: - '*' http: - name: test route: - destination: host: httpbin.default.svc.cluster.local port: number: 8000https://${テストドメイン}をブラウザのアドレスバーに入力します。ブラウザのアドレスバーは、次の図のようになります。
アイコンをクリックします。接続は安全ですと表示され、ブラウザが証明書を信頼していることを示します。