やりたかったこと
Sparkで実行される分散処理アプリケーションが存在。内容としては別アカウントのS3のログファイルを読み込み、自アカウントのS3に整形されたログを配置する。
解決策
-
バケット自体に特定のAWSアカウントからの読み込みができるようにバケットポリシーを変更する
-
クロスアカウントの情報(AWS STS)を使って一時的な認証情報をSpark上に読み込ませて使おうとしましたが、ダメでした。
今回は1, 2の紹介をします。
特定のAWSアカウントから読めるようにバケットポリシーを変更する
S3を開き、「バケットポリシーの追加」を選択
下記を追加する(既存のポリシーがあると思うので必要な部分だけ使ってください)
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "GetObject",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::AWSアカウント番号:root"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::読み込ませたいバケット/*"
},
{
"Sid": "ListBucket",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::AWSアカウント番号root"
},
"Action": "s3:ListBucket",
"Resource": "arn:aws:s3:::読みこませたいバケット"
}
]
}
STSを使った認証でEMRからS3にアクセスができない理由
結論から言うとhadoop ver 2.7.2では、一時認証が対応していない?
spark上では、認証情報は下記のようなコードを書く(Scalaのコードです)
sc.hadoopConfiguration.set("fs.s3.awsAccessKeyId", xxxxxxxxxx)
sc.hadoopConfiguration.set("fs.s3.awsSecretAccessKey", xxxxxxxxxx)
一時認証の取得は以下となります(pythonです)
import sys, codecs, boto3
import datetime
import csv
import gzip
sts_client = boto3.client('sts')
assumedRoleObject = sts_client.assume_role(
RoleArn="arn:aws:iam::クロスアカウントを設定したIamRole",
RoleSessionName="セッションに使う名前(適当でOKかも?)"
)
aws_access_key_id = credentials['AccessKeyId'],
aws_secret_access_key = credentials['SecretAccessKey'],
aws_session_token = credentials['SessionToken']
上記のように取得できた、
- アクセスキー
- シークレットキー
- セッショントークン
を使ってpython上では別アカウントのS3の読み込みができました。
同じようにspark上でやろうとしたら、
セッショントークンどうやって入れるんだろ?
という問題にぶち当たりました。
hadoopの公式サイトにもアクセスキー、シークレットキーの2つしか対応していないぽいらしく
できないという雑談が公式のissueとして上がっているっぽいです。
https://issues.apache.org/jira/browse/HADOOP-9680
結論
先日(2016/08/03)、EMRのメジャーアップデートがありました。
この段階ではまだ、hadoopは2.7.2のままでした。
今後のアップデートで一時認証に対応するかもしれませんが、
今はバケット自体にアクセス許可をするのが一番早いかも。