From 0cb65fd9f6865d606625ddb16206090779462c1f Mon Sep 17 00:00:00 2001 From: Martin Kosek Date: Wed, 13 Jul 2011 14:01:17 +0200 Subject: Filter reverse zones in dnszone-find Implements a new option to filter out reverse zones. This patch also do some clean up in dns plugin - debug prints were accidentally left here in the last dns patch. https://fedorahosted.org/freeipa/ticket/1471 --- API.txt | 3 ++- VERSION | 2 +- ipalib/plugins/dns.py | 23 +++++++++++++++++++---- ipaserver/plugins/ldap2.py | 35 ++++++++++++++++++++++++++++------- 4 files changed, 50 insertions(+), 13 deletions(-) diff --git a/API.txt b/API.txt index 4a057d149..44292a988 100644 --- a/API.txt +++ b/API.txt @@ -780,7 +780,7 @@ output: Output('summary', (, ), 'User-friendly output: Output('result', , 'True means the operation was successful') output: Output('value', , "The primary_key value of the entry, e.g. 'jdoe' for a user") command: dnszone_find -args: 1,18,4 +args: 1,19,4 arg: Str('criteria?', noextrawhitespace=False) option: Str('idnsname', attribute=True, autofill=False, cli_name='name', label=Gettext('Zone name', domain='ipa', localedir=None), multivalue=False, normalizer=, primary_key=True, query=True, required=False) option: Str('idnssoamname', attribute=True, autofill=False, cli_name='name_server', label=Gettext('Authoritative nameserver', domain='ipa', localedir=None), multivalue=False, query=True, required=False) @@ -797,6 +797,7 @@ option: Bool('idnszoneactive', attribute=True, autofill=False, cli_name='zone_ac option: Bool('idnsallowdynupdate', attribute=True, autofill=False, cli_name='allow_dynupdate', default=False, label=Gettext('Dynamic update', domain='ipa', localedir=None), multivalue=False, query=True, required=False) option: Int('timelimit?', autofill=False, flags=['no_display'], label=Gettext('Time Limit', domain='ipa', localedir=None), minvalue=0) option: Int('sizelimit?', autofill=False, flags=['no_display'], label=Gettext('Size Limit', domain='ipa', localedir=None), minvalue=0) +option: Flag('forward_only', autofill=True, cli_name='forward_only', default=False, label=Gettext('Forward zones only', domain='ipa', localedir=None)) option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui', flags=['no_output']) option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui', flags=['no_output']) option: Str('version?', exclude='webui', flags=['no_option', 'no_output']) diff --git a/VERSION b/VERSION index b4b706689..224c73567 100644 --- a/VERSION +++ b/VERSION @@ -79,4 +79,4 @@ IPA_DATA_VERSION=20100614120000 # # ######################################################## IPA_API_VERSION_MAJOR=2 -IPA_API_VERSION_MINOR=8 +IPA_API_VERSION_MINOR=9 diff --git a/ipalib/plugins/dns.py b/ipalib/plugins/dns.py index 5c990ace1..e7a0a05a3 100644 --- a/ipalib/plugins/dns.py +++ b/ipalib/plugins/dns.py @@ -458,6 +458,25 @@ class dnszone_find(LDAPSearch): Search for DNS zones (SOA records). """ + takes_options = LDAPSearch.takes_options + ( + Flag('forward_only', + label=_('Forward zones only'), + cli_name='forward_only', + doc=_('Search for forward zones only'), + ), + ) + + def pre_callback(self, ldap, filter, attrs_list, base_dn, scope, *args, **options): + if options.get('forward_only', False): + search_kw = {} + search_kw['idnsname'] = _valid_reverse_zones.keys() + rev_zone_filter = ldap.make_filter(search_kw, rules=ldap.MATCH_NONE, exact=False, + trailing_wildcard=False) + filter = ldap.combine_filters((rev_zone_filter, filter), rules=ldap.MATCH_ALL) + + return (filter, base_dn, scope) + + api.register(dnszone_find) @@ -823,8 +842,6 @@ class dnsrecord_mod(dnsrecord_mod_record): old_entry_attrs.setdefault(a, []) if v or v is None: # overwrite the old entry old_entry_attrs[a] = v - print "DNSRECORD_MOD::update_old_entry_callback: old:", old_entry_attrs - print "DNSRECORD_MOD::update_old_entry_callback: new:", entry_attrs def record_options_2_entry(self, **options): entries = dict((t, options.get(t, [])) for t in _record_attributes) @@ -835,12 +852,10 @@ class dnsrecord_mod(dnsrecord_mod_record): rtype_cb = '_%s_pre_callback' % rtype if hasattr(self.obj, rtype_cb): dn = getattr(self.obj, rtype_cb)(ldap, dn, entry_attrs, *keys, **options) - print "DNSRECORD_MOD::pre_callback: rtype_cb:", rtype_cb return dn def post_callback(self, keys, entry_attrs): - print "DNSRECORD_MOD::post_callback:", entry_attrs if not self.obj.is_pkey_zone_record(*keys): for a in _record_attributes: if a in entry_attrs and entry_attrs[a]: diff --git a/ipaserver/plugins/ldap2.py b/ipaserver/plugins/ldap2.py index 6f34984ca..a2e592d30 100644 --- a/ipaserver/plugins/ldap2.py +++ b/ipaserver/plugins/ldap2.py @@ -457,7 +457,8 @@ class ldap2(CrudBackend, Encoder): return flt @encode_args(1, 2) - def make_filter_from_attr(self, attr, value, rules='|', exact=True): + def make_filter_from_attr(self, attr, value, rules='|', exact=True, + leading_wildcard=True, trailing_wildcard=True): """ Make filter for ldap2.find_entries from attribute. @@ -465,28 +466,42 @@ class ldap2(CrudBackend, Encoder): rules -- see ldap2.make_filter exact -- boolean, True - make filter as (attr=value) False - make filter as (attr=*value*) + leading_wildcard -- boolean, True - allow heading filter wildcard when exact=False + False - forbid heading filter wildcard when exact=False + trailing_wildcard -- boolean, True - allow trailing filter wildcard when exact=False + False - forbid trailing filter wildcard when exact=False """ if isinstance(value, (list, tuple)): flts = [] if rules == self.MATCH_NONE: for v in value: flts.append( - self.make_filter_from_attr(attr, v, exact=exact) + self.make_filter_from_attr(attr, v, exact=exact, + leading_wildcard=leading_wildcard, + trailing_wildcard=trailing_wildcard) ) return '(!%s)' % self.combine_filters(flts) for v in value: - flts.append(self.make_filter_from_attr(attr, v, rules, exact)) + flts.append(self.make_filter_from_attr(attr, v, rules, exact, + leading_wildcard=leading_wildcard, + trailing_wildcard=trailing_wildcard)) return self.combine_filters(flts, rules) elif value is not None: value = _ldap_filter.escape_filter_chars(value) if not exact: - value = '*%s*' % value + template = '%s' + if leading_wildcard: + template = '*' + template + if trailing_wildcard: + template = template + '*' + value = template % value if rules == self.MATCH_NONE: return '(!(%s=%s))' % (attr, value) return '(%s=%s)' % (attr, value) return '' - def make_filter(self, entry_attrs, attrs_list=None, rules='|', exact=True): + def make_filter(self, entry_attrs, attrs_list=None, rules='|', exact=True, + leading_wildcard=True, trailing_wildcard=True): """ Make filter for ldap2.find_entries from entry attributes. @@ -495,6 +510,10 @@ class ldap2(CrudBackend, Encoder): rules -- specifies how to determine a match (default ldap2.MATCH_ANY) exact -- boolean, True - make filter as (attr=value) False - make filter as (attr=*value*) + leading_wildcard -- boolean, True - allow heading filter wildcard when exact=False + False - forbid heading filter wildcard when exact=False + trailing_wildcard -- boolean, True - allow trailing filter wildcard when exact=False + False - forbid trailing filter wildcard when exact=False rules can be one of the following: ldap2.MATCH_NONE - match entries that do not match any attribute @@ -505,14 +524,16 @@ class ldap2(CrudBackend, Encoder): if attrs_list is None: for (k, v) in entry_attrs.iteritems(): flts.append( - self.make_filter_from_attr(k, v, rules, exact) + self.make_filter_from_attr(k, v, rules, exact, + leading_wildcard, trailing_wildcard) ) else: for a in attrs_list: value = entry_attrs.get(a, None) if value is not None: flts.append( - self.make_filter_from_attr(a, value, rules, exact) + self.make_filter_from_attr(a, value, rules, exact, + leading_wildcard, trailing_wildcard) ) return self.combine_filters(flts, rules) -- cgit