If you want to restrict access to instances or load balancers on EC2 to specific IP ranges, you can use Security Groups or ACLs. However, if you want to restrict access to other APIs provided by AWS based on IP, you cannot use Security Groups or ACLs. For that, you need an IAM policy.
For example, let’s say you want to restrict access to the APIs that read data from Parameter Store in AWS Systems Manager based on IP. First, let’s check the default policy for Parameter Store. You can find it under “AWS IAM -> Policies”.
There is a policy called AmazonSSMReadOnlyAccess. The policy details are as follows
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ssm:Describe*",
"ssm:Get*",
"ssm:List*"
],
"Resource": "*"
}
]
}
We only need to add an IP-based condition here. Once you have copied the detailed JSON value of the default policy AmazonSSMReadOnlyAccess, let’s create a new policy.
Go to “AWS IAM -> Policies -> Create Policy” and you will be presented with a visual editor and a JSON input field to create a policy.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ssm:Describe*",
"ssm:Get*",
"ssm:List*"
],
"Resource": "*",
"Condition": {
"IpAddress": {
"aws:SourceIp": [
"{IP_ADDRESS_TO_ALLOW}"
]
}
}
}
]
}
The difference from the default policy we saw earlier is the addition of the “Condition” section. Replace {IP_ADDRESS_TO_ALLOW} with the IP addresses or CIDR ranges you want to allow. However, when you request AWS APIs, the source IP will usually appear as a public IP, so you should not put private IP ranges here.
If you set up a policy in this way and apply it to a specific account, that account will only be able to access the API from the IP ranges you configured. In the example above I used “Allow,” but it would work the same way if you replaced “Allow” with “Deny” and “IpAddress” with “NotIpAddress.” If both Allow and Deny exist for the same resource and action in an IAM policy, Deny takes precedence.