Warning the user when using a loopback IP as forwarder

Changing the --forwarder option to accept a loopback IP.
Previously, an error would be raised, now we just show a
warning message.

Fixes: https://pagure.io/freeipa/issue/5801
Reviewed-By: Stanislav Laznicka <slaznick@redhat.com>
Reviewed-By: Martin Basti <mbasti@redhat.com>
This commit is contained in:
Felipe Barreto
2017-10-23 09:45:56 -02:00
parent b84e8be5ac
commit 405da071d1
5 changed files with 37 additions and 8 deletions

View File

@@ -54,7 +54,7 @@ def parse_options():
help="Master Server IP Address. This option can be used " help="Master Server IP Address. This option can be used "
"multiple times") "multiple times")
parser.add_option("--forwarder", dest="forwarders", action="append", parser.add_option("--forwarder", dest="forwarders", action="append",
type="ip", help="Add a DNS forwarder. This option can be used multiple times") type="ip_with_loopback", help="Add a DNS forwarder. This option can be used multiple times")
parser.add_option("--no-forwarders", dest="no_forwarders", action="store_true", parser.add_option("--no-forwarders", dest="no_forwarders", action="store_true",
default=False, help="Do not add any DNS forwarders, use root servers instead") default=False, help="Do not add any DNS forwarders, use root servers instead")
parser.add_option("--auto-forwarders", dest="auto_forwarders", parser.add_option("--auto-forwarders", dest="auto_forwarders",

View File

@@ -23,6 +23,7 @@ from optparse import (
# pylint: enable=deprecated-module # pylint: enable=deprecated-module
from copy import copy from copy import copy
import socket import socket
import functools
from dns import resolver, rdatatype from dns import resolver, rdatatype
from dns.exception import DNSException from dns.exception import DNSException
@@ -33,6 +34,7 @@ from six.moves.urllib.parse import urlsplit
# pylint: enable=import-error # pylint: enable=import-error
from ipapython.dn import DN from ipapython.dn import DN
from ipapython.ipautil import CheckedIPAddress, CheckedIPAddressLoopback
try: try:
# pylint: disable=ipa-forbidden-import # pylint: disable=ipa-forbidden-import
@@ -65,13 +67,16 @@ class IPAFormatter(IndentedHelpFormatter):
ret += "%s %s\n" % (spacing, line) ret += "%s %s\n" % (spacing, line)
return ret return ret
def check_ip_option(option, opt, value):
from ipapython.ipautil import CheckedIPAddress
def check_ip_option(option, opt, value, allow_loopback=False):
try: try:
if allow_loopback:
return CheckedIPAddressLoopback(value)
else:
return CheckedIPAddress(value) return CheckedIPAddress(value)
except Exception as e: except Exception as e:
raise OptionValueError("option %s: invalid IP address %s: %s" % (opt, value, e)) raise OptionValueError("option {}: invalid IP address {}: {}"
.format(opt, value, e))
def check_dn_option(option, opt, value): def check_dn_option(option, opt, value):
try: try:
@@ -95,9 +100,11 @@ class IPAOption(Option):
security-sensitive such as passwords. security-sensitive such as passwords.
""" """
ATTRS = Option.ATTRS + ["sensitive", "constructor"] ATTRS = Option.ATTRS + ["sensitive", "constructor"]
TYPES = Option.TYPES + ("ip", "dn", "constructor") TYPES = Option.TYPES + ("ip", "dn", "constructor", "ip_with_loopback")
TYPE_CHECKER = copy(Option.TYPE_CHECKER) TYPE_CHECKER = copy(Option.TYPE_CHECKER)
TYPE_CHECKER["ip"] = check_ip_option TYPE_CHECKER["ip"] = check_ip_option
TYPE_CHECKER["ip_with_loopback"] = functools.partial(check_ip_option,
allow_loopback=True)
TYPE_CHECKER["dn"] = check_dn_option TYPE_CHECKER["dn"] = check_dn_option
TYPE_CHECKER["constructor"] = check_constructor TYPE_CHECKER["constructor"] = check_constructor

View File

@@ -16,7 +16,8 @@ import six
from ipapython import admintool from ipapython import admintool
from ipapython.ipa_log_manager import standard_logging_setup from ipapython.ipa_log_manager import standard_logging_setup
from ipapython.ipautil import CheckedIPAddress, private_ccache from ipapython.ipautil import (CheckedIPAddress, CheckedIPAddressLoopback,
private_ccache)
from . import core, common from . import core, common
@@ -166,6 +167,8 @@ class ConfigureTool(admintool.AdminTool):
kwargs['type'] = 'int' kwargs['type'] = 'int'
elif knob_scalar_type is long: elif knob_scalar_type is long:
kwargs['type'] = 'long' kwargs['type'] = 'long'
elif knob_scalar_type is CheckedIPAddressLoopback:
kwargs['type'] = 'ip_with_loopback'
elif knob_scalar_type is CheckedIPAddress: elif knob_scalar_type is CheckedIPAddress:
kwargs['type'] = 'ip' kwargs['type'] = 'ip'
elif issubclass(knob_scalar_type, enum.Enum): elif issubclass(knob_scalar_type, enum.Enum):

View File

@@ -244,6 +244,25 @@ class CheckedIPAddress(UnsafeIPAddress):
self._net = ifnet self._net = ifnet
class CheckedIPAddressLoopback(CheckedIPAddress):
"""IPv4 or IPv6 address with additional constraints with
possibility to use a loopback IP.
Reserved or link-local addresses are never accepted.
"""
def __init__(self, addr, parse_netmask=True, allow_multicast=False):
super(CheckedIPAddressLoopback, self).__init__(
addr, parse_netmask=parse_netmask,
allow_multicast=allow_multicast,
allow_loopback=True)
if self.is_loopback():
# print is being used instead of a logger, because at this
# moment, in execution process, there is no logger configured
print("WARNING: You are using a loopback IP: {}".format(addr),
file=sys.stderr)
def valid_ip(addr): def valid_ip(addr):
return netaddr.valid_ipv4(addr) or netaddr.valid_ipv6(addr) return netaddr.valid_ipv4(addr) or netaddr.valid_ipv6(addr)

View File

@@ -491,7 +491,7 @@ class DNSInstallInterface(hostname.HostNameInstallInterface):
forwarders = knob( forwarders = knob(
# pylint: disable=invalid-sequence-index # pylint: disable=invalid-sequence-index
typing.List[ipautil.CheckedIPAddress], None, typing.List[ipautil.CheckedIPAddressLoopback], None,
description=("Add a DNS forwarder. This option can be used multiple " description=("Add a DNS forwarder. This option can be used multiple "
"times"), "times"),
cli_names='--forwarder', cli_names='--forwarder',