feat(bigip): surface the three AWAF forms + honest declines in the console & report - #54
Merged
Merged
Conversation
…nsole & report
The BIG-IP backend (apply_bigip → emit(target="bigip-awaf")) already handles all
three shipped forms (service_policy, waf_data_guard, api_schema) and honestly
declines the rest, but two presentational surfaces predated waf_data_guard and
api_schema and misrepresented the state:
Console ④ Mitigate "Apply on your own BIG-IP" panel
- Dropdown was hardcoded to service_policy findings only, so 2 of 3 shipped forms
were unreachable and no decline was ever shown. Now driven by /api/emit
(target=bigip-awaf) — every shipped form is selectable and every declining
control is listed inline with its reason. Help text rewritten (was "Only
service_policy … has an AWAF form today").
- Refreshed the ② Review "Emit for another WAF" copy to name all three forms +
the waf staging decline.
Standalone report
- FIX (verified crash): a BIG-IP apply wrote before_after as a [before, after]
list while every XC apply writes a {before, after} dict, so building a report
after any "Apply on your own BIG-IP" run raised AttributeError on ba.get().
Root-caused in bigip_apply.py (now the dict shape); export.py's silent drop is
fixed too. _impact_rows also normalizes the legacy list shape so reports over
pre-fix audit logs still render.
- New "BIG-IP Advanced WAF (bring-your-own)" section, computed per-finding from
the SAME emitter over the run's policies.json + probes.json: names the form
emitted for each finding, and splits declines into "no AWAF object at all"
(XC-only, structural) vs "form exists but this finding lacked the data". No
fabricated "supported" states.
- apply_bigip_awaf now labelled in the impact table.
emitters.py: AWAF_FORMS registry (form names, one place) + WAF_STAGING_REASON
constant shared by emit and the legends.
+7 tests. Full suite 1126 pass, ruff clean. Offline throughout — no lab.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What & why
Task A of the BIG-IP resume: the console ④ Mitigate "Apply on your own BIG-IP" panel (PRs #47–#48) and the standalone report predate
waf_data_guardandapi_schema, so they didn't reflect the current forms. The backend was already correct —apply_bigipdispatches throughemit(target="bigip-awaf")and handles all three shipped forms while honestly declining the rest — so this is a purely presentational fix. Offline throughout (no lab).Audit findings (all verified before changing anything)
Console panel — dropdown hardcoded to
service_policy(index.html:638), sowaf_data_guard/api_schemafindings were unreachable and no decline was ever surfaced. Help text said "Onlyservice_policyband-aids have an AWAF form today" (stale).Report — no BIG-IP surface at all, and a verified crash: a BIG-IP apply wrote
before_afteras a[before, after]list (bigip_apply.py:205) while every XC apply writes a{before, after}dict; the report doesba.get("before"), so building a report after any BIG-IP apply raisedAttributeError: 'list' object has no attribute 'get'. (export.py:142already guarded this shape and silently dropped it.)Changes
Console
/api/emit(targetbigip-awaf) — the emitter is the source of truth, so all three forms are selectable and every declining control is listed inline with its reason. Help text rewritten.wafstaging decline.Report
before_afterlist→dict inconsistency inbigip_apply.py(fixes the crash + the export drop)._impact_rowsalso normalizes the legacy list shape so reports over pre-fix audit logs still render.policies.json+probes.json: names the form emitted for each finding, and splits declines into "no Advanced-WAF object at all" (XC-only, structural) vs "form exists but this finding lacked the data". No fabricated "supported" states.apply_bigip_awafnow labelled in the impact table.emitters.py —
AWAF_FORMSregistry (form names in one place, read by the report) + sharedWAF_STAGING_REASONconstant.Tests
+7 tests (emitter registry↔emit consistency, report BIG-IP section + decline split, the crash regression + legacy-list tolerance, the
/api/emitpanel contract). Full suite 1126 pass, 15 skipped, ruff clean.🤖 Generated with Claude Code