Share via


Azure IoT MQ プレビュー認証を構成する

重要

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

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

Azure IoT MQ プレビューでは、クライアントのために複数の認証方法がサポートされます。BrokerAuthentication リソースを使用して、各リスナーが独自の認証システムを使用するように構成できます。

既定の BrokerAuthentication リソース

Azure IoT Operations プレビューは、azure-iot-operations 名前空間内の listener という名前の既定のリスナーとリンクされた、authn という名前の既定の BrokerAuthentication リソースをデプロイします。 これは、認証に Kubernetes サービス アカウント トークン (SAT) のみを使用するように構成されています。 これを検査するには、次を実行します。

kubectl get brokerauthentication authn -n azure-iot-operations -o yaml

出力には、簡潔にするためにメタデータが除外された既定の BrokerAuthentication リソースが示されます。

apiVersion: mq.iotoperations.azure.com/v1beta1
kind: BrokerAuthentication
metadata:
  name: authn
  namespace: azure-iot-operations
spec:
  listenerRef:
    - listener
  authenticationMethods:
    - sat:
        audiences: ["aio-mq"]

構成を変更するには、この BrokerAuthentication リソースの authenticationMethods 設定を編集するか、別の名前で新しい BrokerAuthentication リソースを作成します。 次に、kubectl apply を使用してそれをデプロイします。

BrokerListener と BrokerAuthentication の関係

BrokerListener と BrokerAuthentication は別個のリソースですが、listenerRef を使用して互いにリンクされています。 次の規則が適用されます。

  • BrokerListener がリンクできる BrokerAuthentication は 1 つだけです
  • BrokerAuthentication は複数の BrokerListener にリンクできます
  • 各 BrokerAuthentication は一度に複数の認証方法をサポートできます

Authentication flow

配列内の認証方法の順序により、Azure IoT MQ でのクライアントの認証方法が決まります。 Azure IoT MQ は、最初に指定されたメソッドを使用してクライアントの資格情報の認証を試み、一致するものが見つかるか、末尾に達するまで配列を反復処理します。

各メソッドでは、Azure IoT MQ により、クライアントの資格情報がそのメソッドに "該当する" かどうかがチェックされます。 たとえば、SAT 認証では $sat から始まるユーザー名が必要であり、X.509 認証ではクライアント証明書が必要です。 クライアントの資格情報が該当する場合、Azure IoT MQ により、有効かどうかが検証されます。 詳しくは、認証方法の構成に関するセクションをご覧ください。

カスタム認証の場合、Azure IoT MQ では、カスタム認証サーバーとの通信エラーは "資格情報の該当なし" として扱われます。 この動作により、カスタム サーバーに到達できない場合、Azure IoT MQ は他のメソッドにフォールバックします。

認証フローは、次の場合に終了します。

  • 以下のいずれかの条件が満たされている場合。
    • クライアントの資格情報が以下のいずれかのメソッドに対して該当し、有効である場合。
    • クライアントの資格情報がいずれのメソッドにも該当しない場合。
    • クライアントの資格情報が以下のいずれかのメソッドに対して該当するが、無効である場合。
  • Azure IoT MQ により、認証フローの結果に基づいて、クライアントへのアクセスが許可または拒否されます。

Azure IoT MQ には、複数の認証方法を使用することによるフォールバック メカニズムが備わっています。 次に例を示します。

apiVersion: mq.iotoperations.azure.com/v1beta1
kind: BrokerAuthentication
metadata: 
  name: authn
  namespace: azure-iot-operations
spec:
  listenerRef:
    - listener
  authenticationMethods:
    - custom:
        # ...
    - sat:
        # ...
    - usernamePassword:
        # ...

前の例では、カスタム認証、SAT 認証、ユーザー名/パスワード認証について説明しました。 クライアントに接続すると、Azure IoT MQ は、カスタム認証 > SAT > ユーザー名/パスワードという順番で指定したメソッドを使用してクライアントの認証を試みます。

  1. Azure IoT MQ により、クライアントの資格情報がカスタム認証に対して有効かどうかがチェックされます。 カスタム認証では、外部サーバーに依存して資格情報の有効性を判断しているため、ブローカーによってすべての資格情報がカスタム認証に該当すると見なされ、カスタム認証サーバーに転送されます。

  2. カスタム認証サーバーから Pass または Fail の結果で応答が返された場合、認証フローは終了します。 ただし、カスタム認証サーバーが使用できない場合、Azure IoT MQ は、指定された残りのメソッドにフォールバックします。ここでは SAT が次のメソッドです。

  3. Azure IoT MQ は、SAT 資格情報として資格情報の認証を試みます。 MQTT ユーザー名が $sat で始まる場合、Azure IoT MQ では MQTT パスワードが SAT として評価されます。 それ以外の場合、ブローカーによってユーザー名/パスワードにフォールバックされ、指定された MQTT ユーザー名とパスワードが有効であるかどうかがチェックされます。

カスタム認証サーバーが使用できず、すべての後続のメソッドで提供された資格情報が該当しないと判断された場合は、ブローカーによってクライアントの接続が拒否されます。

認証を無効にする

テストをする場合は、BrokerListener リソース内で変更して認証を無効にします。

spec:
  authenticationEnabled: false

認証方法を構成する

各認証オプションの詳細については、次のセクションを参照してください。

ユーザー名とパスワード

各クライアントには、以下の必須プロパティがあります。

たとえば、clients.toml で始まる ID と PBKDF2 エンコードされたパスワードです。

# Credential #1
# username: client1
# password: password
[client1]
password = "$pbkdf2-sha512$i=100000,l=64$HqJwOCHweNk1pLryiu3RsA$KVSvxKYcibIG5S5n55RvxKRTdAAfCUtBJoy5IuFzdSZyzkwvUcU+FPawEWFPn+06JyZsndfRTfpiEh+2eSJLkg"

[client1.attributes]
floor = "floor1"
site = "site1"

# Credential #2
# username: client2
# password: password2
[client2]
password = "$pbkdf2-sha512$i=100000,l=64$+H7jXzcEbq2kkyvpxtxePQ$jTzW6fSesiuNRLMIkDDAzBEILk7iyyDZ3rjlEwQap4UJP4TaCR+EXQXNukO7qNJWlPPP8leNnJDCBgX/255Ezw"

[client2.attributes]
floor = "floor2"
site = "site1"

PBKDF2 を使用してパスワードをエンコードするには、az iot ops mq get-password-hash コマンドを含む Azure IoT Operations CLI 拡張機能を使用します。 これにより、SHA-512 アルゴリズムと 128 ビットのランダム化された salt を使用して、パスフレーズから PBKDF2 パスワード ハッシュが生成されます。

az iot ops mq get-password-hash --phrase TestPassword

出力には、コピー用の PBKDF2 パスワード ハッシュが表示されます。

{
  "hash": "$pbkdf2-sha512$i=210000,l=64$4SnaHtmi7m++00fXNHMTOQ$rPT8BWv7IszPDtpj7gFC40RhhPuP66GJHIpL5G7SYvw+8rFrybyRGDy+PVBYClmdHQGEoy0dvV+ytFTKoYSS4A"
}

次に、ファイルを passwords.toml として保存し、そのキーの下の Kubernetes シークレットにインポートします。

kubectl create secret generic passwords-db --from-file=passwords.toml -n azure-iot-operations

BrokerAuthentication カスタム リソースのシークレットへの参照を含めるようにします。

spec:
  authenticationMethods:
    - usernamePassword:
        secretName: passwords-db

変更が有効になるまで、数分かかる場合があります。

Azure Key Vault を使用して、Kubernetes シークレットではなく Azure IoT MQ 用のシークレットを管理できます。 詳細については、「Azure Key Vault または Kubernetes シークレットを使用してシークレットを管理する」を参照してください。

X.509 クライアント証明書

前提条件

  • TLS が有効になるよう構成された Azure IoT MQ。
  • Step CLI
  • クライアント証明書と PEM ファイル内の発行中の証明書チェーン。 いずれもない場合は、Step CLI を使用して作成します。
  • 公開キーの暗号と用語 (ルート CA、プライベート キー、中間証明書など) に関する知識。

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

信頼されたクライアント ルート CA 証明書をインポートする

信頼されたルート CA 証明書は、クライアント証明書を検証するために必要です。 クライアント証明書の検証に使用できるルート証明書をインポートするには、まず client_ca.pem キーの下で、証明書の PEM を ConfigMap としてインポートします。 クライアント証明書は、Azure IoT MQ で認証されるよう、この CA でルートする必要があります。

kubectl create configmap client-ca --from-file=client_ca.pem -n azure-iot-operations

ルート CA 証明書が正常にインポートされているかどうかをチェックするには、kubectl describe configmap を実行します。 結果には、同じ PEM 証明書ファイルの base64 エンコードが示されます。

$ kubectl describe configmap client-ca -n azure-iot-operations
Name:         client-ca
Namespace:    azure-iot-operations

Data
====
client_ca.pem:
----
-----BEGIN CERTIFICATE-----
MIIBmzCCAUGgAwIBAgIQVAZ2I0ydpCut1imrk+fM3DAKBggqhkjOPQQDAjAsMRAw
...
t2xMXcOTeYiv2wnTq0Op0ERKICHhko2PyCGGwnB2Gg==
-----END CERTIFICATE-----


BinaryData
====

証明書から属性へのマッピングをインポートする

X.509 クライアント証明書のプロパティを使用してクライアント用の認可ポリシーを使用するには、証明書から属性へのマッピング TOML ファイルを作成し、キー x509Attributes.toml の下に Kubernetes シークレットとしてインポートします。 このファイルを使用すると、認可ポリシーで使用できるクライアント証明書のサブジェクト名が属性にマップされます。 この値は、認可ポリシーを使用しない場合でも必須です。

kubectl create secret generic x509-attributes --from-file=x509Attributes.toml -n azure-iot-operations

属性ファイル構文の詳細については、X.509 認証を使用するクライアントの認可に関するページを参照してください。

ユーザー名/パスワード認証を使用する場合と同様に、Azure Key Vault を使用して、Kubernetes シークレットではなくこのシークレットを管理できます。 詳細については、「Azure Key Vault または Kubernetes シークレットを使用してシークレットを管理する」を参照してください。

X.509 クライアント認証を有効にする

最後に、信頼されたクライアント ルート CA 証明書と証明書から属性へのマッピングをインポートしたら、認証方法の 1 つとして x509 を追加し、X.509 クライアント認証を有効にします。これは、TLS 対応リスナーにリンクされた BrokerAuthentication リソースの一部として行います。 次に例を示します。

spec:
  authenticationMethods:
    - x509:
        trustedClientCaCert: client-ca
        attributes:
          secretName: x509-attributes

X.509 クライアント証明書を使用して mosquitto クライアントを Azure IoT MQ プレビューに接続する

Mosquitto のようなクライアントが TLS と X.509 クライアント認証を使用して Azure IoT MQ に接続できるようにするには、3 つのファイルが必要です。 次に例を示します。

mosquitto_pub -q 1 -t hello -d -V mqttv5 -m world -i thermostat \
-h "<IOT_MQ_EXTERNAL_IP>" \
--cert thermostat_cert.pem \
--key thermostat_key.pem \
--cafile chain.pem

この例では次のとおりです。

  • --cert パラメータは、クライアント証明書 PEM ファイルを指定します。
  • --key パラメータは、クライアント秘密キー PEM ファイルを指定します。
  • 3 つ目のパラメータ --cafile は最も複雑な信頼された証明書データベースであり、2 つの目的で使用されます。
    • Mosquitto クライアントが TLS 経由で Azure IoT MQ に接続する場合、サーバー証明書が検証されます。 データベース内のルート証明書を検索し、サーバー証明書への信頼されたチェーンを作成します。 そのため、このファイルにサーバー ルート証明書をコピーする必要があります。
    • Azure IoT MQ によって Mosquitto クライアントのクライアント証明書が要求されるときには、サーバーに送信するための有効な証明書チェーンも必要になります。 --cert パラメータは Mosquitto が送信する証明書を指定しますが、これだけでは十分ではありません。 Azure IoT MQ には中間証明書も必要であるため、この証明書だけでは検証することができません。 Mosquitto はデータベース ファイルを使用して必要な証明書チェーンを作成します。 これをサポートするため、cafile には中間証明書とルート証明書の両方が含まれている必要があります。

Azure IoT MQ プレビューの X.509 クライアント認証フローを理解する

X.509 クライアント認証フローの図。

クライアント認証フローの手順を次に示します。

  1. X.509 クライアント認証が有効になっている場合、接続しているクライアントは、クライアント証明書と、Azure IoT MQ が構成済みの信頼できる証明書のうちの 1 つをルートとする証明書チェーンを作成するために使用する中間証明書を提示する必要があります。
  2. ロード バランサーにより、通信がいずれかのフロントエンド ブローカーに送られます。
  3. フロントエンド ブローカーは、クライアント証明書を受信すると、構成済み証明書のうちの 1 つをルートとする証明書チェーンの作成を試みます。 TLS ハンドシェイクには証明書が必要です。 フロントエンド ブローカーによって正常にチェーンが作成され、提示されたチェーンが検証されると、TLS ハンドシェイクが完了します。 接続しているクライアントは、作成した TLS チャネルを通じて MQTT パケットをフロントエンドに送信できます。
  4. TLS チャネルは開かれていますが、クライアントの認証または認可はまだ完了していません。
  5. 次に、クライアントにより CONNETCT パケットが Azure IoT MQ に送信されます。
  6. CONNECT パケットはフロントエンドにもう一度ルートされます。
  7. フロントエンドでは、ユーザー名とパスワード フィールド、CONNECT パケットからの認証データ、TLS ハンドシェイク中に提示されたクライアント証明書チェーンなど、これまでに提示されたすべての資格情報が収集されます。
  8. フロントエンドにより、これらの資格情報が認証サービスに送信されます。 認証サービスにより、証明書チェーンがもう一度チェックされ、チェーン内のすべての証明書のサブジェクト名が収集されます。
  9. 認証サービスは、構成済みの認可規則を使用して、接続しているクライアントが持つ属性を判断します。 これらの属性により、CONNECT パケット自体を含め、クライアントが実行できる操作が決定されます。
  10. 認証サービスにより、決定がフロントエンド ブローカーに返されます。
  11. フロントエンド ブローカーにより、クライアント属性と、接続が許可されているかどうかが認識されます。 その場合、MQTT 接続が完了し、クライアントは認可規則によって決定された MQTT パケットの送受信を続行できます。

Kubernetes サービス アカウント トークン

Kubernetes サービス アカウント トークン (SAT) は、Kubernetes サービス アカウントに関連付けられている JSON Web トークンです。 クライアントによって、自身を認証するために、Azure IoT MQ の MQTT ブローカーに SAT が提示されます。

Azure IoT MQ では、"バインド サービス アカウント トークン" が使用されます。これについては、「Kubernetes の新しいサービス アカウント トークンについて GKE ユーザーが知っておくべきこと」の投稿で詳しく説明されています。 投稿で説明されている代表的な機能を次に示します。

Kubernetes 1.13 で導入され、1.21 で既定の形式となったバインド トークンは、レガシ トークンの制限された機能すべてに対処するものです。他にも次のような特徴があります。

  • トークン自体が盗用、誤用しずらいものです。これらは、時間、対象ユーザー、オブジェクトに対してバインドされています。
  • OpenID Connect (OIDC) という標準化された形式を採用し、完全な OIDC 検出により、サービス プロバイダーが受け入れやすくなります。
  • 新しい Kubelet 予測ボリュームの種類を使用して、ポッドにより安全に配布されます。

ブローカーでは、Kubernetes Token Review APIを使用してトークンが検証されます。 Kubernetes の TokenRequestProjection 機能を有効にして、audiences を指定します (1.21 以降では既定)。 この機能が有効になっていない場合、SAT は使用できません。

サービス アカウントの作成

SAT を作成するには、最初にサービス アカウントを作成します。 次のコマンドを使用すると、mqtt-client というサービス アカウントが作成されます。

kubectl create serviceaccount mqtt-client -n azure-iot-operations

認可用の属性を追加する

SAT 経由のクライアント認証では、必要に応じて、カスタム認可ポリシーで使用する属性で注釈が付けられた SAT を持つことができます。 詳細については、Kubernetes サービス アカウント トークンを使用するクライアントの認可に関するページを参照してください。

サービス アカウント トークン (SAT) 認証を有効にする

BrokerAuthentication リソースの authenticationMethods 設定を変更して、有効な認証方法として sat を指定します。 audiences により、トークンの有効な対象ユーザーの一覧が指定されます。 Azure IoT MQ のブローカー サービスを識別する一意の値を選択します。 1 つ以上の対象ユーザーを指定し、すべての SAT が指定された対象ユーザーのいずれかと一致する必要があります。

spec:
  authenticationMethods:
    - sat:
        audiences: ["aio-mq", "my-audience"]

kubectl apply を使用して変更を適用します。 変更が有効になるまで、数分かかる場合があります。

SAT 認証をテストする

SAT 認証は、Azure IoT MQ と同じクラスター内のクライアントから使用する必要があります。 次のコマンドにより、Mosquitto クライアントを持つポッドが指定され、前の手順で作成した SAT がポッドにマウントされます。

apiVersion: v1
kind: Pod
metadata:
  name: mqtt-client
  namespace: azure-iot-operations
spec:
  serviceAccountName: mqtt-client
  containers:
  - image: efrecon/mqtt-client
    name: mqtt-client
    command: ["sleep", "infinity"]
    volumeMounts:
    - name: mqtt-client-token
      mountPath: /var/run/secrets/tokens
  volumes:
  - name: mqtt-client-token
    projected:
      sources:
      - serviceAccountToken:
          path: mqtt-client-token
          audience: my-audience
          expirationSeconds: 86400

ここで、ポッド構成の serviceAccountName フィールドは、使用されているトークンに関連付けられているサービス アカウントと一致する必要があります。 また、ポッド構成の serviceAccountToken.audience フィールドは、BrokerAuthentication リソースで構成された audiences のいずれかである必要があります。

ポッドが作成されたら、ポッドでシェルを開始します。

kubectl exec --stdin --tty mqtt-client -n azure-iot-operations -- sh

トークンは、前の例の構成 /var/run/secrets/tokens で指定されたパスにマウントされます。 トークンを取得し、それを使用して認証します。

token=$(cat /var/run/secrets/tokens/mqtt-client-token)

mosquitto_pub -h aio-mq-dmqtt-frontend -V mqttv5 -t hello -m world -u '$sat' -P "$token"

MQTT ユーザー名を $sat に設定する必要があります。 MQTT パスワードは SAT 自体に設定する必要があります。

サービス アカウント トークンを更新する

サービス アカウント トークンは、限られた期間有効であり、expirationSeconds を使用して構成されます。 ただし、Kubernetes は、有効期限が切れる前にトークンを自動的に更新します。 トークンはバックグラウンドで更新されます。クライアントは、それを再フェッチする以外に何も行う必要はありません。

たとえば、「SAT 認証をテストする」の例にあるように、クライアントが、ボリュームとしてマウントされたトークンを使用するポッドである場合、最新のトークンは同じパス /var/run/secrets/tokens/mqtt-client-token で取得できます。 新しい接続を作成するときに、クライアントは最新のトークンをフェッチし、それを使用して認証を行うことができます。 クライアントには、最新のトークンをフェッチして接続を再試行することで MQTT 未承認エラーを処理するメカニズムも必要です。

カスタム認証

カスタム認証を使用して、指定された認証方法以外にもクライアント認証を拡張します。 サービスは API に準拠している限り任意であるため、"プラグ可能" です。

クライアントが Azure IoT MQ に接続し、カスタム認証が有効になっている場合、Azure IoT MQ は、クライアントが提示するすべての資格情報と共に HTTP 要求を使用して、クライアント資格情報の検証をカスタム認証サーバーに委任します。 カスタム認証サーバーは、クライアントの認可用の属性を使用して、クライアントに対して承認または拒否で応答します。

カスタム認証サービスを作成する

カスタム認証サーバーは、Azure IoT MQ とは別に実装およびデプロイされます。

サンプルのカスタム認証サーバーと手順は、GitHub で入手できます。 このサンプルをテンプレートとして使用し、独自のカスタム認証ロジックを実装するための開始点として使用します。

API

Azure IoT MQ とカスタム認証サーバーの間の API は、カスタム認証の API 仕様に従います。 OpenAPI 仕様は GitHub で入手できます。

TLS 暗号化を使用した HTTPS が必要

Azure IoT MQ は、機密性の高いクライアント資格情報を含む要求をカスタム認証サーバーに送信します。 これらの資格情報を保護するには、Azure IoT MQ とカスタム認証サーバー間の通信を TLS で暗号化する必要があります。

カスタム認証サーバーはサーバー証明書を提示する必要があり、Azure IoT MQ には、サーバー証明書を検証するための信頼されたルート CA 証明書が必要です。 必要に応じて、カスタム認証サーバーでは、自身を認証するためのクライアント証明書を提示するために Azure IoT MQ が必要になる場合があります。

リスナーのカスタム認証を有効にする

BrokerAuthentication リソースの authenticationMethods 設定を変更して、有効な認証方法として custom を指定します。 次に、カスタム認証サーバーとの通信に必要なパラメータを指定します。

この例では、使用する可能性のあるすべてのパラメータを示します。 必要とされる正確なパラメータは、各カスタム サーバーの要件によって異なります。

spec:
  authenticationMethods:
    - custom:
        # Endpoint for custom authentication requests. Required.
        endpoint: https://auth-server-template
        # Trusted CA certificate for validating custom authentication server certificate.
        # Required unless the server certificate is publicly-rooted.
        caCert: custom-auth-ca
        # Authentication between Azure IoT MQ with the custom authentication server.
        # The broker may present X.509 credentials or no credentials to the server.
        auth:
          x509:
            secretName: custom-auth-client-cert
            namespace: azure-iot-operations
        # Optional additional HTTP headers that the broker will send to the
        # custom authentication server.
        headers:
          header_key: header_value