🦝

Redshift serverlessのData APIを利用するときの権限の話

2022/12/07に公開約2,600字

何が起きていたか

AWS GlueでRedshift serverlessのテーブルに対して、boto3を使ってデータを書き込むジョブを作成したが、権限で詰まった。

具体的には、ジョブ時に、cloudwatchに送信されたエラーログに以下のようなエラー文が含まれていました。

'Error': 'ERROR: permission denied for relation test_table',

結論

IAMのポリシーだけではなく、RedshiftでIAMロールに対して権限を付与する(GRANT文を実行する)必要があった。

解説

boto3のRedshiftDataAPIServiceは以下ドキュメント

https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/redshift-data.html

以下は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つ存在することに注意しましょう。

この記事の中での各ロールの目的・役割は以下です。

  • s3-redshift-copy-role

SQL文中で指定するロール
(SQL文中ではarnにより指定します。)

  • executor-role

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

ログインするとコメントできます