I have an AWS IAM policy in Terraform that is written like such:
            {
                "Effect": "Allow",
                "Action": [
                    "s3:ListBucket"
                ],
                "Resource": "arn:aws:s3:::bucket-name",
                "Condition": {
                    "StringLike": {
                        "s3:prefix": "${local.account_id}/*"
                    }
                }
            }
However, I'm trying to understand why s3:prefix is used at all. Can't this be done with:
            {
                "Effect": "Allow",
                "Action": [
                    "s3:ListBucket"
                ],
                "Resource": "arn:aws:s3:::bucket-name/${local.account_id}/*",
            }
                s3:ListBucket only applies to the Resource of bucket. In your second example, your Resource are objects, and the s3:ListBucket will not apply. So your policy will have no effect.
In contrast, in the frist example the Resource is actual bucket, not objects. s3:ListBucket will work. Additionally, due to the Condition,  s3:ListBucket will only allow listing content of folder ${local.account_id} in the bucket.
Other such scenarios are discussed here.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With