libs.tools.resolve_identifier(): add option to filter out linklocal ips and only physical interfaces

This commit is contained in:
Franzi 2023-09-09 15:37:37 +02:00
parent 6539923644
commit 2b51812118
Signed by: kunsi
GPG key ID: 12E3D2136B818350
3 changed files with 19 additions and 27 deletions

View file

@ -78,7 +78,7 @@ def port_rules_to_nftables(metadata):
if target in ('*', 'ipv4', 'ipv6'): if target in ('*', 'ipv4', 'ipv6'):
ruleset.add(f'inet filter input {version_str} {port_str} accept {comment}') ruleset.add(f'inet filter input {version_str} {port_str} accept {comment}')
else: else:
resolved = repo.libs.tools.resolve_identifier(repo, target) resolved = repo.libs.tools.resolve_identifier(repo, target, linklocal=True)
for address in resolved['ipv4']: for address in resolved['ipv4']:
ruleset.add(f'inet filter input meta nfproto ipv4 {port_str} ip saddr {address} accept {comment}') ruleset.add(f'inet filter input meta nfproto ipv4 {port_str} ip saddr {address} accept {comment}')

View file

@ -134,7 +134,7 @@ def generate_dns_entries_for_nodes(metadata):
ip4 = None ip4 = None
ip6 = None ip6 = None
found_ips = repo.libs.tools.resolve_identifier(repo, rnode.name) found_ips = repo.libs.tools.resolve_identifier(repo, rnode.name, only_physical=True)
for ip in sorted(found_ips['ipv4']): for ip in sorted(found_ips['ipv4']):
if not ip4 and not ip.is_private: if not ip4 and not ip.is_private:
ip4 = ip ip4 = ip
@ -144,30 +144,10 @@ def generate_dns_entries_for_nodes(metadata):
ip6 = ip ip6 = ip
if not ip4 and found_ips['ipv4']: if not ip4 and found_ips['ipv4']:
# This node apparently does not have a public IPv4 address. # do it again, but do not filter out private addresses
# We now manually iterate over that nodes interfaces to get for ip in sorted(found_ips['ipv4']):
# a IPv4 address which is tied to a physical interface. if not ip4:
# Note we can't use resolve_identifier() here, because we ip4 = ip
# only want physical interfaces.
for interface, config in rnode.metadata.get('interfaces', {}).items():
if not (
interface.startswith('bond') or
interface.startswith('br') or
interface.startswith('eno') or
interface.startswith('enp') or
interface.startswith('eth') or
interface == 'default' # dummy nodes use these
):
continue
for ip in sorted(config.get('ips', set())):
if '/' in ip:
addr = ip_address(ip.split('/')[0])
else:
addr = ip_address(ip)
if not ip4 and isinstance(addr, IPv4Address):
ip4 = addr
if ip4: if ip4:
results.add('{} IN A {}'.format(dns_name, ip4)) results.add('{} IN A {}'.format(dns_name, ip4))

View file

@ -5,7 +5,7 @@ from bundlewrap.utils.text import bold, red
from bundlewrap.utils.ui import io from bundlewrap.utils.ui import io
def resolve_identifier(repo, identifier): def resolve_identifier(repo, identifier, linklocal=False, only_physical=False):
""" """
Try to resolve an identifier (group or node). Return a set of ip Try to resolve an identifier (group or node). Return a set of ip
addresses valid for this identifier. addresses valid for this identifier.
@ -34,6 +34,15 @@ def resolve_identifier(repo, identifier):
found_ips = set() found_ips = set()
for node in nodes: for node in nodes:
for interface, config in node.metadata.get('interfaces', {}).items(): for interface, config in node.metadata.get('interfaces', {}).items():
if only_physical and not (
interface.startswith('bond') or
interface.startswith('br') or
interface.startswith('en') or
interface.startswith('et') or
interface == 'default' # dummy nodes use these
):
continue
for ip in config.get('ips', set()): for ip in config.get('ips', set()):
if '/' in ip: if '/' in ip:
found_ips.add(ip_address(ip.split('/')[0])) found_ips.add(ip_address(ip.split('/')[0]))
@ -54,6 +63,9 @@ def resolve_identifier(repo, identifier):
} }
for ip in found_ips: for ip in found_ips:
if ip.is_link_local and not linklocal:
continue
if isinstance(ip, IPv4Address): if isinstance(ip, IPv4Address):
ip_dict['ipv4'].add(ip) ip_dict['ipv4'].add(ip)
else: else: