Skip to content

Commit d8357be

Browse files
committed
feat: azure deployment v1
1 parent 23e0c06 commit d8357be

41 files changed

Lines changed: 3715 additions & 225 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
**/bin/*
77
**/obj/*
88

9+
910
# Ignore .env, except in web-frontend, where an
1011
# empty copy is needed for vite-envs to work.
1112
.env
@@ -24,3 +25,48 @@ e2e/.env
2425

2526
# Load test user pool (contains credentials)
2627
load-tests/data/users.json
28+
29+
# Local .terraform directories
30+
.terraform/
31+
32+
# .tfstate files
33+
*.tfstate
34+
*.tfstate.*
35+
36+
# Crash log files
37+
crash.log
38+
crash.*.log
39+
40+
# Exclude all .tfvars files, which are likely to contain sensitive data, such as
41+
# password, private keys, and other secrets. These should not be part of version
42+
# control as they are data points which are potentially sensitive and subject
43+
# to change depending on the environment.
44+
*.tfvars
45+
*.tfvars.json
46+
47+
# Ignore override files as they are usually used to override resources locally and so
48+
# are not checked in
49+
override.tf
50+
override.tf.json
51+
*_override.tf
52+
*_override.tf.json
53+
54+
# Ignore transient lock info files created by terraform apply
55+
.terraform.tfstate.lock.info
56+
57+
# Include override files you do wish to add to version control using negated pattern
58+
# !example_override.tf
59+
60+
# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan
61+
# example: *tfplan*
62+
63+
# Ignore CLI configuration files
64+
.terraformrc
65+
terraform.rc
66+
67+
# Optional: ignore graph output files generated by `terraform graph`
68+
# *.dot
69+
70+
# Optional: ignore plan files saved before destroying Terraform configuration
71+
# Uncomment the line below if you want to ignore planout files.
72+
# planout

shared/infra/azure/.terraform.lock.hcl

Lines changed: 42 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

shared/infra/azure/main.tf

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# Shared Infrastructure Stack
2+
# Deploys shared resources for integrated environments (dev, prod)
3+
4+
module "shared" {
5+
source = "./modules/shared-resources"
6+
7+
env = var.env
8+
location = var.location
9+
dd_api_key = var.dd_api_key
10+
dd_site = var.dd_site
11+
vnet_address_space = var.vnet_address_space
12+
container_apps_subnet_prefix = var.container_apps_subnet_prefix
13+
private_endpoints_subnet_prefix = var.private_endpoints_subnet_prefix
14+
postgresql_subnet_prefix = var.postgresql_subnet_prefix
15+
postgresql_admin_username = var.postgresql_admin_username
16+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Shared Container App Environment
2+
# All services in this environment can communicate internally via:
3+
# http://<app-name>.internal.<environment-unique-id>.<region>.azurecontainerapps.io
4+
resource "azurerm_container_app_environment" "shared" {
5+
name = "cae-stickerlandia-${var.env}"
6+
location = azurerm_resource_group.shared.location
7+
resource_group_name = azurerm_resource_group.shared.name
8+
log_analytics_workspace_id = azurerm_log_analytics_workspace.main.id
9+
infrastructure_subnet_id = azurerm_subnet.container_apps.id
10+
internal_load_balancer_enabled = false
11+
tags = local.tags
12+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# PostgreSQL Flexible Server (shared cluster - services create their own databases)
2+
resource "azurerm_postgresql_flexible_server" "shared" {
3+
name = "psql-stickerlandia-${var.env}"
4+
location = azurerm_resource_group.shared.location
5+
resource_group_name = azurerm_resource_group.shared.name
6+
version = "16"
7+
delegated_subnet_id = azurerm_subnet.postgresql.id
8+
private_dns_zone_id = azurerm_private_dns_zone.postgresql.id
9+
public_network_access_enabled = false
10+
administrator_login = var.postgresql_admin_username
11+
administrator_password = random_password.postgresql_admin_password.result
12+
zone = "1"
13+
storage_mb = 32768
14+
storage_tier = "P4"
15+
sku_name = var.postgresql_sku_name
16+
tags = local.tags
17+
18+
depends_on = [
19+
azurerm_private_dns_zone_virtual_network_link.postgresql
20+
]
21+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Azure Front Door Standard (shared entry point for all services)
2+
resource "azurerm_cdn_frontdoor_profile" "shared" {
3+
name = "afd-stickerlandia-${var.env}"
4+
resource_group_name = azurerm_resource_group.shared.name
5+
sku_name = "Standard_AzureFrontDoor"
6+
tags = local.tags
7+
}
8+
9+
# Shared Front Door Endpoint
10+
resource "azurerm_cdn_frontdoor_endpoint" "shared" {
11+
name = "stickerlandia-api-${var.env}"
12+
cdn_frontdoor_profile_id = azurerm_cdn_frontdoor_profile.shared.id
13+
tags = local.tags
14+
}
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
# Random suffix for globally unique Key Vault name
2+
resource "random_string" "kv_suffix" {
3+
length = 6
4+
special = false
5+
upper = false
6+
}
7+
8+
# Shared Key Vault for secrets management
9+
resource "azurerm_key_vault" "shared" {
10+
name = "kv-sticker-${var.env}-${random_string.kv_suffix.result}"
11+
location = azurerm_resource_group.shared.location
12+
resource_group_name = azurerm_resource_group.shared.name
13+
tenant_id = data.azurerm_client_config.current.tenant_id
14+
sku_name = "standard"
15+
soft_delete_retention_days = 7
16+
purge_protection_enabled = false
17+
public_network_access_enabled = true
18+
rbac_authorization_enabled = true
19+
tags = local.tags
20+
21+
network_acls {
22+
bypass = "AzureServices"
23+
default_action = "Allow"
24+
}
25+
}
26+
27+
# Private Endpoint for Key Vault
28+
resource "azurerm_private_endpoint" "keyvault" {
29+
name = "pe-keyvault-${var.env}"
30+
location = azurerm_resource_group.shared.location
31+
resource_group_name = azurerm_resource_group.shared.name
32+
subnet_id = azurerm_subnet.private_endpoints.id
33+
tags = local.tags
34+
35+
private_service_connection {
36+
name = "keyvault-connection"
37+
private_connection_resource_id = azurerm_key_vault.shared.id
38+
is_manual_connection = false
39+
subresource_names = ["vault"]
40+
}
41+
42+
private_dns_zone_group {
43+
name = "keyvault-dns-group"
44+
private_dns_zone_ids = [azurerm_private_dns_zone.keyvault.id]
45+
}
46+
}
47+
48+
# Role assignment for current user to manage secrets during deployment
49+
resource "azurerm_role_assignment" "keyvault_admin" {
50+
scope = azurerm_key_vault.shared.id
51+
role_definition_name = "Key Vault Secrets Officer"
52+
principal_id = data.azurerm_client_config.current.object_id
53+
}
54+
55+
# Store Datadog API Key in Key Vault (shared across all services)
56+
resource "azurerm_key_vault_secret" "dd_api_key" {
57+
name = "dd-api-key"
58+
value = var.dd_api_key
59+
key_vault_id = azurerm_key_vault.shared.id
60+
tags = local.tags
61+
62+
depends_on = [
63+
azurerm_role_assignment.keyvault_admin,
64+
azurerm_private_endpoint.keyvault
65+
]
66+
}
67+
68+
# Store PostgreSQL admin password in Key Vault
69+
resource "random_password" "postgresql_admin_password" {
70+
length = 32
71+
special = true
72+
override_special = "!#$%&*()-_=+[]{}<>:?"
73+
}
74+
75+
resource "azurerm_key_vault_secret" "postgresql_admin_password" {
76+
name = "postgresql-admin-password"
77+
value = random_password.postgresql_admin_password.result
78+
key_vault_id = azurerm_key_vault.shared.id
79+
tags = local.tags
80+
81+
depends_on = [
82+
azurerm_role_assignment.keyvault_admin,
83+
azurerm_private_endpoint.keyvault
84+
]
85+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# Shared Resources Module
2+
# This module can be called from:
3+
# 1. The shared infrastructure stack (for integrated environments like dev/prod)
4+
# 2. Service stacks directly (for ephemeral/test environments)
5+
6+
terraform {
7+
required_providers {
8+
azurerm = {
9+
source = "hashicorp/azurerm"
10+
version = "~> 4.27"
11+
}
12+
random = {
13+
source = "hashicorp/random"
14+
version = "~> 3.8"
15+
}
16+
}
17+
}
18+
19+
# Local values
20+
locals {
21+
resource_group_name = coalesce(var.resource_group_name, "rg-stickerlandia-shared-${var.env}")
22+
23+
default_tags = {
24+
env = var.env
25+
project = "stickerlandia"
26+
scope = "shared"
27+
source = "terraform"
28+
}
29+
30+
tags = merge(local.default_tags, var.tags)
31+
}
32+
33+
# Data sources
34+
data "azurerm_subscription" "current" {}
35+
36+
data "azurerm_client_config" "current" {}
37+
38+
# Resource Group
39+
resource "azurerm_resource_group" "shared" {
40+
name = local.resource_group_name
41+
location = var.location
42+
tags = local.tags
43+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Service Bus Namespace (shared - services create their own queues/topics)
2+
resource "azurerm_servicebus_namespace" "shared" {
3+
name = "sb-stickerlandia-${var.env}"
4+
location = azurerm_resource_group.shared.location
5+
resource_group_name = azurerm_resource_group.shared.name
6+
sku = "Standard"
7+
tags = local.tags
8+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Log Analytics Workspace (required by Container Apps)
2+
resource "azurerm_log_analytics_workspace" "main" {
3+
name = "log-stickerlandia-${var.env}"
4+
location = azurerm_resource_group.shared.location
5+
resource_group_name = azurerm_resource_group.shared.name
6+
sku = "PerGB2018"
7+
retention_in_days = 30
8+
tags = local.tags
9+
}

0 commit comments

Comments
 (0)