azure-access-baseline

Install

How to get Bastion running from a clean machine. The offline path (steps 1–4) needs no Azure account and no credentials — it analyses the captured estate snapshot in samples/ and produces a real report. The live path (step 5) scans your own subscriptions.

For what Bastion is and what the rules check, see README.md.

1. Prerequisites

Tool Version Needed for
.NET SDK 8.0 the scanner and the rule engine
Node.js 20 LTS web/ — the findings dashboard
Git any recent clone
Azure CLI latest only for live scans and az bicep build
dotnet --version && node --version

2. Clone and build

git clone https://github.com/NickZivkovic1993/azure-access-baseline.git
cd azure-access-baseline

dotnet restore Bastion.sln
dotnet build Bastion.sln
cd web && npm ci && cd ..

3. Verify the install

Exactly what CI runs on every push:

dotnet test Bastion.sln            # 15 rule-engine tests
cd web && npm run build && cd ..

Bicep validation is optional locally (it needs the Azure CLI):

az bicep build --file infra/main.bicep

4. Run it offline — no Azure needed

dotnet run --project src/Bastion.Scanner -- rules
dotnet run --project src/Bastion.Scanner -- analyze samples/estate.json --format markdown

analyze reads the deliberately messy two-subscription snapshot in samples/estate.json, runs the baseline, and prints the one-page access review — 13 findings.

It exits 2, and that is correct. The scanner exits non-zero when High or Critical findings are open, so a scheduled pipeline fails on drift. Don’t read the exit code as a crash.

To see the findings in the dashboard instead:

dotnet run --project src/Bastion.Scanner -- analyze samples/estate.json --format json --output findings.json
cd web && npm run dev          # :5173 — load findings.json

5. Scan a live estate (optional)

Scanning reads your Azure estate; it never writes to it.

Permissions the scanning identity needs:

Then:

az login
dotnet run --project src/Bastion.Scanner -- scan                                    # JSON
dotnet run --project src/Bastion.Scanner -- scan --format sarif --output findings.sarif
dotnet run --project src/Bastion.Scanner -- scan --save-snapshot estate.json        # capture for offline analysis

Authentication is DefaultAzureCredentialaz login locally, a managed identity or workload-identity federation in a pipeline. There are no keys or connection strings to configure anywhere.

6. Deploy the baseline (optional)

infra/ is the remediation as Bicep — the managed identity that replaces shared secrets, OIDC federation for GitHub Actions, an RBAC-mode Key Vault, and group-scoped privileged roles:

az deployment group create -g <resource-group> -f infra/main.bicep

Review the parameters first; this one does write to your subscription.

Troubleshooting