skip to Main Content

I have an S3 bucket in Account A and a lambda function in Account B. I want the lambda to read the contents from the bucket, so have assigned the appropriate permissions to the IAM role and added that IAM role to the bucket’s trust policy. The lambda works fine when it is not part of my VPC, but when it is in the VPC of Account B then the lambda times out which makes me think that the timeout is due to a connectivity problem.

I have used a VPC endpoint for a different lambda to access Secrets Manager, but a VPC endpoint to connect to S3 doesn’t solve the problem in this case. I have read in some places that the lambda needs a NAT/Internet Gateway in order to connect to a cross account Bucket, but AWS say:

By default, Lambda functions have access to the public internet. This is not the case after they have been configured with access to one of your VPCs. If you continue to need access to resources on the internet, set up a NAT instance or Amazon NAT Gateway. Alternatively, you can also use VPC endpoints to enable private communications between your VPC and supported AWS services.

So, simple question really: Does the lambda need a NAT/Internet gateway to access the bucket, or should the VPC endpoint be enough?

EDIT:
terraform for the VPC endpoint.

resource "aws_vpc_endpoint" "s3" {
  vpc_id            = aws_vpc.main.id
  service_name      = "com.amazonaws.eu-west-1.s3"
  vpc_endpoint_type = "Interface"

  security_group_ids = [
    aws_security_group.lambda.id,
  ]

  subnet_ids          = [aws_subnet.subnet_1a.id]

  tags = {
    Name        = "vpc-endpoint-s3"
    Environment = var.aws_profile
    Terraform   = true
  }
}

resource "aws_vpc_endpoint_security_group_association" "s3" {
  vpc_endpoint_id   = aws_vpc_endpoint.s3.id
  security_group_id = aws_security_group.lambda.id
}

3

Answers


  1. Chosen as BEST ANSWER

    I found a solution which I will post here for anyone who encounters the same issue.

    Unlike the VPC Endpoint for Secrets Manager, the VPC Endpoint type should be Gateway, not Interface. The association with the Lambda therefore needs to be made via the route table, not directly on the endpoint by attaching subnets and security groups. I have the lambda in the public subnet associated with the route table now and it seems to be working.

    Here is the terraform: vpc_endpoint

    resource "aws_vpc_endpoint" "s3" {
      vpc_id            = aws_vpc.main.id
      service_name      = "com.amazonaws.eu-west-1.s3"
      vpc_endpoint_type = "Gateway"
    
      tags = {
        Name        = "vpc-endpoint-s3"
        Environment = var.aws_profile
        Terraform   = true
      }
    }
    

    aws_vpc_endpoint_route_table_association

    resource "aws_vpc_endpoint_route_table_association" "s3" {
      route_table_id  = aws_route_table.rt.id
      vpc_endpoint_id = aws_vpc_endpoint.s3.id
    }
    

    aws_route_table

    resource "aws_route_table" "rt" {
      vpc_id = aws_vpc.main.id
    
      route {
        cidr_block = "0.0.0.0/0"
        gateway_id = aws_internet_gateway.igw.id
      }
    
      tags = {
        Name        = "rt"
        Environment = var.aws_profile
        Terraform   = true
      }
    }
    

    Hopefully this will help the next person


  2. Does the lambda need a NAT/Internet gateway to access the bucket, or should the VPC endpoint be enough?

    If you do have NAT/IGW, your lambda must be in a private subnet with properly setup route table to NAT.

    Alternatively, use VPC endpoint or do not place your function in a VPC. In that case, you do not have to do anything special to access s3.

    Login or Signup to reply.
  3. A VPC endpoint is all you need to connect to an AWS service from a VPC. In the case of S3, you have the choice to choose between an interface endpoint and a gateway endpoint.

    You have configured the interface endpoint incorrectly. This is the issue:

    security_group_ids = [
      aws_security_group.lambda.id,
    ]
    

    you are associating the security group of the lambda to the VPC endpoint, however I suspect that that security group does not allow access to itself.

    Instead, following best practices, you should create a separate security group for the endpoint:

    resource "aws_security_group" "vpc_endpoint_security_group" {
      vpc_id = aws_vpc.main.id
      name   = "allow traffic to vpc endpoint"
      ingress {
        from_port = 0
        to_port   = 0
        protocol  = -1
        security_groups = [aws_security_group.lambda.id]
      }
      egress {
        from_port = 0
        to_port   = 0
        protocol  = "-1"
        cidr_blocks = ["0.0.0.0/0"]
      }
    }
    
    resource "aws_vpc_endpoint" "s3" {
      vpc_id            = aws_vpc.main.id
      service_name      = "com.amazonaws.eu-west-1.s3"
      vpc_endpoint_type = "Interface"
    
      security_group_ids = [
        aws_security_group.vpc_endpoint_security_group.id,
      ]
    
      subnet_ids          = [aws_subnet.subnet_1a.id]
    
      tags = {
        Name        = "vpc-endpoint-s3"
        Environment = var.aws_profile
        Terraform   = true
      }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search