Azure Deployment
This guide walks you through deploying Beacon to Azure using an automated template. The template creates all required resources in one go.
What Gets Created
The deployment template creates:
| Resource | Purpose |
|---|---|
| Resource Group | Container for all Beacon resources |
| App Registration | Multi-tenant app for accessing client M365 data |
| Function App | Runs the Beacon polling service (Linux, Flex Consumption) |
| App Service Plan | Flex Consumption serverless hosting plan |
| Storage Account | Required by Azure Functions, config, and alert deduplication |
| Federated Credential | Secure authentication (no secrets needed) |
| Log Analytics Workspace | Stores alerts for querying and dashboards |
| Application Insights | Function App logging and monitoring |
| Data Collection Endpoint | Ingestion endpoint for Log Analytics |
| Data Collection Rule | Routes alerts to the custom table |
| Custom Table (Beacon_Alerts_CL) | Schema for alert data |
| Workbook (Beacon Alerts) | Dashboard for alert visualisation in Log Analytics |
| Role Assignments | Storage Blob Data Owner, Storage Table Data Contributor, Monitoring Metrics Publisher |
Prerequisites
Before you begin, you'll need:
- Azure subscription with permission to create resources
- Azure CLI installed (Download here)
- Bicep CLI installed (run
az bicep installif not already installed)
Step 1: Download the Template
Download both template files from the repository:
beacon.bicep- Main deployment filebeacon-resources.bicep- Resource definitions
Save both files to the same folder on your computer.
TIP
You can also clone the entire repository:
git clone https://github.com/emildosen/beacon.git
cd beacon/infraStep 2: Sign In to Azure
Open a terminal and sign in:
az loginA browser window will open. Sign in with your Azure account. If you have multiple subscriptions, you'll be asked to select one after authenticating.
Step 3: Deploy Infrastructure
Run the deployment command, replacing the location with your preferred Azure region:
az deployment sub create \
--location australiaeast \
--template-file beacon.bicepAvailable Regions
Common regions include: australiaeast, northeurope, westeurope, eastus, westus2, uksouth, southeastasia.
For a full list, run: az account list-locations -o table
Deployment Parameters
You can customise the deployment with these parameters:
Basic Parameters
| Parameter | Default | Description |
|---|---|---|
resourceGroupName | rg-beacon | Name for the resource group |
appName | Beacon | Name used for the app registration and resources |
enableFederatedAuth | true | Enable federated authentication for the Function App managed identity |
Resource Names
Use these parameters to specify custom names for resources, useful when resources already exist or you need specific naming conventions. Leave empty to use auto-generated names. Default patterns use the appName parameter (shown below as {app}).
| Parameter | Default | Description |
|---|---|---|
functionAppName | {app}-func-[6 random] | Function App name |
storageAccountName | {app}[10 random] | Storage Account name |
appServicePlanName | {app}-plan | App Service Plan name |
logAnalyticsWorkspaceName | law-{app} | Log Analytics Workspace name |
dataCollectionEndpointName | dce-{app} | Data Collection Endpoint name |
dataCollectionRuleName | dcr-{app} | Data Collection Rule name |
appInsightsName | ai-{app} | Application Insights name |
Example with custom values:
az deployment sub create \
--location australiaeast \
--template-file beacon.bicep \
--parameters \
resourceGroupName=rg-beacon-prod \
appName=BeaconProdExample with custom resource names:
az deployment sub create \
--location australiaeast \
--template-file beacon.bicep \
--parameters \
resourceGroupName=rg-beacon-prod \
functionAppName=my-existing-func \
storageAccountName=myexistingstorageExample disabling federated auth (for client secret authentication):
az deployment sub create \
--location australiaeast \
--template-file beacon.bicep \
--parameters \
enableFederatedAuth=falseHosting Plan
Beacon deploys on the Flex Consumption plan. This is a serverless plan that scales to zero when idle and only charges for actual execution time. All storage access uses managed identity — no connection strings or secrets are stored in app settings.
Step 4: Note the Outputs
When deployment completes, you'll see output values. Save these for later:
Outputs:
adminConsentUrl: https://login.microsoftonline.com/.../adminconsent?client_id=...
appRegistrationAppId: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
appRegistrationName: Beacon
customTableName: Beacon_Alerts_CL
dataCollectionEndpointUrl: https://dce-beacon-xxxx.australiaeast-1.ingest.monitor.azure.com
dataCollectionRuleId: dcr-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
dataCollectionRuleName: dcr-beacon-alerts
functionAppName: beacon-func-xxxxxx
functionAppUrl: https://beacon-func-xxxxxx.azurewebsites.net
logAnalyticsWorkspaceId: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
logAnalyticsWorkspaceName: law-beacon
resourceGroupName: rg-beacon
storageAccountName: beaconxxxxxxxxxx
appInsightsName: ai-beaconThe adminConsentUrl is particularly important - you'll need it for onboarding client tenants.
Step 5: Grant Admin Consent
The app registration is created with the required permissions, but admin consent must still be granted.
For your own tenant
Not strictly necessary, only if you want to monitor your own tenant too.
- Open the
adminConsentUrlfrom the deployment outputs - Sign in with a Global Administrator account
- Review the permissions and click Accept
For client tenants
For each client tenant you want to monitor:
- Replace the tenant ID in the consent URL:
https://login.microsoftonline.com/{client-tenant-id}/adminconsent?client_id={app-client-id} - Send this URL to the client's Global Administrator
- They sign in and accept the permissions
Expected Behaviour
After granting consent, you'll see an error. This is expected. The app has no redirect URL configured, so the browser has nowhere to go. The consent itself was granted successfully.
Verify Deployment
- Open the Azure Portal
- Navigate to Resource groups → rg-beacon (or your custom name)
- Confirm all resources are present and healthy
To check the Function App:
- Open the Function App resource
- Go to Functions in the left menu
- You should see the
pollAuditLogsfunction listed
To verify alerts are being ingested (after the function has run):
- Open the Log Analytics workspace → Logs
- Run this query:kusto
Beacon_Alerts_CL | take 10
Troubleshooting
Deployment fails with permission error
You need sufficient permissions to:
- Create resource groups in the subscription
- Create app registrations in Entra ID
- Create resources (storage accounts, function apps, etc.)
Try running with an account that has Owner or Contributor role on the subscription, plus Application Administrator in Entra ID.
Bicep extension error
If you see an error about the Microsoft Graph extension:
az bicep upgradeThe Graph extension requires Bicep version 0.29.0 or later.
Function App shows no functions
The code is deployed from GitHub via a deployment script. If functions aren't appearing:
- Open the Function App in Azure Portal
- Check Overview for any deployment errors
- In the resource group, check the deployment script resource (
beacon-deploy-code) for logs - Verify the
deploymentpackageblob container hasbeacon.zip
No data in Log Analytics
If alerts aren't appearing in the Beacon_Alerts_CL table:
- Check the Function App logs for errors
- Verify the function has run at least once (check Monitor in the function)
- Ensure admin consent was granted for client tenants
Updating Beacon
Re-run the Bicep deployment from Step 3. The template automatically downloads and deploys the latest release from GitHub.
az deployment sub create \
--location australiaeast \
--template-file beacon.bicepClean Up
To remove all Beacon resources:
az group delete --name rg-beacon --yesWarning
This deletes all resources in the resource group, including any data in the storage account. The app registration is not deleted automatically. Remove it manually from Entra ID if needed.