From 477e450b8a18deae18de2af7708bce379f5dafa6 Mon Sep 17 00:00:00 2001 From: Alex Petre Date: Wed, 30 Apr 2025 10:02:23 -0400 Subject: [PATCH 01/34] Initial Support for AWS EKS --- contexts/aws-example/blueprint.yaml | 130 +++++++++++ .../terraform/cluster/aws-eks.tfvars | 1 + .../aws-example/terraform/gitops/flux.tfvars | 1 + .../terraform/network/aws-vpc.tfvars | 1 + terraform/cluster/aws-eks/.terraform.lock.hcl | 64 +++++ terraform/cluster/aws-eks/main.tf | 221 ++++++++++++++++++ terraform/cluster/aws-eks/outputs.tf | 28 +++ .../cluster/aws-eks/templates/kubeconfig.tpl | 26 +++ terraform/cluster/aws-eks/variables.tf | 73 ++++++ terraform/network/aws-vpc/.terraform.lock.hcl | 25 ++ terraform/network/aws-vpc/main.tf | 181 ++++++++++++++ terraform/network/aws-vpc/outputs.tf | 23 ++ terraform/network/aws-vpc/variables.tf | 57 +++++ windsor.yaml | 10 +- 14 files changed, 840 insertions(+), 1 deletion(-) create mode 100644 contexts/aws-example/blueprint.yaml create mode 100644 contexts/aws-example/terraform/cluster/aws-eks.tfvars create mode 100644 contexts/aws-example/terraform/gitops/flux.tfvars create mode 100644 contexts/aws-example/terraform/network/aws-vpc.tfvars create mode 100644 terraform/cluster/aws-eks/.terraform.lock.hcl create mode 100644 terraform/cluster/aws-eks/main.tf create mode 100644 terraform/cluster/aws-eks/outputs.tf create mode 100644 terraform/cluster/aws-eks/templates/kubeconfig.tpl create mode 100644 terraform/cluster/aws-eks/variables.tf create mode 100644 terraform/network/aws-vpc/.terraform.lock.hcl create mode 100644 terraform/network/aws-vpc/main.tf create mode 100644 terraform/network/aws-vpc/outputs.tf create mode 100644 terraform/network/aws-vpc/variables.tf diff --git a/contexts/aws-example/blueprint.yaml b/contexts/aws-example/blueprint.yaml new file mode 100644 index 00000000..e40231c9 --- /dev/null +++ b/contexts/aws-example/blueprint.yaml @@ -0,0 +1,130 @@ +kind: Blueprint +apiVersion: blueprints.windsorcli.dev/v1alpha1 +metadata: + name: aws-example + description: This blueprint outlines resources in the aws-example context +repository: + url: github.com/windsorcli/core + ref: + branch: aws-eks + secretName: flux-system +sources: +- name: core + url: github.com/windsorcli/core + ref: + tag: v0.3.0 +terraform: +- path: network/aws-vpc +- path: cluster/aws-eks +- path: gitops/flux +kustomize: +- name: telemetry-base + path: telemetry/base + components: + - prometheus + - prometheus/flux +- name: telemetry-resources + path: telemetry/resources + dependsOn: + - telemetry-base + components: + - metrics-server + - prometheus + - prometheus/flux +- name: policy-base + path: policy/base + components: + - kyverno +- name: policy-resources + path: policy/resources + dependsOn: + - policy-base +# - name: csi +# path: csi +# source: core +# dependsOn: +# - policy-resources +# force: true +# components: +# - openebs +# - openebs/dynamic-localpv +# - name: lb-base +# path: lb/base +# source: core +# dependsOn: +# - policy-resources +# force: true +# components: +# - metallb +# - name: lb-resources +# path: lb/resources +# source: core +# dependsOn: +# - lb-base +# force: true +# components: +# - metallb/layer2 +- name: ingress-base + path: ingress/base + source: core + dependsOn: + - pki-resources + force: true + components: + - nginx + - nginx/loadbalancer + - nginx/coredns + - nginx/flux-webhook + - nginx/web +- name: pki-base + path: pki/base + source: core + dependsOn: + - policy-resources + force: true + components: + - cert-manager + - trust-manager +- name: pki-resources + path: pki/resources + source: core + dependsOn: + - pki-base + force: true + components: + - private-issuer/ca + - public-issuer/selfsigned +- name: dns + path: dns + source: core + dependsOn: + - ingress-base + - pki-base + force: true + components: + - coredns + - coredns/etcd + - external-dns + - external-dns/coredns + - external-dns/ingress +- name: gitops + path: gitops/flux + source: core + dependsOn: + - ingress-base + force: true + components: + - webhook +- name: observability + path: observability + source: core + dependsOn: + - csi + - ingress-base + components: + - grafana + - grafana/ingress + - grafana/prometheus + - grafana/node + - grafana/kubernetes + - grafana/flux diff --git a/contexts/aws-example/terraform/cluster/aws-eks.tfvars b/contexts/aws-example/terraform/cluster/aws-eks.tfvars new file mode 100644 index 00000000..84aa3876 --- /dev/null +++ b/contexts/aws-example/terraform/cluster/aws-eks.tfvars @@ -0,0 +1 @@ +// Managed by Windsor CLI: This file is partially managed by the windsor CLI. Your changes will not be overwritten. diff --git a/contexts/aws-example/terraform/gitops/flux.tfvars b/contexts/aws-example/terraform/gitops/flux.tfvars new file mode 100644 index 00000000..84aa3876 --- /dev/null +++ b/contexts/aws-example/terraform/gitops/flux.tfvars @@ -0,0 +1 @@ +// Managed by Windsor CLI: This file is partially managed by the windsor CLI. Your changes will not be overwritten. diff --git a/contexts/aws-example/terraform/network/aws-vpc.tfvars b/contexts/aws-example/terraform/network/aws-vpc.tfvars new file mode 100644 index 00000000..84aa3876 --- /dev/null +++ b/contexts/aws-example/terraform/network/aws-vpc.tfvars @@ -0,0 +1 @@ +// Managed by Windsor CLI: This file is partially managed by the windsor CLI. Your changes will not be overwritten. diff --git a/terraform/cluster/aws-eks/.terraform.lock.hcl b/terraform/cluster/aws-eks/.terraform.lock.hcl new file mode 100644 index 00000000..c980c876 --- /dev/null +++ b/terraform/cluster/aws-eks/.terraform.lock.hcl @@ -0,0 +1,64 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "registry.terraform.io/hashicorp/aws" { + version = "5.96.0" + constraints = "~> 5.0" + hashes = [ + "h1:a/VEUu6BGQSPlUAzbN+zqaDCdi0QGh/VzBgo2gCran0=", + "zh:3f7e734abb9d647c851f5cb987837d7c073c9cbf1f520a031027d827f93d3b68", + "zh:5ca9400360a803a11cf432ca203be9f09da8fff9c96110a83c9029102b18c9d5", + "zh:5d421f475d467af182a527b7a61d50105dc63394316edf1c775ef736f84b941c", + "zh:68f2328e7f3e7666835d6815b39b46b08954a91204f82a6f648c928a0b09a744", + "zh:6a4170e7e2764df2968d1df65efebda55273dfc36dc6741207afb5e4b7e85448", + "zh:73f2a15bee21f7c92a071e2520216d0a40041aca52c0f6682e540da8ffcfada4", + "zh:9843d6973aedfd4cbaafd7110420d0c4c1d7ef4a2eeff508294c3adcc3613145", + "zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425", + "zh:9d1abd6be717c42f2a6257ee227d3e9548c31f01c976ed7b32b2745a63659a67", + "zh:a70d642e323021d54a92f0daa81d096cb5067cb99ce116047a42eb1cb1d579a0", + "zh:b9a2b293208d5a0449275fae463319e0998c841e0bcd4014594a49ba54bb70d6", + "zh:ce0b0eb7ac24ff58c20efcb526c3f792a95be3617c795b45bbeea9f302903ae7", + "zh:dbbf98b3cd8003833c472bdb89321c17a9bbdc1b785e7e3d75f8af924ee5a0e4", + "zh:df86cf9311a4be8bb4a251196650653f97e01fbf5fe72deecc8f28a35a5352ae", + "zh:f92992881afd9339f3e539fcd90cfc1e9ed1356b5e760bbcc804314c3cd6837f", + ] +} + +provider "registry.terraform.io/hashicorp/kubernetes" { + version = "2.36.0" + constraints = "~> 2.23" + hashes = [ + "h1:94wlXkBzfXwyLVuJVhMdzK+VGjFnMjdmFkYhQ1RUFhI=", + "zh:07f38fcb7578984a3e2c8cf0397c880f6b3eb2a722a120a08a634a607ea495ca", + "zh:1adde61769c50dbb799d8bf8bfd5c8c504a37017dfd06c7820f82bcf44ca0d39", + "zh:39707f23ab58fd0e686967c0f973c0f5a39c14d6ccfc757f97c345fdd0cd4624", + "zh:4cc3dc2b5d06cc22d1c734f7162b0a8fdc61990ff9efb64e59412d65a7ccc92a", + "zh:8382dcb82ba7303715b5e67939e07dd1c8ecddbe01d12f39b82b2b7d7357e1d9", + "zh:88e8e4f90034186b8bfdea1b8d394621cbc46a064ff2418027e6dba6807d5227", + "zh:a6276a75ad170f76d88263fdb5f9558998bf3a3f7650d7bd3387b396410e59f3", + "zh:bc816c7e0606e5df98a0c7634b240bb0c8100c3107b8b17b554af702edc6a0c5", + "zh:cb2f31d58f37020e840af52755c18afd1f09a833c4903ac59270ab440fab57b7", + "zh:ee0d103b8d0089fb1918311683110b4492a9346f0471b136af46d3b019576b22", + "zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c", + "zh:f688b9ec761721e401f6859c19c083e3be20a650426f4747cd359cdc079d212a", + ] +} + +provider "registry.terraform.io/hashicorp/local" { + version = "2.5.2" + hashes = [ + "h1:IyFbOIO6mhikFNL/2h1iZJ6kyN3U00jgkpCLUCThAfE=", + "zh:136299545178ce281c56f36965bf91c35407c11897f7082b3b983d86cb79b511", + "zh:3b4486858aa9cb8163378722b642c57c529b6c64bfbfc9461d940a84cd66ebea", + "zh:4855ee628ead847741aa4f4fc9bed50cfdbf197f2912775dd9fe7bc43fa077c0", + "zh:4b8cd2583d1edcac4011caafe8afb7a95e8110a607a1d5fb87d921178074a69b", + "zh:52084ddaff8c8cd3f9e7bcb7ce4dc1eab00602912c96da43c29b4762dc376038", + "zh:71562d330d3f92d79b2952ffdda0dad167e952e46200c767dd30c6af8d7c0ed3", + "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", + "zh:805f81ade06ff68fa8b908d31892eaed5c180ae031c77ad35f82cb7a74b97cf4", + "zh:8b6b3ebeaaa8e38dd04e56996abe80db9be6f4c1df75ac3cccc77642899bd464", + "zh:ad07750576b99248037b897de71113cc19b1a8d0bc235eb99173cc83d0de3b1b", + "zh:b9f1c3bfadb74068f5c205292badb0661e17ac05eb23bfe8bd809691e4583d0e", + "zh:cc4cbcd67414fefb111c1bf7ab0bc4beb8c0b553d01719ad17de9a047adff4d1", + ] +} diff --git a/terraform/cluster/aws-eks/main.tf b/terraform/cluster/aws-eks/main.tf new file mode 100644 index 00000000..12aee3e8 --- /dev/null +++ b/terraform/cluster/aws-eks/main.tf @@ -0,0 +1,221 @@ +// Define the required Terraform version and providers +terraform { + required_version = ">=1.8" + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 5.0" + } + kubernetes = { + source = "hashicorp/kubernetes" + version = "~> 2.23" + } + } +} + +#----------------------------------------------------------------------------------------------------------------------- +# Data +#----------------------------------------------------------------------------------------------------------------------- + +data "aws_subnets" "private" { + filter { + name = "tag:Tier" + values = ["private"] + } + filter { + name = "vpc-id" + values = [var.vpc_id] + } +} + +data "aws_region" "current" {} + +#----------------------------------------------------------------------------------------------------------------------- +# EKS Cluster +#----------------------------------------------------------------------------------------------------------------------- + +resource "aws_eks_cluster" "this" { + name = var.cluster_name + role_arn = aws_iam_role.cluster.arn + version = var.kubernetes_version + + vpc_config { + subnet_ids = data.aws_subnets.private.ids + } + + depends_on = [ + aws_iam_role_policy_attachment.cluster_AmazonEKSClusterPolicy, + aws_iam_role_policy_attachment.cluster_AmazonEKSVPCResourceController, + ] +} + +#----------------------------------------------------------------------------------------------------------------------- +# IAM Roles +#----------------------------------------------------------------------------------------------------------------------- + +resource "aws_iam_role" "cluster" { + name = "${var.cluster_name}-cluster-role" + + assume_role_policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Action = "sts:AssumeRole" + Effect = "Allow" + Principal = { + Service = "eks.amazonaws.com" + } + }, + ] + }) +} + +resource "aws_iam_role_policy_attachment" "cluster_AmazonEKSClusterPolicy" { + policy_arn = "arn:aws:iam::aws:policy/AmazonEKSClusterPolicy" + role = aws_iam_role.cluster.name +} + +resource "aws_iam_role_policy_attachment" "cluster_AmazonEKSVPCResourceController" { + policy_arn = "arn:aws:iam::aws:policy/AmazonEKSVPCResourceController" + role = aws_iam_role.cluster.name +} + +resource "aws_iam_role" "node_group" { + name = "${var.cluster_name}-node-group-role" + + assume_role_policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Action = "sts:AssumeRole" + Effect = "Allow" + Principal = { + Service = "ec2.amazonaws.com" + } + }, + ] + }) +} + +resource "aws_iam_role_policy_attachment" "node_group_AmazonEKSWorkerNodePolicy" { + policy_arn = "arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy" + role = aws_iam_role.node_group.name +} + +resource "aws_iam_role_policy_attachment" "node_group_AmazonEKS_CNI_Policy" { + policy_arn = "arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy" + role = aws_iam_role.node_group.name +} + +resource "aws_iam_role_policy_attachment" "node_group_AmazonEC2ContainerRegistryReadOnly" { + policy_arn = "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly" + role = aws_iam_role.node_group.name +} + +#----------------------------------------------------------------------------------------------------------------------- +# Node Groups +#----------------------------------------------------------------------------------------------------------------------- + +resource "aws_eks_node_group" "this" { + for_each = var.node_groups + + cluster_name = aws_eks_cluster.this.name + node_group_name = each.key + node_role_arn = aws_iam_role.node_group.arn + subnet_ids = data.aws_subnets.private.ids + instance_types = each.value.instance_types + disk_size = each.value.disk_size + + scaling_config { + desired_size = each.value.desired_size + max_size = each.value.max_size + min_size = each.value.min_size + } + + dynamic "taint" { + for_each = each.value.taints + content { + key = taint.value.key + value = taint.value.value + effect = taint.value.effect + } + } + + labels = each.value.labels + + depends_on = [ + aws_iam_role_policy_attachment.node_group_AmazonEKSWorkerNodePolicy, + aws_iam_role_policy_attachment.node_group_AmazonEKS_CNI_Policy, + aws_iam_role_policy_attachment.node_group_AmazonEC2ContainerRegistryReadOnly, + ] +} + +#----------------------------------------------------------------------------------------------------------------------- +# Fargate Profile +#----------------------------------------------------------------------------------------------------------------------- + +resource "aws_iam_role" "fargate" { + name = "${var.cluster_name}-fargate-profile" + + assume_role_policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Action = "sts:AssumeRole" + Effect = "Allow" + Principal = { + Service = "eks-fargate-pods.amazonaws.com" + } + } + ] + }) +} + +resource "aws_iam_role_policy_attachment" "fargate_pod_execution_role_policy" { + policy_arn = "arn:aws:iam::aws:policy/AmazonEKSFargatePodExecutionRolePolicy" + role = aws_iam_role.fargate.name +} + +resource "aws_eks_fargate_profile" "this" { + for_each = var.fargate_profiles != null ? var.fargate_profiles : {} + + cluster_name = aws_eks_cluster.this.name + fargate_profile_name = each.key + pod_execution_role_arn = aws_iam_role.fargate.arn + subnet_ids = data.aws_subnets.private.ids + + dynamic "selector" { + for_each = each.value.selectors + content { + namespace = selector.value.namespace + labels = lookup(selector.value, "labels", null) + } + } + + tags = lookup(each.value, "tags", {}) +} + +#----------------------------------------------------------------------------------------------------------------------- +# Kubeconfig +#----------------------------------------------------------------------------------------------------------------------- + +locals { + kubeconfig_path = "${var.context_path}/.kube/config" +} + +resource "local_sensitive_file" "kubeconfig" { + count = local.kubeconfig_path != "" ? 1 : 0 + + content = templatefile("${path.module}/templates/kubeconfig.tpl", { + cluster_name = aws_eks_cluster.this.name + cluster_endpoint = aws_eks_cluster.this.endpoint + cluster_ca = aws_eks_cluster.this.certificate_authority[0].data + region = data.aws_region.current.name + }) + filename = local.kubeconfig_path + file_permission = "0600" + + lifecycle { + ignore_changes = [content] // Ignore changes to content to prevent unnecessary updates + } +} diff --git a/terraform/cluster/aws-eks/outputs.tf b/terraform/cluster/aws-eks/outputs.tf new file mode 100644 index 00000000..51b15a25 --- /dev/null +++ b/terraform/cluster/aws-eks/outputs.tf @@ -0,0 +1,28 @@ +#----------------------------------------------------------------------------------------------------------------------- +# Outputs +#----------------------------------------------------------------------------------------------------------------------- + +output "cluster_id" { + description = "The name/id of the EKS cluster." + value = aws_eks_cluster.this.id +} + +output "cluster_arn" { + description = "The Amazon Resource Name (ARN) of the cluster." + value = aws_eks_cluster.this.arn +} + +output "cluster_endpoint" { + description = "The endpoint for the Kubernetes API server." + value = aws_eks_cluster.this.endpoint +} + +output "cluster_security_group_id" { + description = "The security group ID attached to the EKS cluster." + value = aws_eks_cluster.this.vpc_config[0].cluster_security_group_id +} + +output "kubeconfig_certificate_authority_data" { + description = "The base64 encoded certificate data required to communicate with the cluster." + value = aws_eks_cluster.this.certificate_authority[0].data +} diff --git a/terraform/cluster/aws-eks/templates/kubeconfig.tpl b/terraform/cluster/aws-eks/templates/kubeconfig.tpl new file mode 100644 index 00000000..9354987d --- /dev/null +++ b/terraform/cluster/aws-eks/templates/kubeconfig.tpl @@ -0,0 +1,26 @@ +apiVersion: v1 +kind: Config +clusters: +- name: ${cluster_name} + cluster: + server: ${cluster_endpoint} + certificate-authority-data: ${cluster_ca} +contexts: +- name: ${cluster_name} + context: + cluster: ${cluster_name} + user: ${cluster_name} +current-context: ${cluster_name} +users: +- name: ${cluster_name} + user: + exec: + apiVersion: client.authentication.k8s.io/v1beta1 + command: aws + args: + - eks + - get-token + - --cluster-name + - ${cluster_name} + - --region + - ${region} diff --git a/terraform/cluster/aws-eks/variables.tf b/terraform/cluster/aws-eks/variables.tf new file mode 100644 index 00000000..ad6af2c7 --- /dev/null +++ b/terraform/cluster/aws-eks/variables.tf @@ -0,0 +1,73 @@ + +#----------------------------------------------------------------------------------------------------------------------- +# Variables +#----------------------------------------------------------------------------------------------------------------------- + +variable "context_path" { + type = string + description = "The path to the context folder, where kubeconfig is stored" + default = "" +} + +variable "cluster_name" { + description = "The name of the EKS cluster." + type = string + default = "windsor-core" + validation { + condition = length(var.cluster_name) > 0 + error_message = "The cluster name must not be empty." + } +} + +variable "kubernetes_version" { + description = "The kubernetes version to deploy." + type = string + default = "1.32" + validation { + condition = can(regex("^\\d+\\.\\d+$", var.kubernetes_version)) + error_message = "The Kubernetes version should be in format like '1.32'." + } +} + +variable "vpc_id" { + description = "The ID of the VPC where the EKS cluster will be created." + type = string + default = "vpc-0c2bbc3cc4734c126" +} + +variable "node_groups" { + description = "Map of EKS managed node group definitions to create." + type = map(object({ + instance_types = list(string) + min_size = number + max_size = number + desired_size = number + disk_size = optional(number, 20) + labels = optional(map(string), {}) + taints = optional(list(object({ + key = string + value = string + effect = string + })), []) + })) + default = { + default = { + instance_types = ["t3.medium"] + min_size = 1 + max_size = 3 + desired_size = 2 + } + } +} + +variable "fargate_profiles" { + description = "Map of EKS Fargate profile definitions to create." + type = map(object({ + selectors = list(object({ + namespace = string + labels = optional(map(string), {}) + })) + tags = optional(map(string), {}) + })) + default = {} +} diff --git a/terraform/network/aws-vpc/.terraform.lock.hcl b/terraform/network/aws-vpc/.terraform.lock.hcl new file mode 100644 index 00000000..fa8dfe69 --- /dev/null +++ b/terraform/network/aws-vpc/.terraform.lock.hcl @@ -0,0 +1,25 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "registry.terraform.io/hashicorp/aws" { + version = "5.96.0" + constraints = "~> 5.0" + hashes = [ + "h1:a/VEUu6BGQSPlUAzbN+zqaDCdi0QGh/VzBgo2gCran0=", + "zh:3f7e734abb9d647c851f5cb987837d7c073c9cbf1f520a031027d827f93d3b68", + "zh:5ca9400360a803a11cf432ca203be9f09da8fff9c96110a83c9029102b18c9d5", + "zh:5d421f475d467af182a527b7a61d50105dc63394316edf1c775ef736f84b941c", + "zh:68f2328e7f3e7666835d6815b39b46b08954a91204f82a6f648c928a0b09a744", + "zh:6a4170e7e2764df2968d1df65efebda55273dfc36dc6741207afb5e4b7e85448", + "zh:73f2a15bee21f7c92a071e2520216d0a40041aca52c0f6682e540da8ffcfada4", + "zh:9843d6973aedfd4cbaafd7110420d0c4c1d7ef4a2eeff508294c3adcc3613145", + "zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425", + "zh:9d1abd6be717c42f2a6257ee227d3e9548c31f01c976ed7b32b2745a63659a67", + "zh:a70d642e323021d54a92f0daa81d096cb5067cb99ce116047a42eb1cb1d579a0", + "zh:b9a2b293208d5a0449275fae463319e0998c841e0bcd4014594a49ba54bb70d6", + "zh:ce0b0eb7ac24ff58c20efcb526c3f792a95be3617c795b45bbeea9f302903ae7", + "zh:dbbf98b3cd8003833c472bdb89321c17a9bbdc1b785e7e3d75f8af924ee5a0e4", + "zh:df86cf9311a4be8bb4a251196650653f97e01fbf5fe72deecc8f28a35a5352ae", + "zh:f92992881afd9339f3e539fcd90cfc1e9ed1356b5e760bbcc804314c3cd6837f", + ] +} diff --git a/terraform/network/aws-vpc/main.tf b/terraform/network/aws-vpc/main.tf new file mode 100644 index 00000000..8a7dcda9 --- /dev/null +++ b/terraform/network/aws-vpc/main.tf @@ -0,0 +1,181 @@ +// Define the required Terraform version and providers +terraform { + required_version = ">=1.8" + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 5.0" + } + } +} + +#----------------------------------------------------------------------------------------------------------------------- +# AWS VPC Configuration +#----------------------------------------------------------------------------------------------------------------------- + +resource "aws_vpc" "main" { + cidr_block = var.cidr_block + enable_dns_support = true + enable_dns_hostnames = true + + tags = { + Name = "${var.name}-vpc" + } +} + +#----------------------------------------------------------------------------------------------------------------------- +# Subnets +#----------------------------------------------------------------------------------------------------------------------- + +data "aws_availability_zones" "available" {} + +# Public Subnets +resource "aws_subnet" "public" { + count = var.availability_zones + vpc_id = aws_vpc.main.id + cidr_block = cidrsubnet(var.cidr_block, var.subnet_newbits, count.index) + availability_zone = data.aws_availability_zones.available.names[count.index] + + map_public_ip_on_launch = true + + tags = { + Name = "${var.name}-public-${data.aws_availability_zones.available.names[count.index]}" + Tier = "public" + } +} + +# Private Subnets +resource "aws_subnet" "private" { + count = var.availability_zones + vpc_id = aws_vpc.main.id + cidr_block = cidrsubnet(var.cidr_block, var.subnet_newbits, count.index + length(data.aws_availability_zones.available.names)) + availability_zone = data.aws_availability_zones.available.names[count.index] + + tags = { + Name = "${var.name}-private-${data.aws_availability_zones.available.names[count.index]}" + Tier = "private" + } +} + +# Data Subnets +resource "aws_subnet" "data" { + count = var.availability_zones + vpc_id = aws_vpc.main.id + cidr_block = cidrsubnet(var.cidr_block, var.subnet_newbits, count.index + 2 * length(data.aws_availability_zones.available.names)) + availability_zone = data.aws_availability_zones.available.names[count.index] + + tags = { + Name = "${var.name}-data-${data.aws_availability_zones.available.names[count.index]}" + Tier = "data" + } +} + +#----------------------------------------------------------------------------------------------------------------------- +# Internet Gateway +#----------------------------------------------------------------------------------------------------------------------- + +resource "aws_internet_gateway" "main" { + vpc_id = aws_vpc.main.id + + tags = { + Name = "${var.name}-igw" + } +} + +#----------------------------------------------------------------------------------------------------------------------- +# NAT Gateways +#----------------------------------------------------------------------------------------------------------------------- + +resource "aws_eip" "nat" { + count = var.availability_zones + domain = "vpc" + + tags = { + Name = "${var.name}-nat-eip-${data.aws_availability_zones.available.names[count.index]}" + } +} + +resource "aws_nat_gateway" "main" { + count = var.availability_zones + allocation_id = aws_eip.nat[count.index].id + subnet_id = aws_subnet.public[count.index].id + + tags = { + Name = "${var.name}-nat-${data.aws_availability_zones.available.names[count.index]}" + } + + depends_on = [aws_internet_gateway.main] +} + +#----------------------------------------------------------------------------------------------------------------------- +# Route Tables +#----------------------------------------------------------------------------------------------------------------------- + +# Public Route Table +resource "aws_route_table" "public" { + vpc_id = aws_vpc.main.id + + route { + cidr_block = "0.0.0.0/0" + gateway_id = aws_internet_gateway.main.id + } + + tags = { + Name = "${var.name}-public-rt" + } +} + +# Private Route Tables (one per AZ) +resource "aws_route_table" "private" { + count = var.availability_zones + vpc_id = aws_vpc.main.id + + route { + cidr_block = "0.0.0.0/0" + nat_gateway_id = aws_nat_gateway.main[count.index].id + } + + tags = { + Name = "${var.name}-private-rt-${data.aws_availability_zones.available.names[count.index]}" + } +} + +# Data Route Tables (one per AZ) +resource "aws_route_table" "data" { + count = var.availability_zones + vpc_id = aws_vpc.main.id + + route { + cidr_block = "0.0.0.0/0" + nat_gateway_id = aws_nat_gateway.main[count.index].id + } + + tags = { + Name = "${var.name}-data-rt-${data.aws_availability_zones.available.names[count.index]}" + } +} + +#----------------------------------------------------------------------------------------------------------------------- +# Route Table Associations +#----------------------------------------------------------------------------------------------------------------------- + +# Public Subnet Associations +resource "aws_route_table_association" "public" { + count = var.availability_zones + subnet_id = aws_subnet.public[count.index].id + route_table_id = aws_route_table.public.id +} + +# Private Subnet Associations +resource "aws_route_table_association" "private" { + count = var.availability_zones + subnet_id = aws_subnet.private[count.index].id + route_table_id = aws_route_table.private[count.index].id +} + +# Data Subnet Associations +resource "aws_route_table_association" "data" { + count = var.availability_zones + subnet_id = aws_subnet.data[count.index].id + route_table_id = aws_route_table.data[count.index].id +} diff --git a/terraform/network/aws-vpc/outputs.tf b/terraform/network/aws-vpc/outputs.tf new file mode 100644 index 00000000..1281f382 --- /dev/null +++ b/terraform/network/aws-vpc/outputs.tf @@ -0,0 +1,23 @@ +#----------------------------------------------------------------------------------------------------------------------- +# Outputs +#----------------------------------------------------------------------------------------------------------------------- + +output "vpc_id" { + description = "The ID of the VPC" + value = aws_vpc.main.id +} + +output "public_subnet_ids" { + description = "List of public subnet IDs" + value = aws_subnet.public[*].id +} + +output "private_subnet_ids" { + description = "List of private subnet IDs" + value = aws_subnet.private[*].id +} + +output "data_subnet_ids" { + description = "List of data subnet IDs" + value = aws_subnet.data[*].id +} diff --git a/terraform/network/aws-vpc/variables.tf b/terraform/network/aws-vpc/variables.tf new file mode 100644 index 00000000..e01b0e94 --- /dev/null +++ b/terraform/network/aws-vpc/variables.tf @@ -0,0 +1,57 @@ +#----------------------------------------------------------------------------------------------------------------------- +# Variables +#----------------------------------------------------------------------------------------------------------------------- + +variable "name" { + description = "Name prefix for all resources in the VPC" + type = string + default = "main" +} + +variable "cidr_block" { + description = "CIDR block for the VPC" + type = string + default = "10.0.0.0/16" +} + +variable "availability_zones" { + description = "Number of availability zones to use for the subnets" + type = number + default = 3 + } + +variable "subnet_newbits" { + description = "Number of new bits for the subnet" + type = number + default = 4 +} + +variable "enable_dns_hostnames" { + description = "Enable DNS hostnames in the VPC" + type = bool + default = true +} + +variable "enable_dns_support" { + description = "Enable DNS support in the VPC" + type = bool + default = true +} + +variable "enable_nat_gateway" { + description = "Enable NAT Gateway for private subnets" + type = bool + default = true +} + +variable "single_nat_gateway" { + description = "Use a single NAT Gateway for all private subnets" + type = bool + default = false +} + +variable "tags" { + description = "Additional tags for all resources" + type = map(string) + default = {} +} diff --git a/windsor.yaml b/windsor.yaml index c189add8..72953d91 100644 --- a/windsor.yaml +++ b/windsor.yaml @@ -54,4 +54,12 @@ contexts: cidr_block: 10.5.0.0/16 dns: enabled: false - domain: test \ No newline at end of file + domain: test + aws-example: + aws: + enabled: true + region: us-east-2 + terraform: + enabled: true + backend: + type: local From b58f1abe12b698edb4c8abac98ba3c847aba7b38 Mon Sep 17 00:00:00 2001 From: Alex Petre Date: Thu, 1 May 2025 09:42:46 -0400 Subject: [PATCH 02/34] Add AWS-specific add-ons to config --- .gitignore | 3 + contexts/aws-example/blueprint.yaml | 25 -- terraform/cluster/aws-eks/.terraform.lock.hcl | 20 -- terraform/cluster/aws-eks/main.tf | 272 +++++++++++++++++- terraform/cluster/aws-eks/variables.tf | 14 + 5 files changed, 285 insertions(+), 49 deletions(-) diff --git a/.gitignore b/.gitignore index 3d37ca5f..d32249ea 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,6 @@ contexts/**/.tfstate/ contexts/**/.kube/ contexts/**/.talos/ contexts/**/.aws/ + +# macOS system files +**/.DS_Store diff --git a/contexts/aws-example/blueprint.yaml b/contexts/aws-example/blueprint.yaml index e40231c9..0ba86f88 100644 --- a/contexts/aws-example/blueprint.yaml +++ b/contexts/aws-example/blueprint.yaml @@ -39,31 +39,6 @@ kustomize: path: policy/resources dependsOn: - policy-base -# - name: csi -# path: csi -# source: core -# dependsOn: -# - policy-resources -# force: true -# components: -# - openebs -# - openebs/dynamic-localpv -# - name: lb-base -# path: lb/base -# source: core -# dependsOn: -# - policy-resources -# force: true -# components: -# - metallb -# - name: lb-resources -# path: lb/resources -# source: core -# dependsOn: -# - lb-base -# force: true -# components: -# - metallb/layer2 - name: ingress-base path: ingress/base source: core diff --git a/terraform/cluster/aws-eks/.terraform.lock.hcl b/terraform/cluster/aws-eks/.terraform.lock.hcl index c980c876..2d85f213 100644 --- a/terraform/cluster/aws-eks/.terraform.lock.hcl +++ b/terraform/cluster/aws-eks/.terraform.lock.hcl @@ -24,26 +24,6 @@ provider "registry.terraform.io/hashicorp/aws" { ] } -provider "registry.terraform.io/hashicorp/kubernetes" { - version = "2.36.0" - constraints = "~> 2.23" - hashes = [ - "h1:94wlXkBzfXwyLVuJVhMdzK+VGjFnMjdmFkYhQ1RUFhI=", - "zh:07f38fcb7578984a3e2c8cf0397c880f6b3eb2a722a120a08a634a607ea495ca", - "zh:1adde61769c50dbb799d8bf8bfd5c8c504a37017dfd06c7820f82bcf44ca0d39", - "zh:39707f23ab58fd0e686967c0f973c0f5a39c14d6ccfc757f97c345fdd0cd4624", - "zh:4cc3dc2b5d06cc22d1c734f7162b0a8fdc61990ff9efb64e59412d65a7ccc92a", - "zh:8382dcb82ba7303715b5e67939e07dd1c8ecddbe01d12f39b82b2b7d7357e1d9", - "zh:88e8e4f90034186b8bfdea1b8d394621cbc46a064ff2418027e6dba6807d5227", - "zh:a6276a75ad170f76d88263fdb5f9558998bf3a3f7650d7bd3387b396410e59f3", - "zh:bc816c7e0606e5df98a0c7634b240bb0c8100c3107b8b17b554af702edc6a0c5", - "zh:cb2f31d58f37020e840af52755c18afd1f09a833c4903ac59270ab440fab57b7", - "zh:ee0d103b8d0089fb1918311683110b4492a9346f0471b136af46d3b019576b22", - "zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c", - "zh:f688b9ec761721e401f6859c19c083e3be20a650426f4747cd359cdc079d212a", - ] -} - provider "registry.terraform.io/hashicorp/local" { version = "2.5.2" hashes = [ diff --git a/terraform/cluster/aws-eks/main.tf b/terraform/cluster/aws-eks/main.tf index 12aee3e8..bd7cda77 100644 --- a/terraform/cluster/aws-eks/main.tf +++ b/terraform/cluster/aws-eks/main.tf @@ -6,10 +6,6 @@ terraform { source = "hashicorp/aws" version = "~> 5.0" } - kubernetes = { - source = "hashicorp/kubernetes" - version = "~> 2.23" - } } } @@ -195,6 +191,274 @@ resource "aws_eks_fargate_profile" "this" { tags = lookup(each.value, "tags", {}) } +#----------------------------------------------------------------------------------------------------------------------- +# Add-On Versions +#----------------------------------------------------------------------------------------------------------------------- + +data "aws_eks_addon_version" "default" { + for_each = var.addons + + addon_name = each.key + kubernetes_version = aws_eks_cluster.this.version + most_recent = true +} + +#----------------------------------------------------------------------------------------------------------------------- +# VPC CNI IAM Role +#----------------------------------------------------------------------------------------------------------------------- + +resource "aws_iam_role" "vpc_cni" { + count = contains(keys(var.addons), "vpc-cni") ? 1 : 0 + name = "${var.cluster_name}-vpc-cni-role" + + assume_role_policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Action = ["sts:AssumeRole", "sts:TagSession"] + Effect = "Allow" + Principal = { + Service = "pods.eks.amazonaws.com" + } + } + ] + }) + + tags = { + Name = "${var.cluster_name}-vpc-cni-role" + } +} + +resource "aws_iam_role_policy_attachment" "vpc_cni" { + count = contains(keys(var.addons), "vpc-cni") ? 1 : 0 + policy_arn = "arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy" + role = aws_iam_role.vpc_cni[0].name +} + + +#----------------------------------------------------------------------------------------------------------------------- +# EBS CSI Driver IAM Role +#----------------------------------------------------------------------------------------------------------------------- + +resource "aws_iam_role" "ebs_csi" { + count = contains(keys(var.addons), "aws-ebs-csi-driver") ? 1 : 0 + name = "${var.cluster_name}-aws-ebs-csi-driver-role" + + assume_role_policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Action = ["sts:AssumeRole", "sts:TagSession"] + Effect = "Allow" + Principal = { + Service = "pods.eks.amazonaws.com" + } + } + ] + }) + + tags = { + Name = "${var.cluster_name}-aws-ebs-csi-driver-role" + } +} + +resource "aws_iam_role_policy_attachment" "ebs_csi" { + count = contains(keys(var.addons), "aws-ebs-csi-driver") ? 1 : 0 + policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonEBSCSIDriverPolicy" + role = aws_iam_role.ebs_csi[0].name +} + +#----------------------------------------------------------------------------------------------------------------------- +# EFS CSI Driver IAM Role +#----------------------------------------------------------------------------------------------------------------------- + +resource "aws_iam_role" "efs_csi" { + count = contains(keys(var.addons), "aws-efs-csi-driver") ? 1 : 0 + name = "${var.cluster_name}-aws-efs-csi-driver-role" + + assume_role_policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Action = ["sts:AssumeRole", "sts:TagSession"] + Effect = "Allow" + Principal = { + Service = "pods.eks.amazonaws.com" + } + } + ] + }) + + tags = { + Name = "${var.cluster_name}-aws-efs-csi-driver-role" + } +} + +resource "aws_iam_policy" "efs_csi" { + count = contains(keys(var.addons), "aws-efs-csi-driver") ? 1 : 0 + name = "${var.cluster_name}-aws-efs-csi-driver-policy" + description = "IAM policy for EFS CSI Driver" + + policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Effect = "Allow" + Action = [ + "elasticfilesystem:DescribeAccessPoints", + "elasticfilesystem:DescribeFileSystems", + "elasticfilesystem:DescribeMountTargets", + "ec2:DescribeAvailabilityZones" + ] + Resource = "*" + }, + { + Effect = "Allow" + Action = [ + "elasticfilesystem:CreateAccessPoint" + ] + Resource = "*" + Condition = { + StringLike = { + "aws:RequestTag/efs.csi.aws.com/cluster" = "true" + } + } + }, + { + Effect = "Allow" + Action = [ + "elasticfilesystem:DeleteAccessPoint" + ] + Resource = "*" + Condition = { + StringLike = { + "aws:ResourceTag/efs.csi.aws.com/cluster" = "true" + } + } + } + ] + }) + + tags = { + Name = "${var.cluster_name}-aws-efs-csi-driver-policy" + } +} + +resource "aws_iam_role_policy_attachment" "efs_csi" { + count = contains(keys(var.addons), "aws-efs-csi-driver") ? 1 : 0 + policy_arn = aws_iam_policy.efs_csi[0].arn + role = aws_iam_role.efs_csi[0].name +} + +#----------------------------------------------------------------------------------------------------------------------- +# Pod Identity Agent IAM Role +#----------------------------------------------------------------------------------------------------------------------- + +resource "aws_iam_role" "pod_identity_agent" { + count = contains(keys(var.addons), "pod-identity-agent") ? 1 : 0 + name = "${var.cluster_name}-pod-identity-agent-role" + + assume_role_policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Effect = "Allow" + Principal = { + Service = "eks.amazonaws.com" + } + Action = "sts:AssumeRole" + } + ] + }) + + tags = { + Name = "${var.cluster_name}-pod-identity-agent-role" + } +} + +resource "aws_iam_policy" "pod_identity_agent" { + count = contains(keys(var.addons), "pod-identity-agent") ? 1 : 0 + name = "${var.cluster_name}-pod-identity-agent-policy" + description = "IAM policy for EKS Pod Identity Agent" + + policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Effect = "Allow" + Action = [ + "iam:CreateServiceLinkedRole" + ] + Resource = "*" + Condition = { + StringEquals = { + "iam:AWSServiceName" = "eks-auth.amazonaws.com" + } + } + } + ] + }) + + tags = { + Name = "${var.cluster_name}-pod-identity-agent-policy" + } +} + +resource "aws_iam_role_policy_attachment" "pod_identity_agent" { + count = contains(keys(var.addons), "pod-identity-agent") ? 1 : 0 + policy_arn = aws_iam_policy.pod_identity_agent[0].arn + role = aws_iam_role.pod_identity_agent[0].name +} + +#----------------------------------------------------------------------------------------------------------------------- +# Create Add-Ons +#----------------------------------------------------------------------------------------------------------------------- + +locals { + addon_configuration = { + for name, addon in var.addons : name => { + version = lookup(addon, "version", data.aws_eks_addon_version.default[name].version) + role_arn = ( + name == "vpc-cni" ? try(aws_iam_role.vpc_cni[0].arn, null) : + name == "aws-ebs-csi-driver" ? try(aws_iam_role.ebs_csi[0].arn, null) : + name == "aws-efs-csi-driver" ? try(aws_iam_role.efs_csi[0].arn, null) : + name == "eks-pod-identity-agent" ? try(aws_iam_role.pod_identity_agent[0].arn, null) : + null + ) + service_account_name = ( + name == "vpc-cni" ? "aws-node" : + name == "aws-ebs-csi-driver" ? "ebs-csi-controller-sa" : + name == "aws-efs-csi-driver" ? "efs-csi-controller-sa" : + null + ) + tags = lookup(addon, "tags", {}) + } + } +} + +resource "aws_eks_addon" "this" { + for_each = var.addons + + cluster_name = aws_eks_cluster.this.name + addon_name = each.key + addon_version = local.addon_configuration[each.key].version + service_account_role_arn = ( + each.key == "eks-pod-identity-agent" ? local.addon_configuration[each.key].role_arn : null + ) + + dynamic "pod_identity_association" { + for_each = ( + each.key != "eks-pod-identity-agent" && + local.addon_configuration[each.key].role_arn != null + ) ? [1] : [] + content { + role_arn = local.addon_configuration[each.key].role_arn + service_account = local.addon_configuration[each.key].service_account_name + } + } + tags = local.addon_configuration[each.key].tags +} + #----------------------------------------------------------------------------------------------------------------------- # Kubeconfig #----------------------------------------------------------------------------------------------------------------------- diff --git a/terraform/cluster/aws-eks/variables.tf b/terraform/cluster/aws-eks/variables.tf index ad6af2c7..27ef3754 100644 --- a/terraform/cluster/aws-eks/variables.tf +++ b/terraform/cluster/aws-eks/variables.tf @@ -71,3 +71,17 @@ variable "fargate_profiles" { })) default = {} } + +variable "addons" { + description = "Map of EKS add-ons" + type = map(object({ + version = optional(string) + tags = optional(map(string), {}) + })) + default = { + vpc-cni = {} + aws-efs-csi-driver = {} + aws-ebs-csi-driver = {} + eks-pod-identity-agent = {} + } +} From ac1f8dfc87fed41778b42f0abb3b5c86c61a57f0 Mon Sep 17 00:00:00 2001 From: Alex Petre Date: Thu, 1 May 2025 09:46:21 -0400 Subject: [PATCH 03/34] fmt --- terraform/cluster/aws-eks/main.tf | 20 ++++++++++---------- terraform/cluster/aws-eks/variables.tf | 14 +++++++------- terraform/network/aws-vpc/variables.tf | 2 +- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/terraform/cluster/aws-eks/main.tf b/terraform/cluster/aws-eks/main.tf index bd7cda77..f1cbb1c9 100644 --- a/terraform/cluster/aws-eks/main.tf +++ b/terraform/cluster/aws-eks/main.tf @@ -209,7 +209,7 @@ data "aws_eks_addon_version" "default" { resource "aws_iam_role" "vpc_cni" { count = contains(keys(var.addons), "vpc-cni") ? 1 : 0 - name = "${var.cluster_name}-vpc-cni-role" + name = "${var.cluster_name}-vpc-cni-role" assume_role_policy = jsonencode({ Version = "2012-10-17" @@ -230,7 +230,7 @@ resource "aws_iam_role" "vpc_cni" { } resource "aws_iam_role_policy_attachment" "vpc_cni" { - count = contains(keys(var.addons), "vpc-cni") ? 1 : 0 + count = contains(keys(var.addons), "vpc-cni") ? 1 : 0 policy_arn = "arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy" role = aws_iam_role.vpc_cni[0].name } @@ -417,7 +417,7 @@ resource "aws_iam_role_policy_attachment" "pod_identity_agent" { locals { addon_configuration = { for name, addon in var.addons : name => { - version = lookup(addon, "version", data.aws_eks_addon_version.default[name].version) + version = lookup(addon, "version", data.aws_eks_addon_version.default[name].version) role_arn = ( name == "vpc-cni" ? try(aws_iam_role.vpc_cni[0].arn, null) : name == "aws-ebs-csi-driver" ? try(aws_iam_role.ebs_csi[0].arn, null) : @@ -431,7 +431,7 @@ locals { name == "aws-efs-csi-driver" ? "efs-csi-controller-sa" : null ) - tags = lookup(addon, "tags", {}) + tags = lookup(addon, "tags", {}) } } } @@ -439,24 +439,24 @@ locals { resource "aws_eks_addon" "this" { for_each = var.addons - cluster_name = aws_eks_cluster.this.name - addon_name = each.key - addon_version = local.addon_configuration[each.key].version + cluster_name = aws_eks_cluster.this.name + addon_name = each.key + addon_version = local.addon_configuration[each.key].version service_account_role_arn = ( each.key == "eks-pod-identity-agent" ? local.addon_configuration[each.key].role_arn : null ) dynamic "pod_identity_association" { for_each = ( - each.key != "eks-pod-identity-agent" && + each.key != "eks-pod-identity-agent" && local.addon_configuration[each.key].role_arn != null ) ? [1] : [] content { - role_arn = local.addon_configuration[each.key].role_arn + role_arn = local.addon_configuration[each.key].role_arn service_account = local.addon_configuration[each.key].service_account_name } } - tags = local.addon_configuration[each.key].tags + tags = local.addon_configuration[each.key].tags } #----------------------------------------------------------------------------------------------------------------------- diff --git a/terraform/cluster/aws-eks/variables.tf b/terraform/cluster/aws-eks/variables.tf index 27ef3754..08f27705 100644 --- a/terraform/cluster/aws-eks/variables.tf +++ b/terraform/cluster/aws-eks/variables.tf @@ -44,7 +44,7 @@ variable "node_groups" { desired_size = number disk_size = optional(number, 20) labels = optional(map(string), {}) - taints = optional(list(object({ + taints = optional(list(object({ key = string value = string effect = string @@ -75,13 +75,13 @@ variable "fargate_profiles" { variable "addons" { description = "Map of EKS add-ons" type = map(object({ - version = optional(string) - tags = optional(map(string), {}) + version = optional(string) + tags = optional(map(string), {}) })) default = { - vpc-cni = {} - aws-efs-csi-driver = {} - aws-ebs-csi-driver = {} - eks-pod-identity-agent = {} + vpc-cni = {} + aws-efs-csi-driver = {} + aws-ebs-csi-driver = {} + eks-pod-identity-agent = {} } } diff --git a/terraform/network/aws-vpc/variables.tf b/terraform/network/aws-vpc/variables.tf index e01b0e94..76ccb85d 100644 --- a/terraform/network/aws-vpc/variables.tf +++ b/terraform/network/aws-vpc/variables.tf @@ -18,7 +18,7 @@ variable "availability_zones" { description = "Number of availability zones to use for the subnets" type = number default = 3 - } +} variable "subnet_newbits" { description = "Number of new bits for the subnet" From 4498ee574323f5d24304e5833e7477c5c042ff2e Mon Sep 17 00:00:00 2001 From: Alex Petre Date: Thu, 1 May 2025 09:59:23 -0400 Subject: [PATCH 04/34] Modify the blueprint for testing --- contexts/aws-example/blueprint.yaml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/contexts/aws-example/blueprint.yaml b/contexts/aws-example/blueprint.yaml index 0ba86f88..2b19a317 100644 --- a/contexts/aws-example/blueprint.yaml +++ b/contexts/aws-example/blueprint.yaml @@ -41,7 +41,6 @@ kustomize: - policy-base - name: ingress-base path: ingress/base - source: core dependsOn: - pki-resources force: true @@ -53,7 +52,6 @@ kustomize: - nginx/web - name: pki-base path: pki/base - source: core dependsOn: - policy-resources force: true @@ -62,7 +60,6 @@ kustomize: - trust-manager - name: pki-resources path: pki/resources - source: core dependsOn: - pki-base force: true @@ -71,7 +68,6 @@ kustomize: - public-issuer/selfsigned - name: dns path: dns - source: core dependsOn: - ingress-base - pki-base @@ -84,7 +80,6 @@ kustomize: - external-dns/ingress - name: gitops path: gitops/flux - source: core dependsOn: - ingress-base force: true @@ -92,9 +87,7 @@ kustomize: - webhook - name: observability path: observability - source: core dependsOn: - - csi - ingress-base components: - grafana From 2ffcee38bab6ff4da8bbc00058b39cf3c5987787 Mon Sep 17 00:00:00 2001 From: Alex Petre Date: Thu, 1 May 2025 10:03:06 -0400 Subject: [PATCH 05/34] Fix URL --- contexts/aws-example/blueprint.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contexts/aws-example/blueprint.yaml b/contexts/aws-example/blueprint.yaml index 2b19a317..9d62d39a 100644 --- a/contexts/aws-example/blueprint.yaml +++ b/contexts/aws-example/blueprint.yaml @@ -4,7 +4,7 @@ metadata: name: aws-example description: This blueprint outlines resources in the aws-example context repository: - url: github.com/windsorcli/core + url: https://github.com/windsorcli/core ref: branch: aws-eks secretName: flux-system From a0686d8feaae59f4238a0dd3e5cbcb83550a8316 Mon Sep 17 00:00:00 2001 From: Alex Petre Date: Thu, 1 May 2025 10:05:34 -0400 Subject: [PATCH 06/34] ref branch, source core --- contexts/aws-example/blueprint.yaml | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/contexts/aws-example/blueprint.yaml b/contexts/aws-example/blueprint.yaml index 9d62d39a..0c01bd69 100644 --- a/contexts/aws-example/blueprint.yaml +++ b/contexts/aws-example/blueprint.yaml @@ -12,7 +12,7 @@ sources: - name: core url: github.com/windsorcli/core ref: - tag: v0.3.0 + branch: aws-eks terraform: - path: network/aws-vpc - path: cluster/aws-eks @@ -20,11 +20,13 @@ terraform: kustomize: - name: telemetry-base path: telemetry/base + source: core components: - prometheus - prometheus/flux - name: telemetry-resources path: telemetry/resources + source: core dependsOn: - telemetry-base components: @@ -33,14 +35,17 @@ kustomize: - prometheus/flux - name: policy-base path: policy/base + source: core components: - kyverno - name: policy-resources path: policy/resources + source: core dependsOn: - policy-base - name: ingress-base path: ingress/base + source: core dependsOn: - pki-resources force: true @@ -52,6 +57,7 @@ kustomize: - nginx/web - name: pki-base path: pki/base + source: core dependsOn: - policy-resources force: true @@ -60,6 +66,7 @@ kustomize: - trust-manager - name: pki-resources path: pki/resources + source: core dependsOn: - pki-base force: true @@ -68,6 +75,7 @@ kustomize: - public-issuer/selfsigned - name: dns path: dns + source: core dependsOn: - ingress-base - pki-base @@ -80,6 +88,7 @@ kustomize: - external-dns/ingress - name: gitops path: gitops/flux + source: core dependsOn: - ingress-base force: true @@ -87,6 +96,7 @@ kustomize: - webhook - name: observability path: observability + source: core dependsOn: - ingress-base components: From dea31f9b8104f3de7142e6854e1ad68243ffb2e4 Mon Sep 17 00:00:00 2001 From: Alex Petre Date: Fri, 2 May 2025 10:16:00 -0400 Subject: [PATCH 07/34] Fix for AWS specific issue --- contexts/aws-example/blueprint.yaml | 2 +- .../nginx/aws-loadbalancer/kustomization.yaml | 4 ++ .../patches/helm-release.yaml | 17 ++++++ terraform/cluster/aws-eks/main.tf | 53 ++++++++++++++++++- terraform/cluster/aws-eks/variables.tf | 25 ++++++++- 5 files changed, 98 insertions(+), 3 deletions(-) create mode 100644 kustomize/ingress/base/nginx/aws-loadbalancer/kustomization.yaml create mode 100644 kustomize/ingress/base/nginx/aws-loadbalancer/patches/helm-release.yaml diff --git a/contexts/aws-example/blueprint.yaml b/contexts/aws-example/blueprint.yaml index 0c01bd69..9f4631dc 100644 --- a/contexts/aws-example/blueprint.yaml +++ b/contexts/aws-example/blueprint.yaml @@ -51,7 +51,7 @@ kustomize: force: true components: - nginx - - nginx/loadbalancer + - nginx/aws-loadbalancer - nginx/coredns - nginx/flux-webhook - nginx/web diff --git a/kustomize/ingress/base/nginx/aws-loadbalancer/kustomization.yaml b/kustomize/ingress/base/nginx/aws-loadbalancer/kustomization.yaml new file mode 100644 index 00000000..8138d116 --- /dev/null +++ b/kustomize/ingress/base/nginx/aws-loadbalancer/kustomization.yaml @@ -0,0 +1,4 @@ +apiVersion: kustomize.config.k8s.io/v1alpha1 +kind: Component +patches: + - path: patches/helm-release.yaml diff --git a/kustomize/ingress/base/nginx/aws-loadbalancer/patches/helm-release.yaml b/kustomize/ingress/base/nginx/aws-loadbalancer/patches/helm-release.yaml new file mode 100644 index 00000000..50aa086a --- /dev/null +++ b/kustomize/ingress/base/nginx/aws-loadbalancer/patches/helm-release.yaml @@ -0,0 +1,17 @@ +--- +apiVersion: helm.toolkit.fluxcd.io/v2 +kind: HelmRelease +metadata: + name: ingress-nginx-controller + namespace: system-ingress +spec: + values: + controller: + service: + type: LoadBalancer + loadBalancerIP: ${LOADBALANCER_IP_START} + enableHttp: true + enableTls: false + ports: + http: 80 + https: 443 diff --git a/terraform/cluster/aws-eks/main.tf b/terraform/cluster/aws-eks/main.tf index f1cbb1c9..4bb1435f 100644 --- a/terraform/cluster/aws-eks/main.tf +++ b/terraform/cluster/aws-eks/main.tf @@ -120,7 +120,6 @@ resource "aws_eks_node_group" "this" { node_role_arn = aws_iam_role.node_group.arn subnet_ids = data.aws_subnets.private.ids instance_types = each.value.instance_types - disk_size = each.value.disk_size scaling_config { desired_size = each.value.desired_size @@ -139,6 +138,12 @@ resource "aws_eks_node_group" "this" { labels = each.value.labels + # Set max pods per node to 64 + launch_template { + name = aws_launch_template.node_group[each.key].name + version = aws_launch_template.node_group[each.key].latest_version + } + depends_on = [ aws_iam_role_policy_attachment.node_group_AmazonEKSWorkerNodePolicy, aws_iam_role_policy_attachment.node_group_AmazonEKS_CNI_Policy, @@ -146,6 +151,42 @@ resource "aws_eks_node_group" "this" { ] } +resource "aws_launch_template" "node_group" { + for_each = var.node_groups + + name = "${var.cluster_name}-${each.key}" + + block_device_mappings { + device_name = "/dev/xvda" + ebs { + volume_size = each.value.disk_size + volume_type = "gp3" + delete_on_termination = true + } + } + + network_interfaces { + associate_public_ip_address = false + delete_on_termination = true + security_groups = [aws_eks_cluster.this.vpc_config[0].cluster_security_group_id] + } + + user_data = base64encode(<<-EOT +MIME-Version: 1.0 +Content-Type: multipart/mixed; boundary="==BOUNDARY==" + +--==BOUNDARY== +Content-Type: text/x-shellscript; charset="us-ascii" + +#!/bin/bash +set -o xtrace +/etc/eks/bootstrap.sh ${aws_eks_cluster.this.name} --use-max-pods false --kubelet-extra-args '--max-pods=110' + +--==BOUNDARY==-- +EOT + ) +} + #----------------------------------------------------------------------------------------------------------------------- # Fargate Profile #----------------------------------------------------------------------------------------------------------------------- @@ -446,6 +487,16 @@ resource "aws_eks_addon" "this" { each.key == "eks-pod-identity-agent" ? local.addon_configuration[each.key].role_arn : null ) + # Configure VPC CNI to allow more max pods per node + configuration_values = each.key == "vpc-cni" ? jsonencode({ + env = { + ENABLE_PREFIX_DELEGATION = tostring(var.vpc_cni_config.enable_prefix_delegation) + WARM_PREFIX_TARGET = tostring(var.vpc_cni_config.warm_prefix_target) + WARM_IP_TARGET = tostring(var.vpc_cni_config.warm_ip_target) + MINIMUM_IP_TARGET = tostring(var.vpc_cni_config.minimum_ip_target) + } + }) : null + dynamic "pod_identity_association" { for_each = ( each.key != "eks-pod-identity-agent" && diff --git a/terraform/cluster/aws-eks/variables.tf b/terraform/cluster/aws-eks/variables.tf index 08f27705..f1bdf02c 100644 --- a/terraform/cluster/aws-eks/variables.tf +++ b/terraform/cluster/aws-eks/variables.tf @@ -42,7 +42,7 @@ variable "node_groups" { min_size = number max_size = number desired_size = number - disk_size = optional(number, 20) + disk_size = optional(number, 64) labels = optional(map(string), {}) taints = optional(list(object({ key = string @@ -60,6 +60,29 @@ variable "node_groups" { } } +variable "max_pods_per_node" { + description = "Maximum number of pods that can run on a single node" + type = number + default = 64 +} + +variable "vpc_cni_config" { + description = "Configuration for the VPC CNI addon" + type = object({ + enable_prefix_delegation = bool + warm_prefix_target = number + warm_ip_target = number + minimum_ip_target = number + }) + default = { + enable_prefix_delegation = true + warm_prefix_target = 1 + warm_ip_target = 1 + minimum_ip_target = 1 + } +} + + variable "fargate_profiles" { description = "Map of EKS Fargate profile definitions to create." type = map(object({ From 0cb18363d95b944eedd74acc45909fd3ce2b33bb Mon Sep 17 00:00:00 2001 From: Alex Petre Date: Fri, 2 May 2025 10:44:42 -0400 Subject: [PATCH 08/34] remove the loadbalancer patch --- contexts/aws-example/blueprint.yaml | 1 - .../nginx/aws-loadbalancer/kustomization.yaml | 4 ---- .../aws-loadbalancer/patches/helm-release.yaml | 17 ----------------- 3 files changed, 22 deletions(-) delete mode 100644 kustomize/ingress/base/nginx/aws-loadbalancer/kustomization.yaml delete mode 100644 kustomize/ingress/base/nginx/aws-loadbalancer/patches/helm-release.yaml diff --git a/contexts/aws-example/blueprint.yaml b/contexts/aws-example/blueprint.yaml index 9f4631dc..b7b25f29 100644 --- a/contexts/aws-example/blueprint.yaml +++ b/contexts/aws-example/blueprint.yaml @@ -51,7 +51,6 @@ kustomize: force: true components: - nginx - - nginx/aws-loadbalancer - nginx/coredns - nginx/flux-webhook - nginx/web diff --git a/kustomize/ingress/base/nginx/aws-loadbalancer/kustomization.yaml b/kustomize/ingress/base/nginx/aws-loadbalancer/kustomization.yaml deleted file mode 100644 index 8138d116..00000000 --- a/kustomize/ingress/base/nginx/aws-loadbalancer/kustomization.yaml +++ /dev/null @@ -1,4 +0,0 @@ -apiVersion: kustomize.config.k8s.io/v1alpha1 -kind: Component -patches: - - path: patches/helm-release.yaml diff --git a/kustomize/ingress/base/nginx/aws-loadbalancer/patches/helm-release.yaml b/kustomize/ingress/base/nginx/aws-loadbalancer/patches/helm-release.yaml deleted file mode 100644 index 50aa086a..00000000 --- a/kustomize/ingress/base/nginx/aws-loadbalancer/patches/helm-release.yaml +++ /dev/null @@ -1,17 +0,0 @@ ---- -apiVersion: helm.toolkit.fluxcd.io/v2 -kind: HelmRelease -metadata: - name: ingress-nginx-controller - namespace: system-ingress -spec: - values: - controller: - service: - type: LoadBalancer - loadBalancerIP: ${LOADBALANCER_IP_START} - enableHttp: true - enableTls: false - ports: - http: 80 - https: 443 From 8920d4f249ba072f71754e7639de1c60834fa604 Mon Sep 17 00:00:00 2001 From: Alex Petre Date: Fri, 2 May 2025 11:41:47 -0400 Subject: [PATCH 09/34] CoreDNS & ExternalDNS addons --- contexts/aws-example/blueprint.yaml | 14 -------- terraform/cluster/aws-eks/.terraform.lock.hcl | 32 +++++++++---------- terraform/cluster/aws-eks/variables.tf | 2 ++ terraform/network/aws-vpc/.terraform.lock.hcl | 32 +++++++++---------- 4 files changed, 34 insertions(+), 46 deletions(-) diff --git a/contexts/aws-example/blueprint.yaml b/contexts/aws-example/blueprint.yaml index b7b25f29..63bf3f7b 100644 --- a/contexts/aws-example/blueprint.yaml +++ b/contexts/aws-example/blueprint.yaml @@ -51,7 +51,6 @@ kustomize: force: true components: - nginx - - nginx/coredns - nginx/flux-webhook - nginx/web - name: pki-base @@ -72,19 +71,6 @@ kustomize: components: - private-issuer/ca - public-issuer/selfsigned -- name: dns - path: dns - source: core - dependsOn: - - ingress-base - - pki-base - force: true - components: - - coredns - - coredns/etcd - - external-dns - - external-dns/coredns - - external-dns/ingress - name: gitops path: gitops/flux source: core diff --git a/terraform/cluster/aws-eks/.terraform.lock.hcl b/terraform/cluster/aws-eks/.terraform.lock.hcl index 2d85f213..78476919 100644 --- a/terraform/cluster/aws-eks/.terraform.lock.hcl +++ b/terraform/cluster/aws-eks/.terraform.lock.hcl @@ -2,25 +2,25 @@ # Manual edits may be lost in future updates. provider "registry.terraform.io/hashicorp/aws" { - version = "5.96.0" + version = "5.97.0" constraints = "~> 5.0" hashes = [ - "h1:a/VEUu6BGQSPlUAzbN+zqaDCdi0QGh/VzBgo2gCran0=", - "zh:3f7e734abb9d647c851f5cb987837d7c073c9cbf1f520a031027d827f93d3b68", - "zh:5ca9400360a803a11cf432ca203be9f09da8fff9c96110a83c9029102b18c9d5", - "zh:5d421f475d467af182a527b7a61d50105dc63394316edf1c775ef736f84b941c", - "zh:68f2328e7f3e7666835d6815b39b46b08954a91204f82a6f648c928a0b09a744", - "zh:6a4170e7e2764df2968d1df65efebda55273dfc36dc6741207afb5e4b7e85448", - "zh:73f2a15bee21f7c92a071e2520216d0a40041aca52c0f6682e540da8ffcfada4", - "zh:9843d6973aedfd4cbaafd7110420d0c4c1d7ef4a2eeff508294c3adcc3613145", + "h1:rUDE0OgA+6IiEA+w0cPp3/QQNH4SpjFjYcQ6p7byKS4=", + "zh:02790ad98b767d8f24d28e8be623f348bcb45590205708334d52de2fb14f5a95", + "zh:088b4398a161e45762dc28784fcc41c4fa95bd6549cb708b82de577f2d39ffc7", + "zh:0c381a457b7af391c43fc0167919443f6105ad2702bde4d02ddea9fd7c9d3539", + "zh:1a4b57a5043dcca64d8b8bae8b30ef4f6b98ed2144f792f39c4e816d3f1e2c56", + "zh:1bf00a67f39e67664337bde065180d41d952242801ebcd1c777061d4ffaa1cc1", + "zh:24c549f53d6bd022af31426d3e78f21264d8a72409821669e7fd41966ae68b2b", + "zh:3abda50bbddb35d86081fe39522e995280aea7f004582c4af22112c03ac8b375", + "zh:7388ed7f21ce2eb46bd9066626ce5f3e2a5705f67f643acce8ae71972f66eaf6", + "zh:96740f2ff94e5df2b2d29a5035a1a1026fe821f61712b2099b224fb2c2277663", "zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425", - "zh:9d1abd6be717c42f2a6257ee227d3e9548c31f01c976ed7b32b2745a63659a67", - "zh:a70d642e323021d54a92f0daa81d096cb5067cb99ce116047a42eb1cb1d579a0", - "zh:b9a2b293208d5a0449275fae463319e0998c841e0bcd4014594a49ba54bb70d6", - "zh:ce0b0eb7ac24ff58c20efcb526c3f792a95be3617c795b45bbeea9f302903ae7", - "zh:dbbf98b3cd8003833c472bdb89321c17a9bbdc1b785e7e3d75f8af924ee5a0e4", - "zh:df86cf9311a4be8bb4a251196650653f97e01fbf5fe72deecc8f28a35a5352ae", - "zh:f92992881afd9339f3e539fcd90cfc1e9ed1356b5e760bbcc804314c3cd6837f", + "zh:9f399f8e8683a3a3a6d63a41c7c3a5a5f266eedef40ea69eba75bacf03699879", + "zh:bcf2b288d4706ebd198f75d2159663d657535483331107f2cdef381f10688baf", + "zh:cc76c8a9fc3bad05a8779c1f80fe8c388734f1ec1dd0affa863343490527b466", + "zh:de4359cf1b057bfe7a563be93829ec64bf72e7a2b85a72d075238081ef5eb1db", + "zh:e208fa77051a1f9fa1eff6c5c58aabdcab0de1695b97cdea7b8dd81df3e0ed73", ] } diff --git a/terraform/cluster/aws-eks/variables.tf b/terraform/cluster/aws-eks/variables.tf index f1bdf02c..350a8970 100644 --- a/terraform/cluster/aws-eks/variables.tf +++ b/terraform/cluster/aws-eks/variables.tf @@ -106,5 +106,7 @@ variable "addons" { aws-efs-csi-driver = {} aws-ebs-csi-driver = {} eks-pod-identity-agent = {} + coredns = {} + external-dns = {} } } diff --git a/terraform/network/aws-vpc/.terraform.lock.hcl b/terraform/network/aws-vpc/.terraform.lock.hcl index fa8dfe69..e6762f06 100644 --- a/terraform/network/aws-vpc/.terraform.lock.hcl +++ b/terraform/network/aws-vpc/.terraform.lock.hcl @@ -2,24 +2,24 @@ # Manual edits may be lost in future updates. provider "registry.terraform.io/hashicorp/aws" { - version = "5.96.0" + version = "5.97.0" constraints = "~> 5.0" hashes = [ - "h1:a/VEUu6BGQSPlUAzbN+zqaDCdi0QGh/VzBgo2gCran0=", - "zh:3f7e734abb9d647c851f5cb987837d7c073c9cbf1f520a031027d827f93d3b68", - "zh:5ca9400360a803a11cf432ca203be9f09da8fff9c96110a83c9029102b18c9d5", - "zh:5d421f475d467af182a527b7a61d50105dc63394316edf1c775ef736f84b941c", - "zh:68f2328e7f3e7666835d6815b39b46b08954a91204f82a6f648c928a0b09a744", - "zh:6a4170e7e2764df2968d1df65efebda55273dfc36dc6741207afb5e4b7e85448", - "zh:73f2a15bee21f7c92a071e2520216d0a40041aca52c0f6682e540da8ffcfada4", - "zh:9843d6973aedfd4cbaafd7110420d0c4c1d7ef4a2eeff508294c3adcc3613145", + "h1:rUDE0OgA+6IiEA+w0cPp3/QQNH4SpjFjYcQ6p7byKS4=", + "zh:02790ad98b767d8f24d28e8be623f348bcb45590205708334d52de2fb14f5a95", + "zh:088b4398a161e45762dc28784fcc41c4fa95bd6549cb708b82de577f2d39ffc7", + "zh:0c381a457b7af391c43fc0167919443f6105ad2702bde4d02ddea9fd7c9d3539", + "zh:1a4b57a5043dcca64d8b8bae8b30ef4f6b98ed2144f792f39c4e816d3f1e2c56", + "zh:1bf00a67f39e67664337bde065180d41d952242801ebcd1c777061d4ffaa1cc1", + "zh:24c549f53d6bd022af31426d3e78f21264d8a72409821669e7fd41966ae68b2b", + "zh:3abda50bbddb35d86081fe39522e995280aea7f004582c4af22112c03ac8b375", + "zh:7388ed7f21ce2eb46bd9066626ce5f3e2a5705f67f643acce8ae71972f66eaf6", + "zh:96740f2ff94e5df2b2d29a5035a1a1026fe821f61712b2099b224fb2c2277663", "zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425", - "zh:9d1abd6be717c42f2a6257ee227d3e9548c31f01c976ed7b32b2745a63659a67", - "zh:a70d642e323021d54a92f0daa81d096cb5067cb99ce116047a42eb1cb1d579a0", - "zh:b9a2b293208d5a0449275fae463319e0998c841e0bcd4014594a49ba54bb70d6", - "zh:ce0b0eb7ac24ff58c20efcb526c3f792a95be3617c795b45bbeea9f302903ae7", - "zh:dbbf98b3cd8003833c472bdb89321c17a9bbdc1b785e7e3d75f8af924ee5a0e4", - "zh:df86cf9311a4be8bb4a251196650653f97e01fbf5fe72deecc8f28a35a5352ae", - "zh:f92992881afd9339f3e539fcd90cfc1e9ed1356b5e760bbcc804314c3cd6837f", + "zh:9f399f8e8683a3a3a6d63a41c7c3a5a5f266eedef40ea69eba75bacf03699879", + "zh:bcf2b288d4706ebd198f75d2159663d657535483331107f2cdef381f10688baf", + "zh:cc76c8a9fc3bad05a8779c1f80fe8c388734f1ec1dd0affa863343490527b466", + "zh:de4359cf1b057bfe7a563be93829ec64bf72e7a2b85a72d075238081ef5eb1db", + "zh:e208fa77051a1f9fa1eff6c5c58aabdcab0de1695b97cdea7b8dd81df3e0ed73", ] } From 70924920ec380e782e26a0ad175937285e16d4bd Mon Sep 17 00:00:00 2001 From: Alex Petre Date: Fri, 2 May 2025 14:11:00 -0400 Subject: [PATCH 10/34] DNS name & externalDNS role --- terraform/cluster/aws-eks/main.tf | 71 +++++++++++++++++++++++++++++++ windsor.yaml | 2 + 2 files changed, 73 insertions(+) diff --git a/terraform/cluster/aws-eks/main.tf b/terraform/cluster/aws-eks/main.tf index 4bb1435f..28efd82f 100644 --- a/terraform/cluster/aws-eks/main.tf +++ b/terraform/cluster/aws-eks/main.tf @@ -451,6 +451,72 @@ resource "aws_iam_role_policy_attachment" "pod_identity_agent" { role = aws_iam_role.pod_identity_agent[0].name } + +#----------------------------------------------------------------------------------------------------------------------- +# External DNS IAM Role +#----------------------------------------------------------------------------------------------------------------------- + +resource "aws_iam_role" "external_dns" { + count = contains(keys(var.addons), "external-dns") ? 1 : 0 + name = "${var.cluster_name}-external-dns-role" + + assume_role_policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Action = ["sts:AssumeRole", "sts:TagSession"] + Effect = "Allow" + Principal = { + Service = "pods.eks.amazonaws.com" + } + } + ] + }) + + tags = { + Name = "${var.cluster_name}-external-dns-role" + } +} + +resource "aws_iam_policy" "external_dns" { + count = contains(keys(var.addons), "external-dns") ? 1 : 0 + name = "${var.cluster_name}-external-dns-policy" + description = "IAM policy for External DNS" + + policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Effect = "Allow" + Action = [ + "route53:ChangeResourceRecordSets" + ] + Resource = [ + "arn:aws:route53:::hostedzone/*" + ] + }, + { + Effect = "Allow" + Action = [ + "route53:ListHostedZones", + "route53:ListResourceRecordSets" + ] + Resource = ["*"] + } + ] + }) + + tags = { + Name = "${var.cluster_name}-external-dns-policy" + } +} + +resource "aws_iam_role_policy_attachment" "external_dns" { + count = contains(keys(var.addons), "external-dns") ? 1 : 0 + policy_arn = aws_iam_policy.external_dns[0].arn + role = aws_iam_role.external_dns[0].name +} + #----------------------------------------------------------------------------------------------------------------------- # Create Add-Ons #----------------------------------------------------------------------------------------------------------------------- @@ -464,12 +530,15 @@ locals { name == "aws-ebs-csi-driver" ? try(aws_iam_role.ebs_csi[0].arn, null) : name == "aws-efs-csi-driver" ? try(aws_iam_role.efs_csi[0].arn, null) : name == "eks-pod-identity-agent" ? try(aws_iam_role.pod_identity_agent[0].arn, null) : + name == "external-dns" ? try(aws_iam_role.external_dns[0].arn, null) : null ) service_account_name = ( name == "vpc-cni" ? "aws-node" : name == "aws-ebs-csi-driver" ? "ebs-csi-controller-sa" : name == "aws-efs-csi-driver" ? "efs-csi-controller-sa" : + name == "eks-pod-identity-agent" ? "pod-identity-agent" : + name == "external-dns" ? "external-dns" : null ) tags = lookup(addon, "tags", {}) @@ -483,6 +552,8 @@ resource "aws_eks_addon" "this" { cluster_name = aws_eks_cluster.this.name addon_name = each.key addon_version = local.addon_configuration[each.key].version + resolve_conflicts_on_create = "OVERWRITE" + resolve_conflicts_on_update = "OVERWRITE" service_account_role_arn = ( each.key == "eks-pod-identity-agent" ? local.addon_configuration[each.key].role_arn : null ) diff --git a/windsor.yaml b/windsor.yaml index 72953d91..f8168a1b 100644 --- a/windsor.yaml +++ b/windsor.yaml @@ -63,3 +63,5 @@ contexts: enabled: true backend: type: local + dns: + domain: aws-test.internal \ No newline at end of file From af879f0387d656c101824183854b57c7cbc86f52 Mon Sep 17 00:00:00 2001 From: Alex Petre Date: Fri, 2 May 2025 15:46:39 -0400 Subject: [PATCH 11/34] Add testing internal hosted zone --- terraform/network/aws-vpc/main.tf | 13 +++++++++++++ terraform/network/aws-vpc/variables.tf | 6 ++++++ windsor.yaml | 4 +++- 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/terraform/network/aws-vpc/main.tf b/terraform/network/aws-vpc/main.tf index 8a7dcda9..b806a151 100644 --- a/terraform/network/aws-vpc/main.tf +++ b/terraform/network/aws-vpc/main.tf @@ -179,3 +179,16 @@ resource "aws_route_table_association" "data" { subnet_id = aws_subnet.data[count.index].id route_table_id = aws_route_table.data[count.index].id } + +#----------------------------------------------------------------------------------------------------------------------- +# Route53 Hosted Zone +#----------------------------------------------------------------------------------------------------------------------- + +resource "aws_route53_zone" "main" { + count = var.domain_name != null ? 1 : 0 + name = var.domain_name + + vpc { + vpc_id = aws_vpc.main.id + } +} diff --git a/terraform/network/aws-vpc/variables.tf b/terraform/network/aws-vpc/variables.tf index 76ccb85d..fbcabd42 100644 --- a/terraform/network/aws-vpc/variables.tf +++ b/terraform/network/aws-vpc/variables.tf @@ -55,3 +55,9 @@ variable "tags" { type = map(string) default = {} } + +variable "domain_name" { + description = "The domain name for the Route53 hosted zone" + type = string + default = null +} diff --git a/windsor.yaml b/windsor.yaml index f8168a1b..14faf34d 100644 --- a/windsor.yaml +++ b/windsor.yaml @@ -56,6 +56,8 @@ contexts: enabled: false domain: test aws-example: + environment: + TF_VAR_domain_name: aws-test.internal aws: enabled: true region: us-east-2 @@ -64,4 +66,4 @@ contexts: backend: type: local dns: - domain: aws-test.internal \ No newline at end of file + domain: aws-test.internal From 41a56ac21bd039dfc468350af13e88315daba7b1 Mon Sep 17 00:00:00 2001 From: Alex Petre Date: Mon, 5 May 2025 10:01:29 -0400 Subject: [PATCH 12/34] fmt --- terraform/cluster/aws-eks/main.tf | 16 ++++++++-------- terraform/cluster/aws-eks/variables.tf | 12 ++++++------ 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/terraform/cluster/aws-eks/main.tf b/terraform/cluster/aws-eks/main.tf index 28efd82f..5bb72979 100644 --- a/terraform/cluster/aws-eks/main.tf +++ b/terraform/cluster/aws-eks/main.tf @@ -159,16 +159,16 @@ resource "aws_launch_template" "node_group" { block_device_mappings { device_name = "/dev/xvda" ebs { - volume_size = each.value.disk_size - volume_type = "gp3" + volume_size = each.value.disk_size + volume_type = "gp3" delete_on_termination = true } } network_interfaces { associate_public_ip_address = false - delete_on_termination = true - security_groups = [aws_eks_cluster.this.vpc_config[0].cluster_security_group_id] + delete_on_termination = true + security_groups = [aws_eks_cluster.this.vpc_config[0].cluster_security_group_id] } user_data = base64encode(<<-EOT @@ -457,7 +457,7 @@ resource "aws_iam_role_policy_attachment" "pod_identity_agent" { #----------------------------------------------------------------------------------------------------------------------- resource "aws_iam_role" "external_dns" { - count = contains(keys(var.addons), "external-dns") ? 1 : 0 + count = contains(keys(var.addons), "external-dns") ? 1 : 0 name = "${var.cluster_name}-external-dns-role" assume_role_policy = jsonencode({ @@ -549,9 +549,9 @@ locals { resource "aws_eks_addon" "this" { for_each = var.addons - cluster_name = aws_eks_cluster.this.name - addon_name = each.key - addon_version = local.addon_configuration[each.key].version + cluster_name = aws_eks_cluster.this.name + addon_name = each.key + addon_version = local.addon_configuration[each.key].version resolve_conflicts_on_create = "OVERWRITE" resolve_conflicts_on_update = "OVERWRITE" service_account_role_arn = ( diff --git a/terraform/cluster/aws-eks/variables.tf b/terraform/cluster/aws-eks/variables.tf index 350a8970..b650874a 100644 --- a/terraform/cluster/aws-eks/variables.tf +++ b/terraform/cluster/aws-eks/variables.tf @@ -70,15 +70,15 @@ variable "vpc_cni_config" { description = "Configuration for the VPC CNI addon" type = object({ enable_prefix_delegation = bool - warm_prefix_target = number - warm_ip_target = number - minimum_ip_target = number + warm_prefix_target = number + warm_ip_target = number + minimum_ip_target = number }) default = { enable_prefix_delegation = true - warm_prefix_target = 1 - warm_ip_target = 1 - minimum_ip_target = 1 + warm_prefix_target = 1 + warm_ip_target = 1 + minimum_ip_target = 1 } } From d46dc7f2c5e51ec4f8b9f8d16fc128858e45f377 Mon Sep 17 00:00:00 2001 From: Alex Petre Date: Mon, 5 May 2025 10:09:11 -0400 Subject: [PATCH 13/34] checkov fixes --- terraform/cluster/aws-eks/main.tf | 48 +++++++++++++++++++++++++------ terraform/network/aws-vpc/main.tf | 2 +- 2 files changed, 41 insertions(+), 9 deletions(-) diff --git a/terraform/cluster/aws-eks/main.tf b/terraform/cluster/aws-eks/main.tf index 5bb72979..e6a177db 100644 --- a/terraform/cluster/aws-eks/main.tf +++ b/terraform/cluster/aws-eks/main.tf @@ -29,22 +29,47 @@ data "aws_region" "current" {} #----------------------------------------------------------------------------------------------------------------------- # EKS Cluster #----------------------------------------------------------------------------------------------------------------------- - resource "aws_eks_cluster" "this" { name = var.cluster_name role_arn = aws_iam_role.cluster.arn version = var.kubernetes_version vpc_config { - subnet_ids = data.aws_subnets.private.ids + subnet_ids = data.aws_subnets.private.ids + endpoint_private_access = true + endpoint_public_access = false # Disable public endpoint for security + } + + # Enable secrets encryption using AWS KMS + encryption_config { + provider { + key_arn = aws_kms_key.eks_encryption_key.arn + } + resources = ["secrets"] } + # Enable control plane logging for all log types + enabled_cluster_log_types = [ + "api", + "audit", + "authenticator", + "controllerManager", + "scheduler" + ] + depends_on = [ aws_iam_role_policy_attachment.cluster_AmazonEKSClusterPolicy, aws_iam_role_policy_attachment.cluster_AmazonEKSVPCResourceController, + aws_kms_key.eks_encryption_key, ] } +resource "aws_kms_key" "eks_encryption_key" { + description = "KMS key for EKS cluster ${var.cluster_name} secrets encryption" + deletion_window_in_days = 7 + enable_key_rotation = true +} + #----------------------------------------------------------------------------------------------------------------------- # IAM Roles #----------------------------------------------------------------------------------------------------------------------- @@ -111,7 +136,6 @@ resource "aws_iam_role_policy_attachment" "node_group_AmazonEC2ContainerRegistry #----------------------------------------------------------------------------------------------------------------------- # Node Groups #----------------------------------------------------------------------------------------------------------------------- - resource "aws_eks_node_group" "this" { for_each = var.node_groups @@ -171,6 +195,14 @@ resource "aws_launch_template" "node_group" { security_groups = [aws_eks_cluster.this.vpc_config[0].cluster_security_group_id] } + # Disable IMDSv1 and require IMDSv2 + metadata_options { + http_endpoint = "enabled" + http_tokens = "required" + http_put_response_hop_limit = 1 + instance_metadata_tags = "enabled" + } + user_data = base64encode(<<-EOT MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="==BOUNDARY==" @@ -351,14 +383,14 @@ resource "aws_iam_policy" "efs_csi" { "elasticfilesystem:DescribeMountTargets", "ec2:DescribeAvailabilityZones" ] - Resource = "*" + Resource = "arn:aws:elasticfilesystem:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:*" }, { Effect = "Allow" Action = [ "elasticfilesystem:CreateAccessPoint" ] - Resource = "*" + Resource = "arn:aws:elasticfilesystem:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:*" Condition = { StringLike = { "aws:RequestTag/efs.csi.aws.com/cluster" = "true" @@ -370,7 +402,7 @@ resource "aws_iam_policy" "efs_csi" { Action = [ "elasticfilesystem:DeleteAccessPoint" ] - Resource = "*" + Resource = "arn:aws:elasticfilesystem:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:*" Condition = { StringLike = { "aws:ResourceTag/efs.csi.aws.com/cluster" = "true" @@ -430,7 +462,7 @@ resource "aws_iam_policy" "pod_identity_agent" { Action = [ "iam:CreateServiceLinkedRole" ] - Resource = "*" + Resource = "arn:aws:iam::${data.aws_caller_identity.current.account_id}:role/eks-auth.amazonaws.com" Condition = { StringEquals = { "iam:AWSServiceName" = "eks-auth.amazonaws.com" @@ -501,7 +533,7 @@ resource "aws_iam_policy" "external_dns" { "route53:ListHostedZones", "route53:ListResourceRecordSets" ] - Resource = ["*"] + Resource = ["arn:aws:route53:::hostedzone/*"] } ] }) diff --git a/terraform/network/aws-vpc/main.tf b/terraform/network/aws-vpc/main.tf index b806a151..741453de 100644 --- a/terraform/network/aws-vpc/main.tf +++ b/terraform/network/aws-vpc/main.tf @@ -36,7 +36,7 @@ resource "aws_subnet" "public" { cidr_block = cidrsubnet(var.cidr_block, var.subnet_newbits, count.index) availability_zone = data.aws_availability_zones.available.names[count.index] - map_public_ip_on_launch = true + map_public_ip_on_launch = false # Disable automatic public IP assignment for security tags = { Name = "${var.name}-public-${data.aws_availability_zones.available.names[count.index]}" From 938e8b474a47e3dbd00ab233b6b27f110f2d37ab Mon Sep 17 00:00:00 2001 From: Alex Petre Date: Mon, 5 May 2025 10:16:01 -0400 Subject: [PATCH 14/34] checkov fixes, 2 --- terraform/cluster/aws-eks/main.tf | 34 +++++++++++- terraform/network/aws-vpc/main.tf | 92 ++++++++++++++++++++++++++++++- 2 files changed, 123 insertions(+), 3 deletions(-) diff --git a/terraform/cluster/aws-eks/main.tf b/terraform/cluster/aws-eks/main.tf index e6a177db..ac13d43f 100644 --- a/terraform/cluster/aws-eks/main.tf +++ b/terraform/cluster/aws-eks/main.tf @@ -37,7 +37,7 @@ resource "aws_eks_cluster" "this" { vpc_config { subnet_ids = data.aws_subnets.private.ids endpoint_private_access = true - endpoint_public_access = false # Disable public endpoint for security + endpoint_public_access = false # Disable public endpoint for security } # Enable secrets encryption using AWS KMS @@ -68,8 +68,40 @@ resource "aws_kms_key" "eks_encryption_key" { description = "KMS key for EKS cluster ${var.cluster_name} secrets encryption" deletion_window_in_days = 7 enable_key_rotation = true + + policy = jsonencode({ + Version = "2012-10-17", + Statement = [ + { + Sid = "Enable IAM User Permissions", + Effect = "Allow", + Principal = { + AWS = "arn:aws:iam::${data.aws_caller_identity.current.account_id}:root" + }, + Action = "kms:*", + Resource = "*" + }, + { + Sid = "Allow EKS to use the key for secrets encryption", + Effect = "Allow", + Principal = { + Service = "eks.amazonaws.com" + }, + Action = [ + "kms:Encrypt", + "kms:Decrypt", + "kms:ReEncrypt*", + "kms:GenerateDataKey*", + "kms:DescribeKey" + ], + Resource = "*" + } + ] + }) } +data "aws_caller_identity" "current" {} + #----------------------------------------------------------------------------------------------------------------------- # IAM Roles #----------------------------------------------------------------------------------------------------------------------- diff --git a/terraform/network/aws-vpc/main.tf b/terraform/network/aws-vpc/main.tf index 741453de..f1a177e1 100644 --- a/terraform/network/aws-vpc/main.tf +++ b/terraform/network/aws-vpc/main.tf @@ -23,6 +23,59 @@ resource "aws_vpc" "main" { } } +# Enable VPC Flow Logs +resource "aws_flow_log" "vpc_flow_logs" { + log_destination = aws_cloudwatch_log_group.vpc_flow_logs.arn + log_destination_type = "cloud-watch-logs" + traffic_type = "ALL" + vpc_id = aws_vpc.main.id + iam_role_arn = aws_iam_role.vpc_flow_logs.arn +} + +resource "aws_cloudwatch_log_group" "vpc_flow_logs" { + name = "/aws/vpc-flow-logs/${var.name}" + retention_in_days = 30 + + tags = { + Name = "${var.name}-vpc-flow-logs" + } +} + +resource "aws_iam_role" "vpc_flow_logs" { + name = "${var.name}-vpc-flow-logs-role" + + assume_role_policy = jsonencode({ + Version = "2012-10-17" + Statement = [{ + Action = "sts:AssumeRole" + Effect = "Allow" + Principal = { + Service = "vpc-flow-logs.amazonaws.com" + } + }] + }) +} + +resource "aws_iam_role_policy" "vpc_flow_logs" { + name = "${var.name}-vpc-flow-logs-policy" + role = aws_iam_role.vpc_flow_logs.id + + policy = jsonencode({ + Version = "2012-10-17" + Statement = [{ + Action = [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents", + "logs:DescribeLogGroups", + "logs:DescribeLogStreams" + ] + Effect = "Allow" + Resource = "arn:aws:logs:*:*:log-group:/aws/vpc-flow-logs/*" + }] + }) +} + #----------------------------------------------------------------------------------------------------------------------- # Subnets #----------------------------------------------------------------------------------------------------------------------- @@ -36,7 +89,7 @@ resource "aws_subnet" "public" { cidr_block = cidrsubnet(var.cidr_block, var.subnet_newbits, count.index) availability_zone = data.aws_availability_zones.available.names[count.index] - map_public_ip_on_launch = false # Disable automatic public IP assignment for security + map_public_ip_on_launch = false # Disable automatic public IP assignment for security tags = { Name = "${var.name}-public-${data.aws_availability_zones.available.names[count.index]}" @@ -183,7 +236,6 @@ resource "aws_route_table_association" "data" { #----------------------------------------------------------------------------------------------------------------------- # Route53 Hosted Zone #----------------------------------------------------------------------------------------------------------------------- - resource "aws_route53_zone" "main" { count = var.domain_name != null ? 1 : 0 name = var.domain_name @@ -192,3 +244,39 @@ resource "aws_route53_zone" "main" { vpc_id = aws_vpc.main.id } } + +# Enable DNS query logging for Route53 hosted zone +resource "aws_cloudwatch_log_group" "route53_query_logs" { + count = var.domain_name != null ? 1 : 0 + name = "/aws/route53/${var.domain_name}" + + retention_in_days = 30 + + tags = { + Name = "${var.name}-route53-query-logs" + } +} + +resource "aws_route53_query_log" "main" { + count = var.domain_name != null ? 1 : 0 + depends_on = [aws_cloudwatch_log_resource_policy.route53_query_logging] + cloudwatch_log_group_arn = aws_cloudwatch_log_group.route53_query_logs[0].arn + zone_id = aws_route53_zone.main[0].zone_id +} + +resource "aws_cloudwatch_log_resource_policy" "route53_query_logging" { + count = var.domain_name != null ? 1 : 0 + policy_name = "route53-query-logging-policy" + policy_document = jsonencode({ + Version = "2012-10-17" + Statement = [{ + Action = [ + "logs:CreateLogStream", + "logs:PutLogEvents", + ] + Effect = "Allow" + Principal = { Service = "route53.amazonaws.com" } + Resource = "arn:aws:logs:*:*:log-group:/aws/route53/*" + }] + }) +} From 5aa11228368f7289f1c567d12eaf864bbfa41cc4 Mon Sep 17 00:00:00 2001 From: Alex Petre Date: Mon, 5 May 2025 10:24:01 -0400 Subject: [PATCH 15/34] checkov fixes, 3 --- terraform/network/aws-vpc/main.tf | 62 ++++++++++++++++++++++++++++++- 1 file changed, 60 insertions(+), 2 deletions(-) diff --git a/terraform/network/aws-vpc/main.tf b/terraform/network/aws-vpc/main.tf index f1a177e1..9398d6c0 100644 --- a/terraform/network/aws-vpc/main.tf +++ b/terraform/network/aws-vpc/main.tf @@ -9,6 +9,10 @@ terraform { } } +data "aws_caller_identity" "current" {} + +data "aws_region" "current" {} + #----------------------------------------------------------------------------------------------------------------------- # AWS VPC Configuration #----------------------------------------------------------------------------------------------------------------------- @@ -34,13 +38,50 @@ resource "aws_flow_log" "vpc_flow_logs" { resource "aws_cloudwatch_log_group" "vpc_flow_logs" { name = "/aws/vpc-flow-logs/${var.name}" - retention_in_days = 30 + retention_in_days = 365 + kms_key_id = aws_kms_key.cloudwatch_logs_encryption.arn tags = { Name = "${var.name}-vpc-flow-logs" } } +resource "aws_kms_key" "cloudwatch_logs_encryption" { + description = "KMS key for CloudWatch Logs encryption" + deletion_window_in_days = 7 + enable_key_rotation = true + + policy = jsonencode({ + Version = "2012-10-17", + Statement = [ + { + Sid = "Enable IAM User Permissions", + Effect = "Allow", + Principal = { + AWS = "arn:aws:iam::${data.aws_caller_identity.current.account_id}:root" + }, + Action = "kms:*", + Resource = "*" + }, + { + Sid = "Allow CloudWatch Logs to use the key", + Effect = "Allow", + Principal = { + Service = "logs.${data.aws_region.current.name}.amazonaws.com" + }, + Action = [ + "kms:Encrypt", + "kms:Decrypt", + "kms:ReEncrypt*", + "kms:GenerateDataKey*", + "kms:DescribeKey" + ], + Resource = "*" + } + ] + }) +} + resource "aws_iam_role" "vpc_flow_logs" { name = "${var.name}-vpc-flow-logs-role" @@ -250,7 +291,7 @@ resource "aws_cloudwatch_log_group" "route53_query_logs" { count = var.domain_name != null ? 1 : 0 name = "/aws/route53/${var.domain_name}" - retention_in_days = 30 + retention_in_days = 365 tags = { Name = "${var.name}-route53-query-logs" @@ -280,3 +321,20 @@ resource "aws_cloudwatch_log_resource_policy" "route53_query_logging" { }] }) } + +# Enable DNSSEC for the hosted zone +resource "aws_route53_hosted_zone_dnssec" "main" { + count = var.domain_name != null ? 1 : 0 + + hosted_zone_id = aws_route53_zone.main[0].zone_id +} + +# Optionally, define a key signing key (KSK) for DNSSEC +resource "aws_route53_key_signing_key" "main" { + count = var.domain_name != null ? 1 : 0 + hosted_zone_id = aws_route53_zone.main[0].zone_id + name = "${var.name}-ksk" + key_management_service_arn = aws_kms_key.cloudwatch_logs_encryption.arn + status = "ACTIVE" +} + From 0771d4705332b2dec541cfab47c3fce6c8d0f4ce Mon Sep 17 00:00:00 2001 From: Alex Petre Date: Mon, 5 May 2025 15:13:27 -0400 Subject: [PATCH 16/34] unify default vpc name --- terraform/cluster/aws-eks/main.tf | 10 +++++++++- terraform/cluster/aws-eks/variables.tf | 2 +- terraform/network/aws-vpc/variables.tf | 2 +- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/terraform/cluster/aws-eks/main.tf b/terraform/cluster/aws-eks/main.tf index ac13d43f..1ffc3a62 100644 --- a/terraform/cluster/aws-eks/main.tf +++ b/terraform/cluster/aws-eks/main.tf @@ -13,6 +13,14 @@ terraform { # Data #----------------------------------------------------------------------------------------------------------------------- +data "aws_vpc" "default" { + count = var.vpc_id == null ? 1 : 0 + filter { + name = "tag:Name" + values = ["${var.cluster_name}-vpc"] + } +} + data "aws_subnets" "private" { filter { name = "tag:Tier" @@ -20,7 +28,7 @@ data "aws_subnets" "private" { } filter { name = "vpc-id" - values = [var.vpc_id] + values = [var.vpc_id != null ? var.vpc_id : data.aws_vpc.default[0].id] } } diff --git a/terraform/cluster/aws-eks/variables.tf b/terraform/cluster/aws-eks/variables.tf index b650874a..c6b32b54 100644 --- a/terraform/cluster/aws-eks/variables.tf +++ b/terraform/cluster/aws-eks/variables.tf @@ -32,7 +32,7 @@ variable "kubernetes_version" { variable "vpc_id" { description = "The ID of the VPC where the EKS cluster will be created." type = string - default = "vpc-0c2bbc3cc4734c126" + default = null } variable "node_groups" { diff --git a/terraform/network/aws-vpc/variables.tf b/terraform/network/aws-vpc/variables.tf index fbcabd42..84ffee95 100644 --- a/terraform/network/aws-vpc/variables.tf +++ b/terraform/network/aws-vpc/variables.tf @@ -5,7 +5,7 @@ variable "name" { description = "Name prefix for all resources in the VPC" type = string - default = "main" + default = "windsor-core" } variable "cidr_block" { From c8f841a3a411963f83bb6af0bbcbe765cf577edc Mon Sep 17 00:00:00 2001 From: Alex Petre Date: Mon, 5 May 2025 17:02:35 -0400 Subject: [PATCH 17/34] mkdir -p --- terraform/cluster/aws-eks/main.tf | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/terraform/cluster/aws-eks/main.tf b/terraform/cluster/aws-eks/main.tf index 1ffc3a62..d468c3b9 100644 --- a/terraform/cluster/aws-eks/main.tf +++ b/terraform/cluster/aws-eks/main.tf @@ -661,6 +661,16 @@ locals { kubeconfig_path = "${var.context_path}/.kube/config" } +# Create the kubeconfig directory if it doesn't exist +resource "null_resource" "create_kubeconfig_dir" { + count = local.kubeconfig_path != "" ? 1 : 0 + + provisioner "local-exec" { + command = "mkdir -p $(dirname ${local.kubeconfig_path})" + } +} + + resource "local_sensitive_file" "kubeconfig" { count = local.kubeconfig_path != "" ? 1 : 0 From 79c3fb0d0cc04851777fdaa9515251894a536b47 Mon Sep 17 00:00:00 2001 From: Alex Petre Date: Tue, 6 May 2025 10:46:35 -0400 Subject: [PATCH 18/34] override temporarily --- terraform/cluster/aws-eks/main.tf | 2 +- terraform/cluster/aws-eks/variables.tf | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/terraform/cluster/aws-eks/main.tf b/terraform/cluster/aws-eks/main.tf index d468c3b9..1cc7395d 100644 --- a/terraform/cluster/aws-eks/main.tf +++ b/terraform/cluster/aws-eks/main.tf @@ -658,7 +658,7 @@ resource "aws_eks_addon" "this" { #----------------------------------------------------------------------------------------------------------------------- locals { - kubeconfig_path = "${var.context_path}/.kube/config" + kubeconfig_path = "${var.context_path_override}/.kube/config" } # Create the kubeconfig directory if it doesn't exist diff --git a/terraform/cluster/aws-eks/variables.tf b/terraform/cluster/aws-eks/variables.tf index c6b32b54..67a79388 100644 --- a/terraform/cluster/aws-eks/variables.tf +++ b/terraform/cluster/aws-eks/variables.tf @@ -3,7 +3,7 @@ # Variables #----------------------------------------------------------------------------------------------------------------------- -variable "context_path" { +variable "context_path_override" { type = string description = "The path to the context folder, where kubeconfig is stored" default = "" From d050428f7c56438aa507ec8cdada9d50f37bef91 Mon Sep 17 00:00:00 2001 From: Alex Petre Date: Tue, 6 May 2025 11:31:25 -0400 Subject: [PATCH 19/34] something --- terraform/cluster/aws-eks/main.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/terraform/cluster/aws-eks/main.tf b/terraform/cluster/aws-eks/main.tf index 1cc7395d..9fddd972 100644 --- a/terraform/cluster/aws-eks/main.tf +++ b/terraform/cluster/aws-eks/main.tf @@ -658,7 +658,7 @@ resource "aws_eks_addon" "this" { #----------------------------------------------------------------------------------------------------------------------- locals { - kubeconfig_path = "${var.context_path_override}/.kube/config" + kubeconfig_path = "${var.something}/.kube/config" } # Create the kubeconfig directory if it doesn't exist From 555b4293d9c2fe5c55f8c22f3b3a16b8315437cc Mon Sep 17 00:00:00 2001 From: Alex Petre Date: Tue, 6 May 2025 11:32:42 -0400 Subject: [PATCH 20/34] something var --- terraform/cluster/aws-eks/variables.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/terraform/cluster/aws-eks/variables.tf b/terraform/cluster/aws-eks/variables.tf index 67a79388..a38795f0 100644 --- a/terraform/cluster/aws-eks/variables.tf +++ b/terraform/cluster/aws-eks/variables.tf @@ -3,7 +3,7 @@ # Variables #----------------------------------------------------------------------------------------------------------------------- -variable "context_path_override" { +variable "something" { type = string description = "The path to the context folder, where kubeconfig is stored" default = "" From 7a6e6ded42ea1d43776831e3d9d8c16793f94082 Mon Sep 17 00:00:00 2001 From: Alex Petre Date: Wed, 7 May 2025 09:46:08 -0400 Subject: [PATCH 21/34] remove default value --- terraform/cluster/aws-eks/variables.tf | 1 - 1 file changed, 1 deletion(-) diff --git a/terraform/cluster/aws-eks/variables.tf b/terraform/cluster/aws-eks/variables.tf index a38795f0..1fdedbaf 100644 --- a/terraform/cluster/aws-eks/variables.tf +++ b/terraform/cluster/aws-eks/variables.tf @@ -6,7 +6,6 @@ variable "something" { type = string description = "The path to the context folder, where kubeconfig is stored" - default = "" } variable "cluster_name" { From 6fb6b86835d56afeb1f217aa35f67c0db8973a74 Mon Sep 17 00:00:00 2001 From: Alex Petre Date: Fri, 9 May 2025 10:24:59 -0400 Subject: [PATCH 22/34] back to context_path --- terraform/cluster/aws-eks/main.tf | 2 +- terraform/cluster/aws-eks/variables.tf | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/terraform/cluster/aws-eks/main.tf b/terraform/cluster/aws-eks/main.tf index 9fddd972..d468c3b9 100644 --- a/terraform/cluster/aws-eks/main.tf +++ b/terraform/cluster/aws-eks/main.tf @@ -658,7 +658,7 @@ resource "aws_eks_addon" "this" { #----------------------------------------------------------------------------------------------------------------------- locals { - kubeconfig_path = "${var.something}/.kube/config" + kubeconfig_path = "${var.context_path}/.kube/config" } # Create the kubeconfig directory if it doesn't exist diff --git a/terraform/cluster/aws-eks/variables.tf b/terraform/cluster/aws-eks/variables.tf index 1fdedbaf..c6b32b54 100644 --- a/terraform/cluster/aws-eks/variables.tf +++ b/terraform/cluster/aws-eks/variables.tf @@ -3,9 +3,10 @@ # Variables #----------------------------------------------------------------------------------------------------------------------- -variable "something" { +variable "context_path" { type = string description = "The path to the context folder, where kubeconfig is stored" + default = "" } variable "cluster_name" { From 68ccb5d88d9cb6cb1dccfe87ac9efd257d9ec3a6 Mon Sep 17 00:00:00 2001 From: Alex Petre Date: Tue, 13 May 2025 14:03:35 -0400 Subject: [PATCH 23/34] remove outputs for now --- terraform/cluster/aws-eks/outputs.tf | 40 ++++++++++++++-------------- terraform/network/aws-vpc/outputs.tf | 32 +++++++++++----------- 2 files changed, 36 insertions(+), 36 deletions(-) diff --git a/terraform/cluster/aws-eks/outputs.tf b/terraform/cluster/aws-eks/outputs.tf index 51b15a25..730e5ef0 100644 --- a/terraform/cluster/aws-eks/outputs.tf +++ b/terraform/cluster/aws-eks/outputs.tf @@ -2,27 +2,27 @@ # Outputs #----------------------------------------------------------------------------------------------------------------------- -output "cluster_id" { - description = "The name/id of the EKS cluster." - value = aws_eks_cluster.this.id -} +# output "cluster_id" { +# description = "The name/id of the EKS cluster." +# value = aws_eks_cluster.this.id +# } -output "cluster_arn" { - description = "The Amazon Resource Name (ARN) of the cluster." - value = aws_eks_cluster.this.arn -} +# output "cluster_arn" { +# description = "The Amazon Resource Name (ARN) of the cluster." +# value = aws_eks_cluster.this.arn +# } -output "cluster_endpoint" { - description = "The endpoint for the Kubernetes API server." - value = aws_eks_cluster.this.endpoint -} +# output "cluster_endpoint" { +# description = "The endpoint for the Kubernetes API server." +# value = aws_eks_cluster.this.endpoint +# } -output "cluster_security_group_id" { - description = "The security group ID attached to the EKS cluster." - value = aws_eks_cluster.this.vpc_config[0].cluster_security_group_id -} +# output "cluster_security_group_id" { +# description = "The security group ID attached to the EKS cluster." +# value = aws_eks_cluster.this.vpc_config[0].cluster_security_group_id +# } -output "kubeconfig_certificate_authority_data" { - description = "The base64 encoded certificate data required to communicate with the cluster." - value = aws_eks_cluster.this.certificate_authority[0].data -} +# output "kubeconfig_certificate_authority_data" { +# description = "The base64 encoded certificate data required to communicate with the cluster." +# value = aws_eks_cluster.this.certificate_authority[0].data +# } diff --git a/terraform/network/aws-vpc/outputs.tf b/terraform/network/aws-vpc/outputs.tf index 1281f382..3ef8d93e 100644 --- a/terraform/network/aws-vpc/outputs.tf +++ b/terraform/network/aws-vpc/outputs.tf @@ -2,22 +2,22 @@ # Outputs #----------------------------------------------------------------------------------------------------------------------- -output "vpc_id" { - description = "The ID of the VPC" - value = aws_vpc.main.id -} +# output "vpc_id" { +# description = "The ID of the VPC" +# value = aws_vpc.main.id +# } -output "public_subnet_ids" { - description = "List of public subnet IDs" - value = aws_subnet.public[*].id -} +# output "public_subnet_ids" { +# description = "List of public subnet IDs" +# value = aws_subnet.public[*].id +# } -output "private_subnet_ids" { - description = "List of private subnet IDs" - value = aws_subnet.private[*].id -} +# output "private_subnet_ids" { +# description = "List of private subnet IDs" +# value = aws_subnet.private[*].id +# } -output "data_subnet_ids" { - description = "List of data subnet IDs" - value = aws_subnet.data[*].id -} +# output "data_subnet_ids" { +# description = "List of data subnet IDs" +# value = aws_subnet.data[*].id +# } From 77f0a735907dbd3bdb017c38b562b0062b4b14f6 Mon Sep 17 00:00:00 2001 From: Alex Petre Date: Tue, 13 May 2025 14:45:28 -0400 Subject: [PATCH 24/34] implement default with context id --- terraform/cluster/aws-eks/main.tf | 52 +++++++------- terraform/cluster/aws-eks/variables.tf | 12 ++-- terraform/network/aws-vpc/main.tf | 94 +++++++------------------- terraform/network/aws-vpc/variables.tf | 8 ++- 4 files changed, 67 insertions(+), 99 deletions(-) diff --git a/terraform/cluster/aws-eks/main.tf b/terraform/cluster/aws-eks/main.tf index d468c3b9..e88b0ad0 100644 --- a/terraform/cluster/aws-eks/main.tf +++ b/terraform/cluster/aws-eks/main.tf @@ -9,6 +9,10 @@ terraform { } } +locals { + name = var.cluster_name != "" ? var.cluster_name : "windsor-core-${var.context_id}" +} + #----------------------------------------------------------------------------------------------------------------------- # Data #----------------------------------------------------------------------------------------------------------------------- @@ -16,8 +20,8 @@ terraform { data "aws_vpc" "default" { count = var.vpc_id == null ? 1 : 0 filter { - name = "tag:Name" - values = ["${var.cluster_name}-vpc"] + name = "tag:WindsorContextID" + values = [var.context_id] } } @@ -38,7 +42,7 @@ data "aws_region" "current" {} # EKS Cluster #----------------------------------------------------------------------------------------------------------------------- resource "aws_eks_cluster" "this" { - name = var.cluster_name + name = local.name role_arn = aws_iam_role.cluster.arn version = var.kubernetes_version @@ -73,7 +77,7 @@ resource "aws_eks_cluster" "this" { } resource "aws_kms_key" "eks_encryption_key" { - description = "KMS key for EKS cluster ${var.cluster_name} secrets encryption" + description = "KMS key for EKS cluster ${local.name} secrets encryption" deletion_window_in_days = 7 enable_key_rotation = true @@ -115,7 +119,7 @@ data "aws_caller_identity" "current" {} #----------------------------------------------------------------------------------------------------------------------- resource "aws_iam_role" "cluster" { - name = "${var.cluster_name}-cluster-role" + name = "${local.name}-cluster-role" assume_role_policy = jsonencode({ Version = "2012-10-17" @@ -142,7 +146,7 @@ resource "aws_iam_role_policy_attachment" "cluster_AmazonEKSVPCResourceControlle } resource "aws_iam_role" "node_group" { - name = "${var.cluster_name}-node-group-role" + name = "${local.name}-node-group-role" assume_role_policy = jsonencode({ Version = "2012-10-17" @@ -218,7 +222,7 @@ resource "aws_eks_node_group" "this" { resource "aws_launch_template" "node_group" { for_each = var.node_groups - name = "${var.cluster_name}-${each.key}" + name = "${local.name}-${each.key}" block_device_mappings { device_name = "/dev/xvda" @@ -264,7 +268,7 @@ EOT #----------------------------------------------------------------------------------------------------------------------- resource "aws_iam_role" "fargate" { - name = "${var.cluster_name}-fargate-profile" + name = "${local.name}-fargate-profile" assume_role_policy = jsonencode({ Version = "2012-10-17" @@ -322,7 +326,7 @@ data "aws_eks_addon_version" "default" { resource "aws_iam_role" "vpc_cni" { count = contains(keys(var.addons), "vpc-cni") ? 1 : 0 - name = "${var.cluster_name}-vpc-cni-role" + name = "${local.name}-vpc-cni-role" assume_role_policy = jsonencode({ Version = "2012-10-17" @@ -338,7 +342,7 @@ resource "aws_iam_role" "vpc_cni" { }) tags = { - Name = "${var.cluster_name}-vpc-cni-role" + Name = "${local.name}-vpc-cni-role" } } @@ -355,7 +359,7 @@ resource "aws_iam_role_policy_attachment" "vpc_cni" { resource "aws_iam_role" "ebs_csi" { count = contains(keys(var.addons), "aws-ebs-csi-driver") ? 1 : 0 - name = "${var.cluster_name}-aws-ebs-csi-driver-role" + name = "${local.name}-aws-ebs-csi-driver-role" assume_role_policy = jsonencode({ Version = "2012-10-17" @@ -371,7 +375,7 @@ resource "aws_iam_role" "ebs_csi" { }) tags = { - Name = "${var.cluster_name}-aws-ebs-csi-driver-role" + Name = "${local.name}-aws-ebs-csi-driver-role" } } @@ -387,7 +391,7 @@ resource "aws_iam_role_policy_attachment" "ebs_csi" { resource "aws_iam_role" "efs_csi" { count = contains(keys(var.addons), "aws-efs-csi-driver") ? 1 : 0 - name = "${var.cluster_name}-aws-efs-csi-driver-role" + name = "${local.name}-aws-efs-csi-driver-role" assume_role_policy = jsonencode({ Version = "2012-10-17" @@ -403,13 +407,13 @@ resource "aws_iam_role" "efs_csi" { }) tags = { - Name = "${var.cluster_name}-aws-efs-csi-driver-role" + Name = "${local.name}-aws-efs-csi-driver-role" } } resource "aws_iam_policy" "efs_csi" { count = contains(keys(var.addons), "aws-efs-csi-driver") ? 1 : 0 - name = "${var.cluster_name}-aws-efs-csi-driver-policy" + name = "${local.name}-aws-efs-csi-driver-policy" description = "IAM policy for EFS CSI Driver" policy = jsonencode({ @@ -453,7 +457,7 @@ resource "aws_iam_policy" "efs_csi" { }) tags = { - Name = "${var.cluster_name}-aws-efs-csi-driver-policy" + Name = "${local.name}-aws-efs-csi-driver-policy" } } @@ -469,7 +473,7 @@ resource "aws_iam_role_policy_attachment" "efs_csi" { resource "aws_iam_role" "pod_identity_agent" { count = contains(keys(var.addons), "pod-identity-agent") ? 1 : 0 - name = "${var.cluster_name}-pod-identity-agent-role" + name = "${local.name}-pod-identity-agent-role" assume_role_policy = jsonencode({ Version = "2012-10-17" @@ -485,13 +489,13 @@ resource "aws_iam_role" "pod_identity_agent" { }) tags = { - Name = "${var.cluster_name}-pod-identity-agent-role" + Name = "${local.name}-pod-identity-agent-role" } } resource "aws_iam_policy" "pod_identity_agent" { count = contains(keys(var.addons), "pod-identity-agent") ? 1 : 0 - name = "${var.cluster_name}-pod-identity-agent-policy" + name = "${local.name}-pod-identity-agent-policy" description = "IAM policy for EKS Pod Identity Agent" policy = jsonencode({ @@ -513,7 +517,7 @@ resource "aws_iam_policy" "pod_identity_agent" { }) tags = { - Name = "${var.cluster_name}-pod-identity-agent-policy" + Name = "${local.name}-pod-identity-agent-policy" } } @@ -530,7 +534,7 @@ resource "aws_iam_role_policy_attachment" "pod_identity_agent" { resource "aws_iam_role" "external_dns" { count = contains(keys(var.addons), "external-dns") ? 1 : 0 - name = "${var.cluster_name}-external-dns-role" + name = "${local.name}-external-dns-role" assume_role_policy = jsonencode({ Version = "2012-10-17" @@ -546,13 +550,13 @@ resource "aws_iam_role" "external_dns" { }) tags = { - Name = "${var.cluster_name}-external-dns-role" + Name = "${local.name}-external-dns-role" } } resource "aws_iam_policy" "external_dns" { count = contains(keys(var.addons), "external-dns") ? 1 : 0 - name = "${var.cluster_name}-external-dns-policy" + name = "${local.name}-external-dns-policy" description = "IAM policy for External DNS" policy = jsonencode({ @@ -579,7 +583,7 @@ resource "aws_iam_policy" "external_dns" { }) tags = { - Name = "${var.cluster_name}-external-dns-policy" + Name = "${local.name}-external-dns-policy" } } diff --git a/terraform/cluster/aws-eks/variables.tf b/terraform/cluster/aws-eks/variables.tf index c6b32b54..c1a37e66 100644 --- a/terraform/cluster/aws-eks/variables.tf +++ b/terraform/cluster/aws-eks/variables.tf @@ -9,14 +9,16 @@ variable "context_path" { default = "" } +variable "context_id" { + type = string + description = "The windsor context id for this deployment" + default = "" +} + variable "cluster_name" { description = "The name of the EKS cluster." type = string - default = "windsor-core" - validation { - condition = length(var.cluster_name) > 0 - error_message = "The cluster name must not be empty." - } + default = "" } variable "kubernetes_version" { diff --git a/terraform/network/aws-vpc/main.tf b/terraform/network/aws-vpc/main.tf index 9398d6c0..ba0f1aeb 100644 --- a/terraform/network/aws-vpc/main.tf +++ b/terraform/network/aws-vpc/main.tf @@ -13,6 +13,10 @@ data "aws_caller_identity" "current" {} data "aws_region" "current" {} +locals { + name = var.name != "" ? var.name : "windsor-core-${var.context_id}" +} + #----------------------------------------------------------------------------------------------------------------------- # AWS VPC Configuration #----------------------------------------------------------------------------------------------------------------------- @@ -23,7 +27,8 @@ resource "aws_vpc" "main" { enable_dns_hostnames = true tags = { - Name = "${var.name}-vpc" + Name = local.name + WindsorContextID = var.context_id } } @@ -37,12 +42,12 @@ resource "aws_flow_log" "vpc_flow_logs" { } resource "aws_cloudwatch_log_group" "vpc_flow_logs" { - name = "/aws/vpc-flow-logs/${var.name}" + name = "/aws/vpc-flow-logs/${local.name}" retention_in_days = 365 kms_key_id = aws_kms_key.cloudwatch_logs_encryption.arn tags = { - Name = "${var.name}-vpc-flow-logs" + Name = "${local.name}-vpc-flow-logs" } } @@ -83,7 +88,7 @@ resource "aws_kms_key" "cloudwatch_logs_encryption" { } resource "aws_iam_role" "vpc_flow_logs" { - name = "${var.name}-vpc-flow-logs-role" + name = "${local.name}-vpc-flow-logs-role" assume_role_policy = jsonencode({ Version = "2012-10-17" @@ -98,7 +103,7 @@ resource "aws_iam_role" "vpc_flow_logs" { } resource "aws_iam_role_policy" "vpc_flow_logs" { - name = "${var.name}-vpc-flow-logs-policy" + name = "${local.name}-vpc-flow-logs-policy" role = aws_iam_role.vpc_flow_logs.id policy = jsonencode({ @@ -133,7 +138,7 @@ resource "aws_subnet" "public" { map_public_ip_on_launch = false # Disable automatic public IP assignment for security tags = { - Name = "${var.name}-public-${data.aws_availability_zones.available.names[count.index]}" + Name = "${local.name}-public-${data.aws_availability_zones.available.names[count.index]}" Tier = "public" } } @@ -142,11 +147,13 @@ resource "aws_subnet" "public" { resource "aws_subnet" "private" { count = var.availability_zones vpc_id = aws_vpc.main.id - cidr_block = cidrsubnet(var.cidr_block, var.subnet_newbits, count.index + length(data.aws_availability_zones.available.names)) + cidr_block = cidrsubnet( + var.cidr_block, var.subnet_newbits, count.index + length(data.aws_availability_zones.available.names) + ) availability_zone = data.aws_availability_zones.available.names[count.index] tags = { - Name = "${var.name}-private-${data.aws_availability_zones.available.names[count.index]}" + Name = "${local.name}-private-${data.aws_availability_zones.available.names[count.index]}" Tier = "private" } } @@ -155,11 +162,13 @@ resource "aws_subnet" "private" { resource "aws_subnet" "data" { count = var.availability_zones vpc_id = aws_vpc.main.id - cidr_block = cidrsubnet(var.cidr_block, var.subnet_newbits, count.index + 2 * length(data.aws_availability_zones.available.names)) + cidr_block = cidrsubnet( + var.cidr_block, var.subnet_newbits, count.index + 2 * length(data.aws_availability_zones.available.names) + ) availability_zone = data.aws_availability_zones.available.names[count.index] tags = { - Name = "${var.name}-data-${data.aws_availability_zones.available.names[count.index]}" + Name = "${local.name}-data-${data.aws_availability_zones.available.names[count.index]}" Tier = "data" } } @@ -172,7 +181,7 @@ resource "aws_internet_gateway" "main" { vpc_id = aws_vpc.main.id tags = { - Name = "${var.name}-igw" + Name = "${local.name}-igw" } } @@ -185,7 +194,7 @@ resource "aws_eip" "nat" { domain = "vpc" tags = { - Name = "${var.name}-nat-eip-${data.aws_availability_zones.available.names[count.index]}" + Name = "${local.name}-nat-eip-${data.aws_availability_zones.available.names[count.index]}" } } @@ -195,7 +204,7 @@ resource "aws_nat_gateway" "main" { subnet_id = aws_subnet.public[count.index].id tags = { - Name = "${var.name}-nat-${data.aws_availability_zones.available.names[count.index]}" + Name = "${local.name}-nat-${data.aws_availability_zones.available.names[count.index]}" } depends_on = [aws_internet_gateway.main] @@ -215,7 +224,7 @@ resource "aws_route_table" "public" { } tags = { - Name = "${var.name}-public-rt" + Name = "${local.name}-public-rt" } } @@ -230,7 +239,7 @@ resource "aws_route_table" "private" { } tags = { - Name = "${var.name}-private-rt-${data.aws_availability_zones.available.names[count.index]}" + Name = "${local.name}-private-rt-${data.aws_availability_zones.available.names[count.index]}" } } @@ -245,7 +254,7 @@ resource "aws_route_table" "data" { } tags = { - Name = "${var.name}-data-rt-${data.aws_availability_zones.available.names[count.index]}" + Name = "${local.name}-data-rt-${data.aws_availability_zones.available.names[count.index]}" } } @@ -285,56 +294,3 @@ resource "aws_route53_zone" "main" { vpc_id = aws_vpc.main.id } } - -# Enable DNS query logging for Route53 hosted zone -resource "aws_cloudwatch_log_group" "route53_query_logs" { - count = var.domain_name != null ? 1 : 0 - name = "/aws/route53/${var.domain_name}" - - retention_in_days = 365 - - tags = { - Name = "${var.name}-route53-query-logs" - } -} - -resource "aws_route53_query_log" "main" { - count = var.domain_name != null ? 1 : 0 - depends_on = [aws_cloudwatch_log_resource_policy.route53_query_logging] - cloudwatch_log_group_arn = aws_cloudwatch_log_group.route53_query_logs[0].arn - zone_id = aws_route53_zone.main[0].zone_id -} - -resource "aws_cloudwatch_log_resource_policy" "route53_query_logging" { - count = var.domain_name != null ? 1 : 0 - policy_name = "route53-query-logging-policy" - policy_document = jsonencode({ - Version = "2012-10-17" - Statement = [{ - Action = [ - "logs:CreateLogStream", - "logs:PutLogEvents", - ] - Effect = "Allow" - Principal = { Service = "route53.amazonaws.com" } - Resource = "arn:aws:logs:*:*:log-group:/aws/route53/*" - }] - }) -} - -# Enable DNSSEC for the hosted zone -resource "aws_route53_hosted_zone_dnssec" "main" { - count = var.domain_name != null ? 1 : 0 - - hosted_zone_id = aws_route53_zone.main[0].zone_id -} - -# Optionally, define a key signing key (KSK) for DNSSEC -resource "aws_route53_key_signing_key" "main" { - count = var.domain_name != null ? 1 : 0 - hosted_zone_id = aws_route53_zone.main[0].zone_id - name = "${var.name}-ksk" - key_management_service_arn = aws_kms_key.cloudwatch_logs_encryption.arn - status = "ACTIVE" -} - diff --git a/terraform/network/aws-vpc/variables.tf b/terraform/network/aws-vpc/variables.tf index 84ffee95..334a64d6 100644 --- a/terraform/network/aws-vpc/variables.tf +++ b/terraform/network/aws-vpc/variables.tf @@ -2,10 +2,16 @@ # Variables #----------------------------------------------------------------------------------------------------------------------- +variable "context_id" { + type = string + description = "The windsor context id for this deployment" + default = "" +} + variable "name" { description = "Name prefix for all resources in the VPC" type = string - default = "windsor-core" + default = "" } variable "cidr_block" { From c9b8d7a09bf8f4af25e689cc6fff2ea55e5c9dc2 Mon Sep 17 00:00:00 2001 From: Alex Petre Date: Tue, 13 May 2025 15:17:40 -0400 Subject: [PATCH 25/34] allow public access to eks api --- terraform/cluster/aws-eks/main.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/terraform/cluster/aws-eks/main.tf b/terraform/cluster/aws-eks/main.tf index e88b0ad0..fa9974b6 100644 --- a/terraform/cluster/aws-eks/main.tf +++ b/terraform/cluster/aws-eks/main.tf @@ -49,7 +49,7 @@ resource "aws_eks_cluster" "this" { vpc_config { subnet_ids = data.aws_subnets.private.ids endpoint_private_access = true - endpoint_public_access = false # Disable public endpoint for security + endpoint_public_access = true # Disable public endpoint for security } # Enable secrets encryption using AWS KMS From 2bc12aae53ad0589c6127b4722df280b491d999c Mon Sep 17 00:00:00 2001 From: Alex Petre Date: Tue, 13 May 2025 15:33:08 -0400 Subject: [PATCH 26/34] change external-dns policy --- terraform/cluster/aws-eks/main.tf | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/terraform/cluster/aws-eks/main.tf b/terraform/cluster/aws-eks/main.tf index fa9974b6..d890fd46 100644 --- a/terraform/cluster/aws-eks/main.tf +++ b/terraform/cluster/aws-eks/main.tf @@ -567,9 +567,7 @@ resource "aws_iam_policy" "external_dns" { Action = [ "route53:ChangeResourceRecordSets" ] - Resource = [ - "arn:aws:route53:::hostedzone/*" - ] + Resource = ["*"] }, { Effect = "Allow" @@ -577,7 +575,7 @@ resource "aws_iam_policy" "external_dns" { "route53:ListHostedZones", "route53:ListResourceRecordSets" ] - Resource = ["arn:aws:route53:::hostedzone/*"] + Resource = ["*"] } ] }) From f2542c4a78b3bfd88b80faf34353c8c62407acfa Mon Sep 17 00:00:00 2001 From: Alex Petre Date: Wed, 14 May 2025 12:19:50 -0400 Subject: [PATCH 27/34] efs perms --- terraform/cluster/aws-eks/main.tf | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/terraform/cluster/aws-eks/main.tf b/terraform/cluster/aws-eks/main.tf index d890fd46..bcc21d7d 100644 --- a/terraform/cluster/aws-eks/main.tf +++ b/terraform/cluster/aws-eks/main.tf @@ -427,14 +427,14 @@ resource "aws_iam_policy" "efs_csi" { "elasticfilesystem:DescribeMountTargets", "ec2:DescribeAvailabilityZones" ] - Resource = "arn:aws:elasticfilesystem:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:*" + Resource = "*" }, { Effect = "Allow" Action = [ "elasticfilesystem:CreateAccessPoint" ] - Resource = "arn:aws:elasticfilesystem:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:*" + Resource = "*" Condition = { StringLike = { "aws:RequestTag/efs.csi.aws.com/cluster" = "true" @@ -446,7 +446,7 @@ resource "aws_iam_policy" "efs_csi" { Action = [ "elasticfilesystem:DeleteAccessPoint" ] - Resource = "arn:aws:elasticfilesystem:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:*" + Resource = "*" Condition = { StringLike = { "aws:ResourceTag/efs.csi.aws.com/cluster" = "true" From 04b6b1eb933ce856470396ae0dd3b36a6df67ac8 Mon Sep 17 00:00:00 2001 From: Alex Petre Date: Wed, 14 May 2025 12:26:21 -0400 Subject: [PATCH 28/34] efs managed policy --- terraform/cluster/aws-eks/main.tf | 52 +------------------------------ 1 file changed, 1 insertion(+), 51 deletions(-) diff --git a/terraform/cluster/aws-eks/main.tf b/terraform/cluster/aws-eks/main.tf index bcc21d7d..84fa906a 100644 --- a/terraform/cluster/aws-eks/main.tf +++ b/terraform/cluster/aws-eks/main.tf @@ -411,59 +411,9 @@ resource "aws_iam_role" "efs_csi" { } } -resource "aws_iam_policy" "efs_csi" { - count = contains(keys(var.addons), "aws-efs-csi-driver") ? 1 : 0 - name = "${local.name}-aws-efs-csi-driver-policy" - description = "IAM policy for EFS CSI Driver" - - policy = jsonencode({ - Version = "2012-10-17" - Statement = [ - { - Effect = "Allow" - Action = [ - "elasticfilesystem:DescribeAccessPoints", - "elasticfilesystem:DescribeFileSystems", - "elasticfilesystem:DescribeMountTargets", - "ec2:DescribeAvailabilityZones" - ] - Resource = "*" - }, - { - Effect = "Allow" - Action = [ - "elasticfilesystem:CreateAccessPoint" - ] - Resource = "*" - Condition = { - StringLike = { - "aws:RequestTag/efs.csi.aws.com/cluster" = "true" - } - } - }, - { - Effect = "Allow" - Action = [ - "elasticfilesystem:DeleteAccessPoint" - ] - Resource = "*" - Condition = { - StringLike = { - "aws:ResourceTag/efs.csi.aws.com/cluster" = "true" - } - } - } - ] - }) - - tags = { - Name = "${local.name}-aws-efs-csi-driver-policy" - } -} - resource "aws_iam_role_policy_attachment" "efs_csi" { count = contains(keys(var.addons), "aws-efs-csi-driver") ? 1 : 0 - policy_arn = aws_iam_policy.efs_csi[0].arn + policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonEFSCSIDriverPolicy" role = aws_iam_role.efs_csi[0].name } From 95837ec4aed7956e628e2efbc79858f2777cf4df Mon Sep 17 00:00:00 2001 From: Alex Petre Date: Wed, 14 May 2025 14:33:24 -0400 Subject: [PATCH 29/34] checkov --- terraform/cluster/aws-eks/main.tf | 16 ++++++++++++---- terraform/cluster/aws-eks/variables.tf | 6 ++++++ terraform/network/aws-vpc/main.tf | 15 +++++++++++++++ 3 files changed, 33 insertions(+), 4 deletions(-) diff --git a/terraform/cluster/aws-eks/main.tf b/terraform/cluster/aws-eks/main.tf index 84fa906a..8dd810ed 100644 --- a/terraform/cluster/aws-eks/main.tf +++ b/terraform/cluster/aws-eks/main.tf @@ -49,7 +49,7 @@ resource "aws_eks_cluster" "this" { vpc_config { subnet_ids = data.aws_subnets.private.ids endpoint_private_access = true - endpoint_public_access = true # Disable public endpoint for security + endpoint_public_access = var.endpoint_public_access } # Enable secrets encryption using AWS KMS @@ -505,6 +505,9 @@ resource "aws_iam_role" "external_dns" { } resource "aws_iam_policy" "external_dns" { + # This policy is based on the official External DNS documentation for AWS + # https://kubernetes-sigs.github.io/external-dns/v0.17.0/docs/tutorials/aws/#iam-policy + # checkov:skip=CKV_AWS_355: This policy is straight from the External DNS documentation count = contains(keys(var.addons), "external-dns") ? 1 : 0 name = "${local.name}-external-dns-policy" description = "IAM policy for External DNS" @@ -517,15 +520,20 @@ resource "aws_iam_policy" "external_dns" { Action = [ "route53:ChangeResourceRecordSets" ] - Resource = ["*"] + Resource = [ + "arn:aws:route53:::hostedzone/*" + ] }, { Effect = "Allow" Action = [ "route53:ListHostedZones", - "route53:ListResourceRecordSets" + "route53:ListResourceRecordSets", + "route53:ListTagsForResource" + ] + Resource = [ + "*" ] - Resource = ["*"] } ] }) diff --git a/terraform/cluster/aws-eks/variables.tf b/terraform/cluster/aws-eks/variables.tf index c1a37e66..30108956 100644 --- a/terraform/cluster/aws-eks/variables.tf +++ b/terraform/cluster/aws-eks/variables.tf @@ -31,6 +31,12 @@ variable "kubernetes_version" { } } +variable "endpoint_public_access" { + description = "Whether to enable public access to the EKS cluster." + type = bool + default = true +} + variable "vpc_id" { description = "The ID of the VPC where the EKS cluster will be created." type = string diff --git a/terraform/network/aws-vpc/main.tf b/terraform/network/aws-vpc/main.tf index ba0f1aeb..f6af15d4 100644 --- a/terraform/network/aws-vpc/main.tf +++ b/terraform/network/aws-vpc/main.tf @@ -32,6 +32,21 @@ resource "aws_vpc" "main" { } } +resource "aws_default_security_group" "default" { + vpc_id = aws_vpc.main.id + + # Ensure no ingress rules are defined (restricting all inbound traffic) + ingress = [] + + # Ensure no egress rules are defined (restricting all outbound traffic) + egress = [] + + tags = { + Name = "${local.name}-default-sg" + Description = "Default security group with all traffic restricted" + } +} + # Enable VPC Flow Logs resource "aws_flow_log" "vpc_flow_logs" { log_destination = aws_cloudwatch_log_group.vpc_flow_logs.arn From ce0dea5434a3197fae6ad8bd6ba506da8cf9f376 Mon Sep 17 00:00:00 2001 From: Alex Petre Date: Wed, 14 May 2025 14:38:38 -0400 Subject: [PATCH 30/34] cluster api access checkov --- terraform/cluster/aws-eks/main.tf | 15 +++++++++++++++ terraform/cluster/aws-eks/variables.tf | 6 ++++++ 2 files changed, 21 insertions(+) diff --git a/terraform/cluster/aws-eks/main.tf b/terraform/cluster/aws-eks/main.tf index 8dd810ed..331b9ac5 100644 --- a/terraform/cluster/aws-eks/main.tf +++ b/terraform/cluster/aws-eks/main.tf @@ -42,6 +42,7 @@ data "aws_region" "current" {} # EKS Cluster #----------------------------------------------------------------------------------------------------------------------- resource "aws_eks_cluster" "this" { + # checkov:skip=CKV_AWS_38: Public access set via a variable. name = local.name role_arn = aws_iam_role.cluster.arn version = var.kubernetes_version @@ -50,6 +51,7 @@ resource "aws_eks_cluster" "this" { subnet_ids = data.aws_subnets.private.ids endpoint_private_access = true endpoint_public_access = var.endpoint_public_access + security_group_ids = [aws_security_group.cluster_api_access.id] } # Enable secrets encryption using AWS KMS @@ -76,6 +78,19 @@ resource "aws_eks_cluster" "this" { ] } +resource "aws_security_group" "cluster_api_access" { + name = "${local.name}-cluster-api-access" + description = "Security group for EKS cluster API access" + vpc_id = data.aws_vpc.default[0].id + + ingress { + from_port = 443 + to_port = 443 + protocol = "tcp" + cidr_blocks = [var.cluster_api_access_cidr_block] + } +} + resource "aws_kms_key" "eks_encryption_key" { description = "KMS key for EKS cluster ${local.name} secrets encryption" deletion_window_in_days = 7 diff --git a/terraform/cluster/aws-eks/variables.tf b/terraform/cluster/aws-eks/variables.tf index 30108956..3549459d 100644 --- a/terraform/cluster/aws-eks/variables.tf +++ b/terraform/cluster/aws-eks/variables.tf @@ -37,6 +37,12 @@ variable "endpoint_public_access" { default = true } +variable "cluster_api_access_cidr_block" { + description = "The CIDR block for the cluster API access." + type = string + default = "0.0.0.0/0" +} + variable "vpc_id" { description = "The ID of the VPC where the EKS cluster will be created." type = string From f102ab3c8206ba549ced3f36af4ccae14454bd33 Mon Sep 17 00:00:00 2001 From: Alex Petre Date: Wed, 14 May 2025 14:40:46 -0400 Subject: [PATCH 31/34] more checkov --- terraform/cluster/aws-eks/main.tf | 2 ++ 1 file changed, 2 insertions(+) diff --git a/terraform/cluster/aws-eks/main.tf b/terraform/cluster/aws-eks/main.tf index 331b9ac5..6cd48380 100644 --- a/terraform/cluster/aws-eks/main.tf +++ b/terraform/cluster/aws-eks/main.tf @@ -43,6 +43,7 @@ data "aws_region" "current" {} #----------------------------------------------------------------------------------------------------------------------- resource "aws_eks_cluster" "this" { # checkov:skip=CKV_AWS_38: Public access set via a variable. + # checkov:skip=CKV_AWS_39: Public access set via a variable. name = local.name role_arn = aws_iam_role.cluster.arn version = var.kubernetes_version @@ -88,6 +89,7 @@ resource "aws_security_group" "cluster_api_access" { to_port = 443 protocol = "tcp" cidr_blocks = [var.cluster_api_access_cidr_block] + description = "Allow K8s API access from the specified CIDR block" } } From 4f819984d6d33a79a414edb0e63a35848d5e3cc8 Mon Sep 17 00:00:00 2001 From: Alex Petre Date: Wed, 14 May 2025 14:43:35 -0400 Subject: [PATCH 32/34] fmt --- terraform/cluster/aws-eks/main.tf | 4 ++-- terraform/network/aws-vpc/main.tf | 16 ++++++++-------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/terraform/cluster/aws-eks/main.tf b/terraform/cluster/aws-eks/main.tf index 6cd48380..e3923c30 100644 --- a/terraform/cluster/aws-eks/main.tf +++ b/terraform/cluster/aws-eks/main.tf @@ -80,9 +80,9 @@ resource "aws_eks_cluster" "this" { } resource "aws_security_group" "cluster_api_access" { - name = "${local.name}-cluster-api-access" + name = "${local.name}-cluster-api-access" description = "Security group for EKS cluster API access" - vpc_id = data.aws_vpc.default[0].id + vpc_id = data.aws_vpc.default[0].id ingress { from_port = 443 diff --git a/terraform/network/aws-vpc/main.tf b/terraform/network/aws-vpc/main.tf index f6af15d4..20248b4f 100644 --- a/terraform/network/aws-vpc/main.tf +++ b/terraform/network/aws-vpc/main.tf @@ -27,7 +27,7 @@ resource "aws_vpc" "main" { enable_dns_hostnames = true tags = { - Name = local.name + Name = local.name WindsorContextID = var.context_id } } @@ -42,7 +42,7 @@ resource "aws_default_security_group" "default" { egress = [] tags = { - Name = "${local.name}-default-sg" + Name = "${local.name}-default-sg" Description = "Default security group with all traffic restricted" } } @@ -160,9 +160,9 @@ resource "aws_subnet" "public" { # Private Subnets resource "aws_subnet" "private" { - count = var.availability_zones - vpc_id = aws_vpc.main.id - cidr_block = cidrsubnet( + count = var.availability_zones + vpc_id = aws_vpc.main.id + cidr_block = cidrsubnet( var.cidr_block, var.subnet_newbits, count.index + length(data.aws_availability_zones.available.names) ) availability_zone = data.aws_availability_zones.available.names[count.index] @@ -175,9 +175,9 @@ resource "aws_subnet" "private" { # Data Subnets resource "aws_subnet" "data" { - count = var.availability_zones - vpc_id = aws_vpc.main.id - cidr_block = cidrsubnet( + count = var.availability_zones + vpc_id = aws_vpc.main.id + cidr_block = cidrsubnet( var.cidr_block, var.subnet_newbits, count.index + 2 * length(data.aws_availability_zones.available.names) ) availability_zone = data.aws_availability_zones.available.names[count.index] From 5d756ae30c133d13a3f851f7ee05ee96a33d779f Mon Sep 17 00:00:00 2001 From: Alex Petre Date: Wed, 14 May 2025 15:46:41 -0400 Subject: [PATCH 33/34] some edits --- terraform/cluster/aws-eks/main.tf | 4 ++-- terraform/cluster/aws-eks/variables.tf | 8 +++++--- terraform/network/aws-vpc/main.tf | 19 ++++++++++++------- terraform/network/aws-vpc/variables.tf | 18 ++++++++++++++++++ 4 files changed, 37 insertions(+), 12 deletions(-) diff --git a/terraform/cluster/aws-eks/main.tf b/terraform/cluster/aws-eks/main.tf index e3923c30..99220318 100644 --- a/terraform/cluster/aws-eks/main.tf +++ b/terraform/cluster/aws-eks/main.tf @@ -4,13 +4,13 @@ terraform { required_providers { aws = { source = "hashicorp/aws" - version = "~> 5.0" + version = "5.97.0" } } } locals { - name = var.cluster_name != "" ? var.cluster_name : "windsor-core-${var.context_id}" + name = var.cluster_name != "" ? var.cluster_name : "cluster-${var.context_id}" } #----------------------------------------------------------------------------------------------------------------------- diff --git a/terraform/cluster/aws-eks/variables.tf b/terraform/cluster/aws-eks/variables.tf index 3549459d..c2b768f4 100644 --- a/terraform/cluster/aws-eks/variables.tf +++ b/terraform/cluster/aws-eks/variables.tf @@ -24,13 +24,15 @@ variable "cluster_name" { variable "kubernetes_version" { description = "The kubernetes version to deploy." type = string - default = "1.32" + # renovate: datasource=github-releases depName=kubernetes package=kubernetes/kubernetes + default = "1.32" validation { - condition = can(regex("^\\d+\\.\\d+$", var.kubernetes_version)) - error_message = "The Kubernetes version should be in format like '1.32'." + condition = can(regex("^1\\.\\d+\\$", var.kubernetes_version)) + error_message = "The Kubernetes version should be in version format like '1.32'." } } + variable "endpoint_public_access" { description = "Whether to enable public access to the EKS cluster." type = bool diff --git a/terraform/network/aws-vpc/main.tf b/terraform/network/aws-vpc/main.tf index 20248b4f..34df0aa9 100644 --- a/terraform/network/aws-vpc/main.tf +++ b/terraform/network/aws-vpc/main.tf @@ -4,7 +4,7 @@ terraform { required_providers { aws = { source = "hashicorp/aws" - version = "~> 5.0" + version = "5.97.0" } } } @@ -14,7 +14,7 @@ data "aws_caller_identity" "current" {} data "aws_region" "current" {} locals { - name = var.name != "" ? var.name : "windsor-core-${var.context_id}" + name = var.name != "" ? var.name : "network-${var.context_id}" } #----------------------------------------------------------------------------------------------------------------------- @@ -49,17 +49,19 @@ resource "aws_default_security_group" "default" { # Enable VPC Flow Logs resource "aws_flow_log" "vpc_flow_logs" { + count = var.enable_flow_logs ? 1 : 0 log_destination = aws_cloudwatch_log_group.vpc_flow_logs.arn log_destination_type = "cloud-watch-logs" traffic_type = "ALL" vpc_id = aws_vpc.main.id - iam_role_arn = aws_iam_role.vpc_flow_logs.arn + iam_role_arn = aws_iam_role.vpc_flow_logs[0].arn } resource "aws_cloudwatch_log_group" "vpc_flow_logs" { + count = var.enable_flow_logs ? 1 : 0 name = "/aws/vpc-flow-logs/${local.name}" retention_in_days = 365 - kms_key_id = aws_kms_key.cloudwatch_logs_encryption.arn + kms_key_id = var.create_flow_logs_kms_key ? aws_kms_key.cloudwatch_logs_encryption[0].arn : var.flow_logs_kms_key_id tags = { Name = "${local.name}-vpc-flow-logs" @@ -67,6 +69,7 @@ resource "aws_cloudwatch_log_group" "vpc_flow_logs" { } resource "aws_kms_key" "cloudwatch_logs_encryption" { + count = var.create_flow_logs_kms_key ? 1 : 0 description = "KMS key for CloudWatch Logs encryption" deletion_window_in_days = 7 enable_key_rotation = true @@ -103,7 +106,8 @@ resource "aws_kms_key" "cloudwatch_logs_encryption" { } resource "aws_iam_role" "vpc_flow_logs" { - name = "${local.name}-vpc-flow-logs-role" + count = var.enable_flow_logs ? 1 : 0 + name = "${local.name}-vpc-flow-logs-role" assume_role_policy = jsonencode({ Version = "2012-10-17" @@ -118,8 +122,9 @@ resource "aws_iam_role" "vpc_flow_logs" { } resource "aws_iam_role_policy" "vpc_flow_logs" { - name = "${local.name}-vpc-flow-logs-policy" - role = aws_iam_role.vpc_flow_logs.id + count = var.enable_flow_logs ? 1 : 0 + name = "${local.name}-vpc-flow-logs-policy" + role = aws_iam_role.vpc_flow_logs[0].id policy = jsonencode({ Version = "2012-10-17" diff --git a/terraform/network/aws-vpc/variables.tf b/terraform/network/aws-vpc/variables.tf index 334a64d6..bfcb90bd 100644 --- a/terraform/network/aws-vpc/variables.tf +++ b/terraform/network/aws-vpc/variables.tf @@ -56,6 +56,24 @@ variable "single_nat_gateway" { default = false } +variable "enable_flow_logs" { + description = "Enable flow logs for the VPC" + type = bool + default = true +} + +variable "create_flow_logs_kms_key" { + description = "Create a KMS key for flow logs" + type = bool + default = true +} + +variable "flow_logs_kms_key_id" { + description = "The KMS key ID for flow logs" + type = string + default = null +} + variable "tags" { description = "Additional tags for all resources" type = map(string) From 5bce071b7b77e4f71183cdbdcdcbe49d1e84bb5c Mon Sep 17 00:00:00 2001 From: Alex Petre Date: Thu, 15 May 2025 11:28:16 -0400 Subject: [PATCH 34/34] Naming updates --- contexts/aws-example/blueprint.yaml | 4 ++-- terraform/cluster/aws-eks/main.tf | 32 ++++++++++++------------- terraform/network/aws-vpc/main.tf | 37 +++++++++-------------------- 3 files changed, 29 insertions(+), 44 deletions(-) diff --git a/contexts/aws-example/blueprint.yaml b/contexts/aws-example/blueprint.yaml index 63bf3f7b..cdda6557 100644 --- a/contexts/aws-example/blueprint.yaml +++ b/contexts/aws-example/blueprint.yaml @@ -6,13 +6,13 @@ metadata: repository: url: https://github.com/windsorcli/core ref: - branch: aws-eks + branch: main secretName: flux-system sources: - name: core url: github.com/windsorcli/core ref: - branch: aws-eks + branch: main terraform: - path: network/aws-vpc - path: cluster/aws-eks diff --git a/terraform/cluster/aws-eks/main.tf b/terraform/cluster/aws-eks/main.tf index 99220318..134965d1 100644 --- a/terraform/cluster/aws-eks/main.tf +++ b/terraform/cluster/aws-eks/main.tf @@ -136,7 +136,7 @@ data "aws_caller_identity" "current" {} #----------------------------------------------------------------------------------------------------------------------- resource "aws_iam_role" "cluster" { - name = "${local.name}-cluster-role" + name = "${local.name}-cluster" assume_role_policy = jsonencode({ Version = "2012-10-17" @@ -163,7 +163,7 @@ resource "aws_iam_role_policy_attachment" "cluster_AmazonEKSVPCResourceControlle } resource "aws_iam_role" "node_group" { - name = "${local.name}-node-group-role" + name = "${local.name}-node-group" assume_role_policy = jsonencode({ Version = "2012-10-17" @@ -343,7 +343,7 @@ data "aws_eks_addon_version" "default" { resource "aws_iam_role" "vpc_cni" { count = contains(keys(var.addons), "vpc-cni") ? 1 : 0 - name = "${local.name}-vpc-cni-role" + name = "${local.name}-vpc-cni" assume_role_policy = jsonencode({ Version = "2012-10-17" @@ -359,7 +359,7 @@ resource "aws_iam_role" "vpc_cni" { }) tags = { - Name = "${local.name}-vpc-cni-role" + Name = "${local.name}-vpc-cni" } } @@ -376,7 +376,7 @@ resource "aws_iam_role_policy_attachment" "vpc_cni" { resource "aws_iam_role" "ebs_csi" { count = contains(keys(var.addons), "aws-ebs-csi-driver") ? 1 : 0 - name = "${local.name}-aws-ebs-csi-driver-role" + name = "${local.name}-aws-ebs-csi-driver" assume_role_policy = jsonencode({ Version = "2012-10-17" @@ -392,7 +392,7 @@ resource "aws_iam_role" "ebs_csi" { }) tags = { - Name = "${local.name}-aws-ebs-csi-driver-role" + Name = "${local.name}-aws-ebs-csi-driver" } } @@ -408,7 +408,7 @@ resource "aws_iam_role_policy_attachment" "ebs_csi" { resource "aws_iam_role" "efs_csi" { count = contains(keys(var.addons), "aws-efs-csi-driver") ? 1 : 0 - name = "${local.name}-aws-efs-csi-driver-role" + name = "${local.name}-aws-efs-csi-driver" assume_role_policy = jsonencode({ Version = "2012-10-17" @@ -424,7 +424,7 @@ resource "aws_iam_role" "efs_csi" { }) tags = { - Name = "${local.name}-aws-efs-csi-driver-role" + Name = "${local.name}-aws-efs-csi-driver" } } @@ -440,7 +440,7 @@ resource "aws_iam_role_policy_attachment" "efs_csi" { resource "aws_iam_role" "pod_identity_agent" { count = contains(keys(var.addons), "pod-identity-agent") ? 1 : 0 - name = "${local.name}-pod-identity-agent-role" + name = "${local.name}-pod-identity-agent" assume_role_policy = jsonencode({ Version = "2012-10-17" @@ -456,13 +456,13 @@ resource "aws_iam_role" "pod_identity_agent" { }) tags = { - Name = "${local.name}-pod-identity-agent-role" + Name = "${local.name}-pod-identity-agent" } } resource "aws_iam_policy" "pod_identity_agent" { count = contains(keys(var.addons), "pod-identity-agent") ? 1 : 0 - name = "${local.name}-pod-identity-agent-policy" + name = "${local.name}-pod-identity-agent" description = "IAM policy for EKS Pod Identity Agent" policy = jsonencode({ @@ -484,7 +484,7 @@ resource "aws_iam_policy" "pod_identity_agent" { }) tags = { - Name = "${local.name}-pod-identity-agent-policy" + Name = "${local.name}-pod-identity-agent" } } @@ -501,7 +501,7 @@ resource "aws_iam_role_policy_attachment" "pod_identity_agent" { resource "aws_iam_role" "external_dns" { count = contains(keys(var.addons), "external-dns") ? 1 : 0 - name = "${local.name}-external-dns-role" + name = "${local.name}-external-dns" assume_role_policy = jsonencode({ Version = "2012-10-17" @@ -517,7 +517,7 @@ resource "aws_iam_role" "external_dns" { }) tags = { - Name = "${local.name}-external-dns-role" + Name = "${local.name}-external-dns" } } @@ -526,7 +526,7 @@ resource "aws_iam_policy" "external_dns" { # https://kubernetes-sigs.github.io/external-dns/v0.17.0/docs/tutorials/aws/#iam-policy # checkov:skip=CKV_AWS_355: This policy is straight from the External DNS documentation count = contains(keys(var.addons), "external-dns") ? 1 : 0 - name = "${local.name}-external-dns-policy" + name = "${local.name}-external-dns" description = "IAM policy for External DNS" policy = jsonencode({ @@ -556,7 +556,7 @@ resource "aws_iam_policy" "external_dns" { }) tags = { - Name = "${local.name}-external-dns-policy" + Name = "${local.name}-external-dns" } } diff --git a/terraform/network/aws-vpc/main.tf b/terraform/network/aws-vpc/main.tf index 34df0aa9..d998c13b 100644 --- a/terraform/network/aws-vpc/main.tf +++ b/terraform/network/aws-vpc/main.tf @@ -42,7 +42,7 @@ resource "aws_default_security_group" "default" { egress = [] tags = { - Name = "${local.name}-default-sg" + Name = "${local.name}-default" Description = "Default security group with all traffic restricted" } } @@ -107,7 +107,7 @@ resource "aws_kms_key" "cloudwatch_logs_encryption" { resource "aws_iam_role" "vpc_flow_logs" { count = var.enable_flow_logs ? 1 : 0 - name = "${local.name}-vpc-flow-logs-role" + name = "${local.name}-vpc-flow-logs" assume_role_policy = jsonencode({ Version = "2012-10-17" @@ -123,7 +123,7 @@ resource "aws_iam_role" "vpc_flow_logs" { resource "aws_iam_role_policy" "vpc_flow_logs" { count = var.enable_flow_logs ? 1 : 0 - name = "${local.name}-vpc-flow-logs-policy" + name = "${local.name}-vpc-flow-logs" role = aws_iam_role.vpc_flow_logs[0].id policy = jsonencode({ @@ -178,8 +178,8 @@ resource "aws_subnet" "private" { } } -# Data Subnets -resource "aws_subnet" "data" { +# Isolated Subnets +resource "aws_subnet" "isolated" { count = var.availability_zones vpc_id = aws_vpc.main.id cidr_block = cidrsubnet( @@ -188,8 +188,8 @@ resource "aws_subnet" "data" { availability_zone = data.aws_availability_zones.available.names[count.index] tags = { - Name = "${local.name}-data-${data.aws_availability_zones.available.names[count.index]}" - Tier = "data" + Name = "${local.name}-isolated-${data.aws_availability_zones.available.names[count.index]}" + Tier = "isolated" } } @@ -201,7 +201,7 @@ resource "aws_internet_gateway" "main" { vpc_id = aws_vpc.main.id tags = { - Name = "${local.name}-igw" + Name = local.name } } @@ -214,7 +214,7 @@ resource "aws_eip" "nat" { domain = "vpc" tags = { - Name = "${local.name}-nat-eip-${data.aws_availability_zones.available.names[count.index]}" + Name = "${local.name}-nat-${data.aws_availability_zones.available.names[count.index]}" } } @@ -244,7 +244,7 @@ resource "aws_route_table" "public" { } tags = { - Name = "${local.name}-public-rt" + Name = "${local.name}-public" } } @@ -259,22 +259,7 @@ resource "aws_route_table" "private" { } tags = { - Name = "${local.name}-private-rt-${data.aws_availability_zones.available.names[count.index]}" - } -} - -# Data Route Tables (one per AZ) -resource "aws_route_table" "data" { - count = var.availability_zones - vpc_id = aws_vpc.main.id - - route { - cidr_block = "0.0.0.0/0" - nat_gateway_id = aws_nat_gateway.main[count.index].id - } - - tags = { - Name = "${local.name}-data-rt-${data.aws_availability_zones.available.names[count.index]}" + Name = "${local.name}-private-${data.aws_availability_zones.available.names[count.index]}" } }