drgn
drgn

Reputation: 1140

AWS private API Gateway through VPC Endpoint

First of all I am very new to AWS. Here is what i'm trying to achieve:

The public subnet is working perfectly well, I can access SSH and HTTP. The private subnet cause me a little trouble. For debug purpose i launched off an EC2 instance in it. From one of the "public instance" I am able to ping the "private instance" private IP (Well there is no public IP obviously)

Following the documentation, I created a VPC Endpoint in my private subnet which created a Network interface where i attached a security group that allow HTTP(S) (80 and 443) from the whole VPC CIDR. The endpoint type is Interface

So, now i have a private subnet with an Endpoint that allow HTTP(S) traffic. That endpoint have some (private) DNS NAME and (probably) also a private IP (Could not find it)

Now I want to add an API Gateway to front some AWS lambda. I create said API and as an Endpoint Type -> Private

Following this : Official Documentation The "only" way to "link" the API Gateway to the VPC Endpoint is to add a resource policy. So I input the following

{
"Version": "2012-10-17",
"Statement": [
    {
        "Effect": "Deny",
        "Principal": "*",
        "Action": "execute-api:Invoke",
        "Resource": "arn:aws:execute-api:<REGION>:<MY ID>:<API GATEWAY ID>/*/*/<MY RESOURCE>",
        "Condition": {
            "StringNotEquals": {
                "aws:sourceVpce": "<VPC ENDPOINT ID>"
            }
        }
    },
    {
        "Effect": "Allow",
        "Principal": "*",
        "Action": "execute-api:Invoke",
        "Resource": "arn:aws:execute-api:<REGION>:<MY ID>:<API GATEWAY ID>/*/*/<MY RESOURCE>"
    }
]

}

And for the sake of completeness here is my lambda (python3.6):

from __future__ import division
def lambda_handler(event, context):
  return {
      "statusCode":200,
      "headers": {"Content-Type": "application/json" },
      "body" : "It work!"
  }

Finally the problem:

What would be the URL to invoke this REST Api! API Gateway (In the lamdba Console) Tell me this:

https://<API GATEWAY ID>.<REGION>.amazonaws.com/<MY STAGE>/<MY RESOURCE>

Ok! Lets call that url: APIURL I ssh to the EC2 instance in the public subnet and run the following:

curl https://$APIURL

And it work: It output: "It work!" but that APIURL does not seem to come from the VPC endpoint so I try the following (still from the public subnet EC2):

curl https://vpce-XXXXXXX-XXXX.execute-api.REGION.vpce.amazonaws.com/<MY STAGE>/<MY RESOURCE>

And i get: {"message":"Forbidden"}

That does not seem right. As i test i change de API Gateway resource policy for the following:

{
"Version": "2012-10-17",
"Statement": [
    {
        "Effect": "Deny",
        "Principal": "*",
        "Action": "execute-api:Invoke",
        "Resource": "arn:aws:execute-api:<REGION>:<MY ID>:<API ID>/*/*/<MY RESOURCE>"
    }
]

}

And NOTHING changed. The APIURL is still working and the VPCE Url still give me forbidden.

What am I doing wrong? My apologies for the long post.

Upvotes: 9

Views: 5586

Answers (2)

matthewatabet
matthewatabet

Reputation: 1481

A policy role update does not take effect until the api has been deployed to a stage.

https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-resource-policies-create-attach.html

If you update the resource policy after the API is created, you'll need to deploy the API to propagate the changes after you've attached the updated policy.

Upvotes: 7

Aress Support
Aress Support

Reputation: 1425

As your API url is working fine,there seems to be a problem with the policy.
In IAM policy Deny permission will override the Allow permission. Try changing your policy to the following:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": "*",
            "Action": "execute-api:Invoke",
            "Resource": [
                "arn:aws:execute-api:region:account-id:api-id/*",
            "Condition": {
              "StringEquals":{
                             "aws:SourceVpce": "<VPC Endpoint ID>"
                         }
                       }
                    ]
        },
        {
            "Effect": "Deny",
            "Principal": "*",
            "Action": "execute-api:Invoke",
            "Resource": [
                "arn:aws:execute-api:region:account-id:api-id/*"
            ],
            "Condition" : {
                "StringNotEquals": {
                    "aws:SourceVpce": "<VPC Endpoint ID>"
                }
            }
        }
    ]
}

For further reference, follow this link:
https://aws.amazon.com/blogs/compute/introducing-amazon-api-gateway-private-endpoints/

Upvotes: 0

Related Questions