From 5462652280034474ad778205bc63c357850ac79b Mon Sep 17 00:00:00 2001 From: miguelhar <98769216+miguelhar@users.noreply.github.com> Date: Wed, 29 Jun 2022 17:58:04 -0400 Subject: [PATCH 01/17] Initial commit --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 923db1d4..d28bd19a 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,2 @@ # terraform-aws-eks -Terraform module for deploying a Domino on EKS +Terraform module to deploy EKS on AWS From 62b3e6ffa2b0dea9724f1f2614383c760e8366d7 Mon Sep 17 00:00:00 2001 From: Miguel Harmant Date: Wed, 29 Jun 2022 18:10:03 -0400 Subject: [PATCH 02/17] PLAT-4955 Terraform EKS module initial commit --- .gitignore | 4 +- .pre-commit-config.yaml | 41 + .tflint.hcl | 6 + README.md | 121 +- example/README.md | 33 + example/main.tf | 16 + example/outputs.tf | 4 + example/variables.tf | 0 example/versions.tf | 3 + main.tf | 123 + outputs.tf | 29 + submodules/bastion/README.md | 58 + submodules/bastion/main.tf | 160 + submodules/bastion/outputs.tf | 9 + submodules/bastion/variables.tf | 62 + submodules/bastion/versions.tf | 10 + submodules/eks/README.md | 100 + submodules/eks/cluster.tf | 108 + submodules/eks/eks-bastion-access.tf | 65 + submodules/eks/iam.tf | 320 ++ submodules/eks/main.tf | 198 + submodules/eks/node-group.tf | 311 ++ submodules/eks/outputs.tf | 30 + submodules/eks/templates/linux_custom.tpl | 12 + submodules/eks/variables.tf | 122 + submodules/eks/versions.tf | 14 + submodules/k8s/README.md | 54 + submodules/k8s/main.tf | 93 + submodules/k8s/outputs.tf | 4 + submodules/k8s/templates/aws-auth.yaml.tftpl | 20 + .../docker-repo-creds-secret.yaml.tftpl | 12 + .../k8s/templates/ebs-storageclass.yaml.tftpl | 12 + .../efs-persistent-volume-claim.yaml.tftpl | 15 + .../efs-persistent-volume.yaml.tftpl | 18 + .../k8s/templates/efs-storageclass.yaml.tftpl | 9 + .../k8s/templates/k8s-functions.sh.tftpl | 68 + .../k8s/templates/k8s-pre-setup.sh.tftpl | 17 + .../k8s/templates/k8s-pre-setup.sh.tftpl.back | 172 + submodules/k8s/variables.tf | 67 + submodules/k8s/versions.tf | 17 + submodules/network/README.md | 62 + submodules/network/internet-gateway.tf | 20 + submodules/network/main.tf | 0 submodules/network/nat-gateway.tf | 8 + submodules/network/outputs.tf | 32 + submodules/network/route-tables.tf | 47 + submodules/network/subnets.tf | 31 + submodules/network/variables.tf | 65 + submodules/network/versions.tf | 10 + submodules/network/vpc.tf | 86 + submodules/storage/README.md | 69 + submodules/storage/efs.tf | 56 + submodules/storage/main.tf | 41 + submodules/storage/outputs.tf | 17 + submodules/storage/s3.tf | 472 ++ submodules/storage/variables.tf | 42 + submodules/storage/versions.tf | 10 + submodules/subnets-cidr/README.md | 53 + submodules/subnets-cidr/main.tf | 40 + submodules/subnets-cidr/outputs.tf | 25 + submodules/subnets-cidr/variables.tf | 68 + submodules/subnets-cidr/versions.tf | 3 + terraform_tflint.txt | 0 terraform_tfsec.txt | 4630 +++++++++++++++++ variables.tf | 137 + versions.tf | 22 + 66 files changed, 8581 insertions(+), 2 deletions(-) create mode 100644 .pre-commit-config.yaml create mode 100644 .tflint.hcl create mode 100644 example/README.md create mode 100755 example/main.tf create mode 100644 example/outputs.tf create mode 100644 example/variables.tf create mode 100644 example/versions.tf create mode 100644 main.tf create mode 100755 outputs.tf create mode 100644 submodules/bastion/README.md create mode 100644 submodules/bastion/main.tf create mode 100644 submodules/bastion/outputs.tf create mode 100644 submodules/bastion/variables.tf create mode 100644 submodules/bastion/versions.tf create mode 100644 submodules/eks/README.md create mode 100755 submodules/eks/cluster.tf create mode 100644 submodules/eks/eks-bastion-access.tf create mode 100644 submodules/eks/iam.tf create mode 100644 submodules/eks/main.tf create mode 100644 submodules/eks/node-group.tf create mode 100644 submodules/eks/outputs.tf create mode 100644 submodules/eks/templates/linux_custom.tpl create mode 100755 submodules/eks/variables.tf create mode 100644 submodules/eks/versions.tf create mode 100644 submodules/k8s/README.md create mode 100644 submodules/k8s/main.tf create mode 100644 submodules/k8s/outputs.tf create mode 100644 submodules/k8s/templates/aws-auth.yaml.tftpl create mode 100644 submodules/k8s/templates/docker-repo-creds-secret.yaml.tftpl create mode 100644 submodules/k8s/templates/ebs-storageclass.yaml.tftpl create mode 100644 submodules/k8s/templates/efs-persistent-volume-claim.yaml.tftpl create mode 100644 submodules/k8s/templates/efs-persistent-volume.yaml.tftpl create mode 100644 submodules/k8s/templates/efs-storageclass.yaml.tftpl create mode 100644 submodules/k8s/templates/k8s-functions.sh.tftpl create mode 100644 submodules/k8s/templates/k8s-pre-setup.sh.tftpl create mode 100644 submodules/k8s/templates/k8s-pre-setup.sh.tftpl.back create mode 100755 submodules/k8s/variables.tf create mode 100644 submodules/k8s/versions.tf create mode 100644 submodules/network/README.md create mode 100644 submodules/network/internet-gateway.tf create mode 100644 submodules/network/main.tf create mode 100644 submodules/network/nat-gateway.tf create mode 100644 submodules/network/outputs.tf create mode 100644 submodules/network/route-tables.tf create mode 100644 submodules/network/subnets.tf create mode 100644 submodules/network/variables.tf create mode 100644 submodules/network/versions.tf create mode 100644 submodules/network/vpc.tf create mode 100644 submodules/storage/README.md create mode 100644 submodules/storage/efs.tf create mode 100644 submodules/storage/main.tf create mode 100644 submodules/storage/outputs.tf create mode 100644 submodules/storage/s3.tf create mode 100755 submodules/storage/variables.tf create mode 100644 submodules/storage/versions.tf create mode 100644 submodules/subnets-cidr/README.md create mode 100644 submodules/subnets-cidr/main.tf create mode 100644 submodules/subnets-cidr/outputs.tf create mode 100644 submodules/subnets-cidr/variables.tf create mode 100644 submodules/subnets-cidr/versions.tf create mode 100644 terraform_tflint.txt create mode 100644 terraform_tfsec.txt create mode 100755 variables.tf create mode 100644 versions.tf diff --git a/.gitignore b/.gitignore index 7a3e2fd0..09516a59 100644 --- a/.gitignore +++ b/.gitignore @@ -1,10 +1,12 @@ # Local .terraform directories **/.terraform/* - +**/resources/* # .tfstate files *.tfstate *.tfstate.* +**.terraform.lock.hcl* +**.terraform.lock.hcl # Crash log files crash.log diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 00000000..b9b2e1fe --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,41 @@ +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.3.0 + hooks: + - id: check-merge-conflict + - id: end-of-file-fixer + - id: no-commit-to-branch + - id: check-case-conflict + - repo: https://github.com/antonbabenko/pre-commit-terraform + rev: v1.74.1 + hooks: + - id: terraform_docs + args: + - '--hook-config=--path-to-file=README.md' + - '--hook-config=--add-to-existing-file=true' + - '--hook-config=--create-file-if-not-exist=true' + - '--hook-config=--recursive.enabled=true' + - '--hook-config=--recursive.path=submodules' + - id: terraform_fmt + - id: terraform_tflint + args: + - '--args=--config=__GIT_WORKING_DIR__/.tflint.hcl' + - '--args=--only=terraform_deprecated_interpolation' + - '--args=--only=terraform_deprecated_index' + - '--args=--only=terraform_unused_declarations' + - '--args=--only=terraform_comment_syntax' + - '--args=--only=terraform_documented_outputs' + - '--args=--only=terraform_documented_variables' + - '--args=--only=terraform_typed_variables' + - '--args=--only=terraform_module_pinned_source' + - '--args=--only=terraform_naming_convention' + - '--args=--only=terraform_required_version' + - '--args=--only=terraform_required_providers' + - '--args=--only=terraform_standard_module_structure' + - '--args=--only=terraform_workspace_remote' + - id: terraform_validate + - id: terrascan + args: + - '--args=--non-recursive' + - '--args=--policy-type=aws' + - '--args=--skip-rules=AC_AWS_0369' #Flow logs are enabled, terrascan does not follow the logical path of the resource diff --git a/.tflint.hcl b/.tflint.hcl new file mode 100644 index 00000000..6abb90f9 --- /dev/null +++ b/.tflint.hcl @@ -0,0 +1,6 @@ +plugin "aws" { + enabled = true + deep_check = true + version = "0.14.0" + source = "github.com/terraform-linters/tflint-ruleset-aws" +} diff --git a/README.md b/README.md index d28bd19a..bf88f732 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,121 @@ # terraform-aws-eks -Terraform module to deploy EKS on AWS + +## Create terraform remote state bucket +* Authenticate with aws, make sure that environment variables: `AWS_REGION`, `AWS_ACCESS_KEY_ID` ,`AWS_SECRET_ACCESS_KEY` are set. If your account has MFA set up you will also need `AWS_SESSION_TOKEN`. + +### Prerequisites +* [awscli](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) +* jq (Optional, it parses the api response) + +#### 1. Create Bucket(if you already have a bucket just set the `AWS_TERRAFORM_REMOTE_STATE_BUCKET` to its name, and skip this step): +```bash +export AWS_ACCOUNT="$(aws sts get-caller-identity | jq -r .Account)" +export AWS_TERRAFORM_REMOTE_STATE_BUCKET="domino-terraform-rs-${AWS_ACCOUNT}-${AWS_REGION}" + +aws s3api create-bucket \ + --bucket "${AWS_TERRAFORM_REMOTE_STATE_BUCKET}" \ + --region ${AWS_REGION} \ + --create-bucket-configuration LocationConstraint="${AWS_REGION}" | jq . +``` + +#### Verify bucket exists + +```bash +aws s3api head-bucket --bucket "${AWS_TERRAFORM_REMOTE_STATE_BUCKET}" +``` +You should NOT see an error. + +## 2. Initialize the terraform remote-state + +```bash +### Set the deploy id. This will be used later as well. +export TF_VAR_deploy_id="mh-tf-test" ## <-- Feel free to rename. +terraform init \ + -backend-config="bucket=${AWS_TERRAFORM_REMOTE_STATE_BUCKET}" \ + -backend-config="key=domino-eks/${TF_VAR_deploy_id}" \ + -backend-config="region=${AWS_REGION}" + +``` + + + +## If you need to delete the bucket + +```bash + +aws s3 rb s3://"${AWS_TERRAFORM_REMOTE_STATE_BUCKET}" --force +``` + +# Terraform-docs + + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.0 | +| [aws](#requirement\_aws) | >= 4.0 | +| [local](#requirement\_local) | >= 2.2.0 | +| [tls](#requirement\_tls) | >= 3.4.0 | + +## Providers + +| Name | Version | +|------|---------| +| [aws](#provider\_aws) | 4.22.0 | +| [local](#provider\_local) | 2.2.3 | +| [tls](#provider\_tls) | 3.4.0 | + +## Modules + +| Name | Source | Version | +|------|--------|---------| +| [bastion](#module\_bastion) | ./submodules/bastion | n/a | +| [eks](#module\_eks) | ./submodules/eks | n/a | +| [k8s\_setup](#module\_k8s\_setup) | ./submodules/k8s | n/a | +| [network](#module\_network) | ./submodules/network | n/a | +| [storage](#module\_storage) | ./submodules/storage | n/a | +| [subnets\_cidr](#module\_subnets\_cidr) | ./submodules/subnets-cidr | n/a | + +## Resources + +| Name | Type | +|------|------| +| [aws_key_pair.domino](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/key_pair) | resource | +| [local_sensitive_file.pvt_key](https://registry.terraform.io/providers/hashicorp/local/latest/docs/resources/sensitive_file) | resource | +| [tls_private_key.domino](https://registry.terraform.io/providers/hashicorp/tls/latest/docs/resources/private_key) | resource | +| [aws_availability_zones.available](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/availability_zones) | data source | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [availability\_zones](#input\_availability\_zones) | List of Availibility zones to distribute the deployment, EKS needs at least 2,https://docs.aws.amazon.com/eks/latest/userguide/network_reqs.html. | `list(string)` | `[]` | no | +| [base\_cidr\_block](#input\_base\_cidr\_block) | CIDR block to serve the main private and public subnets. | `string` | `"10.0.0.0/16"` | no | +| [create\_bastion](#input\_create\_bastion) | Create bastion toggle. | `bool` | `false` | no | +| [deploy\_id](#input\_deploy\_id) | Domino Deployment ID. | `string` | `"domino-eks"` | no | +| [efs\_access\_point\_path](#input\_efs\_access\_point\_path) | Filesystem path for efs. | `string` | `"/domino"` | no | +| [eks\_master\_role\_names](#input\_eks\_master\_role\_names) | IAM role names to be added as masters in eks. | `list(string)` | `[]` | no | +| [enable\_route53\_iam\_policy](#input\_enable\_route53\_iam\_policy) | Enable route53 IAM policy toggle. | `bool` | `false` | no | +| [k8s\_version](#input\_k8s\_version) | EKS cluster k8s version. | `string` | `"1.22"` | no | +| [node\_groups](#input\_node\_groups) | EKS managed node groups definition. | `map(map(any))` |
{
"compute": {
"desired": 1,
"instance_type": "m5.2xlarge",
"max": 10,
"min": 0
},
"gpu": {
"desired": 1,
"instance_type": "g4dn.xlarge",
"max": 10,
"min": 0
},
"platform": {
"desired": 1,
"instance_type": "m5.4xlarge",
"max": 10,
"min": 0
}
}
| no | +| [number\_of\_azs](#input\_number\_of\_azs) | Number of AZ to distribute the deployment, EKS needs at least 2. | `number` | `3` | no | +| [private\_cidr\_network\_bits](#input\_private\_cidr\_network\_bits) | Number of network bits to allocate to the public subnet. i.e /19 -> 8,190 IPs. | `number` | `19` | no | +| [public\_cidr\_network\_bits](#input\_public\_cidr\_network\_bits) | Number of network bits to allocate to the public subnet. i.e /27 -> 30 IPs. | `number` | `27` | no | +| [region](#input\_region) | AWS region for the deployment | `string` | n/a | yes | +| [route53\_hosted\_zone](#input\_route53\_hosted\_zone) | AWS Route53 Hosted zone. | `string` | n/a | yes | +| [ssh\_pvt\_key\_name](#input\_ssh\_pvt\_key\_name) | ssh private key filename. | `string` | `"domino.pem"` | no | +| [tags](#input\_tags) | Deployment tags. | `map(string)` | `{}` | no | +| [vpc\_id](#input\_vpc\_id) | VPC ID for bringing your own vpc, will bypass creation of such. | `string` | `""` | no | + +## Outputs + +| Name | Description | +|------|-------------| +| [deploy\_id](#output\_deploy\_id) | Deployment ID. | +| [efs\_filesystem\_id](#output\_efs\_filesystem\_id) | EFS volume handle :: | +| [hostname](#output\_hostname) | Domino instance URL. | +| [k8s\_tunnel\_command](#output\_k8s\_tunnel\_command) | Command to run the k8s tunnel mallory. | +| [region](#output\_region) | Deployment region. | +| [ssh\_bastion\_command](#output\_ssh\_bastion\_command) | Command to ssh into the bastion host | + diff --git a/example/README.md b/example/README.md new file mode 100644 index 00000000..6c312e6d --- /dev/null +++ b/example/README.md @@ -0,0 +1,33 @@ +# example + + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.0 | + +## Providers + +No providers. + +## Modules + +| Name | Source | Version | +|------|--------|---------| +| [domino\_eks](#module\_domino\_eks) | ../../terraform-aws-eks | n/a | + +## Resources + +No resources. + +## Inputs + +No inputs. + +## Outputs + +| Name | Description | +|------|-------------| +| [domino\_eks](#output\_domino\_eks) | EKS module outputs | + diff --git a/example/main.tf b/example/main.tf new file mode 100755 index 00000000..acb46795 --- /dev/null +++ b/example/main.tf @@ -0,0 +1,16 @@ +module "domino_eks" { + source = "../../terraform-aws-eks" + deploy_id = "mhtfeks" + region = "us-west-2" + number_of_azs = 2 + route53_hosted_zone = "infra-team-sandbox.domino.tech" + eks_master_role_names = ["okta-poweruser", "okta-fulladmin"] + create_bastion = true + enable_route53_iam_policy = true + tags = { + deploy_id = "domino-eks" + deploy_tag = "domino-eks" + deploy_type = "terraform-aws-eks" + domino-deploy-id = "domino-eks" + } +} diff --git a/example/outputs.tf b/example/outputs.tf new file mode 100644 index 00000000..b14d2084 --- /dev/null +++ b/example/outputs.tf @@ -0,0 +1,4 @@ +output "domino_eks" { + description = "EKS module outputs" + value = module.domino_eks +} diff --git a/example/variables.tf b/example/variables.tf new file mode 100644 index 00000000..e69de29b diff --git a/example/versions.tf b/example/versions.tf new file mode 100644 index 00000000..7117131f --- /dev/null +++ b/example/versions.tf @@ -0,0 +1,3 @@ +terraform { + required_version = ">= 1.0" +} diff --git a/main.tf b/main.tf new file mode 100644 index 00000000..bd4c375e --- /dev/null +++ b/main.tf @@ -0,0 +1,123 @@ +resource "tls_private_key" "domino" { + algorithm = "RSA" +} + + +resource "aws_key_pair" "domino" { + key_name = var.deploy_id + public_key = trimspace(tls_private_key.domino.public_key_openssh) +} + +resource "local_sensitive_file" "pvt_key" { + content = tls_private_key.domino.private_key_openssh + file_permission = "0400" + filename = local.ssh_pvt_key_path +} + + +data "aws_availability_zones" "available" { + state = "available" + filter { + name = "region-name" + values = [var.region] + } +} + +locals { + availability_zones_data = zipmap(data.aws_availability_zones.available.names, data.aws_availability_zones.available.zone_ids) + ## EKS needs at least 2 availability zones: https://docs.aws.amazon.com/eks/latest/userguide/network_reqs.html + availability_zone_names = length(var.availability_zones) >= 2 ? toset(var.availability_zones) : toset(slice(keys(local.availability_zones_data), 0, var.number_of_azs)) + availability_zone_ids = [for name in local.availability_zone_names : local.availability_zones_data[name]] + availability_zones = zipmap(local.availability_zone_names, local.availability_zone_ids) + bastion_user = "ec2-user" + ssh_pvt_key_path = "resources/${var.deploy_id}/${var.ssh_pvt_key_name}" + kubeconfig_path = "resources/${var.deploy_id}/kubeconfig" +} + +module "subnets_cidr" { + source = "./submodules/subnets-cidr" + availability_zones = local.availability_zones + base_cidr_block = var.base_cidr_block + public_cidr_network_bits = var.public_cidr_network_bits + private_cidr_network_bits = var.private_cidr_network_bits + subnet_name_prefix = var.deploy_id +} + +module "network" { + source = "./submodules/network" + region = var.region + public_subnets = module.subnets_cidr.public_subnets + private_subnets = module.subnets_cidr.private_subnets + deploy_id = var.deploy_id + base_cidr_block = var.base_cidr_block + vpc_id = var.vpc_id + monitoring_s3_bucket_arn = module.storage.monitoring_s3_bucket_arn + tags = var.tags +} + +locals { + public_subnets = module.network.public_subnets + private_subnets = module.network.private_subnets +} + + +module "storage" { + source = "./submodules/storage" + deploy_id = var.deploy_id + efs_access_point_path = var.efs_access_point_path + route53_hosted_zone = var.route53_hosted_zone + subnets = [for s in local.private_subnets : { + name = s.name + id = s.id + cidr_block = s.cidr_block + }] + vpc_id = module.network.vpc_id + tags = var.tags +} + +module "bastion" { + count = var.create_bastion ? 1 : 0 + + source = "./submodules/bastion" + region = var.region + vpc_id = module.network.vpc_id + deploy_id = var.deploy_id + ssh_pvt_key_name = aws_key_pair.domino.key_name + bastion_public_subnet_id = local.public_subnets[0].id + tags = var.tags +} + +module "eks" { + source = "./submodules/eks" + region = var.region + k8s_version = var.k8s_version + vpc_id = module.network.vpc_id + deploy_id = var.deploy_id + private_subnets = local.private_subnets + ssh_pvt_key_name = aws_key_pair.domino.key_name + route53_hosted_zone = var.route53_hosted_zone + bastion_security_group_id = try(module.bastion[0].security_group_id, "") + create_bastion_sg = var.create_bastion + enable_route53_iam_policy = var.enable_route53_iam_policy + kubeconfig_path = local.kubeconfig_path + node_groups = var.node_groups + s3_buckets = module.storage.s3_buckets + tags = var.tags +} + + +module "k8s_setup" { + source = "./submodules/k8s" + deploy_id = var.deploy_id + ssh_pvt_key_name = abspath(local.ssh_pvt_key_path) + bastion_user = local.bastion_user + bastion_public_ip = try(module.bastion[0].public_ip, "") + k8s_cluster_endpoint = module.eks.cluster_endpoint + managed_nodes_role_arns = module.eks.managed_nodes_role_arns + eks_master_role_names = concat(var.eks_master_role_names, module.eks.eks_master_role_name) + kubeconfig_path = local.kubeconfig_path + depends_on = [ + module.eks, + module.bastion + ] +} diff --git a/outputs.tf b/outputs.tf new file mode 100755 index 00000000..bcd2474b --- /dev/null +++ b/outputs.tf @@ -0,0 +1,29 @@ +output "ssh_bastion_command" { + description = "Command to ssh into the bastion host" + value = "ssh -i ${local.ssh_pvt_key_path} -oUserKnownHostsFile=/dev/null -oStrictHostKeyChecking=no ${local.bastion_user}@${module.bastion[0].public_ip}" +} + +output "k8s_tunnel_command" { + description = "Command to run the k8s tunnel mallory." + value = module.k8s_setup.k8s_tunnel_command +} + +output "hostname" { + description = "Domino instance URL." + value = "${var.deploy_id}.${var.route53_hosted_zone}" +} + +output "efs_filesystem_id" { + description = "EFS volume handle ::" + value = module.storage.efs_volume_handle +} + +output "region" { + description = "Deployment region." + value = var.region +} + +output "deploy_id" { + description = "Deployment ID." + value = var.deploy_id +} diff --git a/submodules/bastion/README.md b/submodules/bastion/README.md new file mode 100644 index 00000000..6afbdc2b --- /dev/null +++ b/submodules/bastion/README.md @@ -0,0 +1,58 @@ +# bastion + + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.0 | +| [aws](#requirement\_aws) | >= 4.0 | + +## Providers + +| Name | Version | +|------|---------| +| [aws](#provider\_aws) | 4.22.0 | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [aws_eip.bastion](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eip) | resource | +| [aws_iam_instance_profile.bastion](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_instance_profile) | resource | +| [aws_iam_policy.bastion_assume_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | +| [aws_iam_role.bastion](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | +| [aws_iam_role_policy_attachment.bastion](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | +| [aws_iam_role_policy_attachment.bastion_assume_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | +| [aws_instance.bastion](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance) | resource | +| [aws_security_group.bastion](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group) | resource | +| [aws_security_group_rule.bastion](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource | +| [aws_ami.amazon_linux_2](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ami) | data source | +| [aws_caller_identity.aws_account](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | +| [aws_iam_policy_document.bastion](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_iam_policy_document.bastion_assume_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_partition.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/partition) | data source | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [bastion\_public\_subnet\_id](#input\_bastion\_public\_subnet\_id) | Public subnet to create bastion host in. | `string` | n/a | yes | +| [bastion\_security\_group\_rules](#input\_bastion\_security\_group\_rules) | Bastion host security group rules. | `map(any)` |
{
"bastion_inbound_ssh": {
"cidr_blocks": [
"0.0.0.0/0"
],
"description": "Inbound ssh",
"from_port": "22",
"protocol": "-1",
"source_security_group_id": null,
"to_port": "22",
"type": "ingress"
},
"bastion_outbound_traffic": {
"cidr_blocks": [
"0.0.0.0/0"
],
"description": "Allow all outbound traffic by default",
"from_port": "0",
"protocol": "-1",
"source_security_group_id": null,
"to_port": "0",
"type": "egress"
}
}
| no | +| [deploy\_id](#input\_deploy\_id) | Domino Deployment ID | `string` | n/a | yes | +| [region](#input\_region) | AWS region for the deployment | `string` | n/a | yes | +| [ssh\_pvt\_key\_name](#input\_ssh\_pvt\_key\_name) | ssh private key filename. | `string` | n/a | yes | +| [tags](#input\_tags) | Deployment tags | `map(string)` | n/a | yes | +| [vpc\_id](#input\_vpc\_id) | VPC ID. | `string` | n/a | yes | + +## Outputs + +| Name | Description | +|------|-------------| +| [public\_ip](#output\_public\_ip) | Bastion host public ip. | +| [security\_group\_id](#output\_security\_group\_id) | Bastion host security group id. | + diff --git a/submodules/bastion/main.tf b/submodules/bastion/main.tf new file mode 100644 index 00000000..fac1a5d0 --- /dev/null +++ b/submodules/bastion/main.tf @@ -0,0 +1,160 @@ +data "aws_partition" "current" {} +data "aws_caller_identity" "aws_account" {} + +locals { + dns_suffix = data.aws_partition.current.dns_suffix + aws_account_id = data.aws_caller_identity.aws_account.account_id +} + + +resource "aws_security_group" "bastion" { + name = "${var.deploy_id}-bastion" + description = "Bastion security group" + vpc_id = var.vpc_id + + lifecycle { + create_before_destroy = true + } + + tags = merge({ "Name" = "${var.deploy_id}-bastion" }, var.tags) +} +resource "aws_security_group_rule" "bastion" { + for_each = var.bastion_security_group_rules + + security_group_id = aws_security_group.bastion.id + protocol = each.value.protocol + from_port = each.value.from_port + to_port = each.value.to_port + type = each.value.type + description = each.value.description + cidr_blocks = try(each.value.cidr_blocks, null) + source_security_group_id = try(each.value.source_security_group_id, null) +} +## Bastion iam role +data "aws_iam_policy_document" "bastion" { + statement { + actions = ["sts:AssumeRole"] + + principals { + type = "Service" + identifiers = ["ec2.${local.dns_suffix}"] + } + } + + statement { + effect = "Allow" + actions = ["sts:AssumeRole"] + + principals { + type = "AWS" + identifiers = ["arn:aws:iam::${local.aws_account_id}:root"] + } + } +} + +resource "aws_iam_role" "bastion" { + assume_role_policy = data.aws_iam_policy_document.bastion.json + name = "${var.deploy_id}-bastion" + tags = merge({ "Name" = "${var.deploy_id}-bastion" }, var.tags) +} + +resource "aws_iam_role_policy_attachment" "bastion" { + policy_arn = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore" + role = aws_iam_role.bastion.name +} + +resource "aws_iam_instance_profile" "bastion" { + name = "${var.deploy_id}-bastion" + role = aws_iam_role.bastion.name +} + + +data "aws_ami" "amazon_linux_2" { + most_recent = true + owners = ["amazon"] + + filter { + name = "name" + values = ["amzn2-ami-hvm*"] + } +} + +resource "aws_instance" "bastion" { + ami = data.aws_ami.amazon_linux_2.id + associate_public_ip_address = "true" + iam_instance_profile = aws_iam_instance_profile.bastion.name + monitoring = true + + capacity_reservation_specification { + capacity_reservation_preference = "open" + } + + disable_api_termination = "false" + ebs_optimized = "false" + + enclave_options { + enabled = "false" + } + + get_password_data = "false" + hibernation = "false" + instance_initiated_shutdown_behavior = "stop" + instance_type = "t2.micro" + key_name = var.ssh_pvt_key_name + + metadata_options { + http_endpoint = "enabled" + http_put_response_hop_limit = "1" + http_tokens = "required" + instance_metadata_tags = "disabled" + } + + root_block_device { + delete_on_termination = "true" + encrypted = "true" + iops = "3000" + throughput = "125" + volume_size = "40" + volume_type = "gp3" + } + + source_dest_check = "true" + subnet_id = var.bastion_public_subnet_id + + vpc_security_group_ids = [aws_security_group.bastion.id] + tags = merge({ "Name" = "${var.deploy_id}-bastion" }, var.tags) + lifecycle { + ignore_changes = [ + root_block_device[0].tags, + ] + } +} + +resource "aws_eip" "bastion" { + instance = aws_instance.bastion.id + network_border_group = var.region + vpc = "true" + tags = var.tags +} + +data "aws_iam_policy_document" "bastion_assume_role" { + statement { + + effect = "Allow" + resources = [aws_iam_role.bastion.arn] + actions = ["sts:AssumeRole"] + } +} + +resource "aws_iam_policy" "bastion_assume_role" { + name = "${var.deploy_id}-bastion-assume" + + description = "Allows bastion to assume a role" + policy = data.aws_iam_policy_document.bastion_assume_role.json +} + + +resource "aws_iam_role_policy_attachment" "bastion_assume_role" { + policy_arn = aws_iam_policy.bastion_assume_role.arn + role = aws_iam_role.bastion.name +} diff --git a/submodules/bastion/outputs.tf b/submodules/bastion/outputs.tf new file mode 100644 index 00000000..985b3736 --- /dev/null +++ b/submodules/bastion/outputs.tf @@ -0,0 +1,9 @@ +output "security_group_id" { + description = "Bastion host security group id." + value = aws_security_group.bastion.id +} + +output "public_ip" { + description = "Bastion host public ip." + value = aws_eip.bastion.public_ip +} diff --git a/submodules/bastion/variables.tf b/submodules/bastion/variables.tf new file mode 100644 index 00000000..9675fe00 --- /dev/null +++ b/submodules/bastion/variables.tf @@ -0,0 +1,62 @@ +variable "deploy_id" { + type = string + description = "Domino Deployment ID" + + validation { + condition = can(regex("^[a-z-0-9]{3,32}$", var.deploy_id)) + error_message = "Argument deploy_id must: start with a letter, contain lowercase alphanumeric characters(can contain hyphens[-]) with length between 3 and 32 characters." + } +} + +variable "region" { + type = string + description = "AWS region for the deployment" +} + +variable "tags" { + type = map(string) + description = "Deployment tags" +} + +variable "vpc_id" { + type = string + description = "VPC ID." +} + +variable "ssh_pvt_key_name" { + type = string + description = "ssh private key filename." +} + +variable "bastion_public_subnet_id" { + type = string + description = "Public subnet to create bastion host in." +} + +variable "bastion_security_group_rules" { + type = map(any) + + description = "Bastion host security group rules." + + default = { + bastion_outbound_traffic = { + description = "Allow all outbound traffic by default" + protocol = "-1" + from_port = "0" + to_port = "0" + type = "egress" + cidr_blocks = ["0.0.0.0/0"] + source_security_group_id = null + } + bastion_inbound_ssh = { + description = "Inbound ssh" + protocol = "-1" + from_port = "22" + to_port = "22" + type = "ingress" + cidr_blocks = ["0.0.0.0/0"] + source_security_group_id = null + } + } + +} diff --git a/submodules/bastion/versions.tf b/submodules/bastion/versions.tf new file mode 100644 index 00000000..ca6fac6f --- /dev/null +++ b/submodules/bastion/versions.tf @@ -0,0 +1,10 @@ +terraform { + + required_version = ">= 1.0" + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 4.0" + } + } +} diff --git a/submodules/eks/README.md b/submodules/eks/README.md new file mode 100644 index 00000000..bca0db3f --- /dev/null +++ b/submodules/eks/README.md @@ -0,0 +1,100 @@ +# eks + + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.0 | +| [aws](#requirement\_aws) | >= 4.0 | +| [null](#requirement\_null) | >= 3.1.0 | + +## Providers + +| Name | Version | +|------|---------| +| [aws](#provider\_aws) | 4.22.0 | +| [null](#provider\_null) | 3.1.1 | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [aws_eks_addon.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eks_addon) | resource | +| [aws_eks_cluster.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eks_cluster) | resource | +| [aws_eks_node_group.compute](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eks_node_group) | resource | +| [aws_eks_node_group.gpu](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eks_node_group) | resource | +| [aws_eks_node_group.platform](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eks_node_group) | resource | +| [aws_iam_policy.autoscaler](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | +| [aws_iam_policy.domino_ecr_restricted](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | +| [aws_iam_policy.ebs_csi](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | +| [aws_iam_policy.route53](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | +| [aws_iam_policy.s3](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | +| [aws_iam_policy.snapshot](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | +| [aws_iam_role.eks_cluster](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | +| [aws_iam_role.eks_nodes](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | +| [aws_iam_role_policy_attachment.aws_eks_nodes](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | +| [aws_iam_role_policy_attachment.custom_eks_nodes](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | +| [aws_iam_role_policy_attachment.custom_eks_nodes_route53](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | +| [aws_iam_role_policy_attachment.eks_cluster](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | +| [aws_kms_key.eks_cluster](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_key) | resource | +| [aws_launch_template.compute](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/launch_template) | resource | +| [aws_launch_template.gpu](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/launch_template) | resource | +| [aws_launch_template.platform](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/launch_template) | resource | +| [aws_security_group.eks_cluster](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group) | resource | +| [aws_security_group.eks_nodes](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group) | resource | +| [aws_security_group_rule.bastion_eks](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource | +| [aws_security_group_rule.eks](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource | +| [aws_security_group_rule.eks_cluster](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource | +| [aws_security_group_rule.node](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource | +| [null_resource.kubeconfig](https://registry.terraform.io/providers/hashicorp/null/latest/docs/resources/resource) | resource | +| [aws_ami.eks_gpu](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ami) | data source | +| [aws_caller_identity.aws_account](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | +| [aws_iam_policy_document.autoscaler](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_iam_policy_document.domino_ecr_restricted](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_iam_policy_document.ebs_csi](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_iam_policy_document.eks_cluster](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_iam_policy_document.eks_nodes](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_iam_policy_document.kms_key](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_iam_policy_document.route53](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_iam_policy_document.s3](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_iam_policy_document.snapshot](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_partition.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/partition) | data source | +| [aws_route53_zone.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/route53_zone) | data source | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [bastion\_security\_group\_id](#input\_bastion\_security\_group\_id) | Bastion security group id. | `string` | `""` | no | +| [create\_bastion\_sg](#input\_create\_bastion\_sg) | Create bastion access rules toggle. | `bool` | n/a | yes | +| [deploy\_id](#input\_deploy\_id) | Domino Deployment ID | `string` | n/a | yes | +| [eks\_cluster\_addons](#input\_eks\_cluster\_addons) | EKS cluster addons. | `list(string)` |
[
"vpc-cni",
"kube-proxy",
"coredns"
]
| no | +| [eks\_security\_group\_rules](#input\_eks\_security\_group\_rules) | EKS security group rules. | `map(any)` | `{}` | no | +| [enable\_route53\_iam\_policy](#input\_enable\_route53\_iam\_policy) | Enable route53 iam policy toggle. | `bool` | `false` | no | +| [k8s\_version](#input\_k8s\_version) | EKS cluster k8s version. | `string` | `"1.22"` | no | +| [kubeconfig\_path](#input\_kubeconfig\_path) | Kubeconfig filename. | `string` | `"kubeconfig"` | no | +| [node\_groups](#input\_node\_groups) | EKS managed node groups definition | `map(map(any))` |
{
"compute": {
"desired": 1,
"instance_type": "m5.2xlarge",
"max": 10,
"min": 0
},
"gpu": {
"desired": 0,
"instance_type": "g4dn.xlarge",
"max": 10,
"min": 0
},
"platform": {
"desired": 1,
"instance_type": "m5.4xlarge",
"max": 10,
"min": 0
}
}
| no | +| [private\_subnets](#input\_private\_subnets) | Private subnets object |
list(object({
cidr_block = string
name = string
type = string
zone = string
zone_id = string
id = string
}))
| n/a | yes | +| [region](#input\_region) | AWS region for the deployment | `string` | n/a | yes | +| [route53\_hosted\_zone](#input\_route53\_hosted\_zone) | Route53 zone | `string` | n/a | yes | +| [s3\_buckets](#input\_s3\_buckets) | S3 buckets information that the nodegroups need access to |
list(object({
bucket_name = string
arn = string
}))
| n/a | yes | +| [ssh\_pvt\_key\_name](#input\_ssh\_pvt\_key\_name) | ssh private key filename. | `string` | n/a | yes | +| [tags](#input\_tags) | Deployment tags | `map(string)` | n/a | yes | +| [vpc\_id](#input\_vpc\_id) | VPC ID. | `string` | n/a | yes | + +## Outputs + +| Name | Description | +|------|-------------| +| [cluster\_endpoint](#output\_cluster\_endpoint) | EKS cluster API endpoint. | +| [eks\_master\_role\_name](#output\_eks\_master\_role\_name) | EKS master role arns. | +| [hosted\_zone\_id](#output\_hosted\_zone\_id) | DNS hosted zone ID. | +| [managed\_nodes\_role\_arns](#output\_managed\_nodes\_role\_arns) | EKS managed nodes arns. | +| [nodes\_security\_group\_id](#output\_nodes\_security\_group\_id) | EKS managed nodes security group id. | +| [security\_group\_id](#output\_security\_group\_id) | EKS security group id. | + diff --git a/submodules/eks/cluster.tf b/submodules/eks/cluster.tf new file mode 100755 index 00000000..999a66c8 --- /dev/null +++ b/submodules/eks/cluster.tf @@ -0,0 +1,108 @@ +## EKS key +data "aws_iam_policy_document" "kms_key" { + statement { + actions = [ + "kms:Create*", "kms:Describe*", "kms:Enable*", "kms:List*", "kms:Put*", "kms:Update*", "kms:Revoke*", "kms:Disable*", "kms:Get*", "kms:Delete*", "kms:ScheduleKeyDeletion", "kms:CancelKeyDeletion", "kubeconms:GenerateDataKey", "kms:TagResource", "kms:UntagResource" + ] + resources = ["*"] + effect = "Allow" + principals { + type = "AWS" + identifiers = ["arn:aws:iam::${local.aws_account_id}:root"] + } + } +} + +resource "aws_kms_key" "eks_cluster" { + customer_master_key_spec = "SYMMETRIC_DEFAULT" + enable_key_rotation = "true" + is_enabled = "true" + key_usage = "ENCRYPT_DECRYPT" + multi_region = "false" + policy = data.aws_iam_policy_document.kms_key.json + tags = merge({ "Name" = "${var.deploy_id}-eks-cluster" }, var.tags) + +} +## END - EKS key + +## EKS security-group +resource "aws_security_group" "eks_cluster" { + name = "${var.deploy_id}-cluster" + description = "EKS cluster security group" + vpc_id = var.vpc_id + + lifecycle { + create_before_destroy = true + } + tags = merge({ "Name" = "${var.deploy_id}-eks-cluster" }, var.tags) +} + +resource "aws_security_group_rule" "eks_cluster" { + for_each = local.eks_cluster_security_group_rules + + security_group_id = aws_security_group.eks_cluster.id + protocol = each.value.protocol + from_port = each.value.from_port + to_port = each.value.to_port + type = each.value.type + description = each.value.description + cidr_blocks = try(each.value.cidr_blocks, null) + source_security_group_id = try(each.value.source_security_group_id, null) +} + +## END - EKS security-group + +## EKS cluster +resource "aws_eks_cluster" "this" { + name = var.deploy_id + role_arn = aws_iam_role.eks_cluster.arn + enabled_cluster_log_types = ["api", "audit", "authenticator", "controllerManager", "scheduler"] + version = var.k8s_version + tags = var.tags + + encryption_config { + provider { + key_arn = aws_kms_key.eks_cluster.arn + } + resources = ["secrets"] + } + + kubernetes_network_config { + ip_family = "ipv4" + service_ipv4_cidr = "172.20.0.0/16" + } + + + vpc_config { + endpoint_private_access = "true" + endpoint_public_access = "false" + security_group_ids = [aws_security_group.eks_cluster.id] + subnet_ids = [for sb in var.private_subnets : sb.id] + } + depends_on = [aws_iam_role_policy_attachment.eks_cluster] +} + +resource "aws_eks_addon" "this" { + for_each = toset(var.eks_cluster_addons) + cluster_name = aws_eks_cluster.this.name + resolve_conflicts = "OVERWRITE" + addon_name = each.key + + depends_on = [ + aws_eks_node_group.compute, + aws_eks_node_group.platform, + aws_eks_node_group.gpu, + ] + + tags = var.tags +} + +resource "null_resource" "kubeconfig" { + provisioner "local-exec" { + command = "export KUBECONFIG=${var.kubeconfig_path} && aws eks update-kubeconfig --region ${var.region} --name ${aws_eks_cluster.this.name}" + } + triggers = { + domino_eks_cluster_ca = aws_eks_cluster.this.certificate_authority[0].data + } + depends_on = [aws_eks_cluster.this] +} diff --git a/submodules/eks/eks-bastion-access.tf b/submodules/eks/eks-bastion-access.tf new file mode 100644 index 00000000..95f3840b --- /dev/null +++ b/submodules/eks/eks-bastion-access.tf @@ -0,0 +1,65 @@ + +locals { + bastion_eks_security_group_rules = { + bastion_to_eks_api = { + description = "Bastion outbound to eks cluster ${var.deploy_id}:443 API" + protocol = "tcp" + from_port = "443" + to_port = "443" + type = "egress" + security_group_id = var.bastion_security_group_id + source_security_group_id = aws_security_group.eks_cluster.id + } + bastion_to_eks_nodes_ssh = { + description = "Bastion ssh to eks cluster nodes outbound" + protocol = "tcp" + from_port = "22" + to_port = "22" + type = "egress" + security_group_id = var.bastion_security_group_id + source_security_group_id = aws_security_group.eks_nodes.id + } + eks_api_from_bastion = { + description = "Eks cluster ${var.deploy_id}:443 inbound from bastion" + protocol = "tcp" + from_port = "443" + to_port = "443" + type = "ingress" + security_group_id = aws_security_group.eks_cluster.id + source_security_group_id = var.bastion_security_group_id + } + eks_nodes_ssh_from_bastion = { + description = "Bastion ssh to eks cluster nodes inbound" + protocol = "tcp" + from_port = "22" + to_port = "22" + type = "ingress" + security_group_id = var.bastion_security_group_id + source_security_group_id = aws_security_group.eks_nodes.id + } + } +} + +resource "aws_security_group_rule" "bastion_eks" { + for_each = { for k, v in local.bastion_eks_security_group_rules : k => v if var.create_bastion_sg } + + security_group_id = each.value.security_group_id + protocol = each.value.protocol + from_port = each.value.from_port + to_port = each.value.to_port + type = each.value.type + description = each.value.description + source_security_group_id = each.value.source_security_group_id +} + +resource "aws_security_group_rule" "eks" { + for_each = var.eks_security_group_rules + + security_group_id = each.value.security_group_id + protocol = each.value.protocol + from_port = each.value.from_port + to_port = each.value.to_port + type = each.value.type + description = each.value.description + source_security_group_id = each.value.source_security_group_id +} diff --git a/submodules/eks/iam.tf b/submodules/eks/iam.tf new file mode 100644 index 00000000..41571b20 --- /dev/null +++ b/submodules/eks/iam.tf @@ -0,0 +1,320 @@ +## EKS IAM +data "aws_iam_policy_document" "eks_cluster" { + statement { + sid = "EKSClusterAssumeRole" + actions = ["sts:AssumeRole"] + + principals { + type = "Service" + identifiers = ["eks.${local.dns_suffix}"] + } + } +} + +resource "aws_iam_role" "eks_cluster" { + name = "${var.deploy_id}-eks" + assume_role_policy = data.aws_iam_policy_document.eks_cluster.json + tags = var.tags +} + +resource "aws_iam_role_policy_attachment" "eks_cluster" { + policy_arn = "${local.policy_arn_prefix}/AmazonEKSClusterPolicy" + role = aws_iam_role.eks_cluster.name +} + + +## Customer managed policies +data "aws_iam_policy_document" "domino_ecr_restricted" { + statement { + + effect = "Deny" + resources = ["arn:aws:ecr:*:${local.aws_account_id}:*"] + + actions = [ + "ecr:BatchCheckLayerAvailability", + "ecr:BatchGetImage", + "ecr:GetDownloadUrlForLayer", + ] + + condition { + test = "StringNotEqualsIfExists" + variable = "ecr:ResourceTag/domino-deploy-id" + values = [var.deploy_id] + } + } +} + +resource "aws_iam_policy" "domino_ecr_restricted" { + name = "${var.deploy_id}-DominoEcrRestricted" + path = "/" + policy = data.aws_iam_policy_document.domino_ecr_restricted.json +} + +data "aws_iam_policy_document" "s3" { + statement { + + effect = "Allow" + resources = ["*"] + + actions = [ + "s3:ListBucket", + "s3:GetBucketLocation", + "s3:ListBucketMultipartUploads", + ] + } + + statement { + sid = "" + effect = "Allow" + + resources = [for b in var.s3_buckets : "${b.arn}*"] + + actions = [ + "s3:PutObject", + "s3:GetObject", + "s3:DeleteObject", + "s3:ListMultipartUploadParts", + "s3:AbortMultipartUpload", + ] + } +} + +resource "aws_iam_policy" "s3" { + name = "${var.deploy_id}-S3" + path = "/" + policy = data.aws_iam_policy_document.s3.json +} + +data "aws_iam_policy_document" "autoscaler" { + statement { + + effect = "Allow" + resources = ["*"] + + actions = [ + "autoscaling:DescribeAutoScalingGroups", + "autoscaling:DescribeLaunchConfigurations", + "autoscaling:DescribeTags", + "ec2:DescribeLaunchTemplateVersions", + ] + } + + statement { + + effect = "Allow" + resources = ["*"] + + actions = [ + "autoscaling:DescribeAutoScalingInstances", + "autoscaling:SetDesiredCapacity", + "autoscaling:TerminateInstanceInAutoScalingGroup", + ] + + condition { + test = "StringEquals" + variable = "autoscaling:ResourceTag/eks:cluster-name" + values = [var.deploy_id] + } + } +} + +resource "aws_iam_policy" "autoscaler" { + name = "${var.deploy_id}-Autoscaler" + path = "/" + policy = data.aws_iam_policy_document.autoscaler.json +} + +data "aws_iam_policy_document" "ebs_csi" { + statement { + + effect = "Allow" + resources = ["*"] + + actions = [ + "ec2:DescribeAvailabilityZones", + "ec2:DescribeInstances", + "ec2:DescribeInstanceStatus", + "ec2:DescribeSnapshots", + "ec2:DescribeTags", + "ec2:DescribeVolumes", + "ec2:DescribeVolumesModifications", + ] + } + + statement { + + effect = "Allow" + resources = ["*"] + + actions = [ + "ec2:CreateSnapshot", + "ec2:AttachVolume", + "ec2:DetachVolume", + "ec2:ModifyVolume", + ] + + condition { + test = "StringLike" + variable = "aws:ResourceTag/kubernetes.io/cluster/${var.deploy_id}" + values = ["owned"] + } + } + + statement { + sid = "" + effect = "Allow" + + resources = [ + "arn:aws:ec2:*:*:volume/*", + "arn:aws:ec2:*:*:snapshot/*", + ] + + actions = ["ec2:CreateTags"] + + condition { + test = "StringEquals" + variable = "ec2:CreateAction" + + values = [ + "CreateVolume", + "CreateSnapshot", + ] + } + } + + statement { + sid = "" + effect = "Allow" + + resources = [ + "arn:aws:ec2:*:*:volume/*", + "arn:aws:ec2:*:*:snapshot/*", + ] + + actions = ["ec2:DeleteTags"] + } + + statement { + + effect = "Allow" + resources = ["*"] + actions = ["ec2:CreateVolume"] + + condition { + test = "StringLike" + variable = "aws:RequestTag/KubernetesCluster" + values = [var.deploy_id] + } + } + + statement { + + effect = "Allow" + resources = ["*"] + + actions = [ + "ec2:DeleteVolume", + "ec2:DeleteSnapshot", + ] + + condition { + test = "StringLike" + variable = "aws:ResourceTag/KubernetesCluster" + values = [var.deploy_id] + } + } +} + +resource "aws_iam_policy" "ebs_csi" { + name = "${var.deploy_id}-ebs-csi" + path = "/" + policy = data.aws_iam_policy_document.ebs_csi.json +} + +data "aws_iam_policy_document" "route53" { + statement { + + effect = "Allow" + resources = ["*"] + actions = ["route53:ListHostedZones"] + } + + statement { + + effect = "Allow" + resources = [local.aws_route53_zone_arn] + + actions = [ + "route53:ChangeResourceRecordSets", + "route53:ListResourceRecordSets", + ] + } +} + +resource "aws_iam_policy" "route53" { + count = var.enable_route53_iam_policy ? 1 : 0 + name = "${var.deploy_id}-Route53" + path = "/" + policy = data.aws_iam_policy_document.route53.json +} + +data "aws_iam_policy_document" "snapshot" { + statement { + + effect = "Allow" + resources = ["*"] + + actions = [ + "ec2:CreateSnapshot", + "ec2:CreateTags", + "ec2:DeleteSnapshot", + "ec2:DeleteTags", + "ec2:DescribeAvailabilityZones", + "ec2:DescribeSnapshots", + "ec2:DescribeTags", + ] + } +} + +resource "aws_iam_policy" "snapshot" { + name = "${var.deploy_id}-snapshot" + path = "/" + policy = data.aws_iam_policy_document.snapshot.json +} + +locals { + + eks_aws_node_iam_policies = toset([ + "arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy", + "arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy", + "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly", + "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore" + ]) + + eks_custom_node_iam_policies = { + "domino_ecr_restricted" = aws_iam_policy.domino_ecr_restricted.arn, + "s3" = aws_iam_policy.s3.arn, + "autoscaler" = aws_iam_policy.autoscaler.arn, + "ebs_csi" = aws_iam_policy.ebs_csi.arn, + "route53" = try(aws_iam_policy.route53[0].arn, ""), + "snapshot" = aws_iam_policy.snapshot.arn + } +} + +resource "aws_iam_role_policy_attachment" "aws_eks_nodes" { + for_each = toset(local.eks_aws_node_iam_policies) + policy_arn = each.key + role = aws_iam_role.eks_nodes.name +} + +resource "aws_iam_role_policy_attachment" "custom_eks_nodes" { + for_each = { for name, arn in local.eks_custom_node_iam_policies : name => arn if name != "route53" } + policy_arn = each.value + role = aws_iam_role.eks_nodes.name +} + +resource "aws_iam_role_policy_attachment" "custom_eks_nodes_route53" { + count = var.enable_route53_iam_policy ? 1 : 0 + policy_arn = local.eks_custom_node_iam_policies["route53"] + role = aws_iam_role.eks_nodes.name +} diff --git a/submodules/eks/main.tf b/submodules/eks/main.tf new file mode 100644 index 00000000..ae347aec --- /dev/null +++ b/submodules/eks/main.tf @@ -0,0 +1,198 @@ + +data "aws_partition" "current" {} +data "aws_caller_identity" "aws_account" {} + +locals { + aws_account_id = data.aws_caller_identity.aws_account.account_id + dns_suffix = data.aws_partition.current.dns_suffix + policy_arn_prefix = "arn:${data.aws_partition.current.partition}:iam::aws:policy" + eks_cluster_security_group_rules = { + ingress_nodes_443 = { + description = "Private subnets to ${var.deploy_id} EKS cluster API" + protocol = "tcp" + from_port = 443 + to_port = 443 + type = "ingress" + cidr_blocks = [for sb in var.private_subnets : sb.cidr_block] + } + egress_nodes_9443 = { + description = "EKS control plane to nodes" + protocol = "tcp" + from_port = 9443 + to_port = 9443 + type = "egress" + cidr_blocks = [for sb in var.private_subnets : sb.cidr_block] + } + egress_nodes_443 = { + description = "${var.deploy_id} EKS cluster API to private subnets" + protocol = "tcp" + from_port = 443 + to_port = 443 + type = "egress" + cidr_blocks = [for sb in var.private_subnets : sb.cidr_block] + } + egress_nodes_kubelet = { + description = "${var.deploy_id} EKS cluster API to private subnets" + protocol = "tcp" + from_port = 10250 + to_port = 10250 + type = "egress" + cidr_blocks = [for sb in var.private_subnets : sb.cidr_block] + } + } + + node_security_group_rules = { + ingress_cluster_9443 = { + description = "Cluster API to node groups 9443, hephaestus" + protocol = "tcp" + from_port = 9443 + to_port = 9443 + type = "ingress" + source_cluster_security_group = true + } + egress_cluster_443 = { + description = "Node groups to cluster API 443" + protocol = "tcp" + from_port = 443 + to_port = 443 + type = "egress" + source_cluster_security_group = true + } + ingress_cluster_443 = { + description = "Cluster API to node groups 443" + protocol = "tcp" + from_port = 443 + to_port = 443 + type = "ingress" + source_cluster_security_group = true + } + ingress_cluster_kubelet = { + description = "Cluster API to node kubelets" + protocol = "tcp" + from_port = 10250 + to_port = 10250 + type = "ingress" + source_cluster_security_group = true + } + ingress_cluster_coredns_tcp = { + description = "Cluster to node CoreDNS TCP" + protocol = "tcp" + from_port = 53 + to_port = 53 + type = "ingress" + source_cluster_security_group = true + } + egress_cluster_coredns_tcp = { + description = "Cluster to node CoreDNS TCP" + protocol = "tcp" + from_port = 53 + to_port = 53 + type = "egress" + source_cluster_security_group = true + } + ingress_cluster_coredns_udp = { + description = "Cluster to node CoreDNS UDP" + protocol = "udp" + from_port = 53 + to_port = 53 + type = "ingress" + source_cluster_security_group = true + } + egress_cluster_coredns_udp = { + description = "Cluster to node CoreDNS UDP" + protocol = "udp" + from_port = 53 + to_port = 53 + type = "egress" + source_cluster_security_group = true + } + ingress_self_coredns_tcp = { + description = "Node to node CoreDNS" + protocol = "tcp" + from_port = 53 + to_port = 53 + type = "ingress" + self = true + } + egress_self_coredns_tcp = { + description = "Node to node CoreDNS" + protocol = "tcp" + from_port = 53 + to_port = 53 + type = "egress" + self = true + } + ingress_self_coredns_udp = { + description = "Node to node CoreDNS" + protocol = "udp" + from_port = 53 + to_port = 53 + type = "ingress" + self = true + } + egress_self_coredns_udp = { + description = "Node to node CoreDNS" + protocol = "udp" + from_port = 53 + to_port = 53 + type = "egress" + self = true + } + egress_https = { + description = "Egress all HTTPS to internet" + protocol = "tcp" + from_port = 443 + to_port = 443 + type = "egress" + cidr_blocks = ["0.0.0.0/0"] + } + egress_ntp_tcp = { + description = "Egress NTP/TCP to internet" + protocol = "tcp" + from_port = 123 + to_port = 123 + type = "egress" + cidr_blocks = ["0.0.0.0/0"] + } + egress_ntp_udp = { + description = "Egress NTP/UDP to internet" + protocol = "udp" + from_port = 123 + to_port = 123 + type = "egress" + cidr_blocks = ["0.0.0.0/0"] + } + teleport_3024 = { + description = "Access to Teleport" + protocol = "tcp" + from_port = 3024 + to_port = 3024 + type = "egress" + cidr_blocks = ["0.0.0.0/0"] + } + efs_2049 = { + description = "Access to EFS" + protocol = "tcp" + from_port = 2049 + to_port = 2049 + type = "egress" + cidr_blocks = ["0.0.0.0/0"] + } + inter_node_traffic_int = { + description = "Node to node pod/svc trafic in" + protocol = "tcp" + from_port = 1025 + to_port = 65535 + type = "ingress" + self = true + } + inter_node_traffic_out = { + description = "Node to node pod/svc trafic out" + protocol = "tcp" + from_port = 1025 + to_port = 65535 + type = "egress" + self = true + } + } +} diff --git a/submodules/eks/node-group.tf b/submodules/eks/node-group.tf new file mode 100644 index 00000000..c324bdff --- /dev/null +++ b/submodules/eks/node-group.tf @@ -0,0 +1,311 @@ + +## EKS Nodes +data "aws_iam_policy_document" "eks_nodes" { + statement { + actions = ["sts:AssumeRole"] + + principals { + type = "Service" + identifiers = ["ec2.${local.dns_suffix}"] + } + } +} + +data "aws_route53_zone" "this" { + name = var.route53_hosted_zone + private_zone = false +} + +resource "aws_iam_role" "eks_nodes" { + name = "${var.deploy_id}-eks-nodes" + assume_role_policy = data.aws_iam_policy_document.eks_nodes.json + tags = var.tags +} + +## EKS Nodes security-group +locals { + aws_route53_zone_arn = data.aws_route53_zone.this.arn +} + +resource "aws_security_group" "eks_nodes" { + name = "${var.deploy_id}-nodes" + description = "EKS cluster Nodes security group" + vpc_id = var.vpc_id + + lifecycle { + create_before_destroy = true + } + tags = merge({ "Name" = "${var.deploy_id}-eks-nodes" }, var.tags) +} + +resource "aws_security_group_rule" "node" { + for_each = local.node_security_group_rules + + # Required + security_group_id = aws_security_group.eks_nodes.id + protocol = each.value.protocol + from_port = each.value.from_port + to_port = each.value.to_port + type = each.value.type + description = each.value.description + cidr_blocks = try(each.value.cidr_blocks, null) + self = try(each.value.self, null) + source_security_group_id = try( + each.value.source_security_group_id, + try(each.value.source_cluster_security_group, false) ? aws_security_group.eks_cluster.id : null + ) +} + +## END - EKS Nodes security-group + + +data "aws_ami" "eks_gpu" { + filter { + name = "name" + values = ["amazon-eks-gpu-node-${var.k8s_version}-v*"] + } + most_recent = true + owners = ["amazon"] +} + +resource "aws_launch_template" "compute" { + name = "${var.deploy_id}-compute" + + block_device_mappings { + device_name = "/dev/xvda" + + ebs { + delete_on_termination = "true" + encrypted = "true" + volume_size = "100" + volume_type = "gp3" + } + } + + disable_api_termination = "false" + instance_type = var.node_groups.compute.instance_type + key_name = var.ssh_pvt_key_name + vpc_security_group_ids = [aws_security_group.eks_nodes.id] + + metadata_options { + http_endpoint = "enabled" + http_put_response_hop_limit = "2" + http_tokens = "required" + } + tag_specifications { + resource_type = "instance" + tags = merge({ + "Name" = "${var.deploy_id}-compute" + }, var.tags) + } + + tag_specifications { + resource_type = "volume" + tags = merge({ "Name" = "${var.deploy_id}-compute" }, var.tags) + } + tags = var.tags +} + +resource "aws_eks_node_group" "compute" { + for_each = { for sb in var.private_subnets : sb.zone => sb if lookup(var.node_groups, "compute", {}) != {} } + cluster_name = aws_eks_cluster.this.name + node_group_name = "${var.deploy_id}-compute-${each.value.zone}" + node_role_arn = aws_iam_role.eks_nodes.arn + subnet_ids = [each.value.id] + tags = var.tags + scaling_config { + min_size = var.node_groups.compute.min + max_size = var.node_groups.compute.max + desired_size = var.node_groups.compute.desired + } + + launch_template { + id = aws_launch_template.compute.id + version = aws_launch_template.compute.latest_version + } + + + labels = { + "lifecycle" = "OnDemand" + "dominodatalab.com/node-pool" = "default" + "dominodatalab.com/domino-node" = "true" + } + + lifecycle { + create_before_destroy = true + ignore_changes = [ + scaling_config[0].desired_size, + ] + } + + depends_on = [ + aws_iam_role_policy_attachment.aws_eks_nodes, + aws_iam_role_policy_attachment.custom_eks_nodes + ] +} + +resource "aws_launch_template" "platform" { + name = "${var.deploy_id}-platform" + + block_device_mappings { + device_name = "/dev/xvda" + + ebs { + delete_on_termination = "true" + encrypted = "true" + volume_size = "100" + volume_type = "gp3" + } + } + + disable_api_termination = "false" + instance_type = var.node_groups.platform.instance_type + key_name = var.ssh_pvt_key_name + vpc_security_group_ids = [aws_security_group.eks_nodes.id] + + metadata_options { + http_endpoint = "enabled" + http_put_response_hop_limit = "2" + http_tokens = "required" + } + tag_specifications { + resource_type = "instance" + tags = merge({ + "Name" = "${var.deploy_id}-platform" + }, var.tags) + } + + tag_specifications { + resource_type = "volume" + tags = merge({ "Name" = "${var.deploy_id}-platform" }, var.tags) + } + tags = var.tags +} + +resource "aws_eks_node_group" "platform" { + for_each = { for sb in var.private_subnets : sb.zone => sb if lookup(var.node_groups, "platform", {}) != {} } + cluster_name = aws_eks_cluster.this.name + node_group_name = "${var.deploy_id}-platform-${each.value.zone}" + node_role_arn = aws_iam_role.eks_nodes.arn + subnet_ids = [each.value.id] + tags = var.tags + scaling_config { + min_size = var.node_groups.platform.min + max_size = var.node_groups.platform.max + desired_size = var.node_groups.platform.desired + } + + launch_template { + id = aws_launch_template.platform.id + version = aws_launch_template.platform.latest_version + } + + + labels = { + "lifecycle" = "OnDemand" + "dominodatalab.com/node-pool" = "platform" + "dominodatalab.com/domino-node" = "true" + } + + lifecycle { + create_before_destroy = true + ignore_changes = [ + scaling_config[0].desired_size, + ] + } + + depends_on = [ + aws_iam_role_policy_attachment.aws_eks_nodes, + aws_iam_role_policy_attachment.custom_eks_nodes + ] +} + +locals { + gpu_bootstrap_extra_args = "--node-labels lifecycle=OnDemand --node-labels=dominodatalab.com/node-pool=default-gpu,nvidia.com/gpu=true,dominodatalab.com/domino-node=true --register-with-taints=nvidia.com/gpu=true:NoSchedule" + gpu_user_data = base64encode(templatefile("${path.module}/templates/linux_custom.tpl", { + cluster_name = aws_eks_cluster.this.name + cluster_endpoint = aws_eks_cluster.this.endpoint + cluster_auth_base64 = aws_eks_cluster.this.certificate_authority[0].data + bootstrap_extra_args = local.gpu_bootstrap_extra_args + pre_bootstrap_user_data = "" + post_bootstrap_user_data = "echo ALL DONE !!!" + })) +} + + +resource "aws_launch_template" "gpu" { + name = "${var.deploy_id}-gpu" + image_id = data.aws_ami.eks_gpu.image_id + disable_api_termination = "false" + instance_type = var.node_groups.gpu.instance_type + key_name = var.ssh_pvt_key_name + vpc_security_group_ids = [aws_security_group.eks_nodes.id] + user_data = local.gpu_user_data + block_device_mappings { + device_name = "/dev/xvda" + + ebs { + delete_on_termination = "true" + encrypted = "true" + volume_size = "100" + volume_type = "gp3" + } + } + + + metadata_options { + http_endpoint = "enabled" + http_put_response_hop_limit = "2" + http_tokens = "required" + } + tag_specifications { + resource_type = "instance" + tags = merge({ + "Name" = "${var.deploy_id}-gpu" + }, var.tags) + } + + tag_specifications { + resource_type = "volume" + tags = merge({ "Name" = "${var.deploy_id}-gpu" }, var.tags) + } + tags = var.tags +} + +resource "aws_eks_node_group" "gpu" { + for_each = { for sb in var.private_subnets : sb.zone => sb if lookup(var.node_groups, "gpu", {}) != {} } + cluster_name = aws_eks_cluster.this.name + node_group_name = "${var.deploy_id}-gpu-${each.value.zone}" + node_role_arn = aws_iam_role.eks_nodes.arn + subnet_ids = [each.value.id] + tags = var.tags + scaling_config { + min_size = var.node_groups.gpu.min + max_size = var.node_groups.gpu.max + desired_size = var.node_groups.gpu.desired + } + + launch_template { + id = aws_launch_template.gpu.id + version = aws_launch_template.gpu.latest_version + } + + + labels = { + "lifecycle" = "OnDemand" + "dominodatalab.com/node-pool" = "gpu" + "dominodatalab.com/domino-node" = "true" + } + + lifecycle { + create_before_destroy = true + ignore_changes = [ + scaling_config[0].desired_size, + ] + } + + depends_on = [ + aws_iam_role_policy_attachment.aws_eks_nodes, + aws_iam_role_policy_attachment.custom_eks_nodes + ] +} diff --git a/submodules/eks/outputs.tf b/submodules/eks/outputs.tf new file mode 100644 index 00000000..6535c6aa --- /dev/null +++ b/submodules/eks/outputs.tf @@ -0,0 +1,30 @@ + +output "security_group_id" { + description = "EKS security group id." + value = aws_security_group.eks_cluster.id +} + +output "nodes_security_group_id" { + description = "EKS managed nodes security group id." + value = aws_security_group.eks_nodes.id +} + +output "cluster_endpoint" { + description = "EKS cluster API endpoint." + value = aws_eks_cluster.this.endpoint +} + +output "managed_nodes_role_arns" { + description = "EKS managed nodes arns." + value = [aws_iam_role.eks_nodes.arn] +} + +output "eks_master_role_name" { + description = "EKS master role arns." + value = [aws_iam_role.eks_cluster.name] +} + +output "hosted_zone_id" { + description = "DNS hosted zone ID." + value = data.aws_route53_zone.this.zone_id +} diff --git a/submodules/eks/templates/linux_custom.tpl b/submodules/eks/templates/linux_custom.tpl new file mode 100644 index 00000000..e6f376dc --- /dev/null +++ b/submodules/eks/templates/linux_custom.tpl @@ -0,0 +1,12 @@ +#!/bin/bash +set -ex +KUBELET_CONFIG=/etc/kubernetes/kubelet/kubelet-config.json +echo "$(jq '.eventRecordQPS=0' $KUBELET_CONFIG)" > $KUBELET_CONFIG +yum install -y https://s3.amazonaws.com/ec2-downloads-windows/SSMAgent/latest/linux_amd64/amazon-ssm-agent.rpm +${pre_bootstrap_user_data ~} + +# Custom user data template provided for rendering +B64_CLUSTER_CA=${cluster_auth_base64} +API_SERVER_URL=${cluster_endpoint} +/etc/eks/bootstrap.sh ${cluster_name} ${bootstrap_extra_args} --b64-cluster-ca $B64_CLUSTER_CA --apiserver-endpoint $API_SERVER_URL +${post_bootstrap_user_data ~} diff --git a/submodules/eks/variables.tf b/submodules/eks/variables.tf new file mode 100755 index 00000000..2f0ae2a7 --- /dev/null +++ b/submodules/eks/variables.tf @@ -0,0 +1,122 @@ +variable "deploy_id" { + type = string + description = "Domino Deployment ID" + + validation { + condition = can(regex("^[a-z-0-9]{3,32}$", var.deploy_id)) + error_message = "Argument deploy_id must: start with a letter, contain lowercase alphanumeric characters(can contain hyphens[-]) with length between 3 and 32 characters." + } +} + +variable "region" { + type = string + description = "AWS region for the deployment" +} + +variable "tags" { + type = map(string) + description = "Deployment tags" +} + +variable "k8s_version" { + type = string + description = "EKS cluster k8s version." + default = "1.22" +} + +variable "node_groups" { + type = map(map(any)) + description = "EKS managed node groups definition" + default = { + "compute" = { + instance_type = "m5.2xlarge" + min = 0 + max = 10 + desired = 1 + }, + "platform" = { + instance_type = "m5.4xlarge" + min = 0 + max = 10 + desired = 1 + }, + "gpu" = { + instance_type = "g4dn.xlarge" + min = 0 + max = 10 + desired = 0 + } + } +} + +variable "kubeconfig_path" { + type = string + description = "Kubeconfig filename." + default = "kubeconfig" +} + +variable "private_subnets" { + description = "Private subnets object" + type = list(object({ + cidr_block = string + name = string + type = string + zone = string + zone_id = string + id = string + })) +} + +variable "vpc_id" { + type = string + description = "VPC ID." +} + +variable "ssh_pvt_key_name" { + type = string + description = "ssh private key filename." +} + +variable "route53_hosted_zone" { + type = string + description = "Route53 zone" +} + +variable "bastion_security_group_id" { + type = string + description = "Bastion security group id." + default = "" +} + +variable "enable_route53_iam_policy" { + type = bool + description = "Enable route53 iam policy toggle." + default = false +} + +variable "eks_cluster_addons" { + type = list(string) + description = "EKS cluster addons." + default = ["vpc-cni", "kube-proxy", "coredns"] + # default = ["vpc-cni", "kube-proxy", "coredns", "aws-ebs-csi-driver"] +} + +variable "eks_security_group_rules" { + type = map(any) + description = "EKS security group rules." + default = {} +} + +variable "create_bastion_sg" { + type = bool + description = "Create bastion access rules toggle." +} + +variable "s3_buckets" { + description = "S3 buckets information that the nodegroups need access to" + type = list(object({ + bucket_name = string + arn = string + })) + +} diff --git a/submodules/eks/versions.tf b/submodules/eks/versions.tf new file mode 100644 index 00000000..b18ed224 --- /dev/null +++ b/submodules/eks/versions.tf @@ -0,0 +1,14 @@ +terraform { + + required_version = ">= 1.0" + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 4.0" + } + null = { + source = "hashicorp/null" + version = ">= 3.1.0" + } + } +} diff --git a/submodules/k8s/README.md b/submodules/k8s/README.md new file mode 100644 index 00000000..9966b8c5 --- /dev/null +++ b/submodules/k8s/README.md @@ -0,0 +1,54 @@ +# k8s + + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.0 | +| [aws](#requirement\_aws) | >= 4.0 | +| [local](#requirement\_local) | >= 2.2.0 | +| [null](#requirement\_null) | >= 3.1.0 | + +## Providers + +| Name | Version | +|------|---------| +| [aws](#provider\_aws) | 4.22.0 | +| [local](#provider\_local) | 2.2.3 | +| [null](#provider\_null) | 3.1.1 | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [local_file.templates](https://registry.terraform.io/providers/hashicorp/local/latest/docs/resources/file) | resource | +| [null_resource.run_k8s_pre_setup](https://registry.terraform.io/providers/hashicorp/null/latest/docs/resources/resource) | resource | +| [aws_iam_role.eks_master_roles](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_role) | data source | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [bastion\_public\_ip](#input\_bastion\_public\_ip) | Bastion host public ip. | `string` | n/a | yes | +| [bastion\_user](#input\_bastion\_user) | ec2 instance user. | `string` | `"ec2-user"` | no | +| [calico\_version](#input\_calico\_version) | Calico operator version. | `string` | `"v1.11.0"` | no | +| [deploy\_id](#input\_deploy\_id) | Domino Deployment ID | `string` | n/a | yes | +| [eks\_master\_role\_names](#input\_eks\_master\_role\_names) | IAM role names to be added as masters in eks. | `list(string)` | `[]` | no | +| [k8s\_cluster\_endpoint](#input\_k8s\_cluster\_endpoint) | EKS cluster API endpoint. | `string` | n/a | yes | +| [kubeconfig\_path](#input\_kubeconfig\_path) | Kubeconfig filename. | `string` | `"kubeconfig"` | no | +| [mallory\_local\_normal\_port](#input\_mallory\_local\_normal\_port) | Mallory k8s tunnel normal port. | `string` | `"1315"` | no | +| [mallory\_local\_smart\_port](#input\_mallory\_local\_smart\_port) | Mallory k8s tunnel smart(filters based on the blocked list) port. | `string` | `"1316"` | no | +| [managed\_nodes\_role\_arns](#input\_managed\_nodes\_role\_arns) | EKS managed nodes arns to be added to aws-auth for api auth. | `list(string)` | n/a | yes | +| [ssh\_pvt\_key\_name](#input\_ssh\_pvt\_key\_name) | ssh private key filename. | `string` | `"domino.pem"` | no | + +## Outputs + +| Name | Description | +|------|-------------| +| [k8s\_tunnel\_command](#output\_k8s\_tunnel\_command) | Command to run the k8s tunnel mallory. | + diff --git a/submodules/k8s/main.tf b/submodules/k8s/main.tf new file mode 100644 index 00000000..b7c5b58d --- /dev/null +++ b/submodules/k8s/main.tf @@ -0,0 +1,93 @@ + + +data "aws_iam_role" "eks_master_roles" { + for_each = toset(var.eks_master_role_names) + name = each.key +} + +locals { + mallory_config_filename = "mallory.json" + mallory_container_name = "mallory_k8s_tunnel" + mallory_config_path_container = "/root/.config/${local.mallory_config_filename}" + pvt_key_path_container = "/root/${basename(var.ssh_pvt_key_name)}" + k8s_functions_sh_filename = "k8s-functions.sh" + k8s_functions_sh_template = "k8s-functions.sh.tftpl" + k8s_pre_setup_sh_filename = "k8s-pre-setup.sh" + k8s_pre_setup_sh_template = "k8s-pre-setup.sh.tftpl" + aws_auth_filename = "aws-auth.yaml" + aws_auth_template = "aws-auth.yaml.tftpl" + calico = { + operator_url = "https://raw.githubusercontent.com/aws/amazon-vpc-cni-k8s/${var.calico_version}/config/master/calico-operator.yaml" + custom_resources_url = "https://raw.githubusercontent.com/aws/amazon-vpc-cni-k8s/${var.calico_version}/config/master/calico-crs.yaml" + } + + k8s_tunnel_command = "docker run --rm --name ${local.mallory_container_name} -d -v $PWD/${local.mallory_config_filename}:${local.mallory_config_path_container} -p ${var.mallory_local_normal_port}:${var.mallory_local_normal_port} -p ${var.mallory_local_smart_port}:${var.mallory_local_smart_port} -v ${var.ssh_pvt_key_name}:${local.pvt_key_path_container} zoobab/mallory" + + resources_directory = "${path.cwd}/resources/${var.deploy_id}" + templates_dir = "${path.module}/templates" + + templates = { + k8s_functions_sh = { + filename = local.k8s_functions_sh_filename + content = templatefile("${local.templates_dir}/${local.k8s_functions_sh_template}", { + kubeconfig_path = basename(var.kubeconfig_path) + k8s_tunnel_command = local.k8s_tunnel_command + mallory_port = var.mallory_local_smart_port + mallory_container_name = local.mallory_container_name + aws_auth_yaml = basename(local.aws_auth_filename) + calico_operator_url = local.calico.operator_url + calico_custom_resources_url = local.calico.custom_resources_url + }) + } + + k8s_presetup = { + filename = local.k8s_pre_setup_sh_filename + content = templatefile("${local.templates_dir}/${local.k8s_pre_setup_sh_template}", { + k8s_functions_sh_filename = local.k8s_functions_sh_filename + }) + } + + mallory_k8s_tunnel = { + filename = local.mallory_config_filename + content = jsonencode( + { + "id_rsa" = local.pvt_key_path_container + "local_smart" = ":${var.mallory_local_smart_port}" + "local_normal" = ":${var.mallory_local_normal_port}" + "remote" = "ssh://${var.bastion_user}@${var.bastion_public_ip}:22" + "blocked" = [var.k8s_cluster_endpoint] + }) } + + aws_auth = { + filename = local.aws_auth_filename + content = templatefile("${local.templates_dir}/${local.aws_auth_template}", + { + eks_managed_nodes_role_arns = sort(var.managed_nodes_role_arns) + eks_master_role_arns = try({ for r in sort(var.eks_master_role_names) : r => data.aws_iam_role.eks_master_roles[r].arn }, {}) + + }) + + } + } + +} + +resource "local_file" "templates" { + for_each = { for k, v in local.templates : k => v } + content = each.value.content + filename = "${local.resources_directory}/${each.value.filename}" + directory_permission = "0777" + file_permission = "0744" +} + +resource "null_resource" "run_k8s_pre_setup" { + provisioner "local-exec" { + command = basename(local_file.templates["k8s_presetup"].filename) + interpreter = ["bash", "-ex"] + working_dir = local.resources_directory + } + + depends_on = [ + local_file.templates, + ] +} diff --git a/submodules/k8s/outputs.tf b/submodules/k8s/outputs.tf new file mode 100644 index 00000000..4f1aed84 --- /dev/null +++ b/submodules/k8s/outputs.tf @@ -0,0 +1,4 @@ +output "k8s_tunnel_command" { + description = "Command to run the k8s tunnel mallory." + value = local.k8s_tunnel_command +} diff --git a/submodules/k8s/templates/aws-auth.yaml.tftpl b/submodules/k8s/templates/aws-auth.yaml.tftpl new file mode 100644 index 00000000..51cc304c --- /dev/null +++ b/submodules/k8s/templates/aws-auth.yaml.tftpl @@ -0,0 +1,20 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: aws-auth + namespace: kube-system +data: + mapRoles: | +%{ for arn in eks_managed_nodes_role_arns ~} + - rolearn: ${arn} + username: system:node:{{EC2PrivateDNSName}} + groups: + - system:bootstrappers + - system:nodes +%{ endfor ~} +%{ for role, arn in eks_master_role_arns ~} + - rolearn: ${arn} + username: ${role} + groups: + - system:masters +%{ endfor ~} diff --git a/submodules/k8s/templates/docker-repo-creds-secret.yaml.tftpl b/submodules/k8s/templates/docker-repo-creds-secret.yaml.tftpl new file mode 100644 index 00000000..4f5765a5 --- /dev/null +++ b/submodules/k8s/templates/docker-repo-creds-secret.yaml.tftpl @@ -0,0 +1,12 @@ +%{ for ns in namespaces ~} +--- +kind: Secret +apiVersion: v1 +metadata: + name: ${name} + namespace: ${ns} +data: + ".dockerconfigjson": ${quay_auth_encoded} +type: kubernetes.io/dockerconfigjson + +%{ endfor ~} diff --git a/submodules/k8s/templates/ebs-storageclass.yaml.tftpl b/submodules/k8s/templates/ebs-storageclass.yaml.tftpl new file mode 100644 index 00000000..4c718c58 --- /dev/null +++ b/submodules/k8s/templates/ebs-storageclass.yaml.tftpl @@ -0,0 +1,12 @@ +--- +kind: StorageClass +apiVersion: storage.k8s.io/v1 +metadata: + name: ${name} +provisioner: ${driver} +parameters: + encrypted: 'true' + type: gp3 +reclaimPolicy: Delete +allowVolumeExpansion: true +volumeBindingMode: WaitForFirstConsumer diff --git a/submodules/k8s/templates/efs-persistent-volume-claim.yaml.tftpl b/submodules/k8s/templates/efs-persistent-volume-claim.yaml.tftpl new file mode 100644 index 00000000..26348e99 --- /dev/null +++ b/submodules/k8s/templates/efs-persistent-volume-claim.yaml.tftpl @@ -0,0 +1,15 @@ +--- +kind: PersistentVolumeClaim +apiVersion: v1 +metadata: + name: ${pvc_name} + namespace: ${namespace} +spec: + accessModes: + - ReadWriteMany + resources: + requests: + storage: ${capacity} + volumeName: ${pv_name} + storageClassName: ${storage_class} + volumeMode: Filesystem diff --git a/submodules/k8s/templates/efs-persistent-volume.yaml.tftpl b/submodules/k8s/templates/efs-persistent-volume.yaml.tftpl new file mode 100644 index 00000000..f216e33a --- /dev/null +++ b/submodules/k8s/templates/efs-persistent-volume.yaml.tftpl @@ -0,0 +1,18 @@ +--- +kind: PersistentVolume +apiVersion: v1 +metadata: + name: ${pv_name} +spec: + capacity: + storage: ${capacity} + csi: + driver: ${driver} + volumeHandle: ${efs_volume_handle} + volumeAttributes: + encryptInTransit: 'true' + accessModes: + - ReadWriteMany + persistentVolumeReclaimPolicy: Retain + storageClassName: ${storage_class} + volumeMode: Filesystem diff --git a/submodules/k8s/templates/efs-storageclass.yaml.tftpl b/submodules/k8s/templates/efs-storageclass.yaml.tftpl new file mode 100644 index 00000000..728402aa --- /dev/null +++ b/submodules/k8s/templates/efs-storageclass.yaml.tftpl @@ -0,0 +1,9 @@ +--- +kind: StorageClass +apiVersion: storage.k8s.io/v1 +metadata: + name: ${name} +provisioner: ${driver} +reclaimPolicy: Delete +allowVolumeExpansion: true +volumeBindingMode: Immediate diff --git a/submodules/k8s/templates/k8s-functions.sh.tftpl b/submodules/k8s/templates/k8s-functions.sh.tftpl new file mode 100644 index 00000000..e9a36e11 --- /dev/null +++ b/submodules/k8s/templates/k8s-functions.sh.tftpl @@ -0,0 +1,68 @@ +#! /usr/bin/env bash + +RED="\e[31m" +GREEN="\e[32m" +EC="\e[0m" + +open_ssh_tunnel_to_k8s_api() { + printf "$GREEN Setting up mallory k8s tunnel... $EC \n" + if [[ -z "$https_proxy" ]]; then + MALLORY_PORT=${mallory_port} + https_proxy=http://localhost:$MALLORY_PORT + export https_proxy + fi + eval ${k8s_tunnel_command} && sleep 3 + echo +} + +check_kubeconfig() { + KUBECONFIG="${kubeconfig_path}" + printf "$GREEN Checking if $KUBECONFIG exists... $EC \n" + if test -f "$KUBECONFIG"; then + echo "$KUBECONFIG exists." && export KUBECONFIG + else + echo "$KUBECONFIG does not exist." && exit 1 + fi + echo +} + +set_k8s_auth() { + AWS_AUTH_YAML="${aws_auth_yaml}" + if test -f "$AWS_AUTH_YAML"; then + printf "$GREEN Updating $AWS_AUTH_YAML... $EC \n" + kubectl apply -f "$AWS_AUTH_YAML" + else + printf "$RED $AWS_AUTH_YAML does not exist. $EC \n" && exit 1 + fi + echo +} + +install_calico() { + CALICO_OPERATOR_YAML_URL=${calico_operator_url} + printf "$GREEN Installing Calico Operator $EC \n" + kubectl apply -f $CALICO_OPERATOR_YAML_URL || printf "$RED There was an error installing the calico operator" + echo + CALICO_CRD_YAML_URL=${calico_custom_resources_url} + printf "$GREEN Installing Calico Custom resources $EC \n" || printf "$RED There was an error installing the calico CRD" + kubectl apply -f $CALICO_CRD_YAML_URL + echo +} + +kubectl_apply() { + k8s_manifest="$1" + if test -f "$k8s_manifest"; then + echo "Applying $k8s_manifest..." + kubectl apply -f $k8s_manifest + else + printf "$RED $k8s_manifest does not exist. $EC \n" && exit 1 + fi + + kubectl apply -f "$k8s_manifest" +} + +close_ssh_tunnel_to_k8s_api() { + printf "$GREEN Shutting down mallory k8s tunnel ${mallory_container_name} ... $EC" + docker kill "${mallory_container_name}" + docker rm "${mallory_container_name}" || true + echo +} diff --git a/submodules/k8s/templates/k8s-pre-setup.sh.tftpl b/submodules/k8s/templates/k8s-pre-setup.sh.tftpl new file mode 100644 index 00000000..00dc96ec --- /dev/null +++ b/submodules/k8s/templates/k8s-pre-setup.sh.tftpl @@ -0,0 +1,17 @@ +#! /usr/bin/env bash + +RED="\e[31m" +GREEN="\e[32m" +EC="\e[0m" + +source ${k8s_functions_sh_filename} + +main() { + open_ssh_tunnel_to_k8s_api + check_kubeconfig + set_k8s_auth + install_calico +} + +trap close_ssh_tunnel_to_k8s_api EXIT +main diff --git a/submodules/k8s/templates/k8s-pre-setup.sh.tftpl.back b/submodules/k8s/templates/k8s-pre-setup.sh.tftpl.back new file mode 100644 index 00000000..64898311 --- /dev/null +++ b/submodules/k8s/templates/k8s-pre-setup.sh.tftpl.back @@ -0,0 +1,172 @@ +#! /usr/bin/env bash + +RED="\e[31m" +GREEN="\e[32m" +EC="\e[0m" + +open_ssh_tunnel_to_k8s_api() { + printf "$GREEN Setting up mallory k8s tunnel... $EC \n" + if [[ -z "$https_proxy" ]]; then + MALLORY_PORT=${mallory_port} + https_proxy=http://localhost:$MALLORY_PORT + export https_proxy + fi + eval ${k8s_tunnel_command} && sleep 3 + echo +} + +check_kubeconfig() { + KUBECONFIG="${kubeconfig_path}" + printf "$GREEN Checking if $KUBECONFIG exists... $EC \n" + if test -f "$KUBECONFIG"; then + echo "$KUBECONFIG exists." && export KUBECONFIG + else + echo "$KUBECONFIG does not exist." && exit 1 + fi + echo +} + +set_k8s_auth() {\ + AWS_AUTH_YAML="${aws_auth_yaml}" + if test -f "$AWS_AUTH_YAML"; then + printf "$GREEN Updating $AWS_AUTH_YAML... $EC \n" + kubectl apply -f "$AWS_AUTH_YAML" + else + printf "$RED $AWS_AUTH_YAML does not exist. $EC \n" && exit 1 + fi + echo +} + +install_calico() { + CALICO_OPERATOR_YAML_URL=${calico_operator_url} + printf "$GREEN Installing Calico Operator $EC \n" + kubectl apply -f $CALICO_OPERATOR_YAML_URL || printf "$RED There was an error installing the calico operator" + echo + CALICO_CRD_YAML_URL=${calico_custom_resources_url} + printf "$GREEN Installing Calico Custom resources $EC \n" || printf "$RED There was an error installing the calico CRD" + kubectl apply -f $CALICO_CRD_YAML_URL + echo +} + + +create_namespace() { + namespace=$1 + printf "$GREEN Creating namespace $namespace $EC \n" + kubectl create namespace $namespace --dry-run=client --save-config -o yaml | kubectl apply -f - + echo +} + +helm_install() { + HELM_REPO=${domino_helm_repo} + printf "$RED Make sure you are authenticated with $HELM_REPO $EC \n" + chart_name=$1 + chart_version=$2 + namespace=$3 + + printf "$GREEN Installing helm-chart:$chart_name version:$chart_version $EC \n" + + helm_command="helm upgrade --install $chart_name $HELM_REPO/$chart_name --version $chart_version --namespace $namespace" + echo "$helm_command" + eval "$helm_command" +} + +kubectl_apply() { + k8s_manifest="$1" + if test -f "$k8s_manifest"; then + echo "Applying $k8s_manifest..." + kubectl apply -f $k8s_manifest + else + printf "$RED $k8s_manifest does not exist. $EC \n" && exit 1 + fi + + kubectl apply -f "$k8s_manifest" +} + +create_namespaces() { + %{~ for namespace in domino_namespaces ~} + create_namespace ${namespace} + %{~ endfor } + echo +} + +install_helm_charts() { + %{~ for chart in helm_charts ~} + helm_install ${chart.name} ${chart.version} ${domino_namespaces_map[chart.namespace]} + %{~ endfor } + echo +} + +# create_storage_classes() { +# echo "Creating storageclasses..." + +# %{~ for manifest in domino_storage_classes_filenames ~} +# kubectl_apply ${manifest} +# %{~ endfor } +# echo +# } + +create_persistent_volumes() { + printf "$GREEN Creating persistent-volumes... $EC \n" + + %{~ for manifest in domino_persistent_volume_filenames ~} + kubectl_apply ${manifest} + %{~ endfor } + echo +} +create_persistent_volume_claims() { + printf "$GREEN Creating persistent-volume-claims... $EC \n" + + %{~ for manifest in domino_persistent_volume_claims_filenames ~} + kubectl_apply ${manifest} + %{~ endfor } + echo +} +create_persistent_storage() { + create_persistent_volumes && create_persistent_volume_claims +} + +close_ssh_tunnel_to_k8s_api() { + printf "$GREEN Shutting down mallory k8s tunnel ${mallory_container_name} ... $EC" + docker kill "${mallory_container_name}" + docker rm "${mallory_container_name}" || true + echo +} + +create_docker_cred_secret() { + printf "$GREEN Creating domino-quay-repos secret (for domino docker repo pullImageSecret)... $EC" + kubectl create secret \ + docker-registry \ + -o yaml --dry-run=client --save-config \ + --docker-server=quay.io \ + --docker-username=$QUAY_USERNAME \ + --docker-password=$QUAY_PASSWORD \ + --docker-email=. ${domino_docker_pull_secret_name} | kubectl apply -f - + + echo +} + +create_domino_cm() { + printf "$GREEN Creating configmap for fleetcommand configuration(${domino_config_filename})... $EC" + kubectl create configmap \ + -o yaml --dry-run=client --save-config \ + fleetcommand-agent-config \ + --from-file=${domino_config_filename} | kubectl apply -f - + echo +} + + + +main() { + open_ssh_tunnel_to_k8s_api + check_kubeconfig + set_k8s_auth + # create_namespaces + # create_docker_cred_secret + # create_persistent_storage + install_calico + # create_domino_cm + # install_helm_charts +} + +trap close_ssh_tunnel_to_k8s_api EXIT +main diff --git a/submodules/k8s/variables.tf b/submodules/k8s/variables.tf new file mode 100755 index 00000000..e1f9ce68 --- /dev/null +++ b/submodules/k8s/variables.tf @@ -0,0 +1,67 @@ +variable "deploy_id" { + type = string + description = "Domino Deployment ID" + + validation { + condition = can(regex("^[a-z-0-9]{3,32}$", var.deploy_id)) + error_message = "Argument deploy_id must: start with a letter, contain lowercase alphanumeric characters(can contain hyphens[-]) with length between 3 and 32 characters." + } +} + +variable "kubeconfig_path" { + type = string + description = "Kubeconfig filename." + default = "kubeconfig" +} + +variable "ssh_pvt_key_name" { + type = string + description = "ssh private key filename." + default = "domino.pem" +} + + +variable "bastion_user" { + type = string + description = "ec2 instance user." + default = "ec2-user" + +} + +variable "bastion_public_ip" { + type = string + description = "Bastion host public ip." +} +variable "k8s_cluster_endpoint" { + type = string + description = "EKS cluster API endpoint." +} + +variable "managed_nodes_role_arns" { + type = list(string) + description = "EKS managed nodes arns to be added to aws-auth for api auth." +} + +variable "eks_master_role_names" { + type = list(string) + description = "IAM role names to be added as masters in eks." + default = [] +} + +variable "mallory_local_normal_port" { + type = string + description = "Mallory k8s tunnel normal port." + default = "1315" +} + +variable "mallory_local_smart_port" { + type = string + description = "Mallory k8s tunnel smart(filters based on the blocked list) port." + default = "1316" +} + +variable "calico_version" { + type = string + description = "Calico operator version." + default = "v1.11.0" +} diff --git a/submodules/k8s/versions.tf b/submodules/k8s/versions.tf new file mode 100644 index 00000000..d6618ab4 --- /dev/null +++ b/submodules/k8s/versions.tf @@ -0,0 +1,17 @@ +terraform { + required_version = ">= 1.0" + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 4.0" + } + null = { + source = "hashicorp/null" + version = ">= 3.1.0" + } + local = { + source = "hashicorp/local" + version = ">= 2.2.0" + } + } +} diff --git a/submodules/network/README.md b/submodules/network/README.md new file mode 100644 index 00000000..f5fe0a72 --- /dev/null +++ b/submodules/network/README.md @@ -0,0 +1,62 @@ +# network + + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.0 | +| [aws](#requirement\_aws) | >= 4.0 | + +## Providers + +| Name | Version | +|------|---------| +| [aws](#provider\_aws) | 4.22.0 | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [aws_default_network_acl.default](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/default_network_acl) | resource | +| [aws_eip.public](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eip) | resource | +| [aws_flow_log.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/flow_log) | resource | +| [aws_internet_gateway.igw](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/internet_gateway) | resource | +| [aws_internet_gateway_attachment.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/internet_gateway_attachment) | resource | +| [aws_nat_gateway.ngw](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/nat_gateway) | resource | +| [aws_route_table.private](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route_table) | resource | +| [aws_route_table.public](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route_table) | resource | +| [aws_route_table_association.private](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route_table_association) | resource | +| [aws_route_table_association.public](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route_table_association) | resource | +| [aws_subnet.private](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/subnet) | resource | +| [aws_subnet.public](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/subnet) | resource | +| [aws_vpc.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc) | resource | +| [aws_vpc_endpoint.s3](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_endpoint) | resource | +| [aws_network_acls.default](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/network_acls) | data source | +| [aws_vpc.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/vpc) | data source | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [base\_cidr\_block](#input\_base\_cidr\_block) | CIDR block to serve the main private and public subnets | `string` | n/a | yes | +| [deploy\_id](#input\_deploy\_id) | Domino Deployment ID | `string` | `""` | no | +| [monitoring\_s3\_bucket\_arn](#input\_monitoring\_s3\_bucket\_arn) | Monitoring bucket for vpc flow logging | `string` | n/a | yes | +| [private\_subnets](#input\_private\_subnets) | Private subnets object |
list(object({
cidr_block = string
name = string
type = string
zone = string
zone_id = string
}))
| n/a | yes | +| [public\_subnets](#input\_public\_subnets) | Public subnets object |
list(object({
cidr_block = string
name = string
type = string
zone = string
zone_id = string
}))
| n/a | yes | +| [region](#input\_region) | AWS region for the deployment | `string` | n/a | yes | +| [tags](#input\_tags) | Deployment tags | `map(string)` | n/a | yes | +| [vpc\_id](#input\_vpc\_id) | VPC ID. | `string` | `""` | no | + +## Outputs + +| Name | Description | +|------|-------------| +| [private\_subnets](#output\_private\_subnets) | Private subnets object. Adds id to the object | +| [public\_subnets](#output\_public\_subnets) | Public subnets object. Adds id to the object | +| [vpc\_id](#output\_vpc\_id) | VPC id. | + diff --git a/submodules/network/internet-gateway.tf b/submodules/network/internet-gateway.tf new file mode 100644 index 00000000..a400fa48 --- /dev/null +++ b/submodules/network/internet-gateway.tf @@ -0,0 +1,20 @@ +resource "aws_internet_gateway" "igw" { + # vpc_id = local.vpc_id + tags = merge({ "Name" = "${var.deploy_id}-domino-igw" }, var.tags) +} + + +resource "aws_internet_gateway_attachment" "this" { + internet_gateway_id = aws_internet_gateway.igw.id + vpc_id = local.vpc_id +} + + +resource "aws_eip" "public" { + for_each = { for sb in var.public_subnets : sb.name => sb } + network_border_group = var.region + public_ipv4_pool = "amazon" + vpc = true + tags = merge({ "Name" = each.value.name }, var.tags) + depends_on = [aws_internet_gateway.igw] +} diff --git a/submodules/network/main.tf b/submodules/network/main.tf new file mode 100644 index 00000000..e69de29b diff --git a/submodules/network/nat-gateway.tf b/submodules/network/nat-gateway.tf new file mode 100644 index 00000000..2e1e2d4c --- /dev/null +++ b/submodules/network/nat-gateway.tf @@ -0,0 +1,8 @@ +resource "aws_nat_gateway" "ngw" { + for_each = { for sb in var.public_subnets : sb.zone => sb } + allocation_id = aws_eip.public[each.value.name].allocation_id + connectivity_type = "public" + subnet_id = aws_subnet.public[each.value.name].id + tags = merge({ "Name" = each.value.name }, { "zone" = each.value.zone }, var.tags) + depends_on = [aws_internet_gateway.igw] +} diff --git a/submodules/network/outputs.tf b/submodules/network/outputs.tf new file mode 100644 index 00000000..5c6e8d5b --- /dev/null +++ b/submodules/network/outputs.tf @@ -0,0 +1,32 @@ +output "vpc_id" { + description = "VPC id." + value = local.vpc_id +} + +output "private_subnets" { + description = "Private subnets object. Adds id to the object" + value = [for sb in var.private_subnets : + { + id = aws_subnet.private[sb.name].id + name = sb.name + cidr_block = sb.cidr_block + zone = sb.zone + zone_id = sb.zone_id + type = sb.type + } + ] +} + +output "public_subnets" { + description = "Public subnets object. Adds id to the object" + value = [for sb in var.public_subnets : + { + id = aws_subnet.public[sb.name].id + name = sb.name + cidr_block = sb.cidr_block + zone = sb.zone + zone_id = sb.zone_id + type = sb.type + } + ] +} diff --git a/submodules/network/route-tables.tf b/submodules/network/route-tables.tf new file mode 100644 index 00000000..387b23e2 --- /dev/null +++ b/submodules/network/route-tables.tf @@ -0,0 +1,47 @@ +resource "aws_route_table" "public" { + for_each = { for sb in var.public_subnets : sb.name => sb } + route { + cidr_block = "0.0.0.0/0" + gateway_id = aws_internet_gateway.igw.id + } + vpc_id = local.vpc_id + tags = merge( + { + "Name" = each.value.name, + "kubernetes.io/role/elb" = "1", + "kubernetes.io/cluster/${var.deploy_id}" = "shared", + }, + var.tags + ) + +} + +resource "aws_route_table_association" "public" { + for_each = { for sb in var.public_subnets : sb.name => sb } + subnet_id = aws_subnet.public[each.value.name].id + route_table_id = aws_route_table.public[each.value.name].id +} + +resource "aws_route_table" "private" { + for_each = { for sb in var.private_subnets : sb.name => sb } + route { + cidr_block = "0.0.0.0/0" + nat_gateway_id = aws_nat_gateway.ngw[each.value.zone].id + } + vpc_id = local.vpc_id + tags = merge( + { + "Name" = each.value.name, + "kubernetes.io/role/internal-elb" = "1", + "kubernetes.io/cluster/${var.deploy_id}" = "shared", + }, + var.tags + ) + +} + +resource "aws_route_table_association" "private" { + for_each = { for sb in var.private_subnets : sb.name => sb } + subnet_id = aws_subnet.private[each.value.name].id + route_table_id = aws_route_table.private[each.value.name].id +} diff --git a/submodules/network/subnets.tf b/submodules/network/subnets.tf new file mode 100644 index 00000000..29229669 --- /dev/null +++ b/submodules/network/subnets.tf @@ -0,0 +1,31 @@ +resource "aws_subnet" "public" { + for_each = { for sb in var.public_subnets : sb.name => sb } + + availability_zone_id = each.value.zone_id + vpc_id = local.vpc_id + cidr_block = each.value.cidr_block + tags = merge( + { + "Name" = each.value.name, + "kubernetes.io/role/elb" = "1", + "kubernetes.io/cluster/${var.deploy_id}" = "shared", + }, + var.tags + ) +} + +resource "aws_subnet" "private" { + for_each = { for sb in var.private_subnets : sb.name => sb } + + availability_zone_id = each.value.zone_id + vpc_id = local.vpc_id + cidr_block = each.value.cidr_block + tags = merge( + { + "Name" = each.value.name, + "kubernetes.io/role/internal-elb" = "1", + "kubernetes.io/cluster/${var.deploy_id}" = "shared", + }, + var.tags + ) +} diff --git a/submodules/network/variables.tf b/submodules/network/variables.tf new file mode 100644 index 00000000..b059202e --- /dev/null +++ b/submodules/network/variables.tf @@ -0,0 +1,65 @@ +variable "deploy_id" { + type = string + description = "Domino Deployment ID" + default = "" + + validation { + condition = can(regex("^[a-z-0-9]{3,32}$", var.deploy_id)) + error_message = "Argument deploy_id must: start with a letter, contain lowercase alphanumeric characters(can contain hyphens[-]) with length between 3 and 32 characters." + } +} + +variable "region" { + type = string + description = "AWS region for the deployment" +} + +variable "tags" { + type = map(string) + description = "Deployment tags" +} + +variable "base_cidr_block" { + type = string + description = "CIDR block to serve the main private and public subnets" + validation { + condition = ( + try(cidrhost(var.base_cidr_block, 0), null) == regex("^(.*)/", var.base_cidr_block)[0] && + try(cidrnetmask(var.base_cidr_block), null) == "255.255.0.0" + ) + error_message = "Argument base_cidr_block must be a valid CIDR block." + } +} + +variable "public_subnets" { + description = "Public subnets object" + type = list(object({ + cidr_block = string + name = string + type = string + zone = string + zone_id = string + })) +} + +variable "private_subnets" { + description = "Private subnets object" + type = list(object({ + cidr_block = string + name = string + type = string + zone = string + zone_id = string + })) +} + +variable "vpc_id" { + type = string + description = "VPC ID." + default = "" +} + +variable "monitoring_s3_bucket_arn" { + type = string + description = "Monitoring bucket for vpc flow logging" +} diff --git a/submodules/network/versions.tf b/submodules/network/versions.tf new file mode 100644 index 00000000..ca6fac6f --- /dev/null +++ b/submodules/network/versions.tf @@ -0,0 +1,10 @@ +terraform { + + required_version = ">= 1.0" + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 4.0" + } + } +} diff --git a/submodules/network/vpc.tf b/submodules/network/vpc.tf new file mode 100644 index 00000000..1f2bc825 --- /dev/null +++ b/submodules/network/vpc.tf @@ -0,0 +1,86 @@ + +## Bring your own VPC +data "aws_vpc" "this" { + count = var.vpc_id != "" ? 1 : 0 + state = "available" + id = var.vpc_id +} + +resource "aws_vpc" "this" { + count = var.vpc_id != "" ? 0 : 1 + assign_generated_ipv6_cidr_block = "false" + cidr_block = var.base_cidr_block + enable_dns_hostnames = true + enable_dns_support = true + tags = merge({ "Name" = var.deploy_id }, var.tags) +} + +locals { + vpc_id = var.vpc_id != "" ? data.aws_vpc.this[0].id : aws_vpc.this[0].id +} + +resource "aws_vpc_endpoint" "s3" { + vpc_id = local.vpc_id + service_name = "com.amazonaws.${var.region}.s3" + + route_table_ids = concat( + [for s in aws_route_table.public : s.id], + [for s in aws_route_table.private : s.id] + ) + + tags = merge({ "Name" = "${var.deploy_id}-s3" }, var.tags) +} + +data "aws_network_acls" "default" { + vpc_id = local.vpc_id + + filter { + name = "default" + values = ["true"] + } +} + +resource "aws_default_network_acl" "default" { + default_network_acl_id = one(data.aws_network_acls.default.ids) + + egress { + action = "allow" + cidr_block = "0.0.0.0/0" + from_port = "0" + icmp_code = "0" + icmp_type = "0" + protocol = "-1" + rule_no = "100" + to_port = "0" + } + + ingress { + action = "allow" + cidr_block = "0.0.0.0/0" + from_port = "0" + icmp_code = "0" + icmp_type = "0" + protocol = "-1" + rule_no = "100" + to_port = "0" + } + + subnet_ids = concat( + [for s in aws_subnet.public : s.id], + [for s in aws_subnet.private : s.id] + ) + + lifecycle { + ignore_changes = [subnet_ids] + } + + tags = var.tags +} + +resource "aws_flow_log" "this" { + log_destination = var.monitoring_s3_bucket_arn + vpc_id = local.vpc_id + max_aggregation_interval = 600 + log_destination_type = "s3" + traffic_type = "REJECT" +} diff --git a/submodules/storage/README.md b/submodules/storage/README.md new file mode 100644 index 00000000..8da307fb --- /dev/null +++ b/submodules/storage/README.md @@ -0,0 +1,69 @@ +# storage + + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.0 | +| [aws](#requirement\_aws) | >= 4.0 | + +## Providers + +| Name | Version | +|------|---------| +| [aws](#provider\_aws) | 4.22.0 | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [aws_efs_access_point.eks](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/efs_access_point) | resource | +| [aws_efs_file_system.eks](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/efs_file_system) | resource | +| [aws_efs_mount_target.eks](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/efs_mount_target) | resource | +| [aws_s3_bucket.backups](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket) | resource | +| [aws_s3_bucket.blobs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket) | resource | +| [aws_s3_bucket.logs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket) | resource | +| [aws_s3_bucket.monitoring](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket) | resource | +| [aws_s3_bucket.registry](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket) | resource | +| [aws_s3_bucket_acl.monitoring](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_acl) | resource | +| [aws_s3_bucket_logging.buckets_logging](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_logging) | resource | +| [aws_s3_bucket_policy.buckets_policies](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_policy) | resource | +| [aws_s3_bucket_public_access_block.block_public_accss](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block) | resource | +| [aws_s3_bucket_request_payment_configuration.buckets_payer](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_request_payment_configuration) | resource | +| [aws_s3_bucket_server_side_encryption_configuration.buckets_encryption](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_server_side_encryption_configuration) | resource | +| [aws_s3_bucket_versioning.buckets_versioning](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_versioning) | resource | +| [aws_security_group.efs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group) | resource | +| [aws_security_group_rule.efs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource | +| [aws_canonical_user_id.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/canonical_user_id) | data source | +| [aws_elb_service_account.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/elb_service_account) | data source | +| [aws_iam_policy_document.backups](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_iam_policy_document.blobs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_iam_policy_document.logs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_iam_policy_document.monitoring](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_iam_policy_document.registry](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_route53_zone.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/route53_zone) | data source | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [deploy\_id](#input\_deploy\_id) | Domino Deployment ID | `string` | n/a | yes | +| [efs\_access\_point\_path](#input\_efs\_access\_point\_path) | Filesystem path for efs. | `string` | `"/domino"` | no | +| [route53\_hosted\_zone](#input\_route53\_hosted\_zone) | AWS Route53 Hosted zone. | `string` | n/a | yes | +| [subnets](#input\_subnets) | List of subnet ids to create EFS mount targets |
list(object({
name = string
id = string
cidr_block = string
}))
| n/a | yes | +| [tags](#input\_tags) | Deployment tags. | `map(string)` | n/a | yes | +| [vpc\_id](#input\_vpc\_id) | VPC ID | `string` | n/a | yes | + +## Outputs + +| Name | Description | +|------|-------------| +| [efs\_volume\_handle](#output\_efs\_volume\_handle) | EFS volume handle :: | +| [monitoring\_s3\_bucket\_arn](#output\_monitoring\_s3\_bucket\_arn) | Monitoring bucket arn | +| [s3\_buckets](#output\_s3\_buckets) | S3 buckets name and arn | + diff --git a/submodules/storage/efs.tf b/submodules/storage/efs.tf new file mode 100644 index 00000000..b234f188 --- /dev/null +++ b/submodules/storage/efs.tf @@ -0,0 +1,56 @@ +resource "aws_efs_file_system" "eks" { + encrypted = "true" + performance_mode = "generalPurpose" + provisioned_throughput_in_mibps = "0" + throughput_mode = "bursting" + + tags = merge({ "Name" = "${var.deploy_id}" }, var.tags) +} + +resource "aws_security_group" "efs" { + name = "${var.deploy_id}-efs" + description = "EFS security group" + vpc_id = var.vpc_id + + lifecycle { + create_before_destroy = true + } + tags = merge({ "Name" = "${var.deploy_id}-efs" }, var.tags) +} + +resource "aws_security_group_rule" "efs" { + security_group_id = aws_security_group.efs.id + protocol = "tcp" + from_port = 2049 + to_port = 2049 + type = "ingress" + description = "EFS access" + cidr_blocks = [for sb in var.subnets : sb.cidr_block] +} + +resource "aws_efs_mount_target" "eks" { + for_each = { for sb in var.subnets : sb.name => sb } + file_system_id = aws_efs_file_system.eks.id + security_groups = [aws_security_group.efs.id] + subnet_id = each.value.id +} + +resource "aws_efs_access_point" "eks" { + file_system_id = aws_efs_file_system.eks.id + + posix_user { + gid = "0" + uid = "0" + } + + root_directory { + creation_info { + owner_gid = "0" + owner_uid = "0" + permissions = "777" + } + + path = var.efs_access_point_path + } + tags = var.tags +} diff --git a/submodules/storage/main.tf b/submodules/storage/main.tf new file mode 100644 index 00000000..fd2935ac --- /dev/null +++ b/submodules/storage/main.tf @@ -0,0 +1,41 @@ +data "aws_route53_zone" "this" { + name = var.route53_hosted_zone + private_zone = false +} +data "aws_canonical_user_id" "current" {} +data "aws_elb_service_account" "this" {} + +locals { + s3_buckets = { + backups = { + bucket_name = aws_s3_bucket.backups.bucket + id = aws_s3_bucket.backups.id + policy_json = data.aws_iam_policy_document.backups.json + arn = aws_s3_bucket.backups.arn + } + blobs = { + bucket_name = aws_s3_bucket.blobs.bucket + id = aws_s3_bucket.blobs.id + policy_json = data.aws_iam_policy_document.blobs.json + arn = aws_s3_bucket.blobs.arn + } + logs = { + bucket_name = aws_s3_bucket.logs.bucket + id = aws_s3_bucket.logs.id + policy_json = data.aws_iam_policy_document.logs.json + arn = aws_s3_bucket.logs.arn + } + monitoring = { + bucket_name = aws_s3_bucket.monitoring.bucket + id = aws_s3_bucket.monitoring.id + policy_json = data.aws_iam_policy_document.monitoring.json + arn = aws_s3_bucket.monitoring.arn + } + registry = { + bucket_name = aws_s3_bucket.registry.bucket + id = aws_s3_bucket.registry.id + policy_json = data.aws_iam_policy_document.registry.json + arn = aws_s3_bucket.registry.arn + } + } +} diff --git a/submodules/storage/outputs.tf b/submodules/storage/outputs.tf new file mode 100644 index 00000000..071314c2 --- /dev/null +++ b/submodules/storage/outputs.tf @@ -0,0 +1,17 @@ +output "efs_volume_handle" { + description = "EFS volume handle ::" + value = "${aws_efs_access_point.eks.file_system_id}::${aws_efs_access_point.eks.id}" +} + +output "monitoring_s3_bucket_arn" { + description = "Monitoring bucket arn" + value = aws_s3_bucket.backups.arn +} + +output "s3_buckets" { + description = "S3 buckets name and arn" + value = [for b in local.s3_buckets : { + "bucket_name" = b.bucket_name, + "arn" = b.arn + }] +} diff --git a/submodules/storage/s3.tf b/submodules/storage/s3.tf new file mode 100644 index 00000000..afa8bebd --- /dev/null +++ b/submodules/storage/s3.tf @@ -0,0 +1,472 @@ + +resource "aws_s3_bucket" "backups" { + bucket = "${var.deploy_id}-backups" + force_destroy = "true" + hosted_zone_id = data.aws_route53_zone.this.zone_id + object_lock_enabled = "false" + tags = var.tags + + lifecycle { + ignore_changes = [ + hosted_zone_id, + ] + } +} + +data "aws_iam_policy_document" "backups" { + statement { + effect = "Deny" + + resources = [ + "arn:aws:s3:::${aws_s3_bucket.backups.bucket}", + "arn:aws:s3:::${aws_s3_bucket.backups.bucket}/*", + ] + + actions = ["s3:*"] + + condition { + test = "Bool" + variable = "aws:SecureTransport" + values = ["false"] + } + + principals { + type = "AWS" + identifiers = ["*"] + } + } + + statement { + sid = "DenyIncorrectEncryptionHeader" + effect = "Deny" + resources = ["arn:aws:s3:::${aws_s3_bucket.backups.bucket}/*"] + actions = ["s3:PutObject"] + + condition { + test = "StringNotEquals" + variable = "s3:x-amz-server-side-encryption" + values = ["AES256"] + } + + principals { + type = "AWS" + identifiers = ["*"] + } + } + + statement { + sid = "DenyUnEncryptedObjectUploads" + effect = "Deny" + resources = ["arn:aws:s3:::${aws_s3_bucket.backups.bucket}/*"] + actions = ["s3:PutObject"] + + condition { + test = "Null" + variable = "s3:x-amz-server-side-encryption" + values = ["true"] + } + + principals { + type = "AWS" + identifiers = ["*"] + } + } +} + +resource "aws_s3_bucket" "blobs" { + bucket = "${var.deploy_id}-blobs" + force_destroy = "true" + hosted_zone_id = data.aws_route53_zone.this.zone_id + object_lock_enabled = "false" + tags = var.tags + + lifecycle { + ignore_changes = [ + hosted_zone_id, + ] + } +} + +data "aws_iam_policy_document" "blobs" { + statement { + + effect = "Deny" + + resources = [ + "arn:aws:s3:::${aws_s3_bucket.blobs.bucket}", + "arn:aws:s3:::${aws_s3_bucket.blobs.bucket}/*", + ] + + actions = ["s3:*"] + + condition { + test = "Bool" + variable = "aws:SecureTransport" + values = ["false"] + } + + principals { + type = "AWS" + identifiers = ["*"] + } + } + + + statement { + sid = "DenyIncorrectEncryptionHeader" + effect = "Deny" + resources = ["arn:aws:s3:::${aws_s3_bucket.blobs.bucket}/*"] + actions = ["s3:PutObject"] + + condition { + test = "StringNotEquals" + variable = "s3:x-amz-server-side-encryption" + values = ["AES256"] + } + + principals { + type = "AWS" + identifiers = ["*"] + } + } + + statement { + sid = "DenyUnEncryptedObjectUploads" + effect = "Deny" + resources = ["arn:aws:s3:::${aws_s3_bucket.blobs.bucket}/*"] + actions = ["s3:PutObject"] + + condition { + test = "Null" + variable = "s3:x-amz-server-side-encryption" + values = ["true"] + } + + principals { + type = "AWS" + identifiers = ["*"] + } + } +} + +resource "aws_s3_bucket" "logs" { + bucket = "${var.deploy_id}-logs" + force_destroy = "true" + hosted_zone_id = data.aws_route53_zone.this.zone_id + object_lock_enabled = "false" + tags = var.tags + + lifecycle { + ignore_changes = [ + hosted_zone_id, + ] + } +} + +data "aws_iam_policy_document" "logs" { + statement { + + effect = "Deny" + + resources = [ + "arn:aws:s3:::${aws_s3_bucket.logs.bucket}", + "arn:aws:s3:::${aws_s3_bucket.logs.bucket}/*", + ] + + actions = ["s3:*"] + + condition { + test = "Bool" + variable = "aws:SecureTransport" + values = ["false"] + } + + principals { + type = "AWS" + identifiers = ["*"] + } + } + + statement { + sid = "DenyIncorrectEncryptionHeader" + effect = "Deny" + resources = ["arn:aws:s3:::${aws_s3_bucket.logs.bucket}/*"] + actions = ["s3:PutObject"] + + condition { + test = "StringNotEquals" + variable = "s3:x-amz-server-side-encryption" + values = ["AES256"] + } + + principals { + type = "AWS" + identifiers = ["*"] + } + } + + statement { + sid = "DenyUnEncryptedObjectUploads" + effect = "Deny" + resources = ["arn:aws:s3:::${aws_s3_bucket.logs.bucket}/*"] + actions = ["s3:PutObject"] + + condition { + test = "Null" + variable = "s3:x-amz-server-side-encryption" + values = ["true"] + } + + principals { + type = "AWS" + identifiers = ["*"] + } + } +} + +resource "aws_s3_bucket" "monitoring" { + bucket = "${var.deploy_id}-monitoring" + force_destroy = "true" + hosted_zone_id = data.aws_route53_zone.this.zone_id + object_lock_enabled = "false" + tags = var.tags + + lifecycle { + ignore_changes = [ + hosted_zone_id, + ] + } +} + +data "aws_iam_policy_document" "monitoring" { + statement { + + effect = "Deny" + + resources = [ + "arn:aws:s3:::${aws_s3_bucket.monitoring.bucket}", + "arn:aws:s3:::${aws_s3_bucket.monitoring.bucket}/*", + ] + + actions = ["s3:*"] + + condition { + test = "Bool" + variable = "aws:SecureTransport" + values = ["false"] + } + + principals { + type = "AWS" + identifiers = ["*"] + } + } + + statement { + sid = "" + effect = "Allow" + resources = ["arn:aws:s3:::${aws_s3_bucket.monitoring.bucket}/*"] + + actions = [ + "s3:PutObject*", + "s3:Abort*", + ] + + principals { + type = "AWS" + identifiers = [data.aws_elb_service_account.this.arn] + } + } + + statement { + sid = "AWSLogDeliveryWrite" + effect = "Allow" + resources = ["arn:aws:s3:::${aws_s3_bucket.monitoring.bucket}/*"] + actions = ["s3:PutObject"] + + condition { + test = "StringEquals" + variable = "s3:x-amz-acl" + values = ["bucket-owner-full-control"] + } + + principals { + type = "Service" + identifiers = ["delivery.logs.amazonaws.com"] + } + } + + statement { + sid = "AWSLogDeliveryCheck" + effect = "Allow" + resources = ["arn:aws:s3:::${aws_s3_bucket.monitoring.bucket}"] + + actions = [ + "s3:GetBucketAcl", + "s3:ListBucket", + ] + + principals { + type = "Service" + identifiers = ["delivery.logs.amazonaws.com"] + } + } +} + +resource "aws_s3_bucket_acl" "monitoring" { + bucket = aws_s3_bucket.monitoring.id + + access_control_policy { + + owner { + id = data.aws_canonical_user_id.current.id + } + + grant { + grantee { + type = "CanonicalUser" + id = data.aws_canonical_user_id.current.id + } + permission = "FULL_CONTROL" + } + + grant { + grantee { + type = "Group" + uri = "http://acs.amazonaws.com/groups/s3/LogDelivery" + } + permission = "WRITE" + } + + grant { + grantee { + type = "Group" + uri = "http://acs.amazonaws.com/groups/s3/LogDelivery" + } + permission = "READ_ACP" + } + } +} + +resource "aws_s3_bucket" "registry" { + bucket = "${var.deploy_id}-registry" + force_destroy = "true" + hosted_zone_id = data.aws_route53_zone.this.zone_id + object_lock_enabled = "false" + tags = var.tags + + lifecycle { + ignore_changes = [ + hosted_zone_id, + ] + } +} + +data "aws_iam_policy_document" "registry" { + statement { + effect = "Deny" + resources = [ + "arn:aws:s3:::${aws_s3_bucket.registry.bucket}", + "arn:aws:s3:::${aws_s3_bucket.registry.bucket}/*", + ] + + actions = ["s3:*"] + + condition { + test = "Bool" + variable = "aws:SecureTransport" + values = ["false"] + } + + principals { + type = "AWS" + identifiers = ["*"] + } + } + + statement { + sid = "DenyIncorrectEncryptionHeader" + effect = "Deny" + resources = ["arn:aws:s3:::${aws_s3_bucket.registry.bucket}/*"] + actions = ["s3:PutObject"] + + condition { + test = "StringNotEquals" + variable = "s3:x-amz-server-side-encryption" + values = ["AES256"] + } + + principals { + type = "AWS" + identifiers = ["*"] + } + } + + statement { + sid = "DenyUnEncryptedObjectUploads" + effect = "Deny" + resources = ["arn:aws:s3:::${aws_s3_bucket.registry.bucket}/*"] + actions = ["s3:PutObject"] + + condition { + test = "Null" + variable = "s3:x-amz-server-side-encryption" + values = ["true"] + } + + principals { + type = "AWS" + identifiers = ["*"] + } + } +} + +resource "aws_s3_bucket_policy" "buckets_policies" { + for_each = local.s3_buckets + bucket = each.value.id + policy = each.value.policy_json +} + +resource "aws_s3_bucket_server_side_encryption_configuration" "buckets_encryption" { + for_each = local.s3_buckets + + bucket = each.value.bucket_name + rule { + apply_server_side_encryption_by_default { + sse_algorithm = "AES256" + } + bucket_key_enabled = "false" + } +} + +resource "aws_s3_bucket_request_payment_configuration" "buckets_payer" { + for_each = local.s3_buckets + bucket = each.value.bucket_name + payer = "BucketOwner" +} + +resource "aws_s3_bucket_logging" "buckets_logging" { + for_each = { for k, v in local.s3_buckets : k => v if v.bucket_name != aws_s3_bucket.monitoring.bucket } + bucket = each.value.id + target_bucket = aws_s3_bucket.monitoring.bucket + target_prefix = "${each.value.bucket_name}/" +} + +resource "aws_s3_bucket_versioning" "buckets_versioning" { + for_each = local.s3_buckets + bucket = each.value.id + + versioning_configuration { + status = "Enabled" + mfa_delete = "Disabled" + } +} + +resource "aws_s3_bucket_public_access_block" "block_public_accss" { + for_each = local.s3_buckets + bucket = each.value.id + block_public_acls = true + block_public_policy = true + ignore_public_acls = true + restrict_public_buckets = true +} diff --git a/submodules/storage/variables.tf b/submodules/storage/variables.tf new file mode 100755 index 00000000..113067b8 --- /dev/null +++ b/submodules/storage/variables.tf @@ -0,0 +1,42 @@ +variable "deploy_id" { + type = string + description = "Domino Deployment ID" + + validation { + condition = can(regex("^[a-z-0-9]{3,32}$", var.deploy_id)) + error_message = "Argument deploy_id must: start with a letter, contain lowercase alphanumeric characters(can contain hyphens[-]) with length between 3 and 32 characters." + } +} + + +variable "efs_access_point_path" { + type = string + description = "Filesystem path for efs." + default = "/domino" + +} + +variable "route53_hosted_zone" { + type = string + description = "AWS Route53 Hosted zone." +} + +variable "tags" { + type = map(string) + description = "Deployment tags." +} + +variable "subnets" { + type = list(object({ + name = string + id = string + cidr_block = string + })) + description = "List of subnet ids to create EFS mount targets" +} + +variable "vpc_id" { + type = string + description = "VPC ID" + +} diff --git a/submodules/storage/versions.tf b/submodules/storage/versions.tf new file mode 100644 index 00000000..ca6fac6f --- /dev/null +++ b/submodules/storage/versions.tf @@ -0,0 +1,10 @@ +terraform { + + required_version = ">= 1.0" + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 4.0" + } + } +} diff --git a/submodules/subnets-cidr/README.md b/submodules/subnets-cidr/README.md new file mode 100644 index 00000000..9c6a906d --- /dev/null +++ b/submodules/subnets-cidr/README.md @@ -0,0 +1,53 @@ +## Example +```hcl + module "subnets" { + source = "../submodules/cidr-subnets" + availability_zones = var.availability_zones + pod_base_cidr_block = var.pod_base_cidr_block + base_cidr_block = var.base_cidr_block + public_cidr_network_bits = var.public_cidr_mask + private_cidr_network_bits = var.private_cidr_mask + subnet_name_prefix = var.deploy_id + } + + output "subnets" { + value = module.subnets_cidr + } +``` + + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.0 | + +## Providers + +No providers. + +## Modules + +No modules. + +## Resources + +No resources. + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [availability\_zones](#input\_availability\_zones) | Map of availability zone: names - > ids where the subnets will be created | `map(string)` |
{
"us-west-2a": "usw2-az1",
"us-west-2b": "usw2-az2",
"us-west-2c": "usw2-az3"
}
| no | +| [base\_cidr\_block](#input\_base\_cidr\_block) | CIDR block to serve the main private and public subnets | `string` | `"10.0.0.0/16"` | no | +| [private\_cidr\_network\_bits](#input\_private\_cidr\_network\_bits) | Number of network bits to allocate to the public subnet. i.e /19 -> 8,190 IPs | `number` | `19` | no | +| [public\_cidr\_network\_bits](#input\_public\_cidr\_network\_bits) | Number of network bits to allocate to the public subnet. i.e /27 -> 30 IPs | `number` | `27` | no | +| [subnet\_name\_prefix](#input\_subnet\_name\_prefix) | String to serve as a prefix/identifier when naming the subnets | `string` | n/a | yes | + +## Outputs + +| Name | Description | +|------|-------------| +| [private\_subnets](#output\_private\_subnets) | Map containing the CIDR information for the private subnets | +| [public\_subnets](#output\_public\_subnets) | Map containing the CIDR information for the public subnets | + diff --git a/submodules/subnets-cidr/main.tf b/submodules/subnets-cidr/main.tf new file mode 100644 index 00000000..0b879869 --- /dev/null +++ b/submodules/subnets-cidr/main.tf @@ -0,0 +1,40 @@ +locals { + availability_zones = var.availability_zones + availability_zones_number = length(local.availability_zones) + + ## Calculating public and private subnets based on the base base cidr and desired network bits + base_cidr_network_bits = tonumber(regex("[^/]*$", var.base_cidr_block)) + ## We have one Cidr to carve the nw bits for both pvt and public subnets + ## `...local.availability_zones_number * 2)` --> we have 2 types private and public subnets + new_bits_list = [for n in range(0, local.availability_zones_number * 2) : (n % 2 == 0 ? var.private_cidr_network_bits - local.base_cidr_network_bits : var.public_cidr_network_bits - local.base_cidr_network_bits)] + subnets_cidr_blocks = cidrsubnets(var.base_cidr_block, local.new_bits_list...) + + ## Match the public subnet var to the list of cidr blocks + public_subnets_cidr_blocks = [for sn in local.subnets_cidr_blocks : sn if length(regexall(".*/${var.public_cidr_network_bits}.*", sn)) > 0] + ## Match the private subnet var to the list of cidr blocks + private_subnets_cidr_blocks = [for sn in local.subnets_cidr_blocks : sn if length(regexall(".*/${var.private_cidr_network_bits}.*", sn)) > 0] + + ## Get the public subnets by matching the mask and populating its params + public_subnets = [ + for i, sn in local.public_subnets_cidr_blocks : + { + "cidr_block" = sn, + "zone" = element(keys(local.availability_zones), i % floor(i / length(local.availability_zones))), + "zone_id" = element(values(local.availability_zones), i % floor(i / length(local.availability_zones))), + "name" = "${var.subnet_name_prefix}-PublicSubnet-${element(keys(local.availability_zones), i % floor(i / length(local.availability_zones)))}-${i + 1}", + "type" = "public" + } + ] + + ## Get the private subnets by matching the mask and populating its params + private_subnets = [ + for i, sn in local.private_subnets_cidr_blocks : + { + "cidr_block" = sn, + "zone" = element(keys(local.availability_zones), i % floor(i / length(local.availability_zones))), + "zone_id" = element(values(local.availability_zones), i % floor(i / length(local.availability_zones))), + "name" = "${var.subnet_name_prefix}-PrivateSubnet-${element(keys(local.availability_zones), i % floor(i / length(local.availability_zones)))}-${i + 1}", + "type" = "private" + } + ] +} diff --git a/submodules/subnets-cidr/outputs.tf b/submodules/subnets-cidr/outputs.tf new file mode 100644 index 00000000..ece2060f --- /dev/null +++ b/submodules/subnets-cidr/outputs.tf @@ -0,0 +1,25 @@ +output "public_subnets" { + description = "Map containing the CIDR information for the public subnets" + value = [for k, v in local.public_subnets : + { + name = v.name + cidr_block = v.cidr_block + zone = v.zone + zone_id = v.zone_id + type = v.type + } + ] +} + +output "private_subnets" { + description = "Map containing the CIDR information for the private subnets" + value = [for k, v in local.private_subnets : + { + name = v.name + cidr_block = v.cidr_block + zone = v.zone + zone_id = v.zone_id + type = v.type + } + ] +} diff --git a/submodules/subnets-cidr/variables.tf b/submodules/subnets-cidr/variables.tf new file mode 100644 index 00000000..bed5210b --- /dev/null +++ b/submodules/subnets-cidr/variables.tf @@ -0,0 +1,68 @@ +variable "availability_zones" { + type = map(string) + + default = { + "us-west-2a" = "usw2-az1", + "us-west-2b" = "usw2-az2", + "us-west-2c" = "usw2-az3" + } + + description = "Map of availability zone: names - > ids where the subnets will be created" + validation { + condition = ( + length(compact(keys(var.availability_zones))) == length(compact(keys(var.availability_zones))) && + length(compact(values(var.availability_zones))) == length(compact(values(var.availability_zones))) && + length(distinct(keys(var.availability_zones))) == length(keys(var.availability_zones)) && + length(distinct(values(var.availability_zones))) == length(values(var.availability_zones)) + ) + error_message = "Argument availability_zones must not contain any duplicate/empty key or value." + } +} + +# variable "pod_base_cidr_block" { +# type = string +# default = "100.164.0.0/16" +# description = "CIDR block to serve the pods subnets" +# validation { +# condition = ( +# try(cidrhost(var.pod_base_cidr_block, 0), null) == regex("^(.*)/", var.pod_base_cidr_block)[0] && +# try(cidrnetmask(var.pod_base_cidr_block), null) == "255.255.0.0" +# ) +# error_message = "Argument pod_base_cidr_block must be a valid CIDR block." +# } +# } + +variable "base_cidr_block" { + type = string + default = "10.0.0.0/16" + description = "CIDR block to serve the main private and public subnets" + validation { + condition = ( + try(cidrhost(var.base_cidr_block, 0), null) == regex("^(.*)/", var.base_cidr_block)[0] && + try(cidrnetmask(var.base_cidr_block), null) == "255.255.0.0" + ) + error_message = "Argument base_cidr_block must be a valid CIDR block." + } +} + +variable "public_cidr_network_bits" { + type = number + description = "Number of network bits to allocate to the public subnet. i.e /27 -> 30 IPs" + default = 27 +} + +variable "private_cidr_network_bits" { + type = number + description = "Number of network bits to allocate to the public subnet. i.e /19 -> 8,190 IPs" + default = 19 +} + +variable "subnet_name_prefix" { + type = string + description = "String to serve as a prefix/identifier when naming the subnets" + + validation { + condition = can(regex("^[a-z-0-9]{3,32}$", var.subnet_name_prefix)) + error_message = "Argument deploy_id must: start with a letter, contain lowercase alphanumeric characters(can contain hyphens[-]) with length between 3 and 32 characters." + } +} diff --git a/submodules/subnets-cidr/versions.tf b/submodules/subnets-cidr/versions.tf new file mode 100644 index 00000000..7117131f --- /dev/null +++ b/submodules/subnets-cidr/versions.tf @@ -0,0 +1,3 @@ +terraform { + required_version = ">= 1.0" +} diff --git a/terraform_tflint.txt b/terraform_tflint.txt new file mode 100644 index 00000000..e69de29b diff --git a/terraform_tfsec.txt b/terraform_tfsec.txt new file mode 100644 index 00000000..5dbe38d8 --- /dev/null +++ b/terraform_tfsec.txt @@ -0,0 +1,4630 @@ +Terraform validate with tfsec............................................Failed +- hook id: terraform_tfsec +- exit code: 1 + +Results #1-2 HIGH IAM policy document uses sensitive action 'ec2:CreateTags' on wildcarded resource 'arn:aws:ec2:*:*:volume/*' (2 similar results) +──────────────────────────────────────────────────────────────────────────────── + submodules/eks/iam.tf Lines 149-152 +───────┬──────────────────────────────────────────────────────────────────────── + 149 │  resources = [ + 150 │  "arn:aws:ec2:*:*:volume/*", + 151 │  "arn:aws:ec2:*:*:snapshot/*", + 152 │  ] +───────┴──────────────────────────────────────────────────────────────────────── + Individual Causes + - /Users/miguel.harmant/src/dominodatalab/terraform-aws-eks/main.tf:74-89 (module.eks) + - /Users/miguel.harmant/src/dominodatalab/terraform-aws-eks/main.tf:74-89 (module.eks) +──────────────────────────────────────────────────────────────────────────────── +  ID aws-iam-no-policy-wildcards +  Impact Overly permissive policies may grant access to sensitive resources + Resolution Specify the exact permissions required, and to which resources they should apply instead of using wildcards. + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/iam/no-policy-wildcards/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document +──────────────────────────────────────────────────────────────────────────────── + + +Results #3-4 HIGH IAM policy document uses sensitive action 'ec2:DeleteTags' on wildcarded resource 'arn:aws:ec2:*:*:volume/*' (2 similar results) +──────────────────────────────────────────────────────────────────────────────── + submodules/eks/iam.tf Lines 171-174 +───────┬──────────────────────────────────────────────────────────────────────── + 171 │  resources = [ + 172 │  "arn:aws:ec2:*:*:volume/*", + 173 │  "arn:aws:ec2:*:*:snapshot/*", + 174 │  ] +───────┴──────────────────────────────────────────────────────────────────────── + Individual Causes + - /Users/miguel.harmant/src/dominodatalab/terraform-aws-eks/main.tf:74-89 (module.eks) + - /Users/miguel.harmant/src/dominodatalab/terraform-aws-eks/main.tf:74-89 (module.eks) +──────────────────────────────────────────────────────────────────────────────── +  ID aws-iam-no-policy-wildcards +  Impact Overly permissive policies may grant access to sensitive resources + Resolution Specify the exact permissions required, and to which resources they should apply instead of using wildcards. + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/iam/no-policy-wildcards/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document +──────────────────────────────────────────────────────────────────────────────── + + +Result #5 HIGH IAM policy document uses sensitive action 'ec2:DeleteVolume' on wildcarded resource '*'  +──────────────────────────────────────────────────────────────────────────────── + submodules/eks/iam.tf Line 195 +───────┬──────────────────────────────────────────────────────────────────────── + 192 │  statement { + 193 │  + 194 │  effect = "Allow" + 195 │  resources = ["*"] + 196 │  + 197 │  actions = [ + 198 │  "ec2:DeleteVolume", + 199 │  "ec2:DeleteSnapshot", + 200 │  ] + 201 │  + 202 │  condition { + 203 │  test = "StringLike" + 204 │  variable = "aws:ResourceTag/KubernetesCluster" + 205 │  values = [var.deploy_id] + 206 │  } + 207 │  } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-iam-no-policy-wildcards +  Impact Overly permissive policies may grant access to sensitive resources + Resolution Specify the exact permissions required, and to which resources they should apply instead of using wildcards. + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/iam/no-policy-wildcards/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document +──────────────────────────────────────────────────────────────────────────────── + + +Result #6 HIGH IAM policy document uses sensitive action 'ec2:CreateSnapshot' on wildcarded resource '*'  +──────────────────────────────────────────────────────────────────────────────── + submodules/eks/iam.tf Line 247 +───────┬──────────────────────────────────────────────────────────────────────── + 244 │  statement { + 245 │  + 246 │  effect = "Allow" + 247 │  resources = ["*"] + 248 │  + 249 │  actions = [ + 250 │  "ec2:CreateSnapshot", + 251 │  "ec2:CreateTags", + 252 │  "ec2:DeleteSnapshot", + 253 │  "ec2:DeleteTags", + 254 │  "ec2:DescribeAvailabilityZones", + 255 │  "ec2:DescribeSnapshots", + 256 │  "ec2:DescribeTags", + 257 │  ] + 258 │  } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-iam-no-policy-wildcards +  Impact Overly permissive policies may grant access to sensitive resources + Resolution Specify the exact permissions required, and to which resources they should apply instead of using wildcards. + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/iam/no-policy-wildcards/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document +──────────────────────────────────────────────────────────────────────────────── + + +Result #7 HIGH IAM policy document uses sensitive action 's3:ListBucket' on wildcarded resource '*'  +──────────────────────────────────────────────────────────────────────────────── + submodules/eks/iam.tf Line 34 +───────┬──────────────────────────────────────────────────────────────────────── + 31 │  statement { + 32 │  + 33 │  effect = "Allow" + 34 │  resources = ["*"] + 35 │  + 36 │  actions = [ + 37 │  "s3:ListBucket", + 38 │  "s3:GetBucketLocation", + 39 │  "s3:ListBucketMultipartUploads", + 40 │  ] + 41 │  } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-iam-no-policy-wildcards +  Impact Overly permissive policies may grant access to sensitive resources + Resolution Specify the exact permissions required, and to which resources they should apply instead of using wildcards. + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/iam/no-policy-wildcards/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document +──────────────────────────────────────────────────────────────────────────────── + + +Results #8-11 HIGH IAM policy document uses sensitive action 's3:PutObject' on wildcarded resource 'arn:aws:s3:::' (4 similar results) +──────────────────────────────────────────────────────────────────────────────── + submodules/eks/iam.tf Lines 47-52 +───────┬──────────────────────────────────────────────────────────────────────── + 47 │  resources = [ + 48 │  "arn:aws:s3:::${var.deploy_id}-blobs*", + 49 │  "arn:aws:s3:::${var.deploy_id}-logs*", + 50 │  "arn:aws:s3:::${var.deploy_id}-backups*", + 51 │  "arn:aws:s3:::${var.deploy_id}-registry*", + 52 │  ] +───────┴──────────────────────────────────────────────────────────────────────── + Individual Causes + - /Users/miguel.harmant/src/dominodatalab/terraform-aws-eks/main.tf:74-89 (module.eks) + - /Users/miguel.harmant/src/dominodatalab/terraform-aws-eks/main.tf:74-89 (module.eks) + - /Users/miguel.harmant/src/dominodatalab/terraform-aws-eks/main.tf:74-89 (module.eks) + - /Users/miguel.harmant/src/dominodatalab/terraform-aws-eks/main.tf:74-89 (module.eks) +──────────────────────────────────────────────────────────────────────────────── +  ID aws-iam-no-policy-wildcards +  Impact Overly permissive policies may grant access to sensitive resources + Resolution Specify the exact permissions required, and to which resources they should apply instead of using wildcards. + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/iam/no-policy-wildcards/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document +──────────────────────────────────────────────────────────────────────────────── + + +Result #12 HIGH IAM policy document uses sensitive action 'autoscaling:SetDesiredCapacity' on wildcarded resource '*'  +──────────────────────────────────────────────────────────────────────────────── + submodules/eks/iam.tf Line 87 +───────┬──────────────────────────────────────────────────────────────────────── + 84 │  statement { + 85 │  + 86 │  effect = "Allow" + 87 │  resources = ["*"] + 88 │  + 89 │  actions = [ + 90 │  "autoscaling:DescribeAutoScalingInstances", + 91 │  "autoscaling:SetDesiredCapacity", + 92 │  "autoscaling:TerminateInstanceInAutoScalingGroup", + 93 │  ] + 94 │  + 95 │  condition { + 96 │  test = "StringEquals" + 97 │  variable = "autoscaling:ResourceTag/eks:cluster-name" + 98 │  values = [var.deploy_id] + 99 │  } + 100 │  } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-iam-no-policy-wildcards +  Impact Overly permissive policies may grant access to sensitive resources + Resolution Specify the exact permissions required, and to which resources they should apply instead of using wildcards. + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/iam/no-policy-wildcards/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document +──────────────────────────────────────────────────────────────────────────────── + + +Result #13 HIGH No public access block so not blocking public acls  +──────────────────────────────────────────────────────────────────────────────── + submodules/storage/main.tf Lines 148-160 +───────┬──────────────────────────────────────────────────────────────────────── + 148 │ resource "aws_s3_bucket" "blobs" { + 149 │  bucket = "${var.deploy_id}-blobs" + 150 │  force_destroy = "false" + 151 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 152 │  object_lock_enabled = "false" + 153 │  tags = var.tags + 154 │  + 155 │  lifecycle { + 156 │  ignore_changes = [ + 157 │  hosted_zone_id, + 158 │  ] + 159 │  } + 160 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-block-public-acls +  Impact PUT calls with public ACLs specified can make objects public + Resolution Enable blocking any PUT calls with a public ACL specified + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/block-public-acls/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block#block_public_acls +──────────────────────────────────────────────────────────────────────────────── + + +Result #14 HIGH No public access block so not blocking public policies  +──────────────────────────────────────────────────────────────────────────────── + submodules/storage/main.tf Lines 148-160 +───────┬──────────────────────────────────────────────────────────────────────── + 148 │ resource "aws_s3_bucket" "blobs" { + 149 │  bucket = "${var.deploy_id}-blobs" + 150 │  force_destroy = "false" + 151 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 152 │  object_lock_enabled = "false" + 153 │  tags = var.tags + 154 │  + 155 │  lifecycle { + 156 │  ignore_changes = [ + 157 │  hosted_zone_id, + 158 │  ] + 159 │  } + 160 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-block-public-policy +  Impact Users could put a policy that allows public access + Resolution Prevent policies that allow public access being PUT + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/block-public-policy/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block#block_public_policy +──────────────────────────────────────────────────────────────────────────────── + + +Result #15 HIGH Bucket does not have encryption enabled  +──────────────────────────────────────────────────────────────────────────────── + submodules/storage/main.tf Lines 148-160 +───────┬──────────────────────────────────────────────────────────────────────── + 148 │ resource "aws_s3_bucket" "blobs" { + 149 │  bucket = "${var.deploy_id}-blobs" + 150 │  force_destroy = "false" + 151 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 152 │  object_lock_enabled = "false" + 153 │  tags = var.tags + 154 │  + 155 │  lifecycle { + 156 │  ignore_changes = [ + 157 │  hosted_zone_id, + 158 │  ] + 159 │  } + 160 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-enable-bucket-encryption +  Impact The bucket objects could be read if compromised + Resolution Configure bucket encryption + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/enable-bucket-encryption/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket#enable-default-server-side-encryption +──────────────────────────────────────────────────────────────────────────────── + + +Result #16 HIGH No public access block so not ignoring public acls  +──────────────────────────────────────────────────────────────────────────────── + submodules/storage/main.tf Lines 148-160 +───────┬──────────────────────────────────────────────────────────────────────── + 148 │ resource "aws_s3_bucket" "blobs" { + 149 │  bucket = "${var.deploy_id}-blobs" + 150 │  force_destroy = "false" + 151 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 152 │  object_lock_enabled = "false" + 153 │  tags = var.tags + 154 │  + 155 │  lifecycle { + 156 │  ignore_changes = [ + 157 │  hosted_zone_id, + 158 │  ] + 159 │  } + 160 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-ignore-public-acls +  Impact PUT calls with public ACLs specified can make objects public + Resolution Enable ignoring the application of public ACLs in PUT calls + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/ignore-public-acls/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block#ignore_public_acls +──────────────────────────────────────────────────────────────────────────────── + + +Result #17 HIGH No public access block so not restricting public buckets  +──────────────────────────────────────────────────────────────────────────────── + submodules/storage/main.tf Lines 148-160 +───────┬──────────────────────────────────────────────────────────────────────── + 148 │ resource "aws_s3_bucket" "blobs" { + 149 │  bucket = "${var.deploy_id}-blobs" + 150 │  force_destroy = "false" + 151 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 152 │  object_lock_enabled = "false" + 153 │  tags = var.tags + 154 │  + 155 │  lifecycle { + 156 │  ignore_changes = [ + 157 │  hosted_zone_id, + 158 │  ] + 159 │  } + 160 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-no-public-buckets +  Impact Public buckets can be accessed by anyone + Resolution Limit the access to public buckets to only the owner or AWS Services (eg; CloudFront) + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/no-public-buckets/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block#restrict_public_buckets¡ +──────────────────────────────────────────────────────────────────────────────── + + +Result #18 HIGH Bucket does not encrypt data with a customer managed key.  +──────────────────────────────────────────────────────────────────────────────── + submodules/storage/main.tf Lines 148-160 +───────┬──────────────────────────────────────────────────────────────────────── + 148 │ resource "aws_s3_bucket" "blobs" { + 149 │  bucket = "${var.deploy_id}-blobs" + 150 │  force_destroy = "false" + 151 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 152 │  object_lock_enabled = "false" + 153 │  tags = var.tags + 154 │  + 155 │  lifecycle { + 156 │  ignore_changes = [ + 157 │  hosted_zone_id, + 158 │  ] + 159 │  } + 160 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-encryption-customer-key +  Impact Using AWS managed keys does not allow for fine grained control + Resolution Enable encryption using customer managed keys + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/encryption-customer-key/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket#enable-default-server-side-encryption +──────────────────────────────────────────────────────────────────────────────── + + +Result #19 HIGH No public access block so not blocking public acls  +──────────────────────────────────────────────────────────────────────────────── + submodules/storage/main.tf Lines 223-235 +───────┬──────────────────────────────────────────────────────────────────────── + 223 │ resource "aws_s3_bucket" "logs" { + 224 │  bucket = "${var.deploy_id}-logs" + 225 │  force_destroy = "false" + 226 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 227 │  object_lock_enabled = "false" + 228 │  tags = var.tags + 229 │  + 230 │  lifecycle { + 231 │  ignore_changes = [ + 232 │  hosted_zone_id, + 233 │  ] + 234 │  } + 235 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-block-public-acls +  Impact PUT calls with public ACLs specified can make objects public + Resolution Enable blocking any PUT calls with a public ACL specified + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/block-public-acls/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block#block_public_acls +──────────────────────────────────────────────────────────────────────────────── + + +Result #20 HIGH No public access block so not blocking public policies  +──────────────────────────────────────────────────────────────────────────────── + submodules/storage/main.tf Lines 223-235 +───────┬──────────────────────────────────────────────────────────────────────── + 223 │ resource "aws_s3_bucket" "logs" { + 224 │  bucket = "${var.deploy_id}-logs" + 225 │  force_destroy = "false" + 226 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 227 │  object_lock_enabled = "false" + 228 │  tags = var.tags + 229 │  + 230 │  lifecycle { + 231 │  ignore_changes = [ + 232 │  hosted_zone_id, + 233 │  ] + 234 │  } + 235 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-block-public-policy +  Impact Users could put a policy that allows public access + Resolution Prevent policies that allow public access being PUT + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/block-public-policy/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block#block_public_policy +──────────────────────────────────────────────────────────────────────────────── + + +Result #21 HIGH Bucket does not have encryption enabled  +──────────────────────────────────────────────────────────────────────────────── + submodules/storage/main.tf Lines 223-235 +───────┬──────────────────────────────────────────────────────────────────────── + 223 │ resource "aws_s3_bucket" "logs" { + 224 │  bucket = "${var.deploy_id}-logs" + 225 │  force_destroy = "false" + 226 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 227 │  object_lock_enabled = "false" + 228 │  tags = var.tags + 229 │  + 230 │  lifecycle { + 231 │  ignore_changes = [ + 232 │  hosted_zone_id, + 233 │  ] + 234 │  } + 235 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-enable-bucket-encryption +  Impact The bucket objects could be read if compromised + Resolution Configure bucket encryption + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/enable-bucket-encryption/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket#enable-default-server-side-encryption +──────────────────────────────────────────────────────────────────────────────── + + +Result #22 HIGH No public access block so not ignoring public acls  +──────────────────────────────────────────────────────────────────────────────── + submodules/storage/main.tf Lines 223-235 +───────┬──────────────────────────────────────────────────────────────────────── + 223 │ resource "aws_s3_bucket" "logs" { + 224 │  bucket = "${var.deploy_id}-logs" + 225 │  force_destroy = "false" + 226 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 227 │  object_lock_enabled = "false" + 228 │  tags = var.tags + 229 │  + 230 │  lifecycle { + 231 │  ignore_changes = [ + 232 │  hosted_zone_id, + 233 │  ] + 234 │  } + 235 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-ignore-public-acls +  Impact PUT calls with public ACLs specified can make objects public + Resolution Enable ignoring the application of public ACLs in PUT calls + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/ignore-public-acls/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block#ignore_public_acls +──────────────────────────────────────────────────────────────────────────────── + + +Result #23 HIGH No public access block so not restricting public buckets  +──────────────────────────────────────────────────────────────────────────────── + submodules/storage/main.tf Lines 223-235 +───────┬──────────────────────────────────────────────────────────────────────── + 223 │ resource "aws_s3_bucket" "logs" { + 224 │  bucket = "${var.deploy_id}-logs" + 225 │  force_destroy = "false" + 226 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 227 │  object_lock_enabled = "false" + 228 │  tags = var.tags + 229 │  + 230 │  lifecycle { + 231 │  ignore_changes = [ + 232 │  hosted_zone_id, + 233 │  ] + 234 │  } + 235 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-no-public-buckets +  Impact Public buckets can be accessed by anyone + Resolution Limit the access to public buckets to only the owner or AWS Services (eg; CloudFront) + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/no-public-buckets/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block#restrict_public_buckets¡ +──────────────────────────────────────────────────────────────────────────────── + + +Result #24 HIGH Bucket does not encrypt data with a customer managed key.  +──────────────────────────────────────────────────────────────────────────────── + submodules/storage/main.tf Lines 223-235 +───────┬──────────────────────────────────────────────────────────────────────── + 223 │ resource "aws_s3_bucket" "logs" { + 224 │  bucket = "${var.deploy_id}-logs" + 225 │  force_destroy = "false" + 226 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 227 │  object_lock_enabled = "false" + 228 │  tags = var.tags + 229 │  + 230 │  lifecycle { + 231 │  ignore_changes = [ + 232 │  hosted_zone_id, + 233 │  ] + 234 │  } + 235 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-encryption-customer-key +  Impact Using AWS managed keys does not allow for fine grained control + Resolution Enable encryption using customer managed keys + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/encryption-customer-key/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket#enable-default-server-side-encryption +──────────────────────────────────────────────────────────────────────────────── + + +Result #25 HIGH No public access block so not blocking public acls  +──────────────────────────────────────────────────────────────────────────────── + submodules/storage/main.tf Lines 313-325 +───────┬──────────────────────────────────────────────────────────────────────── + 313 │ resource "aws_s3_bucket" "monitoring" { + 314 │  bucket = "${var.deploy_id}-monitoring" + 315 │  force_destroy = "true" + 316 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 317 │  object_lock_enabled = "false" + 318 │  tags = var.tags + 319 │  + 320 │  lifecycle { + 321 │  ignore_changes = [ + 322 │  hosted_zone_id, + 323 │  ] + 324 │  } + 325 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-block-public-acls +  Impact PUT calls with public ACLs specified can make objects public + Resolution Enable blocking any PUT calls with a public ACL specified + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/block-public-acls/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block#block_public_acls +──────────────────────────────────────────────────────────────────────────────── + + +Result #26 HIGH No public access block so not blocking public policies  +──────────────────────────────────────────────────────────────────────────────── + submodules/storage/main.tf Lines 313-325 +───────┬──────────────────────────────────────────────────────────────────────── + 313 │ resource "aws_s3_bucket" "monitoring" { + 314 │  bucket = "${var.deploy_id}-monitoring" + 315 │  force_destroy = "true" + 316 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 317 │  object_lock_enabled = "false" + 318 │  tags = var.tags + 319 │  + 320 │  lifecycle { + 321 │  ignore_changes = [ + 322 │  hosted_zone_id, + 323 │  ] + 324 │  } + 325 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-block-public-policy +  Impact Users could put a policy that allows public access + Resolution Prevent policies that allow public access being PUT + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/block-public-policy/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block#block_public_policy +──────────────────────────────────────────────────────────────────────────────── + + +Result #27 HIGH Bucket does not have encryption enabled  +──────────────────────────────────────────────────────────────────────────────── + submodules/storage/main.tf Lines 313-325 +───────┬──────────────────────────────────────────────────────────────────────── + 313 │ resource "aws_s3_bucket" "monitoring" { + 314 │  bucket = "${var.deploy_id}-monitoring" + 315 │  force_destroy = "true" + 316 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 317 │  object_lock_enabled = "false" + 318 │  tags = var.tags + 319 │  + 320 │  lifecycle { + 321 │  ignore_changes = [ + 322 │  hosted_zone_id, + 323 │  ] + 324 │  } + 325 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-enable-bucket-encryption +  Impact The bucket objects could be read if compromised + Resolution Configure bucket encryption + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/enable-bucket-encryption/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket#enable-default-server-side-encryption +──────────────────────────────────────────────────────────────────────────────── + + +Result #28 HIGH No public access block so not ignoring public acls  +──────────────────────────────────────────────────────────────────────────────── + submodules/storage/main.tf Lines 313-325 +───────┬──────────────────────────────────────────────────────────────────────── + 313 │ resource "aws_s3_bucket" "monitoring" { + 314 │  bucket = "${var.deploy_id}-monitoring" + 315 │  force_destroy = "true" + 316 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 317 │  object_lock_enabled = "false" + 318 │  tags = var.tags + 319 │  + 320 │  lifecycle { + 321 │  ignore_changes = [ + 322 │  hosted_zone_id, + 323 │  ] + 324 │  } + 325 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-ignore-public-acls +  Impact PUT calls with public ACLs specified can make objects public + Resolution Enable ignoring the application of public ACLs in PUT calls + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/ignore-public-acls/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block#ignore_public_acls +──────────────────────────────────────────────────────────────────────────────── + + +Result #29 HIGH No public access block so not restricting public buckets  +──────────────────────────────────────────────────────────────────────────────── + submodules/storage/main.tf Lines 313-325 +───────┬──────────────────────────────────────────────────────────────────────── + 313 │ resource "aws_s3_bucket" "monitoring" { + 314 │  bucket = "${var.deploy_id}-monitoring" + 315 │  force_destroy = "true" + 316 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 317 │  object_lock_enabled = "false" + 318 │  tags = var.tags + 319 │  + 320 │  lifecycle { + 321 │  ignore_changes = [ + 322 │  hosted_zone_id, + 323 │  ] + 324 │  } + 325 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-no-public-buckets +  Impact Public buckets can be accessed by anyone + Resolution Limit the access to public buckets to only the owner or AWS Services (eg; CloudFront) + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/no-public-buckets/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block#restrict_public_buckets¡ +──────────────────────────────────────────────────────────────────────────────── + + +Result #30 HIGH Bucket does not encrypt data with a customer managed key.  +──────────────────────────────────────────────────────────────────────────────── + submodules/storage/main.tf Lines 313-325 +───────┬──────────────────────────────────────────────────────────────────────── + 313 │ resource "aws_s3_bucket" "monitoring" { + 314 │  bucket = "${var.deploy_id}-monitoring" + 315 │  force_destroy = "true" + 316 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 317 │  object_lock_enabled = "false" + 318 │  tags = var.tags + 319 │  + 320 │  lifecycle { + 321 │  ignore_changes = [ + 322 │  hosted_zone_id, + 323 │  ] + 324 │  } + 325 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-encryption-customer-key +  Impact Using AWS managed keys does not allow for fine grained control + Resolution Enable encryption using customer managed keys + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/encryption-customer-key/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket#enable-default-server-side-encryption +──────────────────────────────────────────────────────────────────────────────── + + +Result #31 HIGH No public access block so not blocking public acls  +──────────────────────────────────────────────────────────────────────────────── + submodules/storage/main.tf Lines 421-434 +───────┬──────────────────────────────────────────────────────────────────────── + 421 │ resource "aws_s3_bucket" "registry" { + 422 │  arn = "arn:aws:s3:::${var.deploy_id}-registry" + 423 │  bucket = "${var.deploy_id}-registry" + 424 │  force_destroy = "false" + 425 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 426 │  object_lock_enabled = "false" + 427 │  tags = var.tags + 428 │  + 429 │  lifecycle { + 430 │  ignore_changes = [ + 431 │  hosted_zone_id, + 432 │  ] + 433 │  } + 434 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-block-public-acls +  Impact PUT calls with public ACLs specified can make objects public + Resolution Enable blocking any PUT calls with a public ACL specified + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/block-public-acls/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block#block_public_acls +──────────────────────────────────────────────────────────────────────────────── + + +Result #32 HIGH No public access block so not blocking public policies  +──────────────────────────────────────────────────────────────────────────────── + submodules/storage/main.tf Lines 421-434 +───────┬──────────────────────────────────────────────────────────────────────── + 421 │ resource "aws_s3_bucket" "registry" { + 422 │  arn = "arn:aws:s3:::${var.deploy_id}-registry" + 423 │  bucket = "${var.deploy_id}-registry" + 424 │  force_destroy = "false" + 425 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 426 │  object_lock_enabled = "false" + 427 │  tags = var.tags + 428 │  + 429 │  lifecycle { + 430 │  ignore_changes = [ + 431 │  hosted_zone_id, + 432 │  ] + 433 │  } + 434 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-block-public-policy +  Impact Users could put a policy that allows public access + Resolution Prevent policies that allow public access being PUT + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/block-public-policy/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block#block_public_policy +──────────────────────────────────────────────────────────────────────────────── + + +Result #33 HIGH Bucket does not have encryption enabled  +──────────────────────────────────────────────────────────────────────────────── + submodules/storage/main.tf Lines 421-434 +───────┬──────────────────────────────────────────────────────────────────────── + 421 │ resource "aws_s3_bucket" "registry" { + 422 │  arn = "arn:aws:s3:::${var.deploy_id}-registry" + 423 │  bucket = "${var.deploy_id}-registry" + 424 │  force_destroy = "false" + 425 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 426 │  object_lock_enabled = "false" + 427 │  tags = var.tags + 428 │  + 429 │  lifecycle { + 430 │  ignore_changes = [ + 431 │  hosted_zone_id, + 432 │  ] + 433 │  } + 434 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-enable-bucket-encryption +  Impact The bucket objects could be read if compromised + Resolution Configure bucket encryption + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/enable-bucket-encryption/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket#enable-default-server-side-encryption +──────────────────────────────────────────────────────────────────────────────── + + +Result #34 HIGH No public access block so not ignoring public acls  +──────────────────────────────────────────────────────────────────────────────── + submodules/storage/main.tf Lines 421-434 +───────┬──────────────────────────────────────────────────────────────────────── + 421 │ resource "aws_s3_bucket" "registry" { + 422 │  arn = "arn:aws:s3:::${var.deploy_id}-registry" + 423 │  bucket = "${var.deploy_id}-registry" + 424 │  force_destroy = "false" + 425 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 426 │  object_lock_enabled = "false" + 427 │  tags = var.tags + 428 │  + 429 │  lifecycle { + 430 │  ignore_changes = [ + 431 │  hosted_zone_id, + 432 │  ] + 433 │  } + 434 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-ignore-public-acls +  Impact PUT calls with public ACLs specified can make objects public + Resolution Enable ignoring the application of public ACLs in PUT calls + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/ignore-public-acls/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block#ignore_public_acls +──────────────────────────────────────────────────────────────────────────────── + + +Result #35 HIGH No public access block so not restricting public buckets  +──────────────────────────────────────────────────────────────────────────────── + submodules/storage/main.tf Lines 421-434 +───────┬──────────────────────────────────────────────────────────────────────── + 421 │ resource "aws_s3_bucket" "registry" { + 422 │  arn = "arn:aws:s3:::${var.deploy_id}-registry" + 423 │  bucket = "${var.deploy_id}-registry" + 424 │  force_destroy = "false" + 425 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 426 │  object_lock_enabled = "false" + 427 │  tags = var.tags + 428 │  + 429 │  lifecycle { + 430 │  ignore_changes = [ + 431 │  hosted_zone_id, + 432 │  ] + 433 │  } + 434 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-no-public-buckets +  Impact Public buckets can be accessed by anyone + Resolution Limit the access to public buckets to only the owner or AWS Services (eg; CloudFront) + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/no-public-buckets/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block#restrict_public_buckets¡ +──────────────────────────────────────────────────────────────────────────────── + + +Result #36 HIGH Bucket does not encrypt data with a customer managed key.  +──────────────────────────────────────────────────────────────────────────────── + submodules/storage/main.tf Lines 421-434 +───────┬──────────────────────────────────────────────────────────────────────── + 421 │ resource "aws_s3_bucket" "registry" { + 422 │  arn = "arn:aws:s3:::${var.deploy_id}-registry" + 423 │  bucket = "${var.deploy_id}-registry" + 424 │  force_destroy = "false" + 425 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 426 │  object_lock_enabled = "false" + 427 │  tags = var.tags + 428 │  + 429 │  lifecycle { + 430 │  ignore_changes = [ + 431 │  hosted_zone_id, + 432 │  ] + 433 │  } + 434 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-encryption-customer-key +  Impact Using AWS managed keys does not allow for fine grained control + Resolution Enable encryption using customer managed keys + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/encryption-customer-key/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket#enable-default-server-side-encryption +──────────────────────────────────────────────────────────────────────────────── + + +Result #37 HIGH No public access block so not blocking public acls  +──────────────────────────────────────────────────────────────────────────────── + submodules/storage/main.tf Lines 72-84 +───────┬──────────────────────────────────────────────────────────────────────── + 72 │ resource "aws_s3_bucket" "backups" { + 73 │  bucket = "${var.deploy_id}-backups" + 74 │  force_destroy = "false" + 75 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 76 │  object_lock_enabled = "false" + 77 │  tags = var.tags + 78 │  + 79 │  lifecycle { + 80 │  ignore_changes = [ + 81 │  hosted_zone_id, + 82 │  ] + 83 │  } + 84 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-block-public-acls +  Impact PUT calls with public ACLs specified can make objects public + Resolution Enable blocking any PUT calls with a public ACL specified + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/block-public-acls/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block#block_public_acls +──────────────────────────────────────────────────────────────────────────────── + + +Result #38 HIGH No public access block so not blocking public policies  +──────────────────────────────────────────────────────────────────────────────── + submodules/storage/main.tf Lines 72-84 +───────┬──────────────────────────────────────────────────────────────────────── + 72 │ resource "aws_s3_bucket" "backups" { + 73 │  bucket = "${var.deploy_id}-backups" + 74 │  force_destroy = "false" + 75 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 76 │  object_lock_enabled = "false" + 77 │  tags = var.tags + 78 │  + 79 │  lifecycle { + 80 │  ignore_changes = [ + 81 │  hosted_zone_id, + 82 │  ] + 83 │  } + 84 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-block-public-policy +  Impact Users could put a policy that allows public access + Resolution Prevent policies that allow public access being PUT + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/block-public-policy/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block#block_public_policy +──────────────────────────────────────────────────────────────────────────────── + + +Result #39 HIGH Bucket does not have encryption enabled  +──────────────────────────────────────────────────────────────────────────────── + submodules/storage/main.tf Lines 72-84 +───────┬──────────────────────────────────────────────────────────────────────── + 72 │ resource "aws_s3_bucket" "backups" { + 73 │  bucket = "${var.deploy_id}-backups" + 74 │  force_destroy = "false" + 75 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 76 │  object_lock_enabled = "false" + 77 │  tags = var.tags + 78 │  + 79 │  lifecycle { + 80 │  ignore_changes = [ + 81 │  hosted_zone_id, + 82 │  ] + 83 │  } + 84 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-enable-bucket-encryption +  Impact The bucket objects could be read if compromised + Resolution Configure bucket encryption + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/enable-bucket-encryption/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket#enable-default-server-side-encryption +──────────────────────────────────────────────────────────────────────────────── + + +Result #40 HIGH No public access block so not ignoring public acls  +──────────────────────────────────────────────────────────────────────────────── + submodules/storage/main.tf Lines 72-84 +───────┬──────────────────────────────────────────────────────────────────────── + 72 │ resource "aws_s3_bucket" "backups" { + 73 │  bucket = "${var.deploy_id}-backups" + 74 │  force_destroy = "false" + 75 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 76 │  object_lock_enabled = "false" + 77 │  tags = var.tags + 78 │  + 79 │  lifecycle { + 80 │  ignore_changes = [ + 81 │  hosted_zone_id, + 82 │  ] + 83 │  } + 84 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-ignore-public-acls +  Impact PUT calls with public ACLs specified can make objects public + Resolution Enable ignoring the application of public ACLs in PUT calls + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/ignore-public-acls/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block#ignore_public_acls +──────────────────────────────────────────────────────────────────────────────── + + +Result #41 HIGH No public access block so not restricting public buckets  +──────────────────────────────────────────────────────────────────────────────── + submodules/storage/main.tf Lines 72-84 +───────┬──────────────────────────────────────────────────────────────────────── + 72 │ resource "aws_s3_bucket" "backups" { + 73 │  bucket = "${var.deploy_id}-backups" + 74 │  force_destroy = "false" + 75 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 76 │  object_lock_enabled = "false" + 77 │  tags = var.tags + 78 │  + 79 │  lifecycle { + 80 │  ignore_changes = [ + 81 │  hosted_zone_id, + 82 │  ] + 83 │  } + 84 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-no-public-buckets +  Impact Public buckets can be accessed by anyone + Resolution Limit the access to public buckets to only the owner or AWS Services (eg; CloudFront) + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/no-public-buckets/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block#restrict_public_buckets¡ +──────────────────────────────────────────────────────────────────────────────── + + +Result #42 HIGH Bucket does not encrypt data with a customer managed key.  +──────────────────────────────────────────────────────────────────────────────── + submodules/storage/main.tf Lines 72-84 +───────┬──────────────────────────────────────────────────────────────────────── + 72 │ resource "aws_s3_bucket" "backups" { + 73 │  bucket = "${var.deploy_id}-backups" + 74 │  force_destroy = "false" + 75 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 76 │  object_lock_enabled = "false" + 77 │  tags = var.tags + 78 │  + 79 │  lifecycle { + 80 │  ignore_changes = [ + 81 │  hosted_zone_id, + 82 │  ] + 83 │  } + 84 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-encryption-customer-key +  Impact Using AWS managed keys does not allow for fine grained control + Resolution Enable encryption using customer managed keys + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/encryption-customer-key/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket#enable-default-server-side-encryption +──────────────────────────────────────────────────────────────────────────────── + + +Result #43 MEDIUM Bucket does not have logging enabled  +──────────────────────────────────────────────────────────────────────────────── + submodules/storage/main.tf Lines 148-160 +───────┬──────────────────────────────────────────────────────────────────────── + 148 │ resource "aws_s3_bucket" "blobs" { + 149 │  bucket = "${var.deploy_id}-blobs" + 150 │  force_destroy = "false" + 151 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 152 │  object_lock_enabled = "false" + 153 │  tags = var.tags + 154 │  + 155 │  lifecycle { + 156 │  ignore_changes = [ + 157 │  hosted_zone_id, + 158 │  ] + 159 │  } + 160 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-enable-bucket-logging +  Impact There is no way to determine the access to this bucket + Resolution Add a logging block to the resource to enable access logging + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/enable-bucket-logging/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket +──────────────────────────────────────────────────────────────────────────────── + + +Result #44 MEDIUM Bucket does not have versioning enabled  +──────────────────────────────────────────────────────────────────────────────── + submodules/storage/main.tf Lines 148-160 +───────┬──────────────────────────────────────────────────────────────────────── + 148 │ resource "aws_s3_bucket" "blobs" { + 149 │  bucket = "${var.deploy_id}-blobs" + 150 │  force_destroy = "false" + 151 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 152 │  object_lock_enabled = "false" + 153 │  tags = var.tags + 154 │  + 155 │  lifecycle { + 156 │  ignore_changes = [ + 157 │  hosted_zone_id, + 158 │  ] + 159 │  } + 160 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-enable-versioning +  Impact Deleted or modified data would not be recoverable + Resolution Enable versioning to protect against accidental/malicious removal or modification + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/enable-versioning/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket#versioning +──────────────────────────────────────────────────────────────────────────────── + + +Result #45 MEDIUM Bucket does not have logging enabled  +──────────────────────────────────────────────────────────────────────────────── + submodules/storage/main.tf Lines 223-235 +───────┬──────────────────────────────────────────────────────────────────────── + 223 │ resource "aws_s3_bucket" "logs" { + 224 │  bucket = "${var.deploy_id}-logs" + 225 │  force_destroy = "false" + 226 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 227 │  object_lock_enabled = "false" + 228 │  tags = var.tags + 229 │  + 230 │  lifecycle { + 231 │  ignore_changes = [ + 232 │  hosted_zone_id, + 233 │  ] + 234 │  } + 235 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-enable-bucket-logging +  Impact There is no way to determine the access to this bucket + Resolution Add a logging block to the resource to enable access logging + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/enable-bucket-logging/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket +──────────────────────────────────────────────────────────────────────────────── + + +Result #46 MEDIUM Bucket does not have versioning enabled  +──────────────────────────────────────────────────────────────────────────────── + submodules/storage/main.tf Lines 223-235 +───────┬──────────────────────────────────────────────────────────────────────── + 223 │ resource "aws_s3_bucket" "logs" { + 224 │  bucket = "${var.deploy_id}-logs" + 225 │  force_destroy = "false" + 226 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 227 │  object_lock_enabled = "false" + 228 │  tags = var.tags + 229 │  + 230 │  lifecycle { + 231 │  ignore_changes = [ + 232 │  hosted_zone_id, + 233 │  ] + 234 │  } + 235 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-enable-versioning +  Impact Deleted or modified data would not be recoverable + Resolution Enable versioning to protect against accidental/malicious removal or modification + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/enable-versioning/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket#versioning +──────────────────────────────────────────────────────────────────────────────── + + +Result #47 MEDIUM Bucket does not have logging enabled  +──────────────────────────────────────────────────────────────────────────────── + submodules/storage/main.tf Lines 313-325 +───────┬──────────────────────────────────────────────────────────────────────── + 313 │ resource "aws_s3_bucket" "monitoring" { + 314 │  bucket = "${var.deploy_id}-monitoring" + 315 │  force_destroy = "true" + 316 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 317 │  object_lock_enabled = "false" + 318 │  tags = var.tags + 319 │  + 320 │  lifecycle { + 321 │  ignore_changes = [ + 322 │  hosted_zone_id, + 323 │  ] + 324 │  } + 325 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-enable-bucket-logging +  Impact There is no way to determine the access to this bucket + Resolution Add a logging block to the resource to enable access logging + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/enable-bucket-logging/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket +──────────────────────────────────────────────────────────────────────────────── + + +Result #48 MEDIUM Bucket does not have versioning enabled  +──────────────────────────────────────────────────────────────────────────────── + submodules/storage/main.tf Lines 313-325 +───────┬──────────────────────────────────────────────────────────────────────── + 313 │ resource "aws_s3_bucket" "monitoring" { + 314 │  bucket = "${var.deploy_id}-monitoring" + 315 │  force_destroy = "true" + 316 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 317 │  object_lock_enabled = "false" + 318 │  tags = var.tags + 319 │  + 320 │  lifecycle { + 321 │  ignore_changes = [ + 322 │  hosted_zone_id, + 323 │  ] + 324 │  } + 325 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-enable-versioning +  Impact Deleted or modified data would not be recoverable + Resolution Enable versioning to protect against accidental/malicious removal or modification + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/enable-versioning/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket#versioning +──────────────────────────────────────────────────────────────────────────────── + + +Result #49 MEDIUM Bucket does not have logging enabled  +──────────────────────────────────────────────────────────────────────────────── + submodules/storage/main.tf Lines 421-434 +───────┬──────────────────────────────────────────────────────────────────────── + 421 │ resource "aws_s3_bucket" "registry" { + 422 │  arn = "arn:aws:s3:::${var.deploy_id}-registry" + 423 │  bucket = "${var.deploy_id}-registry" + 424 │  force_destroy = "false" + 425 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 426 │  object_lock_enabled = "false" + 427 │  tags = var.tags + 428 │  + 429 │  lifecycle { + 430 │  ignore_changes = [ + 431 │  hosted_zone_id, + 432 │  ] + 433 │  } + 434 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-enable-bucket-logging +  Impact There is no way to determine the access to this bucket + Resolution Add a logging block to the resource to enable access logging + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/enable-bucket-logging/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket +──────────────────────────────────────────────────────────────────────────────── + + +Result #50 MEDIUM Bucket does not have versioning enabled  +──────────────────────────────────────────────────────────────────────────────── + submodules/storage/main.tf Lines 421-434 +───────┬──────────────────────────────────────────────────────────────────────── + 421 │ resource "aws_s3_bucket" "registry" { + 422 │  arn = "arn:aws:s3:::${var.deploy_id}-registry" + 423 │  bucket = "${var.deploy_id}-registry" + 424 │  force_destroy = "false" + 425 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 426 │  object_lock_enabled = "false" + 427 │  tags = var.tags + 428 │  + 429 │  lifecycle { + 430 │  ignore_changes = [ + 431 │  hosted_zone_id, + 432 │  ] + 433 │  } + 434 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-enable-versioning +  Impact Deleted or modified data would not be recoverable + Resolution Enable versioning to protect against accidental/malicious removal or modification + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/enable-versioning/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket#versioning +──────────────────────────────────────────────────────────────────────────────── + + +Result #51 MEDIUM Bucket does not have logging enabled  +──────────────────────────────────────────────────────────────────────────────── + submodules/storage/main.tf Lines 72-84 +───────┬──────────────────────────────────────────────────────────────────────── + 72 │ resource "aws_s3_bucket" "backups" { + 73 │  bucket = "${var.deploy_id}-backups" + 74 │  force_destroy = "false" + 75 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 76 │  object_lock_enabled = "false" + 77 │  tags = var.tags + 78 │  + 79 │  lifecycle { + 80 │  ignore_changes = [ + 81 │  hosted_zone_id, + 82 │  ] + 83 │  } + 84 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-enable-bucket-logging +  Impact There is no way to determine the access to this bucket + Resolution Add a logging block to the resource to enable access logging + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/enable-bucket-logging/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket +──────────────────────────────────────────────────────────────────────────────── + + +Result #52 MEDIUM Bucket does not have versioning enabled  +──────────────────────────────────────────────────────────────────────────────── + submodules/storage/main.tf Lines 72-84 +───────┬──────────────────────────────────────────────────────────────────────── + 72 │ resource "aws_s3_bucket" "backups" { + 73 │  bucket = "${var.deploy_id}-backups" + 74 │  force_destroy = "false" + 75 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 76 │  object_lock_enabled = "false" + 77 │  tags = var.tags + 78 │  + 79 │  lifecycle { + 80 │  ignore_changes = [ + 81 │  hosted_zone_id, + 82 │  ] + 83 │  } + 84 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-enable-versioning +  Impact Deleted or modified data would not be recoverable + Resolution Enable versioning to protect against accidental/malicious removal or modification + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/enable-versioning/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket#versioning +──────────────────────────────────────────────────────────────────────────────── + + +Result #53 LOW Bucket does not have a corresponding public access block.  +──────────────────────────────────────────────────────────────────────────────── + submodules/storage/main.tf Lines 148-160 +───────┬──────────────────────────────────────────────────────────────────────── + 148 │ resource "aws_s3_bucket" "blobs" { + 149 │  bucket = "${var.deploy_id}-blobs" + 150 │  force_destroy = "false" + 151 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 152 │  object_lock_enabled = "false" + 153 │  tags = var.tags + 154 │  + 155 │  lifecycle { + 156 │  ignore_changes = [ + 157 │  hosted_zone_id, + 158 │  ] + 159 │  } + 160 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-specify-public-access-block +  Impact Public access policies may be applied to sensitive data buckets + Resolution Define a aws_s3_bucket_public_access_block for the given bucket to control public access policies + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/specify-public-access-block/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block#bucket +──────────────────────────────────────────────────────────────────────────────── + + +Result #54 LOW Bucket does not have a corresponding public access block.  +──────────────────────────────────────────────────────────────────────────────── + submodules/storage/main.tf Lines 223-235 +───────┬──────────────────────────────────────────────────────────────────────── + 223 │ resource "aws_s3_bucket" "logs" { + 224 │  bucket = "${var.deploy_id}-logs" + 225 │  force_destroy = "false" + 226 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 227 │  object_lock_enabled = "false" + 228 │  tags = var.tags + 229 │  + 230 │  lifecycle { + 231 │  ignore_changes = [ + 232 │  hosted_zone_id, + 233 │  ] + 234 │  } + 235 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-specify-public-access-block +  Impact Public access policies may be applied to sensitive data buckets + Resolution Define a aws_s3_bucket_public_access_block for the given bucket to control public access policies + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/specify-public-access-block/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block#bucket +──────────────────────────────────────────────────────────────────────────────── + + +Result #55 LOW Bucket does not have a corresponding public access block.  +──────────────────────────────────────────────────────────────────────────────── + submodules/storage/main.tf Lines 313-325 +───────┬──────────────────────────────────────────────────────────────────────── + 313 │ resource "aws_s3_bucket" "monitoring" { + 314 │  bucket = "${var.deploy_id}-monitoring" + 315 │  force_destroy = "true" + 316 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 317 │  object_lock_enabled = "false" + 318 │  tags = var.tags + 319 │  + 320 │  lifecycle { + 321 │  ignore_changes = [ + 322 │  hosted_zone_id, + 323 │  ] + 324 │  } + 325 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-specify-public-access-block +  Impact Public access policies may be applied to sensitive data buckets + Resolution Define a aws_s3_bucket_public_access_block for the given bucket to control public access policies + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/specify-public-access-block/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block#bucket +──────────────────────────────────────────────────────────────────────────────── + + +Result #56 LOW Bucket does not have a corresponding public access block.  +──────────────────────────────────────────────────────────────────────────────── + submodules/storage/main.tf Lines 421-434 +───────┬──────────────────────────────────────────────────────────────────────── + 421 │ resource "aws_s3_bucket" "registry" { + 422 │  arn = "arn:aws:s3:::${var.deploy_id}-registry" + 423 │  bucket = "${var.deploy_id}-registry" + 424 │  force_destroy = "false" + 425 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 426 │  object_lock_enabled = "false" + 427 │  tags = var.tags + 428 │  + 429 │  lifecycle { + 430 │  ignore_changes = [ + 431 │  hosted_zone_id, + 432 │  ] + 433 │  } + 434 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-specify-public-access-block +  Impact Public access policies may be applied to sensitive data buckets + Resolution Define a aws_s3_bucket_public_access_block for the given bucket to control public access policies + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/specify-public-access-block/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block#bucket +──────────────────────────────────────────────────────────────────────────────── + + +Result #57 LOW Bucket does not have a corresponding public access block.  +──────────────────────────────────────────────────────────────────────────────── + submodules/storage/main.tf Lines 72-84 +───────┬──────────────────────────────────────────────────────────────────────── + 72 │ resource "aws_s3_bucket" "backups" { + 73 │  bucket = "${var.deploy_id}-backups" + 74 │  force_destroy = "false" + 75 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 76 │  object_lock_enabled = "false" + 77 │  tags = var.tags + 78 │  + 79 │  lifecycle { + 80 │  ignore_changes = [ + 81 │  hosted_zone_id, + 82 │  ] + 83 │  } + 84 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-specify-public-access-block +  Impact Public access policies may be applied to sensitive data buckets + Resolution Define a aws_s3_bucket_public_access_block for the given bucket to control public access policies + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/specify-public-access-block/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block#bucket +──────────────────────────────────────────────────────────────────────────────── + + + timings + ────────────────────────────────────────── + disk i/o  2.427674ms + parsing  67.362509ms + adaptation  3.439651ms + checks  17.628036ms + total  90.85787ms + + counts + ────────────────────────────────────────── + modules downloaded  0 + modules processed  6 + blocks processed  188 + files read  33 + + results + ────────────────────────────────────────── + passed  78 + ignored  0 + critical  0 + high  42 + medium  10 + low  5 + + 78 passed, 57 potential problem(s) detected. + + +Results #1-2 HIGH IAM policy document uses sensitive action 'ec2:CreateTags' on wildcarded resource 'arn:aws:ec2:*:*:volume/*' (2 similar results) +──────────────────────────────────────────────────────────────────────────────── + ../submodules/eks/iam.tf Lines 149-152 +───────┬──────────────────────────────────────────────────────────────────────── + 149 │  resources = [ + 150 │  "arn:aws:ec2:*:*:volume/*", + 151 │  "arn:aws:ec2:*:*:snapshot/*", + 152 │  ] +───────┴──────────────────────────────────────────────────────────────────────── + Individual Causes + - /Users/miguel.harmant/src/dominodatalab/terraform-aws-eks/example/main.tf:1-16 (module.domino_eks) + - /Users/miguel.harmant/src/dominodatalab/terraform-aws-eks/example/main.tf:1-16 (module.domino_eks) +──────────────────────────────────────────────────────────────────────────────── +  ID aws-iam-no-policy-wildcards +  Impact Overly permissive policies may grant access to sensitive resources + Resolution Specify the exact permissions required, and to which resources they should apply instead of using wildcards. + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/iam/no-policy-wildcards/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document +──────────────────────────────────────────────────────────────────────────────── + + +Results #3-4 HIGH IAM policy document uses sensitive action 'ec2:DeleteTags' on wildcarded resource 'arn:aws:ec2:*:*:volume/*' (2 similar results) +──────────────────────────────────────────────────────────────────────────────── + ../submodules/eks/iam.tf Lines 171-174 +───────┬──────────────────────────────────────────────────────────────────────── + 171 │  resources = [ + 172 │  "arn:aws:ec2:*:*:volume/*", + 173 │  "arn:aws:ec2:*:*:snapshot/*", + 174 │  ] +───────┴──────────────────────────────────────────────────────────────────────── + Individual Causes + - /Users/miguel.harmant/src/dominodatalab/terraform-aws-eks/example/main.tf:1-16 (module.domino_eks) + - /Users/miguel.harmant/src/dominodatalab/terraform-aws-eks/example/main.tf:1-16 (module.domino_eks) +──────────────────────────────────────────────────────────────────────────────── +  ID aws-iam-no-policy-wildcards +  Impact Overly permissive policies may grant access to sensitive resources + Resolution Specify the exact permissions required, and to which resources they should apply instead of using wildcards. + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/iam/no-policy-wildcards/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document +──────────────────────────────────────────────────────────────────────────────── + + +Result #5 HIGH IAM policy document uses sensitive action 'ec2:DeleteVolume' on wildcarded resource '*'  +──────────────────────────────────────────────────────────────────────────────── + ../submodules/eks/iam.tf Line 195 +───────┬──────────────────────────────────────────────────────────────────────── + 192 │  statement { + 193 │  + 194 │  effect = "Allow" + 195 │  resources = ["*"] + 196 │  + 197 │  actions = [ + 198 │  "ec2:DeleteVolume", + 199 │  "ec2:DeleteSnapshot", + 200 │  ] + 201 │  + 202 │  condition { + 203 │  test = "StringLike" + 204 │  variable = "aws:ResourceTag/KubernetesCluster" + 205 │  values = [var.deploy_id] + 206 │  } + 207 │  } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-iam-no-policy-wildcards +  Impact Overly permissive policies may grant access to sensitive resources + Resolution Specify the exact permissions required, and to which resources they should apply instead of using wildcards. + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/iam/no-policy-wildcards/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document +──────────────────────────────────────────────────────────────────────────────── + + +Result #6 HIGH IAM policy document uses sensitive action 'ec2:CreateSnapshot' on wildcarded resource '*'  +──────────────────────────────────────────────────────────────────────────────── + ../submodules/eks/iam.tf Line 247 +───────┬──────────────────────────────────────────────────────────────────────── + 244 │  statement { + 245 │  + 246 │  effect = "Allow" + 247 │  resources = ["*"] + 248 │  + 249 │  actions = [ + 250 │  "ec2:CreateSnapshot", + 251 │  "ec2:CreateTags", + 252 │  "ec2:DeleteSnapshot", + 253 │  "ec2:DeleteTags", + 254 │  "ec2:DescribeAvailabilityZones", + 255 │  "ec2:DescribeSnapshots", + 256 │  "ec2:DescribeTags", + 257 │  ] + 258 │  } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-iam-no-policy-wildcards +  Impact Overly permissive policies may grant access to sensitive resources + Resolution Specify the exact permissions required, and to which resources they should apply instead of using wildcards. + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/iam/no-policy-wildcards/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document +──────────────────────────────────────────────────────────────────────────────── + + +Result #7 HIGH IAM policy document uses sensitive action 's3:ListBucket' on wildcarded resource '*'  +──────────────────────────────────────────────────────────────────────────────── + ../submodules/eks/iam.tf Line 34 +───────┬──────────────────────────────────────────────────────────────────────── + 31 │  statement { + 32 │  + 33 │  effect = "Allow" + 34 │  resources = ["*"] + 35 │  + 36 │  actions = [ + 37 │  "s3:ListBucket", + 38 │  "s3:GetBucketLocation", + 39 │  "s3:ListBucketMultipartUploads", + 40 │  ] + 41 │  } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-iam-no-policy-wildcards +  Impact Overly permissive policies may grant access to sensitive resources + Resolution Specify the exact permissions required, and to which resources they should apply instead of using wildcards. + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/iam/no-policy-wildcards/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document +──────────────────────────────────────────────────────────────────────────────── + + +Results #8-11 HIGH IAM policy document uses sensitive action 's3:PutObject' on wildcarded resource 'arn:aws:s3:::' (4 similar results) +──────────────────────────────────────────────────────────────────────────────── + ../submodules/eks/iam.tf Lines 47-52 +───────┬──────────────────────────────────────────────────────────────────────── + 47 │  resources = [ + 48 │  "arn:aws:s3:::${var.deploy_id}-blobs*", + 49 │  "arn:aws:s3:::${var.deploy_id}-logs*", + 50 │  "arn:aws:s3:::${var.deploy_id}-backups*", + 51 │  "arn:aws:s3:::${var.deploy_id}-registry*", + 52 │  ] +───────┴──────────────────────────────────────────────────────────────────────── + Individual Causes + - /Users/miguel.harmant/src/dominodatalab/terraform-aws-eks/example/main.tf:1-16 (module.domino_eks) + - /Users/miguel.harmant/src/dominodatalab/terraform-aws-eks/example/main.tf:1-16 (module.domino_eks) + - /Users/miguel.harmant/src/dominodatalab/terraform-aws-eks/example/main.tf:1-16 (module.domino_eks) + - /Users/miguel.harmant/src/dominodatalab/terraform-aws-eks/example/main.tf:1-16 (module.domino_eks) +──────────────────────────────────────────────────────────────────────────────── +  ID aws-iam-no-policy-wildcards +  Impact Overly permissive policies may grant access to sensitive resources + Resolution Specify the exact permissions required, and to which resources they should apply instead of using wildcards. + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/iam/no-policy-wildcards/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document +──────────────────────────────────────────────────────────────────────────────── + + +Result #12 HIGH IAM policy document uses sensitive action 'autoscaling:SetDesiredCapacity' on wildcarded resource '*'  +──────────────────────────────────────────────────────────────────────────────── + ../submodules/eks/iam.tf Line 87 +───────┬──────────────────────────────────────────────────────────────────────── + 84 │  statement { + 85 │  + 86 │  effect = "Allow" + 87 │  resources = ["*"] + 88 │  + 89 │  actions = [ + 90 │  "autoscaling:DescribeAutoScalingInstances", + 91 │  "autoscaling:SetDesiredCapacity", + 92 │  "autoscaling:TerminateInstanceInAutoScalingGroup", + 93 │  ] + 94 │  + 95 │  condition { + 96 │  test = "StringEquals" + 97 │  variable = "autoscaling:ResourceTag/eks:cluster-name" + 98 │  values = [var.deploy_id] + 99 │  } + 100 │  } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-iam-no-policy-wildcards +  Impact Overly permissive policies may grant access to sensitive resources + Resolution Specify the exact permissions required, and to which resources they should apply instead of using wildcards. + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/iam/no-policy-wildcards/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document +──────────────────────────────────────────────────────────────────────────────── + + +Result #13 HIGH No public access block so not blocking public acls  +──────────────────────────────────────────────────────────────────────────────── + ../submodules/storage/main.tf Lines 148-160 +───────┬──────────────────────────────────────────────────────────────────────── + 148 │ resource "aws_s3_bucket" "blobs" { + 149 │  bucket = "${var.deploy_id}-blobs" + 150 │  force_destroy = "false" + 151 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 152 │  object_lock_enabled = "false" + 153 │  tags = var.tags + 154 │  + 155 │  lifecycle { + 156 │  ignore_changes = [ + 157 │  hosted_zone_id, + 158 │  ] + 159 │  } + 160 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-block-public-acls +  Impact PUT calls with public ACLs specified can make objects public + Resolution Enable blocking any PUT calls with a public ACL specified + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/block-public-acls/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block#block_public_acls +──────────────────────────────────────────────────────────────────────────────── + + +Result #14 HIGH No public access block so not blocking public policies  +──────────────────────────────────────────────────────────────────────────────── + ../submodules/storage/main.tf Lines 148-160 +───────┬──────────────────────────────────────────────────────────────────────── + 148 │ resource "aws_s3_bucket" "blobs" { + 149 │  bucket = "${var.deploy_id}-blobs" + 150 │  force_destroy = "false" + 151 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 152 │  object_lock_enabled = "false" + 153 │  tags = var.tags + 154 │  + 155 │  lifecycle { + 156 │  ignore_changes = [ + 157 │  hosted_zone_id, + 158 │  ] + 159 │  } + 160 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-block-public-policy +  Impact Users could put a policy that allows public access + Resolution Prevent policies that allow public access being PUT + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/block-public-policy/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block#block_public_policy +──────────────────────────────────────────────────────────────────────────────── + + +Result #15 HIGH Bucket does not have encryption enabled  +──────────────────────────────────────────────────────────────────────────────── + ../submodules/storage/main.tf Lines 148-160 +───────┬──────────────────────────────────────────────────────────────────────── + 148 │ resource "aws_s3_bucket" "blobs" { + 149 │  bucket = "${var.deploy_id}-blobs" + 150 │  force_destroy = "false" + 151 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 152 │  object_lock_enabled = "false" + 153 │  tags = var.tags + 154 │  + 155 │  lifecycle { + 156 │  ignore_changes = [ + 157 │  hosted_zone_id, + 158 │  ] + 159 │  } + 160 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-enable-bucket-encryption +  Impact The bucket objects could be read if compromised + Resolution Configure bucket encryption + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/enable-bucket-encryption/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket#enable-default-server-side-encryption +──────────────────────────────────────────────────────────────────────────────── + + +Result #16 HIGH No public access block so not ignoring public acls  +──────────────────────────────────────────────────────────────────────────────── + ../submodules/storage/main.tf Lines 148-160 +───────┬──────────────────────────────────────────────────────────────────────── + 148 │ resource "aws_s3_bucket" "blobs" { + 149 │  bucket = "${var.deploy_id}-blobs" + 150 │  force_destroy = "false" + 151 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 152 │  object_lock_enabled = "false" + 153 │  tags = var.tags + 154 │  + 155 │  lifecycle { + 156 │  ignore_changes = [ + 157 │  hosted_zone_id, + 158 │  ] + 159 │  } + 160 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-ignore-public-acls +  Impact PUT calls with public ACLs specified can make objects public + Resolution Enable ignoring the application of public ACLs in PUT calls + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/ignore-public-acls/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block#ignore_public_acls +──────────────────────────────────────────────────────────────────────────────── + + +Result #17 HIGH No public access block so not restricting public buckets  +──────────────────────────────────────────────────────────────────────────────── + ../submodules/storage/main.tf Lines 148-160 +───────┬──────────────────────────────────────────────────────────────────────── + 148 │ resource "aws_s3_bucket" "blobs" { + 149 │  bucket = "${var.deploy_id}-blobs" + 150 │  force_destroy = "false" + 151 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 152 │  object_lock_enabled = "false" + 153 │  tags = var.tags + 154 │  + 155 │  lifecycle { + 156 │  ignore_changes = [ + 157 │  hosted_zone_id, + 158 │  ] + 159 │  } + 160 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-no-public-buckets +  Impact Public buckets can be accessed by anyone + Resolution Limit the access to public buckets to only the owner or AWS Services (eg; CloudFront) + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/no-public-buckets/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block#restrict_public_buckets¡ +──────────────────────────────────────────────────────────────────────────────── + + +Result #18 HIGH Bucket does not encrypt data with a customer managed key.  +──────────────────────────────────────────────────────────────────────────────── + ../submodules/storage/main.tf Lines 148-160 +───────┬──────────────────────────────────────────────────────────────────────── + 148 │ resource "aws_s3_bucket" "blobs" { + 149 │  bucket = "${var.deploy_id}-blobs" + 150 │  force_destroy = "false" + 151 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 152 │  object_lock_enabled = "false" + 153 │  tags = var.tags + 154 │  + 155 │  lifecycle { + 156 │  ignore_changes = [ + 157 │  hosted_zone_id, + 158 │  ] + 159 │  } + 160 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-encryption-customer-key +  Impact Using AWS managed keys does not allow for fine grained control + Resolution Enable encryption using customer managed keys + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/encryption-customer-key/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket#enable-default-server-side-encryption +──────────────────────────────────────────────────────────────────────────────── + + +Result #19 HIGH No public access block so not blocking public acls  +──────────────────────────────────────────────────────────────────────────────── + ../submodules/storage/main.tf Lines 223-235 +───────┬──────────────────────────────────────────────────────────────────────── + 223 │ resource "aws_s3_bucket" "logs" { + 224 │  bucket = "${var.deploy_id}-logs" + 225 │  force_destroy = "false" + 226 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 227 │  object_lock_enabled = "false" + 228 │  tags = var.tags + 229 │  + 230 │  lifecycle { + 231 │  ignore_changes = [ + 232 │  hosted_zone_id, + 233 │  ] + 234 │  } + 235 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-block-public-acls +  Impact PUT calls with public ACLs specified can make objects public + Resolution Enable blocking any PUT calls with a public ACL specified + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/block-public-acls/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block#block_public_acls +──────────────────────────────────────────────────────────────────────────────── + + +Result #20 HIGH No public access block so not blocking public policies  +──────────────────────────────────────────────────────────────────────────────── + ../submodules/storage/main.tf Lines 223-235 +───────┬──────────────────────────────────────────────────────────────────────── + 223 │ resource "aws_s3_bucket" "logs" { + 224 │  bucket = "${var.deploy_id}-logs" + 225 │  force_destroy = "false" + 226 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 227 │  object_lock_enabled = "false" + 228 │  tags = var.tags + 229 │  + 230 │  lifecycle { + 231 │  ignore_changes = [ + 232 │  hosted_zone_id, + 233 │  ] + 234 │  } + 235 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-block-public-policy +  Impact Users could put a policy that allows public access + Resolution Prevent policies that allow public access being PUT + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/block-public-policy/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block#block_public_policy +──────────────────────────────────────────────────────────────────────────────── + + +Result #21 HIGH Bucket does not have encryption enabled  +──────────────────────────────────────────────────────────────────────────────── + ../submodules/storage/main.tf Lines 223-235 +───────┬──────────────────────────────────────────────────────────────────────── + 223 │ resource "aws_s3_bucket" "logs" { + 224 │  bucket = "${var.deploy_id}-logs" + 225 │  force_destroy = "false" + 226 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 227 │  object_lock_enabled = "false" + 228 │  tags = var.tags + 229 │  + 230 │  lifecycle { + 231 │  ignore_changes = [ + 232 │  hosted_zone_id, + 233 │  ] + 234 │  } + 235 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-enable-bucket-encryption +  Impact The bucket objects could be read if compromised + Resolution Configure bucket encryption + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/enable-bucket-encryption/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket#enable-default-server-side-encryption +──────────────────────────────────────────────────────────────────────────────── + + +Result #22 HIGH No public access block so not ignoring public acls  +──────────────────────────────────────────────────────────────────────────────── + ../submodules/storage/main.tf Lines 223-235 +───────┬──────────────────────────────────────────────────────────────────────── + 223 │ resource "aws_s3_bucket" "logs" { + 224 │  bucket = "${var.deploy_id}-logs" + 225 │  force_destroy = "false" + 226 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 227 │  object_lock_enabled = "false" + 228 │  tags = var.tags + 229 │  + 230 │  lifecycle { + 231 │  ignore_changes = [ + 232 │  hosted_zone_id, + 233 │  ] + 234 │  } + 235 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-ignore-public-acls +  Impact PUT calls with public ACLs specified can make objects public + Resolution Enable ignoring the application of public ACLs in PUT calls + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/ignore-public-acls/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block#ignore_public_acls +──────────────────────────────────────────────────────────────────────────────── + + +Result #23 HIGH No public access block so not restricting public buckets  +──────────────────────────────────────────────────────────────────────────────── + ../submodules/storage/main.tf Lines 223-235 +───────┬──────────────────────────────────────────────────────────────────────── + 223 │ resource "aws_s3_bucket" "logs" { + 224 │  bucket = "${var.deploy_id}-logs" + 225 │  force_destroy = "false" + 226 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 227 │  object_lock_enabled = "false" + 228 │  tags = var.tags + 229 │  + 230 │  lifecycle { + 231 │  ignore_changes = [ + 232 │  hosted_zone_id, + 233 │  ] + 234 │  } + 235 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-no-public-buckets +  Impact Public buckets can be accessed by anyone + Resolution Limit the access to public buckets to only the owner or AWS Services (eg; CloudFront) + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/no-public-buckets/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block#restrict_public_buckets¡ +──────────────────────────────────────────────────────────────────────────────── + + +Result #24 HIGH Bucket does not encrypt data with a customer managed key.  +──────────────────────────────────────────────────────────────────────────────── + ../submodules/storage/main.tf Lines 223-235 +───────┬──────────────────────────────────────────────────────────────────────── + 223 │ resource "aws_s3_bucket" "logs" { + 224 │  bucket = "${var.deploy_id}-logs" + 225 │  force_destroy = "false" + 226 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 227 │  object_lock_enabled = "false" + 228 │  tags = var.tags + 229 │  + 230 │  lifecycle { + 231 │  ignore_changes = [ + 232 │  hosted_zone_id, + 233 │  ] + 234 │  } + 235 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-encryption-customer-key +  Impact Using AWS managed keys does not allow for fine grained control + Resolution Enable encryption using customer managed keys + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/encryption-customer-key/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket#enable-default-server-side-encryption +──────────────────────────────────────────────────────────────────────────────── + + +Result #25 HIGH No public access block so not blocking public acls  +──────────────────────────────────────────────────────────────────────────────── + ../submodules/storage/main.tf Lines 313-325 +───────┬──────────────────────────────────────────────────────────────────────── + 313 │ resource "aws_s3_bucket" "monitoring" { + 314 │  bucket = "${var.deploy_id}-monitoring" + 315 │  force_destroy = "true" + 316 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 317 │  object_lock_enabled = "false" + 318 │  tags = var.tags + 319 │  + 320 │  lifecycle { + 321 │  ignore_changes = [ + 322 │  hosted_zone_id, + 323 │  ] + 324 │  } + 325 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-block-public-acls +  Impact PUT calls with public ACLs specified can make objects public + Resolution Enable blocking any PUT calls with a public ACL specified + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/block-public-acls/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block#block_public_acls +──────────────────────────────────────────────────────────────────────────────── + + +Result #26 HIGH No public access block so not blocking public policies  +──────────────────────────────────────────────────────────────────────────────── + ../submodules/storage/main.tf Lines 313-325 +───────┬──────────────────────────────────────────────────────────────────────── + 313 │ resource "aws_s3_bucket" "monitoring" { + 314 │  bucket = "${var.deploy_id}-monitoring" + 315 │  force_destroy = "true" + 316 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 317 │  object_lock_enabled = "false" + 318 │  tags = var.tags + 319 │  + 320 │  lifecycle { + 321 │  ignore_changes = [ + 322 │  hosted_zone_id, + 323 │  ] + 324 │  } + 325 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-block-public-policy +  Impact Users could put a policy that allows public access + Resolution Prevent policies that allow public access being PUT + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/block-public-policy/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block#block_public_policy +──────────────────────────────────────────────────────────────────────────────── + + +Result #27 HIGH Bucket does not have encryption enabled  +──────────────────────────────────────────────────────────────────────────────── + ../submodules/storage/main.tf Lines 313-325 +───────┬──────────────────────────────────────────────────────────────────────── + 313 │ resource "aws_s3_bucket" "monitoring" { + 314 │  bucket = "${var.deploy_id}-monitoring" + 315 │  force_destroy = "true" + 316 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 317 │  object_lock_enabled = "false" + 318 │  tags = var.tags + 319 │  + 320 │  lifecycle { + 321 │  ignore_changes = [ + 322 │  hosted_zone_id, + 323 │  ] + 324 │  } + 325 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-enable-bucket-encryption +  Impact The bucket objects could be read if compromised + Resolution Configure bucket encryption + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/enable-bucket-encryption/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket#enable-default-server-side-encryption +──────────────────────────────────────────────────────────────────────────────── + + +Result #28 HIGH No public access block so not ignoring public acls  +──────────────────────────────────────────────────────────────────────────────── + ../submodules/storage/main.tf Lines 313-325 +───────┬──────────────────────────────────────────────────────────────────────── + 313 │ resource "aws_s3_bucket" "monitoring" { + 314 │  bucket = "${var.deploy_id}-monitoring" + 315 │  force_destroy = "true" + 316 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 317 │  object_lock_enabled = "false" + 318 │  tags = var.tags + 319 │  + 320 │  lifecycle { + 321 │  ignore_changes = [ + 322 │  hosted_zone_id, + 323 │  ] + 324 │  } + 325 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-ignore-public-acls +  Impact PUT calls with public ACLs specified can make objects public + Resolution Enable ignoring the application of public ACLs in PUT calls + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/ignore-public-acls/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block#ignore_public_acls +──────────────────────────────────────────────────────────────────────────────── + + +Result #29 HIGH No public access block so not restricting public buckets  +──────────────────────────────────────────────────────────────────────────────── + ../submodules/storage/main.tf Lines 313-325 +───────┬──────────────────────────────────────────────────────────────────────── + 313 │ resource "aws_s3_bucket" "monitoring" { + 314 │  bucket = "${var.deploy_id}-monitoring" + 315 │  force_destroy = "true" + 316 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 317 │  object_lock_enabled = "false" + 318 │  tags = var.tags + 319 │  + 320 │  lifecycle { + 321 │  ignore_changes = [ + 322 │  hosted_zone_id, + 323 │  ] + 324 │  } + 325 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-no-public-buckets +  Impact Public buckets can be accessed by anyone + Resolution Limit the access to public buckets to only the owner or AWS Services (eg; CloudFront) + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/no-public-buckets/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block#restrict_public_buckets¡ +──────────────────────────────────────────────────────────────────────────────── + + +Result #30 HIGH Bucket does not encrypt data with a customer managed key.  +──────────────────────────────────────────────────────────────────────────────── + ../submodules/storage/main.tf Lines 313-325 +───────┬──────────────────────────────────────────────────────────────────────── + 313 │ resource "aws_s3_bucket" "monitoring" { + 314 │  bucket = "${var.deploy_id}-monitoring" + 315 │  force_destroy = "true" + 316 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 317 │  object_lock_enabled = "false" + 318 │  tags = var.tags + 319 │  + 320 │  lifecycle { + 321 │  ignore_changes = [ + 322 │  hosted_zone_id, + 323 │  ] + 324 │  } + 325 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-encryption-customer-key +  Impact Using AWS managed keys does not allow for fine grained control + Resolution Enable encryption using customer managed keys + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/encryption-customer-key/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket#enable-default-server-side-encryption +──────────────────────────────────────────────────────────────────────────────── + + +Result #31 HIGH No public access block so not blocking public acls  +──────────────────────────────────────────────────────────────────────────────── + ../submodules/storage/main.tf Lines 421-434 +───────┬──────────────────────────────────────────────────────────────────────── + 421 │ resource "aws_s3_bucket" "registry" { + 422 │  arn = "arn:aws:s3:::${var.deploy_id}-registry" + 423 │  bucket = "${var.deploy_id}-registry" + 424 │  force_destroy = "false" + 425 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 426 │  object_lock_enabled = "false" + 427 │  tags = var.tags + 428 │  + 429 │  lifecycle { + 430 │  ignore_changes = [ + 431 │  hosted_zone_id, + 432 │  ] + 433 │  } + 434 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-block-public-acls +  Impact PUT calls with public ACLs specified can make objects public + Resolution Enable blocking any PUT calls with a public ACL specified + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/block-public-acls/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block#block_public_acls +──────────────────────────────────────────────────────────────────────────────── + + +Result #32 HIGH No public access block so not blocking public policies  +──────────────────────────────────────────────────────────────────────────────── + ../submodules/storage/main.tf Lines 421-434 +───────┬──────────────────────────────────────────────────────────────────────── + 421 │ resource "aws_s3_bucket" "registry" { + 422 │  arn = "arn:aws:s3:::${var.deploy_id}-registry" + 423 │  bucket = "${var.deploy_id}-registry" + 424 │  force_destroy = "false" + 425 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 426 │  object_lock_enabled = "false" + 427 │  tags = var.tags + 428 │  + 429 │  lifecycle { + 430 │  ignore_changes = [ + 431 │  hosted_zone_id, + 432 │  ] + 433 │  } + 434 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-block-public-policy +  Impact Users could put a policy that allows public access + Resolution Prevent policies that allow public access being PUT + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/block-public-policy/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block#block_public_policy +──────────────────────────────────────────────────────────────────────────────── + + +Result #33 HIGH Bucket does not have encryption enabled  +──────────────────────────────────────────────────────────────────────────────── + ../submodules/storage/main.tf Lines 421-434 +───────┬──────────────────────────────────────────────────────────────────────── + 421 │ resource "aws_s3_bucket" "registry" { + 422 │  arn = "arn:aws:s3:::${var.deploy_id}-registry" + 423 │  bucket = "${var.deploy_id}-registry" + 424 │  force_destroy = "false" + 425 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 426 │  object_lock_enabled = "false" + 427 │  tags = var.tags + 428 │  + 429 │  lifecycle { + 430 │  ignore_changes = [ + 431 │  hosted_zone_id, + 432 │  ] + 433 │  } + 434 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-enable-bucket-encryption +  Impact The bucket objects could be read if compromised + Resolution Configure bucket encryption + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/enable-bucket-encryption/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket#enable-default-server-side-encryption +──────────────────────────────────────────────────────────────────────────────── + + +Result #34 HIGH No public access block so not ignoring public acls  +──────────────────────────────────────────────────────────────────────────────── + ../submodules/storage/main.tf Lines 421-434 +───────┬──────────────────────────────────────────────────────────────────────── + 421 │ resource "aws_s3_bucket" "registry" { + 422 │  arn = "arn:aws:s3:::${var.deploy_id}-registry" + 423 │  bucket = "${var.deploy_id}-registry" + 424 │  force_destroy = "false" + 425 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 426 │  object_lock_enabled = "false" + 427 │  tags = var.tags + 428 │  + 429 │  lifecycle { + 430 │  ignore_changes = [ + 431 │  hosted_zone_id, + 432 │  ] + 433 │  } + 434 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-ignore-public-acls +  Impact PUT calls with public ACLs specified can make objects public + Resolution Enable ignoring the application of public ACLs in PUT calls + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/ignore-public-acls/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block#ignore_public_acls +──────────────────────────────────────────────────────────────────────────────── + + +Result #35 HIGH No public access block so not restricting public buckets  +──────────────────────────────────────────────────────────────────────────────── + ../submodules/storage/main.tf Lines 421-434 +───────┬──────────────────────────────────────────────────────────────────────── + 421 │ resource "aws_s3_bucket" "registry" { + 422 │  arn = "arn:aws:s3:::${var.deploy_id}-registry" + 423 │  bucket = "${var.deploy_id}-registry" + 424 │  force_destroy = "false" + 425 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 426 │  object_lock_enabled = "false" + 427 │  tags = var.tags + 428 │  + 429 │  lifecycle { + 430 │  ignore_changes = [ + 431 │  hosted_zone_id, + 432 │  ] + 433 │  } + 434 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-no-public-buckets +  Impact Public buckets can be accessed by anyone + Resolution Limit the access to public buckets to only the owner or AWS Services (eg; CloudFront) + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/no-public-buckets/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block#restrict_public_buckets¡ +──────────────────────────────────────────────────────────────────────────────── + + +Result #36 HIGH Bucket does not encrypt data with a customer managed key.  +──────────────────────────────────────────────────────────────────────────────── + ../submodules/storage/main.tf Lines 421-434 +───────┬──────────────────────────────────────────────────────────────────────── + 421 │ resource "aws_s3_bucket" "registry" { + 422 │  arn = "arn:aws:s3:::${var.deploy_id}-registry" + 423 │  bucket = "${var.deploy_id}-registry" + 424 │  force_destroy = "false" + 425 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 426 │  object_lock_enabled = "false" + 427 │  tags = var.tags + 428 │  + 429 │  lifecycle { + 430 │  ignore_changes = [ + 431 │  hosted_zone_id, + 432 │  ] + 433 │  } + 434 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-encryption-customer-key +  Impact Using AWS managed keys does not allow for fine grained control + Resolution Enable encryption using customer managed keys + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/encryption-customer-key/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket#enable-default-server-side-encryption +──────────────────────────────────────────────────────────────────────────────── + + +Result #37 HIGH No public access block so not blocking public acls  +──────────────────────────────────────────────────────────────────────────────── + ../submodules/storage/main.tf Lines 72-84 +───────┬──────────────────────────────────────────────────────────────────────── + 72 │ resource "aws_s3_bucket" "backups" { + 73 │  bucket = "${var.deploy_id}-backups" + 74 │  force_destroy = "false" + 75 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 76 │  object_lock_enabled = "false" + 77 │  tags = var.tags + 78 │  + 79 │  lifecycle { + 80 │  ignore_changes = [ + 81 │  hosted_zone_id, + 82 │  ] + 83 │  } + 84 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-block-public-acls +  Impact PUT calls with public ACLs specified can make objects public + Resolution Enable blocking any PUT calls with a public ACL specified + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/block-public-acls/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block#block_public_acls +──────────────────────────────────────────────────────────────────────────────── + + +Result #38 HIGH No public access block so not blocking public policies  +──────────────────────────────────────────────────────────────────────────────── + ../submodules/storage/main.tf Lines 72-84 +───────┬──────────────────────────────────────────────────────────────────────── + 72 │ resource "aws_s3_bucket" "backups" { + 73 │  bucket = "${var.deploy_id}-backups" + 74 │  force_destroy = "false" + 75 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 76 │  object_lock_enabled = "false" + 77 │  tags = var.tags + 78 │  + 79 │  lifecycle { + 80 │  ignore_changes = [ + 81 │  hosted_zone_id, + 82 │  ] + 83 │  } + 84 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-block-public-policy +  Impact Users could put a policy that allows public access + Resolution Prevent policies that allow public access being PUT + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/block-public-policy/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block#block_public_policy +──────────────────────────────────────────────────────────────────────────────── + + +Result #39 HIGH Bucket does not have encryption enabled  +──────────────────────────────────────────────────────────────────────────────── + ../submodules/storage/main.tf Lines 72-84 +───────┬──────────────────────────────────────────────────────────────────────── + 72 │ resource "aws_s3_bucket" "backups" { + 73 │  bucket = "${var.deploy_id}-backups" + 74 │  force_destroy = "false" + 75 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 76 │  object_lock_enabled = "false" + 77 │  tags = var.tags + 78 │  + 79 │  lifecycle { + 80 │  ignore_changes = [ + 81 │  hosted_zone_id, + 82 │  ] + 83 │  } + 84 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-enable-bucket-encryption +  Impact The bucket objects could be read if compromised + Resolution Configure bucket encryption + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/enable-bucket-encryption/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket#enable-default-server-side-encryption +──────────────────────────────────────────────────────────────────────────────── + + +Result #40 HIGH No public access block so not ignoring public acls  +──────────────────────────────────────────────────────────────────────────────── + ../submodules/storage/main.tf Lines 72-84 +───────┬──────────────────────────────────────────────────────────────────────── + 72 │ resource "aws_s3_bucket" "backups" { + 73 │  bucket = "${var.deploy_id}-backups" + 74 │  force_destroy = "false" + 75 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 76 │  object_lock_enabled = "false" + 77 │  tags = var.tags + 78 │  + 79 │  lifecycle { + 80 │  ignore_changes = [ + 81 │  hosted_zone_id, + 82 │  ] + 83 │  } + 84 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-ignore-public-acls +  Impact PUT calls with public ACLs specified can make objects public + Resolution Enable ignoring the application of public ACLs in PUT calls + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/ignore-public-acls/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block#ignore_public_acls +──────────────────────────────────────────────────────────────────────────────── + + +Result #41 HIGH No public access block so not restricting public buckets  +──────────────────────────────────────────────────────────────────────────────── + ../submodules/storage/main.tf Lines 72-84 +───────┬──────────────────────────────────────────────────────────────────────── + 72 │ resource "aws_s3_bucket" "backups" { + 73 │  bucket = "${var.deploy_id}-backups" + 74 │  force_destroy = "false" + 75 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 76 │  object_lock_enabled = "false" + 77 │  tags = var.tags + 78 │  + 79 │  lifecycle { + 80 │  ignore_changes = [ + 81 │  hosted_zone_id, + 82 │  ] + 83 │  } + 84 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-no-public-buckets +  Impact Public buckets can be accessed by anyone + Resolution Limit the access to public buckets to only the owner or AWS Services (eg; CloudFront) + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/no-public-buckets/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block#restrict_public_buckets¡ +──────────────────────────────────────────────────────────────────────────────── + + +Result #42 HIGH Bucket does not encrypt data with a customer managed key.  +──────────────────────────────────────────────────────────────────────────────── + ../submodules/storage/main.tf Lines 72-84 +───────┬──────────────────────────────────────────────────────────────────────── + 72 │ resource "aws_s3_bucket" "backups" { + 73 │  bucket = "${var.deploy_id}-backups" + 74 │  force_destroy = "false" + 75 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 76 │  object_lock_enabled = "false" + 77 │  tags = var.tags + 78 │  + 79 │  lifecycle { + 80 │  ignore_changes = [ + 81 │  hosted_zone_id, + 82 │  ] + 83 │  } + 84 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-encryption-customer-key +  Impact Using AWS managed keys does not allow for fine grained control + Resolution Enable encryption using customer managed keys + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/encryption-customer-key/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket#enable-default-server-side-encryption +──────────────────────────────────────────────────────────────────────────────── + + +Result #43 MEDIUM Bucket does not have logging enabled  +──────────────────────────────────────────────────────────────────────────────── + ../submodules/storage/main.tf Lines 148-160 +───────┬──────────────────────────────────────────────────────────────────────── + 148 │ resource "aws_s3_bucket" "blobs" { + 149 │  bucket = "${var.deploy_id}-blobs" + 150 │  force_destroy = "false" + 151 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 152 │  object_lock_enabled = "false" + 153 │  tags = var.tags + 154 │  + 155 │  lifecycle { + 156 │  ignore_changes = [ + 157 │  hosted_zone_id, + 158 │  ] + 159 │  } + 160 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-enable-bucket-logging +  Impact There is no way to determine the access to this bucket + Resolution Add a logging block to the resource to enable access logging + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/enable-bucket-logging/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket +──────────────────────────────────────────────────────────────────────────────── + + +Result #44 MEDIUM Bucket does not have versioning enabled  +──────────────────────────────────────────────────────────────────────────────── + ../submodules/storage/main.tf Lines 148-160 +───────┬──────────────────────────────────────────────────────────────────────── + 148 │ resource "aws_s3_bucket" "blobs" { + 149 │  bucket = "${var.deploy_id}-blobs" + 150 │  force_destroy = "false" + 151 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 152 │  object_lock_enabled = "false" + 153 │  tags = var.tags + 154 │  + 155 │  lifecycle { + 156 │  ignore_changes = [ + 157 │  hosted_zone_id, + 158 │  ] + 159 │  } + 160 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-enable-versioning +  Impact Deleted or modified data would not be recoverable + Resolution Enable versioning to protect against accidental/malicious removal or modification + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/enable-versioning/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket#versioning +──────────────────────────────────────────────────────────────────────────────── + + +Result #45 MEDIUM Bucket does not have logging enabled  +──────────────────────────────────────────────────────────────────────────────── + ../submodules/storage/main.tf Lines 223-235 +───────┬──────────────────────────────────────────────────────────────────────── + 223 │ resource "aws_s3_bucket" "logs" { + 224 │  bucket = "${var.deploy_id}-logs" + 225 │  force_destroy = "false" + 226 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 227 │  object_lock_enabled = "false" + 228 │  tags = var.tags + 229 │  + 230 │  lifecycle { + 231 │  ignore_changes = [ + 232 │  hosted_zone_id, + 233 │  ] + 234 │  } + 235 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-enable-bucket-logging +  Impact There is no way to determine the access to this bucket + Resolution Add a logging block to the resource to enable access logging + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/enable-bucket-logging/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket +──────────────────────────────────────────────────────────────────────────────── + + +Result #46 MEDIUM Bucket does not have versioning enabled  +──────────────────────────────────────────────────────────────────────────────── + ../submodules/storage/main.tf Lines 223-235 +───────┬──────────────────────────────────────────────────────────────────────── + 223 │ resource "aws_s3_bucket" "logs" { + 224 │  bucket = "${var.deploy_id}-logs" + 225 │  force_destroy = "false" + 226 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 227 │  object_lock_enabled = "false" + 228 │  tags = var.tags + 229 │  + 230 │  lifecycle { + 231 │  ignore_changes = [ + 232 │  hosted_zone_id, + 233 │  ] + 234 │  } + 235 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-enable-versioning +  Impact Deleted or modified data would not be recoverable + Resolution Enable versioning to protect against accidental/malicious removal or modification + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/enable-versioning/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket#versioning +──────────────────────────────────────────────────────────────────────────────── + + +Result #47 MEDIUM Bucket does not have logging enabled  +──────────────────────────────────────────────────────────────────────────────── + ../submodules/storage/main.tf Lines 313-325 +───────┬──────────────────────────────────────────────────────────────────────── + 313 │ resource "aws_s3_bucket" "monitoring" { + 314 │  bucket = "${var.deploy_id}-monitoring" + 315 │  force_destroy = "true" + 316 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 317 │  object_lock_enabled = "false" + 318 │  tags = var.tags + 319 │  + 320 │  lifecycle { + 321 │  ignore_changes = [ + 322 │  hosted_zone_id, + 323 │  ] + 324 │  } + 325 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-enable-bucket-logging +  Impact There is no way to determine the access to this bucket + Resolution Add a logging block to the resource to enable access logging + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/enable-bucket-logging/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket +──────────────────────────────────────────────────────────────────────────────── + + +Result #48 MEDIUM Bucket does not have versioning enabled  +──────────────────────────────────────────────────────────────────────────────── + ../submodules/storage/main.tf Lines 313-325 +───────┬──────────────────────────────────────────────────────────────────────── + 313 │ resource "aws_s3_bucket" "monitoring" { + 314 │  bucket = "${var.deploy_id}-monitoring" + 315 │  force_destroy = "true" + 316 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 317 │  object_lock_enabled = "false" + 318 │  tags = var.tags + 319 │  + 320 │  lifecycle { + 321 │  ignore_changes = [ + 322 │  hosted_zone_id, + 323 │  ] + 324 │  } + 325 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-enable-versioning +  Impact Deleted or modified data would not be recoverable + Resolution Enable versioning to protect against accidental/malicious removal or modification + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/enable-versioning/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket#versioning +──────────────────────────────────────────────────────────────────────────────── + + +Result #49 MEDIUM Bucket does not have logging enabled  +──────────────────────────────────────────────────────────────────────────────── + ../submodules/storage/main.tf Lines 421-434 +───────┬──────────────────────────────────────────────────────────────────────── + 421 │ resource "aws_s3_bucket" "registry" { + 422 │  arn = "arn:aws:s3:::${var.deploy_id}-registry" + 423 │  bucket = "${var.deploy_id}-registry" + 424 │  force_destroy = "false" + 425 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 426 │  object_lock_enabled = "false" + 427 │  tags = var.tags + 428 │  + 429 │  lifecycle { + 430 │  ignore_changes = [ + 431 │  hosted_zone_id, + 432 │  ] + 433 │  } + 434 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-enable-bucket-logging +  Impact There is no way to determine the access to this bucket + Resolution Add a logging block to the resource to enable access logging + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/enable-bucket-logging/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket +──────────────────────────────────────────────────────────────────────────────── + + +Result #50 MEDIUM Bucket does not have versioning enabled  +──────────────────────────────────────────────────────────────────────────────── + ../submodules/storage/main.tf Lines 421-434 +───────┬──────────────────────────────────────────────────────────────────────── + 421 │ resource "aws_s3_bucket" "registry" { + 422 │  arn = "arn:aws:s3:::${var.deploy_id}-registry" + 423 │  bucket = "${var.deploy_id}-registry" + 424 │  force_destroy = "false" + 425 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 426 │  object_lock_enabled = "false" + 427 │  tags = var.tags + 428 │  + 429 │  lifecycle { + 430 │  ignore_changes = [ + 431 │  hosted_zone_id, + 432 │  ] + 433 │  } + 434 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-enable-versioning +  Impact Deleted or modified data would not be recoverable + Resolution Enable versioning to protect against accidental/malicious removal or modification + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/enable-versioning/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket#versioning +──────────────────────────────────────────────────────────────────────────────── + + +Result #51 MEDIUM Bucket does not have logging enabled  +──────────────────────────────────────────────────────────────────────────────── + ../submodules/storage/main.tf Lines 72-84 +───────┬──────────────────────────────────────────────────────────────────────── + 72 │ resource "aws_s3_bucket" "backups" { + 73 │  bucket = "${var.deploy_id}-backups" + 74 │  force_destroy = "false" + 75 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 76 │  object_lock_enabled = "false" + 77 │  tags = var.tags + 78 │  + 79 │  lifecycle { + 80 │  ignore_changes = [ + 81 │  hosted_zone_id, + 82 │  ] + 83 │  } + 84 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-enable-bucket-logging +  Impact There is no way to determine the access to this bucket + Resolution Add a logging block to the resource to enable access logging + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/enable-bucket-logging/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket +──────────────────────────────────────────────────────────────────────────────── + + +Result #52 MEDIUM Bucket does not have versioning enabled  +──────────────────────────────────────────────────────────────────────────────── + ../submodules/storage/main.tf Lines 72-84 +───────┬──────────────────────────────────────────────────────────────────────── + 72 │ resource "aws_s3_bucket" "backups" { + 73 │  bucket = "${var.deploy_id}-backups" + 74 │  force_destroy = "false" + 75 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 76 │  object_lock_enabled = "false" + 77 │  tags = var.tags + 78 │  + 79 │  lifecycle { + 80 │  ignore_changes = [ + 81 │  hosted_zone_id, + 82 │  ] + 83 │  } + 84 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-enable-versioning +  Impact Deleted or modified data would not be recoverable + Resolution Enable versioning to protect against accidental/malicious removal or modification + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/enable-versioning/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket#versioning +──────────────────────────────────────────────────────────────────────────────── + + +Result #53 LOW Bucket does not have a corresponding public access block.  +──────────────────────────────────────────────────────────────────────────────── + ../submodules/storage/main.tf Lines 148-160 +───────┬──────────────────────────────────────────────────────────────────────── + 148 │ resource "aws_s3_bucket" "blobs" { + 149 │  bucket = "${var.deploy_id}-blobs" + 150 │  force_destroy = "false" + 151 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 152 │  object_lock_enabled = "false" + 153 │  tags = var.tags + 154 │  + 155 │  lifecycle { + 156 │  ignore_changes = [ + 157 │  hosted_zone_id, + 158 │  ] + 159 │  } + 160 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-specify-public-access-block +  Impact Public access policies may be applied to sensitive data buckets + Resolution Define a aws_s3_bucket_public_access_block for the given bucket to control public access policies + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/specify-public-access-block/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block#bucket +──────────────────────────────────────────────────────────────────────────────── + + +Result #54 LOW Bucket does not have a corresponding public access block.  +──────────────────────────────────────────────────────────────────────────────── + ../submodules/storage/main.tf Lines 223-235 +───────┬──────────────────────────────────────────────────────────────────────── + 223 │ resource "aws_s3_bucket" "logs" { + 224 │  bucket = "${var.deploy_id}-logs" + 225 │  force_destroy = "false" + 226 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 227 │  object_lock_enabled = "false" + 228 │  tags = var.tags + 229 │  + 230 │  lifecycle { + 231 │  ignore_changes = [ + 232 │  hosted_zone_id, + 233 │  ] + 234 │  } + 235 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-specify-public-access-block +  Impact Public access policies may be applied to sensitive data buckets + Resolution Define a aws_s3_bucket_public_access_block for the given bucket to control public access policies + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/specify-public-access-block/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block#bucket +──────────────────────────────────────────────────────────────────────────────── + + +Result #55 LOW Bucket does not have a corresponding public access block.  +──────────────────────────────────────────────────────────────────────────────── + ../submodules/storage/main.tf Lines 313-325 +───────┬──────────────────────────────────────────────────────────────────────── + 313 │ resource "aws_s3_bucket" "monitoring" { + 314 │  bucket = "${var.deploy_id}-monitoring" + 315 │  force_destroy = "true" + 316 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 317 │  object_lock_enabled = "false" + 318 │  tags = var.tags + 319 │  + 320 │  lifecycle { + 321 │  ignore_changes = [ + 322 │  hosted_zone_id, + 323 │  ] + 324 │  } + 325 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-specify-public-access-block +  Impact Public access policies may be applied to sensitive data buckets + Resolution Define a aws_s3_bucket_public_access_block for the given bucket to control public access policies + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/specify-public-access-block/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block#bucket +──────────────────────────────────────────────────────────────────────────────── + + +Result #56 LOW Bucket does not have a corresponding public access block.  +──────────────────────────────────────────────────────────────────────────────── + ../submodules/storage/main.tf Lines 421-434 +───────┬──────────────────────────────────────────────────────────────────────── + 421 │ resource "aws_s3_bucket" "registry" { + 422 │  arn = "arn:aws:s3:::${var.deploy_id}-registry" + 423 │  bucket = "${var.deploy_id}-registry" + 424 │  force_destroy = "false" + 425 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 426 │  object_lock_enabled = "false" + 427 │  tags = var.tags + 428 │  + 429 │  lifecycle { + 430 │  ignore_changes = [ + 431 │  hosted_zone_id, + 432 │  ] + 433 │  } + 434 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-specify-public-access-block +  Impact Public access policies may be applied to sensitive data buckets + Resolution Define a aws_s3_bucket_public_access_block for the given bucket to control public access policies + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/specify-public-access-block/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block#bucket +──────────────────────────────────────────────────────────────────────────────── + + +Result #57 LOW Bucket does not have a corresponding public access block.  +──────────────────────────────────────────────────────────────────────────────── + ../submodules/storage/main.tf Lines 72-84 +───────┬──────────────────────────────────────────────────────────────────────── + 72 │ resource "aws_s3_bucket" "backups" { + 73 │  bucket = "${var.deploy_id}-backups" + 74 │  force_destroy = "false" + 75 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 76 │  object_lock_enabled = "false" + 77 │  tags = var.tags + 78 │  + 79 │  lifecycle { + 80 │  ignore_changes = [ + 81 │  hosted_zone_id, + 82 │  ] + 83 │  } + 84 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-specify-public-access-block +  Impact Public access policies may be applied to sensitive data buckets + Resolution Define a aws_s3_bucket_public_access_block for the given bucket to control public access policies + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/specify-public-access-block/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block#bucket +──────────────────────────────────────────────────────────────────────────────── + + + timings + ────────────────────────────────────────── + disk i/o  3.539778ms + parsing  142.938486ms + adaptation  3.508176ms + checks  15.017841ms + total  165.004281ms + + counts + ────────────────────────────────────────── + modules downloaded  0 + modules processed  8 + blocks processed  215 + files read  41 + + results + ────────────────────────────────────────── + passed  98 + ignored  0 + critical  0 + high  42 + medium  10 + low  5 + + 98 passed, 57 potential problem(s) detected. + + timings + ────────────────────────────────────────── + disk i/o  257.752µs + parsing  1.954257ms + adaptation  250.256µs + checks  12.378276ms + total  14.840541ms + + counts + ────────────────────────────────────────── + modules downloaded  0 + modules processed  1 + blocks processed  25 + files read  4 + + results + ────────────────────────────────────────── + passed  9 + ignored  0 + critical  0 + high  0 + medium  0 + low  0 + + +No problems detected! + + +Results #1-2 HIGH IAM policy document uses sensitive action 'ec2:CreateTags' on wildcarded resource 'arn:aws:ec2:*:*:volume/*' (2 similar results) +──────────────────────────────────────────────────────────────────────────────── + iam.tf Lines 149-152 +───────┬──────────────────────────────────────────────────────────────────────── + 149 │  resources = [ + 150 │  "arn:aws:ec2:*:*:volume/*", + 151 │  "arn:aws:ec2:*:*:snapshot/*", + 152 │  ] +───────┴──────────────────────────────────────────────────────────────────────── + Individual Causes + - /Users/miguel.harmant/src/dominodatalab/terraform-aws-eks/submodules/eks/iam.tf:109-208 (data.aws_iam_policy_document.ebs_csi) + - /Users/miguel.harmant/src/dominodatalab/terraform-aws-eks/submodules/eks/iam.tf:109-208 (data.aws_iam_policy_document.ebs_csi) +──────────────────────────────────────────────────────────────────────────────── +  ID aws-iam-no-policy-wildcards +  Impact Overly permissive policies may grant access to sensitive resources + Resolution Specify the exact permissions required, and to which resources they should apply instead of using wildcards. + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/iam/no-policy-wildcards/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document +──────────────────────────────────────────────────────────────────────────────── + + +Results #3-4 HIGH IAM policy document uses sensitive action 'ec2:DeleteTags' on wildcarded resource 'arn:aws:ec2:*:*:volume/*' (2 similar results) +──────────────────────────────────────────────────────────────────────────────── + iam.tf Lines 171-174 +───────┬──────────────────────────────────────────────────────────────────────── + 171 │  resources = [ + 172 │  "arn:aws:ec2:*:*:volume/*", + 173 │  "arn:aws:ec2:*:*:snapshot/*", + 174 │  ] +───────┴──────────────────────────────────────────────────────────────────────── + Individual Causes + - /Users/miguel.harmant/src/dominodatalab/terraform-aws-eks/submodules/eks/iam.tf:109-208 (data.aws_iam_policy_document.ebs_csi) + - /Users/miguel.harmant/src/dominodatalab/terraform-aws-eks/submodules/eks/iam.tf:109-208 (data.aws_iam_policy_document.ebs_csi) +──────────────────────────────────────────────────────────────────────────────── +  ID aws-iam-no-policy-wildcards +  Impact Overly permissive policies may grant access to sensitive resources + Resolution Specify the exact permissions required, and to which resources they should apply instead of using wildcards. + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/iam/no-policy-wildcards/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document +──────────────────────────────────────────────────────────────────────────────── + + +Result #5 HIGH IAM policy document uses sensitive action 'ec2:DeleteVolume' on wildcarded resource '*'  +──────────────────────────────────────────────────────────────────────────────── + iam.tf Line 195 +───────┬──────────────────────────────────────────────────────────────────────── + 192 │  statement { + 193 │  + 194 │  effect = "Allow" + 195 │  resources = ["*"] + 196 │  + 197 │  actions = [ + 198 │  "ec2:DeleteVolume", + 199 │  "ec2:DeleteSnapshot", + 200 │  ] + 201 │  + 202 │  condition { + 203 │  test = "StringLike" + 204 │  variable = "aws:ResourceTag/KubernetesCluster" + 205 │  values = [var.deploy_id] + 206 │  } + 207 │  } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-iam-no-policy-wildcards +  Impact Overly permissive policies may grant access to sensitive resources + Resolution Specify the exact permissions required, and to which resources they should apply instead of using wildcards. + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/iam/no-policy-wildcards/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document +──────────────────────────────────────────────────────────────────────────────── + + +Result #6 HIGH IAM policy document uses sensitive action 'ec2:CreateSnapshot' on wildcarded resource '*'  +──────────────────────────────────────────────────────────────────────────────── + iam.tf Line 247 +───────┬──────────────────────────────────────────────────────────────────────── + 244 │  statement { + 245 │  + 246 │  effect = "Allow" + 247 │  resources = ["*"] + 248 │  + 249 │  actions = [ + 250 │  "ec2:CreateSnapshot", + 251 │  "ec2:CreateTags", + 252 │  "ec2:DeleteSnapshot", + 253 │  "ec2:DeleteTags", + 254 │  "ec2:DescribeAvailabilityZones", + 255 │  "ec2:DescribeSnapshots", + 256 │  "ec2:DescribeTags", + 257 │  ] + 258 │  } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-iam-no-policy-wildcards +  Impact Overly permissive policies may grant access to sensitive resources + Resolution Specify the exact permissions required, and to which resources they should apply instead of using wildcards. + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/iam/no-policy-wildcards/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document +──────────────────────────────────────────────────────────────────────────────── + + +Result #7 HIGH IAM policy document uses sensitive action 's3:ListBucket' on wildcarded resource '*'  +──────────────────────────────────────────────────────────────────────────────── + iam.tf Line 34 +───────┬──────────────────────────────────────────────────────────────────────── + 31 │  statement { + 32 │  + 33 │  effect = "Allow" + 34 │  resources = ["*"] + 35 │  + 36 │  actions = [ + 37 │  "s3:ListBucket", + 38 │  "s3:GetBucketLocation", + 39 │  "s3:ListBucketMultipartUploads", + 40 │  ] + 41 │  } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-iam-no-policy-wildcards +  Impact Overly permissive policies may grant access to sensitive resources + Resolution Specify the exact permissions required, and to which resources they should apply instead of using wildcards. + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/iam/no-policy-wildcards/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document +──────────────────────────────────────────────────────────────────────────────── + + +Results #8-11 HIGH IAM policy document uses sensitive action 's3:PutObject' on wildcarded resource 'arn:aws:s3:::' (4 similar results) +──────────────────────────────────────────────────────────────────────────────── + iam.tf Lines 47-52 +───────┬──────────────────────────────────────────────────────────────────────── + 47 │  resources = [ + 48 │  "arn:aws:s3:::${var.deploy_id}-blobs*", + 49 │  "arn:aws:s3:::${var.deploy_id}-logs*", + 50 │  "arn:aws:s3:::${var.deploy_id}-backups*", + 51 │  "arn:aws:s3:::${var.deploy_id}-registry*", + 52 │  ] +───────┴──────────────────────────────────────────────────────────────────────── + Individual Causes + - /Users/miguel.harmant/src/dominodatalab/terraform-aws-eks/submodules/eks/iam.tf:30-62 (data.aws_iam_policy_document.s3) + - /Users/miguel.harmant/src/dominodatalab/terraform-aws-eks/submodules/eks/iam.tf:30-62 (data.aws_iam_policy_document.s3) + - /Users/miguel.harmant/src/dominodatalab/terraform-aws-eks/submodules/eks/iam.tf:30-62 (data.aws_iam_policy_document.s3) + - /Users/miguel.harmant/src/dominodatalab/terraform-aws-eks/submodules/eks/iam.tf:30-62 (data.aws_iam_policy_document.s3) +──────────────────────────────────────────────────────────────────────────────── +  ID aws-iam-no-policy-wildcards +  Impact Overly permissive policies may grant access to sensitive resources + Resolution Specify the exact permissions required, and to which resources they should apply instead of using wildcards. + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/iam/no-policy-wildcards/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document +──────────────────────────────────────────────────────────────────────────────── + + +Result #12 HIGH IAM policy document uses sensitive action 'autoscaling:SetDesiredCapacity' on wildcarded resource '*'  +──────────────────────────────────────────────────────────────────────────────── + iam.tf Line 87 +───────┬──────────────────────────────────────────────────────────────────────── + 84 │  statement { + 85 │  + 86 │  effect = "Allow" + 87 │  resources = ["*"] + 88 │  + 89 │  actions = [ + 90 │  "autoscaling:DescribeAutoScalingInstances", + 91 │  "autoscaling:SetDesiredCapacity", + 92 │  "autoscaling:TerminateInstanceInAutoScalingGroup", + 93 │  ] + 94 │  + 95 │  condition { + 96 │  test = "StringEquals" + 97 │  variable = "autoscaling:ResourceTag/eks:cluster-name" + 98 │  values = [var.deploy_id] + 99 │  } + 100 │  } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-iam-no-policy-wildcards +  Impact Overly permissive policies may grant access to sensitive resources + Resolution Specify the exact permissions required, and to which resources they should apply instead of using wildcards. + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/iam/no-policy-wildcards/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document +──────────────────────────────────────────────────────────────────────────────── + + + timings + ────────────────────────────────────────── + disk i/o  613.791µs + parsing  19.144145ms + adaptation  816.404µs + checks  15.066847ms + total  35.641187ms + + counts + ────────────────────────────────────────── + modules downloaded  0 + modules processed  1 + blocks processed  66 + files read  8 + + results + ────────────────────────────────────────── + passed  68 + ignored  0 + critical  0 + high  12 + medium  0 + low  0 + + 68 passed, 12 potential problem(s) detected. + + timings + ────────────────────────────────────────── + disk i/o  253.601µs + parsing  4.323863ms + adaptation  162.778µs + checks  12.516196ms + total  17.256438ms + + counts + ────────────────────────────────────────── + modules downloaded  0 + modules processed  1 + blocks processed  27 + files read  4 + + results + ────────────────────────────────────────── + passed  0 + ignored  0 + critical  0 + high  0 + medium  0 + low  0 + + +No problems detected! + + timings + ────────────────────────────────────────── + disk i/o  0s + parsing  0s + adaptation  0s + checks  0s + total  0s + + counts + ────────────────────────────────────────── + modules downloaded  0 + modules processed  0 + blocks processed  0 + files read  0 + + results + ────────────────────────────────────────── + passed  0 + ignored  0 + critical  0 + high  0 + medium  0 + low  0 + + +No problems detected! + + timings + ────────────────────────────────────────── + disk i/o  465.765µs + parsing  1.754874ms + adaptation  200.557µs + checks  13.614491ms + total  16.035687ms + + counts + ────────────────────────────────────────── + modules downloaded  0 + modules processed  1 + blocks processed  26 + files read  9 + + results + ────────────────────────────────────────── + passed  0 + ignored  0 + critical  0 + high  0 + medium  0 + low  0 + + +No problems detected! + + +Result #1 HIGH No public access block so not blocking public acls  +──────────────────────────────────────────────────────────────────────────────── + main.tf Lines 148-160 +───────┬──────────────────────────────────────────────────────────────────────── + 148 │ resource "aws_s3_bucket" "blobs" { + 149 │  bucket = "${var.deploy_id}-blobs" + 150 │  force_destroy = "false" + 151 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 152 │  object_lock_enabled = "false" + 153 │  tags = var.tags + 154 │  + 155 │  lifecycle { + 156 │  ignore_changes = [ + 157 │  hosted_zone_id, + 158 │  ] + 159 │  } + 160 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-block-public-acls +  Impact PUT calls with public ACLs specified can make objects public + Resolution Enable blocking any PUT calls with a public ACL specified + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/block-public-acls/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block#block_public_acls +──────────────────────────────────────────────────────────────────────────────── + + +Result #2 HIGH No public access block so not blocking public policies  +──────────────────────────────────────────────────────────────────────────────── + main.tf Lines 148-160 +───────┬──────────────────────────────────────────────────────────────────────── + 148 │ resource "aws_s3_bucket" "blobs" { + 149 │  bucket = "${var.deploy_id}-blobs" + 150 │  force_destroy = "false" + 151 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 152 │  object_lock_enabled = "false" + 153 │  tags = var.tags + 154 │  + 155 │  lifecycle { + 156 │  ignore_changes = [ + 157 │  hosted_zone_id, + 158 │  ] + 159 │  } + 160 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-block-public-policy +  Impact Users could put a policy that allows public access + Resolution Prevent policies that allow public access being PUT + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/block-public-policy/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block#block_public_policy +──────────────────────────────────────────────────────────────────────────────── + + +Result #3 HIGH Bucket does not have encryption enabled  +──────────────────────────────────────────────────────────────────────────────── + main.tf Lines 148-160 +───────┬──────────────────────────────────────────────────────────────────────── + 148 │ resource "aws_s3_bucket" "blobs" { + 149 │  bucket = "${var.deploy_id}-blobs" + 150 │  force_destroy = "false" + 151 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 152 │  object_lock_enabled = "false" + 153 │  tags = var.tags + 154 │  + 155 │  lifecycle { + 156 │  ignore_changes = [ + 157 │  hosted_zone_id, + 158 │  ] + 159 │  } + 160 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-enable-bucket-encryption +  Impact The bucket objects could be read if compromised + Resolution Configure bucket encryption + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/enable-bucket-encryption/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket#enable-default-server-side-encryption +──────────────────────────────────────────────────────────────────────────────── + + +Result #4 HIGH No public access block so not ignoring public acls  +──────────────────────────────────────────────────────────────────────────────── + main.tf Lines 148-160 +───────┬──────────────────────────────────────────────────────────────────────── + 148 │ resource "aws_s3_bucket" "blobs" { + 149 │  bucket = "${var.deploy_id}-blobs" + 150 │  force_destroy = "false" + 151 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 152 │  object_lock_enabled = "false" + 153 │  tags = var.tags + 154 │  + 155 │  lifecycle { + 156 │  ignore_changes = [ + 157 │  hosted_zone_id, + 158 │  ] + 159 │  } + 160 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-ignore-public-acls +  Impact PUT calls with public ACLs specified can make objects public + Resolution Enable ignoring the application of public ACLs in PUT calls + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/ignore-public-acls/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block#ignore_public_acls +──────────────────────────────────────────────────────────────────────────────── + + +Result #5 HIGH No public access block so not restricting public buckets  +──────────────────────────────────────────────────────────────────────────────── + main.tf Lines 148-160 +───────┬──────────────────────────────────────────────────────────────────────── + 148 │ resource "aws_s3_bucket" "blobs" { + 149 │  bucket = "${var.deploy_id}-blobs" + 150 │  force_destroy = "false" + 151 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 152 │  object_lock_enabled = "false" + 153 │  tags = var.tags + 154 │  + 155 │  lifecycle { + 156 │  ignore_changes = [ + 157 │  hosted_zone_id, + 158 │  ] + 159 │  } + 160 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-no-public-buckets +  Impact Public buckets can be accessed by anyone + Resolution Limit the access to public buckets to only the owner or AWS Services (eg; CloudFront) + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/no-public-buckets/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block#restrict_public_buckets¡ +──────────────────────────────────────────────────────────────────────────────── + + +Result #6 HIGH Bucket does not encrypt data with a customer managed key.  +──────────────────────────────────────────────────────────────────────────────── + main.tf Lines 148-160 +───────┬──────────────────────────────────────────────────────────────────────── + 148 │ resource "aws_s3_bucket" "blobs" { + 149 │  bucket = "${var.deploy_id}-blobs" + 150 │  force_destroy = "false" + 151 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 152 │  object_lock_enabled = "false" + 153 │  tags = var.tags + 154 │  + 155 │  lifecycle { + 156 │  ignore_changes = [ + 157 │  hosted_zone_id, + 158 │  ] + 159 │  } + 160 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-encryption-customer-key +  Impact Using AWS managed keys does not allow for fine grained control + Resolution Enable encryption using customer managed keys + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/encryption-customer-key/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket#enable-default-server-side-encryption +──────────────────────────────────────────────────────────────────────────────── + + +Result #7 HIGH No public access block so not blocking public acls  +──────────────────────────────────────────────────────────────────────────────── + main.tf Lines 223-235 +───────┬──────────────────────────────────────────────────────────────────────── + 223 │ resource "aws_s3_bucket" "logs" { + 224 │  bucket = "${var.deploy_id}-logs" + 225 │  force_destroy = "false" + 226 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 227 │  object_lock_enabled = "false" + 228 │  tags = var.tags + 229 │  + 230 │  lifecycle { + 231 │  ignore_changes = [ + 232 │  hosted_zone_id, + 233 │  ] + 234 │  } + 235 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-block-public-acls +  Impact PUT calls with public ACLs specified can make objects public + Resolution Enable blocking any PUT calls with a public ACL specified + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/block-public-acls/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block#block_public_acls +──────────────────────────────────────────────────────────────────────────────── + + +Result #8 HIGH No public access block so not blocking public policies  +──────────────────────────────────────────────────────────────────────────────── + main.tf Lines 223-235 +───────┬──────────────────────────────────────────────────────────────────────── + 223 │ resource "aws_s3_bucket" "logs" { + 224 │  bucket = "${var.deploy_id}-logs" + 225 │  force_destroy = "false" + 226 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 227 │  object_lock_enabled = "false" + 228 │  tags = var.tags + 229 │  + 230 │  lifecycle { + 231 │  ignore_changes = [ + 232 │  hosted_zone_id, + 233 │  ] + 234 │  } + 235 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-block-public-policy +  Impact Users could put a policy that allows public access + Resolution Prevent policies that allow public access being PUT + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/block-public-policy/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block#block_public_policy +──────────────────────────────────────────────────────────────────────────────── + + +Result #9 HIGH Bucket does not have encryption enabled  +──────────────────────────────────────────────────────────────────────────────── + main.tf Lines 223-235 +───────┬──────────────────────────────────────────────────────────────────────── + 223 │ resource "aws_s3_bucket" "logs" { + 224 │  bucket = "${var.deploy_id}-logs" + 225 │  force_destroy = "false" + 226 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 227 │  object_lock_enabled = "false" + 228 │  tags = var.tags + 229 │  + 230 │  lifecycle { + 231 │  ignore_changes = [ + 232 │  hosted_zone_id, + 233 │  ] + 234 │  } + 235 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-enable-bucket-encryption +  Impact The bucket objects could be read if compromised + Resolution Configure bucket encryption + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/enable-bucket-encryption/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket#enable-default-server-side-encryption +──────────────────────────────────────────────────────────────────────────────── + + +Result #10 HIGH No public access block so not ignoring public acls  +──────────────────────────────────────────────────────────────────────────────── + main.tf Lines 223-235 +───────┬──────────────────────────────────────────────────────────────────────── + 223 │ resource "aws_s3_bucket" "logs" { + 224 │  bucket = "${var.deploy_id}-logs" + 225 │  force_destroy = "false" + 226 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 227 │  object_lock_enabled = "false" + 228 │  tags = var.tags + 229 │  + 230 │  lifecycle { + 231 │  ignore_changes = [ + 232 │  hosted_zone_id, + 233 │  ] + 234 │  } + 235 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-ignore-public-acls +  Impact PUT calls with public ACLs specified can make objects public + Resolution Enable ignoring the application of public ACLs in PUT calls + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/ignore-public-acls/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block#ignore_public_acls +──────────────────────────────────────────────────────────────────────────────── + + +Result #11 HIGH No public access block so not restricting public buckets  +──────────────────────────────────────────────────────────────────────────────── + main.tf Lines 223-235 +───────┬──────────────────────────────────────────────────────────────────────── + 223 │ resource "aws_s3_bucket" "logs" { + 224 │  bucket = "${var.deploy_id}-logs" + 225 │  force_destroy = "false" + 226 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 227 │  object_lock_enabled = "false" + 228 │  tags = var.tags + 229 │  + 230 │  lifecycle { + 231 │  ignore_changes = [ + 232 │  hosted_zone_id, + 233 │  ] + 234 │  } + 235 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-no-public-buckets +  Impact Public buckets can be accessed by anyone + Resolution Limit the access to public buckets to only the owner or AWS Services (eg; CloudFront) + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/no-public-buckets/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block#restrict_public_buckets¡ +──────────────────────────────────────────────────────────────────────────────── + + +Result #12 HIGH Bucket does not encrypt data with a customer managed key.  +──────────────────────────────────────────────────────────────────────────────── + main.tf Lines 223-235 +───────┬──────────────────────────────────────────────────────────────────────── + 223 │ resource "aws_s3_bucket" "logs" { + 224 │  bucket = "${var.deploy_id}-logs" + 225 │  force_destroy = "false" + 226 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 227 │  object_lock_enabled = "false" + 228 │  tags = var.tags + 229 │  + 230 │  lifecycle { + 231 │  ignore_changes = [ + 232 │  hosted_zone_id, + 233 │  ] + 234 │  } + 235 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-encryption-customer-key +  Impact Using AWS managed keys does not allow for fine grained control + Resolution Enable encryption using customer managed keys + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/encryption-customer-key/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket#enable-default-server-side-encryption +──────────────────────────────────────────────────────────────────────────────── + + +Result #13 HIGH No public access block so not blocking public acls  +──────────────────────────────────────────────────────────────────────────────── + main.tf Lines 313-325 +───────┬──────────────────────────────────────────────────────────────────────── + 313 │ resource "aws_s3_bucket" "monitoring" { + 314 │  bucket = "${var.deploy_id}-monitoring" + 315 │  force_destroy = "true" + 316 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 317 │  object_lock_enabled = "false" + 318 │  tags = var.tags + 319 │  + 320 │  lifecycle { + 321 │  ignore_changes = [ + 322 │  hosted_zone_id, + 323 │  ] + 324 │  } + 325 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-block-public-acls +  Impact PUT calls with public ACLs specified can make objects public + Resolution Enable blocking any PUT calls with a public ACL specified + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/block-public-acls/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block#block_public_acls +──────────────────────────────────────────────────────────────────────────────── + + +Result #14 HIGH No public access block so not blocking public policies  +──────────────────────────────────────────────────────────────────────────────── + main.tf Lines 313-325 +───────┬──────────────────────────────────────────────────────────────────────── + 313 │ resource "aws_s3_bucket" "monitoring" { + 314 │  bucket = "${var.deploy_id}-monitoring" + 315 │  force_destroy = "true" + 316 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 317 │  object_lock_enabled = "false" + 318 │  tags = var.tags + 319 │  + 320 │  lifecycle { + 321 │  ignore_changes = [ + 322 │  hosted_zone_id, + 323 │  ] + 324 │  } + 325 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-block-public-policy +  Impact Users could put a policy that allows public access + Resolution Prevent policies that allow public access being PUT + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/block-public-policy/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block#block_public_policy +──────────────────────────────────────────────────────────────────────────────── + + +Result #15 HIGH Bucket does not have encryption enabled  +──────────────────────────────────────────────────────────────────────────────── + main.tf Lines 313-325 +───────┬──────────────────────────────────────────────────────────────────────── + 313 │ resource "aws_s3_bucket" "monitoring" { + 314 │  bucket = "${var.deploy_id}-monitoring" + 315 │  force_destroy = "true" + 316 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 317 │  object_lock_enabled = "false" + 318 │  tags = var.tags + 319 │  + 320 │  lifecycle { + 321 │  ignore_changes = [ + 322 │  hosted_zone_id, + 323 │  ] + 324 │  } + 325 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-enable-bucket-encryption +  Impact The bucket objects could be read if compromised + Resolution Configure bucket encryption + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/enable-bucket-encryption/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket#enable-default-server-side-encryption +──────────────────────────────────────────────────────────────────────────────── + + +Result #16 HIGH No public access block so not ignoring public acls  +──────────────────────────────────────────────────────────────────────────────── + main.tf Lines 313-325 +───────┬──────────────────────────────────────────────────────────────────────── + 313 │ resource "aws_s3_bucket" "monitoring" { + 314 │  bucket = "${var.deploy_id}-monitoring" + 315 │  force_destroy = "true" + 316 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 317 │  object_lock_enabled = "false" + 318 │  tags = var.tags + 319 │  + 320 │  lifecycle { + 321 │  ignore_changes = [ + 322 │  hosted_zone_id, + 323 │  ] + 324 │  } + 325 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-ignore-public-acls +  Impact PUT calls with public ACLs specified can make objects public + Resolution Enable ignoring the application of public ACLs in PUT calls + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/ignore-public-acls/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block#ignore_public_acls +──────────────────────────────────────────────────────────────────────────────── + + +Result #17 HIGH No public access block so not restricting public buckets  +──────────────────────────────────────────────────────────────────────────────── + main.tf Lines 313-325 +───────┬──────────────────────────────────────────────────────────────────────── + 313 │ resource "aws_s3_bucket" "monitoring" { + 314 │  bucket = "${var.deploy_id}-monitoring" + 315 │  force_destroy = "true" + 316 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 317 │  object_lock_enabled = "false" + 318 │  tags = var.tags + 319 │  + 320 │  lifecycle { + 321 │  ignore_changes = [ + 322 │  hosted_zone_id, + 323 │  ] + 324 │  } + 325 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-no-public-buckets +  Impact Public buckets can be accessed by anyone + Resolution Limit the access to public buckets to only the owner or AWS Services (eg; CloudFront) + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/no-public-buckets/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block#restrict_public_buckets¡ +──────────────────────────────────────────────────────────────────────────────── + + +Result #18 HIGH Bucket does not encrypt data with a customer managed key.  +──────────────────────────────────────────────────────────────────────────────── + main.tf Lines 313-325 +───────┬──────────────────────────────────────────────────────────────────────── + 313 │ resource "aws_s3_bucket" "monitoring" { + 314 │  bucket = "${var.deploy_id}-monitoring" + 315 │  force_destroy = "true" + 316 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 317 │  object_lock_enabled = "false" + 318 │  tags = var.tags + 319 │  + 320 │  lifecycle { + 321 │  ignore_changes = [ + 322 │  hosted_zone_id, + 323 │  ] + 324 │  } + 325 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-encryption-customer-key +  Impact Using AWS managed keys does not allow for fine grained control + Resolution Enable encryption using customer managed keys + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/encryption-customer-key/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket#enable-default-server-side-encryption +──────────────────────────────────────────────────────────────────────────────── + + +Result #19 HIGH No public access block so not blocking public acls  +──────────────────────────────────────────────────────────────────────────────── + main.tf Lines 421-434 +───────┬──────────────────────────────────────────────────────────────────────── + 421 │ resource "aws_s3_bucket" "registry" { + 422 │  arn = "arn:aws:s3:::${var.deploy_id}-registry" + 423 │  bucket = "${var.deploy_id}-registry" + 424 │  force_destroy = "false" + 425 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 426 │  object_lock_enabled = "false" + 427 │  tags = var.tags + 428 │  + 429 │  lifecycle { + 430 │  ignore_changes = [ + 431 │  hosted_zone_id, + 432 │  ] + 433 │  } + 434 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-block-public-acls +  Impact PUT calls with public ACLs specified can make objects public + Resolution Enable blocking any PUT calls with a public ACL specified + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/block-public-acls/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block#block_public_acls +──────────────────────────────────────────────────────────────────────────────── + + +Result #20 HIGH No public access block so not blocking public policies  +──────────────────────────────────────────────────────────────────────────────── + main.tf Lines 421-434 +───────┬──────────────────────────────────────────────────────────────────────── + 421 │ resource "aws_s3_bucket" "registry" { + 422 │  arn = "arn:aws:s3:::${var.deploy_id}-registry" + 423 │  bucket = "${var.deploy_id}-registry" + 424 │  force_destroy = "false" + 425 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 426 │  object_lock_enabled = "false" + 427 │  tags = var.tags + 428 │  + 429 │  lifecycle { + 430 │  ignore_changes = [ + 431 │  hosted_zone_id, + 432 │  ] + 433 │  } + 434 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-block-public-policy +  Impact Users could put a policy that allows public access + Resolution Prevent policies that allow public access being PUT + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/block-public-policy/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block#block_public_policy +──────────────────────────────────────────────────────────────────────────────── + + +Result #21 HIGH Bucket does not have encryption enabled  +──────────────────────────────────────────────────────────────────────────────── + main.tf Lines 421-434 +───────┬──────────────────────────────────────────────────────────────────────── + 421 │ resource "aws_s3_bucket" "registry" { + 422 │  arn = "arn:aws:s3:::${var.deploy_id}-registry" + 423 │  bucket = "${var.deploy_id}-registry" + 424 │  force_destroy = "false" + 425 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 426 │  object_lock_enabled = "false" + 427 │  tags = var.tags + 428 │  + 429 │  lifecycle { + 430 │  ignore_changes = [ + 431 │  hosted_zone_id, + 432 │  ] + 433 │  } + 434 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-enable-bucket-encryption +  Impact The bucket objects could be read if compromised + Resolution Configure bucket encryption + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/enable-bucket-encryption/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket#enable-default-server-side-encryption +──────────────────────────────────────────────────────────────────────────────── + + +Result #22 HIGH No public access block so not ignoring public acls  +──────────────────────────────────────────────────────────────────────────────── + main.tf Lines 421-434 +───────┬──────────────────────────────────────────────────────────────────────── + 421 │ resource "aws_s3_bucket" "registry" { + 422 │  arn = "arn:aws:s3:::${var.deploy_id}-registry" + 423 │  bucket = "${var.deploy_id}-registry" + 424 │  force_destroy = "false" + 425 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 426 │  object_lock_enabled = "false" + 427 │  tags = var.tags + 428 │  + 429 │  lifecycle { + 430 │  ignore_changes = [ + 431 │  hosted_zone_id, + 432 │  ] + 433 │  } + 434 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-ignore-public-acls +  Impact PUT calls with public ACLs specified can make objects public + Resolution Enable ignoring the application of public ACLs in PUT calls + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/ignore-public-acls/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block#ignore_public_acls +──────────────────────────────────────────────────────────────────────────────── + + +Result #23 HIGH No public access block so not restricting public buckets  +──────────────────────────────────────────────────────────────────────────────── + main.tf Lines 421-434 +───────┬──────────────────────────────────────────────────────────────────────── + 421 │ resource "aws_s3_bucket" "registry" { + 422 │  arn = "arn:aws:s3:::${var.deploy_id}-registry" + 423 │  bucket = "${var.deploy_id}-registry" + 424 │  force_destroy = "false" + 425 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 426 │  object_lock_enabled = "false" + 427 │  tags = var.tags + 428 │  + 429 │  lifecycle { + 430 │  ignore_changes = [ + 431 │  hosted_zone_id, + 432 │  ] + 433 │  } + 434 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-no-public-buckets +  Impact Public buckets can be accessed by anyone + Resolution Limit the access to public buckets to only the owner or AWS Services (eg; CloudFront) + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/no-public-buckets/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block#restrict_public_buckets¡ +──────────────────────────────────────────────────────────────────────────────── + + +Result #24 HIGH Bucket does not encrypt data with a customer managed key.  +──────────────────────────────────────────────────────────────────────────────── + main.tf Lines 421-434 +───────┬──────────────────────────────────────────────────────────────────────── + 421 │ resource "aws_s3_bucket" "registry" { + 422 │  arn = "arn:aws:s3:::${var.deploy_id}-registry" + 423 │  bucket = "${var.deploy_id}-registry" + 424 │  force_destroy = "false" + 425 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 426 │  object_lock_enabled = "false" + 427 │  tags = var.tags + 428 │  + 429 │  lifecycle { + 430 │  ignore_changes = [ + 431 │  hosted_zone_id, + 432 │  ] + 433 │  } + 434 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-encryption-customer-key +  Impact Using AWS managed keys does not allow for fine grained control + Resolution Enable encryption using customer managed keys + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/encryption-customer-key/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket#enable-default-server-side-encryption +──────────────────────────────────────────────────────────────────────────────── + + +Result #25 HIGH No public access block so not blocking public acls  +──────────────────────────────────────────────────────────────────────────────── + main.tf Lines 72-84 +───────┬──────────────────────────────────────────────────────────────────────── + 72 │ resource "aws_s3_bucket" "backups" { + 73 │  bucket = "${var.deploy_id}-backups" + 74 │  force_destroy = "false" + 75 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 76 │  object_lock_enabled = "false" + 77 │  tags = var.tags + 78 │  + 79 │  lifecycle { + 80 │  ignore_changes = [ + 81 │  hosted_zone_id, + 82 │  ] + 83 │  } + 84 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-block-public-acls +  Impact PUT calls with public ACLs specified can make objects public + Resolution Enable blocking any PUT calls with a public ACL specified + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/block-public-acls/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block#block_public_acls +──────────────────────────────────────────────────────────────────────────────── + + +Result #26 HIGH No public access block so not blocking public policies  +──────────────────────────────────────────────────────────────────────────────── + main.tf Lines 72-84 +───────┬──────────────────────────────────────────────────────────────────────── + 72 │ resource "aws_s3_bucket" "backups" { + 73 │  bucket = "${var.deploy_id}-backups" + 74 │  force_destroy = "false" + 75 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 76 │  object_lock_enabled = "false" + 77 │  tags = var.tags + 78 │  + 79 │  lifecycle { + 80 │  ignore_changes = [ + 81 │  hosted_zone_id, + 82 │  ] + 83 │  } + 84 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-block-public-policy +  Impact Users could put a policy that allows public access + Resolution Prevent policies that allow public access being PUT + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/block-public-policy/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block#block_public_policy +──────────────────────────────────────────────────────────────────────────────── + + +Result #27 HIGH Bucket does not have encryption enabled  +──────────────────────────────────────────────────────────────────────────────── + main.tf Lines 72-84 +───────┬──────────────────────────────────────────────────────────────────────── + 72 │ resource "aws_s3_bucket" "backups" { + 73 │  bucket = "${var.deploy_id}-backups" + 74 │  force_destroy = "false" + 75 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 76 │  object_lock_enabled = "false" + 77 │  tags = var.tags + 78 │  + 79 │  lifecycle { + 80 │  ignore_changes = [ + 81 │  hosted_zone_id, + 82 │  ] + 83 │  } + 84 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-enable-bucket-encryption +  Impact The bucket objects could be read if compromised + Resolution Configure bucket encryption + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/enable-bucket-encryption/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket#enable-default-server-side-encryption +──────────────────────────────────────────────────────────────────────────────── + + +Result #28 HIGH No public access block so not ignoring public acls  +──────────────────────────────────────────────────────────────────────────────── + main.tf Lines 72-84 +───────┬──────────────────────────────────────────────────────────────────────── + 72 │ resource "aws_s3_bucket" "backups" { + 73 │  bucket = "${var.deploy_id}-backups" + 74 │  force_destroy = "false" + 75 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 76 │  object_lock_enabled = "false" + 77 │  tags = var.tags + 78 │  + 79 │  lifecycle { + 80 │  ignore_changes = [ + 81 │  hosted_zone_id, + 82 │  ] + 83 │  } + 84 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-ignore-public-acls +  Impact PUT calls with public ACLs specified can make objects public + Resolution Enable ignoring the application of public ACLs in PUT calls + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/ignore-public-acls/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block#ignore_public_acls +──────────────────────────────────────────────────────────────────────────────── + + +Result #29 HIGH No public access block so not restricting public buckets  +──────────────────────────────────────────────────────────────────────────────── + main.tf Lines 72-84 +───────┬──────────────────────────────────────────────────────────────────────── + 72 │ resource "aws_s3_bucket" "backups" { + 73 │  bucket = "${var.deploy_id}-backups" + 74 │  force_destroy = "false" + 75 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 76 │  object_lock_enabled = "false" + 77 │  tags = var.tags + 78 │  + 79 │  lifecycle { + 80 │  ignore_changes = [ + 81 │  hosted_zone_id, + 82 │  ] + 83 │  } + 84 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-no-public-buckets +  Impact Public buckets can be accessed by anyone + Resolution Limit the access to public buckets to only the owner or AWS Services (eg; CloudFront) + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/no-public-buckets/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block#restrict_public_buckets¡ +──────────────────────────────────────────────────────────────────────────────── + + +Result #30 HIGH Bucket does not encrypt data with a customer managed key.  +──────────────────────────────────────────────────────────────────────────────── + main.tf Lines 72-84 +───────┬──────────────────────────────────────────────────────────────────────── + 72 │ resource "aws_s3_bucket" "backups" { + 73 │  bucket = "${var.deploy_id}-backups" + 74 │  force_destroy = "false" + 75 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 76 │  object_lock_enabled = "false" + 77 │  tags = var.tags + 78 │  + 79 │  lifecycle { + 80 │  ignore_changes = [ + 81 │  hosted_zone_id, + 82 │  ] + 83 │  } + 84 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-encryption-customer-key +  Impact Using AWS managed keys does not allow for fine grained control + Resolution Enable encryption using customer managed keys + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/encryption-customer-key/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket#enable-default-server-side-encryption +──────────────────────────────────────────────────────────────────────────────── + + +Result #31 MEDIUM Bucket does not have logging enabled  +──────────────────────────────────────────────────────────────────────────────── + main.tf Lines 148-160 +───────┬──────────────────────────────────────────────────────────────────────── + 148 │ resource "aws_s3_bucket" "blobs" { + 149 │  bucket = "${var.deploy_id}-blobs" + 150 │  force_destroy = "false" + 151 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 152 │  object_lock_enabled = "false" + 153 │  tags = var.tags + 154 │  + 155 │  lifecycle { + 156 │  ignore_changes = [ + 157 │  hosted_zone_id, + 158 │  ] + 159 │  } + 160 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-enable-bucket-logging +  Impact There is no way to determine the access to this bucket + Resolution Add a logging block to the resource to enable access logging + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/enable-bucket-logging/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket +──────────────────────────────────────────────────────────────────────────────── + + +Result #32 MEDIUM Bucket does not have versioning enabled  +──────────────────────────────────────────────────────────────────────────────── + main.tf Lines 148-160 +───────┬──────────────────────────────────────────────────────────────────────── + 148 │ resource "aws_s3_bucket" "blobs" { + 149 │  bucket = "${var.deploy_id}-blobs" + 150 │  force_destroy = "false" + 151 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 152 │  object_lock_enabled = "false" + 153 │  tags = var.tags + 154 │  + 155 │  lifecycle { + 156 │  ignore_changes = [ + 157 │  hosted_zone_id, + 158 │  ] + 159 │  } + 160 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-enable-versioning +  Impact Deleted or modified data would not be recoverable + Resolution Enable versioning to protect against accidental/malicious removal or modification + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/enable-versioning/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket#versioning +──────────────────────────────────────────────────────────────────────────────── + + +Result #33 MEDIUM Bucket does not have logging enabled  +──────────────────────────────────────────────────────────────────────────────── + main.tf Lines 223-235 +───────┬──────────────────────────────────────────────────────────────────────── + 223 │ resource "aws_s3_bucket" "logs" { + 224 │  bucket = "${var.deploy_id}-logs" + 225 │  force_destroy = "false" + 226 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 227 │  object_lock_enabled = "false" + 228 │  tags = var.tags + 229 │  + 230 │  lifecycle { + 231 │  ignore_changes = [ + 232 │  hosted_zone_id, + 233 │  ] + 234 │  } + 235 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-enable-bucket-logging +  Impact There is no way to determine the access to this bucket + Resolution Add a logging block to the resource to enable access logging + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/enable-bucket-logging/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket +──────────────────────────────────────────────────────────────────────────────── + + +Result #34 MEDIUM Bucket does not have versioning enabled  +──────────────────────────────────────────────────────────────────────────────── + main.tf Lines 223-235 +───────┬──────────────────────────────────────────────────────────────────────── + 223 │ resource "aws_s3_bucket" "logs" { + 224 │  bucket = "${var.deploy_id}-logs" + 225 │  force_destroy = "false" + 226 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 227 │  object_lock_enabled = "false" + 228 │  tags = var.tags + 229 │  + 230 │  lifecycle { + 231 │  ignore_changes = [ + 232 │  hosted_zone_id, + 233 │  ] + 234 │  } + 235 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-enable-versioning +  Impact Deleted or modified data would not be recoverable + Resolution Enable versioning to protect against accidental/malicious removal or modification + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/enable-versioning/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket#versioning +──────────────────────────────────────────────────────────────────────────────── + + +Result #35 MEDIUM Bucket does not have logging enabled  +──────────────────────────────────────────────────────────────────────────────── + main.tf Lines 313-325 +───────┬──────────────────────────────────────────────────────────────────────── + 313 │ resource "aws_s3_bucket" "monitoring" { + 314 │  bucket = "${var.deploy_id}-monitoring" + 315 │  force_destroy = "true" + 316 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 317 │  object_lock_enabled = "false" + 318 │  tags = var.tags + 319 │  + 320 │  lifecycle { + 321 │  ignore_changes = [ + 322 │  hosted_zone_id, + 323 │  ] + 324 │  } + 325 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-enable-bucket-logging +  Impact There is no way to determine the access to this bucket + Resolution Add a logging block to the resource to enable access logging + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/enable-bucket-logging/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket +──────────────────────────────────────────────────────────────────────────────── + + +Result #36 MEDIUM Bucket does not have versioning enabled  +──────────────────────────────────────────────────────────────────────────────── + main.tf Lines 313-325 +───────┬──────────────────────────────────────────────────────────────────────── + 313 │ resource "aws_s3_bucket" "monitoring" { + 314 │  bucket = "${var.deploy_id}-monitoring" + 315 │  force_destroy = "true" + 316 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 317 │  object_lock_enabled = "false" + 318 │  tags = var.tags + 319 │  + 320 │  lifecycle { + 321 │  ignore_changes = [ + 322 │  hosted_zone_id, + 323 │  ] + 324 │  } + 325 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-enable-versioning +  Impact Deleted or modified data would not be recoverable + Resolution Enable versioning to protect against accidental/malicious removal or modification + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/enable-versioning/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket#versioning +──────────────────────────────────────────────────────────────────────────────── + + +Result #37 MEDIUM Bucket does not have logging enabled  +──────────────────────────────────────────────────────────────────────────────── + main.tf Lines 421-434 +───────┬──────────────────────────────────────────────────────────────────────── + 421 │ resource "aws_s3_bucket" "registry" { + 422 │  arn = "arn:aws:s3:::${var.deploy_id}-registry" + 423 │  bucket = "${var.deploy_id}-registry" + 424 │  force_destroy = "false" + 425 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 426 │  object_lock_enabled = "false" + 427 │  tags = var.tags + 428 │  + 429 │  lifecycle { + 430 │  ignore_changes = [ + 431 │  hosted_zone_id, + 432 │  ] + 433 │  } + 434 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-enable-bucket-logging +  Impact There is no way to determine the access to this bucket + Resolution Add a logging block to the resource to enable access logging + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/enable-bucket-logging/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket +──────────────────────────────────────────────────────────────────────────────── + + +Result #38 MEDIUM Bucket does not have versioning enabled  +──────────────────────────────────────────────────────────────────────────────── + main.tf Lines 421-434 +───────┬──────────────────────────────────────────────────────────────────────── + 421 │ resource "aws_s3_bucket" "registry" { + 422 │  arn = "arn:aws:s3:::${var.deploy_id}-registry" + 423 │  bucket = "${var.deploy_id}-registry" + 424 │  force_destroy = "false" + 425 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 426 │  object_lock_enabled = "false" + 427 │  tags = var.tags + 428 │  + 429 │  lifecycle { + 430 │  ignore_changes = [ + 431 │  hosted_zone_id, + 432 │  ] + 433 │  } + 434 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-enable-versioning +  Impact Deleted or modified data would not be recoverable + Resolution Enable versioning to protect against accidental/malicious removal or modification + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/enable-versioning/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket#versioning +──────────────────────────────────────────────────────────────────────────────── + + +Result #39 MEDIUM Bucket does not have logging enabled  +──────────────────────────────────────────────────────────────────────────────── + main.tf Lines 72-84 +───────┬──────────────────────────────────────────────────────────────────────── + 72 │ resource "aws_s3_bucket" "backups" { + 73 │  bucket = "${var.deploy_id}-backups" + 74 │  force_destroy = "false" + 75 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 76 │  object_lock_enabled = "false" + 77 │  tags = var.tags + 78 │  + 79 │  lifecycle { + 80 │  ignore_changes = [ + 81 │  hosted_zone_id, + 82 │  ] + 83 │  } + 84 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-enable-bucket-logging +  Impact There is no way to determine the access to this bucket + Resolution Add a logging block to the resource to enable access logging + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/enable-bucket-logging/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket +──────────────────────────────────────────────────────────────────────────────── + + +Result #40 MEDIUM Bucket does not have versioning enabled  +──────────────────────────────────────────────────────────────────────────────── + main.tf Lines 72-84 +───────┬──────────────────────────────────────────────────────────────────────── + 72 │ resource "aws_s3_bucket" "backups" { + 73 │  bucket = "${var.deploy_id}-backups" + 74 │  force_destroy = "false" + 75 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 76 │  object_lock_enabled = "false" + 77 │  tags = var.tags + 78 │  + 79 │  lifecycle { + 80 │  ignore_changes = [ + 81 │  hosted_zone_id, + 82 │  ] + 83 │  } + 84 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-enable-versioning +  Impact Deleted or modified data would not be recoverable + Resolution Enable versioning to protect against accidental/malicious removal or modification + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/enable-versioning/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket#versioning +──────────────────────────────────────────────────────────────────────────────── + + +Result #41 LOW Bucket does not have a corresponding public access block.  +──────────────────────────────────────────────────────────────────────────────── + main.tf Lines 148-160 +───────┬──────────────────────────────────────────────────────────────────────── + 148 │ resource "aws_s3_bucket" "blobs" { + 149 │  bucket = "${var.deploy_id}-blobs" + 150 │  force_destroy = "false" + 151 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 152 │  object_lock_enabled = "false" + 153 │  tags = var.tags + 154 │  + 155 │  lifecycle { + 156 │  ignore_changes = [ + 157 │  hosted_zone_id, + 158 │  ] + 159 │  } + 160 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-specify-public-access-block +  Impact Public access policies may be applied to sensitive data buckets + Resolution Define a aws_s3_bucket_public_access_block for the given bucket to control public access policies + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/specify-public-access-block/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block#bucket +──────────────────────────────────────────────────────────────────────────────── + + +Result #42 LOW Bucket does not have a corresponding public access block.  +──────────────────────────────────────────────────────────────────────────────── + main.tf Lines 223-235 +───────┬──────────────────────────────────────────────────────────────────────── + 223 │ resource "aws_s3_bucket" "logs" { + 224 │  bucket = "${var.deploy_id}-logs" + 225 │  force_destroy = "false" + 226 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 227 │  object_lock_enabled = "false" + 228 │  tags = var.tags + 229 │  + 230 │  lifecycle { + 231 │  ignore_changes = [ + 232 │  hosted_zone_id, + 233 │  ] + 234 │  } + 235 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-specify-public-access-block +  Impact Public access policies may be applied to sensitive data buckets + Resolution Define a aws_s3_bucket_public_access_block for the given bucket to control public access policies + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/specify-public-access-block/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block#bucket +──────────────────────────────────────────────────────────────────────────────── + + +Result #43 LOW Bucket does not have a corresponding public access block.  +──────────────────────────────────────────────────────────────────────────────── + main.tf Lines 313-325 +───────┬──────────────────────────────────────────────────────────────────────── + 313 │ resource "aws_s3_bucket" "monitoring" { + 314 │  bucket = "${var.deploy_id}-monitoring" + 315 │  force_destroy = "true" + 316 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 317 │  object_lock_enabled = "false" + 318 │  tags = var.tags + 319 │  + 320 │  lifecycle { + 321 │  ignore_changes = [ + 322 │  hosted_zone_id, + 323 │  ] + 324 │  } + 325 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-specify-public-access-block +  Impact Public access policies may be applied to sensitive data buckets + Resolution Define a aws_s3_bucket_public_access_block for the given bucket to control public access policies + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/specify-public-access-block/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block#bucket +──────────────────────────────────────────────────────────────────────────────── + + +Result #44 LOW Bucket does not have a corresponding public access block.  +──────────────────────────────────────────────────────────────────────────────── + main.tf Lines 421-434 +───────┬──────────────────────────────────────────────────────────────────────── + 421 │ resource "aws_s3_bucket" "registry" { + 422 │  arn = "arn:aws:s3:::${var.deploy_id}-registry" + 423 │  bucket = "${var.deploy_id}-registry" + 424 │  force_destroy = "false" + 425 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 426 │  object_lock_enabled = "false" + 427 │  tags = var.tags + 428 │  + 429 │  lifecycle { + 430 │  ignore_changes = [ + 431 │  hosted_zone_id, + 432 │  ] + 433 │  } + 434 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-specify-public-access-block +  Impact Public access policies may be applied to sensitive data buckets + Resolution Define a aws_s3_bucket_public_access_block for the given bucket to control public access policies + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/specify-public-access-block/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block#bucket +──────────────────────────────────────────────────────────────────────────────── + + +Result #45 LOW Bucket does not have a corresponding public access block.  +──────────────────────────────────────────────────────────────────────────────── + main.tf Lines 72-84 +───────┬──────────────────────────────────────────────────────────────────────── + 72 │ resource "aws_s3_bucket" "backups" { + 73 │  bucket = "${var.deploy_id}-backups" + 74 │  force_destroy = "false" + 75 │  hosted_zone_id = data.aws_route53_zone.this.zone_id + 76 │  object_lock_enabled = "false" + 77 │  tags = var.tags + 78 │  + 79 │  lifecycle { + 80 │  ignore_changes = [ + 81 │  hosted_zone_id, + 82 │  ] + 83 │  } + 84 │ } +───────┴──────────────────────────────────────────────────────────────────────── +  ID aws-s3-specify-public-access-block +  Impact Public access policies may be applied to sensitive data buckets + Resolution Define a aws_s3_bucket_public_access_block for the given bucket to control public access policies + + More Information + - https://aquasecurity.github.io/tfsec/v1.15.4/checks/aws/s3/specify-public-access-block/ + - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block#bucket +──────────────────────────────────────────────────────────────────────────────── + + + timings + ────────────────────────────────────────── + disk i/o  329.114µs + parsing  5.215424ms + adaptation  492.987µs + checks  14.744622ms + total  20.782147ms + + counts + ────────────────────────────────────────── + modules downloaded  0 + modules processed  1 + blocks processed  28 + files read  4 + + results + ────────────────────────────────────────── + passed  6 + ignored  0 + critical  0 + high  30 + medium  10 + low  5 + + 6 passed, 45 potential problem(s) detected. + + timings + ────────────────────────────────────────── + disk i/o  218.636µs + parsing  13.747053ms + adaptation  192.667µs + checks  13.256097ms + total  27.414453ms + + counts + ────────────────────────────────────────── + modules downloaded  0 + modules processed  1 + blocks processed  9 + files read  4 + + results + ────────────────────────────────────────── + passed  0 + ignored  0 + critical  0 + high  0 + medium  0 + low  0 + + +No problems detected! + + diff --git a/variables.tf b/variables.tf new file mode 100755 index 00000000..8b9856c9 --- /dev/null +++ b/variables.tf @@ -0,0 +1,137 @@ +variable "deploy_id" { + type = string + description = "Domino Deployment ID." + default = "domino-eks" + + validation { + condition = can(regex("^[a-z-0-9]{3,32}$", var.deploy_id)) + error_message = "Argument deploy_id must: start with a letter, contain lowercase alphanumeric characters(can contain hyphens[-]) with length between 3 and 32 characters." + } +} + +variable "region" { + type = string + description = "AWS region for the deployment" +} + +variable "number_of_azs" { + type = number + description = "Number of AZ to distribute the deployment, EKS needs at least 2." + default = 3 + validation { + condition = var.number_of_azs >= 2 + error_message = "EKS deployment needs at least 2 zones." + } +} + + +variable "availability_zones" { + type = list(string) + description = "List of Availibility zones to distribute the deployment, EKS needs at least 2,https://docs.aws.amazon.com/eks/latest/userguide/network_reqs.html." + default = [] +} + + +variable "route53_hosted_zone" { + type = string + description = "AWS Route53 Hosted zone." +} + +variable "tags" { + type = map(string) + description = "Deployment tags." + default = {} +} + +variable "k8s_version" { + type = string + description = "EKS cluster k8s version." + default = "1.22" +} + +variable "public_cidr_network_bits" { + type = number + description = "Number of network bits to allocate to the public subnet. i.e /27 -> 30 IPs." + default = 27 +} + +variable "private_cidr_network_bits" { + type = number + description = "Number of network bits to allocate to the public subnet. i.e /19 -> 8,190 IPs." + default = 19 +} + +variable "node_groups" { + type = map(map(any)) + description = "EKS managed node groups definition." + default = { + "compute" = { + instance_type = "m5.2xlarge" + min = 0 + max = 10 + desired = 1 + }, + "platform" = { + instance_type = "m5.4xlarge" + min = 0 + max = 10 + desired = 1 + }, + "gpu" = { + instance_type = "g4dn.xlarge" + min = 0 + max = 10 + desired = 1 + } + } +} + +variable "base_cidr_block" { + type = string + default = "10.0.0.0/16" + description = "CIDR block to serve the main private and public subnets." + validation { + condition = ( + try(cidrhost(var.base_cidr_block, 0), null) == regex("^(.*)/", var.base_cidr_block)[0] && + try(cidrnetmask(var.base_cidr_block), null) == "255.255.0.0" + ) + error_message = "Argument base_cidr_block must be a valid CIDR block." + } +} + +variable "eks_master_role_names" { + type = list(string) + description = "IAM role names to be added as masters in eks." + default = [] +} + +variable "enable_route53_iam_policy" { + type = bool + description = "Enable route53 IAM policy toggle." + default = false +} + +variable "vpc_id" { + type = string + description = "VPC ID for bringing your own vpc, will bypass creation of such." + default = "" +} + +variable "create_bastion" { + type = bool + description = "Create bastion toggle." + default = false +} + +variable "efs_access_point_path" { + type = string + description = "Filesystem path for efs." + default = "/domino" + +} + +variable "ssh_pvt_key_name" { + type = string + description = "ssh private key filename." + default = "domino.pem" +} diff --git a/versions.tf b/versions.tf new file mode 100644 index 00000000..06f4dea6 --- /dev/null +++ b/versions.tf @@ -0,0 +1,22 @@ +terraform { + + required_version = ">= 1.0" + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 4.0" + } + local = { + source = "hashicorp/local" + version = ">= 2.2.0" + } + tls = { + source = "hashicorp/tls" + version = ">= 3.4.0" + } + } +} + +provider "aws" { + region = var.region +} From 4bab588d2e22254b8e34549c3569cb08743ccc64 Mon Sep 17 00:00:00 2001 From: Miguel Harmant Date: Thu, 4 Aug 2022 11:58:47 -0400 Subject: [PATCH 03/17] PLAT-4955 Terraform EKS module, updated gpu labels,taints --- submodules/eks/README.md | 2 +- submodules/eks/node-group.tf | 12 +++++++++--- submodules/eks/variables.tf | 2 +- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/submodules/eks/README.md b/submodules/eks/README.md index bca0db3f..06c6d694 100644 --- a/submodules/eks/README.md +++ b/submodules/eks/README.md @@ -78,7 +78,7 @@ No modules. | [enable\_route53\_iam\_policy](#input\_enable\_route53\_iam\_policy) | Enable route53 iam policy toggle. | `bool` | `false` | no | | [k8s\_version](#input\_k8s\_version) | EKS cluster k8s version. | `string` | `"1.22"` | no | | [kubeconfig\_path](#input\_kubeconfig\_path) | Kubeconfig filename. | `string` | `"kubeconfig"` | no | -| [node\_groups](#input\_node\_groups) | EKS managed node groups definition | `map(map(any))` |
{
"compute": {
"desired": 1,
"instance_type": "m5.2xlarge",
"max": 10,
"min": 0
},
"gpu": {
"desired": 0,
"instance_type": "g4dn.xlarge",
"max": 10,
"min": 0
},
"platform": {
"desired": 1,
"instance_type": "m5.4xlarge",
"max": 10,
"min": 0
}
}
| no | +| [node\_groups](#input\_node\_groups) | EKS managed node groups definition | `map(map(any))` |
{
"compute": {
"desired": 1,
"instance_type": "m5.2xlarge",
"max": 30,
"min": 0
},
"gpu": {
"desired": 0,
"instance_type": "g4dn.xlarge",
"max": 10,
"min": 0
},
"platform": {
"desired": 1,
"instance_type": "m5.4xlarge",
"max": 10,
"min": 0
}
}
| no | | [private\_subnets](#input\_private\_subnets) | Private subnets object |
list(object({
cidr_block = string
name = string
type = string
zone = string
zone_id = string
id = string
}))
| n/a | yes | | [region](#input\_region) | AWS region for the deployment | `string` | n/a | yes | | [route53\_hosted\_zone](#input\_route53\_hosted\_zone) | Route53 zone | `string` | n/a | yes | diff --git a/submodules/eks/node-group.tf b/submodules/eks/node-group.tf index c324bdff..6ca95240 100644 --- a/submodules/eks/node-group.tf +++ b/submodules/eks/node-group.tf @@ -221,7 +221,8 @@ resource "aws_eks_node_group" "platform" { } locals { - gpu_bootstrap_extra_args = "--node-labels lifecycle=OnDemand --node-labels=dominodatalab.com/node-pool=default-gpu,nvidia.com/gpu=true,dominodatalab.com/domino-node=true --register-with-taints=nvidia.com/gpu=true:NoSchedule" + # gpu_bootstrap_extra_args = "--node-labels lifecycle=OnDemand --node-labels=dominodatalab.com/node-pool=default-gpu,nvidia.com/gpu=true,dominodatalab.com/domino-node=true --register-with-taints=nvidia.com/gpu=true:NoSchedule" + gpu_bootstrap_extra_args = "" gpu_user_data = base64encode(templatefile("${path.module}/templates/linux_custom.tpl", { cluster_name = aws_eks_cluster.this.name cluster_endpoint = aws_eks_cluster.this.endpoint @@ -290,11 +291,16 @@ resource "aws_eks_node_group" "gpu" { version = aws_launch_template.gpu.latest_version } - + taint { + key = "nvidia.com/gpu" + value = "true" + effect = "NO_SCHEDULE" + } labels = { "lifecycle" = "OnDemand" - "dominodatalab.com/node-pool" = "gpu" + "dominodatalab.com/node-pool" = "default-gpu" "dominodatalab.com/domino-node" = "true" + "nvidia.com/gpu" = "true" } lifecycle { diff --git a/submodules/eks/variables.tf b/submodules/eks/variables.tf index 2f0ae2a7..d2d36f7a 100755 --- a/submodules/eks/variables.tf +++ b/submodules/eks/variables.tf @@ -31,7 +31,7 @@ variable "node_groups" { "compute" = { instance_type = "m5.2xlarge" min = 0 - max = 10 + max = 30 desired = 1 }, "platform" = { From 6b37f97549e65a974af2c09a4a01f59b272b0fe4 Mon Sep 17 00:00:00 2001 From: Miguel Harmant Date: Fri, 5 Aug 2022 13:51:07 -0400 Subject: [PATCH 04/17] PLAT-4955 Terraform EKS module, instance_type offering validation --- .pre-commit-config.yaml | 10 ++--- README.md | 13 +++++-- main.tf | 76 +++++++++++++++++++++++++++---------- outputs.tf | 5 +++ submodules/eks/variables.tf | 4 ++ variables.tf | 38 ++++++++++++++++--- versions.tf | 5 +++ 7 files changed, 117 insertions(+), 34 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index b9b2e1fe..dbccf714 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -34,8 +34,8 @@ repos: - '--args=--only=terraform_standard_module_structure' - '--args=--only=terraform_workspace_remote' - id: terraform_validate - - id: terrascan - args: - - '--args=--non-recursive' - - '--args=--policy-type=aws' - - '--args=--skip-rules=AC_AWS_0369' #Flow logs are enabled, terrascan does not follow the logical path of the resource + # - id: terrascan # Skipping until they update lifecycle block; Data resources do not have lifecycle settings, so a lifecycle block is not allowed. + # args: + # - '--args=--non-recursive' + # - '--args=--policy-type=aws' + # - '--args=--skip-rules=AC_AWS_0369' #Flow logs are enabled, terrascan does not follow the logical path of the resource diff --git a/README.md b/README.md index bf88f732..1068f78a 100644 --- a/README.md +++ b/README.md @@ -56,6 +56,7 @@ aws s3 rb s3://"${AWS_TERRAFORM_REMOTE_STATE_BUCKET}" --force | [terraform](#requirement\_terraform) | >= 1.0 | | [aws](#requirement\_aws) | >= 4.0 | | [local](#requirement\_local) | >= 2.2.0 | +| [null](#requirement\_null) | >= 3.1.1 | | [tls](#requirement\_tls) | >= 3.4.0 | ## Providers @@ -64,6 +65,7 @@ aws s3 rb s3://"${AWS_TERRAFORM_REMOTE_STATE_BUCKET}" --force |------|---------| | [aws](#provider\_aws) | 4.22.0 | | [local](#provider\_local) | 2.2.3 | +| [null](#provider\_null) | 3.1.1 | | [tls](#provider\_tls) | 3.4.0 | ## Modules @@ -85,12 +87,14 @@ aws s3 rb s3://"${AWS_TERRAFORM_REMOTE_STATE_BUCKET}" --force | [local_sensitive_file.pvt_key](https://registry.terraform.io/providers/hashicorp/local/latest/docs/resources/sensitive_file) | resource | | [tls_private_key.domino](https://registry.terraform.io/providers/hashicorp/tls/latest/docs/resources/private_key) | resource | | [aws_availability_zones.available](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/availability_zones) | data source | +| [aws_ec2_instance_type_offerings.nodes](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ec2_instance_type_offerings) | data source | +| [null_data_source.validate_zones](https://registry.terraform.io/providers/hashicorp/null/latest/docs/data-sources/data_source) | data source | ## Inputs | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| [availability\_zones](#input\_availability\_zones) | List of Availibility zones to distribute the deployment, EKS needs at least 2,https://docs.aws.amazon.com/eks/latest/userguide/network_reqs.html. | `list(string)` | `[]` | no | +| [availability\_zones](#input\_availability\_zones) | List of Availibility zones to distribute the deployment, EKS needs at least 2,https://docs.aws.amazon.com/eks/latest/userguide/network_reqs.html.
Note that setting this variable bypasses validation of the status of the zones data 'aws\_availability\_zones' 'available'.
Caller is responsible for validating status of these zones. | `list(string)` | `[]` | no | | [base\_cidr\_block](#input\_base\_cidr\_block) | CIDR block to serve the main private and public subnets. | `string` | `"10.0.0.0/16"` | no | | [create\_bastion](#input\_create\_bastion) | Create bastion toggle. | `bool` | `false` | no | | [deploy\_id](#input\_deploy\_id) | Domino Deployment ID. | `string` | `"domino-eks"` | no | @@ -98,10 +102,10 @@ aws s3 rb s3://"${AWS_TERRAFORM_REMOTE_STATE_BUCKET}" --force | [eks\_master\_role\_names](#input\_eks\_master\_role\_names) | IAM role names to be added as masters in eks. | `list(string)` | `[]` | no | | [enable\_route53\_iam\_policy](#input\_enable\_route53\_iam\_policy) | Enable route53 IAM policy toggle. | `bool` | `false` | no | | [k8s\_version](#input\_k8s\_version) | EKS cluster k8s version. | `string` | `"1.22"` | no | -| [node\_groups](#input\_node\_groups) | EKS managed node groups definition. | `map(map(any))` |
{
"compute": {
"desired": 1,
"instance_type": "m5.2xlarge",
"max": 10,
"min": 0
},
"gpu": {
"desired": 1,
"instance_type": "g4dn.xlarge",
"max": 10,
"min": 0
},
"platform": {
"desired": 1,
"instance_type": "m5.4xlarge",
"max": 10,
"min": 0
}
}
| no | +| [node\_groups](#input\_node\_groups) | EKS managed node groups definition. |
object({
compute = object({
instance_type = string
min = number
max = number
desired = number
}),
platform = object({
instance_type = string
min = number
max = number
desired = number
}),
gpu = object({
instance_type = string
min = number
max = number
desired = number
})
})
|
{
"compute": {
"desired": 1,
"instance_type": "m5.2xlarge",
"max": 10,
"min": 0
},
"gpu": {
"desired": 1,
"instance_type": "g4dn.xlarge",
"max": 10,
"min": 0
},
"platform": {
"desired": 1,
"instance_type": "m5.4xlarge",
"max": 10,
"min": 0
}
}
| no | | [number\_of\_azs](#input\_number\_of\_azs) | Number of AZ to distribute the deployment, EKS needs at least 2. | `number` | `3` | no | -| [private\_cidr\_network\_bits](#input\_private\_cidr\_network\_bits) | Number of network bits to allocate to the public subnet. i.e /19 -> 8,190 IPs. | `number` | `19` | no | -| [public\_cidr\_network\_bits](#input\_public\_cidr\_network\_bits) | Number of network bits to allocate to the public subnet. i.e /27 -> 30 IPs. | `number` | `27` | no | +| [private\_cidr\_network\_bits](#input\_private\_cidr\_network\_bits) | Number of network bits to allocate to the private subnet. i.e /19 -> 8,192 IPs. | `number` | `19` | no | +| [public\_cidr\_network\_bits](#input\_public\_cidr\_network\_bits) | Number of network bits to allocate to the public subnet. i.e /27 -> 32 IPs. | `number` | `27` | no | | [region](#input\_region) | AWS region for the deployment | `string` | n/a | yes | | [route53\_hosted\_zone](#input\_route53\_hosted\_zone) | AWS Route53 Hosted zone. | `string` | n/a | yes | | [ssh\_pvt\_key\_name](#input\_ssh\_pvt\_key\_name) | ssh private key filename. | `string` | `"domino.pem"` | no | @@ -118,4 +122,5 @@ aws s3 rb s3://"${AWS_TERRAFORM_REMOTE_STATE_BUCKET}" --force | [k8s\_tunnel\_command](#output\_k8s\_tunnel\_command) | Command to run the k8s tunnel mallory. | | [region](#output\_region) | Deployment region. | | [ssh\_bastion\_command](#output\_ssh\_bastion\_command) | Command to ssh into the bastion host | +| [zone\_validation](#output\_zone\_validation) | UNUSED, To silence TFLint unused resource warning | diff --git a/main.tf b/main.tf index bd4c375e..6e366f0c 100644 --- a/main.tf +++ b/main.tf @@ -1,20 +1,27 @@ -resource "tls_private_key" "domino" { - algorithm = "RSA" -} +# Validating zone offerings. +# Check the zones where the instance types are being offered +data "aws_ec2_instance_type_offerings" "nodes" { + for_each = var.node_groups -resource "aws_key_pair" "domino" { - key_name = var.deploy_id - public_key = trimspace(tls_private_key.domino.public_key_openssh) -} + filter { + name = "instance-type" + # values = toset([for i in var.node_groups : i.instance_type]) + values = [each.value.instance_type] + } -resource "local_sensitive_file" "pvt_key" { - content = tls_private_key.domino.private_key_openssh - file_permission = "0400" - filename = local.ssh_pvt_key_path -} + location_type = "availability-zone" + lifecycle { + # Validating the number of zones is greater than 2. EKS needs at least 2. + postcondition { + condition = length(toset(self.locations)) >= 2 + error_message = "Availability of the instance types does not satisfy the number of zones" + } + } +} +# Get "available" azs for the region data "aws_availability_zones" "available" { state = "available" filter { @@ -24,14 +31,43 @@ data "aws_availability_zones" "available" { } locals { - availability_zones_data = zipmap(data.aws_availability_zones.available.names, data.aws_availability_zones.available.zone_ids) - ## EKS needs at least 2 availability zones: https://docs.aws.amazon.com/eks/latest/userguide/network_reqs.html - availability_zone_names = length(var.availability_zones) >= 2 ? toset(var.availability_zones) : toset(slice(keys(local.availability_zones_data), 0, var.number_of_azs)) - availability_zone_ids = [for name in local.availability_zone_names : local.availability_zones_data[name]] - availability_zones = zipmap(local.availability_zone_names, local.availability_zone_ids) - bastion_user = "ec2-user" - ssh_pvt_key_path = "resources/${var.deploy_id}/${var.ssh_pvt_key_name}" - kubeconfig_path = "resources/${var.deploy_id}/kubeconfig" + # Get zones where ALL instance types are offered(intersection). + zone_intersection_instance_offerings = setintersection(toset(data.aws_ec2_instance_type_offerings.nodes["compute"].locations), toset(data.aws_ec2_instance_type_offerings.nodes["platform"].locations), toset(data.aws_ec2_instance_type_offerings.nodes["gpu"].locations)) + # Get the zones that are available and offered in the region for the instance types. + az_names = length(var.availability_zones) > 0 ? var.availability_zones : data.aws_availability_zones.available.names + offered_azs = setintersection(local.zone_intersection_instance_offerings, toset(local.az_names)) + available_azs_data = zipmap(data.aws_availability_zones.available.names, data.aws_availability_zones.available.zone_ids) + # Getting the required azs name and id. + availability_zones = { for name in slice(tolist(local.offered_azs), 0, var.number_of_azs) : name => local.available_azs_data[name] } + bastion_user = "ec2-user" + ssh_pvt_key_path = "resources/${var.deploy_id}/${var.ssh_pvt_key_name}" + kubeconfig_path = "resources/${var.deploy_id}/kubeconfig" +} + +# Validate that the number of offered and available zones satisfy the number of required zones. https://github.com/hashicorp/terraform/issues/31122 may result in a more elegant validation and deprecation of the null_data_source +data "null_data_source" "validate_zones" { + lifecycle { + precondition { + condition = length(local.offered_azs) >= var.number_of_azs + error_message = "Availability of the instance types does not satisfy the number of zones" + } + } +} + +## Creating SSH pvt key to access bastion and EKS nodes +resource "tls_private_key" "domino" { + algorithm = "RSA" +} + +resource "local_sensitive_file" "pvt_key" { + content = tls_private_key.domino.private_key_openssh + file_permission = "0400" + filename = local.ssh_pvt_key_path +} + +resource "aws_key_pair" "domino" { + key_name = var.deploy_id + public_key = trimspace(tls_private_key.domino.public_key_openssh) } module "subnets_cidr" { diff --git a/outputs.tf b/outputs.tf index bcd2474b..47d87776 100755 --- a/outputs.tf +++ b/outputs.tf @@ -27,3 +27,8 @@ output "deploy_id" { description = "Deployment ID." value = var.deploy_id } + +output "zone_validation" { + description = "UNUSED, To silence TFLint unused resource warning" + value = data.null_data_source.validate_zones.id +} diff --git a/submodules/eks/variables.tf b/submodules/eks/variables.tf index d2d36f7a..a4d05ad0 100755 --- a/submodules/eks/variables.tf +++ b/submodules/eks/variables.tf @@ -65,6 +65,10 @@ variable "private_subnets" { zone_id = string id = string })) + validation { + condition = length(var.private_subnets) >= 2 + error_message = "EKS deployment needs at least 2 subnets. https://docs.aws.amazon.com/eks/latest/userguide/network_reqs.html." + } } variable "vpc_id" { diff --git a/variables.tf b/variables.tf index 8b9856c9..8a7592a7 100755 --- a/variables.tf +++ b/variables.tf @@ -27,8 +27,17 @@ variable "number_of_azs" { variable "availability_zones" { type = list(string) - description = "List of Availibility zones to distribute the deployment, EKS needs at least 2,https://docs.aws.amazon.com/eks/latest/userguide/network_reqs.html." - default = [] + description = <= 2 + error_message = "EKS deployment needs at least 2 zones." + } + default = [] } @@ -51,18 +60,37 @@ variable "k8s_version" { variable "public_cidr_network_bits" { type = number - description = "Number of network bits to allocate to the public subnet. i.e /27 -> 30 IPs." + description = "Number of network bits to allocate to the public subnet. i.e /27 -> 32 IPs." default = 27 } variable "private_cidr_network_bits" { type = number - description = "Number of network bits to allocate to the public subnet. i.e /19 -> 8,190 IPs." + description = "Number of network bits to allocate to the private subnet. i.e /19 -> 8,192 IPs." default = 19 } variable "node_groups" { - type = map(map(any)) + type = object({ + compute = object({ + instance_type = string + min = number + max = number + desired = number + }), + platform = object({ + instance_type = string + min = number + max = number + desired = number + }), + gpu = object({ + instance_type = string + min = number + max = number + desired = number + }) + }) description = "EKS managed node groups definition." default = { "compute" = { diff --git a/versions.tf b/versions.tf index 06f4dea6..af9a086c 100644 --- a/versions.tf +++ b/versions.tf @@ -14,6 +14,11 @@ terraform { source = "hashicorp/tls" version = ">= 3.4.0" } + + null = { + source = "hashicorp/null" + version = ">= 3.1.1" + } } } From 89997b58236ff988dddebf655aa66e077266d19e Mon Sep 17 00:00:00 2001 From: Miguel Harmant Date: Mon, 15 Aug 2022 11:47:17 -0400 Subject: [PATCH 05/17] PLAT-4955 Terraform EKS module, PR comments, 1 --- README.md | 8 +-- example/main.tf | 16 +++--- main.tf | 11 ++-- outputs.tf | 2 +- submodules/eks/README.md | 7 ++- submodules/eks/iam.tf | 4 +- submodules/eks/node-group.tf | 93 ++++++++++++++++----------------- submodules/eks/variables.tf | 66 +++++++++++++---------- submodules/eks/versions.tf | 4 +- submodules/storage/README.md | 3 +- submodules/storage/efs.tf | 2 +- submodules/storage/main.tf | 4 -- submodules/storage/s3.tf | 45 ++-------------- submodules/storage/variables.tf | 13 ++--- variables.tf | 89 ++++++++++++++++++++----------- versions.tf | 4 +- 16 files changed, 180 insertions(+), 191 deletions(-) diff --git a/README.md b/README.md index 1068f78a..61cc52a3 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,7 @@ aws s3 rb s3://"${AWS_TERRAFORM_REMOTE_STATE_BUCKET}" --force | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 1.0 | +| [terraform](#requirement\_terraform) | >= 1.2.0 | | [aws](#requirement\_aws) | >= 4.0 | | [local](#requirement\_local) | >= 2.2.0 | | [null](#requirement\_null) | >= 3.1.1 | @@ -100,14 +100,14 @@ aws s3 rb s3://"${AWS_TERRAFORM_REMOTE_STATE_BUCKET}" --force | [deploy\_id](#input\_deploy\_id) | Domino Deployment ID. | `string` | `"domino-eks"` | no | | [efs\_access\_point\_path](#input\_efs\_access\_point\_path) | Filesystem path for efs. | `string` | `"/domino"` | no | | [eks\_master\_role\_names](#input\_eks\_master\_role\_names) | IAM role names to be added as masters in eks. | `list(string)` | `[]` | no | -| [enable\_route53\_iam\_policy](#input\_enable\_route53\_iam\_policy) | Enable route53 IAM policy toggle. | `bool` | `false` | no | | [k8s\_version](#input\_k8s\_version) | EKS cluster k8s version. | `string` | `"1.22"` | no | -| [node\_groups](#input\_node\_groups) | EKS managed node groups definition. |
object({
compute = object({
instance_type = string
min = number
max = number
desired = number
}),
platform = object({
instance_type = string
min = number
max = number
desired = number
}),
gpu = object({
instance_type = string
min = number
max = number
desired = number
})
})
|
{
"compute": {
"desired": 1,
"instance_type": "m5.2xlarge",
"max": 10,
"min": 0
},
"gpu": {
"desired": 1,
"instance_type": "g4dn.xlarge",
"max": 10,
"min": 0
},
"platform": {
"desired": 1,
"instance_type": "m5.4xlarge",
"max": 10,
"min": 0
}
}
| no | +| [node\_groups](#input\_node\_groups) | EKS managed node groups definition. |
object({
compute = object({
ami = optional(string)
instance_type = string
min_per_az = number
max_per_az = number
desired_per_az = number
volume = object({
size = string
type = string
})
}),
platform = object({
ami = optional(string)
instance_type = string
min_per_az = number
max_per_az = number
desired_per_az = number
volume = object({
size = string
type = string
})
}),
gpu = object({
ami = optional(string)
instance_type = string
min_per_az = number
max_per_az = number
desired_per_az = number
volume = object({
size = string
type = string
})
})
})
|
{
"compute": {
"desired_per_az": 1,
"instance_type": "m5.2xlarge",
"max_per_az": 10,
"min_per_az": 0,
"volume": {
"size": "100",
"type": "gp3"
}
},
"gpu": {
"desired_per_az": 0,
"instance_type": "g4dn.xlarge",
"max_per_az": 10,
"min_per_az": 0,
"volume": {
"size": "100",
"type": "gp3"
}
},
"platform": {
"desired_per_az": 1,
"instance_type": "m5.4xlarge",
"max_per_az": 10,
"min_per_az": 0,
"volume": {
"size": "100",
"type": "gp3"
}
}
}
| no | | [number\_of\_azs](#input\_number\_of\_azs) | Number of AZ to distribute the deployment, EKS needs at least 2. | `number` | `3` | no | | [private\_cidr\_network\_bits](#input\_private\_cidr\_network\_bits) | Number of network bits to allocate to the private subnet. i.e /19 -> 8,192 IPs. | `number` | `19` | no | | [public\_cidr\_network\_bits](#input\_public\_cidr\_network\_bits) | Number of network bits to allocate to the public subnet. i.e /27 -> 32 IPs. | `number` | `27` | no | | [region](#input\_region) | AWS region for the deployment | `string` | n/a | yes | -| [route53\_hosted\_zone](#input\_route53\_hosted\_zone) | AWS Route53 Hosted zone. | `string` | n/a | yes | +| [route53\_hosted\_zone\_name](#input\_route53\_hosted\_zone\_name) | AWS Route53 Hosted zone. | `string` | n/a | yes | +| [s3\_force\_destroy\_toggle](#input\_s3\_force\_destroy\_toggle) | Toogle to allow recursive deletion of all objects in the s3 buckets. if 'false' terraform will NOT be able to delete non-empty buckets | `string` | `"false"` | no | | [ssh\_pvt\_key\_name](#input\_ssh\_pvt\_key\_name) | ssh private key filename. | `string` | `"domino.pem"` | no | | [tags](#input\_tags) | Deployment tags. | `map(string)` | `{}` | no | | [vpc\_id](#input\_vpc\_id) | VPC ID for bringing your own vpc, will bypass creation of such. | `string` | `""` | no | diff --git a/example/main.tf b/example/main.tf index acb46795..adf09fad 100755 --- a/example/main.tf +++ b/example/main.tf @@ -1,12 +1,12 @@ module "domino_eks" { - source = "../../terraform-aws-eks" - deploy_id = "mhtfeks" - region = "us-west-2" - number_of_azs = 2 - route53_hosted_zone = "infra-team-sandbox.domino.tech" - eks_master_role_names = ["okta-poweruser", "okta-fulladmin"] - create_bastion = true - enable_route53_iam_policy = true + source = "../../terraform-aws-eks" + deploy_id = "mhtfeks" + region = "us-west-2" + number_of_azs = 2 + route53_hosted_zone_name = "infra-team-sandbox.domino.tech" + eks_master_role_names = ["okta-poweruser", "okta-fulladmin"] + s3_force_destroy_toggle = "true" + create_bastion = true tags = { deploy_id = "domino-eks" deploy_tag = "domino-eks" diff --git a/main.tf b/main.tf index 6e366f0c..3f8d2640 100644 --- a/main.tf +++ b/main.tf @@ -98,10 +98,10 @@ locals { module "storage" { - source = "./submodules/storage" - deploy_id = var.deploy_id - efs_access_point_path = var.efs_access_point_path - route53_hosted_zone = var.route53_hosted_zone + source = "./submodules/storage" + deploy_id = var.deploy_id + efs_access_point_path = var.efs_access_point_path + s3_force_destroy_toggle = var.s3_force_destroy_toggle subnets = [for s in local.private_subnets : { name = s.name id = s.id @@ -131,10 +131,9 @@ module "eks" { deploy_id = var.deploy_id private_subnets = local.private_subnets ssh_pvt_key_name = aws_key_pair.domino.key_name - route53_hosted_zone = var.route53_hosted_zone + route53_hosted_zone_name = var.route53_hosted_zone_name bastion_security_group_id = try(module.bastion[0].security_group_id, "") create_bastion_sg = var.create_bastion - enable_route53_iam_policy = var.enable_route53_iam_policy kubeconfig_path = local.kubeconfig_path node_groups = var.node_groups s3_buckets = module.storage.s3_buckets diff --git a/outputs.tf b/outputs.tf index 47d87776..8dd267b1 100755 --- a/outputs.tf +++ b/outputs.tf @@ -10,7 +10,7 @@ output "k8s_tunnel_command" { output "hostname" { description = "Domino instance URL." - value = "${var.deploy_id}.${var.route53_hosted_zone}" + value = "${var.deploy_id}.${var.route53_hosted_zone_name}" } output "efs_filesystem_id" { diff --git a/submodules/eks/README.md b/submodules/eks/README.md index 06c6d694..340869ec 100644 --- a/submodules/eks/README.md +++ b/submodules/eks/README.md @@ -5,7 +5,7 @@ | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 1.0 | +| [terraform](#requirement\_terraform) | >= 1.2.0 | | [aws](#requirement\_aws) | >= 4.0 | | [null](#requirement\_null) | >= 3.1.0 | @@ -75,13 +75,12 @@ No modules. | [deploy\_id](#input\_deploy\_id) | Domino Deployment ID | `string` | n/a | yes | | [eks\_cluster\_addons](#input\_eks\_cluster\_addons) | EKS cluster addons. | `list(string)` |
[
"vpc-cni",
"kube-proxy",
"coredns"
]
| no | | [eks\_security\_group\_rules](#input\_eks\_security\_group\_rules) | EKS security group rules. | `map(any)` | `{}` | no | -| [enable\_route53\_iam\_policy](#input\_enable\_route53\_iam\_policy) | Enable route53 iam policy toggle. | `bool` | `false` | no | | [k8s\_version](#input\_k8s\_version) | EKS cluster k8s version. | `string` | `"1.22"` | no | | [kubeconfig\_path](#input\_kubeconfig\_path) | Kubeconfig filename. | `string` | `"kubeconfig"` | no | -| [node\_groups](#input\_node\_groups) | EKS managed node groups definition | `map(map(any))` |
{
"compute": {
"desired": 1,
"instance_type": "m5.2xlarge",
"max": 30,
"min": 0
},
"gpu": {
"desired": 0,
"instance_type": "g4dn.xlarge",
"max": 10,
"min": 0
},
"platform": {
"desired": 1,
"instance_type": "m5.4xlarge",
"max": 10,
"min": 0
}
}
| no | +| [node\_groups](#input\_node\_groups) | EKS managed node groups definition. |
object({
compute = object({
ami = optional(string)
instance_type = string
min_per_az = number
max_per_az = number
desired_per_az = number
volume = object({
size = string
type = string
})
}),
platform = object({
ami = optional(string)
instance_type = string
min_per_az = number
max_per_az = number
desired_per_az = number
volume = object({
size = string
type = string
})
}),
gpu = object({
ami = optional(string)
instance_type = string
min_per_az = number
max_per_az = number
desired_per_az = number
volume = object({
size = string
type = string
})
})
})
| n/a | yes | | [private\_subnets](#input\_private\_subnets) | Private subnets object |
list(object({
cidr_block = string
name = string
type = string
zone = string
zone_id = string
id = string
}))
| n/a | yes | | [region](#input\_region) | AWS region for the deployment | `string` | n/a | yes | -| [route53\_hosted\_zone](#input\_route53\_hosted\_zone) | Route53 zone | `string` | n/a | yes | +| [route53\_hosted\_zone\_name](#input\_route53\_hosted\_zone\_name) | Route53 zone | `string` | n/a | yes | | [s3\_buckets](#input\_s3\_buckets) | S3 buckets information that the nodegroups need access to |
list(object({
bucket_name = string
arn = string
}))
| n/a | yes | | [ssh\_pvt\_key\_name](#input\_ssh\_pvt\_key\_name) | ssh private key filename. | `string` | n/a | yes | | [tags](#input\_tags) | Deployment tags | `map(string)` | n/a | yes | diff --git a/submodules/eks/iam.tf b/submodules/eks/iam.tf index 41571b20..94a514a8 100644 --- a/submodules/eks/iam.tf +++ b/submodules/eks/iam.tf @@ -252,7 +252,7 @@ data "aws_iam_policy_document" "route53" { } resource "aws_iam_policy" "route53" { - count = var.enable_route53_iam_policy ? 1 : 0 + count = var.route53_hosted_zone_name != "" ? 1 : 0 name = "${var.deploy_id}-Route53" path = "/" policy = data.aws_iam_policy_document.route53.json @@ -314,7 +314,7 @@ resource "aws_iam_role_policy_attachment" "custom_eks_nodes" { } resource "aws_iam_role_policy_attachment" "custom_eks_nodes_route53" { - count = var.enable_route53_iam_policy ? 1 : 0 + count = var.route53_hosted_zone_name != "" ? 1 : 0 policy_arn = local.eks_custom_node_iam_policies["route53"] role = aws_iam_role.eks_nodes.name } diff --git a/submodules/eks/node-group.tf b/submodules/eks/node-group.tf index 6ca95240..3e3471ca 100644 --- a/submodules/eks/node-group.tf +++ b/submodules/eks/node-group.tf @@ -12,7 +12,7 @@ data "aws_iam_policy_document" "eks_nodes" { } data "aws_route53_zone" "this" { - name = var.route53_hosted_zone + name = var.route53_hosted_zone_name private_zone = false } @@ -22,11 +22,24 @@ resource "aws_iam_role" "eks_nodes" { tags = var.tags } -## EKS Nodes security-group locals { - aws_route53_zone_arn = data.aws_route53_zone.this.arn + # gpu_bootstrap_extra_args = "--node-labels lifecycle=OnDemand --node-labels=dominodatalab.com/node-pool=default-gpu,nvidia.com/gpu=true,dominodatalab.com/domino-node=true --register-with-taints=nvidia.com/gpu=true:NoSchedule" + + aws_route53_zone_arn = data.aws_route53_zone.this.arn + gpu_bootstrap_extra_args = "" + gpu_user_data = base64encode(templatefile("${path.module}/templates/linux_custom.tpl", { + cluster_name = aws_eks_cluster.this.name + cluster_endpoint = aws_eks_cluster.this.endpoint + cluster_auth_base64 = aws_eks_cluster.this.certificate_authority[0].data + bootstrap_extra_args = local.gpu_bootstrap_extra_args + pre_bootstrap_user_data = "" + post_bootstrap_user_data = "echo ALL DONE !!!" + })) + node_group_gpu_ami_id = var.node_groups.gpu.ami != null ? var.node_groups.gpu.ami : data.aws_ami.eks_gpu.image_id + # node_group_compute_ami_id = var.node_groups.compute.ami != null ? var.node_groups.compute.ami : data.aws_ami.eks_gpu.image_id } + resource "aws_security_group" "eks_nodes" { name = "${var.deploy_id}-nodes" description = "EKS cluster Nodes security group" @@ -56,9 +69,6 @@ resource "aws_security_group_rule" "node" { ) } -## END - EKS Nodes security-group - - data "aws_ami" "eks_gpu" { filter { name = "name" @@ -69,7 +79,12 @@ data "aws_ami" "eks_gpu" { } resource "aws_launch_template" "compute" { - name = "${var.deploy_id}-compute" + name = "${var.deploy_id}-compute" + disable_api_termination = "false" + instance_type = var.node_groups.compute.instance_type + key_name = var.ssh_pvt_key_name + vpc_security_group_ids = [aws_security_group.eks_nodes.id] + image_id = var.node_groups.compute.ami block_device_mappings { device_name = "/dev/xvda" @@ -77,16 +92,11 @@ resource "aws_launch_template" "compute" { ebs { delete_on_termination = "true" encrypted = "true" - volume_size = "100" - volume_type = "gp3" + volume_size = var.node_groups.compute.volume.size + volume_type = var.node_groups.compute.volume.type } } - disable_api_termination = "false" - instance_type = var.node_groups.compute.instance_type - key_name = var.ssh_pvt_key_name - vpc_security_group_ids = [aws_security_group.eks_nodes.id] - metadata_options { http_endpoint = "enabled" http_put_response_hop_limit = "2" @@ -114,9 +124,9 @@ resource "aws_eks_node_group" "compute" { subnet_ids = [each.value.id] tags = var.tags scaling_config { - min_size = var.node_groups.compute.min - max_size = var.node_groups.compute.max - desired_size = var.node_groups.compute.desired + min_size = var.node_groups.compute.min_per_az + max_size = var.node_groups.compute.max_per_az + desired_size = var.node_groups.compute.desired_per_az } launch_template { @@ -145,7 +155,12 @@ resource "aws_eks_node_group" "compute" { } resource "aws_launch_template" "platform" { - name = "${var.deploy_id}-platform" + name = "${var.deploy_id}-platform" + disable_api_termination = "false" + instance_type = var.node_groups.platform.instance_type + key_name = var.ssh_pvt_key_name + vpc_security_group_ids = [aws_security_group.eks_nodes.id] + image_id = var.node_groups.platform.ami block_device_mappings { device_name = "/dev/xvda" @@ -153,16 +168,11 @@ resource "aws_launch_template" "platform" { ebs { delete_on_termination = "true" encrypted = "true" - volume_size = "100" - volume_type = "gp3" + volume_size = var.node_groups.platform.volume.size + volume_type = var.node_groups.platform.volume.type } } - disable_api_termination = "false" - instance_type = var.node_groups.platform.instance_type - key_name = var.ssh_pvt_key_name - vpc_security_group_ids = [aws_security_group.eks_nodes.id] - metadata_options { http_endpoint = "enabled" http_put_response_hop_limit = "2" @@ -190,9 +200,9 @@ resource "aws_eks_node_group" "platform" { subnet_ids = [each.value.id] tags = var.tags scaling_config { - min_size = var.node_groups.platform.min - max_size = var.node_groups.platform.max - desired_size = var.node_groups.platform.desired + min_size = var.node_groups.platform.min_per_az + max_size = var.node_groups.platform.max_per_az + desired_size = var.node_groups.platform.desired_per_az } launch_template { @@ -220,23 +230,9 @@ resource "aws_eks_node_group" "platform" { ] } -locals { - # gpu_bootstrap_extra_args = "--node-labels lifecycle=OnDemand --node-labels=dominodatalab.com/node-pool=default-gpu,nvidia.com/gpu=true,dominodatalab.com/domino-node=true --register-with-taints=nvidia.com/gpu=true:NoSchedule" - gpu_bootstrap_extra_args = "" - gpu_user_data = base64encode(templatefile("${path.module}/templates/linux_custom.tpl", { - cluster_name = aws_eks_cluster.this.name - cluster_endpoint = aws_eks_cluster.this.endpoint - cluster_auth_base64 = aws_eks_cluster.this.certificate_authority[0].data - bootstrap_extra_args = local.gpu_bootstrap_extra_args - pre_bootstrap_user_data = "" - post_bootstrap_user_data = "echo ALL DONE !!!" - })) -} - - resource "aws_launch_template" "gpu" { name = "${var.deploy_id}-gpu" - image_id = data.aws_ami.eks_gpu.image_id + image_id = local.node_group_gpu_ami_id disable_api_termination = "false" instance_type = var.node_groups.gpu.instance_type key_name = var.ssh_pvt_key_name @@ -248,12 +244,11 @@ resource "aws_launch_template" "gpu" { ebs { delete_on_termination = "true" encrypted = "true" - volume_size = "100" - volume_type = "gp3" + volume_size = var.node_groups.gpu.volume.size + volume_type = var.node_groups.gpu.volume.type } } - metadata_options { http_endpoint = "enabled" http_put_response_hop_limit = "2" @@ -281,9 +276,9 @@ resource "aws_eks_node_group" "gpu" { subnet_ids = [each.value.id] tags = var.tags scaling_config { - min_size = var.node_groups.gpu.min - max_size = var.node_groups.gpu.max - desired_size = var.node_groups.gpu.desired + min_size = var.node_groups.gpu.min_per_az + max_size = var.node_groups.gpu.max_per_az + desired_size = var.node_groups.gpu.desired_per_az } launch_template { diff --git a/submodules/eks/variables.tf b/submodules/eks/variables.tf index a4d05ad0..eebbe16c 100755 --- a/submodules/eks/variables.tf +++ b/submodules/eks/variables.tf @@ -25,28 +25,42 @@ variable "k8s_version" { } variable "node_groups" { - type = map(map(any)) - description = "EKS managed node groups definition" - default = { - "compute" = { - instance_type = "m5.2xlarge" - min = 0 - max = 30 - desired = 1 - }, - "platform" = { - instance_type = "m5.4xlarge" - min = 0 - max = 10 - desired = 1 - }, - "gpu" = { - instance_type = "g4dn.xlarge" - min = 0 - max = 10 - desired = 0 - } - } + description = "EKS managed node groups definition." + type = object({ + compute = object({ + ami = optional(string) + instance_type = string + min_per_az = number + max_per_az = number + desired_per_az = number + volume = object({ + size = string + type = string + }) + }), + platform = object({ + ami = optional(string) + instance_type = string + min_per_az = number + max_per_az = number + desired_per_az = number + volume = object({ + size = string + type = string + }) + }), + gpu = object({ + ami = optional(string) + instance_type = string + min_per_az = number + max_per_az = number + desired_per_az = number + volume = object({ + size = string + type = string + }) + }) + }) } variable "kubeconfig_path" { @@ -81,7 +95,7 @@ variable "ssh_pvt_key_name" { description = "ssh private key filename." } -variable "route53_hosted_zone" { +variable "route53_hosted_zone_name" { type = string description = "Route53 zone" } @@ -92,12 +106,6 @@ variable "bastion_security_group_id" { default = "" } -variable "enable_route53_iam_policy" { - type = bool - description = "Enable route53 iam policy toggle." - default = false -} - variable "eks_cluster_addons" { type = list(string) description = "EKS cluster addons." diff --git a/submodules/eks/versions.tf b/submodules/eks/versions.tf index b18ed224..6b999fcc 100644 --- a/submodules/eks/versions.tf +++ b/submodules/eks/versions.tf @@ -1,6 +1,6 @@ terraform { - - required_version = ">= 1.0" + experiments = [module_variable_optional_attrs] + required_version = ">= 1.2.0" required_providers { aws = { source = "hashicorp/aws" diff --git a/submodules/storage/README.md b/submodules/storage/README.md index 8da307fb..be142cef 100644 --- a/submodules/storage/README.md +++ b/submodules/storage/README.md @@ -46,7 +46,6 @@ No modules. | [aws_iam_policy_document.logs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_iam_policy_document.monitoring](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_iam_policy_document.registry](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | -| [aws_route53_zone.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/route53_zone) | data source | ## Inputs @@ -54,7 +53,7 @@ No modules. |------|-------------|------|---------|:--------:| | [deploy\_id](#input\_deploy\_id) | Domino Deployment ID | `string` | n/a | yes | | [efs\_access\_point\_path](#input\_efs\_access\_point\_path) | Filesystem path for efs. | `string` | `"/domino"` | no | -| [route53\_hosted\_zone](#input\_route53\_hosted\_zone) | AWS Route53 Hosted zone. | `string` | n/a | yes | +| [s3\_force\_destroy\_toggle](#input\_s3\_force\_destroy\_toggle) | Toogle to allow recursive deletion of all objects in the s3 buckets. if 'false' terraform will NOT be able to delete non-empty buckets | `string` | `"false"` | no | | [subnets](#input\_subnets) | List of subnet ids to create EFS mount targets |
list(object({
name = string
id = string
cidr_block = string
}))
| n/a | yes | | [tags](#input\_tags) | Deployment tags. | `map(string)` | n/a | yes | | [vpc\_id](#input\_vpc\_id) | VPC ID | `string` | n/a | yes | diff --git a/submodules/storage/efs.tf b/submodules/storage/efs.tf index b234f188..28c99468 100644 --- a/submodules/storage/efs.tf +++ b/submodules/storage/efs.tf @@ -4,7 +4,7 @@ resource "aws_efs_file_system" "eks" { provisioned_throughput_in_mibps = "0" throughput_mode = "bursting" - tags = merge({ "Name" = "${var.deploy_id}" }, var.tags) + tags = merge({ "Name" = var.deploy_id }, var.tags) } resource "aws_security_group" "efs" { diff --git a/submodules/storage/main.tf b/submodules/storage/main.tf index fd2935ac..b511e857 100644 --- a/submodules/storage/main.tf +++ b/submodules/storage/main.tf @@ -1,7 +1,3 @@ -data "aws_route53_zone" "this" { - name = var.route53_hosted_zone - private_zone = false -} data "aws_canonical_user_id" "current" {} data "aws_elb_service_account" "this" {} diff --git a/submodules/storage/s3.tf b/submodules/storage/s3.tf index afa8bebd..24584688 100644 --- a/submodules/storage/s3.tf +++ b/submodules/storage/s3.tf @@ -1,16 +1,9 @@ resource "aws_s3_bucket" "backups" { bucket = "${var.deploy_id}-backups" - force_destroy = "true" - hosted_zone_id = data.aws_route53_zone.this.zone_id + force_destroy = var.s3_force_destroy_toggle object_lock_enabled = "false" tags = var.tags - - lifecycle { - ignore_changes = [ - hosted_zone_id, - ] - } } data "aws_iam_policy_document" "backups" { @@ -75,16 +68,9 @@ data "aws_iam_policy_document" "backups" { resource "aws_s3_bucket" "blobs" { bucket = "${var.deploy_id}-blobs" - force_destroy = "true" - hosted_zone_id = data.aws_route53_zone.this.zone_id + force_destroy = var.s3_force_destroy_toggle object_lock_enabled = "false" tags = var.tags - - lifecycle { - ignore_changes = [ - hosted_zone_id, - ] - } } data "aws_iam_policy_document" "blobs" { @@ -151,16 +137,9 @@ data "aws_iam_policy_document" "blobs" { resource "aws_s3_bucket" "logs" { bucket = "${var.deploy_id}-logs" - force_destroy = "true" - hosted_zone_id = data.aws_route53_zone.this.zone_id + force_destroy = var.s3_force_destroy_toggle object_lock_enabled = "false" tags = var.tags - - lifecycle { - ignore_changes = [ - hosted_zone_id, - ] - } } data "aws_iam_policy_document" "logs" { @@ -226,16 +205,9 @@ data "aws_iam_policy_document" "logs" { resource "aws_s3_bucket" "monitoring" { bucket = "${var.deploy_id}-monitoring" - force_destroy = "true" - hosted_zone_id = data.aws_route53_zone.this.zone_id + force_destroy = var.s3_force_destroy_toggle object_lock_enabled = "false" tags = var.tags - - lifecycle { - ignore_changes = [ - hosted_zone_id, - ] - } } data "aws_iam_policy_document" "monitoring" { @@ -350,16 +322,9 @@ resource "aws_s3_bucket_acl" "monitoring" { resource "aws_s3_bucket" "registry" { bucket = "${var.deploy_id}-registry" - force_destroy = "true" - hosted_zone_id = data.aws_route53_zone.this.zone_id + force_destroy = var.s3_force_destroy_toggle object_lock_enabled = "false" tags = var.tags - - lifecycle { - ignore_changes = [ - hosted_zone_id, - ] - } } data "aws_iam_policy_document" "registry" { diff --git a/submodules/storage/variables.tf b/submodules/storage/variables.tf index 113067b8..e349d210 100755 --- a/submodules/storage/variables.tf +++ b/submodules/storage/variables.tf @@ -16,11 +16,6 @@ variable "efs_access_point_path" { } -variable "route53_hosted_zone" { - type = string - description = "AWS Route53 Hosted zone." -} - variable "tags" { type = map(string) description = "Deployment tags." @@ -36,7 +31,13 @@ variable "subnets" { } variable "vpc_id" { - type = string description = "VPC ID" + type = string + +} +variable "s3_force_destroy_toggle" { + description = "Toogle to allow recursive deletion of all objects in the s3 buckets. if 'false' terraform will NOT be able to delete non-empty buckets" + type = string + default = "false" } diff --git a/variables.tf b/variables.tf index 8a7592a7..de4d1f9d 100755 --- a/variables.tf +++ b/variables.tf @@ -41,7 +41,7 @@ variable "availability_zones" { } -variable "route53_hosted_zone" { +variable "route53_hosted_zone_name" { type = string description = "AWS Route53 Hosted zone." } @@ -73,43 +73,70 @@ variable "private_cidr_network_bits" { variable "node_groups" { type = object({ compute = object({ - instance_type = string - min = number - max = number - desired = number + ami = optional(string) + instance_type = string + min_per_az = number + max_per_az = number + desired_per_az = number + volume = object({ + size = string + type = string + }) }), platform = object({ - instance_type = string - min = number - max = number - desired = number + ami = optional(string) + instance_type = string + min_per_az = number + max_per_az = number + desired_per_az = number + volume = object({ + size = string + type = string + }) }), gpu = object({ - instance_type = string - min = number - max = number - desired = number + ami = optional(string) + instance_type = string + min_per_az = number + max_per_az = number + desired_per_az = number + volume = object({ + size = string + type = string + }) }) }) description = "EKS managed node groups definition." default = { "compute" = { - instance_type = "m5.2xlarge" - min = 0 - max = 10 - desired = 1 + instance_type = "m5.2xlarge" + min_per_az = 0 + max_per_az = 10 + desired_per_az = 1 + volume = { + size = "100" + type = "gp3" + } }, "platform" = { - instance_type = "m5.4xlarge" - min = 0 - max = 10 - desired = 1 + instance_type = "m5.4xlarge" + min_per_az = 0 + max_per_az = 10 + desired_per_az = 1 + volume = { + size = "100" + type = "gp3" + } }, "gpu" = { - instance_type = "g4dn.xlarge" - min = 0 - max = 10 - desired = 1 + instance_type = "g4dn.xlarge" + min_per_az = 0 + max_per_az = 10 + desired_per_az = 0 + volume = { + size = "100" + type = "gp3" + } } } } @@ -133,12 +160,6 @@ variable "eks_master_role_names" { default = [] } -variable "enable_route53_iam_policy" { - type = bool - description = "Enable route53 IAM policy toggle." - default = false -} - variable "vpc_id" { type = string description = "VPC ID for bringing your own vpc, will bypass creation of such." @@ -163,3 +184,9 @@ variable "ssh_pvt_key_name" { description = "ssh private key filename." default = "domino.pem" } + +variable "s3_force_destroy_toggle" { + description = "Toogle to allow recursive deletion of all objects in the s3 buckets. if 'false' terraform will NOT be able to delete non-empty buckets" + type = string + default = "false" +} diff --git a/versions.tf b/versions.tf index af9a086c..8532a443 100644 --- a/versions.tf +++ b/versions.tf @@ -1,6 +1,6 @@ terraform { - - required_version = ">= 1.0" + experiments = [module_variable_optional_attrs] + required_version = ">= 1.2.0" required_providers { aws = { source = "hashicorp/aws" From d6c23d7edc4f0d4fdfc88aedcd8f873a7c29914a Mon Sep 17 00:00:00 2001 From: Miguel Harmant Date: Wed, 17 Aug 2022 16:32:30 -0400 Subject: [PATCH 06/17] PLAT-4955 Terraform EKS module, support additional node groups, bring your own ssh key, store resources in parent directory --- README.md | 39 +++-- example/main.tf | 17 +- main.tf | 57 +++---- outputs.tf | 5 - submodules/bastion/README.md | 6 +- submodules/bastion/main.tf | 43 +++-- submodules/bastion/variables.tf | 35 ++-- submodules/eks/README.md | 12 +- submodules/eks/cluster.tf | 45 ++++-- submodules/eks/iam.tf | 1 - submodules/eks/node-group.tf | 212 ++++++++++++++++++------- submodules/eks/variables.tf | 49 ++++-- submodules/k8s/README.md | 2 +- submodules/k8s/main.tf | 4 +- submodules/k8s/variables.tf | 5 +- submodules/network/README.md | 1 - submodules/network/internet-gateway.tf | 10 +- submodules/network/nat-gateway.tf | 7 +- submodules/network/route-tables.tf | 27 ++-- submodules/network/subnets.tf | 26 ++- submodules/network/variables.tf | 5 - submodules/network/vpc.tf | 12 +- submodules/storage/README.md | 4 +- submodules/storage/efs.tf | 11 +- submodules/storage/s3.tf | 45 +++--- submodules/storage/variables.tf | 17 +- variables.tf | 47 +++++- versions.tf | 3 + 28 files changed, 470 insertions(+), 277 deletions(-) diff --git a/README.md b/README.md index 61cc52a3..66c41cfd 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,15 @@ # terraform-aws-eks -## Create terraform remote state bucket +## Create SSH Key pair +### Prerequisites +* Host with `ssh-keygen` installed + +### Command +```bash + ssh-keygen -q -P '' -t rsa -b 4096 -m PEM -f domino.pem +``` + +## Create terraform remote state bucket(OPTIONAL) * Authenticate with aws, make sure that environment variables: `AWS_REGION`, `AWS_ACCESS_KEY_ID` ,`AWS_SECRET_ACCESS_KEY` are set. If your account has MFA set up you will also need `AWS_SESSION_TOKEN`. ### Prerequisites @@ -26,15 +35,20 @@ aws s3api head-bucket --bucket "${AWS_TERRAFORM_REMOTE_STATE_BUCKET}" You should NOT see an error. ## 2. Initialize the terraform remote-state +Create a file called terraform.tf(the name does not matter) with the following content +```hcl +terraform { + backend "s3" {} +} +``` ```bash ### Set the deploy id. This will be used later as well. -export TF_VAR_deploy_id="mh-tf-test" ## <-- Feel free to rename. -terraform init \ +export TF_VAR_deploy_id="domino-eks-1" ## <-- Feel free to rename. +terraform init -migrate-state \ -backend-config="bucket=${AWS_TERRAFORM_REMOTE_STATE_BUCKET}" \ -backend-config="key=domino-eks/${TF_VAR_deploy_id}" \ -backend-config="region=${AWS_REGION}" - ``` @@ -63,10 +77,9 @@ aws s3 rb s3://"${AWS_TERRAFORM_REMOTE_STATE_BUCKET}" --force | Name | Version | |------|---------| -| [aws](#provider\_aws) | 4.22.0 | -| [local](#provider\_local) | 2.2.3 | +| [aws](#provider\_aws) | 4.26.0 | | [null](#provider\_null) | 3.1.1 | -| [tls](#provider\_tls) | 3.4.0 | +| [tls](#provider\_tls) | 4.0.1 | ## Modules @@ -84,31 +97,32 @@ aws s3 rb s3://"${AWS_TERRAFORM_REMOTE_STATE_BUCKET}" --force | Name | Type | |------|------| | [aws_key_pair.domino](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/key_pair) | resource | -| [local_sensitive_file.pvt_key](https://registry.terraform.io/providers/hashicorp/local/latest/docs/resources/sensitive_file) | resource | -| [tls_private_key.domino](https://registry.terraform.io/providers/hashicorp/tls/latest/docs/resources/private_key) | resource | | [aws_availability_zones.available](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/availability_zones) | data source | | [aws_ec2_instance_type_offerings.nodes](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ec2_instance_type_offerings) | data source | | [null_data_source.validate_zones](https://registry.terraform.io/providers/hashicorp/null/latest/docs/data-sources/data_source) | data source | +| [tls_public_key.domino](https://registry.terraform.io/providers/hashicorp/tls/latest/docs/data-sources/public_key) | data source | ## Inputs | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| +| [additional\_node\_groups](#input\_additional\_node\_groups) | Additional EKS managed node groups definition. |
map(object({
ami = optional(string)
name = string
instance_type = string
min_per_az = number
max_per_az = number
desired_per_az = number
label = string
volume = object({
size = string
type = string
})
}))
| `{}` | no | | [availability\_zones](#input\_availability\_zones) | List of Availibility zones to distribute the deployment, EKS needs at least 2,https://docs.aws.amazon.com/eks/latest/userguide/network_reqs.html.
Note that setting this variable bypasses validation of the status of the zones data 'aws\_availability\_zones' 'available'.
Caller is responsible for validating status of these zones. | `list(string)` | `[]` | no | | [base\_cidr\_block](#input\_base\_cidr\_block) | CIDR block to serve the main private and public subnets. | `string` | `"10.0.0.0/16"` | no | +| [bastion\_ami\_id](#input\_bastion\_ami\_id) | AMI ID for the bastion EC2 instance, otherwise we will use the latest 'amazon\_linux\_2' ami | `string` | `""` | no | | [create\_bastion](#input\_create\_bastion) | Create bastion toggle. | `bool` | `false` | no | +| [default\_node\_groups](#input\_default\_node\_groups) | EKS managed node groups definition. |
object({
compute = object({
name = string
ami = optional(string)
instance_type = string
min_per_az = number
max_per_az = number
desired_per_az = number
volume = object({
size = string
type = string
})
}),
platform = object({
name = string
ami = optional(string)
instance_type = string
min_per_az = number
max_per_az = number
desired_per_az = number
volume = object({
size = string
type = string
})
}),
gpu = object({
name = string
ami = optional(string)
instance_type = string
min_per_az = number
max_per_az = number
desired_per_az = number
volume = object({
size = string
type = string
})
})
})
|
{
"compute": {
"desired_per_az": 1,
"instance_type": "m5.2xlarge",
"max_per_az": 10,
"min_per_az": 0,
"name": "compute",
"volume": {
"size": "100",
"type": "gp3"
}
},
"gpu": {
"desired_per_az": 0,
"instance_type": "g4dn.xlarge",
"max_per_az": 10,
"min_per_az": 0,
"name": "gpu",
"volume": {
"size": "100",
"type": "gp3"
}
},
"platform": {
"desired_per_az": 1,
"instance_type": "m5.4xlarge",
"max_per_az": 10,
"min_per_az": 0,
"name": "platform",
"volume": {
"size": "100",
"type": "gp3"
}
}
}
| no | | [deploy\_id](#input\_deploy\_id) | Domino Deployment ID. | `string` | `"domino-eks"` | no | | [efs\_access\_point\_path](#input\_efs\_access\_point\_path) | Filesystem path for efs. | `string` | `"/domino"` | no | | [eks\_master\_role\_names](#input\_eks\_master\_role\_names) | IAM role names to be added as masters in eks. | `list(string)` | `[]` | no | | [k8s\_version](#input\_k8s\_version) | EKS cluster k8s version. | `string` | `"1.22"` | no | -| [node\_groups](#input\_node\_groups) | EKS managed node groups definition. |
object({
compute = object({
ami = optional(string)
instance_type = string
min_per_az = number
max_per_az = number
desired_per_az = number
volume = object({
size = string
type = string
})
}),
platform = object({
ami = optional(string)
instance_type = string
min_per_az = number
max_per_az = number
desired_per_az = number
volume = object({
size = string
type = string
})
}),
gpu = object({
ami = optional(string)
instance_type = string
min_per_az = number
max_per_az = number
desired_per_az = number
volume = object({
size = string
type = string
})
})
})
|
{
"compute": {
"desired_per_az": 1,
"instance_type": "m5.2xlarge",
"max_per_az": 10,
"min_per_az": 0,
"volume": {
"size": "100",
"type": "gp3"
}
},
"gpu": {
"desired_per_az": 0,
"instance_type": "g4dn.xlarge",
"max_per_az": 10,
"min_per_az": 0,
"volume": {
"size": "100",
"type": "gp3"
}
},
"platform": {
"desired_per_az": 1,
"instance_type": "m5.4xlarge",
"max_per_az": 10,
"min_per_az": 0,
"volume": {
"size": "100",
"type": "gp3"
}
}
}
| no | | [number\_of\_azs](#input\_number\_of\_azs) | Number of AZ to distribute the deployment, EKS needs at least 2. | `number` | `3` | no | | [private\_cidr\_network\_bits](#input\_private\_cidr\_network\_bits) | Number of network bits to allocate to the private subnet. i.e /19 -> 8,192 IPs. | `number` | `19` | no | | [public\_cidr\_network\_bits](#input\_public\_cidr\_network\_bits) | Number of network bits to allocate to the public subnet. i.e /27 -> 32 IPs. | `number` | `27` | no | | [region](#input\_region) | AWS region for the deployment | `string` | n/a | yes | | [route53\_hosted\_zone\_name](#input\_route53\_hosted\_zone\_name) | AWS Route53 Hosted zone. | `string` | n/a | yes | -| [s3\_force\_destroy\_toggle](#input\_s3\_force\_destroy\_toggle) | Toogle to allow recursive deletion of all objects in the s3 buckets. if 'false' terraform will NOT be able to delete non-empty buckets | `string` | `"false"` | no | -| [ssh\_pvt\_key\_name](#input\_ssh\_pvt\_key\_name) | ssh private key filename. | `string` | `"domino.pem"` | no | +| [s3\_force\_destroy\_on\_deletion](#input\_s3\_force\_destroy\_on\_deletion) | Toogle to allow recursive deletion of all objects in the s3 buckets. if 'false' terraform will NOT be able to delete non-empty buckets | `bool` | `false` | no | +| [ssh\_pvt\_key\_path](#input\_ssh\_pvt\_key\_path) | SSH private key filepath. | `string` | n/a | yes | | [tags](#input\_tags) | Deployment tags. | `map(string)` | `{}` | no | | [vpc\_id](#input\_vpc\_id) | VPC ID for bringing your own vpc, will bypass creation of such. | `string` | `""` | no | @@ -122,5 +136,4 @@ aws s3 rb s3://"${AWS_TERRAFORM_REMOTE_STATE_BUCKET}" --force | [k8s\_tunnel\_command](#output\_k8s\_tunnel\_command) | Command to run the k8s tunnel mallory. | | [region](#output\_region) | Deployment region. | | [ssh\_bastion\_command](#output\_ssh\_bastion\_command) | Command to ssh into the bastion host | -| [zone\_validation](#output\_zone\_validation) | UNUSED, To silence TFLint unused resource warning | diff --git a/example/main.tf b/example/main.tf index adf09fad..373ea005 100755 --- a/example/main.tf +++ b/example/main.tf @@ -1,12 +1,13 @@ module "domino_eks" { - source = "../../terraform-aws-eks" - deploy_id = "mhtfeks" - region = "us-west-2" - number_of_azs = 2 - route53_hosted_zone_name = "infra-team-sandbox.domino.tech" - eks_master_role_names = ["okta-poweruser", "okta-fulladmin"] - s3_force_destroy_toggle = "true" - create_bastion = true + source = "../../terraform-aws-eks" + deploy_id = "mhtfeks" + region = "us-west-2" + number_of_azs = 2 + route53_hosted_zone_name = "infra-team-sandbox.domino.tech" + eks_master_role_names = ["okta-poweruser", "okta-fulladmin"] + s3_force_destroy_on_deletion = true + create_bastion = true + ssh_pvt_key_path = "domino.pem" tags = { deploy_id = "domino-eks" deploy_tag = "domino-eks" diff --git a/main.tf b/main.tf index 3f8d2640..734036a2 100644 --- a/main.tf +++ b/main.tf @@ -2,11 +2,11 @@ # Check the zones where the instance types are being offered data "aws_ec2_instance_type_offerings" "nodes" { - for_each = var.node_groups + for_each = merge(var.default_node_groups, var.additional_node_groups) filter { name = "instance-type" - # values = toset([for i in var.node_groups : i.instance_type]) + # values = toset([for i in var.default_node_groups : i.instance_type]) values = [each.value.instance_type] } @@ -32,42 +32,45 @@ data "aws_availability_zones" "available" { locals { # Get zones where ALL instance types are offered(intersection). - zone_intersection_instance_offerings = setintersection(toset(data.aws_ec2_instance_type_offerings.nodes["compute"].locations), toset(data.aws_ec2_instance_type_offerings.nodes["platform"].locations), toset(data.aws_ec2_instance_type_offerings.nodes["gpu"].locations)) + zone_intersection_instance_offerings = setintersection([for k, v in data.aws_ec2_instance_type_offerings.nodes : toset(v.locations)]...) # Get the zones that are available and offered in the region for the instance types. az_names = length(var.availability_zones) > 0 ? var.availability_zones : data.aws_availability_zones.available.names offered_azs = setintersection(local.zone_intersection_instance_offerings, toset(local.az_names)) available_azs_data = zipmap(data.aws_availability_zones.available.names, data.aws_availability_zones.available.zone_ids) # Getting the required azs name and id. - availability_zones = { for name in slice(tolist(local.offered_azs), 0, var.number_of_azs) : name => local.available_azs_data[name] } - bastion_user = "ec2-user" - ssh_pvt_key_path = "resources/${var.deploy_id}/${var.ssh_pvt_key_name}" - kubeconfig_path = "resources/${var.deploy_id}/kubeconfig" + + bastion_user = "ec2-user" + working_dir = path.cwd + ssh_pvt_key_path = "${local.working_dir}/${var.ssh_pvt_key_path}" + kubeconfig_path = "${local.working_dir}/kubeconfig" } # Validate that the number of offered and available zones satisfy the number of required zones. https://github.com/hashicorp/terraform/issues/31122 may result in a more elegant validation and deprecation of the null_data_source data "null_data_source" "validate_zones" { + inputs = { + validated = true + } lifecycle { precondition { condition = length(local.offered_azs) >= var.number_of_azs - error_message = "Availability of the instance types does not satisfy the number of zones" + error_message = "Availability of the instance types does not satisfy the desired number of zones, or the desired number of zones is higher than the available/offered zones" } } } -## Creating SSH pvt key to access bastion and EKS nodes -resource "tls_private_key" "domino" { - algorithm = "RSA" +locals { + availability_zones = { for name in slice(tolist(local.offered_azs), 0, var.number_of_azs) : name => local.available_azs_data[name] if data.null_data_source.validate_zones.outputs["validated"] } } -resource "local_sensitive_file" "pvt_key" { - content = tls_private_key.domino.private_key_openssh - file_permission = "0400" - filename = local.ssh_pvt_key_path +## Importing SSH pvt key to access bastion and EKS nodes + +data "tls_public_key" "domino" { + private_key_openssh = file(var.ssh_pvt_key_path) } resource "aws_key_pair" "domino" { key_name = var.deploy_id - public_key = trimspace(tls_private_key.domino.public_key_openssh) + public_key = trimspace(data.tls_public_key.domino.public_key_openssh) } module "subnets_cidr" { @@ -88,7 +91,6 @@ module "network" { base_cidr_block = var.base_cidr_block vpc_id = var.vpc_id monitoring_s3_bucket_arn = module.storage.monitoring_s3_bucket_arn - tags = var.tags } locals { @@ -98,17 +100,16 @@ locals { module "storage" { - source = "./submodules/storage" - deploy_id = var.deploy_id - efs_access_point_path = var.efs_access_point_path - s3_force_destroy_toggle = var.s3_force_destroy_toggle + source = "./submodules/storage" + deploy_id = var.deploy_id + efs_access_point_path = var.efs_access_point_path + s3_force_destroy_on_deletion = var.s3_force_destroy_on_deletion subnets = [for s in local.private_subnets : { name = s.name id = s.id cidr_block = s.cidr_block }] vpc_id = module.network.vpc_id - tags = var.tags } module "bastion" { @@ -118,9 +119,9 @@ module "bastion" { region = var.region vpc_id = module.network.vpc_id deploy_id = var.deploy_id - ssh_pvt_key_name = aws_key_pair.domino.key_name + ssh_pvt_key_path = aws_key_pair.domino.key_name bastion_public_subnet_id = local.public_subnets[0].id - tags = var.tags + bastion_ami_id = var.bastion_ami_id } module "eks" { @@ -130,21 +131,21 @@ module "eks" { vpc_id = module.network.vpc_id deploy_id = var.deploy_id private_subnets = local.private_subnets - ssh_pvt_key_name = aws_key_pair.domino.key_name + ssh_pvt_key_path = aws_key_pair.domino.key_name route53_hosted_zone_name = var.route53_hosted_zone_name bastion_security_group_id = try(module.bastion[0].security_group_id, "") create_bastion_sg = var.create_bastion kubeconfig_path = local.kubeconfig_path - node_groups = var.node_groups + default_node_groups = var.default_node_groups + additional_node_groups = var.additional_node_groups s3_buckets = module.storage.s3_buckets - tags = var.tags } module "k8s_setup" { source = "./submodules/k8s" deploy_id = var.deploy_id - ssh_pvt_key_name = abspath(local.ssh_pvt_key_path) + ssh_pvt_key_path = abspath(local.ssh_pvt_key_path) bastion_user = local.bastion_user bastion_public_ip = try(module.bastion[0].public_ip, "") k8s_cluster_endpoint = module.eks.cluster_endpoint diff --git a/outputs.tf b/outputs.tf index 8dd267b1..20b6b954 100755 --- a/outputs.tf +++ b/outputs.tf @@ -27,8 +27,3 @@ output "deploy_id" { description = "Deployment ID." value = var.deploy_id } - -output "zone_validation" { - description = "UNUSED, To silence TFLint unused resource warning" - value = data.null_data_source.validate_zones.id -} diff --git a/submodules/bastion/README.md b/submodules/bastion/README.md index 6afbdc2b..d5888279 100644 --- a/submodules/bastion/README.md +++ b/submodules/bastion/README.md @@ -41,12 +41,12 @@ No modules. | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| +| [bastion\_ami\_id](#input\_bastion\_ami\_id) | AMI ID for the bastion EC2 instance, otherwise we will use the latest 'amazon\_linux\_2' ami. | `string` | `""` | no | | [bastion\_public\_subnet\_id](#input\_bastion\_public\_subnet\_id) | Public subnet to create bastion host in. | `string` | n/a | yes | -| [bastion\_security\_group\_rules](#input\_bastion\_security\_group\_rules) | Bastion host security group rules. | `map(any)` |
{
"bastion_inbound_ssh": {
"cidr_blocks": [
"0.0.0.0/0"
],
"description": "Inbound ssh",
"from_port": "22",
"protocol": "-1",
"source_security_group_id": null,
"to_port": "22",
"type": "ingress"
},
"bastion_outbound_traffic": {
"cidr_blocks": [
"0.0.0.0/0"
],
"description": "Allow all outbound traffic by default",
"from_port": "0",
"protocol": "-1",
"source_security_group_id": null,
"to_port": "0",
"type": "egress"
}
}
| no | +| [bastion\_security\_group\_rules](#input\_bastion\_security\_group\_rules) | Bastion host security group rules. |
map(object({
protocol = string
from_port = string
to_port = string
type = string
description = string
cidr_blocks = list(string)
source_security_group_id = string

}))
|
{
"bastion_inbound_ssh": {
"cidr_blocks": [
"0.0.0.0/0"
],
"description": "Inbound ssh",
"from_port": "22",
"protocol": "-1",
"source_security_group_id": null,
"to_port": "22",
"type": "ingress"
},
"bastion_outbound_traffic": {
"cidr_blocks": [
"0.0.0.0/0"
],
"description": "Allow all outbound traffic by default",
"from_port": "0",
"protocol": "-1",
"source_security_group_id": null,
"to_port": "0",
"type": "egress"
}
}
| no | | [deploy\_id](#input\_deploy\_id) | Domino Deployment ID | `string` | n/a | yes | | [region](#input\_region) | AWS region for the deployment | `string` | n/a | yes | -| [ssh\_pvt\_key\_name](#input\_ssh\_pvt\_key\_name) | ssh private key filename. | `string` | n/a | yes | -| [tags](#input\_tags) | Deployment tags | `map(string)` | n/a | yes | +| [ssh\_pvt\_key\_path](#input\_ssh\_pvt\_key\_path) | SSH private key filepath. | `string` | n/a | yes | | [vpc\_id](#input\_vpc\_id) | VPC ID. | `string` | n/a | yes | ## Outputs diff --git a/submodules/bastion/main.tf b/submodules/bastion/main.tf index fac1a5d0..7fd51683 100644 --- a/submodules/bastion/main.tf +++ b/submodules/bastion/main.tf @@ -16,7 +16,9 @@ resource "aws_security_group" "bastion" { create_before_destroy = true } - tags = merge({ "Name" = "${var.deploy_id}-bastion" }, var.tags) + tags = { + "Name" = "${var.deploy_id}-bastion" + } } resource "aws_security_group_rule" "bastion" { for_each = var.bastion_security_group_rules @@ -55,7 +57,9 @@ data "aws_iam_policy_document" "bastion" { resource "aws_iam_role" "bastion" { assume_role_policy = data.aws_iam_policy_document.bastion.json name = "${var.deploy_id}-bastion" - tags = merge({ "Name" = "${var.deploy_id}-bastion" }, var.tags) + tags = { + "Name" = "${var.deploy_id}-bastion" + } } resource "aws_iam_role_policy_attachment" "bastion" { @@ -68,8 +72,8 @@ resource "aws_iam_instance_profile" "bastion" { role = aws_iam_role.bastion.name } - data "aws_ami" "amazon_linux_2" { + count = var.bastion_ami_id == "" ? 1 : 0 most_recent = true owners = ["amazon"] @@ -79,9 +83,13 @@ data "aws_ami" "amazon_linux_2" { } } +locals { + bastion_ami_id = var.bastion_ami_id != "" ? var.bastion_ami_id : data.aws_ami.amazon_linux_2[0].id +} + resource "aws_instance" "bastion" { - ami = data.aws_ami.amazon_linux_2.id - associate_public_ip_address = "true" + ami = local.bastion_ami_id + associate_public_ip_address = true iam_instance_profile = aws_iam_instance_profile.bastion.name monitoring = true @@ -89,18 +97,18 @@ resource "aws_instance" "bastion" { capacity_reservation_preference = "open" } - disable_api_termination = "false" - ebs_optimized = "false" + disable_api_termination = false + ebs_optimized = false enclave_options { - enabled = "false" + enabled = false } - get_password_data = "false" - hibernation = "false" + get_password_data = false + hibernation = false instance_initiated_shutdown_behavior = "stop" instance_type = "t2.micro" - key_name = var.ssh_pvt_key_name + key_name = var.ssh_pvt_key_path metadata_options { http_endpoint = "enabled" @@ -110,19 +118,21 @@ resource "aws_instance" "bastion" { } root_block_device { - delete_on_termination = "true" - encrypted = "true" + delete_on_termination = true + encrypted = true iops = "3000" throughput = "125" volume_size = "40" volume_type = "gp3" } - source_dest_check = "true" + source_dest_check = true subnet_id = var.bastion_public_subnet_id vpc_security_group_ids = [aws_security_group.bastion.id] - tags = merge({ "Name" = "${var.deploy_id}-bastion" }, var.tags) + tags = { + "Name" = "${var.deploy_id}-bastion" + } lifecycle { ignore_changes = [ root_block_device[0].tags, @@ -133,8 +143,7 @@ resource "aws_instance" "bastion" { resource "aws_eip" "bastion" { instance = aws_instance.bastion.id network_border_group = var.region - vpc = "true" - tags = var.tags + vpc = true } data "aws_iam_policy_document" "bastion_assume_role" { diff --git a/submodules/bastion/variables.tf b/submodules/bastion/variables.tf index 9675fe00..9758a070 100644 --- a/submodules/bastion/variables.tf +++ b/submodules/bastion/variables.tf @@ -8,52 +8,61 @@ variable "deploy_id" { } } -variable "region" { +variable "bastion_ami_id" { + description = "AMI ID for the bastion EC2 instance, otherwise we will use the latest 'amazon_linux_2' ami." type = string - description = "AWS region for the deployment" + default = "" } - -variable "tags" { - type = map(string) - description = "Deployment tags" +variable "region" { + description = "AWS region for the deployment" + type = string } variable "vpc_id" { - type = string description = "VPC ID." + type = string } -variable "ssh_pvt_key_name" { +variable "ssh_pvt_key_path" { + description = "SSH private key filepath." type = string - description = "ssh private key filename." } variable "bastion_public_subnet_id" { - type = string description = "Public subnet to create bastion host in." + type = string } variable "bastion_security_group_rules" { - type = map(any) description = "Bastion host security group rules." + type = map(object({ + protocol = string + from_port = string + to_port = string + type = string + description = string + cidr_blocks = list(string) + source_security_group_id = string + + })) default = { bastion_outbound_traffic = { - description = "Allow all outbound traffic by default" protocol = "-1" from_port = "0" to_port = "0" type = "egress" + description = "Allow all outbound traffic by default" cidr_blocks = ["0.0.0.0/0"] source_security_group_id = null } bastion_inbound_ssh = { - description = "Inbound ssh" protocol = "-1" from_port = "22" to_port = "22" type = "ingress" + description = "Inbound ssh" cidr_blocks = ["0.0.0.0/0"] source_security_group_id = null } diff --git a/submodules/eks/README.md b/submodules/eks/README.md index 340869ec..91bc1921 100644 --- a/submodules/eks/README.md +++ b/submodules/eks/README.md @@ -26,6 +26,7 @@ No modules. |------|------| | [aws_eks_addon.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eks_addon) | resource | | [aws_eks_cluster.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eks_cluster) | resource | +| [aws_eks_node_group.additional_node_groups](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eks_node_group) | resource | | [aws_eks_node_group.compute](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eks_node_group) | resource | | [aws_eks_node_group.gpu](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eks_node_group) | resource | | [aws_eks_node_group.platform](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eks_node_group) | resource | @@ -42,6 +43,7 @@ No modules. | [aws_iam_role_policy_attachment.custom_eks_nodes_route53](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | | [aws_iam_role_policy_attachment.eks_cluster](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | | [aws_kms_key.eks_cluster](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_key) | resource | +| [aws_launch_template.additional_node_groups](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/launch_template) | resource | | [aws_launch_template.compute](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/launch_template) | resource | | [aws_launch_template.gpu](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/launch_template) | resource | | [aws_launch_template.platform](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/launch_template) | resource | @@ -70,20 +72,20 @@ No modules. | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| +| [additional\_node\_groups](#input\_additional\_node\_groups) | Additional EKS managed node groups definition. |
map(object({
name = string
ami = optional(string)
instance_type = string
min_per_az = number
max_per_az = number
desired_per_az = number
label = string
volume = object({
size = string
type = string
})
}))
| `{}` | no | | [bastion\_security\_group\_id](#input\_bastion\_security\_group\_id) | Bastion security group id. | `string` | `""` | no | | [create\_bastion\_sg](#input\_create\_bastion\_sg) | Create bastion access rules toggle. | `bool` | n/a | yes | +| [default\_node\_groups](#input\_default\_node\_groups) | EKS managed node groups definition. |
object({
compute = object({
name = string
ami = optional(string)
instance_type = string
min_per_az = number
max_per_az = number
desired_per_az = number
volume = object({
size = string
type = string
})
}),
platform = object({
name = string
ami = optional(string)
instance_type = string
min_per_az = number
max_per_az = number
desired_per_az = number
volume = object({
size = string
type = string
})
}),
gpu = object({
name = string
ami = optional(string)
instance_type = string
min_per_az = number
max_per_az = number
desired_per_az = number
volume = object({
size = string
type = string
})
})
})
| n/a | yes | | [deploy\_id](#input\_deploy\_id) | Domino Deployment ID | `string` | n/a | yes | | [eks\_cluster\_addons](#input\_eks\_cluster\_addons) | EKS cluster addons. | `list(string)` |
[
"vpc-cni",
"kube-proxy",
"coredns"
]
| no | -| [eks\_security\_group\_rules](#input\_eks\_security\_group\_rules) | EKS security group rules. | `map(any)` | `{}` | no | +| [eks\_security\_group\_rules](#input\_eks\_security\_group\_rules) | EKS security group rules. |
map(object({
security_group_id = string
protocol = string
from_port = string
to_port = string
type = string
description = string
source_security_group_id = string
}))
| `{}` | no | | [k8s\_version](#input\_k8s\_version) | EKS cluster k8s version. | `string` | `"1.22"` | no | -| [kubeconfig\_path](#input\_kubeconfig\_path) | Kubeconfig filename. | `string` | `"kubeconfig"` | no | -| [node\_groups](#input\_node\_groups) | EKS managed node groups definition. |
object({
compute = object({
ami = optional(string)
instance_type = string
min_per_az = number
max_per_az = number
desired_per_az = number
volume = object({
size = string
type = string
})
}),
platform = object({
ami = optional(string)
instance_type = string
min_per_az = number
max_per_az = number
desired_per_az = number
volume = object({
size = string
type = string
})
}),
gpu = object({
ami = optional(string)
instance_type = string
min_per_az = number
max_per_az = number
desired_per_az = number
volume = object({
size = string
type = string
})
})
})
| n/a | yes | +| [kubeconfig\_path](#input\_kubeconfig\_path) | Kubeconfig file path. | `string` | `"kubeconfig"` | no | | [private\_subnets](#input\_private\_subnets) | Private subnets object |
list(object({
cidr_block = string
name = string
type = string
zone = string
zone_id = string
id = string
}))
| n/a | yes | | [region](#input\_region) | AWS region for the deployment | `string` | n/a | yes | | [route53\_hosted\_zone\_name](#input\_route53\_hosted\_zone\_name) | Route53 zone | `string` | n/a | yes | | [s3\_buckets](#input\_s3\_buckets) | S3 buckets information that the nodegroups need access to |
list(object({
bucket_name = string
arn = string
}))
| n/a | yes | -| [ssh\_pvt\_key\_name](#input\_ssh\_pvt\_key\_name) | ssh private key filename. | `string` | n/a | yes | -| [tags](#input\_tags) | Deployment tags | `map(string)` | n/a | yes | +| [ssh\_pvt\_key\_path](#input\_ssh\_pvt\_key\_path) | SSH private key filepath. | `string` | n/a | yes | | [vpc\_id](#input\_vpc\_id) | VPC ID. | `string` | n/a | yes | ## Outputs diff --git a/submodules/eks/cluster.tf b/submodules/eks/cluster.tf index 999a66c8..9d52868d 100755 --- a/submodules/eks/cluster.tf +++ b/submodules/eks/cluster.tf @@ -2,7 +2,21 @@ data "aws_iam_policy_document" "kms_key" { statement { actions = [ - "kms:Create*", "kms:Describe*", "kms:Enable*", "kms:List*", "kms:Put*", "kms:Update*", "kms:Revoke*", "kms:Disable*", "kms:Get*", "kms:Delete*", "kms:ScheduleKeyDeletion", "kms:CancelKeyDeletion", "kubeconms:GenerateDataKey", "kms:TagResource", "kms:UntagResource" + "kms:Create*", + "kms:Describe*", + "kms:Enable*", + "kms:List*", + "kms:Put*", + "kms:Update*", + "kms:Revoke*", + "kms:Disable*", + "kms:Get*", + "kms:Delete*", + "kms:ScheduleKeyDeletion", + "kms:CancelKeyDeletion", + "kubeconms:GenerateDataKey", + "kms:TagResource", + "kms:UntagResource" ] resources = ["*"] effect = "Allow" @@ -15,17 +29,16 @@ data "aws_iam_policy_document" "kms_key" { resource "aws_kms_key" "eks_cluster" { customer_master_key_spec = "SYMMETRIC_DEFAULT" - enable_key_rotation = "true" - is_enabled = "true" + enable_key_rotation = true + is_enabled = true key_usage = "ENCRYPT_DECRYPT" - multi_region = "false" + multi_region = false policy = data.aws_iam_policy_document.kms_key.json - tags = merge({ "Name" = "${var.deploy_id}-eks-cluster" }, var.tags) - + tags = { + "Name" = "${var.deploy_id}-eks-cluster" + } } -## END - EKS key -## EKS security-group resource "aws_security_group" "eks_cluster" { name = "${var.deploy_id}-cluster" description = "EKS cluster security group" @@ -34,7 +47,9 @@ resource "aws_security_group" "eks_cluster" { lifecycle { create_before_destroy = true } - tags = merge({ "Name" = "${var.deploy_id}-eks-cluster" }, var.tags) + tags = { + "Name" = "${var.deploy_id}-eks-cluster" + } } resource "aws_security_group_rule" "eks_cluster" { @@ -58,7 +73,6 @@ resource "aws_eks_cluster" "this" { role_arn = aws_iam_role.eks_cluster.arn enabled_cluster_log_types = ["api", "audit", "authenticator", "controllerManager", "scheduler"] version = var.k8s_version - tags = var.tags encryption_config { provider { @@ -74,8 +88,8 @@ resource "aws_eks_cluster" "this" { vpc_config { - endpoint_private_access = "true" - endpoint_public_access = "false" + endpoint_private_access = true + endpoint_public_access = false security_group_ids = [aws_security_group.eks_cluster.id] subnet_ids = [for sb in var.private_subnets : sb.id] } @@ -93,13 +107,14 @@ resource "aws_eks_addon" "this" { aws_eks_node_group.platform, aws_eks_node_group.gpu, ] - - tags = var.tags } resource "null_resource" "kubeconfig" { provisioner "local-exec" { - command = "export KUBECONFIG=${var.kubeconfig_path} && aws eks update-kubeconfig --region ${var.region} --name ${aws_eks_cluster.this.name}" + environment = { + KUBECONFIG = var.kubeconfig_path + } + command = "aws eks update-kubeconfig --region ${var.region} --name ${aws_eks_cluster.this.name}" } triggers = { domino_eks_cluster_ca = aws_eks_cluster.this.certificate_authority[0].data diff --git a/submodules/eks/iam.tf b/submodules/eks/iam.tf index 94a514a8..eac3e585 100644 --- a/submodules/eks/iam.tf +++ b/submodules/eks/iam.tf @@ -14,7 +14,6 @@ data "aws_iam_policy_document" "eks_cluster" { resource "aws_iam_role" "eks_cluster" { name = "${var.deploy_id}-eks" assume_role_policy = data.aws_iam_policy_document.eks_cluster.json - tags = var.tags } resource "aws_iam_role_policy_attachment" "eks_cluster" { diff --git a/submodules/eks/node-group.tf b/submodules/eks/node-group.tf index 3e3471ca..b26685bf 100644 --- a/submodules/eks/node-group.tf +++ b/submodules/eks/node-group.tf @@ -19,7 +19,6 @@ data "aws_route53_zone" "this" { resource "aws_iam_role" "eks_nodes" { name = "${var.deploy_id}-eks-nodes" assume_role_policy = data.aws_iam_policy_document.eks_nodes.json - tags = var.tags } locals { @@ -35,8 +34,8 @@ locals { pre_bootstrap_user_data = "" post_bootstrap_user_data = "echo ALL DONE !!!" })) - node_group_gpu_ami_id = var.node_groups.gpu.ami != null ? var.node_groups.gpu.ami : data.aws_ami.eks_gpu.image_id - # node_group_compute_ami_id = var.node_groups.compute.ami != null ? var.node_groups.compute.ami : data.aws_ami.eks_gpu.image_id + node_group_gpu_ami_id = var.default_node_groups.gpu.ami != null ? var.default_node_groups.gpu.ami : data.aws_ami.eks_gpu.image_id + # node_group_compute_ami_id = var.default_node_groups.compute.ami != null ? var.default_node_groups.compute.ami : data.aws_ami.eks_gpu.image_id } @@ -48,7 +47,9 @@ resource "aws_security_group" "eks_nodes" { lifecycle { create_before_destroy = true } - tags = merge({ "Name" = "${var.deploy_id}-eks-nodes" }, var.tags) + tags = { + "Name" = "${var.deploy_id}-eks-nodes" + } } resource "aws_security_group_rule" "node" { @@ -80,20 +81,20 @@ data "aws_ami" "eks_gpu" { resource "aws_launch_template" "compute" { name = "${var.deploy_id}-compute" - disable_api_termination = "false" - instance_type = var.node_groups.compute.instance_type - key_name = var.ssh_pvt_key_name + disable_api_termination = false + instance_type = var.default_node_groups.compute.instance_type + key_name = var.ssh_pvt_key_path vpc_security_group_ids = [aws_security_group.eks_nodes.id] - image_id = var.node_groups.compute.ami + image_id = var.default_node_groups.compute.ami block_device_mappings { device_name = "/dev/xvda" ebs { - delete_on_termination = "true" - encrypted = "true" - volume_size = var.node_groups.compute.volume.size - volume_type = var.node_groups.compute.volume.type + delete_on_termination = true + encrypted = true + volume_size = var.default_node_groups.compute.volume.size + volume_type = var.default_node_groups.compute.volume.type } } @@ -104,29 +105,29 @@ resource "aws_launch_template" "compute" { } tag_specifications { resource_type = "instance" - tags = merge({ + tags = { "Name" = "${var.deploy_id}-compute" - }, var.tags) + } } tag_specifications { resource_type = "volume" - tags = merge({ "Name" = "${var.deploy_id}-compute" }, var.tags) + tags = { + "Name" = "${var.deploy_id}-compute" + } } - tags = var.tags } resource "aws_eks_node_group" "compute" { - for_each = { for sb in var.private_subnets : sb.zone => sb if lookup(var.node_groups, "compute", {}) != {} } + for_each = { for sb in var.private_subnets : sb.zone => sb if lookup(var.default_node_groups, "compute", {}) != {} } cluster_name = aws_eks_cluster.this.name node_group_name = "${var.deploy_id}-compute-${each.value.zone}" node_role_arn = aws_iam_role.eks_nodes.arn subnet_ids = [each.value.id] - tags = var.tags scaling_config { - min_size = var.node_groups.compute.min_per_az - max_size = var.node_groups.compute.max_per_az - desired_size = var.node_groups.compute.desired_per_az + min_size = var.default_node_groups.compute.min_per_az + max_size = var.default_node_groups.compute.max_per_az + desired_size = var.default_node_groups.compute.desired_per_az } launch_template { @@ -138,7 +139,7 @@ resource "aws_eks_node_group" "compute" { labels = { "lifecycle" = "OnDemand" "dominodatalab.com/node-pool" = "default" - "dominodatalab.com/domino-node" = "true" + "dominodatalab.com/domino-node" = true } lifecycle { @@ -156,20 +157,20 @@ resource "aws_eks_node_group" "compute" { resource "aws_launch_template" "platform" { name = "${var.deploy_id}-platform" - disable_api_termination = "false" - instance_type = var.node_groups.platform.instance_type - key_name = var.ssh_pvt_key_name + disable_api_termination = false + instance_type = var.default_node_groups.platform.instance_type + key_name = var.ssh_pvt_key_path vpc_security_group_ids = [aws_security_group.eks_nodes.id] - image_id = var.node_groups.platform.ami + image_id = var.default_node_groups.platform.ami block_device_mappings { device_name = "/dev/xvda" ebs { - delete_on_termination = "true" - encrypted = "true" - volume_size = var.node_groups.platform.volume.size - volume_type = var.node_groups.platform.volume.type + delete_on_termination = true + encrypted = true + volume_size = var.default_node_groups.platform.volume.size + volume_type = var.default_node_groups.platform.volume.type } } @@ -180,29 +181,29 @@ resource "aws_launch_template" "platform" { } tag_specifications { resource_type = "instance" - tags = merge({ + tags = { "Name" = "${var.deploy_id}-platform" - }, var.tags) + } } tag_specifications { resource_type = "volume" - tags = merge({ "Name" = "${var.deploy_id}-platform" }, var.tags) + tags = { + "Name" = "${var.deploy_id}-platform" + } } - tags = var.tags } resource "aws_eks_node_group" "platform" { - for_each = { for sb in var.private_subnets : sb.zone => sb if lookup(var.node_groups, "platform", {}) != {} } + for_each = { for sb in var.private_subnets : sb.zone => sb if lookup(var.default_node_groups, "platform", {}) != {} } cluster_name = aws_eks_cluster.this.name node_group_name = "${var.deploy_id}-platform-${each.value.zone}" node_role_arn = aws_iam_role.eks_nodes.arn subnet_ids = [each.value.id] - tags = var.tags scaling_config { - min_size = var.node_groups.platform.min_per_az - max_size = var.node_groups.platform.max_per_az - desired_size = var.node_groups.platform.desired_per_az + min_size = var.default_node_groups.platform.min_per_az + max_size = var.default_node_groups.platform.max_per_az + desired_size = var.default_node_groups.platform.desired_per_az } launch_template { @@ -214,7 +215,7 @@ resource "aws_eks_node_group" "platform" { labels = { "lifecycle" = "OnDemand" "dominodatalab.com/node-pool" = "platform" - "dominodatalab.com/domino-node" = "true" + "dominodatalab.com/domino-node" = true } lifecycle { @@ -233,19 +234,19 @@ resource "aws_eks_node_group" "platform" { resource "aws_launch_template" "gpu" { name = "${var.deploy_id}-gpu" image_id = local.node_group_gpu_ami_id - disable_api_termination = "false" - instance_type = var.node_groups.gpu.instance_type - key_name = var.ssh_pvt_key_name + disable_api_termination = false + instance_type = var.default_node_groups.gpu.instance_type + key_name = var.ssh_pvt_key_path vpc_security_group_ids = [aws_security_group.eks_nodes.id] user_data = local.gpu_user_data block_device_mappings { device_name = "/dev/xvda" ebs { - delete_on_termination = "true" - encrypted = "true" - volume_size = var.node_groups.gpu.volume.size - volume_type = var.node_groups.gpu.volume.type + delete_on_termination = true + encrypted = true + volume_size = var.default_node_groups.gpu.volume.size + volume_type = var.default_node_groups.gpu.volume.type } } @@ -256,29 +257,29 @@ resource "aws_launch_template" "gpu" { } tag_specifications { resource_type = "instance" - tags = merge({ + tags = { "Name" = "${var.deploy_id}-gpu" - }, var.tags) + } } tag_specifications { resource_type = "volume" - tags = merge({ "Name" = "${var.deploy_id}-gpu" }, var.tags) + tags = { + "Name" = "${var.deploy_id}-gpu" + } } - tags = var.tags } resource "aws_eks_node_group" "gpu" { - for_each = { for sb in var.private_subnets : sb.zone => sb if lookup(var.node_groups, "gpu", {}) != {} } + for_each = { for sb in var.private_subnets : sb.zone => sb if lookup(var.default_node_groups, "gpu", {}) != {} } cluster_name = aws_eks_cluster.this.name node_group_name = "${var.deploy_id}-gpu-${each.value.zone}" node_role_arn = aws_iam_role.eks_nodes.arn subnet_ids = [each.value.id] - tags = var.tags scaling_config { - min_size = var.node_groups.gpu.min_per_az - max_size = var.node_groups.gpu.max_per_az - desired_size = var.node_groups.gpu.desired_per_az + min_size = var.default_node_groups.gpu.min_per_az + max_size = var.default_node_groups.gpu.max_per_az + desired_size = var.default_node_groups.gpu.desired_per_az } launch_template { @@ -288,14 +289,107 @@ resource "aws_eks_node_group" "gpu" { taint { key = "nvidia.com/gpu" - value = "true" + value = true effect = "NO_SCHEDULE" } labels = { "lifecycle" = "OnDemand" "dominodatalab.com/node-pool" = "default-gpu" - "dominodatalab.com/domino-node" = "true" - "nvidia.com/gpu" = "true" + "dominodatalab.com/domino-node" = true + "nvidia.com/gpu" = true + } + + lifecycle { + create_before_destroy = true + ignore_changes = [ + scaling_config[0].desired_size, + ] + } + + depends_on = [ + aws_iam_role_policy_attachment.aws_eks_nodes, + aws_iam_role_policy_attachment.custom_eks_nodes + ] +} + +## Additional node groups + +locals { + additional_node_groups_per_zone = length(var.additional_node_groups) > 0 ? flatten([ + for sb in var.private_subnets : [ + for ng in var.additional_node_groups : { + # ng_resource_id = "${ng.name}-${sb.zone}" + subnet_zone = sb.zone + subnet_id = sb.id + node_group = ng + } + ] + ]) : [] +} + + +resource "aws_launch_template" "additional_node_groups" { + for_each = var.additional_node_groups + name = "${var.deploy_id}-${try(each.value.name, each.key)}" + disable_api_termination = false + instance_type = each.value.instance_type + key_name = var.ssh_pvt_key_path + vpc_security_group_ids = [aws_security_group.eks_nodes.id] + image_id = each.value.ami + + block_device_mappings { + device_name = "/dev/xvda" + + ebs { + delete_on_termination = true + encrypted = true + volume_size = each.value.volume.size + volume_type = each.value.volume.type + } + } + + metadata_options { + http_endpoint = "enabled" + http_put_response_hop_limit = "2" + http_tokens = "required" + } + tag_specifications { + resource_type = "instance" + tags = { + "Name" = "${var.deploy_id}-${each.key}" + } + } + + tag_specifications { + resource_type = "volume" + tags = { + "Name" = "${var.deploy_id}-${each.key}" + } + } +} + +resource "aws_eks_node_group" "additional_node_groups" { + for_each = { for ng in local.additional_node_groups_per_zone : "${ng.node_group.name}-${ng.subnet_zone}" => ng } + cluster_name = aws_eks_cluster.this.name + node_group_name = "${var.deploy_id}-platform-${each.value.subnet_zone}" + node_role_arn = aws_iam_role.eks_nodes.arn + subnet_ids = [each.value.subnet_id] + scaling_config { + min_size = each.value.node_group.min_per_az + max_size = each.value.node_group.max_per_az + desired_size = each.value.node_group.desired_per_az + } + + launch_template { + id = aws_launch_template.additional_node_groups[each.value.node_group.name].id + version = aws_launch_template.additional_node_groups[each.value.node_group.name].latest_version + } + + + labels = { + "lifecycle" = "OnDemand" + "dominodatalab.com/node-pool" = each.value.node_group.label + "dominodatalab.com/domino-node" = true } lifecycle { diff --git a/submodules/eks/variables.tf b/submodules/eks/variables.tf index eebbe16c..d2ff3a8f 100755 --- a/submodules/eks/variables.tf +++ b/submodules/eks/variables.tf @@ -13,21 +13,17 @@ variable "region" { description = "AWS region for the deployment" } -variable "tags" { - type = map(string) - description = "Deployment tags" -} - variable "k8s_version" { type = string description = "EKS cluster k8s version." default = "1.22" } -variable "node_groups" { +variable "default_node_groups" { description = "EKS managed node groups definition." type = object({ compute = object({ + name = string ami = optional(string) instance_type = string min_per_az = number @@ -39,6 +35,7 @@ variable "node_groups" { }) }), platform = object({ + name = string ami = optional(string) instance_type = string min_per_az = number @@ -50,6 +47,7 @@ variable "node_groups" { }) }), gpu = object({ + name = string ami = optional(string) instance_type = string min_per_az = number @@ -63,9 +61,27 @@ variable "node_groups" { }) } +variable "additional_node_groups" { + description = "Additional EKS managed node groups definition." + type = map(object({ + name = string + ami = optional(string) + instance_type = string + min_per_az = number + max_per_az = number + desired_per_az = number + label = string + volume = object({ + size = string + type = string + }) + })) + default = {} +} + variable "kubeconfig_path" { type = string - description = "Kubeconfig filename." + description = "Kubeconfig file path." default = "kubeconfig" } @@ -90,9 +106,9 @@ variable "vpc_id" { description = "VPC ID." } -variable "ssh_pvt_key_name" { +variable "ssh_pvt_key_path" { type = string - description = "ssh private key filename." + description = "SSH private key filepath." } variable "route53_hosted_zone_name" { @@ -110,18 +126,25 @@ variable "eks_cluster_addons" { type = list(string) description = "EKS cluster addons." default = ["vpc-cni", "kube-proxy", "coredns"] - # default = ["vpc-cni", "kube-proxy", "coredns", "aws-ebs-csi-driver"] } variable "eks_security_group_rules" { - type = map(any) description = "EKS security group rules." - default = {} + type = map(object({ + security_group_id = string + protocol = string + from_port = string + to_port = string + type = string + description = string + source_security_group_id = string + })) + default = {} } variable "create_bastion_sg" { - type = bool description = "Create bastion access rules toggle." + type = bool } variable "s3_buckets" { diff --git a/submodules/k8s/README.md b/submodules/k8s/README.md index 9966b8c5..ff5e65fd 100644 --- a/submodules/k8s/README.md +++ b/submodules/k8s/README.md @@ -44,7 +44,7 @@ No modules. | [mallory\_local\_normal\_port](#input\_mallory\_local\_normal\_port) | Mallory k8s tunnel normal port. | `string` | `"1315"` | no | | [mallory\_local\_smart\_port](#input\_mallory\_local\_smart\_port) | Mallory k8s tunnel smart(filters based on the blocked list) port. | `string` | `"1316"` | no | | [managed\_nodes\_role\_arns](#input\_managed\_nodes\_role\_arns) | EKS managed nodes arns to be added to aws-auth for api auth. | `list(string)` | n/a | yes | -| [ssh\_pvt\_key\_name](#input\_ssh\_pvt\_key\_name) | ssh private key filename. | `string` | `"domino.pem"` | no | +| [ssh\_pvt\_key\_path](#input\_ssh\_pvt\_key\_path) | SSH private key filepath. | `string` | n/a | yes | ## Outputs diff --git a/submodules/k8s/main.tf b/submodules/k8s/main.tf index b7c5b58d..2295d6a3 100644 --- a/submodules/k8s/main.tf +++ b/submodules/k8s/main.tf @@ -9,7 +9,7 @@ locals { mallory_config_filename = "mallory.json" mallory_container_name = "mallory_k8s_tunnel" mallory_config_path_container = "/root/.config/${local.mallory_config_filename}" - pvt_key_path_container = "/root/${basename(var.ssh_pvt_key_name)}" + pvt_key_path_container = "/root/${basename(var.ssh_pvt_key_path)}" k8s_functions_sh_filename = "k8s-functions.sh" k8s_functions_sh_template = "k8s-functions.sh.tftpl" k8s_pre_setup_sh_filename = "k8s-pre-setup.sh" @@ -21,7 +21,7 @@ locals { custom_resources_url = "https://raw.githubusercontent.com/aws/amazon-vpc-cni-k8s/${var.calico_version}/config/master/calico-crs.yaml" } - k8s_tunnel_command = "docker run --rm --name ${local.mallory_container_name} -d -v $PWD/${local.mallory_config_filename}:${local.mallory_config_path_container} -p ${var.mallory_local_normal_port}:${var.mallory_local_normal_port} -p ${var.mallory_local_smart_port}:${var.mallory_local_smart_port} -v ${var.ssh_pvt_key_name}:${local.pvt_key_path_container} zoobab/mallory" + k8s_tunnel_command = "docker run --rm --name ${local.mallory_container_name} -d -v $PWD/${local.mallory_config_filename}:${local.mallory_config_path_container} -p ${var.mallory_local_normal_port}:${var.mallory_local_normal_port} -p ${var.mallory_local_smart_port}:${var.mallory_local_smart_port} -v ${var.ssh_pvt_key_path}:${local.pvt_key_path_container} zoobab/mallory" resources_directory = "${path.cwd}/resources/${var.deploy_id}" templates_dir = "${path.module}/templates" diff --git a/submodules/k8s/variables.tf b/submodules/k8s/variables.tf index e1f9ce68..c8de6067 100755 --- a/submodules/k8s/variables.tf +++ b/submodules/k8s/variables.tf @@ -14,10 +14,9 @@ variable "kubeconfig_path" { default = "kubeconfig" } -variable "ssh_pvt_key_name" { +variable "ssh_pvt_key_path" { type = string - description = "ssh private key filename." - default = "domino.pem" + description = "SSH private key filepath." } diff --git a/submodules/network/README.md b/submodules/network/README.md index f5fe0a72..f16b4819 100644 --- a/submodules/network/README.md +++ b/submodules/network/README.md @@ -49,7 +49,6 @@ No modules. | [private\_subnets](#input\_private\_subnets) | Private subnets object |
list(object({
cidr_block = string
name = string
type = string
zone = string
zone_id = string
}))
| n/a | yes | | [public\_subnets](#input\_public\_subnets) | Public subnets object |
list(object({
cidr_block = string
name = string
type = string
zone = string
zone_id = string
}))
| n/a | yes | | [region](#input\_region) | AWS region for the deployment | `string` | n/a | yes | -| [tags](#input\_tags) | Deployment tags | `map(string)` | n/a | yes | | [vpc\_id](#input\_vpc\_id) | VPC ID. | `string` | `""` | no | ## Outputs diff --git a/submodules/network/internet-gateway.tf b/submodules/network/internet-gateway.tf index a400fa48..baddeb78 100644 --- a/submodules/network/internet-gateway.tf +++ b/submodules/network/internet-gateway.tf @@ -1,6 +1,8 @@ resource "aws_internet_gateway" "igw" { # vpc_id = local.vpc_id - tags = merge({ "Name" = "${var.deploy_id}-domino-igw" }, var.tags) + tags = { + "Name" = "${var.deploy_id}-domino-igw" + } } @@ -15,6 +17,8 @@ resource "aws_eip" "public" { network_border_group = var.region public_ipv4_pool = "amazon" vpc = true - tags = merge({ "Name" = each.value.name }, var.tags) - depends_on = [aws_internet_gateway.igw] + tags = { + "Name" = each.value.name + } + depends_on = [aws_internet_gateway.igw] } diff --git a/submodules/network/nat-gateway.tf b/submodules/network/nat-gateway.tf index 2e1e2d4c..bd5e9c84 100644 --- a/submodules/network/nat-gateway.tf +++ b/submodules/network/nat-gateway.tf @@ -3,6 +3,9 @@ resource "aws_nat_gateway" "ngw" { allocation_id = aws_eip.public[each.value.name].allocation_id connectivity_type = "public" subnet_id = aws_subnet.public[each.value.name].id - tags = merge({ "Name" = each.value.name }, { "zone" = each.value.zone }, var.tags) - depends_on = [aws_internet_gateway.igw] + tags = { + "Name" = each.value.name + "zone" = each.value.zone + } + depends_on = [aws_internet_gateway.igw] } diff --git a/submodules/network/route-tables.tf b/submodules/network/route-tables.tf index 387b23e2..0514f973 100644 --- a/submodules/network/route-tables.tf +++ b/submodules/network/route-tables.tf @@ -5,14 +5,11 @@ resource "aws_route_table" "public" { gateway_id = aws_internet_gateway.igw.id } vpc_id = local.vpc_id - tags = merge( - { - "Name" = each.value.name, - "kubernetes.io/role/elb" = "1", - "kubernetes.io/cluster/${var.deploy_id}" = "shared", - }, - var.tags - ) + tags = { + "Name" = each.value.name, + "kubernetes.io/role/elb" = "1", + "kubernetes.io/cluster/${var.deploy_id}" = "shared", + } } @@ -29,15 +26,11 @@ resource "aws_route_table" "private" { nat_gateway_id = aws_nat_gateway.ngw[each.value.zone].id } vpc_id = local.vpc_id - tags = merge( - { - "Name" = each.value.name, - "kubernetes.io/role/internal-elb" = "1", - "kubernetes.io/cluster/${var.deploy_id}" = "shared", - }, - var.tags - ) - + tags = { + "Name" = each.value.name, + "kubernetes.io/role/internal-elb" = "1", + "kubernetes.io/cluster/${var.deploy_id}" = "shared", + } } resource "aws_route_table_association" "private" { diff --git a/submodules/network/subnets.tf b/submodules/network/subnets.tf index 29229669..fed2c8e8 100644 --- a/submodules/network/subnets.tf +++ b/submodules/network/subnets.tf @@ -4,14 +4,11 @@ resource "aws_subnet" "public" { availability_zone_id = each.value.zone_id vpc_id = local.vpc_id cidr_block = each.value.cidr_block - tags = merge( - { - "Name" = each.value.name, - "kubernetes.io/role/elb" = "1", - "kubernetes.io/cluster/${var.deploy_id}" = "shared", - }, - var.tags - ) + tags = { + "Name" = each.value.name, + "kubernetes.io/role/elb" = "1", + "kubernetes.io/cluster/${var.deploy_id}" = "shared", + } } resource "aws_subnet" "private" { @@ -20,12 +17,9 @@ resource "aws_subnet" "private" { availability_zone_id = each.value.zone_id vpc_id = local.vpc_id cidr_block = each.value.cidr_block - tags = merge( - { - "Name" = each.value.name, - "kubernetes.io/role/internal-elb" = "1", - "kubernetes.io/cluster/${var.deploy_id}" = "shared", - }, - var.tags - ) + tags = { + "Name" = each.value.name, + "kubernetes.io/role/internal-elb" = "1", + "kubernetes.io/cluster/${var.deploy_id}" = "shared", + } } diff --git a/submodules/network/variables.tf b/submodules/network/variables.tf index b059202e..7f17b89a 100644 --- a/submodules/network/variables.tf +++ b/submodules/network/variables.tf @@ -14,11 +14,6 @@ variable "region" { description = "AWS region for the deployment" } -variable "tags" { - type = map(string) - description = "Deployment tags" -} - variable "base_cidr_block" { type = string description = "CIDR block to serve the main private and public subnets" diff --git a/submodules/network/vpc.tf b/submodules/network/vpc.tf index 1f2bc825..9eb5a80e 100644 --- a/submodules/network/vpc.tf +++ b/submodules/network/vpc.tf @@ -8,11 +8,13 @@ data "aws_vpc" "this" { resource "aws_vpc" "this" { count = var.vpc_id != "" ? 0 : 1 - assign_generated_ipv6_cidr_block = "false" + assign_generated_ipv6_cidr_block = false cidr_block = var.base_cidr_block enable_dns_hostnames = true enable_dns_support = true - tags = merge({ "Name" = var.deploy_id }, var.tags) + tags = { + "Name" = var.deploy_id + } } locals { @@ -28,7 +30,9 @@ resource "aws_vpc_endpoint" "s3" { [for s in aws_route_table.private : s.id] ) - tags = merge({ "Name" = "${var.deploy_id}-s3" }, var.tags) + tags = { + "Name" = "${var.deploy_id}-s3" + } } data "aws_network_acls" "default" { @@ -73,8 +77,6 @@ resource "aws_default_network_acl" "default" { lifecycle { ignore_changes = [subnet_ids] } - - tags = var.tags } resource "aws_flow_log" "this" { diff --git a/submodules/storage/README.md b/submodules/storage/README.md index be142cef..b0d21320 100644 --- a/submodules/storage/README.md +++ b/submodules/storage/README.md @@ -53,9 +53,9 @@ No modules. |------|-------------|------|---------|:--------:| | [deploy\_id](#input\_deploy\_id) | Domino Deployment ID | `string` | n/a | yes | | [efs\_access\_point\_path](#input\_efs\_access\_point\_path) | Filesystem path for efs. | `string` | `"/domino"` | no | -| [s3\_force\_destroy\_toggle](#input\_s3\_force\_destroy\_toggle) | Toogle to allow recursive deletion of all objects in the s3 buckets. if 'false' terraform will NOT be able to delete non-empty buckets | `string` | `"false"` | no | +| [s3\_encryption\_use\_sse\_kms\_key](#input\_s3\_encryption\_use\_sse\_kms\_key) | if true use 'aws:kms' else 'AES256' for the s3 server-side-encryption. | `bool` | `false` | no | +| [s3\_force\_destroy\_on\_deletion](#input\_s3\_force\_destroy\_on\_deletion) | Toogle to allow recursive deletion of all objects in the s3 buckets. if 'false' terraform will NOT be able to delete non-empty buckets | `bool` | `false` | no | | [subnets](#input\_subnets) | List of subnet ids to create EFS mount targets |
list(object({
name = string
id = string
cidr_block = string
}))
| n/a | yes | -| [tags](#input\_tags) | Deployment tags. | `map(string)` | n/a | yes | | [vpc\_id](#input\_vpc\_id) | VPC ID | `string` | n/a | yes | ## Outputs diff --git a/submodules/storage/efs.tf b/submodules/storage/efs.tf index 28c99468..11741d45 100644 --- a/submodules/storage/efs.tf +++ b/submodules/storage/efs.tf @@ -1,10 +1,12 @@ resource "aws_efs_file_system" "eks" { - encrypted = "true" + encrypted = true performance_mode = "generalPurpose" provisioned_throughput_in_mibps = "0" throughput_mode = "bursting" - tags = merge({ "Name" = var.deploy_id }, var.tags) + tags = { + "Name" = var.deploy_id + } } resource "aws_security_group" "efs" { @@ -15,7 +17,9 @@ resource "aws_security_group" "efs" { lifecycle { create_before_destroy = true } - tags = merge({ "Name" = "${var.deploy_id}-efs" }, var.tags) + tags = { + "Name" = "${var.deploy_id}-efs" + } } resource "aws_security_group_rule" "efs" { @@ -52,5 +56,4 @@ resource "aws_efs_access_point" "eks" { path = var.efs_access_point_path } - tags = var.tags } diff --git a/submodules/storage/s3.tf b/submodules/storage/s3.tf index 24584688..6671b3d2 100644 --- a/submodules/storage/s3.tf +++ b/submodules/storage/s3.tf @@ -1,9 +1,12 @@ +locals { + s3_server_side_encryption = var.s3_encryption_use_sse_kms_key ? "aws:kms" : "AES256" +} resource "aws_s3_bucket" "backups" { bucket = "${var.deploy_id}-backups" - force_destroy = var.s3_force_destroy_toggle - object_lock_enabled = "false" - tags = var.tags + force_destroy = var.s3_force_destroy_on_deletion + object_lock_enabled = false + } data "aws_iam_policy_document" "backups" { @@ -38,7 +41,7 @@ data "aws_iam_policy_document" "backups" { condition { test = "StringNotEquals" variable = "s3:x-amz-server-side-encryption" - values = ["AES256"] + values = [local.s3_server_side_encryption] } principals { @@ -68,9 +71,9 @@ data "aws_iam_policy_document" "backups" { resource "aws_s3_bucket" "blobs" { bucket = "${var.deploy_id}-blobs" - force_destroy = var.s3_force_destroy_toggle - object_lock_enabled = "false" - tags = var.tags + force_destroy = var.s3_force_destroy_on_deletion + object_lock_enabled = false + } data "aws_iam_policy_document" "blobs" { @@ -107,7 +110,7 @@ data "aws_iam_policy_document" "blobs" { condition { test = "StringNotEquals" variable = "s3:x-amz-server-side-encryption" - values = ["AES256"] + values = [local.s3_server_side_encryption] } principals { @@ -137,9 +140,9 @@ data "aws_iam_policy_document" "blobs" { resource "aws_s3_bucket" "logs" { bucket = "${var.deploy_id}-logs" - force_destroy = var.s3_force_destroy_toggle - object_lock_enabled = "false" - tags = var.tags + force_destroy = var.s3_force_destroy_on_deletion + object_lock_enabled = false + } data "aws_iam_policy_document" "logs" { @@ -175,7 +178,7 @@ data "aws_iam_policy_document" "logs" { condition { test = "StringNotEquals" variable = "s3:x-amz-server-side-encryption" - values = ["AES256"] + values = [local.s3_server_side_encryption] } principals { @@ -205,9 +208,9 @@ data "aws_iam_policy_document" "logs" { resource "aws_s3_bucket" "monitoring" { bucket = "${var.deploy_id}-monitoring" - force_destroy = var.s3_force_destroy_toggle - object_lock_enabled = "false" - tags = var.tags + force_destroy = var.s3_force_destroy_on_deletion + object_lock_enabled = false + } data "aws_iam_policy_document" "monitoring" { @@ -322,9 +325,9 @@ resource "aws_s3_bucket_acl" "monitoring" { resource "aws_s3_bucket" "registry" { bucket = "${var.deploy_id}-registry" - force_destroy = var.s3_force_destroy_toggle - object_lock_enabled = "false" - tags = var.tags + force_destroy = var.s3_force_destroy_on_deletion + object_lock_enabled = false + } data "aws_iam_policy_document" "registry" { @@ -358,7 +361,7 @@ data "aws_iam_policy_document" "registry" { condition { test = "StringNotEquals" variable = "s3:x-amz-server-side-encryption" - values = ["AES256"] + values = [local.s3_server_side_encryption] } principals { @@ -398,9 +401,9 @@ resource "aws_s3_bucket_server_side_encryption_configuration" "buckets_encryptio bucket = each.value.bucket_name rule { apply_server_side_encryption_by_default { - sse_algorithm = "AES256" + sse_algorithm = local.s3_server_side_encryption } - bucket_key_enabled = "false" + bucket_key_enabled = false } } diff --git a/submodules/storage/variables.tf b/submodules/storage/variables.tf index e349d210..d35781e8 100755 --- a/submodules/storage/variables.tf +++ b/submodules/storage/variables.tf @@ -16,11 +16,6 @@ variable "efs_access_point_path" { } -variable "tags" { - type = map(string) - description = "Deployment tags." -} - variable "subnets" { type = list(object({ name = string @@ -36,8 +31,14 @@ variable "vpc_id" { } -variable "s3_force_destroy_toggle" { +variable "s3_force_destroy_on_deletion" { description = "Toogle to allow recursive deletion of all objects in the s3 buckets. if 'false' terraform will NOT be able to delete non-empty buckets" - type = string - default = "false" + type = bool + default = false +} + +variable "s3_encryption_use_sse_kms_key" { + description = "if true use 'aws:kms' else 'AES256' for the s3 server-side-encryption." + type = bool + default = false } diff --git a/variables.tf b/variables.tf index de4d1f9d..913b2986 100755 --- a/variables.tf +++ b/variables.tf @@ -70,9 +70,10 @@ variable "private_cidr_network_bits" { default = 19 } -variable "node_groups" { +variable "default_node_groups" { type = object({ compute = object({ + name = string ami = optional(string) instance_type = string min_per_az = number @@ -84,6 +85,7 @@ variable "node_groups" { }) }), platform = object({ + name = string ami = optional(string) instance_type = string min_per_az = number @@ -95,6 +97,7 @@ variable "node_groups" { }) }), gpu = object({ + name = string ami = optional(string) instance_type = string min_per_az = number @@ -109,6 +112,7 @@ variable "node_groups" { description = "EKS managed node groups definition." default = { "compute" = { + name = "compute" instance_type = "m5.2xlarge" min_per_az = 0 max_per_az = 10 @@ -119,6 +123,7 @@ variable "node_groups" { } }, "platform" = { + name = "platform" instance_type = "m5.4xlarge" min_per_az = 0 max_per_az = 10 @@ -129,6 +134,7 @@ variable "node_groups" { } }, "gpu" = { + name = "gpu" instance_type = "g4dn.xlarge" min_per_az = 0 max_per_az = 10 @@ -141,6 +147,24 @@ variable "node_groups" { } } +variable "additional_node_groups" { + description = "Additional EKS managed node groups definition." + type = map(object({ + ami = optional(string) + name = string + instance_type = string + min_per_az = number + max_per_az = number + desired_per_az = number + label = string + volume = object({ + size = string + type = string + }) + })) + default = {} +} + variable "base_cidr_block" { type = string default = "10.0.0.0/16" @@ -172,6 +196,12 @@ variable "create_bastion" { default = false } +variable "bastion_ami_id" { + description = "AMI ID for the bastion EC2 instance, otherwise we will use the latest 'amazon_linux_2' ami" + type = string + default = "" +} + variable "efs_access_point_path" { type = string description = "Filesystem path for efs." @@ -179,14 +209,17 @@ variable "efs_access_point_path" { } -variable "ssh_pvt_key_name" { +variable "ssh_pvt_key_path" { type = string - description = "ssh private key filename." - default = "domino.pem" + description = "SSH private key filepath." + validation { + condition = fileexists(var.ssh_pvt_key_path) + error_message = "Private key does not exist. Please provide the right path or generate a key with the following command: ssh-keygen -q -P '' -t rsa -b 4096 -m PEM -f domino.pem" + } } -variable "s3_force_destroy_toggle" { +variable "s3_force_destroy_on_deletion" { description = "Toogle to allow recursive deletion of all objects in the s3 buckets. if 'false' terraform will NOT be able to delete non-empty buckets" - type = string - default = "false" + type = bool + default = false } diff --git a/versions.tf b/versions.tf index 8532a443..afbcdd4e 100644 --- a/versions.tf +++ b/versions.tf @@ -24,4 +24,7 @@ terraform { provider "aws" { region = var.region + default_tags { + tags = var.tags + } } From fd8cea2dd616103921157944245861f2d29cc658 Mon Sep 17 00:00:00 2001 From: Miguel Harmant Date: Thu, 18 Aug 2022 14:18:19 -0400 Subject: [PATCH 07/17] PLAT-4955 Terraform EKS module, test for mallory file, ignore template ids --- .gitignore | 7 +++++++ README.md | 2 +- submodules/eks/README.md | 2 +- submodules/eks/variables.tf | 1 - submodules/k8s/main.tf | 6 +++++- submodules/k8s/templates/k8s-functions.sh.tftpl | 8 +++++++- variables.tf | 2 +- 7 files changed, 22 insertions(+), 6 deletions(-) diff --git a/.gitignore b/.gitignore index 09516a59..961c099b 100644 --- a/.gitignore +++ b/.gitignore @@ -29,3 +29,10 @@ override.tf.json # Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan # example: *tfplan* +aws-auth.yaml +domino.pem +domino.pem.pub +k8s-functions.sh +k8s-pre-setup.sh +kubeconfig +mallory.json diff --git a/README.md b/README.md index 66c41cfd..08269022 100644 --- a/README.md +++ b/README.md @@ -115,7 +115,7 @@ aws s3 rb s3://"${AWS_TERRAFORM_REMOTE_STATE_BUCKET}" --force | [deploy\_id](#input\_deploy\_id) | Domino Deployment ID. | `string` | `"domino-eks"` | no | | [efs\_access\_point\_path](#input\_efs\_access\_point\_path) | Filesystem path for efs. | `string` | `"/domino"` | no | | [eks\_master\_role\_names](#input\_eks\_master\_role\_names) | IAM role names to be added as masters in eks. | `list(string)` | `[]` | no | -| [k8s\_version](#input\_k8s\_version) | EKS cluster k8s version. | `string` | `"1.22"` | no | +| [k8s\_version](#input\_k8s\_version) | EKS cluster k8s version. | `string` | `"1.23"` | no | | [number\_of\_azs](#input\_number\_of\_azs) | Number of AZ to distribute the deployment, EKS needs at least 2. | `number` | `3` | no | | [private\_cidr\_network\_bits](#input\_private\_cidr\_network\_bits) | Number of network bits to allocate to the private subnet. i.e /19 -> 8,192 IPs. | `number` | `19` | no | | [public\_cidr\_network\_bits](#input\_public\_cidr\_network\_bits) | Number of network bits to allocate to the public subnet. i.e /27 -> 32 IPs. | `number` | `27` | no | diff --git a/submodules/eks/README.md b/submodules/eks/README.md index 91bc1921..24cfdeee 100644 --- a/submodules/eks/README.md +++ b/submodules/eks/README.md @@ -79,7 +79,7 @@ No modules. | [deploy\_id](#input\_deploy\_id) | Domino Deployment ID | `string` | n/a | yes | | [eks\_cluster\_addons](#input\_eks\_cluster\_addons) | EKS cluster addons. | `list(string)` |
[
"vpc-cni",
"kube-proxy",
"coredns"
]
| no | | [eks\_security\_group\_rules](#input\_eks\_security\_group\_rules) | EKS security group rules. |
map(object({
security_group_id = string
protocol = string
from_port = string
to_port = string
type = string
description = string
source_security_group_id = string
}))
| `{}` | no | -| [k8s\_version](#input\_k8s\_version) | EKS cluster k8s version. | `string` | `"1.22"` | no | +| [k8s\_version](#input\_k8s\_version) | EKS cluster k8s version. | `string` | n/a | yes | | [kubeconfig\_path](#input\_kubeconfig\_path) | Kubeconfig file path. | `string` | `"kubeconfig"` | no | | [private\_subnets](#input\_private\_subnets) | Private subnets object |
list(object({
cidr_block = string
name = string
type = string
zone = string
zone_id = string
id = string
}))
| n/a | yes | | [region](#input\_region) | AWS region for the deployment | `string` | n/a | yes | diff --git a/submodules/eks/variables.tf b/submodules/eks/variables.tf index d2ff3a8f..ce63f521 100755 --- a/submodules/eks/variables.tf +++ b/submodules/eks/variables.tf @@ -16,7 +16,6 @@ variable "region" { variable "k8s_version" { type = string description = "EKS cluster k8s version." - default = "1.22" } variable "default_node_groups" { diff --git a/submodules/k8s/main.tf b/submodules/k8s/main.tf index 2295d6a3..2a996c30 100644 --- a/submodules/k8s/main.tf +++ b/submodules/k8s/main.tf @@ -23,7 +23,7 @@ locals { k8s_tunnel_command = "docker run --rm --name ${local.mallory_container_name} -d -v $PWD/${local.mallory_config_filename}:${local.mallory_config_path_container} -p ${var.mallory_local_normal_port}:${var.mallory_local_normal_port} -p ${var.mallory_local_smart_port}:${var.mallory_local_smart_port} -v ${var.ssh_pvt_key_path}:${local.pvt_key_path_container} zoobab/mallory" - resources_directory = "${path.cwd}/resources/${var.deploy_id}" + resources_directory = path.cwd templates_dir = "${path.module}/templates" templates = { @@ -34,6 +34,7 @@ locals { k8s_tunnel_command = local.k8s_tunnel_command mallory_port = var.mallory_local_smart_port mallory_container_name = local.mallory_container_name + mallory_config_file = local.mallory_config_filename aws_auth_yaml = basename(local.aws_auth_filename) calico_operator_url = local.calico.operator_url calico_custom_resources_url = local.calico.custom_resources_url @@ -90,4 +91,7 @@ resource "null_resource" "run_k8s_pre_setup" { depends_on = [ local_file.templates, ] + lifecycle { + ignore_changes = [id] + } } diff --git a/submodules/k8s/templates/k8s-functions.sh.tftpl b/submodules/k8s/templates/k8s-functions.sh.tftpl index e9a36e11..c66e78fb 100644 --- a/submodules/k8s/templates/k8s-functions.sh.tftpl +++ b/submodules/k8s/templates/k8s-functions.sh.tftpl @@ -11,7 +11,13 @@ open_ssh_tunnel_to_k8s_api() { https_proxy=http://localhost:$MALLORY_PORT export https_proxy fi - eval ${k8s_tunnel_command} && sleep 3 + + if test -f "${mallory_config_file}"; then + eval ${k8s_tunnel_command} && sleep 3 + else + echo "Mallory config file ${mallory_config_file} does not exist." && exit 1 + fi + echo } diff --git a/variables.tf b/variables.tf index 913b2986..0b42e327 100755 --- a/variables.tf +++ b/variables.tf @@ -55,7 +55,7 @@ variable "tags" { variable "k8s_version" { type = string description = "EKS cluster k8s version." - default = "1.22" + default = "1.23" } variable "public_cidr_network_bits" { From e621d26c4e0e4b1746d998c545031c37a186d221 Mon Sep 17 00:00:00 2001 From: Miguel Harmant Date: Tue, 30 Aug 2022 12:38:26 -0400 Subject: [PATCH 08/17] PLAT-4955 Terraform EKS module, modify outputs --- .gitignore | 1 + README.md | 4 +- example/README.md | 2 +- example/versions.tf | 2 +- outputs.tf | 12 ++- submodules/eks/cluster.tf | 8 +- submodules/eks/eks-bastion-access.tf | 42 ---------- submodules/eks/iam.tf | 2 - submodules/eks/main.tf | 80 ++++++++++++++++++- submodules/eks/node-group.tf | 38 ++++----- submodules/k8s/main.tf | 3 - .../k8s/templates/k8s-functions.sh.tftpl | 1 + submodules/storage/README.md | 4 +- submodules/storage/outputs.tf | 12 ++- 14 files changed, 131 insertions(+), 80 deletions(-) diff --git a/.gitignore b/.gitignore index 961c099b..ea3542c3 100644 --- a/.gitignore +++ b/.gitignore @@ -36,3 +36,4 @@ k8s-functions.sh k8s-pre-setup.sh kubeconfig mallory.json +domino.yml diff --git a/README.md b/README.md index 08269022..f4a5ee66 100644 --- a/README.md +++ b/README.md @@ -131,7 +131,9 @@ aws s3 rb s3://"${AWS_TERRAFORM_REMOTE_STATE_BUCKET}" --force | Name | Description | |------|-------------| | [deploy\_id](#output\_deploy\_id) | Deployment ID. | -| [efs\_filesystem\_id](#output\_efs\_filesystem\_id) | EFS volume handle :: | +| [efs\_access\_point\_id](#output\_efs\_access\_point\_id) | EFS access\_point id | +| [efs\_file\_system\_id](#output\_efs\_file\_system\_id) | EFS filesystem id | +| [efs\_volume\_handle](#output\_efs\_volume\_handle) | EFS volume handle :: | | [hostname](#output\_hostname) | Domino instance URL. | | [k8s\_tunnel\_command](#output\_k8s\_tunnel\_command) | Command to run the k8s tunnel mallory. | | [region](#output\_region) | Deployment region. | diff --git a/example/README.md b/example/README.md index 6c312e6d..e887973c 100644 --- a/example/README.md +++ b/example/README.md @@ -5,7 +5,7 @@ | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 1.0 | +| [terraform](#requirement\_terraform) | >= 1.2.0 | ## Providers diff --git a/example/versions.tf b/example/versions.tf index 7117131f..3e6ba018 100644 --- a/example/versions.tf +++ b/example/versions.tf @@ -1,3 +1,3 @@ terraform { - required_version = ">= 1.0" + required_version = ">= 1.2.0" } diff --git a/outputs.tf b/outputs.tf index 20b6b954..a9a1c0af 100755 --- a/outputs.tf +++ b/outputs.tf @@ -13,11 +13,21 @@ output "hostname" { value = "${var.deploy_id}.${var.route53_hosted_zone_name}" } -output "efs_filesystem_id" { +output "efs_volume_handle" { description = "EFS volume handle ::" value = module.storage.efs_volume_handle } +output "efs_access_point_id" { + description = "EFS access_point id" + value = module.storage.efs_access_point_id +} + +output "efs_file_system_id" { + description = "EFS filesystem id" + value = module.storage.efs_file_system_id +} + output "region" { description = "Deployment region." value = var.region diff --git a/submodules/eks/cluster.tf b/submodules/eks/cluster.tf index 9d52868d..2e583983 100755 --- a/submodules/eks/cluster.tf +++ b/submodules/eks/cluster.tf @@ -35,12 +35,12 @@ resource "aws_kms_key" "eks_cluster" { multi_region = false policy = data.aws_iam_policy_document.kms_key.json tags = { - "Name" = "${var.deploy_id}-eks-cluster" + "Name" = "${local.eks_cluster_name}-eks-cluster" } } resource "aws_security_group" "eks_cluster" { - name = "${var.deploy_id}-cluster" + name = "${local.eks_cluster_name}-cluster" description = "EKS cluster security group" vpc_id = var.vpc_id @@ -48,7 +48,7 @@ resource "aws_security_group" "eks_cluster" { create_before_destroy = true } tags = { - "Name" = "${var.deploy_id}-eks-cluster" + "Name" = "${local.eks_cluster_name}-eks-cluster" } } @@ -69,7 +69,7 @@ resource "aws_security_group_rule" "eks_cluster" { ## EKS cluster resource "aws_eks_cluster" "this" { - name = var.deploy_id + name = local.eks_cluster_name role_arn = aws_iam_role.eks_cluster.arn enabled_cluster_log_types = ["api", "audit", "authenticator", "controllerManager", "scheduler"] version = var.k8s_version diff --git a/submodules/eks/eks-bastion-access.tf b/submodules/eks/eks-bastion-access.tf index 95f3840b..4f70efcb 100644 --- a/submodules/eks/eks-bastion-access.tf +++ b/submodules/eks/eks-bastion-access.tf @@ -1,45 +1,3 @@ - -locals { - bastion_eks_security_group_rules = { - bastion_to_eks_api = { - description = "Bastion outbound to eks cluster ${var.deploy_id}:443 API" - protocol = "tcp" - from_port = "443" - to_port = "443" - type = "egress" - security_group_id = var.bastion_security_group_id - source_security_group_id = aws_security_group.eks_cluster.id - } - bastion_to_eks_nodes_ssh = { - description = "Bastion ssh to eks cluster nodes outbound" - protocol = "tcp" - from_port = "22" - to_port = "22" - type = "egress" - security_group_id = var.bastion_security_group_id - source_security_group_id = aws_security_group.eks_nodes.id - } - eks_api_from_bastion = { - description = "Eks cluster ${var.deploy_id}:443 inbound from bastion" - protocol = "tcp" - from_port = "443" - to_port = "443" - type = "ingress" - security_group_id = aws_security_group.eks_cluster.id - source_security_group_id = var.bastion_security_group_id - } - eks_nodes_ssh_from_bastion = { - description = "Bastion ssh to eks cluster nodes inbound" - protocol = "tcp" - from_port = "22" - to_port = "22" - type = "ingress" - security_group_id = var.bastion_security_group_id - source_security_group_id = aws_security_group.eks_nodes.id - } - } -} - resource "aws_security_group_rule" "bastion_eks" { for_each = { for k, v in local.bastion_eks_security_group_rules : k => v if var.create_bastion_sg } diff --git a/submodules/eks/iam.tf b/submodules/eks/iam.tf index eac3e585..8463a3b9 100644 --- a/submodules/eks/iam.tf +++ b/submodules/eks/iam.tf @@ -21,8 +21,6 @@ resource "aws_iam_role_policy_attachment" "eks_cluster" { role = aws_iam_role.eks_cluster.name } - -## Customer managed policies data "aws_iam_policy_document" "domino_ecr_restricted" { statement { diff --git a/submodules/eks/main.tf b/submodules/eks/main.tf index ae347aec..bab5ef79 100644 --- a/submodules/eks/main.tf +++ b/submodules/eks/main.tf @@ -3,12 +3,13 @@ data "aws_partition" "current" {} data "aws_caller_identity" "aws_account" {} locals { + eks_cluster_name = var.deploy_id aws_account_id = data.aws_caller_identity.aws_account.account_id dns_suffix = data.aws_partition.current.dns_suffix policy_arn_prefix = "arn:${data.aws_partition.current.partition}:iam::aws:policy" eks_cluster_security_group_rules = { ingress_nodes_443 = { - description = "Private subnets to ${var.deploy_id} EKS cluster API" + description = "Private subnets to ${local.eks_cluster_name} EKS cluster API" protocol = "tcp" from_port = 443 to_port = 443 @@ -24,7 +25,7 @@ locals { cidr_blocks = [for sb in var.private_subnets : sb.cidr_block] } egress_nodes_443 = { - description = "${var.deploy_id} EKS cluster API to private subnets" + description = "${local.eks_cluster_name} EKS cluster API to private subnets" protocol = "tcp" from_port = 443 to_port = 443 @@ -32,7 +33,7 @@ locals { cidr_blocks = [for sb in var.private_subnets : sb.cidr_block] } egress_nodes_kubelet = { - description = "${var.deploy_id} EKS cluster API to private subnets" + description = "${local.eks_cluster_name} EKS cluster API to private subnets" protocol = "tcp" from_port = 10250 to_port = 10250 @@ -178,7 +179,39 @@ locals { type = "egress" cidr_blocks = ["0.0.0.0/0"] } - inter_node_traffic_int = { + inter_node_traffic_in_80 = { + description = "Node to node http traffic" + protocol = "tcp" + from_port = 80 + to_port = 80 + type = "ingress" + self = true + } + inter_node_traffic_out_80 = { + description = "Node to node http traffic" + protocol = "tcp" + from_port = 80 + to_port = 80 + type = "egress" + self = true + } + inter_node_traffic_in_443 = { + description = "Node to node https traffic" + protocol = "tcp" + from_port = 443 + to_port = 443 + type = "ingress" + self = true + } + inter_node_traffic_out_443 = { + description = "Node to node https traffic" + protocol = "tcp" + from_port = 443 + to_port = 443 + type = "egress" + self = true + } + inter_node_traffic_in = { description = "Node to node pod/svc trafic in" protocol = "tcp" from_port = 1025 @@ -195,4 +228,43 @@ locals { self = true } } + + bastion_eks_security_group_rules = { + bastion_to_eks_api = { + description = "Bastion outbound to eks cluster ${local.eks_cluster_name}:443 API" + protocol = "tcp" + from_port = "443" + to_port = "443" + type = "egress" + security_group_id = var.bastion_security_group_id + source_security_group_id = aws_security_group.eks_cluster.id + } + bastion_to_eks_nodes_ssh = { + description = "Bastion ssh to eks cluster nodes outbound" + protocol = "tcp" + from_port = "22" + to_port = "22" + type = "egress" + security_group_id = var.bastion_security_group_id + source_security_group_id = aws_security_group.eks_nodes.id + } + eks_api_from_bastion = { + description = "Eks cluster ${local.eks_cluster_name}:443 inbound from bastion" + protocol = "tcp" + from_port = "443" + to_port = "443" + type = "ingress" + security_group_id = aws_security_group.eks_cluster.id + source_security_group_id = var.bastion_security_group_id + } + eks_nodes_ssh_from_bastion = { + description = "Bastion ssh to eks cluster nodes inbound" + protocol = "tcp" + from_port = "22" + to_port = "22" + type = "ingress" + security_group_id = var.bastion_security_group_id + source_security_group_id = aws_security_group.eks_nodes.id + } + } } diff --git a/submodules/eks/node-group.tf b/submodules/eks/node-group.tf index b26685bf..bfb14f9f 100644 --- a/submodules/eks/node-group.tf +++ b/submodules/eks/node-group.tf @@ -17,7 +17,7 @@ data "aws_route53_zone" "this" { } resource "aws_iam_role" "eks_nodes" { - name = "${var.deploy_id}-eks-nodes" + name = "${local.eks_cluster_name}-eks-nodes" assume_role_policy = data.aws_iam_policy_document.eks_nodes.json } @@ -40,7 +40,7 @@ locals { resource "aws_security_group" "eks_nodes" { - name = "${var.deploy_id}-nodes" + name = "${local.eks_cluster_name}-nodes" description = "EKS cluster Nodes security group" vpc_id = var.vpc_id @@ -48,7 +48,7 @@ resource "aws_security_group" "eks_nodes" { create_before_destroy = true } tags = { - "Name" = "${var.deploy_id}-eks-nodes" + "Name" = "${local.eks_cluster_name}-eks-nodes" } } @@ -80,7 +80,7 @@ data "aws_ami" "eks_gpu" { } resource "aws_launch_template" "compute" { - name = "${var.deploy_id}-compute" + name = "${local.eks_cluster_name}-compute" disable_api_termination = false instance_type = var.default_node_groups.compute.instance_type key_name = var.ssh_pvt_key_path @@ -106,14 +106,14 @@ resource "aws_launch_template" "compute" { tag_specifications { resource_type = "instance" tags = { - "Name" = "${var.deploy_id}-compute" + "Name" = "${local.eks_cluster_name}-compute" } } tag_specifications { resource_type = "volume" tags = { - "Name" = "${var.deploy_id}-compute" + "Name" = "${local.eks_cluster_name}-compute" } } } @@ -121,7 +121,7 @@ resource "aws_launch_template" "compute" { resource "aws_eks_node_group" "compute" { for_each = { for sb in var.private_subnets : sb.zone => sb if lookup(var.default_node_groups, "compute", {}) != {} } cluster_name = aws_eks_cluster.this.name - node_group_name = "${var.deploy_id}-compute-${each.value.zone}" + node_group_name = "${local.eks_cluster_name}-compute-${each.value.zone}" node_role_arn = aws_iam_role.eks_nodes.arn subnet_ids = [each.value.id] scaling_config { @@ -156,7 +156,7 @@ resource "aws_eks_node_group" "compute" { } resource "aws_launch_template" "platform" { - name = "${var.deploy_id}-platform" + name = "${local.eks_cluster_name}-platform" disable_api_termination = false instance_type = var.default_node_groups.platform.instance_type key_name = var.ssh_pvt_key_path @@ -182,14 +182,14 @@ resource "aws_launch_template" "platform" { tag_specifications { resource_type = "instance" tags = { - "Name" = "${var.deploy_id}-platform" + "Name" = "${local.eks_cluster_name}-platform" } } tag_specifications { resource_type = "volume" tags = { - "Name" = "${var.deploy_id}-platform" + "Name" = "${local.eks_cluster_name}-platform" } } } @@ -197,7 +197,7 @@ resource "aws_launch_template" "platform" { resource "aws_eks_node_group" "platform" { for_each = { for sb in var.private_subnets : sb.zone => sb if lookup(var.default_node_groups, "platform", {}) != {} } cluster_name = aws_eks_cluster.this.name - node_group_name = "${var.deploy_id}-platform-${each.value.zone}" + node_group_name = "${local.eks_cluster_name}-platform-${each.value.zone}" node_role_arn = aws_iam_role.eks_nodes.arn subnet_ids = [each.value.id] scaling_config { @@ -232,7 +232,7 @@ resource "aws_eks_node_group" "platform" { } resource "aws_launch_template" "gpu" { - name = "${var.deploy_id}-gpu" + name = "${local.eks_cluster_name}-gpu" image_id = local.node_group_gpu_ami_id disable_api_termination = false instance_type = var.default_node_groups.gpu.instance_type @@ -258,14 +258,14 @@ resource "aws_launch_template" "gpu" { tag_specifications { resource_type = "instance" tags = { - "Name" = "${var.deploy_id}-gpu" + "Name" = "${local.eks_cluster_name}-gpu" } } tag_specifications { resource_type = "volume" tags = { - "Name" = "${var.deploy_id}-gpu" + "Name" = "${local.eks_cluster_name}-gpu" } } } @@ -273,7 +273,7 @@ resource "aws_launch_template" "gpu" { resource "aws_eks_node_group" "gpu" { for_each = { for sb in var.private_subnets : sb.zone => sb if lookup(var.default_node_groups, "gpu", {}) != {} } cluster_name = aws_eks_cluster.this.name - node_group_name = "${var.deploy_id}-gpu-${each.value.zone}" + node_group_name = "${local.eks_cluster_name}-gpu-${each.value.zone}" node_role_arn = aws_iam_role.eks_nodes.arn subnet_ids = [each.value.id] scaling_config { @@ -330,7 +330,7 @@ locals { resource "aws_launch_template" "additional_node_groups" { for_each = var.additional_node_groups - name = "${var.deploy_id}-${try(each.value.name, each.key)}" + name = "${local.eks_cluster_name}-${try(each.value.name, each.key)}" disable_api_termination = false instance_type = each.value.instance_type key_name = var.ssh_pvt_key_path @@ -356,14 +356,14 @@ resource "aws_launch_template" "additional_node_groups" { tag_specifications { resource_type = "instance" tags = { - "Name" = "${var.deploy_id}-${each.key}" + "Name" = "${local.eks_cluster_name}-${try(each.value.name, each.key)}" } } tag_specifications { resource_type = "volume" tags = { - "Name" = "${var.deploy_id}-${each.key}" + "Name" = "${local.eks_cluster_name}-${try(each.value.name, each.key)}" } } } @@ -371,7 +371,7 @@ resource "aws_launch_template" "additional_node_groups" { resource "aws_eks_node_group" "additional_node_groups" { for_each = { for ng in local.additional_node_groups_per_zone : "${ng.node_group.name}-${ng.subnet_zone}" => ng } cluster_name = aws_eks_cluster.this.name - node_group_name = "${var.deploy_id}-platform-${each.value.subnet_zone}" + node_group_name = "${local.eks_cluster_name}-platform-${each.value.subnet_zone}" node_role_arn = aws_iam_role.eks_nodes.arn subnet_ids = [each.value.subnet_id] scaling_config { diff --git a/submodules/k8s/main.tf b/submodules/k8s/main.tf index 2a996c30..0cca583d 100644 --- a/submodules/k8s/main.tf +++ b/submodules/k8s/main.tf @@ -91,7 +91,4 @@ resource "null_resource" "run_k8s_pre_setup" { depends_on = [ local_file.templates, ] - lifecycle { - ignore_changes = [id] - } } diff --git a/submodules/k8s/templates/k8s-functions.sh.tftpl b/submodules/k8s/templates/k8s-functions.sh.tftpl index c66e78fb..5e7a2beb 100644 --- a/submodules/k8s/templates/k8s-functions.sh.tftpl +++ b/submodules/k8s/templates/k8s-functions.sh.tftpl @@ -13,6 +13,7 @@ open_ssh_tunnel_to_k8s_api() { fi if test -f "${mallory_config_file}"; then + { docker kill ${mallory_container_name} && docker rm ${mallory_container_name}; } || true eval ${k8s_tunnel_command} && sleep 3 else echo "Mallory config file ${mallory_config_file} does not exist." && exit 1 diff --git a/submodules/storage/README.md b/submodules/storage/README.md index b0d21320..7ad6b72b 100644 --- a/submodules/storage/README.md +++ b/submodules/storage/README.md @@ -62,7 +62,9 @@ No modules. | Name | Description | |------|-------------| -| [efs\_volume\_handle](#output\_efs\_volume\_handle) | EFS volume handle :: | +| [efs\_access\_point\_id](#output\_efs\_access\_point\_id) | EFS access\_point id | +| [efs\_file\_system\_id](#output\_efs\_file\_system\_id) | EFS filesystem id | +| [efs\_volume\_handle](#output\_efs\_volume\_handle) | EFS volume handle :: | | [monitoring\_s3\_bucket\_arn](#output\_monitoring\_s3\_bucket\_arn) | Monitoring bucket arn | | [s3\_buckets](#output\_s3\_buckets) | S3 buckets name and arn | diff --git a/submodules/storage/outputs.tf b/submodules/storage/outputs.tf index 071314c2..14c029a3 100644 --- a/submodules/storage/outputs.tf +++ b/submodules/storage/outputs.tf @@ -1,8 +1,18 @@ output "efs_volume_handle" { - description = "EFS volume handle ::" + description = "EFS volume handle ::" value = "${aws_efs_access_point.eks.file_system_id}::${aws_efs_access_point.eks.id}" } +output "efs_access_point_id" { + description = "EFS access_point id" + value = aws_efs_access_point.eks.id +} + +output "efs_file_system_id" { + description = "EFS filesystem id" + value = aws_efs_file_system.eks.id +} + output "monitoring_s3_bucket_arn" { description = "Monitoring bucket arn" value = aws_s3_bucket.backups.arn From c9a6fa633fc84a0420a32f018d1dbb5a27de4514 Mon Sep 17 00:00:00 2001 From: Miguel Harmant Date: Tue, 30 Aug 2022 12:39:02 -0400 Subject: [PATCH 09/17] PLAT-4955 Terraform EKS module, modify outputs --- .pre-commit-config.yaml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index dbccf714..650af383 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -34,8 +34,8 @@ repos: - '--args=--only=terraform_standard_module_structure' - '--args=--only=terraform_workspace_remote' - id: terraform_validate - # - id: terrascan # Skipping until they update lifecycle block; Data resources do not have lifecycle settings, so a lifecycle block is not allowed. - # args: - # - '--args=--non-recursive' - # - '--args=--policy-type=aws' - # - '--args=--skip-rules=AC_AWS_0369' #Flow logs are enabled, terrascan does not follow the logical path of the resource + - id: terrascan # Skipping until they update lifecycle block; Data resources do not have lifecycle settings, so a lifecycle block is not allowed. + args: + - '--args=--non-recursive' + - '--args=--policy-type=aws' + - '--args=--skip-rules=AC_AWS_0369' #Flow logs are enabled, terrascan does not follow the logical path of the resource From e662a77cac3b51f4c03447196ec7a36572314ec1 Mon Sep 17 00:00:00 2001 From: Miguel Harmant Date: Tue, 30 Aug 2022 12:39:57 -0400 Subject: [PATCH 10/17] PLAT-4955 Terraform EKS module, modify outputs --- .pre-commit-config.yaml | 10 +++++----- variables.tf | 1 - 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 650af383..dbccf714 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -34,8 +34,8 @@ repos: - '--args=--only=terraform_standard_module_structure' - '--args=--only=terraform_workspace_remote' - id: terraform_validate - - id: terrascan # Skipping until they update lifecycle block; Data resources do not have lifecycle settings, so a lifecycle block is not allowed. - args: - - '--args=--non-recursive' - - '--args=--policy-type=aws' - - '--args=--skip-rules=AC_AWS_0369' #Flow logs are enabled, terrascan does not follow the logical path of the resource + # - id: terrascan # Skipping until they update lifecycle block; Data resources do not have lifecycle settings, so a lifecycle block is not allowed. + # args: + # - '--args=--non-recursive' + # - '--args=--policy-type=aws' + # - '--args=--skip-rules=AC_AWS_0369' #Flow logs are enabled, terrascan does not follow the logical path of the resource diff --git a/variables.tf b/variables.tf index 0b42e327..35c98fc1 100755 --- a/variables.tf +++ b/variables.tf @@ -40,7 +40,6 @@ variable "availability_zones" { default = [] } - variable "route53_hosted_zone_name" { type = string description = "AWS Route53 Hosted zone." From c6dd74b8018cc9288ea5a8376b94f6c74e542f50 Mon Sep 17 00:00:00 2001 From: Miguel Harmant Date: Wed, 31 Aug 2022 12:20:28 -0400 Subject: [PATCH 11/17] PLAT-4955 Terraform EKS module, Add CODEOWNERS --- .github/CODEOWNERS | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 .github/CODEOWNERS diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 00000000..c2fe172c --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,4 @@ +# CODEOWNERS +# https://help.github.com/en/github/creating-cloning-and-archiving-repositories/about-code-owners#codeowners-file-location + +* @dominodatalab/platform From 21b1edcb35657fc5ba214068552d009f7c29b47a Mon Sep 17 00:00:00 2001 From: Miguel Harmant Date: Wed, 31 Aug 2022 13:06:55 -0400 Subject: [PATCH 12/17] PLAT-4955 Terraform EKS module, Cleanup --- example/README.md | 7 +- example/main.tf | 12 ++-- example/variables.tf | 29 +++++++++ main.tf | 7 +- submodules/bastion/main.tf | 1 - submodules/bastion/variables.tf | 5 -- submodules/bastion/versions.tf | 1 - submodules/k8s/README.md | 1 - submodules/k8s/main.tf | 2 - submodules/k8s/variables.tf | 10 --- submodules/network/internet-gateway.tf | 2 - submodules/network/main.tf | 86 +++++++++++++++++++++++++ submodules/network/versions.tf | 1 - submodules/network/vpc.tf | 88 -------------------------- submodules/subnets-cidr/variables.tf | 13 ---- variables.tf | 1 - 16 files changed, 126 insertions(+), 140 deletions(-) delete mode 100644 submodules/network/vpc.tf diff --git a/example/README.md b/example/README.md index e887973c..5683c950 100644 --- a/example/README.md +++ b/example/README.md @@ -23,7 +23,12 @@ No resources. ## Inputs -No inputs. +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [deploy\_id](#input\_deploy\_id) | Domino Deployment ID. | `string` | `"domino-eks-example"` | no | +| [k8s\_version](#input\_k8s\_version) | EKS cluster k8s version. | `string` | `"1.23"` | no | +| [region](#input\_region) | AWS region for the deployment | `string` | n/a | yes | +| [tags](#input\_tags) | Deployment tags. | `map(string)` |
{
"deploy_id": "domino-eks-example",
"deploy_tag": "domino-eks-example",
"deploy_type": "terraform-aws-eks",
"domino-deploy-id": "domino-eks-example"
}
| no | ## Outputs diff --git a/example/main.tf b/example/main.tf index 373ea005..b059dde3 100755 --- a/example/main.tf +++ b/example/main.tf @@ -1,17 +1,13 @@ module "domino_eks" { source = "../../terraform-aws-eks" - deploy_id = "mhtfeks" - region = "us-west-2" + deploy_id = var.deploy_id + region = var.region number_of_azs = 2 + k8s_version = var.k8s_version route53_hosted_zone_name = "infra-team-sandbox.domino.tech" eks_master_role_names = ["okta-poweruser", "okta-fulladmin"] s3_force_destroy_on_deletion = true create_bastion = true ssh_pvt_key_path = "domino.pem" - tags = { - deploy_id = "domino-eks" - deploy_tag = "domino-eks" - deploy_type = "terraform-aws-eks" - domino-deploy-id = "domino-eks" - } + tags = var.tags } diff --git a/example/variables.tf b/example/variables.tf index e69de29b..b96e4fe1 100644 --- a/example/variables.tf +++ b/example/variables.tf @@ -0,0 +1,29 @@ +variable "deploy_id" { + type = string + description = "Domino Deployment ID." + default = "domino-eks-example" +} + + +variable "region" { + type = string + description = "AWS region for the deployment" +} + + +variable "tags" { + type = map(string) + description = "Deployment tags." + default = { + deploy_id = "domino-eks-example" + deploy_tag = "domino-eks-example" + deploy_type = "terraform-aws-eks" + domino-deploy-id = "domino-eks-example" + } +} + +variable "k8s_version" { + type = string + description = "EKS cluster k8s version." + default = "1.23" +} diff --git a/main.tf b/main.tf index 734036a2..549db1f6 100644 --- a/main.tf +++ b/main.tf @@ -5,8 +5,7 @@ data "aws_ec2_instance_type_offerings" "nodes" { for_each = merge(var.default_node_groups, var.additional_node_groups) filter { - name = "instance-type" - # values = toset([for i in var.default_node_groups : i.instance_type]) + name = "instance-type" values = [each.value.instance_type] } @@ -38,7 +37,6 @@ locals { offered_azs = setintersection(local.zone_intersection_instance_offerings, toset(local.az_names)) available_azs_data = zipmap(data.aws_availability_zones.available.names, data.aws_availability_zones.available.zone_ids) # Getting the required azs name and id. - bastion_user = "ec2-user" working_dir = path.cwd ssh_pvt_key_path = "${local.working_dir}/${var.ssh_pvt_key_path}" @@ -98,7 +96,6 @@ locals { private_subnets = module.network.private_subnets } - module "storage" { source = "./submodules/storage" deploy_id = var.deploy_id @@ -141,10 +138,8 @@ module "eks" { s3_buckets = module.storage.s3_buckets } - module "k8s_setup" { source = "./submodules/k8s" - deploy_id = var.deploy_id ssh_pvt_key_path = abspath(local.ssh_pvt_key_path) bastion_user = local.bastion_user bastion_public_ip = try(module.bastion[0].public_ip, "") diff --git a/submodules/bastion/main.tf b/submodules/bastion/main.tf index 7fd51683..192d7e17 100644 --- a/submodules/bastion/main.tf +++ b/submodules/bastion/main.tf @@ -6,7 +6,6 @@ locals { aws_account_id = data.aws_caller_identity.aws_account.account_id } - resource "aws_security_group" "bastion" { name = "${var.deploy_id}-bastion" description = "Bastion security group" diff --git a/submodules/bastion/variables.tf b/submodules/bastion/variables.tf index 9758a070..03e1b557 100644 --- a/submodules/bastion/variables.tf +++ b/submodules/bastion/variables.tf @@ -1,11 +1,6 @@ variable "deploy_id" { type = string description = "Domino Deployment ID" - - validation { - condition = can(regex("^[a-z-0-9]{3,32}$", var.deploy_id)) - error_message = "Argument deploy_id must: start with a letter, contain lowercase alphanumeric characters(can contain hyphens[-]) with length between 3 and 32 characters." - } } variable "bastion_ami_id" { diff --git a/submodules/bastion/versions.tf b/submodules/bastion/versions.tf index ca6fac6f..b4912520 100644 --- a/submodules/bastion/versions.tf +++ b/submodules/bastion/versions.tf @@ -1,5 +1,4 @@ terraform { - required_version = ">= 1.0" required_providers { aws = { diff --git a/submodules/k8s/README.md b/submodules/k8s/README.md index ff5e65fd..266f4285 100644 --- a/submodules/k8s/README.md +++ b/submodules/k8s/README.md @@ -37,7 +37,6 @@ No modules. | [bastion\_public\_ip](#input\_bastion\_public\_ip) | Bastion host public ip. | `string` | n/a | yes | | [bastion\_user](#input\_bastion\_user) | ec2 instance user. | `string` | `"ec2-user"` | no | | [calico\_version](#input\_calico\_version) | Calico operator version. | `string` | `"v1.11.0"` | no | -| [deploy\_id](#input\_deploy\_id) | Domino Deployment ID | `string` | n/a | yes | | [eks\_master\_role\_names](#input\_eks\_master\_role\_names) | IAM role names to be added as masters in eks. | `list(string)` | `[]` | no | | [k8s\_cluster\_endpoint](#input\_k8s\_cluster\_endpoint) | EKS cluster API endpoint. | `string` | n/a | yes | | [kubeconfig\_path](#input\_kubeconfig\_path) | Kubeconfig filename. | `string` | `"kubeconfig"` | no | diff --git a/submodules/k8s/main.tf b/submodules/k8s/main.tf index 0cca583d..f9c82843 100644 --- a/submodules/k8s/main.tf +++ b/submodules/k8s/main.tf @@ -1,5 +1,3 @@ - - data "aws_iam_role" "eks_master_roles" { for_each = toset(var.eks_master_role_names) name = each.key diff --git a/submodules/k8s/variables.tf b/submodules/k8s/variables.tf index c8de6067..54adddd9 100755 --- a/submodules/k8s/variables.tf +++ b/submodules/k8s/variables.tf @@ -1,13 +1,3 @@ -variable "deploy_id" { - type = string - description = "Domino Deployment ID" - - validation { - condition = can(regex("^[a-z-0-9]{3,32}$", var.deploy_id)) - error_message = "Argument deploy_id must: start with a letter, contain lowercase alphanumeric characters(can contain hyphens[-]) with length between 3 and 32 characters." - } -} - variable "kubeconfig_path" { type = string description = "Kubeconfig filename." diff --git a/submodules/network/internet-gateway.tf b/submodules/network/internet-gateway.tf index baddeb78..5a93d8f9 100644 --- a/submodules/network/internet-gateway.tf +++ b/submodules/network/internet-gateway.tf @@ -5,13 +5,11 @@ resource "aws_internet_gateway" "igw" { } } - resource "aws_internet_gateway_attachment" "this" { internet_gateway_id = aws_internet_gateway.igw.id vpc_id = local.vpc_id } - resource "aws_eip" "public" { for_each = { for sb in var.public_subnets : sb.name => sb } network_border_group = var.region diff --git a/submodules/network/main.tf b/submodules/network/main.tf index e69de29b..e639016d 100644 --- a/submodules/network/main.tf +++ b/submodules/network/main.tf @@ -0,0 +1,86 @@ +data "aws_vpc" "this" { + count = var.vpc_id != "" ? 1 : 0 + state = "available" + id = var.vpc_id +} + +resource "aws_vpc" "this" { + count = var.vpc_id != "" ? 0 : 1 + assign_generated_ipv6_cidr_block = false + cidr_block = var.base_cidr_block + enable_dns_hostnames = true + enable_dns_support = true + tags = { + "Name" = var.deploy_id + } +} + +locals { + vpc_id = var.vpc_id != "" ? data.aws_vpc.this[0].id : aws_vpc.this[0].id +} + +resource "aws_vpc_endpoint" "s3" { + vpc_id = local.vpc_id + service_name = "com.amazonaws.${var.region}.s3" + + route_table_ids = concat( + [for s in aws_route_table.public : s.id], + [for s in aws_route_table.private : s.id] + ) + + tags = { + "Name" = "${var.deploy_id}-s3" + } +} + +data "aws_network_acls" "default" { + vpc_id = local.vpc_id + + filter { + name = "default" + values = ["true"] + } +} + +resource "aws_default_network_acl" "default" { + default_network_acl_id = one(data.aws_network_acls.default.ids) + + egress { + action = "allow" + cidr_block = "0.0.0.0/0" + from_port = "0" + icmp_code = "0" + icmp_type = "0" + protocol = "-1" + rule_no = "100" + to_port = "0" + } + + ingress { + action = "allow" + cidr_block = "0.0.0.0/0" + from_port = "0" + icmp_code = "0" + icmp_type = "0" + protocol = "-1" + rule_no = "100" + to_port = "0" + } + + subnet_ids = concat( + [for s in aws_subnet.public : s.id], + [for s in aws_subnet.private : s.id] + ) + + lifecycle { + ignore_changes = [subnet_ids] + } +} + +resource "aws_flow_log" "this" { + log_destination = var.monitoring_s3_bucket_arn + vpc_id = local.vpc_id + max_aggregation_interval = 600 + log_destination_type = "s3" + traffic_type = "REJECT" +} diff --git a/submodules/network/versions.tf b/submodules/network/versions.tf index ca6fac6f..b4912520 100644 --- a/submodules/network/versions.tf +++ b/submodules/network/versions.tf @@ -1,5 +1,4 @@ terraform { - required_version = ">= 1.0" required_providers { aws = { diff --git a/submodules/network/vpc.tf b/submodules/network/vpc.tf deleted file mode 100644 index 9eb5a80e..00000000 --- a/submodules/network/vpc.tf +++ /dev/null @@ -1,88 +0,0 @@ - -## Bring your own VPC -data "aws_vpc" "this" { - count = var.vpc_id != "" ? 1 : 0 - state = "available" - id = var.vpc_id -} - -resource "aws_vpc" "this" { - count = var.vpc_id != "" ? 0 : 1 - assign_generated_ipv6_cidr_block = false - cidr_block = var.base_cidr_block - enable_dns_hostnames = true - enable_dns_support = true - tags = { - "Name" = var.deploy_id - } -} - -locals { - vpc_id = var.vpc_id != "" ? data.aws_vpc.this[0].id : aws_vpc.this[0].id -} - -resource "aws_vpc_endpoint" "s3" { - vpc_id = local.vpc_id - service_name = "com.amazonaws.${var.region}.s3" - - route_table_ids = concat( - [for s in aws_route_table.public : s.id], - [for s in aws_route_table.private : s.id] - ) - - tags = { - "Name" = "${var.deploy_id}-s3" - } -} - -data "aws_network_acls" "default" { - vpc_id = local.vpc_id - - filter { - name = "default" - values = ["true"] - } -} - -resource "aws_default_network_acl" "default" { - default_network_acl_id = one(data.aws_network_acls.default.ids) - - egress { - action = "allow" - cidr_block = "0.0.0.0/0" - from_port = "0" - icmp_code = "0" - icmp_type = "0" - protocol = "-1" - rule_no = "100" - to_port = "0" - } - - ingress { - action = "allow" - cidr_block = "0.0.0.0/0" - from_port = "0" - icmp_code = "0" - icmp_type = "0" - protocol = "-1" - rule_no = "100" - to_port = "0" - } - - subnet_ids = concat( - [for s in aws_subnet.public : s.id], - [for s in aws_subnet.private : s.id] - ) - - lifecycle { - ignore_changes = [subnet_ids] - } -} - -resource "aws_flow_log" "this" { - log_destination = var.monitoring_s3_bucket_arn - vpc_id = local.vpc_id - max_aggregation_interval = 600 - log_destination_type = "s3" - traffic_type = "REJECT" -} diff --git a/submodules/subnets-cidr/variables.tf b/submodules/subnets-cidr/variables.tf index bed5210b..88c59945 100644 --- a/submodules/subnets-cidr/variables.tf +++ b/submodules/subnets-cidr/variables.tf @@ -19,19 +19,6 @@ variable "availability_zones" { } } -# variable "pod_base_cidr_block" { -# type = string -# default = "100.164.0.0/16" -# description = "CIDR block to serve the pods subnets" -# validation { -# condition = ( -# try(cidrhost(var.pod_base_cidr_block, 0), null) == regex("^(.*)/", var.pod_base_cidr_block)[0] && -# try(cidrnetmask(var.pod_base_cidr_block), null) == "255.255.0.0" -# ) -# error_message = "Argument pod_base_cidr_block must be a valid CIDR block." -# } -# } - variable "base_cidr_block" { type = string default = "10.0.0.0/16" diff --git a/variables.tf b/variables.tf index 35c98fc1..cfc22ab4 100755 --- a/variables.tf +++ b/variables.tf @@ -24,7 +24,6 @@ variable "number_of_azs" { } } - variable "availability_zones" { type = list(string) description = < Date: Wed, 31 Aug 2022 14:05:07 -0400 Subject: [PATCH 13/17] PLAT-4955 Terraform EKS module, Add tf managed cloudwatch log group to enforce tagging --- example/README.md | 6 +++--- example/variables.tf | 9 +++++---- submodules/eks/README.md | 1 + submodules/eks/cluster.tf | 9 +++++++-- 4 files changed, 16 insertions(+), 9 deletions(-) diff --git a/example/README.md b/example/README.md index 5683c950..2ef2cae2 100644 --- a/example/README.md +++ b/example/README.md @@ -25,10 +25,10 @@ No resources. | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| [deploy\_id](#input\_deploy\_id) | Domino Deployment ID. | `string` | `"domino-eks-example"` | no | +| [deploy\_id](#input\_deploy\_id) | Domino Deployment ID. | `string` | `"mhtfeks"` | no | | [k8s\_version](#input\_k8s\_version) | EKS cluster k8s version. | `string` | `"1.23"` | no | -| [region](#input\_region) | AWS region for the deployment | `string` | n/a | yes | -| [tags](#input\_tags) | Deployment tags. | `map(string)` |
{
"deploy_id": "domino-eks-example",
"deploy_tag": "domino-eks-example",
"deploy_type": "terraform-aws-eks",
"domino-deploy-id": "domino-eks-example"
}
| no | +| [region](#input\_region) | AWS region for the deployment | `string` | `"us-west-2"` | no | +| [tags](#input\_tags) | Deployment tags. | `map(string)` |
{
"deploy_id": "domino-eks",
"deploy_tag": "domino-eks",
"deploy_type": "terraform-aws-eks",
"domino-deploy-id": "domino-eks"
}
| no | ## Outputs diff --git a/example/variables.tf b/example/variables.tf index b96e4fe1..584b7822 100644 --- a/example/variables.tf +++ b/example/variables.tf @@ -1,13 +1,14 @@ variable "deploy_id" { type = string description = "Domino Deployment ID." - default = "domino-eks-example" + default = "mhtfeks" } variable "region" { type = string description = "AWS region for the deployment" + default = "us-west-2" } @@ -15,10 +16,10 @@ variable "tags" { type = map(string) description = "Deployment tags." default = { - deploy_id = "domino-eks-example" - deploy_tag = "domino-eks-example" + deploy_id = "domino-eks" + deploy_tag = "domino-eks" deploy_type = "terraform-aws-eks" - domino-deploy-id = "domino-eks-example" + domino-deploy-id = "domino-eks" } } diff --git a/submodules/eks/README.md b/submodules/eks/README.md index 24cfdeee..de436d1f 100644 --- a/submodules/eks/README.md +++ b/submodules/eks/README.md @@ -24,6 +24,7 @@ No modules. | Name | Type | |------|------| +| [aws_cloudwatch_log_group.eks_cluster](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group) | resource | | [aws_eks_addon.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eks_addon) | resource | | [aws_eks_cluster.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eks_cluster) | resource | | [aws_eks_node_group.additional_node_groups](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eks_node_group) | resource | diff --git a/submodules/eks/cluster.tf b/submodules/eks/cluster.tf index 2e583983..b1c5ee70 100755 --- a/submodules/eks/cluster.tf +++ b/submodules/eks/cluster.tf @@ -65,7 +65,9 @@ resource "aws_security_group_rule" "eks_cluster" { source_security_group_id = try(each.value.source_security_group_id, null) } -## END - EKS security-group +resource "aws_cloudwatch_log_group" "eks_cluster" { + name = "/aws/eks/${local.eks_cluster_name}/cluster" +} ## EKS cluster resource "aws_eks_cluster" "this" { @@ -93,7 +95,10 @@ resource "aws_eks_cluster" "this" { security_group_ids = [aws_security_group.eks_cluster.id] subnet_ids = [for sb in var.private_subnets : sb.id] } - depends_on = [aws_iam_role_policy_attachment.eks_cluster] + depends_on = [ + aws_iam_role_policy_attachment.eks_cluster, + aws_cloudwatch_log_group.eks_cluster + ] } resource "aws_eks_addon" "this" { From 4c92fa96fb369c633f5ad5e51b321692a671cdb5 Mon Sep 17 00:00:00 2001 From: Miguel Harmant Date: Wed, 31 Aug 2022 17:59:31 -0400 Subject: [PATCH 14/17] PLAT-4955 Terraform EKS module, Add toggle to create VPC endpoints for S3 --- README.md | 1 + example/main.tf | 1 + main.tf | 2 ++ submodules/network/README.md | 1 + submodules/network/main.tf | 6 ++++-- submodules/network/variables.tf | 6 ++++++ variables.tf | 6 ++++++ 7 files changed, 21 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index f4a5ee66..650ffc36 100644 --- a/README.md +++ b/README.md @@ -115,6 +115,7 @@ aws s3 rb s3://"${AWS_TERRAFORM_REMOTE_STATE_BUCKET}" --force | [deploy\_id](#input\_deploy\_id) | Domino Deployment ID. | `string` | `"domino-eks"` | no | | [efs\_access\_point\_path](#input\_efs\_access\_point\_path) | Filesystem path for efs. | `string` | `"/domino"` | no | | [eks\_master\_role\_names](#input\_eks\_master\_role\_names) | IAM role names to be added as masters in eks. | `list(string)` | `[]` | no | +| [enable\_vpc\_endpoints\_s3](#input\_enable\_vpc\_endpoints\_s3) | Enable VPC endpoints for S3 service. This is intented for mission critical, highly available deployments | `bool` | `false` | no | | [k8s\_version](#input\_k8s\_version) | EKS cluster k8s version. | `string` | `"1.23"` | no | | [number\_of\_azs](#input\_number\_of\_azs) | Number of AZ to distribute the deployment, EKS needs at least 2. | `number` | `3` | no | | [private\_cidr\_network\_bits](#input\_private\_cidr\_network\_bits) | Number of network bits to allocate to the private subnet. i.e /19 -> 8,192 IPs. | `number` | `19` | no | diff --git a/example/main.tf b/example/main.tf index b059dde3..2382d77b 100755 --- a/example/main.tf +++ b/example/main.tf @@ -9,5 +9,6 @@ module "domino_eks" { s3_force_destroy_on_deletion = true create_bastion = true ssh_pvt_key_path = "domino.pem" + enable_vpc_endpoints_s3 = false tags = var.tags } diff --git a/main.tf b/main.tf index 549db1f6..209d6395 100644 --- a/main.tf +++ b/main.tf @@ -88,7 +88,9 @@ module "network" { deploy_id = var.deploy_id base_cidr_block = var.base_cidr_block vpc_id = var.vpc_id + enable_vpc_endpoints_s3 = var.enable_vpc_endpoints_s3 monitoring_s3_bucket_arn = module.storage.monitoring_s3_bucket_arn + } locals { diff --git a/submodules/network/README.md b/submodules/network/README.md index f16b4819..20820627 100644 --- a/submodules/network/README.md +++ b/submodules/network/README.md @@ -45,6 +45,7 @@ No modules. |------|-------------|------|---------|:--------:| | [base\_cidr\_block](#input\_base\_cidr\_block) | CIDR block to serve the main private and public subnets | `string` | n/a | yes | | [deploy\_id](#input\_deploy\_id) | Domino Deployment ID | `string` | `""` | no | +| [enable\_vpc\_endpoints\_s3](#input\_enable\_vpc\_endpoints\_s3) | Enable VPC endpoints for S3 service. This is intented for mission critical, highly available deployments | `bool` | `false` | no | | [monitoring\_s3\_bucket\_arn](#input\_monitoring\_s3\_bucket\_arn) | Monitoring bucket for vpc flow logging | `string` | n/a | yes | | [private\_subnets](#input\_private\_subnets) | Private subnets object |
list(object({
cidr_block = string
name = string
type = string
zone = string
zone_id = string
}))
| n/a | yes | | [public\_subnets](#input\_public\_subnets) | Public subnets object |
list(object({
cidr_block = string
name = string
type = string
zone = string
zone_id = string
}))
| n/a | yes | diff --git a/submodules/network/main.tf b/submodules/network/main.tf index e639016d..9739fa14 100644 --- a/submodules/network/main.tf +++ b/submodules/network/main.tf @@ -20,8 +20,10 @@ locals { } resource "aws_vpc_endpoint" "s3" { - vpc_id = local.vpc_id - service_name = "com.amazonaws.${var.region}.s3" + count = var.enable_vpc_endpoints_s3 ? 1 : 0 + vpc_id = local.vpc_id + service_name = "com.amazonaws.${var.region}.s3" + vpc_endpoint_type = "Gateway" route_table_ids = concat( [for s in aws_route_table.public : s.id], diff --git a/submodules/network/variables.tf b/submodules/network/variables.tf index 7f17b89a..9ab7c90b 100644 --- a/submodules/network/variables.tf +++ b/submodules/network/variables.tf @@ -58,3 +58,9 @@ variable "monitoring_s3_bucket_arn" { type = string description = "Monitoring bucket for vpc flow logging" } + +variable "enable_vpc_endpoints_s3" { + description = "Enable VPC endpoints for S3 service. This is intented for mission critical, highly available deployments" + type = bool + default = false +} diff --git a/variables.tf b/variables.tf index cfc22ab4..f2c56cce 100755 --- a/variables.tf +++ b/variables.tf @@ -221,3 +221,9 @@ variable "s3_force_destroy_on_deletion" { type = bool default = false } + +variable "enable_vpc_endpoints_s3" { + description = "Enable VPC endpoints for S3 service. This is intented for mission critical, highly available deployments" + type = bool + default = false +} From 517ecf3b8a63cec2329d54fc97d749f0eed32d99 Mon Sep 17 00:00:00 2001 From: Miguel Harmant Date: Tue, 6 Sep 2022 14:23:40 -0400 Subject: [PATCH 15/17] PLAT-93 enhance deploy_id variable restrictions --- example/README.md | 4 ++-- example/variables.tf | 8 ++++---- variables.tf | 11 +++++++++-- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/example/README.md b/example/README.md index 2ef2cae2..2abbd843 100644 --- a/example/README.md +++ b/example/README.md @@ -25,10 +25,10 @@ No resources. | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| [deploy\_id](#input\_deploy\_id) | Domino Deployment ID. | `string` | `"mhtfeks"` | no | +| [deploy\_id](#input\_deploy\_id) | Domino Deployment ID. | `string` | `"domino-eks-test"` | no | | [k8s\_version](#input\_k8s\_version) | EKS cluster k8s version. | `string` | `"1.23"` | no | | [region](#input\_region) | AWS region for the deployment | `string` | `"us-west-2"` | no | -| [tags](#input\_tags) | Deployment tags. | `map(string)` |
{
"deploy_id": "domino-eks",
"deploy_tag": "domino-eks",
"deploy_type": "terraform-aws-eks",
"domino-deploy-id": "domino-eks"
}
| no | +| [tags](#input\_tags) | Deployment tags. | `map(string)` |
{
"deploy_id": "domino-eks-test",
"deploy_tag": "domino-eks-test",
"deploy_type": "terraform-aws-eks",
"domino-deploy-id": "domino-eks-test"
}
| no | ## Outputs diff --git a/example/variables.tf b/example/variables.tf index 584b7822..2914ea93 100644 --- a/example/variables.tf +++ b/example/variables.tf @@ -1,7 +1,7 @@ variable "deploy_id" { type = string description = "Domino Deployment ID." - default = "mhtfeks" + default = "domino-eks-test" } @@ -16,10 +16,10 @@ variable "tags" { type = map(string) description = "Deployment tags." default = { - deploy_id = "domino-eks" - deploy_tag = "domino-eks" + deploy_id = "domino-eks-test" + deploy_tag = "domino-eks-test" deploy_type = "terraform-aws-eks" - domino-deploy-id = "domino-eks" + domino-deploy-id = "domino-eks-test" } } diff --git a/variables.tf b/variables.tf index f2c56cce..70aae17b 100755 --- a/variables.tf +++ b/variables.tf @@ -2,10 +2,17 @@ variable "deploy_id" { type = string description = "Domino Deployment ID." default = "domino-eks" + nullable = false validation { - condition = can(regex("^[a-z-0-9]{3,32}$", var.deploy_id)) - error_message = "Argument deploy_id must: start with a letter, contain lowercase alphanumeric characters(can contain hyphens[-]) with length between 3 and 32 characters." + condition = length(var.deploy_id) >= 3 && length(var.deploy_id) <= 32 && can(regex("^[a-z]([-a-z0-9]*[a-z0-9])$", var.deploy_id)) + error_message = < Date: Tue, 6 Sep 2022 14:24:33 -0400 Subject: [PATCH 16/17] Rename tests folder --- example/README.md | 38 -------------------------------------- example/main.tf | 14 -------------- example/outputs.tf | 4 ---- example/variables.tf | 30 ------------------------------ example/versions.tf | 3 --- 5 files changed, 89 deletions(-) delete mode 100644 example/README.md delete mode 100755 example/main.tf delete mode 100644 example/outputs.tf delete mode 100644 example/variables.tf delete mode 100644 example/versions.tf diff --git a/example/README.md b/example/README.md deleted file mode 100644 index 2abbd843..00000000 --- a/example/README.md +++ /dev/null @@ -1,38 +0,0 @@ -# example - - -## Requirements - -| Name | Version | -|------|---------| -| [terraform](#requirement\_terraform) | >= 1.2.0 | - -## Providers - -No providers. - -## Modules - -| Name | Source | Version | -|------|--------|---------| -| [domino\_eks](#module\_domino\_eks) | ../../terraform-aws-eks | n/a | - -## Resources - -No resources. - -## Inputs - -| Name | Description | Type | Default | Required | -|------|-------------|------|---------|:--------:| -| [deploy\_id](#input\_deploy\_id) | Domino Deployment ID. | `string` | `"domino-eks-test"` | no | -| [k8s\_version](#input\_k8s\_version) | EKS cluster k8s version. | `string` | `"1.23"` | no | -| [region](#input\_region) | AWS region for the deployment | `string` | `"us-west-2"` | no | -| [tags](#input\_tags) | Deployment tags. | `map(string)` |
{
"deploy_id": "domino-eks-test",
"deploy_tag": "domino-eks-test",
"deploy_type": "terraform-aws-eks",
"domino-deploy-id": "domino-eks-test"
}
| no | - -## Outputs - -| Name | Description | -|------|-------------| -| [domino\_eks](#output\_domino\_eks) | EKS module outputs | - diff --git a/example/main.tf b/example/main.tf deleted file mode 100755 index 2382d77b..00000000 --- a/example/main.tf +++ /dev/null @@ -1,14 +0,0 @@ -module "domino_eks" { - source = "../../terraform-aws-eks" - deploy_id = var.deploy_id - region = var.region - number_of_azs = 2 - k8s_version = var.k8s_version - route53_hosted_zone_name = "infra-team-sandbox.domino.tech" - eks_master_role_names = ["okta-poweruser", "okta-fulladmin"] - s3_force_destroy_on_deletion = true - create_bastion = true - ssh_pvt_key_path = "domino.pem" - enable_vpc_endpoints_s3 = false - tags = var.tags -} diff --git a/example/outputs.tf b/example/outputs.tf deleted file mode 100644 index b14d2084..00000000 --- a/example/outputs.tf +++ /dev/null @@ -1,4 +0,0 @@ -output "domino_eks" { - description = "EKS module outputs" - value = module.domino_eks -} diff --git a/example/variables.tf b/example/variables.tf deleted file mode 100644 index 2914ea93..00000000 --- a/example/variables.tf +++ /dev/null @@ -1,30 +0,0 @@ -variable "deploy_id" { - type = string - description = "Domino Deployment ID." - default = "domino-eks-test" -} - - -variable "region" { - type = string - description = "AWS region for the deployment" - default = "us-west-2" -} - - -variable "tags" { - type = map(string) - description = "Deployment tags." - default = { - deploy_id = "domino-eks-test" - deploy_tag = "domino-eks-test" - deploy_type = "terraform-aws-eks" - domino-deploy-id = "domino-eks-test" - } -} - -variable "k8s_version" { - type = string - description = "EKS cluster k8s version." - default = "1.23" -} diff --git a/example/versions.tf b/example/versions.tf deleted file mode 100644 index 3e6ba018..00000000 --- a/example/versions.tf +++ /dev/null @@ -1,3 +0,0 @@ -terraform { - required_version = ">= 1.2.0" -} From 83096cd3207d959dbd53d793bb83f764f0eedac6 Mon Sep 17 00:00:00 2001 From: Miguel Harmant Date: Tue, 6 Sep 2022 14:24:49 -0400 Subject: [PATCH 17/17] Rename tests folder --- tests/README.md | 38 ++++++++++++++++++++++++++++++++++++++ tests/main.tf | 14 ++++++++++++++ tests/outputs.tf | 4 ++++ tests/variables.tf | 30 ++++++++++++++++++++++++++++++ tests/versions.tf | 3 +++ 5 files changed, 89 insertions(+) create mode 100644 tests/README.md create mode 100755 tests/main.tf create mode 100644 tests/outputs.tf create mode 100644 tests/variables.tf create mode 100644 tests/versions.tf diff --git a/tests/README.md b/tests/README.md new file mode 100644 index 00000000..2abbd843 --- /dev/null +++ b/tests/README.md @@ -0,0 +1,38 @@ +# example + + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.2.0 | + +## Providers + +No providers. + +## Modules + +| Name | Source | Version | +|------|--------|---------| +| [domino\_eks](#module\_domino\_eks) | ../../terraform-aws-eks | n/a | + +## Resources + +No resources. + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [deploy\_id](#input\_deploy\_id) | Domino Deployment ID. | `string` | `"domino-eks-test"` | no | +| [k8s\_version](#input\_k8s\_version) | EKS cluster k8s version. | `string` | `"1.23"` | no | +| [region](#input\_region) | AWS region for the deployment | `string` | `"us-west-2"` | no | +| [tags](#input\_tags) | Deployment tags. | `map(string)` |
{
"deploy_id": "domino-eks-test",
"deploy_tag": "domino-eks-test",
"deploy_type": "terraform-aws-eks",
"domino-deploy-id": "domino-eks-test"
}
| no | + +## Outputs + +| Name | Description | +|------|-------------| +| [domino\_eks](#output\_domino\_eks) | EKS module outputs | + diff --git a/tests/main.tf b/tests/main.tf new file mode 100755 index 00000000..2382d77b --- /dev/null +++ b/tests/main.tf @@ -0,0 +1,14 @@ +module "domino_eks" { + source = "../../terraform-aws-eks" + deploy_id = var.deploy_id + region = var.region + number_of_azs = 2 + k8s_version = var.k8s_version + route53_hosted_zone_name = "infra-team-sandbox.domino.tech" + eks_master_role_names = ["okta-poweruser", "okta-fulladmin"] + s3_force_destroy_on_deletion = true + create_bastion = true + ssh_pvt_key_path = "domino.pem" + enable_vpc_endpoints_s3 = false + tags = var.tags +} diff --git a/tests/outputs.tf b/tests/outputs.tf new file mode 100644 index 00000000..b14d2084 --- /dev/null +++ b/tests/outputs.tf @@ -0,0 +1,4 @@ +output "domino_eks" { + description = "EKS module outputs" + value = module.domino_eks +} diff --git a/tests/variables.tf b/tests/variables.tf new file mode 100644 index 00000000..2914ea93 --- /dev/null +++ b/tests/variables.tf @@ -0,0 +1,30 @@ +variable "deploy_id" { + type = string + description = "Domino Deployment ID." + default = "domino-eks-test" +} + + +variable "region" { + type = string + description = "AWS region for the deployment" + default = "us-west-2" +} + + +variable "tags" { + type = map(string) + description = "Deployment tags." + default = { + deploy_id = "domino-eks-test" + deploy_tag = "domino-eks-test" + deploy_type = "terraform-aws-eks" + domino-deploy-id = "domino-eks-test" + } +} + +variable "k8s_version" { + type = string + description = "EKS cluster k8s version." + default = "1.23" +} diff --git a/tests/versions.tf b/tests/versions.tf new file mode 100644 index 00000000..3e6ba018 --- /dev/null +++ b/tests/versions.tf @@ -0,0 +1,3 @@ +terraform { + required_version = ">= 1.2.0" +}