can't access my instances by public IP in a VPC (aka: what is wrong with my terraform)? As stated in the title of the question, I have a Terraform file (attached below), but the infrastructure it builds doesn't allow me to connect by SSH (I get "Connection timed out"). So either the packets aren't getting to the EC2 instances or the responses aren't getting out. Any ideas? For the purposes of this question the DNS and ALB can be ignored (the former works fine, the latter almost certainly doesn't yet).

provider "aws" {
  region = "us-west-2"
}

resource "aws_vpc" "vpc" {
  cidr_block = "10.0.0.0/16"
}

resource "aws_internet_gateway" "gw" {
  vpc_id = "${aws_vpc.vpc.id}"
}

resource "aws_subnet" "subnet_a" {
  vpc_id = "${aws_vpc.vpc.id}"
  cidr_block = "10.0.1.0/24"
  availability_zone = "us-west-2a"
}

resource "aws_subnet" "subnet_b" {
  vpc_id = "${aws_vpc.vpc.id}"
  cidr_block = "10.0.2.0/24"
  availability_zone = "us-west-2b"
}

resource "aws_route_table" "rt" {
  vpc_id = "${aws_vpc.vpc.id}"

  route {
    cidr_block = "0.0.0.0/0"
    gateway_id = "${aws_internet_gateway.gw.id}"
  }
}

resource "aws_route_table_association" "rt_a" {
  subnet_id = "${aws_subnet.subnet_a.id}"
  route_table_id = "${aws_route_table.rt.id}"
}

resource "aws_route_table_association" "rt_b" {
  subnet_id = "${aws_subnet.subnet_b.id}"
  route_table_id = "${aws_route_table.rt.id}"
}

resource "aws_security_group" "alb_sg" {
  vpc_id = "${aws_vpc.vpc.id}"

  ingress {
    from_port = 0
    to_port = 80
    protocol = "tcp"
  }

  ingress {
    from_port = 0
    to_port = 443
    protocol = "tcp"
  }
}

resource "aws_alb" "alb" {
  internal = false
  load_balancer_type = "application"
  security_groups = ["${aws_security_group.alb_sg.id}"]
  subnets = ["${aws_subnet.subnet_a.id}","${aws_subnet.subnet_b.id}"]
}

resource "aws_route53_zone" "primary" {
  name = "REDACTED.REDACTED"
}

resource "aws_route53_record" "alias_route53_record" {
  zone_id = "${aws_route53_zone.primary.zone_id}"
  name    = "REDACTED.REDACTED"
  type    = "A"

  alias {
    name                   = "${aws_alb.alb.dns_name}"
    zone_id                = "${aws_alb.alb.zone_id}"
    evaluate_target_health = true
  }
}

resource "aws_key_pair" "kp" {
  key_name = "kp2019y09m25d001i"
  public_key = "ssh-rsa REDACTED"
}

resource "aws_instance" "instance_a" {
  ami = "ami-08ba47c10a42c61be"
  instance_type = "t2.micro"
  availability_zone = "us-west-2a"
  subnet_id = "${aws_subnet.subnet_a.id}"
  associate_public_ip_address = true
  key_name = "${aws_key_pair.kp.key_name}"
}

resource "aws_instance" "instance_b" {
  ami = "ami-08ba47c10a42c61be"
  instance_type = "t2.micro"
  availability_zone = "us-west-2b"
  subnet_id = "${aws_subnet.subnet_b.id}"
  associate_public_ip_address = true
  key_name = "${aws_key_pair.kp.key_name}"
}

output "instance_a_ip" {
  value = "${aws_instance.instance_a.public_ip}"
}

output "instance_b_ip" {
  value = "${aws_instance.instance_b.public_ip}"
}
Your default security groups and newly created security groups include default rules that do not enable you to access your instance from the Internet.
Add this:


resource "aws_security_group" "allow-ssh" {
  vpc_id = "${aws_vpc.vpc.id}"

  ingress {
    from_port = 0
    to_port = 22
    protocol = "tcp"
  }
}


Then add the line vpc_security_group_ids = [aws_security_group.allow-ssh.id] to the instance definitions.