Blob Blame History Raw
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