Armadilloフォーラム

azure-iot-device TLS関連エラーでAzureへの接続に失敗

fkben

2021年7月13日 13時23分

お世話になります。
Azure IoT Hubにazure-iot-deviceを利用してデータを送信しようとすると
エラーが発生します。
同じネットワークに接続しているラズパイでは問題なく通信できて
いますので、ルータの設定などネットワークの問題ではないという認識です。
大変お手数ですが、解決策のアドバイスをよろしくお願いいたします。

<現象>
azure-iot-sampleのSimulatedDeviceSync.pyに接続文字列を指定して実行すると
下記のようなエラーメッセージ(一部抜粋)が出力される。

File "/usr/local/lib/python3.7/dist-packages/azure/iot/device/iothub/sync_clients.py", line 47, in handle_result
message="Error in the IoTHub client due to TLS exchanges.", cause=e
azure.iot.device.exceptions.ClientError: ClientError('Error in the IoTHub client due to TLS exchanges.') caused by TlsExchangeAuthError(None)

<環境>
Armadillo-640(Buster)
Python:3.7.3
azure-iot-device:2.7.1
certifi:2021.5.30
/etc/ssl/certs、/usr/local/lib/python3.7/dist-package/ceritfiの
いずれにも、Baltimore_CyberTrust_Rootに関する情報は存在。
certifi.where()で確認すると後者(cacert.pem)が表示されます。
IoTデバイス(認証の種類):対称キー
その他:プロキシーサーバは存在しない。

以上、よろしくお願いいたします。

コメント

at_shinya.koga

2021年7月13日 14時17分

アットマークテクノの古賀です。

fkbenさん:
>Azure IoT Hubにazure-iot-deviceを利用してデータを送信しようとすると
>エラーが発生します。
>同じネットワークに接続しているラズパイでは問題なく通信できて
>いますので、ルータの設定などネットワークの問題ではないという認識です。
>大変お手数ですが、解決策のアドバイスをよろしくお願いいたします。
>
><現象>
>azure-iot-sampleのSimulatedDeviceSync.pyに接続文字列を指定して実行すると
>下記のようなエラーメッセージ(一部抜粋)が出力される。
>
>File "/usr/local/lib/python3.7/dist-packages/azure/iot/device/iothub/sync_clients.py", line 47, in handle_result
> message="Error in the IoTHub client due to TLS exchanges.", cause=e
>azure.iot.device.exceptions.ClientError: ClientError('Error in the IoTHub client due to TLS exchanges.') caused by TlsExchangeAuthError(None)

SimulatedDeviceSync.py ということは、こちらにある、iot-hub/Quickstarts/simulated-device/ にあるサンプルコードをお使いだという認識で、合っているでしょうか?
https://github.com/Azure-Samples/azure-iot-samples-python/tree/master/i…

><環境>
>Armadillo-640(Buster)
>Python:3.7.3
>azure-iot-device:2.7.1
>certifi:2021.5.30
> /etc/ssl/certs、/usr/local/lib/python3.7/dist-package/ceritfiの
> いずれにも、Baltimore_CyberTrust_Rootに関する情報は存在。
> certifi.where()で確認すると後者(cacert.pem)が表示されます。
>IoTデバイス(認証の種類):対称キー
>その他:プロキシーサーバは存在しない。

上記認識で合っている場合、iot-hub/Quickstarts/simulated-device-2/ の方にあるサンプルコード(SimulatedDevice.py)を使う、クイックスタートガイドの手順で行った場合にも同様のエラーになるのかどうか、試してみて頂いてもよろしいでしょうか?
https://docs.microsoft.com/ja-jp/azure/iot-hub/quickstart-control-devic…

以上、取り急ぎお返事です。どうぞ宜しくお願いします。

fkben

2021年7月13日 14時33分

> アットマークテクノの古賀です。
>
> fkbenさん:
> >Azure IoT Hubにazure-iot-deviceを利用してデータを送信しようとすると
> >エラーが発生します。
> >同じネットワークに接続しているラズパイでは問題なく通信できて
> >いますので、ルータの設定などネットワークの問題ではないという認識です。
> >大変お手数ですが、解決策のアドバイスをよろしくお願いいたします。
> >
> ><現象>
> >azure-iot-sampleのSimulatedDeviceSync.pyに接続文字列を指定して実行すると
> >下記のようなエラーメッセージ(一部抜粋)が出力される。
> >
> >File "/usr/local/lib/python3.7/dist-packages/azure/iot/device/iothub/sync_clients.py", line 47, in handle_result
> > message="Error in the IoTHub client due to TLS exchanges.", cause=e
> >azure.iot.device.exceptions.ClientError: ClientError('Error in the IoTHub client due to TLS exchanges.') caused by TlsExchangeAuthError(None)
>
> SimulatedDeviceSync.py ということは、こちらにある、iot-hub/Quickstarts/simulated-device/ にあるサンプルコードをお使いだという認識で、合っているでしょうか?
> https://github.com/Azure-Samples/azure-iot-samples-python/tree/master/i…
>
> ><環境>
> >Armadillo-640(Buster)
> >Python:3.7.3
> >azure-iot-device:2.7.1
> >certifi:2021.5.30
> > /etc/ssl/certs、/usr/local/lib/python3.7/dist-package/ceritfiの
> > いずれにも、Baltimore_CyberTrust_Rootに関する情報は存在。
> > certifi.where()で確認すると後者(cacert.pem)が表示されます。
> >IoTデバイス(認証の種類):対称キー
> >その他:プロキシーサーバは存在しない。
>
> 上記認識で合っている場合、iot-hub/Quickstarts/simulated-device-2/ の方にあるサンプルコード(SimulatedDevice.py)を使う、クイックスタートガイドの手順で行った場合にも同様のエラーになるのかどうか、試してみて頂いてもよろしいでしょうか?
> https://docs.microsoft.com/ja-jp/azure/iot-hub/quickstart-control-devic…
>
>
> 以上、取り急ぎお返事です。どうぞ宜しくお願いします。
>

fkben

2021年7月13日 14時43分

古賀様

お世話になります。早速のご対応ありがとうございます。
返信がおかしくなってしまいましたが無視して下さい。
サンプルコードについてですが、古賀さんのご指摘の通りです。
SimulatedDevice.pyも試してみましたが同じ結果でした。
よろしくお願いいたします。

at_shinya.koga

2021年7月13日 16時27分

アットマークテクノの古賀です。

fkbenさん:
>お世話になります。早速のご対応ありがとうございます。
>返信がおかしくなってしまいましたが無視して下さい。
>サンプルコードについてですが、古賀さんのご指摘の通りです。

了解しました。

>SimulatedDevice.pyも試してみましたが同じ結果でした。

こちらについても、了解しました。
Armadillo-640 については、外付けセンサーと組み合わせた構成で Azure IoT Plug and Play デバイス認定を受けていますが、そちらは、stretch + Pytyon 3.8.9 の組み合わせでした:
- https://devicecatalog.azure.com/devices/1709e739-c2ad-4de8-99ed-7ac17ad…
- https://prtnrsvcstorprdcus.blob.core.windows.net/device-get-started-doc…

buster + Python 3.7.3 ですと、CPU とカーネルが同じ Armadillo-IoT gateway A6 でもデバイス認定を受けており、IoT Hub DPS を認証エンドポイントとして IoT Hub に接続できています:
- https://devicecatalog.azure.com/devices/82e1c942-c398-487b-93fb-9e198b2…
- https://prtnrsvcstorprdcus.blob.core.windows.net/device-get-started-doc…

IoT Hub に直接認証させる場合も問題ないと思いますが、こちらで再現確認してみます。数日お時間を頂くことになるかも知れませんが、結果が出ましたら、お知らせしますので、いましばらくお待ちいただけますか。どうぞ宜しくお願いします。

fkben

2021年7月13日 17時13分

古賀様

ご回答ありがとうございます。IoT Hub DPSなどは利用せずに、シンプルに手動でデバイスを作成し
接続文字列をスクリプトで利用している次第です。
Busterをインストール後に、「# apt-get install Python3」でインストールしたのがPython 3.7.3です。
SORACOM ONYXを認証させる、UVCの有効化のために、カーネルの再構築は行っています。
今回の件とは関係はないとは思いますが…。
現象の再確認よろしくお願いいたします。

> アットマークテクノの古賀です。
>
> fkbenさん:
> >お世話になります。早速のご対応ありがとうございます。
> >返信がおかしくなってしまいましたが無視して下さい。
> >サンプルコードについてですが、古賀さんのご指摘の通りです。
>
> 了解しました。
>
> >SimulatedDevice.pyも試してみましたが同じ結果でした。
>
> こちらについても、了解しました。
> Armadillo-640 については、外付けセンサーと組み合わせた構成で Azure IoT Plug and Play デバイス認定を受けていますが、そちらは、stretch + Pytyon 3.8.9 の組み合わせでした:
> - https://devicecatalog.azure.com/devices/1709e739-c2ad-4de8-99ed-7ac17ad…
> - https://prtnrsvcstorprdcus.blob.core.windows.net/device-get-started-doc…
>
> buster + Python 3.7.3 ですと、CPU とカーネルが同じ Armadillo-IoT gateway A6 でもデバイス認定を受けており、IoT Hub DPS を認証エンドポイントとして IoT Hub に接続できています:
> - https://devicecatalog.azure.com/devices/82e1c942-c398-487b-93fb-9e198b2…
> - https://prtnrsvcstorprdcus.blob.core.windows.net/device-get-started-doc…
>
> IoT Hub に直接認証させる場合も問題ないと思いますが、こちらで再現確認してみます。数日お時間を頂くことになるかも知れませんが、結果が出ましたら、お知らせしますので、いましばらくお待ちいただけますか。どうぞ宜しくお願いします。

at_shinya.koga

2021年7月13日 17時49分

アットマークテクノの古賀です。

fkbenさん:
>ご回答ありがとうございます。IoT Hub DPSなどは利用せずに、シンプルに手動でデバイスを作成し
>接続文字列をスクリプトで利用している次第です。
>Busterをインストール後に、「# apt-get install Python3」でインストールしたのがPython 3.7.3です。

了解しました。こちらでは、ひとまず、
Armadillo-640 + stretch + Python 3.8.9 + azure-iot-device 2.7.0
という組み合わせで、SimulatedDeviceSync.py が問題なく動作することを確認できました。その後、その環境で azure-iot-device を 2.7.1 に upgrade して確認しましたが、問題ありませんでした。

>SORACOM ONYXを認証させる、UVCの有効化のために、カーネルの再構築は行っています。
>今回の件とは関係はないとは思いますが…。

SORACOM ONYX をお使いということは、Azure IoT Hub には、LTE 経由で接続していらっしゃるでしょうか?
こちらは、LAN 経由で接続しています(その違いが影響することは、ないと思いますが)。

>現象の再確認よろしくお願いいたします。

>>buster + Python 3.7.3 ですと、CPU とカーネルが同じ Armadillo-IoT gateway A6 でもデバイス認定を受けており、IoT Hub DPS を認証エンドポイントとして IoT Hub に接続できています:
>> - https://devicecatalog.azure.com/devices/82e1c942-c398-487b-93fb-9e198b2…
>> - https://prtnrsvcstorprdcus.blob.core.windows.net/device-get-started-doc…
>>
>>IoT Hub に直接認証させる場合も問題ないと思いますが、こちらで再現確認してみます。数日お時間を頂くことになるかも知れませんが、結果が出ましたら、お知らせしますので、いましばらくお待ちいただけますか。どうぞ宜しくお願いします。

buster + Python 3.7.3 + azure-iot-device 2.7.1 での結果が出ましたら、追ってお知らせします。

at_shinya.koga

2021年7月13日 18時20分

アットマークテクノの古賀です。

本件ですが、もしかすると、こちらで対策が説明されているのと同じ問題が原因かも知れません:

python3のSSLエラー(CERTIFICATE_VERIFY_FAILED)
https://qiita.com/tommy19970714/items/96edba36dfde468e26f3

fkbenさん(2021年7月13日 13時23分):
>Azure IoT Hubにazure-iot-deviceを利用してデータを送信しようとすると
>エラーが発生します。
>同じネットワークに接続しているラズパイでは問題なく通信できて
>いますので、ルータの設定などネットワークの問題ではないという認識です。
>大変お手数ですが、解決策のアドバイスをよろしくお願いいたします。
>
><現象>
>azure-iot-sampleのSimulatedDeviceSync.pyに接続文字列を指定して実行すると
>下記のようなエラーメッセージ(一部抜粋)が出力される。
>
>File "/usr/local/lib/python3.7/dist-packages/azure/iot/device/iothub/sync_clients.py", line 47, in handle_result
> message="Error in the IoTHub client due to TLS exchanges.", cause=e
>azure.iot.device.exceptions.ClientError: ClientError('Error in the IoTHub client due to TLS exchanges.') caused by TlsExchangeAuthError(None)
>
><環境>
>Armadillo-640(Buster)
>Python:3.7.3
>azure-iot-device:2.7.1
>certifi:2021.5.30
> /etc/ssl/certs、/usr/local/lib/python3.7/dist-package/ceritfiの
> いずれにも、Baltimore_CyberTrust_Rootに関する情報は存在。
> certifi.where()で確認すると後者(cacert.pem)が表示されます。

上の Qiita エントリで説明されているように、certifi.where() が返す python の SSL 証明書のパスを、環境変数 SSL_CERT_FILE に設定してみて下さい。.bashrc での設定が必要ですが、以前に、Armadillo-IoT gateway G3L + buster + Python 3.7.3 で試した時に、SSL_CERT_FILE を設定しないとエラーしたのを思い出しました。

>>>IoT Hub に直接認証させる場合も問題ないと思いますが、こちらで再現確認してみます。数日お時間を頂くことになるかも知れませんが、結果が出ましたら、お知らせしますので、いましばらくお待ちいただけますか。どうぞ宜しくお願いします。
>
>buster + Python 3.7.3 + azure-iot-device 2.7.1 での結果が出ましたら、追ってお知らせします。

SSL_CERT_FILE の設定を追加しても変わらない、という場合には、こちらで再現確認してみますので。

fkben

2021年7月14日 10時09分

古賀様

ご確認ありがとうございます。アドバイスいただきました通り、環境変数(SSL_CERT_FILE)を設定することで
正しくサンプル(SimulatedDeviceSync.py)が実行できるようになりました。Azure側でも受信を確認済み。
ありがとうございました。
今回は一般ユーザで実行しましたが、sudoで実行した場合の対応も行います。
ONYXの利用も考えていますが、今はLANでの確認を行っています。

環境についてですが、strech + python3.8.9、buster+python3.7.3であったりと
状況に応じて色々とあるかと思いますが、推奨の環境がありますか?
漠然とですが、buster で、apt-get、pip3などでデフォルトで取得できる環境、
必要に応じて適宜更新と考えています。
環境に関する記述も行っておりますが、「問題の解決」ありがとうございました。
以上、よろしくお願いいたします。

> アットマークテクノの古賀です。
>
> 本件ですが、もしかすると、こちらで対策が説明されているのと同じ問題が原因かも知れません:
>
> python3のSSLエラー(CERTIFICATE_VERIFY_FAILED)
> https://qiita.com/tommy19970714/items/96edba36dfde468e26f3
>
> fkbenさん(2021年7月13日 13時23分):
> >Azure IoT Hubにazure-iot-deviceを利用してデータを送信しようとすると
> >エラーが発生します。
> >同じネットワークに接続しているラズパイでは問題なく通信できて
> >いますので、ルータの設定などネットワークの問題ではないという認識です。
> >大変お手数ですが、解決策のアドバイスをよろしくお願いいたします。
> >
> ><現象>
> >azure-iot-sampleのSimulatedDeviceSync.pyに接続文字列を指定して実行すると
> >下記のようなエラーメッセージ(一部抜粋)が出力される。
> >
> >File "/usr/local/lib/python3.7/dist-packages/azure/iot/device/iothub/sync_clients.py", line 47, in handle_result
> > message="Error in the IoTHub client due to TLS exchanges.", cause=e
> >azure.iot.device.exceptions.ClientError: ClientError('Error in the IoTHub client due to TLS exchanges.') caused by TlsExchangeAuthError(None)
> >
> ><環境>
> >Armadillo-640(Buster)
> >Python:3.7.3
> >azure-iot-device:2.7.1
> >certifi:2021.5.30
> > /etc/ssl/certs、/usr/local/lib/python3.7/dist-package/ceritfiの
> > いずれにも、Baltimore_CyberTrust_Rootに関する情報は存在。
> > certifi.where()で確認すると後者(cacert.pem)が表示されます。
>
> 上の Qiita エントリで説明されているように、certifi.where() が返す python の SSL 証明書のパスを、環境変数 SSL_CERT_FILE に設定してみて下さい。.bashrc での設定が必要ですが、以前に、Armadillo-IoT gateway G3L + buster + Python 3.7.3 で試した時に、SSL_CERT_FILE を設定しないとエラーしたのを思い出しました。
>
> >>>IoT Hub に直接認証させる場合も問題ないと思いますが、こちらで再現確認してみます。数日お時間を頂くことになるかも知れませんが、結果が出ましたら、お知らせしますので、いましばらくお待ちいただけますか。どうぞ宜しくお願いします。
> >
> >buster + Python 3.7.3 + azure-iot-device 2.7.1 での結果が出ましたら、追ってお知らせします。
>
> SSL_CERT_FILE の設定を追加しても変わらない、という場合には、こちらで再現確認してみますので。

at_shinya.koga

2021年7月14日 13時44分

アットマークテクノの古賀です。

fkbenさん:
>ご確認ありがとうございます。アドバイスいただきました通り、環境変数(SSL_CERT_FILE)を設定することで
>正しくサンプル(SimulatedDeviceSync.py)が実行できるようになりました。Azure側でも受信を確認済み。
>ありがとうございました。

ご連絡有難うございます。解決して何よりです。

>今回は一般ユーザで実行しましたが、sudoで実行した場合の対応も行います。
>ONYXの利用も考えていますが、今はLANでの確認を行っています。

了解しました。

>環境についてですが、strech + python3.8.9、buster+python3.7.3であったりと
>状況に応じて色々とあるかと思いますが、推奨の環境がありますか?
>漠然とですが、buster で、apt-get、pip3などでデフォルトで取得できる環境、
>必要に応じて適宜更新と考えています。

そうですね。現状、出荷時点で stretch の製品もありますが、azure-iot-device の動作要件に自然に対応可能な環境ということで、buster をベースに構築して頂くのが良いと思います。

昨日のコメントに URL を書いた、Azure IoT Plug and Play の認定デバイスカタログの Get Started Guide は、現状の出荷時搭載ユーザーランドが stretch な製品については、strech ベースでの設定手順を記載していますが、apt と pip3 でのインストールだけで環境構築できるという点で、buster の方が便利です。

ただし、buster に関しては、環境変数 SSL_CERT_FILE の問題に加え、curl コマンド(cURL)が参照する外部 CA 証明書の問題もあります。こちらは、update-ca-certificates --fresh を実行することで解決できますが、ご留意ください。詳細は、以下の弊社ブログをご覧ください:

Debian Buster:cURLが失敗してしまう場合の対策について
https://armadillo.atmark-techno.com/blog/10899/9638

>環境に関する記述も行っておりますが、「問題の解決」ありがとうございました。

以上、追加情報でした。参考になりましたら幸いです。

at_shinya.koga

2021年7月14日 14時11分

アットマークテクノの古賀です。

環境変数 SSL_CERT_FILE の問題についての、補足です。
.bashrc で設定するのではなく、アプリケーションで設定する、という方策も可能です。

古賀:
>>ご確認ありがとうございます。アドバイスいただきました通り、環境変数(SSL_CERT_FILE)を設定することで
>>正しくサンプル(SimulatedDeviceSync.py)が実行できるようになりました。Azure側でも受信を確認済み。
>>ありがとうございました。
>
>ご連絡有難うございます。解決して何よりです。
>
>>今回は一般ユーザで実行しましたが、sudoで実行した場合の対応も行います。
>>ONYXの利用も考えていますが、今はLANでの確認を行っています。

>>環境についてですが、strech + python3.8.9、buster+python3.7.3であったりと
>>状況に応じて色々とあるかと思いますが、推奨の環境がありますか?
>>漠然とですが、buster で、apt-get、pip3などでデフォルトで取得できる環境、
>>必要に応じて適宜更新と考えています。
>
>そうですね。現状、出荷時点で stretch の製品もありますが、azure-iot-device の動作要件に自然に対応可能な環境ということで、buster をベースに構築して頂くのが良いと思います。

古賀(2021年7月13日 18時20分):
>上の Qiita エントリで説明されているように、certifi.where() が返す python の SSL 証明書のパスを、環境変数 SSL_CERT_FILE に設定してみて下さい。.bashrc での設定が必要ですが、以前に、Armadillo-IoT gateway G3L + buster + Python 3.7.3 で試した時に、SSL_CERT_FILE を設定しないとエラーしたのを思い出しました。

弊社で公開している、 Azure IoT Plug and Play サンプルアプリケーション(Python で実装)では、/etc/os-release を見て、buster 以降であれば、環境変数 SSL_CERT_FILE に certif.where() の戻り値をセットするようにしています:
https://github.com/atmark-techno/Azure-IoT-samples/blob/162f8810b516ed8…

以上、もし参考になりましたら幸いです。

fkben

2021年7月14日 16時00分

古賀様

ご回答ありがとうございます。
busterでの開発が便利、ただし、CA関連で工夫が必要という件、了解いたしました。
この方向性で進めてみます。
丁寧なご対応ありがとうございました。

> アットマークテクノの古賀です。
>
> 環境変数 SSL_CERT_FILE の問題についての、補足です。
> .bashrc で設定するのではなく、アプリケーションで設定する、という方策も可能です。
>
> 古賀:
> >>ご確認ありがとうございます。アドバイスいただきました通り、環境変数(SSL_CERT_FILE)を設定することで
> >>正しくサンプル(SimulatedDeviceSync.py)が実行できるようになりました。Azure側でも受信を確認済み。
> >>ありがとうございました。
> >
> >ご連絡有難うございます。解決して何よりです。
> >
> >>今回は一般ユーザで実行しましたが、sudoで実行した場合の対応も行います。
> >>ONYXの利用も考えていますが、今はLANでの確認を行っています。
> …
> >>環境についてですが、strech + python3.8.9、buster+python3.7.3であったりと
> >>状況に応じて色々とあるかと思いますが、推奨の環境がありますか?
> >>漠然とですが、buster で、apt-get、pip3などでデフォルトで取得できる環境、
> >>必要に応じて適宜更新と考えています。
> >
> >そうですね。現状、出荷時点で stretch の製品もありますが、azure-iot-device の動作要件に自然に対応可能な環境ということで、buster をベースに構築して頂くのが良いと思います。
>
> 古賀(2021年7月13日 18時20分):
> >上の Qiita エントリで説明されているように、certifi.where() が返す python の SSL 証明書のパスを、環境変数 SSL_CERT_FILE に設定してみて下さい。.bashrc での設定が必要ですが、以前に、Armadillo-IoT gateway G3L + buster + Python 3.7.3 で試した時に、SSL_CERT_FILE を設定しないとエラーしたのを思い出しました。
>
> 弊社で公開している、 Azure IoT Plug and Play サンプルアプリケーション(Python で実装)では、/etc/os-release を見て、buster 以降であれば、環境変数 SSL_CERT_FILE に certif.where() の戻り値をセットするようにしています:
> https://github.com/atmark-techno/Azure-IoT-samples/blob/162f8810b516ed8…
>
> 以上、もし参考になりましたら幸いです。
>