summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--install/share/default-aci.ldif8
-rw-r--r--ipalib/plugins/host.py36
-rw-r--r--tests/test_xmlrpc/test_host_plugin.py112
-rw-r--r--tests/test_xmlrpc/test_hostgroup_plugin.py1
-rw-r--r--tests/test_xmlrpc/test_netgroup_plugin.py1
-rw-r--r--tests/test_xmlrpc/test_service_plugin.py2
6 files changed, 154 insertions, 6 deletions
diff --git a/install/share/default-aci.ldif b/install/share/default-aci.ldif
index 2ca30069..e03c65c4 100644
--- a/install/share/default-aci.ldif
+++ b/install/share/default-aci.ldif
@@ -51,3 +51,11 @@ changetype: modify
add: aci
aci: (targetattr="userCertificate || krbLastPwdChange")(version 3.0; acl "Hosts can modify service userCertificate"; allow(write) userdn = "ldap:///self";)
+# Define which hosts can edit other hosts
+# The managedby attribute stores the DN of hosts that are allowed to manage
+# another host.
+dn: cn=computers,cn=accounts,$SUFFIX
+changetype: modify
+add: aci
+aci: (targetattr="userCertificate || krbPrincipalKey")(version 3.0; acl "Hosts can manage other host Certificates and kerberos keys"; allow(write) userattr = "parent[0,1].managedby#USERDN";)
+
diff --git a/ipalib/plugins/host.py b/ipalib/plugins/host.py
index 23728fad..2e77dd5f 100644
--- a/ipalib/plugins/host.py
+++ b/ipalib/plugins/host.py
@@ -65,6 +65,9 @@ EXAMPLES:
Disable the host kerberos key:
ipa host-disable test.example.com
+
+ Add a host that can manage this host's keytab and certificate:
+ ipa host-add-managedby --hosts=test2 test
"""
import platform
@@ -98,6 +101,9 @@ host_output_params = (
Flag('has_keytab',
label=_('Keytab'),
),
+ Str('managedby_host',
+ label='Managed by',
+ ),
Str('subject',
label=_('Subject'),
),
@@ -135,17 +141,18 @@ class host(LDAPObject):
# object_class_config = 'ipahostobjectclasses'
search_attributes = [
'fqdn', 'description', 'l', 'nshostlocation', 'krbprincipalname',
- 'nshardwareplatform', 'nsosversion',
+ 'nshardwareplatform', 'nsosversion', 'managedby'
]
default_attributes = [
'fqdn', 'description', 'l', 'nshostlocation', 'krbprincipalname',
'nshardwareplatform', 'nsosversion', 'usercertificate', 'memberof',
- 'krblastpwdchange',
+ 'krblastpwdchange', 'managedby'
]
uuid_attribute = 'ipauniqueid'
attribute_members = {
'enrolledby': ['user'],
'memberof': ['hostgroup', 'netgroup', 'rolegroup'],
+ 'managedby': ['host'],
}
label = _('Hosts')
@@ -233,6 +240,7 @@ class host_add(LDAPCreate):
has_output_params = LDAPCreate.has_output_params + host_output_params
msg_summary = _('Added host "%(value)s"')
+ member_attributes = ['managedby']
takes_options = (
Flag('force',
doc=_('force host name even if not in DNS'),
@@ -286,6 +294,7 @@ class host_del(LDAPDelete):
"""
msg_summary = _('Deleted host "%(value)s"')
+ member_attributes = ['managedby']
def pre_callback(self, ldap, dn, *keys, **options):
# If we aren't given a fqdn, find it
@@ -346,6 +355,7 @@ class host_mod(LDAPUpdate):
has_output_params = LDAPUpdate.has_output_params + host_output_params
msg_summary = _('Modified host "%(value)s"')
+ member_attributes = ['managedby']
takes_options = LDAPUpdate.takes_options + (
Str('krbprincipalname?',
@@ -404,7 +414,6 @@ class host_mod(LDAPUpdate):
entry_attrs['userpassword'] = ipa_generate_password()
setattr(context, 'randompassword', entry_attrs['userpassword'])
del entry_attrs['random']
- entry_attrs['managedby'] = dn
return dn
@@ -426,6 +435,7 @@ class host_find(LDAPSearch):
msg_summary = ngettext(
'%(count)d host matched', '%(count)d hosts matched'
)
+ member_attributes = ['managedby']
def pre_callback(self, ldap, filter, attrs_list, base_dn, *args, **options):
if 'locality' in attrs_list:
@@ -446,6 +456,7 @@ class host_show(LDAPRetrieve):
Display information about a host.
"""
has_output_params = LDAPRetrieve.has_output_params + host_output_params
+ member_attributes = ['managedby']
def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
if 'krblastpwdchange' in entry_attrs:
@@ -545,3 +556,22 @@ class host_disable(LDAPQuery):
)
api.register(host_disable)
+
+class host_add_managedby(LDAPAddMember):
+ """
+ Add hosts that can manage this host.
+ """
+ member_attributes = ['managedby']
+ has_output_params = LDAPAddMember.has_output_params + host_output_params
+
+api.register(host_add_managedby)
+
+
+class host_remove_managedby(LDAPRemoveMember):
+ """
+ Remove hosts that can manage this host.
+ """
+ member_attributes = ['managedby']
+ has_output_params = LDAPRemoveMember.has_output_params + host_output_params
+
+api.register(host_remove_managedby)
diff --git a/tests/test_xmlrpc/test_host_plugin.py b/tests/test_xmlrpc/test_host_plugin.py
index 283674c2..6026efea 100644
--- a/tests/test_xmlrpc/test_host_plugin.py
+++ b/tests/test_xmlrpc/test_host_plugin.py
@@ -35,6 +35,9 @@ service1 = u'dns/%s@%s' % (fqdn1, api.env.realm)
service1dn = u'krbprincipalname=%s,cn=services,cn=accounts,%s' % (service1.lower(), api.env.basedn)
fqdn2 = u'shouldnotexist.%s' % api.env.domain
dn2 = u'fqdn=%s,cn=computers,cn=accounts,%s' % (fqdn2, api.env.basedn)
+fqdn3 = u'testhost2.%s' % api.env.domain
+short3 = u'testhost2'
+dn3 = u'fqdn=%s,cn=computers,cn=accounts,%s' % (fqdn3, api.env.basedn)
servercert = 'MIICbzCCAdigAwIBAgICA/4wDQYJKoZIhvcNAQEFBQAwKTEnMCUGA1UEAxMeSVBBIFRlc3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4XDTEwMDgwOTE1MDIyN1oXDTIwMDgwOTE1MDIyN1owKTEMMAoGA1UEChMDSVBBMRkwFwYDVQQDExBwdW1hLmdyZXlvYWsuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwYbfEOQPgGenPn9vt1JFKvWm/Je3y2tawGWA3LXDuqfFJyYtZ8ib3TcBUOnLk9WK5g2qCwHaNlei7bj8ggIfr5hegAVe10cun+wYErjnYo7hsHYd+57VZezeipWrXu+7NoNd4+c4A5lk4A/xJay9j3bYx2oOM8BEox4xWYoWge1ljPrc5JK46f0X7AGW4F2VhnKPnf8rwSuzI1U8VGjutyM9TWNy3m9KMWeScjyG/ggIpOjUDMV7HkJL0Di61lznR9jXubpiEC7gWGbTp84eGl/Nn9bgK1AwHfJ2lHwfoY4uiL7ge1gyP6EvuUlHoBzdb7pekiX28iePjW3iEG9IawIDAQABoyIwIDARBglghkgBhvhCAQEEBAMCBkAwCwYDVR0PBAQDAgUgMA0GCSqGSIb3DQEBBQUAA4GBACRESLemRV9BPxfEgbALuxH5oE8jQm8WZ3pm2pALbpDlAd9wQc3yVf6RtkfVthyDnM18bg7IhxKpd77/p3H8eCnS8w5MLVRda6ktUC6tGhFTS4QKAf0WyDGTcIgkXbeDw0OPAoNHivoXbIXIIRxlw/XgaSaMzJQDBG8iROsN4kCv'
@@ -44,6 +47,7 @@ class test_host(Declarative):
cleanup_commands = [
('host_del', [fqdn1], {}),
('host_del', [fqdn2], {}),
+ ('host_del', [fqdn3], {}),
('service_del', [service1], {}),
]
@@ -90,6 +94,7 @@ class test_host(Declarative):
krbprincipalname=[u'host/%s@%s' % (fqdn1, api.env.realm)],
objectclass=objectclasses.host,
ipauniqueid=[fuzzy_uuid],
+ managedby_host=[fqdn1],
),
),
),
@@ -120,7 +125,8 @@ class test_host(Declarative):
description=[u'Test host 1'],
l=[u'Undisclosed location 1'],
krbprincipalname=[u'host/%s@%s' % (fqdn1, api.env.realm)],
- has_keytab=False
+ has_keytab=False,
+ managedby_host=[fqdn1],
),
),
),
@@ -145,7 +151,7 @@ class test_host(Declarative):
krbprincipalname=[u'host/%s@%s' % (fqdn1, api.env.realm)],
serverhostname=[u'testhost1'],
objectclass=objectclasses.host,
- managedby=[dn1],
+ managedby_host=[fqdn1],
ipauniqueid=[fuzzy_uuid],
has_keytab=False
),
@@ -167,6 +173,7 @@ class test_host(Declarative):
description=[u'Test host 1'],
l=[u'Undisclosed location 1'],
krbprincipalname=[u'host/%s@%s' % (fqdn1, api.env.realm)],
+ managedby_host=[u'%s' % fqdn1],
),
],
),
@@ -194,8 +201,8 @@ class test_host(Declarative):
krbprincipalname=[u'host/%s@%s' % (fqdn1, api.env.realm)],
serverhostname=[u'testhost1'],
objectclass=objectclasses.host,
- managedby=[dn1],
ipauniqueid=[fuzzy_uuid],
+ managedby_host=[u'%s' % fqdn1],
),
],
),
@@ -214,6 +221,7 @@ class test_host(Declarative):
fqdn=[fqdn1],
l=[u'Undisclosed location 1'],
krbprincipalname=[u'host/%s@%s' % (fqdn1, api.env.realm)],
+ managedby_host=[u'%s' % fqdn1],
usercertificate=[base64.b64decode(servercert)],
valid_not_before=u'Mon Aug 09 15:02:27 2010 UTC',
valid_not_after=u'Sun Aug 09 15:02:27 2020 UTC',
@@ -240,6 +248,7 @@ class test_host(Declarative):
l=[u'Undisclosed location 1'],
krbprincipalname=[u'host/%s@%s' % (fqdn1, api.env.realm)],
has_keytab=False,
+ managedby_host=[u'%s' % fqdn1],
usercertificate=[base64.b64decode(servercert)],
valid_not_before=u'Mon Aug 09 15:02:27 2010 UTC',
valid_not_after=u'Sun Aug 09 15:02:27 2020 UTC',
@@ -252,6 +261,101 @@ class test_host(Declarative):
),
),
+ dict(
+ desc='Create %r' % fqdn3,
+ command=('host_add', [fqdn3],
+ dict(
+ description=u'Test host 2',
+ l=u'Undisclosed location 2',
+ force=True,
+ ),
+ ),
+ expected=dict(
+ value=fqdn3,
+ summary=u'Added host "%s"' % fqdn3,
+ result=dict(
+ dn=dn3,
+ fqdn=[fqdn3],
+ description=[u'Test host 2'],
+ l=[u'Undisclosed location 2'],
+ krbprincipalname=[u'host/%s@%s' % (fqdn3, api.env.realm)],
+ objectclass=objectclasses.host,
+ ipauniqueid=[fuzzy_uuid],
+ managedby_host=[u'%s' % fqdn3],
+ ),
+ ),
+ ),
+
+
+ dict(
+ desc='Add managedby_host %r to %r' % (fqdn1, fqdn3),
+ command=('host_add_managedby', [fqdn3],
+ dict(
+ host=u'%s' % fqdn1,
+ ),
+ ),
+ expected=dict(
+ completed=1,
+ failed=dict(
+ managedby = dict(
+ host=tuple(),
+ ),
+ ),
+ result=dict(
+ dn=dn3,
+ fqdn=[fqdn3],
+ description=[u'Test host 2'],
+ l=[u'Undisclosed location 2'],
+ krbprincipalname=[u'host/%s@%s' % (fqdn3, api.env.realm)],
+ managedby_host=[u'%s' % fqdn3, u'%s' % fqdn1],
+ ),
+ ),
+ ),
+
+ dict(
+ desc='Retrieve %r' % fqdn3,
+ command=('host_show', [fqdn3], {}),
+ expected=dict(
+ value=fqdn3,
+ summary=None,
+ result=dict(
+ dn=dn3,
+ fqdn=[fqdn3],
+ description=[u'Test host 2'],
+ l=[u'Undisclosed location 2'],
+ krbprincipalname=[u'host/%s@%s' % (fqdn3, api.env.realm)],
+ has_keytab=False,
+ managedby_host=[u'%s' % fqdn3, u'%s' % fqdn1],
+ ),
+ ),
+ ),
+
+ dict(
+ desc='Remove managedby_host %r from %r' % (fqdn1, fqdn3),
+ command=('host_remove_managedby', [fqdn3],
+ dict(
+ host=u'%s' % fqdn1,
+ ),
+ ),
+ expected=dict(
+ completed=1,
+ failed=dict(
+ managedby = dict(
+ host=tuple(),
+ ),
+ ),
+ result=dict(
+ dn=dn3,
+ fqdn=[fqdn3],
+ description=[u'Test host 2'],
+ l=[u'Undisclosed location 2'],
+ krbprincipalname=[u'host/%s@%s' % (fqdn3, api.env.realm)],
+ managedby_host=[u'%s' % fqdn3],
+ ),
+ ),
+ ),
+
+
dict(
desc='Try to rename %r' % fqdn1,
@@ -313,6 +417,7 @@ class test_host(Declarative):
krbprincipalname=[u'host/%s@%s' % (fqdn1, api.env.realm)],
objectclass=objectclasses.host,
ipauniqueid=[fuzzy_uuid],
+ managedby_host=[u'%s' % fqdn1],
),
),
),
@@ -383,6 +488,7 @@ class test_host(Declarative):
krbprincipalname=[u'host/%s@%s' % (fqdn2, api.env.realm)],
objectclass=objectclasses.host,
ipauniqueid=[fuzzy_uuid],
+ managedby_host=[u'%s' % fqdn2],
),
),
),
diff --git a/tests/test_xmlrpc/test_hostgroup_plugin.py b/tests/test_xmlrpc/test_hostgroup_plugin.py
index 70cbe3d4..1d143f0c 100644
--- a/tests/test_xmlrpc/test_hostgroup_plugin.py
+++ b/tests/test_xmlrpc/test_hostgroup_plugin.py
@@ -113,6 +113,7 @@ class test_hostgroup(Declarative):
krbprincipalname=[u'host/%s@%s' % (fqdn1, api.env.realm)],
objectclass=objectclasses.host,
ipauniqueid=[fuzzy_uuid],
+ managedby_host=[fqdn1],
),
),
),
diff --git a/tests/test_xmlrpc/test_netgroup_plugin.py b/tests/test_xmlrpc/test_netgroup_plugin.py
index 76874daa..4c3aeafc 100644
--- a/tests/test_xmlrpc/test_netgroup_plugin.py
+++ b/tests/test_xmlrpc/test_netgroup_plugin.py
@@ -164,6 +164,7 @@ class test_netgroup(Declarative):
krbprincipalname=[u'host/%s@%s' % (host1, api.env.realm)],
objectclass=objectclasses.host,
ipauniqueid=[fuzzy_uuid],
+ managedby_host=[host1],
),
),
),
diff --git a/tests/test_xmlrpc/test_service_plugin.py b/tests/test_xmlrpc/test_service_plugin.py
index fc8e08e9..5cd9cff9 100644
--- a/tests/test_xmlrpc/test_service_plugin.py
+++ b/tests/test_xmlrpc/test_service_plugin.py
@@ -88,6 +88,7 @@ class test_host(Declarative):
krbprincipalname=[u'host/%s@%s' % (fqdn1, api.env.realm)],
objectclass=objectclasses.host,
ipauniqueid=[fuzzy_uuid],
+ managedby_host=[u'%s' % fqdn1],
),
),
),
@@ -113,6 +114,7 @@ class test_host(Declarative):
krbprincipalname=[u'host/%s@%s' % (fqdn2, api.env.realm)],
objectclass=objectclasses.host,
ipauniqueid=[fuzzy_uuid],
+ managedby_host=[u'%s' % fqdn2],
),
),
),