diff --git a/skills/cloud/azure-review/SKILL.md b/skills/cloud/azure-review/SKILL.md index ac6d6ac7..3184fe2c 100644 --- a/skills/cloud/azure-review/SKILL.md +++ b/skills/cloud/azure-review/SKILL.md @@ -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 @@ -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 --- @@ -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:** - **Line(s):** - **Description:** - **Evidence:** +- **Not Evaluable Reason:** - **Remediation:** +### 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 -- @@ -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. --- @@ -224,6 +235,9 @@ 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 @@ -231,4 +245,5 @@ Produce the final report using the structure defined in the Output Format sectio ## 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. diff --git a/skills/cloud/azure-review/benchmark-checklist.md b/skills/cloud/azure-review/benchmark-checklist.md index 41a67846..6ffbf0f6 100644 --- a/skills/cloud/azure-review/benchmark-checklist.md +++ b/skills/cloud/azure-review/benchmark-checklist.md @@ -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: @@ -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 diff --git a/skills/cloud/azure-review/tests/key-vault-rbac-private-endpoint-edge-cases.md b/skills/cloud/azure-review/tests/key-vault-rbac-private-endpoint-edge-cases.md new file mode 100644 index 00000000..b1f7dd2e --- /dev/null +++ b/skills/cloud/azure-review/tests/key-vault-rbac-private-endpoint-edge-cases.md @@ -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." +```