From e6db422836005e3a7e3e8cd136cfb4ee7e10aeae Mon Sep 17 00:00:00 2001 From: Hugo Tinoco <43675476+h4ndzdatm0ld@users.noreply.github.com> Date: Sat, 11 Mar 2023 12:14:35 +0000 Subject: [PATCH 1/6] Starting adding routeros --- docs/dev/include_parser_list.md | 1 + netutils/config/compliance.py | 1 + netutils/config/parser.py | 12 ++ .../mikrotik_routeros/routeros_backup.txt | 62 +++++++++ .../mikrotik_routeros/routeros_feature.py | 3 + .../mikrotik_routeros/routeros_intended.txt | 62 +++++++++ .../mikrotik_routeros/routeros_received.json | 12 ++ .../routeros_full_received.py | 119 ++++++++++++++++++ .../mikrotik_routeros/routeros_full_sent.txt | 62 +++++++++ 9 files changed, 334 insertions(+) create mode 100644 tests/unit/mock/config/compliance/compliance/mikrotik_routeros/routeros_backup.txt create mode 100644 tests/unit/mock/config/compliance/compliance/mikrotik_routeros/routeros_feature.py create mode 100644 tests/unit/mock/config/compliance/compliance/mikrotik_routeros/routeros_intended.txt create mode 100644 tests/unit/mock/config/compliance/compliance/mikrotik_routeros/routeros_received.json create mode 100644 tests/unit/mock/config/parser/base/mikrotik_routeros/routeros_full_received.py create mode 100644 tests/unit/mock/config/parser/base/mikrotik_routeros/routeros_full_sent.txt diff --git a/docs/dev/include_parser_list.md b/docs/dev/include_parser_list.md index 65279f72..97d30c9b 100644 --- a/docs/dev/include_parser_list.md +++ b/docs/dev/include_parser_list.md @@ -13,5 +13,6 @@ | fortinet_fortios | netutils.config.parser.FortinetConfigParser | | juniper_junos | netutils.config.parser.JunosConfigParser | | linux | netutils.config.parser.LINUXConfigParser | +| mikrotik_routeros | netutils.config.parser.RouterOSConfigParser | | mrv_optiswitch | netutils.config.parser.OptiswitchConfigParser | | nokia_sros | netutils.config.parser.NokiaConfigParser | \ No newline at end of file diff --git a/netutils/config/compliance.py b/netutils/config/compliance.py index 59e176bd..af7a3a11 100644 --- a/netutils/config/compliance.py +++ b/netutils/config/compliance.py @@ -20,6 +20,7 @@ "aruba_aoscx": parser.ArubaConfigParser, "mrv_optiswitch": parser.OptiswitchConfigParser, "extreme_netiron": parser.NetironConfigParser, + "mikrotik_routeros": parser.RouterOSConfigParser, } # TODO: Once support for 3.7 is dropped, there should be a typing.TypedDict for this which should then also be used diff --git a/netutils/config/parser.py b/netutils/config/parser.py index a07d56fa..6a93f7f1 100644 --- a/netutils/config/parser.py +++ b/netutils/config/parser.py @@ -1375,3 +1375,15 @@ class NetironConfigParser(BaseSpaceConfigParser): def banner_end(self) -> str: """Demarcate End of Banner char(s).""" raise NotImplementedError("Extreme Netiron platform doesn't have a banner.") + + +class RouterOSConfigParser(BaseSpaceConfigParser): + """Mikrotik RouterOS config parser.""" + + comment_chars: t.List[str] = ["#"] + banner_start: t.List[str] = [] + + @property + def banner_end(self) -> str: + """Demarcate End of Banner char(s).""" + raise NotImplementedError("RouterOS platform doesn't have a banner.") diff --git a/tests/unit/mock/config/compliance/compliance/mikrotik_routeros/routeros_backup.txt b/tests/unit/mock/config/compliance/compliance/mikrotik_routeros/routeros_backup.txt new file mode 100644 index 00000000..2f17f6ec --- /dev/null +++ b/tests/unit/mock/config/compliance/compliance/mikrotik_routeros/routeros_backup.txt @@ -0,0 +1,62 @@ +# by RouterOS 6.49.6 +# software id = WZ00-84LP +# +# model = CCR1036-8G-2S+ +# serial number = C6CD0BF7A020 +/interface bridge add name=google-vpc-peering-iface +/interface bridge add name=loopback +/interface bonding add mode=802.3ad name=Po1 slaves=sfp-sfpplus1,sfp-sfpplus2 +/interface vlan add interface=Po1 name=vlan11-mgmt vlan-id=11 +/interface vlan add interface=vlan2933-Transit-to-CC-NNI name=vlan3049-Transit-to-XXX vlan-id=3049 +/interface vlan add disabled=yes interface=Po1 name=vlan3051-Transit-to-CSW-through-QoE-Disabled vlan-id=3051 +/interface vlan add interface=Po1 mtu=1300 name=vlan3225-Transit-CORE-Agg1-to-COREXXX vlan-id=3225 +/interface wireless security-profiles set [ find default=yes ] supplicant-identity=MikroTik +/ip ipsec peer add address=50.157.100.38/32 exchange-mode=ike2 local-address=55.106.77.11 name=google-vpc-peer +/ip pool add name=BNEdgeLiteTest ranges=192.168.69.254 +/ip pool add name=BNEdgeLiteTest2 ranges=192.168.70.254 +/ip dhcp-server add address-pool=BNEdgeLiteTest disabled=no interface=ether1 name=dhcp1 +/ip dhcp-server add address-pool=BNEdgeLiteTest2 disabled=no interface=ether2 name=dhcp2 +/routing bgp instance set default as=1234 router-id=10.127.1.3 +/routing ospf instance set [ find default=yes ] router-id=10.127.1.3 +/snmp community add addresses=::/0 name=somestringa +/system logging action set 3 bsd-syslog=yes remote=172.16.11.1 remote-port=5140 +/user group set full policy=local,telnet,ssh,ftp,reboot,read,write,policy,test,winbox,password,web,sniff,sensitive,api,romon,dude,tikapp +/user group add name=prom policy=ssh,read,winbox,api,!local,!telnet,!ftp,!reboot,!write,!policy,!test,!password,!web,!sniff,!sensitive,!romon,!dude,!tikapp +#error exporting /interface bridge calea +/ip neighbor discovery-settings set discover-interface-list=!dynamic +/ip address add address=10.0.11.13/24 interface=vlan11-mgmt network=10.0.11.0 +/ip address add address=192.168.69.1/24 interface=ether1 network=192.168.69.0 +/ip dhcp-server network add address=192.168.69.0/24 gateway=192.168.69.1 +/ip dhcp-server network add address=192.168.70.0/24 gateway=192.168.70.1 +/ip dns set servers=8.8.8.8 +/ip firewall address-list add address=34.157.17.38 list=whitelist +/ip firewall address-list add address=72.202.79.109 list=google-vpc-acl +/ip firewall address-list add address=34.157.17.38 list=google-vpc-acl +#error exporting /ip firewall calea +/ip firewall filter add action=drop chain=input dst-address=50.106.77.11 src-address-list=!google-vpc-acl +/ip firewall nat add action=dst-nat chain=dstnat dst-address=50.106.77.11 dst-port=443 protocol=tcp to-addresses=10.1.15.10 +/ip firewall nat add action=masquerade chain=srcnat out-interface=vlan12-Servers +/ip firewall nat add action=src-nat chain=srcnat src-address=50.64.0.75 to-addresses=55.106.77.11 +/ip ipsec identity add peer=google-vpc-peer secret=***** +/ip ipsec policy set 0 disabled=yes +/ip ipsec policy add disabled=yes dst-address=169.254.1.1/32 peer=google-vpc-peer src-address=169.254.1.2/32 tunnel=yes +/ip ipsec policy add disabled=yes dst-address=10.150.0.0/20 peer=google-vpc-peer src-address=0.0.0.0/0 tunnel=yes +/ip service set telnet disabled=yes +/ip service set ftp disabled=yes +/ip service set www disabled=yes +/ip service set api address=10.1.15.5/32,10.120.16.0/20,172.16.11.0/24 +/ip service set api-ssl disabled=yes +/routing bgp network add network=55.106.77.11/32 synchronize=no +/routing bgp network add network=55.106.77.12/32 synchronize=no +/routing bgp peer add in-filter=ibgp-allow-default-in name=CSW out-filter=ibgp-no-default-out remote-address=10.127.1.10 remote-as=12345 update-source=loopback +/routing filter add action=discard chain=ibgp-no-default-out prefix=10.127.1.0/24 +/routing filter add action=accept chain=ibgp-no-default-out prefix=10.64.0.0/10 prefix-length=22-32 +/routing ospf interface add dead-interval=8s hello-interval=2s interface=vlan3049-Transit-to-85Presidential network-type=point-to-point +/routing ospf interface add cost=11 dead-interval=8s hello-interval=2s interface=vlan3166-Transit-HalseyCore-Agg1-to-Indigo-5 network-type=point-to-point +/routing ospf network add area=backbone network=10.126.0.16/29 +/routing ospf network add area=backbone network=10.127.1.3/32 +/snmp set enabled=yes trap-community=somestring +/system clock set time-zone-name=America/New_York +/system identity set name=ag1.123site.nwk.nj +/system logging add action=remote topics=error +/system logging add action=remote topics=info diff --git a/tests/unit/mock/config/compliance/compliance/mikrotik_routeros/routeros_feature.py b/tests/unit/mock/config/compliance/compliance/mikrotik_routeros/routeros_feature.py new file mode 100644 index 00000000..3556f809 --- /dev/null +++ b/tests/unit/mock/config/compliance/compliance/mikrotik_routeros/routeros_feature.py @@ -0,0 +1,3 @@ +features = [ + {"name": "bgp", "ordered": True, "section": ["routing bgp"]}, +] diff --git a/tests/unit/mock/config/compliance/compliance/mikrotik_routeros/routeros_intended.txt b/tests/unit/mock/config/compliance/compliance/mikrotik_routeros/routeros_intended.txt new file mode 100644 index 00000000..2f17f6ec --- /dev/null +++ b/tests/unit/mock/config/compliance/compliance/mikrotik_routeros/routeros_intended.txt @@ -0,0 +1,62 @@ +# by RouterOS 6.49.6 +# software id = WZ00-84LP +# +# model = CCR1036-8G-2S+ +# serial number = C6CD0BF7A020 +/interface bridge add name=google-vpc-peering-iface +/interface bridge add name=loopback +/interface bonding add mode=802.3ad name=Po1 slaves=sfp-sfpplus1,sfp-sfpplus2 +/interface vlan add interface=Po1 name=vlan11-mgmt vlan-id=11 +/interface vlan add interface=vlan2933-Transit-to-CC-NNI name=vlan3049-Transit-to-XXX vlan-id=3049 +/interface vlan add disabled=yes interface=Po1 name=vlan3051-Transit-to-CSW-through-QoE-Disabled vlan-id=3051 +/interface vlan add interface=Po1 mtu=1300 name=vlan3225-Transit-CORE-Agg1-to-COREXXX vlan-id=3225 +/interface wireless security-profiles set [ find default=yes ] supplicant-identity=MikroTik +/ip ipsec peer add address=50.157.100.38/32 exchange-mode=ike2 local-address=55.106.77.11 name=google-vpc-peer +/ip pool add name=BNEdgeLiteTest ranges=192.168.69.254 +/ip pool add name=BNEdgeLiteTest2 ranges=192.168.70.254 +/ip dhcp-server add address-pool=BNEdgeLiteTest disabled=no interface=ether1 name=dhcp1 +/ip dhcp-server add address-pool=BNEdgeLiteTest2 disabled=no interface=ether2 name=dhcp2 +/routing bgp instance set default as=1234 router-id=10.127.1.3 +/routing ospf instance set [ find default=yes ] router-id=10.127.1.3 +/snmp community add addresses=::/0 name=somestringa +/system logging action set 3 bsd-syslog=yes remote=172.16.11.1 remote-port=5140 +/user group set full policy=local,telnet,ssh,ftp,reboot,read,write,policy,test,winbox,password,web,sniff,sensitive,api,romon,dude,tikapp +/user group add name=prom policy=ssh,read,winbox,api,!local,!telnet,!ftp,!reboot,!write,!policy,!test,!password,!web,!sniff,!sensitive,!romon,!dude,!tikapp +#error exporting /interface bridge calea +/ip neighbor discovery-settings set discover-interface-list=!dynamic +/ip address add address=10.0.11.13/24 interface=vlan11-mgmt network=10.0.11.0 +/ip address add address=192.168.69.1/24 interface=ether1 network=192.168.69.0 +/ip dhcp-server network add address=192.168.69.0/24 gateway=192.168.69.1 +/ip dhcp-server network add address=192.168.70.0/24 gateway=192.168.70.1 +/ip dns set servers=8.8.8.8 +/ip firewall address-list add address=34.157.17.38 list=whitelist +/ip firewall address-list add address=72.202.79.109 list=google-vpc-acl +/ip firewall address-list add address=34.157.17.38 list=google-vpc-acl +#error exporting /ip firewall calea +/ip firewall filter add action=drop chain=input dst-address=50.106.77.11 src-address-list=!google-vpc-acl +/ip firewall nat add action=dst-nat chain=dstnat dst-address=50.106.77.11 dst-port=443 protocol=tcp to-addresses=10.1.15.10 +/ip firewall nat add action=masquerade chain=srcnat out-interface=vlan12-Servers +/ip firewall nat add action=src-nat chain=srcnat src-address=50.64.0.75 to-addresses=55.106.77.11 +/ip ipsec identity add peer=google-vpc-peer secret=***** +/ip ipsec policy set 0 disabled=yes +/ip ipsec policy add disabled=yes dst-address=169.254.1.1/32 peer=google-vpc-peer src-address=169.254.1.2/32 tunnel=yes +/ip ipsec policy add disabled=yes dst-address=10.150.0.0/20 peer=google-vpc-peer src-address=0.0.0.0/0 tunnel=yes +/ip service set telnet disabled=yes +/ip service set ftp disabled=yes +/ip service set www disabled=yes +/ip service set api address=10.1.15.5/32,10.120.16.0/20,172.16.11.0/24 +/ip service set api-ssl disabled=yes +/routing bgp network add network=55.106.77.11/32 synchronize=no +/routing bgp network add network=55.106.77.12/32 synchronize=no +/routing bgp peer add in-filter=ibgp-allow-default-in name=CSW out-filter=ibgp-no-default-out remote-address=10.127.1.10 remote-as=12345 update-source=loopback +/routing filter add action=discard chain=ibgp-no-default-out prefix=10.127.1.0/24 +/routing filter add action=accept chain=ibgp-no-default-out prefix=10.64.0.0/10 prefix-length=22-32 +/routing ospf interface add dead-interval=8s hello-interval=2s interface=vlan3049-Transit-to-85Presidential network-type=point-to-point +/routing ospf interface add cost=11 dead-interval=8s hello-interval=2s interface=vlan3166-Transit-HalseyCore-Agg1-to-Indigo-5 network-type=point-to-point +/routing ospf network add area=backbone network=10.126.0.16/29 +/routing ospf network add area=backbone network=10.127.1.3/32 +/snmp set enabled=yes trap-community=somestring +/system clock set time-zone-name=America/New_York +/system identity set name=ag1.123site.nwk.nj +/system logging add action=remote topics=error +/system logging add action=remote topics=info diff --git a/tests/unit/mock/config/compliance/compliance/mikrotik_routeros/routeros_received.json b/tests/unit/mock/config/compliance/compliance/mikrotik_routeros/routeros_received.json new file mode 100644 index 00000000..348e6f14 --- /dev/null +++ b/tests/unit/mock/config/compliance/compliance/mikrotik_routeros/routeros_received.json @@ -0,0 +1,12 @@ +{ + "bgp": { + "actual": "set protocols bgp local-as 65252\nset protocols bgp group p2p export send-direct\nset protocols bgp group p2p neighbor 10.10.0.22 peer-as 65252\nset protocols bgp group p2p neighbor 10.10.0.26 peer-as 65252\nset protocols bgp group p2p neighbor 10.11.11.6 peer-as 65253", + "cannot_parse": true, + "compliant": true, + "extra": "", + "intended": "set protocols bgp local-as 65252\nset protocols bgp group p2p export send-direct\nset protocols bgp group p2p neighbor 10.10.0.22 peer-as 65252\nset protocols bgp group p2p neighbor 10.10.0.26 peer-as 65252\nset protocols bgp group p2p neighbor 10.11.11.6 peer-as 65253", + "missing": "", + "ordered_compliant": true, + "unordered_compliant": true + } +} diff --git a/tests/unit/mock/config/parser/base/mikrotik_routeros/routeros_full_received.py b/tests/unit/mock/config/parser/base/mikrotik_routeros/routeros_full_received.py new file mode 100644 index 00000000..faa60fe0 --- /dev/null +++ b/tests/unit/mock/config/parser/base/mikrotik_routeros/routeros_full_received.py @@ -0,0 +1,119 @@ +from netutils.config.parser import ConfigLine + +data = [ + ConfigLine(config_line="/interface bridge add name=google-vpc-peering-iface", parents=()), + ConfigLine(config_line="/interface bridge add name=loopback", parents=()), + ConfigLine(config_line="/interface bonding add mode=802.3ad name=Po1 slaves=sfp-sfpplus1,sfp-sfpplus2", parents=()), + ConfigLine(config_line="/interface vlan add interface=Po1 name=vlan11-mgmt vlan-id=11", parents=()), + ConfigLine( + config_line="/interface vlan add interface=vlan2933-Transit-to-CC-NNI name=vlan3049-Transit-to-XXX vlan-id=3049", + parents=(), + ), + ConfigLine( + config_line="/interface vlan add disabled=yes interface=Po1 name=vlan3051-Transit-to-CSW-through-QoE-Disabled vlan-id=3051", + parents=(), + ), + ConfigLine( + config_line="/interface vlan add interface=Po1 mtu=1300 name=vlan3225-Transit-CORE-Agg1-to-COREXXX vlan-id=3225", + parents=(), + ), + ConfigLine( + config_line="/interface wireless security-profiles set [ find default=yes ] supplicant-identity=MikroTik", + parents=(), + ), + ConfigLine( + config_line="/ip ipsec peer add address=50.157.100.38/32 exchange-mode=ike2 local-address=55.106.77.11 name=google-vpc-peer", + parents=(), + ), + ConfigLine(config_line="/ip pool add name=BNEdgeLiteTest ranges=192.168.69.254", parents=()), + ConfigLine(config_line="/ip pool add name=BNEdgeLiteTest2 ranges=192.168.70.254", parents=()), + ConfigLine( + config_line="/ip dhcp-server add address-pool=BNEdgeLiteTest disabled=no interface=ether1 name=dhcp1", + parents=(), + ), + ConfigLine( + config_line="/ip dhcp-server add address-pool=BNEdgeLiteTest2 disabled=no interface=ether2 name=dhcp2", + parents=(), + ), + ConfigLine(config_line="/routing bgp instance set default as=1234 router-id=10.127.1.3", parents=()), + ConfigLine(config_line="/routing ospf instance set [ find default=yes ] router-id=10.127.1.3", parents=()), + ConfigLine(config_line="/snmp community add addresses=::/0 name=somestringa", parents=()), + ConfigLine( + config_line="/system logging action set 3 bsd-syslog=yes remote=172.16.11.1 remote-port=5140", parents=() + ), + ConfigLine( + config_line="/user group set full policy=local,telnet,ssh,ftp,reboot,read,write,policy,test,winbox,password,web,sniff,sensitive,api,romon,dude,tikapp", + parents=(), + ), + ConfigLine( + config_line="/user group add name=prom policy=ssh,read,winbox,api,!local,!telnet,!ftp,!reboot,!write,!policy,!test,!password,!web,!sniff,!sensitive,!romon,!dude,!tikapp", + parents=(), + ), + ConfigLine(config_line="/ip neighbor discovery-settings set discover-interface-list=!dynamic", parents=()), + ConfigLine(config_line="/ip address add address=10.0.11.13/24 interface=vlan11-mgmt network=10.0.11.0", parents=()), + ConfigLine(config_line="/ip address add address=192.168.69.1/24 interface=ether1 network=192.168.69.0", parents=()), + ConfigLine(config_line="/ip dhcp-server network add address=192.168.69.0/24 gateway=192.168.69.1", parents=()), + ConfigLine(config_line="/ip dhcp-server network add address=192.168.70.0/24 gateway=192.168.70.1", parents=()), + ConfigLine(config_line="/ip dns set servers=8.8.8.8", parents=()), + ConfigLine(config_line="/ip firewall address-list add address=34.157.17.38 list=whitelist", parents=()), + ConfigLine(config_line="/ip firewall address-list add address=72.202.79.109 list=google-vpc-acl", parents=()), + ConfigLine(config_line="/ip firewall address-list add address=34.157.17.38 list=google-vpc-acl", parents=()), + ConfigLine( + config_line="/ip firewall filter add action=drop chain=input dst-address=50.106.77.11 src-address-list=!google-vpc-acl", + parents=(), + ), + ConfigLine( + config_line="/ip firewall nat add action=dst-nat chain=dstnat dst-address=50.106.77.11 dst-port=443 protocol=tcp to-addresses=10.1.15.10", + parents=(), + ), + ConfigLine( + config_line="/ip firewall nat add action=masquerade chain=srcnat out-interface=vlan12-Servers", parents=() + ), + ConfigLine( + config_line="/ip firewall nat add action=src-nat chain=srcnat src-address=50.64.0.75 to-addresses=55.106.77.11", + parents=(), + ), + ConfigLine(config_line="/ip ipsec identity add peer=google-vpc-peer secret=*****", parents=()), + ConfigLine(config_line="/ip ipsec policy set 0 disabled=yes", parents=()), + ConfigLine( + config_line="/ip ipsec policy add disabled=yes dst-address=169.254.1.1/32 peer=google-vpc-peer src-address=169.254.1.2/32 tunnel=yes", + parents=(), + ), + ConfigLine( + config_line="/ip ipsec policy add disabled=yes dst-address=10.150.0.0/20 peer=google-vpc-peer src-address=0.0.0.0/0 tunnel=yes", + parents=(), + ), + ConfigLine(config_line="/ip service set telnet disabled=yes", parents=()), + ConfigLine(config_line="/ip service set ftp disabled=yes", parents=()), + ConfigLine(config_line="/ip service set www disabled=yes", parents=()), + ConfigLine(config_line="/ip service set api address=10.1.15.5/32,10.120.16.0/20,172.16.11.0/24", parents=()), + ConfigLine(config_line="/ip service set api-ssl disabled=yes", parents=()), + ConfigLine(config_line="/routing bgp network add network=55.106.77.11/32 synchronize=no", parents=()), + ConfigLine(config_line="/routing bgp network add network=55.106.77.12/32 synchronize=no", parents=()), + ConfigLine( + config_line="/routing bgp peer add in-filter=ibgp-allow-default-in name=CSW out-filter=ibgp-no-default-out remote-address=10.127.1.10 remote-as=12345 update-source=loopback", + parents=(), + ), + ConfigLine( + config_line="/routing filter add action=discard chain=ibgp-no-default-out prefix=10.127.1.0/24", parents=() + ), + ConfigLine( + config_line="/routing filter add action=accept chain=ibgp-no-default-out prefix=10.64.0.0/10 prefix-length=22-32", + parents=(), + ), + ConfigLine( + config_line="/routing ospf interface add dead-interval=8s hello-interval=2s interface=vlan3049-Transit-to-85Presidential network-type=point-to-point", + parents=(), + ), + ConfigLine( + config_line="/routing ospf interface add cost=11 dead-interval=8s hello-interval=2s interface=vlan3166-Transit-HalseyCore-Agg1-to-Indigo-5 network-type=point-to-point", + parents=(), + ), + ConfigLine(config_line="/routing ospf network add area=backbone network=10.126.0.16/29", parents=()), + ConfigLine(config_line="/routing ospf network add area=backbone network=10.127.1.3/32", parents=()), + ConfigLine(config_line="/snmp set enabled=yes trap-community=somestring", parents=()), + ConfigLine(config_line="/system clock set time-zone-name=America/New_York", parents=()), + ConfigLine(config_line="/system identity set name=ag1.123site.nwk.nj", parents=()), + ConfigLine(config_line="/system logging add action=remote topics=error", parents=()), + ConfigLine(config_line="/system logging add action=remote topics=info", parents=()), +] diff --git a/tests/unit/mock/config/parser/base/mikrotik_routeros/routeros_full_sent.txt b/tests/unit/mock/config/parser/base/mikrotik_routeros/routeros_full_sent.txt new file mode 100644 index 00000000..2f17f6ec --- /dev/null +++ b/tests/unit/mock/config/parser/base/mikrotik_routeros/routeros_full_sent.txt @@ -0,0 +1,62 @@ +# by RouterOS 6.49.6 +# software id = WZ00-84LP +# +# model = CCR1036-8G-2S+ +# serial number = C6CD0BF7A020 +/interface bridge add name=google-vpc-peering-iface +/interface bridge add name=loopback +/interface bonding add mode=802.3ad name=Po1 slaves=sfp-sfpplus1,sfp-sfpplus2 +/interface vlan add interface=Po1 name=vlan11-mgmt vlan-id=11 +/interface vlan add interface=vlan2933-Transit-to-CC-NNI name=vlan3049-Transit-to-XXX vlan-id=3049 +/interface vlan add disabled=yes interface=Po1 name=vlan3051-Transit-to-CSW-through-QoE-Disabled vlan-id=3051 +/interface vlan add interface=Po1 mtu=1300 name=vlan3225-Transit-CORE-Agg1-to-COREXXX vlan-id=3225 +/interface wireless security-profiles set [ find default=yes ] supplicant-identity=MikroTik +/ip ipsec peer add address=50.157.100.38/32 exchange-mode=ike2 local-address=55.106.77.11 name=google-vpc-peer +/ip pool add name=BNEdgeLiteTest ranges=192.168.69.254 +/ip pool add name=BNEdgeLiteTest2 ranges=192.168.70.254 +/ip dhcp-server add address-pool=BNEdgeLiteTest disabled=no interface=ether1 name=dhcp1 +/ip dhcp-server add address-pool=BNEdgeLiteTest2 disabled=no interface=ether2 name=dhcp2 +/routing bgp instance set default as=1234 router-id=10.127.1.3 +/routing ospf instance set [ find default=yes ] router-id=10.127.1.3 +/snmp community add addresses=::/0 name=somestringa +/system logging action set 3 bsd-syslog=yes remote=172.16.11.1 remote-port=5140 +/user group set full policy=local,telnet,ssh,ftp,reboot,read,write,policy,test,winbox,password,web,sniff,sensitive,api,romon,dude,tikapp +/user group add name=prom policy=ssh,read,winbox,api,!local,!telnet,!ftp,!reboot,!write,!policy,!test,!password,!web,!sniff,!sensitive,!romon,!dude,!tikapp +#error exporting /interface bridge calea +/ip neighbor discovery-settings set discover-interface-list=!dynamic +/ip address add address=10.0.11.13/24 interface=vlan11-mgmt network=10.0.11.0 +/ip address add address=192.168.69.1/24 interface=ether1 network=192.168.69.0 +/ip dhcp-server network add address=192.168.69.0/24 gateway=192.168.69.1 +/ip dhcp-server network add address=192.168.70.0/24 gateway=192.168.70.1 +/ip dns set servers=8.8.8.8 +/ip firewall address-list add address=34.157.17.38 list=whitelist +/ip firewall address-list add address=72.202.79.109 list=google-vpc-acl +/ip firewall address-list add address=34.157.17.38 list=google-vpc-acl +#error exporting /ip firewall calea +/ip firewall filter add action=drop chain=input dst-address=50.106.77.11 src-address-list=!google-vpc-acl +/ip firewall nat add action=dst-nat chain=dstnat dst-address=50.106.77.11 dst-port=443 protocol=tcp to-addresses=10.1.15.10 +/ip firewall nat add action=masquerade chain=srcnat out-interface=vlan12-Servers +/ip firewall nat add action=src-nat chain=srcnat src-address=50.64.0.75 to-addresses=55.106.77.11 +/ip ipsec identity add peer=google-vpc-peer secret=***** +/ip ipsec policy set 0 disabled=yes +/ip ipsec policy add disabled=yes dst-address=169.254.1.1/32 peer=google-vpc-peer src-address=169.254.1.2/32 tunnel=yes +/ip ipsec policy add disabled=yes dst-address=10.150.0.0/20 peer=google-vpc-peer src-address=0.0.0.0/0 tunnel=yes +/ip service set telnet disabled=yes +/ip service set ftp disabled=yes +/ip service set www disabled=yes +/ip service set api address=10.1.15.5/32,10.120.16.0/20,172.16.11.0/24 +/ip service set api-ssl disabled=yes +/routing bgp network add network=55.106.77.11/32 synchronize=no +/routing bgp network add network=55.106.77.12/32 synchronize=no +/routing bgp peer add in-filter=ibgp-allow-default-in name=CSW out-filter=ibgp-no-default-out remote-address=10.127.1.10 remote-as=12345 update-source=loopback +/routing filter add action=discard chain=ibgp-no-default-out prefix=10.127.1.0/24 +/routing filter add action=accept chain=ibgp-no-default-out prefix=10.64.0.0/10 prefix-length=22-32 +/routing ospf interface add dead-interval=8s hello-interval=2s interface=vlan3049-Transit-to-85Presidential network-type=point-to-point +/routing ospf interface add cost=11 dead-interval=8s hello-interval=2s interface=vlan3166-Transit-HalseyCore-Agg1-to-Indigo-5 network-type=point-to-point +/routing ospf network add area=backbone network=10.126.0.16/29 +/routing ospf network add area=backbone network=10.127.1.3/32 +/snmp set enabled=yes trap-community=somestring +/system clock set time-zone-name=America/New_York +/system identity set name=ag1.123site.nwk.nj +/system logging add action=remote topics=error +/system logging add action=remote topics=info From ef6e109548c2ce9e3af289486348f4f21a0b5b7c Mon Sep 17 00:00:00 2001 From: h4ndzdatm0ld Date: Tue, 21 Mar 2023 23:00:44 +0000 Subject: [PATCH 2/6] Basic RouterOS Parser capabilities --- netutils/lib_mapper.py | 2 ++ .../mikrotik_routeros/routeros_backup.txt | 3 --- .../mikrotik_routeros/routeros_feature.py | 4 +++- .../mikrotik_routeros/routeros_intended.txt | 4 +--- .../mikrotik_routeros/routeros_received.json | 24 +++++++++++++++++-- 5 files changed, 28 insertions(+), 9 deletions(-) diff --git a/netutils/lib_mapper.py b/netutils/lib_mapper.py index 5fd9310f..2f18c996 100644 --- a/netutils/lib_mapper.py +++ b/netutils/lib_mapper.py @@ -140,6 +140,7 @@ "sros": "nokia_sros", "vyos": "brocade_vyos", "aoscx": "aruba_aoscx", + "ros": "mikrotik_routeros", } PYNTC_LIB_MAPPER = { @@ -216,6 +217,7 @@ "paloalto_panos": "panos", "nokia_sros": "sros", "aruba_aoscx": "aoscx", + "mikrotik_routeros": "ros", } PYNTC_LIB_MAPPER_REVERSE = { diff --git a/tests/unit/mock/config/compliance/compliance/mikrotik_routeros/routeros_backup.txt b/tests/unit/mock/config/compliance/compliance/mikrotik_routeros/routeros_backup.txt index 2f17f6ec..d32a05c7 100644 --- a/tests/unit/mock/config/compliance/compliance/mikrotik_routeros/routeros_backup.txt +++ b/tests/unit/mock/config/compliance/compliance/mikrotik_routeros/routeros_backup.txt @@ -22,7 +22,6 @@ /system logging action set 3 bsd-syslog=yes remote=172.16.11.1 remote-port=5140 /user group set full policy=local,telnet,ssh,ftp,reboot,read,write,policy,test,winbox,password,web,sniff,sensitive,api,romon,dude,tikapp /user group add name=prom policy=ssh,read,winbox,api,!local,!telnet,!ftp,!reboot,!write,!policy,!test,!password,!web,!sniff,!sensitive,!romon,!dude,!tikapp -#error exporting /interface bridge calea /ip neighbor discovery-settings set discover-interface-list=!dynamic /ip address add address=10.0.11.13/24 interface=vlan11-mgmt network=10.0.11.0 /ip address add address=192.168.69.1/24 interface=ether1 network=192.168.69.0 @@ -32,7 +31,6 @@ /ip firewall address-list add address=34.157.17.38 list=whitelist /ip firewall address-list add address=72.202.79.109 list=google-vpc-acl /ip firewall address-list add address=34.157.17.38 list=google-vpc-acl -#error exporting /ip firewall calea /ip firewall filter add action=drop chain=input dst-address=50.106.77.11 src-address-list=!google-vpc-acl /ip firewall nat add action=dst-nat chain=dstnat dst-address=50.106.77.11 dst-port=443 protocol=tcp to-addresses=10.1.15.10 /ip firewall nat add action=masquerade chain=srcnat out-interface=vlan12-Servers @@ -54,7 +52,6 @@ /routing ospf interface add dead-interval=8s hello-interval=2s interface=vlan3049-Transit-to-85Presidential network-type=point-to-point /routing ospf interface add cost=11 dead-interval=8s hello-interval=2s interface=vlan3166-Transit-HalseyCore-Agg1-to-Indigo-5 network-type=point-to-point /routing ospf network add area=backbone network=10.126.0.16/29 -/routing ospf network add area=backbone network=10.127.1.3/32 /snmp set enabled=yes trap-community=somestring /system clock set time-zone-name=America/New_York /system identity set name=ag1.123site.nwk.nj diff --git a/tests/unit/mock/config/compliance/compliance/mikrotik_routeros/routeros_feature.py b/tests/unit/mock/config/compliance/compliance/mikrotik_routeros/routeros_feature.py index 3556f809..531f8a6e 100644 --- a/tests/unit/mock/config/compliance/compliance/mikrotik_routeros/routeros_feature.py +++ b/tests/unit/mock/config/compliance/compliance/mikrotik_routeros/routeros_feature.py @@ -1,3 +1,5 @@ features = [ - {"name": "bgp", "ordered": True, "section": ["routing bgp"]}, + {"name": "bgp", "ordered": True, "section": ["/routing bgp instance"]}, + {"name": "snmp", "ordered": True, "section": ["/snmp"]}, + {"name": "ospf-networks", "ordered": True, "section": ["/routing ospf network"]}, ] diff --git a/tests/unit/mock/config/compliance/compliance/mikrotik_routeros/routeros_intended.txt b/tests/unit/mock/config/compliance/compliance/mikrotik_routeros/routeros_intended.txt index 2f17f6ec..c296173b 100644 --- a/tests/unit/mock/config/compliance/compliance/mikrotik_routeros/routeros_intended.txt +++ b/tests/unit/mock/config/compliance/compliance/mikrotik_routeros/routeros_intended.txt @@ -22,7 +22,6 @@ /system logging action set 3 bsd-syslog=yes remote=172.16.11.1 remote-port=5140 /user group set full policy=local,telnet,ssh,ftp,reboot,read,write,policy,test,winbox,password,web,sniff,sensitive,api,romon,dude,tikapp /user group add name=prom policy=ssh,read,winbox,api,!local,!telnet,!ftp,!reboot,!write,!policy,!test,!password,!web,!sniff,!sensitive,!romon,!dude,!tikapp -#error exporting /interface bridge calea /ip neighbor discovery-settings set discover-interface-list=!dynamic /ip address add address=10.0.11.13/24 interface=vlan11-mgmt network=10.0.11.0 /ip address add address=192.168.69.1/24 interface=ether1 network=192.168.69.0 @@ -32,7 +31,6 @@ /ip firewall address-list add address=34.157.17.38 list=whitelist /ip firewall address-list add address=72.202.79.109 list=google-vpc-acl /ip firewall address-list add address=34.157.17.38 list=google-vpc-acl -#error exporting /ip firewall calea /ip firewall filter add action=drop chain=input dst-address=50.106.77.11 src-address-list=!google-vpc-acl /ip firewall nat add action=dst-nat chain=dstnat dst-address=50.106.77.11 dst-port=443 protocol=tcp to-addresses=10.1.15.10 /ip firewall nat add action=masquerade chain=srcnat out-interface=vlan12-Servers @@ -52,7 +50,7 @@ /routing filter add action=discard chain=ibgp-no-default-out prefix=10.127.1.0/24 /routing filter add action=accept chain=ibgp-no-default-out prefix=10.64.0.0/10 prefix-length=22-32 /routing ospf interface add dead-interval=8s hello-interval=2s interface=vlan3049-Transit-to-85Presidential network-type=point-to-point -/routing ospf interface add cost=11 dead-interval=8s hello-interval=2s interface=vlan3166-Transit-HalseyCore-Agg1-to-Indigo-5 network-type=point-to-point +/routing ospf interface add cost=11 dead-interval=8s hello-interval=2s interface=vlan3166-Transit-Core-Agg1-to-SiteXYZ network-type=point-to-point /routing ospf network add area=backbone network=10.126.0.16/29 /routing ospf network add area=backbone network=10.127.1.3/32 /snmp set enabled=yes trap-community=somestring diff --git a/tests/unit/mock/config/compliance/compliance/mikrotik_routeros/routeros_received.json b/tests/unit/mock/config/compliance/compliance/mikrotik_routeros/routeros_received.json index 348e6f14..2d974195 100644 --- a/tests/unit/mock/config/compliance/compliance/mikrotik_routeros/routeros_received.json +++ b/tests/unit/mock/config/compliance/compliance/mikrotik_routeros/routeros_received.json @@ -1,12 +1,32 @@ { "bgp": { - "actual": "set protocols bgp local-as 65252\nset protocols bgp group p2p export send-direct\nset protocols bgp group p2p neighbor 10.10.0.22 peer-as 65252\nset protocols bgp group p2p neighbor 10.10.0.26 peer-as 65252\nset protocols bgp group p2p neighbor 10.11.11.6 peer-as 65253", + "actual": "/routing bgp instance set default as=1234 router-id=10.127.1.3", "cannot_parse": true, "compliant": true, "extra": "", - "intended": "set protocols bgp local-as 65252\nset protocols bgp group p2p export send-direct\nset protocols bgp group p2p neighbor 10.10.0.22 peer-as 65252\nset protocols bgp group p2p neighbor 10.10.0.26 peer-as 65252\nset protocols bgp group p2p neighbor 10.11.11.6 peer-as 65253", + "intended": "/routing bgp instance set default as=1234 router-id=10.127.1.3", "missing": "", "ordered_compliant": true, "unordered_compliant": true + }, + "snmp": { + "actual": "/snmp community add addresses=::/0 name=somestringa\n/snmp set enabled=yes trap-community=somestring", + "cannot_parse": true, + "compliant": true, + "extra": "", + "intended": "/snmp community add addresses=::/0 name=somestringa\n/snmp set enabled=yes trap-community=somestring", + "missing": "", + "ordered_compliant": true, + "unordered_compliant": true + }, + "ospf-networks": { + "actual": "/routing ospf network add area=backbone network=10.126.0.16/29", + "cannot_parse": true, + "compliant": false, + "extra": "", + "intended": "/routing ospf network add area=backbone network=10.126.0.16/29\n/routing ospf network add area=backbone network=10.127.1.3/32", + "missing": "/routing ospf network add area=backbone network=10.127.1.3/32", + "ordered_compliant": false, + "unordered_compliant": false } } From 319ff2bcffe6b3c2fd7f41930b19d3822c77c51b Mon Sep 17 00:00:00 2001 From: h4ndzdatm0ld Date: Tue, 21 Mar 2023 23:32:21 +0000 Subject: [PATCH 3/6] Mappers --- docs/user/lib_mapper/napalm.md | 1 + docs/user/lib_mapper/napalm_reverse.md | 1 + .../mikrotik_routeros/routeros_feature.py | 6 ++++++ .../mikrotik_routeros/routeros_received.json | 5 +++++ .../mikrotik_routeros/routeros_sent.txt | 10 ++++++++++ 5 files changed, 23 insertions(+) create mode 100644 tests/unit/mock/config/compliance/config_section_not_parsed/mikrotik_routeros/routeros_feature.py create mode 100644 tests/unit/mock/config/compliance/config_section_not_parsed/mikrotik_routeros/routeros_received.json create mode 100644 tests/unit/mock/config/compliance/config_section_not_parsed/mikrotik_routeros/routeros_sent.txt diff --git a/docs/user/lib_mapper/napalm.md b/docs/user/lib_mapper/napalm.md index 2e2a792f..4216e4c0 100644 --- a/docs/user/lib_mapper/napalm.md +++ b/docs/user/lib_mapper/napalm.md @@ -12,5 +12,6 @@ | nxos | → | cisco_nxos | | nxos_ssh | → | cisco_nxos | | panos | → | paloalto_panos | +| ros | → | mikrotik_routeros | | sros | → | nokia_sros | | vyos | → | brocade_vyos | \ No newline at end of file diff --git a/docs/user/lib_mapper/napalm_reverse.md b/docs/user/lib_mapper/napalm_reverse.md index 0cb9f5af..a4b7b8b3 100644 --- a/docs/user/lib_mapper/napalm_reverse.md +++ b/docs/user/lib_mapper/napalm_reverse.md @@ -11,5 +11,6 @@ | fortinet | → | fortios | | huawei_vrp | → | huawei | | juniper_junos | → | junos | +| mikrotik_routeros | → | ros | | nokia_sros | → | sros | | paloalto_panos | → | panos | \ No newline at end of file diff --git a/tests/unit/mock/config/compliance/config_section_not_parsed/mikrotik_routeros/routeros_feature.py b/tests/unit/mock/config/compliance/config_section_not_parsed/mikrotik_routeros/routeros_feature.py new file mode 100644 index 00000000..df05b7a3 --- /dev/null +++ b/tests/unit/mock/config/compliance/config_section_not_parsed/mikrotik_routeros/routeros_feature.py @@ -0,0 +1,6 @@ +features = [ + {"name": "routing-filter", "ordered": True, "section": ["/routing filter"]}, + {"name": "ospf", "ordered": True, "section": ["/routing ospf"]}, + {"name": "snmp", "ordered": True, "section": ["/snmp"]}, + {"name": "ip-firewall", "ordered": True, "section": ["/ip firewall"]}, +] diff --git a/tests/unit/mock/config/compliance/config_section_not_parsed/mikrotik_routeros/routeros_received.json b/tests/unit/mock/config/compliance/config_section_not_parsed/mikrotik_routeros/routeros_received.json new file mode 100644 index 00000000..1f56386b --- /dev/null +++ b/tests/unit/mock/config/compliance/config_section_not_parsed/mikrotik_routeros/routeros_received.json @@ -0,0 +1,5 @@ +{ + "remaining_cfg": "/system clock set time-zone-name=America/New_York\n/system identity set name=ag1.123site.nwk.nj\n/system logging add action=remote topics=error\n/system logging add action=remote topics=info", + + "section_not_found": ["ip-firewall"] +} diff --git a/tests/unit/mock/config/compliance/config_section_not_parsed/mikrotik_routeros/routeros_sent.txt b/tests/unit/mock/config/compliance/config_section_not_parsed/mikrotik_routeros/routeros_sent.txt new file mode 100644 index 00000000..47f233fc --- /dev/null +++ b/tests/unit/mock/config/compliance/config_section_not_parsed/mikrotik_routeros/routeros_sent.txt @@ -0,0 +1,10 @@ +/routing filter add action=discard chain=ibgp-no-default-out prefix=10.127.1.0/24 +/routing filter add action=accept chain=ibgp-no-default-out prefix=10.64.0.0/10 prefix-length=22-32 +/routing ospf interface add dead-interval=8s hello-interval=2s interface=vlan3049-Transit-to-85Presidential network-type=point-to-point +/routing ospf interface add cost=11 dead-interval=8s hello-interval=2s interface=vlan3166-Transit-HalseyCore-Agg1-to-Indigo-5 network-type=point-to-point +/routing ospf network add area=backbone network=10.126.0.16/29 +/snmp set enabled=yes trap-community=somestring +/system clock set time-zone-name=America/New_York +/system identity set name=ag1.123site.nwk.nj +/system logging add action=remote topics=error +/system logging add action=remote topics=info \ No newline at end of file From 14ccd4d8fc844b3b17eff0c4ff969926ac1c3825 Mon Sep 17 00:00:00 2001 From: h4ndzdatm0ld Date: Sat, 1 Apr 2023 21:23:24 +0000 Subject: [PATCH 4/6] feedback: Parsing tests for system note --- .../routeros_full_received.py | 32 +++++++++++++++++++ .../mikrotik_routeros/routeros_full_sent.txt | 8 +++++ 2 files changed, 40 insertions(+) diff --git a/tests/unit/mock/config/parser/base/mikrotik_routeros/routeros_full_received.py b/tests/unit/mock/config/parser/base/mikrotik_routeros/routeros_full_received.py index faa60fe0..82e8fd04 100644 --- a/tests/unit/mock/config/parser/base/mikrotik_routeros/routeros_full_received.py +++ b/tests/unit/mock/config/parser/base/mikrotik_routeros/routeros_full_received.py @@ -116,4 +116,36 @@ ConfigLine(config_line="/system identity set name=ag1.123site.nwk.nj", parents=()), ConfigLine(config_line="/system logging add action=remote topics=error", parents=()), ConfigLine(config_line="/system logging add action=remote topics=info", parents=()), + ConfigLine( + config_line='/system note set note="This is a \\\\\\"System Note\\\\\\" for a Mikrotik router.\\\\n\\\\\\', + parents=(), + ), + ConfigLine( + config_line=' \\nIt includes double quotes (\\\\\\") and special characters such as:\\\\n\\\\\\', + parents=('/system note set note="This is a \\\\\\"System Note\\\\\\" for a Mikrotik router.\\\\n\\\\\\',), + ), + ConfigLine( + config_line=" \\n@, #, \\$, %, ^, &, *, (, ), _, +, [, ], {, }, |, ;, ',', ., /, <, >, and \\?.\\\\n\\\\\\", + parents=('/system note set note="This is a \\\\\\"System Note\\\\\\" for a Mikrotik router.\\\\n\\\\\\',), + ), + ConfigLine( + config_line=" \\n\\\\n\\\\\\", + parents=('/system note set note="This is a \\\\\\"System Note\\\\\\" for a Mikrotik router.\\\\n\\\\\\',), + ), + ConfigLine( + config_line=" \\nRemember to escape any special characters with a backslash (\\\\\\\\) when necessary.\\\\n\\\\\\", + parents=('/system note set note="This is a \\\\\\"System Note\\\\\\" for a Mikrotik router.\\\\n\\\\\\',), + ), + ConfigLine( + config_line=" \\n\\\\n\\\\\\", + parents=('/system note set note="This is a \\\\\\"System Note\\\\\\" for a Mikrotik router.\\\\n\\\\\\',), + ), + ConfigLine( + config_line=" \\nThis is a multiline note with several lines of text.\\\\n\\\\\\", + parents=('/system note set note="This is a \\\\\\"System Note\\\\\\" for a Mikrotik router.\\\\n\\\\\\',), + ), + ConfigLine( + config_line=' \\nWow, what a great example of a note to ensure proper parsing by NetUtils!"', + parents=('/system note set note="This is a \\\\\\"System Note\\\\\\" for a Mikrotik router.\\\\n\\\\\\',), + ), ] diff --git a/tests/unit/mock/config/parser/base/mikrotik_routeros/routeros_full_sent.txt b/tests/unit/mock/config/parser/base/mikrotik_routeros/routeros_full_sent.txt index 2f17f6ec..e2c9703f 100644 --- a/tests/unit/mock/config/parser/base/mikrotik_routeros/routeros_full_sent.txt +++ b/tests/unit/mock/config/parser/base/mikrotik_routeros/routeros_full_sent.txt @@ -60,3 +60,11 @@ /system identity set name=ag1.123site.nwk.nj /system logging add action=remote topics=error /system logging add action=remote topics=info +/system note set note="This is a \\\"System Note\\\" for a Mikrotik router.\\n\\\ + \nIt includes double quotes (\\\") and special characters such as:\\n\\\ + \n@, #, \$, %, ^, &, *, (, ), _, +, [, ], {, }, |, ;, ',', ., /, <, >, and \?.\\n\\\ + \n\\n\\\ + \nRemember to escape any special characters with a backslash (\\\\) when necessary.\\n\\\ + \n\\n\\\ + \nThis is a multiline note with several lines of text.\\n\\\ + \nWow, what a great example of a note to ensure proper parsing by NetUtils!" \ No newline at end of file From f28525a58e42c9bf8ebba96735b5ac172b7a22e9 Mon Sep 17 00:00:00 2001 From: h4ndzdatm0ld Date: Fri, 14 Apr 2023 05:32:10 +0000 Subject: [PATCH 5/6] if it looks like a duck, banners like a banner, then.. --- netutils/config/parser.py | 37 ++++++++++++++++--- .../routeros_full_received.py | 30 +-------------- .../mikrotik_routeros/routeros_full_sent.txt | 3 +- 3 files changed, 35 insertions(+), 35 deletions(-) diff --git a/netutils/config/parser.py b/netutils/config/parser.py index 6a93f7f1..c9891816 100644 --- a/netutils/config/parser.py +++ b/netutils/config/parser.py @@ -1381,9 +1381,36 @@ class RouterOSConfigParser(BaseSpaceConfigParser): """Mikrotik RouterOS config parser.""" comment_chars: t.List[str] = ["#"] - banner_start: t.List[str] = [] + banner_start: t.List[str] = ["/system note set note=", "set note="] - @property - def banner_end(self) -> str: - """Demarcate End of Banner char(s).""" - raise NotImplementedError("RouterOS platform doesn't have a banner.") + def is_banner_end(self, line: str) -> bool: + """Determine if end of banner.""" + if line.endswith('"') or line.startswith("/"): + return True + return False + + def _build_banner(self, config_line: str) -> t.Optional[str]: + """Handle banner config lines. + + Args: + config_line: The start of the banner (system note) config. + + Returns: + The next configuration line in the configuration text or None when banner end is the end of the config text. + + Raises: + ValueError: When the parser is unable to identify the End of the Banner. + """ + banner_config = [config_line] + for line in self.generator_config: + if not self.is_banner_end(line): + banner_config.append(line) + else: + banner_config.append(line) + line = "\n".join(banner_config) + self._update_config_lines(line) + try: + return next(self.generator_config) + except StopIteration: + return None + raise ValueError("Unable to parse banner (system note) end.") diff --git a/tests/unit/mock/config/parser/base/mikrotik_routeros/routeros_full_received.py b/tests/unit/mock/config/parser/base/mikrotik_routeros/routeros_full_received.py index 82e8fd04..fd06c50f 100644 --- a/tests/unit/mock/config/parser/base/mikrotik_routeros/routeros_full_received.py +++ b/tests/unit/mock/config/parser/base/mikrotik_routeros/routeros_full_received.py @@ -117,35 +117,7 @@ ConfigLine(config_line="/system logging add action=remote topics=error", parents=()), ConfigLine(config_line="/system logging add action=remote topics=info", parents=()), ConfigLine( - config_line='/system note set note="This is a \\\\\\"System Note\\\\\\" for a Mikrotik router.\\\\n\\\\\\', + config_line='/system note set note="This is a \\\\\\"System Note\\\\\\" for a Mikrotik router.\\\\n\\\\\\\n \\nIt includes double quotes (\\\\\\") and special characters such as:\\\\n\\\\\\\n \\n@, #, \\$, %, ^, &, *, (, ), _, +, [, ], {, }, |, ;, \',\', ., /, <, >, and \\?.\\\\n\\\\\\\n \\n\\\\n\\\\\\\n \\nRemember to escape any special characters with a backslash (\\\\\\\\) when necessary.\\\\n\\\\\\\n \\n\\\\n\\\\\\\n \\nThis is a multiline note with several lines of text.\\\\n\\\\\\\n \\nWow, what a great example of a note to ensure proper parsing by NetUtils!\n \\nWe are treating this as a banner."', parents=(), ), - ConfigLine( - config_line=' \\nIt includes double quotes (\\\\\\") and special characters such as:\\\\n\\\\\\', - parents=('/system note set note="This is a \\\\\\"System Note\\\\\\" for a Mikrotik router.\\\\n\\\\\\',), - ), - ConfigLine( - config_line=" \\n@, #, \\$, %, ^, &, *, (, ), _, +, [, ], {, }, |, ;, ',', ., /, <, >, and \\?.\\\\n\\\\\\", - parents=('/system note set note="This is a \\\\\\"System Note\\\\\\" for a Mikrotik router.\\\\n\\\\\\',), - ), - ConfigLine( - config_line=" \\n\\\\n\\\\\\", - parents=('/system note set note="This is a \\\\\\"System Note\\\\\\" for a Mikrotik router.\\\\n\\\\\\',), - ), - ConfigLine( - config_line=" \\nRemember to escape any special characters with a backslash (\\\\\\\\) when necessary.\\\\n\\\\\\", - parents=('/system note set note="This is a \\\\\\"System Note\\\\\\" for a Mikrotik router.\\\\n\\\\\\',), - ), - ConfigLine( - config_line=" \\n\\\\n\\\\\\", - parents=('/system note set note="This is a \\\\\\"System Note\\\\\\" for a Mikrotik router.\\\\n\\\\\\',), - ), - ConfigLine( - config_line=" \\nThis is a multiline note with several lines of text.\\\\n\\\\\\", - parents=('/system note set note="This is a \\\\\\"System Note\\\\\\" for a Mikrotik router.\\\\n\\\\\\',), - ), - ConfigLine( - config_line=' \\nWow, what a great example of a note to ensure proper parsing by NetUtils!"', - parents=('/system note set note="This is a \\\\\\"System Note\\\\\\" for a Mikrotik router.\\\\n\\\\\\',), - ), ] diff --git a/tests/unit/mock/config/parser/base/mikrotik_routeros/routeros_full_sent.txt b/tests/unit/mock/config/parser/base/mikrotik_routeros/routeros_full_sent.txt index e2c9703f..89f8d6fa 100644 --- a/tests/unit/mock/config/parser/base/mikrotik_routeros/routeros_full_sent.txt +++ b/tests/unit/mock/config/parser/base/mikrotik_routeros/routeros_full_sent.txt @@ -67,4 +67,5 @@ \nRemember to escape any special characters with a backslash (\\\\) when necessary.\\n\\\ \n\\n\\\ \nThis is a multiline note with several lines of text.\\n\\\ - \nWow, what a great example of a note to ensure proper parsing by NetUtils!" \ No newline at end of file + \nWow, what a great example of a note to ensure proper parsing by NetUtils! + \nWe are treating this as a banner." \ No newline at end of file From 4f0ac6f7d14e8395db74b1183d1c66c0024a53b0 Mon Sep 17 00:00:00 2001 From: h4ndzdatm0ld Date: Fri, 14 Apr 2023 05:58:35 +0000 Subject: [PATCH 6/6] banner_end satisfied, but rely on is_banner_end --- netutils/config/parser.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/netutils/config/parser.py b/netutils/config/parser.py index c9891816..c28515a2 100644 --- a/netutils/config/parser.py +++ b/netutils/config/parser.py @@ -1383,6 +1383,11 @@ class RouterOSConfigParser(BaseSpaceConfigParser): comment_chars: t.List[str] = ["#"] banner_start: t.List[str] = ["/system note set note=", "set note="] + @property + def banner_end(self) -> str: + """Demarcate End of Banner char(s).""" + raise NotImplementedError("Mikrotik platform uses system note as a banner.") + def is_banner_end(self, line: str) -> bool: """Determine if end of banner.""" if line.endswith('"') or line.startswith("/"):