BUT all three of them (AWS, Azure and GCP) have pros and cons, so you just have to spend a good amount of time learning their quirks.
and too much string to hang yourself with
In my mind, "not well designed" would be "I cannot represent my security need in this policy language" versus the more common opinion "AWS IAM is a black box" means "I cannot understand why I am getting a 403"
GCP's IAM is, in this premise, not well designed because I cannot express ReadOnlyAccess in their policy language without having a constantly updating policy job, because they do not have wildcards in the Action as does AWS. Contrast `Action: ["s3:Get*"]` which would cheerfully include access to a future GetBucketV7 verb to GCP's "storage.buckets.get" which must always be specified, in full, and when storage2.buckets.get comes out, it's my job to find all references and patch them
There's another common fix, which is to apply a permission boundary to IAM roles. This allows the use of generic policies like "ReadOnlyAccess" but can then be further downscoped to resources by tag (or other similar ABAC schemes)
With Amazon, you are genuinely the customer. AWS may do many things in a bizarre or byzantine way, but it is constantly trying to be there for the developer in ways that many competitors in my opinion are not.
It is, without any question. Even of you work at a Microsoft shop, the benefits you get from vertical integration isn't that clear. Azure requires a far greater cognitive load to handle and to make matters worse ultimately experiences far more outages.