Skip to content
Agentmart
Submit a tool

azure-access-and-exposure-audit

Audit Azure network exposure and harden ACLs, or diagnose RBAC/PIM access, activation, and approval failures with PowerShell or bash.

Skill by GuicedEE

IndexedApache-2.0★ 5
Write a review

Install

Works with Claude Code, Claude apps, Codex, Cursor, Gemini CLI, GitHub Copilot, VS Code, OpenCode, Goose, Windsurf. Read the repository before you give any tool access to your data.

npx agentmarket install skill/guicedee-azure-access-and-exposure-audit

Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.

Get the weekly diff

The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.

We use your email only for this newsletter. Privacy

About

Audit Azure network exposure and harden ACLs, or diagnose RBAC/PIM access, activation, and approval failures with PowerShell or bash.

Use cases: cloud, security

No reviews yet. Installed it? Reviews come from verified installers only. How reviews work

Permissions

What this skill can do and what it asks for, from its SKILL.md and code. Checked Oct 25, 2026.

Tools
No tools found
Secrets
None asked for
Install scripts
None found
Runs as
Python package

Network hosts it talks to 2

  • codeload.github.com · found in install command
  • management.azure.com · found in code

Files it touches

  • ~/.claude/skills/azure-access-and-exposure-audit

What's inside

Skill name
azure-access-and-exposure-audit
Description
Audit Azure network exposure and harden ACLs, or diagnose RBAC/PIM access, activation, and approval failures with PowerShell or bash.
License
Apache-2.0
Instructions
221 lines in SKILL.md · view on GitHub

Before installing

  • Ships executable scripts

Files (21)

  • plugin.json · .claude-plugin/
  • .gitattributes
  • SKILL.md
  • openai.yaml · agents/
  • apm.yml
  • access-and-pim.md · references/
  • edge-waf-traps.md · references/
  • powershell-az-traps.md · references/
  • public-exposure-audit.md · references/
  • Get-AzGroupRbacMap.ps1 · scripts/
  • Get-AzPimStatus.ps1 · scripts/
  • Get-AzPublicExposure.ps1 · scripts/
  • Set-AzNetworkAclHardening.ps1 · scripts/
  • get-az-group-rbac-map.sh · scripts/
  • get-az-pim-status.sh · scripts/
  • get-az-public-exposure.sh · scripts/
  • run-checks.sh · scripts/
  • set-az-network-acl-hardening.sh · scripts/
  • mock_azure.py · tests/
  • requirements.txt · tests/
  • test_audit_scripts.py · tests/

SKILL.md (first lines)

# Azure access and exposure audit

Two related investigation workflows: **is this exposed?** and **why can't this identity do that?**

Both fail the same way — a plausible but wrong answer, produced fast. Every rule here exists
because it caused a real wrong answer. **Report evidence, not inference.**

## Core rules

1. **Never trust a name.** Not a group name, not a variable name, not a resource name. Enumerate
   what it actually grants or does.
2. **Never trust Resource Graph for a verdict.** It returns empty `publicNetworkAccess` for the
   types that matter most. ARG for inventory, direct ARM GET for the verdict.
3. **Separate "exposed" from "one control deep".** Overstating a hardening task as an exposure
   destroys credibility; understating a real exposure is worse.
4. **Read the module before setting its flag.** `enable_<security-thing> = true` is not
   automatically additive — it can be a kill switch.
5. **State what could not be verified.** An audit with an honest gap beats one with a guess.

## Scripts — pick your platform

Every tool ships in PowerShell and bash. Both report incomplete reads explicitly;
their presentation and PIM policy handling differ as described below.

| Task | Windows (PowerShell 5.1+) | Linux / macOS (bash) |
|---|---|---|
| Exposure audit | `Get-AzPublicExposure.ps1` | `get-az-public-exposure.sh` |
| Group → real RBAC | `Get-AzGroupRbacMap.ps1` | `get-az-group-rbac-map.sh` |
| PIM status / activate / approve | `Get-AzPimStatus.ps1` | `get-az-pim-status.sh` |
| networkAcls hardening | `Set-AzNetworkAclHardening.ps1` | `set-az-network-acl-hardening.sh` |

**Dependencies:** the `.sh` scripts need **only `az`** — no `jq`, no `curl`. All parsing goes
through `az --query ... -o tsv`. They are bash 3.2 compatible, so they run on stock macOS.

```bash
chmod +x scripts/*.sh    # once, after cloning
scripts/run-checks.sh    # regression gate - re-run after ANY change to a .sh script
```

**PowerShell Core (`pwsh`) also runs on Linux/macOS**, so the `.ps1` versions work there too if
preferred — they use only `az`, `Invoke-RestMethod` and built-in cmdlets.

> ⚠️ **Do not run the `.sh` versions under Git Bash on Windows.** Two independent things break, and
> both fail *silently*:
> 1. MSYS rewrites a leading `/subscriptions/...` argument into `C:/Program Files/Git/subscriptions/...`,
>    so every `--ids` lookup fails, stderr is suppressed, and **every resource reports as a FINDING**.
> 2. `az` is `az.cmd`, parsed by `cmd`, which mangles the `( )` in `asTarget()` / `asApprover()` and
>    fails with `-o was unexpected at this time` — which looks like an auth error.
>
> Use the `.ps1` versions on Windows; they call ARM directly with a bearer token. **WSL is fine** and
> is a good place to test the `.sh` variants — it does not rewrite argument paths.

**Verification status:** this revision is checked with PowerShell parsing, bash syntax/help/
argument/encoding checks, and offline CLI/ARM fixtures on Windows PowerShell 5.1 and WSL Ubuntu.
The fixtures exercise read and membership failures, scoped hardening with preserved bypasses,
exposure controls and CSV identities, RBAC scopes, and scoped PIM activation/deactivation bodies.
No live cloud audit, activation, approval, or hardening operation was performed
for this revision. Perform a report-only pass before using these scripts in a new estate.

Run the regression suite from this skill directory with Python 3 and its test-only dependency:

```text
python -m pip install -r tests/requirements.txt
python -B tests/test_audit_scripts.py
```

On Linux/macOS use `python3`. Run on Windows for PowerShell coverage and on Linux/macOS for bash
coverage. The fake transport rejects unrecognized calls and never invokes a live Azure command.

## Workflow A — public exposure audit

Use when responding to an exposure finding or auditing an estate.

```powershell
scripts/Get-AzPublicExposure.ps1 -SubscriptionId <sub1>,<sub2> -CsvPath .\exposure.csv
```
```bash
scripts/get-az-public-exposure.sh -s <sub1> -s <sub2> -c ./exposure.csv
```

Enumerates 17 selected resource types and reads each with a direct ARM GET. This is a bounded
configuration audit, not proof of network reachability or exhaustive Azure coverage. Results are
`FINDING`, `weak-2nd-control`, `explained`, `info`, `ok`, or `unverifiable`. Read failures and
unsupported/missing controls remain visible; `info` requires interpretation and is not compliance.
Exit codes: `2` means an incomplete audit, `1` means findings with no incomplete reads, and `0`
means neither. `0` does not certify informational results. CSV output includes subscription and
resource identity. `-a` / `-IncludeCompliant` also shows `ok` results.

Then:

1. **Re-verify every item on the supplied list.** Compliance lists are frequently wrong; say so
   with evidence when they are.
2. **Explain the false positives** rather than silently dropping them — NAT-gateway public IPs are
   egress-only and Front Door is public by design. Assess App Service slots separately; they do
   not share the parent's private endpoint. Record the evidence for the next scan.
3. **Report gaps the list missed.** These are usually the real finding.
4. **Check the edge for a WAF**, not just for "is it public".

Read **[references/public-exposure-audit.md](references/public-exposure-audit.md)** for the type
matrix, per-type verdict rules, the false-positive catalogue and the two-control model.

### Hardening

```powershell
scripts/Set-AzNetworkAclHardening.ps1 -TargetJsonPath .\targets.json          # report
scripts/Set-AzNetworkAclHardening.ps1 -TargetJsonPath .\targets.json -Apply   # change
```
```bash
scripts/set-az-network-acl-hardening.sh -f ./targets.tsv        # report
scripts/set-az-network-acl-hardening.sh -f ./targets.tsv -A     # change
```

PowerShell takes JSON objects
(`{ "Kind": "storage"|"keyvault", "Sub": "...", "Rg": "...", "Name": "...", "Label": "dev" }`);
bash takes the same fields as **tab-separated** lines (`kind<TAB>sub<TAB>rg<TAB>name<TAB>label`,
`#` comments allowed).

The hardening commands change only `defaultAction` to `Deny`; they omit `--bypass` to preserve
the existing Storage or Key Vault bypass configuration in both report and apply modes.

From GuicedEE/ai-rules, Apache-2.0.

More from GuicedEE/ai-rules

Signals

Stars
5
Forks
0
Open issues
0
Last commit (this folder)
Oct 14, 2026 (13 days ago)

From GitHub (fetched Oct 24, 2026).

Details

License
Apache-2.0
First seen
Oct 24, 2026
Last checked
Oct 24, 2026

More from GuicedEE

Cite this page

azure-access-and-exposure-audit skill. Agent Mart. https://agentmart.dev/skills/guicedee-azure-access-and-exposure-audit (last updated 2026-10-24)