From 7f946312d6ef1c187a27c032f61d9bf8be742cfd Mon Sep 17 00:00:00 2001 From: Joshua Kite Date: Thu, 19 Sep 2024 15:19:16 +0100 Subject: [PATCH 1/6] update contribution doc --- CONTRIBUTING | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/CONTRIBUTING b/CONTRIBUTING index 17d3e74..18cc2bc 100644 --- a/CONTRIBUTING +++ b/CONTRIBUTING @@ -4,6 +4,10 @@ I am always happy to consider contributions to the code offered here. Please fee I generally try to avoid breaking changes and changes to default behaviour except e.g. where versions have become deprecated. New options that don't change default behaviour are welcome. -All proposed code changes must be tested before submission! I don't have a formal test suite so I'm afraid it is a case of testing changes manually with deployment, log in successfully, etc. +All proposed code changes must be tested before submission! I don't have a formal test suite so I'm afraid it is a case of testing changes manually with deployment, log in successfully, etc. I will generally test with Open Tofu current version as a starting point using the `/examples` here with varioations to test any conditional logic. + +examples will need module version incrementing with new version and deploying to check validity - I will expect to handle this but would welcome suggestions with P/Rs! + +If the feature change is significant then it may be worth considering adding another example deployment to test it. Thanks \ No newline at end of file From f9b3fdfa91f7f635897b28d91c0299e108d7fad6 Mon Sep 17 00:00:00 2001 From: Joshua Bird Date: Wed, 11 Sep 2024 11:33:36 -0700 Subject: [PATCH 2/6] Add support for launch template metadata options. --- main.tf | 12 ++++++++++++ variables.tf | 8 +++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/main.tf b/main.tf index 728bc37..c7c0498 100755 --- a/main.tf +++ b/main.tf @@ -59,6 +59,18 @@ resource "aws_launch_template" "bastion-service-host" { } } + dynamic "metadata_options" { + for_each = length(keys(var.bastion_metadata_options)) > 0 ? { bastion_metadata_options = var.bastion_metadata_options } : {} + + content { + http_endpoint = lookup(metadata_options.value, "http_endpoint", "enabled") + http_tokens = lookup(metadata_options.value, "http_tokens", "optional") + http_put_response_hop_limit = lookup(metadata_options.value, "http_put_response_hop_limit", 1) + http_protocol_ipv6 = lookup(metadata_options.value, "http_protocol_ipv6", null) + instance_metadata_tags = lookup(metadata_options.value, "instance_metadata_tags", null) + } + } + lifecycle { create_before_destroy = true } diff --git a/variables.tf b/variables.tf index 75aefba..b7e83e2 100755 --- a/variables.tf +++ b/variables.tf @@ -237,4 +237,10 @@ variable "bastion_service_port" { type = number description = "Port for containerised ssh daemon" default = 22 -} \ No newline at end of file +} + +variable "bastion_metadata_options" { + type = map(any) + description = "Passthrough for aws_launch_template.metadata_options. Keys http_endpoint, http_tokens, http_put_response_hop_limit, http_protocol_ipv6, and instance_metadata_tags are supported." + default = {} +} From c556ca503fc24283c2e3253b2924de1987f0af4b Mon Sep 17 00:00:00 2001 From: Joshua Bird Date: Wed, 11 Sep 2024 11:43:26 -0700 Subject: [PATCH 3/6] Update README. --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index c1624be..de99b47 100755 --- a/README.md +++ b/README.md @@ -263,6 +263,7 @@ name = "${var.environment_name}-${data.aws_region.current.name}-${var.vpc}-basti These have been generated with [terraform-docs](https://github.com/segmentio/terraform-docs) + ## Requirements | Name | Version | @@ -331,6 +332,7 @@ No modules. | [bastion\_ebs\_size](#input\_bastion\_ebs\_size) | Size of EBS attached to the bastion instance | `number` | `8` | no | | [bastion\_host\_name](#input\_bastion\_host\_name) | The hostname to give to the bastion instance | `string` | `""` | no | | [bastion\_instance\_types](#input\_bastion\_instance\_types) | List of ec2 types for the bastion host, used by aws\_launch\_template (first from the list) and in aws\_autoscaling\_group | `list` |
[
"t3.small",
"t3.medium",
"t3.large"
]
| no | +| [bastion\_metadata\_options](#input\_bastion\_metadata\_options) | Passthrough for aws\_launch\_template.metadata\_options. Keys http\_endpoint, http\_tokens, http\_put\_response\_hop\_limit, http\_protocol\_ipv6, and instance\_metadata\_tags are supported. | `map(any)` | `{}` | no | | [bastion\_service\_host\_key\_name](#input\_bastion\_service\_host\_key\_name) | AWS ssh key *.pem to be used for ssh access to the bastion service host | `string` | `""` | no | | [bastion\_service\_port](#input\_bastion\_service\_port) | Port for containerised ssh daemon | `number` | `22` | no | | [bastion\_vpc\_name](#input\_bastion\_vpc\_name) | define the last part of the hostname, by default this is the vpc ID with magic default value of 'vpc\_id' but you can pass a custom string, or an empty value to omit this | `string` | `"vpc_id"` | no | @@ -378,3 +380,4 @@ No modules. | [policy\_example\_for\_parent\_account\_empty\_if\_not\_used](#output\_policy\_example\_for\_parent\_account\_empty\_if\_not\_used) | You must apply an IAM policy with trust relationship identical or compatible with this in your other AWS account for IAM lookups to function there with STS:AssumeRole and allow users to login | | [service\_dns\_entry](#output\_service\_dns\_entry) | dns-registered url for service and host | | [target\_group\_arn](#output\_target\_group\_arn) | aws load balancer target group arn | + From a007d3cc635c52bc3eb6e0d2b329fe3313359717 Mon Sep 17 00:00:00 2001 From: Joshua Bird Date: Thu, 12 Sep 2024 12:57:44 -0700 Subject: [PATCH 4/6] Remove dynamic block. Do not supply any defaults. --- main.tf | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/main.tf b/main.tf index c7c0498..a2be95f 100755 --- a/main.tf +++ b/main.tf @@ -59,16 +59,12 @@ resource "aws_launch_template" "bastion-service-host" { } } - dynamic "metadata_options" { - for_each = length(keys(var.bastion_metadata_options)) > 0 ? { bastion_metadata_options = var.bastion_metadata_options } : {} - - content { - http_endpoint = lookup(metadata_options.value, "http_endpoint", "enabled") - http_tokens = lookup(metadata_options.value, "http_tokens", "optional") - http_put_response_hop_limit = lookup(metadata_options.value, "http_put_response_hop_limit", 1) - http_protocol_ipv6 = lookup(metadata_options.value, "http_protocol_ipv6", null) - instance_metadata_tags = lookup(metadata_options.value, "instance_metadata_tags", null) - } + metadata_options { + http_endpoint = try(var.bastion_metadata_options.http_endpoint, null) + http_tokens = try(var.bastion_metadata_options.http_tokens, null) + http_put_response_hop_limit = try(var.bastion_metadata_options.http_put_response_hop_limit, null) + http_protocol_ipv6 = try(var.bastion_metadata_options.http_protocol_ipv6, null) + instance_metadata_tags = try(var.bastion_metadata_options.instance_metadata_tags, null) } lifecycle { From c30358422ba9c703cdaa339ccf68884819c99b44 Mon Sep 17 00:00:00 2001 From: Joshua Bird Date: Fri, 13 Sep 2024 09:36:07 -0700 Subject: [PATCH 5/6] Bump min TF to 1.3. Update input variable. Add dynamic block. Update changelog. --- README.md | 6 +++--- changelog.md | 5 +++++ .../custom-outbound-security-group/README.md | 2 +- .../custom-outbound-security-group/versions.tf | 2 +- examples/full-with-public-ip/README.md | 2 +- examples/full-with-public-ip/versions.tf | 2 +- main.tf | 17 +++++++++++------ variables.tf | 10 ++++++++-- versions.tf | 2 +- 9 files changed, 32 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index de99b47..79143b2 100755 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # This Terraform deploys a stateless containerised sshd bastion service on AWS with IAM based authentication: -This module requires Terraform >/=1.2.0 Older versions were previously supported going back to Terraform 0.11.x with module version to ~> v4.0 +This module requires Terraform >/=1.3.0 Older versions were previously supported going back to Terraform 0.11.x with module version to ~> v4.0 **N.B. If you are using a newer version of this module when you have an older version deployed, please review the changelog!** @@ -268,7 +268,7 @@ These have been generated with [terraform-docs](https://github.com/segmentio/ter | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 1.2.0 | +| [terraform](#requirement\_terraform) | >= 1.3.0 | ## Providers @@ -332,7 +332,7 @@ No modules. | [bastion\_ebs\_size](#input\_bastion\_ebs\_size) | Size of EBS attached to the bastion instance | `number` | `8` | no | | [bastion\_host\_name](#input\_bastion\_host\_name) | The hostname to give to the bastion instance | `string` | `""` | no | | [bastion\_instance\_types](#input\_bastion\_instance\_types) | List of ec2 types for the bastion host, used by aws\_launch\_template (first from the list) and in aws\_autoscaling\_group | `list` |
[
"t3.small",
"t3.medium",
"t3.large"
]
| no | -| [bastion\_metadata\_options](#input\_bastion\_metadata\_options) | Passthrough for aws\_launch\_template.metadata\_options. Keys http\_endpoint, http\_tokens, http\_put\_response\_hop\_limit, http\_protocol\_ipv6, and instance\_metadata\_tags are supported. | `map(any)` | `{}` | no | +| [bastion\_metadata\_options](#input\_bastion\_metadata\_options) | Passthrough for aws\_launch\_template.metadata\_options. |
object({
http_endpoint = optional(string)
http_tokens = optional(string)
http_put_response_hop_limit = optional(number)
http_protocol_ipv6 = optional(string)
instance_metadata_tags = optional(string)
})
| `{}` | no | | [bastion\_service\_host\_key\_name](#input\_bastion\_service\_host\_key\_name) | AWS ssh key *.pem to be used for ssh access to the bastion service host | `string` | `""` | no | | [bastion\_service\_port](#input\_bastion\_service\_port) | Port for containerised ssh daemon | `number` | `22` | no | | [bastion\_vpc\_name](#input\_bastion\_vpc\_name) | define the last part of the hostname, by default this is the vpc ID with magic default value of 'vpc\_id' but you can pass a custom string, or an empty value to omit this | `string` | `"vpc_id"` | no | diff --git a/changelog.md b/changelog.md index b72698b..f9c7909 100644 --- a/changelog.md +++ b/changelog.md @@ -1,3 +1,8 @@ +# TBD + +- **Feature:** EC2 instances can be supplied metadata options through `var.bastion_metadata_options` +- **Change:** Increment required terraform version to >= 1.3.0 + # 8.1 - **Feature:** Make default permissive outbound security group rule creation conditional: `var.custom_outbound_security_group` `type = bool`. Historic behaviour is followed by default diff --git a/examples/custom-outbound-security-group/README.md b/examples/custom-outbound-security-group/README.md index 07ecd58..afaf242 100644 --- a/examples/custom-outbound-security-group/README.md +++ b/examples/custom-outbound-security-group/README.md @@ -30,7 +30,7 @@ ssh -p 443 user@load_balancer_dns_output_value | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 1.2.0 | +| [terraform](#requirement\_terraform) | >= 1.3.0 | ## Providers diff --git a/examples/custom-outbound-security-group/versions.tf b/examples/custom-outbound-security-group/versions.tf index 78f0a7d..34b3c36 100644 --- a/examples/custom-outbound-security-group/versions.tf +++ b/examples/custom-outbound-security-group/versions.tf @@ -1,6 +1,6 @@ terraform { - required_version = ">= 1.2.0" + required_version = ">= 1.3.0" required_providers { aws = { source = "hashicorp/aws" diff --git a/examples/full-with-public-ip/README.md b/examples/full-with-public-ip/README.md index 8a01673..cca794d 100644 --- a/examples/full-with-public-ip/README.md +++ b/examples/full-with-public-ip/README.md @@ -8,7 +8,7 @@ This example shows a complete setup for a new `bastion` service with all needed | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 1.2.0 | +| [terraform](#requirement\_terraform) | >= 1.3.0 | ## Providers diff --git a/examples/full-with-public-ip/versions.tf b/examples/full-with-public-ip/versions.tf index 78f0a7d..34b3c36 100644 --- a/examples/full-with-public-ip/versions.tf +++ b/examples/full-with-public-ip/versions.tf @@ -1,6 +1,6 @@ terraform { - required_version = ">= 1.2.0" + required_version = ">= 1.3.0" required_providers { aws = { source = "hashicorp/aws" diff --git a/main.tf b/main.tf index a2be95f..3c8995c 100755 --- a/main.tf +++ b/main.tf @@ -59,12 +59,17 @@ resource "aws_launch_template" "bastion-service-host" { } } - metadata_options { - http_endpoint = try(var.bastion_metadata_options.http_endpoint, null) - http_tokens = try(var.bastion_metadata_options.http_tokens, null) - http_put_response_hop_limit = try(var.bastion_metadata_options.http_put_response_hop_limit, null) - http_protocol_ipv6 = try(var.bastion_metadata_options.http_protocol_ipv6, null) - instance_metadata_tags = try(var.bastion_metadata_options.instance_metadata_tags, null) + # Hide the `metadata_options` block if it's empty + dynamic "metadata_options" { + for_each = length(compact(values(var.bastion_metadata_options))) > 0 ? { bastion_metadata_options = var.bastion_metadata_options } : {} + + content { + http_endpoint = try(var.bastion_metadata_options.http_endpoint, null) + http_tokens = try(var.bastion_metadata_options.http_tokens, null) + http_put_response_hop_limit = try(var.bastion_metadata_options.http_put_response_hop_limit, null) + http_protocol_ipv6 = try(var.bastion_metadata_options.http_protocol_ipv6, null) + instance_metadata_tags = try(var.bastion_metadata_options.instance_metadata_tags, null) + } } lifecycle { diff --git a/variables.tf b/variables.tf index b7e83e2..c8ca179 100755 --- a/variables.tf +++ b/variables.tf @@ -240,7 +240,13 @@ variable "bastion_service_port" { } variable "bastion_metadata_options" { - type = map(any) - description = "Passthrough for aws_launch_template.metadata_options. Keys http_endpoint, http_tokens, http_put_response_hop_limit, http_protocol_ipv6, and instance_metadata_tags are supported." + type = object({ + http_endpoint = optional(string) + http_tokens = optional(string) + http_put_response_hop_limit = optional(number) + http_protocol_ipv6 = optional(string) + instance_metadata_tags = optional(string) + }) + description = "Passthrough for aws_launch_template.metadata_options." default = {} } diff --git a/versions.tf b/versions.tf index 78f0a7d..34b3c36 100644 --- a/versions.tf +++ b/versions.tf @@ -1,6 +1,6 @@ terraform { - required_version = ">= 1.2.0" + required_version = ">= 1.3.0" required_providers { aws = { source = "hashicorp/aws" From ee3422a83b845ec4cf1dfaec58e78fd02ce35ec5 Mon Sep 17 00:00:00 2001 From: Joshua Kite Date: Thu, 19 Sep 2024 15:35:09 +0100 Subject: [PATCH 6/6] final changes for merge to main --- .gitignore | 3 +++ CONTRIBUTING | 4 ++-- README.md | 7 +++---- changelog.md | 2 +- variables.tf | 2 +- 5 files changed, 10 insertions(+), 8 deletions(-) diff --git a/.gitignore b/.gitignore index 6299374..85902db 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,6 @@ terraform.tfstate.backup .gitignore .vscode/ to_do.md +.pluralith/ +.terraform/ +.terraform.lock.hcl diff --git a/CONTRIBUTING b/CONTRIBUTING index 18cc2bc..99be113 100644 --- a/CONTRIBUTING +++ b/CONTRIBUTING @@ -6,8 +6,8 @@ I generally try to avoid breaking changes and changes to default behaviour excep All proposed code changes must be tested before submission! I don't have a formal test suite so I'm afraid it is a case of testing changes manually with deployment, log in successfully, etc. I will generally test with Open Tofu current version as a starting point using the `/examples` here with varioations to test any conditional logic. -examples will need module version incrementing with new version and deploying to check validity - I will expect to handle this but would welcome suggestions with P/Rs! - If the feature change is significant then it may be worth considering adding another example deployment to test it. +Please also update `changelog.md` with `TBD` + Thanks \ No newline at end of file diff --git a/README.md b/README.md index 79143b2..34f5a61 100755 --- a/README.md +++ b/README.md @@ -274,8 +274,8 @@ These have been generated with [terraform-docs](https://github.com/segmentio/ter | Name | Version | |------|---------| -| [aws](#provider\_aws) | 4.22.0 | -| [cloudinit](#provider\_cloudinit) | 2.2.0 | +| [aws](#provider\_aws) | n/a | +| [cloudinit](#provider\_cloudinit) | n/a | ## Modules @@ -332,7 +332,7 @@ No modules. | [bastion\_ebs\_size](#input\_bastion\_ebs\_size) | Size of EBS attached to the bastion instance | `number` | `8` | no | | [bastion\_host\_name](#input\_bastion\_host\_name) | The hostname to give to the bastion instance | `string` | `""` | no | | [bastion\_instance\_types](#input\_bastion\_instance\_types) | List of ec2 types for the bastion host, used by aws\_launch\_template (first from the list) and in aws\_autoscaling\_group | `list` |
[
"t3.small",
"t3.medium",
"t3.large"
]
| no | -| [bastion\_metadata\_options](#input\_bastion\_metadata\_options) | Passthrough for aws\_launch\_template.metadata\_options. |
object({
http_endpoint = optional(string)
http_tokens = optional(string)
http_put_response_hop_limit = optional(number)
http_protocol_ipv6 = optional(string)
instance_metadata_tags = optional(string)
})
| `{}` | no | +| [bastion\_metadata\_options](#input\_bastion\_metadata\_options) | Passthrough for aws\_launch\_template.metadata\_options. **Don't** apply `http_*` options if you're not sure what you're doing! |
object({
http_endpoint = optional(string)
http_tokens = optional(string)
http_put_response_hop_limit = optional(number)
http_protocol_ipv6 = optional(string)
instance_metadata_tags = optional(string)
})
| `{}` | no | | [bastion\_service\_host\_key\_name](#input\_bastion\_service\_host\_key\_name) | AWS ssh key *.pem to be used for ssh access to the bastion service host | `string` | `""` | no | | [bastion\_service\_port](#input\_bastion\_service\_port) | Port for containerised ssh daemon | `number` | `22` | no | | [bastion\_vpc\_name](#input\_bastion\_vpc\_name) | define the last part of the hostname, by default this is the vpc ID with magic default value of 'vpc\_id' but you can pass a custom string, or an empty value to omit this | `string` | `"vpc_id"` | no | @@ -380,4 +380,3 @@ No modules. | [policy\_example\_for\_parent\_account\_empty\_if\_not\_used](#output\_policy\_example\_for\_parent\_account\_empty\_if\_not\_used) | You must apply an IAM policy with trust relationship identical or compatible with this in your other AWS account for IAM lookups to function there with STS:AssumeRole and allow users to login | | [service\_dns\_entry](#output\_service\_dns\_entry) | dns-registered url for service and host | | [target\_group\_arn](#output\_target\_group\_arn) | aws load balancer target group arn | - diff --git a/changelog.md b/changelog.md index f9c7909..c0b0934 100644 --- a/changelog.md +++ b/changelog.md @@ -1,4 +1,4 @@ -# TBD +# 8.2 - **Feature:** EC2 instances can be supplied metadata options through `var.bastion_metadata_options` - **Change:** Increment required terraform version to >= 1.3.0 diff --git a/variables.tf b/variables.tf index c8ca179..34740d5 100755 --- a/variables.tf +++ b/variables.tf @@ -247,6 +247,6 @@ variable "bastion_metadata_options" { http_protocol_ipv6 = optional(string) instance_metadata_tags = optional(string) }) - description = "Passthrough for aws_launch_template.metadata_options." + description = "Passthrough for aws_launch_template.metadata_options. **Don't** apply `http_*` options if you're not sure what you're doing!" default = {} }