Skip to content

Instantly share code, notes, and snippets.

@danquack
Last active January 26, 2020 17:50
Show Gist options
  • Save danquack/5c4ffc2b57324005a3f782366b4da3ce to your computer and use it in GitHub Desktop.
Save danquack/5c4ffc2b57324005a3f782366b4da3ce to your computer and use it in GitHub Desktop.
Private Fargate Instance with no internet egress: https://dev.to/danquack/private-fargate-deployment-with-vpc-endpoints-1h0p
data "aws_iam_policy_document" "fargate-role-policy" {
statement {
actions = ["sts:AssumeRole"]
principals {
type = "Service"
identifiers = ["ecs.amazonaws.com", "ecs-tasks.amazonaws.com"]
}
}
}
resource "aws_iam_policy" "fargate_execution" {
name = "fargate_execution_policy"
policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ecr:GetDownloadUrlForLayer",
"ecr:BatchGetImage",
"ecr:BatchCheckLayerAvailability"
],
"Resource": "arn:aws:ecr:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:repository/${var.app_image}"
},
{
"Effect": "Allow",
"Action": [
"ecr:GetAuthorizationToken"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream"
],
"Resource": "*"
}
]
}
EOF
}
resource "aws_iam_policy" "fargate_task" {
name = "fargate_task_policy"
policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "*"
}
]
}
EOF
}
resource "aws_iam_role" "fargate_execution" {
name = "fargate_execution_role"
assume_role_policy = data.aws_iam_policy_document.fargate-role-policy.json
}
resource "aws_iam_role" "fargate_task" {
name = "fargate_task_role"
assume_role_policy = data.aws_iam_policy_document.fargate-role-policy.json
}
resource "aws_iam_role_policy_attachment" "fargate-execution" {
role = aws_iam_role.fargate_execution.name
policy_arn = aws_iam_policy.fargate_execution.arn
}
resource "aws_iam_role_policy_attachment" "fargate-task" {
role = aws_iam_role.fargate_task.name
policy_arn = aws_iam_policy.fargate_task.arn
}
# Fargate Container
resource "aws_cloudwatch_log_group" "app" {
name = "/ecs/app"
tags = {
Environment = "dev"
}
}
resource "aws_ecs_cluster" "main" {
depends_on = [aws_cloudwatch_log_group.app]
name = "cluster"
}
locals {
container_defintion = [{
cpu = 1024
image = "${data.aws_caller_identity.current.account_id}.dkr.ecr.${data.aws_region.current.name}.amazonaws.com/${var.app_image}"
memory = 2048
name = "app"
networkMode = "awsvpc"
logConfiguration = {
logdriver = "awslogs"
options = {
"awslogs-group" = "/ecs/app"
"awslogs-region" = data.aws_region.current.name
"awslogs-stream-prefix" = "stdout"
}
}
}]
}
resource "aws_ecs_task_definition" "app" {
family = "app"
network_mode = "awsvpc"
cpu = local.container_defintion.0.cpu
memory = local.container_defintion.0.memory
requires_compatibilities = ["FARGATE"]
container_definitions = jsonencode(local.container_defintion)
execution_role_arn = aws_iam_role.fargate_execution.arn
task_role_arn = aws_iam_role.fargate_task.arn
tags = {
Name = "app"
Environment = "dev"
}
}
resource "aws_ecs_service" "main" {
name = "service"
cluster = aws_ecs_cluster.main.id
task_definition = aws_ecs_task_definition.app.arn
desired_count = "1"
launch_type = "FARGATE"
network_configuration {
security_groups = [aws_security_group.ecs_task.id]
subnets = [aws_subnet.private_a.id]
}
}
provider "aws" {
region = "us-east-1"
}
data "aws_region" "current" {}
data "aws_caller_identity" "current" {}
resource "aws_security_group" "vpce" {
name = "vpce"
vpc_id = aws_vpc.main.id
ingress {
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = [aws_vpc.main.cidr_block]
}
tags = {
Environment = "dev"
}
}
resource "aws_security_group" "ecs_task" {
name = "ecs"
vpc_id = aws_vpc.main.id
egress {
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = [aws_vpc.main.cidr_block]
}
egress {
from_port = 443
to_port = 443
protocol = "tcp"
prefix_list_ids = [aws_vpc_endpoint.s3.prefix_list_id]
}
tags = {
Environment = "dev"
}
}
variable "app_image" {}
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
enable_dns_hostnames = true
enable_dns_support = true
tags = {
Name = "endpoint"
Environment = "dev"
}
}
resource "aws_subnet" "private_a" {
vpc_id = aws_vpc.main.id
cidr_block = "10.0.2.0/24"
availability_zone = "${data.aws_region.current.name}a"
tags = {
Name = "endpoint-private-a"
Environment = "dev"
}
}
resource "aws_subnet" "private_b" {
vpc_id = aws_vpc.main.id
cidr_block = "10.0.1.0/24"
availability_zone = "${data.aws_region.current.name}b"
tags = {
Name = "endpoint-private-b"
Environment = "dev"
}
}
resource "aws_route_table" "private" {
vpc_id = aws_vpc.main.id
tags = {
Name = "Endpoint Private"
Environment = "dev"
}
}
resource "aws_route_table_association" "private_a" {
subnet_id = aws_subnet.private_a.id
route_table_id = aws_route_table.private.id
}
resource "aws_route_table_association" "private_b" {
subnet_id = aws_subnet.private_b.id
route_table_id = aws_route_table.private.id
}
resource "aws_vpc_endpoint" "s3" {
vpc_id = aws_vpc.main.id
service_name = "com.amazonaws.${data.aws_region.current.name}.s3"
vpc_endpoint_type = "Gateway"
route_table_ids = [aws_route_table.private.id]
tags = {
Name = "s3-endpoint"
Environment = "dev"
}
}
resource "aws_vpc_endpoint" "dkr" {
vpc_id = aws_vpc.main.id
private_dns_enabled = true
service_name = "com.amazonaws.${data.aws_region.current.name}.ecr.dkr"
vpc_endpoint_type = "Interface"
security_group_ids = [
aws_security_group.vpce.id,
]
subnet_ids = [aws_subnet.private_a.id, aws_subnet.private_b.id]
tags = {
Name = "dkr-endpoint"
Environment = "dev"
}
}
resource "aws_vpc_endpoint" "logs" {
vpc_id = aws_vpc.main.id
private_dns_enabled = true
service_name = "com.amazonaws.${data.aws_region.current.name}.logs"
vpc_endpoint_type = "Interface"
security_group_ids = [
aws_security_group.vpce.id,
]
subnet_ids = [aws_subnet.private_a.id, aws_subnet.private_b.id]
tags = {
Name = "logs-endpoint"
Environment = "dev"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment