From 76eea85701af80dc972c47e14aecc7a688b9c846 Mon Sep 17 00:00:00 2001 From: Martin Babinsky Date: Tue, 23 Jun 2015 13:42:01 +0200 Subject: new commands to manage user/host/service certificates A new group of commands is introduced that simplifies adding and removing binary certificates to entries. A general form of the command is ipa [user/host/service]-[add/remove]-cert [pkey] --certificate=[BASE64 BLOB] Part of http://www.freeipa.org/page/V4/User_Certificates and https://fedorahosted.org/freeipa/ticket/4238 Reviewed-By: Jan Cholasta --- API.txt | 66 +++++++++++++++++++++++++++++++++++++++++++++++ VERSION | 4 +-- ipalib/plugins/host.py | 27 +++++++++++++++++-- ipalib/plugins/service.py | 21 +++++++++++++++ ipalib/plugins/user.py | 52 +++++++++++++++++++++++++++++++++++++ 5 files changed, 166 insertions(+), 4 deletions(-) diff --git a/API.txt b/API.txt index 17a1afe01..e226712d3 100644 --- a/API.txt +++ b/API.txt @@ -2066,6 +2066,17 @@ option: Str('version?', exclude='webui') output: Entry('result', , Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None)) output: Output('summary', (, ), None) output: PrimaryKey('value', None, None) +command: host_add_cert +args: 1,5,3 +arg: Str('fqdn', attribute=True, cli_name='hostname', multivalue=False, primary_key=True, query=True, required=True) +option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui') +option: Flag('no_members', autofill=True, default=False, exclude='webui') +option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui') +option: Bytes('usercertificate', alwaysask=True, attribute=True, cli_name='certificate', multivalue=True, required=False) +option: Str('version?', exclude='webui') +output: Entry('result', , Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None)) +output: Output('summary', (, ), None) +output: PrimaryKey('value', None, None) command: host_add_managedby args: 1,5,3 arg: Str('fqdn', attribute=True, cli_name='hostname', multivalue=False, primary_key=True, query=True, required=True) @@ -2220,6 +2231,17 @@ option: Str('version?', exclude='webui') output: Entry('result', , Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None)) output: Output('summary', (, ), None) output: PrimaryKey('value', None, None) +command: host_remove_cert +args: 1,5,3 +arg: Str('fqdn', attribute=True, cli_name='hostname', multivalue=False, primary_key=True, query=True, required=True) +option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui') +option: Flag('no_members', autofill=True, default=False, exclude='webui') +option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui') +option: Bytes('usercertificate', alwaysask=True, attribute=True, cli_name='certificate', multivalue=True, required=False) +option: Str('version?', exclude='webui') +output: Entry('result', , Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None)) +output: Output('summary', (, ), None) +output: PrimaryKey('value', None, None) command: host_remove_managedby args: 1,5,3 arg: Str('fqdn', attribute=True, cli_name='hostname', multivalue=False, primary_key=True, query=True, required=True) @@ -3861,6 +3883,17 @@ option: Str('version?', exclude='webui') output: Entry('result', , Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None)) output: Output('summary', (, ), None) output: PrimaryKey('value', None, None) +command: service_add_cert +args: 1,5,3 +arg: Str('krbprincipalname', attribute=True, cli_name='principal', multivalue=False, primary_key=True, query=True, required=True) +option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui') +option: Flag('no_members', autofill=True, default=False, exclude='webui') +option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui') +option: Bytes('usercertificate', alwaysask=True, attribute=True, cli_name='certificate', multivalue=True, required=False) +option: Str('version?', exclude='webui') +output: Entry('result', , Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None)) +output: Output('summary', (, ), None) +output: PrimaryKey('value', None, None) command: service_add_host args: 1,5,3 arg: Str('krbprincipalname', attribute=True, cli_name='principal', multivalue=False, primary_key=True, query=True, required=True) @@ -3979,6 +4012,17 @@ option: Str('version?', exclude='webui') output: Entry('result', , Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None)) output: Output('summary', (, ), None) output: PrimaryKey('value', None, None) +command: service_remove_cert +args: 1,5,3 +arg: Str('krbprincipalname', attribute=True, cli_name='principal', multivalue=False, primary_key=True, query=True, required=True) +option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui') +option: Flag('no_members', autofill=True, default=False, exclude='webui') +option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui') +option: Bytes('usercertificate', alwaysask=True, attribute=True, cli_name='certificate', multivalue=True, required=False) +option: Str('version?', exclude='webui') +output: Entry('result', , Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None)) +output: Output('summary', (, ), None) +output: PrimaryKey('value', None, None) command: service_remove_host args: 1,5,3 arg: Str('krbprincipalname', attribute=True, cli_name='principal', multivalue=False, primary_key=True, query=True, required=True) @@ -5166,6 +5210,17 @@ option: Str('version?', exclude='webui') output: Entry('result', , Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None)) output: Output('summary', (, ), None) output: PrimaryKey('value', None, None) +command: user_add_cert +args: 1,5,3 +arg: Str('uid', attribute=True, cli_name='login', maxlength=255, multivalue=False, pattern='^[a-zA-Z0-9_.][a-zA-Z0-9_.-]{0,252}[a-zA-Z0-9_.$-]?$', primary_key=True, query=True, required=True) +option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui') +option: Flag('no_members', autofill=True, default=False, exclude='webui') +option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui') +option: Bytes('usercertificate', alwaysask=True, attribute=True, cli_name='certificate', multivalue=True, required=False) +option: Str('version?', exclude='webui') +output: Entry('result', , Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None)) +output: Output('summary', (, ), None) +output: PrimaryKey('value', None, None) command: user_del args: 1,4,3 arg: Str('uid', attribute=True, cli_name='login', maxlength=255, multivalue=True, pattern='^[a-zA-Z0-9_.][a-zA-Z0-9_.-]{0,252}[a-zA-Z0-9_.$-]?$', primary_key=True, query=True, required=True) @@ -5305,6 +5360,17 @@ option: Str('version?', exclude='webui') output: Entry('result', , Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None)) output: Output('summary', (, ), None) output: PrimaryKey('value', None, None) +command: user_remove_cert +args: 1,5,3 +arg: Str('uid', attribute=True, cli_name='login', maxlength=255, multivalue=False, pattern='^[a-zA-Z0-9_.][a-zA-Z0-9_.-]{0,252}[a-zA-Z0-9_.$-]?$', primary_key=True, query=True, required=True) +option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui') +option: Flag('no_members', autofill=True, default=False, exclude='webui') +option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui') +option: Bytes('usercertificate', alwaysask=True, attribute=True, cli_name='certificate', multivalue=True, required=False) +option: Str('version?', exclude='webui') +output: Entry('result', , Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None)) +output: Output('summary', (, ), None) +output: PrimaryKey('value', None, None) command: user_show args: 1,5,3 arg: Str('uid', attribute=True, cli_name='login', maxlength=255, multivalue=False, pattern='^[a-zA-Z0-9_.][a-zA-Z0-9_.-]{0,252}[a-zA-Z0-9_.$-]?$', primary_key=True, query=True, required=True) diff --git a/VERSION b/VERSION index 2f884ff73..266a04af1 100644 --- a/VERSION +++ b/VERSION @@ -90,5 +90,5 @@ IPA_DATA_VERSION=20100614120000 # # ######################################################## IPA_API_VERSION_MAJOR=2 -IPA_API_VERSION_MINOR=136 -# Last change: pvoborni: add topologysuffix-verify command +IPA_API_VERSION_MINOR=137 +# Last change: mbabinsk: Commands to manage user/host/service certificates diff --git a/ipalib/plugins/host.py b/ipalib/plugins/host.py index f5871f81e..410b4bd12 100644 --- a/ipalib/plugins/host.py +++ b/ipalib/plugins/host.py @@ -28,11 +28,12 @@ from ipalib.plugins.baseldap import (LDAPQuery, LDAPObject, LDAPCreate, LDAPDelete, LDAPUpdate, LDAPSearch, LDAPRetrieve, LDAPAddMember, LDAPRemoveMember, host_is_master, - pkey_to_value, add_missing_object_class) + pkey_to_value, add_missing_object_class, + LDAPAddAttribute, LDAPRemoveAttribute) from ipalib.plugins.service import (split_principal, validate_certificate, set_certificate_attrs, ticket_flags_params, update_krbticketflags, set_kerberos_attrs, rename_ipaallowedtoperform_from_ldap, - rename_ipaallowedtoperform_to_ldap) + rename_ipaallowedtoperform_to_ldap, revoke_certs) from ipalib.plugins.dns import (dns_container_exists, _record_types, add_records_for_host_validation, add_records_for_host, get_reverse_zone) @@ -1246,3 +1247,25 @@ class host_disallow_create_keytab(LDAPRemoveMember): rename_ipaallowedtoperform_from_ldap(entry_attrs, options) rename_ipaallowedtoperform_from_ldap(failed, options) return (completed, dn) + + +@register() +class host_add_cert(LDAPAddAttribute): + __doc__ = _('Add certificates to host entry') + msg_summary = _('Added certificates to host "%(value)s"') + attribute = 'usercertificate' + + +@register() +class host_remove_cert(LDAPRemoveAttribute): + __doc__ = _('Remove certificates from host entry') + msg_summary = _('Removed certificates from host "%(value)s"') + attribute = 'usercertificate' + + def post_callback(self, ldap, dn, entry_attrs, *keys, **options): + assert isinstance(dn, DN) + + if 'usercertificate' in options: + revoke_certs(options['usercertificate'], self.log) + + return dn diff --git a/ipalib/plugins/service.py b/ipalib/plugins/service.py index 18d7b3e54..a5e10921b 100644 --- a/ipalib/plugins/service.py +++ b/ipalib/plugins/service.py @@ -861,3 +861,24 @@ class service_disable(LDAPQuery): value=pkey_to_value(keys[0], options), ) + +@register() +class service_add_cert(LDAPAddAttribute): + __doc__ = _('Add new certificates to a service') + msg_summary = _('Added certificates to service principal "%(value)s"') + attribute = 'usercertificate' + + +@register() +class service_remove_cert(LDAPRemoveAttribute): + __doc__ = _('Remove certificates from a service') + msg_summary = _('Removed certificates from service principal "%(value)s"') + attribute = 'usercertificate' + + def post_callback(self, ldap, dn, entry_attrs, *keys, **options): + assert isinstance(dn, DN) + + if 'usercertificate' in options: + revoke_certs(options['usercertificate'], self.log) + + return dn diff --git a/ipalib/plugins/user.py b/ipalib/plugins/user.py index bc6989cce..9bd7bf7e5 100644 --- a/ipalib/plugins/user.py +++ b/ipalib/plugins/user.py @@ -1001,3 +1001,55 @@ class user_status(LDAPQuery): summary=unicode(_('Account disabled: %(disabled)s' % dict(disabled=disabled))), ) + + +@register() +class user_add_cert(LDAPAddAttribute): + __doc__ = _('Add one or more certificates to the user entry') + msg_summary = _('Added certificates to user "%(value)s"') + attribute = 'usercertificate' + + def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, + **options): + assert isinstance(dn, DN) + + new_attr_name = '%s;binary' % self.attribute + if self.attribute in entry_attrs: + entry_attrs[new_attr_name] = entry_attrs.pop(self.attribute) + + return dn + + def post_callback(self, ldap, dn, entry_attrs, *keys, **options): + assert isinstance(dn, DN) + + old_attr_name = '%s;binary' % self.attribute + if old_attr_name in entry_attrs: + entry_attrs[self.attribute] = entry_attrs.pop(old_attr_name) + + return dn + + +@register() +class user_remove_cert(LDAPRemoveAttribute): + __doc__ = _('Remove one or more certificates to the user entry') + msg_summary = _('Removed certificates from user "%(value)s"') + attribute = 'usercertificate' + + def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, + **options): + assert isinstance(dn, DN) + + new_attr_name = '%s;binary' % self.attribute + if self.attribute in entry_attrs: + entry_attrs[new_attr_name] = entry_attrs.pop(self.attribute) + + return dn + + def post_callback(self, ldap, dn, entry_attrs, *keys, **options): + assert isinstance(dn, DN) + + old_attr_name = '%s;binary' % self.attribute + if old_attr_name in entry_attrs: + entry_attrs[self.attribute] = entry_attrs.pop(old_attr_name) + + return dn -- cgit