diff --git a/.github/workflows/api-image.yaml b/.github/workflows/api-image.yaml index df6dade..608a374 100644 --- a/.github/workflows/api-image.yaml +++ b/.github/workflows/api-image.yaml @@ -11,7 +11,7 @@ on: - "shared/**" - "go.work" - "go.work.sum" - - ".github/workflows/api-image.yml" + - ".github/workflows/api-image.yaml" pull_request: branches: - main diff --git a/.github/workflows/tui-image.yaml b/.github/workflows/tui-image.yaml index 7c7208f..ec43c5c 100644 --- a/.github/workflows/tui-image.yaml +++ b/.github/workflows/tui-image.yaml @@ -11,7 +11,7 @@ on: - "shared/**" - "go.work" - "go.work.sum" - - ".github/workflows/tui-image.yml" + - ".github/workflows/tui-image.yaml" pull_request: branches: - main diff --git a/.gitignore b/.gitignore index c82f970..bf72ee9 100644 --- a/.gitignore +++ b/.gitignore @@ -33,3 +33,6 @@ profile.cov # Helm *.tgz Charts/ + +# Terraform +terraform/.terraform diff --git a/README.md b/README.md index e949eda..45f38d9 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,20 @@ ## Description A Feature Flag service, self hosted or AWS cloud native. +## Currently it supports +- RBAC authorization natively +- TUI client so it can work on servers locally without needing a display env or compositor (and to cut cloud costs) +- You can only sign from the register endpoint, so you can't create an account from TUI to prevent dummy projects from existing (mostly, you still can use a regular client like **curl** or **postman** to create them like the demo) +- Every CRUD operation is done throught a **REST** endpoint, the real-time feature is done through a **Websocket** endpoint +- You can control **rollout percentage** (increase/decrease by only 5% at a time) +- Flag state is visible depending on time (unchanged for so long or not) +- Only one admin per project, to prevent collisions +- Deployable on **AWS Cloud** or locally on an **on-premise** server +- Supports **TLS** termination on the api layer (not end-to-end) +- All data are backed up regularly (configurable) + +> **Note:** If you want to fork this project make sure to configure the secrets on your behalf as well + ## Diagrams ### 1. Kubernetes Diagram @@ -27,6 +41,7 @@ You can find the **eraser.io** diagram code here [AWS Cloud Diagram Text](assets - Helm v3.19.0 - minikube v1.38.1 (for local dev) - docker v29.6.1 (client + server) +- Terraform v1.15.6 ## Used Packages @@ -107,6 +122,39 @@ control ├── go.work.sum ├── LICENSE ├── README.md +├── terraform # Iac +│   ├── main.tf +│   ├── modules +│   │   ├── caching +│   │   │   ├── main.tf +│   │   │   ├── outputs.tf +│   │   │   └── variables.tf +│   │   ├── compute +│   │   │   ├── ecr.tf +│   │   │   ├── eks.tf +│   │   │   ├── outputs.tf +│   │   │   └── variables.tf +│   │   ├── data +│   │   │   ├── main.tf +│   │   │   ├── outputs.tf +│   │   │   └── variables.tf +│   │   ├── edge +│   │   │   ├── oidc.tf +│   │   │   ├── outputs.tf +│   │   │   ├── variables.tf +│   │   │   └── waf.tf +│   │   ├── security +│   │   │   ├── main.tf +│   │   │   ├── outputs.tf +│   │   │   └── variables.tf +│   │   └── vpc +│   │   ├── main.tf +│   │   ├── outputs.tf +│   │   └── variables.tf +│   ├── outputs.tf +│   ├── providers.tf +│   ├── README.md +│   └── variables.tf ├── shared # Shared module between api and tui │   ├── go.mod │   └── types.go @@ -463,3 +511,32 @@ The rest is the same | TUI can't reach API | Verify `--network=host` is used when running TUI container | | `invalid authorization format` | Ensure `Bearer $TOKEN` header is set correctly | | Stale images after code changes | Re-run `go build` and `docker build` steps at top | + +## AWS + Terraform +If you want to deploy it on the cloud (only AWS is supported for now), don't forget to configure your profile or use your credentials locally +```bash +nvim ~/.aws/credentials + +# Which should contain +# [default] +# aws_access_key_id = +# aws_secret_access_key = +``` + +Then you can +```bash +# If you changed anything in the tf files, make sure to format them (it's optional but recommended) +terraform fmt -recursive + +# Validate to make sure there are no errors +terraform validate + +# Then proceed with planning +terraform plan + +# If you're ready to deploy, then +terraform apply +``` + +# Contributions +We currently accept contributions, but we don't mind if you fork this repo and build on top of it, so feel free to do so. diff --git a/terraform/README.md b/terraform/README.md new file mode 100644 index 0000000..321ac8c --- /dev/null +++ b/terraform/README.md @@ -0,0 +1,59 @@ + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.9 | +| [aws](#requirement\_aws) | ~> 5.60 | + +## Providers + +No providers. + +## Modules + +| Name | Source | Version | +|------|--------|---------| +| [caching](#module\_caching) | ./modules/caching | n/a | +| [compute](#module\_compute) | ./modules/compute | n/a | +| [data](#module\_data) | ./modules/data | n/a | +| [edge](#module\_edge) | ./modules/edge | n/a | +| [security](#module\_security) | ./modules/security | n/a | +| [vpc](#module\_vpc) | ./modules/vpc | n/a | + +## Resources + +No resources. + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [aws\_region](#input\_aws\_region) | n/a | `string` | `"us-east-1"` | no | +| [azs](#input\_azs) | n/a | `list` |
[
"us-east-1a",
"us-east-1b"
]
| no | +| [cache\_node\_type](#input\_cache\_node\_type) | n/a | `string` | `"cache.t4g.micro"` | no | +| [data\_subnet\_cidrs](#input\_data\_subnet\_cidrs) | n/a | `list(string)` | n/a | yes | +| [db\_instance\_class](#input\_db\_instance\_class) | n/a | `string` | `"db.t4g.micro"` | no | +| [db\_password](#input\_db\_password) | n/a | `any` | n/a | yes | +| [db\_username](#input\_db\_username) | n/a | `string` | `"control"` | no | +| [eks\_cluster\_version](#input\_eks\_cluster\_version) | n/a | `string` | `"1.30"` | no | +| [environment](#input\_environment) | n/a | `string` | `"prod"` | no | +| [github\_repo](#input\_github\_repo) | org/repo for the OIDC trust policy | `string` | `"ignorant05/control"` | no | +| [node\_desired\_size](#input\_node\_desired\_size) | n/a | `number` | `2` | no | +| [node\_instance\_type](#input\_node\_instance\_type) | n/a | `string` | `"t3.medium"` | no | +| [private\_subnet\_cidrs](#input\_private\_subnet\_cidrs) | n/a | `list(string)` | n/a | yes | +| [project](#input\_project) | n/a | `string` | `"control"` | no | +| [public\_subnet\_cidrs](#input\_public\_subnet\_cidrs) | n/a | `list(string)` | n/a | yes | +| [redis\_auth\_token](#input\_redis\_auth\_token) | n/a | `string` | n/a | yes | +| [vpc\_cidr](#input\_vpc\_cidr) | n/a | `string` | `"10.0.0.0/16"` | no | + +## Outputs + +| Name | Description | +|------|-------------| +| [ecr\_repository\_url](#output\_ecr\_repository\_url) | n/a | +| [eks\_cluster\_name](#output\_eks\_cluster\_name) | n/a | +| [github\_actions\_role\_arn](#output\_github\_actions\_role\_arn) | n/a | +| [rds\_endpoint](#output\_rds\_endpoint) | n/a | +| [redis\_endpoint](#output\_redis\_endpoint) | n/a | + \ No newline at end of file diff --git a/terraform/main.tf b/terraform/main.tf new file mode 100644 index 0000000..d40cadd --- /dev/null +++ b/terraform/main.tf @@ -0,0 +1,81 @@ +terraform { + required_version = ">= 1.9" + + backend "s3" { + bucket = "control-tfstate" + key = "eks/terraform.tfstate" + region = "us-east-1" + use_lockfile = true + encrypt = true + } + + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 5.60" + } + } +} + +module "vpc" { + source = "./modules/vpc" + + aws_region = var.aws_region + project = var.project + vpc_cidr = var.vpc_cidr + azs = var.azs + public_subnet_cidrs = var.public_subnet_cidrs + private_subnet_cidrs = var.private_subnet_cidrs + data_subnet_cidrs = var.data_subnet_cidrs +} + +module "compute" { + source = "./modules/compute" + + project = var.project + environment = var.environment + eks_cluster_version = var.eks_cluster_version + vpc_id = module.vpc.vpc_id + private_subnets = module.vpc.private_subnets + node_instance_type = var.node_instance_type + node_desired_size = var.node_desired_size +} + +module "security" { + source = "./modules/security" + + project = var.project + vpc_id = module.vpc.vpc_id + eks_node_security_group_id = module.compute.node_security_group_id +} + +module "data" { + source = "./modules/data" + + project = var.project + environment = var.environment + data_subnets = module.vpc.data_subnets + security_group_id = module.security.rds_security_group_id + db_instance_class = var.db_instance_class + db_username = var.db_username + db_password = var.db_password +} + +module "caching" { + source = "./modules/caching" + + project = var.project + environment = var.environment + data_subnets = module.vpc.data_subnets + security_group_id = module.security.redis_security_group_id + cache_node_type = var.cache_node_type + redis_auth_token = var.redis_auth_token +} + +module "edge" { + source = "./modules/edge" + + project = var.project + github_repo = var.github_repo + eks_cluster_arn = module.compute.cluster_arn +} diff --git a/terraform/modules/caching/main.tf b/terraform/modules/caching/main.tf new file mode 100644 index 0000000..997cefc --- /dev/null +++ b/terraform/modules/caching/main.tf @@ -0,0 +1,18 @@ +resource "aws_elasticache_subnet_group" "this" { + name = "${var.project}-cache" + subnet_ids = var.data_subnets +} + +resource "aws_elasticache_replication_group" "redis" { + replication_group_id = "${var.project}-${var.environment}" + description = "control feature-flag cache + pubsub" + engine = "redis" + engine_version = "7.1" + node_type = var.cache_node_type + num_cache_clusters = 1 + subnet_group_name = aws_elasticache_subnet_group.this.name + security_group_ids = [var.security_group_id] + at_rest_encryption_enabled = true + transit_encryption_enabled = true + auth_token = var.redis_auth_token +} diff --git a/terraform/modules/caching/outputs.tf b/terraform/modules/caching/outputs.tf new file mode 100644 index 0000000..d6dea04 --- /dev/null +++ b/terraform/modules/caching/outputs.tf @@ -0,0 +1,3 @@ +output "primary_endpoint" { + value = aws_elasticache_replication_group.redis.primary_endpoint_address +} diff --git a/terraform/modules/caching/variables.tf b/terraform/modules/caching/variables.tf new file mode 100644 index 0000000..9504778 --- /dev/null +++ b/terraform/modules/caching/variables.tf @@ -0,0 +1,24 @@ +variable "project" { + type = string +} + +variable "environment" { + type = string +} + +variable "data_subnets" { + type = list(string) +} + +variable "security_group_id" { + type = string +} + +variable "cache_node_type" { + type = string +} + +variable "redis_auth_token" { + type = string + sensitive = true +} diff --git a/terraform/modules/compute/ecr.tf b/terraform/modules/compute/ecr.tf new file mode 100644 index 0000000..eebf4fa --- /dev/null +++ b/terraform/modules/compute/ecr.tf @@ -0,0 +1,25 @@ +resource "aws_ecr_repository" "control_api" { + name = "control-api" + image_tag_mutability = "IMMUTABLE" + + image_scanning_configuration { + scan_on_push = true + } +} + +resource "aws_ecr_lifecycle_policy" "control_api" { + repository = aws_ecr_repository.control_api.name + policy = jsonencode({ + rules = [{ + rulePriority = 1 + description = "expire untagged images after 14 days" + selection = { + tagStatus = "untagged" + countType = "sinceImagePushed" + countUnit = "days" + countNumber = 14 + } + action = { type = "expire" } + }] + }) +} diff --git a/terraform/modules/compute/eks.tf b/terraform/modules/compute/eks.tf new file mode 100644 index 0000000..74e4e01 --- /dev/null +++ b/terraform/modules/compute/eks.tf @@ -0,0 +1,23 @@ +module "eks" { + source = "terraform-aws-modules/eks/aws" + version = "~> 20.24" + + cluster_name = "${var.project}-${var.environment}" + cluster_version = var.eks_cluster_version + + vpc_id = var.vpc_id + subnet_ids = var.private_subnets + + cluster_endpoint_public_access = true + + eks_managed_node_groups = { + default = { + instance_types = [var.node_instance_type] + min_size = 1 + max_size = var.node_desired_size + 2 + desired_size = var.node_desired_size + } + } + + enable_cluster_creator_admin_permissions = true +} diff --git a/terraform/modules/compute/outputs.tf b/terraform/modules/compute/outputs.tf new file mode 100644 index 0000000..a88d9f3 --- /dev/null +++ b/terraform/modules/compute/outputs.tf @@ -0,0 +1,19 @@ +output "cluster_name" { + value = module.eks.cluster_name +} + +output "cluster_arn" { + value = module.eks.cluster_arn +} + +output "cluster_endpoint" { + value = module.eks.cluster_endpoint +} + +output "node_security_group_id" { + value = module.eks.node_security_group_id +} + +output "ecr_repository_url" { + value = aws_ecr_repository.control_api.repository_url +} diff --git a/terraform/modules/compute/variables.tf b/terraform/modules/compute/variables.tf new file mode 100644 index 0000000..f6cef21 --- /dev/null +++ b/terraform/modules/compute/variables.tf @@ -0,0 +1,27 @@ +variable "project" { + type = string +} + +variable "environment" { + type = string +} + +variable "eks_cluster_version" { + type = string +} + +variable "vpc_id" { + type = string +} + +variable "private_subnets" { + type = list(string) +} + +variable "node_instance_type" { + type = string +} + +variable "node_desired_size" { + type = number +} diff --git a/terraform/modules/data/main.tf b/terraform/modules/data/main.tf new file mode 100644 index 0000000..26e093c --- /dev/null +++ b/terraform/modules/data/main.tf @@ -0,0 +1,22 @@ +resource "aws_db_subnet_group" "this" { + name = "${var.project}-db" + subnet_ids = var.data_subnets +} + +resource "aws_db_instance" "postgres" { + identifier = "${var.project}-${var.environment}" + engine = "postgres" + engine_version = "16" + instance_class = var.db_instance_class + allocated_storage = 20 + storage_type = "gp3" + db_name = "control" + username = var.db_username + password = var.db_password + db_subnet_group_name = aws_db_subnet_group.this.name + vpc_security_group_ids = [var.security_group_id] + publicly_accessible = false + skip_final_snapshot = false + backup_retention_period = 7 + deletion_protection = true +} diff --git a/terraform/modules/data/outputs.tf b/terraform/modules/data/outputs.tf new file mode 100644 index 0000000..8b04f3d --- /dev/null +++ b/terraform/modules/data/outputs.tf @@ -0,0 +1,7 @@ +output "endpoint" { + value = aws_db_instance.postgres.endpoint +} + +output "address" { + value = aws_db_instance.postgres.address +} diff --git a/terraform/modules/data/variables.tf b/terraform/modules/data/variables.tf new file mode 100644 index 0000000..c266976 --- /dev/null +++ b/terraform/modules/data/variables.tf @@ -0,0 +1,28 @@ +variable "project" { + type = string +} + +variable "environment" { + type = string +} + +variable "data_subnets" { + type = list(string) +} + +variable "security_group_id" { + type = string +} + +variable "db_instance_class" { + type = string +} + +variable "db_username" { + type = string +} + +variable "db_password" { + type = string + sensitive = true +} diff --git a/terraform/modules/edge/oidc.tf b/terraform/modules/edge/oidc.tf new file mode 100644 index 0000000..61b5468 --- /dev/null +++ b/terraform/modules/edge/oidc.tf @@ -0,0 +1,51 @@ +data "tls_certificate" "github" { + url = "https://token.actions.githubusercontent.com/.well-known/openid-configuration" +} + +resource "aws_iam_openid_connect_provider" "github" { + url = "https://token.actions.githubusercontent.com" + client_id_list = ["sts.amazonaws.com"] + thumbprint_list = [data.tls_certificate.github.certificates[0].sha1_fingerprint] +} + +resource "aws_iam_role" "github_actions" { + name = "${var.project}-gha-deploy" + + assume_role_policy = jsonencode({ + Version = "2012-10-17" + Statement = [{ + Effect = "Allow" + Principal = { Federated = aws_iam_openid_connect_provider.github.arn } + Action = "sts:AssumeRoleWithWebIdentity" + Condition = { + StringEquals = { + "token.actions.githubusercontent.com:aud" = "sts.amazonaws.com" + } + StringLike = { + "token.actions.githubusercontent.com:sub" = "repo:${var.github_repo}:ref:refs/heads/main" + } + } + }] + }) +} + +resource "aws_iam_role_policy" "github_actions" { + name = "ecr-eks-deploy" + role = aws_iam_role.github_actions.id + + policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Effect = "Allow" + Action = ["ecr:GetAuthorizationToken", "ecr:BatchCheckLayerAvailability", "ecr:PutImage", "ecr:InitiateLayerUpload", "ecr:UploadLayerPart", "ecr:CompleteLayerUpload"] + Resource = "*" + }, + { + Effect = "Allow" + Action = ["eks:DescribeCluster"] + Resource = var.eks_cluster_arn + } + ] + }) +} diff --git a/terraform/modules/edge/outputs.tf b/terraform/modules/edge/outputs.tf new file mode 100644 index 0000000..bd39492 --- /dev/null +++ b/terraform/modules/edge/outputs.tf @@ -0,0 +1,7 @@ +output "github_actions_role_arn" { + value = aws_iam_role.github_actions.arn +} + +output "waf_web_acl_arn" { + value = aws_wafv2_web_acl.api.arn +} diff --git a/terraform/modules/edge/variables.tf b/terraform/modules/edge/variables.tf new file mode 100644 index 0000000..3fcabd0 --- /dev/null +++ b/terraform/modules/edge/variables.tf @@ -0,0 +1,11 @@ +variable "project" { + type = string +} + +variable "github_repo" { + type = string +} + +variable "eks_cluster_arn" { + type = string +} diff --git a/terraform/modules/edge/waf.tf b/terraform/modules/edge/waf.tf new file mode 100644 index 0000000..2d365a7 --- /dev/null +++ b/terraform/modules/edge/waf.tf @@ -0,0 +1,75 @@ +resource "aws_wafv2_web_acl" "api" { + name = "${var.project}-api" + scope = "REGIONAL" + + default_action { + allow {} + } + + rule { + name = "aws-managed-common" + priority = 1 + + override_action { + none {} + } + + statement { + managed_rule_group_statement { + name = "AWSManagedRulesCommonRuleSet" + vendor_name = "AWS" + } + } + + visibility_config { + cloudwatch_metrics_enabled = true + metric_name = "common-rules" + sampled_requests_enabled = true + } + } + + rule { + name = "rate-limit-login" + priority = 2 + + action { + block {} + } + + statement { + rate_based_statement { + limit = 300 + aggregate_key_type = "IP" + + scope_down_statement { + byte_match_statement { + search_string = "/api/v1/login" + + field_to_match { + uri_path {} + } + + text_transformation { + priority = 0 + type = "NONE" + } + + positional_constraint = "STARTS_WITH" + } + } + } + } + + visibility_config { + cloudwatch_metrics_enabled = true + metric_name = "login-rate-limit" + sampled_requests_enabled = true + } + } + + visibility_config { + cloudwatch_metrics_enabled = true + metric_name = "${var.project}-api" + sampled_requests_enabled = true + } +} diff --git a/terraform/modules/security/main.tf b/terraform/modules/security/main.tf new file mode 100644 index 0000000..b6222e1 --- /dev/null +++ b/terraform/modules/security/main.tf @@ -0,0 +1,37 @@ +resource "aws_security_group" "rds" { + name_prefix = "${var.project}-rds-" + vpc_id = var.vpc_id + + ingress { + from_port = 5432 + to_port = 5432 + protocol = "tcp" + security_groups = [var.eks_node_security_group_id] + } + + egress { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } +} + +resource "aws_security_group" "redis" { + name_prefix = "${var.project}-redis-" + vpc_id = var.vpc_id + + ingress { + from_port = 6379 + to_port = 6379 + protocol = "tcp" + security_groups = [var.eks_node_security_group_id] + } + + egress { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } +} diff --git a/terraform/modules/security/outputs.tf b/terraform/modules/security/outputs.tf new file mode 100644 index 0000000..8ada17a --- /dev/null +++ b/terraform/modules/security/outputs.tf @@ -0,0 +1,7 @@ +output "rds_security_group_id" { + value = aws_security_group.rds.id +} + +output "redis_security_group_id" { + value = aws_security_group.redis.id +} diff --git a/terraform/modules/security/variables.tf b/terraform/modules/security/variables.tf new file mode 100644 index 0000000..9e1faff --- /dev/null +++ b/terraform/modules/security/variables.tf @@ -0,0 +1,11 @@ +variable "project" { + type = string +} + +variable "vpc_id" { + type = string +} + +variable "eks_node_security_group_id" { + type = string +} diff --git a/terraform/modules/vpc/main.tf b/terraform/modules/vpc/main.tf new file mode 100644 index 0000000..8a4852d --- /dev/null +++ b/terraform/modules/vpc/main.tf @@ -0,0 +1,62 @@ +module "vpc" { + source = "terraform-aws-modules/vpc/aws" + version = "~> 5.8" + + name = "${var.project}-vpc" + cidr = var.vpc_cidr + azs = var.azs + + public_subnets = var.public_subnet_cidrs + private_subnets = var.private_subnet_cidrs + intra_subnets = var.data_subnet_cidrs + + enable_nat_gateway = true + single_nat_gateway = true + enable_dns_hostnames = true + + private_subnet_tags = { "kubernetes.io/role/internal-elb" = "1" } + public_subnet_tags = { "kubernetes.io/role/elb" = "1" } +} + +resource "aws_vpc_endpoint" "ecr_api" { + vpc_id = module.vpc.vpc_id + service_name = "com.amazonaws.${var.aws_region}.ecr.api" + vpc_endpoint_type = "Interface" + subnet_ids = module.vpc.private_subnets + security_group_ids = [aws_security_group.vpc_endpoints.id] + private_dns_enabled = true +} + +resource "aws_vpc_endpoint" "ecr_dkr" { + vpc_id = module.vpc.vpc_id + service_name = "com.amazonaws.${var.aws_region}.ecr.dkr" + vpc_endpoint_type = "Interface" + subnet_ids = module.vpc.private_subnets + security_group_ids = [aws_security_group.vpc_endpoints.id] + private_dns_enabled = true +} + +resource "aws_vpc_endpoint" "s3" { + vpc_id = module.vpc.vpc_id + service_name = "com.amazonaws.${var.aws_region}.s3" + vpc_endpoint_type = "Gateway" + route_table_ids = module.vpc.private_route_table_ids +} + +resource "aws_security_group" "vpc_endpoints" { + name_prefix = "${var.project}-vpce-" + vpc_id = module.vpc.vpc_id + + ingress { + from_port = 443 + to_port = 443 + protocol = "tcp" + cidr_blocks = [var.vpc_cidr] + } + egress { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } +} diff --git a/terraform/modules/vpc/outputs.tf b/terraform/modules/vpc/outputs.tf new file mode 100644 index 0000000..35ed290 --- /dev/null +++ b/terraform/modules/vpc/outputs.tf @@ -0,0 +1,23 @@ +output "vpc_id" { + value = module.vpc.vpc_id +} + +output "vpc_cidr" { + value = module.vpc.vpc_cidr_block +} + +output "public_subnets" { + value = module.vpc.public_subnets +} + +output "private_subnets" { + value = module.vpc.private_subnets +} + +output "data_subnets" { + value = module.vpc.intra_subnets +} + +output "private_route_table_ids" { + value = module.vpc.private_route_table_ids +} diff --git a/terraform/modules/vpc/variables.tf b/terraform/modules/vpc/variables.tf new file mode 100644 index 0000000..4e9a37a --- /dev/null +++ b/terraform/modules/vpc/variables.tf @@ -0,0 +1,21 @@ +variable "aws_region" { + type = string +} +variable "project" { + type = string +} +variable "vpc_cidr" { + type = string +} +variable "azs" { + type = list(string) +} +variable "public_subnet_cidrs" { + type = list(string) +} +variable "private_subnet_cidrs" { + type = list(string) +} +variable "data_subnet_cidrs" { + type = list(string) +} diff --git a/terraform/outputs.tf b/terraform/outputs.tf new file mode 100644 index 0000000..a3ed788 --- /dev/null +++ b/terraform/outputs.tf @@ -0,0 +1,19 @@ +output "eks_cluster_name" { + value = module.compute.cluster_name +} + +output "ecr_repository_url" { + value = module.compute.ecr_repository_url +} + +output "rds_endpoint" { + value = module.data.endpoint +} + +output "redis_endpoint" { + value = module.caching.primary_endpoint +} + +output "github_actions_role_arn" { + value = module.edge.github_actions_role_arn +} diff --git a/terraform/providers.tf b/terraform/providers.tf new file mode 100644 index 0000000..c9d7ccb --- /dev/null +++ b/terraform/providers.tf @@ -0,0 +1,3 @@ +provider "aws" { + region = var.aws_region +} diff --git a/terraform/variables.tf b/terraform/variables.tf new file mode 100644 index 0000000..e53bf8c --- /dev/null +++ b/terraform/variables.tf @@ -0,0 +1,68 @@ +variable "aws_region" { + default = "us-east-1" +} + +variable "project" { + default = "control" +} + +variable "environment" { + default = "prod" +} + +variable "vpc_cidr" { + default = "10.0.0.0/16" +} + +variable "azs" { + default = ["us-east-1a", "us-east-1b"] +} + +variable "eks_cluster_version" { + default = "1.30" +} + +variable "node_instance_type" { + default = "t3.medium" +} + +variable "node_desired_size" { + default = 2 +} + +variable "db_instance_class" { + default = "db.t4g.micro" +} + +variable "cache_node_type" { + default = "cache.t4g.micro" +} + +variable "db_username" { + default = "control" +} + +variable "db_password" { + sensitive = true +} + +variable "github_repo" { + description = "org/repo for the OIDC trust policy" + default = "ignorant05/control" +} + +variable "public_subnet_cidrs" { + type = list(string) +} + +variable "private_subnet_cidrs" { + type = list(string) +} + +variable "data_subnet_cidrs" { + type = list(string) +} + +variable "redis_auth_token" { + type = string +}