You could add a bucket policy to your S3 bucket, which I'll cover first, if you want to limit access to a particular principal, as well as modify your IAM policy a bit. I will cover both below. After the usual version/statement opening line, the statements in an S3 bucket policy would look similar to the following:
{
"Effect": "Allow",
"Principal": {
"AWS": "roleArn"
},
"Action": [
"s3:[bucketActions]"
],
"Resource": "arn:aws:s3:::[bucket-name]",
}
{
"Effect": "Allow",
"Principal": {
"AWS": "roleArn"
},
"Action": [
"s3:[objectActions]"
],
"Resource": "arn:aws:s3:::[bucket-name]/*",
}
For some reason even though the S3 bucket policy is specific to the bucket you're accessing in order to apply the policy in the first place, you do still have to explicitly state its ARNs.
There are a couple of important notes here.
Resource Section of your S3 policy
Remember that the bucket ARN refers just to the buckets in your account, not their objects, and would not include the /* at the end of the ARN. This rule holds true for all actions that specifically refer to the buckets themselves and not their objects.
Object actions, on the other hand, would be things like "s3:PutObject*" or "s3:GetObject*", etc. (Obviously you could select the specific "put object" actions, such as just the ability to write objects or to write the object's ACL, etc., if you want to scope down for best security practice.) The main point, though, is that actions referencing objects would relate to the resource line with /* at the end, whereas actions referencing the buckets themselves would not.
IAM policy
Your question was why you would need to use a condition. You don't need a condition in this case, if your intention is to grant list bucket access to specific buckets. You'll want to remove the /* at the end of the ARN for that type of action, as already noted above (the same applies to both S3 and IAM policies for this particular policy component). And as a side note, S3 policies include a Principal (indicating which roles/users the policy applies to), whereas IAM policies do not (because IAM roles/users, to which these IAM policies are attached, are the principal). First things first - a basic example of what your IAM policy could look like:
{
"Effect": "Allow",
"Action": [
"s3:[bucketActions]"
],
"Resource": "arn:aws:s3:::[bucket-name]",
}
{
"Effect": "Allow",
"Action": [
"s3:[objectActions]"
],
"Resource": "arn:aws:s3:::[bucket-name]/*",
}
There are definitely times when you would use a condition, but those would be cases when, for example, you want to specify the IP range that a user is/ isn't allowed to connect from, or (in an S3 policy) you want to deny certain actions to everyone except the ARN that matches the string you place in your condition.
There are also definitely times for S3 prefixes to be used within your IAM policies. For example, suppose you are a large company and have prefixed all buckets storing offshore data with "offshore" as the first part of the bucket name. Well, then you may want to either grant or restrict access to all buckets beginning with that specific S3 prefix, or name (you can use wildcards as part of that).