Creating an e3 Bucket Policy to Restrict Access by IP Address or Subnet
In this guide we will explain how to create an e3 bucket policy that restricts access to a bucket so that data requests are only permitted from a single IP address or an approved range of IP addresses (a subnet). Requests originating from any other address will be denied.
This is a common way to "fence in" a bucket so that only your office network, a specific server, or a known VPN egress address can read from or write to it.
Important — do not restrict
s3:*while setting this up. Denying every action ("Action": "s3:*") from non-approved addresses also deniess3:PutBucketPolicyands3:DeleteBucketPolicy. If the service does not see the source IP you expect, you can lock yourself out of bucket-policy management entirely with no way to self-recover. The safe approach in this guide restricts data-plane actions only (reads, writes, lists) and deliberately leaves the policy-management actions out of the Deny so you can always correct or remove the rule.
Basic Policy Structure
This policy uses the same JSON structure described in "Understanding and Creating a Basic e3 Bucket Policy." Make sure you are familiar with Version, Statement, Sid, Effect, Principal, Action, and Resource.
To restrict by IP, we add one extra element: a Condition block that evaluates the source address of each request using the aws:SourceIp condition key.
The Logic: Deny data access if the request is NOT from an approved address
The most reliable way to enforce an IP allow-list is with a Deny rule using the NotIpAddress condition. The logic is: "Deny the data operations on this bucket if the request did NOT come from one of my approved addresses."
A Deny rule is preferred over an Allow rule here because in policy evaluation an explicit Deny always wins. Even if some other policy or permission would otherwise grant access, the IP restriction still holds — it "fails closed."
Crucially, we apply the Deny only to data-plane actions (listing the bucket, and reading/writing/deleting objects). We intentionally do not include the policy-management actions (s3:GetBucketPolicy, s3:PutBucketPolicy, s3:DeleteBucketPolicy) in the Deny. Keeping those outside the rule means that even if the IP condition behaves unexpectedly, you can still read, fix, or remove the policy and recover access.
How IP addresses and ranges are written
The aws:SourceIp value uses standard CIDR notation:
A single IPv4 address (e.g. 203.0.113.50)
203.0.113.50/32
A small range / subnet (e.g. a /24 block, 256 addresses)
203.0.113.0/24
A larger private range
10.0.0.0/8
Multiple separate addresses or ranges
List each as a separate string in the array
A /32 suffix means "this exact address only." Lower numbers (e.g. /24, /16, /8) widen the range.
Recommended Policy: Restrict Data Access to a Single IP Address
This is the safe default for IP restriction. It denies bucket-listing and object read/write/delete operations on your-bucket-name unless the request comes from 203.0.113.50. Policy-management actions are left out of the Deny so you can always recover.
Replace the placeholders:
your-bucket-namewith the name of your bucket.203.0.113.50/32with the public IP address you want to allow.
Policy JSON:
Explanation of the Recommended Policy
Two statements, two resource scopes. Bucket-level actions (like
ListBucket) target the bucket ARNarn:aws:s3:::your-bucket-name, while object-level actions (likeGetObject/PutObject) target the objects ARNarn:aws:s3:::your-bucket-name/*. Splitting them keeps each action paired with the correct resource."Effect": "Deny": Each rule blocks the listed actions when its condition is met."Principal": "*": The rule applies to all users. To scope it to one specific user instead, replace"*"with{ "AWS": ["arn:aws:iam::your-account-id:user/your-username"] }.Data-plane actions only. The two statements cover listing, reading, writing, deleting, multipart uploads, and object ACLs — the operations you actually want fenced to an IP. They deliberately exclude
s3:GetBucketPolicy,s3:PutBucketPolicy, ands3:DeleteBucketPolicy, so policy management remains possible from any address and you retain a recovery path."Condition": { "NotIpAddress": { "aws:SourceIp": "203.0.113.50/32" } }: The Deny applies only when the request's source IP is not203.0.113.50.A request from
203.0.113.50→ does not matchNotIpAddress→ the Deny does not apply → access proceeds.A request from any other address → matches
NotIpAddress→ the Deny applies → access is blocked.
Restrict to an IP Range / Subnet
To allow a whole subnet instead of a single host, change the CIDR suffix on both statements. For example, allow the entire 203.0.113.0/24 block (addresses 203.0.113.0–203.0.113.255) by setting:
in each Condition block of the recommended policy above.
Allow Several Addresses or Ranges
To permit multiple locations — for example, an office IP and a server subnet — supply an array of CIDR values in each Condition block. A request is allowed if it matches any entry in the list:
The Deny applies only when the source IP is not in any of the listed entries. Remember to update the Condition in both statements (bucket-level and object-level) so the allow-list stays consistent.
Applying the Policy with the AWS CLI
The e3 service is S3-compatible, so you can manage bucket policies with the standard AWS CLI by pointing it at the e3 endpoint.
1. Configure the AWS CLI (one time)
If you have not configured a profile yet, run:
Enter the Access Key and Secret Key from your e3 Access Keys page when prompted. For the default region you can enter a placeholder such as ca-central-1; the region value is not used to route requests when you specify an endpoint.
2. Confirm the public IP you will allow
Before you write the IP into the policy, confirm the public address your traffic actually leaves from. Run this on the machine that should retain access:
The address returned is the one e3 evaluates against your policy. Put that value in aws:SourceIp.
3. Save the policy to a file
Save your chosen policy JSON to a file, for example restrict-ip-policy.json.
4. Apply the policy
Run put-bucket-policy, pointing --endpoint-url at your e3 Service URL (shown on the Access Keys page):
If the command returns no output, the policy was accepted. (The AWS CLI prints nothing on a successful put-bucket-policy.)
Confirming the Policy Was Applied
Retrieve the policy currently attached to the bucket:
This returns the policy document as a JSON string. Confirm it matches what you applied — check the bucket name, the aws:SourceIp values, and the Effect.
Because the recommended policy leaves s3:GetBucketPolicy out of the Deny, this command works from any address, which is exactly the recovery path you want.
To view it as readable formatted JSON (if you have the jq tool installed):
Testing That the Policy Works
Testing is essential. You should verify both the "allowed" and "blocked" paths. The full sequence — confirm your IP, apply, test access, and confirm the policy — looks like this:
Test 1 — From an approved address (should succeed)
From a machine using one of your allowed IPs, the list command above should return the bucket contents normally.
Test 2 — From a non-approved address (should be denied)
From a machine not on an approved IP (for example, a home connection, a mobile hotspot, or a cloud VM in a different network), run the same list command:
This should fail with an AccessDenied error, confirming the restriction is active. Meanwhile, get-bucket-policy should still succeed from this same non-approved address — confirming your recovery path is intact.
Important Notes
Use the correct public IP address
aws:SourceIp is matched against the public IP that e3 sees on the incoming connection. If your servers sit behind NAT, a firewall, or a VPN, the address e3 observes is the public egress IP of that network — not the internal/private LAN address of the machine (e.g. not 192.168.x.x or 10.x.x.x). Always allow-list the public address your traffic actually leaves from. Confirm it with curl -4 https://checkip.amazonaws.com from the source machine.
Avoid locking yourself out
The recommended policy is designed so you cannot lose access to policy management — s3:GetBucketPolicy, s3:PutBucketPolicy, and s3:DeleteBucketPolicy are never inside the Deny. Still, to stay safe:
Double-check your approved IP/CIDR values before applying.
Apply and test from a machine that is already on an approved address.
Consider temporarily including your admin workstation's IP in the allow-list while you validate, then tighten it afterward.
If you ever do get locked out, contact eazyBackup support — our team may be able to assist with removing or correcting the policy on the back end.
Do not use
"Action": "s3:*"while testing IP restrictions. If the service does not see the expected client IP, this can also denyPutBucketPolicyandDeleteBucketPolicy, preventing self-service recovery. Restrict the specific data-plane actions shown above instead.
Watch out for dynamic IP addresses
Many residential and small-office internet connections use IP addresses that change periodically. If you restrict to a single dynamic IP, access will break when that address changes. For these situations, allow the provider's broader assigned range, use a static IP, or route traffic through a fixed VPN/proxy egress address.
Deny always wins
Deny always winsIf you also have Allow policies on the bucket, remember that an explicit Deny overrides any Allow. The IP restriction above takes precedence for the data-plane actions it covers — which is the intended, fail-closed behaviour.
Advanced (not recommended): denying all actions with s3:*
s3:*Some administrators want to deny every S3 action from non-approved IPs, including policy management, for the strictest possible lockdown. This is an advanced configuration and carries a real lockout risk: if we do not observe the source IP you expect, a s3:* Deny will also block PutBucketPolicy and DeleteBucketPolicy, leaving no self-service way to fix or remove the policy. Only do this if you fully control and have verified the source-IP path end to end, and you understand that recovery may require contacting eazyBackup support. For nearly all use cases, the data-plane policy shown earlier provides the protection you want without the lockout risk.
Last updated