Skip to content

API gw resource policy

0

Hi Team,

I have added a resource policy to my API Gateway that restricts access to calls made only from a specific account, as well as the account where the API Gateway itself resides (to allow calls from the bastion host). Below is the policy I implemented:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": [
          "arn:aws:iam::here_stg_account_id:root",
          "arn:aws:iam::here_api_gw_account_id:root"
        ]
      },
      "Action": "execute-api:Invoke",
      "Resource": "arn:aws:execute-api:region:api_gw_account_id:xsdxxxsdx/*"
    }
  ]
}

After applying and redeploying the API Gateway, I attempted to invoke it from the EC2 bastion in the stg_account_id and api_gw_account_id, which should have been permitted. However, I received the following error:

"Message": "User: anonymous is not authorized to perform: execute-api:Invoke on resource: arn:aws:execute-api:region:********3415:xsdxxxsdx/trn/POST/my-resource"

the objective is to allow only one account to hit the API gw and the account where the API gw itself is in.

i call the pi gw from the ec2 to test like this :

curl -X 'POST' \
  'https://xxxxxxx.execute-api.region.amazonaws.com/stg/my-resource' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "key1": "value1"
}'

I changed the API GW policy to restrict by IP range instead of AWS accnts Ids, but still have the same error :

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": "*",
      "Action": "execute-api:Invoke",
      "Resource": "arn:aws:execute-api:region:api_gw_account_id:xsdxxxsdx/*",
      "Condition": {
        "IpAddress": {
          "aws:SourceIp": [
            "x.x.x.x.x/yy",
            "x2.x2.x2.x2/16"
          ]
        }
      }
    }
  ]
}

for IP range should I use AWS_IAM also? at the API gw level

Could someone help me troubleshoot this issue?

3 Answers
1
Accepted Answer

Hello,

Greetings from AWS!

I understand that you wish to restrict access to API Gateway to account where API Gateway resides and the another account. You also mentioned that you tried with resource policy, however you still received the "Message": "User: anonymous is not authorized to perform: execute-api:Invoke on resource".

Please note that, we need to enable IAM Auth. Here, enabling AWS_IAM authentication along with the resource policy is necessary whenever we configure a resource policy allowing certain IAM entities to restrict access to our API [1].

Additionally, we need to make Sigv4 [2] request to API Gateway by passing access key and secret access key of a user/role in that account. When we make the Sigv4 request to API Gateway, then API Gateway identifies the user/role who is making the request and authenticates the request. As you were allowing the root access in your principal means you are providing the API Gateway access to all the users/roles in that account and restricting the API Gateway access to the outside world.

Further, you were receiving the "User: anonymous" while making curl request from EC2 as API Gateway is not able to identify the principal who is making the request.

Moving ahead, it is not required to use AWS_IAM auth when you are allowing specific IPs in resource policy. Here API Gateway allow/deny the request based on the client IP. Please note that the 'aws:SourceIp' condition value works only for public IP address range. You can restrict the access using the sample policy below [3].

  "Version": "2012-10-17",
  "Statement": [{
      "Effect": "Allow",
      "Principal": "*",
      "Action": "execute-api:Invoke",
      "Resource": "execute-api:/*/*/*"
    },
    {
      "Effect": "Deny",
      "Principal": "*",
      "Action": "execute-api:Invoke",
      "Resource": "execute-api:/*/*/*",
      "Condition": {
        "NotIpAddress": {
          "aws:SourceIp": ["sourceIpOrCIDRBlock", "sourceIpOrCIDRBlock"]
        }
      }
    }
  ]
}

Hope this answers your query!


REFERENCES

[1] https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-authorization-flow.html#apigateway-authorization-flow-iam

[2] https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_sigv-create-signed-request.html

[3] https://repost.aws/knowledge-center/api-gateway-resource-policy-access

AWS
answered a year ago
EXPERT
reviewed 10 months ago
  • Thank you for your response.

    I don't have public IP ranges available. For the other account I want to restrict, I'm using its private VPC CIDR, and for the account where the API Gateway resides, I'm using its private IP address.

    If I restrict access by SourceVpc, do I also need to enable AWS_IAM authentication at the API Gateway level?

    { "Version": "2012-10-17", "Statement": [ { "Effect": "Deny", "Principal": "", "Action": "execute-api:Invoke", "Resource": "arn:aws:execute-api:region:123456789:edc14xs/", "Condition": { "StringNotEquals": { "aws:SourceVpc": "vpc-05412547841245" } } } ]

  • i used VpcSourceIp and it worked :

    { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": "", "Action": "execute-api:Invoke", "Resource": "arn:aws:execute-api:region:21212121212:xsxddd/" }, { "Sid": "blocks traffic to the API GW unless the request is from specified private IP addresses (aws:VpcSourceIp)", "Effect": "Deny", "Principal": "", "Action": "execute-api:Invoke", Resource": "arn:aws:execute-api:region:21212121212:xsxddd/" "Condition": { "NotIpAddress": { "aws:VpcSourceIp": [ "x.x.x.x.x/19", "x.x.x.x.x/16" ] } } } ] }

    but not sure why the Deny statement alone not work, I need to add the allow statement along with it?

0

Hi,

You should try a policy with a condition like the one below

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowAccount1",
            "Effect": "Allow",
            "Action": "execute-api:Invoke",
            "Resource": "arn:aws:execute-api:us-east-1:*:a123456789/test/POST/mydemoresource/*",
            "Condition": {
                "StringEquals": {
                    "aws:SourceAccount": "<your-account-1>"
                }
            }
        },
       {
            "Sid": "AllowAccount2",
            "Effect": "Allow",
            "Action": "execute-api:Invoke",
            "Resource": "arn:aws:execute-api:us-east-1:*:a123456789/test/POST/mydemoresource/*",
            "Condition": {
                "StringEquals": {
                    "aws:SourceAccount": "<your-account-2>"
                }
            }
        }
    ]
}

See https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_condition-keys.html for IAM condition keys

Best.

Didier

EXPERT
answered a year ago
  • i tried the resource policy you suggested, also added : "Principal": { "AWS": "*" },

    otherwise the policy will not be valid, but I still have the some error as in my original message.

    "Message": "User: anonymous is not authorized to perform: execute-api:Invoke on resource: arn:aws:execute-api:region:********3415:xsdxxxsdx/trn/POST/my-resource"

0

Thank you for providing the details of your API Gateway resource policy and the issue you're experiencing. Let's troubleshoot this problem.

The error message you're receiving suggests that the user is being treated as "anonymous" when trying to access the API. This typically happens when the request is not properly authenticated, even if the resource policy allows access from specific AWS accounts.

There are a few things to consider:

  1. IAM Authentication: When you set the Principal in your resource policy to specific AWS accounts, you need to ensure that you're using AWS_IAM authorization for every method in your API. If you haven't enabled IAM authentication, the API will treat all incoming requests as anonymous, regardless of the resource policy.

  2. IAM Permissions: The IAM user or role used to make the request from the EC2 bastion must have the necessary permissions to invoke the API. This is in addition to the resource policy. You need to ensure that the IAM entity has a policy attached that allows the "execute-api:Invoke" action on your API resource.

  3. Signing the Request: When making the API call from the EC2 instance, make sure you're properly signing the request with AWS credentials. If you're using an AWS SDK, this should be handled automatically, but if you're making direct HTTP requests, you need to ensure they're signed correctly.

  4. Cross-Account Access: If you're accessing the API from a different account than where the API resides, both the IAM policies in the calling account and the resource policy in the API account must explicitly allow the access.

To resolve this issue:

  1. Enable AWS_IAM authorization for all methods in your API Gateway.
  2. Ensure the IAM role or user associated with your EC2 bastion has a policy that allows "execute-api:Invoke" on your API resource.
  3. Verify that your API calls from the EC2 bastion are properly authenticated and signed with AWS credentials.
  4. If accessing cross-account, double-check both the IAM policies in the calling account and the resource policy in the API account.

If you've confirmed all these steps and are still experiencing issues, you may want to temporarily broaden your resource policy for testing purposes (e.g., allow all principals) to isolate whether the problem is with the resource policy or with the authentication/authorization setup.

Remember to always follow the principle of least privilege when configuring your final policies.
Sources
Create and attach an API Gateway resource policy to an API - Amazon API Gateway
How API Gateway resource policies affect authorization workflow - Amazon API Gateway

answered a year ago

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.