diff options
author | Fraser Tweedale <ftweedal@redhat.com> | 2015-05-14 01:46:06 -0400 |
---|---|---|
committer | Jan Cholasta <jcholast@redhat.com> | 2016-06-15 07:13:38 +0200 |
commit | 3d4db834caa0688bcefc0092b7978402b783eaf3 (patch) | |
tree | e9fddc70bdff260ce738dc9458938851453d86c0 /ipaserver/plugins/ca.py | |
parent | 8135651abb857fbe489a1de8aacad3747d7d5cc9 (diff) | |
download | freeipa-3d4db834caa0688bcefc0092b7978402b783eaf3.tar.gz freeipa-3d4db834caa0688bcefc0092b7978402b783eaf3.tar.xz freeipa-3d4db834caa0688bcefc0092b7978402b783eaf3.zip |
Add 'ca' plugin
This commit adds the 'ca' plugin for creating and managing
lightweight CAs. The initial implementation supports a single level
of sub-CAs underneath the IPA CA.
This commit also:
- adds the container for FreeIPA CA objects
- adds schema for the FreeIPA CA objects
- updates ipa-pki-proxy.conf to allow access to the Dogtag
lightweight CAs REST API.
Part of: https://fedorahosted.org/freeipa/ticket/4559
Reviewed-By: Jan Cholasta <jcholast@redhat.com>
Reviewed-By: Martin Babinsky <mbabinsk@redhat.com>
Diffstat (limited to 'ipaserver/plugins/ca.py')
-rw-r--r-- | ipaserver/plugins/ca.py | 217 |
1 files changed, 217 insertions, 0 deletions
diff --git a/ipaserver/plugins/ca.py b/ipaserver/plugins/ca.py new file mode 100644 index 000000000..ee98f0a2a --- /dev/null +++ b/ipaserver/plugins/ca.py @@ -0,0 +1,217 @@ +# +# Copyright (C) 2016 FreeIPA Contributors see COPYING for license +# + +from ipalib import api, errors, DNParam, Str +from ipalib.constants import IPA_CA_CN +from ipalib.plugable import Registry +from ipaserver.plugins.baseldap import ( + LDAPObject, LDAPSearch, LDAPCreate, LDAPDelete, + LDAPUpdate, LDAPRetrieve) +from ipaserver.plugins.cert import ca_enabled_check +from ipalib import _, ngettext + + +__doc__ = _(""" +Manage Certificate Authorities + +Subordinate Certificate Authorities (Sub-CAs) can be added for scoped issuance +of X.509 certificates. + +EXAMPLES: + + Create new CA, subordinate to the IPA CA. + + ipa ca-add puppet --desc "Puppet" \\ + --subject "CN=Puppet CA,O=EXAMPLE.COM" + +""") + + +register = Registry() + + +@register() +class ca(LDAPObject): + """ + Lightweight CA Object + """ + container_dn = api.env.container_ca + object_name = _('Certificate Authority') + object_name_plural = _('Certificate Authorities') + object_class = ['ipaca'] + permission_filter_objectclasses = ['ipaca'] + default_attributes = [ + 'cn', 'description', 'ipacaid', 'ipacaissuerdn', 'ipacasubjectdn', + ] + rdn_attribute = 'cn' + rdn_is_primary_key = True + label = _('Certificate Authorities') + label_singular = _('Certificate Authority') + + takes_params = ( + Str('cn', + primary_key=True, + cli_name='name', + label=_('Name'), + doc=_('Name for referencing the CA'), + ), + Str('description?', + cli_name='desc', + label=_('Description'), + doc=_('Description of the purpose of the CA'), + ), + Str('ipacaid', + cli_name='id', + label=_('Authority ID'), + doc=_('Dogtag Authority ID'), + flags=['no_create', 'no_update'], + ), + DNParam('ipacasubjectdn', + cli_name='subject', + label=_('Subject DN'), + doc=_('Subject Distinguished Name'), + flags=['no_update'], + ), + DNParam('ipacaissuerdn', + cli_name='issuer', + label=_('Issuer DN'), + doc=_('Issuer Distinguished Name'), + flags=['no_create', 'no_update'], + ), + ) + + permission_filter_objectclasses = ['ipaca'] + managed_permissions = { + 'System: Read CAs': { + 'replaces_global_anonymous_aci': True, + 'ipapermbindruletype': 'all', + 'ipapermright': {'read', 'search', 'compare'}, + 'ipapermdefaultattr': { + 'cn', + 'description', + 'ipacaid', + 'ipacaissuerdn', + 'ipacasubjectdn', + 'objectclass', + }, + }, + 'System: Add CA': { + 'ipapermright': {'add'}, + 'replaces': [ + '(target = "ldap:///cn=*,cn=cas,cn=ca,$SUFFIX")(version 3.0;acl "permission:Add CA";allow (add) groupdn = "ldap:///cn=Add CA,cn=permissions,cn=pbac,$SUFFIX";)', + ], + 'default_privileges': {'CA Administrator'}, + }, + 'System: Delete CA': { + 'ipapermright': {'delete'}, + 'replaces': [ + '(target = "ldap:///cn=*,cn=cas,cn=ca,$SUFFIX")(version 3.0;acl "permission:Delete CA";allow (delete) groupdn = "ldap:///cn=Delete CA,cn=permissions,cn=pbac,$SUFFIX";)', + ], + 'default_privileges': {'CA Administrator'}, + }, + 'System: Modify CA': { + 'ipapermright': {'write'}, + 'ipapermdefaultattr': { + 'cn', + 'description', + }, + 'replaces': [ + '(targetattr = "cn || description")(target = "ldap:///cn=*,cn=cas,cn=ca,$SUFFIX")(version 3.0;acl "permission:Modify CA";allow (write) groupdn = "ldap:///cn=Modify CA,cn=permissions,cn=pbac,$SUFFIX";)', + ], + 'default_privileges': {'CA Administrator'}, + }, + } + + +@register() +class ca_find(LDAPSearch): + __doc__ = _("Search for CAs.") + msg_summary = ngettext( + '%(count)d CA matched', '%(count)d CAs matched', 0 + ) + + def execute(self, *keys, **options): + ca_enabled_check() + return super(ca_find, self).execute(*keys, **options) + + +@register() +class ca_show(LDAPRetrieve): + __doc__ = _("Display the properties of a CA.") + + def execute(self, *args, **kwargs): + ca_enabled_check() + return super(ca_show, self).execute(*args, **kwargs) + + +@register() +class ca_add(LDAPCreate): + __doc__ = _("Create a CA.") + msg_summary = _('Created CA "%(value)s"') + + def pre_callback(self, ldap, dn, entry, entry_attrs, *keys, **options): + ca_enabled_check() + if not ldap.can_add(dn[1:]): + raise errors.ACIError( + info=_("Insufficient 'add' privilege for entry '%s'.") % dn) + + # check for name collision before creating CA in Dogtag + try: + api.Object.ca.get_dn_if_exists(keys[-1]) + self.obj.handle_duplicate_entry(*keys) + except errors.NotFound: + pass + + # Create the CA in Dogtag. + with self.api.Backend.ra_lightweight_ca as ca_api: + resp = ca_api.create_ca(options['ipacasubjectdn']) + entry['ipacaid'] = [resp['id']] + entry['ipacaissuerdn'] = [resp['issuerDN']] + + # In the event that the issued certificate's subject DN + # differs from what was requested, record the actual DN. + # + entry['ipacasubjectdn'] = [resp['dn']] + return dn + + +@register() +class ca_del(LDAPDelete): + __doc__ = _('Delete a CA.') + + msg_summary = _('Deleted CA "%(value)s"') + + def pre_callback(self, ldap, dn, *keys, **options): + ca_enabled_check() + + if keys[0] == IPA_CA_CN: + raise errors.ProtectedEntryError( + label=_("CA"), + key=keys[0], + reason=_("IPA CA cannot be deleted")) + + ca_id = self.api.Command.ca_show(keys[0])['result']['ipacaid'][0] + with self.api.Backend.ra_lightweight_ca as ca_api: + ca_api.disable_ca(ca_id) + ca_api.delete_ca(ca_id) + + return dn + + +@register() +class ca_mod(LDAPUpdate): + __doc__ = _("Modify CA configuration.") + msg_summary = _('Modified CA "%(value)s"') + + def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): + ca_enabled_check() + + if 'rename' in options or 'cn' in entry_attrs: + if keys[0] == IPA_CA_CN: + raise errors.ProtectedEntryError( + label=_("CA"), + key=keys[0], + reason=u'IPA CA cannot be renamed') + + return dn |