[terraform] tfstate/state lockingをs3/dynamodbで管理しているときにスイッチロールしてplan/applyするためのIAMポリシー

# 結論

以下IAMポリシーをスイッチロール用IAMロールに設定する

- ReadOnlyAccess(AWS管理ポリシー)
    - terraformでの管理範囲が限定されているなら特定サービス用のAWS管理ポリシー(*ReadOnlyAccess)か、特定サービス/リソース参照専用のカスタムポリシーを作成し設定する
- tfstate用S3バケット内オブジェクトのPutObject
- state locking用のdynamodbのPutItem

# ReadOnlyAccessのみ状態からの検証記録

## terraform init

OK

## terraform plan

```
> terraform plan
╷
│ Error: Error acquiring the state lock
│
│ Error message: 2 errors occurred:
│       * AccessDeniedException: xxxxxxxxxxxxxxxxxxxx is not authorized to perform: dynamodb:PutItem on resource:
│ xxxxxxxxxxxxxxxxxxxx because no identity-based policy allows the dynamodb:PutItem action
│       status code: 400, request id: xxxxxxxxxxxxxxxxxxxx
│       * unexpected end of JSON input
│
│
│
│ Terraform acquires a state lock to protect the state from being written
│ by multiple users at the same time. Please resolve the issue above and try
│ again. For most commands, you can disable locking with the "-lock=false"
│ flag, but this is not recommended.
```

state locking用テーブルにlockをかけられずNG
state locking用テーブルのPutItemを許可し再実行

```
│ Error: Error releasing the state lock
│
│ Error message: AccessDeniedException: xxxxxxxxxxxxxxxxxxxx is not authorized to perform: dynamodb:DeleteItem on resource:
│ xxxxxxxxxxxxxxxxxxxx because no identity-based policy allows the dynamodb:DeleteItem action
│       status code: 400, request id: xxxxxxxxxxxxxxxxxxxx
│ Lock Info:
│   ID:        xxxxxxxxxxxxxxxxxxxx
│   Path:      xxxxxxxxxxxxxxxxxxxx
│   Operation: OperationTypePlan
│   Who:       xxxxxxxxxxxxxxxxxxxx
│   Version:   1.x.x
│   Created:   2022-xxxxxxxxxxxxxxxxxxxx
│   Info:
│
│
│ Terraform acquires a lock when accessing your state to prevent others
│ running Terraform to potentially modify the state at the same time. An
│ error occurred while releasing this lock. This could mean that the lock
│ did or did not release properly. If the lock didn't release properly,
│ Terraform may not be able to run future commands since it'll appear as if
│ the lock is held.
│
│ In this scenario, please call the "force-unlock" command to unlock the
│ state manually. This is a very dangerous operation since if it is done
│ erroneously it could result in two people modifying state at the same time.
│ Only call this command if you're certain that the unlock above failed and
│ that no one else is holding a lock.
```

```Refreshing state...```は進んだが最後にエラー
state lockingテーブルにかけたロックを外せなくなった
state lockingテーブルのDeleteItemを許可し再実行
OK
terraform plan可能になった

## terraform apply

```
│ Error: Failed to save state
│
│ Error saving state: failed to upload state: AccessDenied: Access Denied
│       status code: 403, request id: xxxxxxxxxxxxxxxxxxxx, host id: xxxxxxxxxxxxxxxxxxxx
╵
╷
│ Error: Failed to persist state to backend
│
│ The error shown above has prevented Terraform from writing the updated state to the configured backend. To allow for recovery, the state has been written to the file "errored.tfstate" in the current working
│ directory.
│
│ Running "terraform apply" again at this point will create a forked state, making it harder to recover.
│
│ To retry writing this state, use the following command:
│     terraform state push errored.tfstate
│
╵
```

```Refreshing state...```は進んだが最後にエラー
tfstate用S3バケット内オブジェクトのPutObjectを許可し再実行
OK