Skip to content

Commit 6b8d99d

Browse files
Add Key Vault to Terraform deployment (#69)
1 parent 52fb97f commit 6b8d99d

5 files changed

Lines changed: 115 additions & 10 deletions

File tree

samples/web-app-sql-database/python/terraform/README.md

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22

33
This directory contains Terraform modules and a deployment script for provisioning Azure services in LocalStack for Azure. Refer to the [Azure Web App with Azure SQL Database](../README.md) guide for details about the sample application.
44

5-
> **NOTE**: Terraform modules do not install Azure Key Vault. This will be fixed soon.
6-
75
## Prerequisites
86

97
Before deploying this solution, ensure you have the following tools installed:
@@ -32,13 +30,12 @@ For more information, see [Get started with the az tool on LocalStack](https://a
3230
The [main.tf](main.tf) Terraform module creates the following Azure resources:
3331

3432
1. [Azure Resource Group](https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/manage-resource-groups-cli): Logical container for all resources in the sample.
35-
1. [Azure Resource Group](https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/manage-resource-groups-cli): Logical container for all resources
3633
2. [Azure SQL Server](https://learn.microsoft.com/en-us/azure/azure-sql/database/sql-database-paas-overview): Logical server hosting one or more Azure SQL Databases.
3734
3. [Azure SQL Database](https://learn.microsoft.com/en-us/azure/azure-sql/database/): The `PlannerDB` database storing relational vacation activity data.
3835
4. [Azure App Service Plan](https://learn.microsoft.com/en-us/azure/app-service/overview-hosting-plans): The compute resource that hosts the web application.
3936
5. [Azure Web App](https://learn.microsoft.com/en-us/azure/app-service/overview): Hosts the Python Flask single-page application (*Vacation Planner*), connected to Azure SQL Database.
40-
6. [App Service Source Control](https://learn.microsoft.com/en-us/rest/api/appservice/web-apps/create-or-update-source-control?view=rest-appservice-2024-11-01): (Optional) Configures automatic deployment from a public GitHub repository.
41-
7. [Azure Key Vault](https://learn.microsoft.com/en-us/azure/key-vault/general/overview): Stores the SQL connection string in a secret.
37+
6. [Azure Key Vault](https://learn.microsoft.com/en-us/azure/key-vault/general/overview): Stores the SQL connection string as a secret and a self-signed certificate for HTTPS.
38+
7. [App Service Source Control](https://learn.microsoft.com/en-us/rest/api/appservice/web-apps/create-or-update-source-control?view=rest-appservice-2024-11-01): (Optional) Configures automatic deployment from a public GitHub repository.
4239

4340
The system implements a Vacation Planner web application that stores and retrieves activity data from Azure SQL Database. For more information, see [Azure Web App with Azure SQL Database](../README.md).
4441

samples/web-app-sql-database/python/terraform/deploy.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ fi
217217

218218
# Create the zip package of the web app
219219
echo "Creating zip package of the web app..."
220-
zip -r "$ZIPFILE" app.py activities.py database.py static templates requirements.txt
220+
zip -r "$ZIPFILE" app.py activities.py database.py certificates.py static templates requirements.txt
221221

222222
# Deploy the web app
223223
echo "Deploying web app [$WEB_APP_NAME] with zip file [$ZIPFILE]..."

samples/web-app-sql-database/python/terraform/main.tf

Lines changed: 82 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,12 @@ locals {
55
sql_server_name = "${var.prefix}-sqlserver-${var.suffix}"
66
app_service_plan_name = "${var.prefix}-app-service-plan-${var.suffix}"
77
web_app_name = "${var.prefix}-webapp-${var.suffix}"
8+
key_vault_name = "${var.prefix}-kv-${var.suffix}"
89
}
910

11+
# Retrieve the current Azure client configuration
12+
data "azurerm_client_config" "current" {}
13+
1014
# Create a resource group
1115
resource "azurerm_resource_group" "example" {
1216
name = local.resource_group_name
@@ -111,10 +115,10 @@ resource "azurerm_linux_web_app" "example" {
111115
app_settings = {
112116
SCM_DO_BUILD_DURING_DEPLOYMENT = "true"
113117
ENABLE_ORYX_BUILD = "true"
114-
SQL_SERVER = azurerm_mssql_server.example.fully_qualified_domain_name
115-
SQL_DATABASE = azurerm_mssql_database.example.name
116-
SQL_USERNAME = var.sql_database_username
117-
SQL_PASSWORD = var.sql_database_password
118+
KEY_VAULT_NAME = azurerm_key_vault.example.name
119+
SECRET_NAME = azurerm_key_vault_secret.sql_connection_string.name
120+
KEYVAULT_URI = azurerm_key_vault.example.vault_uri
121+
CERT_NAME = azurerm_key_vault_certificate.example.name
118122
LOGIN_NAME = var.login_name
119123
}
120124

@@ -125,6 +129,80 @@ resource "azurerm_linux_web_app" "example" {
125129
}
126130
}
127131

132+
# Create a Key Vault
133+
resource "azurerm_key_vault" "example" {
134+
name = local.key_vault_name
135+
resource_group_name = azurerm_resource_group.example.name
136+
location = azurerm_resource_group.example.location
137+
tenant_id = data.azurerm_client_config.current.tenant_id
138+
sku_name = "standard"
139+
enable_rbac_authorization = false
140+
soft_delete_retention_days = 7
141+
tags = var.tags
142+
143+
lifecycle {
144+
ignore_changes = [
145+
tags
146+
]
147+
}
148+
}
149+
150+
# Grant the Web App managed identity access to Key Vault secrets and certificates
151+
resource "azurerm_key_vault_access_policy" "web_app" {
152+
key_vault_id = azurerm_key_vault.example.id
153+
tenant_id = data.azurerm_client_config.current.tenant_id
154+
object_id = azurerm_linux_web_app.example.identity[0].principal_id
155+
156+
secret_permissions = [
157+
"Get",
158+
"List",
159+
]
160+
161+
certificate_permissions = [
162+
"Get",
163+
]
164+
}
165+
166+
# Create a Key Vault secret for SQL connection string
167+
resource "azurerm_key_vault_secret" "sql_connection_string" {
168+
name = var.secret_name
169+
value = "Server=tcp:${azurerm_mssql_server.example.fully_qualified_domain_name},1433;Database=${azurerm_mssql_database.example.name};User ID=${var.sql_database_username};Password=${var.sql_database_password};Encrypt=yes;TrustServerCertificate=no;Connection Timeout=30;"
170+
key_vault_id = azurerm_key_vault.example.id
171+
}
172+
173+
# Create a self-signed certificate in Key Vault
174+
resource "azurerm_key_vault_certificate" "example" {
175+
name = var.cert_name
176+
key_vault_id = azurerm_key_vault.example.id
177+
178+
certificate_policy {
179+
issuer_parameters {
180+
name = "Self"
181+
}
182+
183+
key_properties {
184+
exportable = true
185+
key_size = 2048
186+
key_type = "RSA"
187+
reuse_key = false
188+
}
189+
190+
secret_properties {
191+
content_type = "application/x-pkcs12"
192+
}
193+
194+
x509_certificate_properties {
195+
subject = "CN=${var.cert_subject}"
196+
validity_in_months = 12
197+
198+
key_usage = [
199+
"digitalSignature",
200+
"keyEncipherment",
201+
]
202+
}
203+
}
204+
}
205+
128206
# Deploy code from a public GitHub repo
129207
resource "azurerm_app_service_source_control" "example" {
130208
count = var.repo_url == "" ? 0 : 1

samples/web-app-sql-database/python/terraform/outputs.tf

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,16 @@ output "web_app_name" {
2020

2121
output "web_app_url" {
2222
value = azurerm_linux_web_app.example.default_hostname
23+
}
24+
25+
output "key_vault_name" {
26+
value = azurerm_key_vault.example.name
27+
}
28+
29+
output "key_vault_url" {
30+
value = azurerm_key_vault.example.vault_uri
31+
}
32+
33+
output "sql_connection_string_secret_uri" {
34+
value = azurerm_key_vault_secret.sql_connection_string.id
2335
}

samples/web-app-sql-database/python/terraform/variables.tf

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,24 @@ variable "login_name" {
349349
default = "paolo"
350350
}
351351

352+
variable "secret_name" {
353+
description = "(Optional) Specifies the name of the Key Vault secret for the SQL connection string."
354+
type = string
355+
default = "sql-connection-string"
356+
}
357+
358+
variable "cert_name" {
359+
description = "(Optional) Specifies the name of the Key Vault certificate."
360+
type = string
361+
default = "webapp-cert"
362+
}
363+
364+
variable "cert_subject" {
365+
description = "(Optional) Specifies the subject of the self-signed certificate."
366+
type = string
367+
default = "sample-web-app-sql"
368+
}
369+
352370
variable "tags" {
353371
description = "(Optional) Specifies the tags to be applied to the resources."
354372
type = map(string)

0 commit comments

Comments
 (0)