Home > Software engineering >  Spring on Fargate can't connect to AWS SES
Spring on Fargate can't connect to AWS SES

Time:04-27

I'm trying to send emails through my Java application that I'm running on a container in Fargate. My containers are running in a VPC behind a API gateway, the connections to external services are made through VPC endpoints.

All that infra is deployed using Terraform. The Java app runs ok localy, but not when deployed to AWS, so I'm thinking that there is one missing config.

The Java app follows the AWS guidelines found here:

https://docs.aws.amazon.com/ses/latest/dg/send-email-raw.html

Following are some spinets of the Terraform code:

# SECURITY GROUPS
resource "aws_security_group" "security_group_containers" {
  name   = "security_group_containers_${var.project_name}_${var.environment}"
  vpc_id = var.vpc_id

  ingress {
    protocol         = "-1"
    from_port        = 0
    to_port          = 0
    cidr_blocks      = ["0.0.0.0/0"]
    ipv6_cidr_blocks = ["::/0"]
    self             = true
  }

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

  tags = {
    Name        = "security_group_containers_${var.project_name}_${var.environment}"
  }
}

resource "aws_security_group" "security_group_ses" {
  name        = "security_group_ses_${var.project_name}_${var.environment}"
  vpc_id      = var.vpc_id

  ingress {
    protocol    = "-1"
    from_port   = 0
    to_port     = 0
    cidr_blocks      = ["0.0.0.0/0"]
    ipv6_cidr_blocks = ["::/0"]
  }

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

  tags = {
    Name = "security_group_ses_${var.project_name}_${var.environment}"
  }
}

# VPC

resource "aws_vpc" "main" {
    cidr_block           = var.cidr
    enable_dns_support   = true
    enable_dns_hostnames = true
  }

resource "aws_subnet" "private_subnet" {
    vpc_id            = aws_vpc.main.id
    cidr_block        = var.private_subnets[0]
    availability_zone = "us-east-1b"

    tags = {
        Name= "private_subnet_${var.project_name}_${var.environment}"
    }
}


# VPC ENDPOINT
resource "aws_vpc_endpoint" "ses_endpoint" {
  security_group_ids  = [aws_security_group.security_group_ses]
  service_name        = "com.amazonaws.${var.aws_region}.email-smtp"
  vpc_endpoint_type   = "Interface"
  subnet_ids          = [aws_subnet.private_subnet.id]
  private_dns_enabled = true
  tags = {
    "Name" = "vpc_endpoint_ses_${var.project_name}_${var.environment}"
  }
  vpc_id = aws_vpc.main.id
}

If there are any important service missing tell me so I can add it.

As you can see I'm keeping all traffic open, so the solution found here doesn't works for me. When the app tries to send an email I get to following error:

software.amazon.awssdk.core.exception.SdkClientException: Unable to execute HTTP request: Connect to email.us-east-1.amazonaws.com:443 [email.us-east-1.amazonaws.com/52.0.170.238, email.us-east-1.amazonaws.com/54.234.96.52, email.us-east-1.amazonaws.com/34.239.37.81, email.us-east-1.amazonaws.com/18.208.125.60, email.us-east-1.amazonaws.com/52.204.223.71, email.us-east-1.amazonaws.com/18.235.72.5, email.us-east-1.amazonaws.com/18.234.10.182, email.us-east-1.amazonaws.com/44.194.249.132] failed: connect timed out

I think that I'm missing some config to make the java awssdk use the VPC endpoint.

Edit 01 - adding execution policies:

arn:aws:iam::aws:policy/AmazonSESFullAccess

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ses:*"
            ],
            "Resource": "*"
        }
    ]
}

arn:aws:iam::aws:policy/AmazonECS_FullAccess (too large)

arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ecr:GetAuthorizationToken",
                "ecr:BatchCheckLayerAvailability",
                "ecr:GetDownloadUrlForLayer",
                "ecr:BatchGetImage",
                "logs:CreateLogStream",
                "logs:PutLogEvents"
            ],
            "Resource": "*"
        }
    ]
}

Edit 02 - changed to use a SMTP library:

The code used can be found here

Everything worked fine with SMTP

CodePudding user response:

You've created a VPC endpoint for the SES SMTP API, but the error message you are getting email.us-east-1.amazonaws.com:443 is for the AWS SES Service API. You can see the two sets of APIs here. If you are using the AWS SDK to interact with SES in your Java application, then you need to change VPC endpoint to be service_name = "com.amazonaws.${var.aws_region}.email"

Your current endpoint configuration would work if you were configuring your Java application to use SMTP (such as with the JavaMail API).

  • Related