この記事は約2分で読めます。
この記事は1年以上前に書かれたものです。
内容が古い可能性がありますのでご注意ください。
こんにちは! サーバーワークスの松井です。
今回は、AWS IoT 証明書経由で安全にデバイス内にある画像をS3にアップロードする方法をご紹介します。
今回紹介する方法では、AWS Credentialをデバイスに配置しないでAWS環境に画像を送信できるので安全です。
デバイス内にある画像をS3にアップロードする方法としては、AWS IoT のロールエイリアスを使って、一時的にデバイスに権限を与え、AWS CLI経由でアップロードする方法もあります。
ロールエイリアスの使い方は、以下のブログをご参考ください。
事前準備
・IoT Coreでのモノの作成
・デバイスへの証明書の配置
・デバイスに画像を配置
・python3.9が実行できる環境
・画像のアップロード先のS3バケットの作成
・S3へのPUT権限がついているpython環境のLambdaの作成
・Cloud9を作成
1. 画像送信プログラムを作成
Cloud9に画像送信プログラムを配置します。
以下のディレクトリ階層にてプログラムを作成していきます。
・ ├── conf │ └── setting.conf ├── main.py ├── settings.py ├── test.jpg
main.py
import requestsimport jsonimport boto3import settingsfrom boto3.session import Sessioncert_filepath = settings.CERT_PATHpri_key_filepath = settings.PRIVATE_KEY_PATHca_filepath = settings.CA_FILE_PATHendpoint = settings.IOT_CREDENTIAL_ENDPOINTdevice_id = settings.DEVICE_IDdef main():# mqtt クライアント初期化mqtt_connection = init_mqtt()img_file = open("./test.jpg", 'rb').read()bin = base64.b64encode(img_file).decode("utf-8")data = {"img": bin,}send_to_iot_core(mqtt_connection, data)def init_mqtt() -> mqtt.Connection:# mqtt クライアントを初期化するtry:event_loop_group = io.EventLoopGroup(1)host_resolver = io.DefaultHostResolver(event_loop_group)client_bootstrap = io.ClientBootstrap(event_loop_group, host_resolver)mqtt_connection = mqtt_connection_builder.mtls_from_path(endpoint=settings.IOT_CREDENTIAL_ENDPOINT,cert_filepath=settings.CERT_PATH,pri_key_filepath=settings.PRIVATE_KEY_PATH,client_bootstrap=client_bootstrap,ca_filepath=settings.ROOT_CA_PATH,client_id=settings.DEVICE_ID,clean_session=False,keep_alive_secs=settings.KEEP_ALIVE,)# 接続開始connected_future = mqtt_connection.connect()# 利用可能になるまで待機connected_future.result()logger.info("mqtt connenction Successed")return mqtt_connectionexcept Exception:logger.exception("Error")raiseif __name__ == "__main__":main()
settings.py
import osimport configparserfrom logging import config# 環境変数設定conf = configparser.ConfigParser()conf.read(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'conf/setting.conf'), encoding='UTF-8')# DEVICEDEVICE_ID = conf['DEVICE']['DEVICE_ID']CERT_PATH = conf['DEVICE']['CERT_PATH']PRIVATE_KEY_PATH = conf['DEVICE']['PRIVATE_KEY_PATH']ROOT_CA_PATH = conf['DEVICE']['ROOT_CA_PATH']# AWSIOT_CREDENTIAL_ENDPOINT = conf['AWS']['IOT_CREDENTIAL_ENDPOINT']
setting.conf
[DEVICE] DEVICE_ID = xxx # デバイス名 CERT_PATH = xxx # 証明書配置パス PRIVATE_KEY_PATH = xxx # 秘密鍵配置パス ROOT_CA_PATH = xxx # amazon CA1パス [AWS] IOT_CREDENTIAL_ENDPOINT = https://xxx.credentials.iot.ap-northeast-1.amazonaws.com
2 画像アップロード用Lambdaプログラムを作成
作成済みのLambdaを以下のコードに書き換えてデプロイし直します。
import jsonimport boto3import base64from base64 import b64decodefrom decimal import Decimalfrom io import BytesIObucket = "test-image-upload-bucket-1111"key = "test.jpg"def lambda_handler(event, context):for data in event["Records"]:# eventデータをデコードdecoded_data = base64.b64decode(data["kinesis"]["data"]).decode()if decoded_data:json_payload = json.loads(decoded_data, parse_float=Decimal)# eventデータをデコードphoto = json_payload["bin"]decode_photo = b64decode(photo)s3 = boto3.resource('s3')obj = s3.Object(bucket, key)obj.put(Body=BytesIO(decode_picture),ContentType="image/jpg")
3. プログラム実行
Cloud9でプログラムを実行します。
$ python main.py
メッセージのペイロードが128KBを超える画像は送信できないのでご注意ください。
IoT Core ログ
{ "timestamp": "2022-xxxxxxxx", "logLevel": "ERROR", "traceId": "xxxxxxxx", "accountId": "xxxxxxxx", "status": "Failure", "eventType": "Publish-In", "protocol": "MQTT", "topicName": "xxxxxxxx", "clientId": "xxxxxxxx", "principalId": "xxxxxxxx", "sourceIp": "xxxxxxxx", "sourcePort": xxxxxxxx, "reason": "PAYLOAD_LIMIT_EXCEEDED", "details": "Message payload exceeds size limit for message type" }
4. 画像を確認
S3に画像がアップロードされているかを確認してください。
S3からダウンロードした画像が、cloud9に配置していた画像と同じ用に表示されていたら成功です。
5. まとめ
すでにAWS IoT CoreにてAWS環境にデータを送信している方は、ほとんど同じ方法で画像もアップロードが可能なので画像も送信したいという方は是非試してください。
ただし、データ送信の制限は、AWS IoT Coreの送信制限に依存するの小規模容量画像を送信したいシーンでご利用してください。
ありがとうございました。