How can you restrict access to an S3 bucket to a single AWS instance when the instances have no public IP address and you're using an S3 endpoint in your VPC?

Background and Detail

We have a VPC that has a Virtual Private Gateway, which runs a VPN back to our on-premise data center. The VPC has no internet gateway. The servers have no public IP addresses. There's an S3 endpoint and a route table set up correctly. Let's say there's one subnet with three instances. We have two S3 buckets yet to be created, which will be encrypted.

We'd like to restrict access from instance A S3 bucket A and instance B to S3 bucket B. Instance C shouldn't have access to either bucket.

We also need to be able to upload information to the buckets from the public internet. This access should only be available through specific IPs, which is easy to do using bucket policies. This could make a difference to the solution though.

This page on AWS documentation says

You cannot use an IAM policy or bucket policy to allow access from a VPC IPv4 CIDR range (the private IPv4 address range). VPC CIDR blocks can be overlapping or identical, which may lead to unexpected results. Therefore, you cannot use the aws:SourceIp condition in your IAM policies for requests to Amazon S3 through a VPC endpoint. This applies to IAM policies for users and roles, and any bucket policies. If a statement includes the aws:SourceIp condition, the value fails to match any provided IP address or range. Instead, you can do the following:

  • Use your route tables to control which instances can access resources in Amazon S3 via the endpoint.
  • For bucket policies, you can restrict access to a specific endpoint or to a specific VPC. For more information, see Using Amazon S3 Bucket Policies.

We can't use route tables as we have two instances that need access to different buckets.

I've also read this page, which wasn't helpful for our situation.

Option: KMS keys

I suspect if we give each bucket its own KMS key and restrict access to the keys to the appropriate instance only that instance can access the decrypted data. I think this will work, but there's some complexity there, and I'm not 100% sure as I haven't done much with KMS.

An advantage of this approach is it denies by default, grants by configuration. Because of the number of users of the account we can't rely on configuration to deny by default, as was very helpfully suggested by Alex below.

Ideas Thoughts or Suggestions

Does anyone have any other suggestions or ideas we could follow up? Or any thoughts / further detail on the KMS idea?


My suggestion would be to use instance roles. These are roles that can be assumed by applications running on specific instances by querying the metadata service - AWS tools support this natively - allowing applications running on that instance to use those credentials. More details on them here.

You would then have a unique role for instance A and another for instance B, then take a look at this post on using Bucket Policies to restrict access to a bucket based on a specific role. Here.

That should probably do what you need. Although the KMS one is also an approach, but probably more complicated. You could also move the instances into different VPCs and use an endpoint policy to restrict access based on source VPC - but that would be very messy and would bring other complications.

| improve this answer | |
  • That's an interesting option thanks Alex, deny all to S3 by default and grant access to a specific bucket in the IAM Role. I guess the downside of that approach is it relies on all of the system operators (we have quite a few) remembering to deny access to all S3 buckets in an IAM role, which would be easy to forget / miss. So you have to configure to deny, rather than default deny and permit access. I think the KMS option is deny by default and grant by exception, which I think would be better in practice - if it can be made to work. – Tim Oct 4 '18 at 18:20
  • You can probably use AWS Config rules to enforce policy in that case. KMS seems a touch over complicated imho. – Alex Moore Oct 21 '18 at 16:45
  • I think config is for checking rather than enforcing policy. "Use AWS Config to evaluate the configuration settings of your AWS resources. You do this by creating AWS Config rules, which represent your ideal configuration settings. AWS Config provides customizable, predefined rules called managed rules to help you get started. You can also create your own custom rules." – Tim Oct 21 '18 at 23:05
  • KMS is something we're using anyway, we have a fairly complex environment with some fairly strict standards to meet (PCI etc). – Tim Oct 22 '18 at 1:04
  • Config is the rule and then you use it to trigger the enforcement, see:docs.aws.amazon.com/config/latest/developerguide/… – Alex Moore Oct 22 '18 at 7:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.