mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-02-25 18:55:28 -06:00
DNS Locations: command dns-update-system-records
command dns-update-system-records updates/fixes DNS records for IPA services: * updating A, AAAA records for CA * updating SRV records for LDAP, kerberos and AD trust * updating TXT record in _kerberos with proper realm * updating dns locations if used https://fedorahosted.org/freeipa/ticket/2008 Reviewed-By: Petr Spacek <pspacek@redhat.com> Reviewed-By: Jan Cholasta <jcholast@redhat.com>
This commit is contained in:
parent
cf634a4ff8
commit
e23159596e
6
API.txt
6
API.txt
@ -1054,6 +1054,12 @@ option: Str('version?')
|
|||||||
output: Output('result', type=[<type 'bool'>])
|
output: Output('result', type=[<type 'bool'>])
|
||||||
output: Output('summary', type=[<type 'unicode'>, <type 'NoneType'>])
|
output: Output('summary', type=[<type 'unicode'>, <type 'NoneType'>])
|
||||||
output: Output('value', type=[<type 'unicode'>])
|
output: Output('value', type=[<type 'unicode'>])
|
||||||
|
command: dns_update_system_records
|
||||||
|
args: 0,2,2
|
||||||
|
option: Flag('dry_run', autofill=True, default=False)
|
||||||
|
option: Str('version?')
|
||||||
|
output: Output('result', type=[<type 'dict'>])
|
||||||
|
output: Output('value', type=[<type 'bool'>])
|
||||||
command: dnsconfig_mod
|
command: dnsconfig_mod
|
||||||
args: 0,11,3
|
args: 0,11,3
|
||||||
option: Str('addattr*', cli_name='addattr')
|
option: Str('addattr*', cli_name='addattr')
|
||||||
|
4
VERSION
4
VERSION
@ -90,5 +90,5 @@ IPA_DATA_VERSION=20100614120000
|
|||||||
# #
|
# #
|
||||||
########################################################
|
########################################################
|
||||||
IPA_API_VERSION_MAJOR=2
|
IPA_API_VERSION_MAJOR=2
|
||||||
IPA_API_VERSION_MINOR=184
|
IPA_API_VERSION_MINOR=185
|
||||||
# Last change: ftweedal - add issuer options to cert-show and cert-find
|
# Last change: mbasti - added command dns-update-system-records
|
||||||
|
@ -21,8 +21,9 @@
|
|||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
|
|
||||||
import six
|
import six
|
||||||
|
import copy
|
||||||
|
|
||||||
from ipaclient.frontend import MethodOverride
|
from ipaclient.frontend import MethodOverride, CommandOverride
|
||||||
from ipalib import errors
|
from ipalib import errors
|
||||||
from ipalib.dns import (get_record_rrtype,
|
from ipalib.dns import (get_record_rrtype,
|
||||||
has_cli_options,
|
has_cli_options,
|
||||||
@ -342,3 +343,29 @@ class dnsforwardzone_mod(MethodOverride):
|
|||||||
_("Server will check DNS forwarder(s)."))
|
_("Server will check DNS forwarder(s)."))
|
||||||
self.Backend.textui.print_plain(
|
self.Backend.textui.print_plain(
|
||||||
_("This may take some time, please wait ..."))
|
_("This may take some time, please wait ..."))
|
||||||
|
|
||||||
|
|
||||||
|
@register(override=True)
|
||||||
|
class dns_update_system_records(CommandOverride):
|
||||||
|
def output_for_cli(self, textui, output, *args, **options):
|
||||||
|
output_super = copy.deepcopy(output)
|
||||||
|
super_res = output_super.get('result', {})
|
||||||
|
super_res.pop('ipa_records', None)
|
||||||
|
super_res.pop('location_records', None)
|
||||||
|
|
||||||
|
super(dns_update_system_records, self).output_for_cli(
|
||||||
|
textui, output_super, *args, **options)
|
||||||
|
|
||||||
|
labels = {
|
||||||
|
p.name: unicode(p.label) for p in self.output_params()
|
||||||
|
}
|
||||||
|
|
||||||
|
result = output.get('result', {})
|
||||||
|
for key in ('ipa_records', 'location_records'):
|
||||||
|
if result.get(key):
|
||||||
|
textui.print_indented(u'{}:'.format(labels[key]), indent=1)
|
||||||
|
for val in sorted(result[key]):
|
||||||
|
textui.print_indented(val, indent=2)
|
||||||
|
textui.print_line(u'')
|
||||||
|
|
||||||
|
return int(not output['value'])
|
||||||
|
@ -395,6 +395,29 @@ class DNSForwardPolicyConflictWithEmptyZone(PublicMessage):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class DNSUpdateOfSystemRecordFailed(PublicMessage):
|
||||||
|
"""
|
||||||
|
** 13022 ** Update of a DNS system record failed
|
||||||
|
"""
|
||||||
|
errno = 13022
|
||||||
|
type = "warning"
|
||||||
|
format = _(
|
||||||
|
"Update of system record '%(record)s' failed with error: %(error)s"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class DNSUpdateNotIPAManagedZone(PublicMessage):
|
||||||
|
"""
|
||||||
|
** 13023 ** Zone for system records is not managed by IPA
|
||||||
|
"""
|
||||||
|
errno = 13023
|
||||||
|
type = "warning"
|
||||||
|
format = _(
|
||||||
|
"IPA does not manage the zone %(zone)s, please add records "
|
||||||
|
"to your DNS server manually"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def iter_messages(variables, base):
|
def iter_messages(variables, base):
|
||||||
"""Return a tuple with all subclasses
|
"""Return a tuple with all subclasses
|
||||||
"""
|
"""
|
||||||
|
@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
|
|
||||||
|
import six
|
||||||
|
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
from dns import (
|
from dns import (
|
||||||
rdataclass,
|
rdataclass,
|
||||||
@ -17,6 +19,10 @@ from ipalib import errors
|
|||||||
from ipalib.dns import record_name_format
|
from ipalib.dns import record_name_format
|
||||||
from ipapython.dnsutil import DNSName, resolve_rrsets
|
from ipapython.dnsutil import DNSName, resolve_rrsets
|
||||||
|
|
||||||
|
if six.PY3:
|
||||||
|
unicode=str
|
||||||
|
|
||||||
|
|
||||||
IPA_DEFAULT_MASTER_SRV_REC = (
|
IPA_DEFAULT_MASTER_SRV_REC = (
|
||||||
# srv record name, port
|
# srv record name, port
|
||||||
(DNSName(u'_ldap._tcp'), 389),
|
(DNSName(u'_ldap._tcp'), 389),
|
||||||
@ -214,7 +220,7 @@ class IPASystemRecords(object):
|
|||||||
for rdata in rdataset:
|
for rdata in rdataset:
|
||||||
option_name = (record_name_format % rdatatype.to_text(
|
option_name = (record_name_format % rdatatype.to_text(
|
||||||
rdata.rdtype).lower())
|
rdata.rdtype).lower())
|
||||||
update_dict[option_name].append(rdata.to_text())
|
update_dict[option_name].append(unicode(rdata.to_text()))
|
||||||
return update_dict
|
return update_dict
|
||||||
|
|
||||||
def __update_dns_records(
|
def __update_dns_records(
|
||||||
@ -378,3 +384,19 @@ class IPASystemRecords(object):
|
|||||||
self.update_base_records(),
|
self.update_base_records(),
|
||||||
self.update_locations_records()
|
self.update_locations_records()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def records_list_from_node(cls, name, node):
|
||||||
|
records = []
|
||||||
|
for rdataset in node:
|
||||||
|
for rd in rdataset:
|
||||||
|
records.append(
|
||||||
|
u'{name} {ttl} {rdclass} {rdtype} {rdata}'.format(
|
||||||
|
name=name.ToASCII(),
|
||||||
|
ttl=rdataset.ttl,
|
||||||
|
rdclass=rdataclass.to_text(rd.rdclass),
|
||||||
|
rdtype=rdatatype.to_text(rd.rdtype),
|
||||||
|
rdata=rd.to_text()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return records
|
||||||
|
@ -72,6 +72,10 @@ from ipapython.ipautil import CheckedIPAddress
|
|||||||
from ipapython.dnsutil import check_zone_overlap
|
from ipapython.dnsutil import check_zone_overlap
|
||||||
from ipapython.dnsutil import DNSName
|
from ipapython.dnsutil import DNSName
|
||||||
from ipapython.dnsutil import related_to_auto_empty_zone
|
from ipapython.dnsutil import related_to_auto_empty_zone
|
||||||
|
from ipaserver.dns_data_management import (
|
||||||
|
IPASystemRecords,
|
||||||
|
IPADomainIsNotManagedByIPAError,
|
||||||
|
)
|
||||||
|
|
||||||
if six.PY3:
|
if six.PY3:
|
||||||
unicode = str
|
unicode = str
|
||||||
@ -4430,3 +4434,104 @@ class dnsforwardzone_add_permission(DNSZoneBase_add_permission):
|
|||||||
@register()
|
@register()
|
||||||
class dnsforwardzone_remove_permission(DNSZoneBase_remove_permission):
|
class dnsforwardzone_remove_permission(DNSZoneBase_remove_permission):
|
||||||
__doc__ = _('Remove a permission for per-forward zone access delegation.')
|
__doc__ = _('Remove a permission for per-forward zone access delegation.')
|
||||||
|
|
||||||
|
|
||||||
|
@register()
|
||||||
|
class dns_update_system_records(Command):
|
||||||
|
__doc__ = _('Update location and IPA server DNS records')
|
||||||
|
|
||||||
|
|
||||||
|
has_output_params = (
|
||||||
|
Str(
|
||||||
|
'ipa_records*',
|
||||||
|
label=_('IPA DNS records')
|
||||||
|
),
|
||||||
|
Str(
|
||||||
|
'location_records*',
|
||||||
|
label=_('IPA location records')
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
has_output = (
|
||||||
|
output.Output(
|
||||||
|
'result',
|
||||||
|
type=dict,
|
||||||
|
doc=_('Dictionary mapping variable name to value'),
|
||||||
|
),
|
||||||
|
output.Output(
|
||||||
|
'value', bool,
|
||||||
|
_('Result of the command'), ['no_display']
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
takes_options = (
|
||||||
|
Flag(
|
||||||
|
'dry_run',
|
||||||
|
label=_('Dry run'),
|
||||||
|
doc=_('Do not update recors only return expected records')
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
def execute(self, *args, **options):
|
||||||
|
|
||||||
|
def output_to_list(iterable):
|
||||||
|
rec_list = []
|
||||||
|
for name, node in iterable:
|
||||||
|
rec_list.extend(IPASystemRecords.records_list_from_node(
|
||||||
|
name, node))
|
||||||
|
return rec_list
|
||||||
|
|
||||||
|
def output_to_list_with_failed(iterable):
|
||||||
|
err_rec_list = []
|
||||||
|
for name, node, error in iterable:
|
||||||
|
err_rec_list.extend([
|
||||||
|
(v, unicode(error)) for v in
|
||||||
|
IPASystemRecords.records_list_from_node(name, node)
|
||||||
|
])
|
||||||
|
return err_rec_list
|
||||||
|
|
||||||
|
result = {
|
||||||
|
'result': {},
|
||||||
|
'value': True,
|
||||||
|
}
|
||||||
|
|
||||||
|
system_records = IPASystemRecords(self.api)
|
||||||
|
|
||||||
|
if options.get('dry_run'):
|
||||||
|
result['result']['ipa_records'] = output_to_list(
|
||||||
|
system_records.get_base_records().items())
|
||||||
|
result['result']['location_records'] = output_to_list(
|
||||||
|
system_records.get_locations_records().items())
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
(
|
||||||
|
(success_base, failed_base),
|
||||||
|
(success_loc, failed_loc),
|
||||||
|
) = system_records.update_dns_records()
|
||||||
|
except IPADomainIsNotManagedByIPAError:
|
||||||
|
result['value'] = False
|
||||||
|
self.add_message(
|
||||||
|
messages.DNSUpdateNotIPAManagedZone(
|
||||||
|
zone=self.api.env.domain)
|
||||||
|
)
|
||||||
|
result['result']['ipa_records'] = output_to_list(
|
||||||
|
system_records.get_base_records().items())
|
||||||
|
else:
|
||||||
|
if success_base:
|
||||||
|
result['result']['ipa_records'] = output_to_list(
|
||||||
|
success_base)
|
||||||
|
if success_loc:
|
||||||
|
result['result']['location_records'] = output_to_list(
|
||||||
|
success_loc)
|
||||||
|
for failed in (failed_base, failed_loc):
|
||||||
|
for record, error in output_to_list_with_failed(failed):
|
||||||
|
self.add_message(
|
||||||
|
messages.DNSUpdateOfSystemRecordFailed(
|
||||||
|
record=record,
|
||||||
|
error=error
|
||||||
|
)
|
||||||
|
)
|
||||||
|
if failed_base or failed_loc:
|
||||||
|
result['value'] = False
|
||||||
|
|
||||||
|
return result
|
||||||
|
Loading…
Reference in New Issue
Block a user