Skip to content

feat(scanner): migrate network rules AZ-NET-001 to 027 to the evaluate() contract #371

Description

@parthrohit22

What problem does this solve?

The 27 network rules (AZ-NET-001 to AZ-NET-027) are the largest rule family. These rules only implement scan(), so the engine reports their coverage as UNKNOWN / LEGACY_RULE_NOT_MIGRATED, and every compliance control mapped to them reads UNKNOWN in the evaluation-derived reports introduced in #310.

Describe the solution

Migrate the rules below to the evaluate() contract defined in scanner/evaluation.py, following the storage reference implementation (STORAGE_REF).

Rules in scope: az_net_001 … az_net_027, plus the shared helpers _perimeter_common.py, _private_link_common.py and _data_link_common.py where they are used by network rules.

Delivery: two PRs to keep review manageable. PR A covers NSG / public exposure / perimeter rules. PR B covers private link, firewall, WAF and routing rules. Where a network list helper returns [] on failure, add a list_*() variant returning Optional[List] as in the foundation issue.

Status mapping

Every path that scan() currently handles with a silent continue must become an explicit status:

Situation Status reason_code
Inventory call failed (returned None) ERROR INVENTORY_UNAVAILABLE
Inventory succeeded but is empty NOT_APPLICABLE NO_RESOURCES_FOUND
Setting is compliant PASS —
Setting is a violation FAIL + the existing finding dict —
A per-resource detail call returned None, or a required field is missing UNKNOWN EVIDENCE_UNAVAILABLE / MISSING_PROPERTIES
Opt-in policy tag not set (policy_required(...) is false) NOT_APPLICABLE POLICY_NOT_REQUIRED
Approved exception tag set NOT_APPLICABLE APPROVED_EXCEPTION

A failed inventory call must never produce PASS or NOT_APPLICABLE.

Acceptance criteria

  • Each rule in scope exposes evaluate(azure_client, subscription_id) -> List[RuleEvaluation] using the shared helpers in scanner/evaluation.py.
  • scan() becomes a thin wrapper returning the findings attached to FAIL evaluations.
  • Detection is unchanged: for the existing test fixtures, scan() returns exactly the same findings as before the change.
  • Each FAIL / PASS evaluation records the inspected value(s) in evidence, for example {"allow_blob_public_access": true}.
  • New tests cover the PASS, FAIL, UNKNOWN, NOT_APPLICABLE and inventory-failure paths for every rule in scope.
  • The rules are picked up automatically by tests/test_rule_evaluation_contract.py and it passes.
  • pytest, ruff check . and ruff format --check . pass.
  • CHANGELOG.md updated under Unreleased.

Alternatives considered

Migrating one rule at a time was considered. Grouping by family lets each PR add the family's inventory helper once and review the shared common module once.

Additional context

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    coreCore team ownership not for studentsenhancementNew feature or requestpriority: mediumShould be fixed soon but not blockingpythonPull requests that update python coderoadmapPlanned feature track, not a current bug

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions