Repository navigation
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.
| 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.
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.
| 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.
| 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.
| 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 |
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 |
| 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
|
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.
| 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 |
| 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.
MIT licensed — reportmate.app