次の方法で共有


Azure IoT MQ Preview で MQTT 通信をセキュリティで保護するために、手動の証明書管理で TLS を構成する

重要

Azure Arc によって有効にされる Azure IoT Operations Preview は、 現在プレビュー段階です。 運用環境ではこのプレビュー ソフトウェアを使わないでください。

ベータ版、プレビュー版、または一般提供としてまだリリースされていない Azure の機能に適用される法律条項については、「Microsoft Azure プレビューの追加使用条件」を参照してください。

BrokerListener リソースを使用して、MQTT ブローカーとクライアントの間の MQTT 通信をセキュリティで保護するように TLS を構成できます。 手動または自動の証明書管理で TLS を構成できます。

特定の TLS 証明書を使用するように Azure IoT MQ Preview を手動で構成するには、Kubernetes シークレットへの参照を使用して BrokerListener リソース内でこれを指定します。 次に、kubectl を使用してそれをデプロイします。 この記事では、テスト用の自己署名証明書を使用して TLS を構成する例を示します。

Step CLI を使用して証明機関を作成する

Step は、独自のプライベート CA を作成および管理するときにすぐに起動して実行できる証明書マネージャーです。

  1. Step CLI をインストールし、ルート証明機関 (CA) の証明書とキーを作成します。

    step certificate create --profile root-ca "Example Root CA" root_ca.crt root_ca.key
    
  2. ルート CA によって署名された中間 CA 証明書とキーを作成します。

    step certificate create --profile intermediate-ca "Example Intermediate CA" intermediate_ca.crt intermediate_ca.key \
    --ca root_ca.crt --ca-key root_ca.key
    

サーバー証明書を作成する

手順 CLI を使用して、中間 CA によって署名されたサーバー証明書を作成します。

step certificate create mqtts-endpoint mqtts-endpoint.crt mqtts-endpoint.key \
--profile leaf \
--not-after 8760h \
--san mqtts-endpoint \
--san localhost \
--ca intermediate_ca.crt --ca-key intermediate_ca.key \
--no-password --insecure

ここで、mqtts-endpointlocalhost は、それぞれ Kubernetes およびローカル クライアントにおける Azure IoT MQ のブローカー フロントエンドのサブジェクトの別名 (SAN) です。 インターネット経由で接続するには、--san外部 IP を追加します。 --no-password --insecure フラグは、パスワード プロンプトをスキップして秘密キーのパスワード保護を無効にするためにテスト目的で使用されます。その理由は、秘密キーが Kubernetes シークレットに格納されるためです。 運用環境では、パスワードを使用し、秘密キーを Azure Key Vault などの安全な場所に格納します。

証明書キー アルゴリズムの要件

EC キーと RSA キーの両方がサポートされていますが、チェーン内のすべての証明書で同じキー アルゴリズムを使用する必要があります。 独自の CA 証明書をインポートする場合、サーバー証明書では CA と同じキー アルゴリズムを使ってください。

サーバー証明書チェーンを Kubernetes シークレットとしてインポートする

  1. 完全なサーバー証明書チェーンを作成します。ここでは証明書の順序が重要です。サーバー証明書はファイルの最初、中間は 2 番目になります。

    cat  mqtts-endpoint.crt intermediate_ca.crt  > server_chain.pem
    
  2. kubectl を使用して、サーバー証明書チェーンとサーバー キーを持つ Kubernetes シークレットを作成します。

    kubectl create secret tls server-cert-secret -n azure-iot-operations \
    --cert server_chain.crt \
    --key mqtts-endpoint.key
    

リスナーの TLS を有効にする

BrokerListener リソースの tls 設定を変更して、Kubernetes シークレットを参照する手動 TLS 構成を指定します。 TLS サーバー証明書に使用されるシークレットの名前をメモします (前の例の server-cert-secret)。

apiVersion: mq.iotoperations.azure.com/v1beta1
kind: BrokerListener
metadata:
  name: manual-tls-listener
  namespace: azure-iot-operations
spec:
  brokerRef: broker
  authenticationEnabled: false # If true, BrokerAuthentication must be configured
  authorizationEnabled: false
  serviceType: loadBalancer # Optional, defaults to clusterIP
  serviceName: mqtts-endpoint # Match the SAN in the server certificate
  port: 8885 # Avoid port conflict with default listener at 8883
  tls:
    manual:
      secretName: server-cert-secret

BrokerListener リソースが作成されると、オペレーターは自動的に Kubernetes サービスを作成し、リスナーをデプロイします。 kubectl get svc を実行して、サービスの状態を確認できます。

TLS を使用してブローカーに接続する

mosquitto クライアントとの TLS 接続をテストするには、メッセージを発行し、パラメータ --cafile にルート CA 証明書を渡します。

$ mosquitto_pub -d -h localhost -p 8885 -i "my-client" -t "test-topic" -m "Hello" --cafile root_ca.crt
Client my-client sending CONNECT
Client my-client received CONNACK (0)
Client my-client sending PUBLISH (d0, q0, r0, m1, 'test-topic', ... (5 bytes))
Client my-client sending DISCONNECT

ヒント

localhost を使用するには、ホスト コンピューターでポートを使用できる必要があります。 たとえば、kubectl port-forward svc/mqtts-endpoint 8885:8885 -n azure-iot-operations のようにします。 K3d のような一部の Kubernetes ディストリビューションでは、k3d cluster edit $CLUSTER_NAME --port-add 8885:8885@loadbalancer で転送されたポートを追加できます。

Note

ブローカーに接続するには、信頼のルートをクライアント (信頼バンドルとも呼ばれます) に配布する必要があります。 この場合、信頼のルートは自己署名ルート CA によって作成されたステップ CLI です。 クライアントがサーバー証明書チェーンを検証するには、信頼のルートの配布が必要です。 MQTT クライアントが Kubernetes クラスター上のワークロードである場合は、ルート CA を使用して ConfigMap を作成し、ポッドにマウントする必要もあります。

MQ 認証が有効になっている場合は、必ずユーザー名やパスワードなどを指定してください。

サーバー証明書に対して外部 IP を使用する

TLS を使用してインターネット経由で接続するには、Azure IoT MQ のサーバー証明書に SAN としての外部ホスト名が必要です。 運用環境では、これは通常、DNS 名または既知の IP アドレスです。 ただし、開発/テスト中は、デプロイ前に割り当てられているホスト名または外部 IP がわからない場合があります。 これを解決するには、まずサーバー証明書なしでリスナーをデプロイし、次に外部 IP を使用してサーバー証明書とシークレットを作成し、最後にシークレットをリスナーにインポートします。

TLS リスナーのサンプル manual-tls-listener をデプロイしようとしても、参照先の Kubernetes シークレット server-cert-secret が存在しない場合は、関連付けられたサービスが作成されますが、ポッドは起動しません。 サービスが作成されるのは、オペレーターがリスナーの外部 IP を予約する必要があるためです。

$ kubectl get svc mqtts-endpoint -n azure-iot-operations
NAME                   TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)             AGE
mqtts-endpoint         LoadBalancer   10.43.93.6      172.18.0.2    8885:30674/TCP      1m15s

ただし、これは想定された動作であり、サーバー証明書をインポートする限り、そのままにしても問題ありません。 正常性マネージャー ログに、Azure IoT MQ がサーバー証明書を待機中であることが示されています。

$ kubectl logs -l app=health-manager -n azure-iot-operations
...
<6>2023-11-06T21:36:13.634Z [INFO] [1] - Server certificate server-cert-secret not found. Awaiting creation of secret.

Note

一般に、分散システムでは、ポッド ログは決定論的ではないため、慎重に使用する必要があります。 このような情報を表示する正しい方法は、Kubernetes イベントとカスタム リソースの状態 (バックログ内) を使用することです。 前の手順は、一時的な回避策と考えてください。

フロントエンド ポッドが稼働していない場合でも、外部 IP は既に使用できます。

$ kubectl get svc mqtts-endpoint -n azure-iot-operations
NAME                   TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)             AGE
mqtts-endpoint         LoadBalancer   10.43.93.6      172.18.0.2    8885:30674/TCP      1m15s

ここから、前と同じ手順に従って、--san でこの外部 IP を使用してサーバー証明書を作成し、同じ方法で Kubernetes シークレットを作成します。 シークレットが作成されると、リスナーに自動的にインポートされます。