mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-02-25 18:55:28 -06:00
dns: Check if domain already exists.
Raise an error when the domain already exists. This can be overriden using --force or --allow-zone-overlap options. https://fedorahosted.org/freeipa/ticket/3681 Reviewed-By: Petr Spacek <pspacek@redhat.com>
This commit is contained in:
parent
6c107d819c
commit
8d19da49c4
@ -57,6 +57,9 @@ def parse_options():
|
|||||||
help="The reverse DNS zone to use. This option can be used multiple times")
|
help="The reverse DNS zone to use. This option can be used multiple times")
|
||||||
parser.add_option("--no-reverse", dest="no_reverse", action="store_true",
|
parser.add_option("--no-reverse", dest="no_reverse", action="store_true",
|
||||||
default=False, help="Do not create new reverse DNS zone")
|
default=False, help="Do not create new reverse DNS zone")
|
||||||
|
parser.add_option("--allow-zone-overlap", dest="allow_zone_overlap",
|
||||||
|
action="store_true", default=False, help="Create DNS "
|
||||||
|
"zone even if it already exists")
|
||||||
parser.add_option("--no-dnssec-validation", dest="no_dnssec_validation", action="store_true",
|
parser.add_option("--no-dnssec-validation", dest="no_dnssec_validation", action="store_true",
|
||||||
default=False, help="Disable DNSSEC validation")
|
default=False, help="Disable DNSSEC validation")
|
||||||
parser.add_option("--dnssec-master", dest="dnssec_master", action="store_true",
|
parser.add_option("--dnssec-master", dest="dnssec_master", action="store_true",
|
||||||
|
@ -62,6 +62,9 @@ Copy OpenDNSSEC metadata from the specified kasp.db file. This will not create a
|
|||||||
\fB\-\-zonemgr\fR
|
\fB\-\-zonemgr\fR
|
||||||
The e\-mail address of the DNS zone manager. Defaults to hostmaster@DOMAIN
|
The e\-mail address of the DNS zone manager. Defaults to hostmaster@DOMAIN
|
||||||
.TP
|
.TP
|
||||||
|
\fB\-\-allow\-zone\-overlap\fR
|
||||||
|
Allow creatin of (reverse) zone even if the zone is already resolvable. Using this option is discouraged as it result in later problems with domain name resolution.
|
||||||
|
.TP
|
||||||
\fB\-U\fR, \fB\-\-unattended\fR
|
\fB\-U\fR, \fB\-\-unattended\fR
|
||||||
An unattended installation that will never prompt for user input
|
An unattended installation that will never prompt for user input
|
||||||
.SH "DEPRECATED OPTIONS"
|
.SH "DEPRECATED OPTIONS"
|
||||||
|
@ -175,6 +175,9 @@ Do not automatically create DNS SSHFP records.
|
|||||||
.TP
|
.TP
|
||||||
\fB\-\-no\-dnssec\-validation\fR
|
\fB\-\-no\-dnssec\-validation\fR
|
||||||
Disable DNSSEC validation on this server.
|
Disable DNSSEC validation on this server.
|
||||||
|
.TP
|
||||||
|
\fB\-\-allow\-zone\-overlap\fR
|
||||||
|
Allow creatin of (reverse) zone even if the zone is already resolvable. Using this option is discouraged as it result in later problems with domain name resolution.
|
||||||
|
|
||||||
.SS "UNINSTALL OPTIONS"
|
.SS "UNINSTALL OPTIONS"
|
||||||
.TP
|
.TP
|
||||||
|
@ -40,7 +40,7 @@ from contextlib import contextmanager
|
|||||||
import locale
|
import locale
|
||||||
import collections
|
import collections
|
||||||
|
|
||||||
from dns import resolver, rdatatype
|
from dns import resolver, rdatatype, reversename
|
||||||
from dns.exception import DNSException, Timeout
|
from dns.exception import DNSException, Timeout
|
||||||
import six
|
import six
|
||||||
from six.moves import input
|
from six.moves import input
|
||||||
@ -1031,6 +1031,22 @@ def host_exists(host):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def reverse_record_exists(ip_address):
|
||||||
|
"""
|
||||||
|
Checks if IP address have some reverse record somewhere.
|
||||||
|
Does not care where it points.
|
||||||
|
|
||||||
|
Returns True/False
|
||||||
|
"""
|
||||||
|
reverse = reversename.from_address(str(ip_address))
|
||||||
|
try:
|
||||||
|
resolver.query(reverse, "PTR")
|
||||||
|
except DNSException:
|
||||||
|
# really don't care what exception, PTR is simply unresolvable
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
def check_zone_overlap(zone, raise_on_timeout=True):
|
def check_zone_overlap(zone, raise_on_timeout=True):
|
||||||
root_logger.info("Checking DNS domain %s, please wait ..." % zone)
|
root_logger.info("Checking DNS domain %s, please wait ..." % zone)
|
||||||
if not isinstance(zone, DNSName):
|
if not isinstance(zone, DNSName):
|
||||||
|
@ -43,10 +43,12 @@ from ipaplatform.constants import constants
|
|||||||
from ipaplatform.paths import paths
|
from ipaplatform.paths import paths
|
||||||
from ipaplatform.tasks import tasks
|
from ipaplatform.tasks import tasks
|
||||||
from ipalib.util import (validate_zonemgr_str, normalize_zonemgr,
|
from ipalib.util import (validate_zonemgr_str, normalize_zonemgr,
|
||||||
get_dns_forward_zone_update_policy, get_dns_reverse_zone_update_policy,
|
get_dns_forward_zone_update_policy,
|
||||||
normalize_zone, get_reverse_zone_default, zone_is_reverse,
|
get_dns_reverse_zone_update_policy,
|
||||||
validate_dnssec_global_forwarder, DNSSECSignatureMissingError,
|
normalize_zone, get_reverse_zone_default,
|
||||||
EDNS0UnsupportedError, UnresolvableRecordError)
|
zone_is_reverse, validate_dnssec_global_forwarder,
|
||||||
|
DNSSECSignatureMissingError, EDNS0UnsupportedError,
|
||||||
|
UnresolvableRecordError, verify_host_resolvable)
|
||||||
from ipalib.constants import CACERT
|
from ipalib.constants import CACERT
|
||||||
|
|
||||||
if six.PY3:
|
if six.PY3:
|
||||||
@ -278,20 +280,48 @@ def find_reverse_zone(ip_address, api=api):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def read_reverse_zone(default, ip_address):
|
def read_reverse_zone(default, ip_address, allow_zone_overlap=False):
|
||||||
while True:
|
while True:
|
||||||
zone = ipautil.user_input("Please specify the reverse zone name", default=default)
|
zone = ipautil.user_input("Please specify the reverse zone name", default=default)
|
||||||
if not zone:
|
if not zone:
|
||||||
return None
|
return None
|
||||||
if verify_reverse_zone(zone, ip_address):
|
if not verify_reverse_zone(zone, ip_address):
|
||||||
break
|
root_logger.error("Invalid reverse zone %s for IP address %s"
|
||||||
else:
|
% (zone, ip_address))
|
||||||
print("Invalid reverse zone %s for IP address %s" % (zone, ip_address))
|
continue
|
||||||
|
if not allow_zone_overlap:
|
||||||
|
try:
|
||||||
|
ipautil.check_zone_overlap(zone, raise_on_timeout=False)
|
||||||
|
except ValueError as e:
|
||||||
|
root_logger.error("Reverse zone %s will not be used: %s"
|
||||||
|
% (zone, e))
|
||||||
|
continue
|
||||||
|
break
|
||||||
|
|
||||||
return normalize_zone(zone)
|
return normalize_zone(zone)
|
||||||
|
|
||||||
|
|
||||||
|
def get_auto_reverse_zones(ip_addresses):
|
||||||
|
auto_zones = []
|
||||||
|
for ip in ip_addresses:
|
||||||
|
if ipautil.reverse_record_exists(ip):
|
||||||
|
# PTR exist there is no reason to create reverse zone
|
||||||
|
root_logger.info("Reverse record for IP address %s already "
|
||||||
|
"exists" % ip)
|
||||||
|
continue
|
||||||
|
default_reverse = get_reverse_zone_default(ip)
|
||||||
|
try:
|
||||||
|
ipautil.check_zone_overlap(default_reverse)
|
||||||
|
except ValueError:
|
||||||
|
root_logger.info("Reverse zone %s for IP address %s already exists"
|
||||||
|
% (default_reverse, ip))
|
||||||
|
continue
|
||||||
|
auto_zones.append((ip, default_reverse))
|
||||||
|
return auto_zones
|
||||||
|
|
||||||
def add_zone(name, zonemgr=None, dns_backup=None, ns_hostname=None,
|
def add_zone(name, zonemgr=None, dns_backup=None, ns_hostname=None,
|
||||||
update_policy=None, force=False, api=api):
|
update_policy=None, force=False, skip_overlap_check=False,
|
||||||
|
api=api):
|
||||||
|
|
||||||
# always normalize zones
|
# always normalize zones
|
||||||
name = normalize_zone(name)
|
name = normalize_zone(name)
|
||||||
@ -317,6 +347,7 @@ def add_zone(name, zonemgr=None, dns_backup=None, ns_hostname=None,
|
|||||||
idnsupdatepolicy=unicode(update_policy),
|
idnsupdatepolicy=unicode(update_policy),
|
||||||
idnsallowquery=u'any',
|
idnsallowquery=u'any',
|
||||||
idnsallowtransfer=u'none',
|
idnsallowtransfer=u'none',
|
||||||
|
skip_overlap_check=skip_overlap_check,
|
||||||
force=force)
|
force=force)
|
||||||
except (errors.DuplicateEntry, errors.EmptyModlist):
|
except (errors.DuplicateEntry, errors.EmptyModlist):
|
||||||
pass
|
pass
|
||||||
@ -406,46 +437,62 @@ def zonemgr_callback(option, opt_str, value, parser):
|
|||||||
|
|
||||||
parser.values.zonemgr = value
|
parser.values.zonemgr = value
|
||||||
|
|
||||||
def check_reverse_zones(ip_addresses, reverse_zones, options, unattended, search_reverse_zones=False):
|
|
||||||
reverse_asked = False
|
|
||||||
|
|
||||||
ret_reverse_zones = []
|
def check_reverse_zones(ip_addresses, reverse_zones, options, unattended,
|
||||||
# check that there is IP address in every reverse zone
|
search_reverse_zones=False):
|
||||||
if reverse_zones:
|
checked_reverse_zones = []
|
||||||
for rz in reverse_zones:
|
|
||||||
for ip in ip_addresses:
|
if not options.no_reverse and not reverse_zones:
|
||||||
if verify_reverse_zone(rz, ip):
|
if unattended:
|
||||||
ret_reverse_zones.append(normalize_zone(rz))
|
options.no_reverse = True
|
||||||
break
|
else:
|
||||||
else:
|
options.no_reverse = not create_reverse()
|
||||||
# no ip matching reverse zone found
|
|
||||||
sys.exit("There is no IP address matching reverse zone %s." % rz)
|
# shortcut
|
||||||
if not options.no_reverse:
|
if options.no_reverse:
|
||||||
# check that there is reverse zone for every IP
|
return []
|
||||||
for ip in ip_addresses:
|
|
||||||
if search_reverse_zones and find_reverse_zone(str(ip)):
|
# verify zones passed in options
|
||||||
# reverse zone is already in LDAP
|
for rz in reverse_zones:
|
||||||
|
# isn't the zone managed by someone else
|
||||||
|
if not options.allow_zone_overlap:
|
||||||
|
try:
|
||||||
|
ipautil.check_zone_overlap(rz)
|
||||||
|
except ValueError as e:
|
||||||
|
msg = "Reverse zone %s will not be used: %s" % (rz, e)
|
||||||
|
if options.unattended:
|
||||||
|
sys.exit(msg)
|
||||||
|
else:
|
||||||
|
root_logger.warning(msg)
|
||||||
continue
|
continue
|
||||||
for rz in ret_reverse_zones:
|
checked_reverse_zones.append(normalize_zone(rz))
|
||||||
if verify_reverse_zone(rz, ip):
|
|
||||||
# reverse zone was entered by user
|
# check that there is reverse zone for every IP
|
||||||
break
|
ips_missing_reverse = []
|
||||||
else:
|
for ip in ip_addresses:
|
||||||
# no reverse zone for ip found
|
if search_reverse_zones and find_reverse_zone(str(ip)):
|
||||||
if not reverse_asked:
|
# reverse zone is already in LDAP
|
||||||
if not unattended and not reverse_zones:
|
continue
|
||||||
# user did not specify reverse_zone nor no_reverse
|
for rz in checked_reverse_zones:
|
||||||
options.no_reverse = not create_reverse()
|
if verify_reverse_zone(rz, ip):
|
||||||
if options.no_reverse:
|
# reverse zone was entered by user
|
||||||
# user decided not to create reverse zone
|
break
|
||||||
return []
|
else:
|
||||||
reverse_asked = True
|
ips_missing_reverse.append(ip)
|
||||||
rz = get_reverse_zone_default(str(ip))
|
|
||||||
if not unattended:
|
# create reverse zone for IP addresses that does not have one
|
||||||
rz = read_reverse_zone(rz, str(ip))
|
for (ip, rz) in get_auto_reverse_zones(ips_missing_reverse):
|
||||||
ret_reverse_zones.append(rz)
|
if unattended:
|
||||||
|
root_logger.warning("Missing reverse record for IP address %s"
|
||||||
|
% ip)
|
||||||
|
else:
|
||||||
|
if ipautil.user_input("Do you want to create reverse zone for IP "
|
||||||
|
"%s" % ip, True):
|
||||||
|
rz = read_reverse_zone(rz, str(ip), options.allow_zone_overlap)
|
||||||
|
checked_reverse_zones.append(rz)
|
||||||
|
|
||||||
|
return checked_reverse_zones
|
||||||
|
|
||||||
return ret_reverse_zones
|
|
||||||
|
|
||||||
def check_forwarders(dns_forwarders, logger):
|
def check_forwarders(dns_forwarders, logger):
|
||||||
print("Checking DNS forwarders, please wait ...")
|
print("Checking DNS forwarders, please wait ...")
|
||||||
@ -770,7 +817,8 @@ class BindInstance(service.Service):
|
|||||||
def __setup_zone(self):
|
def __setup_zone(self):
|
||||||
# Always use force=True as named is not set up yet
|
# Always use force=True as named is not set up yet
|
||||||
add_zone(self.domain, self.zonemgr, dns_backup=self.dns_backup,
|
add_zone(self.domain, self.zonemgr, dns_backup=self.dns_backup,
|
||||||
ns_hostname=self.api.env.host, force=True, api=self.api)
|
ns_hostname=self.api.env.host, force=True,
|
||||||
|
skip_overlap_check=True, api=self.api)
|
||||||
|
|
||||||
add_rr(self.domain, "_kerberos", "TXT", self.realm, api=self.api)
|
add_rr(self.domain, "_kerberos", "TXT", self.realm, api=self.api)
|
||||||
|
|
||||||
@ -788,7 +836,8 @@ class BindInstance(service.Service):
|
|||||||
# Always use force=True as named is not set up yet
|
# Always use force=True as named is not set up yet
|
||||||
for reverse_zone in self.reverse_zones:
|
for reverse_zone in self.reverse_zones:
|
||||||
add_zone(reverse_zone, self.zonemgr, ns_hostname=self.api.env.host,
|
add_zone(reverse_zone, self.zonemgr, ns_hostname=self.api.env.host,
|
||||||
dns_backup=self.dns_backup, force=True, api=self.api)
|
dns_backup=self.dns_backup, force=True,
|
||||||
|
skip_overlap_check=True, api=self.api)
|
||||||
|
|
||||||
def __add_master_records(self, fqdn, addrs):
|
def __add_master_records(self, fqdn, addrs):
|
||||||
host, zone = fqdn.split(".", 1)
|
host, zone = fqdn.split(".", 1)
|
||||||
@ -817,18 +866,19 @@ class BindInstance(service.Service):
|
|||||||
api=self.api)
|
api=self.api)
|
||||||
|
|
||||||
if not dns_zone_exists(zone, self.api):
|
if not dns_zone_exists(zone, self.api):
|
||||||
# add DNS domain for host first
|
# check if master hostname is resolvable
|
||||||
root_logger.debug(
|
try:
|
||||||
"Host domain (%s) is different from DNS domain (%s)!" % (
|
verify_host_resolvable(fqdn, root_logger)
|
||||||
zone, self.domain))
|
except errors.DNSNotARecordError:
|
||||||
root_logger.debug("Add DNS zone for host first.")
|
root_logger.warning("Master FQDN (%s) is not resolvable.",
|
||||||
|
fqdn)
|
||||||
add_zone(zone, self.zonemgr, dns_backup=self.dns_backup,
|
|
||||||
ns_hostname=self.fqdn, force=True, api=self.api)
|
|
||||||
|
|
||||||
# Add forward and reverse records to self
|
# Add forward and reverse records to self
|
||||||
for addr in addrs:
|
for addr in addrs:
|
||||||
add_fwd_rr(zone, host, addr, api=self.api)
|
try:
|
||||||
|
add_fwd_rr(zone, host, addr, self.api)
|
||||||
|
except errors.NotFound as e:
|
||||||
|
pass
|
||||||
|
|
||||||
reverse_zone = find_reverse_zone(addr, self.api)
|
reverse_zone = find_reverse_zone(addr, self.api)
|
||||||
if reverse_zone:
|
if reverse_zone:
|
||||||
|
@ -13,11 +13,13 @@ from subprocess import CalledProcessError
|
|||||||
|
|
||||||
from ipalib import api
|
from ipalib import api
|
||||||
from ipalib import errors
|
from ipalib import errors
|
||||||
|
from ipalib import util
|
||||||
from ipaplatform.paths import paths
|
from ipaplatform.paths import paths
|
||||||
from ipaplatform.constants import constants
|
from ipaplatform.constants import constants
|
||||||
from ipaplatform import services
|
from ipaplatform import services
|
||||||
from ipapython import ipautil
|
from ipapython import ipautil
|
||||||
from ipapython import sysrestore
|
from ipapython import sysrestore
|
||||||
|
from ipapython import dnsutil
|
||||||
from ipapython.dn import DN
|
from ipapython.dn import DN
|
||||||
from ipapython.ipa_log_manager import root_logger
|
from ipapython.ipa_log_manager import root_logger
|
||||||
from ipapython.ipaldap import AUTOBIND_ENABLED
|
from ipapython.ipaldap import AUTOBIND_ENABLED
|
||||||
@ -97,6 +99,19 @@ def _disable_dnssec():
|
|||||||
conn.update_entry(entry)
|
conn.update_entry(entry)
|
||||||
|
|
||||||
|
|
||||||
|
def check_dns_enabled(api):
|
||||||
|
try:
|
||||||
|
api.Backend.rpcclient.connect()
|
||||||
|
result = api.Backend.rpcclient.forward(
|
||||||
|
'dns_is_enabled',
|
||||||
|
version=u'2.112', # All the way back to 3.0 servers
|
||||||
|
)
|
||||||
|
return result['result']
|
||||||
|
finally:
|
||||||
|
if api.Backend.rpcclient.isconnected():
|
||||||
|
api.Backend.rpcclient.disconnect()
|
||||||
|
|
||||||
|
|
||||||
def install_check(standalone, replica, options, hostname):
|
def install_check(standalone, replica, options, hostname):
|
||||||
global ip_addresses
|
global ip_addresses
|
||||||
global reverse_zones
|
global reverse_zones
|
||||||
@ -106,6 +121,27 @@ def install_check(standalone, replica, options, hostname):
|
|||||||
raise RuntimeError("Integrated DNS requires '%s' package" %
|
raise RuntimeError("Integrated DNS requires '%s' package" %
|
||||||
constants.IPA_DNS_PACKAGE_NAME)
|
constants.IPA_DNS_PACKAGE_NAME)
|
||||||
|
|
||||||
|
# when installing first replica with DNS we need to check zone overlap
|
||||||
|
if not replica or not check_dns_enabled(api):
|
||||||
|
domain = dnsutil.DNSName(util.normalize_zone(api.env.domain))
|
||||||
|
print("Checking DNS domain %s, please wait ..." % domain)
|
||||||
|
try:
|
||||||
|
ipautil.check_zone_overlap(domain, raise_on_timeout=False)
|
||||||
|
except ValueError as e:
|
||||||
|
if options.force or options.allow_zone_overlap:
|
||||||
|
root_logger.warning(e.message)
|
||||||
|
else:
|
||||||
|
raise e
|
||||||
|
|
||||||
|
for reverse_zone in options.reverse_zones:
|
||||||
|
try:
|
||||||
|
ipautil.check_zone_overlap(reverse_zone)
|
||||||
|
except ValueError as e:
|
||||||
|
if options.force or options.allow_zone_overlap:
|
||||||
|
root_logger.warning(e.message)
|
||||||
|
else:
|
||||||
|
raise e
|
||||||
|
|
||||||
if standalone:
|
if standalone:
|
||||||
print("==============================================================================")
|
print("==============================================================================")
|
||||||
print("This program will setup DNS for the FreeIPA Server.")
|
print("This program will setup DNS for the FreeIPA Server.")
|
||||||
|
@ -10,6 +10,8 @@ from ipapython.install import common, core
|
|||||||
from ipapython.install.core import Knob
|
from ipapython.install.core import Knob
|
||||||
from ipalib.util import validate_domain_name
|
from ipalib.util import validate_domain_name
|
||||||
from ipaserver.install import bindinstance
|
from ipaserver.install import bindinstance
|
||||||
|
from ipapython.ipautil import check_zone_overlap
|
||||||
|
from ipapython.dnsutil import DNSName
|
||||||
|
|
||||||
VALID_SUBJECT_ATTRS = ['st', 'o', 'ou', 'dnqualifier', 'c',
|
VALID_SUBJECT_ATTRS = ['st', 'o', 'ou', 'dnqualifier', 'c',
|
||||||
'serialnumber', 'l', 'title', 'sn', 'givenname',
|
'serialnumber', 'l', 'title', 'sn', 'givenname',
|
||||||
@ -171,6 +173,11 @@ class BaseServerDNS(common.Installable, core.Group, core.Composite):
|
|||||||
description="Do not add any DNS forwarders, use root servers instead",
|
description="Do not add any DNS forwarders, use root servers instead",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
allow_zone_overlap = Knob(
|
||||||
|
bool, False,
|
||||||
|
description="Create DNS zone even if it already exists",
|
||||||
|
)
|
||||||
|
|
||||||
reverse_zones = Knob(
|
reverse_zones = Knob(
|
||||||
(list, str), [],
|
(list, str), [],
|
||||||
description=("The reverse DNS zone to use. This option can be used "
|
description=("The reverse DNS zone to use. This option can be used "
|
||||||
@ -179,6 +186,12 @@ class BaseServerDNS(common.Installable, core.Group, core.Composite):
|
|||||||
cli_metavar='REVERSE_ZONE',
|
cli_metavar='REVERSE_ZONE',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@reverse_zones.validator
|
||||||
|
def reverse_zones(self, values):
|
||||||
|
if not self.allow_zone_overlap:
|
||||||
|
for zone in values:
|
||||||
|
check_zone_overlap(zone)
|
||||||
|
|
||||||
no_reverse = Knob(
|
no_reverse = Knob(
|
||||||
bool, False,
|
bool, False,
|
||||||
description="Do not create new reverse DNS zone",
|
description="Do not create new reverse DNS zone",
|
||||||
@ -255,6 +268,11 @@ class BaseServer(common.Installable, common.Interactive, core.Composite):
|
|||||||
@domain_name.validator
|
@domain_name.validator
|
||||||
def domain_name(self, value):
|
def domain_name(self, value):
|
||||||
validate_domain_name(value)
|
validate_domain_name(value)
|
||||||
|
if (self.setup_dns and
|
||||||
|
not self.dns.allow_zone_overlap): # pylint: disable=no-member
|
||||||
|
print("Checking DNS domain %s, please wait ..." % value)
|
||||||
|
check_zone_overlap(value, False)
|
||||||
|
|
||||||
|
|
||||||
dm_password = Knob(
|
dm_password = Knob(
|
||||||
str, None,
|
str, None,
|
||||||
@ -452,6 +470,7 @@ class BaseServer(common.Installable, common.Interactive, core.Composite):
|
|||||||
self.no_forwarders = self.dns.no_forwarders
|
self.no_forwarders = self.dns.no_forwarders
|
||||||
self.reverse_zones = self.dns.reverse_zones
|
self.reverse_zones = self.dns.reverse_zones
|
||||||
self.no_reverse = self.dns.no_reverse
|
self.no_reverse = self.dns.no_reverse
|
||||||
|
self.allow_zone_overlap = self.dns.allow_zone_overlap
|
||||||
self.no_dnssec_validation = self.dns.no_dnssec_validation
|
self.no_dnssec_validation = self.dns.no_dnssec_validation
|
||||||
self.dnssec_master = self.dns.dnssec_master
|
self.dnssec_master = self.dns.dnssec_master
|
||||||
self.disable_dnssec_master = self.dns.disable_dnssec_master
|
self.disable_dnssec_master = self.dns.disable_dnssec_master
|
||||||
|
Loading…
Reference in New Issue
Block a user