Tips and Advice on IAM Policy using aws:SourceIP
You may be looking to implement access restrictions using the aws: SourceIp
condition key.
For example, if an IAM group has the following policy and an IAM user belongs to the IAM group with this policy.
Example policy
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Deny", "Action": "*", "Resource": "*", "Condition": { "NotIpAddress": { "aws:SourceIp": [ "xxx.xxx.xxx.xxx/32", "yyy.yyy.yyy.yyy/32", "zzz.zzz.zzz.zzz/32" ] } } } ] }
In this policy, Deny
rejects access from all IP addresses other than those specified in aws:SourceIp
.
At first, this policy looks to be okay, but there may be unintended behavior.
For example, problems may occur when using CloudFront, when registering an ACM certificate in ELB, when uploading a template to Amazon S3 with CloudFormation, and so on.
This is because the aws:SourceIp
condition key has the following properties:
- aws: SourceIp conditional key should be used only in the JSON policy of the specified IAM user, group, role, federated user
- Access is denied if another service calls the API on behalf of the user
Below is a quotation from the documentation:
AWS Global Condition Context Keys | aws:SourceIp Note
The aws:SourceIp condition key should be used in a JSON policy only for IAM users, groups, roles, or federated users that make API calls from within the specified IP range. This policy denies access to an AWS service that makes calls on your behalf. For example, assume that you have a service role that allows AWS CloudFormation to call Amazon EC2 to stop an instance. In that case, the request is denied because the target service (Amazon EC2) sees the IP address of the calling service (AWS CloudFormation) rather than the IP address of the originating user. There is no way to pass the originating IP address through a calling service to the target service for evaluation in a JSON policy.
IAM JSON Policy Elements: Condition Operators | IP Address Condition Operators
The aws:SourceIp condition key works only in a JSON policy if you are calling the tested API directly as a user. If you instead use a service to call the target service on your behalf, the target service sees the IP address of the calling service rather than the IP address of the originating user. This can happen, for example, if you use AWS CloudFormation to call Amazon EC2 to construct instances for you. There is currently no way to pass the originating IP address through a calling service to the target service for evaluation in a JSON policy. For these types of service API calls, do not use the aws:SourceIp condition key.
How should you handle errors when errors actually occur? Let's talk about possible workarounds.
Workaround
Although it is also described in the document as There is no way to pass the originating IP address through a calling service to the target service for evaluation in a JSON policy. Please check whether the error is resolved by the following two methods.
- Try with AWS KMS condition key
kms:ViaService
- Temporarily stop access restriction using
aws:SourceIp
Try with AWS KMS condition key kms:ViaService
There are services that cannot restrict access by source IP address, but with AWS KMS you can allow other services to access KMS via kms:ViaService
.
For example, in ELB, if you receive an error when trying to register an ACM certificate, it may be resolved by this method because KMS is used for ACM certificate registration. In other words, if AWS KMS is used, this method is one workaround to resolve errors.
ACM stores the certificate and its corresponding private key, and uses AWS Key Management Service (AWS KMS) to help protect the private key.
Using Policy Conditions with AWS KMS | kms:ViaService
For example, you can use kms:ViaService to allow an user to use a customer managed CMK only for requests that Amazon S3 makes on their behalf. Or you can use it to deny the user permission to a CMK when a request on their behalf comes from AWS Lambda.
Example policy
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Deny", "Action": "*", "Resource": "*", "Condition": { "Null": { "kms:ViaService": "true" }, "NotIpAddress": { "aws:SourceIp": [ "xxx.xxx.xxx.xxx/32", "yyy.yyy.yyy.yyy/32", "zzz.zzz.zzz.zzz/32" ] } } } ] }
In case of errors due to access to KMS, there is a possibility that it may be resolved by this method, but if it cannot be resolved by this method, you can try the following method.
Temporarily stop access restriction using aws:SourceIp
Temporarily cancel access restriction by source IP because some services cannot restrict access by source IP.
Conclusion
When access is restricted by source IP address, unintended errors may occur due to specification of aws: SourceIp
. We would appreciate it if you could refer to the workarounds we introduced in this blog.