590d18
From d3271ee9de63d9c6275184875d05762666ba9088 Mon Sep 17 00:00:00 2001
590d18
From: "Endi S. Dewata" <edewata@redhat.com>
590d18
Date: Fri, 31 Jul 2015 07:53:15 +0200
590d18
Subject: [PATCH] Added support for changing vault encryption.
590d18
590d18
The vault-mod command has been modified to support changing vault
590d18
encryption attributes (i.e. type, password, public/private keys)
590d18
in addition to normal attributes (i.e. description). Changing the
590d18
encryption requires retrieving the stored secret with the old
590d18
attributes and rearchiving it with the new attributes.
590d18
590d18
https://fedorahosted.org/freeipa/ticket/5176
590d18
590d18
Reviewed-By: Martin Basti <mbasti@redhat.com>
590d18
---
590d18
 API.txt                                   |  27 +++-
590d18
 VERSION                                   |   4 +-
590d18
 ipalib/plugins/vault.py                   | 233 ++++++++++++++++++++++++++--
590d18
 ipatests/test_xmlrpc/test_vault_plugin.py | 249 ++++++++++++++++++++++++++++++
590d18
 4 files changed, 498 insertions(+), 15 deletions(-)
590d18
590d18
diff --git a/API.txt b/API.txt
590d18
index b0f456e725a6c3d24c1071b282de5a28c3b5a671..8105cfb5ba61cabcf5c0f7e1c6e44dfc0cacc9cb 100644
590d18
--- a/API.txt
590d18
+++ b/API.txt
590d18
@@ -5474,11 +5474,12 @@ output: Output('completed', <type 'int'>, None)
590d18
 output: Output('failed', <type 'dict'>, None)
590d18
 output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None))
590d18
 command: vault_archive
590d18
-args: 1,10,3
590d18
+args: 1,11,3
590d18
 arg: Str('cn', attribute=True, cli_name='name', maxlength=255, multivalue=False, pattern='^[a-zA-Z0-9_.-]+$', primary_key=True, query=True, required=True)
590d18
 option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
590d18
 option: Bytes('data?')
590d18
 option: Str('in?')
590d18
+option: Flag('override_password?', autofill=True, default=False)
590d18
 option: Str('password?', cli_name='password')
590d18
 option: Str('password_file?', cli_name='password_file')
590d18
 option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
590d18
@@ -5538,6 +5539,30 @@ output: ListOfEntries('result', (<type 'list'>, <type 'tuple'>), Gettext('A list
590d18
 output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
590d18
 output: Output('truncated', <type 'bool'>, None)
590d18
 command: vault_mod
590d18
+args: 1,18,3
590d18
+arg: Str('cn', attribute=True, cli_name='name', maxlength=255, multivalue=False, pattern='^[a-zA-Z0-9_.-]+$', primary_key=True, query=True, required=True)
590d18
+option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
590d18
+option: Flag('change_password?', autofill=True, default=False)
590d18
+option: Str('description?', cli_name='desc')
590d18
+option: Bytes('ipavaultpublickey?', cli_name='public_key')
590d18
+option: Bytes('ipavaultsalt?', cli_name='salt')
590d18
+option: Str('ipavaulttype?', cli_name='type')
590d18
+option: Str('new_password?', cli_name='new_password')
590d18
+option: Str('new_password_file?', cli_name='new_password_file')
590d18
+option: Str('old_password?', cli_name='old_password')
590d18
+option: Str('old_password_file?', cli_name='old_password_file')
590d18
+option: Bytes('private_key?', cli_name='private_key')
590d18
+option: Str('private_key_file?', cli_name='private_key_file')
590d18
+option: Str('public_key_file?', cli_name='public_key_file')
590d18
+option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
590d18
+option: Str('service?')
590d18
+option: Flag('shared?', autofill=True, default=False)
590d18
+option: Str('username?', cli_name='user')
590d18
+option: Str('version?', exclude='webui')
590d18
+output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None))
590d18
+output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
590d18
+output: PrimaryKey('value', None, None)
590d18
+command: vault_mod_internal
590d18
 args: 1,15,3
590d18
 arg: Str('cn', attribute=True, cli_name='name', maxlength=255, multivalue=False, pattern='^[a-zA-Z0-9_.-]+$', primary_key=True, query=True, required=True)
590d18
 option: Str('addattr*', cli_name='addattr', exclude='webui')
590d18
diff --git a/VERSION b/VERSION
590d18
index 9fe2f4d4f9ff6ffd42c2ee7493c385b0a432a6a0..3fdd2db88a7b2b6d3bd36ba0d7257c9994bc06af 100644
590d18
--- a/VERSION
590d18
+++ b/VERSION
590d18
@@ -90,5 +90,5 @@ IPA_DATA_VERSION=20100614120000
590d18
 #                                                      #
590d18
 ########################################################
590d18
 IPA_API_VERSION_MAJOR=2
590d18
-IPA_API_VERSION_MINOR=152
590d18
-# Last change: mbasti - add 'user-stage' command
590d18
+IPA_API_VERSION_MINOR=153
590d18
+# Last change: edewata - Added support for changing vault encryption.
590d18
diff --git a/ipalib/plugins/vault.py b/ipalib/plugins/vault.py
590d18
index 4b2c8a518e5c9a93e5490841a3d2177536c905b1..6a07a76b5b85680536b27fd147d8ec1583bb0bc7 100644
590d18
--- a/ipalib/plugins/vault.py
590d18
+++ b/ipalib/plugins/vault.py
590d18
@@ -116,11 +116,37 @@ EXAMPLES:
590d18
    ipa vault-show <name>
590d18
        [--user <user>|--service <service>|--shared]
590d18
 """) + _("""
590d18
- Modify a vault:
590d18
+ Modify vault description:
590d18
    ipa vault-mod <name>
590d18
        [--user <user>|--service <service>|--shared]
590d18
        --desc <description>
590d18
 """) + _("""
590d18
+ Modify vault type:
590d18
+   ipa vault-mod <name>
590d18
+       [--user <user>|--service <service>|--shared]
590d18
+       --type <type>
590d18
+       [old password/private key]
590d18
+       [new password/public key]
590d18
+""") + _("""
590d18
+ Modify symmetric vault password:
590d18
+   ipa vault-mod <name>
590d18
+       [--user <user>|--service <service>|--shared]
590d18
+       --change-password
590d18
+   ipa vault-mod <name>
590d18
+       [--user <user>|--service <service>|--shared]
590d18
+       --old-password <old password>
590d18
+       --new-password <new password>
590d18
+   ipa vault-mod <name>
590d18
+       [--user <user>|--service <service>|--shared]
590d18
+       --old-password-file <old password file>
590d18
+       --new-password-file <new password file>
590d18
+""") + _("""
590d18
+ Modify asymmetric vault keys:
590d18
+   ipa vault-mod <name>
590d18
+       [--user <user>|--service <service>|--shared]
590d18
+       --private-key-file <old private key file>
590d18
+       --public-key-file <new public key file>
590d18
+""") + _("""
590d18
  Delete a vault:
590d18
    ipa vault-del <name>
590d18
        [--user <user>|--service <service>|--shared]
590d18
@@ -457,7 +483,7 @@ class vault(LDAPObject):
590d18
 
590d18
             print '  ** Passwords do not match! **'
590d18
 
590d18
-    def get_existing_password(self, new=False):
590d18
+    def get_existing_password(self):
590d18
         """
590d18
         Gets existing password from user.
590d18
         """
590d18
@@ -871,9 +897,182 @@ class vault_find(LDAPSearch):
590d18
 
590d18
 
590d18
 @register()
590d18
-class vault_mod(LDAPUpdate):
590d18
+class vault_mod(PKQuery, Local):
590d18
     __doc__ = _('Modify a vault.')
590d18
 
590d18
+    takes_options = vault_options + (
590d18
+        Str(
590d18
+            'description?',
590d18
+            cli_name='desc',
590d18
+            doc=_('Vault description'),
590d18
+        ),
590d18
+        Str(
590d18
+            'ipavaulttype?',
590d18
+            cli_name='type',
590d18
+            doc=_('Vault type'),
590d18
+        ),
590d18
+        Bytes(
590d18
+            'ipavaultsalt?',
590d18
+            cli_name='salt',
590d18
+            doc=_('Vault salt'),
590d18
+        ),
590d18
+        Flag(
590d18
+            'change_password?',
590d18
+            doc=_('Change password'),
590d18
+        ),
590d18
+        Str(
590d18
+            'old_password?',
590d18
+            cli_name='old_password',
590d18
+            doc=_('Old vault password'),
590d18
+        ),
590d18
+        Str(  # TODO: use File parameter
590d18
+            'old_password_file?',
590d18
+            cli_name='old_password_file',
590d18
+            doc=_('File containing the old vault password'),
590d18
+        ),
590d18
+        Str(
590d18
+            'new_password?',
590d18
+            cli_name='new_password',
590d18
+            doc=_('New vault password'),
590d18
+        ),
590d18
+        Str(  # TODO: use File parameter
590d18
+            'new_password_file?',
590d18
+            cli_name='new_password_file',
590d18
+            doc=_('File containing the new vault password'),
590d18
+        ),
590d18
+        Bytes(
590d18
+            'private_key?',
590d18
+            cli_name='private_key',
590d18
+            doc=_('Old vault private key'),
590d18
+        ),
590d18
+        Str(  # TODO: use File parameter
590d18
+            'private_key_file?',
590d18
+            cli_name='private_key_file',
590d18
+            doc=_('File containing the old vault private key'),
590d18
+        ),
590d18
+        Bytes(
590d18
+            'ipavaultpublickey?',
590d18
+            cli_name='public_key',
590d18
+            doc=_('New vault public key'),
590d18
+        ),
590d18
+        Str(  # TODO: use File parameter
590d18
+            'public_key_file?',
590d18
+            cli_name='public_key_file',
590d18
+            doc=_('File containing the new vault public key'),
590d18
+        ),
590d18
+    )
590d18
+
590d18
+    has_output = output.standard_entry
590d18
+
590d18
+    def forward(self, *args, **options):
590d18
+
590d18
+        vault_type = options.pop('ipavaulttype', False)
590d18
+        salt = options.pop('ipavaultsalt', False)
590d18
+        change_password = options.pop('change_password', False)
590d18
+
590d18
+        old_password = options.pop('old_password', None)
590d18
+        old_password_file = options.pop('old_password_file', None)
590d18
+        new_password = options.pop('new_password', None)
590d18
+        new_password_file = options.pop('new_password_file', None)
590d18
+
590d18
+        old_private_key = options.pop('private_key', None)
590d18
+        old_private_key_file = options.pop('private_key_file', None)
590d18
+        new_public_key = options.pop('ipavaultpublickey', None)
590d18
+        new_public_key_file = options.pop('public_key_file', None)
590d18
+
590d18
+        if self.api.env.in_server:
590d18
+            backend = self.api.Backend.ldap2
590d18
+        else:
590d18
+            backend = self.api.Backend.rpcclient
590d18
+        if not backend.isconnected():
590d18
+            backend.connect(ccache=krbV.default_context().default_ccache())
590d18
+
590d18
+        # determine the vault type based on parameters specified
590d18
+        if vault_type:
590d18
+            pass
590d18
+
590d18
+        elif change_password or new_password or new_password_file or salt:
590d18
+            vault_type = u'symmetric'
590d18
+
590d18
+        elif new_public_key or new_public_key_file:
590d18
+            vault_type = u'asymmetric'
590d18
+
590d18
+        # if vault type is specified, retrieve existing secret
590d18
+        if vault_type:
590d18
+            opts = options.copy()
590d18
+            opts.pop('description', None)
590d18
+
590d18
+            opts['password'] = old_password
590d18
+            opts['password_file'] = old_password_file
590d18
+            opts['private_key'] = old_private_key
590d18
+            opts['private_key_file'] = old_private_key_file
590d18
+
590d18
+            response = self.api.Command.vault_retrieve(*args, **opts)
590d18
+            data = response['result']['data']
590d18
+
590d18
+        opts = options.copy()
590d18
+
590d18
+        # if vault type is specified, update crypto attributes
590d18
+        if vault_type:
590d18
+            opts['ipavaulttype'] = vault_type
590d18
+
590d18
+            if vault_type == u'standard':
590d18
+                opts['ipavaultsalt'] = None
590d18
+                opts['ipavaultpublickey'] = None
590d18
+
590d18
+            elif vault_type == u'symmetric':
590d18
+                if salt:
590d18
+                    opts['ipavaultsalt'] = salt
590d18
+                else:
590d18
+                    opts['ipavaultsalt'] = os.urandom(16)
590d18
+
590d18
+                opts['ipavaultpublickey'] = None
590d18
+
590d18
+            elif vault_type == u'asymmetric':
590d18
+
590d18
+                # get new vault public key
590d18
+                if new_public_key and new_public_key_file:
590d18
+                    raise errors.MutuallyExclusiveError(
590d18
+                        reason=_('New public key specified multiple times'))
590d18
+
590d18
+                elif new_public_key:
590d18
+                    pass
590d18
+
590d18
+                elif new_public_key_file:
590d18
+                    new_public_key = validated_read('public_key_file',
590d18
+                                                    new_public_key_file,
590d18
+                                                    mode='rb')
590d18
+
590d18
+                else:
590d18
+                    raise errors.ValidationError(
590d18
+                        name='ipavaultpublickey',
590d18
+                        error=_('Missing new vault public key'))
590d18
+
590d18
+                opts['ipavaultsalt'] = None
590d18
+                opts['ipavaultpublickey'] = new_public_key
590d18
+
590d18
+        response = self.api.Command.vault_mod_internal(*args, **opts)
590d18
+
590d18
+        # if vault type is specified, rearchive existing secret
590d18
+        if vault_type:
590d18
+            opts = options.copy()
590d18
+            opts.pop('description', None)
590d18
+
590d18
+            opts['data'] = data
590d18
+            opts['password'] = new_password
590d18
+            opts['password_file'] = new_password_file
590d18
+            opts['override_password'] = True
590d18
+
590d18
+            self.api.Command.vault_archive(*args, **opts)
590d18
+
590d18
+        return response
590d18
+
590d18
+
590d18
+@register()
590d18
+class vault_mod_internal(LDAPUpdate):
590d18
+
590d18
+    NO_CLI = True
590d18
+
590d18
     takes_options = LDAPUpdate.takes_options + vault_options
590d18
 
590d18
     msg_summary = _('Modified vault "%(value)s"')
590d18
@@ -994,6 +1193,10 @@ class vault_archive(PKQuery, Local):
590d18
             cli_name='password_file',
590d18
             doc=_('File containing the vault password'),
590d18
         ),
590d18
+        Flag(
590d18
+            'override_password?',
590d18
+            doc=_('Override existing password'),
590d18
+        ),
590d18
     )
590d18
 
590d18
     has_output = output.standard_entry
590d18
@@ -1008,6 +1211,8 @@ class vault_archive(PKQuery, Local):
590d18
         password = options.get('password')
590d18
         password_file = options.get('password_file')
590d18
 
590d18
+        override_password = options.pop('override_password', False)
590d18
+
590d18
         # don't send these parameters to server
590d18
         if 'data' in options:
590d18
             del options['data']
590d18
@@ -1062,15 +1267,19 @@ class vault_archive(PKQuery, Local):
590d18
                 password = password.rstrip('\n')
590d18
 
590d18
             else:
590d18
-                password = self.obj.get_existing_password()
590d18
-
590d18
-            # verify password by retrieving existing data
590d18
-            opts = options.copy()
590d18
-            opts['password'] = password
590d18
-            try:
590d18
-                self.api.Command.vault_retrieve(*args, **opts)
590d18
-            except errors.NotFound:
590d18
-                pass
590d18
+                if override_password:
590d18
+                    password = self.obj.get_new_password()
590d18
+                else:
590d18
+                    password = self.obj.get_existing_password()
590d18
+
590d18
+            if not override_password:
590d18
+                # verify password by retrieving existing data
590d18
+                opts = options.copy()
590d18
+                opts['password'] = password
590d18
+                try:
590d18
+                    self.api.Command.vault_retrieve(*args, **opts)
590d18
+                except errors.NotFound:
590d18
+                    pass
590d18
 
590d18
             salt = vault['ipavaultsalt'][0]
590d18
 
590d18
diff --git a/ipatests/test_xmlrpc/test_vault_plugin.py b/ipatests/test_xmlrpc/test_vault_plugin.py
590d18
index fe2f2f67d664e0640fdda99fd3e2f068ee61cb01..40ce46406702740ef5a781c3d3569b4f2e088b92 100644
590d18
--- a/ipatests/test_xmlrpc/test_vault_plugin.py
590d18
+++ b/ipatests/test_xmlrpc/test_vault_plugin.py
590d18
@@ -36,6 +36,7 @@ asymmetric_vault_name = u'asymmetric_test_vault'
590d18
 secret = ''.join(map(chr, xrange(0, 256)))
590d18
 
590d18
 password = u'password'
590d18
+other_password = u'other_password'
590d18
 
590d18
 public_key = """
590d18
 -----BEGIN PUBLIC KEY-----
590d18
@@ -79,6 +80,48 @@ kUlCMj24a8XsShzYTWBIyW2ngvGe3pQ9PfjkUdm0LGZjYITCBvgOKw==
590d18
 -----END RSA PRIVATE KEY-----
590d18
 """
590d18
 
590d18
+other_public_key = """
590d18
+-----BEGIN PUBLIC KEY-----
590d18
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv7E/QLVyKjrgDctZ50U7
590d18
+rmtL7Ks1QLoccp9WvZJ6WI1rYd0fX5FySS4dI6QTNZc6qww8NeNuZtkoxT9m1wkk
590d18
+Rl/3wK7fWNLenH/+VHOaTQc20exg7ztfsO7JIsmKmigtticdR5C4jLfjcOp+WjLH
590d18
+w3zrmrO5SIZ8njxMoDcQJa2vu/t281U/I7ti8ue09FSitIECU05vgmPS+MnXR8HK
590d18
+PxXqrNkjl29mXNbPiByWwlse3Prwved9I7fwgpiHJqUBFudD/0tZ4DWyLG7t9wM1
590d18
+O8gRaRg1r+ENVpmMSvXo4+8+bR3rEYddD5zU7nKXafeuthXlXplae/8uZmCiSI63
590d18
+TwIDAQAB
590d18
+-----END PUBLIC KEY-----
590d18
+"""
590d18
+
590d18
+other_private_key = """
590d18
+-----BEGIN RSA PRIVATE KEY-----
590d18
+MIIEpgIBAAKCAQEAv7E/QLVyKjrgDctZ50U7rmtL7Ks1QLoccp9WvZJ6WI1rYd0f
590d18
+X5FySS4dI6QTNZc6qww8NeNuZtkoxT9m1wkkRl/3wK7fWNLenH/+VHOaTQc20exg
590d18
+7ztfsO7JIsmKmigtticdR5C4jLfjcOp+WjLHw3zrmrO5SIZ8njxMoDcQJa2vu/t2
590d18
+81U/I7ti8ue09FSitIECU05vgmPS+MnXR8HKPxXqrNkjl29mXNbPiByWwlse3Prw
590d18
+ved9I7fwgpiHJqUBFudD/0tZ4DWyLG7t9wM1O8gRaRg1r+ENVpmMSvXo4+8+bR3r
590d18
+EYddD5zU7nKXafeuthXlXplae/8uZmCiSI63TwIDAQABAoIBAQCA+0GFR9F+isjx
590d18
+Xy+qBpKmxLl8kKKvX8r+cSpLOkEqTlW/rqqKgnI0vVuL/L2UJKKsLvpghBxoBZyC
590d18
+RCvtatBGrhIlS0UrHg/9m73Ek1hylfUUAQokTn4PrkwWJSgmm/xOATmZSs5ymNTn
590d18
+yFCmXl69sdNR77YvD5bQXeBtOT+bKXy7yQ1TmYPwwSjL+WSlMV6ZfE3HNVmxPTpk
590d18
+CTFS638cJblWk9MUIy8HIlhu6If2P4RnHr7ZGGivhREayvs0zXcAfqhIyFHruxSE
590d18
+yYnmqH9paWjv5mP3YyLoKr+NUvvxnBr/9wCTt0TKgG8G6rpkHuPDLQni9wUGnew8
590d18
+QdMgFEohAoGBAPH4vaVB5gDVfvIqwJBsBLHpPq72GvxjrM/exD0jIIpXZxz9gCql
590d18
+CmC5b1RS1uy8PMoc/RO4CE7UTLaTesciP6LjTD1RhH3rLLJO8/iVC1RXgMrCLHLm
590d18
+ZQnDhIQGGNQxpvBjQy5ZOWat2dFxYhHN630IFPOtrWsOmJ5HsL1JrjzxAoGBAMrO
590d18
+R1zNwQ42VbJS6AFshZVjmUV2h3REGh4zG/9IqL0Hz493hyCTGoDPLLXIbtkqNqzQ
590d18
+XibSZ9RMVPKKTiNQTx91DTgh4Anz8xUr84tA2iAf3ayNWKi3Y3GhmP2EWp1qYeom
590d18
+kV8Uq0lt4dHZuEo3LuqvbtbzlF9qUXqKS5qy6Tg/AoGBAKCp02o2HjzxhS/QeTmr
590d18
+r1ZeE7PiTzrECAuh01TwzPtuW1XhcEdgfEqK9cPcmT5pIkflBZkhOcr1pdYYiI5O
590d18
+TEigeY/BX6KoE251hALLG9GtpCN82DyWhAH+oy9ySOwj5793eTT+I2HtD1LE4SQH
590d18
+QVQsmJTP/fS2pVl7KnwUvy9RAoGBAKzo2qchNewsHzx+uxgbsnkABfnXaP2T4sDE
590d18
+yqYJCPTB6BFl02vOf9Y6zN/gF8JH333P2bY3xhaXTgXMLXqmSg+D+NVW7HEP8Lyo
590d18
+UGj1zgN9p74qdODEGqETKiFb6vYzcW/1mhP6x18/tDz658k+611kXZge7O288+MK
590d18
+bhNjXrx5AoGBAMox25PcxVgOjCd9+LdUcIOG6LQ971eCH1NKL9YAekICnwMrStbK
590d18
+veCYju6ok4ZWnMiH8MR1jgC39RWtjJZwynCuPXUP2/vZkoVf1tCZyz7dSm8TdS/2
590d18
+5NdOHVy7+NQcEPSm7/FmXdpcR9ZSGAuxMBfnEUibdyz5LdJGnFUN/+HS
590d18
+-----END RSA PRIVATE KEY-----
590d18
+"""
590d18
+
590d18
 
590d18
 class test_vault_plugin(Declarative):
590d18
 
590d18
@@ -580,6 +623,48 @@ class test_vault_plugin(Declarative):
590d18
         },
590d18
 
590d18
         {
590d18
+            'desc': 'Change standard vault to symmetric vault',
590d18
+            'command': (
590d18
+                'vault_mod',
590d18
+                [standard_vault_name],
590d18
+                {
590d18
+                    'ipavaulttype': u'symmetric',
590d18
+                    'new_password': password,
590d18
+                },
590d18
+            ),
590d18
+            'expected': {
590d18
+                'value': standard_vault_name,
590d18
+                'summary': u'Modified vault "%s"' % standard_vault_name,
590d18
+                'result': {
590d18
+                    'cn': [standard_vault_name],
590d18
+                    'ipavaulttype': [u'symmetric'],
590d18
+                    'ipavaultsalt': [fuzzy_string],
590d18
+                    'owner_user': [u'admin'],
590d18
+                },
590d18
+            },
590d18
+        },
590d18
+
590d18
+        {
590d18
+            'desc': 'Retrieve secret from standard vault converted to '
590d18
+                    'symmetric vault',
590d18
+            'command': (
590d18
+                'vault_retrieve',
590d18
+                [standard_vault_name],
590d18
+                {
590d18
+                    'password': password,
590d18
+                },
590d18
+            ),
590d18
+            'expected': {
590d18
+                'value': standard_vault_name,
590d18
+                'summary': 'Retrieved data from vault "%s"'
590d18
+                           % standard_vault_name,
590d18
+                'result': {
590d18
+                    'data': secret,
590d18
+                },
590d18
+            },
590d18
+        },
590d18
+
590d18
+        {
590d18
             'desc': 'Create symmetric vault',
590d18
             'command': (
590d18
                 'vault_add',
590d18
@@ -642,6 +727,90 @@ class test_vault_plugin(Declarative):
590d18
         },
590d18
 
590d18
         {
590d18
+            'desc': 'Change symmetric vault password',
590d18
+            'command': (
590d18
+                'vault_mod',
590d18
+                [symmetric_vault_name],
590d18
+                {
590d18
+                    'old_password': password,
590d18
+                    'new_password': other_password,
590d18
+                },
590d18
+            ),
590d18
+            'expected': {
590d18
+                'value': symmetric_vault_name,
590d18
+                'summary': u'Modified vault "%s"' % symmetric_vault_name,
590d18
+                'result': {
590d18
+                    'cn': [symmetric_vault_name],
590d18
+                    'ipavaulttype': [u'symmetric'],
590d18
+                    'ipavaultsalt': [fuzzy_string],
590d18
+                    'owner_user': [u'admin'],
590d18
+                },
590d18
+            },
590d18
+        },
590d18
+
590d18
+        {
590d18
+            'desc': 'Retrieve secret from symmetric vault with new password',
590d18
+            'command': (
590d18
+                'vault_retrieve',
590d18
+                [symmetric_vault_name],
590d18
+                {
590d18
+                    'password': other_password,
590d18
+                },
590d18
+            ),
590d18
+            'expected': {
590d18
+                'value': symmetric_vault_name,
590d18
+                'summary': 'Retrieved data from vault "%s"'
590d18
+                           % symmetric_vault_name,
590d18
+                'result': {
590d18
+                    'data': secret,
590d18
+                },
590d18
+            },
590d18
+        },
590d18
+
590d18
+        {
590d18
+            'desc': 'Change symmetric vault to asymmetric vault',
590d18
+            'command': (
590d18
+                'vault_mod',
590d18
+                [symmetric_vault_name],
590d18
+                {
590d18
+                    'ipavaulttype': u'asymmetric',
590d18
+                    'old_password': other_password,
590d18
+                    'ipavaultpublickey': public_key,
590d18
+                },
590d18
+            ),
590d18
+            'expected': {
590d18
+                'value': symmetric_vault_name,
590d18
+                'summary': u'Modified vault "%s"' % symmetric_vault_name,
590d18
+                'result': {
590d18
+                    'cn': [symmetric_vault_name],
590d18
+                    'ipavaulttype': [u'asymmetric'],
590d18
+                    'ipavaultpublickey': [public_key],
590d18
+                    'owner_user': [u'admin'],
590d18
+                },
590d18
+            },
590d18
+        },
590d18
+
590d18
+        {
590d18
+            'desc': 'Retrieve secret from symmetric vault converted to '
590d18
+                    'asymmetric vault',
590d18
+            'command': (
590d18
+                'vault_retrieve',
590d18
+                [symmetric_vault_name],
590d18
+                {
590d18
+                    'private_key': private_key,
590d18
+                },
590d18
+            ),
590d18
+            'expected': {
590d18
+                'value': symmetric_vault_name,
590d18
+                'summary': 'Retrieved data from vault "%s"'
590d18
+                           % symmetric_vault_name,
590d18
+                'result': {
590d18
+                    'data': secret,
590d18
+                },
590d18
+            },
590d18
+        },
590d18
+
590d18
+        {
590d18
             'desc': 'Create asymmetric vault',
590d18
             'command': (
590d18
                 'vault_add',
590d18
@@ -702,4 +871,84 @@ class test_vault_plugin(Declarative):
590d18
             },
590d18
         },
590d18
 
590d18
+        {
590d18
+            'desc': 'Change asymmetric vault keys',
590d18
+            'command': (
590d18
+                'vault_mod',
590d18
+                [asymmetric_vault_name],
590d18
+                {
590d18
+                    'private_key': private_key,
590d18
+                    'ipavaultpublickey': other_public_key,
590d18
+                },
590d18
+            ),
590d18
+            'expected': {
590d18
+                'value': asymmetric_vault_name,
590d18
+                'summary': u'Modified vault "%s"' % asymmetric_vault_name,
590d18
+                'result': {
590d18
+                    'cn': [asymmetric_vault_name],
590d18
+                    'ipavaulttype': [u'asymmetric'],
590d18
+                    'ipavaultpublickey': [other_public_key],
590d18
+                    'owner_user': [u'admin'],
590d18
+                },
590d18
+            },
590d18
+        },
590d18
+
590d18
+        {
590d18
+            'desc': 'Retrieve secret from asymmetric vault with new keys',
590d18
+            'command': (
590d18
+                'vault_retrieve',
590d18
+                [asymmetric_vault_name],
590d18
+                {
590d18
+                    'private_key': other_private_key,
590d18
+                },
590d18
+            ),
590d18
+            'expected': {
590d18
+                'value': asymmetric_vault_name,
590d18
+                'summary': 'Retrieved data from vault "%s"'
590d18
+                           % asymmetric_vault_name,
590d18
+                'result': {
590d18
+                    'data': secret,
590d18
+                },
590d18
+            },
590d18
+        },
590d18
+
590d18
+        {
590d18
+            'desc': 'Change asymmetric vault to standard vault',
590d18
+            'command': (
590d18
+                'vault_mod',
590d18
+                [asymmetric_vault_name],
590d18
+                {
590d18
+                    'ipavaulttype': u'standard',
590d18
+                    'private_key': other_private_key,
590d18
+                },
590d18
+            ),
590d18
+            'expected': {
590d18
+                'value': asymmetric_vault_name,
590d18
+                'summary': u'Modified vault "%s"' % asymmetric_vault_name,
590d18
+                'result': {
590d18
+                    'cn': [asymmetric_vault_name],
590d18
+                    'ipavaulttype': [u'standard'],
590d18
+                    'owner_user': [u'admin'],
590d18
+                },
590d18
+            },
590d18
+        },
590d18
+
590d18
+        {
590d18
+            'desc': 'Retrieve secret from asymmetric vault converted to '
590d18
+                    'standard vault',
590d18
+            'command': (
590d18
+                'vault_retrieve',
590d18
+                [asymmetric_vault_name],
590d18
+                {},
590d18
+            ),
590d18
+            'expected': {
590d18
+                'value': asymmetric_vault_name,
590d18
+                'summary': 'Retrieved data from vault "%s"'
590d18
+                           % asymmetric_vault_name,
590d18
+                'result': {
590d18
+                    'data': secret,
590d18
+                },
590d18
+            },
590d18
+        },
590d18
+
590d18
     ]
590d18
-- 
590d18
2.4.3
590d18