Extensible Security-Event Pipeline: Rule Suppression and Plugin-Based Enrichment
Abnormal AiSoftware Engineer · Technical ScreenLast updated
Tests your ability to design and implement an extensible, plugin-based security event processing engine supporting multi-tenant enrichments and dynamic rule suppression.
Context
Modern cloud security platforms ingest massive streams of telemetry events (e.g., login attempts, file downloads, API key usage). Before triggering an alert, each event must pass through a processing pipeline that dynamically enriches the event with contextual threat intelligence and evaluates suppression rules to filter out known false positives or benign behaviors.
Different tenants (organizations) require different configurations: some enrichers and suppression rules apply globally, while others are tenant-specific. In addition, new enrichers and rules must be pluggable at runtime without requiring core pipeline redeployments.
Requirements
Implement an extensible, in-memory pipeline engine consisting of:
Event: An object containing at leasttenant_id: str,event_type: str,timestamp: int, andattributes: dict.Enricher(Interface/Base Class): Defines a methodenrich(event: Event) -> Nonethat mutates the event'sattributesin-place or records additional metadata.SuppressionRule(Interface/Base Class): Defines a methodshould_suppress(event: Event) -> boolthat returnsTrueif the event should be dropped/suppressed.SecurityPipeline: Manages registration and execution of enrichers and suppression rules:register_enricher(enricher: Enricher, tenant_id: Optional[str] = None) -> None: Registers an enricher. Iftenant_idisNone, it applies globally to all tenants. Otherwise, it only applies to the specified tenant.register_suppression_rule(rule: SuppressionRule, tenant_id: Optional[str] = None) -> None: Registers a suppression rule globally or per tenant.process(event: Event) -> Optional[Event]: Executes all applicable global enrichers followed by tenant-specific enrichers. Then, evaluates global suppression rules followed by tenant suppression rules. If any suppression rule returnsTrue, processing stops andNoneis returned. If no suppression rule triggers, return the enrichedEvent.
Error Handling & Edge Cases
- If an enricher raises an exception, the pipeline should log or capture the error in
event.attributes["pipeline_errors"]and continue processing rather than crashing the pipeline. - Order of enricher execution should preserve the order in which they were registered.
- Suppression rules should be evaluated in order; the first rule that returns
Trueshort-circuits further suppression evaluations.
Example
class IPReputationEnricher:
def enrich(self, event: Event) -> None:
ip = event.attributes.get("source_ip")
if ip == "192.168.1.100":
event.attributes["is_internal"] = True
else:
event.attributes["is_internal"] = False
class InternalIPSuppressionRule:
def should_suppress(self, event: Event) -> bool:
return event.attributes.get("is_internal") is True
pipeline = SecurityPipeline()
pipeline.register_enricher(IPReputationEnricher()) # Global
pipeline.register_suppression_rule(InternalIPSuppressionRule(), tenant_id="tenant_a")
event_1 = Event(
tenant_id="tenant_a",
event_type="login",
timestamp=1600000000,
attributes={"source_ip": "192.168.1.100"}
)
result_1 = pipeline.process(event_1)
# Output: None (Enriched with is_internal=True, then suppressed by tenant_a rule)
event_2 = Event(
tenant_id="tenant_b",
event_type="login",
timestamp=1600000001,
attributes={"source_ip": "192.168.1.100"}
)
result_2 = pipeline.process(event_2)
# Output: Event with attributes: {"source_ip": "192.168.1.100", "is_internal": True}
# (Suppression rule was only registered for tenant_a)
Hints
Hint 1
Maintain separate collections for global versus tenant-specific enrichers and rules to avoid scanning unrelated tenant logic during execution.
Hint 2
Ensure enrichment runs strictly before suppression evaluation, as suppression rules often depend on attributes populated by enrichers.
Hint 3
Wrap plugin invocations in a try-except block to guarantee that faulty third-party plugins cannot crash the entire pipeline.
Follow-up questions
- How would you support dynamic hot-reloading of plugins and rules from an external store (e.g., database or S3) without restarting worker nodes or dropping in-flight events?
- If certain enrichers involve high-latency network I/O (e.g., third-party threat intelligence APIs), how would you optimize the pipeline execution (e.g., async concurrency, timeouts, circuit breakers)?
- How would you allow tenants to define custom rule suppression logic using a safe, sandboxed expression language instead of deploying arbitrary Python code?
Solution walkthrough is for members
Get the full walkthrough with reference code and complexity analysis, plus Kitty Coach at 300 messages a day. Hints, the code runner and community answers stay free.