この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
最近、boto3でIoT Coreにアクセスすると、SSL validation failed
エラーになる事があります。応急処置は下記ブログで紹介されていますが、本記事では根本対応をご紹介します。
環境
ライブラリ | バージョン |
---|---|
boto3 | 1.16.31 |
botocore | 1.19.31 |
certifi | 2020.12.05 |
SSL validation failedエラーが発生する
たとえば、boto3でIoT Coreにアクセスすると、SSL validation failed
が発生します。
下記は、LambdaからIoT CoreのデバイスシャドウをGetする際のエラーメッセージです。
{
"errorMessage": "SSL validation failed for https://data.iot.ap-northeast-1.amazonaws.com/things/led-device/shadow [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1091)",
"errorType": "SSLError",
"stackTrace": [
" File \"/var/task/lambda_function.py\", line 18, in lambda_handler\n res = iot_data.get_thing_shadow(thingName='led-device')\n",
" File \"/var/runtime/botocore/client.py\", line 357, in _api_call\n return self._make_api_call(operation_name, kwargs)\n",
" File \"/var/runtime/botocore/client.py\", line 663, in _make_api_call\n operation_model, request_dict, request_context)\n",
" File \"/var/runtime/botocore/client.py\", line 682, in _make_request\n return self._endpoint.make_request(operation_model, request_dict)\n",
" File \"/var/runtime/botocore/endpoint.py\", line 102, in make_request\n return self._send_request(request_dict, operation_model)\n",
" File \"/var/runtime/botocore/endpoint.py\", line 137, in _send_request\n success_response, exception):\n",
" File \"/var/runtime/botocore/endpoint.py\", line 256, in _needs_retry\n caught_exception=caught_exception, request_dict=request_dict)\n",
" File \"/var/runtime/botocore/hooks.py\", line 356, in emit\n return self._emitter.emit(aliased_event_name, **kwargs)\n",
" File \"/var/runtime/botocore/hooks.py\", line 228, in emit\n return self._emit(event_name, kwargs)\n",
" File \"/var/runtime/botocore/hooks.py\", line 211, in _emit\n response = handler(**kwargs)\n",
" File \"/var/runtime/botocore/retryhandler.py\", line 183, in __call__\n if self._checker(attempts, response, caught_exception):\n",
" File \"/var/runtime/botocore/retryhandler.py\", line 251, in __call__\n caught_exception)\n",
" File \"/var/runtime/botocore/retryhandler.py\", line 277, in _should_retry\n return self._checker(attempt_number, response, caught_exception)\n",
" File \"/var/runtime/botocore/retryhandler.py\", line 317, in __call__\n caught_exception)\n",
" File \"/var/runtime/botocore/retryhandler.py\", line 223, in __call__\n attempt_number, caught_exception)\n",
" File \"/var/runtime/botocore/retryhandler.py\", line 359, in _check_caught_exception\n raise caught_exception\n",
" File \"/var/runtime/botocore/endpoint.py\", line 200, in _do_get_response\n http_response = self._send(request)\n",
" File \"/var/runtime/botocore/endpoint.py\", line 269, in _send\n return self.http_session.send(request)\n",
" File \"/var/runtime/botocore/httpsession.py\", line 281, in send\n raise SSLError(endpoint_url=request.url, error=e)\n"
]
}
Lambdaコード例
import boto3
iot_data = boto3.client('iot-data')
def lambda_handler(event, context):
res = iot_data.get_thing_shadow(thingName='led-device')
print(res)
原因
botocoreが使っているcertifiにおいて、バージョンが2020.11.08から2020.12.05になるとき、Symantec社のルートCA証明書が削除されているためです。 Symantec社の認証局無効化については以前にいろいろ発表されており、certifiが今回その対応をしたことによるものですね。
対応方法:ATSエンドポイントにアクセスする
IoT CoreのATSエンドポイントを使って、アクセスするように修正します。
ATSエンドポイントを取得する
いずれかの方法で取得できます。
- IoT Coreの設定画面でATSエンドポイントを取得する
- AWS CLIコマンドでATSエンドポイントを取得する
IoT Coreの設定画面でATSエンドポイントを取得する
ブラウザでIoT Coreにアクセスし、「設定」にある「カスタムエンドポイント」を使います。
AWS CLIコマンドでATSエンドポイントを取得する
下記コマンドを実行します。
$ aws iot describe-endpoint --endpoint-type iot:Data-ATS
{
"endpointAddress": "xxxxxx-ats.iot.ap-northeast-1.amazonaws.com"
}
boto3でIoT CoreのATSエンドポイントに接続する
boto3.client
のendpoint_url
でATSエンドポイントを明示すればOKです。https://
の付与も忘れないでください。
import boto3
iot_data = boto3.client('iot-data', endpoint_url='https://xxxxxx-ats.iot.ap-northeast-1.amazonaws.com')
def lambda_handler(event, context):
res = iot_data.get_thing_shadow(thingName='led-device')
print(res)
さいごに
ATSエンドポイントが推奨されていることは知っていましたが、「boto3の接続時にATSエンドポイントを明示すること」は盲点でした。 困っている方の参考になれば幸いです。