Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 2 additions & 5 deletions samples/web-app-sql-database/python/terraform/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@

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.

> **NOTE**: Terraform modules do not install Azure Key Vault. This will be fixed soon.

## Prerequisites

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

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.
1. [Azure Resource Group](https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/manage-resource-groups-cli): Logical container for all resources
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.
3. [Azure SQL Database](https://learn.microsoft.com/en-us/azure/azure-sql/database/): The `PlannerDB` database storing relational vacation activity data.
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.
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.
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.
7. [Azure Key Vault](https://learn.microsoft.com/en-us/azure/key-vault/general/overview): Stores the SQL connection string in a secret.
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.
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.

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).

Expand Down
2 changes: 1 addition & 1 deletion samples/web-app-sql-database/python/terraform/deploy.sh
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ fi

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

# Deploy the web app
echo "Deploying web app [$WEB_APP_NAME] with zip file [$ZIPFILE]..."
Expand Down
86 changes: 82 additions & 4 deletions samples/web-app-sql-database/python/terraform/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,12 @@ locals {
sql_server_name = "${var.prefix}-sqlserver-${var.suffix}"
app_service_plan_name = "${var.prefix}-app-service-plan-${var.suffix}"
web_app_name = "${var.prefix}-webapp-${var.suffix}"
key_vault_name = "${var.prefix}-kv-${var.suffix}"
}

# Retrieve the current Azure client configuration
data "azurerm_client_config" "current" {}

# Create a resource group
resource "azurerm_resource_group" "example" {
name = local.resource_group_name
Expand Down Expand Up @@ -111,10 +115,10 @@ resource "azurerm_linux_web_app" "example" {
app_settings = {
SCM_DO_BUILD_DURING_DEPLOYMENT = "true"
ENABLE_ORYX_BUILD = "true"
SQL_SERVER = azurerm_mssql_server.example.fully_qualified_domain_name
SQL_DATABASE = azurerm_mssql_database.example.name
SQL_USERNAME = var.sql_database_username
SQL_PASSWORD = var.sql_database_password
KEY_VAULT_NAME = azurerm_key_vault.example.name
SECRET_NAME = azurerm_key_vault_secret.sql_connection_string.name
KEYVAULT_URI = azurerm_key_vault.example.vault_uri
CERT_NAME = azurerm_key_vault_certificate.example.name
LOGIN_NAME = var.login_name
}

Expand All @@ -125,6 +129,80 @@ resource "azurerm_linux_web_app" "example" {
}
}

# Create a Key Vault
resource "azurerm_key_vault" "example" {
name = local.key_vault_name
resource_group_name = azurerm_resource_group.example.name
location = azurerm_resource_group.example.location
tenant_id = data.azurerm_client_config.current.tenant_id
sku_name = "standard"
enable_rbac_authorization = false
soft_delete_retention_days = 7
tags = var.tags

lifecycle {
ignore_changes = [
tags
]
}
}

# Grant the Web App managed identity access to Key Vault secrets and certificates
resource "azurerm_key_vault_access_policy" "web_app" {
key_vault_id = azurerm_key_vault.example.id
tenant_id = data.azurerm_client_config.current.tenant_id
object_id = azurerm_linux_web_app.example.identity[0].principal_id

secret_permissions = [
"Get",
"List",
]

certificate_permissions = [
"Get",
]
}

# Create a Key Vault secret for SQL connection string
resource "azurerm_key_vault_secret" "sql_connection_string" {
name = var.secret_name
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;"
key_vault_id = azurerm_key_vault.example.id
}

# Create a self-signed certificate in Key Vault
resource "azurerm_key_vault_certificate" "example" {
name = var.cert_name
key_vault_id = azurerm_key_vault.example.id

certificate_policy {
issuer_parameters {
name = "Self"
}

key_properties {
exportable = true
key_size = 2048
key_type = "RSA"
reuse_key = false
}

secret_properties {
content_type = "application/x-pkcs12"
}

x509_certificate_properties {
subject = "CN=${var.cert_subject}"
validity_in_months = 12

key_usage = [
"digitalSignature",
"keyEncipherment",
]
}
}
}

# Deploy code from a public GitHub repo
resource "azurerm_app_service_source_control" "example" {
count = var.repo_url == "" ? 0 : 1
Expand Down
12 changes: 12 additions & 0 deletions samples/web-app-sql-database/python/terraform/outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,16 @@ output "web_app_name" {

output "web_app_url" {
value = azurerm_linux_web_app.example.default_hostname
}

output "key_vault_name" {
value = azurerm_key_vault.example.name
}

output "key_vault_url" {
value = azurerm_key_vault.example.vault_uri
}

output "sql_connection_string_secret_uri" {
value = azurerm_key_vault_secret.sql_connection_string.id
}
18 changes: 18 additions & 0 deletions samples/web-app-sql-database/python/terraform/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,24 @@ variable "login_name" {
default = "paolo"
}

variable "secret_name" {
description = "(Optional) Specifies the name of the Key Vault secret for the SQL connection string."
type = string
default = "sql-connection-string"
}

variable "cert_name" {
description = "(Optional) Specifies the name of the Key Vault certificate."
type = string
default = "webapp-cert"
}

variable "cert_subject" {
description = "(Optional) Specifies the subject of the self-signed certificate."
type = string
default = "sample-web-app-sql"
}

variable "tags" {
description = "(Optional) Specifies the tags to be applied to the resources."
type = map(string)
Expand Down
Loading