By using AWS re:Post, you agree to the Terms of Use

{"message":"forbidden"} when accessing private API Gateway


I'm setting up a private API Gateway with a single endpoint with a proxy integration to a lambda that echoes the entered path parameter. When testing this API in the console everything works as intended. The resource policy for the API Gateway is set up as follows:

    "Version": "2012-10-17",
    "Statement": [
            "Effect": "Allow",
            "Principal": "*",
            "Action": "execute-api:Invoke",
            "Resource": "arn:aws:execute-api:<region>:<account-id>:<api-gateway-id>/*"
            "Effect": "Deny",
            "Principal": "*",
            "Action": "execute-api:Invoke",
            "Resource": "arn:aws:execute-api:<region>:<account-id>:<api-gateway-id>/*",
            "Condition": {
                "StringNotEquals": {
                    "aws:SourceVpc": "<vpc-id>"

I've also set up a VPC Endpoint in my VPC. The endpoint is connected to one subnet in each AZ. The security group for the VPCE is set up to allow inbound TCP traffic on port 443 (HTTPS) from anywhere and all outbound traffic to anywhere. The endpoint has Private DNS Names Enabled set to true. The policy is set to allow full access.

The API Gateway was created via the console and I associated the VPCE to the API Gateway when I created the API Gateway. I've also later disassociated and reassociated the the VPCE to the API Gateway via the console. I've also associated the VPCE to the API via cli.

My problem is that when I'm now trying to access the endpoint that I set up in my private API Gateway via curl from an EC2 in one of the subnets associated with the VPCE, I get a 403 response with body {"message":"forbidden"}. I'm using the first two dns listed under DNS names in the Details pane for my VPCE.

I have also tried using the private dns (https://<api-gateway-id>.execute-api.<region> That results in a "Could not resolve host:" response. This is a second or alternative problem as the VPCE has Private DNS Names set to enabled and should work if I've understood it correctly.

So far some of the things I've tried:
I've tried with and without the stage name as the initial path.
I've removing the Resource policy from the API Gateway and I've tried removing the Deny-part of it. I've also tried with a Deny-part with VPCE instead of VPC.

The troubleshooting guide at Link: indicates that it might be the resource policy but I haven't been able to figure it out.

One thing I've noticed is that after associating the VPCE to my API Gateway it shows in the list in the console. However, when I use the aws get-rest-api command in the console, the VPCE is not listed in the endpointConfiguration like is shows in the response here: Link:

Is it the resource policy that is wrong or is it something else I'm missing?

Thanks in advance

Edited by: frlo on Jan 20, 2020 1:36 AM

3 Answers

Updated with clarification of URL used to access API Gateway.

answered 3 years ago


Can you confirm your curl either includes a host header override or the x-apigw-api-id header as noted in the documentation?


answered 3 years ago


Thanks for the reply.

The command I've used:

curl -v -k -H "Host: <api-gw-id>-execute-api.<region>" https://<vpce-dns-hostname>.execute-api.<region>

I've double checked the header and url. But it seems that wasn't enough.

After thinking to try to put the host header after the url like in the documentation I rewrote the whole command instead of using up arrow and editing and it worked. After some triple-checking it turns out my problem was a typo in the host header. The character between <api-gw-id> and execute-api had been a hyphen instead of a dot.

Kind regards

Edited by: frlo on Jan 21, 2020 12:57 AM

answered 3 years 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.

Guidelines for Answering Questions