Automating the α and the Ω of Your Infrastructure Automatic creation and destruction through Infrastructure as code

Problems with Managing (Cloud) Infrastructure (Manually)

Visibility

  • Details are siloed in someone's head
  • Changes are not visible
  • Dependencies are hard to see

Difficulty

  • Almost impossible to replicate
  • Different APIs for different cloud providers
  • Tedious and prone to errors

Infrastructure as Code

Provision, update, and manage your cloud infrastructure with code.

Benefits

  • Automated
  • Version control with VCS like Git
  • Replicate just by "copy/pasting" or changing variables
  • "Just" read the code to figure out details
  • "Just" read the code to figure out dependencies
  • Abstraction and reusability

Terraform

  • FOSS and paid versions
  • Declarative configuration
  • Single format across multiple providers
  • Huge list of providers supported

Ansible/Chef/Puppet

  • Configuration management that can also manage infrastructure
  • More "procedural" form of provisioning
  • Works well with Terraform — configure after Terraform provisions

CloudFormation/Heat

  • Specific to the service
  • Each service has its own syntax

Launching an EC2 Instance

  • Create an EC2 Instance
  • Create security group rule to allow SSH access

Provider

  • Providers are plugins
provider "aws" {
  version = "~> 1.33"
  region  = "${var.aws_region}"
}

variables

  • Variables allows reusability.
  • Define different variables for different "instances" or enrivonments
  • Many ways to manage environment in Terraform.
  • Provide values at run time with `varfiles`.

Security Group Rules

  • Firewall rules for instances
  • Use Interpolation to "refer" to other Terraform resources
  • Creates implicit dependencies
  • Terraform will figure out the rest

AMI

  • Find image to launch instance
  • Use `data` sources to refer to existing infrastructure
  • No need to hardcode AMI

Instance

  • Finally "deploy" the instance
  • Interpolate other resources

Terraform Execution

  • Desired state: Configuration files
  • Actual state: AWS Infrastructure
  • Known State: Terraform State
  • Terraform figures out the dependencies and the steps required to create the resources.

Plan

Plan

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  + aws_instance.instance
      id:                                        <computed>
      ami:                                       "ami-0238c4a6bd553d40a"
      arn:                                       <computed>
      associate_public_ip_address:               <computed>
      availability_zone:                         <computed>
      cpu_core_count:                            <computed>
      cpu_threads_per_core:                      <computed>
      ebs_block_device.#:                        <computed>
      ephemeral_block_device.#:                  <computed>
      get_password_data:                         "false"
      instance_state:                            <computed>
      instance_type:                             "t2.micro"
      ipv6_address_count:                        <computed>
      ipv6_addresses.#:                          <computed>
      key_name:                                  "terraform"
      network_interface.#:                       <computed>
      network_interface_id:                      <computed>
      password_data:                             <computed>
      placement_group:                           <computed>
      primary_network_interface_id:              <computed>
      private_dns:                               <computed>
      private_ip:                                <computed>
      public_dns:                                <computed>
      public_ip:                                 <computed>
      root_block_device.#:                       "1"
      root_block_device.0.delete_on_termination: "true"
      root_block_device.0.volume_id:             <computed>
      root_block_device.0.volume_size:           "8"
      root_block_device.0.volume_type:           "gp2"
      security_groups.#:                         <computed>
      source_dest_check:                         "true"
      subnet_id:                                 "subnet-364a6551"
      tags.%:                                    "3"
      tags.Name:                                 "Terraform Demo"
      tags.Terraform:                            "true"
      tags.Usage:                                "Terraform Talk by Yong Wen"
      tenancy:                                   <computed>
      volume_tags.%:                             "3"
      volume_tags.Name:                          "Terraform Demo"
      volume_tags.Terraform:                     "true"
      volume_tags.Usage:                         "Terraform Talk by Yong Wen"
      vpc_security_group_ids.#:                  <computed>

  + aws_security_group.instance
      id:                                        <computed>
      arn:                                       <computed>
      description:                               "Managed by Terraform"
      egress.#:                                  <computed>
      ingress.#:                                 <computed>
      name:                                      "Terraform Demo"
      owner_id:                                  <computed>
      revoke_rules_on_delete:                    "false"
      tags.%:                                    "3"
      tags.Name:                                 "Terraform Demo"
      tags.Terraform:                            "true"
      tags.Usage:                                "Terraform Talk by Yong Wen"
      vpc_id:                                    "vpc-dac9bcbd"

  + aws_security_group_rule.ssh_inbound
      id:                                        <computed>
      cidr_blocks.#:                             "1"
      cidr_blocks.0:                             "10.0.0.0/8"
      from_port:                                 "22"
      protocol:                                  "tcp"
      security_group_id:                         "${aws_security_group.instance.id}"
      self:                                      "false"
      source_security_group_id:                  <computed>
      to_port:                                   "22"
      type:                                      "ingress"


Plan: 3 to add, 0 to change, 0 to destroy.

Executing the Plan

Modify

  • Plan will show the diff in what Terraform will do
  • Some changes are destructive
  • Some are "in-place"
An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  ~ update in-place
-/+ destroy and then create replacement

Terraform will perform the following actions:

  ~ aws_instance.instance
      tags.%:                   "3" => "4"
      tags.Demo:                "" => "true"
      volume_tags.%:            "3" => "4"
      volume_tags.Demo:         "" => "true"

  ~ aws_security_group.instance
      tags.%:                   "3" => "4"
      tags.Demo:                "" => "true"

-/+ aws_security_group_rule.ssh_inbound (new resource required)
      id:                       "sgrule-68829610" => <computed> (forces new resource)
      cidr_blocks.#:            "1" => "2" (forces new resource)
      cidr_blocks.0:            "10.0.0.0/8" => "10.0.0.0/8"
      cidr_blocks.1:            "" => "192.168.0.0/16" (forces new resource)
      from_port:                "22" => "22"
      protocol:                 "tcp" => "tcp"
      security_group_id:        "sg-062b707aad99b2c9b" => "sg-062b707aad99b2c9b"
      self:                     "false" => "false"
      source_security_group_id: "" => <computed>
      to_port:                  "22" => "22"
      type:                     "ingress" => "ingress"


Plan: 1 to add, 2 to change, 1 to destroy.

Destroy!

  • Easy to clean up and destroy
  • (Also easy to re-create!)
  • Reverse of create — Terraform calculates the dependencies and destroys them in reverse.
An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  - destroy

Terraform will perform the following actions:

  - aws_instance.instance

  - aws_security_group.instance

  - aws_security_group_rule.ssh_inbound


Plan: 0 to add, 0 to change, 3 to destroy.

Do you really want to destroy all resources?
  Terraform will destroy all your managed infrastructure, as shown above.
  There is no undo. Only 'yes' will be accepted to confirm.

Application Demo

Application

  • Silly Chatroom
  • Stateless Static Javascript Client
  • Stateful Server

github.com/gyng/comicchat

Basic Idea

  • Autoscaling Group (ASG) for clients and servers separately
  • One Elastic Load Balancer (ELB) with different listener rules to target the ASG

Diagram

Hidden Details…

  • Security groups rules between ELB and EC2 instances
  • Launch configuration details for ASG
  • Listener for ports
  • Redirect HTTP ➡ HTTPS listener
  • Certificate for HTTPS
  • Listener rules to handle different host names
  • Target groups for ASG
  • Dependencies… which should I create first?

Client Autoscaling Group

Client Launch Configuration

Security Group Rules

ELB

Listeners

Don't forget extra security rules!

Repeat for the server.

terraform plan

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create
 <= read (data resources)

Terraform will perform the following actions:

 <= data.template_file.client_user_data
      id:                                        <computed>
      rendered:                                  <computed>
      template:                                  "#!/usr/bin/env bash\nset -euo pipefail\n\n# Send the log output from this script to user-data.log, syslog, and the console\n# From: https://alestic.com/2010/12/ec2-user-data-output/\nexec > >(tee /var/log/user-data.log|logger -t user-data -s 2>/dev/console) 2>&1\n\n# Install dependencies\n\napt-get update\napt-get install -y git\n\ncurl -fsSL get.docker.com | sh -\n\ncurl -L https://github.com/docker/compose/releases/download/1.22.0/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose\nchmod +x /usr/local/bin/docker-compose\n\n# Install Application\nmkdir -p /opt/comicchat\n\ncd /opt/comicchat\ngit clone ${url} ./\ngit checkout ${branch}\n\nCOMPOSE_OVERRIDE=$(cat <<EOF\nversion: \"2.4\"\nservices:\n  client:\n    build:\n      context: .\n      args:\n        WS_URL: \"wss://${server_fqdn}:${server_lb_port}\"\n\nEOF\n)\n\necho \"$${COMPOSE_OVERRIDE}\" > docker-compose.override.yml\n\ndocker-compose up -d client\n"
      vars.%:                                    <computed>

  + aws_autoscaling_attachment.client
      id:                                        <computed>
      alb_target_group_arn:                      "${aws_lb_target_group.client.arn}"
      autoscaling_group_name:                    "${aws_autoscaling_group.client.id}"

  + aws_autoscaling_attachment.server
      id:                                        <computed>
      alb_target_group_arn:                      "${aws_lb_target_group.server.arn}"
      autoscaling_group_name:                    "${aws_autoscaling_group.server.id}"

  + aws_autoscaling_group.client
      id:                                        <computed>
      arn:                                       <computed>
      default_cooldown:                          <computed>
      desired_capacity:                          "3"
      force_delete:                              "false"
      health_check_grace_period:                 "300"
      health_check_type:                         "ELB"
      launch_configuration:                      "${aws_launch_configuration.client.name}"
      load_balancers.#:                          <computed>
      max_size:                                  "3"
      metrics_granularity:                       "1Minute"
      min_size:                                  "3"
      name:                                      "terraform-demo-client"
      protect_from_scale_in:                     "false"
      service_linked_role_arn:                   <computed>
      tag.#:                                     "1"
      tag.1140031200.key:                        "Name"
      tag.1140031200.propagate_at_launch:        "true"
      tag.1140031200.value:                      "terraform-demo-client"
      target_group_arns.#:                       <computed>
      vpc_zone_identifier.#:                     "3"
      vpc_zone_identifier.1395284303:            "subnet-364a6551"
      vpc_zone_identifier.3491269669:            "subnet-958162cc"
      vpc_zone_identifier.486740267:             "subnet-f793cfbe"
      wait_for_capacity_timeout:                 "10m"

  + aws_autoscaling_group.server
      id:                                        <computed>
      arn:                                       <computed>
      default_cooldown:                          <computed>
      desired_capacity:                          "1"
      force_delete:                              "false"
      health_check_grace_period:                 "300"
      health_check_type:                         <computed>
      launch_configuration:                      "${aws_launch_configuration.server.name}"
      load_balancers.#:                          <computed>
      max_size:                                  "1"
      metrics_granularity:                       "1Minute"
      min_size:                                  "1"
      name:                                      "terraform-demo-server"
      protect_from_scale_in:                     "false"
      service_linked_role_arn:                   <computed>
      tag.#:                                     "1"
      tag.1075806302.key:                        "Name"
      tag.1075806302.propagate_at_launch:        "true"
      tag.1075806302.value:                      "terraform-demo-server"
      target_group_arns.#:                       <computed>
      vpc_zone_identifier.#:                     "3"
      vpc_zone_identifier.1395284303:            "subnet-364a6551"
      vpc_zone_identifier.3491269669:            "subnet-958162cc"
      vpc_zone_identifier.486740267:             "subnet-f793cfbe"
      wait_for_capacity_timeout:                 "10m"

  + aws_launch_configuration.client
      id:                                        <computed>
      associate_public_ip_address:               "false"
      ebs_block_device.#:                        <computed>
      ebs_optimized:                             <computed>
      enable_monitoring:                         "true"
      image_id:                                  "ami-0238c4a6bd553d40a"
      instance_type:                             "t2.micro"
      key_name:                                  "terraform"
      name:                                      <computed>
      name_prefix:                               "terraform-demo-client"
      root_block_device.#:                       "1"
      root_block_device.0.delete_on_termination: "true"
      root_block_device.0.iops:                  <computed>
      root_block_device.0.volume_size:           "8"
      root_block_device.0.volume_type:           "gp2"
      security_groups.#:                         <computed>
      user_data:                                 "0aa85067c0f5bbd064a5ceb68eefff39c8964ce7"

  + aws_launch_configuration.server
      id:                                        <computed>
      associate_public_ip_address:               "false"
      ebs_block_device.#:                        <computed>
      ebs_optimized:                             <computed>
      enable_monitoring:                         "true"
      image_id:                                  "ami-0238c4a6bd553d40a"
      instance_type:                             "t2.micro"
      key_name:                                  "terraform"
      name:                                      <computed>
      name_prefix:                               "terraform-demo-server"
      root_block_device.#:                       "1"
      root_block_device.0.delete_on_termination: "true"
      root_block_device.0.iops:                  <computed>
      root_block_device.0.volume_size:           "8"
      root_block_device.0.volume_type:           "gp2"
      security_groups.#:                         <computed>
      user_data:                                 "115a995abccff2d4a518757526bb4c588e35d10c"

  + aws_lb.lb
      id:                                        <computed>
      access_logs.#:                             <computed>
      arn:                                       <computed>
      arn_suffix:                                <computed>
      dns_name:                                  <computed>
      enable_deletion_protection:                "false"
      enable_http2:                              "true"
      idle_timeout:                              "60"
      internal:                                  <computed>
      ip_address_type:                           <computed>
      load_balancer_type:                        "application"
      name:                                      "terraform-demo"
      security_groups.#:                         <computed>
      subnet_mapping.#:                          <computed>
      subnets.#:                                 "3"
      subnets.1395284303:                        "subnet-364a6551"
      subnets.3491269669:                        "subnet-958162cc"
      subnets.486740267:                         "subnet-f793cfbe"
      tags.%:                                    "3"
      tags.Name:                                 "terraform-demo"
      tags.Terraform:                            "true"
      tags.Usage:                                "Terraform Talk by Yong Wen"
      vpc_id:                                    <computed>
      zone_id:                                   <computed>

  + aws_lb_listener.front_end
      id:                                        <computed>
      arn:                                       <computed>
      default_action.#:                          "1"
      default_action.0.redirect.#:               "1"
      default_action.0.redirect.0.host:          "#{host}"
      default_action.0.redirect.0.path:          "/#{path}"
      default_action.0.redirect.0.port:          "443"
      default_action.0.redirect.0.protocol:      "HTTPS"
      default_action.0.redirect.0.query:         "#{query}"
      default_action.0.redirect.0.status_code:   "HTTP_301"
      default_action.0.type:                     "redirect"
      load_balancer_arn:                         "${aws_lb.lb.arn}"
      port:                                      "80"
      protocol:                                  "HTTP"
      ssl_policy:                                <computed>

  + aws_lb_listener.https
      id:                                        <computed>
      arn:                                       <computed>
      certificate_arn:                           "arn:aws:acm:ap-southeast-1:957891382910:certificate/992aea66-8188-418a-b38e-88ec2df2526e"
      default_action.#:                          "1"
      default_action.0.target_group_arn:         "${aws_lb_target_group.sink.arn}"
      default_action.0.type:                     "forward"
      load_balancer_arn:                         "${aws_lb.lb.arn}"
      port:                                      "443"
      protocol:                                  "HTTPS"
      ssl_policy:                                "ELBSecurityPolicy-TLS-1-2-2017-01"

  + aws_lb_listener.server_wss
      id:                                        <computed>
      arn:                                       <computed>
      certificate_arn:                           "arn:aws:acm:ap-southeast-1:957891382910:certificate/992aea66-8188-418a-b38e-88ec2df2526e"
      default_action.#:                          "1"
      default_action.0.target_group_arn:         "${aws_lb_target_group.sink.arn}"
      default_action.0.type:                     "forward"
      load_balancer_arn:                         "${aws_lb.lb.arn}"
      port:                                      "8080"
      protocol:                                  "HTTPS"
      ssl_policy:                                "ELBSecurityPolicy-TLS-1-2-2017-01"

  + aws_lb_listener_rule.client
      id:                                        <computed>
      action.#:                                  "1"
      action.0.target_group_arn:                 "${aws_lb_target_group.client.arn}"
      action.0.type:                             "forward"
      arn:                                       <computed>
      condition.#:                               "1"
      condition.~3110813782.field:               "host-header"
      condition.~3110813782.values.#:            <computed>
      listener_arn:                              "${aws_lb_listener.https.arn}"
      priority:                                  "100"

  + aws_lb_listener_rule.server
      id:                                        <computed>
      action.#:                                  "1"
      action.0.target_group_arn:                 "${aws_lb_target_group.server.arn}"
      action.0.type:                             "forward"
      arn:                                       <computed>
      condition.#:                               "1"
      condition.~3110813782.field:               "host-header"
      condition.~3110813782.values.#:            <computed>
      listener_arn:                              "${aws_lb_listener.server_wss.arn}"
      priority:                                  "100"

  + aws_lb_target_group.client
      id:                                        <computed>
      arn:                                       <computed>
      arn_suffix:                                <computed>
      deregistration_delay:                      "300"
      health_check.#:                            "1"
      health_check.0.healthy_threshold:          "3"
      health_check.0.interval:                   "30"
      health_check.0.matcher:                    <computed>
      health_check.0.path:                       "/"
      health_check.0.port:                       "8080"
      health_check.0.protocol:                   "HTTP"
      health_check.0.timeout:                    <computed>
      health_check.0.unhealthy_threshold:        "3"
      name:                                      "terraform-demo-client"
      port:                                      "8080"
      protocol:                                  "HTTP"
      proxy_protocol_v2:                         "false"
      slow_start:                                "0"
      stickiness.#:                              "1"
      stickiness.0.cookie_duration:              "86400"
      stickiness.0.enabled:                      "true"
      stickiness.0.type:                         "lb_cookie"
      tags.%:                                    "3"
      tags.Name:                                 "terraform-demo-client"
      tags.Terraform:                            "true"
      tags.Usage:                                "Terraform Talk by Yong Wen"
      target_type:                               "instance"
      vpc_id:                                    "vpc-dac9bcbd"

  + aws_lb_target_group.server
      id:                                        <computed>
      arn:                                       <computed>
      arn_suffix:                                <computed>
      deregistration_delay:                      "300"
      health_check.#:                            <computed>
      name:                                      "terraform-demo-server"
      port:                                      "8084"
      protocol:                                  "HTTP"
      proxy_protocol_v2:                         "false"
      slow_start:                                "0"
      stickiness.#:                              "1"
      stickiness.0.cookie_duration:              "86400"
      stickiness.0.enabled:                      "true"
      stickiness.0.type:                         "lb_cookie"
      tags.%:                                    "3"
      tags.Name:                                 "terraform-demo-server"
      tags.Terraform:                            "true"
      tags.Usage:                                "Terraform Talk by Yong Wen"
      target_type:                               "instance"
      vpc_id:                                    "vpc-dac9bcbd"

  + aws_lb_target_group.sink
      id:                                        <computed>
      arn:                                       <computed>
      arn_suffix:                                <computed>
      deregistration_delay:                      "30"
      health_check.#:                            <computed>
      name:                                      "terraform-demo-sink"
      port:                                      "80"
      protocol:                                  "HTTP"
      proxy_protocol_v2:                         "false"
      slow_start:                                "0"
      stickiness.#:                              <computed>
      tags.%:                                    "3"
      tags.Name:                                 "terraform-demo-sink"
      tags.Terraform:                            "true"
      tags.Usage:                                "Terraform Talk by Yong Wen"
      target_type:                               "instance"
      vpc_id:                                    "vpc-dac9bcbd"

  + aws_route53_record.domain
      id:                                        <computed>
      alias.#:                                   "1"
      alias.~2577902594.evaluate_target_health:  "false"
      alias.~2577902594.name:                    "${aws_lb.lb.dns_name}"
      alias.~2577902594.zone_id:                 "${aws_lb.lb.zone_id}"
      allow_overwrite:                           "true"
      fqdn:                                      <computed>
      name:                                      "chat.gahmen.tech"
      type:                                      "A"
      zone_id:                                   "Z341R9I374MQG8"

  + aws_security_group.client
      id:                                        <computed>
      arn:                                       <computed>
      description:                               "Security Group for terraform-demo-client"
      egress.#:                                  <computed>
      ingress.#:                                 <computed>
      name:                                      <computed>
      name_prefix:                               "terraform-demo-client"
      owner_id:                                  <computed>
      revoke_rules_on_delete:                    "false"
      tags.%:                                    "3"
      tags.Name:                                 "terraform-demo-client"
      tags.Terraform:                            "true"
      tags.Usage:                                "Terraform Talk by Yong Wen"
      vpc_id:                                    "vpc-dac9bcbd"

  + aws_security_group.lb
      id:                                        <computed>
      arn:                                       <computed>
      description:                               "Security group for Comicchat Load balancer"
      egress.#:                                  <computed>
      ingress.#:                                 <computed>
      name:                                      "terraform-demo"
      owner_id:                                  <computed>
      revoke_rules_on_delete:                    "false"
      tags.%:                                    "3"
      tags.Name:                                 "terraform-demo"
      tags.Terraform:                            "true"
      tags.Usage:                                "Terraform Talk by Yong Wen"
      vpc_id:                                    "vpc-dac9bcbd"

  + aws_security_group.server
      id:                                        <computed>
      arn:                                       <computed>
      description:                               "Security Group for terraform-demo-server"
      egress.#:                                  <computed>
      ingress.#:                                 <computed>
      name:                                      <computed>
      name_prefix:                               "terraform-demo-server"
      owner_id:                                  <computed>
      revoke_rules_on_delete:                    "false"
      tags.%:                                    "3"
      tags.Name:                                 "terraform-demo-server"
      tags.Terraform:                            "true"
      tags.Usage:                                "Terraform Talk by Yong Wen"
      vpc_id:                                    "vpc-dac9bcbd"

  + aws_security_group_rule.client_egress
      id:                                        <computed>
      cidr_blocks.#:                             "1"
      cidr_blocks.0:                             "0.0.0.0/0"
      from_port:                                 "0"
      protocol:                                  "-1"
      security_group_id:                         "${aws_security_group.client.id}"
      self:                                      "false"
      source_security_group_id:                  <computed>
      to_port:                                   "0"
      type:                                      "egress"

  + aws_security_group_rule.client_lb_inbound
      id:                                        <computed>
      from_port:                                 "8080"
      protocol:                                  "tcp"
      security_group_id:                         "${aws_security_group.client.id}"
      self:                                      "false"
      source_security_group_id:                  "${aws_security_group.lb.id}"
      to_port:                                   "8080"
      type:                                      "ingress"

  + aws_security_group_rule.client_ssh_inbound
      id:                                        <computed>
      cidr_blocks.#:                             "1"
      cidr_blocks.0:                             "10.0.0.0/8"
      from_port:                                 "22"
      protocol:                                  "tcp"
      security_group_id:                         "${aws_security_group.client.id}"
      self:                                      "false"
      source_security_group_id:                  <computed>
      to_port:                                   "22"
      type:                                      "ingress"

  + aws_security_group_rule.lb_client_egress
      id:                                        <computed>
      from_port:                                 "8080"
      protocol:                                  "tcp"
      security_group_id:                         "${aws_security_group.lb.id}"
      self:                                      "false"
      source_security_group_id:                  "${aws_security_group.client.id}"
      to_port:                                   "8080"
      type:                                      "egress"

  + aws_security_group_rule.lb_http_ingress
      id:                                        <computed>
      cidr_blocks.#:                             "1"
      cidr_blocks.0:                             "0.0.0.0/0"
      from_port:                                 "80"
      protocol:                                  "tcp"
      security_group_id:                         "${aws_security_group.lb.id}"
      self:                                      "false"
      source_security_group_id:                  <computed>
      to_port:                                   "80"
      type:                                      "ingress"

  + aws_security_group_rule.lb_https_ingress
      id:                                        <computed>
      cidr_blocks.#:                             "1"
      cidr_blocks.0:                             "0.0.0.0/0"
      from_port:                                 "443"
      protocol:                                  "tcp"
      security_group_id:                         "${aws_security_group.lb.id}"
      self:                                      "false"
      source_security_group_id:                  <computed>
      to_port:                                   "443"
      type:                                      "ingress"

  + aws_security_group_rule.lb_server_egress
      id:                                        <computed>
      from_port:                                 "8084"
      protocol:                                  "tcp"
      security_group_id:                         "${aws_security_group.lb.id}"
      self:                                      "false"
      source_security_group_id:                  "${aws_security_group.server.id}"
      to_port:                                   "8084"
      type:                                      "egress"

  + aws_security_group_rule.lb_wss_ingress
      id:                                        <computed>
      cidr_blocks.#:                             "1"
      cidr_blocks.0:                             "0.0.0.0/0"
      from_port:                                 "8080"
      protocol:                                  "tcp"
      security_group_id:                         "${aws_security_group.lb.id}"
      self:                                      "false"
      source_security_group_id:                  <computed>
      to_port:                                   "8080"
      type:                                      "ingress"

  + aws_security_group_rule.server_egress
      id:                                        <computed>
      cidr_blocks.#:                             "1"
      cidr_blocks.0:                             "0.0.0.0/0"
      from_port:                                 "0"
      protocol:                                  "-1"
      security_group_id:                         "${aws_security_group.server.id}"
      self:                                      "false"
      source_security_group_id:                  <computed>
      to_port:                                   "0"
      type:                                      "egress"

  + aws_security_group_rule.server_lb_inbound
      id:                                        <computed>
      from_port:                                 "8084"
      protocol:                                  "tcp"
      security_group_id:                         "${aws_security_group.server.id}"
      self:                                      "false"
      source_security_group_id:                  "${aws_security_group.lb.id}"
      to_port:                                   "8084"
      type:                                      "ingress"

  + aws_security_group_rule.server_ssh_inbound
      id:                                        <computed>
      cidr_blocks.#:                             "1"
      cidr_blocks.0:                             "10.0.0.0/8"
      from_port:                                 "22"
      protocol:                                  "tcp"
      security_group_id:                         "${aws_security_group.server.id}"
      self:                                      "false"
      source_security_group_id:                  <computed>
      to_port:                                   "22"
      type:                                      "ingress"


Plan: 30 to add, 0 to change, 0 to destroy.

Dependency Graph

Creation — α

It works!

chat.gahmen.tech

terraform destroy — Ω

Bonus: Enable GuardDuty and AWS Config for all regions

Open Source Module

We will make use of an open source module to help us along.

github.com/nozaq/terraform-aws-secure-baseline