AWSIoT 대형 데이터 업로드 패턴 구현
AWSIoT 대형 데이터 업로드 패턴 구현
이 Blackbelt 세미나 의 「대형 데이터 업데이트 패턴」을 실장하려고 하면, 미숙이기 때문에 상당히 여러가지 막혔으므로, 방법을 정리할 것입니다.
AWSIoT Thing 생성
이 엔은 보통으로 만들 뿐이므로, 적당하게 흘립니다.
디바이스명은 device00, 이하와 같은 Policy를 작성해, attach 해 둡니다.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "iot:Connect",
"Resource": [
"arn:aws:iot:ap-northeast-1:[YOUR_ACCOUNT_ID]:client/device00"
]
},
{
"Effect": "Allow",
"Action": "iot:Publish",
"Resource": "arn:aws:iot:ap-northeast-1:[YOUR_ACCOUNT_ID]:topic/device00/token/req"
},
{
"Effect": "Allow",
"Action": "iot:Subscribe",
"Resource": "arn:aws:iot:ap-northeast-1:[YOUR_ACCOUNT_ID]:topicfilter/device00/token/res"
},
{
"Effect": "Allow",
"Action": "iot:Receive",
"Resource": "arn:aws:iot:ap-northeast-1:[YOUR_ACCOUNT_ID]:topic/device00/token/res"
}
]
}
또한 인증서 다운로드도 수행합니다.
IAM 역할 설정
이 후 Lambda에서 Token 게시 프로세스와 장치에서 S3에 업로드 프로세스를 만듭니다.
함수 작성시 해당 처리의 실행 권한을 가진 IAM 역할이 필요하기 때문에 먼저 만들어 둡니다.
S3 업로드 처리 역할
장치에 전달하는 STS에 허용할 권한을 부여한 역할을 "s3-role"로 정의합니다.
여기에서는 임의 버킷 이하에 PutObject만을 할 수 있는 권한을 부여해 둡니다.
실제로는 버킷 아래의 장치 이름이 있는 폴더에만 업로드할 수 있도록 할 계획입니다.
STS 발급시 역할 권한을 제한하는 형태로 추가하므로 여기에서는 버킷 이하에의 쓰기 권한을 부여합니다.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Action": [
"s3:PutObject"
],
"Resource": [
"arn:aws:s3:::[YOUR_BACKET_NAME]/*"
]
}
]
}
STS 발급 처리 역할
"s3-role"의 역할 권한을 부여한 STS를 만드는 Lambda 함수에 부여하는 역할 권한을
"create-token"역할로 만듭니다.
Lambda 함수를 실행하므로 기존 정책의 첨부에서 "AWSLambdaBasicExecutionRole"을 부여합니다.
또, 작성한 STS를 AWSIoT의 기능으로 Publish 하므로, 그것을 위한 권한도 부여합니다.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Action": [
"iot:Publish"
],
"Resource": [
"arn:aws:iot:ap-northeast-1:[YOUR_ACCOUNT_ID]:topic/device00/token/res"
]
}
]
}
그리고 STS에 s3-role 권한을 부여하는 권한도 추가합니다.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Resource": "arn:aws:iam::[YOUR_ACCOUNT_ID]:role/s3-role"
}
]
}
또한 s3-role 측에서 create-token 역할을 신뢰하고 AssumeRole을 허용하는 취지의 설정을 해야 합니다.
s3-role 설정 화면에서 "신뢰 관계"탭을 선택하고 "신뢰 관계 편집"을 실행하고 편집기에서
JSON의 "Statement"요소 배열에 다음을 추가합니다.
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::[YOUR_ACCOUNT_ID]:role/create-token"
},
"Action": "sts:AssumeRole"
}
STS 생성 및 디바이스로의 토큰 전송 처리
STS를 게시하고 AWSIoT를 통해 지정된 Topic에 Token을 게시하는 Lambda 프로세스를 만듭니다.
이번에는 슬라이드의 구성에 따라 Topic 경유의 publish로 했습니다만, STS를 사용한 통신이 자주
발생한다고 가정하면 Lambda를 스케줄 시작으로 설정하고 DeviceShadow를 사용하여 정기적으로
Push로 통보하는 것이 더 낫습니다.
import boto3
import json
def lambda_handler(event, context):
sts = boto3.client('sts')
iotData = boto3.client('iot-data')
thingName=event['name']
token = sts.assume_role(
RoleArn="arn:aws:iam::[YOUR_ACCOUNT_ID]:role/s3-role",
RoleSessionName=thingName,
Policy=json.dumps({
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Action": [
"s3:PutObject"
],
"Resource": [
"arn:aws:s3:::large-data-upload-pattern/"+thingName+"/*"
]
}
]
})
)
iotData.publish(
topic=thingName+'/token/res',
qos=1,
payload=json.dumps({
"AccessKeyId": token['Credentials']['AccessKeyId'],
"SecretAccessKey": token['Credentials']['SecretAccessKey'],
"SessionToken": token['Credentials']['SessionToken']
})
)
event 객체의 멤버 'name'에서 장치 이름을 가져 왔지만 여기에 장치 이름을 설정하기 위해
설정은 다음 섹션에서 수행됩니다.
AWSIoT에서 STS 게시 요청 수신
AWSIoT에서 "*/token/req"의 토픽에 토큰 발행 요청이 게시되면 위의 람다를 시작하십시오.
규칙을 만듭니다.
"Rule query statement"가 다음과 같이 설정되고 Action은 Lambda 시작을 선택하고 앞에서 설명합니다.
함수를 지정합니다.
SELECT topic(1) AS name FROM '+/token/req'
지금까지의 설정에서 AWSIoT 콘솔의 "Test"에서 "device00/token/req"로 메시지 (비어 있음)
제출하면 Token이 "device00/token/res"에 publish되는 것을 확인할 수 있습니다.
그리고는 동작 확인입니다.
STS 얻기
아래 샘플 스크립트를 실행하면 "device00/token/req"에 토큰 발행 요청을 보내고,
"device00/token/res"에서 토큰을 검색하여 표준 출력에 표시합니다.
from AWSIoTPythonSDK.MQTTLib import AWSIoTMQTTClient
import json
import time
def cb(client, userdata, message):
print("got message")
print(message.payload)
host="[IOT_ENDPOINT_DOMAIN]"
rootCAPath = "[ROOT_CA_FILE_PATH]"
certificatePath = "[CERTIFICATE_FILE_PATH]"
privateKeyPath = "[PRIVATE_KEY_FILE_PATH]"
myAWSIoTMQTTClient = None
myAWSIoTMQTTClient = AWSIoTMQTTClient("device00")
myAWSIoTMQTTClient.configureEndpoint(host, 8883)
myAWSIoTMQTTClient.configureCredentials(rootCAPath, privateKeyPath, certificatePath)
myAWSIoTMQTTClient.configureAutoReconnectBackoffTime(1, 32, 20)
myAWSIoTMQTTClient.configureOfflinePublishQueueing(-1)
myAWSIoTMQTTClient.configureDrainingFrequency(2)
myAWSIoTMQTTClient.configureConnectDisconnectTimeout(10)
myAWSIoTMQTTClient.configureMQTTOperationTimeout(5)
myAWSIoTMQTTClient.connect()
myAWSIoTMQTTClient.subscribe("device00/token/res", 1, cb)
time.sleep(2)
myAWSIoTMQTTClient.publish("device00/token/req", json.dumps({}), 1)
while True:
time.sleep(5)
S3에 업로드
취득한 토큰을 이용하여 아래의 샘플 스크립트로 적당히 S3에 업로드해 보겠습니다.
import boto3
AWS_S3_BUCKET_NAME = '[YOUR_BACKET_NAME]'
s3 = boto3.resource(
's3',
aws_access_key_id="[ACCESS_KEY]",
aws_secret_access_key="[SECRET_KEY]",
aws_session_token="[SESSION_TOKEN]"
)
bucket = s3.Bucket(AWS_S3_BUCKET_NAME)
obj = bucket.Object("device00/hogehoge")
response = obj.put(
Body="hogehogehogehoge".encode('utf-8'),
ContentEncoding='utf-8',
ContentType='text/plane'
)
요약
정리해 보면 큰 일은 아닙니다만, AssumeRole라든지 권한 주위로 여러가지 막혀 잘 모르기 때문에 힘들었습니다.
Reference
이 문제에 관하여(AWSIoT 대형 데이터 업로드 패턴 구현), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/haiiro-shimeji/items/cc172172bdd041dbbbc4
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "iot:Connect",
"Resource": [
"arn:aws:iot:ap-northeast-1:[YOUR_ACCOUNT_ID]:client/device00"
]
},
{
"Effect": "Allow",
"Action": "iot:Publish",
"Resource": "arn:aws:iot:ap-northeast-1:[YOUR_ACCOUNT_ID]:topic/device00/token/req"
},
{
"Effect": "Allow",
"Action": "iot:Subscribe",
"Resource": "arn:aws:iot:ap-northeast-1:[YOUR_ACCOUNT_ID]:topicfilter/device00/token/res"
},
{
"Effect": "Allow",
"Action": "iot:Receive",
"Resource": "arn:aws:iot:ap-northeast-1:[YOUR_ACCOUNT_ID]:topic/device00/token/res"
}
]
}
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Action": [
"s3:PutObject"
],
"Resource": [
"arn:aws:s3:::[YOUR_BACKET_NAME]/*"
]
}
]
}
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Action": [
"iot:Publish"
],
"Resource": [
"arn:aws:iot:ap-northeast-1:[YOUR_ACCOUNT_ID]:topic/device00/token/res"
]
}
]
}
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Resource": "arn:aws:iam::[YOUR_ACCOUNT_ID]:role/s3-role"
}
]
}
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::[YOUR_ACCOUNT_ID]:role/create-token"
},
"Action": "sts:AssumeRole"
}
import boto3
import json
def lambda_handler(event, context):
sts = boto3.client('sts')
iotData = boto3.client('iot-data')
thingName=event['name']
token = sts.assume_role(
RoleArn="arn:aws:iam::[YOUR_ACCOUNT_ID]:role/s3-role",
RoleSessionName=thingName,
Policy=json.dumps({
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Action": [
"s3:PutObject"
],
"Resource": [
"arn:aws:s3:::large-data-upload-pattern/"+thingName+"/*"
]
}
]
})
)
iotData.publish(
topic=thingName+'/token/res',
qos=1,
payload=json.dumps({
"AccessKeyId": token['Credentials']['AccessKeyId'],
"SecretAccessKey": token['Credentials']['SecretAccessKey'],
"SessionToken": token['Credentials']['SessionToken']
})
)
SELECT topic(1) AS name FROM '+/token/req'
from AWSIoTPythonSDK.MQTTLib import AWSIoTMQTTClient
import json
import time
def cb(client, userdata, message):
print("got message")
print(message.payload)
host="[IOT_ENDPOINT_DOMAIN]"
rootCAPath = "[ROOT_CA_FILE_PATH]"
certificatePath = "[CERTIFICATE_FILE_PATH]"
privateKeyPath = "[PRIVATE_KEY_FILE_PATH]"
myAWSIoTMQTTClient = None
myAWSIoTMQTTClient = AWSIoTMQTTClient("device00")
myAWSIoTMQTTClient.configureEndpoint(host, 8883)
myAWSIoTMQTTClient.configureCredentials(rootCAPath, privateKeyPath, certificatePath)
myAWSIoTMQTTClient.configureAutoReconnectBackoffTime(1, 32, 20)
myAWSIoTMQTTClient.configureOfflinePublishQueueing(-1)
myAWSIoTMQTTClient.configureDrainingFrequency(2)
myAWSIoTMQTTClient.configureConnectDisconnectTimeout(10)
myAWSIoTMQTTClient.configureMQTTOperationTimeout(5)
myAWSIoTMQTTClient.connect()
myAWSIoTMQTTClient.subscribe("device00/token/res", 1, cb)
time.sleep(2)
myAWSIoTMQTTClient.publish("device00/token/req", json.dumps({}), 1)
while True:
time.sleep(5)
import boto3
AWS_S3_BUCKET_NAME = '[YOUR_BACKET_NAME]'
s3 = boto3.resource(
's3',
aws_access_key_id="[ACCESS_KEY]",
aws_secret_access_key="[SECRET_KEY]",
aws_session_token="[SESSION_TOKEN]"
)
bucket = s3.Bucket(AWS_S3_BUCKET_NAME)
obj = bucket.Object("device00/hogehoge")
response = obj.put(
Body="hogehogehogehoge".encode('utf-8'),
ContentEncoding='utf-8',
ContentType='text/plane'
)
Reference
이 문제에 관하여(AWSIoT 대형 데이터 업로드 패턴 구현), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/haiiro-shimeji/items/cc172172bdd041dbbbc4텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)