nautobot/nautobot-app-golden-config

Support a new custom remediation specifically to allow for dynamic rememdation overrides heir_config exposes

jeffkala opened this issue · 1 comments

Environment

  • Nautobot version: 2.1+
  • nautobot-golden-config version: 2.0.5

Proposed Functionality

Heir config allows for dynamic remediation functions (custom remediation but within heir-config realm), ability to register these python functions but have compliance-type (heir_config) register them instead of requiring full custom remedation which is essentially just using heir_config with just a dynamic function.

Use Case

This is one of those scenarios where hier_config doesn't work out of the box. At a previous employer, we wrote what we called dynamic remediations for these types of use cases. A dynamic remediation is a python function that you write to perform a remediation in a specific way that overrides the default remediation method.

Here is an example:

#!/usr/bin/env python

from hier_config import Host

## Dynamic Remediation Function
def acl_rem(lineage):

    # Iterate over ACL items
    for line in lineage.all_children():

        # Find remediations that start with 'no'
        if line.text.startswith('no'):
            line_items = line.text.split()

            # Determine if sequence number is in remediation
            try:
                if isinstance(int(line_items[1]), int):

                    # Remove sequence number from remediation
                    line_items.remove(line_items[1])
            except ValueError:
                pass

        # Remove stale remediaiton line
        lineage.del_child_by_text(line.text)

        # Add updated remediation line
        lineage.add_child(' '.join(line_items))

    # Return lineage
    return lineage



host = Host('acl-rtr', os='ios')
host.load_running_config_from_file('./running_acl.conf')
host.load_generated_config_from_file('./generated_acl.conf')
rem = host.remediation_config()

print("## Unfiltered Remediation")
print(host.remediation_config_filtered_text([],[]))

acl = rem.get_child('equals', 'ip access-list TEST')
dynamic_rem = acl_rem(acl)

print("## Filtered Remediation")
print(host.remediation_config_filtered_text([],[]))

Here is the script output:

% python3 acl.py
## Unfiltered Remediation
ip access-list TEST
  no 20 permit ip host 192.2.0.2
## Filtered Remediation
ip access-list TEST
  no permit ip host 192.2.0.2

https://networktocode.slack.com/archives/C01NWPK6WHL/p1712169405284649?thread_ts=1712083136.419609&cid=C01NWPK6WHL

Here were the contents of the configurations:

% cat running_acl.conf
ip access-list TEST
  10 permit ip host 192.2.0.1
  20 permit ip host 192.2.0.2
% cat generated_acl.conf
ip access-list TEST
  10 permit ip host 192.2.0.1

When I imagine hier_config dynamic remediation's in GC, I imagine a repo folder structure with dynamic remediation conf scripts.

Something like:

hier_config_dynamic_remediations/
|
+-- acl.py

When the repo is loaded into Nautobot, Nautobot registers the dynamic remediation's into the ORM. At that point, you can create a dynamic remediation mapping of:

  1. expression_choice: ["startswith", "endswith", "equals", "contains"]
  2. config_str: "ip access-list TEST"
  3. dynamic_remediation_choice: [list of registered dynamic remediations]
  4. platform(s): platforms to execute dynamic remediation against
  5. enabled: Boolean

At that point, when hier_config is invoked, hier_config can invoke the dynamic remediation as part of the remediation process.