nZac

ECS-Fargate Private ECR Through VPC Endpoints

When working with ECS services that don't have access to the internet you need security group rules that enable the docker pull to connect to the account ECR.

There are a few moving parts.

First, create the VPC endpoints normally required for ECS Fargate. The Secrets manager is not strictly required for ECR endpoints but most containers need a secret.

module "vpc_endpoints" {
  source  = "terraform-aws-modules/vpc/aws//modules/vpc-endpoints"
  version = "~> 5"

  vpc_id = local.vpc_id

  create_security_group      = true
  security_group_name_prefix = "vpc-endpoints-"
  security_group_description = "VPC endpoint security group"
  security_group_rules = {
    ingress_https = {
      description = "HTTPS from VPC"
      cidr_blocks = [local.vpc_cidr_block]
    }
  }

  endpoints = {
    ecr_dkr = {
      service             = "ecr.dkr"
      private_dns_enabled = true
      subnet_ids          = local.private_subnets
      tags                = { Name = "ecr-dkr-vpc-endpoint" }
    },

    ecr_api = {
      service             = "ecr.api"
      private_dns_enabled = true
      subnet_ids          = local.private_subnets
      tags                = { Name = "ecr-api-vpc-endpoint" }
    }

    cloudwatch = {
      service             = "logs"
      private_dns_enabled = true
      subnet_ids          = local.private_subnets
      tags                = { Name = "logs-vpc-endpoint" }
    }

    s3 = {
      service      = "s3"
      service_type = "Gateway"
      subnet_ids   = local.private_subnets
      route_table_ids = local.private_subnet_route_table_ids
      tags         = { Name = "s3-gateway-vpc-endpoint" }
    }

    secretsmanager = {
      service             = "secretsmanager"
      private_dns_enabled = true
      subnet_ids          = local.private_subnets
      tags = {
        Name = "secretsmanager-vpc-endpoint"
      }
    }
  }
}

Note the use of a Gateway S3, that means there is no ENI launched into the VPC whereas the others are interfaces which do have a VPC private ENI created and attached.

Next create an ECS cluster with a service inside that has the following SG rules:

  1. Egress 443 to module.vpc_endpoints.endpoints["s3"].prefix_list_id. This will allow the IP's of the public S3 endpoints even though the traffic is private.
  2. Egress 443 to the source security group id of module.vpc_endpoints.security_group_id. This will allow 443 to the security group of the endpoints.
  3. Make sure your route tables in the private subnet have a route to the S3 gateway.

You might need other SG rules for RDS, Elasticache, OpenSearch, or ingress from an ALB but that is on you.