This project provisions all Azure resources and deploys an Azure Functions app that exports Pulumi Cloud audit logs to Azure Blob Storage on a daily schedule.
- Resource Group, Storage Account and private Blob containers:
audit-logs<stack>(JSON logs + checkpointstate/checkpoint.json)audit-logs-archive(CSV exports)audit-logs-errors(error details)
- User‑Assigned Managed Identity with Blob Data Contributor
- Consumption plan and Function App (Linux, Node 20)
- Application Insights
- A Pulumi Service‑generated access token for the function (
PULUMI_ACCESS_TOKEN)
- Azure subscription
- Node.js LTS
- Pulumi CLI and account
- Azure credentials available for Pulumi providers
- Configure the stack:
pulumi config set audit-log-exporter:subscriptionId <your-azure-subscription-id>
pulumi config set audit-log-exporter:pulumiOrg <your-pulumi-org>
# Optional: increase page cap for large catch-up
pulumi config set audit-log-exporter:maxPages 1000- Deploy:
npm install
pulumi up --yes.
├── Pulumi.yaml
├── Pulumi.<stack>.yaml # Stack config (subscriptionId, pulumiOrg, maxPages)
├── index.ts # Pulumi program (infra + deployment)
├── function-app/
│ ├── auditLogProcessor/
│ │ ├── function.json # schedule (daily) + scriptFile
│ │ └── index.js # logic w/ checkpointing & pagination
│ ├── host.json
│ └── package.json
└── tsconfig.json
Stack keys of interest (set with pulumi config set <key> <value>):
audit-log-exporter:subscriptionId(required): Azure subscription UUID.audit-log-exporter:pulumiOrg(required): Pulumi organization name used for API queries.audit-log-exporter:maxPages(optional, default100): Pagination safety cap per run.audit-log-exporter:blobPrefix(optional, default empty): Path prefix for emitted blobs (e.g.,Pulumi-audit-logs).audit-log-exporter:exportJson(optional, defaulttrue): Emit JSON export.audit-log-exporter:exportCsv(optional, defaulttrue): Emit CSV export.audit-log-exporter:exportCef(optional, defaultfalse): Emit CEF export.audit-log-exporter:immutableRetentionDays(optional): When set, enables immutable storage with versioning on containers with the given retention period.
- Runs daily at 01:45 UTC
- Fetches audit logs in pages (default ~101 events/page)
- Stops duplicates via a blob checkpoint (
state/checkpoint.json) - If it reaches
maxPages, saves a continuation token and resumes next run - Writes JSON/CSV/CEF blobs under
(<prefix>/)year=YYYY/month=MM/day=DD/audit-logs-<ts>.<ext>
functionAppUrlstorageAccountName- Container names
- App Insights details