https://fedorahosted.org/freeipa/ticket/4421
--
David Kupka
From 77faaa3c7887550b493f86f90f654da8e1f42eee Mon Sep 17 00:00:00 2001
From: David Kupka <dku...@redhat.com>
Date: Tue, 2 Sep 2014 16:11:55 +0200
Subject: [PATCH] Allow multiple krbprincipalnames.

Allow user to specify multiple krbprincipalnames and  krbcanonicalname.
User must have "IT specialist" role or "Host Administrators" privilege
assigned.

https://fedorahosted.org/freeipa/ticket/4421
---
 ACI.txt                |  4 +++-
 API.txt                |  2 +-
 ipalib/plugins/host.py | 21 +++++++++++++--------
 3 files changed, 17 insertions(+), 10 deletions(-)

diff --git a/ACI.txt b/ACI.txt
index 1e6bec0ece554fb2457fae0462c0c673a9b24e41..2a83af6ffba230f2d6ba5ec521652dc2312ce6d0 100644
--- a/ACI.txt
+++ b/ACI.txt
@@ -85,7 +85,9 @@ aci: (targetattr = "businesscategory || cn || createtimestamp || description ||
 dn: cn=computers,cn=accounts,dc=ipa,dc=example
 aci: (targetfilter = "(objectclass=ipahost)")(version 3.0;acl "permission:System: Add Hosts";allow (add) groupdn = "ldap:///cn=System: Add Hosts,cn=permissions,cn=pbac,dc=ipa,dc=example";)
 dn: cn=computers,cn=accounts,dc=ipa,dc=example
-aci: (targetattr = "krbprincipalname")(targetfilter = "(&(!(krbprincipalname=*))(objectclass=ipahost))")(version 3.0;acl "permission:System: Add krbPrincipalName to a Host";allow (write) groupdn = "ldap:///cn=System: Add krbPrincipalName to a Host,cn=permissions,cn=pbac,dc=ipa,dc=example";)
+aci: (targetattr = "krbcanonicalname")(targetfilter = "(objectclass=ipahost)")(version 3.0;acl "permission:System: Add krbCanonicalName to a Host";allow (write) groupdn = "ldap:///cn=System: Add krbCanonicalName to a Host,cn=permissions,cn=pbac,dc=ipa,dc=example";)
+dn: cn=computers,cn=accounts,dc=ipa,dc=example
+aci: (targetattr = "krbprincipalname")(targetfilter = "(objectclass=ipahost)")(version 3.0;acl "permission:System: Add krbPrincipalName to a Host";allow (write) groupdn = "ldap:///cn=System: Add krbPrincipalName to a Host,cn=permissions,cn=pbac,dc=ipa,dc=example";)
 dn: cn=computers,cn=accounts,dc=ipa,dc=example
 aci: (targetattr = "enrolledby || objectclass")(targetfilter = "(objectclass=ipahost)")(version 3.0;acl "permission:System: Enroll a Host";allow (write) groupdn = "ldap:///cn=System: Enroll a Host,cn=permissions,cn=pbac,dc=ipa,dc=example";)
 dn: cn=computers,cn=accounts,dc=ipa,dc=example
diff --git a/API.txt b/API.txt
index bbd0f507b2faeec0239920cdcff28fe25d618e02..ef1f70397e7685161821a98a92ea575aa6eff532 100644
--- a/API.txt
+++ b/API.txt
@@ -1884,7 +1884,7 @@ option: Str('description', attribute=True, autofill=False, cli_name='desc', mult
 option: Bool('ipakrbokasdelegate', attribute=False, autofill=False, cli_name='ok_as_delegate', multivalue=False, required=False)
 option: Bool('ipakrbrequirespreauth', attribute=False, autofill=False, cli_name='requires_pre_auth', multivalue=False, required=False)
 option: Str('ipasshpubkey', attribute=True, autofill=False, cli_name='sshpubkey', csv=True, multivalue=True, required=False)
-option: Str('krbprincipalname?', attribute=True, cli_name='principalname')
+option: Str('krbprincipalname?', attribute=True, cli_name='principalname', multivalue=True)
 option: Str('l', attribute=True, autofill=False, cli_name='locality', multivalue=False, required=False)
 option: Str('macaddress', attribute=True, autofill=False, cli_name='macaddress', csv=True, multivalue=True, pattern='^([a-fA-F0-9]{2}[:|\\-]?){5}[a-fA-F0-9]{2}$', required=False)
 option: Flag('no_members', autofill=True, default=False, exclude='webui')
diff --git a/ipalib/plugins/host.py b/ipalib/plugins/host.py
index 570bbe56aa0a315a031051f9a895702ba7c35076..53c2b95b44063049d64e8ad96bd5e52f1e1cab48 100644
--- a/ipalib/plugins/host.py
+++ b/ipalib/plugins/host.py
@@ -303,16 +303,17 @@ class host(LDAPObject):
             # This will let it be added if the client ends up enrolling with
             # an administrator instead.
             'ipapermright': {'write'},
-            'ipapermtargetfilter': [
-                '(objectclass=ipahost)',
-                '(!(krbprincipalname=*))',
-            ],
             'ipapermdefaultattr': {'krbprincipalname'},
             'replaces': [
                 '(target = "ldap:///fqdn=*,cn=computers,cn=accounts,$SUFFIX";)(targetfilter = "(!(krbprincipalname=*))")(targetattr = "krbprincipalname")(version 3.0;acl "permission:Add krbPrincipalName to a host"; allow (write) groupdn = "ldap:///cn=Add krbPrincipalName to a host,cn=permissions,cn=pbac,$SUFFIX";)',
             ],
             'default_privileges': {'Host Administrators', 'Host Enrollment'},
         },
+        'System: Add krbCanonicalName to a Host': {
+            'ipapermright': {'write'},
+            'ipapermdefaultattr': {'krbcanonicalname'},
+            'default_privileges': {'Host Administrators'},
+        },
         'System: Enroll a Host': {
             'ipapermright': {'write'},
             'ipapermdefaultattr': {'objectclass', 'enrolledby'},
@@ -761,6 +762,7 @@ class host_mod(LDAPUpdate):
             label=_('Principal name'),
             doc=_('Kerberos principal name for this host'),
             attribute=True,
+            multivalue=True,
         ),
         Flag('updatedns?',
             doc=_('Update DNS entries'),
@@ -785,11 +787,14 @@ class host_mod(LDAPUpdate):
             entry_attrs['l'] = entry_attrs['locality']
         if 'krbprincipalname' in entry_attrs:
             entry_attrs_old = ldap.get_entry(
-                dn, ['objectclass', 'krbprincipalname']
+                dn, ['objectclass', 'krbprincipalname', 'krbcanonicalname']
             )
-            if 'krbprincipalname' in entry_attrs_old:
-                msg = 'Principal name already set, it is unchangeable.'
-                raise errors.ACIError(info=msg)
+            print(entry_attrs_old)
+            if 'krbprincipalname' in entry_attrs_old and \
+                    'krbcanonicalname' not in entry_attrs and \
+                    'krbcanonicalname' not in entry_attrs_old:
+                msg = 'must be set when specifying multiple krbPrincipalName attributes.'
+                raise errors.ValidationError(name='krbCanonicalName', error=msg)
             obj_classes = entry_attrs_old['objectclass']
             if 'krbprincipalaux' not in obj_classes:
                 obj_classes.append('krbprincipalaux')
-- 
1.9.3

From bedf4efd6cd88f85d99163775e805cd2d7dd81e0 Mon Sep 17 00:00:00 2001
From: David Kupka <dku...@redhat.com>
Date: Thu, 18 Sep 2014 01:53:49 -0400
Subject: [PATCH] Test: Allow multiple krbPrincipalNames

Allow to add multiple krbPrincipalName. krbCanonicalName must be specified
when adding second and next krbPrincipalName.

Related to: https://fedorahosted.org/freeipa/ticket/4421
---
 ipatests/test_xmlrpc/test_host_plugin.py | 137 ++++++++++++++++++++++++++++++-
 1 file changed, 136 insertions(+), 1 deletion(-)

diff --git a/ipatests/test_xmlrpc/test_host_plugin.py b/ipatests/test_xmlrpc/test_host_plugin.py
index 7c0312bae5e9e652085aac8f1970610044504281..21e9aca80b1394281650588369dee29b53bbbf3a 100644
--- a/ipatests/test_xmlrpc/test_host_plugin.py
+++ b/ipatests/test_xmlrpc/test_host_plugin.py
@@ -32,7 +32,7 @@ from nose.tools import raises, assert_raises
 from nose.plugins.skip import SkipTest
 from ipatests.test_xmlrpc.xmlrpc_test import (Declarative, XMLRPC_test,
     fuzzy_uuid, fuzzy_digits, fuzzy_hash, fuzzy_date, fuzzy_issuer,
-    fuzzy_hex)
+    fuzzy_hex, fuzzy_string)
 from ipatests.test_xmlrpc import objectclasses
 from ipatests.test_xmlrpc.testcert import get_testcert
 import base64
@@ -136,6 +136,18 @@ ipv6_fromip_ptr_dn = DN(('idnsname', ipv6_fromip_ptr), revipv6zone_dn)
 sshpubkey = u'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDGAX3xAeLeaJggwTqMjxNwa6XHBUAikXPGMzEpVrlLDCZtv00djsFTBi38PkgxBJVkgRWMrcBsr/35lq7P6w8KGIwA8GI48Z0qBS2NBMJ2u9WQ2hjLN6GdMlo77O0uJY3251p12pCVIS/bHRSq8kHO2No8g7KA9fGGcagPfQH+ee3t7HUkpbQkFTmbPPN++r3V8oVUk5LxbryB3UIIVzNmcSIn3JrXynlvui4MixvrtX6zx+O/bBo68o8/eZD26QrahVbA09fivrn/4h3TM019Eu/c2jOdckfU3cHUV/3Tno5d6JicibyaoDDK7S/yjdn5jhaz8MSEayQvFkZkiF0L public key test'
 sshpubkeyfp = u'13:67:6B:BF:4E:A2:05:8E:AE:25:8B:A1:31:DE:6F:1B public key test (ssh-rsa)'
 
+
+# multiple krbPrincipalNames test
+host5 = u'test'
+fqdn5 = u'%s.%s' % (host5, api.env.domain)
+dn5 = DN(('fqdn',fqdn5),('cn','computers'),('cn','accounts'),api.env.basedn)
+principalname1 = u'host/%s@%s' % (fqdn5, api.env.realm)
+principalname2 = u'IPA01$@%s' % api.env.realm
+canonicalname = principalname1
+ipaddress = u'172.16.0.1'
+it_spec_role_dn = DN(('cn',u'IT Specialist'),api.env.container_rolegroup,
+              api.env.basedn)
+
 class test_host(Declarative):
 
     cleanup_commands = [
@@ -1403,3 +1415,126 @@ class test_host_dns(Declarative):
             ),
         ),
     ]
+
+class test_host_multiple_krbprincipalnames(Declarative):
+    cleanup_commands = [
+        ('host_del', [fqdn5], {'continue': True}),
+        ('dnsrecord_del', [api.env.domain, host5], {'del_all': True}),
+        ('role_remove_member', [u'IT Specialist'], {'user': u'admin'}),
+    ]
+
+    tests = [
+
+        # TODO: remove if admin gets 'IT Specialist' role
+        dict(
+            desc='Assign role IT Specialist to user admin',
+            command=('role_add_member', [u'IT Specialist'], {'user': u'admin'}
+            ),
+            expected=dict(
+                completed=1,
+                result=dict(
+                    dn=it_spec_role_dn,
+                    description=(u'IT Specialist',),
+                    memberofindirect=[fuzzy_string]*28,
+                    memberof_privilege=[fuzzy_string]*4,
+                    member_user=[u'admin'],
+                    cn=[u'IT Specialist'],
+                ),
+                failed=dict(
+                    member=dict(
+                        host=(),
+                        group=(),
+                        hostgroup=(),
+                        service=(),
+                        user=(),
+                    ),
+                ),
+            ),
+        ),
+
+        dict(
+            desc='Add host %s' % fqdn5,
+            command=('host_add', [fqdn5], {'ip_address': ipaddress, 'no_reverse': True}
+            ),
+            expected=dict(
+                value=fqdn5,
+                summary=u'Added host "%s"' % fqdn5,
+                result=dict(
+                    dn=dn5,
+                    fqdn=[fqdn5],
+                    has_keytab=False,
+                    has_password=False,
+                    ipauniqueid=[fuzzy_uuid],
+                    krbprincipalname=[principalname1],
+                    managedby_host=[fqdn5],
+                    objectclass=objectclasses.host,
+                ),
+            ),
+        ),
+
+        dict(
+            desc='Add krbCanonicalName %s' % canonicalname,
+            command=('host_mod', [fqdn5], {'addattr': u'krbcanonicalname=%s' % canonicalname}
+            ),
+            expected=dict(
+                value=fqdn5,
+                summary=u'Modified host "%s"' % fqdn5,
+                result=dict(
+                    fqdn=[fqdn5],
+                    has_keytab=False,
+                    has_password=False,
+                    krbcanonicalname=[canonicalname],
+                    krbprincipalname=[principalname1],
+                    managedby_host=[fqdn5]
+                ),
+            ),
+        ),
+
+        dict(
+            desc='Add kbrPrincipalName %s' % principalname2,
+            command=('host_mod', [fqdn5], {'addattr': u'krbprincipalname=%s' % principalname2}
+            ),
+            expected=dict(
+                value=fqdn5,
+                summary=u'Modified host "%s"' % fqdn5,
+                result=dict(
+                    fqdn=[fqdn5],
+                    has_keytab=False,
+                    has_password=False,
+                    krbprincipalname=[principalname1, principalname2],
+                    managedby_host=[fqdn5]
+                ),
+            ),
+        ),
+    ]
+
+class test_host_fail_to_add_krbprincipalname_when_krbcanonicalname_missing(XMLRPC_test):
+
+    # TODO: Remove when/if admin is in that group by default
+    def test_1_assign_role_it_specialist_to_admin(self):
+        """
+        Add 'IT Specialist' role to admin
+        """
+        api.Command['role_add_member'](u'IT Specialist', user=[u'admin'])
+
+
+    def test_2_create_host(self):
+        """
+        Create host
+        """
+        api.Command['host_add'](fqdn5, ip_address=ipaddress, no_reverse=True)
+
+    @raises(errors.ValidationError)
+    def test_3_try_add_second_krbPrincipalName(self):
+        """
+        Fail to add second krbPrincipalName without krbCanonicalName
+        """
+        api.Command['host_mod'](fqdn5, addattr=u'krbprincipalname=%s' % principalname2)
+
+    def test_4_cleanup(self):
+        """
+        CLEANUP: Remove host and remove 'IT Specialist' role for admin
+        """
+        api.Command['host_del'](fqdn5)
+        api.Command['dnsrecord_del'](api.env.domain, host5, del_all=True)
+        api.Command['role_remove_member'](u'IT Specialist', user=u'admin')
-- 
1.9.3

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

Reply via email to