Lambda から Transcribe の StartCallAnalyticsJob を実行する際に必要な IAM ロールについて
アノテーションの中村 (誠) です。
先日、Lambda から Transcribe の StartCallAnalyticsJob を実行する際に、IAM ロール関連でハマったので、原因と解決策を紹介します。
結論
StartCallAnalyticsJob
を実行するには、Transcribe を信頼されたエンティティとした IAM ロールが必要です。
ハマった環境
S3
S3 バケットはデフォルト設定で作成し、mp3 ファイルをアップロードしました。
Lambda
・ランタイム
Python 3.9
・実行ロール
以下の IAM ポリシーを付与しました。
AWSLambdaBasicExecutionRole
AmazonS3FullAccess
AmazonTranscribeFullAccess
・コード
import boto3 transcribe = boto3.client('transcribe') def lambda_handler(event, context): response = transcribe.start_call_analytics_job( CallAnalyticsJobName='test', Media={ 'MediaFileUri': '{S3-Object-URI}' }, DataAccessRoleArn='{Lambda-Execution-Role}', ChannelDefinitions=[ { 'ChannelId': 0, 'ParticipantRole': 'AGENT' }, { 'ChannelId': 1, 'ParticipantRole': 'CUSTOMER' } ] ) print(response)
ハマったこと
ここまでの設定で Lambda 関数を実行したところ、以下のエラーが発生しました。
An error occurred (AccessDeniedException) when calling the StartCallAnalyticsJob operation: User: arn:aws:sts::{Account-ID}:assumed-role/{Lambda-Execution-Role}/Transcribe-function is not authorized to perform: iam:PassRole on resource: arn:aws:iam::{Account-ID}:role/{Lambda-Execution-Role} because no identity-based policy allows the iam:PassRole action
iam:PassRole
のアクセス許可がないというエラーです。
AWS のサービスにロールを渡すアクセス権限をユーザーに付与する - AWS Identity and Access Management
ユーザーがロール (とそのアクセス許可) を AWS サービスに渡すには、そのサービスにロールを渡すアクセス許可が必要になります。これにより、承認済みのユーザーのみが、アクセス許可を付与するロールを使用してサービスを設定できるようになります。ユーザーが AWS サービスにロールを渡すには、IAM ユーザー、ロール、またはグループに PassRole アクセス許可を付与する必要があります。
こちらのエラーは、Lambda の実行ロールに iam:PassRole
の権限を付与することで解決できました。
{ "Version": "2012-10-17", "Statement": [ { "Sid": "VisualEditor0", "Effect": "Allow", "Action": "iam:PassRole", "Resource": "arn:aws:iam::{Account-ID}:role/*" } ] }
この時点で Lambda の実行ロールに付与した権限は以下のようになりました。
この状態で再度 Lambda 関数を実行したところ、以下のエラーメッセージに変わりました。
An error occurred (BadRequestException) when calling the StartCallAnalyticsJob operation: The S3 URI that you provided can't be accessed. Make sure that you have read permission and try your request again.
今度は S3 にアップロードしたオブジェクトへのアクセスができていないというエラーのようです。
S3 へのアクセス権限は AmazonS3FullAccess
で付与しており、同じアカウント内なのでバケットポリシーは設定しなくてもアクセスできるはずですが、エラーになってしまいました。
CloudTrail で調べてみた
StartCallAnalyticsJob
を実行している userIdentity は以下の通り Lambda 関数の実行ロールでした。
arn:aws:sts::{Account-ID}:assumed-role/{Lambda-Execution-Role}/Transcribe-function
アクセス権限は S3 、Transcribe ともに FullAccess
なので、Lambda の実行ロールのアクセス権限は問題ないと思っていました。
コンソールで StartCallAnalyticsJob をやってみる
Transcribe コンソールでも StartCallAnalyticsJob
を実行可能なことがわかったので、AWS 公式ドキュメント を参考に、Transcribe コンソールから StartCallAnalyticsJob
を実行してみました。
Name を入力し、Language は日本語を指定しました。
Input data は S3 にアップロードしてある mp3 ファイルを指定しました。
IAM ロールを作成する必要があるようなので、「Create an IAM role」を選択して新しく IAM ロールを作成しました。
その他の設定はデフォルトのまま、「Create job」をクリックして、ジョブを作成しました。
ジョブが始まり、しばらく Status が In progess
となります。
しばらく待つと、Status が Complete
になったので、ジョブの詳細を確認してみます。
画面下部の Application integration で DataAccessRoleArn
を確認したところ、自動的に作成された IAM ロールが指定されていたので、この中身を IAM コンソールで確認してみます。
IAM コンソールで確認
Transcribe コンソールで StartCallAnalyticsJob
を実行した際に自動的に作成された IAM ロールを確認してみます。
AmazonTranscribeServiceRole-{input-role-name}
という名前の IAM ロールが作成されていました。
同時に AmazonTranscribeServicePolicy-{input-role-name}
という IAM ポリシーも作成、アタッチされており、必要な権限も付与されていました。
{ "Version": "2012-10-17", "Statement": [ { "Action": ["s3:GetObject"], "Resource": ["arn:aws:s3:::{s3-bucket-name}/*"], "Effect": "Allow" }, { "Action": ["s3:ListBucket"], "Resource": ["arn:aws:s3:::{s3-bucket-name}"], "Effect": "Allow" }, { "Action": ["kms:Decrypt"], "Resource": ["arn:aws:kms:ap-northeast-1:{Account-ID}:key/*"], "Condition": { "StringLike": { "kms:ViaService": ["s3.*.amazonaws.com"] } }, "Effect": "Allow" } ] }
信頼関係も確認してみます。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "transcribe.amazonaws.com" }, "Action": "sts:AssumeRole" } ] }
なんと、信頼関係の Principal
に指定されていたのは、transcribe.amazonaws.com
でした。
先述のエラーはこの部分に関連していると推測したので、自動的に作成されたこちらの IAM ロールを Lambda 関数コード内の DataAccessRoleArn
に指定してみました。
解決策
Lambda 関数の DataAccessRoleArn
を以下のように変更しました。
import boto3 transcribe = boto3.client('transcribe') def lambda_handler(event, context): response = transcribe.start_call_analytics_job( CallAnalyticsJobName='test', Media={ 'MediaFileUri': '{S3-Object-URI}' }, DataAccessRoleArn='{IAM role automatically created by transcribe}', # 変更箇所 ChannelDefinitions=[ { 'ChannelId': 0, 'ParticipantRole': 'AGENT' }, { 'ChannelId': 1, 'ParticipantRole': 'CUSTOMER' } ] ) print(response)
この状態で再度 Lambda 関数を実行したところ、以下のエラーメッセージに変わりました。
An error occurred (ConflictException) when calling the StartCallAnalyticsJob operation: The requested job name already exists. Use a different job name.
同じジョブ名があるというエラーなので、先ほどコンソールで実行したジョブを削除します。
再度 Lambda 関数を実行します。
今度は成功しました!
Transcribe コンソールでもジョブが作成されています。
しばらく待つと、Status が Complete
となったので、問題なく実行できました。
Lambda 関数から StartCallAnalyticsJob を実行した際の挙動
上記の検証から、以下のような挙動になっていると思われます。
- Lambda 関数を実行
- Lambda 関数から
StartCallAnalyticsJob
を実行 - Lambda 関数から
StartCallAnalyticsJob
のパラメーターに指定したDataAccessRoleArn
へPassRole
DataAccessRoleArn
に指定した IAM ロールの権限で Transcribe が分析のために S3 などの AWS リソースへアクセス
Lambda 実行ロールに必要な権限の見直し
先述の挙動から、Lambda 実行ロールに必要な権限を見直しました。
StartCallAnalyticsJob
を実行する IAM ロールには、先述の通り自動的に作成された IAM ポリシーが付与されています。このことから、Lambda 実行ロールに付与していた S3 へのアクセス権限は不要だと推測しました。
さらに、Lambda 関数から PassRole
していることから、 Transcribe への FullAccess
権限も不要だと推測したので、以下の 2 つの権限を外しました。
・AmazonS3FullAccess
・AmazonTranscribeFullAccess
ただし、Transcribe の StartCallAnalyticsJob
を実行する権限は必要だったため、Transcribe に関する権限は以下のように修正しました。
{ "Version": "2012-10-17", "Statement": [ { "Sid": "VisualEditor0", "Effect": "Allow", "Action": "transcribe:StartCallAnalyticsJob", "Resource": "*" } ] }
最終的に、Lambda 実行ロールは以下の状態になりました。
この状態でも Lambda 関数の実行は成功しました。
今回は Resource
までは指定しませんでしたが、Action
に関しては必要最小限に絞ることができました。
まとめ
今回は、Lambda から Transcribe の StartCallAnalyticsJob
を実行する際に、IAM ロール関連でハマったので、原因と解決策を紹介しました。
あらためてポイントをまとめてみました。
・Lambda 関数から StartCallAnalyticsJob
を実行するには、DataAccessRoleArn
へ PassRole
する権限が必要
・StartCallAnalyticsJob
を実行するための IAM ロールには 信頼関係の Principal
で transcribe.amazonaws.com
を指定する必要がある
・Transcribe コンソールから StartCallAnalyticsJob
を実行することで、必要な権限を持った IAM ロールを自動的に作成することが可能
・StartCallAnalyticsJob
の DataAccessRoleArn
には、信頼関係の Principal
で transcribe.amazonaws.com
を指定した IAM ロールを指定する
参考になれば幸いです。
参考資料
- StartCallAnalyticsJob - Transcribe
- TranscribeService — Boto3 Docs 1.22.9 documentation
- AWS のサービスにロールを渡すアクセス権限をユーザーに付与する - AWS Identity and Access Management
- Starting a Call Analytics job - Amazon Transcribe
アノテーション株式会社について
アノテーション株式会社は、クラスメソッド社のグループ企業として「オペレーション・エクセレンス」を担える企業を目指してチャレンジを続けています。「らしく働く、らしく生きる」のスローガンを掲げ、様々な背景をもつ多様なメンバーが自由度の高い働き方を通してお客様へサービスを提供し続けてきました。現在当社では一緒に会社を盛り上げていただけるメンバーを募集中です。少しでもご興味あれば、アノテーション株式会社 WEB サイトをご覧ください。