Не удается подключиться к AWS Keyspaces из лямбды в VPC

#amazon-web-services #terraform #terraform-provider-aws #amazon-keyspaces

#amazon-web-services #terraform #terraform-provider-aws #amazon-keyspaces

Вопрос:

Я следовал приведенным здесь инструкциям и создал инфраструктуру, которая, по моему мнению, мне нужна, используя 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 , 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",
      "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)"
      ]
    }
  ]
}
  

Я создал 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
    ]
  }
}
  

Что я здесь делаю не так?

Комментарии:

1. Попробуйте использовать формат DER корневого сертификата Amazon CA. Либо преобразуйте pem в crt с помощью openssl openssl x509 -outform der -in AWSCA.pem -out your-cert.crt , либо загрузите сертификат формата DER отсюда. amazontrust.com/repository/AmazonRootCA1.cer . Не забудьте обновить код своей функции новым форматом сертификата. 🙂

2. В keyspaces_endpoint_vpc_access группе безопасности нет никаких явных egress правил. Предоставляет ли Terraform доступ по умолчанию «Все исходящие»? (Вы можете проверить, просмотрев группу безопасности после ее развертывания.)

3. @JohnRotenstein, похоже, не имеет значения.

4. @SRATH Я пытался использовать .cer , но получаю ту же ошибку

Ответ №1:

Проблема заключалась в конфигурации SSL в лямбда-коде.

Крайне важно вызывать SetHostNameResolver , но, по-видимому, только внутри VPC:

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