mirror of
https://github.com/ansible-collections/community.general.git
synced 2024-09-14 20:13:21 +02:00
Sanitize IPv6 hostname/port handling
Now we accept IPv6 addresses _with port numbers_ only in the standard [xxx]:NN notation (though bare IPv6 addresses may be given, as before, and non-IPv6 addresses may also be placed in square brackets), and any other host identifiers (IPv4/hostname/host pattern) as before, with an optional :NN suffix.
This commit is contained in:
parent
74aab6f726
commit
745ecd4845
1 changed files with 38 additions and 35 deletions
|
@ -250,43 +250,36 @@ class InventoryParser(object):
|
||||||
|
|
||||||
return hosts
|
return hosts
|
||||||
|
|
||||||
def _expand_hostpattern(self, pattern):
|
def _expand_hostpattern(self, hostpattern):
|
||||||
'''
|
'''
|
||||||
Takes a single host pattern and returns a list of hostnames and an
|
Takes a single host pattern and returns a list of hostnames and an
|
||||||
optional port number that applies to all of them.
|
optional port number that applies to all of them.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
# First, we extract the port number. This is usually ":NN" at the end of
|
# Is a port number specified?
|
||||||
# the expression, but for IPv6 addresses it's ".NN" instead. In either
|
#
|
||||||
# case, we remove it.
|
# This may be a mandatory :NN suffix on any square-bracketed expression
|
||||||
|
# (IPv6 address, IPv4 address, host name, host pattern), or an optional
|
||||||
|
# :NN suffix on an IPv4 address, host name, or pattern. IPv6 addresses
|
||||||
|
# must be in square brackets if a port is specified.
|
||||||
|
|
||||||
port = None
|
port = None
|
||||||
if ':' in pattern:
|
|
||||||
pos = pattern.rindex(':')
|
for type in ['bracketed_hostport', 'hostport']:
|
||||||
try:
|
m = self.patterns[type].match(hostpattern)
|
||||||
port = int(pattern[pos+1:])
|
|
||||||
pattern = pattern[0:pos]
|
|
||||||
except ValueError:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
m = self.patterns['ipv6_hostport'].match(pattern)
|
|
||||||
if m:
|
if m:
|
||||||
(pattern, port) = m.groups()
|
(hostpattern, port) = m.groups()
|
||||||
|
continue
|
||||||
# We're done, because we know this is a single IPv6 address.
|
|
||||||
# But should we support ranges for IPv6 address generation?
|
|
||||||
# See the FIXME note below. We should probably just accept
|
|
||||||
# "[xxx]:nn" syntax instead, and then let xxx be expanded.
|
|
||||||
|
|
||||||
return ([pattern], int(port))
|
|
||||||
|
|
||||||
# Now we're left with just the pattern, which results in a list of one
|
# Now we're left with just the pattern, which results in a list of one
|
||||||
# or more hostnames, depending on whether it contains any [x:y] ranges.
|
# or more hostnames, depending on whether it contains any [x:y] ranges.
|
||||||
|
#
|
||||||
|
# FIXME: We could be more strict here about validation.
|
||||||
|
|
||||||
if detect_range(pattern):
|
if detect_range(hostpattern):
|
||||||
hostnames = expand_hostname_range(pattern)
|
hostnames = expand_hostname_range(hostpattern)
|
||||||
else:
|
else:
|
||||||
hostnames = [pattern]
|
hostnames = [hostpattern]
|
||||||
|
|
||||||
return (hostnames, port)
|
return (hostnames, port)
|
||||||
|
|
||||||
|
@ -362,7 +355,7 @@ class InventoryParser(object):
|
||||||
# should they be? At the moment, they must be non-empty sequences of non
|
# should they be? At the moment, they must be non-empty sequences of non
|
||||||
# whitespace characters excluding ':' and ']', but we should define more
|
# whitespace characters excluding ':' and ']', but we should define more
|
||||||
# precise rules in order to support better diagnostics. The same applies
|
# precise rules in order to support better diagnostics. The same applies
|
||||||
# to hostnames.
|
# to hostnames. It seems sensible for them both to follow DNS rules.
|
||||||
|
|
||||||
self.patterns['groupname'] = re.compile(
|
self.patterns['groupname'] = re.compile(
|
||||||
r'''^
|
r'''^
|
||||||
|
@ -373,18 +366,28 @@ class InventoryParser(object):
|
||||||
''', re.X
|
''', re.X
|
||||||
)
|
)
|
||||||
|
|
||||||
# This matches an IPv6 address, a '.', and a port number. It's not yet
|
# The following patterns match the various ways in which a port number
|
||||||
# very strict about matching the IPv6 address.
|
# may be specified on an IPv6 address, IPv4 address, hostname, or host
|
||||||
#
|
# pattern. All of the above may be enclosed in square brackets with a
|
||||||
# FIXME: There are various shortcomings in the IPv6 handling in the
|
# mandatory :NN suffix; or all but the first may be given without any
|
||||||
# old code, which aren't fixed here yet. For example, Inventory's
|
# brackets but with an :NN suffix.
|
||||||
# parse_inventory() method seems to accept "[ipv6]:nn" syntax. We
|
|
||||||
# should pick one and stick with it.
|
|
||||||
|
|
||||||
self.patterns['ipv6_hostport'] = re.compile(
|
self.patterns['bracketed_hostport'] = re.compile(
|
||||||
r'''^
|
r'''^
|
||||||
([a-fA-F0-9:]+)
|
\[(.+)\] # [host identifier]
|
||||||
\.([0-9]+)
|
:([0-9]+) # :port number
|
||||||
|
$
|
||||||
|
''', re.X
|
||||||
|
)
|
||||||
|
|
||||||
|
self.patterns['hostport'] = re.compile(
|
||||||
|
r'''^
|
||||||
|
((?: # We want to match:
|
||||||
|
[^:\[\]] # (a non-range character
|
||||||
|
| # ...or...
|
||||||
|
\[[^\]]*\] # a complete bracketed expression)
|
||||||
|
)*) # repeated as many times as possible
|
||||||
|
:([0-9]+) # followed by a port number
|
||||||
$
|
$
|
||||||
''', re.X
|
''', re.X
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in a new issue