3

I am setting up the AWS infrastructure using Terraform. One of components is ElasticBeanstalk application/environment with a load balancer and auto-scaling group. I don't want to expose the endpoint to entire Internet but just to the limited list of IP addresses. For that purpose I create the security group with proper inbound rules and assign it to the load balancer. But after script was applied, the load balancer has two security groups - one mine and second one - default, that allows HTTP traffic from any where. As temp workaround I manually remove the inbound rule for the default SG. Such approach is not acceptable as long-term solution since I want full automation of infrastructure setup (without any human interaction).

Here is my config:

resource "aws_elastic_beanstalk_environment" "abc_env" {
  name = "abc-${var.environment_name}"
  application = "${aws_elastic_beanstalk_application.abc-service.name}"
  solution_stack_name = "64bit Amazon Linux 2016.09 v2.3.0 running Python 3.4"
  cname_prefix = "abc-${var.environment_name}"
  tier = "WebServer"
  wait_for_ready_timeout = "30m"

  setting {
    name = "InstanceType"
    namespace = "aws:autoscaling:launchconfiguration"
    value = "m3.medium"
  }
  setting {
    name = "SecurityGroups"
    namespace = "aws:elb:loadbalancer"
    value = "${var.limited_http_acccess_id}"
  }
  setting {
    name = "VPCId"
    namespace = "aws:ec2:vpc"
    value = "${var.vpc_id}"
  }
  setting {
    name = "Subnets"
    namespace = "aws:ec2:vpc"
    value = "${var.public_net_id}"
  }
  setting {
    name = "AssociatePublicIpAddress"
    namespace = "aws:ec2:vpc"
    value = "true"
  }
  setting {
    name = "ELBSubnets"
    namespace = "aws:ec2:vpc"
    value = "${var.public_net_id}"
  }
  setting {
    name = "ELBScheme"
    namespace = "aws:ec2:vpc"
    value = "external"
  }

  setting {
    name = "MinSize"
    namespace = "aws:autoscaling:asg"
    value = "2"
  }
  setting {
    name = "MaxSize"
    namespace = "aws:autoscaling:asg"
    value = "4"
  }
  setting {
    name = "Availability Zones"
    namespace = "aws:autoscaling:asg"
    value = "Any 2"
  }
  setting {
    name = "CrossZone"
    namespace = "aws:elb:loadbalancer"
    value = "true"
  }
  setting {
    name = "Unit"
    namespace = "aws:autoscaling:trigger"
    value = "Percent"
  }
  setting {
    name = "MeasureName"
    namespace = "aws:autoscaling:trigger"
    value = "CPUUtilization"
  }
  setting {
    name = "LowerThreshold"
    namespace = "aws:autoscaling:trigger"
    value = "20"
  }
  setting {
    name = "UpperThreshold"
    namespace = "aws:autoscaling:trigger"
    value = "80"
  }
  setting {
    name = "Period"
    namespace = "aws:autoscaling:trigger"
    value = "5"
  }
  setting {
    name = "UpperBreachScaleIncrement"
    namespace = "aws:autoscaling:trigger"
    value = "1"
  }
  setting {
    name = "LowerBreachScaleIncrement"
    namespace = "aws:autoscaling:trigger"
    value = "-1"
  }
  setting {
    name = "Notification Endpoint"
    namespace = "aws:elasticbeanstalk:sns:topics"
    value = "${var.notification_email}"
  }
  tags = "${merge(var.default_tags, map("Name", "abc environment"))}"
}

So the question is: how can I limit access to my load balancer without manual interaction with AWS (only using Terraform script)?

[UPDATE] Here is my network config

resource "aws_vpc" "main_vpc" {
  cidr_block = "${var.vpc_cidr_block}"
  enable_dns_hostnames = true
}

resource "aws_subnet" "public_network" {
  vpc_id = "${aws_vpc.main_vpc.id}"
  cidr_block = "${var.public_network_cidr_block}"
}

resource "aws_internet_gateway" "gateway" {
  vpc_id = "${aws_vpc.main_vpc.id}"
}

resource "aws_route_table" "public" {
  vpc_id = "${aws_vpc.main_vpc.id}"
  route {
    cidr_block = "0.0.0.0/0"
    gateway_id = "${aws_internet_gateway.gateway.id}"
  }
}

resource "aws_route_table_association" "public" {
  route_table_id = "${aws_route_table.public.id}"
  subnet_id = "${aws_subnet.public_network.id}"
}

resource "aws_security_group" "limited_http_acccess" {
  name = "limited_http_acccess"
  description = "This security group allows to access resources within VPC from specified IP addresses"
  vpc_id = "${aws_vpc.main_vpc.id}"
  ingress {
    from_port = 80
    to_port = 80
    protocol = "TCP"
    cidr_blocks = ["${split(",", var.allowed_cidr_list)}"]
  }
  egress {
    from_port = 0
    to_port = 0
    protocol = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}
igor
  • 699
  • 1
  • 9
  • 26
  • Are you managing the security group with Terraform, and if so, can you post your SG config (without any sensitive information, of course)? You'll want to make sure you have the vpc_id, ingress and egress blocks defined correctly, I've had Terraform do some weird stuff if it's not right.. – mcheshier Jan 17 '17 at 21:05
  • Added network config. For me it looks ok, also everything works as expected, the only thing is that I have to manually edit ingress rules for default Beanstalk SG. – igor Jan 18 '17 at 07:44

1 Answers1

3

According to AWS docs ManagedSecurityGroup needs to be added to ElasticBeansstalk config in order to prevent usage of default security group.

So adding of the following lines to my aws_elastic_beanstalk_environment fixed the issue

  setting {
    name = "ManagedSecurityGroup"
    namespace = "aws:elb:loadbalancer"
    value = "${var.limited_http_acccess_id}"
  }
igor
  • 699
  • 1
  • 9
  • 26
  • I have the same issue with automatic default security groups on the ec2 instance (I add my own aws:autoscaling:launchconfiguration>SecurityGroups) but it always adds a default. Anyone have an idea how to stop that ? – Rolf Wessels Oct 11 '17 at 07:13
  • @RolfWessels, You can try use the same SG for your load balancer and launch configuration ` setting { name = "SecurityGroups" namespace = "aws:autoscaling:launchconfiguration" value = "${var.load_balancer_security_group_id}" } setting { name = "SecurityGroups" namespace = "aws:elb:loadbalancer" value = "${var.load_balancer_security_group_id}" } setting { name = "ManagedSecurityGroup" namespace = "aws:elb:loadbalancer" value = "${var.load_balancer_security_group_id}" }` – igor Oct 12 '17 at 08:14
  • @RollfWessels, But that is not very good idea. Automatically generated SG just allows access from load balancer to your EC2 and adds SSH access rule if you use ` setting { name = "SSHSourceRestriction" namespace = "aws:autoscaling:launchconfiguration" value = "tcp, 22, 22, ${var.bastion_host_cidr}" }` so I don't see any reasons to get rid of it – igor Oct 12 '17 at 08:18
  • Hmm, I will try these tomorrow. The default adds ssh access to my windows servers. Ultimately it is not the end of the world but definitely not needed and I hate the cloudformation naming :-) – Rolf Wessels Oct 12 '17 at 16:59
  • Since these issues are so closely related, it's worth pointing out that, in addition to the elb "ManagedSecurityGroup", there is also an "Environment" security group that gets auto-generated and provides SSH access to the open internet! To turn that off see here: https://github.com/terraform-providers/terraform-provider-aws/issues/2002#issuecomment-393999778 – ecoe Jun 01 '18 at 20:27