Learn how Azure SRE Agent can query Log Analytics workspaces protected by Private Link (AMPLS) using an Azure Function proxy pattern with Easy Auth authentication.
⚠️ Important Note on Network Communication: In this pattern, Azure SRE Agent communicates over the public network to reach the Azure Function proxy. The proxy endpoint is secured with Easy Auth (Microsoft Entra ID) and only authenticated callers can invoke it. We are also actively working on enabling SRE Agent to be injected directly into private networks, which will eliminate the need for a public proxy altogether. Stay tuned for updates on private network injection support.
TL;DR
When you configure Azure Monitor Private Link Scope (AMPLS) with publicNetworkAccessForQuery: Disabled, all public queries to your Log Analytics Workspace are blocked. To enable Azure SRE Agent to query these protected workspaces, deploy Azure Functions inside your VNet as a secure query proxy.
What We Built: This sample deploys to a single subscription with two resource groups (
rg-originations-*andrg-workload-*). The same pattern works identically across subscriptions. Simply deploy each resource group to a different subscription.
Why Public Queries Get Blocked
Many organizations secure their Log Analytics Workspaces using Azure Monitor Private Link Scope (AMPLS) with Private Endpoints. This is a best practice for compliance and data security, but it means all public queries are blocked.
| Resource Type | Can Live in VNet? | How to Access Privately |
|---|---|---|
| Virtual Machine | Yes | Direct (it has a NIC) |
| Container App | Yes | VNet integration |
| Azure SQL | No | Private Endpoint |
| Storage Account | No | Private Endpoint |
| Log Analytics Workspace | No | AMPLS + Private Endpoint |
When you configure publicNetworkAccessForQuery: Disabled on the workspace and queryAccessMode: PrivateOnly on the AMPLS, any query that does not come through a Private Endpoint is rejected. This includes queries from Azure SRE Agent, which runs as a cloud service outside your VNet.
The Architecture
Two resource groups: rg-originations-ampls-demo (LAW + AMPLS, query access disabled) and rg-workload-ampls-demo (VNet + Private Endpoint + Function). This pattern works across subscriptions with cross-subscription RBAC for the Function's Managed Identity.
The Problem: Blocked Queries
When you configure AMPLS with private-only query access, any attempt to query from outside the VNet fails:
InsufficientAccessError: The query was blocked due to private link
2. configuration. Access is denied because this request was not made
3. through a private endpoint.
This is the expected behavior. But it means Azure SRE Agent (which runs as a cloud service, not inside your VNet) cannot directly query these workspaces.
The Solution: Azure Functions as Query Proxy
Deploy Azure Functions inside the workload VNet. This serverless proxy:
| Capability | Description |
|---|---|
| Runs inside VNet | VNet-integrated with vnetRouteAllEnabled: true |
| Uses Managed Identity | Authenticates to LAW via Azure RBAC |
| Exposes HTTPS endpoints | SRE Agent calls as custom HTTP tools |
| Proxies queries | Transforms API calls into KQL queries |
| Serverless scaling | Pay only when queries are executed |
Why This Pattern Works
Data ingestion and query access use different network paths:
| Operation | Direction | Network | Status |
|---|---|---|---|
| Log Ingestion | AMA → Private Endpoint → LAW | Private | Works |
| External Query | Public Internet → LAW | Public | Blocked |
| VNet Query | VNet → Private Endpoint → LAW | Private | Works |
| SRE Agent Query | HTTPS → Function → PE → LAW | Hybrid | Works |
The Azure Function acts as a bridge between two networks: (1) Public side with HTTPS endpoint for SRE Agent, (2) Private side with VNet integration routing all outbound traffic through the Private Endpoint. This is why the pattern works. The Function "translates" public API calls into private network queries.
Setting Up the Architecture
Step 1: Configure the Originations LAW
az monitor log-analytics workspace create --resource-group originations-rg --workspace-name originations-law --location eastus
4. az monitor log-analytics workspace update --resource-group originations-rg --workspace-name originations-law --set properties.publicNetworkAccessForQuery=Disabled
Step 2: Create the Azure Monitor Private Link Scope
az monitor private-link-scope create --name originations-ampls --resource-group originations-rg
5. # ... (see full sample on GitHub)
Step 3: Create the Private Endpoint in Workload Resource Group
az network private-endpoint create --name pe-ampls --resource-group rg-workload-ampls-demo --vnet-name vnet-workload-ampls-demo --subnet endpoints --private-connection-resource-id "/subscriptions/.../resourceGroups/rg-originations-ampls-demo/providers/Microsoft.Insights/privateLinkScopes/ampls-originations-ampls-demo" --group-id azuremonitor --connection-name ampls-connection
Step 4: Deploy the Azure Function
az functionapp plan create --name plan-law-query --resource-group workload-rg --location eastus --sku EP1 --is-linux true
6. az functionapp create --name func-law-query --resource-group workload-rg --plan plan-law-query --runtime python --runtime-version 3.11 --functions-version 4 --assign-identity '[system]'
7. # ... (see full sample on GitHub)
Step 5: Configure Easy Auth (Microsoft Entra ID) on the Function App
Instead of function keys, we secure the Azure Function with Easy Auth (Microsoft Entra ID authentication). This eliminates the need to manage secrets. The SRE Agent authenticates using its Managed Identity.
5a. Set Function Auth Level to Anonymous
Since Easy Auth handles authentication at the platform level, set authLevel to anonymous in each function.json:
{
8. "scriptFile": "__init__.py",
9. "bindings": [
10. {"authLevel": "anonymous", "type": "httpTrigger", "direction": "in", "name": "req", "methods": ["get", "post"]},
11. {"type": "http", "direction": "out", "name": "$return"}
12. ]
13. }
5b. Enable Easy Auth via Azure Portal
- Navigate to your Function App in the Azure Portal
- Go to Settings → Authentication
- Click Add identity provider and select Microsoft
- Configure: Create new app registration, Current tenant, Federated identity credential, Require authentication, HTTP 401 for unauthenticated
- Add the SRE Agent's Managed Identity Client ID under Allowed client applications
- Note the Application (client) ID for PythonTool configuration
Finding the SRE Agent Managed Identity Client ID
Option 1: Azure Portal: Navigate to your SRE Agent → Settings → Identity → copy the Client ID under System assigned or User assigned.
Option 2: Azure CLI:
az containerapp show --name <YOUR-SRE-AGENT-NAME> --resource-group <YOUR-SRE-AGENT-RG> --query "identity.userAssignedIdentities" -o json
5c. Deploy SRE Agent Tools (PythonTools with Easy Auth)
Critical: PythonTools must use def main(**kwargs). Each tool acquires a Bearer Token from the SRE Agent's Managed Identity via IDENTITY_ENDPOINT and calls the Azure Function endpoints. See sample repository for full subagent definition and tool implementations.
How Easy Auth Token Acquisition Works
- PythonTool reads
IDENTITY_ENDPOINTandIDENTITY_HEADERenvironment variables (set automatically by the SRE Agent runtime) - PythonTool calls the identity endpoint with
resource=api://<app-id>to get a Bearer Token - PythonTool includes the token in the
Authorization: Bearer <token>header - Easy Auth validates the token against the App Registration
- Function App executes the query using its Managed Identity
No secrets required: Unlike function keys, Easy Auth uses Managed Identity tokens that are automatically rotated and never stored in code or configuration.
The Investigation Flow
| Step | Actor | Action |
|---|---|---|
| 1 | You | "There are errors on my workload VMs. Investigate." |
| 2 | SRE Agent | Calls Azure Function's query_logs endpoint |
| 3 | Azure Function | Queries LAW via Private Endpoint |
| 4 | Log Analytics | Returns results (allowed, since request came from PE) |
| 5 | Azure Function | Returns JSON response to SRE Agent |
| 6 | SRE Agent | Analyzes logs, identifies root cause, responds |
Security Considerations
| Concern | How It's Secured |
|---|---|
| Log Analytics | Public query access disabled, Private Link only |
| Private Endpoint | In isolated subnet with NSG rules |
| Azure Function | Managed Identity for LAW access (no secrets) |
| API Authentication | Easy Auth (Microsoft Entra ID) with Bearer Token, no secrets to manage |
| VNet Routing | vnetRouteAllEnabled: true for all traffic |
| Audit Trail | All invocations logged in Application Insights |
Try It Yourself
git clone https://github.com/BandaruDheeraj/private-law-query-sample
cd private-law-query-sample
azd up
# See Step 5 for Easy Auth configuration
./inject-failure.ps1
This creates: rg-originations-{env} (LAW + AMPLS) and rg-workload-{env} (VNet + PE + Functions + VMs)
Key Takeaways
AMPLS blocks public queries by design: When you configure Private Link with private-only query access, all external queries are rejected. This is the expected security behavior.
Azure Functions provide a serverless query proxy: VNet-integrated Functions with Managed Identity can query private Log Analytics on behalf of SRE Agent.
Resource groups simulate cross-subscription: This sample uses two resource groups; the same pattern works across subscriptions.
Easy Auth eliminates secret management: Using Microsoft Entra ID authentication instead of function keys means no secrets to rotate or store.
Security is maintained end-to-end: The workspace remains fully private; only the trusted Function can query it. The SRE Agent authenticates with its Managed Identity.
Resources
| Resource | Link |
|---|---|
| Sample Repository | github.com/BandaruDheeraj/private-law-query-sample |
| Azure Monitor Private Link | docs.microsoft.com/azure/azure-monitor/logs/private-link-security |
| Azure Functions VNet Integration | docs.microsoft.com/azure/azure-functions/functions-networking-options |
| AMPLS Design Guidance | docs.microsoft.com/azure/azure-monitor/logs/private-link-design |
| Managed Identity for Azure Functions | docs.microsoft.com/azure/app-service/overview-managed-identity |
| Azure Developer CLI (azd) | learn.microsoft.com/azure/developer/azure-developer-cli |