Web プロジェクトを展開する場合、 SSL 証明書の実装は、すべてのエンジニアが直面する可能性が高い共通の課題であり、私も例外ではありません。
通常、スタートアップは Let's Encrypt のような無料の証明書を選択します。ただし、これらには考慮すべき制限と不都合が伴います。詳細については、証明書プロバイダーの Web サイトを参照してください。
無料の証明書に関して私が個人的に遭遇した問題を詳しく見てみましょう。
これらの問題に定期的に直面してきたため、Let's Encrypt 証明書を利用するカスタマイズされたソリューション構成を開発しました。この記事では、私の調査結果と、その過程で学んだ教訓を共有します。
最近、私は特定のテクノロジ スタックに注目しており、Azure クラウド プロバイダーのコンテキスト内でのKubernetesクラスター ベースのインフラストラクチャ ソリューションについて説明したいと思います。この領域では cert-manager が一般的なソリューションですが、利便性を高めるために Helm を介してインストールすることを好みます。
それでは、これ以上苦労せずに、すぐに飛び込んでみましょう。
helm repo add jetstack https: //charts.jetstack.io
helm repo update kubectl apply -f https: //github.com/jetstack/cert-manager/releases/download/v1.6.1/cert-manager.crds.yaml
helm install cert-manager jetstack/cert-manager -- namespace cert - manager -- create - namespace -- version v1 . 6 . 1
その後、次の YAML ファイルを使用して ClusterIssuer を作成できます。
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-cluster-issuer
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: p….@gmail.com #your e-mail
privateKeySecretRef:
name: letsencrypt-cluster-issuer
solvers:
- http01:
ingress:
class: nginx
今後、証明書を実装するための 2 つのオプションがあります。
両方のオプションを調べてみましょう。
最初のシナリオでは、YAML ファイルは次のようになりました。
apiVersion: cert-manager.io/v1 kind: Certificate metadata: name: myservice2 namespace : test
Spec : duration : 2160h
renewBefore : 72h
dnsNames : - myservice2 . mydomain . org # you resources
secretName : myservice2 - tls
issuerRef : name : letsencrypt - cluster - issuer
kind : ClusterIssuer
特定のサービスの TLS セクションのイングレスで「secretName: myservice2-tls」のみが言及されたことは注目に値します。
ところで、YAML ファイルには次のような便利なパラメーターが含まれています。
コンソールでの作業に慣れている場合は、例として証明書の包括的なビューを提供させてください。
kubectl describe certificates <cert name > -n <namespace name >
では、最終的に何が得られるでしょうか。
個人的には、Ingress を介して Let's Encrypt 証明書を管理する方が信頼性が高く便利であることがわかったので、最近は Ingress を使用しています。このアプローチでは、TLS セクションの secretName とホスト名に加えて、イングレス YAML ファイルでアノテーションを指定するだけで済みます。
annotations : cert-manager .io/cluster-issuer: "letsencrypt-cluster-issuer" cert-manager .io/renew-before: 72h
そして、あなたはそれを手に入れました、それはすべての魔法です!この例では、証明書が期限切れになるまでに 3 日間のバッファー期間を設けて、証明書が自動的に再発行されるようになりました。 Let's Encrypt の場合、デフォルトの期間は 90 日です。
しかし、Let's Encrypt の無料の証明書には制限があるため、私たちのチームは最終的に、ドメインだけでなくサブドメインも保護できる包括的な証明書の必要性を検討しました。 Azure でプロジェクトを開発し続けるうちに、Azure Key Vault がそのような証明書を格納するのに便利な場所であることがわかりました。 Kubernetes クラスター内で akv2k8s ユーティリティを使用しています。興味がある場合は、詳細を確認することをお勧めします。
Azure で証明書を取得したら、次の手順はそれを Azure Key Vault (AKV) に追加することです。このプロセスは比較的簡単ですが、ドメインの所有権を確認するのは少し難しい場合があります。ただし、すべての確認手順が正常に完了すると、証明書はキー コンテナーの [Secrets] セクションに表示されます。
このアプローチの主な利点の 1 つは、証明書の自動更新です。証明書は 1 年後に AKV で再発行および更新され、Kubernetes の Secret と自動的に同期されます。
取得した証明書を Kubernetes クラスターで利用するには、特定のアクセス許可とアクセス権を付与する必要があります。
これを行うには、最初にクラスターの identityProfile.kubeletidentity.objectId を取得する必要があります。これを行うには、次のコマンドを使用します。
az aks show -g < RG > -n < AKS_name >
リソース グループ (RG) はクラスターが格納される場所で、AKS_name はクラスターの名前です。
identityProfile.kubeletidentity.objectId を取得したら、それをコピーする必要があります。次に、シークレットにアクセス許可を付与するためのコマンドに値を追加します。
az keyvault set-policy --name < name AKV > --object-id < get from first step value > --secret-permissions get
次に、 インストール ガイドで説明されているように、Helm またはその他の推奨される方法で akv2k8s のインストールに進むことができます。
公式ドキュメントに従って、Azure Key Vault 証明書を特定の Kubernetes 名前空間のシークレットと同期できます。ここに私のYAMLファイルがあります:
apiVersion: spv.no/v1 kind: AzureKeyVaultSecret metadata: name: wildcard-cert #any name namespace : default
spec : vault : name : SandboxKeyVault # name you keyvault in Azure
object : name : name_object_id # name object id from Azure AKV this cert
type : secret
output : secret : name : wildcard - cert # any name for secret in your namespace
type : kubernetes . io / tls
chainOrder : ensureserverfirst # very important values !!!
私が遭遇した問題を解決する上で重要な役割を果たしたので、最後の行の重要性を強調させてください.最初は、証明書を Kubernetes に正常にアップロードできましたが、意図したとおりに機能しませんでした。問題の診断には時間がかかりました。
結局のところ、Key Vault から PFX 証明書をエクスポートすると、サーバー証明書がチェーンの先頭ではなく末尾に配置されることがあります。証明書の読み込みに失敗し、デフォルトで元の値に戻るため、ingress-nginx などのパラメーターで使用すると問題が発生する可能性があります。ただし、chainOrder を ensureserverfirst に設定すると、サーバー証明書がチェーンの最初に配置されます。
証明書を詳しく調べたところ、チェーンが次の順序で配置されていることがわかりました。
技術的な側面と構成について説明したので、Azure 証明書の特性に戻りましょう。
Azure は、証明書を注文するための 2 つのオプションを提供します。どちらも GoDaddy によって提供されます。
すべてのアプリケーションとサービスが保護されることを期待して、後者を選択しました。ただし、いくつかのニュアンスがありました。
Azure ワイルドカード証明書は、第 1 レベルのサブドメインのみを保護します。たとえば、 mydomain.comという名前のドメインがある場合、証明書は.mydomain.comの形式の第 1 レベルのサブドメインのみをカバーします。
したがって、証明書はservice1.mydomain.com、service2.mydomain.com、service3.mydomain.com などのリソースに対して機能しますが、 service1.test.mydomain.comやmail.service1.mydomain.comはカバーしません。
では、どのようなオプションがありますか?
サブドメインの数、特に第 2 レベルのサブドメインの数が膨大になる可能性があるため、最初のオプションは実用的ではありません。したがって、各サブドメイン ( .service1.mydomain.com, *.dev.mydomain.com… ) に対してワイルドカード証明書を支払うことは、最も合理的な解決策ではありません。
2 番目のオプションについては、この件に関して Azure サポート チームと長い会話を交わし、拒否、フラストレーション、怒りのすべての段階を経て、最終的に、証明書の SAN 機能がまだ実装されていないことに気付きました。
最後まで、Azure でこのような問題が発生しないことを願っていました。対照的に、競合他社である AWS Amazon は、ワイルドカードを含む最大 10 の代替サブジェクト名をサポートする AWS Certificate Manager (ACM) を通じて証明書を提供しています。ワイルドカード文字 (*) を使用して 10 個のサブドメインを作成でき、AWS で最大 100k のクォータ増加をリクエストすることもできます。
最後に、Azure の Front Door サービスで証明書を利用する方法を紹介します。
私にとって、Azure Front Door (AFD) は、Microsoft の世界規模のエッジ ネットワークを利用して、着信トラフィックを適切なエンドポイント (Web アプリケーションやサービスなど) に誘導する、グローバルでスケーラブルなゲートウェイです。 HTTP/HTTPS レイヤー (レイヤー 7) で動作する Front Door は、クライアント要求をプールから使用可能なアプリケーション サーバーにルーティングします。アプリケーションのサーバー側は、 Azure の内部または外部でホストされているかどうかに関係なく、インターネットからアクセスできる任意のサービスにすることができます。
ドキュメント Web サイトの例https://docs.microsoft.com/
Azure Front Door は、世界中の分散アプリケーションやサービスにアクセスする受信トラフィックのバランスを取り、プロキシできる便利なツールです。ルール ハンドラーの構成、ポリシーへの参加、ファイアウォール設定によってさまざまなルールをバインドする機能など、さまざまな機能を提供します。この記事では、AFD サービスの詳細について深く掘り下げることはせず、証明書のサービスの特徴に焦点を当てます。
ご想像のとおり、Azure Front Door への着信トラフィックは、 httpまたはhttpsのいずれかになります。 httpsを選択した場合、Azure Front Door サービス自体で証明書を生成する、独自の証明書をアップロードする、または既存の証明書を Azure Key Vault に同期するという 3 つのオプションがあります。 Front Door サービスが Key Vault にアクセスできるようにするには、必要なアクセス許可を構成する必要があります。
最後のオプションを使用し、証明書の最新バージョンを選択して、手動で更新または再生成する必要がないようにすることをお勧めします。 AKV からの証明書を接続することで、すべてが自動的に最新の状態に保たれます。
この設定により、次の結果が得られます。
Azure Front Door から AKS にトラフィックを転送する際のもう 1 つの特徴を次に示します。
httpトラフィックの処理は問題ではありませんが、リソース プールを設定し、AKS クラスターの外部 IP アドレスを指定するときに留意すべき細かい点があります。 「IP またはノード名」フィールドに入力された値が自動的に入力されるように、「サーバー コンポーネント ノード ヘッダー」フィールドは必ず空白のままにしてください。
Front Door サービスによって利用され、akv2k8s を介して AKS クラスターにフラッシュされる、AKV を介してアタッチされたドメイン ワイルドカード証明書があるとします。 Front Door からアクセスできるすべてのアプリケーションとサービスのインターフェイス ホスト名 (および DNS の CNAME レコード) は次のようになります。
これにより、 *.mydomain.com形式のすべてのサービスが正しく機能するようになります。この構成が完了したら、準備は完了です。
特定のシナリオでは、https を介して Azure Front Door から AKS にトラフィックをリダイレクトする方が有利な場合があります。サーバー プール設定で Azure Front Door が正しく機能するようにするには、SNI と正常性チェックに関連する AKS クラスターに対応する DNS 名を指定することが重要です。そうしないと、セットアップが機能しません。
私の場合、AKS クラスターに割り当てられた名前はありませんでした。以前は直接機能していたサービスしかありませんでしたが、Azure Front Door を介して機能する必要がありました。これに対処するには、AKS クラスター用に別の DNS 名を作成し、DNS を構成し、イングレスに添付された証明書を使用して別のサービスをセットアップする必要がありました。そうして初めて、 httpsトラフィックを AKS クラスターにリダイレクトし、利用可能なすべてのサービスに対して正しく動作することを確認できました。
AKS の接続許可を設定するときは、セキュリティ対策を考慮することが重要です。セキュリティで保護された接続を確保するために、AKS のネットワーク セキュリティ グループ内の Azure Front Door IP アドレスからのみ AKS に接続するアクセス許可を制限できます (下の図を参照)。
さらに、 X-Azure-FDID パラメーターを使用して、ID によって Azure Front Door ヘッダーからのみ接続を受け入れるように、AKS イングレスを設定できます。
1. Azure は、証明書の機能と欠点に関する包括的な情報を提供していません。ただし、購入した証明書をすぐに返金してくれたことは特筆に値します。
2. 開発プロセス中は、引き続き Let's Encrypt を使用します。制限はありますが、最悪の選択肢ではありません。
3. プロジェクトでリソース レベルが異なる複数のサブドメインが必要な場合は、サードパーティ ベンダーの「SAN を使用したワイルドカード (マルチドメインとも呼ばれます)」証明書を検討することをお勧めします。これらの証明書は、Azure にインポートして、最大限に活用できます。
4. 正しく構成されている場合、Azure Front Door は優れたサービスです。強くお勧めします。
執筆者: Pavel Shapurau、リード DevOps エンジニア、Social Discovery Group