From a41e57c19e2b9f97ad95b4ec576c95125dbd4a8d Mon Sep 17 00:00:00 2001 From: Ryan McNeil Date: Mon, 13 May 2024 18:46:25 -0600 Subject: [PATCH 1/4] Scaffold terraform files --- terraform/database.tf | 0 terraform/helm.tf | 0 terraform/kubernetes.tf | 0 terraform/outputs.tf | 0 terraform/providers.tf | 3 +++ terraform/variables.tf | 0 terraform/versions.tf | 12 ++++++++++++ 7 files changed, 15 insertions(+) create mode 100644 terraform/database.tf create mode 100644 terraform/helm.tf create mode 100644 terraform/kubernetes.tf create mode 100644 terraform/outputs.tf create mode 100644 terraform/providers.tf create mode 100644 terraform/variables.tf create mode 100644 terraform/versions.tf diff --git a/terraform/database.tf b/terraform/database.tf new file mode 100644 index 000000000..e69de29bb diff --git a/terraform/helm.tf b/terraform/helm.tf new file mode 100644 index 000000000..e69de29bb diff --git a/terraform/kubernetes.tf b/terraform/kubernetes.tf new file mode 100644 index 000000000..e69de29bb diff --git a/terraform/outputs.tf b/terraform/outputs.tf new file mode 100644 index 000000000..e69de29bb diff --git a/terraform/providers.tf b/terraform/providers.tf new file mode 100644 index 000000000..4b88a911a --- /dev/null +++ b/terraform/providers.tf @@ -0,0 +1,3 @@ +provider "aws" { + region = "us-gov-west-1" +} \ No newline at end of file diff --git a/terraform/variables.tf b/terraform/variables.tf new file mode 100644 index 000000000..e69de29bb diff --git a/terraform/versions.tf b/terraform/versions.tf new file mode 100644 index 000000000..3ab9028e7 --- /dev/null +++ b/terraform/versions.tf @@ -0,0 +1,12 @@ +terraform { + required_providers { + kubernetes = { + source = "hashicorp/kubernetes" + version = "2.23.0" + } + aws = { + source = "hashicorp/aws" + version = "5.23.0" + } + } +} \ No newline at end of file From 311819598983e8de93ff0d84f6ac2025cd3bef1d Mon Sep 17 00:00:00 2001 From: Ryan McNeil Date: Fri, 17 May 2024 08:20:44 -0600 Subject: [PATCH 2/4] add first iteration of db and k8s resrouces --- terraform/database.tf | 66 +++++++++++++++++++++++++++++++++++++ terraform/dev.tfvars | 8 +++++ terraform/eks.tf | 70 ++++++++++++++++++++++++++++++++++++++++ terraform/iam.tf | 57 ++++++++++++++++++++++++++++++++ terraform/kubernetes.tf | 15 +++++++++ terraform/prod.tfvars | 8 +++++ terraform/providers.tf | 21 ++++++++++++ terraform/staging.tfvars | 8 +++++ terraform/variables.tf | 17 ++++++++++ 9 files changed, 270 insertions(+) create mode 100644 terraform/dev.tfvars create mode 100644 terraform/eks.tf create mode 100644 terraform/iam.tf create mode 100644 terraform/prod.tfvars create mode 100644 terraform/staging.tfvars diff --git a/terraform/database.tf b/terraform/database.tf index e69de29bb..8116e9beb 100644 --- a/terraform/database.tf +++ b/terraform/database.tf @@ -0,0 +1,66 @@ +# TODO - likely need to define our own subnet group +data "aws_db_subnet_group" "database" { + name = "dsva-vagov-postgres-db-sng" +} + +resource "aws_rds_cluster" "this" { + backup_retention_period = "7" + cluster_identifier = "dsva-gids-${var.env_name}" + copy_tags_to_snapshot = true + database_name = "dsva_gids_${var.env_name}" + db_subnet_group_name = data.aws_db_subnet_group.database.name + deletion_protection = true + engine = "aurora-postgresql" + engine_mode = "provisioned" + engine_version = "14.4" + master_password = "must_be_eight_characters" # TODO - use `manage_master_user_password` instead? + master_username = "gibct-data-service" + port = "5432" + preferred_backup_window = var.preferred_backup_window + preferred_maintenance_window = var.preferred_maintenance_window + skip_final_snapshot = true + vpc_security_group_ids = [aws_security_group.this.id] + + serverlessv2_scaling_configuration { + max_capacity = 1.0 + min_capacity = 0.5 + } + + tags = merge( + var.base_tags, + { + "Name" = "dsva-gids-${var.env_name}-db" + "application" = "gi-bill-data-service" + }, + ) +} + +resource "aws_rds_cluster_instance" "this" { + cluster_identifier = aws_rds_cluster.this.id + instance_class = "db.serverless" + engine = aws_rds_cluster.this.engine + engine_version = aws_rds_cluster.this.engine_version + db_subnet_group_name = data.aws_db_subnet_group.database.name +} + +resource "aws_security_group" "this" { + name = "dsva-gids-${var.env_name}-db-sg" + description = "Allow DB access from EKS cluster" + vpc_id = var.vpc_id + + ingress { + description = "Access to DB from EKS cluster" + from_port = 5432 + to_port = 5432 + protocol = "tcp" + security_groups = [TODO] + } + + tags = merge( + var.base_tags, + { + "Name" = "dsva-gids-${var.env_name}-db-sg" + "application" = "gi-bill-data-service" + }, + ) +} \ No newline at end of file diff --git a/terraform/dev.tfvars b/terraform/dev.tfvars new file mode 100644 index 000000000..a33e50c12 --- /dev/null +++ b/terraform/dev.tfvars @@ -0,0 +1,8 @@ +base_tags = { + +} + +env_name = "dev" +preferred_backup_window = +preferred_maintenance_window = +vpc_id = \ No newline at end of file diff --git a/terraform/eks.tf b/terraform/eks.tf new file mode 100644 index 000000000..5c4715574 --- /dev/null +++ b/terraform/eks.tf @@ -0,0 +1,70 @@ +# Taken from https://registry.terraform.io/modules/terraform-aws-modules/eks/aws/latest + +module "eks" { + source = "terraform-aws-modules/eks/aws" + version = "~> 20.0" + + cluster_name = "my-cluster" + cluster_version = "1.29" + + cluster_endpoint_public_access = true + + cluster_addons = { + coredns = { + most_recent = true + } + kube-proxy = { + most_recent = true + } + vpc-cni = { + most_recent = true + } + } + + vpc_id = var.vpc_id + subnet_ids = [] + control_plane_subnet_ids = [] + + # EKS Managed Node Group(s) + eks_managed_node_group_defaults = { + instance_types = ["m6i.large", "m5.large", "m5n.large", "m5zn.large"] + } + + eks_managed_node_groups = { + example = { + min_size = 1 + max_size = 10 + desired_size = 1 + + instance_types = ["t3.large"] + capacity_type = "SPOT" + } + } + + # Cluster access entry + # To add the current caller identity as an administrator + enable_cluster_creator_admin_permissions = true + + access_entries = { + # One access entry with a policy associated + example = { + kubernetes_groups = [] + principal_arn = "arn:aws:iam::123456789012:role/something" + + policy_associations = { + example = { + policy_arn = "arn:aws:eks::aws:cluster-access-policy/AmazonEKSViewPolicy" + access_scope = { + namespaces = ["default"] + type = "namespace" + } + } + } + } + } + + tags = { + Environment = "dev" + Terraform = "true" + } +} \ No newline at end of file diff --git a/terraform/iam.tf b/terraform/iam.tf new file mode 100644 index 000000000..2cc2f8b74 --- /dev/null +++ b/terraform/iam.tf @@ -0,0 +1,57 @@ +locals { + #TODO eks_oidc_issuer = trimprefix(module.eks.identity[0].oidc[0].issuer, "https://") +} + +resource "aws_iam_role" "app_role" { + name = "${var.eks_cluster_name}-${var.env_name}" + assume_role_policy = data.aws_iam_policy_document.AssumeRole.json + inline_policy { + name = "policy-${var.eks_cluster_name}-${var.env_name}" + policy = data.aws_iam_policy_document.inline.json + } +} + +# TODO +data "aws_iam_policy_document" "AssumeRole" { + statement { + actions = ["sts:AssumeRoleWithWebIdentity"] + + principals { + type = "Federated" + identifiers = [ + "arn:aws-us-gov:iam::${data.aws_caller_identity.current.account_id}:oidc-provider/${local.eks_oidc_issuer}" + ] + } + + # Limit the scope so that only our desired service account can assume this role + condition { + test = "StringEquals" + variable = "${local.eks_oidc_issuer}:sub" + values = [ + "system:serviceaccount:${var.env_name}:vets-api" + ] + } + + condition { + test = "StringEquals" + variable = "${local.eks_oidc_issuer}:aud" + values = [ + "sts.amazonaws.com" + ] + } + + } +} + +data "aws_iam_policy_document" "inline" { + statement { + effect = "Allow" + actions = [ + "*" + ] + resources = [ + aws_rds_cluster.this.arn, + aws_rds_cluster_instance.this.arn, + ] + } +} diff --git a/terraform/kubernetes.tf b/terraform/kubernetes.tf index e69de29bb..95aa631df 100644 --- a/terraform/kubernetes.tf +++ b/terraform/kubernetes.tf @@ -0,0 +1,15 @@ +resource "kubernetes_namespace" "this" { + metadata { + name = var.env_name + } +} + +resource "kubernetes_service_account" "this" { + metadata { + name = "vets-api" + namespace = kubernetes_namespace.this.metadata.0.name + annotations = { + "eks.amazonaws.com/role-arn" = aws_iam_role.app_role.arn + } + } +} \ No newline at end of file diff --git a/terraform/prod.tfvars b/terraform/prod.tfvars new file mode 100644 index 000000000..972be2d2d --- /dev/null +++ b/terraform/prod.tfvars @@ -0,0 +1,8 @@ +base_tags = { + +} + +env_name = "prod" +preferred_backup_window = +preferred_maintenance_window = +vpc_id = \ No newline at end of file diff --git a/terraform/providers.tf b/terraform/providers.tf index 4b88a911a..5926b3177 100644 --- a/terraform/providers.tf +++ b/terraform/providers.tf @@ -1,3 +1,24 @@ provider "aws" { region = "us-gov-west-1" +} + +provider "kubernetes" { + +} + +provider "helm" { + +} + + +# TODO Why not require the tools vs require as a provider? +terraform { + required_providers { + helm = { + source = "hashicorp/helm" + version = ">= 2.6.0" + } + } + + required_version = "~> 1.0" } \ No newline at end of file diff --git a/terraform/staging.tfvars b/terraform/staging.tfvars new file mode 100644 index 000000000..551b7a773 --- /dev/null +++ b/terraform/staging.tfvars @@ -0,0 +1,8 @@ +base_tags = { + +} + +env_name = "staging" +preferred_backup_window = +preferred_maintenance_window = +vpc_id = \ No newline at end of file diff --git a/terraform/variables.tf b/terraform/variables.tf index e69de29bb..71b48aebf 100644 --- a/terraform/variables.tf +++ b/terraform/variables.tf @@ -0,0 +1,17 @@ +variable "env_name" { + type = string +} + +variable "preferred_backup_window" { + type = string + default = "00:00-01:00" +} + +variable "preferred_maintenance_window" { + type = string + default = "tue:10:01-tue:10:31" +} + +variable "vpc_id" { + type = string +} From f74482b8b8bf98cf5bcee58cdefdb1558eb26b9c Mon Sep 17 00:00:00 2001 From: Ryan McNeil Date: Fri, 24 May 2024 14:58:17 -0600 Subject: [PATCH 3/4] source eks cluster from vsp module --- terraform/eks.tf | 75 +++++------------------------------------------- 1 file changed, 7 insertions(+), 68 deletions(-) diff --git a/terraform/eks.tf b/terraform/eks.tf index 5c4715574..a4cea9367 100644 --- a/terraform/eks.tf +++ b/terraform/eks.tf @@ -1,70 +1,9 @@ -# Taken from https://registry.terraform.io/modules/terraform-aws-modules/eks/aws/latest +module "eks_cluster" { + source = "git::ssh://git@github.com/department-of-veterans-affairs/vsp-platform-infrastructure.git//terraform/modules/eks-cluster?ref=eks-cluster-v0.1.2" -module "eks" { - source = "terraform-aws-modules/eks/aws" - version = "~> 20.0" + vpc_id = module.join_existing_network.vpc.id + subnet_ids = module.join_existing_network.subnets.ids + kubernetes_version = var.kubernetes_version - cluster_name = "my-cluster" - cluster_version = "1.29" - - cluster_endpoint_public_access = true - - cluster_addons = { - coredns = { - most_recent = true - } - kube-proxy = { - most_recent = true - } - vpc-cni = { - most_recent = true - } - } - - vpc_id = var.vpc_id - subnet_ids = [] - control_plane_subnet_ids = [] - - # EKS Managed Node Group(s) - eks_managed_node_group_defaults = { - instance_types = ["m6i.large", "m5.large", "m5n.large", "m5zn.large"] - } - - eks_managed_node_groups = { - example = { - min_size = 1 - max_size = 10 - desired_size = 1 - - instance_types = ["t3.large"] - capacity_type = "SPOT" - } - } - - # Cluster access entry - # To add the current caller identity as an administrator - enable_cluster_creator_admin_permissions = true - - access_entries = { - # One access entry with a policy associated - example = { - kubernetes_groups = [] - principal_arn = "arn:aws:iam::123456789012:role/something" - - policy_associations = { - example = { - policy_arn = "arn:aws:eks::aws:cluster-access-policy/AmazonEKSViewPolicy" - access_scope = { - namespaces = ["default"] - type = "namespace" - } - } - } - } - } - - tags = { - Environment = "dev" - Terraform = "true" - } -} \ No newline at end of file + context = module.context.context +} From 8969fa3f17771e236da78bb564157666185a6d4d Mon Sep 17 00:00:00 2001 From: Ryan McNeil Date: Wed, 29 May 2024 13:35:51 -0600 Subject: [PATCH 4/4] replace EKS outputs --- terraform/database.tf | 2 +- terraform/iam.tf | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/terraform/database.tf b/terraform/database.tf index 8116e9beb..4b44f7d1f 100644 --- a/terraform/database.tf +++ b/terraform/database.tf @@ -53,7 +53,7 @@ resource "aws_security_group" "this" { from_port = 5432 to_port = 5432 protocol = "tcp" - security_groups = [TODO] + security_groups = [module.eks_cluster.security_group_id] } tags = merge( diff --git a/terraform/iam.tf b/terraform/iam.tf index 2cc2f8b74..1e4508712 100644 --- a/terraform/iam.tf +++ b/terraform/iam.tf @@ -1,5 +1,5 @@ locals { - #TODO eks_oidc_issuer = trimprefix(module.eks.identity[0].oidc[0].issuer, "https://") + eks_oidc_issuer = trimprefix(module.eks_cluster.eks_cluster_identity_oidc_issuer, "https://") } resource "aws_iam_role" "app_role" {