无法从VPC中的Lambda连接到AWS Keyspace

问题描述

我已按照here的说明进行操作,并创建了我认为需要使用terraform的基础结构。但是,尝试连接时出现此错误

{
  "errorType": "AggregateException","errorMessage": "One or more errors occurred. (All hosts tried for query Failed (tried 172.31.41.121:9142: AuthenticationException 'The remote certificate is invalid according to the validation procedure.'; 172.31.18.20:9142: AuthenticationException 'The remote certificate is invalid according to the validation procedure.'))","stackTrace": [
    "at lambda_method(Closure,Stream,LambdaContextInternal )"
  ],"cause": {
    "errorType": "NoHostAvailableException","errorMessage": "All hosts tried for query Failed (tried 172.31.41.121:9142: AuthenticationException 'The remote certificate is invalid according to the validation procedure.'; 172.31.18.20:9142: AuthenticationException 'The remote certificate is invalid according to the validation procedure.')","stackTrace": [
      "at Cassandra.Connections.Control.ControlConnection.Connect(Boolean isInitializing)","at Cassandra.Connections.Control.ControlConnection.InitAsync()","at Cassandra.Tasks.TaskHelper.WaitToCompleteAsync(Task task,Int32 timeout)","at Cassandra.Cluster.Init()","at Cassandra.Cluster.ConnectAsync(String keyspace)"
    ]
  },"causes": [
    {
      "errorType": "NoHostAvailableException","stackTrace": [
        "at Cassandra.Connections.Control.ControlConnection.Connect(Boolean isInitializing)","at Cassandra.Cluster.ConnectAsync(String keyspace)"
      ]
    }
  ]
}

我创建了一个aws_vpc_endpoint_service,因此感到惊讶,这是行不通的。

# Security group for resources that want to access Keyspaces from the VPC
resource "aws_security_group" "keyspaces_endpoint_vpc_access" {
  name   = "keyspaces-endpoint-access"
  vpc_id = aws_default_vpc.default.id
}

resource "aws_security_group" "keyspaces_endpoint" {
  name   = "keyspaces-endpoint"
  vpc_id = aws_default_vpc.default.id

  ingress {
    from_port       = 9142
    to_port         = 9142
    protocol        = "tcp"
    security_groups = [ aws_security_group.keyspaces_endpoint_vpc_access.id ]
  }
}

data "aws_vpc_endpoint_service" "keyspaces" {
  service = "cassandra"
}

resource "aws_vpc_endpoint" "keyspaces_endpoint" {
  vpc_id              = aws_default_vpc.default.id
  vpc_endpoint_type   = "Interface"
  service_name        = data.aws_vpc_endpoint_service.keyspaces.service_name
  security_group_ids  = [ aws_security_group.keyspaces_endpoint.id ]
  private_dns_enabled = true

  subnet_ids = [
    data.aws_subnet.selected.id,aws_default_subnet.subnet_a.id,aws_default_subnet.subnet_b.id
  ]

  policy  = <<EOF
      {
        "Statement": [
          {
            "Sid": "keyspaces-full-access","Principal": "*","Action": "cassandra:*","Effect": "Allow","Resource": "*"
          }
        ]
      }
    EOF
}

resource "aws_security_group" "my_func" {
  vpc_id      = aws_default_vpc.default.id

  egress {
    from_port   = 0
    to_port     = 65535
    protocol    = "tcp"
    cidr_blocks = [ "0.0.0.0/0" ]
  }

  lifecycle {
    create_before_destroy = true
  }
}

resource "aws_lambda_function" "my_func" {
  runtime          = "dotnetcore3.1"
  timeout          = 900
  memory_size      = 512

  # etc.

  vpc_config {
    subnet_ids         = [ data.aws_subnet.selected.id ]
    security_group_ids = [
      aws_security_group.my_func.id,aws_security_group.keyspaces_endpoint_vpc_access.id
    ]
  }
}

在这里做什么错了?

解决方法

问题是Lambda代码中的SSL配置。

调用SetHostNameResolver很重要,但显然只有在VPC内部时才调用:

    let sslOptions =
      SSLOptions()
        .SetCertificateCollection(certCollection)
        .SetHostNameResolver (fun _ -> sprintf "cassandra.%s.amazonaws.com" region)