Redshift serverlessのData APIを利用するときの権限の話
何が起きていたか
AWS GlueでRedshift serverlessのテーブルに対して、boto3を使ってデータを書き込むジョブを作成したが、権限で詰まった。
具体的には、ジョブ時に、cloudwatchに送信されたエラーログに以下のようなエラー文が含まれていました。
'Error': 'ERROR: permission denied for relation test_table',
結論
IAMのポリシーだけではなく、RedshiftでIAMロールに対して権限を付与する(GRANT文を実行する)必要があった。
解説
boto3のRedshiftDataAPIServiceは以下ドキュメント
以下はredshift serverlessのテーブルにCOPY分を実行するPythonスクリプト例です。
(こちらの記事のサンプルコードを参考にしています。https://dev.classmethod.jp/articles/redshift-dataapi-from-lambda/)
# 実行するSQLを設定
sql = f"""
COPY public.test_table FROM 's3://test_bucket/test_data.ndjson'
REGION 'ap-northeast-1' IAM_ROLE 'arn:aws:iam::***:role/s3-redshift-copy-role'
FORMAT JSON 'noshred';
"""
data_client = boto3.client('redshift-data')
result = data_client.execute_statement(
Database='dev',
Sql=sql,
WorkgroupName='form-sales-tagger-workgroup'
)
# 実行IDを取得
id = result['Id']
print('id = {}'.format(id))
# クエリが終わるのを待つ
statement = ''
status = ''
while status != 'FINISHED' and status != 'FAILED' and status != 'ABORTED':
statement = data_client.describe_statement(Id=id)
#print(statement)
status = statement['Status']
time.sleep(1)
# 結果の表示
if status == 'FINISHED':
if int(statement['ResultSize']) > 0:
# select文等なら戻り値を表示
statement = data_client.get_statement_result(Id=id)
print(json.dumps(statement['Records']))
else:
# 戻り値がないものはFINISHだけ出力して終わり
print('QUERY FINSHED')
elif status == 'FAILED':
# 失敗時
print('QUERY FAILED\n{}'.format(statement))
elif status == 'ABORTED':
# ユーザによる停止時
print('QUERY ABORTED: The query run was stopped by the user.')
SQL文中でIAM_ROLE
を指定していますが、このロールとは別に
このPythonスクリプトを実行するロールが存在するので、ロールが2つ存在することに注意しましょう。
この記事の中での各ロールの目的・役割は以下です。
SQL文中で指定するロール
(SQL文中ではarnにより指定します。)
pythonスクリプトの実行主体のロール
Lambda関数で実行する場合は、関数に割り当てた実行ロール。ローカルで実行する場合はIAMユーザになります。
権限付与の方法
上記スクリプトを正常に実行完了するためには、
s3-redshift-copy-role
だけでなく、executor-role
に対しての権限にも注意する必要があり、
executor-role
にはスキーマへのコマンド実行権限を付与する必要があります。
(この権限はIAMで管理されているものではなく、Redshiftでのクエリ実行により付与する必要があります。)
redshiftのクエリでIAMロールに対して権限を付与する場合、付与対象はIAMR:<ロール名>
と書きます。
例えば以下のコマンド実行により、executor-role
に対してSQLを実行するための権限を付与できます。(権限を適切に絞る必要がある場合は、コマンドを適宜変更してください。)
GRANT ALL PRIVILEGES on ALL TABLES IN SCHEMA public to "IAMR:executor-role";
注意点
redshiftのテーブルを作成したユーザに対しては、そのテーブルを対象とした処理の権限が自動的に付与されます。
このため自分でテーブルを作成した場合、ローカルではスクリプトの実行に成功しますが、
実行ロールが自分のIAMユーザアカウントにならない環境に移植する場合(Lambda関数に載せた場合など)に失敗するようになります。
以上です。
Discussion