Browse Source

Merge pull request #1094 from Solvik/filter-net

add NetworkValueRejectlistFilter and NetworkValueAllowlistFilter processors
pull/1101/head
Ross McFarland 2 years ago
committed by GitHub
parent
commit
965015c481
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 154 additions and 0 deletions
  1. +5
    -0
      CHANGELOG.md
  2. +87
    -0
      octodns/processor/filter.py
  3. +62
    -0
      tests/test_octodns_processor_filter.py

+ 5
- 0
CHANGELOG.md View File

@ -13,6 +13,11 @@
* Added ZoneNameFilter processor to enable ignoring/alerting on type-os like
octodns.com.octodns.com
* NetworkValueAllowlistFilter/NetworkValueRejectlistFilter added to
processors.filter to enable filtering A/AAAA records based on value. Can be
useful if you have records with non-routable values in an internal copy of a
zone, but want to exclude them when pushing the same zone publically (split
horizon)
* ExcludeRootNsChanges processor that will error (or warn) if plan includes a
change to root NS records
* Include the octodns special section info in Record __repr__, makes it easier


+ 87
- 0
octodns/processor/filter.py View File

@ -2,6 +2,8 @@
#
#
from ipaddress import ip_address, ip_network
from itertools import product
from logging import getLogger
from re import compile as re_compile
@ -189,6 +191,91 @@ class NameRejectlistFilter(_NameBaseFilter, RejectsMixin):
super().__init__(name, rejectlist)
class _NetworkValueBaseFilter(BaseProcessor):
def __init__(self, name, _list):
super().__init__(name)
self.networks = []
for value in _list:
try:
self.networks.append(ip_network(value))
except ValueError:
raise ValueError(f'{value} is not a valid CIDR to use')
def _process(self, zone, *args, **kwargs):
for record in zone.records:
if record._type not in ['A', 'AAAA']:
continue
ips = [ip_address(value) for value in record.values]
if any(
ip in network for ip, network in product(ips, self.networks)
):
self.matches(zone, record)
else:
self.doesnt_match(zone, record)
return zone
process_source_zone = _process
process_target_zone = _process
class NetworkValueAllowlistFilter(_NetworkValueBaseFilter, AllowsMixin):
'''Only manage A and AAAA records with values that match the provider patterns
All other types will be left as-is.
Example usage:
processors:
only-these:
class: octodns.processor.filter.NetworkValueAllowlistFilter
allowlist:
- 127.0.0.1/32
- 192.168.0.0/16
- fd00::/8
zones:
exxampled.com.:
sources:
- config
processors:
- only-these
targets:
- route53
'''
def __init__(self, name, allowlist):
super().__init__(name, allowlist)
class NetworkValueRejectlistFilter(_NetworkValueBaseFilter, RejectsMixin):
'''Reject managing A and AAAA records with value matching a that match the provider patterns
All other types will be left as-is.
Example usage:
processors:
not-these:
class: octodns.processor.filter.NetworkValueRejectlistFilter
rejectlist:
- 127.0.0.1/32
- 192.168.0.0/16
- fd00::/8
zones:
exxampled.com.:
sources:
- config
processors:
- not-these
targets:
- route53
'''
def __init__(self, name, rejectlist):
super().__init__(name, rejectlist)
class IgnoreRootNsFilter(BaseProcessor):
'''Do not manage Root NS Records.


+ 62
- 0
tests/test_octodns_processor_filter.py View File

@ -9,6 +9,8 @@ from octodns.processor.filter import (
IgnoreRootNsFilter,
NameAllowlistFilter,
NameRejectlistFilter,
NetworkValueAllowlistFilter,
NetworkValueRejectlistFilter,
TypeAllowlistFilter,
TypeRejectlistFilter,
ZoneNameFilter,
@ -161,6 +163,66 @@ class TestNameRejectListFilter(TestCase):
)
class TestNetworkValueFilter(TestCase):
zone = Zone('unit.tests.', [])
for record in [
Record.new(
zone,
'private-ipv4',
{'type': 'A', 'ttl': 42, 'value': '10.42.42.42'},
),
Record.new(
zone,
'public-ipv4',
{'type': 'A', 'ttl': 42, 'value': '42.42.42.42'},
),
Record.new(
zone,
'private-ipv6',
{'type': 'AAAA', 'ttl': 42, 'value': 'fd12:3456:789a:1::1'},
),
Record.new(
zone,
'public-ipv6',
{'type': 'AAAA', 'ttl': 42, 'value': 'dead:beef:cafe::1'},
),
Record.new(
zone,
'keep-me',
{'ttl': 30, 'type': 'TXT', 'value': 'this should always be here'},
),
]:
zone.add_record(record)
def test_bad_config(self):
with self.assertRaises(ValueError):
NetworkValueRejectlistFilter(
'rejectlist', set(('string', '42.42.42.42/43'))
)
def test_reject(self):
filter_private = NetworkValueRejectlistFilter(
'rejectlist', set(('10.0.0.0/8', 'fd00::/8'))
)
got = filter_private.process_source_zone(self.zone.copy())
self.assertEqual(
['keep-me', 'public-ipv4', 'public-ipv6'],
sorted([r.name for r in got.records]),
)
def test_allow(self):
filter_private = NetworkValueAllowlistFilter(
'allowlist', set(('10.0.0.0/8', 'fd00::/8'))
)
got = filter_private.process_source_zone(self.zone.copy())
self.assertEqual(
['keep-me', 'private-ipv4', 'private-ipv6'],
sorted([r.name for r in got.records]),
)
class TestIgnoreRootNsFilter(TestCase):
zone = Zone('unit.tests.', [])
root = Record.new(


Loading…
Cancel
Save