Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 17 additions & 2 deletions skills/cloud/azure-review/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ phase: [assess, operate]
frameworks: [CIS-Azure-v2.1.0]
difficulty: intermediate
time_estimate: "60-90min"
version: "1.0.0"
version: "1.0.1"
author: unitoneai
license: MIT
allowed-tools: Read, Grep, Glob
Expand Down Expand Up @@ -54,6 +54,7 @@ The CIS Microsoft Azure Foundations Benchmark v2.1.0 is a consensus-driven secur
- Entra ID (Azure AD) configuration files or policy documents
- NSG and firewall rule definitions
- Key Vault access policies and RBAC assignments
- Key Vault live role assignment export, private endpoint/DNS evidence, and network ACL evidence when evaluating CIS 8.6 and 8.7

---

Expand Down Expand Up @@ -148,12 +149,19 @@ Produce the final report using the structure defined in the Output Format sectio
- **Status:** Pass / Fail / Not Evaluable
- **Severity:** Critical / High / Medium / Low
- **CIS Profile:** Level 1 / Level 2
- **Evidence Confidence:** High / Medium / Low / Not Evaluable
- **File:** <path to relevant config>
- **Line(s):** <line numbers if applicable>
- **Description:** <what was found>
- **Evidence:** <specific configuration or code snippet>
- **Not Evaluable Reason:** <reason code and exact evidence needed>
- **Remediation:** <specific fix with code example>

### Key Vault RBAC and Private Access Evidence

| Vault | RBAC Model | Data-Plane Role Evidence | Management-Plane Grant Risk | Public Network Path | Private Endpoint | Private DNS / Client Resolution | Deployment Exception | Status |
|-------|------------|--------------------------|-----------------------------|---------------------|------------------|---------------------------------|----------------------|--------|

### Prioritized Remediation Plan

1. **[Critical]** CIS X.Y.Z -- <action item>
Expand Down Expand Up @@ -199,7 +207,10 @@ Produce the final report using the structure defined in the Output Format sectio
3. **Overlooking `allow_nested_items_to_be_public` on storage accounts.** CIS 3.7 checks the account-level setting, not individual container access levels. The account setting must be `false` to prevent any container from being public.
4. **NSG rules using service tags.** A rule with `source_address_prefix = "Internet"` is equivalent to `0.0.0.0/0`. Both must be flagged for CIS 6.1 and 6.2.
5. **Key Vault purge protection is irreversible.** CIS 8.5 requires `purge_protection_enabled = true`. Note this cannot be disabled once enabled -- flag this for awareness during remediation.
6. **App Service TLS version on both Linux and Windows.** Check `azurerm_linux_web_app` and `azurerm_windows_web_app` resources separately.
6. **Treating Key Vault RBAC as least privilege by itself.** `enable_rbac_authorization = true` only selects the permission model. Review the data-plane role assignments, group expansion, scope, break-glass path, and live role export before passing CIS 8.6.
7. **Treating a private endpoint resource as private access enforcement.** A Key Vault private endpoint can coexist with `public_network_access_enabled = true`, `default_action = "Allow"`, broad `AzureServices` bypass, or missing private DNS. CIS 8.7 needs the effective path, not only the resource.
8. **Ignoring hosted CI/CD access exceptions.** Private-only vaults often trigger temporary public firewall openings for deployment agents. Require owner, expiry, audit log, and compensating control evidence before accepting the exception.
9. **App Service TLS version on both Linux and Windows.** Check `azurerm_linux_web_app` and `azurerm_windows_web_app` resources separately.

---

Expand All @@ -224,11 +235,15 @@ Produce the final report using the structure defined in the Output Format sectio
- Microsoft Entra ID Security: https://learn.microsoft.com/en-us/entra/identity/
- Azure Storage Security: https://learn.microsoft.com/en-us/azure/storage/common/storage-security-guide
- Azure Key Vault Best Practices: https://learn.microsoft.com/en-us/azure/key-vault/general/best-practices
- Azure Key Vault RBAC Guide: https://learn.microsoft.com/en-us/azure/key-vault/general/rbac-guide
- Azure Key Vault RBAC Migration: https://learn.microsoft.com/en-us/azure/key-vault/general/rbac-migration
- Azure Key Vault Network Security: https://learn.microsoft.com/en-us/azure/key-vault/general/network-security
- Azure App Service Security: https://learn.microsoft.com/en-us/azure/app-service/overview-security
- Terraform AzureRM Provider Documentation: https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs

---

## Changelog

- **1.0.1** -- Added Key Vault RBAC/private-endpoint evidence gates, report fields, and calibration fixtures.
- **1.0.0** -- Initial release. Full coverage of CIS Microsoft Azure Foundations Benchmark v2.1.0 sections 1 through 9.
44 changes: 44 additions & 0 deletions skills/cloud/azure-review/benchmark-checklist.md
Original file line number Diff line number Diff line change
Expand Up @@ -617,6 +617,35 @@ resource "azurerm_key_vault" {
}
```

Passing CIS 8.6 requires evidence that the RBAC model is both enabled and least-privilege in practice. Build a Key Vault RBAC evidence matrix before marking the control as Pass.

| Field | Required Evidence |
|---|---|
| Vault and source | Vault name, subscription, resource group, IaC path, and live export timestamp |
| Permission model | `enable_rbac_authorization = true` and no unmanaged access-policy drift |
| Principal | User, group, service principal, managed identity, or break-glass identity with owner |
| Role and capability | Data-plane role, effective secret/key/certificate permissions, and whether the role can grant access or purge |
| Scope | Vault, key, secret, certificate, resource group, subscription, or management group |
| Justification | Business owner, change ticket, expiry, and last-reviewed date |
| Group expansion | Nested group membership or explicit reason it is unavailable |
| Management-plane grant risk | Owner, Contributor, User Access Administrator, and role assignment writer evidence |
| Live-role export | Azure role assignment export proving IaC and portal state match |
| Status | Pass, Fail, or Not Evaluable with reason code |

Use these Not Evaluable codes when the evidence packet is incomplete:

| Code | Reason |
|---|---|
| `AZ-KV-NE-01` | Live Key Vault role assignment export is missing |
| `AZ-KV-NE-02` | Principal or group membership expansion is missing |
| `AZ-KV-NE-03` | Management-plane grant authority and data-plane access are not separated |
| `AZ-KV-NE-04` | RBAC migration drift between access policies, IaC, and live assignments is unresolved |
| `AZ-KV-NE-05` | Private endpoint DNS or client-resolution evidence is missing |
| `AZ-KV-NE-06` | Public firewall or `AzureServices` bypass exception evidence is missing |
| `AZ-KV-NE-07` | Deployment-agent exception lacks expiry, owner, audit log, or compensating control |

Fail the control when broad data-plane roles such as `Key Vault Administrator`, `Key Vault Data Access Administrator`, or secret/key officer roles are assigned to broad human groups without documented scope, owner, expiry, and review evidence.

### CIS 8.7 -- Ensure that Private Endpoints are used for Azure Key Vault

Check for private endpoint connections to Key Vault:
Expand All @@ -630,6 +659,21 @@ resource "azurerm_private_endpoint" {
}
```

Private endpoint existence is not enough. Evaluate effective private access enforcement:

| Evidence | Pass Standard |
|---|---|
| Public access | `public_network_access_enabled = false`, or public access is enabled only with a documented, time-bound exception |
| Firewall default | If public access remains enabled, `network_acls.default_action = "Deny"` |
| Trusted services bypass | `bypass = "AzureServices"` is justified by a specific supported service path, not used as a blanket exception |
| Private endpoint | `azurerm_private_endpoint` targets the Key Vault `vault` subresource |
| Private DNS | `azurerm_private_dns_zone_group`, VNet link, or equivalent DNS evidence exists for `privatelink.vaultcore.azure.net` |
| Client resolution | Lookup or runtime evidence from the consuming subnet/workload resolves to the private endpoint path |
| Diagnostics | Logs show denied public attempts or successful private-link access where available |
| Deployment path | Hosted CI/CD, break-glass, or migration exceptions have owner, expiry, audit log, and compensating controls |

Fail CIS 8.7 when a private endpoint exists but the vault remains broadly public through `public_network_access_enabled = true`, `network_acls.default_action = "Allow"`, or unsupported bypass use. Mark Not Evaluable with `AZ-KV-NE-05`, `AZ-KV-NE-06`, or `AZ-KV-NE-07` when DNS, firewall exception, or deployment-path evidence is unavailable.

---

## Section 9 -- App Service
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
# Key Vault RBAC and Private Endpoint Edge Cases

These fixtures verify that `azure-review` distinguishes Key Vault control presence from effective least-privilege RBAC and private access enforcement.

```yaml
case_id: AZ-KV-01
title: RBAC and private endpoint are enforced with high-confidence evidence
key_vault:
enable_rbac_authorization: true
public_network_access_enabled: false
purge_protection_enabled: true
rbac:
live_role_export: present
assignments:
- principal: app-managed-identity
role: Key Vault Secrets User
scope: vault
owner: platform-security
ticket: CHG-9021
private_access:
private_endpoint_subresource: vault
private_dns_zone_group: privatelink.vaultcore.azure.net
client_resolution: private_ip_observed
expected_classification:
cis_8_6: Pass
cis_8_7: Pass
confidence: High
reason: "RBAC, live assignment export, public access disablement, private DNS, and client resolution evidence are all present."
```

```yaml
case_id: AZ-KV-02
title: RBAC boolean hides broad data-plane administrator assignment
key_vault:
enable_rbac_authorization: true
rbac:
live_role_export: present
assignments:
- principal: all-engineers
principal_type: group
role: Key Vault Administrator
scope: vault
owner: missing
expiry: missing
expected_classification:
cis_8_6: Fail
severity: High
confidence: High
reason: "RBAC is enabled, but a broad group has full data-plane administration without owner, expiry, or review evidence."
```

```yaml
case_id: AZ-KV-03
title: RBAC migration drift is not evaluable without live role export
key_vault:
enable_rbac_authorization: true
terraform:
access_policy_resources: present
rbac:
live_role_export: missing
portal_assignments: unknown
expected_classification:
cis_8_6: Not Evaluable
not_evaluable_reason: AZ-KV-NE-01
reason: "IaC alone cannot prove that access policies, portal assignments, and live RBAC state are aligned after migration."
```

```yaml
case_id: AZ-KV-04
title: Private endpoint exists but public network path remains open
key_vault:
public_network_access_enabled: true
network_acls:
default_action: Allow
bypass: AzureServices
private_access:
private_endpoint_subresource: vault
private_dns_zone_group: privatelink.vaultcore.azure.net
expected_classification:
cis_8_7: Fail
severity: High
confidence: High
reason: "Private endpoint presence does not enforce private access while public access and default allow are still enabled."
```

```yaml
case_id: AZ-KV-05
title: Private endpoint lacks DNS and client-resolution proof
key_vault:
public_network_access_enabled: false
private_access:
private_endpoint_subresource: vault
private_dns_zone_group: missing
vnet_link: missing
client_resolution: missing
expected_classification:
cis_8_7: Not Evaluable
not_evaluable_reason: AZ-KV-NE-05
reason: "The private endpoint exists, but clients may still resolve or route incorrectly without DNS and client-side evidence."
```

```yaml
case_id: AZ-KV-06
title: Trusted services bypass is accepted without supported service justification
key_vault:
public_network_access_enabled: true
network_acls:
default_action: Deny
bypass: AzureServices
exception_evidence:
supported_service_path: missing
owner: missing
ticket: missing
expected_classification:
cis_8_7: Not Evaluable
not_evaluable_reason: AZ-KV-NE-06
reason: "AzureServices bypass needs a specific supported service path and exception evidence."
```

```yaml
case_id: AZ-KV-07
title: Hosted CI deployment exception has no expiry or audit trail
key_vault:
public_network_access_enabled: true
network_acls:
default_action: Deny
deployment_exception:
reason: hosted_ci_agent_needs_secret_access
owner: release-engineering
expiry: missing
audit_log: missing
compensating_control: missing
expected_classification:
cis_8_7: Not Evaluable
not_evaluable_reason: AZ-KV-NE-07
reason: "Temporary public access for deployment agents requires expiry, audit log, and compensating controls."
```