Skip to content

Remediation Transform Callbacks #180

@jtdub

Description

@jtdub

Is your feature request related to a problem? Please describe.

There are scenarios where the default diff-based remediation workflow produces technically correct but operationally unsafe command sequences. The most common example is ACL modifications on live devices: when removing a deny ip any any rule and adding a new permit rule, the standard remediation will remove the deny first, potentially allowing unwanted traffic during the configuration change window.

Currently, there's no native way within the driver framework to intercept and transform the remediation config after it's computed but before it's applied. Users must write separate post-processing scripts that manipulate the remediation output, which:

  • Duplicates the tree manipulation logic outside the driver
  • Breaks the cohesive driver-based design pattern
  • Makes it harder to share platform-specific remediation patterns
  • Cannot leverage the full HConfig API during transformation

Describe the solution you'd like

Add a remediation_transform_callbacks field to HConfigDriverRules (similar to the existing post_load_callbacks), allowing drivers to register callbacks that transform the remediation config after diff computation.

Proposed Implementation:

  1. Add new field to HConfigDriverRules in driver_base.py:
remediation_transform_callbacks: list[Callable[[HConfig], None]] = Field(
    default_factory=list
)
  1. Update WorkflowRemediation.remediation_config property in workflows.py to apply transforms:
@property
def remediation_config(self) -> HConfig:
    if self._remediation_config:
        return self._remediation_config
 
    remediation_config = self.running_config.config_to_get_to(
        self.generated_config
    ).set_order_weight()
 
    # Apply driver-specific remediation transforms
    for callback in remediation_config.driver.rules.remediation_transform_callbacks:
        callback(remediation_config)
 
    self._remediation_config = remediation_config
    return self._remediation_config
  1. Platform drivers can then define transforms:
# In cisco_ios/driver.py
 
def _safe_acl_remediation(remediation: HConfig) -> None:
    """Add temporary permit-all safety net for ACL modifications."""
    for acl in remediation.get_children(startswith="ip access-list extended"):
        # Check if we're removing deny rules
        has_deny_removals = any(
            child.text.startswith("no") and "deny" in child.text
            for child in acl.children
        )
 
        if has_deny_removals:
            # Add safety entry at the beginning
            safety_child = acl.add_child("  1 permit ip any any")
            safety_child.order_weight = -1000
 
            # Add cleanup at the end
            cleanup_child = acl.add_child("  no 1")
            cleanup_child.order_weight = 1000
 
class HConfigDriverCiscoIOS(HConfigDriverBase):
    @staticmethod
    def _instantiate_rules() -> HConfigDriverRules:
        return HConfigDriverRules(
            # ... existing rules ...
            post_load_callbacks=[
                _rm_ipv6_acl_sequence_numbers,
                _remove_ipv4_acl_remarks,
                _add_acl_sequence_numbers,
            ],
            remediation_transform_callbacks=[
                _safe_acl_remediation,  # NEW
            ],
        )

Benefits:

  • ✅ Follows established post_load_callbacks pattern (familiar to developers)
  • ✅ Platform-specific without coupling to core logic
  • ✅ Full access to HConfig tree manipulation API
  • ✅ Enables safe ACL remediation, BGP session protection, etc.
  • ✅ Users can extend via driver inheritance
  • ✅ Minimal code changes (~15 lines total)
  • ✅ No breaking changes to existing API

Describe alternatives you've considered

  1. Manual Post-Processing (Current Approach)

    • Users write separate scripts to manipulate remediation output
    • Cons: Code duplication, breaks driver cohesion, harder to share patterns
  2. Declarative Remediation Transform Rules

    • Add new rule types like RemediationTransformRule with transform_type enum
    • Pros: Fully declarative, serializable, type-safe
    • Cons: Requires more upfront design, less flexible than callbacks
  3. Plugin System with Registration

    • External plugin framework for user-defined remediation transforms
    • Pros: Users can extend without modifying hier_config source
    • Cons: Significant implementation overhead, may be premature
  4. Workflow Subclassing

    • Users subclass WorkflowRemediation and override remediation_config
    • Cons: Doesn't scale, platform-specific logic should live in drivers

The callback approach (Tier 1) provides immediate value with minimal changes, while leaving room for future enhancement to declarative rules or plugins if needed.

Additional context

Real-World Use Case: Safe ACL Remediation

# Running config
"""
ip access-list extended BLOCK_BAD
  10 deny ip 192.0.2.0 0.0.0.255 any
  12 deny ip any any
  20 permit ip any any
"""
 
# Intended config
"""
ip access-list extended BLOCK_BAD
  10 deny ip 192.0.2.0 0.0.0.255 any
  15 permit tcp any any eq 443
  20 permit ip any any
"""
 
# Standard remediation (UNSAFE - removes deny before adding permit)
"""
ip access-list extended BLOCK_BAD
  no 12 deny ip any any
  15 permit tcp any any eq 443
"""
 
# With remediation transform (SAFE)
"""
ip access-list extended BLOCK_BAD
  1 permit ip any any          # Safety net added first
  no 12 deny ip any any        # Remove problematic deny
  15 permit tcp any any eq 443 # Add new permit
  no 1                         # Remove safety net
"""

Other Potential Use Cases:

  • BGP session protection (add peer shutdown before config changes, re-enable after)
  • Route-map atomic updates (create new, switch reference, delete old)
  • QoS policy safe transitions
  • VLAN database modifications with traffic continuity
  • Multi-step certificate/key rotations

Alignment with hier_config Design Philosophy:

  • Declarative - Transforms are defined in driver rules
  • Hierarchical - Operates on HConfig tree structure
  • Composable - Multiple callbacks can be chained
  • Platform Agnostic - Core workflow unchanged, platform-specific transforms in drivers
  • Lazy Evaluation - Applied during property access, respects caching

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions