main.tf 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. # Some instance variables
  2. locals {
  3. ami_selection = "minion" # master, minion, ...
  4. repo_drive_size = 30 # Consider changing volume type to SC1 if size is ever > 500GB
  5. }
  6. # Rather than pass in the aws security group, we just look it up. This will
  7. # probably be useful other places, as well.
  8. data "aws_security_group" "typical-host" {
  9. name = "typical-host"
  10. vpc_id = var.vpc_id
  11. }
  12. # Use the default EBS key
  13. data "aws_kms_key" "ebs-key" {
  14. key_id = "alias/ebs_root_encrypt_decrypt"
  15. }
  16. resource "aws_network_interface" "instance" {
  17. subnet_id = var.public_subnets[0]
  18. security_groups = [data.aws_security_group.typical-host.id, aws_security_group.repo_server_security_group.id]
  19. description = var.instance_name
  20. tags = merge(local.standard_tags, var.tags, { Name = var.instance_name })
  21. }
  22. resource "aws_eip" "instance" {
  23. vpc = true
  24. tags = merge(local.standard_tags, var.tags, { Name = var.instance_name })
  25. }
  26. resource "aws_eip_association" "instance" {
  27. network_interface_id = aws_network_interface.instance.id
  28. allocation_id = aws_eip.instance.id
  29. }
  30. resource "aws_instance" "instance" {
  31. tenancy = "default"
  32. ebs_optimized = true
  33. disable_api_termination = var.instance_termination_protection
  34. instance_initiated_shutdown_behavior = "stop"
  35. instance_type = "t3a.xlarge"
  36. key_name = "msoc-build"
  37. monitoring = false
  38. iam_instance_profile = "msoc-default-instance-profile"
  39. ami = local.ami_map[local.ami_selection]
  40. # We need to ignore ebs_block_device changes, because if the AMI changes, so does the snapshot_id.
  41. # If they add a feature to block more specific changes (eg `ebs_block_devices[*].snapshot_id`), then
  42. # that could be removed.
  43. lifecycle { ignore_changes = [ami, key_name, user_data, ebs_block_device] }
  44. metadata_options {
  45. http_endpoint = "enabled"
  46. http_tokens = "optional" # tfsec:ignore:aws-ec2-enforce-http-token-imds Breaks salt
  47. }
  48. # These device definitions are optional, but added for clarity.
  49. root_block_device {
  50. volume_type = "gp3"
  51. #volume_size = "60"
  52. delete_on_termination = true
  53. encrypted = true
  54. kms_key_id = data.aws_kms_key.ebs-key.arn
  55. }
  56. ebs_block_device {
  57. # swap
  58. device_name = "/dev/xvdm"
  59. #volume_size = 48
  60. delete_on_termination = true
  61. encrypted = true
  62. kms_key_id = data.aws_kms_key.ebs-key.arn
  63. # Snapshot IDs need to be grabbed from the ami, or it will replace every time. It's ugly.
  64. # This may prompt replacement when the AMI is updated.
  65. # See:
  66. # https://github.com/hashicorp/terraform/issues/19958
  67. # https://github.com/terraform-providers/terraform-provider-aws/issues/13118
  68. snapshot_id = local.block_device_mappings[local.ami_selection]["/dev/xvdm"].ebs.snapshot_id
  69. }
  70. ebs_block_device {
  71. # /home
  72. device_name = "/dev/xvdn"
  73. # volume_size = xx
  74. delete_on_termination = true
  75. encrypted = true
  76. kms_key_id = data.aws_kms_key.ebs-key.arn
  77. snapshot_id = local.block_device_mappings[local.ami_selection]["/dev/xvdn"].ebs.snapshot_id
  78. }
  79. ebs_block_device {
  80. # /var
  81. device_name = "/dev/xvdo"
  82. # volume_size = xx
  83. delete_on_termination = true
  84. encrypted = true
  85. kms_key_id = data.aws_kms_key.ebs-key.arn
  86. snapshot_id = local.block_device_mappings[local.ami_selection]["/dev/xvdo"].ebs.snapshot_id
  87. }
  88. ebs_block_device {
  89. # /var/tmp
  90. device_name = "/dev/xvdp"
  91. # volume_size = xx
  92. delete_on_termination = true
  93. encrypted = true
  94. kms_key_id = data.aws_kms_key.ebs-key.arn
  95. snapshot_id = local.block_device_mappings[local.ami_selection]["/dev/xvdp"].ebs.snapshot_id
  96. }
  97. ebs_block_device {
  98. # /var/log
  99. device_name = "/dev/xvdq"
  100. # volume_size = xx
  101. delete_on_termination = true
  102. encrypted = true
  103. kms_key_id = data.aws_kms_key.ebs-key.arn
  104. snapshot_id = local.block_device_mappings[local.ami_selection]["/dev/xvdq"].ebs.snapshot_id
  105. }
  106. ebs_block_device {
  107. # /var/log/audit
  108. device_name = "/dev/xvdr"
  109. # volume_size = xx
  110. delete_on_termination = true
  111. encrypted = true
  112. kms_key_id = data.aws_kms_key.ebs-key.arn
  113. snapshot_id = local.block_device_mappings[local.ami_selection]["/dev/xvdr"].ebs.snapshot_id
  114. }
  115. ebs_block_device {
  116. # /tmp
  117. device_name = "/dev/xvds"
  118. # volume_size = xx
  119. delete_on_termination = true
  120. encrypted = true
  121. kms_key_id = data.aws_kms_key.ebs-key.arn
  122. snapshot_id = local.block_device_mappings[local.ami_selection]["/dev/xvds"].ebs.snapshot_id
  123. }
  124. network_interface {
  125. device_index = 0
  126. network_interface_id = aws_network_interface.instance.id
  127. }
  128. user_data = data.template_cloudinit_config.cloud_init_config.rendered
  129. tags = merge(local.standard_tags, var.tags, var.instance_tags, { Name = var.instance_name })
  130. volume_tags = merge(local.standard_tags, var.tags, { Name = var.instance_name })
  131. }
  132. module "private_dns_record" {
  133. source = "../../submodules/dns/private_A_record"
  134. name = "${var.instance_name}-server"
  135. ip_addresses = [aws_instance.instance.private_ip]
  136. dns_info = var.dns_info
  137. reverse_enabled = var.reverse_enabled
  138. providers = {
  139. aws.c2 = aws.c2
  140. }
  141. }
  142. # Render a multi-part cloud-init config making use of the part
  143. # above, and other source files
  144. data "template_cloudinit_config" "cloud_init_config" {
  145. gzip = true
  146. base64_encode = true
  147. # Main cloud-config configuration file.
  148. part {
  149. filename = "init.cfg"
  150. content_type = "text/cloud-config"
  151. content = templatefile("${path.module}/cloud-init/cloud-init.tpl",
  152. {
  153. hostname = var.instance_name
  154. fqdn = "${var.instance_name}.${var.dns_info["private"]["zone"]}"
  155. environment = var.environment
  156. salt_master = local.salt_master
  157. proxy = local.proxy
  158. aws_partition = var.aws_partition
  159. aws_partition_alias = var.aws_partition_alias
  160. aws_region = var.aws_region
  161. }
  162. )
  163. }
  164. part {
  165. content_type = "text/cloud-boothook"
  166. content = file("${path.module}/cloud-init/repo_server_volumes.boothook")
  167. }
  168. }
  169. #----------------------------------------------------------------------------
  170. # Repo Server Security Group
  171. #----------------------------------------------------------------------------
  172. resource "aws_security_group" "repo_server_security_group" {
  173. name = "repo_server_security_group"
  174. description = "Security Group for the Repository Server(s) port 80"
  175. vpc_id = var.vpc_id
  176. tags = merge(local.standard_tags, var.tags)
  177. }
  178. #----------------------------------------------------------------------------
  179. # Ingress
  180. #----------------------------------------------------------------------------
  181. resource "aws_security_group_rule" "http-in" {
  182. type = "ingress"
  183. description = "HTTP - Inbound repository requests"
  184. from_port = 80
  185. to_port = 80
  186. protocol = "tcp"
  187. source_security_group_id = aws_security_group.alb_internal.id
  188. security_group_id = aws_security_group.repo_server_security_group.id
  189. }
  190. resource "aws_security_group_rule" "http-in-external" {
  191. type = "ingress"
  192. description = "HTTP - Inbound repository requests from the alb"
  193. from_port = 80
  194. to_port = 80
  195. protocol = "tcp"
  196. source_security_group_id = module.elb.security_group_id
  197. security_group_id = aws_security_group.repo_server_security_group.id
  198. }
  199. # Repo server has an extra volume that is created separately, to keep it from being destroyed
  200. # with the instance.
  201. resource "aws_ebs_volume" "repo_server_drive" {
  202. availability_zone = aws_instance.instance.availability_zone
  203. size = local.repo_drive_size
  204. type = "gp3" # consider moving to sc1 if this is ever > 500GB
  205. encrypted = true
  206. kms_key_id = data.aws_kms_key.ebs-key.arn
  207. #snapshot_id = "${data.aws_ebs_snapshot.repo_snapshot.id}"
  208. tags = merge(local.standard_tags, var.tags, { Name = "${var.instance_name}-repo_volume-_var_www" })
  209. lifecycle {
  210. ignore_changes = [snapshot_id]
  211. }
  212. }
  213. resource "aws_volume_attachment" "repo_attachment" {
  214. device_name = "/dev/xvdf"
  215. volume_id = aws_ebs_volume.repo_server_drive.id
  216. instance_id = aws_instance.instance.id
  217. force_detach = true
  218. }