diff --git a/services/univention-s4-connector/modules/univention/s4connector/s4/dns.py b/services/univention-s4-connector/modules/univention/s4connector/s4/dns.py index 8a6c170c5d..f5fd8afe19 100644 --- a/services/univention-s4-connector/modules/univention/s4connector/s4/dns.py +++ b/services/univention-s4-connector/modules/univention/s4connector/s4/dns.py @@ -498,39 +498,49 @@ def __create_s4_dns_node(s4connector, dnsNodeDn, relativeDomainNames, dnsRecords def __pack_aRecord(object, dnsRecords): # add aRecords + kwargs = {} + ttl = object['attributes'].get('dNSTTL', [None])[0] + if ttl: + kwargs['ttl'] = int(ttl) + # IPv4 for a in object['attributes'].get('aRecord', []): - a_record = ARecord(a) + a_record = ARecord(a, **kwargs) dnsRecords.append(ndr_pack(a_record)) # IPv6 for a in object['attributes'].get('aAAARecord', []): - a_record = AAAARecord(a) + a_record = AAAARecord(a, **kwargs) dnsRecords.append(ndr_pack(a_record)) def __unpack_aRecord(object): - a = [] + r = [] dnsRecords = object['attributes'].get('dnsRecord', []) for dnsRecord in dnsRecords: ndrRecord = ndr_unpack(dnsp.DnssrvRpcRecord, dnsRecord) if ndrRecord.wType == dnsp.DNS_TYPE_A or ndrRecord.wType == dnsp.DNS_TYPE_AAAA: - a.append(ndrRecord.data) - return a + r.append(ndrRecord) + return r def __pack_soaRecord(object, dnsRecords): + kwargs = {} + ttl = object['attributes'].get('dNSTTL', [None])[0] + if ttl: + kwargs['ttl'] = int(ttl) + soaRecord = object['attributes'].get('sOARecord', [None])[0] if soaRecord: soa = soaRecord.split(b' ') - mname = soa[0] - rname = soa[1] - serial = int(soa[2]) - refresh = int(soa[3]) - retry = int(soa[4]) - expire = int(soa[5]) - ttl = int(soa[6]) - soa_record = SOARecord(mname=mname, rname=rname, serial=serial, refresh=refresh, retry=retry, expire=expire, minimum=3600, ttl=ttl) + kwargs['mname'] = soa[0] + kwargs['rname'] = soa[1] + kwargs['serial'] = int(soa[2]) + kwargs['refresh'] = int(soa[3]) + kwargs['retry'] = int(soa[4]) + kwargs['expire'] = int(soa[5]) + kwargs['minimum'] = int(soa[6]) # minimum ttl + soa_record = SOARecord(**kwargs) dnsRecords.append(ndr_pack(soa_record)) @@ -553,8 +563,13 @@ def __unpack_soaRecord(object): def __pack_nsRecord(object, dnsRecords): + kwargs = {} + ttl = object['attributes'].get('dNSTTL', [None])[0] + if ttl: + kwargs['ttl'] = int(ttl) + for nSRecord in object['attributes'].get('nSRecord', []): - a_record = NSRecord(nSRecord) + a_record = NSRecord(nSRecord, **kwargs) dnsRecords.append(ndr_pack(a_record)) @@ -564,18 +579,23 @@ def __unpack_nsRecord(object): for dnsRecord in dnsRecords: ndrRecord = ndr_unpack(dnsp.DnssrvRpcRecord, dnsRecord) if ndrRecord.wType == dnsp.DNS_TYPE_NS: - ns.append(__append_dot(ndrRecord.data)) + ns.append(ndrRecord) return ns def __pack_mxRecord(object, dnsRecords): + kwargs = {} + ttl = object['attributes'].get('dNSTTL', [None])[0] + if ttl: + kwargs['ttl'] = int(ttl) + for mXRecord in object['attributes'].get('mXRecord', []): if mXRecord: ud.debug(ud.LDAP, ud.INFO, '__pack_mxRecord: %s' % mXRecord) mx = mXRecord.split(b' ') priority = mx[0] name = mx[1] - mx_record = MXRecord(name, int(priority)) + mx_record = MXRecord(name, int(priority), **kwargs) dnsRecords.append(ndr_pack(mx_record)) ud.debug(ud.LDAP, ud.INFO, '__pack_mxRecord: %s' % ndr_pack(mx_record)) @@ -591,11 +611,16 @@ def __unpack_mxRecord(object): def __pack_txtRecord(object, dnsRecords): + kwargs = {} + ttl = object['attributes'].get('dNSTTL', [None])[0] + if ttl: + kwargs['ttl'] = int(ttl) + for txtRecord in object['attributes'].get('tXTRecord', []): if txtRecord: ud.debug(ud.LDAP, ud.INFO, '__pack_txtRecord: %s' % txtRecord) token_list = TXT.from_text(rdataclass.IN, rdatatype.TXT, Tokenizer(txtRecord)).strings - ndr_txt_record = ndr_pack(TXTRecord(token_list)) + ndr_txt_record = ndr_pack(TXTRecord(token_list, **kwargs)) dnsRecords.append(ndr_txt_record) ud.debug(ud.LDAP, ud.INFO, '__pack_txtRecord: %s' % ndr_txt_record) @@ -612,9 +637,14 @@ def __unpack_txtRecord(object): def __pack_cName(object, dnsRecords): + kwargs = {} + ttl = object['attributes'].get('dNSTTL', [None])[0] + if ttl: + kwargs['ttl'] = int(ttl) + for c in object['attributes'].get('cNAMERecord', []): c = __remove_dot(c) - c_record = CNameRecord(c) + c_record = CNameRecord(c, **kwargs) dnsRecords.append(ndr_pack(c_record)) @@ -632,13 +662,18 @@ def __unpack_cName(object): def __pack_sRVrecord(object, dnsRecords): + kwargs = {} + ttl = object['attributes'].get('dNSTTL', [None])[0] + if ttl: + kwargs['ttl'] = int(ttl) + for srvRecord in object['attributes'].get('sRVRecord', []): srv = srvRecord.split(b' ') priority = int(srv[0]) weight = int(srv[1]) port = int(srv[2]) target = __remove_dot(srv[3]) - s = SRVRecord(target, port, priority, weight) + s = SRVRecord(target, port, priority, weight, **kwargs) dnsRecords.append(ndr_pack(s)) @@ -653,9 +688,14 @@ def __unpack_sRVrecord(object): def __pack_ptrRecord(object, dnsRecords): + kwargs = {} + ttl = object['attributes'].get('dNSTTL', [None])[0] + if ttl: + kwargs['ttl'] = int(ttl) + for ptr in object['attributes'].get('pTRRecord', []): ptr = __remove_dot(ptr) - ptr_record = PTRRecord(ptr) + ptr_record = PTRRecord(ptr, **kwargs) dnsRecords.append(ndr_pack(ptr_record)) @@ -923,7 +963,7 @@ def ucs_host_record_create(s4connector, object): return # unpack the host record - a = __unpack_aRecord(object) + a_ndrRecord_list = __unpack_aRecord(object) # Does a host record for this zone already exist? ol_filter = format_escaped('(&(relativeDomainName={0!e})(zoneName={1!e}))', relativeDomainName, zoneName) @@ -931,8 +971,10 @@ def ucs_host_record_create(s4connector, object): if len(searchResult) > 0: newRecord = univention.admin.handlers.dns.host_record.object(None, s4connector.lo, position=None, dn=searchResult[0][0], update_zone=False) newRecord.open() + a = [r.data for r in a_ndrRecord_list] if set(newRecord['a']) != set(a): newRecord['a'] = a + newRecord['zonettl'] = [min([r.dwTtlSeconds for r in a_ndrRecord_list])] # complex UDM syntax newRecord.modify() else: ud.debug(ud.LDAP, ud.INFO, 'ucs_host_record_create: do not modify host record') @@ -946,7 +988,8 @@ def ucs_host_record_create(s4connector, object): newRecord = univention.admin.handlers.dns.host_record.object(None, s4connector.lo, position, dn=None, update_zone=False) newRecord.open() newRecord['name'] = relativeDomainName - newRecord['a'] = a + newRecord['a'] = [r.data for r in a_ndrRecord_list] + newRecord['zonettl'] = [min([r.dwTtlSeconds for r in a_ndrRecord_list])] # complex UDM syntax newRecord.create() @@ -1281,7 +1324,8 @@ def ucs_ns_record_create(s4connector, object): relativeDomainName = object['attributes']['relativeDomainName'][0].decode('UTF-8') # unpack the record - c = __unpack_nsRecord(object) + ns_ndrRecord_list = __unpack_nsRecord(object) + ns = [__append_dot(r.data) for r in ns_ndrRecord_list] # Does a host record for this zone already exist? ol_filter = format_escaped('(&(relativeDomainName={0!e})(zoneName={1!e}))', relativeDomainName, zoneName) @@ -1290,8 +1334,9 @@ def ucs_ns_record_create(s4connector, object): foundRecord = univention.admin.handlers.dns.ns_record.object(None, s4connector.lo, position=None, dn=searchResult[0][0], update_zone=False) foundRecord.open() - if set(foundRecord[udm_property]) != set(c): - foundRecord[udm_property] = c + if set(foundRecord[udm_property]) != set(ns): + foundRecord[udm_property] = ns + newRecord['zonettl'] = [min([r.dwTtlSeconds for r in ns_ndrRecord_list])] # complex UDM syntax foundRecord.modify() else: ud.debug(ud.LDAP, ud.INFO, 'ucs_ns_record_create: do not modify ns record') @@ -1302,7 +1347,8 @@ def ucs_ns_record_create(s4connector, object): newRecord = univention.admin.handlers.dns.ns_record.object(None, s4connector.lo, position, dn=None, update_zone=False) newRecord.open() newRecord['zone'] = relativeDomainName - newRecord[udm_property] = c + newRecord['zonettl'] = [min([r.dwTtlSeconds for r in ns_ndrRecord_list])] # complex UDM syntax + newRecord[udm_property] = ns newRecord.create() @@ -1343,11 +1389,12 @@ def ucs_zone_create(s4connector, object, dns_type): ud.debug(ud.LDAP, ud.INFO, "ucs_zone_create: ignoring DC=%s object" % (relativeDomainName,)) return - ns = __unpack_nsRecord(object) + ns_ndrRecord_list = __unpack_nsRecord(object) + ns = [__append_dot(r.data) for r in ns_ndrRecord_list] soa = __unpack_soaRecord(object) - a = __unpack_aRecord(object) + a_ndrRecord_list = __unpack_aRecord(object) mx = __unpack_mxRecord(object) @@ -1388,9 +1435,15 @@ def ucs_zone_create(s4connector, object, dns_type): if int(soa['serial']) != int(zone['serial']): zone['serial'] = soa['serial'] modify = True - for k in ['refresh', 'retry', 'expire', 'ttl']: - if int(soa[k]) != _unixTimeInverval2seconds(zone[k]): - zone[k] = unmapUNIX_TimeInterval(soa[k]) + for k in ['refresh', 'retry', 'expire', ('minimum', 'ttl'), ('ttl', 'zonettl')]: + if isinstance(k, str): + samba_key = k + udm_property = k + else: + samba_key = k[0] + udm_property = k[1] + if int(soa[samba_key]) != _unixTimeInverval2seconds(zone[udm_property]): + zone[udm_property] = soa[samba_key] modify = True if dns_type == 'forward_zone': # The IP address of the DNS forward zone will be used to determine the @@ -1399,6 +1452,7 @@ def ucs_zone_create(s4connector, object, dns_type): aRecords = s4connector.configRegistry.get('connector/s4/mapping/dns/forward_zone/%s/static/ipv4' % zoneName.lower()) aAAARecords = s4connector.configRegistry.get('connector/s4/mapping/dns/forward_zone/%s/static/ipv6' % zoneName.lower()) if not aRecords and not aAAARecords: + a = [r.data for r in a_ndrRecord_list] if set(a) != set(zone['a']): zone['a'] = a modify = True @@ -1425,12 +1479,13 @@ def ucs_zone_create(s4connector, object, dns_type): zone['nameserver'] = ns zone['contact'] = soa['rname'].replace('.', '@', 1) zone['serial'] = soa['serial'] - zone['refresh'] = [soa['refresh']] # complex UDM syntax - zone['retry'] = [soa['retry']] # complex UDM syntax - zone['expire'] = [soa['expire']] # complex UDM syntax - zone['ttl'] = [soa['ttl']] # complex UDM syntax + zone['refresh'] = soa['refresh'] # UDM syntax is mapUNIX_TimeInterval + zone['retry'] = soa['retry'] # UDM syntax is mapUNIX_TimeInterval + zone['expire'] = soa['expire'] # UDM syntax is mapUNIX_TimeInterval + zone['ttl'] = soa['minimum'] # this is the "minimum" ttl part of sOARecord, UDM syntax is mapUNIX_TimeInterval + zone['zonettl'] = soa['ttl'] if dns_type == 'forward_zone': - zone['a'] = a + zone['a'] = [r.data for r in a_ndrRecord_list] zone['mx'] = mx zone.create()