はじめに
業務としてクロスアカウントでRedshiftのData APIの実装をすることになりました。
その実装をするにあたって、IAMロール周りの設定がややこしかったため、自分の備忘録も兼ねて記事にしました。
この記事を読んでいただければ、クロスアカウントのIAMロール設定がわかると思います。
今回のテーマとなる構築として、
「アカウントAのLambdaを使用してDataAPIを実装」
→「アカウントBのRedshiftにクエリを投げる」
を想定しています。
その中で、本記事はIAMロールの設定だけにフォーカスしています。
AWSの他サービスで使用するクロスアカウントのIAMロールの設定も基本的な考え方は同じはずなので、お役に立てればと思います。
記事内の登場用語と略称について
登場用語
Redshift・・・列指向型のRDS、速い
Lambda・・・サーバレスのコンピューティングサービス、15分の壁
DataAPI・・・サーバレス、非同期実行でRedshiftクラスターにSQLクエリを投げられるAPI
IAMロール・・・The☆権限(AWSのエラー原因の超常連)
略称
Data API(Lambda)を実装する側のアカウント・・・L垢
Redshiftが存在するアカウント・・・R垢
L垢側のIAMロール設定について
IAMロールコンソール画面から、ロール→ロール作成
信頼されたエンティティタイプで
AWSのサービスを選択
ユースケースでLambdaを選択(今回はLambdaを用いるため)
許可を追加でAmazonRedshiftFullAccessを付与する
信頼されたエンティティに以下のようにR垢のIAMロールを追加する
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": "sts:AssumeRole"
},
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::000000000000:role/R垢のIAMロール"
},
"Action": "sts:AssumeRole"
}
]
}
{
"Version": "2012-10-17",
"Statement": {
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Resource": "arn:aws:iam::000000000000:role/R垢のIAMロール"
}
}
これでL垢側のIAMロール設定は以上になります。
R垢側のIAMロール設定について
L垢と同じようにロール作成を選択
信頼されたエンティティを選択でAWSアカウントを選択
別のアカウントをチェックし、L垢のアカウントID(数字12桁の識別番号)を入力する
許可ポリシーで
AmazonRedshiftFullAccess or RedshiftDataAPI(もしDataAPI用としてユーザ側で作成していた場合)を選択
IAMロール作成後、信頼されたエンティティで以下のようにL垢側のロールが指定できているか確認
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::000000000000:role/L垢のIAMロール"
},
"Action": "sts:AssumeRole",
"Condition": {}
}
]
}
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "GetClusterCredsStatement",
"Effect": "Allow",
"Action": [
"redshift:GetClusterCredentials"
],
"Resource": [
"arn:aws:redshift:*:*:dbname:*/*",
"arn:aws:redshift:*:*:dbuser:Redshiftのユーザ名/RedshiftのDB名"
]
}
]
}
arn:aws:redshift:::dbuser:Redshiftのユーザ名/RedshiftのDB名で、Redshift側のユーザ名とDB名を指定してあげることを忘れないでください。
これでL垢とR垢のIAMロールの設定は正しく行われたはずです。
L垢のLambdaにL垢で作成したIAMロールを設定すれば、問題なくクエリが投げられると思います。
VPCの設定等は不要です。
最後に
今回は2つのアカウントのIAMロールの設定だけにフォーカスしました。
また、Redshiftに適当なクエリを投げるだけにとどまっています。
よくある構築として、
「アカウントAのLambdaを使用してDataAPIを実装」
→「アカウントAのS3のファイルを指定し、アカウントBのRedshiftにCOPYを行う」
も書いていきますので、参考になれば幸いです。
S3に接続する際のエラーについても沼ったので、そこで合わせて共有できればと思います。
エラー集
"An error occurred (AccessDenied) when calling the AssumeRole operation: 〜〜〜〜〜 is not authorized to perform:
L垢側でR垢のIAMロールをアシュームロールした際のエラーです。
IAMロールに権限が足りなかったり、信頼されたエンティティが不適切だったりすると発生します。
アシュームロールがうまく言ってないです。
とりあえず、IAMに設定されている信頼ポリシーや信頼されたエンティティあたりの見直しをしましょう。
"An error occurred (ValidationException) when calling the ExecuteStatement operation:〜〜〜〜〜 is not authorized to perform:
アシュームロールでの実行自体はうまくいっていますが、Redshiftにアクセスするときに想定された操作ができなかったときに出るエラーです。
R垢のIAMロールでインラインポリシー作成内容について、アクセスを行いたいRedshiftの指定が適切に行われているか見てみましょう。
Special Thanks
IAM周りの設定で相談に乗ってくれ、知見を貸してくださった同社内のSさん、Iさん、ありがとうございました!
その他アドバイスをくださった方々ありがとうございました!