From 83bfd97806d3900f62cac007b66cc8daa0c45234 Mon Sep 17 00:00:00 2001 From: Petr Vobornik Date: Tue, 25 Aug 2015 19:56:00 +0200 Subject: [PATCH] vault: add vault container commands adds commands: * vaultcontainer-show [--service |--user |--shared ] * vaultcontainer-del [--service |--user |--shared ] * vaultcontainer-add-owner [--service |--user |--shared ] [--users ] [--groups ] [--services ] * vaultcontainer-remove-owner [--service |--user |--shared ] [--users ] [--groups ] [--services ] https://fedorahosted.org/freeipa/ticket/5250 Reviewed-By: Petr Vobornik --- API.txt | 53 +++++++++++ VERSION | 4 +- ipalib/plugins/vault.py | 243 +++++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 277 insertions(+), 23 deletions(-) diff --git a/API.txt b/API.txt index 5253e1585e000f39d6e185a94548037dfe54d4d8..4d36a9885157de13529573b3a386b4ef39eba176 100644 --- a/API.txt +++ b/API.txt @@ -5667,6 +5667,59 @@ 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: vaultcontainer_add_owner +args: 0,10,3 +option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui') +option: Str('group*', alwaysask=True, cli_name='groups', csv=True) +option: Flag('no_members', autofill=True, default=False, exclude='webui') +option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui') +option: Str('service?') +option: Str('services', alwaysask=True, cli_name='services', csv=True, multivalue=True, required=False) +option: Flag('shared?', autofill=True, default=False) +option: Str('user*', alwaysask=True, cli_name='users', csv=True) +option: Str('username?', cli_name='user') +option: Str('version?', exclude='webui') +output: Output('completed', , None) +output: Output('failed', , None) +output: Entry('result', , Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None)) +command: vaultcontainer_del +args: 0,5,3 +option: Flag('continue', autofill=True, cli_name='continue', default=False) +option: Str('service?') +option: Flag('shared?', autofill=True, default=False) +option: Str('username?', cli_name='user') +option: Str('version?', exclude='webui') +output: Output('result', , None) +output: Output('summary', (, ), None) +output: ListOfPrimaryKeys('value', None, None) +command: vaultcontainer_remove_owner +args: 0,10,3 +option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui') +option: Str('group*', alwaysask=True, cli_name='groups', csv=True) +option: Flag('no_members', autofill=True, default=False, exclude='webui') +option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui') +option: Str('service?') +option: Str('services', alwaysask=True, cli_name='services', csv=True, multivalue=True, required=False) +option: Flag('shared?', autofill=True, default=False) +option: Str('user*', alwaysask=True, cli_name='users', csv=True) +option: Str('username?', cli_name='user') +option: Str('version?', exclude='webui') +output: Output('completed', , None) +output: Output('failed', , None) +output: Entry('result', , Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None)) +command: vaultcontainer_show +args: 0,8,3 +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: Flag('rights', autofill=True, default=False) +option: Str('service?') +option: Flag('shared?', autofill=True, default=False) +option: Str('username?', cli_name='user') +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) capability: messages 2.52 capability: optional_uid_params 2.54 capability: permissions2 2.69 diff --git a/VERSION b/VERSION index da721fdd548023dc3dcd9b4f6a8ba72922a3c6f2..c2b5c87a2615d77e75259edfb8e3a6b7740fac52 100644 --- a/VERSION +++ b/VERSION @@ -90,5 +90,5 @@ IPA_DATA_VERSION=20100614120000 # # ######################################################## IPA_API_VERSION_MAJOR=2 -IPA_API_VERSION_MINOR=155 -# Last change: ftweedal - remove certprofile 'rename' option +IPA_API_VERSION_MINOR=156 +# Last change: pvoborni - add vault container commands diff --git a/ipalib/plugins/vault.py b/ipalib/plugins/vault.py index e369eeee20f5652942681f7c3e268e6173005452..733741dfc2c87995055599cc3816f321ec344496 100644 --- a/ipalib/plugins/vault.py +++ b/ipalib/plugins/vault.py @@ -257,6 +257,228 @@ vault_options = ( ) +class VaultModMember(LDAPModMember): + def get_options(self): + for param in super(VaultModMember, self).get_options(): + if param.name == 'service' and param not in vault_options: + param = param.clone_rename('services') + yield param + + def get_member_dns(self, **options): + if 'services' in options: + options['service'] = options.pop('services') + else: + options.pop('service', None) + return super(VaultModMember, self).get_member_dns(**options) + + def post_callback(self, ldap, completed, failed, dn, entry_attrs, *keys, **options): + for fail in failed.itervalues(): + fail['services'] = fail.pop('service', []) + self.obj.get_container_attribute(entry_attrs, options) + return completed, dn + + +@register() +class vaultcontainer(LDAPObject): + __doc__ = _(""" + Vault Container object. + """) + + container_dn = api.env.container_vault + + object_name = _('vaultcontainer') + object_name_plural = _('vaultcontainers') + object_class = ['ipaVaultContainer'] + + attribute_members = { + 'owner': ['user', 'group', 'service'], + } + + label = _('Vault Containers') + label_singular = _('Vault Container') + + takes_params = ( + Str( + 'owner_user?', + label=_('Owner users'), + ), + Str( + 'owner_group?', + label=_('Owner groups'), + ), + Str( + 'owner_service?', + label=_('Owner services'), + ), + Str( + 'owner?', + label=_('Failed owners'), + ), + Str( + 'service?', + label=_('Vault service'), + flags={'virtual_attribute'}, + ), + Flag( + 'shared?', + label=_('Shared vault'), + flags={'virtual_attribute'}, + ), + Str( + 'username?', + label=_('Vault user'), + flags={'virtual_attribute'}, + ), + ) + + def get_dn(self, *keys, **options): + """ + Generates vault DN from parameters. + """ + service = options.get('service') + shared = options.get('shared') + user = options.get('username') + + count = (bool(service) + bool(shared) + bool(user)) + if count > 1: + raise errors.MutuallyExclusiveError( + reason=_('Service, shared and user options ' + + 'cannot be specified simultaneously')) + + parent_dn = super(vaultcontainer, self).get_dn(*keys, **options) + + if not count: + principal = getattr(context, 'principal') + + if principal.startswith('host/'): + raise errors.NotImplementedError( + reason=_('Host is not supported')) + + (name, realm) = split_principal(principal) + if '/' in name: + service = name + else: + user = name + + if service: + dn = DN(('cn', service), ('cn', 'services'), parent_dn) + elif shared: + dn = DN(('cn', 'shared'), parent_dn) + elif user: + dn = DN(('cn', user), ('cn', 'users'), parent_dn) + else: + raise RuntimeError + + return dn + + def get_container_attribute(self, entry, options): + if options.get('raw', False): + return + container_dn = DN(self.container_dn, self.api.env.basedn) + if entry.dn.endswith(DN(('cn', 'services'), container_dn)): + entry['service'] = entry.dn[0]['cn'] + elif entry.dn.endswith(DN(('cn', 'shared'), container_dn)): + entry['shared'] = True + elif entry.dn.endswith(DN(('cn', 'users'), container_dn)): + entry['username'] = entry.dn[0]['cn'] + + +@register() +class vaultcontainer_show(LDAPRetrieve): + __doc__ = _('Display information about a vault container.') + + takes_options = LDAPRetrieve.takes_options + vault_options + + has_output_params = LDAPRetrieve.has_output_params + + def pre_callback(self, ldap, dn, attrs_list, *keys, **options): + assert isinstance(dn, DN) + + if not self.api.Command.kra_is_enabled()['result']: + raise errors.InvocationError( + format=_('KRA service is not enabled')) + + return dn + + def post_callback(self, ldap, dn, entry_attrs, *keys, **options): + self.obj.get_container_attribute(entry_attrs, options) + return dn + + +@register() +class vaultcontainer_del(LDAPDelete): + __doc__ = _('Delete a vault container.') + + takes_options = LDAPDelete.takes_options + vault_options + + msg_summary = _('Deleted vault container') + + subtree_delete = False + + def pre_callback(self, ldap, dn, *keys, **options): + assert isinstance(dn, DN) + + if not self.api.Command.kra_is_enabled()['result']: + raise errors.InvocationError( + format=_('KRA service is not enabled')) + + return dn + + def execute(self, *keys, **options): + keys = keys + (u'',) + return super(vaultcontainer_del, self).execute(*keys, **options) + + +@register() +class vaultcontainer_add_owner(VaultModMember, LDAPAddMember): + __doc__ = _('Add owners to a vault container.') + + takes_options = LDAPAddMember.takes_options + vault_options + + member_attributes = ['owner'] + member_param_label = _('owner %s') + member_count_out = ('%i owner added.', '%i owners added.') + + has_output = ( + output.Entry('result'), + output.Output( + 'failed', + type=dict, + doc=_('Owners that could not be added'), + ), + output.Output( + 'completed', + type=int, + doc=_('Number of owners added'), + ), + ) + + +@register() +class vaultcontainer_remove_owner(VaultModMember, LDAPRemoveMember): + __doc__ = _('Remove owners from a vault container.') + + takes_options = LDAPRemoveMember.takes_options + vault_options + + member_attributes = ['owner'] + member_param_label = _('owner %s') + member_count_out = ('%i owner removed.', '%i owners removed.') + + has_output = ( + output.Entry('result'), + output.Output( + 'failed', + type=dict, + doc=_('Owners that could not be removed'), + ), + output.Output( + 'completed', + type=int, + doc=_('Number of owners removed'), + ), + ) + + @register() class vault(LDAPObject): __doc__ = _(""" @@ -1729,27 +1951,6 @@ class vault_retrieve_internal(PKQuery): return response -class VaultModMember(LDAPModMember): - def get_options(self): - for param in super(VaultModMember, self).get_options(): - if param.name == 'service' and param not in vault_options: - param = param.clone_rename('services') - yield param - - def get_member_dns(self, **options): - if 'services' in options: - options['service'] = options.pop('services') - else: - options.pop('service', None) - return super(VaultModMember, self).get_member_dns(**options) - - def post_callback(self, ldap, completed, failed, dn, entry_attrs, *keys, **options): - for fail in failed.itervalues(): - fail['services'] = fail.pop('service', []) - self.obj.get_container_attribute(entry_attrs, options) - return completed, dn - - @register() class vault_add_owner(VaultModMember, LDAPAddMember): __doc__ = _('Add owners to a vault.') -- 2.4.3