Skip to content

Resources

Rod Christiansen edited this page Oct 8, 2026 · 3 revisions

Resources

Every Azure and Entra ID object the module manages, grouped by concern. Resource type names are the Terraform type, so you can grep the repo for them.

The resource group itself is not in this list: main.tf reads it with data "azurerm_resource_group", so Terraform neither creates nor destroys it.

Database — modules/database

Type Name Purpose
azurerm_postgresql_flexible_server pg PostgreSQL 16 server holding all fleet data. Public network access enabled, auto-grow enabled, password auth enabled. Carries prevent_destroy
azurerm_postgresql_flexible_server_database db The ReportMate database, en_US.utf8 / utf8. Carries prevent_destroy
azurerm_postgresql_flexible_server_configuration max_connections Sets the server connection ceiling. Static parameter — a change restarts the server
azurerm_postgresql_flexible_server_firewall_rule azure_services The allow_azure rule (0.0.0.0–0.0.0.0) that lets Azure-hosted services, including the container apps, connect
azurerm_postgresql_flexible_server_firewall_rule allowed_ips One rule per entry in allowed_ips, excluding the catch-all. Each rule covers a single address: the module keeps only the part before / as both start and end
azurerm_postgresql_flexible_server_firewall_rule public_access Created only if allowed_ips contains 0.0.0.0/0. Opens the server to the whole internet
random_id db_suffix Suffix for the generated server name when postgres_server_name is empty
null_resource database_init_api Prints a post-provision summary. It does not run migrations

Auto-grow means Azure moves storage_mb without Terraform, so the server resource ignores changes to it. db_storage_mb is a create-time floor only.

Networking and edge — modules/networking

Created only when enable_custom_domain is true and custom_domain_name is non-empty.

Type Name Purpose
azurerm_cdn_frontdoor_profile main Front Door Standard profile
azurerm_cdn_frontdoor_endpoint main The public endpoint
azurerm_cdn_frontdoor_origin_group main Single origin group, health probe GET / over HTTPS every 60s
azurerm_cdn_frontdoor_origin main Points at the dashboard container app's FQDN. Certificate name check disabled, which Container Apps requires
azurerm_cdn_frontdoor_route main Matches /*, HTTPS-only forwarding, HTTP-to-HTTPS redirect, linked to the custom domain and the default domain
azurerm_cdn_frontdoor_rule_set main HeaderForwardingRules. Currently empty — the header rule was removed because Front Door will not let you modify X-Forwarded-Host or X-Forwarded-Proto
azurerm_cdn_frontdoor_custom_domain main The custom hostname with a managed TLS certificate. dns_zone_id is null, so DNS records are yours to create

There is deliberately no Front Door route to the API. All traffic enters through the dashboard, which adds the internal auth header before proxying.

There is no virtual network, subnet, private endpoint or private DNS zone anywhere in the module. The database and Key Vault are reachable over public endpoints, gated by firewall rules and RBAC rather than by network isolation.

Container platform — modules/containers

Type Name Purpose
azurerm_container_app_environment main The Container Apps environment, wired to the Log Analytics workspace
azurerm_container_app frontend_prod_main The Next.js dashboard. Port 3000, 0.5 vCPU / 1Gi, 1–5 replicas, external ingress, startup/liveness/readiness probes on /. Created when deploy_prod is true or environment is prod/both
azurerm_container_app api_functions The FastAPI backend. Port 8000, 2 vCPU / 4Gi, api_min_replicas–api_max_replicas, external ingress with CORS, liveness on /api/v1/health/live and readiness on /api/v1/health/ready, and a named HTTP concurrency scale rule
azurerm_container_registry acr Basic-tier ACR with admin enabled. Created only when use_custom_registry is true. Admin is on because the maintenance job authenticates with it
azurerm_role_assignment container_acr_pull AcrPull for the managed identity on the ACR
azurerm_role_assignment container_acr_push AcrPush for the managed identity on the ACR
random_id container_suffix Unused suffix generator

Both container apps hold their sensitive configuration as Container Apps secrets: db-url, client-passphrase, api-internal-secret, kiosk-tokens on the dashboard, and db-url, client-passphrase, api-internal-secret on the API. When Key Vault is enabled the dashboard also declares two Key Vault reference secrets resolved through the managed identity.

Scheduled maintenance — modules/maintenance

Type Name Purpose
azurerm_container_app_job maintenance Cron-triggered database cleanup, default 0 2 * * * UTC. 0.25 vCPU / 0.5Gi, 30-minute replica timeout, one retry. Runs <registry>/reportmate-maintenance:latest with DB_HOST, DB_NAME, DB_USER, DB_PASS and EVENT_RETENTION_DAYS set

The job's registry credential secret is generated by Azure when the registry is attached, so the module references it by its generated name and puts secret in ignore_changes.

Storage — modules/storage and modules/functions

Type Name Purpose
azurerm_storage_account main General-purpose account for ingestion. The root passes use_exact_name = true, so storage_account_name is used verbatim
azurerm_storage_queue ingest The osquery-ingest queue
random_id storage_suffix Suffix generator, bypassed by use_exact_name
azurerm_storage_account functions Separate account for the Function App, named after it with hyphens stripped plus storage. Only with enable_functions
azurerm_storage_container deployments Deployment-package container required by Flex Consumption
azurerm_storage_container usage_archive Durable gzip-CSV archive of usage history, which is the one table that cannot be re-collected from a device
azurerm_storage_table render_alerts Table the alert functions upsert per-machine rows into and read back for a daily digest

Serverless functions — modules/functions

Created only when enable_functions is true.

Type Name Purpose
azurerm_service_plan functions Linux plan named <function app>-flex-plan
azurerm_function_app_flex_consumption main Python 3.11 Flex Consumption function app, 512 MB instances, max 40 instances, HTTPS only, system-assigned identity. Hosts scheduled alerting and the usage archive
azurerm_key_vault_access_policy functions Get/List secret permissions on the vault this stack creates
azurerm_role_assignment functions_external_secrets Key Vault Secrets User on each vault in function_app_external_secret_vault_ids. RBAC rather than an access policy, because RBAC-enabled vaults ignore access policies

Identity and access — modules/identity

Type Name Purpose
azurerm_user_assigned_identity main The identity both container apps run as
azurerm_role_assignment storage_blob_contributor Storage Blob Data Contributor on the storage account
azurerm_role_assignment storage_queue_contributor Storage Queue Data Contributor on the storage account
azurerm_role_assignment monitoring_contributor Monitoring Contributor on Application Insights
azurerm_role_assignment pipeline_contributor Contributor on the resource group for a CI/CD service principal. Only with enable_pipeline_permissions and a non-empty pipeline_service_principal_id

Secrets — modules/key_vault

Created when enable_key_vault is true (the default).

Type Name Purpose
azurerm_key_vault reportmate RBAC-authorized vault, purge protection on, 7-day soft delete, network default action Allow with an AzureServices bypass
azurerm_role_assignment current_user Key Vault Administrator for the applying principal
azurerm_role_assignment managed_identity Key Vault Secrets User for the container apps' identity
azurerm_role_assignment devops_group Key Vault Administrator for devops_resource_infrasec_group_object_id
random_password nextauth_secret Generated session secret when none is supplied

Secrets always written: db-password, postgres-server-name, db-username, db-name, azure-ad-client-id, azure-ad-tenant-id, client-passphrase, api-internal-secret, kiosk-tokens, devops-group-object-id, custom-domain-name, nextauth-secret.

Secrets written only when the corresponding value is non-null or non-empty: storage-connection-string, appinsights-connection-string, reportmate-api-base-url, reportmate-frontend-url, auth-client-id, auth-client-secret, auth-tenant-id, ssh-password, and the five macdev-* signing secrets.

The auth module writes three more into the same vault: auth-client-id, auth-client-secret, auth-tenant-id, plus oidc-api-client-id when OIDC is enabled. A removed block in main.tf drops the auth module's former nextauth_secret from state without deleting the vault entry — two writers were rotating it on every apply and invalidating every signed-in session.

Entra ID — modules/auth

Type Name Purpose
azuread_application reportmate_web The dashboard's app registration: web redirect URIs, ID token issuance, Graph delegated permissions (User.Read, profile, email, openid), optional claims including groups as roles, and five app roles
azuread_service_principal reportmate_web Its service principal. app_role_assignment_required is true in prod
azuread_application_password reportmate_web The client secret, expiring per auth_client_secret_expiry
azuread_service_principal_delegated_permission_grant reportmate_web Admin consent for the four Graph scopes. Only in dev
azuread_app_role_assignment authorized_groups Assigns each group in authorized_groups the user role
azuread_app_role_assignment admins Assigns each principal in admin_principal_ids the admin role
null_resource update_identifier_uris Runs az ad app update to set api://<client id>, because tenant policy blocks friendly-name URIs. Re-runs every apply so a transient failure self-heals
random_password app_secret, nextauth_secret Generated secrets
time_sleep wait_for_rbac 60-second wait for vault RBAC to propagate before writing secrets
azurerm_key_vault_secret app_client_id, app_client_secret, app_tenant_id Auth values written to the vault

Gated behind enable_oidc_api (all in modules/auth/api.tf):

Type Name Purpose
azuread_application reportmate_api The API as a protected resource. v2.0 access tokens, an access_as_user delegated scope, and the ReportMate.Read / ReportMate.Ingest / ReportMate.Admin app roles, each allowing both Application and User members
azuread_service_principal reportmate_api Its service principal, with app-role assignment required
azuread_application_pre_authorized azure_cli Pre-authorizes the Azure CLI on the delegated scope so an operator can mint a token without a separate consent step
azuread_app_role_assignment api_readers, api_ingesters, api_admins One assignment per principal in each of the three OIDC principal lists
null_resource reportmate_api_identifier_uri Same identifier-URI provisioner as above
azurerm_key_vault_secret oidc_api_client_id Stores the API client id for reference

Monitoring — modules/monitoring

Type Name Purpose
azurerm_log_analytics_workspace main PerGB2018 workspace backing both Application Insights and Container Apps logs. Retention from log_retention_days, daily ingestion cap from log_daily_quota_gb
azurerm_application_insights main Workspace-based, web type, 30-day retention, 50% sampling, IP masking on, daily cap from app_insights_daily_cap
random_id monitor_suffix Unused suffix generator

The daily quota is a runaway backstop, not a shaping tool — ingestion pauses for the remainder of the UTC day once it is hit.

Clone this wiki locally