はじめに
AWS SAMがStep Functionsをサポートするようになりましたが、CloudWatch Logsへのログ出力設定に不具合があり、ハマりましたので、その内容と対処方法をのこしておきます。
事象内容
SAMでStep Functionsを含むアプリケーションを作成し、 「$ sam deploy」 によるCloudFormation Stackの更新の際に以下のエラーが表示されることがあります。
The state machine IAM Role is not authorized to access the Log Destination (Service: AWSStepFunctions; Status Code: 400; Error Code: AccessDeniedException; Request ID: 4598526e-a9b6-4745-880d-1dd24f47f500; Proxy: null)
具体的には、CloudWatch Logsへのログ出力を有効にしたState Machineを作成する、ログ出力を行っていないState Machineをログ出力するよう変更する、といった更新の際に発生する可能性があります。
これはIAM Role の権限不足のケースだけではなく、CloudWatchLogs自体のResource based policyの権限不足によるケースもあります。
この場合、当該のStep Functions State Machineに付与するIAM Roleの定義をいくら見直しても解決できません。
下記のフォーラムの内容と同等のものとなります。
原因/調査方法
Step FunctionsのState MachineからCloudWatch Logsへログを出力する場合、大きく、State MachineのIAM Roleと、CloudWatch LogsのResource based policyの2つのPermissionsが必要となります。
どちらか一方のPermissionsが不足していた場合、State Machine作成/更新時に前述のエラーが発生するようです。どちらのケースであっても、発生するエラーメッセージは変わらないようです。
単純いState MachineそのものにCloudWatch Logsのログ出力用のIAM Permissionsを付与すればよいだけではないようで、中で少し複雑なことを行っているようですが、詳細は未確認です。
State Machineに付与するIAM Role
まず、State Machineに付与するIAM Roleに、CloudWatch Logsに関する権限(具体的には以下のIAM Permissions)が必要なようです。
このIAM Permissionsは、AWS Management ConsoleのStep Functions Consoleにて、IAM Roleを作成し、且つログを有効にしてState Machineを作成する際に付与されるものと同等です。下記公式ドキュメントにも記載があるものです。
Logging using CloudWatch Logs - AWS Step Functions
https://docs.aws.amazon.com/step-functions/latest/dg/cw-logs.html#cloudwatch-iam-policy
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"logs:CreateLogDelivery",
"logs:GetLogDelivery",
"logs:UpdateLogDelivery",
"logs:DeleteLogDelivery",
"logs:ListLogDeliveries",
"logs:PutResourcePolicy",
"logs:DescribeResourcePolicies",
"logs:DescribeLogGroups"
],
"Resource": "*",
"Effect": "Allow"
}
]
}
CloudWatch LogsのResource based policy
CloudWatch Logsには、それ自体で権限制御するためのResource based policyが備わっています。(このResource based policyは、Log GroupやLog Streamごとではなく、リージョンごとに1つずつという単位で存在している模様)
このCloudWatch LogsのResource based policyにはサイズ上限があり、SAMによりこの上限を超える変更をしようとする場合に発生します。
通常、AWSサービスからCloudWatch Logsにログ出力する際には、出力する側のIAM Entity(≒主体)にIAM Permissionsを付与して権限制御します。
このCloudWatch Logs側のResource based policyの目的は大きく以下の2つあるようですが、Step Functionsは前者に該当するため、これが用いられているものと推測できます。
- 一部のサービスで出力する側のIAM EntityにIAM Roleを付与できない場合
- AWSアカウントをまたいでCloudWatch Logsにログを出力する場合
Step Functionsの挙動
SAMでStep Functions State Machineを作る場合、SAMとしてのCloudFormation template内の定義を元に、自動でCloudWatchLogsのResource based policyを生成し、付与しようとします。
しかしこの際、CloudWatchLogsのResource based policyサイズは5120バイトが上限値であるため、きめ細かな制御を行おうとするとサイズが足りず、必要な権限を付与できないようです。
またStep Functions側の挙動として、CloudWatchLogsへの出力を有効にする設定でState Machine定義を作成・更新する際、CloudWatch LogsのResource based policyに必要な権限があるかチェックしているようです。
Step Functionsとして必要な権限が不足していると判断すると、前述のエラーを発生させ、State Machine定義の作成・更新は失敗します。
以下のコマンドで、設定済みのCloudWatch LogsのResource based policyを参照可能です。
$ aws logs describe-resource-policies
{
"resourcePolicies": [
{
"policyName": "AWSLogDeliveryWrite20150319",
"policyDocument": "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Sid\":\"AWSLogDeliveryWrite\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"delivery.logs.amazonaws.com\"},\"Action\":[\"logs:CreateLogStream\",\"logs:PutLogEvents\"],\"Resource\":[\"arn:aws:logs:us-west-2:123456789012:log-group:/aws/vendedlogs/states/HelloWorld-Logs:log-stream:*\",\"arn:aws:logs:us-west-2:123456789012:log-group:/aws/vendedlogs/states/InputOutputStateMachine-GrBZXWGHTyuW-Logs:log-stream:*\",\"arn:aws:logs:us-west-2:123456789012:log-group:/aws/vendedlogs/states/InputOutput-Logs:log-stream:*\",\"arn:aws:logs:us-west-2:123456789012:log-group:/aws/vendedlogs/states/InputOutputStateMachine-Logs:log-stream:*\"]}]}",
"lastUpdatedTime": 1609057420992
}
]
}
SAMのCFn template側でログ出力設定をいろいろ変えながら試していると、下記のように「Resource」がどんどん追加されていく状況になります。
$ aws logs describe-resource-policies | jq ".resourcePolicies[0].policyDocument | fromjson"
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AWSLogDeliveryWrite",
"Effect": "Allow",
"Principal": {
"Service": "delivery.logs.amazonaws.com"
},
"Action": [
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": [
"arn:aws:logs:us-west-2:123456789012:log-group:/aws/vendedlogs/states/HelloWorld-Logs:log-stream:*",
"arn:aws:logs:us-west-2:123456789012:log-group:/aws/vendedlogs/states/InputOutputStateMachine-GrBZXWGHTyuW-Logs:log-stream:*",
"arn:aws:logs:us-west-2:123456789012:log-group:/aws/vendedlogs/states/InputOutput-Logs:log-stream:*",
"arn:aws:logs:us-west-2:123456789012:log-group:/aws/vendedlogs/states/InputOutputStateMachine-Logs:log-stream:*"
]
}
]
}
対応方法
AWSフォーラムの回答に記載の通り、CloudWatchLogsのResource based policyを手動で更新し、「Resource」の範囲を緩くすることで対処可能です。
手順は以下のとおりです。
### 更新用のPolicy documentを作る
$ vi cloudwatchlogs-resourcebased-policy.json
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AWSLogDeliveryWrite",
"Effect": "Allow",
"Principal": {
"Service": "delivery.logs.amazonaws.com"
},
"Action": [
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": [
"arn:aws:logs:us-west-2:123456789012:log-group:/aws/vendedlogs/states/*:*"
]
}
]
}
### CloudWatchLogsのResource based policyを、上述のPolicy documentで上書きする
$ aws logs put-resource-policy --policy-name AWSLogDeliveryWrite20150319 --policy-document file://cloudwatchlogs-resourcebased-policy.json
{
"resourcePolicy": {
"policyName": "AWSLogDeliveryWrite20150319",
"policyDocument": "{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Sid\": \"AWSLogDeliveryWrite\",\n \"Effect\": \"Allow\",\n \"Principal\": {\n \"Service\": \"delivery.logs.amazonaws.com\"\n },\n \"Action\": [\n \"logs:CreateLogStream\",\n \"logs:PutLogEvents\"\n ],\n \"Resource\": [\n \"arn:aws:logs:us-west-2:123456789012:log-group:/aws/vendedlogs/states/*:*\"\n ]\n }\n ]\n}\n",
"lastUpdatedTime": 1609077195669
}
}
### 更新後のCloudWatchLogs Resource based policyを確認する
$ aws logs describe-resource-policies | jq ".resourcePolicies[0].policyDocument | fromjson"
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AWSLogDeliveryWrite",
"Effect": "Allow",
"Principal": {
"Service": "delivery.logs.amazonaws.com"
},
"Action": [
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "arn:aws:logs:us-west-2:123456789012:log-group:/aws/vendedlogs/states/*:*"
}
]
}
Furthermore
Step Functions State Machineからのログ出力が誰の権限によって行われるか、当該State Machineに付与したIAM Roleの権限で行われるのか、Step Functionsサービス自体の権限で行われるのか、不明確であるため引き続き確認したいと思います。
→検証しました。CloudWatch Logsへのログ出力操作は、当該State Machineに付与したIAM Roleの権限とは無関係でした。
【AWS】Step FunctionsからCloudWatch Logsへのログ出力時の権限を確認する【Step Functions】
参照した情報/関連情報
AWS Developer Forums: Bug with LoggingConfiguration ...
https://forums.aws.amazon.com/thread.jspa?threadID=321488
Amazon CloudWatch Logs resource policy size restrictions - AWS Step Functions
https://docs.aws.amazon.com/step-functions/latest/dg/bp-cwl.html
Enabling Logging from Certain AWS Services - Amazon CloudWatch Logs
https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/AWS-logs-and-resource-policy.html