summaryrefslogtreecommitdiffstats
path: root/ipalib/plugins
diff options
context:
space:
mode:
authorRob Crittenden <rcritten@redhat.com>2009-11-03 09:35:19 -0500
committerJason Gerard DeRose <jderose@redhat.com>2009-11-03 09:04:05 -0700
commitbd619adb5c1cfcd9e72c18896aded82e2ab33faa (patch)
tree749d6ef90707772a5146d03c6bc78ef59a5f664c /ipalib/plugins
parente4c119ed4b05fe600377360e697483bd59000b37 (diff)
downloadfreeipa-bd619adb5c1cfcd9e72c18896aded82e2ab33faa.tar.gz
freeipa-bd619adb5c1cfcd9e72c18896aded82e2ab33faa.tar.xz
freeipa-bd619adb5c1cfcd9e72c18896aded82e2ab33faa.zip
Use a new mechanism for delegating certificate issuance.
Using the client IP address was a rather poor mechanism for controlling who could request certificates for whom. Instead the client machine will bind using the host service principal and request the certificate. In order to do this: * the service will need to exist * the machine needs to be in the certadmin rolegroup * the host needs to be in the managedBy attribute of the service It might look something like: admin ipa host-add client.example.com --password=secret123 ipa service-add HTTP/client.example.com ipa service-add-host --hosts=client.example.com HTTP/client.example.com ipa rolegroup-add-member --hosts=client.example.com certadmin client ipa-client-install ipa-join -w secret123 kinit -kt /etc/krb5.keytab host/client.example.com ipa -d cert-request file://web.csr --principal=HTTP/client.example.com
Diffstat (limited to 'ipalib/plugins')
-rw-r--r--ipalib/plugins/cert.py51
-rw-r--r--ipalib/plugins/rolegroup.py6
-rw-r--r--ipalib/plugins/service.py28
3 files changed, 42 insertions, 43 deletions
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)
+