diff --git a/README.md b/README.md index 28e3b66..37a53d1 100644 --- a/README.md +++ b/README.md @@ -138,6 +138,14 @@ Type: `string` Default: `""` +### [vault\_route53\_private\_dns\_name](#input\_vault\_route53\_private\_dns\_name) + +Description: The Route53 private DNS name for the vault ELB. If not set, no Route53 record will be created. + +Type: `string` + +Default: `""` + ### [ssh\_user](#input\_ssh\_user) Description: User name used for SSH-connections. @@ -186,19 +194,13 @@ Type: `number` Default: `3` -### [vault\_ingress\_cidr\_https](#input\_vault\_ingress\_cidr\_https) - -Description: List of CIDR's from which you are allowed to https access the vault cluster. +### [vault\_ingress\_cidr](#input\_vault\_ingress\_cidr) -Type: `list(string)` +Description: CIDR's from which you are allowed to https access the vault cluster. -Default: +Type: `string` -```json -[ - "0.0.0.0/0" -] -``` +Default: `"0.0.0.0/0"` ### [security\_group\_names](#input\_security\_group\_names) @@ -255,11 +257,11 @@ Default: `null` | Name | Description | |------|-------------| +| [alb\_fqdn\_vault](#output\_alb\_fqdn\_vault) | The AWS provided CNAME of the Vault ALB. | +| [alb\_route53\_public\_dns\_name\_vault](#output\_alb\_route53\_public\_dns\_name\_vault) | The Route53 name attached to the Vault ALB, if specified in variables. | | [asg\_name\_consul\_cluster](#output\_asg\_name\_consul\_cluster) | Autoscaling group name of the Consul cluster. | | [asg\_name\_vault\_cluster](#output\_asg\_name\_vault\_cluster) | Autoscaling group name of the Vault cluster. | | [aws\_region](#output\_aws\_region) | Used AWS region. | -| [elb\_fqdn\_vault](#output\_elb\_fqdn\_vault) | The AWS provided CNAME of the Vault ELB. | -| [elb\_route53\_public\_dns\_name\_vault](#output\_elb\_route53\_public\_dns\_name\_vault) | The Route53 name attached to the Vault ELB, if spcified in variables. | | [iam\_role\_arn\_consul\_cluster](#output\_iam\_role\_arn\_consul\_cluster) | IAM role ARN attached to the Consul cluster. | | [iam\_role\_arn\_vault\_cluster](#output\_iam\_role\_arn\_vault\_cluster) | IAM role ARN attached to the Vault cluster. | | [iam\_role\_id\_consul\_cluster](#output\_iam\_role\_id\_consul\_cluster) | IAM role ID attached to the Consul cluster. | diff --git a/data.tf b/data.tf index 2502393..8684aef 100644 --- a/data.tf +++ b/data.tf @@ -1 +1,30 @@ data "aws_region" "current" {} + +data "aws_route53_zone" "public" { + count = var.vault_route53_public_dns_name != "" ? 1 : 0 + + private_zone = false + + # Removes the first sub-domain part from the FQDN to use as hosted zone. + name = "${replace(var.vault_route53_public_dns_name, "/^.+?\\./", "")}." +} + +data "aws_route53_zone" "private" { + count = var.vault_route53_private_dns_name != "" ? 1 : 0 + + private_zone = true + + # Removes the first sub-domain part from the FQDN to use as hosted zone. + name = "${replace(var.vault_route53_private_dns_name, "/^.+?\\./", "")}." +} + +data "aws_security_groups" "alb" { + filter { + name = "group-name" + values = var.security_group_names + } + filter { + name = "vpc-id" + values = [var.vpc_id] + } +} diff --git a/examples/custom-vpc-with-vault/README.md b/examples/custom-vpc-with-vault/README.md index d69f3cf..c7d85a9 100644 --- a/examples/custom-vpc-with-vault/README.md +++ b/examples/custom-vpc-with-vault/README.md @@ -66,8 +66,8 @@ No resources. | Name | Description | |------|-------------| | [elb\_fqdn\_bastion](#output\_elb\_fqdn\_bastion) | AWS generated CNAME for the bastion host ELB | -| [elb\_fqdn\_vault](#output\_elb\_fqdn\_vault) | AWS generated CNAME for the vault ELB | | [elb\_route53\_public\_dns\_name\_bastion](#output\_elb\_route53\_public\_dns\_name\_bastion) | Route53 public DNS name for the bastion host ELB | -| [elb\_route53\_public\_dns\_name\_vault](#output\_elb\_route53\_public\_dns\_name\_vault) | Route53 public DNS name for the vault ELB | +| [alb\_fqdn\_vault](#output\_alb\_fqdn\_vault) | AWS generated CNAME for the vault ALB | +| [alb\_route53\_public\_dns\_name\_vault](#output\_alb\_route53\_public\_dns\_name\_vault) | Route53 public DNS name for the vault ALB | diff --git a/examples/custom-vpc-with-vault/main.tf b/examples/custom-vpc-with-vault/main.tf index 86e42fc..ab0a417 100644 --- a/examples/custom-vpc-with-vault/main.tf +++ b/examples/custom-vpc-with-vault/main.tf @@ -38,9 +38,9 @@ module "aws_vault" { vault_cluster_name = "vault-example-vault" # Security - ssh_keys = ["ssh-ed25519 AAAAC3Nznte5aaCdi1a1Lzaai/tX6Mc2E+S6g3lrClL09iBZ5cW2OZdSIqomcMko 2 mysshkey"] - ssh_security_group_id = module.aws_vpc.bastion_security_group_id - vault_ingress_cidr_https = ["0.0.0.0/0"] + ssh_keys = ["ssh-ed25519 AAAAC3Nznte5aaCdi1a1Lzaai/tX6Mc2E+S6g3lrClL09iBZ5cW2OZdSIqomcMko 2 mysshkey"] + ssh_security_group_id = module.aws_vpc.bastion_security_group_id + vault_ingress_cidr = "0.0.0.0/0" ssl_certificate_id = "arn:aws:acm:eu-central-1:123456789012:certificate/xxxxx-xxxx-xxxx-xxxx-xxxxx" } diff --git a/examples/custom-vpc-with-vault/outputs.tf b/examples/custom-vpc-with-vault/outputs.tf index a195215..e56aee4 100644 --- a/examples/custom-vpc-with-vault/outputs.tf +++ b/examples/custom-vpc-with-vault/outputs.tf @@ -6,17 +6,17 @@ output "elb_fqdn_bastion" { description = "AWS generated CNAME for the bastion host ELB" } -output "elb_fqdn_vault" { - value = module.aws_vault.elb_fqdn_vault - description = "AWS generated CNAME for the vault ELB" -} - output "elb_route53_public_dns_name_bastion" { value = module.aws_vpc.bastion_route53_public_dns_name description = "Route53 public DNS name for the bastion host ELB" } -output "elb_route53_public_dns_name_vault" { - value = module.aws_vault.elb_route53_public_dns_name_vault - description = "Route53 public DNS name for the vault ELB" +output "alb_fqdn_vault" { + value = module.aws_vault.alb_fqdn_vault + description = "AWS generated CNAME for the vault ALB" +} + +output "alb_route53_public_dns_name_vault" { + value = module.aws_vault.alb_route53_public_dns_name_vault + description = "Route53 public DNS name for the vault ALB" } diff --git a/main.tf b/main.tf index 3c983c6..cdf3e32 100644 --- a/main.tf +++ b/main.tf @@ -27,7 +27,7 @@ module "vault_cluster" { health_check_type = "EC2" - elb_security_group_id = module.vault_elb.security_group_ids[0] + alb_security_group_id = module.vault_alb.security_group_id consul_security_group_id = module.consul_cluster.security_group_id ssh_security_group_id = var.ssh_security_group_id @@ -40,38 +40,108 @@ module "consul_iam_policies_servers" { iam_role_id = module.vault_cluster.iam_role_id } -module "vault_elb" { - source = "github.com/Flaconi/terraform-aws-elb?ref=v2.0.0" - - name = var.vault_cluster_name - vpc_id = var.vpc_id - subnet_ids = var.public_subnet_ids - - lb_port = 443 - lb_protocol = "HTTPS" - instance_port = 8200 - instance_protocol = "HTTPS" - ssl_certificate_id = var.ssl_certificate_id - - target = "HTTPS:8200/v1/sys/health?standbyok=true" - timeout = 5 - interval = 15 - healthy_threshold = 2 - unhealthy_threshold = 2 - - inbound_cidr_blocks = var.vault_ingress_cidr_https - security_group_names = var.security_group_names - - route53_public_dns_name = var.vault_route53_public_dns_name - - public_dns_evaluate_target_health = false +module "vault_alb" { + source = "github.com/terraform-aws-modules/terraform-aws-alb?ref=v9.12.0" + + name = var.vault_cluster_name + vpc_id = var.vpc_id + subnets = var.public_subnet_ids + + security_group_name = "${var.name}-alb" + security_group_description = "ALB security group for external connection" + security_group_ingress_rules = { + all_http = { + from_port = 80 + to_port = 80 + ip_protocol = "tcp" + cidr_ipv4 = var.vault_ingress_cidr + description = "HTTP web traffic" + } + all_https = { + from_port = 443 + to_port = 443 + ip_protocol = "tcp" + cidr_ipv4 = var.vault_ingress_cidr + description = "HTTPS web traffic" + } + } + security_group_egress_rules = { + all = { + ip_protocol = "-1" + cidr_ipv4 = "0.0.0.0/0" + description = "AWS default egress rule" + } + } + security_groups = data.aws_security_groups.alb.ids + + # new + listeners = { + http-https-redirect = { + port = 80 + protocol = "HTTP" + redirect = { + port = "443" + protocol = "HTTPS" + status_code = "HTTP_301" + } + } + https = { + port = 443 + protocol = "HTTPS" + ssl_policy = "ELBSecurityPolicy-TLS13-1-3-2021-06" + certificate_arn = var.ssl_certificate_id + + forward = { + target_group_key = "vault" + } + } + } + + target_groups = { + vault = { + name_prefix = "vault" + protocol = "HTTPS" + port = 8200 + + create_attachment = false + + health_check = { + enable = true + path = "/v1/sys/health?standbyok=true" + port = "traffic-port" + protocol = "HTTPS" + timeout = 5 + interval = 15 + healthy_threshold = 2 + unhealthy_threshold = 2 + } + } + } + + # Route53 Record(s) + route53_records = merge( + var.vault_route53_public_dns_name != "" ? { + public = { + name = var.vault_route53_public_dns_name + type = "A" + zone_id = data.aws_route53_zone.public[0].id + } + } : {}, + var.vault_route53_private_dns_name != "" ? { + private = { + name = var.vault_route53_private_dns_name + type = "A" + zone_id = data.aws_route53_zone.private[0].id + } + } : {} + ) tags = var.tags } resource "aws_autoscaling_attachment" "vault" { autoscaling_group_name = module.vault_cluster.asg_name - elb = module.vault_elb.id + lb_target_group_arn = module.vault_alb.target_groups["vault"].arn } module "consul_cluster" { diff --git a/modules/vault-cluster/README.md b/modules/vault-cluster/README.md index 354b415..c85dba1 100644 --- a/modules/vault-cluster/README.md +++ b/modules/vault-cluster/README.md @@ -89,7 +89,7 @@ machines. | [wait\_for\_capacity\_timeout](#input\_wait\_for\_capacity\_timeout) | A maximum duration that Terraform should wait for ASG instances to be healthy before timing out. Setting this to '0' causes Terraform to skip all Capacity Waiting behavior. | `string` | `"10m"` | no | | [health\_check\_type](#input\_health\_check\_type) | Controls how health checking is done. Must be one of EC2 or ELB. | `string` | `"EC2"` | no | | [health\_check\_grace\_period](#input\_health\_check\_grace\_period) | Time, in seconds, after instance comes into service before checking health. | `number` | `60` | no | -| [elb\_security\_group\_id](#input\_elb\_security\_group\_id) | ID of the security group of a public ELB from which you can API access the Vault instances. | `string` | n/a | yes | +| [alb\_security\_group\_id](#input\_alb\_security\_group\_id) | ID of the security group of a public ELB from which you can API access the Vault instances. | `string` | n/a | yes | | [ssh\_security\_group\_id](#input\_ssh\_security\_group\_id) | ID of the security group of a bastion ssh instance from where you can ssh into the Vault instances. | `string` | n/a | yes | | [consul\_security\_group\_id](#input\_consul\_security\_group\_id) | ID of the security group of the Consul instances to allow traffic from Consul into Vault. | `string` | n/a | yes | | [cluster\_name](#input\_cluster\_name) | The name of the Vault cluster (e.g. vault-stage). This variable is used to namespace all resources created by this module. | `string` | n/a | yes | diff --git a/modules/vault-cluster/security-groups.tf b/modules/vault-cluster/security-groups.tf index 50d779a..751acb4 100644 --- a/modules/vault-cluster/security-groups.tf +++ b/modules/vault-cluster/security-groups.tf @@ -79,7 +79,7 @@ module "lc_security_group" { from_port = "8200" to_port = "8200" protocol = "tcp" - source_security_group_id = var.elb_security_group_id + source_security_group_id = var.alb_security_group_id description = "External API. Allow API access to Vault instances from this security group (from ELB or instances)." }, ] diff --git a/modules/vault-cluster/variables.tf b/modules/vault-cluster/variables.tf index a99aab0..2974d42 100644 --- a/modules/vault-cluster/variables.tf +++ b/modules/vault-cluster/variables.tf @@ -78,7 +78,7 @@ variable "health_check_grace_period" { type = number } -variable "elb_security_group_id" { +variable "alb_security_group_id" { description = "ID of the security group of a public ELB from which you can API access the Vault instances." type = string } diff --git a/outputs.tf b/outputs.tf index 32c59c3..36cbc6a 100644 --- a/outputs.tf +++ b/outputs.tf @@ -1,11 +1,11 @@ -output "elb_fqdn_vault" { - value = module.vault_elb.fqdn - description = "The AWS provided CNAME of the Vault ELB." +output "alb_fqdn_vault" { + value = module.vault_alb.dns_name + description = "The AWS provided CNAME of the Vault ALB." } -output "elb_route53_public_dns_name_vault" { - value = module.vault_elb.route53_public_dns_name - description = "The Route53 name attached to the Vault ELB, if spcified in variables." +output "alb_route53_public_dns_name_vault" { + value = var.vault_route53_public_dns_name + description = "The Route53 name attached to the Vault ALB, if specified in variables." } output "asg_name_consul_cluster" { diff --git a/variables.tf b/variables.tf index 9ce4e5d..efc5c0e 100644 --- a/variables.tf +++ b/variables.tf @@ -43,6 +43,12 @@ variable "vault_route53_public_dns_name" { type = string } +variable "vault_route53_private_dns_name" { + description = "The Route53 private DNS name for the vault ELB. If not set, no Route53 record will be created." + default = "" + type = string +} + variable "ssh_user" { description = "User name used for SSH-connections." type = string @@ -84,10 +90,10 @@ variable "ssh_security_group_id" { type = string } -variable "vault_ingress_cidr_https" { - description = "List of CIDR's from which you are allowed to https access the vault cluster." - type = list(string) - default = ["0.0.0.0/0"] +variable "vault_ingress_cidr" { + description = "CIDR's from which you are allowed to https access the vault cluster." + type = string + default = "0.0.0.0/0" } variable "security_group_names" {