feat(dash): SSL certificate
[csit.git] / fdio.infra.terraform / terraform-aws-elastic-beanstalk-environment / main.tf
1 locals {
2   tags = {
3     "Environment" = "${var.application_name}"
4   }
5
6   # Settings for all loadbalancer types
7   generic_elb_settings = [
8     {
9       namespace = "aws:elasticbeanstalk:environment"
10       name      = "LoadBalancerType"
11       value     = var.environment_loadbalancer_type
12     }
13   ]
14
15   classic_elb_settings = [
16     {
17       namespace = "aws:elb:loadbalancer"
18       name      = "CrossZone"
19       value     = var.environment_loadbalancer_crosszone
20     },
21     {
22       namespace = "aws:elb:loadbalancer"
23       name      = "SecurityGroups"
24       value     = join(",", sort(var.environment_loadbalancer_security_groups))
25     },
26     {
27       namespace = "aws:elb:loadbalancer"
28       name      = "ManagedSecurityGroup"
29       value     = var.environment_loadbalancer_managed_security_group
30     },
31     {
32       namespace = "aws:elb:listener"
33       name      = "ListenerProtocol"
34       value     = "HTTP"
35     },
36     {
37       namespace = "aws:elb:listener"
38       name      = "InstancePort"
39       value     = var.environment_process_default_port
40     },
41     {
42       namespace = "aws:elb:listener"
43       name      = "ListenerEnabled"
44       value     = var.default_listener_enabled || var.environment_loadbalancer_ssl_certificate_id == "" ? "true" : "false"
45     },
46     {
47       namespace = "aws:elb:listener:443"
48       name      = "ListenerProtocol"
49       value     = "HTTPS"
50     },
51     {
52       namespace = "aws:elb:listener:443"
53       name      = "InstancePort"
54       value     = var.environment_process_default_port
55     },
56     {
57       namespace = "aws:elb:listener:443"
58       name      = "SSLCertificateId"
59       value     = var.environment_loadbalancer_ssl_certificate_id
60     },
61     {
62       namespace = "aws:elb:listener:443"
63       name      = "ListenerEnabled"
64       value     = var.environment_loadbalancer_ssl_certificate_id == "" ? "false" : "true"
65     },
66     {
67       namespace = "aws:elb:policies"
68       name      = "ConnectionSettingIdleTimeout"
69       value     = var.loadbalancer_connection_settings_idle_timeout
70     },
71     {
72       namespace = "aws:elb:policies"
73       name      = "ConnectionDrainingEnabled"
74       value     = "true"
75     }
76   ]
77
78   nlb_settings = [
79     {
80       namespace = "aws:elbv2:listener:default"
81       name      = "ListenerEnabled"
82       value     = var.default_listener_enabled
83     }
84   ]
85
86   beanstalk_elb_settings = [
87     {
88       namespace = "aws:ec2:vpc"
89       name      = "ELBSubnets"
90       value     = aws_subnet.subnet.id
91     },
92     {
93       namespace = "aws:elasticbeanstalk:environment:process:default"
94       name      = "Port"
95       value     = var.environment_process_default_port
96     },
97     {
98       namespace = "aws:elasticbeanstalk:environment:process:default"
99       name      = "Protocol"
100       value     = var.environment_loadbalancer_type == "network" ? "TCP" : "HTTP"
101     },
102     {
103       namespace = "aws:ec2:vpc"
104       name      = "ELBScheme"
105       value     = var.environment_type == "LoadBalanced" ? var.elb_scheme : ""
106     },
107     {
108       namespace = "aws:elasticbeanstalk:environment:process:default"
109       name      = "HealthCheckInterval"
110       value     = var.environment_process_default_healthcheck_interval
111     },
112     {
113       namespace = "aws:elasticbeanstalk:environment:process:default"
114       name      = "HealthyThresholdCount"
115       value     = var.environment_process_default_healthy_threshold_count
116     },
117     {
118       namespace = "aws:elasticbeanstalk:environment:process:default"
119       name      = "UnhealthyThresholdCount"
120       value     = var.environment_process_default_unhealthy_threshold_count
121     }
122   ]
123   elb_settings_nlb    = var.environment_loadbalancer_type == "network" ? concat(local.nlb_settings, local.generic_elb_settings, local.beanstalk_elb_settings) : []
124   elb_setting_classic = var.environment_loadbalancer_type == "classic" ? concat(local.classic_elb_settings, local.generic_elb_settings, local.beanstalk_elb_settings) : []
125
126   # Full set of LoadBlanacer settings.
127   elb_settings = var.environment_tier == "WebServer" ? concat(local.elb_settings_nlb, local.elb_setting_classic) : []
128 }
129
130 # Create elastic beanstalk VPC
131 resource "aws_vpc" "vpc" {
132   assign_generated_ipv6_cidr_block = true
133   cidr_block                       = var.vpc_cidr_block
134   enable_dns_hostnames             = var.vpc_enable_dns_hostnames
135   enable_dns_support               = var.vpc_enable_dns_support
136   instance_tenancy                 = var.vpc_instance_tenancy
137   tags                             = local.tags
138 }
139
140 # Create elastic beanstalk Subnets
141 resource "aws_subnet" "subnet" {
142   depends_on = [
143     aws_vpc.vpc
144   ]
145   availability_zone               = var.subnet_availability_zone
146   assign_ipv6_address_on_creation = true
147   cidr_block                      = aws_vpc.vpc.cidr_block
148   ipv6_cidr_block                 = cidrsubnet(aws_vpc.vpc.ipv6_cidr_block, 8, 1)
149   map_public_ip_on_launch         = true
150   vpc_id                          = aws_vpc.vpc.id
151   tags                            = local.tags
152 }
153
154 resource "aws_internet_gateway" "internet_gateway" {
155   depends_on = [
156     aws_vpc.vpc
157   ]
158   vpc_id = aws_vpc.vpc.id
159   tags   = local.tags
160 }
161
162 resource "aws_route" "route" {
163   depends_on = [
164     aws_vpc.vpc,
165     aws_internet_gateway.internet_gateway
166   ]
167   destination_cidr_block = "0.0.0.0/0"
168   gateway_id             = aws_internet_gateway.internet_gateway.id
169   route_table_id         = aws_vpc.vpc.main_route_table_id
170 }
171
172 # Create elastic beanstalk IAM mapping
173 data "aws_iam_policy_document" "service" {
174   statement {
175     actions = [
176       "sts:AssumeRole"
177     ]
178     principals {
179       type        = "Service"
180       identifiers = ["elasticbeanstalk.amazonaws.com"]
181     }
182     effect = "Allow"
183   }
184 }
185
186 resource "aws_iam_role" "service" {
187   assume_role_policy = data.aws_iam_policy_document.service.json
188   name               = "${var.application_name}-eb-service"
189 }
190
191 resource "aws_iam_role_policy_attachment" "enhanced_health" {
192   policy_arn = "arn:aws:iam::aws:policy/service-role/AWSElasticBeanstalkEnhancedHealth"
193   role       = aws_iam_role.service.name
194 }
195
196 resource "aws_iam_role_policy_attachment" "service" {
197   policy_arn = "arn:aws:iam::aws:policy/service-role/AWSElasticBeanstalkService"
198   role       = aws_iam_role.service.name
199 }
200
201 data "aws_iam_policy_document" "ec2" {
202   statement {
203     actions = [
204       "sts:AssumeRole"
205     ]
206     principals {
207       type        = "Service"
208       identifiers = ["ec2.amazonaws.com"]
209     }
210     effect = "Allow"
211   }
212   statement {
213     actions = [
214       "sts:AssumeRole",
215     ]
216     principals {
217       type        = "Service"
218       identifiers = ["ssm.amazonaws.com"]
219     }
220     effect = "Allow"
221   }
222 }
223
224 resource "aws_iam_role" "ec2" {
225   assume_role_policy = data.aws_iam_policy_document.ec2.json
226   name               = "${var.application_name}-eb-ec2"
227 }
228
229 resource "aws_iam_instance_profile" "ec2_iam_instance_profile" {
230   name = "${var.application_name}-iam-instance-profile"
231   role = aws_iam_role.ec2.name
232 }
233
234 resource "aws_iam_role_policy_attachment" "multicontainer_docker" {
235   policy_arn = "arn:aws:iam::aws:policy/AWSElasticBeanstalkMulticontainerDocker"
236   role       = aws_iam_role.ec2.name
237 }
238
239 resource "aws_iam_role_policy_attachment" "web_tier" {
240   policy_arn = "arn:aws:iam::aws:policy/AWSElasticBeanstalkWebTier"
241   role       = aws_iam_role.ec2.name
242 }
243
244 resource "aws_iam_role_policy_attachment" "worker_tier" {
245   policy_arn = "arn:aws:iam::aws:policy/AWSElasticBeanstalkWorkerTier"
246   role       = aws_iam_role.ec2.name
247 }
248
249 resource "aws_iam_role_policy_attachment" "ssm_automation" {
250   policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonSSMAutomationRole"
251   role       = aws_iam_role.ec2.name
252 }
253
254 resource "aws_iam_role_policy_attachment" "ssm_ec2" {
255   policy_arn = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore"
256   role       = aws_iam_role.ec2.name
257 }
258
259 resource "aws_iam_role_policy_attachment" "ecr_readonly" {
260   policy_arn = "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly"
261   role       = aws_iam_role.ec2.name
262 }
263
264 resource "aws_ssm_activation" "ec2" {
265   depends_on = [
266     aws_iam_role.ec2,
267     aws_iam_role_policy_attachment.ssm_ec2
268   ]
269   name               = "${var.application_name}-ec2-activation"
270   iam_role           = aws_iam_role.ec2.id
271   registration_limit = 3
272 }
273
274 data "aws_iam_policy_document" "default" {
275   statement {
276     actions = [
277       "elasticloadbalancing:DescribeInstanceHealth",
278       "elasticloadbalancing:DescribeLoadBalancers",
279       "elasticloadbalancing:DescribeTargetHealth",
280       "ec2:DescribeInstances",
281       "ec2:DescribeInstanceStatus",
282       "ec2:GetConsoleOutput",
283       "ec2:AssociateAddress",
284       "ec2:DescribeAddresses",
285       "ec2:DescribeSecurityGroups",
286       "sqs:GetQueueAttributes",
287       "sqs:GetQueueUrl",
288       "autoscaling:DescribeAutoScalingGroups",
289       "autoscaling:DescribeAutoScalingInstances",
290       "autoscaling:DescribeScalingActivities",
291       "autoscaling:DescribeNotificationConfigurations",
292     ]
293     resources = ["*"]
294     effect    = "Allow"
295   }
296
297   statement {
298     sid = "AllowOperations"
299     actions = [
300       "autoscaling:AttachInstances",
301       "autoscaling:CreateAutoScalingGroup",
302       "autoscaling:CreateLaunchConfiguration",
303       "autoscaling:DeleteLaunchConfiguration",
304       "autoscaling:DeleteAutoScalingGroup",
305       "autoscaling:DeleteScheduledAction",
306       "autoscaling:DescribeAccountLimits",
307       "autoscaling:DescribeAutoScalingGroups",
308       "autoscaling:DescribeAutoScalingInstances",
309       "autoscaling:DescribeLaunchConfigurations",
310       "autoscaling:DescribeLoadBalancers",
311       "autoscaling:DescribeNotificationConfigurations",
312       "autoscaling:DescribeScalingActivities",
313       "autoscaling:DescribeScheduledActions",
314       "autoscaling:DetachInstances",
315       "autoscaling:PutScheduledUpdateGroupAction",
316       "autoscaling:ResumeProcesses",
317       "autoscaling:SetDesiredCapacity",
318       "autoscaling:SetInstanceProtection",
319       "autoscaling:SuspendProcesses",
320       "autoscaling:TerminateInstanceInAutoScalingGroup",
321       "autoscaling:UpdateAutoScalingGroup",
322       "cloudwatch:PutMetricAlarm",
323       "ec2:AssociateAddress",
324       "ec2:AllocateAddress",
325       "ec2:AuthorizeSecurityGroupEgress",
326       "ec2:AuthorizeSecurityGroupIngress",
327       "ec2:CreateSecurityGroup",
328       "ec2:DeleteSecurityGroup",
329       "ec2:DescribeAccountAttributes",
330       "ec2:DescribeAddresses",
331       "ec2:DescribeImages",
332       "ec2:DescribeInstances",
333       "ec2:DescribeKeyPairs",
334       "ec2:DescribeSecurityGroups",
335       "ec2:DescribeSnapshots",
336       "ec2:DescribeSubnets",
337       "ec2:DescribeVpcs",
338       "ec2:DisassociateAddress",
339       "ec2:ReleaseAddress",
340       "ec2:RevokeSecurityGroupEgress",
341       "ec2:RevokeSecurityGroupIngress",
342       "ec2:TerminateInstances",
343       "ecs:CreateCluster",
344       "ecs:DeleteCluster",
345       "ecs:DescribeClusters",
346       "ecs:RegisterTaskDefinition",
347       "elasticbeanstalk:*",
348       "elasticloadbalancing:ApplySecurityGroupsToLoadBalancer",
349       "elasticloadbalancing:ConfigureHealthCheck",
350       "elasticloadbalancing:CreateLoadBalancer",
351       "elasticloadbalancing:DeleteLoadBalancer",
352       "elasticloadbalancing:DeregisterInstancesFromLoadBalancer",
353       "elasticloadbalancing:DescribeInstanceHealth",
354       "elasticloadbalancing:DescribeLoadBalancers",
355       "elasticloadbalancing:DescribeTargetHealth",
356       "elasticloadbalancing:RegisterInstancesWithLoadBalancer",
357       "elasticloadbalancing:DescribeTargetGroups",
358       "elasticloadbalancing:RegisterTargets",
359       "elasticloadbalancing:DeregisterTargets",
360       "iam:ListRoles",
361       "iam:PassRole",
362       "logs:CreateLogGroup",
363       "logs:PutRetentionPolicy",
364       "rds:DescribeDBEngineVersions",
365       "rds:DescribeDBInstances",
366       "rds:DescribeOrderableDBInstanceOptions",
367       "s3:GetObject",
368       "s3:GetObjectAcl",
369       "s3:ListBucket",
370       "sns:CreateTopic",
371       "sns:GetTopicAttributes",
372       "sns:ListSubscriptionsByTopic",
373       "sns:Subscribe",
374       "sqs:GetQueueAttributes",
375       "sqs:GetQueueUrl",
376       "codebuild:CreateProject",
377       "codebuild:DeleteProject",
378       "codebuild:BatchGetBuilds",
379       "codebuild:StartBuild",
380     ]
381     resources = ["*"]
382     effect    = "Allow"
383   }
384
385   statement {
386     sid = "AllowS3OperationsOnElasticBeanstalkBuckets"
387     actions = [
388       "s3:*"
389     ]
390     resources = [
391       "arn:aws:s3:::*"
392     ]
393     effect = "Allow"
394   }
395
396   statement {
397     sid = "AllowDeleteCloudwatchLogGroups"
398     actions = [
399       "logs:DeleteLogGroup"
400     ]
401     resources = [
402       "arn:aws:logs:*:*:log-group:/aws/elasticbeanstalk*"
403     ]
404     effect = "Allow"
405   }
406
407   statement {
408     sid = "AllowCloudformationOperationsOnElasticBeanstalkStacks"
409     actions = [
410       "cloudformation:*"
411     ]
412     resources = [
413       "arn:aws:cloudformation:*:*:stack/awseb-*",
414       "arn:aws:cloudformation:*:*:stack/eb-*"
415     ]
416     effect = "Allow"
417   }
418 }
419
420 resource "aws_iam_role_policy" "default" {
421   depends_on = [
422     aws_iam_role.ec2
423   ]
424   name   = "${var.application_name}-eb-default"
425   policy = data.aws_iam_policy_document.default.json
426   role   = aws_iam_role.ec2.id
427 }
428
429 # Create elastic beanstalk Environment
430 resource "aws_elastic_beanstalk_environment" "environment" {
431   depends_on = [
432     aws_vpc.vpc,
433     aws_subnet.subnet,
434     aws_ssm_activation.ec2
435   ]
436   application            = var.environment_application
437   description            = var.environment_description
438   name                   = var.environment_name
439   solution_stack_name    = var.environment_solution_stack_name
440   tier                   = var.environment_tier
441   wait_for_ready_timeout = var.environment_wait_for_ready_timeout
442   version_label          = var.environment_version_label
443   tags                   = local.tags
444
445   # aws:ec2:instances
446   setting {
447     namespace = "aws:ec2:instances"
448     name      = "InstanceTypes"
449     value     = var.instances_instance_types
450   }
451
452   # aws:ec2:vpc
453   setting {
454     namespace = "aws:ec2:vpc"
455     name      = "VPCId"
456     value     = aws_vpc.vpc.id
457   }
458
459   setting {
460     namespace = "aws:ec2:vpc"
461     name      = "Subnets"
462     value     = aws_subnet.subnet.id
463   }
464
465   setting {
466     namespace = "aws:ec2:vpc"
467     name      = "AssociatePublicIpAddress"
468     value     = var.associate_public_ip_address
469   }
470
471   setting {
472     namespace = "aws:elasticbeanstalk:environment"
473     name      = "ServiceRole"
474     value     = aws_iam_role.service.name
475   }
476
477   # aws:autoscaling:launchconfiguration
478   setting {
479     namespace = "aws:autoscaling:launchconfiguration"
480     name      = "IamInstanceProfile"
481     value     = aws_iam_instance_profile.ec2_iam_instance_profile.name
482   }
483
484   setting {
485     namespace = "aws:autoscaling:launchconfiguration"
486     name      = "DisableIMDSv1"
487     value     = true
488   }
489
490   dynamic "setting" {
491     for_each = local.elb_settings
492     content {
493       namespace = setting.value["namespace"]
494       name      = setting.value["name"]
495       value     = setting.value["value"]
496     }
497   }
498
499   # aws:autoscaling:updatepolicy:rollingupdate
500   setting {
501     namespace = "aws:autoscaling:updatepolicy:rollingupdate"
502     name      = "RollingUpdateEnabled"
503     value     = var.autoscaling_updatepolicy_rolling_update_enabled
504   }
505
506   setting {
507     namespace = "aws:autoscaling:updatepolicy:rollingupdate"
508     name      = "RollingUpdateType"
509     value     = var.autoscaling_updatepolicy_rolling_update_type
510   }
511
512   setting {
513     namespace = "aws:autoscaling:updatepolicy:rollingupdate"
514     name      = "MinInstancesInService"
515     value     = var.autoscaling_updatepolicy_min_instance_in_service
516   }
517
518   setting {
519     namespace = "aws:elasticbeanstalk:application"
520     name      = "Application Healthcheck URL"
521     value     = var.application_healthcheck_url
522   }
523
524   # aws:elasticbeanstalk:command
525   setting {
526     namespace = "aws:elasticbeanstalk:command"
527     name      = "DeploymentPolicy"
528     value     = var.command_deployment_policy
529   }
530
531   # aws:autoscaling:updatepolicy:rollingupdate
532   setting {
533     namespace = "aws:autoscaling:updatepolicy:rollingupdate"
534     name      = "MaxBatchSize"
535     value     = var.updatepolicy_max_batch_size
536   }
537
538   # aws:elasticbeanstalk:healthreporting:system
539   setting {
540     namespace = "aws:elasticbeanstalk:healthreporting:system"
541     name      = "SystemType"
542     value     = var.healthreporting_system_type
543   }
544
545   # aws:elasticbeanstalk:managedactions
546   setting {
547     namespace = "aws:elasticbeanstalk:managedactions"
548     name      = "ManagedActionsEnabled"
549     value     = var.managedactions_managed_actions_enabled ? "true" : "false"
550   }
551
552   setting {
553     namespace = "aws:elasticbeanstalk:managedactions"
554     name      = "PreferredStartTime"
555     value     = var.managedactions_preferred_start_time
556   }
557
558   # aws:elasticbeanstalk:managedactions:platformupdate
559   setting {
560     namespace = "aws:elasticbeanstalk:managedactions:platformupdate"
561     name      = "UpdateLevel"
562     value     = var.managedactions_platformupdate_update_level
563   }
564
565   setting {
566     namespace = "aws:elasticbeanstalk:managedactions:platformupdate"
567     name      = "InstanceRefreshEnabled"
568     value     = var.managedactions_platformupdate_instance_refresh_enabled
569   }
570
571   setting {
572     namespace = "aws:elasticbeanstalk:command"
573     name      = "IgnoreHealthCheck"
574     value     = var.command_ignore_health_check
575   }
576
577   # aws:autoscaling:asg
578   setting {
579     namespace = "aws:autoscaling:asg"
580     name      = "MinSize"
581     value     = var.autoscaling_asg_minsize
582   }
583   setting {
584     namespace = "aws:autoscaling:asg"
585     name      = "MaxSize"
586     value     = var.autoscaling_asg_maxsize
587   }
588
589   # aws:autoscaling:trigger
590   setting {
591     namespace = "aws:autoscaling:trigger"
592     name      = "MeasureName"
593     value     = var.autoscaling_trigger_measure_name
594   }
595
596   setting {
597     namespace = "aws:autoscaling:trigger"
598     name      = "Statistic"
599     value     = var.autoscaling_trigger_statistic
600   }
601
602   setting {
603     namespace = "aws:autoscaling:trigger"
604     name      = "Unit"
605     value     = var.autoscaling_trigger_unit
606   }
607
608   setting {
609     namespace = "aws:autoscaling:trigger"
610     name      = "LowerThreshold"
611     value     = var.autoscaling_trigger_lower_threshold
612   }
613
614   setting {
615     namespace = "aws:autoscaling:trigger"
616     name      = "LowerBreachScaleIncrement"
617     value     = var.autoscaling_trigger_lower_breach_scale_increment
618   }
619
620   setting {
621     namespace = "aws:autoscaling:trigger"
622     name      = "UpperThreshold"
623     value     = var.autoscaling_trigger_upper_threshold
624   }
625
626   setting {
627     namespace = "aws:autoscaling:trigger"
628     name      = "UpperBreachScaleIncrement"
629     value     = var.autoscaling_trigger_upper_breach_scale_increment
630   }
631
632   # aws:elasticbeanstalk:hostmanager
633   setting {
634     namespace = "aws:elasticbeanstalk:hostmanager"
635     name      = "LogPublicationControl"
636     value     = var.hostmanager_log_publication_control ? "true" : "false"
637   }
638
639   # aws:elasticbeanstalk:cloudwatch:logs
640   setting {
641     namespace = "aws:elasticbeanstalk:cloudwatch:logs"
642     name      = "StreamLogs"
643     value     = var.cloudwatch_logs_stream_logs ? "true" : "false"
644   }
645
646   setting {
647     namespace = "aws:elasticbeanstalk:cloudwatch:logs"
648     name      = "DeleteOnTerminate"
649     value     = var.cloudwatch_logs_delete_on_terminate ? "true" : "false"
650   }
651
652   setting {
653     namespace = "aws:elasticbeanstalk:cloudwatch:logs"
654     name      = "RetentionInDays"
655     value     = var.cloudwatch_logs_retention_in_days
656   }
657
658   # aws:elasticbeanstalk:cloudwatch:logs:health
659   setting {
660     namespace = "aws:elasticbeanstalk:cloudwatch:logs:health"
661     name      = "HealthStreamingEnabled"
662     value     = var.cloudwatch_logs_health_health_streaming_enabled ? "true" : "false"
663   }
664
665   setting {
666     namespace = "aws:elasticbeanstalk:cloudwatch:logs:health"
667     name      = "DeleteOnTerminate"
668     value     = var.cloudwatch_logs_health_delete_on_terminate ? "true" : "false"
669   }
670
671   setting {
672     namespace = "aws:elasticbeanstalk:cloudwatch:logs:health"
673     name      = "RetentionInDays"
674     value     = var.cloudwatch_logs_health_retention_in_days
675   }
676
677   # aws:elasticbeanstalk:application:environment
678   dynamic "setting" {
679     for_each = var.environment_variables
680     content {
681       namespace = "aws:elasticbeanstalk:application:environment"
682       name      = setting.key
683       value     = setting.value
684     }
685   }
686 }