https://fedorahosted.org/freeipa/ticket/2671

Changed regex validating net/hostgroup names to allow single letter
names. Unit-tests added.

But the current validation allows weird (host|net)group names like: ".", ".-", "..".
I'm just not sure, do we really want to allow stuff like this?

Patch also fixes one of netgroup and host unit-tests. The error
message in hostname validation function has changed (in ticket #1966).

--
Regards,

Ondrej Hamada
FreeIPA team
jabber: oh...@jabbim.cz
IRC: ohamada

From 62043ae72e77978c3315070eb09bb9939aa5b99e Mon Sep 17 00:00:00 2001
From: Ondrej Hamada <oham...@redhat.com>
Date: Wed, 2 May 2012 15:25:41 +0200
Subject: [PATCH] Allow one letter net/hostgroups names

Changed regex validating net/hostgroup names to allow single letter
names. Unit-tests added.

https://fedorahosted.org/freeipa/ticket/2671

Patch also fixes one of netgroup and host unit-tests. The error
message in hostname validation function has changed (in ticket 1966).
---
 API.txt                                    |   34 +++++++++++++-------------
 VERSION                                    |    2 +-
 ipalib/plugins/netgroup.py                 |    2 +-
 tests/test_xmlrpc/test_host_plugin.py      |    2 +-
 tests/test_xmlrpc/test_hostgroup_plugin.py |   37 ++++++++++++++++++++++++++++
 tests/test_xmlrpc/test_netgroup_plugin.py  |   35 +++++++++++++++++++++++++-
 6 files changed, 91 insertions(+), 21 deletions(-)

diff --git a/API.txt b/API.txt
index 71241b4cc40e14c600127d1087092abf098eb40c..1d32913c0356bfa03574bfc4ef08d46fb408cd57 100644
--- a/API.txt
+++ b/API.txt
@@ -1758,7 +1758,7 @@ output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDA
 output: Output('value', <type 'unicode'>, None)
 command: hostgroup_add
 args: 1,6,3
-arg: Str('cn', attribute=True, cli_name='hostgroup_name', multivalue=False, pattern='^[a-zA-Z0-9_.][a-zA-Z0-9_.-]+$', primary_key=True, required=True)
+arg: Str('cn', attribute=True, cli_name='hostgroup_name', multivalue=False, pattern='^[a-zA-Z0-9_.][a-zA-Z0-9_.-]*$', primary_key=True, required=True)
 option: Str('description', attribute=True, cli_name='desc', multivalue=False, required=True)
 option: Str('setattr*', cli_name='setattr', exclude='webui')
 option: Str('addattr*', cli_name='addattr', exclude='webui')
@@ -1770,7 +1770,7 @@ output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDA
 output: Output('value', <type 'unicode'>, None)
 command: hostgroup_add_member
 args: 1,5,3
-arg: Str('cn', attribute=True, cli_name='hostgroup_name', multivalue=False, pattern='^[a-zA-Z0-9_.][a-zA-Z0-9_.-]+$', primary_key=True, query=True, required=True)
+arg: Str('cn', attribute=True, cli_name='hostgroup_name', multivalue=False, pattern='^[a-zA-Z0-9_.][a-zA-Z0-9_.-]*$', primary_key=True, query=True, required=True)
 option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
 option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
 option: Str('version?', exclude='webui')
@@ -1781,7 +1781,7 @@ output: Output('failed', <type 'dict'>, None)
 output: Output('completed', <type 'int'>, None)
 command: hostgroup_del
 args: 1,1,3
-arg: Str('cn', attribute=True, cli_name='hostgroup_name', multivalue=True, pattern='^[a-zA-Z0-9_.][a-zA-Z0-9_.-]+$', primary_key=True, query=True, required=True)
+arg: Str('cn', attribute=True, cli_name='hostgroup_name', multivalue=True, pattern='^[a-zA-Z0-9_.][a-zA-Z0-9_.-]*$', primary_key=True, query=True, required=True)
 option: Flag('continue', autofill=True, cli_name='continue', default=False)
 output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
 output: Output('result', <type 'dict'>, None)
@@ -1789,7 +1789,7 @@ output: Output('value', <type 'unicode'>, None)
 command: hostgroup_find
 args: 1,20,4
 arg: Str('criteria?', noextrawhitespace=False)
-option: Str('cn', attribute=True, autofill=False, cli_name='hostgroup_name', multivalue=False, pattern='^[a-zA-Z0-9_.][a-zA-Z0-9_.-]+$', primary_key=True, query=True, required=False)
+option: Str('cn', attribute=True, autofill=False, cli_name='hostgroup_name', multivalue=False, pattern='^[a-zA-Z0-9_.][a-zA-Z0-9_.-]*$', primary_key=True, query=True, required=False)
 option: Str('description', attribute=True, autofill=False, cli_name='desc', multivalue=False, query=True, required=False)
 option: Int('timelimit?', autofill=False, minvalue=0)
 option: Int('sizelimit?', autofill=False, minvalue=0)
@@ -1815,7 +1815,7 @@ output: Output('count', <type 'int'>, None)
 output: Output('truncated', <type 'bool'>, None)
 command: hostgroup_mod
 args: 1,8,3
-arg: Str('cn', attribute=True, cli_name='hostgroup_name', multivalue=False, pattern='^[a-zA-Z0-9_.][a-zA-Z0-9_.-]+$', primary_key=True, query=True, required=True)
+arg: Str('cn', attribute=True, cli_name='hostgroup_name', multivalue=False, pattern='^[a-zA-Z0-9_.][a-zA-Z0-9_.-]*$', primary_key=True, query=True, required=True)
 option: Str('description', attribute=True, autofill=False, cli_name='desc', multivalue=False, required=False)
 option: Str('setattr*', cli_name='setattr', exclude='webui')
 option: Str('addattr*', cli_name='addattr', exclude='webui')
@@ -1829,7 +1829,7 @@ output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDA
 output: Output('value', <type 'unicode'>, None)
 command: hostgroup_remove_member
 args: 1,5,3
-arg: Str('cn', attribute=True, cli_name='hostgroup_name', multivalue=False, pattern='^[a-zA-Z0-9_.][a-zA-Z0-9_.-]+$', primary_key=True, query=True, required=True)
+arg: Str('cn', attribute=True, cli_name='hostgroup_name', multivalue=False, pattern='^[a-zA-Z0-9_.][a-zA-Z0-9_.-]*$', primary_key=True, query=True, required=True)
 option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
 option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
 option: Str('version?', exclude='webui')
@@ -1840,7 +1840,7 @@ output: Output('failed', <type 'dict'>, None)
 output: Output('completed', <type 'int'>, None)
 command: hostgroup_show
 args: 1,4,3
-arg: Str('cn', attribute=True, cli_name='hostgroup_name', multivalue=False, pattern='^[a-zA-Z0-9_.][a-zA-Z0-9_.-]+$', primary_key=True, query=True, required=True)
+arg: Str('cn', attribute=True, cli_name='hostgroup_name', multivalue=False, pattern='^[a-zA-Z0-9_.][a-zA-Z0-9_.-]*$', primary_key=True, query=True, required=True)
 option: Flag('rights', autofill=True, default=False)
 option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
 option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
@@ -1921,9 +1921,9 @@ output: Output('enabled', <type 'bool'>, None)
 output: Output('compat', <type 'bool'>, None)
 command: netgroup_add
 args: 1,9,3
-arg: Str('cn', attribute=True, cli_name='name', multivalue=False, pattern='^[a-zA-Z0-9_.][a-zA-Z0-9_.-]+$', primary_key=True, required=True)
+arg: Str('cn', attribute=True, cli_name='name', multivalue=False, pattern='^[a-zA-Z0-9_.][a-zA-Z0-9_.-]*$', primary_key=True, required=True)
 option: Str('description', attribute=True, cli_name='desc', multivalue=False, required=True)
-option: Str('nisdomainname', attribute=True, cli_name='nisdomain', multivalue=False, pattern='^[a-zA-Z0-9_.][a-zA-Z0-9_.-]+$', required=False)
+option: Str('nisdomainname', attribute=True, cli_name='nisdomain', multivalue=False, pattern='^[a-zA-Z0-9_.][a-zA-Z0-9_.-]*$', required=False)
 option: StrEnum('usercategory', attribute=True, cli_name='usercat', multivalue=False, required=False, values=(u'all',))
 option: StrEnum('hostcategory', attribute=True, cli_name='hostcat', multivalue=False, required=False, values=(u'all',))
 option: Str('setattr*', cli_name='setattr', exclude='webui')
@@ -1936,7 +1936,7 @@ output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDA
 output: Output('value', <type 'unicode'>, None)
 command: netgroup_add_member
 args: 1,8,3
-arg: Str('cn', attribute=True, cli_name='name', multivalue=False, pattern='^[a-zA-Z0-9_.][a-zA-Z0-9_.-]+$', primary_key=True, query=True, required=True)
+arg: Str('cn', attribute=True, cli_name='name', multivalue=False, pattern='^[a-zA-Z0-9_.][a-zA-Z0-9_.-]*$', primary_key=True, query=True, required=True)
 option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
 option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
 option: Str('version?', exclude='webui')
@@ -1950,7 +1950,7 @@ output: Output('failed', <type 'dict'>, None)
 output: Output('completed', <type 'int'>, None)
 command: netgroup_del
 args: 1,1,3
-arg: Str('cn', attribute=True, cli_name='name', multivalue=True, pattern='^[a-zA-Z0-9_.][a-zA-Z0-9_.-]+$', primary_key=True, query=True, required=True)
+arg: Str('cn', attribute=True, cli_name='name', multivalue=True, pattern='^[a-zA-Z0-9_.][a-zA-Z0-9_.-]*$', primary_key=True, query=True, required=True)
 option: Flag('continue', autofill=True, cli_name='continue', default=False)
 output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
 output: Output('result', <type 'dict'>, None)
@@ -1958,9 +1958,9 @@ output: Output('value', <type 'unicode'>, None)
 command: netgroup_find
 args: 1,26,4
 arg: Str('criteria?', noextrawhitespace=False)
-option: Str('cn', attribute=True, autofill=False, cli_name='name', multivalue=False, pattern='^[a-zA-Z0-9_.][a-zA-Z0-9_.-]+$', primary_key=True, query=True, required=False)
+option: Str('cn', attribute=True, autofill=False, cli_name='name', multivalue=False, pattern='^[a-zA-Z0-9_.][a-zA-Z0-9_.-]*$', primary_key=True, query=True, required=False)
 option: Str('description', attribute=True, autofill=False, cli_name='desc', multivalue=False, query=True, required=False)
-option: Str('nisdomainname', attribute=True, autofill=False, cli_name='nisdomain', multivalue=False, pattern='^[a-zA-Z0-9_.][a-zA-Z0-9_.-]+$', query=True, required=False)
+option: Str('nisdomainname', attribute=True, autofill=False, cli_name='nisdomain', multivalue=False, pattern='^[a-zA-Z0-9_.][a-zA-Z0-9_.-]*$', query=True, required=False)
 option: Str('ipauniqueid', attribute=True, autofill=False, cli_name='uuid', multivalue=False, query=True, required=False)
 option: StrEnum('usercategory', attribute=True, autofill=False, cli_name='usercat', multivalue=False, query=True, required=False, values=(u'all',))
 option: StrEnum('hostcategory', attribute=True, autofill=False, cli_name='hostcat', multivalue=False, query=True, required=False, values=(u'all',))
@@ -1990,9 +1990,9 @@ output: Output('count', <type 'int'>, None)
 output: Output('truncated', <type 'bool'>, None)
 command: netgroup_mod
 args: 1,11,3
-arg: Str('cn', attribute=True, cli_name='name', multivalue=False, pattern='^[a-zA-Z0-9_.][a-zA-Z0-9_.-]+$', primary_key=True, query=True, required=True)
+arg: Str('cn', attribute=True, cli_name='name', multivalue=False, pattern='^[a-zA-Z0-9_.][a-zA-Z0-9_.-]*$', primary_key=True, query=True, required=True)
 option: Str('description', attribute=True, autofill=False, cli_name='desc', multivalue=False, required=False)
-option: Str('nisdomainname', attribute=True, autofill=False, cli_name='nisdomain', multivalue=False, pattern='^[a-zA-Z0-9_.][a-zA-Z0-9_.-]+$', required=False)
+option: Str('nisdomainname', attribute=True, autofill=False, cli_name='nisdomain', multivalue=False, pattern='^[a-zA-Z0-9_.][a-zA-Z0-9_.-]*$', required=False)
 option: StrEnum('usercategory', attribute=True, autofill=False, cli_name='usercat', multivalue=False, required=False, values=(u'all',))
 option: StrEnum('hostcategory', attribute=True, autofill=False, cli_name='hostcat', multivalue=False, required=False, values=(u'all',))
 option: Str('setattr*', cli_name='setattr', exclude='webui')
@@ -2007,7 +2007,7 @@ output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDA
 output: Output('value', <type 'unicode'>, None)
 command: netgroup_remove_member
 args: 1,8,3
-arg: Str('cn', attribute=True, cli_name='name', multivalue=False, pattern='^[a-zA-Z0-9_.][a-zA-Z0-9_.-]+$', primary_key=True, query=True, required=True)
+arg: Str('cn', attribute=True, cli_name='name', multivalue=False, pattern='^[a-zA-Z0-9_.][a-zA-Z0-9_.-]*$', primary_key=True, query=True, required=True)
 option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
 option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
 option: Str('version?', exclude='webui')
@@ -2021,7 +2021,7 @@ output: Output('failed', <type 'dict'>, None)
 output: Output('completed', <type 'int'>, None)
 command: netgroup_show
 args: 1,4,3
-arg: Str('cn', attribute=True, cli_name='name', multivalue=False, pattern='^[a-zA-Z0-9_.][a-zA-Z0-9_.-]+$', primary_key=True, query=True, required=True)
+arg: Str('cn', attribute=True, cli_name='name', multivalue=False, pattern='^[a-zA-Z0-9_.][a-zA-Z0-9_.-]*$', primary_key=True, query=True, required=True)
 option: Flag('rights', autofill=True, default=False)
 option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
 option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
diff --git a/VERSION b/VERSION
index a8327a0564724ba22031d5350974af5bee1a9067..f27fb473e65dd2db8e819d45e2dd84dc942bb41f 100644
--- a/VERSION
+++ b/VERSION
@@ -79,4 +79,4 @@ IPA_DATA_VERSION=20100614120000
 #                                                      #
 ########################################################
 IPA_API_VERSION_MAJOR=2
-IPA_API_VERSION_MINOR=34
+IPA_API_VERSION_MINOR=35
diff --git a/ipalib/plugins/netgroup.py b/ipalib/plugins/netgroup.py
index 693c00c1a83339cbe9056f10af61bd4e1c1712d1..d2a78098018fe23653fdfdd17ad73b9245905992 100644
--- a/ipalib/plugins/netgroup.py
+++ b/ipalib/plugins/netgroup.py
@@ -50,7 +50,7 @@ EXAMPLES:
 """)
 
 
-NETGROUP_PATTERN='^[a-zA-Z0-9_.][a-zA-Z0-9_.-]+$'
+NETGROUP_PATTERN='^[a-zA-Z0-9_.][a-zA-Z0-9_.-]*$'
 NETGROUP_PATTERN_ERRMSG='may only include letters, numbers, _, -, and .'
 
 # according to most common use cases the netgroup pattern should fit
diff --git a/tests/test_xmlrpc/test_host_plugin.py b/tests/test_xmlrpc/test_host_plugin.py
index b7b3567b6ca5e7c8593beb64c167fe529ac341f6..8798168afa71653b64870c77d11a7fa81ec4c952 100644
--- a/tests/test_xmlrpc/test_host_plugin.py
+++ b/tests/test_xmlrpc/test_host_plugin.py
@@ -698,7 +698,7 @@ class test_host(Declarative):
             command=('host_add', [invalidfqdn1], {}),
             expected=errors.ValidationError(name='hostname',
                 error=u'invalid domain-name: only letters, numbers, and - ' +
-                    u'are allowed. - must not be the DNS label character'),
+                    u'are allowed. DNS label may not start or end with -'),
         ),
 
 
diff --git a/tests/test_xmlrpc/test_hostgroup_plugin.py b/tests/test_xmlrpc/test_hostgroup_plugin.py
index eda5f02f816092d9d298d3bdc7a891cc5ec2cdf0..4f9b91c289f7149db9f34e0fda2bf095466e98b4 100644
--- a/tests/test_xmlrpc/test_hostgroup_plugin.py
+++ b/tests/test_xmlrpc/test_hostgroup_plugin.py
@@ -32,6 +32,10 @@ hostgroup1 = u'testhostgroup1'
 dn1 = DN(('cn',hostgroup1),('cn','hostgroups'),('cn','accounts'),
          api.env.basedn)
 
+hostgroup_single = u'a'
+dn1 = DN(('cn',hostgroup_single),('cn','hostgroups'),('cn','accounts'),
+         api.env.basedn)
+
 fqdn1 = u'testhost1.%s' % api.env.domain
 host_dn1 = DN(('fqdn',fqdn1),('cn','computers'),('cn','accounts'),
               api.env.basedn)
@@ -267,6 +271,39 @@ class test_hostgroup(Declarative):
 
 
         dict(
+            desc='Create  hostgroup with name containing only one letter: %r' % hostgroup_single,
+            command=('hostgroup_add', [hostgroup_single],
+                dict(description=u'Test hostgroup with single letter in name')
+            ),
+            expected=dict(
+                value=hostgroup_single,
+                summary=u'Added hostgroup "a"',
+                result=dict(
+                    dn=lambda x: DN(x) == dn1,
+                    cn=[hostgroup_single],
+                    objectclass=objectclasses.hostgroup,
+                    description=[u'Test hostgroup with single letter in name'],
+                    ipauniqueid=[fuzzy_uuid],
+                    mepmanagedentry=lambda x: [DN(i) for i in x] == \
+                        [DN(('cn',hostgroup_single),('cn','ng'),('cn','alt'),
+                            api.env.basedn)],
+                ),
+            ),
+        ),
+
+
+        dict(
+            desc='Delete %r' % hostgroup_single,
+            command=('hostgroup_del', [hostgroup_single], {}),
+            expected=dict(
+                value=hostgroup_single,
+                summary=u'Deleted hostgroup "a"',
+                result=dict(failed=u''),
+            ),
+        ),
+
+
+        dict(
             desc='Delete host %r' % fqdn1,
             command=('host_del', [fqdn1], {}),
             expected=dict(
diff --git a/tests/test_xmlrpc/test_netgroup_plugin.py b/tests/test_xmlrpc/test_netgroup_plugin.py
index afb2ac73429100b99515b9c5e25c8695fa798b8c..2bdc1bbf1f7a6830d9dde6146915adffbed5b644 100644
--- a/tests/test_xmlrpc/test_netgroup_plugin.py
+++ b/tests/test_xmlrpc/test_netgroup_plugin.py
@@ -38,6 +38,7 @@ ccache = krbV.default_context().default_ccache().name
 
 netgroup1 = u'netgroup1'
 netgroup2 = u'netgroup2'
+netgroup_single = u'a'
 
 host1 = u'ipatesthost.%s' % api.env.domain
 host_dn1 = DN(('fqdn',host1),('cn','computers'),('cn','accounts'),
@@ -173,6 +174,38 @@ class test_netgroup(Declarative):
 
 
         dict(
+            desc='Create netgroup with name containing only one letter: %r' % netgroup_single,
+            command=('netgroup_add', [netgroup_single],
+                dict(description=u'Test netgroup_single')
+            ),
+            expected=dict(
+                value=netgroup_single,
+                summary=u'Added netgroup "%s"' % netgroup_single,
+                result=dict(
+#                    dn=u'ipauniqueid=%s,cn=ng,cn=alt,%s' % (fuzzy_uuid, api.env.basedn),
+                    dn=fuzzy_netgroupdn,
+                    cn=[netgroup_single],
+                    objectclass=objectclasses.netgroup,
+                    description=[u'Test netgroup_single'],
+                    nisdomainname=['%s' % api.env.domain],
+                    ipauniqueid=[fuzzy_uuid],
+                ),
+            ),
+        ),
+
+
+        dict(
+            desc='Delete %r' % netgroup_single,
+            command=('netgroup_del', [netgroup_single], {}),
+            expected=dict(
+                value=netgroup_single,
+                summary=u'Deleted netgroup "%s"' % netgroup_single,
+                result=dict(failed=u''),
+            ),
+        ),
+
+
+        dict(
             desc='Try to create duplicate %r' % netgroup1,
             command=('netgroup_add', [netgroup1],
                 dict(description=u'Test netgroup 1')
@@ -363,7 +396,7 @@ class test_netgroup(Declarative):
             desc='Add invalid host %r to netgroup %r' % (invalidhost, netgroup1),
             command=('netgroup_add_member', [netgroup1], dict(host=invalidhost)),
             expected=errors.ValidationError(name='host',
-             error='only letters, numbers, _, and - are allowed. - must not be the DNS label character'),
+             error='only letters, numbers, _, and - are allowed. DNS label may not start or end with -'),
         ),
 
 
-- 
1.7.6.5

_______________________________________________
Freeipa-devel mailing list
Freeipa-devel@redhat.com
https://www.redhat.com/mailman/listinfo/freeipa-devel

Reply via email to