Browse Source

Updates ALSI to have 3 possible endpoints

Configurable in account.hcl:
```
alsi_workers = 2
alsi_splunk_nlb = true # splunk://moose-alsi-splunk.xdr{,test}.accenturefederalcyber.com:9997 and 9998
alsi_elastic_alb = true # https://moose-alsi-elastic.xdr{,test}.accenturefederalcyber.com -> 9200
alsi_hec_alb = true # https://moose-alsi-hec.xdr{,test}.accenturefederalcyber.com -> 8080
```

Never tagged the last one, so this one will still be v1.10.12
Fred Damstra 4 years ago
parent
commit
fd2b5c79fd

+ 34 - 0
base/splunk_servers/alsi/certificate-elastic.tf

@@ -0,0 +1,34 @@
+#Certificate 
+resource "aws_acm_certificate" "cert_elastic" {
+  count             = var.alsi_elastic_alb ? 1 : 0
+  domain_name       = "${var.prefix}-alsi-elastic.${var.dns_info["public"]["zone"]}"
+  validation_method = "DNS"
+
+  tags = merge(var.standard_tags, var.tags)
+}
+
+resource "aws_acm_certificate_validation" "cert_elastic" {
+  count                   = var.alsi_elastic_alb ? 1 : 0
+  certificate_arn         = aws_acm_certificate.cert_elastic[count.index].arn
+  validation_record_fqdns = [for record in aws_route53_record.cert_elastic_validation: record.fqdn]
+}
+
+resource "aws_route53_record" "cert_elastic_validation" {
+  provider = aws.mdr-common-services-commercial
+
+  # This syntax is tricky. If the bool is true, then we create the for_each map, otherwise we do an empty map.
+  for_each = var.alsi_elastic_alb ? {
+    for dvo in aws_acm_certificate.cert_elastic[0].domain_validation_options : dvo.domain_name => {
+      name   = dvo.resource_record_name
+      record = dvo.resource_record_value
+      type   = dvo.resource_record_type
+    } 
+  } : {}
+
+  allow_overwrite = true
+  name            = each.value.name
+  records         = [each.value.record]
+  ttl             = 60
+  type            = each.value.type
+  zone_id         = var.dns_info["public"]["zone_id"]
+}

+ 34 - 0
base/splunk_servers/alsi/certificate-hec.tf

@@ -0,0 +1,34 @@
+#Certificate 
+resource "aws_acm_certificate" "cert_hec" {
+  count             = var.alsi_hec_alb ? 1 : 0
+  domain_name       = "${var.prefix}-alsi-hec.${var.dns_info["public"]["zone"]}"
+  validation_method = "DNS"
+
+  tags = merge(var.standard_tags, var.tags)
+}
+
+resource "aws_acm_certificate_validation" "cert_hec" {
+  count                   = var.alsi_hec_alb ? 1 : 0
+  certificate_arn         = aws_acm_certificate.cert_hec[count.index].arn
+  validation_record_fqdns = [for record in aws_route53_record.cert_hec_validation: record.fqdn]
+}
+
+resource "aws_route53_record" "cert_hec_validation" {
+  provider = aws.mdr-common-services-commercial
+
+  # This syntax is tricky. If the bool is true, then we create the for_each map, otherwise we do an empty map.
+  for_each = var.alsi_hec_alb ? {
+    for dvo in aws_acm_certificate.cert_hec[0].domain_validation_options : dvo.domain_name => {
+      name   = dvo.resource_record_name
+      record = dvo.resource_record_value
+      type   = dvo.resource_record_type
+    } 
+  } : {}
+
+  allow_overwrite = true
+  name            = each.value.name
+  records         = [each.value.record]
+  ttl             = 60
+  type            = each.value.type
+  zone_id         = var.dns_info["public"]["zone_id"]
+}

+ 7 - 7
base/splunk_servers/alsi/certificate.tf → base/splunk_servers/alsi/certificate-master.tf

@@ -1,21 +1,21 @@
 #Certificate 
-resource "aws_acm_certificate" "cert" {
-  domain_name       = "${var.prefix}-alsi.${var.dns_info["public"]["zone"]}"
+resource "aws_acm_certificate" "cert_master" {
+  domain_name       = "${var.prefix}-alsi.${var.dns_info["private"]["zone"]}"
   validation_method = "DNS"
 
   tags = merge(var.standard_tags, var.tags)
 }
 
-resource "aws_acm_certificate_validation" "cert" {
-  certificate_arn         = aws_acm_certificate.cert.arn
-  validation_record_fqdns = [for record in aws_route53_record.cert_validation: record.fqdn]
+resource "aws_acm_certificate_validation" "cert_master" {
+  certificate_arn         = aws_acm_certificate.cert_master.arn
+  validation_record_fqdns = [for record in aws_route53_record.cert_validation_master: record.fqdn]
 }
 
-resource "aws_route53_record" "cert_validation" {
+resource "aws_route53_record" "cert_validation_master" {
   provider = aws.mdr-common-services-commercial
 
   for_each = {
-    for dvo in aws_acm_certificate.cert.domain_validation_options : dvo.domain_name => {
+    for dvo in aws_acm_certificate.cert_master.domain_validation_options : dvo.domain_name => {
       name   = dvo.resource_record_name
       record = dvo.resource_record_value
       type   = dvo.resource_record_type

+ 15 - 0
base/splunk_servers/alsi/data.tf

@@ -0,0 +1,15 @@
+# Some instance variables
+locals {
+  ami_selection = "minion" # master, minion, ...
+}
+
+# Rather than pass in the aws security group, we just look it up.
+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"
+}

+ 136 - 0
base/splunk_servers/alsi/elb-elastic.tf

@@ -0,0 +1,136 @@
+resource "aws_lb" "alsi-alb-elastic" {
+  count              = var.alsi_elastic_alb ? 1 : 0
+  name               = "${var.prefix}-alsi-alb-elastic"
+  internal           = false
+  load_balancer_type = "application"
+  # Not supported for NLB
+  security_groups    = [aws_security_group.alsi-alb-elastic-sg.id]
+  # Note, changing subnets results in recreation of the resource
+  subnets            = var.subnets
+  enable_cross_zone_load_balancing = true
+
+  access_logs {
+    bucket  = "xdr-elb-${ var.environment }"
+    enabled = true
+  }
+
+  tags = merge(var.standard_tags, var.tags)
+}
+
+#########################
+# Listeners
+resource "aws_lb_listener" "alsi-alb-elastic-listener-https" {
+  count             = var.alsi_elastic_alb ? 1 : 0
+  load_balancer_arn = aws_lb.alsi-alb-elastic[count.index].arn
+  port              = "443"
+  protocol          = "HTTPS"
+  ssl_policy        = "ELBSecurityPolicy-FS-1-2-Res-2019-08" # PFS, TLS1.2, most "restrictive" policy (took awhile to find that)
+  certificate_arn   = aws_acm_certificate.cert_elastic[count.index].arn
+
+  default_action {
+    type             = "forward"
+    target_group_arn = aws_lb_target_group.alsi-alb-elastic-target-9200[count.index].arn
+  }
+}
+
+# Only alb's can redirect
+resource "aws_lb_listener" "alsi-alb-elastic-listener-http" {
+  count             = var.alsi_elastic_alb ? 1 : 0
+  load_balancer_arn = aws_lb.alsi-alb-elastic[count.index].arn
+  port              = "80"
+  protocol          = "HTTP"
+
+  default_action {
+    type             = "redirect"
+
+    redirect {
+      port        = "443"
+      protocol    = "HTTPS"
+      status_code = "HTTP_301"
+    }
+  }
+}
+
+#########################
+# Targets
+resource "aws_lb_target_group" "alsi-alb-elastic-target-9200" {
+  count    = var.alsi_elastic_alb ? 1 : 0
+  name     = "${var.prefix}-alsi-elastic-9200"
+  port     = 9200
+  protocol = "HTTPS"
+  target_type = "instance"
+  vpc_id   = var.vpc_id
+  tags = merge(var.standard_tags, var.tags)
+
+  health_check {
+    enabled = true
+    path = "/api/v1/health"
+    port = 9000
+    protocol = "HTTPS"
+  }
+
+  # sure would be nice to check the actual port
+  #health_check {
+  #  enabled = true
+  #  path = "/"
+  #  port = 9000
+  #  protocol = "HTTPS"
+  #}
+}
+
+resource "aws_lb_target_group_attachment" "alsi-alb-elastic-target-9200-instance" {
+  count            = var.alsi_workers * (var.alsi_elastic_alb ? 1 : 0)
+  target_group_arn = aws_lb_target_group.alsi-alb-elastic-target-9200[0].arn
+  target_id        = aws_instance.worker[count.index].id
+  port             = 9200
+}
+
+#########################
+# Security Group for ALB
+resource "aws_security_group" "alsi-alb-elastic-sg" {
+  name_prefix = "${var.prefix}-alsi-alb-elastic-sg"
+  lifecycle { create_before_destroy = true } # handle updates gracefully
+  description = "Security Group for the Cribl ALB for elastic"
+  vpc_id = var.vpc_id
+  tags = merge(var.standard_tags, var.tags)
+}
+
+resource "aws_security_group_rule" "alsi-alb-elastic-https-in" {
+  type              = "ingress"
+  from_port         = 443
+  to_port           = 443
+  protocol          = "tcp"
+  cidr_blocks       = toset(concat(var.cidr_map["vpc-access"], var.trusted_ips, var.splunk_data_sources))
+  security_group_id = aws_security_group.alsi-alb-elastic-sg.id
+}
+
+resource "aws_security_group_rule" "alsi-hec-http-in" {
+  # Port 80 is open as a redirect to 443
+  type              = "ingress"
+  from_port         = 80
+  to_port           = 80
+  protocol          = "tcp"
+  cidr_blocks       = toset(concat(var.cidr_map["vpc-access"], var.trusted_ips, var.splunk_data_sources))
+  security_group_id = aws_security_group.alsi-alb-elastic-sg.id
+}
+
+resource "aws_security_group_rule" "alsi-alb-elastic-9200-out" {
+  type              = "egress"
+  from_port         = 9200
+  to_port           = 9200
+  protocol          = "tcp"
+  source_security_group_id = aws_security_group.alsi_worker_security_group.id
+  security_group_id = aws_security_group.alsi-alb-elastic-sg.id
+}
+
+#########################
+# DNS Entry
+resource "aws_route53_record" "alsi-alb-elastic" {
+  count = var.alsi_elastic_alb ? 1 : 0
+  zone_id = var.dns_info["public"]["zone_id"]
+  name    = "${ var.prefix }-alsi-elastic"
+  type    = "CNAME"
+  records = [aws_lb.alsi-alb-elastic[count.index].dns_name]
+  ttl = "60"
+  provider = aws.mdr-common-services-commercial
+}

+ 136 - 0
base/splunk_servers/alsi/elb-hec.tf

@@ -0,0 +1,136 @@
+resource "aws_lb" "alsi-alb-hec" {
+  count              = var.alsi_hec_alb ? 1 : 0
+  name               = "${var.prefix}-alsi-alb-hec"
+  internal           = false
+  load_balancer_type = "application"
+  # Not supported for NLB
+  security_groups    = [aws_security_group.alsi-alb-hec-sg.id]
+  # Note, changing subnets results in recreation of the resource
+  subnets            = var.subnets
+  enable_cross_zone_load_balancing = true
+
+  access_logs {
+    bucket  = "xdr-elb-${ var.environment }"
+    enabled = true
+  }
+
+  tags = merge(var.standard_tags, var.tags)
+}
+
+#########################
+# Listeners
+resource "aws_lb_listener" "alsi-alb-hec-listener-https" {
+  count             = var.alsi_hec_alb ? 1 : 0
+  load_balancer_arn = aws_lb.alsi-alb-hec[count.index].arn
+  port              = "443"
+  protocol          = "HTTPS"
+  ssl_policy        = "ELBSecurityPolicy-FS-1-2-Res-2019-08" # PFS, TLS1.2, most "restrictive" policy (took awhile to find that)
+  certificate_arn   = aws_acm_certificate.cert_hec[count.index].arn
+
+  default_action {
+    type             = "forward"
+    target_group_arn = aws_lb_target_group.alsi-alb-hec-target-8088[count.index].arn
+  }
+}
+
+# Only alb's can redirect
+resource "aws_lb_listener" "alsi-alb-hec-listener-http" {
+  count             = var.alsi_hec_alb ? 1 : 0
+  load_balancer_arn = aws_lb.alsi-alb-hec[count.index].arn
+  port              = "80"
+  protocol          = "HTTP"
+
+  default_action {
+    type             = "redirect"
+
+    redirect {
+      port        = "443"
+      protocol    = "HTTPS"
+      status_code = "HTTP_301"
+    }
+  }
+}
+
+#########################
+# Targets
+resource "aws_lb_target_group" "alsi-alb-hec-target-8088" {
+  count    = var.alsi_hec_alb ? 1 : 0
+  name     = "${var.prefix}-alsi-hec-8088"
+  port     = 8088
+  protocol = "HTTPS"
+  target_type = "instance"
+  vpc_id   = var.vpc_id
+  tags = merge(var.standard_tags, var.tags)
+
+  health_check {
+    enabled = true
+    path = "/api/v1/health"
+    port = 9000
+    protocol = "HTTPS"
+  }
+
+  # sure would be nice to check the actual port
+  #health_check {
+  #  enabled = true
+  #  path = "/"
+  #  port = 9000
+  #  protocol = "HTTPS"
+  #}
+}
+
+resource "aws_lb_target_group_attachment" "alsi-alb-hec-target-8088-instance" {
+  count            = var.alsi_workers * (var.alsi_hec_alb ? 1 : 0)
+  target_group_arn = aws_lb_target_group.alsi-alb-hec-target-8088[0].arn
+  target_id        = aws_instance.worker[count.index].id
+  port             = 8088
+}
+
+#########################
+# Security Group for ALB
+resource "aws_security_group" "alsi-alb-hec-sg" {
+  name_prefix = "${var.prefix}-alsi-alb-hec-sg"
+  lifecycle { create_before_destroy = true } # handle updates gracefully
+  description = "Security Group for the Cribl ALB for hec"
+  vpc_id = var.vpc_id
+  tags = merge(var.standard_tags, var.tags)
+}
+
+resource "aws_security_group_rule" "alsi-alb-hec-https-in" {
+  type              = "ingress"
+  from_port         = 443
+  to_port           = 443
+  protocol          = "tcp"
+  cidr_blocks       = toset(concat(var.cidr_map["vpc-access"], var.trusted_ips, var.splunk_data_sources))
+  security_group_id = aws_security_group.alsi-alb-hec-sg.id
+}
+
+resource "aws_security_group_rule" "alsi-elastic-http-in" {
+  # Port 80 is open as a redirect to 443
+  type              = "ingress"
+  from_port         = 80
+  to_port           = 80
+  protocol          = "tcp"
+  cidr_blocks       = toset(concat(var.cidr_map["vpc-access"], var.trusted_ips, var.splunk_data_sources))
+  security_group_id = aws_security_group.alsi-alb-hec-sg.id
+}
+
+resource "aws_security_group_rule" "alsi-alb-hec-8088-out" {
+  type              = "egress"
+  from_port         = 8088
+  to_port           = 8088
+  protocol          = "tcp"
+  source_security_group_id = aws_security_group.alsi_worker_security_group.id
+  security_group_id = aws_security_group.alsi-alb-hec-sg.id
+}
+
+#########################
+# DNS Entry
+resource "aws_route53_record" "alsi-alb-hec" {
+  count = var.alsi_hec_alb ? 1 : 0
+  zone_id = var.dns_info["public"]["zone_id"]
+  name    = "${ var.prefix }-alsi-hec"
+  type    = "CNAME"
+  records = [aws_lb.alsi-alb-hec[count.index].dns_name]
+  ttl = "60"
+  provider = aws.mdr-common-services-commercial
+}

+ 121 - 0
base/splunk_servers/alsi/elb-master.tf

@@ -0,0 +1,121 @@
+resource "aws_lb" "alsi-master-alb" {
+  name               = "${var.prefix}-alsi-master-alb"
+  internal           = true
+  load_balancer_type = "application"
+  security_groups    = [aws_security_group.alsi-master-alb-sg.id]
+  # Note, changing subnets results in recreation of the resource
+  subnets            = var.subnets
+  enable_cross_zone_load_balancing = true
+
+  access_logs {
+    bucket  = "xdr-elb-${ var.environment }"
+    enabled = true
+  }
+
+  tags = merge(var.standard_tags, var.tags)
+}
+
+#########################
+# Listeners
+resource "aws_lb_listener" "alsi-master-alb-listener-https" {
+  load_balancer_arn = aws_lb.alsi-master-alb.arn
+  port              = "443"
+  protocol          = "HTTPS"
+  ssl_policy        = "ELBSecurityPolicy-FS-1-2-Res-2019-08" # PFS, TLS1.2, most "restrictive" policy (took awhile to find that)
+  certificate_arn   = aws_acm_certificate.cert_master.arn
+
+  default_action {
+    type             = "forward"
+    target_group_arn = aws_lb_target_group.alsi-master-alb-target-9000.arn
+  }
+}
+
+# Only alb's can redirect
+resource "aws_lb_listener" "alsi-master-alb-listener-http" {
+  load_balancer_arn = aws_lb.alsi-master-alb.arn
+  port              = "80"
+  protocol          = "HTTP"
+
+  default_action {
+    type             = "redirect"
+
+    redirect {
+      port        = "443"
+      protocol    = "HTTPS"
+      status_code = "HTTP_301"
+    }
+  }
+}
+
+#########################
+# Targets
+resource "aws_lb_target_group" "alsi-master-alb-target-9000" {
+  name     = "${var.prefix}-alsi-master-9000"
+  port     = 9000
+  protocol = "HTTPS"
+  target_type = "instance"
+  vpc_id   = var.vpc_id
+  tags = merge(var.standard_tags, var.tags)
+
+  health_check {
+    enabled = true
+    path = "/api/v1/health"
+    port = 9000
+    protocol = "HTTPS"
+  }
+}
+
+resource "aws_lb_target_group_attachment" "alsi-master-alb-target-9000-instance" {
+  target_group_arn = aws_lb_target_group.alsi-master-alb-target-9000.arn
+  target_id        = aws_instance.master.id
+  port             = 9000
+}
+
+#########################
+# Security Group for ALB
+resource "aws_security_group" "alsi-master-alb-sg" {
+  name_prefix = "${var.prefix}-alsi-master-alb-sg"
+  lifecycle { create_before_destroy = true } # handle updates gracefully
+  description = "Security Group for the Cribl ALB"
+  vpc_id = var.vpc_id
+  tags = merge(var.standard_tags, var.tags)
+}
+
+resource "aws_security_group_rule" "alsi-master-alb-https-in" {
+  type              = "ingress"
+  from_port         = 443
+  to_port           = 443
+  protocol          = "tcp"
+  cidr_blocks       = var.cidr_map["vpc-access"]
+  security_group_id = aws_security_group.alsi-master-alb-sg.id
+}
+
+resource "aws_security_group_rule" "alsi-master-http-in" {
+  # Port 80 is open as a redirect to 443
+  type              = "ingress"
+  from_port         = 80
+  to_port           = 80
+  protocol          = "tcp"
+  cidr_blocks       = var.cidr_map["vpc-access"]
+  security_group_id = aws_security_group.alsi-master-alb-sg.id
+}
+
+resource "aws_security_group_rule" "alsi-master-alb-9000-out" {
+  type              = "egress"
+  from_port         = 9000
+  to_port           = 9000
+  protocol          = "tcp"
+  source_security_group_id = aws_security_group.alsi_master_security_group.id
+  security_group_id = aws_security_group.alsi-master-alb-sg.id
+}
+
+#########################
+# DNS Entry
+resource "aws_route53_record" "alsi_master_alb" {
+  zone_id = var.dns_info["private"]["zone_id"]
+  name    = "${ var.prefix }-alsi"
+  type    = "CNAME"
+  records = [ aws_lb.alsi-master-alb.dns_name ]
+  ttl = "60"
+  provider = aws.c2
+}

+ 0 - 130
base/splunk_servers/alsi/elb.tf

@@ -1,130 +0,0 @@
-resource "aws_lb" "alsi-alb" {
-  name               = "${var.prefix}-alsi-alb"
-  internal           = false
-  load_balancer_type = "application"
-  # Not supported for NLB
-  security_groups    = [aws_security_group.alsi-alb-sg.id]
-  # Note, changing subnets results in recreation of the resource
-  subnets            = var.subnets
-  enable_cross_zone_load_balancing = true
-
-  access_logs {
-    bucket  = "xdr-elb-${ var.environment }"
-    enabled = true
-  }
-
-  tags = merge(var.standard_tags, var.tags)
-}
-
-#########################
-# Listeners
-resource "aws_lb_listener" "alsi-alb-listener-https" {
-  load_balancer_arn = aws_lb.alsi-alb.arn
-  port              = "443"
-  protocol          = "HTTPS"
-  ssl_policy        = "ELBSecurityPolicy-FS-1-2-Res-2019-08" # PFS, TLS1.2, most "restrictive" policy (took awhile to find that)
-  certificate_arn   = aws_acm_certificate.cert.arn
-
-  default_action {
-    type             = "forward"
-    target_group_arn = aws_lb_target_group.alsi-alb-target-443.arn
-  }
-}
-
-# Only alb's can redirect
-resource "aws_lb_listener" "alsi-alb-listener-http" {
-  load_balancer_arn = aws_lb.alsi-alb.arn
-  port              = "80"
-  protocol          = "HTTP"
-
-  default_action {
-    type             = "redirect"
-
-    redirect {
-      port        = "443"
-      protocol    = "HTTPS"
-      status_code = "HTTP_301"
-    }
-  }
-}
-
-#########################
-# Targets
-resource "aws_lb_target_group" "alsi-alb-target-443" {
-  name     = "${var.prefix}-alsi-alb-target-443"
-  port     = 443
-  protocol = "HTTPS"
-  target_type = "instance"
-  vpc_id   = var.vpc_id
-  tags = merge(var.standard_tags, var.tags)
-
-  health_check {
-    enabled = true
-    path = "/api/v1/health"
-    port = 443
-    protocol = "HTTPS"
-  }
-
-  # Does cribl need stickiness?
-  #stickiness {
-  #  type = "lb_cookie"
-  #  cookie_duration = 86400 # 1 day
-  #  enabled = true
-  #}
-}
-
-resource "aws_lb_target_group_attachment" "alsi-alb-target-443-instance" {
-  count            = var.alsi_count
-  target_group_arn = aws_lb_target_group.alsi-alb-target-443.arn
-  target_id        = aws_instance.instance[count.index].id
-  port             = 443
-}
-
-#########################
-# Security Group for ALB
-resource "aws_security_group" "alsi-alb-sg" {
-  name_prefix = "${var.prefix}-alsi-alb-sg"
-  lifecycle { create_before_destroy = true } # handle updates gracefully
-  description = "Security Group for the Cribl ALB"
-  vpc_id = var.vpc_id
-  tags = merge(var.standard_tags, var.tags)
-}
-
-resource "aws_security_group_rule" "alsi-alb-https-in" {
-  type              = "ingress"
-  from_port         = 443
-  to_port           = 443
-  protocol          = "tcp"
-  cidr_blocks       = toset(concat(var.cidr_map["vpc-access"], var.trusted_ips, var.splunk_data_sources))
-  security_group_id = aws_security_group.alsi-alb-sg.id
-}
-
-resource "aws_security_group_rule" "alsi-http-in" {
-  # Port 80 is open as a redirect to 443
-  type              = "ingress"
-  from_port         = 80
-  to_port           = 80
-  protocol          = "tcp"
-  cidr_blocks       = toset(concat(var.cidr_map["vpc-access"], var.trusted_ips, var.splunk_data_sources))
-  security_group_id = aws_security_group.alsi-alb-sg.id
-}
-
-resource "aws_security_group_rule" "alsi-alb-443-out" {
-  type              = "egress"
-  from_port         = 443
-  to_port           = 443
-  protocol          = "tcp"
-  cidr_blocks       = [ var.vpc_cidr ]
-  security_group_id = aws_security_group.alsi-alb-sg.id
-}
-
-#########################
-# DNS Entry
-resource "aws_route53_record" "alsi" {
-  zone_id = var.dns_info["public"]["zone_id"]
-  name    = "${ var.prefix }-alsi"
-  type    = "CNAME"
-  records = [aws_lb.alsi-alb.dns_name]
-  ttl = "60"
-  provider = aws.mdr-common-services-commercial
-}

+ 0 - 191
base/splunk_servers/alsi/main.tf

@@ -1,191 +0,0 @@
-# Some instance variables
-locals {
-  ami_selection = "minion" # master, minion, ...
-  instance_name = "${ var.prefix }-alsi"
-  is_moose = length(regexall("moose", var.prefix)) > 0 ? true : false
-}
-
-# Rather than pass in the aws security group, we just look it up.
-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_network_interface" "instance" {
-  count = var.alsi_count
-  subnet_id = var.subnets[ count.index % length(var.subnets) ] # evenly distributed across subnets
-  security_groups = [ data.aws_security_group.typical-host.id, aws_security_group.alsi_security_group.id ]
-  description = "${local.instance_name}-${count.index}"
-  tags = merge( var.standard_tags, 
-                var.tags, 
-                { 
-                  Name = "${local.instance_name}-${count.index}", 
-                  instance_num = count.index, 
-                  instance_count = var.alsi_count 
-                }
-              )
-}
-
-resource "aws_instance" "instance" {
-  count = var.alsi_count
-  #availability_zone = var.azs[count.index % 2] # automatically determined by the network interface
-  tenancy = "default"
-  ebs_optimized = true
-  disable_api_termination = var.instance_termination_protection
-  instance_initiated_shutdown_behavior = "stop"
-  instance_type = var.instance_type
-  key_name = "msoc-build"
-  monitoring = false
-  iam_instance_profile = "msoc-default-instance-profile"
-
-  ami = local.ami_map[local.ami_selection]
-  # 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 ] }
-
-  # These device definitions are optional, but added for clarity.
-  root_block_device {
-    volume_type = "gp2"
-    #volume_size = Override via var?
-    delete_on_termination = true
-    encrypted = true
-    kms_key_id = data.aws_kms_key.ebs-key.arn
-  }
-
-  network_interface {
-    device_index = 0
-    network_interface_id = aws_network_interface.instance[count.index].id
-  }
-
-  user_data = data.template_cloudinit_config.cloud-init[count.index].rendered
-  tags = merge( var.standard_tags, 
-                var.tags, 
-                { 
-                  Name = "${local.instance_name}-${count.index}", 
-                  instance_num = count.index, 
-                  instance_count = var.alsi_count 
-                }
-              )
-  volume_tags = merge( var.standard_tags, 
-                var.tags, 
-                { 
-                  Name = "${local.instance_name}-${count.index}", 
-                  instance_num = count.index, 
-                  instance_count = var.alsi_count 
-                }
-              )
-}
-
-module "private_dns_record" {
-  count = var.alsi_count
-  source = "../../../submodules/dns/private_A_record"
-
-  name = "${local.instance_name}-${count.index}"
-  ip_addresses = [ aws_instance.instance[count.index].private_ip ]
-  dns_info = var.dns_info
-  reverse_enabled = var.reverse_enabled
-
-  providers = {
-    aws.c2 = aws.c2
-  }
-}
-
-data "template_file" "cloud-init" {
-  count = var.alsi_count
-
-  # Should these be in a common directory? I suspect they'd be reusable
-  template = file("${path.module}/cloud-init/cloud-init.tpl")
-
-  vars = {
-    hostname = "${local.instance_name}-${count.index}"
-    fqdn = "${local.instance_name}-${count.index}.${var.dns_info["private"]["zone"]}"
-    splunk_prefix = var.prefix
-    environment = var.environment
-    salt_master  = var.salt_master
-    proxy = var.proxy
-    aws_partition = var.aws_partition
-    aws_partition_alias = var.aws_partition_alias
-    aws_region = var.aws_region
-  }
-}
-
-# Render a multi-part cloud-init config making use of the part
-# above, and other source files
-data "template_cloudinit_config" "cloud-init" {
-  count         = var.alsi_count
-  gzip          = true
-  base64_encode = true
-
-  # Main cloud-config configuration file.
-  part {
-    filename     = "init.cfg"
-    content_type = "text/cloud-config"
-    content      = data.template_file.cloud-init[count.index].rendered
-  }
-}
-
-## ALSI
-#
-# Summary:
-#   Ingress:
-#     443 - from ALB
-#     443 - From vpc-access
-#
-#   Egress:
-#     8089 - To Splunk
-#     9997 - To Splunk
-resource "aws_security_group" "alsi_security_group" {
-  name_prefix = "${ var.prefix }_alsi_security_group" # name prefix and livecycle allow for smooth updates
-  lifecycle { create_before_destroy = true } # handle updates gracefully
-  description = "Security Group for Aggregated Log Source Ingestion"
-  vpc_id = var.vpc_id
-  tags = merge(var.standard_tags, var.tags)
-}
-
-# Ingress
-resource "aws_security_group_rule" "alsi-alb-web-in" {
-  description       = "Web access"
-  type              = "ingress"
-  from_port         = 443
-  to_port           = 443
-  protocol          = "tcp"
-  source_security_group_id = aws_security_group.alsi-alb-sg.id
-  security_group_id = aws_security_group.alsi_security_group.id
-}
-
-resource "aws_security_group_rule" "alsi-access-web-in" {
-  description       = "Web access"
-  type              = "ingress"
-  from_port         = 443
-  to_port           = 443
-  protocol          = "tcp"
-  cidr_blocks       = var.cidr_map["vpc-access"]
-  security_group_id = aws_security_group.alsi_security_group.id
-}
-
-# Egress
-resource "aws_security_group_rule" "splunk-mgmt" {
-  description       = "Management Access"
-  type              = "egress"
-  from_port         = 8089
-  to_port           = 8089
-  protocol          = "tcp"
-  cidr_blocks       = [ var.vpc_cidr ]
-  security_group_id = aws_security_group.alsi_security_group.id
-} 
-
-resource "aws_security_group_rule" "splunk-data" {
-  description       = "Management Access"
-  type              = "egress"
-  from_port         = 9997
-  to_port           = 9998
-  protocol          = "tcp"
-  cidr_blocks       = [ var.vpc_cidr ]
-  security_group_id = aws_security_group.alsi_security_group.id
-}

+ 168 - 0
base/splunk_servers/alsi/master.tf

@@ -0,0 +1,168 @@
+# Some instance variables
+locals {
+  instance_name_master = "${ var.prefix }-alsi-master"
+}
+
+resource "aws_network_interface" "master" {
+  subnet_id = var.subnets[0]
+  security_groups = [ data.aws_security_group.typical-host.id, aws_security_group.alsi_master_security_group.id ]
+  description = local.instance_name_master
+  tags = merge( var.standard_tags, 
+                var.tags, 
+                { Name = local.instance_name_master }
+              )
+}
+
+resource "aws_instance" "master" {
+  tenancy = "default"
+  ebs_optimized = true
+  disable_api_termination = var.instance_termination_protection
+  instance_initiated_shutdown_behavior = "stop"
+  instance_type = var.instance_types["alsi-master"]
+  key_name = "msoc-build"
+  monitoring = false
+  iam_instance_profile = "msoc-default-instance-profile"
+
+  ami = local.ami_map[local.ami_selection]
+  # 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 ] }
+
+  # These device definitions are optional, but added for clarity.
+  root_block_device {
+    volume_type = "gp2"
+    #volume_size = Override via var?
+    delete_on_termination = true
+    encrypted = true
+    kms_key_id = data.aws_kms_key.ebs-key.arn
+  }
+
+  network_interface {
+    device_index = 0
+    network_interface_id = aws_network_interface.master.id
+  }
+
+  user_data = data.template_cloudinit_config.cloud-init-master.rendered
+  tags = merge( var.standard_tags, 
+                var.tags, 
+                { Name = local.instance_name_master, }
+              )
+  volume_tags = merge( var.standard_tags, 
+                var.tags, 
+                { Name = local.instance_name_master, }
+              )
+}
+
+module "private_dns_record_master" {
+  source = "../../../submodules/dns/private_A_record"
+
+  name = local.instance_name_master
+  ip_addresses = [ aws_instance.master.private_ip ]
+  dns_info = var.dns_info
+  reverse_enabled = var.reverse_enabled
+
+  providers = {
+    aws.c2 = aws.c2
+  }
+}
+
+data "template_file" "cloud-init-master" {
+  # Should these be in a common directory? I suspect they'd be reusable
+  template = file("${path.module}/cloud-init/cloud-init.tpl")
+
+  vars = {
+    hostname = local.instance_name_master
+    fqdn = "${local.instance_name_master}.${var.dns_info["private"]["zone"]}"
+    splunk_prefix = var.prefix
+    environment = var.environment
+    salt_master  = var.salt_master
+    proxy = var.proxy
+    aws_partition = var.aws_partition
+    aws_partition_alias = var.aws_partition_alias
+    aws_region = var.aws_region
+  }
+}
+
+# Render a multi-part cloud-init config making use of the part
+# above, and other source files
+data "template_cloudinit_config" "cloud-init-master" {
+  gzip          = true
+  base64_encode = true
+
+  # Main cloud-config configuration file.
+  part {
+    filename     = "init.cfg"
+    content_type = "text/cloud-config"
+    content      = data.template_file.cloud-init-master.rendered
+  }
+}
+
+## Master
+#
+# Summary:
+#   Ingress:
+#     9000 - From private ALB
+#     9000 - From vpc-access
+#
+#   Egress:
+#     9997/9998 - To Splunk
+resource "aws_security_group" "alsi_master_security_group" {
+  name_prefix = "${ var.prefix }_alsi_master_security_group" # name prefix and livecycle allow for smooth updates
+  lifecycle { create_before_destroy = true } # handle updates gracefully
+  description = "Security Group for Aggregated Log Source Ingestion"
+  vpc_id = var.vpc_id
+  tags = merge(var.standard_tags, var.tags)
+}
+
+# Ingress
+resource "aws_security_group_rule" "alsi-master-alb-web-in" {
+  description       = "Web access"
+  type              = "ingress"
+  from_port         = 9000
+  to_port           = 9000
+  protocol          = "tcp"
+  source_security_group_id = aws_security_group.alsi-master-alb-sg.id
+  security_group_id = aws_security_group.alsi_master_security_group.id
+}
+
+resource "aws_security_group_rule" "alsi-master-vpn-web-in" {
+  description       = "Web access"
+  type              = "ingress"
+  from_port         = 9000
+  to_port           = 9000
+  protocol          = "tcp"
+  cidr_blocks       = var.cidr_map["vpc-access"]
+  security_group_id = aws_security_group.alsi_master_security_group.id
+}
+
+resource "aws_security_group_rule" "alsi-master-interconnections" {
+  description       = "Cribl Replication"
+  type              = "ingress"
+  from_port         = 4200
+  to_port           = 4200
+  protocol          = "tcp"
+  source_security_group_id = aws_security_group.alsi_worker_security_group.id
+  security_group_id = aws_security_group.alsi_master_security_group.id
+}
+
+# Egress
+resource "aws_security_group_rule" "alsi-master-splunk-mgmt" {
+  description       = "Management Access"
+  type              = "egress"
+  from_port         = 8089
+  to_port           = 8089
+  protocol          = "tcp"
+  cidr_blocks       = [ var.vpc_cidr ]
+  security_group_id = aws_security_group.alsi_master_security_group.id
+} 
+
+resource "aws_security_group_rule" "alsi-master-splunk-data" {
+  description       = "Management Access"
+  type              = "egress"
+  from_port         = 9997
+  to_port           = 9998
+  protocol          = "tcp"
+  cidr_blocks       = [ var.vpc_cidr ]
+  security_group_id = aws_security_group.alsi_master_security_group.id
+}

+ 107 - 0
base/splunk_servers/alsi/nlb-splunk.tf

@@ -0,0 +1,107 @@
+#------------------------------------------------------------------------------
+# Splunk2Splunk Requires an NLB
+#------------------------------------------------------------------------------
+resource "aws_eip" "alsi_splunk_nlb" {
+  count = var.alsi_splunk_nlb ? 2 : 0
+
+  vpc  = true
+  tags = merge(var.standard_tags, var.tags, map("Name","${var.prefix}-alsi-splunk" ))
+}
+
+resource "aws_lb" "alsi_splunk_nlb" {
+  count = var.alsi_splunk_nlb ? 1 : 0
+  tags               = merge(var.standard_tags, var.tags, map("Name","${var.prefix}-alsi-splunk" ))
+  name               = "${var.prefix}-alsi-splunk-nlb"
+  internal           = false
+  load_balancer_type = "network"
+  #subnets            = data.terraform_remote_state.infra.subnets
+
+  subnet_mapping {
+    subnet_id = element(var.subnets,0)
+    allocation_id = element(aws_eip.alsi_splunk_nlb.*.id,0)
+  }
+
+  subnet_mapping {
+    subnet_id = element(var.subnets,1)
+    allocation_id = element(aws_eip.alsi_splunk_nlb.*.id,1)
+  }
+
+  access_logs {
+    bucket  = "xdr-elb-${ var.environment }"
+    enabled = true
+  }
+}
+
+resource "aws_lb_target_group" "nlb_targets_9997" {
+  count = var.alsi_splunk_nlb ? 1 : 0
+  name     = "${var.prefix}-alsi-splunk-nlb-9997"
+  port     = 9997
+  protocol = "TCP"
+  vpc_id   = var.vpc_id
+}
+
+resource "aws_lb_listener" "nlb_targets_9997" {
+  count = var.alsi_splunk_nlb ? 1 : 0
+  load_balancer_arn = aws_lb.alsi_splunk_nlb[count.index].arn
+  port              = 9997
+  protocol          = "TCP"
+
+  default_action {
+    target_group_arn = aws_lb_target_group.nlb_targets_9997[count.index].arn
+    type             = "forward"
+  }
+}
+
+resource "aws_lb_target_group_attachment" "alsi_nlb_target_9997_instance" {
+  count            = var.alsi_splunk_nlb ? var.alsi_workers : 0
+  target_group_arn = aws_lb_target_group.nlb_targets_9997[0].arn
+  target_id        = aws_instance.worker[count.index].id
+  port             = 9997
+}
+
+resource "aws_lb_target_group" "nlb_targets_9998" {
+  count = var.alsi_splunk_nlb ? 1 : 0
+  name     = "${var.prefix}-alsi-splunk-nlb-9998"
+  port     = 9998
+  protocol = "TCP"
+  vpc_id   = var.vpc_id
+}
+
+resource "aws_lb_listener" "nlb_targets_9998" {
+  count = var.alsi_splunk_nlb ? 1 : 0
+  load_balancer_arn = aws_lb.alsi_splunk_nlb[count.index].arn
+  port              = 9998
+  protocol          = "TCP"
+
+  default_action {
+    target_group_arn = aws_lb_target_group.nlb_targets_9998[count.index].arn
+    type             = "forward"
+  }
+}
+
+resource "aws_lb_target_group_attachment" "alsi_nlb_target_9998_instance" {
+  count            = var.alsi_splunk_nlb ? var.alsi_workers : 0
+  target_group_arn = aws_lb_target_group.nlb_targets_9998[0].arn
+  target_id        = aws_instance.worker[count.index].id
+  port             = 9998
+}
+
+#########################
+# Security Groups
+
+# no security groups for NLB, access is controlled on the worker itself
+
+#########################
+# DNS Entry
+module "public_dns_record_alsi_nlb" {
+  count = var.alsi_splunk_nlb ? 1 : 0
+  source = "../../../submodules/dns/public_A_record"
+
+  name = "${var.prefix}-alsi-splunk"
+  ip_addresses = aws_eip.alsi_splunk_nlb.*.public_ip
+  dns_info = var.dns_info
+
+  providers = {
+    aws.mdr-common-services-commercial = aws.mdr-common-services-commercial
+  }
+}

+ 26 - 9
base/splunk_servers/alsi/outputs.tf

@@ -1,15 +1,32 @@
-output elb_fqdn {
-  value = aws_route53_record.alsi.fqdn
+output elastic_fqdn {
+  value = aws_route53_record.alsi-alb-elastic.*.fqdn
 }
-
-output instance_fqdn {
-  value = module.private_dns_record[*].forward
+output splunk_fqdn {
+  value = module.public_dns_record_alsi_nlb.*.forward
+}
+output hec_fqdn {
+  value = aws_route53_record.alsi-alb-hec.*.fqdn
+}
+output management_fqdn {
+  value = aws_route53_record.alsi_master_alb.fqdn
 }
 
-output instance_arn {
-  value = aws_instance.instance[*].arn
+output worker_fqdn {
+  value = module.private_dns_record_worker.*.forward
+}
+output worker_arn {
+  value = aws_instance.worker.*.arn
+}
+output worker_private_ip {
+  value = aws_instance.worker.*.private_ip
 }
 
-output instance_private_ip {
-  value = aws_instance.instance[*].private_ip
+output master_fqdn {
+  value = module.private_dns_record_master.forward
+}
+output master_arn {
+  value = aws_instance.master.arn
+}
+output master_private_ip {
+  value = aws_instance.master.private_ip
 }

+ 18 - 4
base/splunk_servers/alsi/vars.tf

@@ -1,7 +1,22 @@
-variable "alsi_count" {
+variable "alsi_workers" {
   type = number
 }
 
+variable "alsi_splunk_nlb" {
+  description = "Create an NLB that forwards to 9997/9998?"
+  type = bool
+}
+
+variable "alsi_elastic_alb" {
+  description = "Create an ALB that forwards to 9200?"
+  type = bool
+}
+
+variable "alsi_hec_alb" {
+  description = "Create an ALB that forwards to 8088?"
+  type = bool
+}
+
 variable "prefix" {
   description = "Prefix for Instance Names"
   type = string
@@ -39,9 +54,8 @@ variable "tags" {
   default     = { }
 }
 
-variable "instance_type" { 
-  type = string
-  default = "t3a.micro"
+variable "instance_types" { 
+  type = map
 }
 
 variable "reverse_enabled" { 

+ 239 - 0
base/splunk_servers/alsi/workers.tf

@@ -0,0 +1,239 @@
+# Some instance variables
+locals {
+  instance_name_worker = "${ var.prefix }-alsi"
+}
+
+resource "aws_network_interface" "worker" {
+  count = var.alsi_workers
+  subnet_id = var.subnets[ count.index % length(var.subnets) ] # evenly distributed across subnets
+  security_groups = [ data.aws_security_group.typical-host.id, aws_security_group.alsi_worker_security_group.id ]
+  description = "${local.instance_name_worker}-${count.index}"
+  tags = merge( var.standard_tags, 
+                var.tags, 
+                { 
+                  Name = "${local.instance_name_worker}-${count.index}", 
+                  instance_num = count.index, 
+                  instance_count = var.alsi_workers 
+                }
+              )
+}
+
+resource "aws_instance" "worker" {
+  count = var.alsi_workers
+  #availability_zone = var.azs[count.index % 2] # automatically determined by the network interface
+  tenancy = "default"
+  ebs_optimized = true
+  disable_api_termination = var.instance_termination_protection
+  instance_initiated_shutdown_behavior = "stop"
+  instance_type = var.instance_types["alsi-worker"]
+  key_name = "msoc-build"
+  monitoring = false
+  iam_instance_profile = "msoc-default-instance-profile"
+
+  ami = local.ami_map[local.ami_selection]
+  # 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 ] }
+
+  # These device definitions are optional, but added for clarity.
+  root_block_device {
+    volume_type = "gp2"
+    #volume_size = Override via var?
+    delete_on_termination = true
+    encrypted = true
+    kms_key_id = data.aws_kms_key.ebs-key.arn
+  }
+
+  network_interface {
+    device_index = 0
+    network_interface_id = aws_network_interface.worker[count.index].id
+  }
+
+  user_data = data.template_cloudinit_config.cloud-init-worker[count.index].rendered
+  tags = merge( var.standard_tags, 
+                var.tags, 
+                { 
+                  Name = "${local.instance_name_worker}-${count.index}", 
+                  instance_num = count.index, 
+                  instance_count = var.alsi_workers 
+                }
+              )
+  volume_tags = merge( var.standard_tags, 
+                var.tags, 
+                { 
+                  Name = "${local.instance_name_worker}-${count.index}", 
+                  instance_num = count.index, 
+                  instance_count = var.alsi_workers 
+                }
+              )
+}
+
+module "private_dns_record_worker" {
+  count = var.alsi_workers
+  source = "../../../submodules/dns/private_A_record"
+
+  name = "${local.instance_name_worker}-${count.index}"
+  ip_addresses = [ aws_instance.worker[count.index].private_ip ]
+  dns_info = var.dns_info
+  reverse_enabled = var.reverse_enabled
+
+  providers = {
+    aws.c2 = aws.c2
+  }
+}
+
+data "template_file" "cloud-init-worker" {
+  count = var.alsi_workers
+
+  # Should these be in a common directory? I suspect they'd be reusable
+  template = file("${path.module}/cloud-init/cloud-init.tpl")
+
+  vars = {
+    hostname = "${local.instance_name_worker}-${count.index}"
+    fqdn = "${local.instance_name_worker}-${count.index}.${var.dns_info["private"]["zone"]}"
+    splunk_prefix = var.prefix
+    environment = var.environment
+    salt_master  = var.salt_master
+    proxy = var.proxy
+    aws_partition = var.aws_partition
+    aws_partition_alias = var.aws_partition_alias
+    aws_region = var.aws_region
+  }
+}
+
+# Render a multi-part cloud-init config making use of the part
+# above, and other source files
+data "template_cloudinit_config" "cloud-init-worker" {
+  count         = var.alsi_workers
+  gzip          = true
+  base64_encode = true
+
+  # Main cloud-config configuration file.
+  part {
+    filename     = "init.cfg"
+    content_type = "text/cloud-config"
+    content      = data.template_file.cloud-init-worker[count.index].rendered
+  }
+}
+
+## ALSI Worker
+#
+# Summary:
+#   Ingress:
+#     9000 - From ALBs
+#     9000 - From vpc-access
+#     8088 - From alb_hec
+#     9200 - From alb_elastic
+#     8088 - From alb_splunk_hec
+#
+#   Egress:
+#     4200 - To master
+#     9997 - To Splunk
+resource "aws_security_group" "alsi_worker_security_group" {
+  name_prefix = "${ var.prefix }_alsi_worker_security_group" # name prefix and livecycle allow for smooth updates
+  lifecycle { create_before_destroy = true } # handle updates gracefully
+  description = "Security Group for Aggregated Log Source Ingestion"
+  vpc_id = var.vpc_id
+  tags = merge(var.standard_tags, var.tags)
+}
+
+# Ingress
+resource "aws_security_group_rule" "alsi_worker_alb_elastic1" {
+  description       = "Health Check"
+  type              = "ingress"
+  from_port         = 9000
+  to_port           = 9000
+  protocol          = "tcp"
+  source_security_group_id = aws_security_group.alsi-alb-elastic-sg.id
+  security_group_id = aws_security_group.alsi_worker_security_group.id
+}
+resource "aws_security_group_rule" "alsi_worker_alb_elastic2" {
+  description       = "Data Stream"
+  type              = "ingress"
+  from_port         = 9200
+  to_port           = 9200
+  protocol          = "tcp"
+  source_security_group_id = aws_security_group.alsi-alb-elastic-sg.id
+  security_group_id = aws_security_group.alsi_worker_security_group.id
+}
+
+# TODO: Repeat top 2 for HEC and S2S forwarders
+
+resource "aws_security_group_rule" "alsi_worker_vpn_in1" {
+  description       = "Web access"
+  type              = "ingress"
+  from_port         = 9000
+  to_port           = 9000
+  protocol          = "tcp"
+  cidr_blocks       = var.cidr_map["vpc-access"]
+  security_group_id = aws_security_group.alsi_worker_security_group.id
+}
+resource "aws_security_group_rule" "alsi_worker_vpn_in2" {
+  description       = "Web access"
+  type              = "ingress"
+  from_port         = 9200
+  to_port           = 9200
+  protocol          = "tcp"
+  cidr_blocks       = var.cidr_map["vpc-access"]
+  security_group_id = aws_security_group.alsi_worker_security_group.id
+}
+resource "aws_security_group_rule" "alsi_worker_vpn_in3" {
+  description       = "Test Splunk access"
+  type              = "ingress"
+  from_port         = 9997
+  to_port           = 9998
+  protocol          = "tcp"
+  cidr_blocks       = var.cidr_map["vpc-access"]
+  security_group_id = aws_security_group.alsi_worker_security_group.id
+}
+resource "aws_security_group_rule" "alsi_worker_vpn_in4" {
+  description       = "Test HEC access"
+  type              = "ingress"
+  from_port         = 8088
+  to_port           = 8088
+  protocol          = "tcp"
+  cidr_blocks       = var.cidr_map["vpc-access"]
+  security_group_id = aws_security_group.alsi_worker_security_group.id
+}
+resource "aws_security_group_rule" "alsi_worker_external_in" {
+  # NLB requires the security group to allow access
+  count = var.alsi_splunk_nlb ? 1 : 0
+  type              = "ingress"
+  from_port         = 9997
+  to_port           = 9998
+  protocol          = "tcp"
+  cidr_blocks       = toset(concat(var.cidr_map["vpc-access"], var.trusted_ips, var.splunk_data_sources))
+  security_group_id = aws_security_group.alsi-alb-hec-sg.id
+}
+
+# Egress
+resource "aws_security_group_rule" "alsi-interconnections" {
+  description       = "cribl replication"
+  type              = "egress"
+  from_port         = 4200
+  to_port           = 4200
+  protocol          = "tcp"
+  source_security_group_id = aws_security_group.alsi_master_security_group.id
+  security_group_id = aws_security_group.alsi_worker_security_group.id
+}
+
+resource "aws_security_group_rule" "alsi-worker-splunk-mgmt" {
+  description       = "Management Access"
+  type              = "egress"
+  from_port         = 8089
+  to_port           = 8089
+  protocol          = "tcp"
+  cidr_blocks       = [ var.vpc_cidr ]
+  security_group_id = aws_security_group.alsi_worker_security_group.id
+} 
+
+resource "aws_security_group_rule" "alsi-worker-splunk-data" {
+  description       = "Management Access"
+  type              = "egress"
+  from_port         = 9997
+  to_port           = 9998
+  protocol          = "tcp"
+  cidr_blocks       = [ var.vpc_cidr ]
+  security_group_id = aws_security_group.alsi_worker_security_group.id
+}