无法从 VPC 私有子网内的 Lambda 发布到 SNS 主题

Unable to publish to SNS Topic from Lambda inside private subnet of VPC

提问人:Sree Teja 提问时间:10/25/2023 更新时间:10/25/2023 访问量:27

问:

我有一个 lambda 函数,它需要访问在我的 VPC 的私有子网上运行的 EC2。因此,我将 lambda 与 VPC 的私有子网相关联。我的 lambda 还需要发布到 SNS 主题。我什至为 SNS 访问配置了 SNS VPC 接口终端节点。但是我无法从这个 lambda 发布到 SNS。我做错了什么?这是我的配置。

resource "aws_vpc_endpoint" "sns" {
  vpc_id              = VPC_ID
  service_name        = "com.amazonaws.ca-central-1.sns"
  vpc_endpoint_type   = "Interface"
  private_dns_enabled = true
  subnet_ids = [
    PRIVATE_SUBNET_ID
  ]
  security_group_ids = [
    SECURITY_GROUP_FOR_PRIVATE_EC2_ID
  ]
}

resource "aws_eip" "nat_eip" {
  domain = "vpc"
  tags = {
    Name = "TAG"
  }

  depends_on = [aws_internet_gateway.db_proxy]
}

resource "aws_nat_gateway" "db_proxy" {
  allocation_id = aws_eip.nat_eip.id
  subnet_id     = PUBLIC_SUBNET_ID

  tags = {
    Name = "TAG"
  }

  depends_on = [aws_internet_gateway.db_proxy]
}

# Route Table associated with Private Subnet
resource "aws_route_table" "db_proxy_private" {
  vpc_id = VPC_ID

  route {
    cidr_block     = "0.0.0.0/0"
    nat_gateway_id = aws_nat_gateway.db_proxy.id
  }

  tags = {
    Name = "TAG"
  }
}

# Security group associated with Private EC2.
resource "aws_security_group" "db_proxy_sg_private" {
  name        = NAME
  description = "Managed by Terraform"
  vpc_id      = VPC_ID

  # To Allow SSH Transport
  ingress {
    from_port   = 22
    protocol    = "tcp"
    to_port     = 22
    cidr_blocks = ["10.0.1.0/24"] // Public Subnet CIDR
    description = "Whitelisted SSH IPs"
  }

  # To Allow Port 80 Transport
  ingress {
    from_port   = 80
    protocol    = "tcp"
    to_port     = 80
    cidr_blocks = ["10.0.1.0/24"] // Public Subnet CIDR
    description = "Outgoing HTTP transport"
  }

  # Open port 8000 for external access
  ingress {
    from_port   = 8000
    protocol    = "tcp"
    to_port     = 8000
    cidr_blocks = ["10.0.1.0/24"] // Public Subnet CIDR
    description = "EC2 HTTP port"
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }

  lifecycle {
    create_before_destroy = true
  }
}

假设 Lambda 已成功与私有子网和私有安全组关联。Lambda 配置未在此处附加。

当 lambda 与私有子网关联时,我的 SNS 调用超时。解离后,它会按预期工作。我假设配置 SNS VPC 接口终端节点有问题。

aws-lambda amazon-sns amazon-vpc vpc- 终端节点

评论

1赞 Mark B 10/25/2023
您为 Lambda 函数分配了哪个安全组?它是否与您在问题中包含的安全组相同,该安全组与您用于 EC2 实例的安全组相同?问题中的 Terraform 代码缺少许多详细信息,例如 Lambda 函数和实际的 VPC 子网。
0赞 Sree Teja 10/25/2023
是的,我将上述安全组用于 lambda 和 SNS 终端节点。
0赞 Sree Teja 10/25/2023
注意:是我的公有子网 CIDR & 是我的私有子网 CIDR。目前,上述安全组允许来自公有子网的 SSH、80 端口、8000 端口。[10.0.1.0/24][10.0.2.0/24]
0赞 Sree Teja 10/25/2023
还要注意的是我的 VPC CIDR。[10.0.0.0/16]
1赞 Mark B 10/25/2023
您的问题是您不允许附加到 SNS 终端节点的安全组中的端口入站连接。将单个安全组用于多个完全不同类型的资源是非常糟糕的做法。您应该为 Lambda 设置一个安全组,为 EC2 设置一个安全组,为 SNS 终端节点设置另一个安全组,每个安全组都具有针对该特定资源的正确规则。443

答:

0赞 Ankush Jain 10/25/2023 #1

看来,Lambda 函数缺少 IAM 权限。VPC 中的 Lambda 函数需要以下权限才能正常工作。

执行角色权限

  • ec2:CreateNetworkInterface
  • ec2:DescribeNetworkInterfaces
  • ec2:DeleteNetworkInterface

这些权限包含在 AWS 托管策略 AWSLambdaVPCAccessExecutionRole 中。

因此,请确保 Lambda 函数的 IAM 角色附加了此托管策略。

评论

1赞 Mark B 10/25/2023
缺少 IAM 权限不会导致超时,而是会导致权限被拒绝错误。
0赞 Sree Teja 10/25/2023
是的,我完全同意@MarkB。我已经配置了 IAM 权限以创建网络接口。我遇到了超时问题,我怀疑这与与 SNS VPC 接口终端节点关联的安全组有关。