Skip to content
Open
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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ The system works through a four-step process:
- `Microsoft.Resources.ResourceDeleteSuccess` (resource deletions)

### 2. Event Storage (Azure Storage Queue)
- Events are queued in an **Azure Storage Queue** for reliable processing
- Events are queued in a private **Azure Storage Queue** for reliable processing
- Uses CloudEvent schema v1.0 format for standardized event structure

### 3. Event Processing (Azure Function)
Expand Down
2 changes: 1 addition & 1 deletion eventgrid.tf
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ resource "azurerm_eventgrid_system_topic_event_subscription" "azure_rm_event_sub

storage_queue_endpoint {
storage_account_id = azurerm_storage_account.stacklet.id
queue_name = azurerm_storage_queue.stacklet.name
queue_name = azapi_resource.stacklet_queue.name
}

included_event_types = var.event_names
Expand Down
4 changes: 2 additions & 2 deletions function.tf
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ resource "local_file" "function_json" {
name = "msg"
type = "queueTrigger"
direction = "in"
queueName = azurerm_storage_queue.stacklet.name
queueName = azapi_resource.stacklet_queue.name
connection = "AzureWebJobsStorage"
}
]
Expand Down Expand Up @@ -129,7 +129,7 @@ resource "azurerm_linux_function_app" "stacklet" {
# Application configuration
AZURE_CLIENT_ID = azurerm_user_assigned_identity.stacklet_identity.client_id
AZURE_AUDIENCE = local.audience
AZURE_STORAGE_QUEUE_NAME = azurerm_storage_queue.stacklet.name
AZURE_STORAGE_QUEUE_NAME = azapi_resource.stacklet_queue.name
AWS_TARGET_ACCOUNT = var.aws_target_account
AWS_TARGET_REGION = var.aws_target_region
AWS_TARGET_ROLE_NAME = var.aws_target_role_name
Expand Down
8 changes: 8 additions & 0 deletions provider.tf
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ terraform {
source = "hashicorp/azurerm"
version = ">=4.35.0"
}
azapi = {
source = "azure/azapi"
version = ">=2.8.0"
}
}
}

Expand All @@ -35,3 +39,7 @@ provider "azurerm" {

subscription_id = var.subscription_id
}

provider "azapi" {
subscription_id = var.subscription_id
}
52 changes: 48 additions & 4 deletions storage.tf
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,54 @@ resource "azurerm_storage_account" "stacklet" {
location = azurerm_resource_group.stacklet_rg.location
account_tier = "Standard"
account_replication_type = "LRS"
tags = local.tags

# Enable public network access temporarily to allow the function app to upload the function code.
# Note: This will always trigger a change on update because the azapi_update_resource will set it to false
# after the function app is deployed, but we need to set it to true again temporarily to allow the function
# app to upload any new function code.
public_network_access_enabled = true

tags = local.tags
}

resource "azurerm_storage_queue" "stacklet" {
name = "${azurerm_storage_account.stacklet.name}-queue"
storage_account_name = azurerm_storage_account.stacklet.name
# Using azapi provider to create storage queue via ARM API (control plane)
# This avoids the need for Terraform to access storage data plane APIs
resource "azapi_resource" "stacklet_queue" {
type = "Microsoft.Storage/storageAccounts/queueServices/queues@2023-01-01"
name = "${azurerm_storage_account.stacklet.name}-queue"
parent_id = "${azurerm_storage_account.stacklet.id}/queueServices/default"

body = {
properties = {
metadata = {}
}
}

depends_on = [azurerm_storage_account.stacklet]
}

# Update storage account network settings to make it private after function app is deployed.
# This ensures the function app code can be uploaded to the storage account before we lock it
# down, and then the actual function run can still occur due to the bypass setting.
resource "azapi_update_resource" "stacklet_storage_network" {
type = "Microsoft.Storage/storageAccounts@2023-01-01"
resource_id = azurerm_storage_account.stacklet.id

body = {
properties = {
# Disable public network access - only private endpoints allowed
publicNetworkAccess = "Disabled"
}
}

depends_on = [azurerm_linux_function_app.stacklet]

# Ensure that the update is applied if the public network access is enabled again (which will
# happen on every update because the azurerm_storage_account resource will always make it
# public to allow the function app to upload any new function code).
lifecycle {
replace_triggered_by = [
azurerm_storage_account.stacklet.public_network_access_enabled
]
}
}