
How to Stream HCP Vault Dedicated Audit Logs to Microsoft Sentinel
Enterprise Developer PlatformsWhat this stack enables: Full audit-log visibility for HCP Vault Dedicated clusters inside Microsoft Sentinel โ without leaving the Azure compliance perimeter.
Summary:
- HCP Vault Dedicated emits audit events through a generic HTTP sink to an Azure Function App
- The Function App validates requests, normalizes nested Vault fields into flat records, and authenticates via managed identity
- Azure Monitor Logs Ingestion API routes normalized records into a custom Log Analytics table (
HCPVaultAudit_CL) via a DCE-backed Data Collection Rule - Optional Microsoft Sentinel onboarding ships four starter scheduled analytics rules out of the box
- The entire infrastructure is Terraform-managed โ one
applyprovisions everything from the resource group to Sentinel
Purpose
HCP Vault Dedicated audit logs capture every authentication, token creation, secret read, and policy evaluation in your cluster. Getting those logs into Sentinel closes the gap between your secrets infrastructure and your SOC โ enabling correlation with Azure Active Directory sign-ins, network flows, and resource changes in a single query surface.
Pre-requisites
Before you start, confirm all of the following:
- HCP Vault Dedicated cluster at Essentials or Standard tier (Plus tier also supported)
- HCP Admin role on the organization
- Azure subscription with Owner or User Access Administrator permissions
- Network path from the HCP cluster to your Azure ingestion endpoint over HTTPS (port 443)
- Tooling installed locally: Terraform (1.5+), Azure CLI, Azure Functions Core Tools v4
- Permissions to create a resource group, Log Analytics workspace, Function App (Consumption plan), and Data Collection Rule in the target Azure subscription
Steps
1. Clone the reference repository
git clone https://github.com/hashicorp/hcp-vault-audit-log-azure
cd hcp-vault-audit-log-azure
The repo contains the Terraform root module, the Function App source (func/), and helper scripts.
2. Authenticate to Azure
az login
az account set --subscription "<YOUR_SUBSCRIPTION_ID>"
3. Run the preflight check
bash scripts/preflight.sh
This validates that required Azure resource providers are registered (microsoft.operationalinsights, microsoft.insights, microsoft.web) and that your account has the minimum permissions before Terraform runs.
4. Configure Terraform variables
bash scripts/configure-terraform.sh
The script prompts for region, resource group name, workspace name, and a bearer token for the HTTP sink. It writes a terraform.tfvars file โ do not commit this file; it contains the bearer token in plaintext.
5. Initialize and apply Terraform
terraform init
terraform apply
Terraform provisions the following resources in a single pass:
| Resource | Purpose |
|---|---|
| Resource group + Log Analytics workspace | Container and storage for all log data |
Custom table HCPVaultAudit_CL | Destination for normalized Vault audit records |
| Data Collection Endpoint (DCE) | HTTPS ingestion entry point |
| DCE-backed Data Collection Rule (DCR) | Routes records from DCE to HCPVaultAudit_CL |
| Function App (Consumption plan) | Validates, normalizes, and forwards audit events |
| System-assigned managed identity | Authenticates Function App to Azure Monitor โ granted Monitoring Metrics Publisher on the DCR only |
| Optional Sentinel workspace onboarding | Four starter scheduled analytics rules |
The managed identity is scoped to Monitoring Metrics Publisher on the DCR. No broader permissions are granted.
6. Publish the Function App
func azure functionapp publish <FUNCTION_APP_NAME>
Use the function app name from terraform output function_app_name.
7. Smoke-test the ingestion endpoint
bash scripts/smoke_test.sh
The script sends a sample audit payload to the Function App URL and polls Log Analytics for the record. Allow up to five minutes for first-time ingestion latency.
8. Retrieve output values
terraform output
Note function_app_url and bearer_token_secret_name โ you need both for the next step.
9. Configure the HCP Vault audit log stream
In the HCP portal:
- Navigate to your Vault Dedicated cluster
- Open Audit Logs โ Enable Log Streaming
- Select Generic HTTP Sink
- Set POST as the HTTP method
- Set JSON as the encoding โ not NDJSON, not compressed (see The Trap below)
- Set Strategy = Bearer, paste the bearer token from Terraform output
- Enter the Function App URL as the sink endpoint
- Save and confirm the test event delivers successfully
10. Validate ingestion in Log Analytics
Run this KQL query in the Log Analytics workspace (allow up to 15 minutes after configuring the sink):
HCPVaultAudit_CL
| where TimeGenerated > ago(24h)
| summarize Events = count() by path
| order by Events desc
| take 20
A non-empty result confirms the full pipeline is operational.
The Trap
Using NDJSON or compressed encoding will silently break the pipeline.
The Function App expects a standard JSON array in the POST body. HCP Vaultโs generic HTTP sink offers three encoding options โ JSON, NDJSON, and compressed. NDJSON delivers one JSON object per line with no wrapping array; the Function Appโs JSON parser fails on the first line break and drops every event without returning an error to Vault. Compressed encoding adds a Content-Encoding: gzip header that the Consumption plan Function App does not decompress by default.
The result: Vault reports the sink as healthy (HTTP 200 from the Function Appโs validation layer), Log Analytics shows zero rows, and there is no obvious error surface to diff against.
Fix: Always select standard JSON encoding in the HCP portal sink configuration. If you have existing events going missing, check HCPVaultAudit_CL | where TimeGenerated > ago(1h) | count before and after toggling encoding.
Security Notes
- Protect Terraform state. The
terraform.tfvarsfile and remote state may contain the bearer token in plaintext. Use a remote backend with encryption at rest (Azure Blob with customer-managed key, or Terraform Cloud). - Least-privilege identity. The managed identity holds only
Monitoring Metrics Publisheron the DCR โ not Contributor or Log Analytics Contributor on the workspace. - Schema changes need care. Modifying the
HCPVaultAudit_CLtable schema after data is ingested may require a table rebuild. Test schema changes in a non-production workspace first. - One sink at a time. The generic HTTP sink supports a single destination. If you need to fan out to multiple SIEM targets, add a routing layer (Event Hub or Logic App) downstream of the Function App rather than duplicating the sink.
Cited References
- HashiCorp: HCP Vault Dedicated Audit Logs to Microsoft Sentinel โ primary source and reference repo
- Azure Monitor Logs Ingestion API overview โ DCE and DCR architecture
- Microsoft Sentinel: Connect data sources โ Sentinel onboarding patterns
- Related: Vault Enterprise Workload Identity Federation and Secret Sync
- Related: Terraform + Sentinel ISO 27001 Compliance Policies
The So What
HCP Vault Dedicated is a managed secrets backend, but audit logs are only useful if they live where your security team can query them. This stack closes that gap with a Terraform-managed pipeline that is deployable in under an hour and adds no ongoing operational overhead โ the Function App scales to zero on a Consumption plan, the managed identity requires no credential rotation, and certificate rotation is handled by the kubelet. If your compliance posture requires evidence of every secret access and policy evaluation, and your SOC runs on Sentinel, this is the reference architecture worth starting from.
Source: HashiCorp Blog
Content created with AI assistance and reviewed for accuracy.
Join the conversation
Stack Insiders is our free community for readers who want to go deeper โ share resources, ask questions, and connect with others across every vertical we cover.
Join Stack Insiders →