Hello community,

here is the log from the commit of package python-hvac for openSUSE:Factory 
checked in at 2020-06-10 00:46:23
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-hvac (Old)
 and      /work/SRC/openSUSE:Factory/.python-hvac.new.3606 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-hvac"

Wed Jun 10 00:46:23 2020 rev:2 rq:812623 version:0.10.3

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-hvac/python-hvac.changes  2020-04-10 
23:53:27.688707975 +0200
+++ /work/SRC/openSUSE:Factory/.python-hvac.new.3606/python-hvac.changes        
2020-06-10 00:46:24.994634300 +0200
@@ -1,0 +2,19 @@
+Mon Jun  8 13:37:14 UTC 2020 - Dirk Mueller <dmuel...@suse.com>
+
+- update to 0.10.3:
+  - Add Support For use_token_groups In LDAP Auth Method. GH-591
+  - Add Raft System Backend Methods. GH-594
+
+-------------------------------------------------------------------
+Tue Jun  2 16:18:03 UTC 2020 - Dirk Mueller <dmuel...@suse.com>
+
+- update to 0.10.2:
+  - Create_role_secret_id: add token_bound_cidrs parameter. GH-585
+  - Add vault rekey verification methods. GH-586
+  - Add request data to exception objects. GH-583
+  - Add marshaling_algorithm to sign/verify params. GH-584
+  - Add issuer to kubernetes configuration. GH-575
+  - Remove json() calls (unneeded following JSONAdapter addition) GH-589
+  - Fix format errors in contributing for HTML docs. GH-577
+
+-------------------------------------------------------------------

Old:
----
  v0.10.1.tar.gz

New:
----
  v0.10.3.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-hvac.spec ++++++
--- /var/tmp/diff_new_pack.2PCGeA/_old  2020-06-10 00:46:26.054636946 +0200
+++ /var/tmp/diff_new_pack.2PCGeA/_new  2020-06-10 00:46:26.058636956 +0200
@@ -18,7 +18,7 @@
 
 %{?!python_module:%define python_module() python-%{**} python3-%{**}}
 Name:           python-hvac
-Version:        0.10.1
+Version:        0.10.3
 Release:        0
 Summary:        HashiCorp Vault API client
 License:        BSD-3-Clause

++++++ v0.10.1.tar.gz -> v0.10.3.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hvac-0.10.1/.bumpversion.cfg 
new/hvac-0.10.3/.bumpversion.cfg
--- old/hvac-0.10.1/.bumpversion.cfg    2020-04-07 22:57:10.000000000 +0200
+++ new/hvac-0.10.3/.bumpversion.cfg    2020-05-24 21:19:23.000000000 +0200
@@ -1,5 +1,5 @@
 [bumpversion]
-current_version = 0.10.1
+current_version = 0.10.3
 commit = True
 tag = True
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hvac-0.10.1/CHANGELOG.md new/hvac-0.10.3/CHANGELOG.md
--- old/hvac-0.10.1/CHANGELOG.md        2020-04-07 22:57:10.000000000 +0200
+++ new/hvac-0.10.3/CHANGELOG.md        2020-05-24 21:19:23.000000000 +0200
@@ -1,5 +1,34 @@
 # Changelog
 
+## 0.10.3 (May 24th, 2020)
+
+### 🚀 Features
+
+- Add Support For use_token_groups In LDAP Auth Method. GH-591
+- Add Raft System Backend Methods. GH-594
+
+Thanks to @finarfin and @jeffwecan for their lovely contributions.
+
+## 0.10.2 (May 19th, 2020)
+
+### 🚀 Features
+
+- Create_role_secret_id: add token_bound_cidrs parameter. GH-585
+- Add vault rekey verification methods. GH-586
+- Add request data to exception objects. GH-583
+- Add marshaling_algorithm to sign/verify params. GH-584
+- Add issuer to kubernetes configuration. GH-575
+
+### 🐛 Bug Fixes
+
+- Remove json() calls (unneeded following JSONAdapter addition) GH-589
+
+### 📚 Documentation
+
+- Fix format errors in contributing for HTML docs. GH-577
+
+Thanks to @TerryHowe, @and-semakin, @jeffwecan, @jschlyter, @jzck, @mdelaney 
and @scarabeusiv for their lovely contributions.
+
 ## 0.10.1 (April 7th, 2020)
 
 ### 💥 Breaking Changes
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hvac-0.10.1/CONTRIBUTING.md 
new/hvac-0.10.3/CONTRIBUTING.md
--- old/hvac-0.10.1/CONTRIBUTING.md     2020-04-07 22:57:10.000000000 +0200
+++ new/hvac-0.10.3/CONTRIBUTING.md     2020-05-24 21:19:23.000000000 +0200
@@ -2,7 +2,7 @@
 
 Feel free to open issues and/or pull requests with additional features or 
improvements! For general questions about contributing to hvac that don't fit 
in the scope of a GitHub issue, and for any folks are interested in becoming a 
maintainer of hvac, please feel free to join our gitter chat room for 
discussions at: [gitter.im/hvac/community](https://gitter.im/hvac/community).
 
-## Typical Devevelopment Environment Setup
+## Typical Development Environment Setup
 
 ```
 virtualenv hvac-env
@@ -20,6 +20,7 @@
 
 1. [Install Vault](https://vaultproject.io/docs/install/index.html) or execute 
`tests/scripts/install-vault.sh`. Note: by default this script installs the OSS 
version of Vault. An enterprise trial version of the Vault binary is available 
for testing (but has an explicitly limited runtime). To run integration test 
cases requiring enterprise Vault, you can invoke the installation script with: 
`install-vault.sh <desired version> 'enterprise'`
 2. Install requirements
+
 ```
 cd hvac
 pip install -r requirements.txt
@@ -63,15 +64,18 @@
 ## Creating / Publishing Releases
 
 - [ ] Checkout the `develop` branch:
+
   ```
   git checkout develop
   git pull
   ```
-- [ ] Update the version number using 
[bumpversion](https://github.com/peritus/bumpversion). Releases typically just 
use the "patch" bumpversion option; but "minor" and "major" are available as 
needed as needed. This will also add an appropriate git commit for the new 
version.
+- [ ] Update the version number using 
[bumpversion](https://github.com/peritus/bumpversion). Releases typically just 
use the "patch" bumpversion option; but "minor" and "major" are available as 
needed. This will also add an appropriate git commit for the new version.
+
   ```
   bumpversion --no-tag {patch|minor|major}
   ```
 - [ ] Pull up the current draft [hvac 
release](https://github.com/hvac/hvac/releases/) and use the 
[release-drafter](https://github.com/toolmantim/release-drafter) generated 
release body to update [CHANGELOG.md](CHANGELOG.md). Then commit the changes:
+
   ```
   git commit CHANGELOG.md -m "Changelog updates for v$(grep -oP 
'(?<=current_version = ).*' .bumpversion.cfg)"
   ```
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hvac-0.10.1/docs/conf.py new/hvac-0.10.3/docs/conf.py
--- old/hvac-0.10.1/docs/conf.py        2020-04-07 22:57:10.000000000 +0200
+++ new/hvac-0.10.3/docs/conf.py        2020-05-24 21:19:23.000000000 +0200
@@ -16,9 +16,9 @@
 author = u'Ian Unruh, Jeffrey Hogan'
 
 # The short X.Y version
-version = '0.10.1'
+version = '0.10.3'
 # The full version, including alpha/beta/rc tags
-release = '0.10.1'
+release = '0.10.3'
 
 
 # -- General configuration ---------------------------------------------------
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hvac-0.10.1/docs/usage/system_backend/index.rst 
new/hvac-0.10.3/docs/usage/system_backend/index.rst
--- old/hvac-0.10.1/docs/usage/system_backend/index.rst 2020-04-07 
22:57:10.000000000 +0200
+++ new/hvac-0.10.3/docs/usage/system_backend/index.rst 2020-05-24 
21:19:23.000000000 +0200
@@ -14,5 +14,6 @@
    mount
    namespace
    policy
+   raft
    seal
    wrapping
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hvac-0.10.1/docs/usage/system_backend/key.rst 
new/hvac-0.10.3/docs/usage/system_backend/key.rst
--- old/hvac-0.10.1/docs/usage/system_backend/key.rst   2020-04-07 
22:57:10.000000000 +0200
+++ new/hvac-0.10.3/docs/usage/system_backend/key.rst   2020-05-24 
21:19:23.000000000 +0200
@@ -264,6 +264,130 @@
         nonce=nonce,
     )
 
+Read Rekey Verify Progress
+--------------------------
+
+.. automethod:: hvac.api.system_backend.Key.read_rekey_verify_progress
+   :noindex:
+
+Examples
+````````
+
+.. testsetup:: sys_key_read_rekey_verify_progress
+
+    keys = manager.keys
+    key = keys[0]
+    rekey_response = client.sys.start_rekey(require_verification=True)
+    nonce = rekey_response['nonce']
+    rekey_response = client.sys.rekey_multi(keys, nonce=nonce)
+
+.. testcode:: sys_key_read_rekey_verify_progress
+
+    import hvac
+    client = hvac.Client(url='https://127.0.0.1:8200')
+
+    response = client.sys.read_rekey_verify_progress()
+
+    print(
+        'Rekey verify progress is %d out of %d' % (
+            response['progress'],
+            response['t'],
+        )
+    )
+
+Example output:
+
+.. testoutput:: sys_key_read_rekey_verify_progress
+
+    Rekey verify progress is 0 out of 3
+
+
+Cancel Rekey Verify
+-------------------
+
+.. automethod:: hvac.api.system_backend.Key.cancel_rekey_verify
+   :noindex:
+
+Examples
+````````
+
+.. testsetup:: sys_key_cancel_rekey_verify
+
+    keys = manager.keys
+    key = keys[0]
+    rekey_response = client.sys.start_rekey(require_verification=True)
+    nonce = rekey_response['nonce']
+    rekey_response = client.sys.rekey_multi(keys, nonce=nonce)
+
+.. testcode:: sys_key_cancel_rekey_verify
+
+    import hvac
+    client = hvac.Client(url='https://127.0.0.1:8200')
+
+    client.sys.cancel_rekey_verify()
+
+
+Rekey Verify
+------------
+
+.. automethod:: hvac.api.system_backend.Key.rekey_verify
+   :noindex:
+
+Examples
+````````
+
+.. testsetup:: sys_key_rekey_verify
+
+    keys = manager.keys
+    rekey_response = client.sys.start_rekey(require_verification=True)
+    nonce = rekey_response['nonce']
+    rekey_response = client.sys.rekey_multi(keys, nonce=nonce)
+    verify_nonce = rekey_response['verification_nonce']
+    manager.keys = rekey_response['keys']
+    key = manager.keys[0]
+
+.. testcode:: sys_key_rekey_verify
+
+    import hvac
+    client = hvac.Client(url='https://127.0.0.1:8200')
+
+    client.sys.rekey_verify(
+        key,
+        nonce=verify_nonce,
+    )
+
+
+Rekey Verify Multi
+------------------
+
+.. automethod:: hvac.api.system_backend.Key.rekey_verify_multi
+   :noindex:
+
+Examples
+````````
+
+.. testsetup:: sys_key_rekey_verify_multi
+
+    keys = manager.keys
+    key = keys[0]
+    rekey_response = client.sys.start_rekey(require_verification=True)
+    nonce = rekey_response['nonce']
+    rekey_response = client.sys.rekey_multi(keys, nonce=nonce)
+    verify_nonce = rekey_response['verification_nonce']
+    manager.keys = rekey_response['keys']
+    keys = manager.keys
+
+.. testcode:: sys_key_rekey_verify_multi
+
+    import hvac
+    client = hvac.Client(url='https://127.0.0.1:8200')
+
+    client.sys.rekey_verify_multi(
+        keys,
+        nonce=verify_nonce,
+    )
+
+
 
 Read Backup Keys
 ----------------
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hvac-0.10.1/docs/usage/system_backend/raft.rst 
new/hvac-0.10.3/docs/usage/system_backend/raft.rst
--- old/hvac-0.10.1/docs/usage/system_backend/raft.rst  1970-01-01 
01:00:00.000000000 +0100
+++ new/hvac-0.10.3/docs/usage/system_backend/raft.rst  2020-05-24 
21:19:23.000000000 +0200
@@ -0,0 +1,49 @@
+Raft
+====
+
+:py:meth:`hvac.api.system_backend.Raft`
+
+.. contents::
+   :local:
+   :depth: 1
+
+Join Raft Cluster
+-----------------
+
+:py:meth:`hvac.api.system_backend.Raft.join_raft_cluster`
+
+.. code:: python
+
+    import hvac
+    client = hvac.Client()
+
+    client.sys.join_raft_cluster(
+        leader_api_addr='https://some-vault-node',
+    )
+
+Read Raft Configuration
+-----------------------
+
+:py:meth:`hvac.api.system_backend.Raft.read_raft_config`
+
+.. code:: python
+
+    import hvac
+    client = hvac.Client()
+
+    raft_config = c.sys.read_raft_config()
+    num_servers_in_cluster = len(raft_config['data']['config']['servers'])
+
+Remove Raft Node
+----------------
+
+:py:meth:`hvac.api.system_backend.Raft.remove_raft_node`
+
+.. code:: python
+
+    import hvac
+    client = hvac.Client()
+
+    client.sys.remove_raft_node(
+        server_id='i-somenodeid',
+    )
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hvac-0.10.1/hvac/adapters.py 
new/hvac-0.10.3/hvac/adapters.py
--- old/hvac-0.10.1/hvac/adapters.py    2020-04-07 22:57:10.000000000 +0200
+++ new/hvac-0.10.3/hvac/adapters.py    2020-05-24 21:19:23.000000000 +0200
@@ -301,7 +301,13 @@
                     pass
             if errors is None:
                 text = response.text
-            utils.raise_for_error(response.status_code, text, errors=errors)
+            utils.raise_for_error(
+                method,
+                url,
+                response.status_code,
+                text,
+                errors=errors
+            )
 
         return response
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hvac-0.10.1/hvac/api/auth_methods/kubernetes.py 
new/hvac-0.10.3/hvac/api/auth_methods/kubernetes.py
--- old/hvac-0.10.1/hvac/api/auth_methods/kubernetes.py 2020-04-07 
22:57:10.000000000 +0200
+++ new/hvac-0.10.3/hvac/api/auth_methods/kubernetes.py 2020-05-24 
21:19:23.000000000 +0200
@@ -14,7 +14,7 @@
     Reference: https://www.vaultproject.io/api/auth/kubernetes/index.html
     """
     def configure(self, kubernetes_host, kubernetes_ca_cert=None, 
token_reviewer_jwt=None, pem_keys=None,
-                  mount_point=DEFAULT_MOUNT_POINT):
+                  issuer=None, mount_point=DEFAULT_MOUNT_POINT):
         """Configure the connection parameters for Kubernetes.
 
         This path honors the distinction between the create and update 
capabilities inside ACL policies.
@@ -35,6 +35,8 @@
             Kubernetes service account JWTs. If a certificate is given, its 
public key will be extracted. Not every
             installation of Kubernetes exposes these keys.
         :type pem_keys: list
+        :param issuer: Optional JWT issuer.
+        :type token_reviewer_jwt: str | unicode
         :param mount_point: The "path" the method/backend was mounted on.
         :type mount_point: str | unicode
         :return: The response of the configure_method request.
@@ -59,6 +61,7 @@
                 'kubernetes_ca_cert': kubernetes_ca_cert,
                 'token_reviewer_jwt': token_reviewer_jwt,
                 'pem_keys': pem_keys,
+                'issuer': issuer,
             })
         )
         api_path = utils.format_url(
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hvac-0.10.1/hvac/api/auth_methods/ldap.py 
new/hvac-0.10.3/hvac/api/auth_methods/ldap.py
--- old/hvac-0.10.1/hvac/api/auth_methods/ldap.py       2020-04-07 
22:57:10.000000000 +0200
+++ new/hvac-0.10.3/hvac/api/auth_methods/ldap.py       2020-05-24 
21:19:23.000000000 +0200
@@ -16,7 +16,7 @@
     def configure(self, user_dn=None, group_dn=None, url=None, 
case_sensitive_names=None, starttls=None,
                   tls_min_version=None, tls_max_version=None, 
insecure_tls=None, certificate=None, bind_dn=None,
                   bind_pass=None, user_attr=None, discover_dn=None, 
deny_null_bind=True, upn_domain=None,
-                  group_filter=None, group_attr=None, 
mount_point=DEFAULT_MOUNT_POINT):
+                  group_filter=None, group_attr=None, use_token_groups=None, 
mount_point=DEFAULT_MOUNT_POINT):
         """
         Configure the LDAP auth method.
 
@@ -72,6 +72,9 @@
             membership. Examples: for groupfilter queries returning group 
objects, use: cn. For queries returning user
             objects, use: memberOf. The default is cn.
         :type group_attr: str | unicode
+        :param use_token_groups: If true, groups are resolved through Active 
Directory tokens. This may speed up nested
+            group membership resolution in large directories.
+        :type use_token_groups: bool
         :param mount_point: The "path" the method/backend was mounted on.
         :type mount_point: str | unicode
         :return: The response of the configure request.
@@ -96,6 +99,7 @@
             'binddn': bind_dn,
             'bindpass': bind_pass,
             'certificate': certificate,
+            'use_token_groups': use_token_groups,
         })
 
         api_path = utils.format_url('/v1/auth/{mount_point}/config', 
mount_point=mount_point)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hvac-0.10.1/hvac/api/auth_methods/userpass.py 
new/hvac-0.10.3/hvac/api/auth_methods/userpass.py
--- old/hvac-0.10.1/hvac/api/auth_methods/userpass.py   2020-04-07 
22:57:10.000000000 +0200
+++ new/hvac-0.10.3/hvac/api/auth_methods/userpass.py   2020-05-24 
21:19:23.000000000 +0200
@@ -47,10 +47,9 @@
         :rtype: dict
         """
         api_path = 
'/v1/auth/{mount_point}/users'.format(mount_point=mount_point)
-        response = self._adapter.list(
+        return self._adapter.list(
             url=api_path,
         )
-        return response.json()
 
     def read_user(self, username, mount_point=DEFAULT_MOUNT_POINT):
         """
@@ -67,10 +66,9 @@
         :rtype: dict
         """
         api_path = 
'/v1/auth/{mount_point}/users/{username}'.format(mount_point=mount_point, 
username=username)
-        response = self._adapter.get(
+        return self._adapter.get(
             url=api_path,
         )
-        return response.json()
 
     def delete_user(self, username, mount_point=DEFAULT_MOUNT_POINT):
         """
@@ -87,10 +85,9 @@
         :rtype: dict
         """
         api_path = 
'/v1/auth/{mount_point}/users/{username}'.format(mount_point=mount_point, 
username=username)
-        response = self._adapter.delete(
+        return self._adapter.delete(
             url=api_path,
         )
-        return response.json()
 
     def update_password_on_user(self, username, password, 
mount_point=DEFAULT_MOUNT_POINT):
         """
@@ -133,8 +130,7 @@
             'password': password,
         }
         api_path = 
'/v1/auth/{mount_point}/login/{username}'.format(mount_point=mount_point, 
username=username)
-        response = self._adapter.post(
+        return self._adapter.post(
             url=api_path,
             json=params,
         )
-        return response.json()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hvac-0.10.1/hvac/api/secrets_engines/transit.py 
new/hvac-0.10.3/hvac/api/secrets_engines/transit.py
--- old/hvac-0.10.1/hvac/api/secrets_engines/transit.py 2020-04-07 
22:57:10.000000000 +0200
+++ new/hvac-0.10.3/hvac/api/secrets_engines/transit.py 2020-05-24 
21:19:23.000000000 +0200
@@ -688,6 +688,7 @@
                 'context': context,
                 'prehashed': prehashed,
                 'signature_algorithm': signature_algorithm,
+                'marshaling_algorithm': marshaling_algorithm,
             })
         )
         api_path = utils.format_url(
@@ -770,6 +771,7 @@
                 'context': context,
                 'prehashed': prehashed,
                 'signature_algorithm': signature_algorithm,
+                'marshaling_algorithm': marshaling_algorithm,
             })
         )
         api_path = utils.format_url('/v1/{mount_point}/verify/{name}', 
mount_point=mount_point, name=name)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hvac-0.10.1/hvac/api/system_backend/__init__.py 
new/hvac-0.10.3/hvac/api/system_backend/__init__.py
--- old/hvac-0.10.1/hvac/api/system_backend/__init__.py 2020-04-07 
22:57:10.000000000 +0200
+++ new/hvac-0.10.3/hvac/api/system_backend/__init__.py 2020-05-24 
21:19:23.000000000 +0200
@@ -12,6 +12,7 @@
 from hvac.api.system_backend.mount import Mount
 from hvac.api.system_backend.namespace import Namespace
 from hvac.api.system_backend.policy import Policy
+from hvac.api.system_backend.raft import Raft
 from hvac.api.system_backend.seal import Seal
 from hvac.api.system_backend.wrapping import Wrapping
 from hvac.api.system_backend.system_backend_mixin import SystemBackendMixin
@@ -29,6 +30,7 @@
     'Mount',
     'Namespace',
     'Policy',
+    'Raft',
     'Seal',
     'SystemBackend',
     'SystemBackendMixin',
@@ -40,7 +42,7 @@
 
 
 class SystemBackend(VaultApiCategory, Audit, Auth, Capabilities, Health, Init, 
Key, Leader, Lease, Mount, Namespace,
-                    Policy, Seal, Wrapping):
+                    Policy, Raft, Seal, Wrapping):
     implemented_classes = [
         Audit,
         Auth,
@@ -53,6 +55,7 @@
         Mount,
         Namespace,
         Policy,
+        Raft,
         Seal,
         Wrapping,
     ]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hvac-0.10.1/hvac/api/system_backend/key.py 
new/hvac-0.10.3/hvac/api/system_backend/key.py
--- old/hvac-0.10.1/hvac/api/system_backend/key.py      2020-04-07 
22:57:10.000000000 +0200
+++ new/hvac-0.10.3/hvac/api/system_backend/key.py      2020-05-24 
21:19:23.000000000 +0200
@@ -311,3 +311,89 @@
         return self._adapter.get(
             url=api_path,
         )
+
+    def cancel_rekey_verify(self):
+        """Cancel any in-progress rekey verification.
+        This clears any progress made and resets the nonce. Unlike 
cancel_rekey, this only resets
+        the current verification operation, not the entire rekey atttempt.
+        The return value is the same as GET along with the new nonce.
+
+        Supported methods:
+            DELETE: /sys/rekey/verify. Produces: 204 (empty body)
+
+        :return: The response of the request.
+        :rtype: requests.Response
+        """
+        api_path = '/v1/sys/rekey/verify'
+        return self._adapter.delete(
+            url=api_path,
+        )
+
+    def rekey_verify(self, key, nonce):
+        """Enter a single new recovery key share to progress the rekey 
verification of the Vault.
+        If the threshold number of new recovery key shares is reached, Vault 
will complete the
+        rekey. Otherwise, this API must be called multiple times until that 
threshold is met.
+        The rekey verification nonce must be provided with each call.
+
+        Supported methods:
+            PUT: /sys/rekey/verify. Produces: 200 application/json
+
+        :param key: Specifies multiple recovery share keys.
+        :type key: str | unicode
+        :param nonce: Specifies the nonce of the rekey verify operation.
+        :type nonce: str | unicode
+        :return: The JSON response of the request.
+        :rtype: dict
+        """
+        params = {
+            'key': key,
+            'nonce': nonce,
+        }
+
+        api_path = '/v1/sys/rekey/verify'
+        return self._adapter.put(
+            url=api_path,
+            json=params,
+        )
+
+    def rekey_verify_multi(self, keys, nonce):
+        """Enter multiple new recovery key shares to progress the rekey 
verification of the Vault.
+        If the threshold number of new recovery key shares is reached, Vault 
will complete the
+        rekey. Otherwise, this API must be called multiple times until that 
threshold is met.
+        The rekey verification nonce must be provided with each call.
+
+        Supported methods:
+            PUT: /sys/rekey/verify. Produces: 200 application/json
+
+        :param keys: Specifies multiple recovery share keys.
+        :type keys: list
+        :param nonce: Specifies the nonce of the rekey verify operation.
+        :type nonce: str | unicode
+        :return: The JSON response of the request.
+        :rtype: dict
+        """
+        result = None
+
+        for key in keys:
+            result = self.rekey_verify(
+                key=key,
+                nonce=nonce,
+            )
+            if result.get('complete'):
+                break
+
+        return result
+
+    def read_rekey_verify_progress(self):
+        """Read the configuration and progress of the current rekey verify 
attempt.
+
+        Supported methods:
+            GET: /sys/rekey/verify. Produces: 200 application/json
+
+        :return: The JSON response of the request.
+        :rtype: requests.Response
+        """
+        api_path = '/v1/sys/rekey/verify'
+        return self._adapter.get(
+            url=api_path,
+        )
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hvac-0.10.1/hvac/api/system_backend/mount.py 
new/hvac-0.10.3/hvac/api/system_backend/mount.py
--- old/hvac-0.10.1/hvac/api/system_backend/mount.py    2020-04-07 
22:57:10.000000000 +0200
+++ new/hvac-0.10.3/hvac/api/system_backend/mount.py    2020-05-24 
21:19:23.000000000 +0200
@@ -33,7 +33,7 @@
 
         :param backend_type: The name of the backend type, such as "github" or 
"token".
         :type backend_type: str | unicode
-        :param path: The path to mount the method on. If not provided, 
defaults to the value of the "method_type"
+        :param path: The path to mount the method on. If not provided, 
defaults to the value of the "backend_type"
             argument.
         :type path: str | unicode
         :param description: A human-friendly description of the mount.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hvac-0.10.1/hvac/api/system_backend/raft.py 
new/hvac-0.10.3/hvac/api/system_backend/raft.py
--- old/hvac-0.10.1/hvac/api/system_backend/raft.py     1970-01-01 
01:00:00.000000000 +0100
+++ new/hvac-0.10.3/hvac/api/system_backend/raft.py     2020-05-24 
21:19:23.000000000 +0200
@@ -0,0 +1,143 @@
+#!/usr/bin/env python
+"""Raft methods module."""
+from hvac.api.system_backend.system_backend_mixin import SystemBackendMixin
+from hvac import utils
+
+
+class Raft(SystemBackendMixin):
+    """Raft cluster-related system backend methods.
+
+    When using Shamir seal, as soon as the Vault server is brought up, this 
API should be invoked
+    instead of sys/init. This API completes in 2 phases. Once this is invoked, 
the joining node
+    will receive a challenge from the Raft's leader node. This challenge can 
be answered by the
+    joining node only after a successful unseal. Hence, the joining node 
should be unsealed using
+    the unseal keys of the Raft's leader node.
+
+    Reference: https://www.vaultproject.io/api-docs/system/storage/raft
+    """
+
+    def join_raft_cluster(self, leader_api_addr, retry=False, 
leader_ca_cert=None, leader_client_cert=None, leader_client_key=None):
+        """Join a new server node to the Raft cluster.
+
+        When using Shamir seal, as soon as the Vault server is brought up, 
this API should be invoked
+        instead of sys/init. This API completes in 2 phases. Once this is 
invoked, the joining node will
+        receive a challenge from the Raft's leader node. This challenge can be 
answered by the joining
+        node only after a successful unseal. Hence, the joining node should be 
unsealed using the unseal
+        keys of the Raft's leader node.
+
+        Supported methods:
+            POST: /sys/storage/raft/join.
+
+        :param leader_api_addr: Address of the leader node in the Raft cluster 
to which this node is trying to join.
+        :type leader_api_addr: str | unicode
+        :param retry: Retry joining the Raft cluster in case of failures.
+        :type retry: bool
+        :param leader_ca_cert: CA certificate used to communicate with Raft's 
leader node.
+        :type leader_ca_cert: str | unicode
+        :param leader_client_cert: Client certificate used to communicate with 
Raft's leader node.
+        :type leader_client_cert: str | unicode
+        :param leader_client_key: Client key used to communicate with Raft's 
leader node.
+        :type leader_client_key: str | unicode
+        :return: The response of the join_raft_cluster request.
+        :rtype: requests.Response
+        """
+        params = utils.remove_nones({
+            'leader_api_addr': leader_api_addr,
+            'retry': retry,
+            'leader_ca_cert': leader_ca_cert,
+            'leader_client_cert': leader_client_cert,
+            'leader_client_key': leader_client_key,
+        })
+        api_path = '/v1/sys/storage/raft/join'
+        return self._adapter.post(
+            url=api_path,
+            json=params,
+        )
+
+    def read_raft_config(self):
+        """Read the details of all the nodes in the raft cluster.
+
+        Supported methods:
+            GET: /sys/storage/raft/configuration.
+
+        :return: The response of the read_raft_config request.
+        :rtype: requests.Response
+        """
+        api_path = '/v1/sys/storage/raft/configuration'
+        return self._adapter.get(
+            url=api_path,
+        )
+
+    def remove_raft_node(self, server_id):
+        """Remove a node from the raft cluster.
+
+        Supported methods:
+            POST: /sys/storage/raft/remove-peer.
+
+        :param server_id: The ID of the node to remove.
+        :type server_id: str
+        :return: The response of the remove_raft_node request.
+        :rtype: requests.Response
+        """
+        params = {
+            'server_id': server_id,
+        }
+        api_path = '/v1/sys/storage/raft/remove-peer'
+        return self._adapter.post(
+            url=api_path,
+            json=params,
+        )
+
+    def take_raft_snapshot(self):
+        """Returns a snapshot of the current state of the raft cluster.
+
+        The snapshot is returned as binary data and should be redirected to a 
file.
+
+        Supported methods:
+            GET: /sys/storage/raft/snapshot.
+
+        :return: The response of the s request.
+        :rtype: requests.Response
+        """
+        api_path = '/v1/sys/storage/raft/snapshot'
+        return self._adapter.get(
+            url=api_path,
+            stream=True,
+        )
+
+    def restore_raft_snapshot(self, snapshot):
+        """Install the provided snapshot, returning the cluster to the state 
defined in it.
+
+        Supported methods:
+            POST: /sys/storage/raft/snapshot.
+
+        :param snapshot: Previously created raft snapshot / binary data.
+        :type snapshot: bytes
+        :return: The response of the restore_raft_snapshot request.
+        :rtype: requests.Response
+        """
+        api_path = '/v1/sys/storage/raft/snapshot'
+        return self._adapter.post(
+            url=api_path,
+            data=snapshot,
+        )
+
+    def force_restore_raft_snapshot(self, snapshot):
+        """Installs the provided snapshot, returning the cluster to the state 
defined in it.
+
+        This is same as writing to /sys/storage/raft/snapshot except that this 
bypasses checks
+        ensuring the Autounseal or shamir keys are consistent with the 
snapshot data.
+
+        Supported methods:
+            POST: /sys/storage/raft/snapshot-force.
+
+        :param snapshot: Previously created raft snapshot / binary data.
+        :type snapshot: bytes
+        :return: The response of the force_restore_raft_snapshot request.
+        :rtype: requests.Response
+        """
+        api_path = '/v1/sys/storage/raft/snapshot-force'
+        return self._adapter.post(
+            url=api_path,
+            data=snapshot,
+        )
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hvac-0.10.1/hvac/exceptions.py 
new/hvac-0.10.3/hvac/exceptions.py
--- old/hvac-0.10.1/hvac/exceptions.py  2020-04-07 22:57:10.000000000 +0200
+++ new/hvac-0.10.3/hvac/exceptions.py  2020-05-24 21:19:23.000000000 +0200
@@ -1,12 +1,17 @@
 class VaultError(Exception):
-    def __init__(self, message=None, errors=None):
+    def __init__(self, message=None, errors=None, method=None, url=None):
         if errors:
             message = ', '.join(errors)
 
         self.errors = errors
+        self.method = method
+        self.url = url
 
         super(VaultError, self).__init__(message)
 
+    def __str__(self):
+        return "{0}, on {1} {2}".format(self.args[0], self.method, self.url)
+
 
 class InvalidRequest(VaultError):
     pass
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hvac-0.10.1/hvac/utils.py 
new/hvac-0.10.3/hvac/utils.py
--- old/hvac-0.10.1/hvac/utils.py       2020-04-07 22:57:10.000000000 +0200
+++ new/hvac-0.10.3/hvac/utils.py       2020-05-24 21:19:23.000000000 +0200
@@ -13,9 +13,13 @@
 from hvac import exceptions
 
 
-def raise_for_error(status_code, message=None, errors=None):
+def raise_for_error(method, url, status_code, message=None, errors=None):
     """Helper method to raise exceptions based on the status code of a 
response received back from Vault.
 
+    :param method: HTTP method of a request to Vault.
+    :type method: str
+    :param url: URL of the endpoint requested in Vault.
+    :type url: str
     :param status_code: Status code received in a response from Vault.
     :type status_code: int
     :param message: Optional message to include in a resulting exception.
@@ -25,29 +29,30 @@
 
     :raises: hvac.exceptions.InvalidRequest | hvac.exceptions.Unauthorized | 
hvac.exceptions.Forbidden |
         hvac.exceptions.InvalidPath | hvac.exceptions.RateLimitExceeded | 
hvac.exceptions.InternalServerError |
-        hvac.exceptions.VaultNotInitialized | hvac.exceptions.VaultDown | 
hvac.exceptions.UnexpectedError
+        hvac.exceptions.VaultNotInitialized | hvac.exceptions.BadGateway | 
hvac.exceptions.VaultDown |
+        hvac.exceptions.UnexpectedError
 
     """
     if status_code == 400:
-        raise exceptions.InvalidRequest(message, errors=errors)
+        raise exceptions.InvalidRequest(message, errors=errors, method=method, 
url=url)
     elif status_code == 401:
-        raise exceptions.Unauthorized(message, errors=errors)
+        raise exceptions.Unauthorized(message, errors=errors, method=method, 
url=url)
     elif status_code == 403:
-        raise exceptions.Forbidden(message, errors=errors)
+        raise exceptions.Forbidden(message, errors=errors, method=method, 
url=url)
     elif status_code == 404:
-        raise exceptions.InvalidPath(message, errors=errors)
+        raise exceptions.InvalidPath(message, errors=errors, method=method, 
url=url)
     elif status_code == 429:
-        raise exceptions.RateLimitExceeded(message, errors=errors)
+        raise exceptions.RateLimitExceeded(message, errors=errors, 
method=method, url=url)
     elif status_code == 500:
-        raise exceptions.InternalServerError(message, errors=errors)
+        raise exceptions.InternalServerError(message, errors=errors, 
method=method, url=url)
     elif status_code == 501:
-        raise exceptions.VaultNotInitialized(message, errors=errors)
+        raise exceptions.VaultNotInitialized(message, errors=errors, 
method=method, url=url)
     elif status_code == 502:
-        raise exceptions.BadGateway(message, errors=errors)
+        raise exceptions.BadGateway(message, errors=errors, method=method, 
url=url)
     elif status_code == 503:
-        raise exceptions.VaultDown(message, errors=errors)
+        raise exceptions.VaultDown(message, errors=errors, method=method, 
url=url)
     else:
-        raise exceptions.UnexpectedError(message or errors)
+        raise exceptions.UnexpectedError(message or errors, method=method, 
url=url)
 
 
 def generate_method_deprecation_message(to_be_removed_in_version, 
old_method_name, method_name=None, module_name=None):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hvac-0.10.1/hvac/v1/__init__.py 
new/hvac-0.10.3/hvac/v1/__init__.py
--- old/hvac-0.10.1/hvac/v1/__init__.py 2020-04-07 22:57:10.000000000 +0200
+++ new/hvac-0.10.3/hvac/v1/__init__.py 2020-05-24 21:19:23.000000000 +0200
@@ -1335,7 +1335,7 @@
         """
         return self._adapter.get('/v1/auth/{0}/role/{1}'.format(mount_point, 
role_name))
 
-    def create_role_secret_id(self, role_name, meta=None, cidr_list=None, 
wrap_ttl=None, mount_point='approle'):
+    def create_role_secret_id(self, role_name, meta=None, cidr_list=None, 
token_bound_cidrs=None, wrap_ttl=None, mount_point='approle'):
         """POST /auth/<mount_point>/role/<role name>/secret-id
 
         :param role_name:
@@ -1344,6 +1344,8 @@
         :type meta:
         :param cidr_list:
         :type cidr_list:
+        :param token_bound_cidrs:
+        :type token_bound_cidrs:
         :param wrap_ttl:
         :type wrap_ttl:
         :param mount_point:
@@ -1358,6 +1360,8 @@
             params['metadata'] = json.dumps(meta)
         if cidr_list is not None:
             params['cidr_list'] = cidr_list
+        if token_bound_cidrs is not None:
+            params['token_bound_cidrs'] = token_bound_cidrs
         return self._adapter.post(url, json=params, wrap_ttl=wrap_ttl)
 
     def get_role_secret_id(self, role_name, secret_id, mount_point='approle'):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hvac-0.10.1/setup.cfg new/hvac-0.10.3/setup.cfg
--- old/hvac-0.10.1/setup.cfg   2020-04-07 22:57:10.000000000 +0200
+++ new/hvac-0.10.3/setup.cfg   2020-05-24 21:19:23.000000000 +0200
@@ -1,5 +1,6 @@
 [metadata]
 description = README.md
+license_files = LICENSE.txt
 
 [bdist_wheel]
 universal = 1
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hvac-0.10.1/setup.py new/hvac-0.10.3/setup.py
--- old/hvac-0.10.1/setup.py    2020-04-07 22:57:10.000000000 +0200
+++ new/hvac-0.10.3/setup.py    2020-05-24 21:19:23.000000000 +0200
@@ -10,7 +10,7 @@
 
 setup(
     name='hvac',
-    version='0.10.1',
+    version='0.10.3',
     description='HashiCorp Vault API client',
     long_description=load_long_description(),
     long_description_content_type="text/markdown",
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/hvac-0.10.1/tests/integration_tests/api/auth_methods/test_kubernetes.py 
new/hvac-0.10.3/tests/integration_tests/api/auth_methods/test_kubernetes.py
--- old/hvac-0.10.1/tests/integration_tests/api/auth_methods/test_kubernetes.py 
2020-04-07 22:57:10.000000000 +0200
+++ new/hvac-0.10.3/tests/integration_tests/api/auth_methods/test_kubernetes.py 
2020-05-24 21:19:23.000000000 +0200
@@ -33,6 +33,10 @@
 
         ),
         param(
+            'issuer test',
+            issuer='bob'
+        ),
+        param(
             'set invalid kubernetes_ca_cert',
             kubernetes_ca_cert='ca_cert',
             raises=exceptions.ParamValidationError,
@@ -49,12 +53,13 @@
             'set invalid token_reviewer_jwt',
             kubernetes_ca_cert='-----BEGIN CERTIFICATE-----\\n.....\\n-----END 
CERTIFICATE-----',
             token_reviewer_jwt='reviewer_jwt',
+            issuer='bob',
             raises=exceptions.InternalServerError,
             exception_message='* not a compact JWS'
         )
     ])
     def test_configure(self, label, kubernetes_ca_cert=None, 
token_reviewer_jwt=None, pem_keys=None,
-                       raises=None, exception_message=''):
+                       issuer=None, raises=None, exception_message=''):
         kubernetes_host = 'https://192.168.99.100:8443'
         if raises:
             with self.assertRaises(raises) as cm:
@@ -73,7 +78,8 @@
             configure_response = self.client.auth.kubernetes.configure(
                 kubernetes_host=kubernetes_host,
                 kubernetes_ca_cert='-----BEGIN 
CERTIFICATE-----\\n.....\\n-----END CERTIFICATE-----',
-                mount_point=self.TEST_MOUNT_POINT
+                mount_point=self.TEST_MOUNT_POINT,
+                issuer="bob"
             )
             logging.debug('configure_response: %s' % configure_response)
             self.assertEqual(
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/hvac-0.10.1/tests/integration_tests/api/system_backend/test_key.py 
new/hvac-0.10.3/tests/integration_tests/api/system_backend/test_key.py
--- old/hvac-0.10.1/tests/integration_tests/api/system_backend/test_key.py      
2020-04-07 22:57:10.000000000 +0200
+++ new/hvac-0.10.3/tests/integration_tests/api/system_backend/test_key.py      
2020-05-24 21:19:23.000000000 +0200
@@ -89,6 +89,32 @@
         cls.manager.keys = result['keys']
         cls.manager.unseal()
 
+    def test_rekey_verify_multi(self):
+        cls = type(self)
+
+        # Start rekey process with verification required and use operator keys
+        self.assertFalse(self.client.sys.read_rekey_progress()['started'])
+        result = self.client.sys.start_rekey(require_verification=True)
+        result = self.client.sys.rekey_multi(cls.manager.keys, 
nonce=result['nonce'])
+        self.assertTrue(result['complete'])
+        cls.manager.keys = result['keys']
+
+        # get the initial verification nonce
+        result = self.client.sys.read_rekey_verify_progress()
+        first_nonce = result['nonce']
+
+        # now cancel the process and verify we have a new verification nonce
+        result = self.client.sys.cancel_rekey_verify()
+        second_nonce = result['nonce']
+        self.assertNotEqual(first_nonce, second_nonce)
+
+        # finally complete the verification process
+        result = self.client.sys.rekey_verify_multi(cls.manager.keys, 
nonce=result['nonce'])
+        self.assertTrue(result['complete'])
+
+        # now we unseal
+        cls.manager.unseal()
+
     def test_get_backed_up_keys(self):
         with self.assertRaises(exceptions.InvalidRequest) as cm:
             self.client.sys.read_backup_keys()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/hvac-0.10.1/tests/integration_tests/v1/test_integration.py 
new/hvac-0.10.3/tests/integration_tests/v1/test_integration.py
--- old/hvac-0.10.1/tests/integration_tests/v1/test_integration.py      
2020-04-07 22:57:10.000000000 +0200
+++ new/hvac-0.10.3/tests/integration_tests/v1/test_integration.py      
2020-05-24 21:19:23.000000000 +0200
@@ -759,7 +759,7 @@
 
         expected_exception_message = 'missing client token'
         actual_exception_message = str(assertRaisesContext.exception)
-        self.assertEqual(expected_exception_message, actual_exception_message)
+        self.assertIn(expected_exception_message, actual_exception_message)
 
         # Reset test state.
         self.client.token = self.manager.root_token
@@ -787,7 +787,7 @@
 
         expected_exception_message = 'failed to decode the PEM encoded PKCS#7 
signature'
         actual_exception_message = str(assertRaisesContext.exception)
-        self.assertEqual(expected_exception_message, actual_exception_message)
+        self.assertIn(expected_exception_message, actual_exception_message)
 
         # Reset test state.
         self.client.token = self.manager.root_token
@@ -815,7 +815,7 @@
 
         expected_exception_message = 'missing client token'
         actual_exception_message = str(assertRaisesContext.exception)
-        self.assertEqual(expected_exception_message, actual_exception_message)
+        self.assertIn(expected_exception_message, actual_exception_message)
 
         # Reset test state.
         self.client.token = self.manager.root_token
@@ -1076,7 +1076,7 @@
 
         expected_exception_message = 'claim "iss" is invalid'
         actual_exception_message = str(assertRaisesContext.exception)
-        self.assertEqual(expected_exception_message, actual_exception_message)
+        self.assertIn(expected_exception_message, actual_exception_message)
 
         # Reset integration test state
         self.client.disable_auth_backend(mount_point=test_mount_point)


Reply via email to