From 83bfd97806d3900f62cac007b66cc8daa0c45234 Mon Sep 17 00:00:00 2001
From: Petr Vobornik <pvoborni@redhat.com>
Date: Tue, 25 Aug 2015 19:56:00 +0200
Subject: [PATCH] vault: add vault container commands
adds commands:
* vaultcontainer-show [--service <service>|--user <user>|--shared ]
* vaultcontainer-del [--service <service>|--user <user>|--shared ]
* vaultcontainer-add-owner
[--service <service>|--user <user>|--shared ]
[--users <users>] [--groups <groups>] [--services <services>]
* vaultcontainer-remove-owner
[--service <service>|--user <user>|--shared ]
[--users <users>] [--groups <groups>] [--services <services>]
https://fedorahosted.org/freeipa/ticket/5250
Reviewed-By: Petr Vobornik <pvoborni@redhat.com>
---
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', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None))
output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), 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', <type 'int'>, None)
+output: Output('failed', <type 'dict'>, None)
+output: Entry('result', <type 'dict'>, 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', <type 'dict'>, None)
+output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), 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', <type 'int'>, None)
+output: Output('failed', <type 'dict'>, None)
+output: Entry('result', <type 'dict'>, 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', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None))
+output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), 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