Skip to content

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:

ResourcePurpose
Resource GroupContainer for all Beacon resources
App RegistrationMulti-tenant app for accessing client M365 data
Function AppRuns the Beacon polling service (Linux, Flex Consumption)
App Service PlanFlex Consumption serverless hosting plan
Storage AccountRequired by Azure Functions, config, and alert deduplication
Federated CredentialSecure authentication (no secrets needed)
Log Analytics WorkspaceStores alerts for querying and dashboards
Application InsightsFunction App logging and monitoring
Data Collection EndpointIngestion endpoint for Log Analytics
Data Collection RuleRoutes 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 AssignmentsStorage 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 install if not already installed)

Step 1: Download the Template

Download both template files from the repository:

Save both files to the same folder on your computer.

TIP

You can also clone the entire repository:

bash
git clone https://github.com/emildosen/beacon.git
cd beacon/infra

Step 2: Sign In to Azure

Open a terminal and sign in:

bash
az login

A 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:

bash
az deployment sub create \
  --location australiaeast \
  --template-file beacon.bicep

Available 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

ParameterDefaultDescription
resourceGroupNamerg-beaconName for the resource group
appNameBeaconName used for the app registration and resources
enableFederatedAuthtrueEnable 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}).

ParameterDefaultDescription
functionAppName{app}-func-[6 random]Function App name
storageAccountName{app}[10 random]Storage Account name
appServicePlanName{app}-planApp Service Plan name
logAnalyticsWorkspaceNamelaw-{app}Log Analytics Workspace name
dataCollectionEndpointNamedce-{app}Data Collection Endpoint name
dataCollectionRuleNamedcr-{app}Data Collection Rule name
appInsightsNameai-{app}Application Insights name

Example with custom values:

bash
az deployment sub create \
  --location australiaeast \
  --template-file beacon.bicep \
  --parameters \
    resourceGroupName=rg-beacon-prod \
    appName=BeaconProd

Example with custom resource names:

bash
az deployment sub create \
  --location australiaeast \
  --template-file beacon.bicep \
  --parameters \
    resourceGroupName=rg-beacon-prod \
    functionAppName=my-existing-func \
    storageAccountName=myexistingstorage

Example disabling federated auth (for client secret authentication):

bash
az deployment sub create \
  --location australiaeast \
  --template-file beacon.bicep \
  --parameters \
    enableFederatedAuth=false

Hosting 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-beacon

The adminConsentUrl is particularly important - you'll need it for onboarding client tenants.

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.

  1. Open the adminConsentUrl from the deployment outputs
  2. Sign in with a Global Administrator account
  3. Review the permissions and click Accept

For client tenants

For each client tenant you want to monitor:

  1. Replace the tenant ID in the consent URL:
    https://login.microsoftonline.com/{client-tenant-id}/adminconsent?client_id={app-client-id}
  2. Send this URL to the client's Global Administrator
  3. 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

  1. Open the Azure Portal
  2. Navigate to Resource groupsrg-beacon (or your custom name)
  3. Confirm all resources are present and healthy

To check the Function App:

  1. Open the Function App resource
  2. Go to Functions in the left menu
  3. You should see the pollAuditLogs function listed

To verify alerts are being ingested (after the function has run):

  1. Open the Log Analytics workspace → Logs
  2. 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:

bash
az bicep upgrade

The 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:

  1. Open the Function App in Azure Portal
  2. Check Overview for any deployment errors
  3. In the resource group, check the deployment script resource (beacon-deploy-code) for logs
  4. Verify the deploymentpackage blob container has beacon.zip

No data in Log Analytics

If alerts aren't appearing in the Beacon_Alerts_CL table:

  1. Check the Function App logs for errors
  2. Verify the function has run at least once (check Monitor in the function)
  3. 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.

bash
az deployment sub create \
  --location australiaeast \
  --template-file beacon.bicep

Clean Up

To remove all Beacon resources:

bash
az group delete --name rg-beacon --yes

Warning

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.