AWS does not provide clear guidance on this situation, which is a shame. This is how I am going to architect the solution:
- Developer box encrypts per-instance configuration blob using the private portion of asymmetric keypair and places it in an S3 bucket.
- Restrict access to S3 bucket using IAM policy.
- Bake public portion of asymmetric keypair into AMI.
- Apply IAM role to EC2 instance and launch it from AMI
- EC2 instance is able to download configuration from S3 (thanks to IAM role) and decrypt it (thanks to having the public key available).
The private key is never shared sent to an instance so it should not be compromised. If the public key is compromised (e.g. if the EC2 instance is rooted), then the attacker can decrypt the contents of the S3 bucket (but at that point they already have root access to the instance and can read configuration directly from the running service).