From 24ec158176de68bdda66d9b87ae20269cf44599b Mon Sep 17 00:00:00 2001 From: Steven B Date: Tue, 28 Feb 2023 14:55:04 -0500 Subject: [PATCH] Upgrade provider (#10) * update license * update ci * relax versions --- .github/workflows/pre-commit.yaml | 13 +-- .github/workflows/pullRequest.yaml | 24 ++---- .github/workflows/tflint.yaml | 6 +- .github/workflows/tfsec.yaml | 6 +- .pre-commit-config.yaml | 36 ++++++-- .tflint.hcl | 3 +- LICENSE | 2 +- README.md | 131 +++++++++++++++++++++-------- bin/install-macos.sh | 3 +- bin/install-ubuntu.sh | 19 +++-- main.tf | 6 +- terraform-docs | 0 versions.tf | 4 +- 13 files changed, 156 insertions(+), 97 deletions(-) delete mode 100644 terraform-docs diff --git a/.github/workflows/pre-commit.yaml b/.github/workflows/pre-commit.yaml index 03de2a3..398767c 100644 --- a/.github/workflows/pre-commit.yaml +++ b/.github/workflows/pre-commit.yaml @@ -2,7 +2,7 @@ name: pre-commit-check on: push: - branches: -- main + branches: - master - prod - develop @@ -19,7 +19,7 @@ jobs: - name: initialize Terraform run: terraform init --backend=false - name: pre-commit - uses: pre-commit/action@v2.0.0 + uses: pre-commit/action@v2.0.3 env: AWS_DEFAULT_REGION: us-east-1 # many of these are covered by better reviewdog linters below @@ -28,12 +28,3 @@ jobs: no-commit-to-branch, terraform_tflint_nocreds, terraform_tfsec - - uses: stefanzweifel/git-auto-commit-action@v4 - if: ${{ failure() }} - with: - commit_message: Apply automatic changes - commit_options: "--no-verify" - # Optional commit user and author settings - commit_user_name: Linter Bot - commit_user_email: noreply@rhythmictech.com - commit_author: Linter Bot diff --git a/.github/workflows/pullRequest.yaml b/.github/workflows/pullRequest.yaml index 5f5186c..8f1eba5 100644 --- a/.github/workflows/pullRequest.yaml +++ b/.github/workflows/pullRequest.yaml @@ -4,6 +4,7 @@ on: pull_request: jobs: + # TODO: #22 add job using https://github.com/reviewdog/action-alex pre-commit: runs-on: ubuntu-latest steps: @@ -15,7 +16,7 @@ jobs: - name: initialize Terraform run: terraform init --backend=false - name: pre-commit - uses: pre-commit/action@v2.0.0 + uses: pre-commit/action@v2.0.3 env: AWS_DEFAULT_REGION: us-east-1 # many of these are covered by better reviewdog linters below @@ -24,23 +25,12 @@ jobs: no-commit-to-branch, terraform_tflint_nocreds, terraform_tfsec - - uses: stefanzweifel/git-auto-commit-action@v4 - if: ${{ failure() }} - with: - commit_message: Apply automatic changes - commit_options: "--no-verify" - # Optional commit user and author settings - commit_user_name: Linter Bot - commit_user_email: noreply@rhythmictech.com - commit_author: Linter Bot tflint: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - - name: setup Terraform - uses: hashicorp/setup-terraform@v1 - with: - terraform_version: 0.12.26 + - name: Install prerequisites + run: ./bin/install-ubuntu.sh - name: Terraform init run: terraform init --backend=false - name: tflint @@ -55,10 +45,8 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - - name: setup Terraform - uses: hashicorp/setup-terraform@v1 - with: - terraform_version: 0.12.26 + - name: Install prerequisites + run: ./bin/install-ubuntu.sh - name: Terraform init run: terraform init --backend=false - name: tfsec diff --git a/.github/workflows/tflint.yaml b/.github/workflows/tflint.yaml index ce54833..10457b5 100644 --- a/.github/workflows/tflint.yaml +++ b/.github/workflows/tflint.yaml @@ -13,10 +13,8 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - - name: setup Terraform - uses: hashicorp/setup-terraform@v1 - with: - terraform_version: 0.12.26 + - name: Install prerequisites + run: ./bin/install-ubuntu.sh - name: Terraform init run: terraform init --backend=false - name: tflint diff --git a/.github/workflows/tfsec.yaml b/.github/workflows/tfsec.yaml index 9067568..2f75a3e 100644 --- a/.github/workflows/tfsec.yaml +++ b/.github/workflows/tfsec.yaml @@ -13,10 +13,8 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - - name: setup Terraform - uses: hashicorp/setup-terraform@v1 - with: - terraform_version: 0.12.26 + - name: Install prerequisites + run: ./bin/install-ubuntu.sh - name: Terraform init run: terraform init --backend=false - name: tfsec diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f13d6ce..8273282 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,17 +1,11 @@ +exclude: ".terraform" repos: - repo: https://github.com/antonbabenko/pre-commit-terraform - rev: v1.31.0 + rev: v1.77.1 hooks: - id: terraform_docs always_run: true - args: - - --args=--sort-by-required - id: terraform_fmt - - id: terraform_tflint - alias: terraform_tflint_deep - name: terraform_tflint_deep - args: - - --args=--deep - id: terraform_tflint alias: terraform_tflint_nocreds name: terraform_tflint_nocreds @@ -33,6 +27,28 @@ repos: cd $(dirname "$FILE") terraform init --backend=false terraform validate . + cd .. + done + ' + language: system + verbose: true + files: \.tf(vars)?$ + exclude: examples + - id: tflock + name: provider_locks + entry: | + bash -c ' + AWS_DEFAULT_REGION=us-east-1 + declare -a DIRS + for FILE in "$@" + do + DIRS+=($(dirname "$FILE")) + done + for DIR in $(printf "%s\n" "${DIRS[@]}" | sort -u) + do + cd $(dirname "$FILE") + terraform providers lock -platform=windows_amd64 -platform=darwin_amd64 -platform=linux_amd64 + cd .. done ' language: system @@ -40,7 +56,7 @@ repos: files: \.tf(vars)?$ exclude: examples - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v3.0.0 + rev: v4.4.0 hooks: - id: check-case-conflict - id: check-json @@ -69,3 +85,5 @@ repos: args: - --markdown-linebreak-ext=md exclude: README.md +ci: + skip: [terraform_docs, terraform_fmt, terraform_tflint, terraform_tfsec, tflock] diff --git a/.tflint.hcl b/.tflint.hcl index 5cba22a..854fb92 100644 --- a/.tflint.hcl +++ b/.tflint.hcl @@ -1,6 +1,5 @@ config { module = true - deep_check = false } rule "terraform_deprecated_interpolation" { @@ -37,7 +36,7 @@ rule "terraform_naming_convention" { } rule "terraform_required_version" { - enabled = true + enabled = false } rule "terraform_required_providers" { diff --git a/LICENSE b/LICENSE index 3fe5c34..c026f1a 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2020 Rhythmic Technologies, Inc. +Copyright (c) 2023 Rhythmic Technologies, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 638759b..38fc659 100644 --- a/README.md +++ b/README.md @@ -1,71 +1,128 @@ # terraform-aws-ec2-single -Template repository for terraform modules. Good for any cloud and any provider. +Module to create a single EC2 instance. -[![tflint](https://github.com/rhythmictech/terraform-aws-ec2-single/workflows/tflint/badge.svg?branch=main&event=push)](https://github.com/rhythmictech/terraform-aws-ec2-single/actions?query=workflow%3Atflint+event%3Apush+branch%3Amain) -[![tfsec](https://github.com/rhythmictech/terraform-aws-ec2-single/workflows/tfsec/badge.svg?branch=main&event=push)](https://github.com/rhythmictech/terraform-aws-ec2-single/actions?query=workflow%3Atfsec+event%3Apush+branch%3Amain) -[![yamllint](https://github.com/rhythmictech/terraform-aws-ec2-single/workflows/yamllint/badge.svg?branch=main&event=push)](https://github.com/rhythmictech/terraform-aws-ec2-single/actions?query=workflow%3Ayamllint+event%3Apush+branch%3Amain) -[![misspell](https://github.com/rhythmictech/terraform-aws-ec2-single/workflows/misspell/badge.svg?branch=main&event=push)](https://github.com/rhythmictech/terraform-aws-ec2-single/actions?query=workflow%3Amisspell+event%3Apush+branch%3Amain) -[![pre-commit-check](https://github.com/rhythmictech/terraform-aws-ec2-single/workflows/pre-commit-check/badge.svg?branch=main&event=push)](https://github.com/rhythmictech/terraform-aws-ec2-single/actions?query=workflow%3Apre-commit-check+event%3Apush+branch%3Amain) +[![tflint](https://github.com/rhythmictech/terraform-aws-ec2-single/workflows/tflint/badge.svg?branch=master&event=push)](https://github.com/rhythmictech/terraform-aws-ec2-single/actions?query=workflow%3Atflint+event%3Apush+branch%3Amaster) +[![tfsec](https://github.com/rhythmictech/terraform-aws-ec2-single/workflows/tfsec/badge.svg?branch=master&event=push)](https://github.com/rhythmictech/terraform-aws-ec2-single/actions?query=workflow%3Atfsec+event%3Apush+branch%3Amaster) +[![yamllint](https://github.com/rhythmictech/terraform-aws-ec2-single/workflows/yamllint/badge.svg?branch=master&event=push)](https://github.com/rhythmictech/terraform-aws-ec2-single/actions?query=workflow%3Ayamllint+event%3Apush+branch%3Amaster) +[![misspell](https://github.com/rhythmictech/terraform-aws-ec2-single/workflows/misspell/badge.svg?branch=master&event=push)](https://github.com/rhythmictech/terraform-aws-ec2-single/actions?query=workflow%3Amisspell+event%3Apush+branch%3Amaster) +[![pre-commit-check](https://github.com/rhythmictech/terraform-aws-ec2-single/workflows/pre-commit-check/badge.svg?branch=master&event=push)](https://github.com/rhythmictech/terraform-aws-ec2-single/actions?query=workflow%3Apre-commit-check+event%3Apush+branch%3Amaster) follow on Twitter + ## Example Here's what using the module will look like ```hcl -module "example" { - source = "rhythmictech/terraform-mycloud-mymodule +module "ec2-pet" { + for_each = local.ec2_pets + + source = "rhythmictech/ec2-single/aws" + version = "1.2.0" + name = each.key + ami_id = lookup(each.value, "ami_id", data.aws_ami.rce_amzn2.id) + create_sg = false + create_ssm = false + env = "ops" + instance_type = each.value.instance_type + security_groups = concat(try(split(",", each.value.security_groups), []), [module.sg-pet["base"].security_group_id, try(module.sg-pet[each.value.role].security_group_id, null)]) + route53_record = each.key + route53_zone_id = data.terraform_remote_state.network.outputs.external_zone_id + ssm_access_arn = data.terraform_remote_state.account.outputs.base_instance_arn + subnet_id = try(local.private_subnet_ids[each.value.subnet], local.private_subnet_ids[0]) + volume_size = each.value.volume_size + volume_type = each.value.volume_type + vpc = data.terraform_remote_state.network.outputs.vpc_id + tags = merge( + local.tags, + { + "Role" = each.value.role, + "Location" = "use1", + "Env" = "ops" + } + ) } ``` -## About -A bit about this module ## Requirements | Name | Version | |------|---------| -| terraform | >= 0.12.26 | -| aws | >= 2.45.0, < 4.0.0 | -| tls | >= 3.1.0, < 4.0.0 | +| [terraform](#requirement\_terraform) | >= 0.12.26 | +| [aws](#requirement\_aws) | >= 2.45.0 | +| [tls](#requirement\_tls) | >= 3.1.0 | ## Providers | Name | Version | |------|---------| -| aws | >= 2.45.0, < 4.0.0 | -| tls | >= 3.1.0, < 4.0.0 | +| [aws](#provider\_aws) | >= 2.45.0 | +| [tls](#provider\_tls) | >= 3.1.0 | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [aws_iam_instance_profile.instance](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_instance_profile) | resource | +| [aws_iam_policy.instance_tags](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | +| [aws_iam_policy.ssm_access](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | +| [aws_iam_role.instance](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | +| [aws_iam_role_policy.instance](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | +| [aws_iam_role_policy_attachment.instance_tags](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | +| [aws_iam_role_policy_attachment.ssm_access](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | +| [aws_iam_role_policy_attachment.ssm_access_arn](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | +| [aws_instance.instance](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance) | resource | +| [aws_key_pair.instance_root](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/key_pair) | resource | +| [aws_route53_record.route53_record](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route53_record) | resource | +| [aws_secretsmanager_secret.instance_root_key](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/secretsmanager_secret) | resource | +| [aws_secretsmanager_secret_version.instance_root_key_value](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/secretsmanager_secret_version) | resource | +| [aws_security_group.instance](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group) | resource | +| [tls_private_key.instance_root](https://registry.terraform.io/providers/hashicorp/tls/latest/docs/resources/private_key) | resource | +| [aws_iam_policy_document.instance_sts_assume_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_iam_policy_document.instance_tags](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_iam_policy_document.ssm_access](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | ## Inputs | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| ami\_id | ID of the AMI to use when creating this instance. | `string` | n/a | yes | -| env | Name of the environment the Instance will be in. | `string` | n/a | yes | -| instance\_type | AWS Instance type, i.e. t3.small. | `string` | n/a | yes | -| name | Moniker to apply to all resources in the module. | `string` | n/a | yes | -| security\_groups | Security Group IDs to attach to the instance. | `list(string)` | n/a | yes | -| subnet\_id | ID of the subnet in which to create the instance. | `string` | n/a | yes | -| volume\_size | Size of the attached volume for this instance. | `number` | n/a | yes | -| volume\_type | Type of storage for the instance attached volume. | `string` | n/a | yes | -| vpc | VPC ID to create the instance in. | `string` | n/a | yes | -| create | Whether or not this instance should be created. Unfortunately needed for TF < 0.13. | `bool` | `true` | no | -| create\_keypair | Whether or not to associate an SSH Keypair with this instance. If this is false and no external\_keypair is defined, no key will be associated with the instance. | `bool` | `false` | no | -| external\_keypair | Name of an external SSH Keypair to associate with this instance. If create\_keypair is false and this is left null, no keypair will be associated with the instance. | `string` | `null` | no | -| instance\_ip | Private IP to assign to the instance, if desired. | `string` | `null` | no | -| tags | User-Defined tags. | `map(string)` | `{}` | no | -| use\_ssm | Whether or not to associate an IAM managed policy to allow SSM access to the instance. | `bool` | `true` | no | -| userdata\_script | Userdata script to execute when provisioning the instance. | `string` | `null` | no | +| [ami\_id](#input\_ami\_id) | ID of the AMI to use when creating this instance. | `string` | n/a | yes | +| [create](#input\_create) | Whether or not this instance should be created. Unfortunately needed for TF < 0.13. | `bool` | `true` | no | +| [create\_keypair](#input\_create\_keypair) | Whether or not to associate an SSH Keypair with this instance. If this is false and no external\_keypair is defined, no key will be associated with the instance. | `bool` | `false` | no | +| [create\_sg](#input\_create\_sg) | Whether or not to create and associate a security group for the instance. | `bool` | `true` | no | +| [create\_ssm](#input\_create\_ssm) | Whether or not to create and associate an IAM managed policy to allow SSM access to the instance. | `bool` | `true` | no | +| [ebs\_block\_device](#input\_ebs\_block\_device) | Additional EBS block devices to attach to the instance | `list(map(string))` | `[]` | no | +| [env](#input\_env) | Name of the environment the Instance will be in. | `string` | n/a | yes | +| [external\_keypair](#input\_external\_keypair) | Name of an external SSH Keypair to associate with this instance. If create\_keypair is false and this is left null, no keypair will be associated with the instance. | `string` | `null` | no | +| [instance\_ip](#input\_instance\_ip) | Private IP to assign to the instance, if desired. | `string` | `null` | no | +| [instance\_type](#input\_instance\_type) | AWS Instance type, i.e. t3.small. | `string` | n/a | yes | +| [name](#input\_name) | Moniker to apply to all resources in the module. | `string` | n/a | yes | +| [route53\_record](#input\_route53\_record) | Route53 record to point to EC2 instance. | `string` | n/a | yes | +| [route53\_zone\_id](#input\_route53\_zone\_id) | Route53 zone ID for the route53\_record. | `string` | n/a | yes | +| [security\_groups](#input\_security\_groups) | Security Group IDs to attach to the instance. | `list(string)` | n/a | yes | +| [ssm\_access\_arn](#input\_ssm\_access\_arn) | Whether or not to associate a pre-created IAM managed policy to allow SSM access to the instance. | `string` | `""` | no | +| [subnet\_id](#input\_subnet\_id) | ID of the subnet in which to create the instance. | `string` | n/a | yes | +| [tags](#input\_tags) | User-Defined tags. | `map(string)` | `{}` | no | +| [userdata\_script](#input\_userdata\_script) | Userdata script to execute when provisioning the instance. | `string` | `null` | no | +| [volume\_iops](#input\_volume\_iops) | IOPS to allocate to the instance's base drive. Only applicable when volume\_type is io1, io2 or gp3. | `number` | `null` | no | +| [volume\_size](#input\_volume\_size) | Size of the attached volume for this instance. | `number` | n/a | yes | +| [volume\_throughput](#input\_volume\_throughput) | Value in MiB/s for throughput on instance volume. Only applicable when volume\_type is gp3. | `number` | `null` | no | +| [volume\_type](#input\_volume\_type) | Type of storage for the instance attached volume. | `string` | n/a | yes | +| [vpc](#input\_vpc) | VPC ID to create the instance in. | `string` | n/a | yes | ## Outputs | Name | Description | |------|-------------| -| iam\_role\_arn | ARN of the IAM Role generated for this instance | -| iam\_role\_name | Name of the IAM Role generated for this instance | -| instance\_id | ID of the instance created | -| instance\_sg\_id | ID of the instance created | -| private\_ip | private ip assigned to this instance | - +| [iam\_role\_arn](#output\_iam\_role\_arn) | ARN of the IAM Role generated for this instance | +| [iam\_role\_name](#output\_iam\_role\_name) | Name of the IAM Role generated for this instance | +| [instance\_id](#output\_instance\_id) | ID of the instance created | +| [instance\_sg\_id](#output\_instance\_sg\_id) | ID of the instance created | +| [private\_ip](#output\_private\_ip) | private ip assigned to this instance | ## The Giants Underneath this Module diff --git a/bin/install-macos.sh b/bin/install-macos.sh index 4bc710b..3800165 100755 --- a/bin/install-macos.sh +++ b/bin/install-macos.sh @@ -14,5 +14,4 @@ git config --global init.templateDir ~/.git-template pre-commit init-templatedir ~/.git-template echo 'installing terraform with tfenv' -tfenv install min-required -tfenv use min-required +tfenv install diff --git a/bin/install-ubuntu.sh b/bin/install-ubuntu.sh index 355de0b..670d0b9 100755 --- a/bin/install-ubuntu.sh +++ b/bin/install-ubuntu.sh @@ -3,9 +3,19 @@ echo 'installing dependencies' sudo apt install python3-pip gawk &&\ pip3 install pre-commit -curl -L "$(curl -s https://api.github.com/repos/segmentio/terraform-docs/releases/latest | grep -o -E "https://.+?-linux-amd64")" > terraform-docs && chmod +x terraform-docs && sudo mv terraform-docs /usr/bin/ -curl -L "$(curl -s https://api.github.com/repos/terraform-linters/tflint/releases/latest | grep -o -E "https://.+?_linux_amd64.zip")" > tflint.zip && unzip tflint.zip && rm tflint.zip && sudo mv tflint /usr/bin/ -env GO111MODULE=on go get -u github.com/liamg/tfsec/cmd/tfsec + +# terraform docs +mkdir tmp +cd tmp +curl -Lo ./terraform-docs.tar.gz https://github.com/terraform-docs/terraform-docs/releases/download/v0.16.0/terraform-docs-v0.16.0-$(uname)-amd64.tar.gz +tar -xzf terraform-docs.tar.gz +chmod +x terraform-docs +sudo mv terraform-docs /usr/bin/ +cd .. +rm -rf tmp + +curl -L "$(curl -sL https://api.github.com/repos/terraform-linters/tflint/releases/latest | grep -o -E "https://.+?_linux_amd64.zip")" > tflint.zip && unzip tflint.zip && rm tflint.zip && sudo mv tflint /usr/bin/ +go install github.com/aquasecurity/tfsec/cmd/tfsec@latest git clone https://github.com/tfutils/tfenv.git ~/.tfenv || true mkdir -p ~/.local/bin/ . ~/.profile @@ -19,5 +29,4 @@ git config --global init.templateDir ~/.git-template pre-commit init-templatedir ~/.git-template echo 'installing terraform with tfenv' -tfenv install min-required -tfenv use min-required +tfenv install diff --git a/main.tf b/main.tf index 017110b..d3389e6 100644 --- a/main.tf +++ b/main.tf @@ -78,7 +78,7 @@ data "aws_iam_policy_document" "ssm_access" { statement { sid = "ManageWithSSM" effect = "Allow" - resources = ["*"] + resources = ["*"] #tfsec:ignore:aws-iam-no-policy-wildcards actions = [ "ec2messages:AcknowledgeMessage", @@ -102,7 +102,7 @@ data "aws_iam_policy_document" "ssm_access" { statement { sid = "SessionManagerAccess" effect = "Allow" - resources = ["*"] + resources = ["*"] #tfsec:ignore:aws-iam-no-policy-wildcards actions = [ "s3:GetEncryptionConfiguration", @@ -193,6 +193,8 @@ resource "aws_secretsmanager_secret_version" "instance_root_key_value" { ########################################## # Instance Definition ########################################## + +#tfsec:ignore:aws-ec2-enforce-http-token-imds resource "aws_instance" "instance" { count = var.create ? 1 : 0 ami = var.ami_id diff --git a/terraform-docs b/terraform-docs deleted file mode 100644 index e69de29..0000000 diff --git a/versions.tf b/versions.tf index 5b6d761..31e31aa 100644 --- a/versions.tf +++ b/versions.tf @@ -4,12 +4,12 @@ terraform { required_providers { aws = { source = "hashicorp/aws" - version = ">= 2.45.0, < 4.0.0" + version = ">= 2.45.0" } tls = { source = "hashicorp/tls" - version = ">= 3.1.0, < 4.0.0" + version = ">= 3.1.0" } } }