GitHub - stacklet/terraform-azure-stacklet-relay: Terraform Module to relay events into Stacklet · GitHub
Skip to content

About

Terraform Module to relay events into Stacklet

Topics

Resources

Stars

0 stars

Watchers

9 watching

Forks

Repository files navigation

Overview

This Terraform module implements an event forwarding system that captures Azure resource events and relays them to Stacklet's AWS-based platform for real-time policy execution and governance. It creates a cross-cloud event bridge that enables Stacklet's governance capabilities to extend from AWS into Azure environments.

Architecture

The system works through a four-step process:

1. Event Capture (Azure EventGrid)

  • Sets up an Azure EventGrid System Topic to capture subscription-level events
  • By default monitors these resource events:
    • Microsoft.Resources.ResourceWriteSuccess (resource creation/updates)
    • Microsoft.Resources.ResourceActionSuccess (resource actions)
    • Microsoft.Resources.ResourceDeleteSuccess (resource deletions)

2. Event Storage (Azure Storage Queue)

  • Events are queued in a private Azure Storage Queue for reliable processing
  • Uses CloudEvent schema v1.0 format for standardized event structure
  • The function app reads the queue over a private endpoint, but Event Grid cannot use one, so it delivers over Azure's trusted-services exception
  • That exception is wider than Event Grid, but it is only a network rule. It is Azure's blanket setting for the whole trusted-services list, so any resource of a trusted type in your tenant can reach the account's public endpoint. Reaching it is not using it: every request still needs a valid credential or role assignment
  • A terraform apply opens the account to the internet briefly so the function app can upload its code, then closes it again at the end of a successful run. A failed apply leaves it open, so run it again and confirm the account is closed

Warning

If a policy in your tenant removes the trusted-services exception, event delivery stops without failing anything you are likely to watch. Terraform still applies and the function app still reports healthy. The signals are the queue that stops filling and Event Grid's delivery-failure count, which climbs as it retries. Run terraform apply again to restore the setting. A policy that keeps removing it strips it again after each apply, so fix the policy rather than re-applying.

3. Event Processing (Azure Function)

  • Python-based Azure Function processes events from the storage queue
  • Uses queue trigger to automatically process incoming events
  • Runs on Linux App Service Plan with Python 3.10

4. Cross-Cloud Authentication & Event Forwarding

  • Uses Azure Managed Identity to get an identity token
  • Performs AssumeRoleWithWebIdentity to obtain AWS credentials
  • Forwards events to AWS EventBridge in the target Stacklet account

Key Components Deployed

  1. Azure Resource Group - Contains all module resources
  2. Azure EventGrid System Topic - Captures subscription-level events
  3. Azure Virtual Network - Keeps all network traffic private
  4. Azure Storage Account & Queue - Provides reliable event storage
  5. Azure Function App - Handles event processing and forwarding
  6. Azure Application Insights - Enables monitoring and logging
  7. Azure AD Application & Service Principal - Manages cross-cloud authentication
  8. User Assigned Identity - Provides managed identity for the function

Benefits

This system enables:

  • Event-driven policy execution - Real-time response to Azure resource changes
  • Real-time compliance monitoring - Immediate visibility into compliance status
  • Automated governance actions - Automated remediation and policy enforcement
  • Cross-cloud resource visibility - Unified governance across Azure and AWS

Provider Configuration

This module does not configure providers. The calling module must configure azurerm and azapi providers with the target subscription. The azuread provider is configured automatically from your Azure credentials.

Credentials are sourced from the standard Azure authentication chain. For local use, authenticate via az login. For automated deployments, supply credentials via environment variables (ARM_CLIENT_ID, ARM_CLIENT_SECRET, ARM_TENANT_ID) or by setting client_id, client_secret, and tenant_id directly on your provider blocks.

Standalone deployment

The common case — deploying the relay directly into a single subscription:

provider "azurerm" {
  features {}
  subscription_id = "your-subscription-id"
}

provider "azapi" {
  subscription_id = "your-subscription-id"
}

module "azure_relay" {
  source  = "stacklet/stacklet-relay/azure"
  version = "0.1.0"

  prefix               = "your-prefix"
  aws_target_account   = "123456789012"
  aws_target_region    = "us-east-1"
  aws_target_role_name = "your-prefix-azure-relay"
  aws_target_event_bus = "your-prefix-azure-relay"
  aws_target_prefix    = "your-prefix"
}

Embedded in a larger root module

If your root module manages multiple Azure subscriptions simultaneously (e.g. a management subscription and a workload subscription), use provider aliases and pass them explicitly via providers:

provider "azurerm" {
  features {}
  subscription_id = "management-subscription-id"
}

provider "azurerm" {
  alias           = "workload"
  features {}
  subscription_id = "workload-subscription-id"
}

provider "azapi" {
  alias           = "workload"
  subscription_id = "workload-subscription-id"
}

module "azure_relay" {
  source  = "stacklet/stacklet-relay/azure"
  version = "0.1.0"

  providers = {
    azurerm = azurerm.workload
    azuread = azuread
    azapi   = azapi.workload
  }

  prefix               = "your-prefix"
  aws_target_account   = "123456789012"
  aws_target_region    = "us-east-1"
  aws_target_role_name = "your-prefix-azure-relay"
  aws_target_event_bus = "your-prefix-azure-relay"
  aws_target_prefix    = "your-prefix"
}

Migrating from a previous version

The following breaking changes were made to align with Terraform's recommended practice of not declaring provider configurations in reusable modules:

  • subscription_id input variable removed — set subscription_id directly on your azurerm and azapi provider blocks instead
  • force_delete_resource_group input variable removed — to allow deletion of a non-empty resource group, set prevent_deletion_if_contains_resources = false in the features {} block of your azurerm provider

No changes to deployed infrastructure are required. On your next terraform plan after moving source to the registry address and setting version, you should see 0 resource changes.

Versioning

This module is published to the Terraform Registry. Set source to the registry address and pin version to a release.

version takes the usual constraint syntax. This module is pre-1.0, and on a 0.x line a minor release is where it ships breaking changes, so pin at the patch level: ~> 0.1.0 accepts 0.1.1 and later patches and holds at 0.2.0. Read the release notes before moving to a new minor.

Requirements

Name Version
terraform >= 1.14.0, < 2.0.0
archive >= 2.7.1, < 3.0.0
azapi >= 2.8.0, < 3.0.0
azuread >= 3.7.0, < 4.0.0
azurerm >= 4.56.0, < 5.0.0
local >= 2.6.2, < 3.0.0
random >= 3.8.1, < 4.0.0

Providers

Name Version
archive >= 2.7.1, < 3.0.0
azapi >= 2.8.0, < 3.0.0
azuread >= 3.7.0, < 4.0.0
azurerm >= 4.56.0, < 5.0.0
local >= 2.6.2, < 3.0.0
random >= 3.8.1, < 4.0.0

Modules

No modules.

Resources

Name Type
azapi_resource.stacklet_queue resource
azapi_update_resource.stacklet_function_network resource
azapi_update_resource.stacklet_storage_network resource
azuread_app_role_assignment.stacklet_app_role_assignment resource
azuread_application.stacklet_application resource
azuread_service_principal.stacklet_sp resource
azurerm_application_insights.stacklet resource
azurerm_eventgrid_system_topic.azure_rm_events resource
azurerm_eventgrid_system_topic_event_subscription.azure_rm_event_subscription resource
azurerm_linux_function_app.stacklet resource
azurerm_private_dns_zone.storage_blob resource
azurerm_private_dns_zone.storage_queue resource
azurerm_private_dns_zone.storage_table resource
azurerm_private_dns_zone_virtual_network_link.storage_blob resource
azurerm_private_dns_zone_virtual_network_link.storage_queue resource
azurerm_private_dns_zone_virtual_network_link.storage_table resource
azurerm_private_endpoint.stacklet_storage_blob resource
azurerm_private_endpoint.stacklet_storage_queue resource
azurerm_private_endpoint.stacklet_storage_table resource
azurerm_resource_group.stacklet_rg resource
azurerm_role_assignment.function_storage_account resource
azurerm_role_assignment.function_storage_blob resource
azurerm_role_assignment.function_storage_queue resource
azurerm_service_plan.stacklet resource
azurerm_storage_account.stacklet resource
azurerm_subnet.stacklet_function resource
azurerm_subnet.stacklet_private_endpoints resource
azurerm_user_assigned_identity.stacklet_identity resource
azurerm_virtual_network.stacklet resource
local_file.function_app_versioned resource
local_file.function_json resource
local_file.host_json resource
random_string.storage_account_suffix resource
random_uuid.app_role_uuid resource
archive_file.function_app data source
azuread_application.stacklet_application data source
azuread_client_config.current data source
azuread_service_principal.stacklet_sp data source
azurerm_eventgrid_system_topic.azure_rm_events data source
azurerm_subscription.current data source

Inputs

Name Description Type Default Required
aws_target_account AWS Target account for relay, to be provided by Stacklet. string n/a yes
aws_target_event_bus AWS Target event bus for relay, to be provided by Stacklet. string n/a yes
aws_target_partition AWS Target partition for relay, to be provided by Stacklet. string "aws" no
aws_target_prefix Deployment prefix for the target Stacklet instance, to be provided by Stacklet. string n/a yes
aws_target_region AWS Target region for relay, to be provided by Stacklet. string n/a yes
aws_target_role_name AWS Target role name for relay, to be provided by Stacklet. string n/a yes
azuread_application Azure AD Application. One per tenant. string null no
event_grid_topic_name Name of an existing Subscription System Topic to attach to. Omit it to have the module create one. Must be set together with event_grid_topic_resource_group. string null no
event_grid_topic_resource_group Name of the resource group containing event_grid_topic_name. Required when event_grid_topic_name is set, and must be omitted otherwise. string null no
event_names Event Names to filter list(string)
[
"Microsoft.Resources.ResourceWriteSuccess",
"Microsoft.Resources.ResourceActionSuccess",
"Microsoft.Resources.ResourceDeleteSuccess"
]
no
prefix A Prefix for all of the generated resources string n/a yes
resource_group_location Resource Group location for generated resources string "East US" no
resource_group_name Resource Group name for generated resources string null no
subnet_prefix_length The network prefix size used for virtual network subnets string 24 no
tags Tags to apply to resources map(any) {} no
vnet_address_space Address space for the relay's virtual network string "10.0.0.0/16" no

Outputs

No outputs.

About

Terraform Module to relay events into Stacklet

Topics

Resources

Stars

0 stars

Watchers

9 watching

Forks

Releases

Packages

Used by

Contributors

Languages