mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-02-25 18:55:28 -06:00
Improve ipa-replica-prepare DNS check
Currently, verify_fqdn() function raises RuntimeError for every problem with the hostname. This makes it difficult for tools like ipa-replica-prepare to behave differently for a subset of raised errors (for example to be able to create a DNS record for new replica when verify_fqdn() reports a lookup error). Implement own exceptions for verify_fqdn() that they can be safely used to distinguish the error type. https://fedorahosted.org/freeipa/ticket/1899
This commit is contained in:
parent
652d315b3e
commit
5b968f9632
@ -30,7 +30,7 @@ from ipaserver.install import installutils, service
|
|||||||
from ipaserver.install import certs
|
from ipaserver.install import certs
|
||||||
from ipaserver.install.installutils import HostnameLocalhost
|
from ipaserver.install.installutils import HostnameLocalhost
|
||||||
from ipaserver.install.installutils import ReplicaConfig, expand_replica_info, read_replica_info
|
from ipaserver.install.installutils import ReplicaConfig, expand_replica_info, read_replica_info
|
||||||
from ipaserver.install.installutils import get_host_name
|
from ipaserver.install.installutils import get_host_name, BadHostError
|
||||||
from ipaserver.install import dsinstance, cainstance
|
from ipaserver.install import dsinstance, cainstance
|
||||||
from ipaserver.install.replication import replica_conn_check
|
from ipaserver.install.replication import replica_conn_check
|
||||||
from ipapython import version
|
from ipapython import version
|
||||||
@ -119,7 +119,7 @@ def main():
|
|||||||
config.dirman_password = dirman_password
|
config.dirman_password = dirman_password
|
||||||
try:
|
try:
|
||||||
host = get_host_name(options.no_host_dns)
|
host = get_host_name(options.no_host_dns)
|
||||||
except RuntimeError, e:
|
except BadHostError, e:
|
||||||
logging.error(str(e))
|
logging.error(str(e))
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
if config.host_name != host:
|
if config.host_name != host:
|
||||||
|
@ -32,7 +32,7 @@ from ipaserver.install import bindinstance, httpinstance, ntpinstance, certs
|
|||||||
from ipaserver.install.replication import replica_conn_check
|
from ipaserver.install.replication import replica_conn_check
|
||||||
from ipaserver.install.installutils import HostnameLocalhost, resolve_host
|
from ipaserver.install.installutils import HostnameLocalhost, resolve_host
|
||||||
from ipaserver.install.installutils import ReplicaConfig, expand_replica_info, read_replica_info
|
from ipaserver.install.installutils import ReplicaConfig, expand_replica_info, read_replica_info
|
||||||
from ipaserver.install.installutils import get_host_name
|
from ipaserver.install.installutils import get_host_name, BadHostError
|
||||||
from ipaserver.plugins.ldap2 import ldap2
|
from ipaserver.plugins.ldap2 import ldap2
|
||||||
from ipaserver.install import cainstance
|
from ipaserver.install import cainstance
|
||||||
from ipapython import version
|
from ipapython import version
|
||||||
@ -328,7 +328,7 @@ def main():
|
|||||||
config.dirman_password = dirman_password
|
config.dirman_password = dirman_password
|
||||||
try:
|
try:
|
||||||
host = get_host_name(options.no_host_dns)
|
host = get_host_name(options.no_host_dns)
|
||||||
except RuntimeError, e:
|
except BadHostError, e:
|
||||||
logging.error(str(e))
|
logging.error(str(e))
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
if config.host_name != host:
|
if config.host_name != host:
|
||||||
|
@ -29,7 +29,7 @@ from ipapython import ipautil
|
|||||||
from ipaserver.install import bindinstance, dsinstance, installutils, certs
|
from ipaserver.install import bindinstance, dsinstance, installutils, certs
|
||||||
from ipaserver.install.bindinstance import add_zone, add_reverse_zone, add_fwd_rr, add_ptr_rr, dns_container_exists
|
from ipaserver.install.bindinstance import add_zone, add_reverse_zone, add_fwd_rr, add_ptr_rr, dns_container_exists
|
||||||
from ipaserver.install.replication import enable_replication_version_checking
|
from ipaserver.install.replication import enable_replication_version_checking
|
||||||
from ipaserver.install.installutils import resolve_host
|
from ipaserver.install.installutils import resolve_host, BadHostError, HostLookupError
|
||||||
from ipaserver.plugins.ldap2 import ldap2
|
from ipaserver.plugins.ldap2 import ldap2
|
||||||
from ipapython import version
|
from ipapython import version
|
||||||
from ipapython.config import IPAOptionParser
|
from ipapython.config import IPAOptionParser
|
||||||
@ -268,9 +268,9 @@ def main():
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
installutils.verify_fqdn(replica_fqdn, system_name_check=False)
|
installutils.verify_fqdn(replica_fqdn, system_name_check=False)
|
||||||
except RuntimeError, e:
|
except BadHostError, e:
|
||||||
msg = str(e)
|
msg = str(e)
|
||||||
if msg.startswith('Unable to resolve host name'):
|
if isinstance(e, HostLookupError):
|
||||||
if options.ip_address is None:
|
if options.ip_address is None:
|
||||||
if dns_container_exists(api.env.host, api.env.basedn,
|
if dns_container_exists(api.env.host, api.env.basedn,
|
||||||
dm_password=dirman_password,
|
dm_password=dirman_password,
|
||||||
|
@ -388,15 +388,10 @@ def read_host_name(host_default,no_host_dns=False):
|
|||||||
print ""
|
print ""
|
||||||
if host_default == "":
|
if host_default == "":
|
||||||
host_default = "master.example.com"
|
host_default = "master.example.com"
|
||||||
while True:
|
|
||||||
host_name = user_input("Server host name", host_default, allow_empty = False)
|
host_name = user_input("Server host name", host_default, allow_empty = False)
|
||||||
print ""
|
print ""
|
||||||
try:
|
|
||||||
verify_fqdn(host_name,no_host_dns)
|
verify_fqdn(host_name,no_host_dns)
|
||||||
except Exception, e:
|
|
||||||
raise e
|
|
||||||
else:
|
|
||||||
break
|
|
||||||
return host_name
|
return host_name
|
||||||
|
|
||||||
def read_domain_name(domain_name, unattended):
|
def read_domain_name(domain_name, unattended):
|
||||||
@ -750,7 +745,7 @@ def main():
|
|||||||
host_name = host_default
|
host_name = host_default
|
||||||
else:
|
else:
|
||||||
host_name = read_host_name(host_default,options.no_host_dns)
|
host_name = read_host_name(host_default,options.no_host_dns)
|
||||||
except RuntimeError, e:
|
except BadHostError, e:
|
||||||
sys.exit(str(e) + "\n")
|
sys.exit(str(e) + "\n")
|
||||||
|
|
||||||
host_name = host_name.lower()
|
host_name = host_name.lower()
|
||||||
|
@ -38,7 +38,19 @@ from ipapython import ipautil, dnsclient, sysrestore
|
|||||||
# Used to determine install status
|
# Used to determine install status
|
||||||
IPA_MODULES = ['httpd', 'kadmin', 'dirsrv', 'pki-cad', 'pkids', 'install', 'krb5kdc', 'ntpd', 'named']
|
IPA_MODULES = ['httpd', 'kadmin', 'dirsrv', 'pki-cad', 'pkids', 'install', 'krb5kdc', 'ntpd', 'named']
|
||||||
|
|
||||||
class HostnameLocalhost(Exception):
|
class BadHostError(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class HostLookupError(BadHostError):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class HostForwardLookupError(HostLookupError):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class HostReverseLookupError(HostLookupError):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class HostnameLocalhost(HostLookupError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
class ReplicaConfig:
|
class ReplicaConfig:
|
||||||
@ -119,22 +131,25 @@ def verify_dns_records(host_name, responses, resaddr, family):
|
|||||||
|
|
||||||
def verify_fqdn(host_name, no_host_dns=False, system_name_check=True):
|
def verify_fqdn(host_name, no_host_dns=False, system_name_check=True):
|
||||||
"""
|
"""
|
||||||
Verify that the given host name is fully-qualified.
|
Run fqdn checks for given host:
|
||||||
|
- test hostname format
|
||||||
|
- test that hostname is fully qualified
|
||||||
|
- test forward and reverse hostname DNS lookup
|
||||||
|
|
||||||
Raises `RuntimeError` if the host name is not fully-qualified.
|
Raises `BadHostError` or derived Exceptions if there is an error
|
||||||
|
|
||||||
:param host_name: The host name to verify.
|
:param host_name: The host name to verify.
|
||||||
:param no_host_dns: If true, skip DNS resolution of the host name.
|
:param no_host_dns: If true, skip DNS resolution tests of the host name.
|
||||||
:param system_name_check: If true, check if the host name matches the system host name.
|
:param system_name_check: If true, check if the host name matches the system host name.
|
||||||
"""
|
"""
|
||||||
if len(host_name.split(".")) < 2 or host_name == "localhost.localdomain":
|
if len(host_name.split(".")) < 2 or host_name == "localhost.localdomain":
|
||||||
raise RuntimeError("Invalid hostname '%s', must be fully-qualified." % host_name)
|
raise BadHostError("Invalid hostname '%s', must be fully-qualified." % host_name)
|
||||||
|
|
||||||
if host_name != host_name.lower():
|
if host_name != host_name.lower():
|
||||||
raise RuntimeError("Invalid hostname '%s', must be lower-case." % host_name)
|
raise BadHostError("Invalid hostname '%s', must be lower-case." % host_name)
|
||||||
|
|
||||||
if ipautil.valid_ip(host_name):
|
if ipautil.valid_ip(host_name):
|
||||||
raise RuntimeError("IP address not allowed as a hostname")
|
raise BadHostError("IP address not allowed as a hostname")
|
||||||
|
|
||||||
if system_name_check:
|
if system_name_check:
|
||||||
system_host_name = socket.gethostname()
|
system_host_name = socket.gethostname()
|
||||||
@ -149,28 +164,28 @@ def verify_fqdn(host_name, no_host_dns=False, system_name_check=True):
|
|||||||
try:
|
try:
|
||||||
hostaddr = socket.getaddrinfo(host_name, None)
|
hostaddr = socket.getaddrinfo(host_name, None)
|
||||||
except:
|
except:
|
||||||
raise RuntimeError("Unable to resolve host name, check /etc/hosts or DNS name resolution")
|
raise HostForwardLookupError("Unable to resolve host name, check /etc/hosts or DNS name resolution")
|
||||||
|
|
||||||
if len(hostaddr) == 0:
|
if len(hostaddr) == 0:
|
||||||
raise RuntimeError("Unable to resolve host name, check /etc/hosts or DNS name resolution")
|
raise HostForwardLookupError("Unable to resolve host name, check /etc/hosts or DNS name resolution")
|
||||||
|
|
||||||
for a in hostaddr:
|
for a in hostaddr:
|
||||||
if a[4][0] == '127.0.0.1' or a[4][0] == '::1':
|
if a[4][0] == '127.0.0.1' or a[4][0] == '::1':
|
||||||
raise RuntimeError("The IPA Server hostname must not resolve to localhost (%s). A routable IP address must be used. Check /etc/hosts to see if %s is an alias for %s" % (a[4][0], host_name, a[4][0]))
|
raise HostForwardLookupError("The IPA Server hostname must not resolve to localhost (%s). A routable IP address must be used. Check /etc/hosts to see if %s is an alias for %s" % (a[4][0], host_name, a[4][0]))
|
||||||
try:
|
try:
|
||||||
resaddr = a[4][0]
|
resaddr = a[4][0]
|
||||||
revname = socket.gethostbyaddr(a[4][0])[0]
|
revname = socket.gethostbyaddr(a[4][0])[0]
|
||||||
except:
|
except:
|
||||||
raise RuntimeError("Unable to resolve the reverse ip address, check /etc/hosts or DNS name resolution")
|
raise HostReverseLookupError("Unable to resolve the reverse ip address, check /etc/hosts or DNS name resolution")
|
||||||
if revname != host_name:
|
if revname != host_name:
|
||||||
raise RuntimeError("The host name %s does not match the reverse lookup %s" % (host_name, revname))
|
raise HostReverseLookupError("The host name %s does not match the reverse lookup %s" % (host_name, revname))
|
||||||
|
|
||||||
# Verify this is NOT a CNAME
|
# Verify this is NOT a CNAME
|
||||||
rs = dnsclient.query(host_name+".", dnsclient.DNS_C_IN, dnsclient.DNS_T_CNAME)
|
rs = dnsclient.query(host_name+".", dnsclient.DNS_C_IN, dnsclient.DNS_T_CNAME)
|
||||||
if len(rs) != 0:
|
if len(rs) != 0:
|
||||||
for rsn in rs:
|
for rsn in rs:
|
||||||
if rsn.dns_type == dnsclient.DNS_T_CNAME:
|
if rsn.dns_type == dnsclient.DNS_T_CNAME:
|
||||||
raise RuntimeError("The IPA Server Hostname cannot be a CNAME, only A and AAAA names are allowed.")
|
raise HostReverseLookupError("The IPA Server Hostname cannot be a CNAME, only A and AAAA names are allowed.")
|
||||||
|
|
||||||
# Verify that it is a DNS A or AAAA record
|
# Verify that it is a DNS A or AAAA record
|
||||||
rs = dnsclient.query(host_name+".", dnsclient.DNS_C_IN, dnsclient.DNS_T_A)
|
rs = dnsclient.query(host_name+".", dnsclient.DNS_C_IN, dnsclient.DNS_T_A)
|
||||||
|
Loading…
Reference in New Issue
Block a user