この記事は個人のメモであり、私の所属する組織を代表するものではありません。また、記事中のコード片はすべてMITライセンスのもの提供されるものとします。
背景
KinesisRecorder + Cognitoを利用してデータをPutする際に以下のようなIAM Roleのパーミッション設定をしてたらハマったのでメモ。このパーミッションだと、Androidでは動くけどiOSではIAMの権限不足のエラーが発生する。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt1420887713000",
"Effect": "Allow",
"Action": [
"kinesis:PutRecord"
],
"Resource": [
"arn:aws:kinesis:ap-northeast-1:YOUR_ACCOUNT_ID:stream/YOUR_STREAM"
]
}
]
}
iOSのKinesisRecorderはPutRecordsを使っていた!
コードを見てみたら、Android版のKinesisRecorderはPutRecord API、iOS版のKinesisRecorderはPutRecords APIを使っているというオチだった。冒頭に書いたIAM RoleのパーミッションだとPutRecords APIは許可されていないのでうまく動いていなかったという話だった。
iOS
https://github.com/aws/aws-sdk-ios/blob/master/Kinesis/AWSKinesisRecorder.m#L309
解決策
なんてほどのたいそうなものではないけど、当該IAM Roleに対してPutRecord、PutRecords両方とも実行パーミッションを与えておけばOKという話でした。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt1420887713000",
"Effect": "Allow",
"Action": [
"kinesis:PutRecord",
"kinesis:PutRecords"
],
"Resource": [
"arn:aws:kinesis:ap-northeast-1:YOUR_ACCOUNT_ID:stream/YOUR_STREAM"
]
}
]
}
参考
検証につかったコードを貼っておく
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
AWSCognitoCredentialsProvider *credentialsProvider = [AWSCognitoCredentialsProvider
credentialsWithRegionType:AWSRegionUSEast1
accountId:@"YOUR_ACCOUNT_ID"
identityPoolId:@"YOUR_IDENTITY_POOL_ID"
unauthRoleArn:@"YOUR_ROLE_ARN"
authRoleArn:nil];
AWSServiceConfiguration *configuration = [AWSServiceConfiguration configurationWithRegion:AWSRegionAPNortheast1
credentialsProvider:credentialsProvider];
[AWSServiceManager defaultServiceManager].defaultServiceConfiguration = configuration;
self.kinesis = [AWSKinesis defaultKinesis];
self.kinesisRecorder = [AWSKinesisRecorder defaultKinesisRecorder];
}
- (IBAction)putRecord:(id)sender {
NSMutableArray *tasks = [NSMutableArray new];
for (int32_t i = 0; i < 100; i++) {
[tasks addObject:[self.kinesisRecorder saveRecord:[[NSString stringWithFormat:@"TestString-%02d", i] dataUsingEncoding:NSUTF8StringEncoding]
streamName:@"YOUR_STREAM"]];
}
[[[BFTask taskForCompletionOfAllTasks:tasks] continueWithSuccessBlock:^id(BFTask *task) {
return [self.kinesisRecorder submitAllRecords];
}] continueWithBlock:^id(BFTask *task) {
if (task.error) {
NSLog(@"Error: [%@]", task.error);
}
return nil;
}];
}
@end