Browse Source

Creates a test instance module

To be tagged v5.2.0
Fred Damstra [afs macbook] 3 years ago
parent
commit
a78f3f7d3c

+ 23 - 0
base/instance_test/ami_by_filter.tf

@@ -0,0 +1,23 @@
+locals {
+  ami = data.aws_ami.ami.image_id
+}
+
+data "aws_ami" "ami" {
+  most_recent = true
+  owners      = [var.common_services_account]
+
+  filter {
+    name   = "virtualization-type"
+    values = ["hvm"]
+  }
+
+  filter {
+    name   = "root-device-type"
+    values = ["ebs"]
+  }
+
+  filter {
+    name   = "name"
+    values = [var.instance_filter]
+  }
+}

+ 77 - 0
base/instance_test/cloud-init/cloud-init.tpl

@@ -0,0 +1,77 @@
+#cloud-config
+preserve_hostname: false
+hostname: ${hostname}
+salt-master: ${salt_master}
+fqdn: ${fqdn}
+
+# Write files happens early
+write_files:
+- content: |
+    proxy=http://${proxy}:80
+  path: /etc/yum.conf
+  append: true
+- content: |
+    proxy_host: ${proxy}
+    proxy_port: 80
+  path: /etc/salt/minion.d/proxy.conf
+- content: |
+    [global]
+    proxy=${proxy}
+  path: /etc/pip.conf
+- content: |
+    export HTTPS_PROXY=http://${proxy}:80
+    export HTTP_PROXY=http://${proxy}:80
+    export NO_PROXY=localhost,127.0.0.1,169.254.169.254,pvt.xdrtest.accenturefederalcyber.com,pvt.xdr.accenturefederalcyber.com,reposerver.msoc.defpoint.local,jenkins.msoc.defpoint.local,pod1search-splunk-sh.msoc.defpoint.local,s3.amazonaws.com,ssm.${ aws_region }.amazonaws.com,ec2messages.${ aws_region }.amazonaws.com,ec2.${ aws_region }.amazonaws.com,ssmmessages.${ aws_region }.amazonaws.com,iratemoses.mdr.defpoint.com,jira.mdr.defpoint.com,reposerver.pvt.xdr.accenturefederalcyber.com,jenkins.pvt.xdr.accenturefederalcyber.com,pod1search-splunk-sh.pvt.xdr.accenturefederalcyber.com,reposerver.pvt.xdrtest.accenturefederalcyber.com,jenkins.pvt.xdrtest.accenturefederalcyber.com,pod1search-splunk-sh.pvt.xdrtest.accenturefederalcyber.com,iratemoses.xdr.accenturefederalcyber.com,jira.xdr.accenturefederalcyber.com,iratemoses.xdrtest.accenturefederalcyber.com,jira.xdrtest.accenturefederalcyber.com
+    export https_proxy=$HTTPS_PROXY
+    export http_proxy=$HTTP_PROXY
+    export no_proxy=$NO_PROXY
+  path: /etc/profile.d/proxy.sh
+- content: |
+    ${fqdn}
+  path: /etc/salt/minion_id
+- content: |
+    master: ${salt_master}
+  path: /etc/salt/minion
+- content: |
+    grains:
+      environment: ${ environment }
+      aws_partition: ${ aws_partition }
+      aws_partition_alias: ${ aws_partition_alias }
+      aws_region: ${ aws_region }
+  path: /etc/salt/minion.d/cloud_init_grains.conf
+
+#yum_repos:
+#  epel-release:
+#    baseurl: http://download.fedoraproject.org/pub/epel/7/$basearch
+#    enabled: false
+#    failovermethod: priority
+#    gpgcheck: true
+#    gpgkey: http://download.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-7
+#    name: Extra Packages for Enterprise Linux 7 - Release
+
+packages:
+ - vim
+
+package_update: true # Always patch
+
+growpart:
+  mode: auto
+  devices: [ '/', '/var', '/var/log', '/var/log/audit', '/var/tmp', '/tmp', '/home' ]
+  ignore_growroot_disabled: false
+
+runcmd:
+ - /bin/systemctl restart salt-minion
+ - /bin/systemctl enable salt-minion
+ - /bin/systemctl start amazon-ssm-agent
+ - /bin/systemctl enable amazon-ssm-agent
+ - /usr/sbin/aide --update --verbose=0
+ - /bin/cp /var/lib/aide/aide.db.new.gz /var/lib/aide/aide.db.gz
+
+# Either final message or power state, but probably not both
+final_message: "The system is up after $UPTIME seconds"
+#power_state:
+#  delay: "+30"
+#  mode: reboot
+#  message: "System configured after $UPTIME seconds"
+#  timeout: 300
+#  condition: true

+ 1 - 0
base/instance_test/constants.tf

@@ -0,0 +1 @@
+../../variables/constants.tf

+ 1 - 0
base/instance_test/employee_ips.tf

@@ -0,0 +1 @@
+../../variables/employee_ips.tf

+ 1 - 0
base/instance_test/globals.tf

@@ -0,0 +1 @@
+../../variables/globals.tf

+ 149 - 0
base/instance_test/main.tf

@@ -0,0 +1,149 @@
+# Rather than pass in the aws security group, we just look it up. This will
+# probably be useful other places, as well.
+data "aws_security_group" "typical-host" {
+  name   = "typical-host"
+  vpc_id = var.vpc_id
+}
+
+# Use the default EBS key
+data "aws_kms_key" "ebs-key" {
+  key_id = "alias/ebs_root_encrypt_decrypt"
+}
+
+resource "aws_instance" "instance" {
+  count = var.enabled ? 1 : 0
+
+  # availability_zone = var.azs[count.index % 2]
+  tenancy                              = "default"
+  ebs_optimized                        = true
+  disable_api_termination              = var.instance_termination_protection
+  instance_initiated_shutdown_behavior = "stop"
+  instance_type                        = "t3a.medium"
+  key_name                             = "msoc-build"
+  monitoring                           = false # checkov:skip=CKV_AWS_126:Detailed monitoring not needed at this time
+  iam_instance_profile                 = "msoc-default-instance-profile"
+  subnet_id                            = var.subnets[0]
+  associate_public_ip_address          = true
+
+  vpc_security_group_ids = [data.aws_security_group.typical-host.id, aws_security_group.test_instance_security_group[count.index].id]
+
+  metadata_options {
+    http_endpoint = "enabled"
+    # checkov:skip=CKV_AWS_79:see tfsec explanation
+    # tfsec:ignore:aws-ec2-enforce-http-token-imds Saltstack doesn't use s3 sources appropriately; see https://github.com/saltstack/salt/issues/60668
+    http_tokens = "optional"
+  }
+
+  ami = local.ami
+  # We need to ignore ebs_block_device changes, because if the AMI changes, so does the snapshot_id.
+  # If they add a feature to block more specific changes (eg `ebs_block_devices[*].snapshot_id`), then
+  # that could be removed.
+  lifecycle { ignore_changes = [ami, key_name, user_data, ebs_block_device] }
+
+  user_data   = data.template_cloudinit_config.cloud-init.rendered
+  tags        = merge(local.standard_tags, var.tags, var.instance_tags, { Name = var.instance_name })
+  volume_tags = merge(local.standard_tags, var.tags, { Name = var.instance_name })
+}
+
+module "private_dns_record" {
+  count = var.enabled ? 1 : 0
+
+  source = "../../submodules/dns/private_A_record"
+
+  name            = var.instance_name
+  ip_addresses    = [aws_instance.instance[count.index].private_ip]
+  dns_info        = var.dns_info
+  reverse_enabled = var.reverse_enabled
+
+  providers = {
+    aws.c2 = aws.c2
+  }
+}
+
+module "public_dns_record" {
+  count = var.enabled ? 1 : 0
+
+  source = "../../submodules/dns/public_A_record"
+
+  name         = var.instance_name
+  ip_addresses = [aws_instance.instance[count.index].public_ip]
+  dns_info     = var.dns_info
+
+  providers = {
+    aws.mdr-common-services-commercial = aws.mdr-common-services-commercial
+  }
+}
+
+# Render a multi-part cloud-init config making use of the part
+# above, and other source files
+data "template_cloudinit_config" "cloud-init" {
+  gzip          = true
+  base64_encode = true
+
+  # Main cloud-config configuration file.
+  part {
+    filename     = "init.cfg"
+    content_type = "text/cloud-config"
+    content = templatefile("${path.module}/cloud-init/cloud-init.tpl",
+      {
+        hostname            = var.instance_name
+        fqdn                = "${var.instance_name}.${var.dns_info["private"]["zone"]}"
+        environment         = var.environment
+        salt_master         = local.salt_master
+        proxy               = local.proxy
+        aws_partition       = var.aws_partition
+        aws_partition_alias = var.aws_partition_alias
+        aws_region          = var.aws_region
+      }
+    )
+  }
+
+  # Additional parts as needed
+  #part {
+  #  content_type = "text/x-shellscript"
+  #  content      = "ffbaz"
+  #}
+}
+
+#----------------------------------------------------------------------------
+# Test Instance Security Group
+#----------------------------------------------------------------------------
+resource "aws_security_group" "test_instance_security_group" {
+  count = var.enabled ? 1 : 0
+
+  name        = "test_instance_security_group"
+  description = "Security Group for Test Instance Server(s)"
+  vpc_id      = var.vpc_id
+  tags        = merge(local.standard_tags, var.tags)
+}
+
+#----------------------------------------------------------------------------
+# INGRESS
+#----------------------------------------------------------------------------
+resource "aws_security_group_rule" "all-in" {
+  count = var.enabled ? 1 : 0
+
+  type              = "ingress"
+  description       = "Allow all inbound to test instance"
+  from_port         = -1
+  to_port           = -1
+  protocol          = -1
+  cidr_blocks       = ["0.0.0.0/0"]
+  security_group_id = aws_security_group.test_instance_security_group[count.index].id
+}
+
+#----------------------------------------------------------------------------
+# EGRESS
+#----------------------------------------------------------------------------
+# Test Instance can access any port
+resource "aws_security_group_rule" "test_instance-out-all-ports" {
+  count = var.enabled ? 1 : 0
+
+  type              = "egress"
+  description       = "Test Instance can access any port internally - Outbound"
+  protocol          = "all"
+  from_port         = -1
+  to_port           = -1
+  cidr_blocks       = ["0.0.0.0/0"]
+  security_group_id = aws_security_group.test_instance_security_group[count.index].id
+}

+ 15 - 0
base/instance_test/outputs.tf

@@ -0,0 +1,15 @@
+output "instance_arn" {
+  value = aws_instance.instance.*.arn
+}
+
+output "instance_public_ip" {
+  value = aws_instance.instance.*.public_ip
+}
+
+output "instance_private_ip" {
+  value = aws_instance.instance.*.private_ip
+}
+
+output "forward_dns" {
+  value = module.public_dns_record.*.forward
+}

+ 52 - 0
base/instance_test/vars.tf

@@ -0,0 +1,52 @@
+variable "enabled" {
+  description = "Whether module is enabled. Set to true to create the instance."
+  type        = bool
+  default     = false
+}
+
+variable "instance_name" {
+  description = "Hostname, DNS entry, etc."
+  type        = string
+}
+
+variable "instance_filter" {
+  description = "Filter string for AMI name. Must be shared to destination account from common services. NOTE: Ubuntu currently only in govcloud malware account."
+  type        = string
+}
+
+variable "azs" {
+  type = list(string)
+}
+
+variable "subnets" {
+  type = list(string)
+}
+
+variable "vpc_id" {
+  type = string
+}
+
+variable "tags" {
+  description = "Tags to add to the resource (in addition to global standard tags)"
+  type        = map(any)
+  default     = {}
+}
+
+variable "instance_tags" {
+  description = "Tags for the instance only."
+  type        = map(string)
+  default     = {}
+}
+
+variable "instance_type" {
+  type    = string
+  default = "t3a.micro"
+}
+
+variable "reverse_enabled" {
+  description = "Whether to create the reverse DNS entry."
+  type        = bool
+  default     = true
+}
+
+