1+ # Main Terraform configuration for Pets Workshop Azure deployment
2+
3+ # Generate random string for unique naming
4+ resource "random_string" "suffix" {
5+ length = 8
6+ special = false
7+ upper = false
8+ }
9+
10+ # Get current user context for Key Vault access policy
11+ data "azurerm_client_config" "current" {}
12+
13+ # Resource Group
14+ resource "azurerm_resource_group" "main" {
15+ name = " ${ var . resource_prefix } -rg-${ random_string . suffix . result } "
16+ location = var. location
17+
18+ tags = var. tags
19+ }
20+
21+ # Application Insights for monitoring
22+ resource "azurerm_application_insights" "main" {
23+ name = " ${ var . resource_prefix } -ai-${ random_string . suffix . result } "
24+ location = azurerm_resource_group. main . location
25+ resource_group_name = azurerm_resource_group. main . name
26+ application_type = " web"
27+
28+ tags = var. tags
29+ }
30+
31+ # Key Vault for storing secrets
32+ resource "azurerm_key_vault" "main" {
33+ name = " ${ var . resource_prefix } -kv-${ random_string . suffix . result } "
34+ location = azurerm_resource_group. main . location
35+ resource_group_name = azurerm_resource_group. main . name
36+ tenant_id = data. azurerm_client_config . current . tenant_id
37+ sku_name = " standard"
38+
39+ # Enable soft delete and purge protection
40+ soft_delete_retention_days = 7
41+ purge_protection_enabled = false
42+
43+ # Network access
44+ network_acls {
45+ default_action = " Allow"
46+ bypass = " AzureServices"
47+ }
48+
49+ tags = var. tags
50+ }
51+
52+ # Key Vault access policy for current user
53+ resource "azurerm_key_vault_access_policy" "current_user" {
54+ key_vault_id = azurerm_key_vault. main . id
55+ tenant_id = data. azurerm_client_config . current . tenant_id
56+ object_id = data. azurerm_client_config . current . object_id
57+
58+ secret_permissions = [
59+ " Get" ,
60+ " List" ,
61+ " Set" ,
62+ " Delete" ,
63+ " Recover" ,
64+ " Backup" ,
65+ " Restore"
66+ ]
67+ }
68+
69+ # SQL Server
70+ resource "azurerm_mssql_server" "main" {
71+ name = " ${ var . resource_prefix } -sql-${ random_string . suffix . result } "
72+ resource_group_name = azurerm_resource_group. main . name
73+ location = azurerm_resource_group. main . location
74+ version = " 12.0"
75+ administrator_login = var. sql_admin_username
76+ administrator_login_password = var. sql_admin_password
77+
78+ # Security configurations
79+ minimum_tls_version = " 1.2"
80+
81+ azuread_administrator {
82+ login_username = var. sql_admin_username
83+ object_id = data. azurerm_client_config . current . object_id
84+ }
85+
86+ tags = var. tags
87+ }
88+
89+ # SQL Database
90+ resource "azurerm_mssql_database" "main" {
91+ name = " ${ var . resource_prefix } -sqldb-${ random_string . suffix . result } "
92+ server_id = azurerm_mssql_server. main . id
93+ collation = " SQL_Latin1_General_CP1_CI_AS"
94+ license_type = " LicenseIncluded"
95+ max_size_gb = 2
96+ sku_name = var. sql_database_sku
97+ zone_redundant = false
98+
99+ tags = var. tags
100+ }
101+
102+ # SQL Server firewall rule to allow Azure services
103+ resource "azurerm_mssql_firewall_rule" "allow_azure_services" {
104+ name = " AllowAzureServices"
105+ server_id = azurerm_mssql_server. main . id
106+ start_ip_address = " 0.0.0.0"
107+ end_ip_address = " 0.0.0.0"
108+ }
109+
110+ # Store database connection string in Key Vault
111+ resource "azurerm_key_vault_secret" "database_connection_string" {
112+ name = " database-connection-string"
113+ value = " mssql+pyodbc://${ var . sql_admin_username } :${ var . sql_admin_password } @${ azurerm_mssql_server . main . fully_qualified_domain_name } :1433/${ azurerm_mssql_database . main . name } ?driver=ODBC+Driver+17+for+SQL+Server"
114+ key_vault_id = azurerm_key_vault. main . id
115+
116+ depends_on = [azurerm_key_vault_access_policy . current_user ]
117+ }
118+
119+ # App Service Plan for Flask backend
120+ resource "azurerm_service_plan" "main" {
121+ name = " ${ var . resource_prefix } -asp-${ random_string . suffix . result } "
122+ resource_group_name = azurerm_resource_group. main . name
123+ location = azurerm_resource_group. main . location
124+ os_type = " Linux"
125+ sku_name = var. app_service_sku
126+
127+ tags = var. tags
128+ }
129+
130+ # App Service for Flask backend
131+ resource "azurerm_linux_web_app" "backend" {
132+ name = " ${ var . resource_prefix } -backend-${ random_string . suffix . result } "
133+ resource_group_name = azurerm_resource_group. main . name
134+ location = azurerm_service_plan. main . location
135+ service_plan_id = azurerm_service_plan. main . id
136+
137+ site_config {
138+ application_stack {
139+ python_version = " 3.11"
140+ }
141+
142+ # Enable CORS for frontend
143+ cors {
144+ allowed_origins = [" *" ] # In production, specify your frontend domain
145+ support_credentials = false
146+ }
147+
148+ # Health check
149+ health_check_path = " /api/dogs"
150+ }
151+
152+ # Application settings
153+ app_settings = {
154+ " APPLICATIONINSIGHTS_CONNECTION_STRING" = azurerm_application_insights.main.connection_string
155+ " SCM_DO_BUILD_DURING_DEPLOYMENT" = " true"
156+ " ENABLE_ORYX_BUILD" = " true"
157+ " WEBSITES_ENABLE_APP_SERVICE_STORAGE" = " false"
158+
159+ # Database configuration will be set via Key Vault reference
160+ " @Microsoft.KeyVault(SecretUri=${azurerm_key_vault_secret.database_connection_string.id})" = " DATABASE_URL"
161+ }
162+
163+ # Identity for Key Vault access
164+ identity {
165+ type = " SystemAssigned"
166+ }
167+
168+ tags = var. tags
169+ }
170+
171+ # Key Vault access policy for App Service managed identity
172+ resource "azurerm_key_vault_access_policy" "app_service" {
173+ key_vault_id = azurerm_key_vault. main . id
174+ tenant_id = azurerm_linux_web_app. backend . identity [0 ]. tenant_id
175+ object_id = azurerm_linux_web_app. backend . identity [0 ]. principal_id
176+
177+ secret_permissions = [
178+ " Get" ,
179+ " List"
180+ ]
181+ }
182+
183+ # Static Web App for frontend
184+ resource "azurerm_static_web_app" "frontend" {
185+ name = " ${ var . resource_prefix } -swa-${ random_string . suffix . result } "
186+ resource_group_name = azurerm_resource_group. main . name
187+ location = var. static_web_app_location
188+ sku_tier = var. static_web_app_sku
189+ sku_size = var. static_web_app_sku
190+
191+ tags = var. tags
192+ }
193+
194+ # Static Web App custom domain (optional)
195+ # Uncomment and configure if you have a custom domain
196+ # resource "azurerm_static_web_app_custom_domain" "frontend" {
197+ # static_web_app_id = azurerm_static_web_app.frontend.id
198+ # domain_name = var.custom_domain
199+ # validation_type = "cname-delegation"
200+ # }
0 commit comments