Most engineers think…
"The WAF blocked it — case closed. Logging is just noise for compliance."
Wrong — and that one belief is why so many WAF incidents take hours instead of minutes. When a real customer is wrongly blocked at 2pm on launch day, "the WAF blocked it" is the start of the investigation, not the end. Without a logging profile sending events somewhere you can read them, you're blind. With one — and the support ID from the block page — you open the exact request, see every violation and the matched signature, and fix the right thing in two minutes. And once you can read the WAF, ASM iRules let you script it: log custom fields, allow a trusted source, or raise your own violation. This lesson turns the WAF from a black box into a black-box recorder you can read and program.
① Logging profiles — the WAF's recorder settings
Think of a CCTV system. The camera (the WAF) sees everything, but whether anything is recorded, and where the tape is stored, is a separate setting. In Advanced WAF that setting is the logging profile. It answers two questions: which requests to log, and where to store them.
You build it at Security ▸ Event Logs ▸ Logging Profiles ▸ Create, enable Application Security, and then choose the destination. The two big choices:
- Local Storage — events stay on the BIG-IP and you read them in the GUI Event Logs. Fine for a lab or low traffic; on a busy box it competes for disk and is lost on reboot.
- Remote Storage — events are forwarded off-box over high-speed logging to a syslog server or SIEM pool. This is the production answer.
For remote storage you also pick the format so the receiving system can parse the fields. There are three you must know for the 303 exam: CSV for a generic syslog server, key-value pairs for a reporting server like Splunk, and CEF for an ArcSight server. Finally, Request Type decides volume: Illegal requests only (the default — just the blocks/alarms) or All Requests (everything, huge volume, use only while tuning).
Sneha at Infosys faces this
Sneha's new WAF blocked a partner's API call during a demo. She opens the GUI to investigate — and the Event Logs are empty. Nothing was recorded.
No logging profile is attached to the virtual server, so the WAF blocked but recorded nothing. A policy without a logging profile is a camera with no recorder.
Check the virtual server's security settings for an attached Log Profile.
Local Traffic ▸ Virtual Servers ▸ vs_partner_api ▸ Security ▸ Policies ▸ Log ProfileCreate a profile at Security ▸ Event Logs ▸ Logging Profiles, enable Application Security, set Request Type = All Requests while she debugs, attach it to the VS, and re-run the call.
Re-trigger the partner call. It now appears under Security ▸ Event Logs ▸ Application ▸ Requests with a support ID she can open. She later flips Request Type back to Illegal requests only for steady-state.
▶ Watch a request become a readable event — then watch the no-profile mistake
Rahul at TCS attaches a logging profile. Press Play for the recorded flow, then Break it to see what happens with no profile attached.
A new policy blocks a request, but the Event Logs are completely empty. What's the most likely cause?
Pause & Predict
Your SOC runs ArcSight. A teammate sets the logging profile's remote format to Key-Value Pairs because "that's what we used at the last job". What breaks, and what should it be? Type your guess.
CEF:Version|Vendor|Product|… structure). Feeding it key-value pairs means ArcSight can't parse the fields, so dashboards and correlation rules go blank. Key-value is the Splunk format; CSV is for a plain syslog server. Match the format to the SIEM — that's the whole point of the format setting.② Trace a block by its support ID
This is the skill that makes you the person the team calls during an incident. A user is blocked. Instead of guessing, you ask them one thing: "what's the support ID on the block page?"
Every blocking response page Advanced WAF returns prints a support ID — a long unique number. You take it to Security ▸ Event Logs ▸ Application ▸ Requests, paste it into the search, and the WAF opens that exact request: the violations it triggered, the matched attack signature, the parameter and value, the source IP, and the full request data. No log-diving, no time filters — one number, one request.
From there the decision is the same tuning judgement you already know: if it's a legitimate request wrongly blocked, you accept the suggestion or relax the entity; if it's a real attack, you confirm the block is correct and move on. The support ID is what turns "somewhere in millions of log lines" into "this one row".
The same value you paste into Event Logs is available in TCL as ASM::support_id. So you can write an iRule that logs the support ID to a custom remote target, injects it into a response header for your app team, or correlates it with an upstream request ID. One identifier, GUI and script — that's why the 303 exam keeps coming back to it.
The four log surfaces — tap to flip
The per-request log. Search by support ID to open one transaction with all its violations, the matched signature, parameter, value and source IP. Your incident starting point.
Aggregated charts — top violations, top URLs, top attacking IPs over time. Use it to spot trends and campaigns, not single requests.
The recorder settings: which requests (illegal vs all) and where they go (local vs remote: CSV / key-value / CEF). Attach to the virtual server to take effect.
Where production events really live — Splunk (key-value), ArcSight (CEF) or a syslog server (CSV). Correlation, alerting and long retention happen here, off the BIG-IP.
A customer says "I was blocked at 3:14pm". What's the fastest way to open their exact request?
ASM::support_id in an iRule.Pause & Predict
During an attack, your BIG-IP's disk fills up and logging stops. The profile is set to Local Storage with Request Type = All Requests. Name the two changes that fix it. Type your guess.
③ ASM iRule events — ASM_REQUEST_DONE and friends
Reading the WAF is half the power. The other half is scripting it. iRules let you run custom logic at specific moments in a transaction. ASM adds its own set of events — moments that fire when the security policy has something to say.
There are three ASM events you must know:
ASM_REQUEST_DONE— fires after ASM finishes processing every request, whether it had a violation or not. This is the modern, all-purpose hook. F5's own guidance: if you're writing new iRules, use this — it replacesASM_REQUEST_VIOLATION.ASM_REQUEST_VIOLATION— the legacy event, fired only when a request violated the policy. Kept for backward compatibility only. Don't reach for it in new work.ASM_RESPONSE_VIOLATION— fires when a response (server → client) violates the policy, e.g. data-leakage / DataGuard matches on the way out.
The reason ASM_REQUEST_DONE won is that it runs once, predictably, at the end of request processing — so inside it you can read ASM::status (did it block?), ASM::violation (what fired?) and ASM::support_id (which transaction?) in one place, for every request, and decide what to do. The old violation-only event couldn't see the clean requests at all.
Symptom you'll see: a junior writes a new logging iRule on ASM_REQUEST_VIOLATION, and it never logs clean traffic — only blocks — so their "log every request" requirement silently fails. Cause: the violation event only fires on violations. Fix: use ASM_REQUEST_DONE and branch on ASM::status. The legacy event exists only so old iRules keep working — F5 explicitly says new iRules should use ASM_REQUEST_DONE.
Karthik at Wipro faces this
Karthik must inject the WAF support ID into a response header so the app team can correlate WAF blocks with their own request IDs. He writes it on ASM_REQUEST_VIOLATION and it only works for blocked requests, not clean ones.
The legacy event fires only on violations. Clean requests never reach his header-injection logic, so the app team can't correlate the majority of traffic.
Confirm which event the iRule is bound to and what fires it.
Local Traffic ▸ iRules ▸ irule_asm_supportid_header — event ASM_REQUEST_VIOLATIONMove the logic to ASM_REQUEST_DONE, capture set sid [ASM::support_id], and set the header in HTTP_RESPONSE. Now every request — clean or blocked — carries the ID.
Send a clean request and a blocked one. Both responses now carry X-WAF-Support-ID; the app team's traces line up with the WAF Event Logs by that value.
The iRule (real, copy-pasteable)
when ASM_REQUEST_DONE {
# runs after EVERY request — clean or violating
set sid [ASM::support_id]
set st [ASM::status]
if { $st ne "" } {
# a violation fired — record what and from where
log local0. "WAF status=$st support_id=$sid \
client=[ASM::client_ip] severity=[ASM::severity] \
violations=[ASM::violation names]"
}
# stash for the response stage
set ::sid_for_resp $sid
}
when HTTP_RESPONSE {
HTTP::header insert "X-WAF-Support-ID" $::sid_for_resp
}
Jun 2 14:07:31 bigip1 info tmm[12044]: Rule /Common/irule_asm_supportid : WAF status=blocked support_id=18446744073709551607 client=203.0.113.7 severity=critical violations=VIOL_ATTACK_SIGNATURE # and on the app side, the response now carries: X-WAF-Support-ID: 18446744073709551607
You're writing a new iRule that must run after every request (clean or blocked) to log a custom field. Which event do you bind it to?
ASM_REQUEST_DONE fires after ASM finishes processing each request, violation or not, so it sees clean traffic too — exactly what "after every request" needs. F5 made it the replacement for ASM_REQUEST_VIOLATION (legacy, violations only). ASM_RESPONSE_VIOLATION is for outbound response checks.Pause & Predict
An iRule calls ASM::raise my_custom_violation on a suspicious request, but nothing ever alarms or blocks. The command runs without error. What's missing in the policy? Type your guess.
ASM::raise only signals a user-defined violation — whether it alarms or blocks is still decided by the policy. You must (1) create the user-defined violation and set its Alarm/Block flags, and (2) enable application-security iRule events in the policy. Without those, the raise is heard but the policy does nothing with it. The iRule proposes; the policy disposes.④ ASM iRule commands — read, allow, raise (and the disable trap)
Inside those events you call ASM commands. Here are the ones the 303 exam and real production both lean on:
ASM::support_id— the transaction's support ID (the same one on the block page).ASM::violation— the list of violations on the current request/response, with details.ASM::violation_dataexposes the same via multiple buffers.ASM::severity— the overall severity of the transaction's violations.ASM::client_ip— the end client's real IP for the current request.ASM::status— the current status of the request/response (did it block?).ASM::unblock— overrides the blocking action for a request that had a blocking violation (surgical allow).ASM::raise— issues a user-defined violation on the present request.ASM::disable/ASM::enable— turn WAF plugin processing off / on for the connection.
Symptom you'll see: someone scripts ASM::disable broadly "to speed things up", and weeks later an attack walks straight through on those connections — the WAF was off. Cause: ASM::disable turns off WAF processing for that connection entirely. Fix: only use it on a specific, documented, trusted path (e.g. an internal health-check URL), never as a blanket switch on customer-facing traffic. Same discipline for ASM::unblock — surgical, logged, justified.
A health-check from a trusted internal monitor keeps tripping a blocking violation. You want only that request to pass while every other check stays enforced. Which command fits?
ASM::unblock overrides the blocking action for a request that had a blocking violation — used surgically (matched on the trusted source/URL) it lets that one request through while the rest of the policy keeps blocking. ASM::disable (a) would turn the WAF off entirely for the connection — far too broad.Stuck? Ask the lesson tutor
Scoped to this blog only — logging profiles, support IDs, ASM events & commands. Tap a question.
Powered by the Techclick lesson tutor · answers grounded in this blog. For anything else, use the main chat at chat.techclick.in.
📝 Wrap-up assessment — six more
You've answered 4 inline. Six left. 70% (7 of 10) marks the lesson complete on your profile. Tap Submit all answers at the end.
🧠 In your own words
Type one line: why does F5 tell you to use ASM_REQUEST_DONE instead of ASM_REQUEST_VIOLATION in new iRules? Then compare to the expert version.
ASM_REQUEST_VIOLATION fires only when a request violated the policy, so it never sees clean traffic — it's kept only for backward compatibility. ASM_REQUEST_DONE fires after ASM finishes processing every request, violation or not, so in one predictable place you can read ASM::status, ASM::violation and ASM::support_id and decide what to do for any request. That's why F5 made it the modern replacement. If your answer mentioned "DONE runs on every request, VIOLATION only on blocks", you've got it.🗣 Teach a friend
Best way to lock it in — explain it in one line to a teammate. Tap to generate a paste-ready summary.
📖 Glossary
- Logging profile
- A reusable object (Security ▸ Event Logs ▸ Logging Profiles) that decides which requests are logged (illegal-only or all) and where they go (local storage or remote high-speed logging). Attach it to the virtual server to take effect.
- Local Storage
- Logging destination that keeps events on the BIG-IP, viewable in the GUI Event Logs. Fine for labs/low traffic; competes for disk and is lost on reboot on busy boxes.
- Remote high-speed logging (HSL)
- F5's low-overhead mechanism for forwarding log messages off-box to an external syslog/SIEM pool — the production logging answer.
- CSV / Key-value / CEF
- The three remote storage formats. CSV = generic syslog; Key-value pairs = Reporting Server / Splunk; CEF (Common Event Format) = ArcSight. Match the format to the SIEM.
- Request Type
- The logging-profile setting choosing All Requests (high volume — tuning) or Illegal requests only (default — steady-state).
- Support ID
- A unique identifier ASM stamps on each transaction and prints on the block page. Search it in Security ▸ Event Logs ▸ Application ▸ Requests to open the exact request. In an iRule it's
ASM::support_id. - ASM_REQUEST_DONE
- iRule event that fires after ASM finishes processing every request, violation or not — the modern, all-purpose ASM hook, replacing ASM_REQUEST_VIOLATION.
- ASM_REQUEST_VIOLATION
- Legacy iRule event that fires only when a request violated the policy. Kept for backward compatibility; not for new iRules.
- ASM_RESPONSE_VIOLATION
- iRule event that fires when a response (server → client) violates the policy, e.g. data-leakage / DataGuard matches.
- ASM::unblock
- iRule command that overrides the blocking action for a request that had a blocking violation — a surgical, logged allow, not a way to disable the WAF.
- ASM::raise
- iRule command that issues a user-defined violation on the present request. Whether it alarms/blocks depends on the policy's flags and enabled iRule events.
- ASM::disable / ASM::enable
- Turn WAF plugin processing off/on for the connection. Use disable only on a specific, trusted, documented path — never as a blanket performance hack.
📚 Sources
- F5 BIG-IP 17.5.0 Documentation — Logging Application Security Events (creating logging profiles, local vs remote storage, CSV / key-value / CEF formats, Request Type illegal-vs-all, viewing local events, attaching to the virtual server). techdocs.f5.com/en-us/bigip-17-5-0/big-ip-asm-implementations/logging-application-security-events.html
- F5 clouddocs — iRules ASM namespace (events ASM_REQUEST_DONE, ASM_REQUEST_VIOLATION, ASM_RESPONSE_VIOLATION; commands ASM::support_id, ASM::violation, ASM::violation_data, ASM::status, ASM::client_ip, ASM::severity, ASM::unblock, ASM::raise, ASM::disable, ASM::enable). clouddocs.f5.com/api/irules/ASM.html
- F5 clouddocs — ASM_REQUEST_DONE event reference ("triggered after ASM finished processing the request and found all violations"; modern replacement for ASM_REQUEST_VIOLATION). clouddocs.f5.com/api/irules/ASM_REQUEST_DONE.html
- F5 KB — K37655278: BIG-IP ASM event logging + K23041827: An iRule that uses ASM violation details (support ID lookup, violation data in iRules, custom logging patterns). my.f5.com
- F5 Agility iRules Labs — Class 2 / Module 1 / Lab 2: ASM Hooks (hands-on ASM_REQUEST_DONE, reading ASM::violation and ASM::support_id, enabling application-security iRule events). f5-agility-labs-irules.readthedocs.io
- F5 Certification — 303 — BIG-IP ASM Specialist Exam Blueprint (logging configuration, event analysis, iRules objectives). education.f5.com/exams/big-ip-asm-specialist-303
- Reddit r/f5networks + DevCentral community.f5.com — practitioner threads on remote logging to Splunk (key-value) vs ArcSight (CEF), tracing blocks by support ID, and ASM_REQUEST_DONE vs the legacy violation event. reddit.com/r/f5networks · community.f5.com
What's next?
You can now turn the WAF into a recorder you read and program: build a logging profile, route events local or remote in the right format, trace any block by its support ID, and script ASM with ASM_REQUEST_DONE and the ASM commands. Tie it back to tuning — when a support-ID trace shows a false positive, you already know how to fix it. Prove it on the simulator and the 303 mock.