[AWS CDK] grantメソッドでAWS Glueテーブルのパーミッションを付与する
こんにちは、CX事業本部 IoT事業部の若槻です。
AWS CDKのドキュメントを見ていると、Glue table constructに次のようなメソッドが用意されていました。
Name | Description |
---|---|
grant(grantee, actions) | Grant the given identity custom permissions. |
grantRead(grantee) | Grant read permissions to the table and the underlying data stored in S3 to an IAM principal. |
grantReadWrite(grantee) | Grant read and write permissions to the table and the underlying data stored in S3 to an IAM principal. |
grantToUnderlyingResources(grantee, actions) | Grant the given identity custom permissions to ALL underlying resources of the table. |
grantWrite(grantee) | Grant write permissions to the table and the underlying data stored in S3 to an IAM principal. |
このgrant**
というメソッドを使えば、Glue tableに対するread/writeなどのパーミッション付与を簡潔に行うことができそうです。
試してみた
grantRead
を使用して、AWS Step Functions state machineに、Glue TableにAthenaクエリを実行ための権限を付与してみます。
環境作成
一連のリソースの作成はAWS CDKで行います。
CDK App初回作成。
mkdir cdk_sample_app && cd cdk_sample_app npx cdk init sample-app --language typescript
なお、aws-cdk-lib
のaws_glue
は現状L1 Constructまでしか対応していません。なので続けて@aws-cdk/aws-glue-alphaを導入しようとしましたが、Conflictが発生。以前のバージョンではすんなり入ったはずなのに...。
$ npm i @aws-cdk/aws-glue-alpha npm ERR! code ERESOLVE npm ERR! ERESOLVE unable to resolve dependency tree npm ERR! npm ERR! While resolving: cdk_sample_app@0.1.0 npm ERR! Found: aws-cdk-lib@2.56.0 npm ERR! node_modules/aws-cdk-lib npm ERR! aws-cdk-lib@"2.56.0" from the root project npm ERR! npm ERR! Could not resolve dependency: npm ERR! peer aws-cdk-lib@"^2.61.1" from @aws-cdk/aws-glue-alpha@2.61.1-alpha.0 npm ERR! node_modules/@aws-cdk/aws-glue-alpha npm ERR! @aws-cdk/aws-glue-alpha@"*" from the root project npm ERR! npm ERR! Fix the upstream dependency conflict, or retry npm ERR! this command with --force, or --legacy-peer-deps npm ERR! to accept an incorrect (and potentially broken) dependency resolution. npm ERR! npm ERR! See /Users/wakatsuki.ryuta/.npm/eresolve-report.txt for a full report.
バージョンを確認するとなぜかaws-cdk-lib
とaws-cdk
が最新版の2.61.1
より古いバージョンが入っていたので最新化した上でならすんなり導入できました。
$ npm i aws-cdk-lib@latest aws-cdk@latest changed 5 packages, and audited 330 packages in 7s 30 packages are looking for funding run `npm fund` for details found 0 vulnerabilities $ npm i @aws-cdk/aws-glue-alpha@latest up to date, audited 330 packages in 2s 30 packages are looking for funding run `npm fund` for details found 0 vulnerabilities
Glue tableのパーミッションを付与しない場合
CDKでstate machineを構成する場合は、タスクの実行に必要なパーミッションを自動作成してくれます。これはAthenaクエリ実行タスク(AthenaStartQueryExecution
)に関してもそうなのですが、一方でクエリ先のGlue tableの権限までは自動付与してくれません。(ただし後述の通りdefault databaseについては付与されます。)
それを踏まえてまずはGlue tableのパーミッションを付与しない場合を試してみます。次のCDK stackを作成します。
import { Construct } from 'constructs'; import { aws_s3, aws_athena, aws_stepfunctions, aws_stepfunctions_tasks, RemovalPolicy, Stack, StackProps, } from 'aws-cdk-lib'; import * as glue_alpha from '@aws-cdk/aws-glue-alpha'; export class CdkSampleStack extends Stack { constructor(scope: Construct, id: string, props: StackProps) { super(scope, id, props); // データソース格納バケット const dataBucket = new aws_s3.Bucket(this, 'dataBucket', { bucketName: `data-${this.account}-${this.region}`, removalPolicy: RemovalPolicy.DESTROY, }); // Athenaクエリ結果格納バケット const athenaQueryResultBucket = new aws_s3.Bucket( this, 'athenaQueryResultBucket', { bucketName: `athena-query-result-${this.account}-${this.region}`, removalPolicy: RemovalPolicy.DESTROY, } ); // Glueデータベース const glueDataBase = new glue_alpha.Database(this, 'glueDataBase', { databaseName: 'glue_data_base', }); // Glueテーブル const glueTable = new glue_alpha.Table(this, 'glueTable', { tableName: 'glue_table', database: glueDataBase, bucket: dataBucket, s3Prefix: 'data/', dataFormat: glue_alpha.DataFormat.JSON, columns: [ { name: 'id', type: glue_alpha.Schema.STRING, }, { name: 'count', type: glue_alpha.Schema.INTEGER, }, ], }); // Athenaワークグループ const athenaWorkGroup = new aws_athena.CfnWorkGroup( this, 'athenaWorkGroup', { name: 'athenaWorkGroup', workGroupConfiguration: { resultConfiguration: { outputLocation: `s3://${athenaQueryResultBucket.bucketName}/result-data`, }, }, recursiveDeleteOption: true, } ); // Athenaクエリ実行(同期実行) new aws_stepfunctions_tasks.AthenaStartQueryExecution( this, 'startAthenaQueryExecutionTask', { queryString: `SELECT * FROM ${glueDataBase.databaseName}.${glueTable.tableName}`, workGroup: athenaWorkGroup.name, integrationPattern: aws_stepfunctions.IntegrationPattern.RUN_JOB, } ); } }
CDKデプロイしてリソースを作成します。
npx cdk deploy "*" --require-approval never
作成されたIAM policyのステートメントは次のようになりました。
{ "Version": "2012-10-17", "Statement": [ { "Action": [ "athena:getDataCatalog", "athena:getQueryExecution", "athena:startQueryExecution" ], "Resource": [ "arn:aws:athena:ap-northeast-1:XXXXXXXXXXXX:datacatalog/AwsDataCatalog", "arn:aws:athena:ap-northeast-1:XXXXXXXXXXXX:workgroup/athenaWorkGroup" ], "Effect": "Allow" }, { "Action": [ "lakeformation:GetDataAccess", "s3:AbortMultipartUpload", "s3:CreateBucket", "s3:GetBucketLocation", "s3:GetObject", "s3:ListBucket", "s3:ListBucketMultipartUploads", "s3:ListMultipartUploadParts", "s3:PutObject" ], "Resource": "*", "Effect": "Allow" }, { "Action": [ "glue:BatchCreatePartition", "glue:BatchDeletePartition", "glue:BatchDeleteTable", "glue:BatchGetPartition", "glue:CreateDatabase", "glue:CreatePartition", "glue:CreateTable", "glue:DeleteDatabase", "glue:DeletePartition", "glue:DeleteTable", "glue:GetDatabase", "glue:GetDatabases", "glue:GetPartition", "glue:GetPartitions", "glue:GetTable", "glue:GetTables", "glue:UpdateDatabase", "glue:UpdatePartition", "glue:UpdateTable" ], "Resource": [ "arn:aws:glue:ap-northeast-1:XXXXXXXXXXXX:catalog", "arn:aws:glue:ap-northeast-1:XXXXXXXXXXXX:database/default", "arn:aws:glue:ap-northeast-1:XXXXXXXXXXXX:table/default/*", "arn:aws:glue:ap-northeast-1:XXXXXXXXXXXX:userDefinedFunction/default/*" ], "Effect": "Allow" } ] }
最初の2つはAthena workgroupの利用に必要なパーミッションです。3つ目はデフォルトのGlue databaseおよびその中に作成されたtableに対するパーミッションです。今回はGlue databaseおよびtableをCDKで独自に作成しているためこの記述では権限が不足してしまいそうです。
作成されたstate mmachineを実行すると、Glue tabelへのパーミッション不足によりAthena queryがエラーとなりました。想定通りの動作です。
Glue tableのパーミッションを付与した場合
Stack定義を次のように修正します。grantRead
メソッドでGlue tableへの読み取りパーミッションをstate machineに付与しています。
// State Machine const stateMachine = new aws_stepfunctions.StateMachine( this, 'stateMachine', { stateMachineName: 'stateMachine', definition: startAthenaQueryExecutionTask, } ); // Glue tableの権限付与 glueTable.grantRead(stateMachine);
CDKデプロイすると、IAM policyのステートメントに次の記述が追加されました。独自に作成したGlue tableに対する権限が付与されていますね。
{ "Action": [ "glue:BatchGetPartition", "glue:GetPartition", "glue:GetPartitions", "glue:GetTable", "glue:GetTableVersion", "glue:GetTableVersions", "glue:GetTables" ], "Resource": "arn:aws:glue:ap-northeast-1:XXXXXXXXXXXX:table/glue_data_base/glue_table", "Effect": "Allow" }, { "Action": [ "s3:GetBucket*", "s3:GetObject*", "s3:List*" ], "Resource": [ "arn:aws:s3:::data-XXXXXXXXXXXX-ap-northeast-1", "arn:aws:s3:::data-XXXXXXXXXXXX-ap-northeast-1/data/*" ], "Effect": "Allow" }
これで十分な権限を付与できてかと思いましたが、Glue databaseに対する権限が不足していました。
Glue databaseに関しても独自に作成している場合は権限の付与が必要なるようです。tableに対するgrantだけではよろしくやってくれないのですね。
仕方がないのでGlue databaseのみ明示的に権限を付与します。
// Glue databaseの権限付与 stateMachine.role.addToPrincipalPolicy( new aws_iam.PolicyStatement({ actions: ['glue:Get*'], effect: aws_iam.Effect.ALLOW, resources: [glueDataBase.databaseArn], }) );
今度こそstate machineの実行を成功させられました。
まとめ
- Athena workgroupの権限はstate machineリソースの作成時に暗黙的に付与される
- Glue tableの権限はgrantReadで簡潔に付与できる
- Glue databaseの権限はaddToPrincipalPolicyなどで明示的に付与が必要
grantメソッドは万能ではなく必要に応じて個別の権限付与は必要でしたが、便利なことには変わりないので有効活用して行きたいです。
参考
以上