Is it more secure to encrypt separate customers' data with separate keys?

One argument in favour of separate keys: assume at some point in the future your app has some sort of SQLInjection or Server-side request forgery (SSRF) vulnerability that lets a user logged in as CustomerA bypass the usual access control rules and fetch data belonging to CustomerB.

If all customers use the same key, then your application layer server will happily decrypt and serve it back through your UI. However if each customer has their own key, then your server will try to decrypt CustomerB's data with CustomerA's key and throw a decryption error. That would be a win for defense in depth.

While in general, using per-customer encryption keys doesn't do a lot (esp. if you store all the keys in the same place), there are some specific cases where it could save your butt.

Unfortunately, the answer is "It depends".

But first, we need to clear up that KMS keys and Buckets are mutually independent, one KMS key (called a CMK) can be tied to multiple buckets, and one bucket can have objects encrypted by multiple CMKs.

Secondly, because of the tight integration between KMS and S3, the only real access control we have is via key grants or IAM permissions (i.e. In order to get an encrypted object in S3, the IAM role must have permission for s3:GetObject and kms:decrypt) there is no way to obtain either the key material or the encrypted cipher-text of the object and perform the decryption/encryption outside of AWS.

Now, what are the factors that would make a single or multi-key strategy a better fit?

If you're storing this data for manual retrieval, keeping them in different buckets makes perfect sense. Buckets are free, and different buckets can be protected by different bucket policies to limit access to certain users/roles. From there, it's not too complex to create a dedicated CMK for each bucket, further isolating the data between customers.

If you're storing data for access by multiple applications (one per customer), then also separate buckets and CMKs for each customer is a good approach. By segregating both buckets and CMKs you're able to isolate each customers data from each other, but more importantly, keep the applications isolated as well.

If you're storing this data for access by one single application, then keeping multiple buckets adds overhead. By definition that application requires access to all CMKs and all buckets, and a compromise on the application would compromise them all. Under this scenario, I wouldn't suggest multi-CMKs, simply because of the additional overhead maintaining the buckets brings little added benefit.

Unless your application grants different IAM roles to different users on login.This is rare, as most apps have an application-level IAM role, rather than a per-user IAM role.But, If you're doing this, then encrypting one bucket with different KMS keys, and providing key-grants to individual IAM roles make perfect sense. This is pretty sophisticated territory, and chances are you wouldn't be asking this question if your app was already doing this :)