1

I want to extract a network group from a Cisco config using Python and regular expressions. The group starts with object-group network Cloudflare and just after that, there are one or more subnets like network-object 173.245.48.0 255.255.240.0. The text would be

object-group network Cloudflare
 network-object 173.245.48.0 255.255.240.0
 network-object 103.21.244.0 255.255.252.0
 network-object 103.22.200.0 255.255.252.0
 network-object 103.31.4.0 255.255.252.0
 network-object 141.101.64.0 255.255.192.0
 network-object 108.162.192.0 255.255.192.0
 network-object 190.93.240.0 255.255.240.0
 network-object 188.114.96.0 255.255.240.0
 network-object 197.234.240.0 255.255.252.0
 network-object 198.41.128.0 255.255.128.0
 network-object 162.158.0.0 255.254.0.0
 network-object 104.16.0.0 255.248.0.0
 network-object 104.24.0.0 255.252.0.0
 network-object 172.64.0.0 255.248.0.0
 network-object 131.0.72.0 255.255.252.0

While using this regex (?P<name>object-group network Cloudflare)\n(?P<subnets> network-object \d+\.\d+\.\d+\.\d+ \d+\.\d+\.\d+\.\d+\n)* I get 3 match groups, of which only the 1st is usable but it contains the header object-group .... Can it be improved? https://regex101.com/r/s925cq/1

Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
mlazzarotto91
  • 103
  • 3
  • 13
  • 1
    What's the official name for this file format? Chances are pretty good that there's a python module ready to parse it and give you all the information you need from it without the need for regexs at all. – Ted Lyngmo Jan 13 '23 at 16:11
  • Your regex looks to work perfectly. What exactly are you trying to achieve? Please give some context and/or code. – PJProudhon Jan 13 '23 at 16:23
  • @TedLyngmo I don't think it has a name. It's the format used by Cisco ASA to define group of network objects. In this case the 'members' are subnets. – mlazzarotto91 Jan 13 '23 at 16:34
  • @PJProudhon What I'm trying to achieve is a script to automatically extract just the subnets contained in the 'Cloudflare' group. If you open the regex101 url, you'll see that in the first match group, the first row is also extracted. I just wanted to know if with a better expression I could extract only the rows starting with ` network-object ` – mlazzarotto91 Jan 13 '23 at 16:36
  • 2
    https://github.com/topics/cisco-asa seems to list quite a few repos. Perhaps there's something useful in there. – Ted Lyngmo Jan 13 '23 at 16:47
  • 1
    @mlazzarotto91 See [regex demo](https://regex101.com/r/3X4Urk/1) ? – SaSkY Jan 13 '23 at 17:00
  • 1
    You can get all the network objects in named group `subnets` with `(?Pobject-group network Cloudflare)\n(?P(?: network-object (?:\d+\.){3}\d+ (?:\d+\.){3}\d+\n)*)` See https://regex101.com/r/OloB8E/1 – The fourth bird Jan 13 '23 at 19:49

2 Answers2

1
data = """
 network-object 1.1.1.1 0.0.0.0
object-group network Cloudflare
 network-object 173.245.48.0 255.255.240.0
 network-object 103.21.244.0 255.255.252.0
 network-object 103.22.200.0 255.255.252.0
 network-object 103.31.4.0 255.255.252.0
 network-object 141.101.64.0 255.255.192.0
 network-object 108.162.192.0 255.255.192.0
 network-object 190.93.240.0 255.255.240.0
 network-object 188.114.96.0 255.255.240.0
 network-object 197.234.240.0 255.255.252.0
 network-object 198.41.128.0 255.255.128.0
 network-object 162.158.0.0 255.254.0.0
 network-object 104.16.0.0 255.248.0.0
 network-object 104.24.0.0 255.252.0.0
 network-object 172.64.0.0 255.248.0.0
 network-object 131.0.72.0 255.255.252.0
access-list outside
"""

regex=r"object-group network (?P<network>\S+)|network-object\s(?P<subnet>\S+?)\s(?P<mask>\S+)"
matches = re.finditer(regex, data)
result = []
network_group = {"network": "Unknown"}


for cnt, match in enumerate(matches):
    info = match.groupdict()
    info1 = {k: v for k, v in info.items() if v is not None}
    if check:=info.get("network"):
        network_group =   {"network": check} if check else network_group
    if not info.get("network"):
        result.append(network_group | info1)
result

enter image description here

pinky
  • 382
  • 1
  • 5
  • 17
1

You can get all the network objects in named group subnets with:

(?P<name>object-group network Cloudflare)\n(?P<subnets>(?: network-object (?:\d+\.){3}\d+ (?:\d+\.){3}\d+\n)+)

Explanation

  • (?P<name>object-group network Cloudflare) Named group name, match literally
  • \n Match a newline
  • (?P<subnets> Named group subnets
    • (?: Non capture group to repeat as a whole
      • network-object
      • (?:\d+\.){3}\d+ (?:\d+\.){3}\d+\n match 2 times the digits with dot part followed by a newline
    • )+ Close the non capture group and repeat 1 or more times (to match at least 1 line)
  • ) Close group subnets

See a regex 101 demo.

The fourth bird
  • 154,723
  • 16
  • 55
  • 70