summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--install/share/60basev2.ldif3
-rw-r--r--install/share/default-aci.ldif7
-rw-r--r--ipalib/plugins/cert.py51
-rw-r--r--ipalib/plugins/rolegroup.py6
-rw-r--r--ipalib/plugins/service.py28
-rw-r--r--ipaserver/plugins/ldap2.py2
6 files changed, 52 insertions, 45 deletions
diff --git a/install/share/60basev2.ldif b/install/share/60basev2.ldif
index 7c3fa43bd..9296e0607 100644
--- a/install/share/60basev2.ldif
+++ b/install/share/60basev2.ldif
@@ -4,9 +4,10 @@ attributeTypes: (2.16.840.1.113730.3.8.3.2 NAME 'ipaClientVersion' DESC 'Text st
attributeTypes: (2.16.840.1.113730.3.8.3.3 NAME 'enrolledBy' DESC 'DN of administrator who performed manual enrollment of the host' SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 X-ORIGIN 'IPA v2' )
attributeTypes: (2.16.840.1.113730.3.8.3.4 NAME 'enrollmentPwd' DESC 'Password used to bulk enroll machines' EQUALITY octetStringMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.40{128} X-ORIGIN 'IPA v2' )
attributeTypes: (2.16.840.1.113730.3.8.3.43 NAME 'fqdn' DESC 'FQDN' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'IPA v2' )
+attributeTypes: (2.16.840.1.113730.3.8.3.53 NAME 'managedBy' DESC 'DNs of entries allowed to manage' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'IPA v2')
objectClasses: (2.16.840.1.113730.3.8.4.1 NAME 'ipaHost' AUXILIARY MUST ( fqdn ) MAY ( userPassword $ ipaClientVersion $ enrolledBy $ memberOf) X-ORIGIN 'IPA v2' )
objectClasses: (2.16.840.1.113730.3.8.4.44 NAME 'ipaObject' DESC 'IPA objectclass' AUXILIARY MUST ( ipaUniqueId ) X-ORIGIN 'IPA v2' )
-objectClasses: (2.16.840.1.113730.3.8.4.2 NAME 'ipaService' DESC 'IPA service objectclass' AUXILIARY MAY ( memberOf ) X-ORIGIN 'IPA v2' )
+objectClasses: (2.16.840.1.113730.3.8.4.2 NAME 'ipaService' DESC 'IPA service objectclass' AUXILIARY MAY ( memberOf $ managedBy ) X-ORIGIN 'IPA v2' )
objectClasses: (2.16.840.1.113730.3.8.4.3 NAME 'nestedGroup' DESC 'Group that supports nesting' SUP groupOfNames STRUCTURAL MAY memberOf X-ORIGIN 'IPA v2' )
objectClasses: (2.16.840.1.113730.3.8.4.4 NAME 'ipaUserGroup' DESC 'IPA user group object class' SUP nestedGroup STRUCTURAL X-ORIGIN 'IPA v2' )
objectClasses: (2.16.840.1.113730.3.8.4.5 NAME 'ipaHostGroup' DESC 'IPA host group object class' SUP nestedGroup STRUCTURAL X-ORIGIN 'IPA v2' )
diff --git a/install/share/default-aci.ldif b/install/share/default-aci.ldif
index 25bd3b224..7f08518b8 100644
--- a/install/share/default-aci.ldif
+++ b/install/share/default-aci.ldif
@@ -36,3 +36,10 @@ dn: cn=services,cn=accounts,$SUFFIX
changetype: modify
add: aci
aci: (targetattr="krbPrincipalName || krbUPEnabled || krbPrincipalKey || krbTicketPolicyReference || krbPrincipalExpiration || krbPasswordExpiration || krbPwdPolicyReference || krbPrincipalType || krbPwdHistory || krbLastPwdChange || krbPrincipalAliases || krbExtraData")(version 3.0; acl "KDC System Account"; allow (read, search, compare, write) userdn="ldap:///uid=kdc,cn=sysaccounts,cn=etc,$SUFFIX";)
+
+# Define which hosts can edit services
+dn: cn=services,cn=accounts,$SUFFIX
+changetype: modify
+add: aci
+aci: (targetattr=userCertificate)(version 3.0; aci "Hosts can modify service userCertificate"; allow(write) userattr = "parent[0,1].managedby#USERDN";)
+
diff --git a/ipalib/plugins/cert.py b/ipalib/plugins/cert.py
index 9750de6f4..0416730f8 100644
--- a/ipalib/plugins/cert.py
+++ b/ipalib/plugins/cert.py
@@ -102,6 +102,7 @@ class cert_request(VirtualCommand):
)
def execute(self, csr, **kw):
+ ldap = self.api.Backend.ldap2
skw = {"all": True}
principal = kw.get('principal')
add = kw.get('add')
@@ -121,35 +122,6 @@ class cert_request(VirtualCommand):
if subject_host.lower() != hostname.lower():
raise errors.ACIError(info="hostname in subject of request '%s' does not match principal hostname '%s'" % (subject_host, hostname))
- # Get the IP address of the machine that submitted the request. We
- # will compare this to the subjectname of the CSR.
- client_ip = getattr(context, 'client_ip')
- rhost = None
- if client_ip not in (None, ''):
- rev = client_ip.split('.')
- if len(rev) == 0:
- rev = client_ip.split(':')
- rev.reverse()
- addr = "%s.in-addr.arpa." % ".".join(rev)
- else:
- rev.reverse()
- addr = "%s.in-addr.arpa." % ".".join(rev)
- rs = dnsclient.query(addr, dnsclient.DNS_C_IN, dnsclient.DNS_T_PTR)
- if len(rs) == 0:
- raise errors.ACIError(info='DNS lookup on client failed for IP %s' % client_ip)
- for rsn in rs:
- if rsn.dns_type == dnsclient.DNS_T_PTR:
- rhost = rsn
- break
-
- if rhost is None:
- raise errors.ACIError(info='DNS lookup on client failed for IP %s' % client_ip)
-
- client_hostname = rhost.rdata.ptrdname[:-1]
- if subject_host.lower() != client_hostname.lower():
- self.log.debug("IPA: hostname in subject of request '%s' does not match requesting hostname '%s'" % (subject_host, client_hostname))
- self.check_access(operation="request certificate different host")
-
# See if the service exists and punt if it doesn't and we aren't
# going to add it
try:
@@ -157,24 +129,23 @@ class cert_request(VirtualCommand):
if 'usercertificate' in service:
# FIXME, what to do here? Do we revoke the old cert?
raise errors.GenericError(format='entry already has a certificate, serial number %s' % get_serial(service['usercertificate']))
- if not can_write(dn, "usercertificate"):
- raise errors.ACIError(info='You need to be a member of the serviceadmin role to update services')
-
except errors.NotFound, e:
if not add:
raise errors.NotFound(reason="The service principal for this request doesn't exist.")
+ try:
+ (dn, service) = api.Command['service_add'](principal, **{})
+ except errors.ACIError:
+ raise errors.ACIError(info='You need to be a member of the serviceadmin role to add services')
+
+ # We got this far so the service entry exists, can we write it?
+ if not ldap.can_write(dn, "usercertificate"):
+ raise errors.ACIError(info="Insufficient 'write' privilege to the 'userCertificate' attribute of entry '%s'." % dn)
# Request the certificate
result = self.Backend.ra.request_certificate(csr, **kw)
- # Success? Then add it to the service entry. We know that it
- # either exists or we should add it.
- if result.get('status') == '0':
- if service is None:
- try:
- service = api.Command['service_add'](principal, **{})
- except errors.ACIError:
- raise errors.ACIError(info='You need to be a member of the serviceadmin role to add services')
+ # Success? Then add it to the service entry.
+ if result.get('status') == 0:
skw = {"usercertificate": str(result.get('certificate'))}
api.Command['service_mod'](principal, **skw)
diff --git a/ipalib/plugins/rolegroup.py b/ipalib/plugins/rolegroup.py
index 85f34157e..fdc632450 100644
--- a/ipalib/plugins/rolegroup.py
+++ b/ipalib/plugins/rolegroup.py
@@ -40,10 +40,12 @@ class rolegroup(LDAPObject):
'cn': 'name',
'member user': 'member users',
'member group': 'member groups',
+ 'member host': 'member hosts',
+ 'member hostgroup': 'member hostgroups',
'memberof taskgroup': 'member of taskgroup',
}
attribute_members = {
- 'member': ['user', 'group'],
+ 'member': ['user', 'group', 'host', 'hostgroup'],
'memberof': ['taskgroup'],
}
@@ -99,7 +101,7 @@ class rolegroup_show(LDAPRetrieve):
"""
Display rolegroup.
"""
-
+
api.register(rolegroup_show)
diff --git a/ipalib/plugins/service.py b/ipalib/plugins/service.py
index 481a9f6dc..449acbaec 100644
--- a/ipalib/plugins/service.py
+++ b/ipalib/plugins/service.py
@@ -103,12 +103,16 @@ class service(LDAPObject):
'krbprincipal', 'krbprincipalaux', 'krbticketpolicyaux', 'ipaobject',
'ipaservice', 'pkiuser'
]
- default_attributes = ['krbprincipalname', 'usercertificate']
+ default_attributes = ['krbprincipalname', 'usercertificate', 'managedby']
uuid_attribute = 'ipauniqueid'
attribute_names = {
'krbprincipalname': 'kerberos principal',
'usercertificate': 'user certificate',
'ipauniqueid': 'unique identifier',
+ 'managedby': 'managed by',
+ }
+ attribute_members = {
+ 'managedby': ['host'],
}
takes_params = (
@@ -131,6 +135,7 @@ class service_add(LDAPCreate):
"""
Add new service.
"""
+ member_attributes = ['managedby']
takes_options = (
Flag('force',
doc='force principal name even if not in DNS',
@@ -176,6 +181,7 @@ class service_del(LDAPDelete):
"""
Delete an existing service.
"""
+ member_attributes = ['managedby']
def pre_callback(self, ldap, dn, *keys, **options):
if self.api.env.enable_ra:
(dn, entry_attrs) = ldap.get_entry(dn, ['usercertificate'])
@@ -192,6 +198,7 @@ class service_mod(LDAPUpdate):
"""
Modify service.
"""
+ member_attributes = ['managedby']
def pre_callback(self, ldap, dn, entry_attrs, *keys, **options):
cert = entry_attrs.get('usercertificate')
if cert:
@@ -213,6 +220,7 @@ class service_find(LDAPSearch):
"""
Search for services.
"""
+ member_attributes = ['managedby']
def pre_callback(self, ldap, filter, attrs_list, base_dn, *args, **options):
# lisp style!
custom_filter = '(&(objectclass=ipaService)' \
@@ -233,6 +241,24 @@ class service_show(LDAPRetrieve):
"""
Display service.
"""
+ member_attributes = ['managedby']
api.register(service_show)
+class service_add_host(LDAPAddMember):
+ """
+ Add members to service.
+ """
+ member_attributes = ['managedby']
+
+api.register(service_add_host)
+
+
+class service_remove_host(LDAPRemoveMember):
+ """
+ Remove members from service.
+ """
+ member_attributes = ['managedby']
+
+api.register(service_remove_host)
+
diff --git a/ipaserver/plugins/ldap2.py b/ipaserver/plugins/ldap2.py
index f8e06576d..38fdb6210 100644
--- a/ipaserver/plugins/ldap2.py
+++ b/ipaserver/plugins/ldap2.py
@@ -512,7 +512,7 @@ class ldap2(CrudBackend, Encoder):
attributes and the entryLevelRights for the entry itself.
"""
principal = getattr(context, 'principal')
- (binddn, attrs) = self.find_entry_by_attr("krbprincipalname", principal, "posixAccount")
+ (binddn, attrs) = self.find_entry_by_attr("krbprincipalname", principal, "krbPrincipalAux")
sctrl = [LDAPControl("1.3.6.1.4.1.42.2.27.9.5.2", True, "dn: " + binddn.encode('UTF-8'))]
self.conn.set_option(_ldap.OPT_SERVER_CONTROLS, sctrl)
(dn, attrs) = self.get_entry(dn, entry_attrs)