From be5f61008f80225ce3f6ae1b9556e0b7087994ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9B=D0=B5=D0=B2?= Date: Mon, 25 Aug 2025 10:01:48 +0500 Subject: [PATCH] =?UTF-8?q?=D1=83=D0=B4=D0=B0=D0=BB=D1=8F=D1=8E=20=D0=BF?= =?UTF-8?q?=D0=B0=D0=BF=D0=BA=D1=83=20venv?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../hvac-2.3.0.dist-info/INSTALLER | 1 - .../hvac-2.3.0.dist-info/LICENSE.txt | 202 -- .../hvac-2.3.0.dist-info/METADATA | 70 - .../site-packages/hvac-2.3.0.dist-info/RECORD | 142 -- .../hvac-2.3.0.dist-info/REQUESTED | 0 .../site-packages/hvac-2.3.0.dist-info/WHEEL | 4 - .../python3.12/site-packages/hvac/__init__.py | 3 - .../hvac/__pycache__/__init__.cpython-312.pyc | Bin 262 -> 0 bytes .../hvac/__pycache__/adapters.cpython-312.pyc | Bin 17692 -> 0 bytes .../__pycache__/aws_utils.cpython-312.pyc | Bin 5212 -> 0 bytes .../__pycache__/exceptions.cpython-312.pyc | Bin 3614 -> 0 bytes .../hvac/__pycache__/utils.cpython-312.pyc | Bin 18993 -> 0 bytes .../python3.12/site-packages/hvac/adapters.py | 419 ----- .../site-packages/hvac/api/__init__.py | 14 - .../api/__pycache__/__init__.cpython-312.pyc | Bin 629 -> 0 bytes .../vault_api_base.cpython-312.pyc | Bin 1000 -> 0 bytes .../vault_api_category.cpython-312.pyc | Bin 5051 -> 0 bytes .../hvac/api/auth_methods/__init__.py | 64 - .../__pycache__/__init__.cpython-312.pyc | Bin 1800 -> 0 bytes .../__pycache__/approle.cpython-312.pyc | Bin 19994 -> 0 bytes .../__pycache__/aws.cpython-312.pyc | Bin 42690 -> 0 bytes .../__pycache__/azure.cpython-312.pyc | Bin 13413 -> 0 bytes .../__pycache__/cert.cpython-312.pyc | Bin 14759 -> 0 bytes .../__pycache__/gcp.cpython-312.pyc | Bin 18452 -> 0 bytes .../__pycache__/github.cpython-312.pyc | Bin 9044 -> 0 bytes .../__pycache__/jwt.cpython-312.pyc | Bin 19517 -> 0 bytes .../__pycache__/kubernetes.cpython-312.pyc | Bin 11917 -> 0 bytes .../__pycache__/ldap.cpython-312.pyc | Bin 22726 -> 0 bytes .../__pycache__/legacy_mfa.cpython-312.pyc | Bin 6990 -> 0 bytes .../__pycache__/oidc.cpython-312.pyc | Bin 8249 -> 0 bytes .../__pycache__/okta.cpython-312.pyc | Bin 11663 -> 0 bytes .../__pycache__/radius.cpython-312.pyc | Bin 8884 -> 0 bytes .../__pycache__/token.cpython-312.pyc | Bin 25373 -> 0 bytes .../__pycache__/userpass.cpython-312.pyc | Bin 6212 -> 0 bytes .../hvac/api/auth_methods/approle.py | 510 ----- .../hvac/api/auth_methods/aws.py | 992 ---------- .../hvac/api/auth_methods/azure.py | 343 ---- .../hvac/api/auth_methods/cert.py | 328 ---- .../hvac/api/auth_methods/gcp.py | 463 ----- .../hvac/api/auth_methods/github.py | 241 --- .../hvac/api/auth_methods/jwt.py | 457 ----- .../hvac/api/auth_methods/kubernetes.py | 308 ---- .../hvac/api/auth_methods/ldap.py | 541 ------ .../hvac/api/auth_methods/legacy_mfa.py | 172 -- .../hvac/api/auth_methods/oidc.py | 166 -- .../hvac/api/auth_methods/okta.py | 332 ---- .../hvac/api/auth_methods/radius.py | 237 --- .../hvac/api/auth_methods/token.py | 658 ------- .../hvac/api/auth_methods/userpass.py | 167 -- .../hvac/api/secrets_engines/__init__.py | 71 - .../__pycache__/__init__.cpython-312.pyc | Bin 1962 -> 0 bytes .../active_directory.cpython-312.pyc | Bin 8010 -> 0 bytes .../__pycache__/aws.cpython-312.pyc | Bin 17301 -> 0 bytes .../__pycache__/azure.cpython-312.pyc | Bin 8092 -> 0 bytes .../__pycache__/consul.cpython-312.pyc | Bin 7495 -> 0 bytes .../__pycache__/database.cpython-312.pyc | Bin 15835 -> 0 bytes .../__pycache__/gcp.cpython-312.pyc | Bin 28375 -> 0 bytes .../__pycache__/identity.cpython-312.pyc | Bin 56795 -> 0 bytes .../__pycache__/kv.cpython-312.pyc | Bin 4209 -> 0 bytes .../__pycache__/kv_v1.cpython-312.pyc | Bin 6164 -> 0 bytes .../__pycache__/kv_v2.cpython-312.pyc | Bin 20335 -> 0 bytes .../__pycache__/ldap.cpython-312.pyc | Bin 10793 -> 0 bytes .../__pycache__/pki.cpython-312.pyc | Bin 29338 -> 0 bytes .../__pycache__/rabbitmq.cpython-312.pyc | Bin 6501 -> 0 bytes .../__pycache__/ssh.cpython-312.pyc | Bin 20664 -> 0 bytes .../__pycache__/transform.cpython-312.pyc | Bin 44285 -> 0 bytes .../__pycache__/transit.cpython-312.pyc | Bin 48326 -> 0 bytes .../api/secrets_engines/active_directory.py | 181 -- .../hvac/api/secrets_engines/aws.py | 407 ---- .../hvac/api/secrets_engines/azure.py | 201 -- .../hvac/api/secrets_engines/consul.py | 171 -- .../hvac/api/secrets_engines/database.py | 405 ---- .../hvac/api/secrets_engines/gcp.py | 746 -------- .../hvac/api/secrets_engines/identity.py | 1642 ----------------- .../hvac/api/secrets_engines/kv.py | 80 - .../hvac/api/secrets_engines/kv_v1.py | 144 -- .../hvac/api/secrets_engines/kv_v2.py | 509 ----- .../hvac/api/secrets_engines/ldap.py | 236 --- .../hvac/api/secrets_engines/pki.py | 878 --------- .../hvac/api/secrets_engines/rabbitmq.py | 147 -- .../hvac/api/secrets_engines/ssh.py | 557 ------ .../hvac/api/secrets_engines/transform.py | 1174 ------------ .../hvac/api/secrets_engines/transit.py | 1163 ------------ .../hvac/api/system_backend/__init__.py | 85 - .../__pycache__/__init__.cpython-312.pyc | Bin 2145 -> 0 bytes .../__pycache__/audit.cpython-312.pyc | Bin 4562 -> 0 bytes .../__pycache__/auth.cpython-312.pyc | Bin 9657 -> 0 bytes .../__pycache__/capabilities.cpython-312.pyc | Bin 1808 -> 0 bytes .../__pycache__/health.cpython-312.pyc | Bin 3586 -> 0 bytes .../__pycache__/init.cpython-312.pyc | Bin 5745 -> 0 bytes .../__pycache__/key.cpython-312.pyc | Bin 16788 -> 0 bytes .../__pycache__/leader.cpython-312.pyc | Bin 1827 -> 0 bytes .../__pycache__/lease.cpython-312.pyc | Bin 5159 -> 0 bytes .../__pycache__/mount.cpython-312.pyc | Bin 10572 -> 0 bytes .../__pycache__/namespace.cpython-312.pyc | Bin 2188 -> 0 bytes .../__pycache__/policies.cpython-312.pyc | Bin 9648 -> 0 bytes .../__pycache__/policy.cpython-312.pyc | Bin 3721 -> 0 bytes .../__pycache__/quota.cpython-312.pyc | Bin 4466 -> 0 bytes .../__pycache__/raft.cpython-312.pyc | Bin 10552 -> 0 bytes .../__pycache__/seal.cpython-312.pyc | Bin 4158 -> 0 bytes .../system_backend_mixin.cpython-312.pyc | Bin 696 -> 0 bytes .../__pycache__/wrapping.cpython-312.pyc | Bin 2416 -> 0 bytes .../hvac/api/system_backend/audit.py | 104 -- .../hvac/api/system_backend/auth.py | 212 --- .../hvac/api/system_backend/capabilities.py | 43 - .../hvac/api/system_backend/health.py | 83 - .../hvac/api/system_backend/init.py | 146 -- .../hvac/api/system_backend/key.py | 407 ---- .../hvac/api/system_backend/leader.py | 35 - .../hvac/api/system_backend/lease.py | 131 -- .../hvac/api/system_backend/mount.py | 239 --- .../hvac/api/system_backend/namespace.py | 46 - .../hvac/api/system_backend/policies.py | 236 --- .../hvac/api/system_backend/policy.py | 86 - .../hvac/api/system_backend/quota.py | 101 - .../hvac/api/system_backend/raft.py | 253 --- .../hvac/api/system_backend/seal.py | 104 -- .../system_backend/system_backend_mixin.py | 11 - .../hvac/api/system_backend/wrapping.py | 51 - .../site-packages/hvac/api/vault_api_base.py | 17 - .../hvac/api/vault_api_category.py | 100 - .../site-packages/hvac/aws_utils.py | 81 - .../site-packages/hvac/constants/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 213 -> 0 bytes .../__pycache__/approle.cpython-312.pyc | Bin 408 -> 0 bytes .../constants/__pycache__/aws.cpython-312.pyc | Bin 597 -> 0 bytes .../__pycache__/azure.cpython-312.pyc | Bin 405 -> 0 bytes .../__pycache__/client.cpython-312.pyc | Bin 581 -> 0 bytes .../constants/__pycache__/gcp.cpython-312.pyc | Bin 743 -> 0 bytes .../__pycache__/identity.cpython-312.pyc | Bin 385 -> 0 bytes .../__pycache__/transit.cpython-312.pyc | Bin 1036 -> 0 bytes .../site-packages/hvac/constants/approle.py | 11 - .../site-packages/hvac/constants/aws.py | 8 - .../site-packages/hvac/constants/azure.py | 9 - .../site-packages/hvac/constants/client.py | 28 - .../site-packages/hvac/constants/gcp.py | 17 - .../site-packages/hvac/constants/identity.py | 8 - .../site-packages/hvac/constants/transit.py | 52 - .../site-packages/hvac/exceptions.py | 85 - .../python3.12/site-packages/hvac/utils.py | 460 ----- .../site-packages/hvac/v1/__init__.py | 552 ------ .../v1/__pycache__/__init__.cpython-312.pyc | Bin 21129 -> 0 bytes 142 files changed, 19347 deletions(-) delete mode 100644 .venv/lib/python3.12/site-packages/hvac-2.3.0.dist-info/INSTALLER delete mode 100644 .venv/lib/python3.12/site-packages/hvac-2.3.0.dist-info/LICENSE.txt delete mode 100644 .venv/lib/python3.12/site-packages/hvac-2.3.0.dist-info/METADATA delete mode 100644 .venv/lib/python3.12/site-packages/hvac-2.3.0.dist-info/RECORD delete mode 100644 .venv/lib/python3.12/site-packages/hvac-2.3.0.dist-info/REQUESTED delete mode 100644 .venv/lib/python3.12/site-packages/hvac-2.3.0.dist-info/WHEEL delete mode 100644 .venv/lib/python3.12/site-packages/hvac/__init__.py delete mode 100644 .venv/lib/python3.12/site-packages/hvac/__pycache__/__init__.cpython-312.pyc delete mode 100644 .venv/lib/python3.12/site-packages/hvac/__pycache__/adapters.cpython-312.pyc delete mode 100644 .venv/lib/python3.12/site-packages/hvac/__pycache__/aws_utils.cpython-312.pyc delete mode 100644 .venv/lib/python3.12/site-packages/hvac/__pycache__/exceptions.cpython-312.pyc delete mode 100644 .venv/lib/python3.12/site-packages/hvac/__pycache__/utils.cpython-312.pyc delete mode 100644 .venv/lib/python3.12/site-packages/hvac/adapters.py delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/__init__.py delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/__pycache__/__init__.cpython-312.pyc delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/__pycache__/vault_api_base.cpython-312.pyc delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/__pycache__/vault_api_category.cpython-312.pyc delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/auth_methods/__init__.py delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/auth_methods/__pycache__/__init__.cpython-312.pyc delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/auth_methods/__pycache__/approle.cpython-312.pyc delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/auth_methods/__pycache__/aws.cpython-312.pyc delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/auth_methods/__pycache__/azure.cpython-312.pyc delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/auth_methods/__pycache__/cert.cpython-312.pyc delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/auth_methods/__pycache__/gcp.cpython-312.pyc delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/auth_methods/__pycache__/github.cpython-312.pyc delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/auth_methods/__pycache__/jwt.cpython-312.pyc delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/auth_methods/__pycache__/kubernetes.cpython-312.pyc delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/auth_methods/__pycache__/ldap.cpython-312.pyc delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/auth_methods/__pycache__/legacy_mfa.cpython-312.pyc delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/auth_methods/__pycache__/oidc.cpython-312.pyc delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/auth_methods/__pycache__/okta.cpython-312.pyc delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/auth_methods/__pycache__/radius.cpython-312.pyc delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/auth_methods/__pycache__/token.cpython-312.pyc delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/auth_methods/__pycache__/userpass.cpython-312.pyc delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/auth_methods/approle.py delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/auth_methods/aws.py delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/auth_methods/azure.py delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/auth_methods/cert.py delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/auth_methods/gcp.py delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/auth_methods/github.py delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/auth_methods/jwt.py delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/auth_methods/kubernetes.py delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/auth_methods/ldap.py delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/auth_methods/legacy_mfa.py delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/auth_methods/oidc.py delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/auth_methods/okta.py delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/auth_methods/radius.py delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/auth_methods/token.py delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/auth_methods/userpass.py delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/secrets_engines/__init__.py delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/secrets_engines/__pycache__/__init__.cpython-312.pyc delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/secrets_engines/__pycache__/active_directory.cpython-312.pyc delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/secrets_engines/__pycache__/aws.cpython-312.pyc delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/secrets_engines/__pycache__/azure.cpython-312.pyc delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/secrets_engines/__pycache__/consul.cpython-312.pyc delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/secrets_engines/__pycache__/database.cpython-312.pyc delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/secrets_engines/__pycache__/gcp.cpython-312.pyc delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/secrets_engines/__pycache__/identity.cpython-312.pyc delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/secrets_engines/__pycache__/kv.cpython-312.pyc delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/secrets_engines/__pycache__/kv_v1.cpython-312.pyc delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/secrets_engines/__pycache__/kv_v2.cpython-312.pyc delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/secrets_engines/__pycache__/ldap.cpython-312.pyc delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/secrets_engines/__pycache__/pki.cpython-312.pyc delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/secrets_engines/__pycache__/rabbitmq.cpython-312.pyc delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/secrets_engines/__pycache__/ssh.cpython-312.pyc delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/secrets_engines/__pycache__/transform.cpython-312.pyc delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/secrets_engines/__pycache__/transit.cpython-312.pyc delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/secrets_engines/active_directory.py delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/secrets_engines/aws.py delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/secrets_engines/azure.py delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/secrets_engines/consul.py delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/secrets_engines/database.py delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/secrets_engines/gcp.py delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/secrets_engines/identity.py delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/secrets_engines/kv.py delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/secrets_engines/kv_v1.py delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/secrets_engines/kv_v2.py delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/secrets_engines/ldap.py delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/secrets_engines/pki.py delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/secrets_engines/rabbitmq.py delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/secrets_engines/ssh.py delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/secrets_engines/transform.py delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/secrets_engines/transit.py delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/system_backend/__init__.py delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/system_backend/__pycache__/__init__.cpython-312.pyc delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/system_backend/__pycache__/audit.cpython-312.pyc delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/system_backend/__pycache__/auth.cpython-312.pyc delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/system_backend/__pycache__/capabilities.cpython-312.pyc delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/system_backend/__pycache__/health.cpython-312.pyc delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/system_backend/__pycache__/init.cpython-312.pyc delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/system_backend/__pycache__/key.cpython-312.pyc delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/system_backend/__pycache__/leader.cpython-312.pyc delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/system_backend/__pycache__/lease.cpython-312.pyc delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/system_backend/__pycache__/mount.cpython-312.pyc delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/system_backend/__pycache__/namespace.cpython-312.pyc delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/system_backend/__pycache__/policies.cpython-312.pyc delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/system_backend/__pycache__/policy.cpython-312.pyc delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/system_backend/__pycache__/quota.cpython-312.pyc delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/system_backend/__pycache__/raft.cpython-312.pyc delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/system_backend/__pycache__/seal.cpython-312.pyc delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/system_backend/__pycache__/system_backend_mixin.cpython-312.pyc delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/system_backend/__pycache__/wrapping.cpython-312.pyc delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/system_backend/audit.py delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/system_backend/auth.py delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/system_backend/capabilities.py delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/system_backend/health.py delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/system_backend/init.py delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/system_backend/key.py delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/system_backend/leader.py delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/system_backend/lease.py delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/system_backend/mount.py delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/system_backend/namespace.py delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/system_backend/policies.py delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/system_backend/policy.py delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/system_backend/quota.py delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/system_backend/raft.py delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/system_backend/seal.py delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/system_backend/system_backend_mixin.py delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/system_backend/wrapping.py delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/vault_api_base.py delete mode 100644 .venv/lib/python3.12/site-packages/hvac/api/vault_api_category.py delete mode 100644 .venv/lib/python3.12/site-packages/hvac/aws_utils.py delete mode 100644 .venv/lib/python3.12/site-packages/hvac/constants/__init__.py delete mode 100644 .venv/lib/python3.12/site-packages/hvac/constants/__pycache__/__init__.cpython-312.pyc delete mode 100644 .venv/lib/python3.12/site-packages/hvac/constants/__pycache__/approle.cpython-312.pyc delete mode 100644 .venv/lib/python3.12/site-packages/hvac/constants/__pycache__/aws.cpython-312.pyc delete mode 100644 .venv/lib/python3.12/site-packages/hvac/constants/__pycache__/azure.cpython-312.pyc delete mode 100644 .venv/lib/python3.12/site-packages/hvac/constants/__pycache__/client.cpython-312.pyc delete mode 100644 .venv/lib/python3.12/site-packages/hvac/constants/__pycache__/gcp.cpython-312.pyc delete mode 100644 .venv/lib/python3.12/site-packages/hvac/constants/__pycache__/identity.cpython-312.pyc delete mode 100644 .venv/lib/python3.12/site-packages/hvac/constants/__pycache__/transit.cpython-312.pyc delete mode 100644 .venv/lib/python3.12/site-packages/hvac/constants/approle.py delete mode 100644 .venv/lib/python3.12/site-packages/hvac/constants/aws.py delete mode 100644 .venv/lib/python3.12/site-packages/hvac/constants/azure.py delete mode 100644 .venv/lib/python3.12/site-packages/hvac/constants/client.py delete mode 100644 .venv/lib/python3.12/site-packages/hvac/constants/gcp.py delete mode 100644 .venv/lib/python3.12/site-packages/hvac/constants/identity.py delete mode 100644 .venv/lib/python3.12/site-packages/hvac/constants/transit.py delete mode 100644 .venv/lib/python3.12/site-packages/hvac/exceptions.py delete mode 100644 .venv/lib/python3.12/site-packages/hvac/utils.py delete mode 100644 .venv/lib/python3.12/site-packages/hvac/v1/__init__.py delete mode 100644 .venv/lib/python3.12/site-packages/hvac/v1/__pycache__/__init__.cpython-312.pyc diff --git a/.venv/lib/python3.12/site-packages/hvac-2.3.0.dist-info/INSTALLER b/.venv/lib/python3.12/site-packages/hvac-2.3.0.dist-info/INSTALLER deleted file mode 100644 index a1b589e..0000000 --- a/.venv/lib/python3.12/site-packages/hvac-2.3.0.dist-info/INSTALLER +++ /dev/null @@ -1 +0,0 @@ -pip diff --git a/.venv/lib/python3.12/site-packages/hvac-2.3.0.dist-info/LICENSE.txt b/.venv/lib/python3.12/site-packages/hvac-2.3.0.dist-info/LICENSE.txt deleted file mode 100644 index 8f71f43..0000000 --- a/.venv/lib/python3.12/site-packages/hvac-2.3.0.dist-info/LICENSE.txt +++ /dev/null @@ -1,202 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright {yyyy} {name of copyright owner} - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - diff --git a/.venv/lib/python3.12/site-packages/hvac-2.3.0.dist-info/METADATA b/.venv/lib/python3.12/site-packages/hvac-2.3.0.dist-info/METADATA deleted file mode 100644 index 7100189..0000000 --- a/.venv/lib/python3.12/site-packages/hvac-2.3.0.dist-info/METADATA +++ /dev/null @@ -1,70 +0,0 @@ -Metadata-Version: 2.1 -Name: hvac -Version: 2.3.0 -Summary: HashiCorp Vault API client -Home-page: https://github.com/hvac/hvac -License: Apache-2.0 -Keywords: hashicorp,vault -Author: Ian Unruh -Author-email: ianunruh@gmail.com -Maintainer: Brian Scholer -Requires-Python: >=3.8,<4.0 -Classifier: License :: OSI Approved :: Apache Software License -Classifier: Programming Language :: Python -Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3.8 -Classifier: Programming Language :: Python :: 3.9 -Classifier: Programming Language :: Python :: 3.10 -Classifier: Programming Language :: Python :: 3.11 -Classifier: Programming Language :: Python :: 3.12 -Classifier: Programming Language :: Python :: Implementation :: CPython -Provides-Extra: parser -Requires-Dist: pyhcl (>=0.4.4,<0.5.0) ; extra == "parser" -Requires-Dist: requests (>=2.27.1,<3.0.0) -Project-URL: Documentation, https://hvac.readthedocs.io/en/stable/overview.html -Project-URL: Repository, https://github.com/hvac/hvac -Description-Content-Type: text/markdown - -# hvac - -![Header image](https://raw.githubusercontent.com/hvac/hvac/main/docs/_static/hvac_logo_800px.png) - -[HashiCorp](https://hashicorp.com/) [Vault](https://www.vaultproject.io) API client for Python 3.x - -[![Build](https://github.com/hvac/hvac/actions/workflows/build-test.yml/badge.svg)](https://github.com/hvac/hvac/actions/workflows/build-test.yml) -[![Lint](https://github.com/hvac/hvac/actions/workflows/lint-and-test.yml/badge.svg)](https://github.com/hvac/hvac/actions/workflows/lint-and-test.yml) -[![codecov](https://codecov.io/gh/hvac/hvac/branch/main/graph/badge.svg)](https://codecov.io/gh/hvac/hvac) -[![Documentation Status](https://readthedocs.org/projects/hvac/badge/)](https://hvac.readthedocs.io/en/latest/?badge=latest) -[![PyPI version](https://badge.fury.io/py/hvac.svg)](https://badge.fury.io/py/hvac) -[![Twitter - @python_hvac](https://img.shields.io/twitter/follow/python_hvac.svg?label=Twitter%20-%20@python_hvac&style=social?style=plastic)](https://twitter.com/python_hvac) -[![Gitter chat](https://badges.gitter.im/hvac/community.png)](https://gitter.im/hvac/community) - -Tested against the latest release, HEAD ref, and 3 previous minor versions (counting back from the latest release) of Vault. -Current official support covers Vault v1.4.7 or later. - -> **NOTE:** Support for EOL Python versions will be dropped at the end of 2022. Starting in 2023, hvac will track -> with the CPython EOL dates. - -## Installation - -```console -pip install hvac -``` - -If you would like to be able to return parsed HCL data as a Python dict for methods that support it: - -```console -pip install "hvac[parser]" -``` - -## Documentation - -Additional documentation for this module available at: [hvac.readthedocs.io](https://hvac.readthedocs.io/en/stable/usage/index.html): - -* [Getting Started](https://hvac.readthedocs.io/en/stable/overview.html#getting-started) -* [Usage](https://hvac.readthedocs.io/en/stable/usage/index.html) -* [Advanced Usage](https://hvac.readthedocs.io/en/stable/advanced_usage.html) -* [Source Reference / Autodoc](https://hvac.readthedocs.io/en/stable/source/index.html) -* [Contributing](https://hvac.readthedocs.io/en/stable/contributing.html) -* [Changelog](https://hvac.readthedocs.io/en/stable/changelog.html) - diff --git a/.venv/lib/python3.12/site-packages/hvac-2.3.0.dist-info/RECORD b/.venv/lib/python3.12/site-packages/hvac-2.3.0.dist-info/RECORD deleted file mode 100644 index 318858f..0000000 --- a/.venv/lib/python3.12/site-packages/hvac-2.3.0.dist-info/RECORD +++ /dev/null @@ -1,142 +0,0 @@ -hvac-2.3.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -hvac-2.3.0.dist-info/LICENSE.txt,sha256=xllut76FgcGL5zbIRvuRc7aezPbvlMUTWJPsVr2Sugg,11358 -hvac-2.3.0.dist-info/METADATA,sha256=Yvx9ppc42yEZlnS6_aBOqMrh3SCKFn8-sStp9xPaKDk,3289 -hvac-2.3.0.dist-info/RECORD,, -hvac-2.3.0.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -hvac-2.3.0.dist-info/WHEEL,sha256=d2fvjOD7sXsVzChCqf0Ty0JbHKBaLYwDbGQDwQTnJ50,88 -hvac/__init__.py,sha256=25yOT_z1e3psfyL8OXfLgGkoTfQQWu4k1ywdXGZpQyU,50 -hvac/__pycache__/__init__.cpython-312.pyc,, -hvac/__pycache__/adapters.cpython-312.pyc,, -hvac/__pycache__/aws_utils.cpython-312.pyc,, -hvac/__pycache__/exceptions.cpython-312.pyc,, -hvac/__pycache__/utils.cpython-312.pyc,, -hvac/adapters.py,sha256=UepSWaL5k78gmV2LbALwtEztZa7ayNpKIlm_eAlOMJU,15613 -hvac/api/__init__.py,sha256=Vtjp1qAFqZE1N6aycW2-rlqOrTi8UqdRyIdXd7Z8c1M,423 -hvac/api/__pycache__/__init__.cpython-312.pyc,, -hvac/api/__pycache__/vault_api_base.cpython-312.pyc,, -hvac/api/__pycache__/vault_api_category.cpython-312.pyc,, -hvac/api/auth_methods/__init__.py,sha256=SLR5FKdP317oWo3855ppXUxW4KHV3BGGKciRm05LwP0,1473 -hvac/api/auth_methods/__pycache__/__init__.cpython-312.pyc,, -hvac/api/auth_methods/__pycache__/approle.cpython-312.pyc,, -hvac/api/auth_methods/__pycache__/aws.cpython-312.pyc,, -hvac/api/auth_methods/__pycache__/azure.cpython-312.pyc,, -hvac/api/auth_methods/__pycache__/cert.cpython-312.pyc,, -hvac/api/auth_methods/__pycache__/gcp.cpython-312.pyc,, -hvac/api/auth_methods/__pycache__/github.cpython-312.pyc,, -hvac/api/auth_methods/__pycache__/jwt.cpython-312.pyc,, -hvac/api/auth_methods/__pycache__/kubernetes.cpython-312.pyc,, -hvac/api/auth_methods/__pycache__/ldap.cpython-312.pyc,, -hvac/api/auth_methods/__pycache__/legacy_mfa.cpython-312.pyc,, -hvac/api/auth_methods/__pycache__/oidc.cpython-312.pyc,, -hvac/api/auth_methods/__pycache__/okta.cpython-312.pyc,, -hvac/api/auth_methods/__pycache__/radius.cpython-312.pyc,, -hvac/api/auth_methods/__pycache__/token.cpython-312.pyc,, -hvac/api/auth_methods/__pycache__/userpass.cpython-312.pyc,, -hvac/api/auth_methods/approle.py,sha256=_PslA3ElGn2w94-4C5-sF4tKufWXi1WabYcH74Lw_uY,20691 -hvac/api/auth_methods/aws.py,sha256=O2-S9VbYc4bHsmePp5MXf13bncto1yMF0pnjUt93qWM,41982 -hvac/api/auth_methods/azure.py,sha256=cW9okkmjmYoeJ8JP9MRRNUZJs46ewrWJDCMb8hOmtAQ,13324 -hvac/api/auth_methods/cert.py,sha256=0PDlcqRTjncHULN_IGfJwWs4TmWMJ0KJrh7NjJre06w,14682 -hvac/api/auth_methods/gcp.py,sha256=hUDJF59BdE_MJPMBmZx2G_jG9WJ7lnoej1QPICaL_jo,18931 -hvac/api/auth_methods/github.py,sha256=cJCg2UsCvWi6t_EnG2Es3FbUL9XrNEG3Tc3nLqyzkM8,8498 -hvac/api/auth_methods/jwt.py,sha256=IALBbMV5f3GrTMViq6qDZTrUEktrXcFbmZ65dkTstV0,19920 -hvac/api/auth_methods/kubernetes.py,sha256=hCBlt08WLB92UG3MI8J7MS7ofBWxEza0sqQdVXkwJwE,12165 -hvac/api/auth_methods/ldap.py,sha256=pWX3ntv8SD4lNsXDC4zgW-FRGioA0n9i_RNQIXebD6I,22974 -hvac/api/auth_methods/legacy_mfa.py,sha256=FZzHu0iO1Vx88DRibuwRVusSS30wvnTwiwSrIf662Vs,6552 -hvac/api/auth_methods/oidc.py,sha256=oFqH8pR8YB6rSWcAhQ9zWTtYUraeb5DFyOqb5Gy2104,8743 -hvac/api/auth_methods/okta.py,sha256=LPEculhB2hTnTvbZSz3GkGR1yv7zKFXZWbofcUxkQlc,11397 -hvac/api/auth_methods/radius.py,sha256=PHe1FMPWHNObckq0jQSvumIjKVuMF4Pj3C4g-aHuCpw,8447 -hvac/api/auth_methods/token.py,sha256=9E21XyCt8o_mpMX1HRr4vAw9FV4E2xi9N9eTTw4uUNo,25885 -hvac/api/auth_methods/userpass.py,sha256=_HP0Nw7ayOcuNQiz2V11gGv-IXdDYeG1KDqalI6FJzI,5582 -hvac/api/secrets_engines/__init__.py,sha256=AbaviTERBkdJqqrkIW07UBSysrXBNeHTiJZVDDeXN08,1712 -hvac/api/secrets_engines/__pycache__/__init__.cpython-312.pyc,, -hvac/api/secrets_engines/__pycache__/active_directory.cpython-312.pyc,, -hvac/api/secrets_engines/__pycache__/aws.cpython-312.pyc,, -hvac/api/secrets_engines/__pycache__/azure.cpython-312.pyc,, -hvac/api/secrets_engines/__pycache__/consul.cpython-312.pyc,, -hvac/api/secrets_engines/__pycache__/database.cpython-312.pyc,, -hvac/api/secrets_engines/__pycache__/gcp.cpython-312.pyc,, -hvac/api/secrets_engines/__pycache__/identity.cpython-312.pyc,, -hvac/api/secrets_engines/__pycache__/kv.cpython-312.pyc,, -hvac/api/secrets_engines/__pycache__/kv_v1.cpython-312.pyc,, -hvac/api/secrets_engines/__pycache__/kv_v2.cpython-312.pyc,, -hvac/api/secrets_engines/__pycache__/ldap.cpython-312.pyc,, -hvac/api/secrets_engines/__pycache__/pki.cpython-312.pyc,, -hvac/api/secrets_engines/__pycache__/rabbitmq.cpython-312.pyc,, -hvac/api/secrets_engines/__pycache__/ssh.cpython-312.pyc,, -hvac/api/secrets_engines/__pycache__/transform.cpython-312.pyc,, -hvac/api/secrets_engines/__pycache__/transit.cpython-312.pyc,, -hvac/api/secrets_engines/active_directory.py,sha256=1TCgHlaI8GqbVzXUtkDe4u2CVuYcFWVUCzYUZENp6GE,7150 -hvac/api/secrets_engines/aws.py,sha256=CGSMJaijMF-rRSIxS1ljPlnYEExKENVcOKkOrC_IK68,17328 -hvac/api/secrets_engines/azure.py,sha256=dmnZbOlU0CnPRfMo6c8OqEO7vLNVIw1-CziAi7qjmmA,7356 -hvac/api/secrets_engines/consul.py,sha256=Iuz7ajKWyZNaVEOJpZgq3A_njdALXaZE7G27RkMTIl0,6728 -hvac/api/secrets_engines/database.py,sha256=Qi3CWnzQEnlZvewpdF-VQrUCl4feIZV0TCiLtZoWpR8,15199 -hvac/api/secrets_engines/gcp.py,sha256=sqmLL0nbqj-_hdeR9cpLISQ8lEsLkJlUdmfD4_yEFBg,27976 -hvac/api/secrets_engines/identity.py,sha256=lKz2F-QFDhNh0L95DdyWj3E5XF8Bj_qxWHjCtf86jgc,60046 -hvac/api/secrets_engines/kv.py,sha256=0tgk1aZnklTgnOU2a2pJknGVv6v_RDP6_6ANp3uGIZw,3000 -hvac/api/secrets_engines/kv_v1.py,sha256=nHYjfA0F9_aAGCC3eMwVjS6bQhqA0gHgZIt7P3_XgDo,5811 -hvac/api/secrets_engines/kv_v2.py,sha256=ZZuChwOPwolnuswZdo9WtQS89lMTxn-3Mt1W5xChC4U,20348 -hvac/api/secrets_engines/ldap.py,sha256=VktJ8jNLm2bUoy_Ku9SV_W-Xs7IDzsQoc2VOHzzE8f8,10096 -hvac/api/secrets_engines/pki.py,sha256=R5hwLbwhN8dzQ3DceP_NlR_OjYMcDBS-RAPc0k4kQpI,28739 -hvac/api/secrets_engines/rabbitmq.py,sha256=aT-KhKdGI7JJwBC1IbM1p79LATKOYBCQBYJSw3bIX6Y,5823 -hvac/api/secrets_engines/ssh.py,sha256=GoUOCUlZwxrTei_gs2gkqsCVGOckxFrQ9-AdrmQef9g,21482 -hvac/api/secrets_engines/transform.py,sha256=9wv-jQF7llueFJojxr1tRkc1LDJ2bHoXRJ-VNdTdgeA,45096 -hvac/api/secrets_engines/transit.py,sha256=VsIZXG2k6Oc1_WgCUOklFG-4cHkPWHWroALfmRLNX2I,52778 -hvac/api/system_backend/__init__.py,sha256=GNFcfUQBPH58-j7Y_XV7qj-b1sAme8Ke-aBV4OWU3c4,1888 -hvac/api/system_backend/__pycache__/__init__.cpython-312.pyc,, -hvac/api/system_backend/__pycache__/audit.cpython-312.pyc,, -hvac/api/system_backend/__pycache__/auth.cpython-312.pyc,, -hvac/api/system_backend/__pycache__/capabilities.cpython-312.pyc,, -hvac/api/system_backend/__pycache__/health.cpython-312.pyc,, -hvac/api/system_backend/__pycache__/init.cpython-312.pyc,, -hvac/api/system_backend/__pycache__/key.cpython-312.pyc,, -hvac/api/system_backend/__pycache__/leader.cpython-312.pyc,, -hvac/api/system_backend/__pycache__/lease.cpython-312.pyc,, -hvac/api/system_backend/__pycache__/mount.cpython-312.pyc,, -hvac/api/system_backend/__pycache__/namespace.cpython-312.pyc,, -hvac/api/system_backend/__pycache__/policies.cpython-312.pyc,, -hvac/api/system_backend/__pycache__/policy.cpython-312.pyc,, -hvac/api/system_backend/__pycache__/quota.cpython-312.pyc,, -hvac/api/system_backend/__pycache__/raft.cpython-312.pyc,, -hvac/api/system_backend/__pycache__/seal.cpython-312.pyc,, -hvac/api/system_backend/__pycache__/system_backend_mixin.cpython-312.pyc,, -hvac/api/system_backend/__pycache__/wrapping.cpython-312.pyc,, -hvac/api/system_backend/audit.py,sha256=97tMu2j3IAI5Qc7ZnZDHr64SeRxhxmWHna5iBN7JE58,3741 -hvac/api/system_backend/auth.py,sha256=txIGYVzFfl7ZSRrwQHvjsqzTQjm4pSJwlnrGFgeUsmI,9289 -hvac/api/system_backend/capabilities.py,sha256=B1o-ZoBbYpfs2a1LSEV7nhjAFqJhl7w5wY6mMcn7ymQ,1668 -hvac/api/system_backend/health.py,sha256=8OiVoqfKpRA0Bc-V9N4MVqgATt3Le0cPgmaZluMPsG8,3310 -hvac/api/system_backend/init.py,sha256=Nbh3ppRNni_vWjGYIZVnVtYYTB7DbzEH_xdwRGpigSY,6253 -hvac/api/system_backend/key.py,sha256=v6x7ZaLfPQgkj5P9txGPEZ1r8utgi6rg-MLAm1EJxQA,15889 -hvac/api/system_backend/leader.py,sha256=cdIu2SUb3y1idNapmyex8wjHDm6PA9ySWumOxDBaYdE,1235 -hvac/api/system_backend/lease.py,sha256=vJvOowbzfgJsSueL3pKMYRgXBusbLankKtNh7noOlDc,4326 -hvac/api/system_backend/mount.py,sha256=7Rrhl5vlT7QgM_D20O5RxxpHjPXNKaJgPNGaa1ODsFM,10108 -hvac/api/system_backend/namespace.py,sha256=hwbOr2dtvfj7EH0uP4l9O8rJ4GwxKtnZc1HaxDDxnls,1393 -hvac/api/system_backend/policies.py,sha256=Xf_7fXwQeY8OflkohXpc35wUrQr8n_b__ZsF865G0JM,8182 -hvac/api/system_backend/policy.py,sha256=29EYX1UxXE-vdNa2x3gdt9Mi2336qnJ1uY6Q03VxeoU,2794 -hvac/api/system_backend/quota.py,sha256=ppaVdrs46iNCfpgIj5gnH0TmQG4m9k44AgcSLIG7Mpw,3773 -hvac/api/system_backend/raft.py,sha256=san20cG6alWabdBn-uW2eWoEHGUk35YdcBPLxLJzD3E,9440 -hvac/api/system_backend/seal.py,sha256=xvIoHbNB7gaVR1uBkJnyYBb29qGI046hbibcrti3ByI,3471 -hvac/api/system_backend/system_backend_mixin.py,sha256=LXCLy-gUv0g9E3noH4m-eqOw5VCmCQjPTZZ7Lp-YBK8,265 -hvac/api/system_backend/wrapping.py,sha256=vzRitztAxnH8ameFlu9BsFeuLrRrZHPwEx8otNQuJjA,1864 -hvac/api/vault_api_base.py,sha256=W7L0_xtr0MYUQScryrH6D5pVK5PtAt-3MB4orflhqZc,479 -hvac/api/vault_api_category.py,sha256=21xWhmiQl5mbCJFX7RXxYFszZGdDiJACa4AH9QoPNzY,3678 -hvac/aws_utils.py,sha256=atwshypIx9bH1OPyWL5W_Qxxixnzdz5oY82P7bO1smQ,3607 -hvac/constants/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -hvac/constants/__pycache__/__init__.cpython-312.pyc,, -hvac/constants/__pycache__/approle.cpython-312.pyc,, -hvac/constants/__pycache__/aws.cpython-312.pyc,, -hvac/constants/__pycache__/azure.cpython-312.pyc,, -hvac/constants/__pycache__/client.cpython-312.pyc,, -hvac/constants/__pycache__/gcp.cpython-312.pyc,, -hvac/constants/__pycache__/identity.cpython-312.pyc,, -hvac/constants/__pycache__/transit.cpython-312.pyc,, -hvac/constants/approle.py,sha256=7-lnC94mv9dYaRdXsIO086g_MpyTzdzp0wUM1aOGfsc,220 -hvac/constants/aws.py,sha256=RBkigoImCLfqq15ewDI47vcQr1DwBw_6uvI6FSm-v18,363 -hvac/constants/azure.py,sha256=yXd1zfqqWS76BMXYk7J9EjFQ3ovJFr5aosBHDEwklcA,221 -hvac/constants/client.py,sha256=nNUZAIoPDnBQ059YfX-W4FuUdV-YyGZ41BbEmCw99eg,927 -hvac/constants/gcp.py,sha256=eTLXYmlFNO3_cI-IGk1ZD1Ghm1XJEE7Xq96fzJmvVhU,515 -hvac/constants/identity.py,sha256=O1svKIkL01h1ZkSBtSoODquVmX9U9v04re_GCIHVuoE,170 -hvac/constants/transit.py,sha256=MlUlCMDnBaq78eFUeFwB8XdjCK_D4JXprzq9i47w_TA,900 -hvac/exceptions.py,sha256=wIk8OfRLk-XYM5cb5dV6RyZ73K8uI139Anlvp-MvgcU,1550 -hvac/utils.py,sha256=DHqdUzkZTSzGX4WE0H4uQvoM5wEDUAKb7Ci0wMjHOEU,18109 -hvac/v1/__init__.py,sha256=M3AQMg1wK-qGJo8EVluw5iBQN3v9UdCPj_g2gP9zm50,17275 -hvac/v1/__pycache__/__init__.cpython-312.pyc,, diff --git a/.venv/lib/python3.12/site-packages/hvac-2.3.0.dist-info/REQUESTED b/.venv/lib/python3.12/site-packages/hvac-2.3.0.dist-info/REQUESTED deleted file mode 100644 index e69de29..0000000 diff --git a/.venv/lib/python3.12/site-packages/hvac-2.3.0.dist-info/WHEEL b/.venv/lib/python3.12/site-packages/hvac-2.3.0.dist-info/WHEEL deleted file mode 100644 index 3695fd1..0000000 --- a/.venv/lib/python3.12/site-packages/hvac-2.3.0.dist-info/WHEEL +++ /dev/null @@ -1,4 +0,0 @@ -Wheel-Version: 1.0 -Generator: poetry-core 1.7.0 -Root-Is-Purelib: true -Tag: py3-none-any diff --git a/.venv/lib/python3.12/site-packages/hvac/__init__.py b/.venv/lib/python3.12/site-packages/hvac/__init__.py deleted file mode 100644 index b8594ac..0000000 --- a/.venv/lib/python3.12/site-packages/hvac/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -from hvac.v1 import Client - -__all__ = ("Client",) diff --git a/.venv/lib/python3.12/site-packages/hvac/__pycache__/__init__.cpython-312.pyc b/.venv/lib/python3.12/site-packages/hvac/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index 03cbdad4ebe8b5c588f23f02c56aa28452b609f2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 262 zcmX@j%ge<81pd30Wf%eJ#~=<2FhLogMSzUy3@HpLj5!Rsj8Tk?Kvon}C6gxeOOO&x z##?O8Ihm<>C4QRBx7ahv5|j1H42zh7Qn%RS;}dgo;^S8`dz-Mn@0_1kQk0()pPZ4Hm!4W2ADoy}8K0J4l$%(huUD3uSEiqn znWSG(S(1^TXRK#vqz}}cs#}nloSg_%t`D+TKR!M)FS8^*Uaz3?7l%!5eoARhs$CH$ e&}v2?F6IRiAD9^#8SgSkJ>U{;WG`X|iU0sU4oK_( diff --git a/.venv/lib/python3.12/site-packages/hvac/__pycache__/adapters.cpython-312.pyc b/.venv/lib/python3.12/site-packages/hvac/__pycache__/adapters.cpython-312.pyc deleted file mode 100644 index 6ccf146f56103797b8a7f20089ae5403a63a30be..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17692 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 diff --git a/.venv/lib/python3.12/site-packages/hvac/__pycache__/aws_utils.cpython-312.pyc b/.venv/lib/python3.12/site-packages/hvac/__pycache__/aws_utils.cpython-312.pyc deleted file mode 100644 index d42becad2991b5d0f14f6dbfa1d7c29ad4ac0e11..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5212 zcmcf_T})fo`CR+rKg=bx4u3K9LQB9awnIWf0!a!=TA(S=6~;QM)w}o{u*tQrbMH0O zu2G{c(u~$A$-@SytLUU@O_fgS!ydA&(mH9$zI?X*BU!ETvORKTzXk85n zO2H1l-P1aS9Fs$l>T%8nE5=&p?69&pq8tk=imA5@dW)G3u$o7RMv09@#HN!4TDr;OhXr1kimS@)M zuzNqr!2->D(AErlFbnU8&DAYCEb8kHT)*zbp8crgY}kt%+NlRyEgE|x=5XUOTczXL z(>CY$1~hZ;uUXCs@xYaH*KqdW10W#{J`c3l(CfDSB&k}jUhS|@RywWO-k7VmEU+Jy zJx{3+k&SlKj72M5*3RDeHMs6;@Bgn1xaphL3P1EsQ_Ok3woU%iTk_(ES03H-moWo?8>0P!Raj5^Sz!#51#9p=$Y!7UC4T#4~`|W z!Sj${vp!=!OQLBxu4aOBdXhrXYKR6Zl-V)(?PBPD##}%QB-|YOelJ4nOpaNpg#`%O ztZVlg6agEy{la{XX#+SoXI^K2&TKLadNshJjO{n}H6~!c&kWyZJktT2RwqhpMAn=! zB48pb0lQ`k9nqMJno}m1(nL`edi#0)vP|E@efQ~Qk|ZysHWmnMxV3 z$uuC!)NTq*oIJ1VEFXgTf2pmGONr^qe$X}b4)aFWo4vp6eKSz(nlcpnVY{En)}_^@ z;7OU@-1|&8dtmIlvxC8jsj+jx*@-cz#bheLr&K!44nEMlP)Q6%OqXaZ1=k$|X9}%p zYLBzWUS8+V$pn+68W+SfFRzDRUhn6@T}gr`3_ruBu_LHynZQbGpcNccKUqPg_0z*L zHL~VNtI?#irnwYVUZUlq+ydKrEv2z5QXC2{MUqv5W$G)9U6gP}bC6_I!bEe&$V)g5 z#gM8w5(KDYz5de6F^!ESgs5guk~Pg?0U6bmUb6)_nWlc3W&q7iIV-A=NNG(`At@!} zaLXd*mDM;!*Q~nsri6?r2{;lHlvpi-Wj?ncE`z3OETJ8MI?}XLM2Si%qBZX^FyRe4 z99STpT!u0;LiuTST8O&oR5zj4Kp#NWehPgp{15n=re7w_WxbW!BGB5SNXl7oJ-n3L zKL6&-^_h~dr|b(AeW615iIQ(L@2>O>-DKiH2YW&ML!CP(w@+3Y zny+2jYRbR3HMjG^_6s+9-svoOM*-Fk0=3?Apzgjx->GunXt8hfy_QnnWU1@va@Sn3 zYp&EaUvPC++B$aHw%dTrmb>uivBL2S1@AL}-tNhBcRZ-+;I+BU$n{9U*HhpQm$_h( z3zoQW-hP{V=xS^uc1_uud_%awY)zN_14Td8$v^z=QzhC2q17@~K||k;lv2(IR)W#0}OS&AdGiJ7sR9$c>b^ zGjQZ<-JG~S0p<#oyN8P1L${oz?$JLVF8Lvzy zh~|kz5)w{}bncBrE~N$0IFV^>E7PF*7Sf3r0g!$L$h339PY*X&(5{WG>)7@7)}1l{ z>G9`cG=-%hWcM<3U-eOf8EnIL__(b5g$+C2cHX4X1RCT&Bsb;|WI=Ps*f)CYqN2hX z<@G?bG9>+wnMDD&@CSHS6GTiAnO{mLqcq6zs>G*ck`iRX3p~VBe(c#v-hB1+P)RQ; zGz%tGF~ifuCqqsL&~6G#2P!J}M=b;>&4Jnra6abd#!1LtT~IB47hvKZqf%#&vvw7v$x1Lgyv{Rvh@HOs#aA z5Ea~z0OlaQsXPuDHlyM_U^0lj#uno8lRB?Egij}-?%{>1I=x?N?p_O#J{CR&$q(`#H8z-}SK*a-A|(=7gEe>s zd=!roehsn=FBrG2dz`4}!0|+$)KiX{={D7(IuBbHPYFGsoDQV1&(6%wW!qz_no@?t zVMzQTAt7YprmQKUsFVn2j|i!h2$_)@I{Z>_ZEY<`6KXImi$+4mBRu?>AuB{Zqn97q zrY}$l*s@;w#|OABI0sT`?1ZGK*~iCp70!G?gTv&eoLy*j9us1~Gr0c1Q0KjqudT}JnsQDaM)>nw7emBxb=Z{H{W>58xSZk@f!bH|0a zk$a7i540WI_Hf^!#2e?q$22*gMQ0QM!=!-)rHHRMp?MvUBNNGc!Iu=*3DTTuzm;Y;cNidpo8^tHUw;wgY|K?8Q8Fc^>elb*ocD-aCQ%{Q3o63 zY%8#B4mQNuc3}59*e1@#fZgX{n>pJ7?0yFu=4>ahT@JQot~=2qSM!N|C2yp776u;Zi({o{fr^asLvT6~+U@B;m6{H>7;V zyv&%+WPil~JB)(A;xfQz!YV1aSX2?FVIN;@1=mJ}y)P781tQjL3T_y=s`dpBjH~)f-O)EYGyAYL<`U{0+;OrRJ2b zSnfQ_SRRwknqXk)n&ma}Im)bnD5{!jiXwh#(9DG8&r-vXCMko;B@7e50ti6_tZOSM zigHFW3{f;t6EC-gmzm_0o~216lTTi!Io(iAovG9~KB$_>i@IhqJtN9fk~T>Vaag)N zCr;=rE1Ai@8LG`BGwSVRZVo1^z0-H%?Ie6nkLM)$4ot;JPR&SilFrIBXR5kp^yTIl zCS<|0Kkg{^3+F~TeoAKtLlon?t2_NvNZT4*1hEUuxY!}wZ&i**lzED zE?DXQ3WOi{9|bzr_Wd3>SOiZ*u5BO;a8r08jDY}UK&GL8wJE}WpuQjqZ2xp^!)+_j zKq*Yuw%e)s$_s_)N&Su7ytg;5Yw?#tJmI!H5}P#aJxK^G3?>FnF3$D;E#tIW#a501IThHMW{qNvxe;>0LgsmR}$F?$+10)~{|xH&6cD|6~8=v8~9Nt-u); zMW0QEDVcdgly!y5&ZS^AMBrEa9AK50faPY^tjyX1O{^#0Ostx+gdWOLt-j5c8iy0+ zO%c8f-iJG_;F)f#a&})3%=YSNqY}B`Qc1!6jqtGmsdS|hL3J6jq^=-*g77KA4+tfM z=Lr8G{0oq1vRa0;87ZSG*Xi9nHB75{RFm>holKpliWMBt*=ZAddI)1=HWWiyoVd&Mf(ZAv$X;P9ys2c3p4NXj65e@~jTf_(cf z>Gw3tJxNU~GOE$p9F;QjQ=Uu3Shm&1B#v z6BrgHKNaWrY8jqZ4zRbx=mU7MNS>rep1Yg9hn{r{-m|+t;*0LO!rn1qU4BNeFS>y$ zaf;8HJCNbqT0?Kxidek%t1~AgTntZt>YCd1c3{7G#oY>jlq8cuSp(ixcW2-wtM6oc7Nct?oq=K&Y@ttN2+1>Z-8Z-Q}s_o!hAS5UCsBPGMH)`W^w?+S^7 zuD*NJFoZM;wtJ)+b#Jw&B_?HW;3LP61bPqM z7r%A*-M~*UKUTcjc}?=l;rq*Xf#-^^h=+OQ7JC^uU49zQvJ2oDb7pJ;?79U(D7oUo zn6SLRM6fRn02N#wFA?ZU0hCWUeOtmfm~V7lPm_uA-i(1%kxIT5QR*tZD65w@9faO5N7j4TE@(6etjY-vdRH z0v*}$#N>=>#9kcBy^J-ft|__XB%Z1H;Y?;S?XFa%t5T@~LMOz)N|jUTRAv68C{Yu) zUHv29x%X`VA=y*yAM+b2?=1H`{pV09AmBLjSATZ-Z%zop|Dqe?aOxLp zAL8O|K^86vvM4)J;w6#&Ixacbuk(_V{kkr>@as&ur#zQDA}{N`4sbAx{T_#^JDjo|dQki(fD zlMds``ki!J*Tz-ek$2`@c_A<6-FeUZ;$5Bk>tfUq-|rHH=af`dQKcy*cR3?Vxs0U7 zlbRw~{gKAvnj%Y?w3NH7NEkwHTEk#uMaqmzaYP^ZAx=6DLDVozwq$#fz$4UQU(fNjb2gf$5RoRZEAolw;f6jjZrnvFhx@Q)>L zkVz#m8F|ci1+*ebZcJa8&~6-~(JxMW~p)deo3f$MvIBrcys(=+ke8VxcM$1*dI8`g!i@=6w*S7g>9 z&giJS?BSwP_HgVdJF&3JE}HVPi)JS3RDmx-IlvlWb<06oI5ECXqF$B2NcB;npl$7x zz53EnJ@lS1P$lJ|QE_5CjxQz#FK4EdK`k{scuvV?v}6u*r)d2rlexj8nRHIgq+*H7 z@$`hE#m>jaW@FLi+91vAAc43x zkew}unMhIf7#pzKfL?^DJNt3EEdA=tMj_=28Q!RPj@p{g(%b(DRq>k#>JBX1{@j!n_>&!&`wNTqO)1|V#w@vrsb z^rrBp_@?7c=bNs#g$37wu;5s5E{Nl9S$xAc@6Nl=3qbeh!M($htRymO9Lxbk#&c34 zo|eWGX__D%z#}W;$uy9h{-6Xhsv=>T0Pr;l0|w$T)K(yseN600k!5rMOU+7hQp=_w zSaA@_0xILA!K9hEnkM*~xs2svkc)#fwaVe)6z@qqrDg2&xb8t0&6O)9Ny%XCP6Hh^ zNt@1QQ%M4fWLz@%B&FjJ7*6=~so_(jheuDH896`1dVGrO28=tCP9^}m=7OoYg%Hn^^#H z^nF$$K9Sl_D7?p`8AibzjKQ#(Bw$2Nj*lxUYy{2%J}ac_j7hMDqxBJgnIg32+@zXI zf<+Re$<#Q;$=Ig%;WBuun*cM(R0;xtp3Y>{E9hj;@UJT3Tcg}AzQjUCa~P4 z_&7vSdSNH%Y9z5^Bvvo%ly*$T)hi@(dI$R108nar3d|#YkjrJYp~1ndlBHEmD}NxP zPSAb--rY~^8H{pH08VLy5KFdPjK<}Rl+NU&%kiriL`K3)Dsh!Yz~(|tP9%Zarok5h zEA*x%(xa6o5V2-R8U-gUp`>SqA~gk+_h^V|eO{?blj^;LGOb>}d`Yl1Og*eg(yU!Y zRaK@ku;XIMbWB&rytjsK#;9j5Cli-#!oXw(OF^$XfYH%niBt^yr+|p@YPWSZ@G~BKPqXM=f9~Mu1&*M%C&)1_<3pC7GbFEoA_bWrNItJ7cdlRQ%BMY$+WExCZYBb7*vKJUlk_g zIt4K#eTNq1s0wi00VpSPJKCpP@V^U+a+#~q-dHA+Vmvf;6SNW2OUW=Q%sUp{$AlN32MH&fAMvW7i8p+Uf!B8COb2N(kasS6-*?`1av++=DyNn+4a8Ls3!_}hZb7&vR3?XvYgZl>dis?rdt;MYEv#mwdjyN zi{76IvN!L<+4nQI!GzZ_)V%Xq;l}T~1c$Kb$qPx)___GUV89le)3;SnH;Tfd@3nS} z7{Att(_xe|T|$&|io)|k+BGA*;(T715uX=s{E=}T^^cqwjXKNixlC+KiLGBS<)%zZ zj+vMdBkU z80Y|964Q;xvQM`|w6cq?%1y^C8|6FPL?PQ0mIb354VGP`R?40$D30II<+v6zmw(yK z`c`hP)s$DqQfAPWUBoc830zTWRg|07vseq_1%aP*ogFF}lx6RXN}5HTdy><$O~Syz zR0bfb9U3r|yY)z~b`~_W-{SO}>%ynqn-_*x9l_AHQp1L&+z;wjTZGNqmO`sOp>y*C zp)It1$z5u0zjfjVzxQcdw9xkCy@AovlP61q`$~g*A9`JborU&Y4+BES=66Hygi2fY z-`lpo6xs0)UROuw{W@Xe&O4(YTzv0)rAYrBB4>~s8ntms=I*4A}-y^hi-r84a-g*0}V)M>I z-Ok@U92SL^?gxT5)L&}uDl|t{9q!itQhWEU@BX+RwWIy-gnskTD|ByvAc(CS|E|4z z)rsHVuKH2q3++iT;1Aq~_Xr>D2_9*8essuv#N+s-(~0X}di+P4+`kMv=(n8TR zO~eye<9=qG0OPc>o0zH@KFR=ys=MgaM<;V`)qdPEzvLx8lYAom<|NH+{VG#=hNuwv z&#w#j{7pAEEpEECVc9Qz=Gf`qwJPAW<`e>(SJ~}%MWLZ>puw@TKGaKeNW5>2>pG{rb zS!fK?0^u^W0q&{_oVdiJN887oFmk*S@v&4zKWa5n+uA}{K#j*>$tm_2)wrsVXD}tP zND`Z4bO=7j)g;1Uaal%WBSWS&qNh}(4;ljePs7o?s=(uc3&2R)c~j9+b!Sv1H?1Q4 zbYdD_jv+91r`3=;a(_v-l4+SKDMO~vy55*dhWU^gA)AXbU1GVYM8RmGVlpFh0}5w!~{VI7tXcj9(9{56()IF#db*pXo zQQPT67DG8`;}BEc8m(ofjTl6zo2e+BUdNv{j?;Bvb%)S6R2Vv4czU=nd~KENvkMOV zUJY;%>%}h@V?_NStB?Y@U#PFHUMUvHOnI= z{=Um7Z-XHB*9k$~o&K5;$nK*96m`SmcYz;Hk=b|^*rT^p3wSE3nDSo{;MeI%!+cxe zE1-?up1Iug1;QW0p_VfVtYru|`PSTzBZ<``=Pc4sYeHANSa0iV+ChT9)w@}RoKp<^ z^>-scUc(pUFBlfZlPttVO#%ar*a@%;i?gB~J1w)F-vNbq#~%SfiKB2m3DRx2W5!z| z*GOyF20m|~5P$Yq2)d?w|ML-;N#QC&Wv~8r?)*B8x>nJk!6-mV3NX0b- zqAGz54F+vQaAWcGJ#31OB44ud~se-ri7Sn;y$r{|Uc@OF#RD72z z!;d8R>lMN|aixB)SU*>4kCYmAth$BpHE~UFhCSC$!YuVQ1J`apQ`j;@$k%*%r8!e< z&Xn4>;D3~D$x_*tzjQ)I3&v+5Eqz9Qlw;`>OXgTV!?BZ@c} z*75kTJN_46qq)U`ggM0Dzh;Ar(?#%+f|6ek;1Qx#ARUizV!yT)*74Hj!e#oJR(uU~ zARMTmMGLVC4y>9rNXByjxUuP+9vvil<|8tF^#E!`JMd45FXNf%v>sa5`4dDzPJ_6$|)xbETiWIp<6J`RN`Fy?nSk{#t+PE+EG%c0!^-yNa9+1kU zTocI#u2E5w|0r)>uR}Ly*=NvYkW~&<)Kw{v1SgMdxU!Fcmqw_51Gnm7I$1DB(7~)Y z-P7A<;+)ajSS_SGifVt2KkeH%0qM31;VVG8my7i;mqM*N(y2D2bJrEZGb`a&i{V#G zjUAGQgKr6hgZ1XPDyY}2h#_(o zL^4!mcBc3Ie$q~bDB*y^DH@iXQBGz-IG~>HuFgBHz~3Y>sp`l(b7sg-cE9g2&{7m~ z6sBPZGAN8*G3rK}2pn2v;Oc(0o*K2!3%1~(canlYRYzW!Y^ZvK+er#QR2_NoeV;+s z3M@wb@eZ(UU6u#=5c>ATgo1nrM96h3fMsKFMa;LL^r#uRFpq$F?7$BpjE}e73Eg*n6N(lvigct%xdOpPp}*5s(oJsnhnEGP;XB zsOm}K(Hz5k9@VXHvm2)OpsUOH)p#;xi&^L{yG^DzuGZPdUk+C>I_lyc^bxE$8}N40 zZ5K{+J0jQEf??1Mut(q+VF?@NN3N0dG21y{l`OmHX*8f71(C87>rm|_np^0!m7aO^ zwOOt|Y}f`YR;@luZ~d_tCl)LFVyx|040#z&3{QQI3bfYbq`H&npTMcwFz(fxi;-lS zx}stl)U!mG>XvYVw&)RjPzPI!-mUj~j+V9!eYmf|Yu43ntg{MvyJD+0R@axz_yI8v?xSM=@&@65Eq1TBqk!|!jX5dl#4Wqv8_)?H5R#< zdcpTgbz6e05EwH;~X8@&LDpT`!gwSBtiT@-4SCp!*NI=!7gbmu6qiye~zE|@5pa3 ziJkU+;;3^(H8m1a?|MPs(j@5Fc6tz@(@r|kcDF{fC2U;rogwCjki^eDWnq!NNUhCA z6V$;Yk!;8bE_FeZnc9pui0py|j`+@4+K8Cb&&XK{xb3Z1_ z!hRrh#8O@7nWWp_95aG}d|v=dMqfw3Jq{{}7}{4Iu1&Ivc z?CkpXq7J^vU0+!+>Q{#`+Ojv9rX-MD*$)NEqf;z?qz>Y(`UEQyi=l2T#x%D|vl#X9 z-Quu?H%y0@`2)*CS1%Bii*zF1mIGD=W|wH>yu3u?`G!7|DsBADZT%{f*ho|MUr_vu z>q05mS_p0~_3T*b*RAU&$gAG!D7$g2Z80DXI6TS6?={?p80g}nPOev!kJsK zU-uj?ZF{!V-TUsDcg|2$tUdD3@8+7kUI;Xs`qOOG?(-ZsSH2YYG}!X4zWIbE1?(Zgo+2 ztUOd5i}Y^uAe+4@j0!ns)5tN!Hv|l@j5IUKfQcEb;C(XgC_-rT!EQxy!bYhfmPE*C zj(j2Z5v$FE^a*X>uThxjTY^XuD7@H0O8M~;_%Fq`MNzo1!6nQJ|Jpetz9)_#&>l!? zz%u5?mz@|A9ytb{D2rK*L|)>7r7!#kDYEoRRy{Pg+vt9brZ<)uM{+ltUY?v|=?JsR zX{qCKY)YG8NCed8%D3n7j8s*0>Gz0r3%G#a)g<^f6ucWt9bF6c_q>fu13%yLv3Gl^ zBeK%bU+n0=lUVN9gEzs}rS#9`kAu7Za_@b{>aBYo5{DlOj(r}uXRTMn1^>PJ_Lchn zVts$9u63oZy9gBBAeCBr?{#dvm0s@XM{qB+5wX2c{hHGghEwJ72Uh(c!2Kk1Vv_1;#&~_wAv?KJbdBwXl(S%w~mj%J0E8$$w>T1J_@|> zsVw^f0LEWc{XXecd~iZ(x&4f&@sX0AghKHv_Ev8aDvi-pQV5k<>B?53i9L(C9JKXm zuD-INk*Kfi$RL*yeZm;Zt}H%EqOT0Ia6=J*Q1SK7D-d?%Mk2jGU3RHTTn6F+yR!t2 zthePb`-zPwQ=cUw5I+6W^J4Vc@7u&LZ(g#g>Rl(Jhe2n zT(|Z5@xKc;-0SRqH}XzorL(Wt*;nX)cDeHqf;qv^&Han}Zys7abZhYA;LdxEtxK8Z z#_g+u80x#T6&Zl<`rq;YB)HNZEw)FO+jlLwKXc;MeUDJrSPD0P8f>_J`m+$8uo_=z zmV`AU{K#g!C4X&%0Gmt5auoI{Hgr0 zcS|YUQSfz;Zrl0O#K+!V+^>W;6~miuJD0;-3%;$Nh8q|B90~0PIhjOkVt<8;H=VSH z{)X^}PTSu-InzqePp1Dgl@!m^Vx^+JZ2QFX;qwtg%Ib_iV$WLh@^W z{6M0{f^H=EWbxEWIkQv~-cyaL!&1ob428#ghNQ}7T~YVQTvtCGM~G(XjM}n0)d74#+%8-lD zbR?WfA>nv2CjY96xm22)Tp=fO#I@)g)j7^6MGc>~sJ39Q*1`<6mrn zFZjm@xCv-(k{WoSK`%?TFJsweE09?2K$@GV^G|mzN<;&fd^hG3*mI z%HK&+T65(#s8OA&>Nup^jfc(h@QAXr#*Vv5)z(_2r(%+Vm*S?)M-9fFhc{GqVn@5| z=0hilGF{U;o@R>V?X;q)KfqzCC}06p(K-r-Hn&(`v8 ze3#|r-(@lRam?cjD_xRY^Bzc&BmNWc<|xc*B)UUN=%1&UMoeXbsT}K5LB7oO?^zWs z5ziWB%#emDZFR*YNZ#|bb!q`FZlx_bMEQfc>e+9uqHqT zzFC^0h-DA{MFspz1uRyjDP{M|)A)P>E7m_1pT(DZn80#Sk2ta$AE+Flt4bHm4>B=U zcW$FD0C-~QZ1eR;w5;iy0T|*wp{?^)^oQw%V5zxhrFmPidE4!Y<>r9}-@S0_&HQ41 zCA_&9-h6wCPXFzfWWqu{8f{(v6U8;`j7 zFw6iBv4iU@gD5(!{wq}ZOX@S(E6`M(9(Nz2CVTh)_vZa~TEBnlmh#_PwicTAUq6jg z>CmyiP5rynzfZ5U4*z-J1Lp@9mJ;tgefz?4*RJA*U4_=+>m$Y1;ZK9z3qvcx?qaa} zR;mzu_D;GOe74|v_VWi`q2<8mpR^8Z03%@`e7ME+e)HiDPt-MnLp_g&09DUXmZQUr zj%d3|xx;)D=sR>p?l9Y!EBokU7W%@BZ3U^f@S^OZe|Lhb@dheL1`qoRgYP9BrQ5S~ zq8$nr4`dM|=4~@Sim7gf&x|w7=wb81IQNC`Am5rgr2ZKQfNg?CJjcg#qIloo5M66N zL2Ud)sQ*OpeS(~u|EHQ>EQ-O diff --git a/.venv/lib/python3.12/site-packages/hvac/adapters.py b/.venv/lib/python3.12/site-packages/hvac/adapters.py deleted file mode 100644 index 1ea601d..0000000 --- a/.venv/lib/python3.12/site-packages/hvac/adapters.py +++ /dev/null @@ -1,419 +0,0 @@ -""" -HTTP Client Library Adapters - -""" -from abc import ABCMeta, abstractmethod - -import requests -import requests.exceptions - -from hvac import utils -from hvac.constants.client import DEFAULT_URL - - -class Adapter(metaclass=ABCMeta): - """Abstract base class used when constructing adapters for use with the Client class.""" - - @classmethod - def from_adapter( - cls, - adapter, - ): - """Create a new adapter based on an existing Adapter instance. - This can be used to create a new type of adapter that inherits the properties of an existing one. - - :param adapter: The existing Adapter instance. - :type adapter: hvac.Adapters.Adapter - """ - - return cls( - base_uri=adapter.base_uri, - token=adapter.token, - cert=adapter._kwargs.get("cert"), - verify=adapter._kwargs.get("verify"), - timeout=adapter._kwargs.get("timeout"), - proxies=adapter._kwargs.get("proxies"), - allow_redirects=adapter.allow_redirects, - session=adapter.session, - namespace=adapter.namespace, - ignore_exceptions=adapter.ignore_exceptions, - strict_http=adapter.strict_http, - request_header=adapter.request_header, - ) - - def __init__( - self, - base_uri=DEFAULT_URL, - token=None, - cert=None, - verify=True, - timeout=30, - proxies=None, - allow_redirects=True, - session=None, - namespace=None, - ignore_exceptions=False, - strict_http=False, - request_header=True, - ): - """Create a new request adapter instance. - - :param base_uri: Base URL for the Vault instance being addressed. - :type base_uri: str - :param token: Authentication token to include in requests sent to Vault. - :type token: str - :param cert: Certificates for use in requests sent to the Vault instance. This should be a tuple with the - certificate and then key. - :type cert: tuple - :param verify: Either a boolean to indicate whether TLS verification should be performed when sending requests to Vault, - or a string pointing at the CA bundle to use for verification. See http://docs.python-requests.org/en/master/user/advanced/#ssl-cert-verification. - :type verify: Union[bool,str] - :param timeout: The timeout value for requests sent to Vault. - :type timeout: int - :param proxies: Proxies to use when preforming requests. - See: http://docs.python-requests.org/en/master/user/advanced/#proxies - :type proxies: dict - :param allow_redirects: Whether to follow redirects when sending requests to Vault. - :type allow_redirects: bool - :param session: Optional session object to use when performing request. - :type session: request.Session - :param namespace: Optional Vault Namespace. - :type namespace: str - :param ignore_exceptions: If True, _always_ return the response object for a given request. I.e., don't raise an exception - based on response status code, etc. - :type ignore_exceptions: bool - :param strict_http: If True, use only standard HTTP verbs in request with additional params, otherwise process as is - :type strict_http: bool - :param request_header: If true, add the X-Vault-Request header to all requests to protect against SSRF vulnerabilities. - :type request_header: bool - """ - if not session: - session = requests.Session() - session.cert, session.verify, session.proxies = cert, verify, proxies - # fix for issue 991 using session verify if set - else: - if session.verify: - # need to set the variable and not assign it to self so it is properly passed in kwargs - verify = session.verify - if session.cert: - cert = session.cert - if session.proxies: - proxies = session.proxies - - self.base_uri = base_uri - self.token = token - self.namespace = namespace - self.session = session - self.allow_redirects = allow_redirects - self.ignore_exceptions = ignore_exceptions - self.strict_http = strict_http - self.request_header = request_header - - self._kwargs = { - "cert": cert, - "verify": verify, - "timeout": timeout, - "proxies": proxies, - } - - @staticmethod - def urljoin(*args): - """Joins given arguments into a url. Trailing and leading slashes are stripped for each argument. - - :param args: Multiple parts of a URL to be combined into one string. - :type args: str | unicode - :return: Full URL combining all provided arguments - :rtype: str | unicode - """ - - return "/".join(map(lambda x: str(x).strip("/"), args)) - - def close(self): - """Close the underlying Requests session.""" - self.session.close() - - def get(self, url, **kwargs): - """Performs a GET request. - - :param url: Partial URL path to send the request to. This will be joined to the end of the instance's base_uri - attribute. - :type url: str | unicode - :param kwargs: Additional keyword arguments to include in the requests call. - :type kwargs: dict - :return: The response of the request. - :rtype: requests.Response - """ - return self.request("get", url, **kwargs) - - def post(self, url, **kwargs): - """Performs a POST request. - - :param url: Partial URL path to send the request to. This will be joined to the end of the instance's base_uri - attribute. - :type url: str | unicode - :param kwargs: Additional keyword arguments to include in the requests call. - :type kwargs: dict - :return: The response of the request. - :rtype: requests.Response - """ - return self.request("post", url, **kwargs) - - def put(self, url, **kwargs): - """Performs a PUT request. - - :param url: Partial URL path to send the request to. This will be joined to the end of the instance's base_uri - attribute. - :type url: str | unicode - :param kwargs: Additional keyword arguments to include in the requests call. - :type kwargs: dict - :return: The response of the request. - :rtype: requests.Response - """ - return self.request("put", url, **kwargs) - - def delete(self, url, **kwargs): - """Performs a DELETE request. - - :param url: Partial URL path to send the request to. This will be joined to the end of the instance's base_uri - attribute. - :type url: str | unicode - :param kwargs: Additional keyword arguments to include in the requests call. - :type kwargs: dict - :return: The response of the request. - :rtype: requests.Response - """ - return self.request("delete", url, **kwargs) - - def list(self, url, **kwargs): - """Performs a LIST request. - - :param url: Partial URL path to send the request to. This will be joined to the end of the instance's base_uri - attribute. - :type url: str | unicode - :param kwargs: Additional keyword arguments to include in the requests call. - :type kwargs: dict - :return: The response of the request. - :rtype: requests.Response - """ - return self.request("list", url, **kwargs) - - def head(self, url, **kwargs): - """Performs a HEAD request. - - :param url: Partial URL path to send the request to. This will be joined to the end of the instance's base_uri - attribute. - :type url: str | unicode - :param kwargs: Additional keyword arguments to include in the requests call. - :type kwargs: dict - :return: The response of the request. - :rtype: requests.Response - """ - return self.request("head", url, **kwargs) - - def login(self, url, use_token=True, **kwargs): - """Perform a login request. - - Associated request is typically to a path prefixed with "/v1/auth") and optionally stores the client token sent - in the resulting Vault response for use by the :py:meth:`hvac.adapters.Adapter` instance under the _adapter - Client attribute. - - :param url: Path to send the authentication request to. - :type url: str | unicode - :param use_token: if True, uses the token in the response received from the auth request to set the "token" - attribute on the the :py:meth:`hvac.adapters.Adapter` instance under the _adapter Client attribute. - :type use_token: bool - :param kwargs: Additional keyword arguments to include in the params sent with the request. - :type kwargs: dict - :return: The response of the auth request. - :rtype: requests.Response - """ - response = self.post(url, **kwargs) - - if use_token: - self.token = self.get_login_token(response) - - return response - - @abstractmethod - def get_login_token(self, response): - """Extracts the client token from a login response. - - :param response: The response object returned by the login method. - :return: A client token. - :rtype: str - """ - return NotImplementedError - - @abstractmethod - def request(self, method, url, headers=None, raise_exception=True, **kwargs): - """Main method for routing HTTP requests to the configured Vault base_uri. Intended to be implement by subclasses. - - :param method: HTTP method to use with the request. E.g., GET, POST, etc. - :type method: str - :param url: Partial URL path to send the request to. This will be joined to the end of the instance's base_uri - attribute. - :type url: str | unicode - :param headers: Additional headers to include with the request. - :type headers: dict - :param kwargs: Additional keyword arguments to include in the requests call. - :type kwargs: dict - :param raise_exception: If True, raise an exception via utils.raise_for_error(). Set this parameter to False to - bypass this functionality. - :type raise_exception: bool - :return: The response of the request. - :rtype: requests.Response - """ - raise NotImplementedError - - -class RawAdapter(Adapter): - """ - The RawAdapter adapter class. - This adapter adds Vault-specific headers as required and optionally raises exceptions on errors, - but always returns Response objects for requests. - """ - - def _raise_for_error(self, method: str, url: str, response: requests.Response): - msg = json = text = errors = None - try: - text = response.text - except Exception: - pass - - if response.headers.get("Content-Type") == "application/json": - try: - json = response.json() - except Exception: - pass - else: - errors = json.get("errors") - - if errors is None: - msg = text - - utils.raise_for_error( - method, - url, - response.status_code, - msg, - errors=errors, - text=text, - json=json, - ) - - def get_login_token(self, response): - """Extracts the client token from a login response. - - :param response: The response object returned by the login method. - :type response: requests.Response - :return: A client token. - :rtype: str - """ - response_json = response.json() - return response_json["auth"]["client_token"] - - def request(self, method, url, headers=None, raise_exception=True, **kwargs): - """Main method for routing HTTP requests to the configured Vault base_uri. - - :param method: HTTP method to use with the request. E.g., GET, POST, etc. - :type method: str - :param url: Partial URL path to send the request to. This will be joined to the end of the instance's base_uri - attribute. - :type url: str | unicode - :param headers: Additional headers to include with the request. - :type headers: dict - :param raise_exception: If True, raise an exception via utils.raise_for_error(). Set this parameter to False to - bypass this functionality. - :type raise_exception: bool - :param kwargs: Additional keyword arguments to include in the requests call. - :type kwargs: dict - :return: The response of the request. - :rtype: requests.Response - """ - while "//" in url: - # Vault CLI treats a double forward slash ('//') as a single forward slash for a given path. - # To avoid issues with the requests module's redirection logic, we perform the same translation here. - url = url.replace("//", "/") - - url = self.urljoin(self.base_uri, url) - - if not headers: - headers = {} - - if self.request_header: - headers["X-Vault-Request"] = "true" - - if self.token: - headers["X-Vault-Token"] = self.token - - if self.namespace: - headers["X-Vault-Namespace"] = self.namespace - - wrap_ttl = kwargs.pop("wrap_ttl", None) - if wrap_ttl: - headers["X-Vault-Wrap-TTL"] = str(wrap_ttl) - - _kwargs = self._kwargs.copy() - _kwargs.update(kwargs) - - if self.strict_http and method.lower() in ("list",): - # Entry point for standard HTTP substitution - params = _kwargs.get("params", {}) - if method.lower() == "list": - method = "get" - params.update({"list": "true"}) - _kwargs["params"] = params - - response = self.session.request( - method=method, - url=url, - headers=headers, - allow_redirects=self.allow_redirects, - **_kwargs - ) - - if not response.ok and (raise_exception and not self.ignore_exceptions): - self._raise_for_error(method, url, response) - - return response - - -class JSONAdapter(RawAdapter): - """ - The JSONAdapter adapter class. - This adapter works just like the RawAdapter adapter except that HTTP 200 responses are returned as JSON dicts. - All non-200 responses are returned as Response objects. - """ - - def get_login_token(self, response): - """Extracts the client token from a login response. - - :param response: The response object returned by the login method. - :type response: dict | requests.Response - :return: A client token. - :rtype: str - """ - return response["auth"]["client_token"] - - def request(self, *args, **kwargs): - """Main method for routing HTTP requests to the configured Vault base_uri. - - :param args: Positional arguments to pass to RawAdapter.request. - :type args: list - :param kwargs: Keyword arguments to pass to RawAdapter.request. - :type kwargs: dict - :return: Dict on HTTP 200 with JSON body, otherwise the response object. - :rtype: dict | requests.Response - """ - response = super().request(*args, **kwargs) - if response.status_code == 200: - try: - return response.json() - except ValueError: - pass - - return response - - -# Retaining the legacy name -Request = RawAdapter diff --git a/.venv/lib/python3.12/site-packages/hvac/api/__init__.py b/.venv/lib/python3.12/site-packages/hvac/api/__init__.py deleted file mode 100644 index d8d3d93..0000000 --- a/.venv/lib/python3.12/site-packages/hvac/api/__init__.py +++ /dev/null @@ -1,14 +0,0 @@ -"""Collection of Vault API endpoint classes.""" -from hvac.api.auth_methods import AuthMethods -from hvac.api.secrets_engines import SecretsEngines -from hvac.api.system_backend import SystemBackend -from hvac.api.vault_api_base import VaultApiBase -from hvac.api.vault_api_category import VaultApiCategory - -__all__ = ( - "AuthMethods", - "SecretsEngines", - "SystemBackend", - "VaultApiBase", - "VaultApiCategory", -) diff --git a/.venv/lib/python3.12/site-packages/hvac/api/__pycache__/__init__.cpython-312.pyc b/.venv/lib/python3.12/site-packages/hvac/api/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index f5fe169e96539051f2b0626395468f6026276539..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 629 zcmYk4O^ee&7{@1VnsnQ(EP^Nql4}mlxbDS+2;Cy;!51ue$Yq!&v(4bVgv_)MZ+;5D zf#O&2EBFZv4uAg7Ja0dS`8AtO5S({Ezg6D@g#NhT`V6kj#Vash zQHgR?2IW8ma*z)K=Z9h_!#wmp6eAhsk@q7J%W*#TJ`x9Vl25?L`LrFU2cOfW7J?O) zYnAA;$#%0}xmN1%`Q!?%_@E zZML{V_mGZ|3PH#ZbOFrhQsGKVhK<+ zHqO!PmHM;epjjcKifGH=EahOQ9S)77Tot5U#i-B&*xY@iVE*tzgfayRaVq l4l<8G&WAw|{6@G(^B$e_=(tCZd-U`?jHZJxadQME{{UV=y)gg) diff --git a/.venv/lib/python3.12/site-packages/hvac/api/__pycache__/vault_api_base.cpython-312.pyc b/.venv/lib/python3.12/site-packages/hvac/api/__pycache__/vault_api_base.cpython-312.pyc deleted file mode 100644 index 5393404ca78a19937d979f7afff6c09adeba515f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1000 zcmZuw&1(}u6rb76w~45r#ey&tK_Yh7kBdYR(h9YpwP;bvWjfiNB&++?nN46r4?XnI zi|6()5TyPEUiX*{H@|uFxmK$nwVr-_*ZYYP z`VE`O%4f#tl`?jbjataYw&vm%R$6y8PjBfMX^7+3rAg9M^ZdT52&+}l&=Rt9+sMvy z{X=12&-}$$s~3mY7ntP4a+#E*FS$+HF=4JtdIM&WITku|=^>ZKA4puO^5tYKYCa+159q&PtU1Q2o*nZ3Z{rgZz}Gad%gQFn8=oL_Px zb20EE5xCUqF~7?tea_l31&Ay%jRE%urt7rLFpheGf5*6W+f>IHV+1-nY=MxVLaNs&@JuqYK!6nAA0 zMiK_OUJ~b&FDbe~x2v8f(OKIPFg;1R%cIB2%Y~@Hz5pR=GwyO;d8VC@O7~N+55$Z* zfccg;lsMEe#s}!;cXaj#n)y|p-I@7Tp8Zmu-Mjm>e08hvw@}7p@8v(F)VSJzxUvlc diff --git a/.venv/lib/python3.12/site-packages/hvac/api/__pycache__/vault_api_category.cpython-312.pyc b/.venv/lib/python3.12/site-packages/hvac/api/__pycache__/vault_api_category.cpython-312.pyc deleted file mode 100644 index 8c5d853ec4e999b273e734c37c2507ed09df34d4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5051 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 diff --git a/.venv/lib/python3.12/site-packages/hvac/api/auth_methods/__pycache__/approle.cpython-312.pyc b/.venv/lib/python3.12/site-packages/hvac/api/auth_methods/__pycache__/approle.cpython-312.pyc deleted file mode 100644 index 18b3f88eafc0cb85258a2eff94227311cfe732ac..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19994 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 diff --git a/.venv/lib/python3.12/site-packages/hvac/api/auth_methods/__pycache__/aws.cpython-312.pyc b/.venv/lib/python3.12/site-packages/hvac/api/auth_methods/__pycache__/aws.cpython-312.pyc deleted file mode 100644 index adca4942f2c43f807b7725f6942e1ce88e3b8fb3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 42690 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 diff --git a/.venv/lib/python3.12/site-packages/hvac/api/auth_methods/__pycache__/azure.cpython-312.pyc b/.venv/lib/python3.12/site-packages/hvac/api/auth_methods/__pycache__/azure.cpython-312.pyc deleted file mode 100644 index 532e73dc859f5c4cded338380a5adaf78c2f3fb9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13413 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 Bprrr+ diff --git a/.venv/lib/python3.12/site-packages/hvac/api/auth_methods/__pycache__/gcp.cpython-312.pyc b/.venv/lib/python3.12/site-packages/hvac/api/auth_methods/__pycache__/gcp.cpython-312.pyc deleted file mode 100644 index 1ae142675780dbcde37765fb04a0383d3a30ba5c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18452 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 XI`YHlqv)$0f!OsE|0U5c@BV)QT|`R7 diff --git a/.venv/lib/python3.12/site-packages/hvac/api/auth_methods/__pycache__/github.cpython-312.pyc b/.venv/lib/python3.12/site-packages/hvac/api/auth_methods/__pycache__/github.cpython-312.pyc deleted file mode 100644 index a1656597fb0cb60f7614d94781c66cb1eb32c94a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9044 zcmeHNO>7&-72Y3`qG-vIB~`X!#~D*WBDyvyJ4urgt`Ws{6Fau7+Olh?O*c#KNL-cN zUC%BhOC|v$@WBNFBt5ha&>V6oimG;RJrwP!1$yemLW){gxM+%A+M8UeK&n&UoBiR6 z7Hv6bet>2KzMY+&-#72)n|bgQ>qq7g*qiu zvq{C&s%4t}CsxWxZi-$hQp?dz!*=6UM=#qM(e1jZR?E(qrN5%u)J@Fr9*SPK9*y}g zjRItD3RIX9VV;sEPRW{te>657)8y;oR2*`m7K2=Zmr5{CajJutCLoveOFJOn$xD-v zOKF&wv=rpGEl8PdZo*r~B8BH`u%5B1QzB>hqR7bD#K}xHl_HSN(P_%4QKWfNavaOf z=W_G&^VvCEk;TkeT6D6ynNux2r$QGwZ*e)@(CC$H$*GiiFXP2TWVuPmBUc;0=d0Dk zny8EQL@hBZMr!$4$LGHw%m!SFRH{iexfau;_vKrD+u$h*k(SZX{nnaXi{FmjlDyY? zM@^W;d9|e3Z7l`xTI;AKZpVX`=Y>o{{TL>B%rvI;nJS~iDN#~14Fh-sf

lsUR+t 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 diff --git a/.venv/lib/python3.12/site-packages/hvac/api/auth_methods/__pycache__/jwt.cpython-312.pyc b/.venv/lib/python3.12/site-packages/hvac/api/auth_methods/__pycache__/jwt.cpython-312.pyc deleted file mode 100644 index e4d248f76d4cb2ab7cc25c753d083d290d9e405c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19517 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 diff --git a/.venv/lib/python3.12/site-packages/hvac/api/auth_methods/__pycache__/legacy_mfa.cpython-312.pyc b/.venv/lib/python3.12/site-packages/hvac/api/auth_methods/__pycache__/legacy_mfa.cpython-312.pyc deleted file mode 100644 index 2b027eba55314f1b769fc0b52cafa9eac7e0638d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6990 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 diff --git a/.venv/lib/python3.12/site-packages/hvac/api/auth_methods/__pycache__/oidc.cpython-312.pyc b/.venv/lib/python3.12/site-packages/hvac/api/auth_methods/__pycache__/oidc.cpython-312.pyc deleted file mode 100644 index 1abe3c85f4cc8df90bc5ecf524d99302439f7331..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8249 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 CrYsTw diff --git a/.venv/lib/python3.12/site-packages/hvac/api/auth_methods/__pycache__/radius.cpython-312.pyc b/.venv/lib/python3.12/site-packages/hvac/api/auth_methods/__pycache__/radius.cpython-312.pyc deleted file mode 100644 index 2c1fe4fb02e162c50bc4b04e53e64e2667d71084..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8884 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 LUH>=1e?G>y3Du3^ diff --git a/.venv/lib/python3.12/site-packages/hvac/api/auth_methods/approle.py b/.venv/lib/python3.12/site-packages/hvac/api/auth_methods/approle.py deleted file mode 100644 index 4f6f750..0000000 --- a/.venv/lib/python3.12/site-packages/hvac/api/auth_methods/approle.py +++ /dev/null @@ -1,510 +0,0 @@ -#!/usr/bin/env python -"""APPROLE methods module.""" -import json -from hvac import exceptions, utils -from hvac.api.vault_api_base import VaultApiBase -from hvac.constants.approle import DEFAULT_MOUNT_POINT, ALLOWED_TOKEN_TYPES -from hvac.utils import validate_list_of_strings_param, list_to_comma_delimited - - -class AppRole(VaultApiBase): - """USERPASS Auth Method (API). - Reference: https://www.vaultproject.io/api-docs/auth/approle/index.html - """ - - def create_or_update_approle( - self, - role_name, - bind_secret_id=None, - secret_id_bound_cidrs=None, - secret_id_num_uses=None, - secret_id_ttl=None, - enable_local_secret_ids=None, - token_ttl=None, - token_max_ttl=None, - token_policies=None, - token_bound_cidrs=None, - token_explicit_max_ttl=None, - token_no_default_policy=None, - token_num_uses=None, - token_period=None, - token_type=None, - mount_point=DEFAULT_MOUNT_POINT, - ): - """ - Create/update approle. - - Supported methods: - POST: /auth/{mount_point}/role/{role_name}. Produces: 204 (empty body) - - :param role_name: The name for the approle. - :type role_name: str | unicode - :param bind_secret_id: Require secret_id to be presented when logging in using this approle. - :type bind_secret_id: bool - :param secret_id_bound_cidrs: Blocks of IP addresses which can perform login operations. - :type secret_id_bound_cidrs: list - :param secret_id_num_uses: Number of times any secret_id can be used to fetch a token. - A value of zero allows unlimited uses. - :type secret_id_num_uses: int - :param secret_id_ttl: Duration after which a secret_id expires. This can be specified - as an integer number of seconds or as a duration value like "5m". - :type secret_id_ttl: str | unicode - :param enable_local_secret_ids: Secret IDs generated using role will be cluster local. - :type enable_local_secret_ids: bool - :param token_ttl: Incremental lifetime for generated tokens. This can be specified - as an integer number of seconds or as a duration value like "5m". - :type token_ttl: str | unicode - :param token_max_ttl: Maximum lifetime for generated tokens: This can be specified - as an integer number of seconds or as a duration value like "5m". - :type token_max_ttl: str | unicode - :param token_policies: List of policies to encode onto generated tokens. - :type token_policies: list - :param token_bound_cidrs: Blocks of IP addresses which can authenticate successfully. - :type token_bound_cidrs: list - :param token_explicit_max_ttl: If set, will encode an explicit max TTL onto the token. This can be specified - as an integer number of seconds or as a duration value like "5m". - :type token_explicit_max_ttl: str | unicode - :param token_no_default_policy: Do not add the default policy to generated tokens, use only tokens - specified in token_policies. - :type token_no_default_policy: bool - :param token_num_uses: Maximum number of times a generated token may be used. A value of zero - allows unlimited uses. - :type token_num_uses: int - :param token_period: The period, if any, to set on the token. This can be specified - as an integer number of seconds or as a duration value like "5m". - :type token_period: str | unicode - :param token_type: The type of token that should be generated, can be "service", "batch", or "default". - :type token_type: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - """ - list_of_strings_params = { - "secret_id_bound_cidrs": secret_id_bound_cidrs, - "token_policies": token_policies, - "token_bound_cidrs": token_bound_cidrs, - } - - if token_type is not None and token_type not in ALLOWED_TOKEN_TYPES: - error_msg = 'unsupported token_type argument provided "{arg}", supported types: "{token_types}"' - raise exceptions.ParamValidationError( - error_msg.format( - arg=token_type, - token_types=",".join(ALLOWED_TOKEN_TYPES), - ) - ) - - params = dict() - - for param_name, param_argument in list_of_strings_params.items(): - validate_list_of_strings_param( - param_name=param_name, - param_argument=param_argument, - ) - if param_argument is not None: - params[param_name] = list_to_comma_delimited(param_argument) - - params.update( - utils.remove_nones( - { - "bind_secret_id": bind_secret_id, - "secret_id_num_uses": secret_id_num_uses, - "secret_id_ttl": secret_id_ttl, - "enable_local_secret_ids": enable_local_secret_ids, - "token_ttl": token_ttl, - "token_max_ttl": token_max_ttl, - "token_explicit_max_ttl": token_explicit_max_ttl, - "token_no_default_policy": token_no_default_policy, - "token_num_uses": token_num_uses, - "token_period": token_period, - "token_type": token_type, - } - ) - ) - - api_path = utils.format_url( - "/v1/auth/{mount_point}/role/{name}", - mount_point=mount_point, - name=role_name, - ) - return self._adapter.post(url=api_path, json=params) - - def list_roles(self, mount_point=DEFAULT_MOUNT_POINT): - """ - List existing roles created in the auth method. - - Supported methods: - LIST: /auth/{mount_point}/role. Produces: 200 application/json - - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the list_roles request. - :rtype: dict - """ - api_path = utils.format_url( - "/v1/auth/{mount_point}/role", mount_point=mount_point - ) - return self._adapter.list(url=api_path) - - def read_role(self, role_name, mount_point=DEFAULT_MOUNT_POINT): - """ - Read role in the auth method. - - Supported methods: - GET: /auth/{mount_point}/role/{role_name}. Produces: 200 application/json - - :param role_name: The name for the role. - :type role_name: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the read_role request. - :rtype: dict - """ - api_path = utils.format_url( - "/v1/auth/{mount_point}/role/{role_name}", - mount_point=mount_point, - role_name=role_name, - ) - return self._adapter.get(url=api_path) - - def delete_role(self, role_name, mount_point=DEFAULT_MOUNT_POINT): - """ - Delete role in the auth method. - - Supported methods: - DELETE: /auth/{mount_point}/role/{role_name}. Produces: 204 (empty body) - - :param role_name: The name for the role. - :type role_name: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - """ - api_path = utils.format_url( - "/v1/auth/{mount_point}/role/{role_name}", - mount_point=mount_point, - role_name=role_name, - ) - return self._adapter.delete(url=api_path) - - def read_role_id(self, role_name, mount_point=DEFAULT_MOUNT_POINT): - """ - Reads the Role ID of a role in the auth method. - - Supported methods: - GET: /auth/{mount_point}/role/{role_name}/role-id. Produces: 200 application/json - - :param role_name: The name for the role. - :type role_name: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the read_role_id request. - :rtype: dict - """ - api_path = utils.format_url( - "/v1/auth/{mount_point}/role/{role_name}/role-id", - mount_point=mount_point, - role_name=role_name, - ) - return self._adapter.get(url=api_path) - - def update_role_id(self, role_name, role_id, mount_point=DEFAULT_MOUNT_POINT): - """ - Updates the Role ID of a role in the auth method. - - Supported methods: - POST: /auth/{mount_point}/role/{role_name}/role-id. Produces: 200 application/json - - :param role_name: The name for the role. - :type role_name: str | unicode - :param role_id: New value for the Role ID. - :type role_id: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the read_role_id request. - :rtype: dict - """ - params = {"role_id": role_id} - - api_path = utils.format_url( - "/v1/auth/{mount_point}/role/{role_name}/role-id", - mount_point=mount_point, - role_name=role_name, - ) - return self._adapter.post(url=api_path, json=params) - - def generate_secret_id( - self, - role_name, - metadata=None, - cidr_list=None, - token_bound_cidrs=None, - mount_point=DEFAULT_MOUNT_POINT, - wrap_ttl=None, - ): - """ - Generates and issues a new Secret ID on a role in the auth method. - - Supported methods: - POST: /auth/{mount_point}/role/{role_name}/secret-id. Produces: 200 application/json - - :param role_name: The name for the role. - :type role_name: str | unicode - :param metadata: Metadata to be tied to the Secret ID. - :type metadata: dict - :param cidr_list: Blocks of IP addresses which can perform login operations. - :type cidr_list: list - :param token_bound_cidrs: Blocks of IP addresses which can authenticate successfully. - :type token_bound_cidrs: list - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :param wrap_ttl: Returns the request as a response-wrapping token. - Can be either an integer number of seconds or a string duration of seconds (`15s`), minutes (`20m`), or hours (`25h`). - :type wrap_ttl: int | str - :return: The JSON response of the read_role_id request. - :rtype: dict - """ - if metadata is not None and not isinstance(metadata, dict): - error_msg = 'unsupported metadata argument provided "{arg}" ({arg_type}), required type: dict"' - raise exceptions.ParamValidationError( - error_msg.format( - arg=metadata, - arg_type=type(metadata), - ) - ) - - params = {} - if metadata: - params = {"metadata": json.dumps(metadata)} - - list_of_strings_params = { - "cidr_list": cidr_list, - "token_bound_cidrs": token_bound_cidrs, - } - for param_name, param_argument in list_of_strings_params.items(): - validate_list_of_strings_param( - param_name=param_name, - param_argument=param_argument, - ) - if param_argument is not None: - params[param_name] = list_to_comma_delimited(param_argument) - - api_path = utils.format_url( - "/v1/auth/{mount_point}/role/{role_name}/secret-id", - mount_point=mount_point, - role_name=role_name, - ) - return self._adapter.post(url=api_path, json=params, wrap_ttl=wrap_ttl) - - def create_custom_secret_id( - self, - role_name, - secret_id, - metadata=None, - cidr_list=None, - token_bound_cidrs=None, - mount_point=DEFAULT_MOUNT_POINT, - wrap_ttl=None, - ): - """ - Generates and issues a new Secret ID on a role in the auth method. - - Supported methods: - POST: /auth/{mount_point}/role/{role_name}/custom-secret-id. Produces: 200 application/json - - :param role_name: The name for the role. - :type role_name: str | unicode - :param secret_id: The Secret ID to read. - :type secret_id: str | unicode - :param metadata: Metadata to be tied to the Secret ID. - :type metadata: dict - :param cidr_list: Blocks of IP addresses which can perform login operations. - :type cidr_list: list - :param token_bound_cidrs: Blocks of IP addresses which can authenticate successfully. - :type token_bound_cidrs: list - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :param wrap_ttl: Returns the request as a response-wrapping token. - Can be either an integer number of seconds or a string duration of seconds (`15s`), minutes (`20m`), or hours (`25h`). - :type wrap_ttl: int | str - :return: The JSON response of the read_role_id request. - :rtype: dict - """ - if metadata is not None and not isinstance(metadata, dict): - error_msg = 'unsupported metadata argument provided "{arg}" ({arg_type}), required type: dict"' - raise exceptions.ParamValidationError( - error_msg.format( - arg=metadata, - arg_type=type(metadata), - ) - ) - - params = {"secret_id": secret_id} - - if metadata: - params["metadata"] = json.dumps(metadata) - - list_of_strings_params = { - "cidr_list": cidr_list, - "token_bound_cidrs": token_bound_cidrs, - } - for param_name, param_argument in list_of_strings_params.items(): - validate_list_of_strings_param( - param_name=param_name, - param_argument=param_argument, - ) - if param_argument is not None: - params[param_name] = list_to_comma_delimited(param_argument) - - api_path = utils.format_url( - "/v1/auth/{mount_point}/role/{role_name}/custom-secret-id", - mount_point=mount_point, - role_name=role_name, - ) - return self._adapter.post(url=api_path, json=params, wrap_ttl=wrap_ttl) - - def read_secret_id(self, role_name, secret_id, mount_point=DEFAULT_MOUNT_POINT): - """ - Read the properties of a Secret ID for a role in the auth method. - - Supported methods: - POST: /auth/{mount_point}/role/{role_name}/secret-id/lookup. Produces: 200 application/json - - :param role_name: The name for the role - :type role_name: str | unicode - :param secret_id: The Secret ID to read. - :type secret_id: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the read_role_id request. - :rtype: dict - """ - params = {"secret_id": secret_id} - api_path = utils.format_url( - "/v1/auth/{mount_point}/role/{role_name}/secret-id/lookup", - mount_point=mount_point, - role_name=role_name, - ) - return self._adapter.post(url=api_path, json=params) - - def destroy_secret_id(self, role_name, secret_id, mount_point=DEFAULT_MOUNT_POINT): - """ - Destroys a Secret ID for a role in the auth method. - - Supported methods: - POST: /auth/{mount_point}/role/{role_name}/secret-id/destroy. Produces 204 (empty body) - - :param role_name: The name for the role - :type role_name: str | unicode - :param secret_id: The Secret ID to read. - :type secret_id: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - """ - params = {"secret_id": secret_id} - api_path = utils.format_url( - "/v1/auth/{mount_point}/role/{role_name}/secret-id/destroy", - mount_point=mount_point, - role_name=role_name, - ) - return self._adapter.post(url=api_path, json=params) - - def list_secret_id_accessors(self, role_name, mount_point=DEFAULT_MOUNT_POINT): - """ - Lists accessors of all issued Secret IDs for a role in the auth method. - - Supported methods: - LIST: /auth/{mount_point}/role/{role_name}/secret-id. Produces: 200 application/json - - :param role_name: The name for the role - :type role_name: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the read_role_id request. - :rtype: dict - """ - api_path = utils.format_url( - "/v1/auth/{mount_point}/role/{role_name}/secret-id", - mount_point=mount_point, - role_name=role_name, - ) - return self._adapter.list(url=api_path) - - def read_secret_id_accessor( - self, role_name, secret_id_accessor, mount_point=DEFAULT_MOUNT_POINT - ): - """ - Read the properties of a Secret ID for a role in the auth method. - - Supported methods: - POST: /auth/{mount_point}/role/{role_name}/secret-id-accessor/lookup. Produces: 200 application/json - - :param role_name: The name for the role - :type role_name: str | unicode - :param secret_id_accessor: The accessor for the Secret ID to read. - :type secret_id_accessor: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the read_role_id request. - :rtype: dict - """ - params = {"secret_id_accessor": secret_id_accessor} - api_path = utils.format_url( - "/v1/auth/{mount_point}/role/{role_name}/secret-id-accessor/lookup", - mount_point=mount_point, - role_name=role_name, - ) - return self._adapter.post(url=api_path, json=params) - - def destroy_secret_id_accessor( - self, role_name, secret_id_accessor, mount_point=DEFAULT_MOUNT_POINT - ): - """ - Destroys a Secret ID for a role in the auth method. - - Supported methods: - POST: /auth/{mount_point}/role/{role_name}/secret-id-accessor/destroy. Produces: 204 (empty body) - - :param role_name: The name for the role - :type role_name: str | unicode - :param secret_id_accessor: The accessor for the Secret ID to read. - :type secret_id_accessor: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - """ - params = {"secret_id_accessor": secret_id_accessor} - api_path = utils.format_url( - "/v1/auth/{mount_point}/role/{role_name}/secret-id-accessor/destroy", - mount_point=mount_point, - role_name=role_name, - ) - return self._adapter.post(url=api_path, json=params) - - def login( - self, role_id, secret_id=None, use_token=True, mount_point=DEFAULT_MOUNT_POINT - ): - """ - Login with APPROLE credentials. - - Supported methods: - POST: /auth/{mount_point}/login. Produces: 200 application/json - - :param role_id: Role ID of the role. - :type role_id: str | unicode - :param secret_id: Secret ID of the role. - :type secret_id: str | unicode - :param use_token: if True, uses the token in the response received from the auth request to set the "token" - attribute on the the :py:meth:`hvac.adapters.Adapter` instance under the _adapter Client attribute. - :type use_token: bool - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the read_role_id request. - :rtype: dict - """ - params = {"role_id": role_id, "secret_id": secret_id} - api_path = utils.format_url( - "/v1/auth/{mount_point}/login", mount_point=mount_point - ) - return self._adapter.login( - url=api_path, - use_token=use_token, - json=params, - ) diff --git a/.venv/lib/python3.12/site-packages/hvac/api/auth_methods/aws.py b/.venv/lib/python3.12/site-packages/hvac/api/auth_methods/aws.py deleted file mode 100644 index 58adb05..0000000 --- a/.venv/lib/python3.12/site-packages/hvac/api/auth_methods/aws.py +++ /dev/null @@ -1,992 +0,0 @@ -#!/usr/bin/python -""" AWS auth method module """ -import logging -import json -from base64 import b64encode - -from hvac import exceptions, aws_utils, utils -from hvac.api.vault_api_base import VaultApiBase -from hvac.constants.aws import ALLOWED_IAM_ALIAS_TYPES, ALLOWED_EC2_ALIAS_TYPES -from hvac.constants.aws import DEFAULT_MOUNT_POINT as AWS_DEFAULT_MOUNT_POINT - -logger = logging.getLogger(__name__) - - -class Aws(VaultApiBase): - """AWS Auth Method (API). - - Reference: https://www.vaultproject.io/api/auth/aws/index.html - """ - - def configure( - self, - max_retries=None, - access_key=None, - secret_key=None, - endpoint=None, - iam_endpoint=None, - sts_endpoint=None, - iam_server_id_header_value=None, - mount_point=AWS_DEFAULT_MOUNT_POINT, - sts_region=None, - ): - """Configure the credentials required to perform API calls to AWS as well as custom endpoints to talk to AWS API. - - The instance identity document fetched from the PKCS#7 signature will provide the EC2 instance ID. - The credentials configured using this endpoint will be used to query the status of the instances via - DescribeInstances API. If static credentials are not provided using this endpoint, then the credentials will be - retrieved from the environment variables AWS_ACCESS_KEY, AWS_SECRET_KEY and AWS_REGION respectively. - If the credentials are still not found and if the method is configured on an EC2 instance with metadata querying - capabilities, the credentials are fetched automatically - - Supported methods: - POST: /auth/{mount_point}/config Produces: 204 (empty body) - - :param max_retries: Number of max retries the client should use for recoverable errors. - The default (-1) falls back to the AWS SDK's default behavior - :type max_retries: int - :param access_key: AWS Access key with permissions to query AWS APIs. The permissions required depend on the - specific configurations. If using the iam auth method without inferencing, then no credentials are - necessary. If using the ec2 auth method or using the iam auth method with inferencing, then these - credentials need access to ec2:DescribeInstances. If additionally a bound_iam_role is specified, then - these credentials also need access to iam:GetInstanceProfile. If, however, an alternate sts configuration - is set for the target account, then the credentials must be permissioned to call sts:AssumeRole on the - configured role, and that role must have the permissions described here - :type access_key: str | unicode - :param secret_key: AWS Secret key with permissions to query AWS APIs - :type secret_key: str | unicode - :param endpoint: URL to override the default generated endpoint for making AWS EC2 API calls - :type endpoint: str | unicode - :param iam_endpoint: URL to override the default generated endpoint for making AWS IAM API calls - :type iam_endpoint: str | unicode - :param sts_endpoint: URL to override the default generated endpoint for making AWS STS API calls - :type sts_endpoint: str | unicode - :param iam_server_id_header_value: The value to require in the X-Vault-AWS-IAM-Server-ID header as part of - GetCallerIdentity requests that are used in the iam auth method. If not set, then no value is required or - validated. If set, clients must include an X-Vault-AWS-IAM-Server-ID header in the headers of login - requests, and further this header must be among the signed headers validated by AWS. This is to protect - against different types of replay attacks, for example a signed request sent to a dev server being resent - to a production server - :type iam_server_id_header_value: str | unicode - :param mount_point: The path the AWS auth method was mounted on. - :type mount_point: str | unicode - :param sts_region: Region to override the default region for making AWS STS API calls. Should only be set if - sts_endpoint is set. If so, should be set to the region in which the custom sts_endpoint resides - :type sts_region: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - - params = utils.remove_nones( - { - "max_retries": max_retries, - "access_key": access_key, - "secret_key": secret_key, - "endpoint": endpoint, - "iam_endpoint": iam_endpoint, - "sts_endpoint": sts_endpoint, - "iam_server_id_header_value": iam_server_id_header_value, - "sts_region": sts_region, - } - ) - api_path = utils.format_url( - "/v1/auth/{mount_point}/config/client", mount_point=mount_point - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def read_config(self, mount_point=AWS_DEFAULT_MOUNT_POINT): - """Read previously configured AWS access credentials. - - Supported methods: - GET: /auth/{mount_point}/config. Produces: 200 application/json - - :param mount_point: The path the AWS auth method was mounted on. - :type mount_point: str | unicode - :return: The data key from the JSON response of the request. - :rtype: dict - """ - api_path = utils.format_url( - "/v1/auth/{mount_point}/config/client", mount_point=mount_point - ) - response = self._adapter.get( - url=api_path, - ) - return response.get("data") - - def delete_config(self, mount_point=AWS_DEFAULT_MOUNT_POINT): - """Delete previously configured AWS access credentials, - - Supported methods: - DELETE: /auth/{mount_point}/config Produces: 204 (empty body) - - :param mount_point: The path the AWS auth method was mounted on. - :type mount_point: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url( - "/v1/auth/{mount_point}/config/client", mount_point=mount_point - ) - return self._adapter.delete(url=api_path) - - def configure_identity_integration( - self, - iam_alias=None, - ec2_alias=None, - mount_point=AWS_DEFAULT_MOUNT_POINT, - iam_metadata=None, - ec2_metadata=None, - ): - """Configure the way that Vault interacts with the Identity store. - - The default (as of Vault 1.0.3) is role_id for both values. - - Supported methods: - POST: /auth/{mount_point}/config/identity Produces: 204 (empty body) - - :param iam_alias: How to generate the identity alias when using the iam auth method. Valid choices are role_id, - unique_id, and full_arn When role_id is selected, the randomly generated ID of the role is used. When - unique_id is selected, the IAM Unique ID of the IAM principal (either the user or role) is used as the - identity alias name. When full_arn is selected, the ARN returned by the sts:GetCallerIdentity call is used - as the alias name. This is either arn:aws:iam:::user/ or - arn:aws:sts:::assumed-role//. Note: if you - select full_arn and then delete and recreate the IAM role, Vault won't be aware and any identity aliases - set up for the role name will still be valid - :type iam_alias: str | unicode - :param iam_metadata: The metadata to include on the token returned by the login endpoint. - This metadata will be added to both audit logs, and on the ``iam_alias``. By default, it includes ``account_id`` - and ``auth_type``. Additionally, ``canonical_arn``, ``client_arn``, ``client_user_id``, ``inferred_aws_region``, ``inferred_entity_id``, - and ``inferred_entity_type`` are available. To include no metadata, set to an empty list ``[]``. - To use only particular fields, select the explicit fields. To restore to defaults, send only a field of ``default``. - Only select fields that will have a low rate of change for your ``iam_alias`` because each change triggers a storage - write and can have a performance impact at scale. - :type iam_metadata: str | unicode | list - :param ec2_alias: Configures how to generate the identity alias when using the ec2 auth method. Valid choices - are role_id, instance_id, and image_id. When role_id is selected, the randomly generated ID of the role is - used. When instance_id is selected, the instance identifier is used as the identity alias name. When - image_id is selected, AMI ID of the instance is used as the identity alias name - :type ec2_alias: str | unicode - :param ec2_metadata: The metadata to include on the token returned by the login endpoint. This metadata will be - added to both audit logs, and on the ``ec2_alias``. By default, it includes ``account_id`` and ``auth_type``. Additionally, - ``ami_id``, ``instance_id``, and ``region`` are available. To include no metadata, set to an empty list ``[]``. - To use only particular fields, select the explicit fields. To restore to defaults, send only a field of ``default``. - Only select fields that will have a low rate of change for your ``ec2_alias`` because each change triggers a storage - write and can have a performance impact at scale. - :type ec2_metadata: str | unicode | list - :param mount_point: The path the AWS auth method was mounted on. - :type mount_point: str | unicode - :return: The response of the request - :rtype: request.Response - """ - if iam_alias is not None and iam_alias not in ALLOWED_IAM_ALIAS_TYPES: - error_msg = f"invalid iam alias type provided: '{iam_alias}' - supported iam alias types: '{','.join(ALLOWED_IAM_ALIAS_TYPES)}'" - raise exceptions.ParamValidationError(error_msg) - if ec2_alias is not None and ec2_alias not in ALLOWED_EC2_ALIAS_TYPES: - error_msg = f"invalid ec2 alias type provided: '{ec2_alias}' - supported ec2 alias types: '{','.join(ALLOWED_EC2_ALIAS_TYPES)}'" - raise exceptions.ParamValidationError(error_msg) - - params = utils.remove_nones( - { - "iam_alias": iam_alias, - "ec2_alias": ec2_alias, - "ec2_metadata": ec2_metadata, - "iam_metadata": iam_metadata, - } - ) - api_auth = "/v1/auth/{mount_point}/config/identity".format( - mount_point=mount_point - ) - return self._adapter.post( - url=api_auth, - json=params, - ) - - def read_identity_integration(self, mount_point=AWS_DEFAULT_MOUNT_POINT): - """Return previously configured identity integration configuration. - - Supported methods: - GET: /auth/{mount_point}/config/identity. Produces: 200 application/json - - :param mount_point: The path the AWS auth method was mounted on. - :type mount_point: str | unicode - :return: The data key from the JSON response of the request. - :rtype: dict - """ - api_path = utils.format_url( - "/v1/auth/{mount_point}/config/identity", mount_point=mount_point - ) - response = self._adapter.get( - url=api_path, - ) - return response.get("data") - - def create_certificate_configuration( - self, - cert_name, - aws_public_cert, - document_type=None, - mount_point=AWS_DEFAULT_MOUNT_POINT, - ): - """Register AWS public key to be used to verify the instance identity documents. - - While the PKCS#7 signature of the identity documents have DSA digest, the identity signature will have RSA - digest, and hence the public keys for each type varies respectively. Indicate the type of the public key using - the "type" parameter - - Supported methods: - POST: /auth/{mount_point}/config/certificate/:cert_name Produces: 204 (empty body) - - :param cert_name: Name of the certificate - :type cert_name: string | unicode - :param aws_public_cert: Base64 encoded AWS Public key required to verify PKCS7 signature of the EC2 instance - metadata - :param document_type: Takes the value of either "pkcs7" or "identity", indicating the type of document which can be - verified using the given certificate - :type document_type: string | unicode - :param mount_point: The path the AWS auth method was mounted on. - :type mount_point: str | unicode - :return: The response of the request - :rtype: request.Response - """ - params = { - "cert_name": cert_name, - "aws_public_cert": aws_public_cert, - } - params.update( - utils.remove_nones( - { - "document_type": document_type, - } - ) - ) - api_path = utils.format_url( - "/v1/auth/{0}/config/certificate/{1}", mount_point, cert_name - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def read_certificate_configuration( - self, cert_name, mount_point=AWS_DEFAULT_MOUNT_POINT - ): - """Return previously configured AWS public key. - - Supported methods: - GET: /v1/auth/{mount_point}/config/certificate/:cert_name Produces: 200 application/json - - :param cert_name: Name of the certificate - :type cert_name: str | unicode - :param mount_point: The path the AWS auth method was mounted on. - :return: The data key from the JSON response of the request. - :rtype: dict - """ - api_path = utils.format_url( - "/v1/auth/{0}/config/certificate/{1}", mount_point, cert_name - ) - response = self._adapter.get( - url=api_path, - ) - return response.get("data") - - def delete_certificate_configuration( - self, cert_name, mount_point=AWS_DEFAULT_MOUNT_POINT - ): - """Remove previously configured AWS public key. - - Supported methods: - DELETE: /auth/{mount_point}/config/certificate/:cert_name Produces: 204 (empty body) - - :param cert_name: Name of the certificate - :type cert_name: str | unicode - :param mount_point: The path the AWS auth method was mounted on. - :type mount_point: str | unicode - :return: The response of the request - :rtype: request.Response - """ - api_path = utils.format_url( - "/v1/auth/{0}/config/certificate/{1}", mount_point, cert_name - ) - return self._adapter.delete( - url=api_path, - ) - - def list_certificate_configurations(self, mount_point=AWS_DEFAULT_MOUNT_POINT): - """List AWS public certificates that are registered with the method. - - Supported methods - LIST: /auth/{mount_point}/config/certificates Produces: 200 application/json - - :param mount_point: The path the AWS auth method was mounted on. - :type mount_point: str - :return: The response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url( - "/v1/auth/{mount_point}/config/certificates", mount_point=mount_point - ) - response = self._adapter.list( - url=api_path, - ) - return response.get("data") - - def create_sts_role( - self, account_id, sts_role, mount_point=AWS_DEFAULT_MOUNT_POINT - ): - """Allow the explicit association of STS roles to satellite AWS accounts (i.e. those which are not the - account in which the Vault server is running.) - - Vault will use credentials obtained by assuming these STS roles when validating IAM principals or EC2 - instances in the particular AWS account - - Supported methods: - POST: /v1/auth/{mount_point}/config/sts/:account_id Produces: 204 (empty body) - - :param account_id: AWS account ID to be associated with STS role. - If set, Vault will use assumed credentials to verify any login attempts from EC2 instances in this account. - :type account_id: str - :param sts_role: AWS ARN for STS role to be assumed when interacting with the account specified. - The Vault server must have permissions to assume this role. - :type sts_role: str - :param mount_point: The path the AWS auth method was mounted on. - :type mount_point: str - :return: The response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url( - "/v1/auth/{0}/config/sts/{1}", mount_point, account_id - ) - params = { - "account_id": account_id, - "sts_role": sts_role, - } - return self._adapter.post( - url=api_path, - json=params, - ) - - def read_sts_role(self, account_id, mount_point=AWS_DEFAULT_MOUNT_POINT): - """Return previously configured STS role. - - :param account_id: AWS account ID that has been previously associated with STS role. - :type account_id: str - :param mount_point: The path the AWS auth method was mounted on. - :type mount_point: str - :return: The response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url( - "/v1/auth/{0}/config/sts/{1}", mount_point, account_id - ) - response = self._adapter.get( - url=api_path, - ) - return response.get("data") - - def list_sts_roles(self, mount_point=AWS_DEFAULT_MOUNT_POINT): - """List AWS Account IDs for which an STS role is registered. - - :param mount_point: The path the AWS auth method was mounted on. - :type mount_point: str - :return: The response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url( - "/v1/auth/{mount_point}/config/sts", mount_point=mount_point - ) - response = self._adapter.list(url=api_path) - return response.get("data") - - def delete_sts_role(self, account_id, mount_point=AWS_DEFAULT_MOUNT_POINT): - """Delete a previously configured AWS account/STS role association. - - :param account_id: - :param mount_point: The path the AWS auth method was mounted on. - :type mount_point: str - :return: The response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url( - "/v1/auth/{0}/config/sts/{1}", mount_point, account_id - ) - return self._adapter.delete( - url=api_path, - ) - - def configure_identity_whitelist_tidy( - self, - safety_buffer=None, - disable_periodic_tidy=None, - mount_point=AWS_DEFAULT_MOUNT_POINT, - ): - """Configure the periodic tidying operation of the whitelisted identity entries. - - :param safety_buffer: The amount of extra time that must have passed beyond the roletag expiration, before - it is removed from the method storage. - :type safety_buffer: str - :param disable_periodic_tidy: If set to 'true', disables the periodic tidying of the identity-whitelist/ entries. - :type disable_periodic_tidy: bool - :param mount_point: The path the AWS auth method was mounted on. - :type mount_point: str - :return: The response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url( - "/v1/auth/{mount_point}/config/tidy/identity-whitelist", - mount_point=mount_point, - ) - params = utils.remove_nones( - { - "safety_buffer": safety_buffer, - "disable_periodic_tidy": disable_periodic_tidy, - } - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def read_identity_whitelist_tidy(self, mount_point=AWS_DEFAULT_MOUNT_POINT): - """Read previously configured periodic whitelist tidying settings. - - :param mount_point: The path the AWS auth method was mounted on. - :type mount_point: str - :return: The response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url( - "/v1/auth/{mount_point}/config/tidy/identity-whitelist", - mount_point=mount_point, - ) - response = self._adapter.get(url=api_path) - return response.get("data") - - def delete_identity_whitelist_tidy(self, mount_point=AWS_DEFAULT_MOUNT_POINT): - """Delete previously configured periodic whitelist tidying settings. - - :param mount_point: The path the AWS auth method was mounted on. - :type mount_point: str - :return: The response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url( - "/v1/auth/{mount_point}/config/tidy/identity-whitelist", - mount_point=mount_point, - ) - return self._adapter.delete( - url=api_path, - ) - - def configure_role_tag_blacklist_tidy( - self, - safety_buffer=None, - disable_periodic_tidy=None, - mount_point=AWS_DEFAULT_MOUNT_POINT, - ): - """Configure the periodic tidying operation of the blacklisted role tag entries. - - :param safety_buffer: The amount of extra time that must have passed beyond the roletag expiration, before - it is removed from the method storage. - :type safety_buffer: str - :param disable_periodic_tidy: If set to 'true', disables the periodic tidying of the roletag-blacklist/ entries. - :type disable_periodic_tidy: bool - :param mount_point: The path the AWS auth method was mounted on. - :type mount_point: str - :return: The response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url( - "/v1/auth/{mount_point}/config/tidy/roletag-blacklist", - mount_point=mount_point, - ) - params = utils.remove_nones( - { - "safety_buffer": safety_buffer, - "disable_periodic_tidy": disable_periodic_tidy, - } - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def read_role_tag_blacklist_tidy(self, mount_point=AWS_DEFAULT_MOUNT_POINT): - """Read previously configured periodic blacklist tidying settings. - - :param mount_point: The path the AWS auth method was mounted on. - :type mount_point: str - :return: The response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url( - "/v1/auth/{mount_point}/config/tidy/roletag-blacklist", - mount_point=mount_point, - ) - response = self._adapter.get(url=api_path) - return response.get("data") - - def delete_role_tag_blacklist_tidy(self, mount_point=AWS_DEFAULT_MOUNT_POINT): - """Delete previously configured periodic blacklist tidying settings. - - :param mount_point: The path the AWS auth method was mounted on. - :type mount_point: str - :return: The response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url( - "/v1/auth/{mount_point}/config/tidy/roletag-blacklist", - mount_point=mount_point, - ) - return self._adapter.delete(url=api_path) - - def create_role( - self, - role, - auth_type=None, - bound_ami_id=None, - bound_account_id=None, - bound_region=None, - bound_vpc_id=None, - bound_subnet_id=None, - bound_iam_role_arn=None, - bound_iam_instance_profile_arn=None, - bound_ec2_instance_id=None, - role_tag=None, - bound_iam_principal_arn=None, - inferred_entity_type=None, - inferred_aws_region=None, - resolve_aws_unique_ids=None, - ttl=None, - max_ttl=None, - period=None, - policies=None, - allow_instance_migration=None, - disallow_reauthentication=None, - mount_point=AWS_DEFAULT_MOUNT_POINT, - ): - """Register a role in the method. - - :param role: - :param auth_type: - :param bound_ami_id: - :param bound_account_id: - :param bound_region: - :param bound_vpc_id: - :param bound_subnet_id: - :param bound_iam_role_arn: - :param bound_iam_instance_profile_arn: - :param bound_ec2_instance_id: - :param role_tag: - :param bound_iam_principal_arn: - :param inferred_entity_type: - :param inferred_aws_region: - :param resolve_aws_unique_ids: - :param ttl: - :param max_ttl: - :param period: - :param policies: - :param allow_instance_migration: - :param disallow_reauthentication: - :param mount_point: The path the AWS auth method was mounted on. - :type mount_point: str - :return: The response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url("/v1/auth/{0}/role/{1}", mount_point, role) - params = { - "role": role, - } - params.update( - utils.remove_nones( - { - "auth_type": auth_type, - "resolve_aws_unique_ids": resolve_aws_unique_ids, - "bound_ami_id": bound_ami_id, - "bound_account_id": bound_account_id, - "bound_region": bound_region, - "bound_vpc_id": bound_vpc_id, - "bound_subnet_id": bound_subnet_id, - "bound_iam_role_arn": bound_iam_role_arn, - "bound_iam_instance_profile_arn": bound_iam_instance_profile_arn, - "bound_ec2_instance_id": bound_ec2_instance_id, - "role_tag": role_tag, - "bound_iam_principal_arn": bound_iam_principal_arn, - "inferred_entity_type": inferred_entity_type, - "inferred_aws_region": inferred_aws_region, - "ttl": ttl, - "max_ttl": max_ttl, - "period": period, - "policies": policies, - "allow_instance_migration": allow_instance_migration, - "disallow_reauthentication": disallow_reauthentication, - } - ) - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def read_role(self, role, mount_point=AWS_DEFAULT_MOUNT_POINT): - """Returns the previously registered role configuration - - :param role: - :param mount_point: The path the AWS auth method was mounted on. - :type mount_point: str - :return: The response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url("/v1/auth/{0}/role/{1}", mount_point, role) - response = self._adapter.get(url=api_path) - return response.get("data") - - def list_roles(self, mount_point=AWS_DEFAULT_MOUNT_POINT): - """Lists all the roles that are registered with the method - - :param mount_point: The path the AWS auth method was mounted on. - :type mount_point: str - :return: The response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url( - "/v1/auth/{mount_point}/roles", mount_point=mount_point - ) - response = self._adapter.list( - url=api_path, - ) - return response.get("data") - - def delete_role(self, role, mount_point=AWS_DEFAULT_MOUNT_POINT): - """Deletes the previously registered role - - :param role: - :param mount_point: The path the AWS auth method was mounted on. - :type mount_point: str - :return: The response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url("/v1/auth/{0}/role/{1}", mount_point, role) - return self._adapter.delete( - url=api_path, - ) - - def create_role_tags( - self, - role, - policies=None, - max_ttl=None, - instance_id=None, - allow_instance_migration=None, - disallow_reauthentication=None, - mount_point=AWS_DEFAULT_MOUNT_POINT, - ): - """Create a role tag on the role, which helps in restricting the capabilities that are set on the role. - - Role tags are not tied to any specific ec2 instance unless specified explicitly using the - instance_id parameter. By default, role tags are designed to be used across all instances that - satisfies the constraints on the role. Regardless of which instances have role tags on them, capabilities - defined in a role tag must be a strict subset of the given role's capabilities. Note that, since adding - and removing a tag is often a widely distributed privilege, care needs to be taken to ensure that the - instances are attached with correct tags to not let them gain more privileges than what were intended. - If a role tag is changed, the capabilities inherited by the instance will be those defined on the new role - tag. Since those must be a subset of the role capabilities, the role should never provide more capabilities - than any given instance can be allowed to gain in a worst-case scenario - - :param role: Name of the role. - :type role: str - :param policies: Policies to be associated with the tag. If set, must be a subset of the role's policies. If - set, but set to an empty value, only the 'default' policy will be given to issued tokens. - :type policies: list - :param max_ttl: The maximum allowed lifetime of tokens issued using this role. - :type max_ttl: str - :param instance_id: Instance ID for which this tag is intended for. If set, the created tag can only be used by - the instance with the given ID. - :type instance_id: str - :param disallow_reauthentication: If set, only allows a single token to be granted per instance ID. This can be - cleared with the auth/aws/identity-whitelist endpoint. Defaults to 'false'. Mutually exclusive with - allow_instance_migration. - :type disallow_reauthentication: bool - :param allow_instance_migration: If set, allows migration of the underlying instance where the client resides. - This keys off of pendingTime in the metadata document, so essentially, this disables the client nonce check - whenever the instance is migrated to a new host and pendingTime is newer than the previously-remembered - time. Use with caution. Defaults to 'false'. Mutually exclusive with disallow_reauthentication. - :type allow_instance_migration: bool - :param mount_point: The path the AWS auth method was mounted on. - :type mount_point: str - :return: The create role tag response. - :rtype: dict - """ - api_path = utils.format_url("/v1/auth/{0}/role/{1}/tag", mount_point, role) - - params = utils.remove_nones( - { - "disallow_reauthentication": disallow_reauthentication, - "policies": policies, - "max_ttl": max_ttl, - "instance_id": instance_id, - "allow_instance_migration": allow_instance_migration, - } - ) - - return self._adapter.post( - url=api_path, - json=params, - ) - - def iam_login( - self, - access_key, - secret_key, - session_token=None, - header_value=None, - role=None, - use_token=True, - region="us-east-1", - mount_point=AWS_DEFAULT_MOUNT_POINT, - ): - """Fetch a token - - This endpoint verifies the pkcs7 signature of the instance identity document or the signature of the - signed GetCallerIdentity request. With the ec2 auth method, or when inferring an EC2 instance, - verifies that the instance is actually in a running state. Cross checks the constraints defined on the - role with which the login is being performed. With the ec2 auth method, as an alternative to pkcs7 - signature, the identity document along with its RSA digest can be supplied to this endpoint - - :param role: Name of the role against which the login is being attempted. - :type role: str - :param use_token: if True, uses the token in the response received from the auth request to set the "token" - attribute on the the :py:meth:`hvac.adapters.Adapter` instance under the _adapter Client attribute. - :type use_token: bool - :param mount_point: The path the AWS auth method was mounted on. - :type mount_point: str - :return: The response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url( - "/v1/auth/{mount_point}/login", mount_point=mount_point - ) - - request = aws_utils.generate_sigv4_auth_request(header_value=header_value) - auth = aws_utils.SigV4Auth(access_key, secret_key, session_token, region) - auth.add_auth(request) - - # https://github.com/hashicorp/vault/blob/master/builtin/credential/aws/cli.go - headers = json.dumps({k: [request.headers[k]] for k in request.headers}) - params = { - "iam_http_request_method": request.method, - "iam_request_url": b64encode(request.url.encode("utf-8")).decode("utf-8"), - "iam_request_headers": b64encode(headers.encode("utf-8")).decode("utf-8"), - "iam_request_body": b64encode(request.body.encode("utf-8")).decode("utf-8"), - "role": role, - } - - return self._adapter.login( - url=api_path, - use_token=use_token, - json=params, - ) - - def ec2_login( - self, - pkcs7, - nonce=None, - role=None, - use_token=True, - mount_point=AWS_DEFAULT_MOUNT_POINT, - ): - """Retrieve a Vault token using an AWS authentication method mount's EC2 role. - - :param pkcs7: PKCS7 signature of the identity document with all newline characters removed. - :type pkcs7: str - :param nonce: The nonce to be used for subsequent login requests. - :type nonce: str - :param role: Name of the role against which the login is being attempted. - :type role: str - :param use_token: if True, uses the token in the response received from the auth request to set the "token" - attribute on the the :py:meth:`hvac.adapters.Adapter` instance under the _adapter Client attribute. - :type use_token: bool - :param mount_point: The path the AWS auth method was mounted on. - :type mount_point: str - :return: The response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url( - "/v1/auth/{mount_point}/login", mount_point=mount_point - ) - params = {"pkcs7": pkcs7} - if nonce: - params["nonce"] = nonce - if role: - params["role"] = role - - return self._adapter.login( - url=api_path, - use_token=use_token, - json=params, - ) - - def place_role_tags_in_blacklist( - self, role_tag, mount_point=AWS_DEFAULT_MOUNT_POINT - ): - """Places a valid role tag in a blacklist - - This ensures that the role tag cannot be used by any instance to perform a login operation again. Note - that if the role tag was previously used to perform a successful login, placing the tag in the blacklist - does not invalidate the already issued token - - :param role_tag: - :param mount_point: The path the AWS auth method was mounted on. - :type mount_point: str - :return: The response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url( - "/v1/auth/{0}/roletag-blacklist/{1}", mount_point, role_tag - ) - return self._adapter.post(url=api_path) - - def read_role_tag_blacklist(self, role_tag, mount_point=AWS_DEFAULT_MOUNT_POINT): - """Returns the blacklist entry of a previously blacklisted role tag - - :param role_tag: - :param mount_point: The path the AWS auth method was mounted on. - :type mount_point: str - :return: The response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url( - "/v1/auth/{0}/roletag-blacklist/{1}", mount_point, role_tag - ) - response = self._adapter.get(url=api_path) - return response.get("data") - - def list_blacklist_tags(self, mount_point=AWS_DEFAULT_MOUNT_POINT): - """Lists all the role tags that are blacklisted - - :param mount_point: The path the AWS auth method was mounted on. - :type mount_point: str - :return: The response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url( - "/v1/auth/{mount_point}/roletag-blacklist", mount_point=mount_point - ) - response = self._adapter.list( - url=api_path, - ) - return response.get("data") - - def delete_blacklist_tags(self, role_tag, mount_point=AWS_DEFAULT_MOUNT_POINT): - """Deletes a blacklisted role tag - - :param role_tag: - :param mount_point: The path the AWS auth method was mounted on. - :type mount_point: str - :return: The response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url( - "/v1/auth/{0}/roletag-blacklist/{1}", mount_point, role_tag - ) - return self._adapter.delete( - url=api_path, - ) - - @utils.aliased_parameter( - "saftey_buffer", "safety_buffer", removed_in_version="3.0.0", position=1 - ) - def tidy_blacklist_tags( - self, safety_buffer="72h", mount_point=AWS_DEFAULT_MOUNT_POINT - ): - """Cleans up the entries in the blacklist based on expiration time on the entry and safety_buffer - - :param safety_buffer: - :param mount_point: The path the AWS auth method was mounted on. - :type mount_point: str - :return: The response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url( - "/v1/auth/{mount_point}/tidy/roletag-blacklist", mount_point=mount_point - ) - params = { - "safety_buffer": safety_buffer, - } - return self._adapter.post( - url=api_path, - json=params, - ) - - def read_identity_whitelist(self, instance_id, mount_point=AWS_DEFAULT_MOUNT_POINT): - """Returns an entry in the whitelist. An entry will be created/updated by every successful login - - :param instance_id: - :param mount_point: The path the AWS auth method was mounted on. - :type mount_point: str - :return: The response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url( - "/v1/auth/{0}/identity-whitelist/{1}", mount_point, instance_id - ) - response = self._adapter.get(url=api_path) - return response.get("data") - - def list_identity_whitelist(self, mount_point=AWS_DEFAULT_MOUNT_POINT): - """Lists all the instance IDs that are in the whitelist of successful logins - - :param mount_point: The path the AWS auth method was mounted on. - :type mount_point: str - :return: The response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url( - "/v1/auth/{mount_point}/identity-whitelist", mount_point=mount_point - ) - response = self._adapter.list( - url=api_path, - ) - return response.get("data") - - def delete_identity_whitelist_entries( - self, instance_id, mount_point=AWS_DEFAULT_MOUNT_POINT - ): - """Deletes a cache of the successful login from an instance - - :param instance_id: - :param mount_point: The path the AWS auth method was mounted on. - :type mount_point: str - :return: The response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url( - "/v1/auth/{0}/identity-whitelist/{1}", mount_point, instance_id - ) - return self._adapter.delete( - url=api_path, - ) - - @utils.aliased_parameter( - "saftey_buffer", "safety_buffer", removed_in_version="3.0.0", position=1 - ) - def tidy_identity_whitelist_entries( - self, safety_buffer="72h", mount_point=AWS_DEFAULT_MOUNT_POINT - ): - """Cleans up the entries in the whitelist based on expiration time and safety_buffer - - :param safety_buffer: - :param mount_point: The path the AWS auth method was mounted on. - :type mount_point: str - :return: The response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url( - "/v1/auth/{mount_point}/tidy/identity-whitelist", mount_point=mount_point - ) - params = { - "safety_buffer": safety_buffer, - } - return self._adapter.post(url=api_path, json=params) diff --git a/.venv/lib/python3.12/site-packages/hvac/api/auth_methods/azure.py b/.venv/lib/python3.12/site-packages/hvac/api/auth_methods/azure.py deleted file mode 100644 index a7053fa..0000000 --- a/.venv/lib/python3.12/site-packages/hvac/api/auth_methods/azure.py +++ /dev/null @@ -1,343 +0,0 @@ -#!/usr/bin/env python -"""Azure auth method module.""" -import logging - -from hvac import exceptions, utils -from hvac.api.vault_api_base import VaultApiBase -from hvac.constants.azure import VALID_ENVIRONMENTS - -DEFAULT_MOUNT_POINT = "azure" -logger = logging.getLogger(__name__) - - -class Azure(VaultApiBase): - """Azure Auth Method (API). - - Reference: https://www.vaultproject.io/api/auth/azure/index.html - """ - - def configure( - self, - tenant_id, - resource, - environment=None, - client_id=None, - client_secret=None, - mount_point=DEFAULT_MOUNT_POINT, - ): - """Configure the credentials required for the plugin to perform API calls to Azure. - - These credentials will be used to query the metadata about the virtual machine. - - Supported methods: - POST: /auth/{mount_point}/config. Produces: 204 (empty body) - - :param tenant_id: The tenant id for the Azure Active Directory organization. - :type tenant_id: str | unicode - :param resource: The configured URL for the application registered in Azure Active Directory. - :type resource: str | unicode - :param environment: The Azure cloud environment. Valid values: AzurePublicCloud, AzureUSGovernmentCloud, - AzureChinaCloud, AzureGermanCloud. - :type environment: str | unicode - :param client_id: The client id for credentials to query the Azure APIs. Currently read permissions to query - compute resources are required. - :type client_id: str | unicode - :param client_secret: The client secret for credentials to query the Azure APIs. - :type client_secret: str | unicode - :param mount_point: The "path" the azure auth method was mounted on. - :type mount_point: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - if environment is not None and environment not in VALID_ENVIRONMENTS: - error_msg = 'invalid environment argument provided: "{arg}"; supported environments: "{environments}"' - raise exceptions.ParamValidationError( - error_msg.format( - arg=environment, - environments=",".join(VALID_ENVIRONMENTS), - ) - ) - params = { - "tenant_id": tenant_id, - "resource": resource, - } - params.update( - utils.remove_nones( - { - "environment": environment, - "client_id": client_id, - "client_secret": client_secret, - } - ) - ) - api_path = utils.format_url( - "/v1/auth/{mount_point}/config", mount_point=mount_point - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def read_config(self, mount_point=DEFAULT_MOUNT_POINT): - """Return the previously configured config, including credentials. - - Supported methods: - GET: /auth/{mount_point}/config. Produces: 200 application/json - - :param mount_point: The "path" the azure auth method was mounted on. - :type mount_point: str | unicode - :return: The data key from the JSON response of the request. - :rtype: dict - """ - api_path = utils.format_url( - "/v1/auth/{mount_point}/config", mount_point=mount_point - ) - response = self._adapter.get( - url=api_path, - ) - return response.get("data") - - def delete_config(self, mount_point=DEFAULT_MOUNT_POINT): - """Delete the previously configured Azure config and credentials. - - Supported methods: - DELETE: /auth/{mount_point}/config. Produces: 204 (empty body) - - :param mount_point: The "path" the azure auth method was mounted on. - :type mount_point: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url( - "/v1/auth/{mount_point}/config", mount_point=mount_point - ) - return self._adapter.delete( - url=api_path, - ) - - def create_role( - self, - name, - policies=None, - ttl=None, - max_ttl=None, - period=None, - bound_service_principal_ids=None, - bound_group_ids=None, - bound_locations=None, - bound_subscription_ids=None, - bound_resource_groups=None, - bound_scale_sets=None, - num_uses=None, - mount_point=DEFAULT_MOUNT_POINT, - ): - """Create a role in the method. - - Role types have specific entities that can perform login operations against this endpoint. Constraints specific - to the role type must be set on the role. These are applied to the authenticated entities attempting to login. - - Supported methods: - POST: /auth/{mount_point}/role/{name}. Produces: 204 (empty body) - - - :param name: Name of the role. - :type name: str | unicode - :param policies: Policies to be set on tokens issued using this role. - :type policies: str | list - :param num_uses: Number of uses to set on a token produced by this role. - :type num_uses: int - :param ttl: The TTL period of tokens issued using this role in seconds. - :type ttl: str | unicode - :param max_ttl: The maximum allowed lifetime of tokens issued in seconds using this role. - :type max_ttl: str | unicode - :param period: If set, indicates that the token generated using this role should never expire. The token should - be renewed within the duration specified by this value. At each renewal, the token's TTL will be set to the - value of this parameter. - :type period: str | unicode - :param bound_service_principal_ids: The list of Service Principal IDs that login is restricted to. - :type bound_service_principal_ids: list - :param bound_group_ids: The list of group ids that login is restricted to. - :type bound_group_ids: list - :param bound_locations: The list of locations that login is restricted to. - :type bound_locations: list - :param bound_subscription_ids: The list of subscription IDs that login is restricted to. - :type bound_subscription_ids: list - :param bound_resource_groups: The list of resource groups that login is restricted to. - :type bound_resource_groups: list - :param bound_scale_sets: The list of scale set names that the login is restricted to. - :type bound_scale_sets: list - :param mount_point: The "path" the azure auth method was mounted on. - :type mount_point: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - if policies is not None: - if not ( - isinstance(policies, str) - or ( - isinstance(policies, list) - and all(isinstance(p, str) for p in policies) - ) - ): - error_msg = 'unsupported policies argument provided "{arg}" ({arg_type}), required type: str or List[str]"' - raise exceptions.ParamValidationError( - error_msg.format( - arg=policies, - arg_type=type(policies), - ) - ) - params = utils.remove_nones( - { - "policies": policies, - "ttl": ttl, - "max_ttl": max_ttl, - "period": period, - "bound_service_principal_ids": bound_service_principal_ids, - "bound_group_ids": bound_group_ids, - "bound_locations": bound_locations, - "bound_subscription_ids": bound_subscription_ids, - "bound_resource_groups": bound_resource_groups, - "bound_scale_sets": bound_scale_sets, - "num_uses": num_uses, - } - ) - - api_path = utils.format_url( - "/v1/auth/{mount_point}/role/{name}", mount_point=mount_point, name=name - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def read_role(self, name, mount_point=DEFAULT_MOUNT_POINT): - """Read the previously registered role configuration. - - Supported methods: - GET: /auth/{mount_point}/role/{name}. Produces: 200 application/json - - - :param name: Name of the role. - :type name: str | unicode - :param mount_point: The "path" the azure auth method was mounted on. - :type mount_point: str | unicode - :return: The "data" key from the JSON response of the request. - :rtype: dict - """ - api_path = utils.format_url( - "/v1/auth/{mount_point}/role/{name}", - mount_point=mount_point, - name=name, - ) - response = self._adapter.get( - url=api_path, - ) - return response.get("data") - - def list_roles(self, mount_point=DEFAULT_MOUNT_POINT): - """List all the roles that are registered with the plugin. - - Supported methods: - LIST: /auth/{mount_point}/role. Produces: 200 application/json - - - :param mount_point: The "path" the azure auth method was mounted on. - :type mount_point: str | unicode - :return: The "data" key from the JSON response of the request. - :rtype: dict - """ - api_path = utils.format_url( - "/v1/auth/{mount_point}/role", mount_point=mount_point - ) - response = self._adapter.list(url=api_path) - return response.get("data") - - def delete_role(self, name, mount_point=DEFAULT_MOUNT_POINT): - """Delete the previously registered role. - - Supported methods: - DELETE: /auth/{mount_point}/role/{name}. Produces: 204 (empty body) - - - :param name: Name of the role. - :type name: str | unicode - :param mount_point: The "path" the azure auth method was mounted on. - :type mount_point: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url( - "/v1/auth/{mount_point}/role/{name}", - mount_point=mount_point, - name=name, - ) - return self._adapter.delete( - url=api_path, - ) - - def login( - self, - role, - jwt, - subscription_id=None, - resource_group_name=None, - vm_name=None, - vmss_name=None, - use_token=True, - mount_point=DEFAULT_MOUNT_POINT, - ): - """Fetch a token. - - This endpoint takes a signed JSON Web Token (JWT) and a role name for some entity. It verifies the JWT signature - to authenticate that entity and then authorizes the entity for the given role. - - Supported methods: - POST: /auth/{mount_point}/login. Produces: 200 application/json - - - :param role: Name of the role against which the login is being attempted. - :type role: str | unicode - :param jwt: Signed JSON Web Token (JWT) from Azure MSI. - :type jwt: str | unicode - :param subscription_id: The subscription ID for the machine that generated the MSI token. This information can - be obtained through instance metadata. - :type subscription_id: str | unicode - :param resource_group_name: The resource group for the machine that generated the MSI token. This information - can be obtained through instance metadata. - :type resource_group_name: str | unicode - :param vm_name: The virtual machine name for the machine that generated the MSI token. This information can be - obtained through instance metadata. If vmss_name is provided, this value is ignored. - :type vm_name: str | unicode - :param vmss_name: The virtual machine scale set name for the machine that generated the MSI token. This - information can be obtained through instance metadata. - :type vmss_name: str | unicode - :param use_token: if True, uses the token in the response received from the auth request to set the "token" - attribute on the the :py:meth:`hvac.adapters.Adapter` instance under the _adapter Client attribute. - :type use_token: bool - :param mount_point: The "path" the azure auth method was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the request. - :rtype: dict - """ - params = { - "role": role, - "jwt": jwt, - } - params.update( - utils.remove_nones( - { - "subscription_id": subscription_id, - "resource_group_name": resource_group_name, - "vm_name": vm_name, - "vmss_name": vmss_name, - } - ) - ) - api_path = utils.format_url( - "/v1/auth/{mount_point}/login", mount_point=mount_point - ) - return self._adapter.login( - url=api_path, - use_token=use_token, - json=params, - ) diff --git a/.venv/lib/python3.12/site-packages/hvac/api/auth_methods/cert.py b/.venv/lib/python3.12/site-packages/hvac/api/auth_methods/cert.py deleted file mode 100644 index e9c832e..0000000 --- a/.venv/lib/python3.12/site-packages/hvac/api/auth_methods/cert.py +++ /dev/null @@ -1,328 +0,0 @@ -#!/usr/bin/env python -"""Cert methods module.""" -import os -import warnings - -from hvac.api.vault_api_base import VaultApiBase -from hvac.utils import validate_pem_format -from hvac import exceptions, utils - - -class Cert(VaultApiBase): - """Cert Auth Method (API). - - Reference: https://www.vaultproject.io/api/auth/cert/index.html - """ - - def create_ca_certificate_role( - self, - name, - certificate="", - certificate_file="", - allowed_common_names="", - allowed_dns_sans="", - allowed_email_sans="", - allowed_uri_sans="", - allowed_organizational_units="", - required_extensions="", - display_name="", - token_ttl=0, - token_max_ttl=0, - token_policies=[], - token_bound_cidrs=[], - token_explicit_max_ttl=0, - token_no_default_policy=False, - token_num_uses=0, - token_period=0, - token_type="", - mount_point="cert", - ): - """Create CA Certificate Role. - - Sets a CA cert and associated parameters in a role name. - - Supported methods: - POST: /auth//certs/:name. Produces: 204 (empty body) - - :param name: The name of the certificate role. - :type name: str - :param certificate: The PEM-format CA certificate. Either certificate or certificate_file is required. - NOTE: Passing a certificate file path with the certificate argument is deprecated and will be dropped in - version 3.0.0 - :type certificate: str - :param certificate_file: File path to the PEM-format CA certificate. Either certificate_file or certificate is - required. - :type certificate_file: str - :param allowed_common_names: Constrain the Common Names in the client certificate with a globbed pattern. Value - is a comma-separated list of patterns. Authentication requires at least one Name matching at least one - pattern. If not set, defaults to allowing all names. - :type allowed_common_names: str | list - :param allowed_dns_sans: Constrain the Alternative Names in the client certificate with a globbed pattern. Value - is a comma-separated list of patterns. Authentication requires at least one DNS matching at least one pattern. - If not set, defaults to allowing all dns. - :type allowed_dns_sans: str | list - :param allowed_email_sans: Constrain the Alternative Names in the client certificate with a globbed pattern. - Value is a comma-separated list of patterns. Authentication requires at least one Email matching at least - one pattern. If not set, defaults to allowing all emails. - :type allowed_email_sans: str | list - :param allowed_uri_sans: Constrain the Alternative Names in the client certificate with a globbed pattern. - Value is a comma-separated list of URI patterns. Authentication requires at least one URI matching at least - one pattern. If not set, defaults to allowing all URIs. - :type allowed_uri_sans: str | list - :param allowed_organizational_units: Constrain the Organizational Units (OU) in the client certificate with a - globbed pattern. Value is a comma-separated list of OU patterns. Authentication requires at least one OU - matching at least one pattern. If not set, defaults to allowing all OUs. - :type allowed_organizational_units: str | list - :param required_extensions: Require specific Custom Extension OIDs to exist and match the pattern. Value is a - comma separated string or array of oid:value. Expects the extension value to be some type of ASN1 encoded - string. All conditions must be met. Supports globbing on value. - :type required_extensions: str | list - :param display_name: The display_name to set on tokens issued when authenticating against this CA certificate. - If not set, defaults to the name of the role. - :type display_name: str | unicode - :param token_ttl: The incremental lifetime for generated tokens. This current value of this will be referenced - at renewal time. - :type token_ttl: int | str - :param token_max_ttl: The maximum lifetime for generated tokens. This current value of this will be referenced - at renewal time. - :type token_max_ttl: int | str - :param token_policies: List of policies to encode onto generated tokens. Depending on the auth method, this list - may be supplemented by user/group/other values. - :type token_policies: list | str - :param token_bound_cidrs: List of CIDR blocks; if set, specifies blocks of IP addresses which can authenticate - successfully, and ties the resulting token to these blocks as well. - :type token_bound_cidrs: list | str - :param token_explicit_max_ttl: If set, will encode an explicit max TTL onto the token. This is a hard cap even - if token_ttl and token_max_ttl would otherwise allow a renewal. - :type token_explicit_max_ttl: int | str - :param token_no_default_policy: If set, the default policy will not be set on generated tokens; otherwise it - will be added to the policies set in token_policies. - :type token_no_default_policy: bool - :param token_num_uses: The maximum number of times a generated token may be used (within its lifetime); 0 means - unlimited. If you require the token to have the ability to create child tokens, you will need to set this value to 0. - :type token_num_uses: int - :param token_period: The period, if any, to set on the token. - :type token_period: int | str - :param token_type: The type of token that should be generated. Can be service, batch, or default to use the - mount's tuned default (which unless changed will be service tokens). For token store roles, there are two - additional possibilities: default-service and default-batch which specify the type to return unless the - client requests a different type at generation time. - :type token_type: str - :param mount_point: - :type mount_point: - """ - if certificate: - try: - utils.validate_pem_format("", certificate) - cert = certificate - except exceptions.ParamValidationError: - with open(certificate) as f_cert: - warnings.warn( - "Passing a certificate file path to `certificate` is deprecated and will be removed in v3.0.0;" - "use `certificate_file` instead. (See https://github.com/hvac/hvac/issues/914)" - ) - cert = f_cert.read() - elif certificate_file: - with open(certificate_file) as f_cert: - cert = f_cert.read() - else: - raise exceptions.ParamValidationError( - "`certificate` or `certificate_file` must be provided" - ) - - params = utils.remove_nones( - { - "name": name, - "certificate": cert, - "allowed_common_names": allowed_common_names, - "allowed_dns_sans": allowed_dns_sans, - "allowed_email_sans": allowed_email_sans, - "allowed_uri_sans": allowed_uri_sans, - "allowed_organizational_units": allowed_organizational_units, - "required_extensions": required_extensions, - "display_name": display_name, - "token_ttl": token_ttl, - "token_max_ttl": token_max_ttl, - "token_policies": token_policies, - "token_bound_cidrs": token_bound_cidrs, - "token_explicit_max_ttl": token_explicit_max_ttl, - "token_no_default_policy": token_no_default_policy, - "token_num_uses": token_num_uses, - "token_period": token_period, - "token_type": token_type, - } - ) - - api_path = "/v1/auth/{mount_point}/certs/{name}".format( - mount_point=mount_point, name=name - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def read_ca_certificate_role(self, name, mount_point="cert"): - """ - Gets information associated with the named role. - - Supported methods: - GET: /auth//certs/{name}. Produces: 200 application/json - - :param name: The name of the certificate role - :type name: str | unicode - :param mount_point: - :type mount_point: - :return: The JSON response of the read_ca_certificate_role request. - :rtype: dict - """ - params = { - "name": name, - } - api_path = "/v1/auth/{mount_point}/certs/{name}".format( - mount_point=mount_point, name=name - ) - return self._adapter.get( - url=api_path, - json=params, - ) - - def list_certificate_roles(self, mount_point="cert"): - """ - Lists configured certificate names. - - Supported methods: - LIST: /auth//certs. Produces: 200 application/json - - :param mount_point: - :type mount_point: - :return: The response of the list_certificate request. - :rtype: requests.Response - """ - api_path = f"/v1/auth/{mount_point}/certs" - return self._adapter.list(url=api_path) - - def delete_certificate_role(self, name, mount_point="cert"): - """ - List existing LDAP existing groups that have been created in this auth method. - - Supported methods: - DELETE: /auth/{mount_point}/groups. Produces: 204 (empty body) - - :param name: The name of the certificate role. - :type name: str | unicode - :param mount_point: - :type mount_point: - """ - api_path = "/v1/auth/{mount_point}/certs/{name}".format( - mount_point=mount_point, name=name - ) - return self._adapter.delete( - url=api_path, - ) - - def configure_tls_certificate(self, mount_point="cert", disable_binding=False): - """ - Configure options for the method. - - Supported methods: - POST: /auth//config. Produces: 204 (empty body) - - - :param disable_binding: If set, during renewal, skips the matching of presented client identity with the client - identity used during login. - :type disable_binding: bool - :param mount_point: - :type mount_point: - """ - params = { - "disable_binding": disable_binding, - } - api_path = f"/v1/auth/{mount_point}/config" - return self._adapter.post( - url=api_path, - json=params, - ) - - def login( - self, - name="", - cacert=False, - cert_pem="", - key_pem="", - mount_point="cert", - use_token=True, - ): - """ - Log in and fetch a token. If there is a valid chain to a CA configured in the method and all role constraints - are matched, a token will be issued. If the certificate has DNS SANs in it, each of those will be verified. - If Common Name is required to be verified, then it should be a fully qualified DNS domain name and must be - duplicated as a DNS SAN - - Supported methods: - POST: /auth//login Produces: 200 application/json - - :param name: Authenticate against only the named certificate role, returning its policy list if successful. If - not set, defaults to trying all certificate roles and returning any one that matches. - :type name: str | unicode - :param cacert: The value used here is for the Vault TLS Listener CA certificate, not the CA that issued the - client authentication certificate. This can be omitted if the CA used to issue the Vault server certificate - is trusted by the local system executing this command. - :type cacert: str | bool - :param cert_pem: Location of the cert.pem used to authenticate the host. - :tupe cert_pem: str | unicode - :param key_pem: Location of the public key.pem used to authenticate the host. - :param key_pem: str | unicode - :param mount_point: - :type mount_point: - :param use_token: If the returned token is stored in the client - :param use_token: bool - :return: The response of the login request. - :rtype: requests.Response - """ - params = {} - if name != "": - params["name"] = name - api_path = f"/v1/auth/{mount_point}/login" - - # Must have cert checking or a CA cert. This is caught lower down but harder to grok - if not cacert: - # If a cacert is not provided try to drop down to the adapter and get the cert there. - # If the cacert is not in the adapter already login will also. - if not self._adapter._kwargs.get("verify"): - raise self.CertificateAuthError( - "cacert must be True, a file_path, or valid CA Certificate." - ) - else: - cacert = self._adapter._kwargs.get("verify") - else: - validate_pem_format("verify", cacert) - # if cert_pem is a string its ready to be used and either has the key with it or the key is provided as an arg - try: - if validate_pem_format("cert_pem", cert_pem): - tls_update = True - except exceptions.ParamValidationError: - tls_update = {} - if not (os.path.exists(cert_pem) or self._adapter._kwargs.get("cert")): - raise FileNotFoundError("Can't find the certificate.") - try: - tls_parts = {"cert_pem": cert_pem, "key_pem": key_pem} - for tls_part in tls_parts: - if tls_parts[tls_part] != "": - tls_update[tls_part] = tls_parts[tls_part] - except ValueError: - tls_update = True - - additional_request_kwargs = {} - if tls_update: - additional_request_kwargs = { - "verify": cacert, - # need to define dict as cert is a tuple - "cert": tuple([cert_pem, key_pem]), - } - - return self._adapter.login( - url=api_path, use_token=use_token, json=params, **additional_request_kwargs - ) - - class CertificateAuthError(Exception): - pass diff --git a/.venv/lib/python3.12/site-packages/hvac/api/auth_methods/gcp.py b/.venv/lib/python3.12/site-packages/hvac/api/auth_methods/gcp.py deleted file mode 100644 index 072c172..0000000 --- a/.venv/lib/python3.12/site-packages/hvac/api/auth_methods/gcp.py +++ /dev/null @@ -1,463 +0,0 @@ -#!/usr/bin/env python -"""GCP methods module.""" -import logging - -from hvac import exceptions, utils -from hvac.api.vault_api_base import VaultApiBase -from hvac.constants.gcp import ALLOWED_ROLE_TYPES, GCP_CERTS_ENDPOINT -from hvac.utils import validate_list_of_strings_param, list_to_comma_delimited - -DEFAULT_MOUNT_POINT = "gcp" - -logger = logging.getLogger(__name__) - - -class Gcp(VaultApiBase): - """Google Cloud Auth Method (API). - - Reference: https://www.vaultproject.io/api/auth/{mount_point}/index.html - """ - - def configure( - self, - credentials=None, - google_certs_endpoint=GCP_CERTS_ENDPOINT, - mount_point=DEFAULT_MOUNT_POINT, - ): - """Configure the credentials required for the GCP auth method to perform API calls to Google Cloud. - - These credentials will be used to query the status of IAM entities and get service account or other Google - public certificates to confirm signed JWTs passed in during login. - - Supported methods: - POST: /auth/{mount_point}/config. Produces: 204 (empty body) - - - :param credentials: A JSON string containing the contents of a GCP credentials file. The credentials file must - have the following permissions: `iam.serviceAccounts.get`, `iam.serviceAccountKeys.get`. - If this value is empty, Vault will try to use Application Default Credentials from the machine on which the - Vault server is running. The project must have the iam.googleapis.com API enabled. - :type credentials: str | unicode - :param google_certs_endpoint: The Google OAuth2 endpoint from which to obtain public certificates. This is used - for testing and should generally not be set by end users. - :type google_certs_endpoint: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - params = utils.remove_nones( - { - "credentials": credentials, - "google_certs_endpoint": google_certs_endpoint, - } - ) - api_path = utils.format_url( - "/v1/auth/{mount_point}/config", mount_point=mount_point - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def read_config(self, mount_point=DEFAULT_MOUNT_POINT): - """Read the configuration, if any, including credentials. - - Supported methods: - GET: /auth/{mount_point}/config. Produces: 200 application/json - - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The data key from the JSON response of the request. - :rtype: dict - """ - api_path = utils.format_url( - "/v1/auth/{mount_point}/config", mount_point=mount_point - ) - response = self._adapter.get( - url=api_path, - ) - return response.get("data") - - def delete_config(self, mount_point=DEFAULT_MOUNT_POINT): - """Delete all GCP configuration data. This operation is idempotent. - - Supported methods: - DELETE: /auth/{mount_point}/config. Produces: 204 (empty body) - - - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url( - "/v1/auth/{mount_point}/config", mount_point=mount_point - ) - return self._adapter.delete( - url=api_path, - ) - - def create_role( - self, - name, - role_type, - project_id, - ttl=None, - max_ttl=None, - period=None, - policies=None, - bound_service_accounts=None, - max_jwt_exp=None, - allow_gce_inference=None, - bound_zones=None, - bound_regions=None, - bound_instance_groups=None, - bound_labels=None, - mount_point=DEFAULT_MOUNT_POINT, - ): - """Register a role in the GCP auth method. - - Role types have specific entities that can perform login operations against this endpoint. Constraints specific - to the role type must be set on the role. These are applied to the authenticated entities attempting to - login. - - Supported methods: - POST: /auth/{mount_point}/role/{name}. Produces: 204 (empty body) - - - :param name: The name of the role. - :type name: str | unicode - :param role_type: The type of this role. Certain fields correspond to specific roles and will be rejected - otherwise. - :type role_type: str | unicode - :param project_id: The GCP project ID. Only entities belonging to this project can authenticate with this role. - :type project_id: str | unicode - :param ttl: The TTL period of tokens issued using this role. This can be specified as an integer number of - seconds or as a duration value like "5m". - :type ttl: str | unicode - :param max_ttl: The maximum allowed lifetime of tokens issued in seconds using this role. This can be specified - as an integer number of seconds or as a duration value like "5m". - :type max_ttl: str | unicode - :param period: If set, indicates that the token generated using this role should never expire. The token should - be renewed within the duration specified by this value. At each renewal, the token's TTL will be set to the - value of this parameter. This can be specified as an integer number of seconds or as a duration value like - "5m". - :type period: str | unicode - :param policies: The list of policies to be set on tokens issued using this role. - :type policies: list - :param bound_service_accounts: A list of service account emails or IDs that login is - restricted to. If set to `*`, all service accounts are allowed (role will still be bound by project). Will be - inferred from service account used to issue metadata token for GCE instances. - :type bound_service_accounts: list - :param max_jwt_exp: The number of seconds past the time of authentication that the login param JWT - must expire within. For example, if a user attempts to login with a token that expires within an hour and - this is set to 15 minutes, Vault will return an error prompting the user to create a new signed JWT with a - shorter exp. The GCE metadata tokens currently do not allow the exp claim to be customized. - :type max_jwt_exp: str | unicode - :param allow_gce_inference: A flag to determine if this role should allow GCE instances to - authenticate by inferring service accounts from the GCE identity metadata token. - :type allow_gce_inference: bool - :param bound_zones: The list of zones that a GCE instance must belong to in order to be - authenticated. If bound_instance_groups is provided, it is assumed to be a zonal group and the group must - belong to this zone. - :type bound_zones: list - :param bound_regions: The list of regions that a GCE instance must belong to in order to be - authenticated. If bound_instance_groups is provided, it is assumed to be a regional group and the group - must belong to this region. If bound_zones are provided, this attribute is ignored. - :type bound_regions: list - :param bound_instance_groups: The instance groups that an authorized instance must belong to in - order to be authenticated. If specified, either bound_zones or bound_regions must be set too. - :type bound_instance_groups: list - :param bound_labels: A list of GCP labels formatted as "key:value" strings that must be set on - authorized GCE instances. Because GCP labels are not currently ACL'd, we recommend that this be used in - conjunction with other restrictions. - :type bound_labels: list - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The data key from the JSON response of the request. - :rtype: requests.Response - """ - type_specific_params = { - "iam": { - "max_jwt_exp": None, - "allow_gce_inference": None, - }, - "gce": { - "bound_zones": None, - "bound_regions": None, - "bound_instance_groups": None, - "bound_labels": None, - }, - } - - list_of_strings_params = { - "policies": policies, - "bound_service_accounts": bound_service_accounts, - "bound_zones": bound_zones, - "bound_regions": bound_regions, - "bound_instance_groups": bound_instance_groups, - "bound_labels": bound_labels, - } - for param_name, param_argument in list_of_strings_params.items(): - validate_list_of_strings_param( - param_name=param_name, - param_argument=param_argument, - ) - - if role_type not in ALLOWED_ROLE_TYPES: - error_msg = 'unsupported role_type argument provided "{arg}", supported types: "{role_types}"' - raise exceptions.ParamValidationError( - error_msg.format( - arg=type, - role_types=",".join(ALLOWED_ROLE_TYPES), - ) - ) - - params = { - "type": role_type, - "project_id": project_id, - "policies": list_to_comma_delimited(policies), - } - params.update( - utils.remove_nones( - { - "ttl": ttl, - "max_ttl": max_ttl, - "period": period, - } - ) - ) - if bound_service_accounts is not None: - params["bound_service_accounts"] = list_to_comma_delimited( - bound_service_accounts - ) - if role_type == "iam": - params.update( - utils.remove_nones( - { - "max_jwt_exp": max_jwt_exp, - "allow_gce_inference": allow_gce_inference, - } - ) - ) - for param, default_arg in type_specific_params["gce"].items(): - if locals().get(param) != default_arg: - warning_msg = 'Argument for parameter "{param}" ignored for role type iam'.format( - param=param - ) - logger.warning(warning_msg) - elif role_type == "gce": - if bound_zones is not None: - params["bound_zones"] = list_to_comma_delimited(bound_zones) - if bound_regions is not None: - params["bound_regions"] = list_to_comma_delimited(bound_regions) - if bound_instance_groups is not None: - params["bound_instance_groups"] = list_to_comma_delimited( - bound_instance_groups - ) - if bound_labels is not None: - params["bound_labels"] = list_to_comma_delimited(bound_labels) - for param, default_arg in type_specific_params["iam"].items(): - if locals().get(param) != default_arg: - warning_msg = 'Argument for parameter "{param}" ignored for role type gce'.format( - param=param - ) - logger.warning(warning_msg) - - api_path = utils.format_url( - "/v1/auth/{mount_point}/role/{name}", - mount_point=mount_point, - name=name, - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def edit_service_accounts_on_iam_role( - self, name, add=None, remove=None, mount_point=DEFAULT_MOUNT_POINT - ): - """Edit service accounts for an existing IAM role in the GCP auth method. - - This allows you to add or remove service accounts from the list of service accounts on the role. - - Supported methods: - POST: /auth/{mount_point}/role/{name}/service-accounts. Produces: 204 (empty body) - - - :param name: The name of an existing iam type role. This will return an error if role is not an iam type role. - :type name: str | unicode - :param add: The list of service accounts to add to the role's service accounts. - :type add: list - :param remove: The list of service accounts to remove from the role's service accounts. - :type remove: list - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - params = utils.remove_nones( - { - "add": add, - "remove": remove, - } - ) - api_path = utils.format_url( - "/v1/auth/{mount_point}/role/{name}/service-accounts", - mount_point=mount_point, - name=name, - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def edit_labels_on_gce_role( - self, name, add=None, remove=None, mount_point=DEFAULT_MOUNT_POINT - ): - """Edit labels for an existing GCE role in the backend. - - This allows you to add or remove labels (keys, values, or both) from the list of keys on the role. - - Supported methods: - POST: /auth/{mount_point}/role/{name}/labels. Produces: 204 (empty body) - - - :param name: The name of an existing gce role. This will return an error if role is not a gce type role. - :type name: str | unicode - :param add: The list of key:value labels to add to the GCE role's bound labels. - :type add: list - :param remove: The list of label keys to remove from the role's bound labels. If any of the specified keys do - not exist, no error is returned (idempotent). - :type remove: list - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The response of the edit_labels_on_gce_role request. - :rtype: requests.Response - """ - params = utils.remove_nones( - { - "add": add, - "remove": remove, - } - ) - api_path = utils.format_url( - "/v1/auth/{mount_point}/role/{name}/labels", - mount_point=mount_point, - name=name, - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def read_role(self, name, mount_point=DEFAULT_MOUNT_POINT): - """Read the previously registered role configuration. - - Supported methods: - GET: /auth/{mount_point}/role/{name}. Produces: 200 application/json - - - :param name: The name of the role to read. - :type name: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The data key from the JSON response of the read_role request. - :rtype: JSON - """ - params = { - "name": name, - } - api_path = utils.format_url( - "/v1/auth/{mount_point}/role/{name}", - mount_point=mount_point, - name=name, - ) - response = self._adapter.get( - url=api_path, - json=params, - ) - return response.get("data") - - def list_roles(self, mount_point=DEFAULT_MOUNT_POINT): - """List all the roles that are registered with the plugin. - - Supported methods: - LIST: /auth/{mount_point}/roles. Produces: 200 application/json - - - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The data key from the JSON response of the request. - :rtype: dict - """ - api_path = utils.format_url( - "/v1/auth/{mount_point}/roles", mount_point=mount_point - ) - response = self._adapter.list( - url=api_path, - ) - return response.get("data") - - def delete_role(self, role, mount_point=DEFAULT_MOUNT_POINT): - """Delete the previously registered role. - - Supported methods: - DELETE: /auth/{mount_point}/role/{role}. Produces: 204 (empty body) - - - :param role: The name of the role to delete. - :type role: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - params = { - "role": role, - } - api_path = utils.format_url( - "/v1/auth/{mount_point}/role/{role}", - mount_point=mount_point, - role=role, - ) - return self._adapter.delete( - url=api_path, - json=params, - ) - - def login(self, role, jwt, use_token=True, mount_point=DEFAULT_MOUNT_POINT): - """Login to retrieve a Vault token via the GCP auth method. - - This endpoint takes a signed JSON Web Token (JWT) and a role name for some entity. It verifies the JWT - signature with Google Cloud to authenticate that entity and then authorizes the entity for the given role. - - Supported methods: - POST: /auth/{mount_point}/login. Produces: 200 application/json - - - :param role: The name of the role against which the login is being attempted. - :type role: str | unicode - :param jwt: A signed JSON web token - :type jwt: str | unicode - :param use_token: if True, uses the token in the response received from the auth request to set the "token" - attribute on the the :py:meth:`hvac.adapters.Adapter` instance under the _adapter Client attribute. - :type use_token: bool - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the request. - :rtype: dict - """ - params = { - "role": role, - "jwt": jwt, - } - api_path = utils.format_url( - "/v1/auth/{mount_point}/login", mount_point=mount_point - ) - return self._adapter.login( - url=api_path, - use_token=use_token, - json=params, - ) diff --git a/.venv/lib/python3.12/site-packages/hvac/api/auth_methods/github.py b/.venv/lib/python3.12/site-packages/hvac/api/auth_methods/github.py deleted file mode 100644 index 165d36e..0000000 --- a/.venv/lib/python3.12/site-packages/hvac/api/auth_methods/github.py +++ /dev/null @@ -1,241 +0,0 @@ -#!/usr/bin/env python -"""Github methods module.""" -from hvac import exceptions, utils -from hvac.api.vault_api_base import VaultApiBase - -DEFAULT_MOUNT_POINT = "github" - - -class Github(VaultApiBase): - """GitHub Auth Method (API). - - Reference: https://www.vaultproject.io/api/auth/github/index.html - """ - - def configure( - self, - organization, - base_url=None, - ttl=None, - max_ttl=None, - mount_point=DEFAULT_MOUNT_POINT, - ): - """Configure the connection parameters for GitHub. - - This path honors the distinction between the create and update capabilities inside ACL policies. - - Supported methods: - POST: /auth/{mount_point}/config. Produces: 204 (empty body) - - - :param organization: The organization users must be part of. - :type organization: str | unicode - :param base_url: The API endpoint to use. Useful if you are running GitHub Enterprise or an API-compatible - authentication server. - :type base_url: str | unicode - :param ttl: Duration after which authentication will be expired. - :type ttl: str | unicode - :param max_ttl: Maximum duration after which authentication will - be expired. - :type max_ttl: 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. - :rtype: requests.Response - """ - params = { - "organization": organization, - } - params.update( - utils.remove_nones( - { - "base_url": base_url, - "ttl": ttl, - "max_ttl": max_ttl, - } - ) - ) - api_path = utils.format_url( - "/v1/auth/{mount_point}/config", - mount_point=mount_point, - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def read_configuration(self, mount_point=DEFAULT_MOUNT_POINT): - """Read the GitHub configuration. - - Supported methods: - GET: /auth/{mount_point}/config. Produces: 200 application/json - - - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the read_configuration request. - :rtype: dict - """ - api_path = utils.format_url( - "/v1/auth/{mount_point}/config", - mount_point=mount_point, - ) - return self._adapter.get(url=api_path) - - def map_team(self, team_name, policies=None, mount_point=DEFAULT_MOUNT_POINT): - """Map a list of policies to a team that exists in the configured GitHub organization. - - Supported methods: - POST: /auth/{mount_point}/map/teams/{team_name}. Produces: 204 (empty body) - - - :param team_name: GitHub team name in "slugified" format - :type team_name: str | unicode - :param policies: Comma separated list of policies to assign - :type policies: List[str] - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The response of the map_github_teams request. - :rtype: requests.Response - """ - # First, perform parameter validation. - if policies is None: - policies = [] - if not isinstance(policies, list) or not all( - isinstance(p, str) for p in policies - ): - error_msg = 'unsupported policies argument provided "{arg}" ({arg_type}), required type: List[str]"' - raise exceptions.ParamValidationError( - error_msg.format( - arg=policies, - arg_type=type(policies), - ) - ) - # Then, perform request. - params = { - "value": ",".join(policies), - } - api_path = utils.format_url( - "/v1/auth/{mount_point}/map/teams/{team_name}", - mount_point=mount_point, - team_name=team_name, - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def read_team_mapping(self, team_name, mount_point=DEFAULT_MOUNT_POINT): - """Read the GitHub team policy mapping. - - Supported methods: - GET: /auth/{mount_point}/map/teams/{team_name}. Produces: 200 application/json - - - :param team_name: GitHub team name - :type team_name: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the read_team_mapping request. - :rtype: dict - """ - api_path = utils.format_url( - "/v1/auth/{mount_point}/map/teams/{team_name}", - mount_point=mount_point, - team_name=team_name, - ) - return self._adapter.get(url=api_path) - - def map_user(self, user_name, policies=None, mount_point=DEFAULT_MOUNT_POINT): - """Map a list of policies to a specific GitHub user exists in the configured organization. - - Supported methods: - POST: /auth/{mount_point}/map/users/{user_name}. Produces: 204 (empty body) - - - :param user_name: GitHub user name - :type user_name: str | unicode - :param policies: Comma separated list of policies to assign - :type policies: List[str] - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The response of the map_github_users request. - :rtype: requests.Response - """ - # First, perform parameter validation. - if policies is None: - policies = [] - if not isinstance(policies, list) or not all( - isinstance(p, str) for p in policies - ): - error_msg = 'unsupported policies argument provided "{arg}" ({arg_type}), required type: List[str]"' - raise exceptions.ParamValidationError( - error_msg.format( - arg=policies, - arg_type=type(policies), - ) - ) - - # Then, perform request. - params = { - "value": ",".join(policies), - } - api_path = utils.format_url( - "/v1/auth/{mount_point}/map/users/{user_name}", - mount_point=mount_point, - user_name=user_name, - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def read_user_mapping(self, user_name, mount_point=DEFAULT_MOUNT_POINT): - """Read the GitHub user policy mapping. - - Supported methods: - GET: /auth/{mount_point}/map/users/{user_name}. Produces: 200 application/json - - - :param user_name: GitHub user name - :type user_name: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the read_user_mapping request. - :rtype: dict - """ - api_path = utils.format_url( - "/v1/auth/{mount_point}/map/users/{user_name}", - mount_point=mount_point, - user_name=user_name, - ) - return self._adapter.get(url=api_path) - - def login(self, token, use_token=True, mount_point=DEFAULT_MOUNT_POINT): - """Login using GitHub access token. - - Supported methods: - POST: /auth/{mount_point}/login. Produces: 200 application/json - - - :param token: GitHub personal API token. - :type token: str | unicode - :param use_token: if True, uses the token in the response received from the auth request to set the "token" - attribute on the the :py:meth:`hvac.adapters.Adapter` instance under the _adapter Client attribute. - :type use_token: bool - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the login request. - :rtype: dict - """ - params = { - "token": token, - } - api_path = utils.format_url( - "/v1/auth/{mount_point}/login", mount_point=mount_point - ) - return self._adapter.login( - url=api_path, - use_token=use_token, - json=params, - ) diff --git a/.venv/lib/python3.12/site-packages/hvac/api/auth_methods/jwt.py b/.venv/lib/python3.12/site-packages/hvac/api/auth_methods/jwt.py deleted file mode 100644 index 8acc59b..0000000 --- a/.venv/lib/python3.12/site-packages/hvac/api/auth_methods/jwt.py +++ /dev/null @@ -1,457 +0,0 @@ -#!/usr/bin/env python -"""JWT/OIDC methods module.""" -from hvac import utils -from hvac.api.vault_api_base import VaultApiBase - - -class JWT(VaultApiBase): - """JWT auth method which can be used to authenticate with Vault by providing a JWT. - - The OIDC method allows authentication via a configured OIDC provider using the user's web browser. - This method may be initiated from the Vault UI or the command line. Alternatively, a JWT can be provided directly. - The JWT is cryptographically verified using locally-provided keys, or, if configured, an OIDC Discovery service can - be used to fetch the appropriate keys. The choice of method is configured per role. - - Reference: https://www.vaultproject.io/api/auth/jwt - """ - - DEFAULT_PATH = "jwt" - - def resolve_path(self, path): - """Return the class's default path if no explicit path is specified. - - :param path: The "path" the method/backend was mounted on. - :type path: str | unicode - :return: The default path for this auth method if no explicit path is specified. - :rtype: str - """ - return path if path is not None else self.DEFAULT_PATH - - def configure( - self, - oidc_discovery_url=None, - oidc_discovery_ca_pem=None, - oidc_client_id=None, - oidc_client_secret=None, - oidc_response_mode=None, - oidc_response_types=None, - jwks_url=None, - jwks_ca_pem=None, - jwt_validation_pubkeys=None, - bound_issuer=None, - jwt_supported_algs=None, - default_role=None, - provider_config=None, - path=None, - namespace_in_state=None, - ): - """Configure the validation information to be used globally across all roles. - - One (and only one) of oidc_discovery_url and jwt_validation_pubkeys must be set. - - Supported methods: - POST: /auth/{path}/config. - - :param oidc_discovery_url: The OIDC Discovery URL, without any .well-known component (base path). Cannot be - used with "jwks_url" or "jwt_validation_pubkeys". - :type oidc_discovery_url: str | unicode - :param oidc_discovery_ca_pem: The CA certificate or chain of certificates, in PEM format, to use to validate - connections to the OIDC Discovery URL. If not set, system certificates are used. - :type oidc_discovery_ca_pem: str | unicode - :param oidc_client_id: The OAuth Client ID from the provider for OIDC roles. - :type oidc_client_id: str | unicode - :param oidc_client_secret: The OAuth Client Secret from the provider for OIDC roles. - :type oidc_client_secret: str | unicode - :param oidc_response_mode: The response mode to be used in the OAuth2 request. Allowed values are "query" and - form_post". Defaults to "query". - :type oidc_response_mode: str | unicode - :param oidc_response_types: The response types to request. Allowed values are "code" and "id_token". Defaults - to "code". Note: "id_token" may only be used if "oidc_response_mode" is set to "form_post". - :type oidc_response_types: str | unicode - :param jwks_url: JWKS URL to use to authenticate signatures. Cannot be used with "oidc_discovery_url" or - "jwt_validation_pubkeys". - :type jwks_url: str | unicode - :param jwks_ca_pem: The CA certificate or chain of certificates, in PEM format, to use to validate connections - to the JWKS URL. If not set, system certificates are used. - :type jwks_ca_pem: str | unicode - :param jwt_validation_pubkeys: A list of PEM-encoded public keys to use to authenticate signatures locally. - Cannot be used with "jwks_url" or "oidc_discovery_url". - :type jwt_validation_pubkeys: str | unicode - :param bound_issuer: in a JWT. - :type bound_issuer: str | unicode - :param jwt_supported_algs: A list of supported signing algorithms. Defaults to [RS256]. - :type jwt_supported_algs: str | unicode - :param default_role: The default role to use if none is provided during login. - :type default_role: str | unicode - :param provider_config: TypeError - :type provider_config: map - :param path: The "path" the method/backend was mounted on. - :type path: str | unicode - :param namespace_in_state: With this setting, the allowed redirect URL(s) in Vault and on the provider side - should not contain a namespace query parameter. - :type namespace_in_state: bool - :return: The response of the configure request. - :rtype: requests.Response - """ - params = utils.remove_nones( - { - "oidc_discovery_url": oidc_discovery_url, - "oidc_discovery_ca_pem": oidc_discovery_ca_pem, - "oidc_client_id": oidc_client_id, - "oidc_client_secret": oidc_client_secret, - "oidc_response_mode": oidc_response_mode, - "oidc_response_types": oidc_response_types, - "jwks_url": jwks_url, - "jwks_ca_pem": jwks_ca_pem, - "jwt_validation_pubkeys": jwt_validation_pubkeys, - "bound_issuer": bound_issuer, - "jwt_supported_algs": jwt_supported_algs, - "default_role": default_role, - "provider_config": provider_config, - "namespace_in_state": namespace_in_state, - } - ) - api_path = utils.format_url( - "/v1/auth/{path}/config", - path=self.resolve_path(path), - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def read_config(self, path=None): - """Read the previously configured config. - - Supported methods: - GET: /auth/{path}/config. - - :return: The response of the read_config request. - :rtype: dict - """ - api_path = utils.format_url( - "/v1/auth/{path}/config", - path=self.resolve_path(path), - ) - return self._adapter.get( - url=api_path, - ) - - def create_role( - self, - name, - user_claim, - allowed_redirect_uris, - role_type="jwt", - bound_audiences=None, - clock_skew_leeway=None, - expiration_leeway=None, - not_before_leeway=None, - bound_subject=None, - bound_claims=None, - groups_claim=None, - claim_mappings=None, - oidc_scopes=None, - bound_claims_type="string", - verbose_oidc_logging=False, - token_ttl=None, - token_max_ttl=None, - token_policies=None, - token_bound_cidrs=None, - token_explicit_max_ttl=None, - token_no_default_policy=None, - token_num_uses=None, - token_period=None, - token_type=None, - path=None, - user_claim_json_pointer=None, - ): - """Register a role in the JWT method. - - Role types have specific entities that can perform login operations against this endpoint. Constraints - specific to the role type must be set on the role. These are applied to the authenticated entities - attempting to login. At least one of the bound values must be set. - - Supported methods: - POST: /auth/{path}/role/:name. - - :param name: Name of the role. - :type name: str | unicode - :param role_type: Type of role, either "oidc" or "jwt" (default). - :type role_type: str | unicode - :param bound_audiences: List of aud claims to match against. Any match is sufficient. - Required for "jwt" roles, optional for "oidc" roles. - :type bound_audiences: list - :param user_claim: The claim to use to uniquely identify the user; this will be used as the name for the - Identity entity alias created due to a successful login. The interpretation of the user claim - is configured with ``user_claim_json_pointer``. If set to ``True``, ``user_claim`` supports JSON pointer syntax - for referencing a claim. The claim value must be a string. - :type user_claim: str | unicode - :param clock_skew_leeway: Only applicable with "jwt" roles. - :type clock_skew_leeway: int - :param expiration_leeway: Only applicable with "jwt" roles. - :type expiration_leeway: int - :param not_before_leeway: Only applicable with "jwt" roles. - :type not_before_leeway: int - :param bound_subject: If set, requires that the sub claim matches this value. - :type bound_subject: str | unicode - :param bound_claims: If set, a dict of claims (keys) to match against respective claim values (values). - The expected value may be a single string or a list of strings. The interpretation of the bound claim - values is configured with bound_claims_type. Keys support JSON pointer syntax for referencing claims. - :type bound_claims: dict - :param groups_claim: The claim to use to uniquely identify the set of groups to which the user belongs; this - will be used as the names for the Identity group aliases created due to a successful login. The claim value - must be a list of strings. Supports JSON pointer syntax for referencing claims. - :type groups_claim: str | unicode - :param claim_mappings: If set, a map of claims (keys) to be copied to specified metadata fields (values). Keys - support JSON pointer syntax for referencing claims. - :type claim_mappings: map - :param oidc_scopes: If set, a list of OIDC scopes to be used with an OIDC role. - The standard scope "openid" is automatically included and need not be specified. - :type oidc_scopes: list - :param allowed_redirect_uris: The list of allowed values for redirect_uri - during OIDC logins. - :type allowed_redirect_uris: list - :param bound_claims_type: Configures the interpretation of the bound_claims values. If "string" (the default), - the values will treated as string literals and must match exactly. If set to "glob", the values will be - interpreted as globs, with * matching any number of characters. - :type bound_claims_type: str | unicode - :param verbose_oidc_logging: Log received OIDC tokens and claims when debug-level - logging is active. Not recommended in production since sensitive information may be present - in OIDC responses. - :type verbose_oidc_logging: bool - :param token_ttl: The incremental lifetime for generated tokens. This current value of this will be referenced - at renewal time. - :type token_ttl: int | str - :param token_max_ttl: The maximum lifetime for generated tokens. This current value of this will be referenced - at renewal time. - :type token_max_ttl: int | str - :param token_policies: List of policies to encode onto generated tokens. Depending on the auth method, this - list may be supplemented by user/group/other values. - :type token_policies: list[str] - :param token_bound_cidrs: List of CIDR blocks; if set, specifies blocks of IP addresses which can authenticate - successfully, and ties the resulting token to these blocks as well. - :type token_bound_cidrs: list[str] - :param token_explicit_max_ttl: If set, will encode an explicit max TTL onto the token. This is a hard cap - even if token_ttl and token_max_ttl would otherwise allow a renewal. - :type token_explicit_max_ttl: int | str - :param token_no_default_policy: If set, the default policy will not be set on generated tokens; otherwise it - will be added to the policies set in token_policies. - :type token_no_default_policy: bool - :param token_num_uses: The maximum number of times a generated token may be used (within its lifetime); 0 means - unlimited. If you require the token to have the ability to create child tokens, you will need to set this - value to 0. - :type token_num_uses: str | unicode - :param token_period: The period, if any, to set on the token. - :type token_period: int | str - :param token_type: The type of token that should be generated. Can be service, batch, or default. - :type token_type: str - :param path: The "path" the method/backend was mounted on. - :type path: str | unicode - :param user_claim_json_pointer: Specifies if the ``user_claim`` value uses JSON pointer syntax for referencing claims. - By default, the ``user_claim`` value will not use JSON pointer. - :type user_claim_json_pointer: bool - :return: The response of the create_role request. - :rtype: dict - """ - params = utils.remove_nones( - { - "name": name, - "role_type": role_type, - "bound_audiences": bound_audiences, - "user_claim": user_claim, - "clock_skew_leeway": clock_skew_leeway, - "expiration_leeway": expiration_leeway, - "not_before_leeway": not_before_leeway, - "bound_subject": bound_subject, - "bound_claims": bound_claims, - "groups_claim": groups_claim, - "claim_mappings": claim_mappings, - "oidc_scopes": oidc_scopes, - "allowed_redirect_uris": allowed_redirect_uris, - "bound_claims_type": bound_claims_type, - "verbose_oidc_logging": verbose_oidc_logging, - "token_ttl": token_ttl, - "token_max_ttl": token_max_ttl, - "token_policies": token_policies, - "token_bound_cidrs": token_bound_cidrs, - "token_explicit_max_ttl": token_explicit_max_ttl, - "token_no_default_policy": token_no_default_policy, - "token_num_uses": token_num_uses, - "token_period": token_period, - "token_type": token_type, - "user_claim_json_pointer": user_claim_json_pointer, - } - ) - api_path = utils.format_url( - "/v1/auth/{path}/role/{name}", - path=self.resolve_path(path), - name=name, - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def read_role(self, name, path=None): - """Read the previously registered role configuration. - - Supported methods: - GET: /auth/{path}/role/:name. - - :param name: Name of the role. - :type name: str | unicode - :param path: The "path" the method/backend was mounted on. - :type path: str | unicode - :return: The response of the read_role request. - :rtype: dict - """ - api_path = utils.format_url( - "/v1/auth/{path}/role/{name}", - path=self.resolve_path(path), - name=name, - ) - return self._adapter.get( - url=api_path, - ) - - def list_roles(self, path=None): - """List all the roles that are registered with the plugin. - - Supported methods: - LIST: /auth/{path}/role. - - :param path: The "path" the method/backend was mounted on. - :type path: str | unicode - :return: The response of the list_roles request. - :rtype: dict - """ - api_path = utils.format_url( - "/v1/auth/{path}/role", - path=self.resolve_path(path), - ) - return self._adapter.list( - url=api_path, - ) - - def delete_role(self, name, path=None): - """Delete the previously registered role. - - Supported methods: - DELETE: /auth/{path}/role/:name. - - :param name: Name of the role. - :type name: str | unicode - :param path: The "path" the method/backend was mounted on. - :type path: str | unicode - :return: The response of the delete_role request. - :rtype: requests.Response - """ - api_path = utils.format_url( - "/v1/auth/{path}/role/{name}", - path=self.resolve_path(path), - name=name, - ) - return self._adapter.delete( - url=api_path, - ) - - def oidc_authorization_url_request(self, role, redirect_uri, path=None): - """Obtain an authorization URL from Vault to start an OIDC login flow. - - Supported methods: - POST: /auth/{path}/auth_url. - - :param role: not provided. - :type role: str | unicode - :param redirect_uri: more information. - :type redirect_uri: str | unicode - :param path: The "path" the method/backend was mounted on. - :type path: str | unicode - :return: The response of the _authorization_url_request request. - :rtype: requests.Response - """ - params = { - "role": role, - "redirect_uri": redirect_uri, - } - api_path = utils.format_url( - "/v1/auth/{path}/oidc/auth_url", - path=self.resolve_path(path), - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def oidc_callback(self, state, nonce, code, path=None): - """Exchange an authorization code for an OIDC ID Token. - - The ID token will be further validated against any bound claims, and if valid a Vault token will be returned. - - Supported methods: - GET: /auth/{path}/callback. - - :param state: Opaque state ID that is part of the Authorization URL and will - be included in the the redirect following successful authentication on the provider. - :type state: str | unicode - :param nonce: Opaque nonce that is part of the Authorization URL and will - be included in the the redirect following successful authentication on the provider. - :type nonce: str | unicode - :param code: Provider-generated authorization code that Vault will exchange for - an ID token. - :type code: str | unicode - :param path: The "path" the method/backend was mounted on. - :type path: str | unicode - :return: The response of the _callback request. - :rtype: requests.Response - """ - params = { - "state": state, - "nonce": nonce, - "code": code, - } - api_path = utils.format_url( - "/v1/auth/{path}/oidc/callback?state={state}&nonce={nonce}&code={code}", - path=self.resolve_path(path), - state=state, - nonce=nonce, - code=code, - ) - return self._adapter.get( - url=api_path, - json=params, - ) - - def jwt_login(self, role, jwt, use_token=True, path=None): - """Fetch a token. - - This endpoint takes a signed JSON Web Token (JWT) and a role name for some entity. - It verifies the JWT signature to authenticate that entity and then authorizes the - entity for the given role. - - Supported methods: - POST: /auth/{path}/login. - - :param role: not provided. - :type role: str | unicode - :param jwt: Signed JSON Web Token (JWT). - :type jwt: str | unicode - :param path: The "path" the method/backend was mounted on. - :type path: str | unicode - :return: The response of the jwt_login request. - :rtype: requests.Response - """ - params = { - "role": role, - "jwt": jwt, - } - api_path = utils.format_url( - "/v1/auth/{path}/login", - path=self.resolve_path(path), - ) - return self._adapter.login( - url=api_path, - use_token=use_token, - json=params, - ) diff --git a/.venv/lib/python3.12/site-packages/hvac/api/auth_methods/kubernetes.py b/.venv/lib/python3.12/site-packages/hvac/api/auth_methods/kubernetes.py deleted file mode 100644 index 26e99b4..0000000 --- a/.venv/lib/python3.12/site-packages/hvac/api/auth_methods/kubernetes.py +++ /dev/null @@ -1,308 +0,0 @@ -#!/usr/bin/env python -"""Kubernetes methods module.""" -from hvac import utils -from hvac.api.vault_api_base import VaultApiBase -from hvac.utils import ( - validate_list_of_strings_param, - comma_delimited_to_list, - validate_pem_format, -) - -DEFAULT_MOUNT_POINT = "kubernetes" - - -class Kubernetes(VaultApiBase): - """Kubernetes Auth Method (API). - - 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, - issuer=None, - mount_point=DEFAULT_MOUNT_POINT, - disable_local_ca_jwt=False, - ): - """Configure the connection parameters for Kubernetes. - - This path honors the distinction between the create and update capabilities inside ACL policies. - - Supported methods: - POST: /auth/{mount_point}/config. Produces: 204 (empty body) - - :param kubernetes_host: Host must be a host string, a host:port pair, or a URL to the base of the - Kubernetes API server. Example: https://k8s.example.com:443 - :type kubernetes_host: str | unicode - :param kubernetes_ca_cert: PEM encoded CA cert for use by the TLS client used to talk with the Kubernetes API. - NOTE: Every line must end with a newline: \n - :type kubernetes_ca_cert: str | unicode - :param token_reviewer_jwt: A service account JWT used to access the TokenReview API to validate other - JWTs during login. If not set the JWT used for login will be used to access the API. - :type token_reviewer_jwt: str | unicode - :param pem_keys: Optional list of PEM-formatted public keys or certificates used to verify the signatures of - 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 - :param disable_local_ca_jwt: Disable defaulting to the local CA cert and service account JWT - :type disable_local_ca_jwt: bool - :return: The response of the configure_method request. - :rtype: requests.Response - """ - list_of_pem_params = { - "kubernetes_ca_cert": kubernetes_ca_cert, - "pem_keys": pem_keys, - } - for param_name, param_argument in list_of_pem_params.items(): - if param_argument is not None: - validate_pem_format( - param_name=param_name, - param_argument=param_argument, - ) - - params = { - "kubernetes_host": kubernetes_host, - "disable_local_ca_jwt": disable_local_ca_jwt, - } - params.update( - utils.remove_nones( - { - "kubernetes_ca_cert": kubernetes_ca_cert, - "token_reviewer_jwt": token_reviewer_jwt, - "pem_keys": pem_keys, - "issuer": issuer, - } - ) - ) - api_path = utils.format_url( - "/v1/auth/{mount_point}/config", mount_point=mount_point - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def read_config(self, mount_point=DEFAULT_MOUNT_POINT): - """Return the previously configured config, including credentials. - - Supported methods: - GET: /auth/{mount_point}/config. Produces: 200 application/json - - :param mount_point: The "path" the kubernetes auth method was mounted on. - :type mount_point: str | unicode - :return: The data key from the JSON response of the request. - :rtype: dict - """ - api_path = utils.format_url( - "/v1/auth/{mount_point}/config", mount_point=mount_point - ) - response = self._adapter.get( - url=api_path, - ) - return response.get("data") - - def create_role( - self, - name, - bound_service_account_names, - bound_service_account_namespaces, - ttl=None, - max_ttl=None, - period=None, - policies=None, - token_type="", - mount_point=DEFAULT_MOUNT_POINT, - alias_name_source=None, - ): - """Create a role in the method. - - Registers a role in the auth method. Role types have specific entities that can perform login operations - against this endpoint. Constraints specific to the role type must be set on the role. These are applied to - the authenticated entities attempting to login. - - Supported methods: - POST: /auth/{mount_point}/role/{name}. Produces: 204 (empty body) - - :param name: Name of the role. - :type name: str | unicode - :param bound_service_account_names: List of service account names able to access this role. If set to "*" - all names are allowed. - :type bound_service_account_names: list | str | unicode - :param bound_service_account_namespaces: List of namespaces allowed to access this role. If set to "*" all - namespaces are allowed. - :type bound_service_account_namespaces: list | str | unicode - :param ttl: The TTL period of tokens issued using this role in seconds. - :type ttl: str | unicode - :param max_ttl: The maximum allowed lifetime of tokens issued in seconds using this role. - :type max_ttl: str | unicode - :param period: If set, indicates that the token generated using this role should never expire. The token should - be renewed within the duration specified by this value. At each renewal, the token's TTL will be set to the - value of this parameter. - :type period: str | unicode - :param policies: Policies to be set on tokens issued using this role. - :type policies: list | str | unicode - :param token_type: The type of token that should be generated. Can be service, batch, or default to use the - mount's tuned default (which unless changed will be service tokens). For token store roles, there are two - additional possibilities: default-service and default-batch which specify the type to return unless the - client requests a different type at generation time. - :type token_type: str - :param mount_point: The "path" the kubernetes auth method was mounted on. - :type mount_point: str | unicode - :param alias_name_source: Configures how identity aliases are generated. - Valid choices are: serviceaccount_uid, serviceaccount_name. - :type alias_name_source: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - list_of_strings_params = { - "bound_service_account_names": bound_service_account_names, - "bound_service_account_namespaces": bound_service_account_namespaces, - "policies": policies, - } - for param_name, param_argument in list_of_strings_params.items(): - validate_list_of_strings_param( - param_name=param_name, - param_argument=param_argument, - ) - - params = { - "bound_service_account_names": comma_delimited_to_list( - bound_service_account_names - ), - "bound_service_account_namespaces": comma_delimited_to_list( - bound_service_account_namespaces - ), - } - if alias_name_source is not None: - params["alias_name_source"] = alias_name_source - - params.update( - utils.remove_nones( - { - "ttl": ttl, - "max_ttl": max_ttl, - "period": period, - } - ) - ) - if policies is not None: - params["policies"] = comma_delimited_to_list(policies) - - if token_type: - params["token_type"] = token_type - - api_path = utils.format_url( - "/v1/auth/{mount_point}/role/{name}", mount_point=mount_point, name=name - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def read_role(self, name, mount_point=DEFAULT_MOUNT_POINT): - """Returns the previously registered role configuration. - - Supported methods: - POST: /auth/{mount_point}/role/{name}. Produces: 200 application/json - - :param name: Name of the role. - :type name: str | unicode - :param mount_point: The "path" the kubernetes auth method was mounted on. - :type mount_point: str | unicode - :return: The "data" key from the JSON response of the request. - :rtype: dict - """ - api_path = utils.format_url( - "/v1/auth/{mount_point}/role/{name}", - mount_point=mount_point, - name=name, - ) - response = self._adapter.get( - url=api_path, - ) - return response.get("data") - - def list_roles(self, mount_point=DEFAULT_MOUNT_POINT): - """List all the roles that are registered with the plugin. - - Supported methods: - LIST: /auth/{mount_point}/role. Produces: 200 application/json - - :param mount_point: The "path" the kubernetes auth method was mounted on. - :type mount_point: str | unicode - :return: The "data" key from the JSON response of the request. - :rtype: dict - """ - api_path = utils.format_url( - "/v1/auth/{mount_point}/role", mount_point=mount_point - ) - response = self._adapter.list( - url=api_path, - ) - return response.get("data") - - def delete_role(self, name, mount_point=DEFAULT_MOUNT_POINT): - """Delete the previously registered role. - - Supported methods: - DELETE: /auth/{mount_point}/role/{name}. Produces: 204 (empty body) - - - :param name: Name of the role. - :type name: str | unicode - :param mount_point: The "path" the kubernetes auth method was mounted on. - :type mount_point: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url( - "/v1/auth/{mount_point}/role/{name}", - mount_point=mount_point, - name=name, - ) - return self._adapter.delete( - url=api_path, - ) - - def login(self, role, jwt, use_token=True, mount_point=DEFAULT_MOUNT_POINT): - """Fetch a token. - - This endpoint takes a signed JSON Web Token (JWT) and a role name for some entity. It verifies the JWT signature - to authenticate that entity and then authorizes the entity for the given role. - - Supported methods: - POST: /auth/{mount_point}/login. Produces: 200 application/json - - :param role: Name of the role against which the login is being attempted. - :type role: str | unicode - :param jwt: Signed JSON Web Token (JWT) from Kubernetes service account. - :type jwt: str | unicode - :param use_token: if True, uses the token in the response received from the auth request to set the "token" - attribute on the the :py:meth:`hvac.adapters.Adapter` instance under the _adapter Client attribute. - :type use_token: bool - :param mount_point: The "path" the kubernetes auth method was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the request. - :rtype: dict - """ - params = { - "role": role, - "jwt": jwt, - } - - api_path = utils.format_url( - "/v1/auth/{mount_point}/login", mount_point=mount_point - ) - response = self._adapter.login( - url=api_path, - use_token=use_token, - json=params, - ) - return response diff --git a/.venv/lib/python3.12/site-packages/hvac/api/auth_methods/ldap.py b/.venv/lib/python3.12/site-packages/hvac/api/auth_methods/ldap.py deleted file mode 100644 index 8faeaa9..0000000 --- a/.venv/lib/python3.12/site-packages/hvac/api/auth_methods/ldap.py +++ /dev/null @@ -1,541 +0,0 @@ -#!/usr/bin/env python -"""LDAP methods module.""" -from hvac import exceptions, utils -from hvac.api.vault_api_base import VaultApiBase - -DEFAULT_MOUNT_POINT = "ldap" - - -class Ldap(VaultApiBase): - """LDAP Auth Method (API). - - Reference: https://www.vaultproject.io/api/auth/ldap/index.html - """ - - @utils.aliased_parameter( - "userdn", "user_dn", removed_in_version="3.0.0", position=1 - ) - @utils.aliased_parameter( - "groupdn", "group_dn", removed_in_version="3.0.0", position=2 - ) - @utils.aliased_parameter( - "binddn", "bind_dn", removed_in_version="3.0.0", position=10 - ) - @utils.aliased_parameter( - "bindpass", "bind_pass", removed_in_version="3.0.0", position=11 - ) - @utils.aliased_parameter( - "userattr", "user_attr", removed_in_version="3.0.0", position=12 - ) - @utils.aliased_parameter( - "discoverdn", "discover_dn", removed_in_version="3.0.0", position=13 - ) - @utils.aliased_parameter( - "upndomain", "upn_domain", removed_in_version="3.0.0", position=15 - ) - @utils.aliased_parameter( - "groupfilter", "group_filter", removed_in_version="3.0.0", position=16 - ) - @utils.aliased_parameter( - "groupattr", "group_attr", removed_in_version="3.0.0", position=17 - ) - def configure( - self, - userdn=None, - groupdn=None, - url=None, - case_sensitive_names=None, - starttls=None, - tls_min_version=None, - tls_max_version=None, - insecure_tls=None, - certificate=None, - binddn=None, - bindpass=None, - userattr=None, - discoverdn=None, - deny_null_bind=True, - upndomain=None, - groupfilter=None, - groupattr=None, - use_token_groups=None, - token_ttl=None, - token_max_ttl=None, - mount_point=DEFAULT_MOUNT_POINT, - *, - anonymous_group_search=None, - client_tls_cert=None, - client_tls_key=None, - connection_timeout=None, - dereference_aliases=None, - max_page_size=None, - request_timeout=None, - token_bound_cidrs=None, - token_explicit_max_ttl=None, - token_no_default_policy=None, - token_num_uses=None, - token_period=None, - token_policies=None, - token_type=None, - userfilter=None, - username_as_alias=None, - ): - """ - Configure the LDAP auth method. - - Supported methods: - POST: /auth/{mount_point}/config. Produces: 204 (empty body) - - :param anonymous_group_search: Use anonymous binds when performing LDAP group searches (note: even when true, - the initial credentials will still be used for the initial connection test). - :type anonymous_group_search: bool - :param client_tls_cert: Client certificate to provide to the LDAP server, must be x509 PEM encoded. - :type client_tls_cert: str | unicode - :param client_tls_key: Client certificate key to provide to the LDAP server, must be x509 PEM encoded. - :type client_tls_key: str | unicode - :param connection_timeout: Timeout, in seconds, when attempting to connect to the LDAP server before trying the - next URL in the configuration. - :type connection_timeout: int - :param dereference_aliases: When aliases should be dereferenced on search operations. - Accepted values are 'never', 'finding', 'searching', 'always'. - :type dereference_aliases: str | unicode - :param max_page_size: If set to a value greater than 0, the LDAP backend will use the LDAP server's paged search - control to request pages of up to the given size. - :type max_page_size: int - :param request_timeout: Timeout, in seconds, for the connection when making requests against the server before - returning back an error. - :type request_timeout: str | unicode - :param token_bound_cidrs: List of CIDR blocks; if set, specifies blocks of IP addresses which can authenticate - successfully, and ties the resulting token to these blocks as well. - :type token_bound_cidrs: list - :param token_explicit_max_ttl: If set, will encode an explicit max TTL onto the token. This is a hard cap even - if token_ttl and token_max_ttl would otherwise allow a renewal. - :type token_explicit_max_ttl: str | unicode - :param token_no_default_policy: If set, the default policy will not be set on generated tokens; otherwise it - will be added to the policies set in token_policies. - :type token_no_default_policy: bool - :param token_num_uses: The maximum number of times a generated token may be used (within its lifetime); 0 means - unlimited. - :type token_num_uses: int - :param token_period: The maximum allowed period value when a periodic token is requested from this role. - :type token_period: str | unicode - :param token_policies: List of token policies to encode onto generated tokens. - :type token_policies: list - :param token_type: The type of token that should be generated. - :type token_type: str | unicode - :param userfilter: An optional LDAP user search filter. - :type userfilter: str | unicode - :param username_as_alias: If set to true, forces the auth method to use the username passed by the user as the - alias name. - :type username_as_alias: bool - :param userdn: Base DN under which to perform user search. Example: ou=Users,dc=example,dc=com - :type userdn: str | unicode - :param user_dn: Alias for userdn. This alias will be removed in v3.0.0. - :type user_dn: str | unicode - :param groupdn: LDAP search base to use for group membership search. This can be the root containing either - groups or users. Example: ou=Groups,dc=example,dc=com - :type groupdn: str | unicode - :param group_dn: Alias for groupdn. This alias will be removed in v3.0.0. - :type group_dn: str | unicode - :param url: The LDAP server to connect to. Examples: ldap://ldap.myorg.com, ldaps://ldap.myorg.com:636. - Multiple URLs can be specified with commas, e.g. ldap://ldap.myorg.com,ldap://ldap2.myorg.com; these will be - tried in-order. - :type url: str | unicode - :param case_sensitive_names: If set, user and group names assigned to policies within the backend will be case - sensitive. Otherwise, names will be normalized to lower case. Case will still be preserved when sending the - username to the LDAP server at login time; this is only for matching local user/group definitions. - :type case_sensitive_names: bool - :param starttls: If true, issues a StartTLS command after establishing an unencrypted connection. - :type starttls: bool - :param tls_min_version: Minimum TLS version to use. Accepted values are tls10, tls11 or tls12. - :type tls_min_version: str | unicode - :param tls_max_version: Maximum TLS version to use. Accepted values are tls10, tls11 or tls12. - :type tls_max_version: str | unicode - :param insecure_tls: If true, skips LDAP server SSL certificate verification - insecure, use with caution! - :type insecure_tls: bool - :param certificate: CA certificate to use when verifying LDAP server certificate, must be x509 PEM encoded. - :type certificate: str | unicode - :param binddn: Distinguished name of object to bind when performing user search. Example: - cn=vault,ou=Users,dc=example,dc=com - :type binddn: str | unicode - :param bind_dn: Alias for binddn. This alias will be removed in v3.0.0. - :type bind_dn: str | unicode - :param bindpass: Password to use along with binddn when performing user search. - :type bindpass: str | unicode - :param bind_pass: Alias for bindpass. This alias will be removed in v3.0.0. - :type bind_pass: str | unicode - :param userattr: Attribute on user attribute object matching the username passed when authenticating. Examples: - sAMAccountName, cn, uid - :type userattr: str | unicode - :param user_attr: Alias for userattr. This alias will be removed in v3.0.0. - :type user_attr: str | unicode - :param discoverdn: Use anonymous bind to discover the bind DN of a user. - :type discoverdn: bool - :param discover_dn: Alias for discoverdn. This alias will be removed in v3.0.0. - :type discover_dn: bool - :param deny_null_bind: This option prevents users from bypassing authentication when providing an empty password. - :type deny_null_bind: bool - :param upndomain: The userPrincipalDomain used to construct the UPN string for the authenticating user. The - constructed UPN will appear as [username]@UPNDomain. Example: example.com, which will cause vault to bind as - username@example.com. - :type upndomain: str | unicode - :param upn_domain: Alias for upndomain. This alias will be removed in v3.0.0. - :type upn_domain: str | unicode - :param groupfilter: Go template used when constructing the group membership query. The template can access the - following context variables: [UserDN, Username]. The default is - `(|(memberUid={{.Username}})(member={{.UserDN}})(uniqueMember={{.UserDN}}))`, which is compatible with several - common directory schemas. To support nested group resolution for Active Directory, instead use the following - query: (&(objectClass=group)(member:1.2.840.113556.1.4.1941:={{.UserDN}})). - :type groupfilter: str | unicode - :param group_filter: Alias for groupfilter. This alias will be removed in v3.0.0. - :type group_filter: str | unicode - :param groupattr: LDAP attribute to follow on objects returned by groupfilter in order to enumerate user group - membership. Examples: for groupfilter queries returning group objects, use: cn. For queries returning user - objects, use: memberOf. The default is cn. - :type groupattr: str | unicode - :param group_attr: Alias for groupattr. This alias will be removed in v3.0.0. - :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 token_ttl: The incremental lifetime for generated tokens. - :type token_ttl: str | unicode - :param token_max_ttl: The maximum lifetime for generated tokens. - :type token_max_ttl: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The response of the configure request. - :rtype: requests.Response - """ - params = utils.remove_nones( - { - "url": url, - "anonymous_group_search": anonymous_group_search, - "binddn": binddn, - "bindpass": bindpass, - "case_sensitive_names": case_sensitive_names, - "certificate": certificate, - "client_tls_cert": client_tls_cert, - "client_tls_key": client_tls_key, - "connection_timeout": connection_timeout, - "deny_null_bind": deny_null_bind, - "dereference_aliases": dereference_aliases, - "discoverdn": discoverdn, - "groupattr": groupattr, - "groupdn": groupdn, - "groupfilter": groupfilter, - "insecure_tls": insecure_tls, - "max_page_size": max_page_size, - "request_timeout": request_timeout, - "starttls": starttls, - "tls_max_version": tls_max_version, - "tls_min_version": tls_min_version, - "token_bound_cidrs": token_bound_cidrs, - "token_explicit_max_ttl": token_explicit_max_ttl, - "token_max_ttl": token_max_ttl, - "token_no_default_policy": token_no_default_policy, - "token_num_uses": token_num_uses, - "token_period": token_period, - "token_policies": token_policies, - "token_ttl": token_ttl, - "token_type": token_type, - "upndomain": upndomain, - "use_token_groups": use_token_groups, - "userattr": userattr, - "userdn": userdn, - "userfilter": userfilter, - "username_as_alias": username_as_alias, - } - ) - - api_path = utils.format_url( - "/v1/auth/{mount_point}/config", mount_point=mount_point - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def read_configuration(self, mount_point=DEFAULT_MOUNT_POINT): - """ - Retrieve the LDAP configuration for the auth method. - - Supported methods: - GET: /auth/{mount_point}/config. Produces: 200 application/json - - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the read_configuration request. - :rtype: dict - """ - api_path = utils.format_url( - "/v1/auth/{mount_point}/config", mount_point=mount_point - ) - return self._adapter.get( - url=api_path, - ) - - def create_or_update_group( - self, name, policies=None, mount_point=DEFAULT_MOUNT_POINT - ): - """ - Create or update LDAP group policies. - - Supported methods: - POST: /auth/{mount_point}/groups/{name}. Produces: 204 (empty body) - - - :param name: The name of the LDAP group - :type name: str | unicode - :param policies: List of policies associated with the group. This parameter is transformed to a comma-delimited - string before being passed to Vault. - :type policies: list - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The response of the create_or_update_group request. - :rtype: requests.Response - """ - if policies is not None and not isinstance(policies, list): - error_msg = '"policies" argument must be an instance of list or None, "{policies_type}" provided.'.format( - policies_type=type(policies), - ) - raise exceptions.ParamValidationError(error_msg) - - params = {} - if policies is not None: - params["policies"] = ",".join(policies) - api_path = utils.format_url( - "/v1/auth/{mount_point}/groups/{name}", - mount_point=mount_point, - name=name, - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def list_groups(self, mount_point=DEFAULT_MOUNT_POINT): - """ - List existing LDAP existing groups that have been created in this auth method. - - Supported methods: - LIST: /auth/{mount_point}/groups. Produces: 200 application/json - - - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the list_groups request. - :rtype: dict - """ - api_path = utils.format_url( - "/v1/auth/{mount_point}/groups", mount_point=mount_point - ) - return self._adapter.list( - url=api_path, - ) - - def read_group(self, name, mount_point=DEFAULT_MOUNT_POINT): - """ - Read policies associated with a LDAP group. - - Supported methods: - GET: /auth/{mount_point}/groups/{name}. Produces: 200 application/json - - - :param name: The name of the LDAP group - :type name: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the read_group request. - :rtype: dict - """ - params = { - "name": name, - } - api_path = utils.format_url( - "/v1/auth/{mount_point}/groups/{name}", - mount_point=mount_point, - name=name, - ) - return self._adapter.get( - url=api_path, - json=params, - ) - - def delete_group(self, name, mount_point=DEFAULT_MOUNT_POINT): - """ - Delete a LDAP group and policy association. - - Supported methods: - DELETE: /auth/{mount_point}/groups/{name}. Produces: 204 (empty body) - - - :param name: The name of the LDAP group - :type name: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The response of the delete_group request. - :rtype: requests.Response - """ - api_path = utils.format_url( - "/v1/auth/{mount_point}/groups/{name}", - mount_point=mount_point, - name=name, - ) - return self._adapter.delete( - url=api_path, - ) - - def create_or_update_user( - self, username, policies=None, groups=None, mount_point=DEFAULT_MOUNT_POINT - ): - """ - Create or update LDAP users policies and group associations. - - Supported methods: - POST: /auth/{mount_point}/users/{username}. Produces: 204 (empty body) - - - :param username: The username of the LDAP user - :type username: str | unicode - :param policies: List of policies associated with the user. This parameter is transformed to a comma-delimited - string before being passed to Vault. - :type policies: str | unicode - :param groups: List of groups associated with the user. This parameter is transformed to a comma-delimited - string before being passed to Vault. - :type groups: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The response of the create_or_update_user request. - :rtype: requests.Response - """ - list_required_params = { - "policies": policies, - "groups": groups, - } - for param_name, param_arg in list_required_params.items(): - if param_arg is not None and not isinstance(param_arg, list): - error_msg = '"{param_name}" argument must be an instance of list or None, "{param_type}" provided.'.format( - param_name=param_name, - param_type=type(param_arg), - ) - raise exceptions.ParamValidationError(error_msg) - - params = {} - if policies is not None: - params["policies"] = ",".join(policies) - if groups is not None: - params["groups"] = ",".join(groups) - api_path = utils.format_url( - "/v1/auth/{mount_point}/users/{username}", - mount_point=mount_point, - username=username, - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def list_users(self, mount_point=DEFAULT_MOUNT_POINT): - """ - List existing users in the method. - - Supported methods: - LIST: /auth/{mount_point}/users. Produces: 200 application/json - - - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the list_users request. - :rtype: dict - """ - api_path = utils.format_url( - "/v1/auth/{mount_point}/users", mount_point=mount_point - ) - return self._adapter.list( - url=api_path, - ) - - def read_user(self, username, mount_point=DEFAULT_MOUNT_POINT): - """ - Read policies associated with a LDAP user. - - Supported methods: - GET: /auth/{mount_point}/users/{username}. Produces: 200 application/json - - - :param username: The username of the LDAP user - :type username: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the read_user request. - :rtype: dict - """ - api_path = utils.format_url( - "/v1/auth/{mount_point}/users/{username}", - mount_point=mount_point, - username=username, - ) - return self._adapter.get( - url=api_path, - ) - - def delete_user(self, username, mount_point=DEFAULT_MOUNT_POINT): - """ - Delete a LDAP user and policy association. - - Supported methods: - DELETE: /auth/{mount_point}/users/{username}. Produces: 204 (empty body) - - - :param username: The username of the LDAP user - :type username: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The response of the delete_user request. - :rtype: requests.Response - """ - api_path = utils.format_url( - "/v1/auth/{mount_point}/users/{username}", - mount_point=mount_point, - username=username, - ) - return self._adapter.delete( - url=api_path, - ) - - def login( - self, username, password, use_token=True, mount_point=DEFAULT_MOUNT_POINT - ): - """ - Log in with LDAP credentials. - - Supported methods: - POST: /auth/{mount_point}/login/{username}. Produces: 200 application/json - - - :param username: The username of the LDAP user - :type username: str | unicode - :param password: The password for the LDAP user - :type password: str | unicode - :param use_token: if True, uses the token in the response received from the auth request to set the "token" - attribute on the the :py:meth:`hvac.adapters.Adapter` instance under the _adapter Client attribute. - :type use_token: bool - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The response of the login_with_user request. - :rtype: requests.Response - """ - params = { - "password": password, - } - api_path = utils.format_url( - "/v1/auth/{mount_point}/login/{username}", - mount_point=mount_point, - username=username, - ) - return self._adapter.login( - url=api_path, - use_token=use_token, - json=params, - ) diff --git a/.venv/lib/python3.12/site-packages/hvac/api/auth_methods/legacy_mfa.py b/.venv/lib/python3.12/site-packages/hvac/api/auth_methods/legacy_mfa.py deleted file mode 100644 index ce4b4ed..0000000 --- a/.venv/lib/python3.12/site-packages/hvac/api/auth_methods/legacy_mfa.py +++ /dev/null @@ -1,172 +0,0 @@ -#!/usr/bin/env python -"""Legacy multi-factor authentication methods module.""" -from hvac.api.vault_api_base import VaultApiBase -from hvac import exceptions, utils - -SUPPORTED_MFA_TYPES = [ - "duo", -] -SUPPORTED_AUTH_METHODS = ["ldap", "okta", "radius", "userpass"] - - -class LegacyMfa(VaultApiBase): - """Multi-factor authentication Auth Method (API). - - .. warning:: - This class's methods correspond to a legacy / unsupported set of Vault API routes. Please see the reference link - for additional context. - - Reference: https://developer.hashicorp.com/vault/docs/v1.10.x/auth/mfa - """ - - def configure(self, mount_point, mfa_type="duo", force=False): - """Configure MFA for a supported method. - - This endpoint allows you to turn on multi-factor authentication with a given backend. - Currently only Duo is supported. - - Supported methods: - POST: /auth/{mount_point}/mfa_config. Produces: 204 (empty body) - - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :param mfa_type: Enables MFA with given backend (available: duo) - :type mfa_type: str | unicode - :param force: If `True`, make the `mfa_config` request regardless of circumstance. If `False` (the default), verify - the provided `mount_point` is available and one of the types of methods supported by this feature. - :type force: bool - :return: The response of the configure MFA request. - :rtype: requests.Response - """ - if mfa_type != "duo" and not force: - # The situation described via this exception is not likely to change in the future. - # However we provided that flexibility here just in case. - error_msg = 'Unsupported mfa_type argument provided "{arg}", supported types: "{mfa_types}"' - raise exceptions.ParamValidationError( - error_msg.format( - mfa_types=",".join(SUPPORTED_MFA_TYPES), - arg=mfa_type, - ) - ) - params = { - "type": mfa_type, - } - - api_path = utils.format_url( - "/v1/auth/{mount_point}/mfa_config", mount_point=mount_point - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def read_configuration(self, mount_point): - """Read the MFA configuration. - - Supported methods: - GET: /auth/{mount_point}/mfa_config. Produces: 200 application/json - - - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the read_configuration request. - :rtype: dict - """ - api_path = utils.format_url( - "/v1/auth/{mount_point}/mfa_config", - mount_point=mount_point, - ) - return self._adapter.get(url=api_path) - - def configure_duo_access(self, mount_point, host, integration_key, secret_key): - """Configure the access keys and host for Duo API connections. - - To authenticate users with Duo, the backend needs to know what host to connect to and must authenticate with an - integration key and secret key. This endpoint is used to configure that information. - - Supported methods: - POST: /auth/{mount_point}/duo/access. Produces: 204 (empty body) - - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :param host: Duo API host - :type host: str | unicode - :param integration_key: Duo integration key - :type integration_key: str | unicode - :param secret_key: Duo secret key - :type secret_key: str | unicode - :return: The response of the `configure_duo_access` request. - :rtype: requests.Response - """ - params = { - "host": host, - "ikey": integration_key, - "skey": secret_key, - } - api_path = utils.format_url( - "/v1/auth/{mount_point}/duo/access", - mount_point=mount_point, - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def configure_duo_behavior( - self, mount_point, push_info=None, user_agent=None, username_format="%s" - ): - """Configure Duo second factor behavior. - - This endpoint allows you to configure how the original auth method username maps to the Duo username by - providing a template format string. - - Supported methods: - POST: /auth/{mount_point}/duo/config. Produces: 204 (empty body) - - - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :param push_info: A string of URL-encoded key/value pairs that provides additional context about the - authentication attempt in the Duo Mobile app - :type push_info: str | unicode - :param user_agent: User agent to connect to Duo (default is empty string `""`) - :type user_agent: str | unicode - :param username_format: Format string given auth method username as argument to create Duo username - (default `%s`) - :type username_format: str | unicode - :return: The response of the `configure_duo_behavior` request. - :rtype: requests.Response - """ - params = { - "username_format": username_format, - } - if push_info is not None: - params["push_info"] = push_info - if user_agent is not None: - params["user_agent"] = user_agent - api_path = utils.format_url( - "/v1/auth/{mount_point}/duo/config", - mount_point=mount_point, - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def read_duo_behavior_configuration(self, mount_point): - """Read the Duo second factor behavior configuration. - - Supported methods: - GET: /auth/{mount_point}/duo/config. Produces: 200 application/json - - - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the `read_duo_behavior_configuration` request. - :rtype: dict - """ - api_path = utils.format_url( - "/v1/auth/{mount_point}/duo/config", - mount_point=mount_point, - ) - return self._adapter.get(url=api_path) diff --git a/.venv/lib/python3.12/site-packages/hvac/api/auth_methods/oidc.py b/.venv/lib/python3.12/site-packages/hvac/api/auth_methods/oidc.py deleted file mode 100644 index bb3f2d6..0000000 --- a/.venv/lib/python3.12/site-packages/hvac/api/auth_methods/oidc.py +++ /dev/null @@ -1,166 +0,0 @@ -#!/usr/bin/env python -"""JWT/OIDC methods module.""" -from hvac.api.auth_methods.jwt import JWT - - -class OIDC(JWT): - """OIDC auth method which can be used to authenticate with Vault using OIDC. - - The OIDC method allows authentication via a configured OIDC provider using the user's web browser. - This method may be initiated from the Vault UI or the command line. Alternatively, a JWT can be provided directly. - The JWT is cryptographically verified using locally-provided keys, or, if configured, an OIDC Discovery service can - be used to fetch the appropriate keys. The choice of method is configured per role. - - Note: this class is duplicative of the JWT class (as both JWT and OIDC share the same family of Vault API routes). - - Reference: https://www.vaultproject.io/api/auth/jwt - """ - - DEFAULT_PATH = "oidc" - - def create_role( - self, - name, - user_claim, - allowed_redirect_uris, - role_type="oidc", - bound_audiences=None, - clock_skew_leeway=None, - expiration_leeway=None, - not_before_leeway=None, - bound_subject=None, - bound_claims=None, - groups_claim=None, - claim_mappings=None, - oidc_scopes=None, - bound_claims_type="string", - verbose_oidc_logging=False, - token_ttl=None, - token_max_ttl=None, - token_policies=None, - token_bound_cidrs=None, - token_explicit_max_ttl=None, - token_no_default_policy=None, - token_num_uses=None, - token_period=None, - token_type=None, - path=None, - user_claim_json_pointer=None, - ): - """Register a role in the OIDC method. - - Role types have specific entities that can perform login operations against this endpoint. Constraints - specific to the role type must be set on the role. These are applied to the authenticated entities - attempting to login. At least one of the bound values must be set. - - Supported methods: - POST: /auth/{path}/role/:name. - - :param name: Name of the role. - :type name: str | unicode - :param role_type: Type of role, either "oidc" or "jwt" (default). - :type role_type: str | unicode - :param bound_audiences: List of aud claims to match against. Any match is sufficient. - Required for "jwt" roles, optional for "oidc" roles. - :type bound_audiences: list - :param user_claim: The claim to use to uniquely identify the user; this will be used as the name for the - Identity entity alias created due to a successful login. The interpretation of the user claim - is configured with ``user_claim_json_pointer``. If set to ``True``, ``user_claim`` supports JSON pointer syntax - for referencing a claim. The claim value must be a string. - :type user_claim: str | unicode - :param clock_skew_leeway: Only applicable with "jwt" roles. - :type clock_skew_leeway: int - :param expiration_leeway: Only applicable with "jwt" roles. - :type expiration_leeway: int - :param not_before_leeway: Only applicable with "jwt" roles. - :type not_before_leeway: int - :param bound_subject: If set, requires that the sub claim matches this value. - :type bound_subject: str | unicode - :param bound_claims: If set, a dict of claims (keys) to match against respective claim values (values). - The expected value may be a single string or a list of strings. The interpretation of the bound claim - values is configured with bound_claims_type. Keys support JSON pointer syntax for referencing claims. - :type bound_claims: dict - :param groups_claim: The claim to use to uniquely identify the set of groups to which the user belongs; this - will be used as the names for the Identity group aliases created due to a successful login. The claim value - must be a list of strings. Supports JSON pointer syntax for referencing claims. - :type groups_claim: str | unicode - :param claim_mappings: If set, a map of claims (keys) to be copied to specified metadata fields (values). Keys - support JSON pointer syntax for referencing claims. - :type claim_mappings: map - :param oidc_scopes: If set, a list of OIDC scopes to be used with an OIDC role. - The standard scope "openid" is automatically included and need not be specified. - :type oidc_scopes: list - :param allowed_redirect_uris: The list of allowed values for redirect_uri - during OIDC logins. - :type allowed_redirect_uris: list - :param bound_claims_type: Configures the interpretation of the bound_claims values. If "string" (the default), - the values will treated as string literals and must match exactly. If set to "glob", the values will be - interpreted as globs, with * matching any number of characters. - :type bound_claims_type: str | unicode - :param verbose_oidc_logging: Log received OIDC tokens and claims when debug-level - logging is active. Not recommended in production since sensitive information may be present - in OIDC responses. - :type verbose_oidc_logging: bool - :param token_ttl: The incremental lifetime for generated tokens. This current value of this will be referenced - at renewal time. - :type token_ttl: int | str - :param token_max_ttl: The maximum lifetime for generated tokens. This current value of this will be referenced - at renewal time. - :type token_max_ttl: int | str - :param token_policies: List of policies to encode onto generated tokens. Depending on the auth method, this - list may be supplemented by user/group/other values. - :type token_policies: list[str] - :param token_bound_cidrs: List of CIDR blocks; if set, specifies blocks of IP addresses which can authenticate - successfully, and ties the resulting token to these blocks as well. - :type token_bound_cidrs: list[str] - :param token_explicit_max_ttl: If set, will encode an explicit max TTL onto the token. This is a hard cap - even if token_ttl and token_max_ttl would otherwise allow a renewal. - :type token_explicit_max_ttl: int | str - :param token_no_default_policy: If set, the default policy will not be set on generated tokens; otherwise it - will be added to the policies set in token_policies. - :type token_no_default_policy: bool - :param token_num_uses: The maximum number of times a generated token may be used (within its lifetime); 0 means - unlimited. If you require the token to have the ability to create child tokens, you will need to set this - value to 0. - :type token_num_uses: str | unicode - :param token_period: The period, if any, to set on the token. - :type token_period: int | str - :param token_type: The type of token that should be generated. Can be service, batch, or default. - :type token_type: str - :param path: The "path" the method/backend was mounted on. - :type path: str | unicode - :param user_claim_json_pointer: Specifies if the ``user_claim`` value uses JSON pointer syntax for referencing claims. - By default, the ``user_claim`` value will not use JSON pointer. - :type user_claim_json_pointer: bool - :return: The response of the create_role request. - :rtype: dict - """ - - super().create_role( - name=name, - user_claim=user_claim, - allowed_redirect_uris=allowed_redirect_uris, - role_type=role_type, - bound_audiences=bound_audiences, - clock_skew_leeway=clock_skew_leeway, - expiration_leeway=expiration_leeway, - not_before_leeway=not_before_leeway, - bound_subject=bound_subject, - bound_claims=bound_claims, - groups_claim=groups_claim, - claim_mappings=claim_mappings, - oidc_scopes=oidc_scopes, - bound_claims_type=bound_claims_type, - verbose_oidc_logging=verbose_oidc_logging, - token_ttl=token_ttl, - token_max_ttl=token_max_ttl, - token_policies=token_policies, - token_bound_cidrs=token_bound_cidrs, - token_explicit_max_ttl=token_explicit_max_ttl, - token_no_default_policy=token_no_default_policy, - token_num_uses=token_num_uses, - token_period=token_period, - token_type=token_type, - path=path, - user_claim_json_pointer=user_claim_json_pointer, - ) diff --git a/.venv/lib/python3.12/site-packages/hvac/api/auth_methods/okta.py b/.venv/lib/python3.12/site-packages/hvac/api/auth_methods/okta.py deleted file mode 100644 index 3317425..0000000 --- a/.venv/lib/python3.12/site-packages/hvac/api/auth_methods/okta.py +++ /dev/null @@ -1,332 +0,0 @@ -#!/usr/bin/env python -"""Okta methods module.""" -from hvac import utils -from hvac.api.vault_api_base import VaultApiBase - -DEFAULT_MOUNT_POINT = "okta" - - -class Okta(VaultApiBase): - """Okta Auth Method (API). - - Reference: https://www.vaultproject.io/api/auth/okta/index.html - """ - - def configure( - self, - org_name, - api_token=None, - base_url=None, - ttl=None, - max_ttl=None, - bypass_okta_mfa=None, - mount_point=DEFAULT_MOUNT_POINT, - ): - """Configure the connection parameters for Okta. - - This path honors the distinction between the create and update capabilities inside ACL policies. - - Supported methods: - POST: /auth/{mount_point}/config. Produces: 204 (empty body) - - - :param org_name: Name of the organization to be used in the Okta API. - :type org_name: str | unicode - :param api_token: Okta API token. This is required to query Okta for user group membership. If this is not - supplied only locally configured groups will be enabled. - :type api_token: str | unicode - :param base_url: If set, will be used as the base domain for API requests. Examples are okta.com, - oktapreview.com, and okta-emea.com. - :type base_url: str | unicode - :param ttl: Duration after which authentication will be expired. - :type ttl: str | unicode - :param max_ttl: Maximum duration after which authentication will be expired. - :type max_ttl: str | unicode - :param bypass_okta_mfa: Whether to bypass an Okta MFA request. Useful if using one of Vault's built-in MFA - mechanisms, but this will also cause certain other statuses to be ignored, such as PASSWORD_EXPIRED. - :type bypass_okta_mfa: bool - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - params = { - "org_name": org_name, - } - params.update( - utils.remove_nones( - { - "api_token": api_token, - "base_url": base_url, - "ttl": ttl, - "max_ttl": max_ttl, - "bypass_okta_mfa": bypass_okta_mfa, - } - ) - ) - api_path = utils.format_url( - "/v1/auth/{mount_point}/config", mount_point=mount_point - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def read_config(self, mount_point=DEFAULT_MOUNT_POINT): - """Read the Okta configuration. - - Supported methods: - GET: /auth/{mount_point}/config. Produces: 200 application/json - - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the request. - :rtype: dict - """ - api_path = utils.format_url( - "/v1/auth/{mount_point}/config", mount_point=mount_point - ) - return self._adapter.get( - url=api_path, - ) - - def list_users(self, mount_point=DEFAULT_MOUNT_POINT): - """List the users configured in the Okta method. - - Supported methods: - LIST: /auth/{mount_point}/users. Produces: 200 application/json - - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the request. - :rtype: dict - """ - api_path = utils.format_url( - "/v1/auth/{mount_point}/users", mount_point=mount_point - ) - return self._adapter.list( - url=api_path, - ) - - def register_user( - self, username, groups=None, policies=None, mount_point=DEFAULT_MOUNT_POINT - ): - """Register a new user and maps a set of policies to it. - - Supported methods: - POST: /auth/{mount_point}/users/{username}. Produces: 204 (empty body) - - :param username: Name of the user. - :type username: str | unicode - :param groups: List or comma-separated string of groups associated with the user. - :type groups: list - :param policies: List or comma-separated string of policies associated with the user. - :type policies: list - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - params = { - "username": username, - } - params.update( - utils.remove_nones( - { - "groups": groups, - "policies": policies, - } - ) - ) - api_path = utils.format_url( - "/v1/auth/{mount_point}/users/{username}", - mount_point=mount_point, - username=username, - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def read_user(self, username, mount_point=DEFAULT_MOUNT_POINT): - """Read the properties of an existing username. - - Supported methods: - GET: /auth/{mount_point}/users/{username}. Produces: 200 application/json - - :param username: Username for this user. - :type username: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the request. - :rtype: dict - """ - params = { - "username": username, - } - api_path = utils.format_url( - "/v1/auth/{mount_point}/users/{username}", - mount_point=mount_point, - username=username, - ) - return self._adapter.get( - url=api_path, - json=params, - ) - - def delete_user(self, username, mount_point=DEFAULT_MOUNT_POINT): - """Delete an existing username from the method. - - Supported methods: - DELETE: /auth/{mount_point}/users/{username}. Produces: 204 (empty body) - - :param username: Username for this user. - :type username: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - params = { - "username": username, - } - api_path = utils.format_url( - "/v1/auth/{mount_point}/users/{username}", - mount_point=mount_point, - username=username, - ) - return self._adapter.delete( - url=api_path, - json=params, - ) - - def list_groups(self, mount_point=DEFAULT_MOUNT_POINT): - """List the groups configured in the Okta method. - - Supported methods: - LIST: /auth/{mount_point}/groups. Produces: 200 application/json - - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the request. - :rtype: dict - """ - api_path = utils.format_url( - "/v1/auth/{mount_point}/groups", mount_point=mount_point - ) - return self._adapter.list( - url=api_path, - ) - - def register_group(self, name, policies=None, mount_point=DEFAULT_MOUNT_POINT): - """Register a new group and maps a set of policies to it. - - Supported methods: - POST: /auth/{mount_point}/groups/{name}. Produces: 204 (empty body) - - :param name: The name of the group. - :type name: str | unicode - :param policies: The list or comma-separated string of policies associated with the group. - :type policies: list - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - params = utils.remove_nones( - { - "policies": policies, - } - ) - api_path = utils.format_url( - "/v1/auth/{mount_point}/groups/{name}", - mount_point=mount_point, - name=name, - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def read_group(self, name, mount_point=DEFAULT_MOUNT_POINT): - """Read the properties of an existing group. - - Supported methods: - GET: /auth/{mount_point}/groups/{name}. Produces: 200 application/json - - :param name: The name for the group. - :type name: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the request. - :rtype: dict - """ - api_path = utils.format_url( - "/v1/auth/{mount_point}/groups/{name}", - mount_point=mount_point, - name=name, - ) - return self._adapter.get( - url=api_path, - ) - - def delete_group(self, name, mount_point=DEFAULT_MOUNT_POINT): - """Delete an existing group from the method. - - Supported methods: - DELETE: /auth/{mount_point}/groups/{name}. Produces: 204 (empty body) - - :param name: The name for the group. - :type name: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - params = { - "name": name, - } - api_path = utils.format_url( - "/v1/auth/{mount_point}/groups/{name}", - mount_point=mount_point, - name=name, - ) - return self._adapter.delete( - url=api_path, - json=params, - ) - - def login( - self, username, password, use_token=True, mount_point=DEFAULT_MOUNT_POINT - ): - """Login with the username and password. - - Supported methods: - POST: /auth/{mount_point}/login/{username}. Produces: 200 application/json - - :param username: Username for this user. - :type username: str | unicode - :param password: Password for the authenticating user. - :type password: str | unicode - :param use_token: if True, uses the token in the response received from the auth request to set the "token" - attribute on the :py:meth:`hvac.adapters.Adapter` instance under the _adapter Client attribute. - :type use_token: bool - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The response of the login request. - :rtype: dict - """ - params = { - "username": username, - "password": password, - } - api_path = utils.format_url( - "/v1/auth/{mount_point}/login/{username}", - mount_point=mount_point, - username=username, - ) - return self._adapter.login( - url=api_path, - use_token=use_token, - json=params, - ) diff --git a/.venv/lib/python3.12/site-packages/hvac/api/auth_methods/radius.py b/.venv/lib/python3.12/site-packages/hvac/api/auth_methods/radius.py deleted file mode 100644 index 291e84f..0000000 --- a/.venv/lib/python3.12/site-packages/hvac/api/auth_methods/radius.py +++ /dev/null @@ -1,237 +0,0 @@ -#!/usr/bin/env python -"""RADIUS methods module.""" -from hvac import exceptions, utils -from hvac.api.vault_api_base import VaultApiBase - -DEFAULT_MOUNT_POINT = "radius" - - -class Radius(VaultApiBase): - """RADIUS Auth Method (API). - - Reference: https://www.vaultproject.io/docs/auth/radius.html - """ - - def configure( - self, - host, - secret, - port=None, - unregistered_user_policies=None, - dial_timeout=None, - nas_port=None, - mount_point=DEFAULT_MOUNT_POINT, - ): - """ - Configure the RADIUS auth method. - - Supported methods: - POST: /auth/{mount_point}/config. Produces: 204 (empty body) - - :param host: The RADIUS server to connect to. Examples: radius.myorg.com, 127.0.0.1 - :type host: str | unicode - :param secret: The RADIUS shared secret. - :type secret: str | unicode - :param port: The UDP port where the RADIUS server is listening on. Defaults is 1812. - :type port: int - :param unregistered_user_policies: A comma-separated list of policies to be granted to unregistered users. - :type unregistered_user_policies: list - :param dial_timeout: Number of second to wait for a backend connection before timing out. Default is 10. - :type dial_timeout: int - :param nas_port: The NAS-Port attribute of the RADIUS request. Defaults is 10. - :type nas_port: int - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The response of the configure request. - :rtype: requests.Response - """ - params = { - "host": host, - "secret": secret, - } - params.update( - utils.remove_nones( - { - "port": port, - "dial_timeout": dial_timeout, - "nas_port": nas_port, - } - ) - ) - # Fill out params dictionary with any optional parameters provided - if unregistered_user_policies is not None: - if not isinstance(unregistered_user_policies, list): - error_msg = ( - '"unregistered_user_policies" argument must be an instance of list or None, ' - '"{unregistered_user_policies}" provided.' - ).format(unregistered_user_policies=type(unregistered_user_policies)) - raise exceptions.ParamValidationError(error_msg) - - params["unregistered_user_policies"] = ",".join(unregistered_user_policies) - - api_path = utils.format_url( - "/v1/auth/{mount_point}/config", mount_point=mount_point - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def read_configuration(self, mount_point=DEFAULT_MOUNT_POINT): - """ - Retrieve the RADIUS configuration for the auth method. - - Supported methods: - GET: /auth/{mount_point}/config. Produces: 200 application/json - - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the read_configuration request. - :rtype: dict - """ - api_path = utils.format_url( - "/v1/auth/{mount_point}/config", mount_point=mount_point - ) - return self._adapter.get( - url=api_path, - ) - - def register_user(self, username, policies=None, mount_point=DEFAULT_MOUNT_POINT): - """ - Create or update RADIUS user with a set of policies. - - Supported methods: - POST: /auth/{mount_point}/users/{username}. Produces: 204 (empty body) - - :param username: Username for this RADIUS user. - :type username: str | unicode - :param policies: List of policies associated with the user. This parameter is transformed to a comma-delimited - string before being passed to Vault. - :type policies: list - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The response of the register_user request. - :rtype: requests.Response - """ - if policies is not None and not isinstance(policies, list): - error_msg = '"policies" argument must be an instance of list or None, "{policies_type}" provided.'.format( - policies_type=type(policies), - ) - raise exceptions.ParamValidationError(error_msg) - - params = {} - if policies is not None: - params["policies"] = ",".join(policies) - api_path = utils.format_url( - "/v1/auth/{mount_point}/users/{name}", - mount_point=mount_point, - name=username, - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def list_users(self, mount_point=DEFAULT_MOUNT_POINT): - """ - List existing users in the method. - - Supported methods: - LIST: /auth/{mount_point}/users. Produces: 200 application/json - - - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the list_users request. - :rtype: dict - """ - api_path = utils.format_url( - "/v1/auth/{mount_point}/users", mount_point=mount_point - ) - return self._adapter.list( - url=api_path, - ) - - def read_user(self, username, mount_point=DEFAULT_MOUNT_POINT): - """ - Read policies associated with a RADIUS user. - - Supported methods: - GET: /auth/{mount_point}/users/{username}. Produces: 200 application/json - - - :param username: The username of the RADIUS user - :type username: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the read_user request. - :rtype: dict - """ - api_path = utils.format_url( - "/v1/auth/{mount_point}/users/{username}", - mount_point=mount_point, - username=username, - ) - return self._adapter.get( - url=api_path, - ) - - def delete_user(self, username, mount_point=DEFAULT_MOUNT_POINT): - """ - Delete a RADIUS user and policy association. - - Supported methods: - DELETE: /auth/{mount_point}/users/{username}. Produces: 204 (empty body) - - - :param username: The username of the RADIUS user - :type username: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The response of the delete_user request. - :rtype: requests.Response - """ - api_path = utils.format_url( - "/v1/auth/{mount_point}/users/{username}", - mount_point=mount_point, - username=username, - ) - return self._adapter.delete( - url=api_path, - ) - - def login( - self, username, password, use_token=True, mount_point=DEFAULT_MOUNT_POINT - ): - """ - Log in with RADIUS credentials. - - Supported methods: - POST: /auth/{mount_point}/login/{username}. Produces: 200 application/json - - - :param username: The username of the RADIUS user - :type username: str | unicode - :param password: The password for the RADIUS user - :type password: str | unicode - :param use_token: if True, uses the token in the response received from the auth request to set the "token" - attribute on the the :py:meth:`hvac.adapters.Adapter` instance under the _adapter Client attribute. - :type use_token: bool - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The response of the login_with_user request. - :rtype: requests.Response - """ - params = { - "password": password, - } - api_path = utils.format_url( - "/v1/auth/{mount_point}/login/{username}", - mount_point=mount_point, - username=username, - ) - return self._adapter.login( - url=api_path, - use_token=use_token, - json=params, - ) diff --git a/.venv/lib/python3.12/site-packages/hvac/api/auth_methods/token.py b/.venv/lib/python3.12/site-packages/hvac/api/auth_methods/token.py deleted file mode 100644 index b0d6a45..0000000 --- a/.venv/lib/python3.12/site-packages/hvac/api/auth_methods/token.py +++ /dev/null @@ -1,658 +0,0 @@ -#!/usr/bin/env python -"""Token methods module.""" -from hvac import utils -from hvac.api.vault_api_base import VaultApiBase - -DEFAULT_MOUNT_POINT = "token" - - -class Token(VaultApiBase): - """Token Auth Method (API). - - Reference: http://localhost:3000/api-docs/auth/token - """ - - def create( - self, - id=None, - role_name=None, - policies=None, - meta=None, - no_parent=False, - no_default_policy=False, - renewable=True, - ttl=None, - type=None, - explicit_max_ttl=None, - display_name="token", - num_uses=0, - period=None, - entity_alias=None, - wrap_ttl=None, - mount_point=DEFAULT_MOUNT_POINT, - ): - """Create a new token. - - Certain options are only available when called by a root token. If used - via the /auth/token/create-orphan endpoint, a root token is not required - to create an orphan token (otherwise set with the no_parent option). If - used with a role name in the path, the token will be created against the - specified role name; this may override options set during this call. - - - :param id: The ID of the client token. Can only be specified by a root token. - The ID provided may not contain a `.` character. Otherwise, the - token ID is a randomly generated value. - :type id: str - :param role_name: The name of the token role. - :type role_name: str - :param policies: A list of policies for the token. This must be a - subset of the policies belonging to the token making the request, unless root. - If not specified, defaults to all the policies of the calling token. - :type policies: list - :param meta: A map of string to string valued metadata. This is - passed through to the audit devices. - :type meta: map - :param no_parent: This argument only has effect if used by a root or sudo caller. - When set to `True`, the token created will not have a parent. - :type no_parent: bool - :param no_default_policy: If `True` the default policy will not be contained in this token's policy set. - :type no_default_policy: bool - :param renewable: Set to false to disable the ability of the token to be renewed past its initial TTL. - Setting the value to true will allow the token to be renewable up to the system/mount maximum TTL. - :type renewable: bool - :param ttl: The TTL period of the token, provided as "1h", where hour is the largest suffix. If not provided, - the token is valid for the default lease TTL, or indefinitely if the root policy is used. - :type ttl: str - :param type: The token type. Can be "batch" or "service". Defaults to the type - specified by the role configuration named by role_name. - :type type: str - :param explicit_max_ttl: If set, the token will have an explicit max TTL set upon it. - This maximum token TTL cannot be changed later, and unlike with normal tokens, updates to the system/mount - max TTL value will have no effect at renewal time -- the token will never be able to be renewed or used past - the value set at issue time. - :type explicit_max_ttl: str - :param display_name: The display name of the token. - :type display_name: str - :param num_uses: The maximum uses for the given token. This can be - used to create a one-time-token or limited use token. The value of 0 has no - limit to the number of uses. - :type num_uses: int - :param period: If specified, the token will be periodic; it will have - no maximum TTL (unless an "explicit-max-ttl" is also set) but every renewal - will use the given period. Requires a root token or one with the sudo capability. - :type period: str - :param entity_alias: Name of the entity alias to associate with during token creation. - Only works in combination with role_name argument and used entity alias must be listed in - `allowed_entity_aliases`. If this has been specified, the entity will not be inherited from the parent. - :type entity_alias: str - :param wrap_ttl: Specifies response wrapping token creation with duration. IE: '15s', '20m', '25h'. - :type wrap_ttl: str - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str - :return: The response of the create request. - :rtype: requests.Response - """ - params = utils.remove_nones( - { - "id": id, - "policies": policies, - "meta": meta, - "no_parent": no_parent, - "no_default_policy": no_default_policy, - "renewable": renewable, - "ttl": ttl, - "type": type, - "explicit_max_ttl": explicit_max_ttl, - "display_name": display_name, - "num_uses": num_uses, - "period": period, - "entity_alias": entity_alias, - } - ) - - api_path = f"/v1/auth/{mount_point}/create" - - if role_name is not None: - api_path = f"{api_path}/{role_name}" - - return self._adapter.post( - url=api_path, - json=params, - wrap_ttl=wrap_ttl, - ) - - def create_orphan( - self, - id=None, - role_name=None, - policies=None, - meta=None, - no_default_policy=False, - renewable=True, - ttl=None, - type=None, - explicit_max_ttl=None, - display_name="token", - num_uses=0, - period=None, - entity_alias=None, - wrap_ttl=None, - mount_point=DEFAULT_MOUNT_POINT, - ): - """Create a new orphaned token. - - Creates a token via the /auth/token/create-orphan endpoint. A root token - is not required to create an orphan token with this endpoint (otherwise - an orphaned token can be set with the `create` method's `no_parent` option). - - - :param id: The ID of the client token. Can only be specified by a root token. - The ID provided may not contain a `.` character. Otherwise, the - token ID is a randomly generated value. - :type id: str - :param role_name: The name of the token role. - :type role_name: str - :param policies: A list of policies for the token. This must be a - subset of the policies belonging to the token making the request, unless root. - If not specified, defaults to all the policies of the calling token. - :type policies: list - :param meta: A map of string to string valued metadata. This is - passed through to the audit devices. - :type meta: map - :param no_default_policy: If `True` the default policy will not be contained in this token's policy set. - :type no_default_policy: bool - :param renewable: Set to false to disable the ability of the token to be renewed past its initial TTL. - Setting the value to true will allow the token to be renewable up to the system/mount maximum TTL. - :type renewable: bool - :param ttl: The TTL period of the token, provided as `1h`, where hour is the largest suffix. If not provided, - the token is valid for the default lease TTL, or indefinitely if the root policy is used. - :type ttl: str - :param type: The token type. Can be `batch` or `service`. Defaults to the type - specified by the role configuration named by role_name. - :type type: str - :param explicit_max_ttl: If set, the token will have an explicit max TTL set upon it. - This maximum token TTL cannot be changed later, and unlike with normal tokens, updates to the system/mount - max TTL value will have no effect at renewal time -- the token will never be able to be renewed or used past - the value set at issue time. - :type explicit_max_ttl: str - :param display_name: The display name of the token. - :type display_name: str - :param num_uses: The maximum uses for the given token. This can be - used to create a one-time-token or limited use token. The value of `0` has no - limit to the number of uses. - :type num_uses: int - :param period: If specified, the token will be periodic; it will have - no maximum TTL (unless an `explicit-max-ttl` is also set) but every renewal - will use the given period. Requires a root token or one with the sudo capability. - :type period: str - :param entity_alias: Name of the entity alias to associate with during token creation. - Only works in combination with role_name argument and used entity alias must be listed in - `allowed_entity_aliases`. If this has been specified, the entity will not be inherited from the parent. - :type entity_alias: str - :param wrap_ttl: Specifies response wrapping token creation with duration. IE: `15s`, `20m`, `25h`. - :type wrap_ttl: str - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str - :return: The response of the create request. - :rtype: requests.Response - """ - params = utils.remove_nones( - { - "id": id, - "role_name": role_name, - "policies": policies, - "meta": meta, - "no_default_policy": no_default_policy, - "renewable": renewable, - "ttl": ttl, - "type": type, - "explicit_max_ttl": explicit_max_ttl, - "display_name": display_name, - "num_uses": num_uses, - "period": period, - "entity_alias": entity_alias, - } - ) - - api_path = f"/v1/auth/{mount_point}/create-orphan" - return self._adapter.post( - url=api_path, - json=params, - wrap_ttl=wrap_ttl, - ) - - def list_accessors(self, mount_point=DEFAULT_MOUNT_POINT): - """List token accessors. - - This requires sudo capability, and access to it should be tightly controlled - as the accessors can be used to revoke very large numbers of tokens and their associated leases at once. - - Supported methods: - LIST: /auth/{mount_point}/accessors. - - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str - :return: The response of the list_accessors request. - :rtype: requests.Response - """ - api_path = f"/v1/auth/{mount_point}/accessors" - return self._adapter.list( - url=api_path, - ) - - def lookup(self, token, mount_point=DEFAULT_MOUNT_POINT): - """Retrieve information about the client token. - - Supported methods: - POST: /auth/{mount_point}/lookup. - - :param token: Token to lookup. - :type token: str - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str - :return: The response of the lookup_a request. - :rtype: requests.Response - """ - params = { - "token": token, - } - api_path = f"/v1/auth/{mount_point}/lookup" - return self._adapter.post( - url=api_path, - json=params, - ) - - def lookup_self(self, mount_point=DEFAULT_MOUNT_POINT): - """Retrieve information about the current client token. - - Supported methods: - GET: /auth/{mount_point}/lookup-self. - - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str - :return: The response of the lookup_a_self request. - :rtype: requests.Response - """ - api_path = f"/v1/auth/{mount_point}/lookup-self" - return self._adapter.get( - url=api_path, - ) - - def lookup_accessor(self, accessor, mount_point=DEFAULT_MOUNT_POINT): - """Retrieve information about the client token from its accessor. - - Supported methods: - POST: /auth/{mount_point}/lookup-accessor. - - :param accessor: Token accessor to lookup. - :type accessor: str - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str - :return: The response of the lookup_accessor request. - :rtype: requests.Response - """ - params = { - "accessor": accessor, - } - api_path = "/v1/auth/{mount_point}/lookup-accessor".format( - mount_point=mount_point - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def renew( - self, token, increment=None, wrap_ttl=None, mount_point=DEFAULT_MOUNT_POINT - ): - """Renew a lease associated with a token. - - This is used to prevent the expiration of a token, and the automatic revocation of it. - Token renewal is possible only if there is a lease associated with it. - - Supported methods: - POST: /auth/{mount_point}/renew. - - :param token: Token to renew. This can be part of the URL or the body. - :type token: str - :param increment: An optional requested lease increment can be provided. - This increment may be ignored. - :type increment: str - :param wrap_ttl: Specifies response wrapping token creation with duration. IE: '15s', '20m', '25h'. - :type wrap_ttl: str - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str - :return: The response of the renew_a request. - :rtype: requests.Response - """ - params = utils.remove_nones( - { - "token": token, - "increment": increment, - } - ) - api_path = f"/v1/auth/{mount_point}/renew" - return self._adapter.post( - url=api_path, - json=params, - wrap_ttl=wrap_ttl, - ) - - def renew_self( - self, increment=None, wrap_ttl=None, mount_point=DEFAULT_MOUNT_POINT - ): - """Renew a lease associated with the calling token. - - This is used to prevent the expiration of a token, and the automatic revocation of it. - Token renewal is possible only if there is a lease associated with it. - - Supported methods: - POST: /auth/{mount_point}/renew-self. - - :param increment: An optional requested lease increment can be - provided. This increment may be ignored. - :type increment: str - :param wrap_ttl: Specifies response wrapping token creation with duration. IE: '15s', '20m', '25h'. - :type wrap_ttl: str - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str - :return: The response of the renew_a_self request. - :rtype: requests.Response - """ - params = utils.remove_nones( - { - "increment": increment, - } - ) - api_path = f"/v1/auth/{mount_point}/renew-self" - return self._adapter.post( - url=api_path, - json=params, - wrap_ttl=wrap_ttl, - ) - - def renew_accessor( - self, accessor, increment=None, wrap_ttl=None, mount_point=DEFAULT_MOUNT_POINT - ): - """Renew a lease associated with a token using its accessor. - - This is used to prevent the expiration of a token, and the automatic revocation of it. - Token renewal is possible only if there is a lease associated with it. - - Supported methods: - POST: /auth/{mount_point}/renew-accessor. - - :param accessor: Accessor associated with the token to - renew. - :type accessor: str - :param increment: An optional requested lease increment can be - provided. This increment may be ignored. - :type increment: str - :param wrap_ttl: Specifies response wrapping token creation with duration. IE: '15s', '20m', '25h'. - :type wrap_ttl: str - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str - :return: The response of the renew_a_accessor request. - :rtype: requests.Response - """ - params = utils.remove_nones( - { - "accessor": accessor, - "increment": increment, - } - ) - api_path = "/v1/auth/{mount_point}/renew-accessor".format( - mount_point=mount_point - ) - return self._adapter.post( - url=api_path, - json=params, - wrap_ttl=wrap_ttl, - ) - - def revoke(self, token, mount_point=DEFAULT_MOUNT_POINT): - """Revoke a token and all child tokens. - - When the token is revoked, all dynamic secrets generated with it are also revoked. - - Supported methods: - POST: /auth/{mount_point}/revoke. - - :param token: Token to revoke. - :type token: str - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str - :return: The response of the revoke_a request. - :rtype: requests.Response - """ - params = { - "token": token, - } - api_path = f"/v1/auth/{mount_point}/revoke" - return self._adapter.post( - url=api_path, - json=params, - ) - - def revoke_self(self, mount_point=DEFAULT_MOUNT_POINT): - """Revoke the token used to call it and all child tokens. - - When the token is revoked, all dynamic secrets generated with it are also revoked. - - Supported methods: - POST: /auth/{mount_point}/revoke-self. - - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str - :return: The response of the revoke_a_self request. - :rtype: requests.Response - """ - api_path = f"/v1/auth/{mount_point}/revoke-self" - return self._adapter.post(url=api_path) - - def revoke_accessor(self, accessor, mount_point=DEFAULT_MOUNT_POINT): - """Revoke the token associated with the accessor and all the child tokens. - - This is meant for purposes where there is no access to token ID but there is need to - revoke a token and its children. - - Supported methods: - POST: /auth/{mount_point}/revoke-accessor. - - :param accessor: Accessor of the token. - :type accessor: str - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str - :return: The response of the revoke_a_accessor request. - :rtype: requests.Response - """ - params = { - "accessor": accessor, - } - api_path = "/v1/auth/{mount_point}/revoke-accessor".format( - mount_point=mount_point - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def revoke_and_orphan_children(self, token, mount_point=DEFAULT_MOUNT_POINT): - """Revoke a token but not its child tokens. - - When the token is revoked, all secrets generated with it are also revoked. - All child tokens are orphaned, but can be revoked sub-sequently using /auth/token/revoke/. - This is a root-protected endpoint. - - Supported methods: - POST: /auth/{mount_point}/revoke-orphan. - - :param token: Token to revoke. - :type token: str - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str - :return: The response of the revoke_and_orphan_children request. - :rtype: requests.Response - """ - params = { - "token": token, - } - api_path = "/v1/auth/{mount_point}/revoke-orphan".format( - mount_point=mount_point - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def read_role(self, role_name, mount_point=DEFAULT_MOUNT_POINT): - """Read the named role configuration. - - Supported methods: - GET: /auth/{mount_point}/roles/{role_name}. - - :param role_name: The name of the token role. - :type role_name: str - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str - :return: The response of the read_role request. - :rtype: requests.Response - """ - api_path = "/v1/auth/{mount_point}/roles/{role_name}".format( - mount_point=mount_point, - role_name=role_name, - ) - return self._adapter.get( - url=api_path, - ) - - def list_roles( - self, - mount_point=DEFAULT_MOUNT_POINT, - ): - """List available token roles. - - Supported methods: - LIST: /auth/{mount_point}/roles. - - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str - :return: The response of the list_roles request. - :rtype: requests.Response - """ - api_path = f"/v1/auth/{mount_point}/roles" - return self._adapter.list( - url=api_path, - ) - - def create_or_update_role( - self, - role_name, - allowed_policies=None, - disallowed_policies=None, - orphan=False, - renewable=True, - path_suffix=None, - allowed_entity_aliases=None, - mount_point=DEFAULT_MOUNT_POINT, - token_period=None, - token_explicit_max_ttl=None, - ): - """Create (or replace) the named role. - - Roles enforce specific behavior when creating tokens that allow token functionality that is otherwise not - available or would require sudo/root privileges to access. Role parameters, when set, override any provided - options to the create endpoints. The role name is also included in the token path, allowing all tokens created - against a role to be revoked using the `/sys/leases/revoke-prefix` endpoint. - - Supported methods: - POST: /auth/{mount_point}/roles/{role_name}. - - :param role_name: The name of the token role. - :type role_name: str - :param allowed_policies: will be added to the created - token automatically. - :type allowed_policies: list - :param disallowed_policies: being added automatically to created - tokens. - :type disallowed_policies: list - :param orphan: tokens created against this policy will - be orphan tokens (they will have no parent). As such, they will not be - automatically revoked by the revocation of any other token. - :type orphan: bool - :param renewable: allow - the token to be renewable up to the system/mount maximum TTL. - :type renewable: bool - :param path_suffix: - :type path_suffix: str - :param allowed_entity_aliases: not case sensitive. - :type allowed_entity_aliases: str - :param token_period: the token will have no maximum TTL, every renewal will use the given period. - :type token_period: str - :param token_explicit_max_ttl: the token cannot be renewed past this TTL value. - :type token_explicit_max_ttl: str - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str - :return: The response of the create_or_update_role request. - :rtype: requests.Response - """ - params = utils.remove_nones( - { - "allowed_policies": allowed_policies, - "disallowed_policies": disallowed_policies, - "orphan": orphan, - "renewable": renewable, - "path_suffix": path_suffix, - "allowed_entity_aliases": allowed_entity_aliases, - "token_period": token_period, - "token_explicit_max_ttl": token_explicit_max_ttl, - } - ) - api_path = "/v1/auth/{mount_point}/roles/{role_name}".format( - mount_point=mount_point, - role_name=role_name, - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def delete_role(self, role_name, mount_point=DEFAULT_MOUNT_POINT): - """Delete the named token role. - - Supported methods: - DELETE: /auth/{mount_point}/roles/{role_name}. - - :param role_name: The name of the token role. - :type role_name: str - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str - :return: The response of the delete_role request. - :rtype: requests.Response - """ - api_path = "/v1/auth/{mount_point}/roles/{role_name}".format( - mount_point=mount_point, - role_name=role_name, - ) - return self._adapter.delete( - url=api_path, - ) - - def tidy(self, mount_point=DEFAULT_MOUNT_POINT): - """Perform some maintenance tasks to clean up invalid entries that may remain in the token store. - - On Enterprise, Tidy will only impact the tokens in the specified namespace, or the root namespace if unspecified. - - Supported methods: - POST: /auth/{mount_point}/tidy. - - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str - :return: The response of the tidy_s request. - :rtype: requests.Response - """ - api_path = f"/v1/auth/{mount_point}/tidy" - return self._adapter.post( - url=api_path, - ) diff --git a/.venv/lib/python3.12/site-packages/hvac/api/auth_methods/userpass.py b/.venv/lib/python3.12/site-packages/hvac/api/auth_methods/userpass.py deleted file mode 100644 index bbfb445..0000000 --- a/.venv/lib/python3.12/site-packages/hvac/api/auth_methods/userpass.py +++ /dev/null @@ -1,167 +0,0 @@ -#!/usr/bin/env python -"""USERPASS methods module.""" -from hvac import utils -from hvac.api.vault_api_base import VaultApiBase - -DEFAULT_MOUNT_POINT = "userpass" - - -class Userpass(VaultApiBase): - """USERPASS Auth Method (API). - Reference: https://www.vaultproject.io/api/auth/userpass/index.html - """ - - def create_or_update_user( - self, - username, - password=None, - policies=None, - mount_point=DEFAULT_MOUNT_POINT, - **kwargs, - ): - """ - Create/update user in userpass. - - Supported methods: - POST: /auth/{mount_point}/users/{username}. Produces: 204 (empty body) - - :param username: The username for the user. - :type username: str | unicode - :param password: The password for the user. Only required when creating the user. - :type password: str | unicode - :param policies: The list of policies to be set on username created. - :type policies: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :param kwargs: Additional arguments to pass along with the corresponding request to Vault. - :type kwargs: dict - """ - params = utils.remove_nones( - { - "password": password, - "policies": policies, - } - ) - params.update(kwargs) - - api_path = "/v1/auth/{mount_point}/users/{username}".format( - mount_point=mount_point, username=username - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def list_user(self, mount_point=DEFAULT_MOUNT_POINT): - """ - List existing users that have been created in the auth method - - Supported methods: - LIST: /auth/{mount_point}/users. Produces: 200 application/json - - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the list_groups request. - :rtype: dict - """ - api_path = f"/v1/auth/{mount_point}/users" - return self._adapter.list( - url=api_path, - ) - - def read_user(self, username, mount_point=DEFAULT_MOUNT_POINT): - """ - Read user in the auth method. - - Supported methods: - GET: /auth/{mount_point}/users/{username}. Produces: 200 application/json - - :param username: The username for the user. - :type name: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the read_group request. - :rtype: dict - """ - api_path = "/v1/auth/{mount_point}/users/{username}".format( - mount_point=mount_point, username=username - ) - return self._adapter.get( - url=api_path, - ) - - def delete_user(self, username, mount_point=DEFAULT_MOUNT_POINT): - """ - Delete user in the auth method. - - Supported methods: - GET: /auth/{mount_point}/users/{username}. Produces: 200 application/json - - :param username: The username for the user. - :type name: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the read_group request. - :rtype: dict - """ - api_path = "/v1/auth/{mount_point}/users/{username}".format( - mount_point=mount_point, username=username - ) - return self._adapter.delete( - url=api_path, - ) - - def update_password_on_user( - self, username, password, mount_point=DEFAULT_MOUNT_POINT - ): - """ - update password for the user in userpass. - - Supported methods: - POST: /auth/{mount_point}/users/{username}/password. Produces: 204 (empty body) - - :param username: The username for the user. - :type username: str | unicode - :param password: The password for the user. Only required when creating the user. - :type password: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - """ - params = { - "password": password, - } - api_path = "/v1/auth/{mount_point}/users/{username}/password".format( - mount_point=mount_point, username=username - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def login( - self, username, password, use_token=True, mount_point=DEFAULT_MOUNT_POINT - ): - """ - Log in with USERPASS credentials. - - Supported methods: - POST: /auth/{mount_point}/login/{username}. Produces: 200 application/json - - :param username: The username for the user. - :type username: str | unicode - :param password: The password for the user. Only required when creating the user. - :type password: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - """ - params = { - "password": password, - } - api_path = "/v1/auth/{mount_point}/login/{username}".format( - mount_point=mount_point, username=username - ) - return self._adapter.login( - url=api_path, - use_token=use_token, - json=params, - ) diff --git a/.venv/lib/python3.12/site-packages/hvac/api/secrets_engines/__init__.py b/.venv/lib/python3.12/site-packages/hvac/api/secrets_engines/__init__.py deleted file mode 100644 index 03cf0b5..0000000 --- a/.venv/lib/python3.12/site-packages/hvac/api/secrets_engines/__init__.py +++ /dev/null @@ -1,71 +0,0 @@ -"""Vault secrets engines endpoints""" -from hvac.api.secrets_engines.active_directory import ActiveDirectory -from hvac.api.secrets_engines.aws import Aws -from hvac.api.secrets_engines.azure import Azure -from hvac.api.secrets_engines.consul import Consul -from hvac.api.secrets_engines.database import Database -from hvac.api.secrets_engines.gcp import Gcp -from hvac.api.secrets_engines.identity import Identity -from hvac.api.secrets_engines.kv import Kv -from hvac.api.secrets_engines.kv_v1 import KvV1 -from hvac.api.secrets_engines.kv_v2 import KvV2 -from hvac.api.secrets_engines.ldap import Ldap -from hvac.api.secrets_engines.pki import Pki -from hvac.api.secrets_engines.rabbitmq import RabbitMQ -from hvac.api.secrets_engines.ssh import Ssh -from hvac.api.secrets_engines.transform import Transform -from hvac.api.secrets_engines.transit import Transit -from hvac.api.vault_api_category import VaultApiCategory - -__all__ = ( - "Aws", - "Azure", - "Gcp", - "ActiveDirectory", - "Identity", - "Kv", - "KvV1", - "KvV2", - "Ldap", - "Pki", - "Transform", - "Transit", - "SecretsEngines", - "Database", - "RabbitMQ", - "Ssh", -) - - -class SecretsEngines(VaultApiCategory): - """Secrets Engines.""" - - implemented_classes = [ - Aws, - Azure, - Gcp, - ActiveDirectory, - Identity, - Kv, - Ldap, - Pki, - Transform, - Transit, - Database, - Consul, - RabbitMQ, - Ssh, - ] - unimplemented_classes = [ - "AliCloud", - "Azure", - "GcpKms", - "Nomad", - "Ssh", - "TOTP", - "Cassandra", - "MongoDb", - "Mssql", - "MySql", - "PostgreSql", - ] diff --git a/.venv/lib/python3.12/site-packages/hvac/api/secrets_engines/__pycache__/__init__.cpython-312.pyc b/.venv/lib/python3.12/site-packages/hvac/api/secrets_engines/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index 87452b47ca47e03333287da1806c8700bd0b7ef9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1962 zcmah}OK&4Z5bm+Z_V{h*xtpgq5LhGDLjpo8gpjOc6`_y^n`jSxX|-n>dz9`OXL{_F zb3h#SKkS_Y65_&{zrba=c}Mbz6BiT_xa^7QwgU*Qy)FBzuWPEitE;Q(=VCF3V4VE) zUFXL%LcglX?MO|?&F?^-BNt)h8g7CcB7qZz;z^zqCN?!Uc}k>lTJsdo2n$=9r+HT7 za8C0K&x-;sXm0VMDB+UkSzZE4+^9o-V8+b$WD&G_}T+@7x-xFJS3-~;KD}fG>yYLLTi)`zM=|)|lV+e5Rz^4Lm=RzbWgw5to}zAdVAwh~}Y?aq2h_)YbmP=K0C_X`J1oQc~XyX`DF<{C2S4ic?2YUUCqFGZ4Ac zKt}D50Y9!U#1ju(;1JhUo9D>t-21JmlzDr-$iWBz)* zyqbPtF8@(0tfzl5?}qQdE_%=7`gXVllen&YX@D<{|M}9Oy6lL1TX#B>(`#)Rom(6I-IeUH|Y<$O5@e3M_%-G3D3CS zMW6I{bcw&gXjiv@czx@DrFC z@Ruh5*Ga=LUZU+0dNe}skI)Arv^zo{YYzC{2-*7AxYdBo!x8!j@Y<~A6W?V1yuWFr NUo39_g+S^9{|1HFKnnl> diff --git a/.venv/lib/python3.12/site-packages/hvac/api/secrets_engines/__pycache__/active_directory.cpython-312.pyc b/.venv/lib/python3.12/site-packages/hvac/api/secrets_engines/__pycache__/active_directory.cpython-312.pyc deleted file mode 100644 index 491877cd9c2a4d724ba53902244b2ccf557f9eb0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8010 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 xx97xpyduUme+VY^XGjjcyR)8| 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 Ba}NLj diff --git a/.venv/lib/python3.12/site-packages/hvac/api/secrets_engines/__pycache__/azure.cpython-312.pyc b/.venv/lib/python3.12/site-packages/hvac/api/secrets_engines/__pycache__/azure.cpython-312.pyc deleted file mode 100644 index a4b9828108d622084779e1101c6543a1f7512cb0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8092 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 diff --git a/.venv/lib/python3.12/site-packages/hvac/api/secrets_engines/__pycache__/database.cpython-312.pyc b/.venv/lib/python3.12/site-packages/hvac/api/secrets_engines/__pycache__/database.cpython-312.pyc deleted file mode 100644 index 517560441828115b4e6b995cf07d55e916fc859f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15835 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 diff --git a/.venv/lib/python3.12/site-packages/hvac/api/secrets_engines/__pycache__/gcp.cpython-312.pyc b/.venv/lib/python3.12/site-packages/hvac/api/secrets_engines/__pycache__/gcp.cpython-312.pyc deleted file mode 100644 index 057d8c37e379bbab660fc958a0fe3583271542f9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 28375 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 KZ-M@@R{tM+(_97s diff --git a/.venv/lib/python3.12/site-packages/hvac/api/secrets_engines/__pycache__/identity.cpython-312.pyc b/.venv/lib/python3.12/site-packages/hvac/api/secrets_engines/__pycache__/identity.cpython-312.pyc deleted file mode 100644 index 43d814d0bde4e69a1bdbddb61e032765431c0984..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 56795 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 diff --git a/.venv/lib/python3.12/site-packages/hvac/api/secrets_engines/__pycache__/kv_v1.cpython-312.pyc b/.venv/lib/python3.12/site-packages/hvac/api/secrets_engines/__pycache__/kv_v1.cpython-312.pyc deleted file mode 100644 index d129ba35897655e0910fff92ceb0a63b27712662..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6164 zcmd^DO>7j&6|SD18JqDB#xr18?4>Yf@en+N7dDa1k1*h631C~;Sc)&L_H^0Pc29S2 zb?KkzI62sAB}$^4_BM$fDdG_2y{?`gJ0Q$% zqO6kAsJgnQ>b+O5UVZhw{&h!3fB! z%ti|8tg7Iqz*rH3E$% zgppYVtc)1StjePEVCzF=HWsv0XvK{vv?E}jGTRdL#-Y_(j;34uC|bAb+?t_Nff|pF z*$bx4=n$P@+yletFdZD7yqV4<5){f^HqSV-b8Lj>g>b!*Y<78hIa5NDUG6NhoXD6? zR(H*;G~CNBmEbp28qVZJ!3u=rLKg+gKzHN&)?%<2p#;59E!LJ<>wu@BR3a7Sd8Fp# zHMK$(qfGjg_Eps9>a$S#6iG+*&*9}R6WnAaMn#@cX))D>d~;dOoHv<4Ehner zCWSsgKTH)}*Wm*G47YY9SQ-9><;K|b2+iIvI7M4%u4CF_EqmY9MSd+qCpiQ`j(H>W z{j+DO?z)yK#b*~i$4*E;qmU6-=X!zSv=KTLTH^(_VIOtoo2?cOv*PcAnd%M8>Yx!b8NvKOUvbT zdx3e{ls;G1q`qvX#OzYmGUu{x84$!iml=LP3$xjftLK(<7@p0S^j!0K)8sDTxzpg# zxn;kt$y=*kc;YinJ^R5%?;=zW$aXJD9oa~pSWlkVY=7_5TfZ>2)krGwsI?j=U8x_e zeRpkRKV9EXH@gm3Rnm2Qi$uB-RT9~k*n;`wD{`!l0h++Eh5({EwM;LF`z2PUwq9V~ zo=*3Nj%5J+QJn)Q6zAv76$s^J6V6-~&ljVn?G^EXC3Fic6)n|s08O4b2iBKN z9c%>kIj2z2ZDa57cl+kl7so$5Fj(FS{s0!8!21mtKpFoJScoAWVxb3twihtu$bNVm zR-I6VD95|7;{a5C6ov96H0v0~fhQ5ay;~`;Uic(%(Q6 zei)>T=W0X@UPzrKd;*vD6H-wh9NI_V?ys{293)FcsYIVE&qDS91T6wAK{eE+L0H`f zqRtE!TWd2KPa|510>7w}xV0GQ2&iIX47L^#?RS+*tP*)1uj!ov8;!`nRVO0#uCiOF z(Xxp9x2pj2X?+%YYAr4RA7xqWuC*G^O1w7mJIVKyDWZ$hTU{M- z-@qFuC-w-O=jk9TxS~ww9HX4Bi$~0xytg;(-6f(fvV;GVP_q@Lb^+{JXQ2IEC9g6ymeM3fJA zAjB8Qsgvq65O5$7?)Tu5hri?aMNWnGeReVq!jcA+@ApxK|it;%vDTbm23A5oNo+SIw(URO+hWhA03pjkgkt| z*)qejAVXxvj)gCkY9Jw(lA&-aZ3igHLa?HM0dc2f8sIuySU^hZmYtzUfnjq6o``@5 zK)%HQB^JOPU@Q26@d9MEJG3t6&0Idr-cSQ1V%%{#2G4Gf)x7eWY~{b3AMH+!;VSgrQ}C3b6uV4myYUhiW=~#+&9yP z(`1In@`8+-Fj(MBILpj9L;LSb0c#*3oCn`S;<7WH;60#=So>S{Rr#8Dz|E%p-1CXN~?tJtS?j@Ot;~r$fK(zVf2|%HOxok<_~z$@F?M z{a2#ELXRB#QM{@`>!pWW<>A4r=gBY6AH3GCe%7Wy{S`?g{{dTcomqe#A#%ZfLVEP& zzYSdXChm<-Ym*Z<$EPK>9tE5DDXdOI^^^pOSO9h$lck{A z2MzBVP(37niKwwwz?7jY007BYqI#NSMxogQ>en@WlroZK;=Hqe}JL3dvqown-|M zkTOx+c)FEm;OR&40uO*)er@Z)_Y8bRli!s!{GNtiML1@GJd0Ie&RJ|>t{9m3vh|`| v`DK0%`Y_+|`k?}>QItQCcm6>7e^1W-@zA?3NOC)VBcdc8UHlutXCULB{`ICU diff --git a/.venv/lib/python3.12/site-packages/hvac/api/secrets_engines/__pycache__/kv_v2.cpython-312.pyc b/.venv/lib/python3.12/site-packages/hvac/api/secrets_engines/__pycache__/kv_v2.cpython-312.pyc deleted file mode 100644 index cce6b684d93f22a3f2388607260daaf3b92c558e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20335 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 diff --git a/.venv/lib/python3.12/site-packages/hvac/api/secrets_engines/__pycache__/ldap.cpython-312.pyc b/.venv/lib/python3.12/site-packages/hvac/api/secrets_engines/__pycache__/ldap.cpython-312.pyc deleted file mode 100644 index 82d1e653194d0dbb91755e0df500b60900486be3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10793 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 diff --git a/.venv/lib/python3.12/site-packages/hvac/api/secrets_engines/__pycache__/ssh.cpython-312.pyc b/.venv/lib/python3.12/site-packages/hvac/api/secrets_engines/__pycache__/ssh.cpython-312.pyc deleted file mode 100644 index cd911fef1a14d1cf0211eab0c9f1ff5ec14fdebc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20664 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 <#vb4pW#_{?XlJ}--0t%IA7Y%&_kY6i-6K8^ z1UpBt7;TD=G&D+XQSvS&6-q+KiV>7`jupu8(76#Bk6D`l@OGXZD10UVMFN<{!a3r# zn6U6fYhs$Bk>{3L(}yTCfBdUlnjI(nF;GwaV&Su=qwdcBrrG5we7i^@VIoO(Mw0lK z+mIiTr1u(f#i<#TaBZxF;)$1De&y1Q*H@)CuHLw^D!qC2@|9I%o@TyC$?sC~A|>QU zFLfqjT0GWTINVx%qP1|eB`&o@WW?6o5lYb*kOvGWS#ds9L@qbRK${1k&j=S@iR}ra$R4L&0Ml@mYKM=a zXH0`nYLMDKPhGIwMFI1`Yz{BB#^zgN!E5)YzLVnqZnm&jKw$4-aqT31CW?RCYKF1}d@+iDGESoJRnaX!gB(}}MJ(}+ zF)2sU?QF9iq%U&(dEOwOIrd60myom*u~_V1gcH9OrvF(u`{ne)t}t;wBd24T4^RK6 JK>xEo{s$|kU#$QD diff --git a/.venv/lib/python3.12/site-packages/hvac/api/secrets_engines/__pycache__/transform.cpython-312.pyc b/.venv/lib/python3.12/site-packages/hvac/api/secrets_engines/__pycache__/transform.cpython-312.pyc deleted file mode 100644 index 3c12a37ea90d969f2927edc06fe7a9aa7360a294..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 44285 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 Y+ksm~=F9HyZcX(6WZ>@%`pb3vBP8ca_5c6? diff --git a/.venv/lib/python3.12/site-packages/hvac/api/secrets_engines/__pycache__/transit.cpython-312.pyc b/.venv/lib/python3.12/site-packages/hvac/api/secrets_engines/__pycache__/transit.cpython-312.pyc deleted file mode 100644 index c4f9e175b16fa3c377a6fed1d6dd0195cdd9071e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 48326 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 CMS;Ko diff --git a/.venv/lib/python3.12/site-packages/hvac/api/secrets_engines/active_directory.py b/.venv/lib/python3.12/site-packages/hvac/api/secrets_engines/active_directory.py deleted file mode 100644 index a980f2b..0000000 --- a/.venv/lib/python3.12/site-packages/hvac/api/secrets_engines/active_directory.py +++ /dev/null @@ -1,181 +0,0 @@ -#!/usr/bin/env python -"""Active Directory methods module.""" - -from hvac import utils -from hvac.api.vault_api_base import VaultApiBase - -DEFAULT_MOUNT_POINT = "ad" - - -class ActiveDirectory(VaultApiBase): - """Active Directory Secrets Engine (API). - Reference: https://www.vaultproject.io/api/secret/ad/index.html - """ - - def configure( - self, - binddn=None, - bindpass=None, - url=None, - userdn=None, - upndomain=None, - ttl=None, - max_ttl=None, - mount_point=DEFAULT_MOUNT_POINT, - *args, - **kwargs - ): - """Configure shared information for the ad secrets engine. - - Supported methods: - POST: /{mount_point}/config. Produces: 204 (empty body) - - :param binddn: Distinguished name of object to bind when performing user and group search. - :type binddn: str | unicode - :param bindpass: Password to use along with binddn when performing user search. - :type bindpass: str | unicode - :param url: Base DN under which to perform user search. - :type url: str | unicode - :param userdn: Base DN under which to perform user search. - :type userdn: str | unicode - :param upndomain: userPrincipalDomain used to construct the UPN string for the authenticating user. - :type upndomain: str | unicode - :param ttl: – The default password time-to-live in seconds. Once the ttl has passed, a password will be rotated the next time it's requested. - :type ttl: int | str - :param max_ttl: The maximum password time-to-live in seconds. No role will be allowed to set a custom ttl greater than the max_ttl - integer number of seconds or Go duration format string.** - :type max_ttl: int | str - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - params = utils.remove_nones( - { - "binddn": binddn, - "bindpass": bindpass, - "url": url, - "userdn": userdn, - "upndomain": upndomain, - "ttl": ttl, - "max_ttl": max_ttl, - } - ) - - params.update(kwargs) - - api_path = utils.format_url("/v1/{mount_point}/config", mount_point=mount_point) - return self._adapter.post( - url=api_path, - json=params, - ) - - def read_config(self, mount_point=DEFAULT_MOUNT_POINT): - """Read the configured shared information for the ad secrets engine. - - Credentials will be omitted from returned data. - - Supported methods: - GET: /{mount_point}/config. Produces: 200 application/json - - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the request. - :rtype: dict - """ - api_path = utils.format_url("/v1/{mount_point}/config", mount_point=mount_point) - return self._adapter.get( - url=api_path, - ) - - def create_or_update_role( - self, name, service_account_name=None, ttl=None, mount_point=DEFAULT_MOUNT_POINT - ): - """This endpoint creates or updates the ad role definition. - - :param name: Specifies the name of an existing role against which to create this ad credential. - :type name: str | unicode - :param service_account_name: The name of a pre-existing service account in Active Directory that maps to this role. - This value is required on create and optional on update. - :type service_account_name: str | unicode - :param ttl: Specifies the TTL for this role. - This is provided as a string duration with a time suffix like "30s" or "1h" or as seconds. - If not provided, the default Vault TTL is used. - :type ttl: str | unicode - :param mount_point: Specifies the place where the secrets engine will be accessible (default: ad). - :type mount_point: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url("/v1/{}/roles/{}", mount_point, name) - params = { - "name": name, - } - params.update( - utils.remove_nones( - { - "service_account_name": service_account_name, - "ttl": ttl, - } - ) - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def read_role(self, name, mount_point=DEFAULT_MOUNT_POINT): - """This endpoint queries for information about a ad role with the given name. - If no role exists with that name, a 404 is returned. - :param name: Specifies the name of the role to query. - :type name: str | unicode - :param mount_point: Specifies the place where the secrets engine will be accessible (default: ad). - :type mount_point: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url("/v1/{}/roles/{}", mount_point, name) - return self._adapter.get( - url=api_path, - ) - - def list_roles(self, mount_point=DEFAULT_MOUNT_POINT): - """This endpoint lists all existing roles in the secrets engine. - :return: The response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url("/v1/{}/roles", mount_point) - return self._adapter.list( - url=api_path, - ) - - def delete_role(self, name, mount_point=DEFAULT_MOUNT_POINT): - """This endpoint deletes a ad role with the given name. - Even if the role does not exist, this endpoint will still return a successful response. - :param name: Specifies the name of the role to delete. - :type name: str | unicode - :param mount_point: Specifies the place where the secrets engine will be accessible (default: ad). - :type mount_point: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url("/v1/{}/roles/{}", mount_point, name) - return self._adapter.delete( - url=api_path, - ) - - def generate_credentials(self, name, mount_point=DEFAULT_MOUNT_POINT): - """This endpoint retrieves the previous and current LDAP password for - the associated account (or rotate if required) - - :param name: Specifies the name of the role to request credentials from. - :type name: str | unicode - :param mount_point: Specifies the place where the secrets engine will be accessible (default: ad). - :type mount_point: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url("/v1/{}/creds/{}", mount_point, name) - return self._adapter.get( - url=api_path, - ) diff --git a/.venv/lib/python3.12/site-packages/hvac/api/secrets_engines/aws.py b/.venv/lib/python3.12/site-packages/hvac/api/secrets_engines/aws.py deleted file mode 100644 index 2eb1427..0000000 --- a/.venv/lib/python3.12/site-packages/hvac/api/secrets_engines/aws.py +++ /dev/null @@ -1,407 +0,0 @@ -#!/usr/bin/env python -"""Aws methods module.""" -import json - -from hvac import exceptions, utils -from hvac.api.vault_api_base import VaultApiBase -from hvac.constants.aws import ( - DEFAULT_MOUNT_POINT, - ALLOWED_CREDS_ENDPOINTS, - ALLOWED_CREDS_TYPES, -) - - -class Aws(VaultApiBase): - """AWS Secrets Engine (API). - - Reference: https://www.vaultproject.io/api/secret/aws/index.html - """ - - def configure_root_iam_credentials( - self, - access_key, - secret_key, - region=None, - iam_endpoint=None, - sts_endpoint=None, - max_retries=None, - mount_point=DEFAULT_MOUNT_POINT, - ): - """Configure the root IAM credentials to communicate with AWS. - - There are multiple ways to pass root IAM credentials to the Vault server, specified below with the highest - precedence first. If credentials already exist, this will overwrite them. - - The official AWS SDK is used for sourcing credentials from env vars, shared files, or IAM/ECS instances. - - * Static credentials provided to the API as a payload - * Credentials in the AWS_ACCESS_KEY, AWS_SECRET_KEY, and AWS_REGION environment variables on the server - * Shared credentials files - * Assigned IAM role or ECS task role credentials - - At present, this endpoint does not confirm that the provided AWS credentials are valid AWS credentials with - proper permissions. - - Supported methods: - POST: /{mount_point}/config/root. Produces: 204 (empty body) - - :param access_key: Specifies the AWS access key ID. - :type access_key: str | unicode - :param secret_key: Specifies the AWS secret access key. - :type secret_key: str | unicode - :param region: Specifies the AWS region. If not set it will use the AWS_REGION env var, AWS_DEFAULT_REGION env - var, or us-east-1 in that order. - :type region: str | unicode - :param iam_endpoint: Specifies a custom HTTP IAM endpoint to use. - :type iam_endpoint: str | unicode - :param sts_endpoint: Specifies a custom HTTP STS endpoint to use. - :type sts_endpoint: str | unicode - :param max_retries: Number of max retries the client should use for recoverable errors. The default (-1) falls - back to the AWS SDK's default behavior. - :type max_retries: int - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - params = { - "access_key": access_key, - "secret_key": secret_key, - "max_retries": max_retries, - } - params.update( - utils.remove_nones( - { - "region": region, - "iam_endpoint": iam_endpoint, - "sts_endpoint": sts_endpoint, - } - ) - ) - api_path = utils.format_url( - "/v1/{mount_point}/config/root", mount_point=mount_point - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def rotate_root_iam_credentials(self, mount_point=DEFAULT_MOUNT_POINT): - """Rotate static root IAM credentials. - - When you have configured Vault with static credentials, you can use this endpoint to have Vault rotate the - access key it used. Note that, due to AWS eventual consistency, after calling this endpoint, subsequent calls - from Vault to AWS may fail for a few seconds until AWS becomes consistent again. - - In order to call this endpoint, Vault's AWS access key MUST be the only access key on the IAM user; otherwise, - generation of a new access key will fail. Once this method is called, Vault will now be the only entity that - knows the AWS secret key is used to access AWS. - - Supported methods: - POST: /{mount_point}/config/rotate-root. Produces: 200 application/json - - :return: The JSON response of the request. - :rtype: dict - """ - api_path = utils.format_url( - "/v1/{mount_point}/config/rotate-root", mount_point=mount_point - ) - return self._adapter.post( - url=api_path, - ) - - def configure_lease(self, lease, lease_max, mount_point=DEFAULT_MOUNT_POINT): - """Configure lease settings for the AWS secrets engine. - - It is optional, as there are default values for lease and lease_max. - - Supported methods: - POST: /{mount_point}/config/lease. Produces: 204 (empty body) - - :param lease: Specifies the lease value provided as a string duration with time suffix. "h" (hour) is the - largest suffix. - :type lease: str | unicode - :param lease_max: Specifies the maximum lease value provided as a string duration with time suffix. "h" (hour) - is the largest suffix. - :type lease_max: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - params = { - "lease": lease, - "lease_max": lease_max, - } - api_path = utils.format_url( - "/v1/{mount_point}/config/lease", mount_point=mount_point - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def read_lease_config(self, mount_point=DEFAULT_MOUNT_POINT): - """Read the current lease settings for the AWS secrets engine. - - Supported methods: - GET: /{mount_point}/config/lease. Produces: 200 application/json - - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the request. - :rtype: dict - """ - api_path = utils.format_url( - "/v1/{mount_point}/config/lease", mount_point=mount_point - ) - return self._adapter.get( - url=api_path, - ) - - def create_or_update_role( - self, - name, - credential_type, - policy_document=None, - default_sts_ttl=None, - max_sts_ttl=None, - role_arns=None, - policy_arns=None, - legacy_params=False, - iam_tags=None, - mount_point=DEFAULT_MOUNT_POINT, - ): - """Create or update the role with the given name. - - If a role with the name does not exist, it will be created. If the role exists, it will be updated with the new - attributes. - - Supported methods: - POST: /{mount_point}/roles/{name}. Produces: 204 (empty body) - - :param name: Specifies the name of the role to create. This is part of the request URL. - :type name: str | unicode - :param credential_type: Specifies the type of credential to be used when retrieving credentials from the role. - Must be one of iam_user, assumed_role, or federation_token. - :type credential_type: str | unicode - :param policy_document: The IAM policy document for the role. The behavior depends on the credential type. With - iam_user, the policy document will be attached to the IAM user generated and augment the permissions the IAM - user has. With assumed_role and federation_token, the policy document will act as a filter on what the - credentials can do. - :type policy_document: dict | str | unicode - :param default_sts_ttl: The default TTL for STS credentials. When a TTL is not specified when STS credentials - are requested, and a default TTL is specified on the role, then this default TTL will be used. Valid only - when credential_type is one of assumed_role or federation_token. - :type default_sts_ttl: str | unicode - :param max_sts_ttl: The max allowed TTL for STS credentials (credentials TTL are capped to max_sts_ttl). Valid - only when credential_type is one of assumed_role or federation_token. - :type max_sts_ttl: str | unicode - :param role_arns: Specifies the ARNs of the AWS roles this Vault role is allowed to assume. Required when - credential_type is assumed_role and prohibited otherwise. This is a comma-separated string or JSON array. - String types supported for Vault legacy parameters. - :type role_arns: list | str | unicode - :param policy_arns: Specifies the ARNs of the AWS managed policies to be attached to IAM users when they are - requested. Valid only when credential_type is iam_user. When credential_type is iam_user, at least one of - policy_arns or policy_document must be specified. This is a comma-separated string or JSON array. - :type policy_arns: list - :param legacy_params: Flag to send legacy (Vault versions < 0.11.0) parameters in the request. When this is set - to True, policy_document and policy_arns are the only parameters used from this method. - :type legacy_params: bool - :param iam_tags: A list of strings representing a key/value pair to be used for any IAM user that is created by - this role. Format is a key and value separated by an =. - :type iam_tags: list - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - if credential_type not in ALLOWED_CREDS_TYPES: - error_msg = 'invalid credential_type argument provided "{arg}", supported types: "{allowed_types}"' - raise exceptions.ParamValidationError( - error_msg.format( - arg=credential_type, - allowed_types=", ".join(ALLOWED_CREDS_TYPES), - ) - ) - if isinstance(policy_document, dict): - policy_document = json.dumps(policy_document, indent=4, sort_keys=True) - - if legacy_params: - # Support for Vault <0.11.0 - params = { - "policy": policy_document, - "arn": policy_arns[0] if isinstance(policy_arns, list) else policy_arns, - } - else: - params = { - "credential_type": credential_type, - } - params.update( - utils.remove_nones( - { - "policy_document": policy_document, - "default_sts_ttl": default_sts_ttl, - "max_sts_ttl": max_sts_ttl, - "role_arns": role_arns, - "policy_arns": policy_arns, - "iam_tags": iam_tags, - } - ) - ) - api_path = utils.format_url( - "/v1/{mount_point}/roles/{name}", - mount_point=mount_point, - name=name, - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def read_role(self, name, mount_point=DEFAULT_MOUNT_POINT): - """Query an existing role by the given name. - - If the role does not exist, a 404 is returned. - - Supported methods: - GET: /{mount_point}/roles/{name}. Produces: 200 application/json - - :param name: Specifies the name of the role to read. This is part of the request URL. - :type name: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the request. - :rtype: dict - """ - api_path = utils.format_url( - "/v1/{mount_point}/roles/{name}", - mount_point=mount_point, - name=name, - ) - return self._adapter.get( - url=api_path, - ) - - def list_roles(self, mount_point=DEFAULT_MOUNT_POINT): - """List all existing roles in the secrets engine. - - Supported methods: - LIST: /{mount_point}/roles. Produces: 200 application/json - - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the request. - :rtype: dict - """ - api_path = utils.format_url("/v1/{mount_point}/roles", mount_point=mount_point) - return self._adapter.list( - url=api_path, - ) - - def delete_role(self, name, mount_point=DEFAULT_MOUNT_POINT): - """Delete an existing role by the given name. - - If the role does not exist, a 404 is returned. - - Supported methods: - DELETE: /{mount_point}/roles/{name}. Produces: 204 (empty body) - - :param name: the name of the role to delete. This - is part of the request URL. - :type name: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url( - "/v1/{mount_point}/roles/{name}", - mount_point=mount_point, - name=name, - ) - return self._adapter.delete( - url=api_path, - ) - - def generate_credentials( - self, - name, - role_arn=None, - ttl=None, - endpoint="creds", - mount_point=DEFAULT_MOUNT_POINT, - role_session_name=None, - ): - """Generates credential based on the named role. - - This role must be created before queried. - - The ``/aws/creds`` and ``/aws/sts`` endpoints are almost identical. The exception is when retrieving credentials for a - role that was specified with the legacy arn or policy parameter. In this case, credentials retrieved through - ``/aws/sts`` must be of either the ``assumed_role`` or ``federation_token`` types, and credentials retrieved through - ``/aws/creds`` must be of the ``iam_user`` type. - - :param name: Specifies the name of the role to generate credentials against. This is part of the request URL. - :type name: str | unicode - :param role_arn: The ARN of the role to assume if ``credential_type`` on the Vault role is assumed_role. Must match - one of the allowed role ARNs in the Vault role. Optional if the Vault role only allows a single AWS role - ARN; required otherwise. - :type role_arn: str | unicode - :param ttl: Specifies the TTL for the use of the STS token. This is specified as a string with a duration - suffix. Valid only when ``credential_type`` is ``assumed_role`` or ``federation_token``. When not specified, the default - sts_ttl set for the role will be used. If that is also not set, then the default value of ``3600s`` will be - used. AWS places limits on the maximum TTL allowed. See the AWS documentation on the ``DurationSeconds`` - parameter for AssumeRole (for ``assumed_role`` credential types) and GetFederationToken (for ``federation_token`` - credential types) for more details. - :type ttl: str | unicode - :param endpoint: Supported endpoints are ``creds`` and ``sts``: - GET: ``/{mount_point}/creds/{name}``. Produces: 200 application/json - POST: ``/{mount_point}/sts/{name}``. Produces: 200 application/json - :type endpoint: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :param role_session_name: The role session name to attach to the assumed role ARN. - ``role_session_name`` is limited to 64 characters; if exceeded, the ``role_session_name`` in the assumed role - ARN will be truncated to 64 characters. If ``role_session_name`` is not provided, then it will be generated - dynamically by default. - :type role_session_name: str | unicode - - :return: The JSON response of the request. - :rtype: dict - """ - if endpoint not in ALLOWED_CREDS_ENDPOINTS: - error_msg = 'invalid endpoint argument provided "{arg}", supported types: "{allowed_endpoints}"' - raise exceptions.ParamValidationError( - error_msg.format( - arg=endpoint, - allowed_endpoints=", ".join(ALLOWED_CREDS_ENDPOINTS), - ) - ) - params = {} - params.update( - utils.remove_nones( - { - "role_arn": role_arn, - "role_session_name": role_session_name, - "ttl": ttl, - } - ) - ) - api_path = utils.format_url( - "/v1/{mount_point}/{endpoint}/{name}", - mount_point=mount_point, - endpoint=endpoint, - name=name, - ) - - if endpoint == "sts": - return self._adapter.post( - url=api_path, - json=params, - ) - else: - return self._adapter.get( - url=api_path, - params=params, - ) diff --git a/.venv/lib/python3.12/site-packages/hvac/api/secrets_engines/azure.py b/.venv/lib/python3.12/site-packages/hvac/api/secrets_engines/azure.py deleted file mode 100644 index 6764970..0000000 --- a/.venv/lib/python3.12/site-packages/hvac/api/secrets_engines/azure.py +++ /dev/null @@ -1,201 +0,0 @@ -#!/usr/bin/env python -"""Azure secret engine methods module.""" -import json - -from hvac import exceptions, utils -from hvac.api.vault_api_base import VaultApiBase -from hvac.constants.azure import VALID_ENVIRONMENTS - -DEFAULT_MOUNT_POINT = "azure" - - -class Azure(VaultApiBase): - """Azure Secrets Engine (API). - - Reference: https://www.vaultproject.io/api/secret/azure/index.html - """ - - def configure( - self, - subscription_id, - tenant_id, - client_id=None, - client_secret=None, - environment=None, - mount_point=DEFAULT_MOUNT_POINT, - ): - """Configure the credentials required for the plugin to perform API calls to Azure. - - These credentials will be used to query roles and create/delete service principals. Environment variables will - override any parameters set in the config. - - Supported methods: - POST: /{mount_point}/config. Produces: 204 (empty body) - - - :param subscription_id: The subscription id for the Azure Active Directory - :type subscription_id: str | unicode - :param tenant_id: The tenant id for the Azure Active Directory. - :type tenant_id: str | unicode - :param client_id: The OAuth2 client id to connect to Azure. - :type client_id: str | unicode - :param client_secret: The OAuth2 client secret to connect to Azure. - :type client_secret: str | unicode - :param environment: The Azure environment. If not specified, Vault will use Azure Public Cloud. - :type environment: str | unicode - :param mount_point: The OAuth2 client secret to connect to Azure. - :type mount_point: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - if environment is not None and environment not in VALID_ENVIRONMENTS: - error_msg = 'invalid environment argument provided "{arg}", supported environments: "{environments}"' - raise exceptions.ParamValidationError( - error_msg.format( - arg=environment, - environments=",".join(VALID_ENVIRONMENTS), - ) - ) - params = { - "subscription_id": subscription_id, - "tenant_id": tenant_id, - } - params.update( - utils.remove_nones( - { - "client_id": client_id, - "client_secret": client_secret, - "environment": environment, - } - ) - ) - api_path = utils.format_url("/v1/{mount_point}/config", mount_point=mount_point) - return self._adapter.post( - url=api_path, - json=params, - ) - - def read_config(self, mount_point=DEFAULT_MOUNT_POINT): - """Read the stored configuration, omitting client_secret. - - Supported methods: - GET: /{mount_point}/config. Produces: 200 application/json - - - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The data key from the JSON response of the request. - :rtype: dict - """ - api_path = utils.format_url("/v1/{mount_point}/config", mount_point=mount_point) - response = self._adapter.get( - url=api_path, - ) - return response.get("data") - - def delete_config(self, mount_point=DEFAULT_MOUNT_POINT): - """Delete the stored Azure configuration and credentials. - - Supported methods: - DELETE: /auth/{mount_point}/config. Produces: 204 (empty body) - - - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url("/v1/{mount_point}/config", mount_point=mount_point) - return self._adapter.delete( - url=api_path, - ) - - def create_or_update_role( - self, name, azure_roles, ttl=None, max_ttl=None, mount_point=DEFAULT_MOUNT_POINT - ): - """Create or update a Vault role. - - The provided Azure roles must exist for this call to succeed. See the Azure secrets roles docs for more - information about roles. - - Supported methods: - POST: /{mount_point}/roles/{name}. Produces: 204 (empty body) - - - :param name: Name of the role. - :type name: str | unicode - :param azure_roles: List of Azure roles to be assigned to the generated service principal. - :type azure_roles: list(dict) - :param ttl: Specifies the default TTL for service principals generated using this role. Accepts time suffixed - strings ("1h") or an integer number of seconds. Defaults to the system/engine default TTL time. - :type ttl: str | unicode - :param max_ttl: Specifies the maximum TTL for service principals generated using this role. Accepts time - suffixed strings ("1h") or an integer number of seconds. Defaults to the system/engine max TTL time. - :type max_ttl: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - params = { - "azure_roles": json.dumps(azure_roles), - } - params.update( - utils.remove_nones( - { - "ttl": ttl, - "max_ttl": max_ttl, - } - ) - ) - api_path = utils.format_url( - "/v1/{mount_point}/roles/{name}", - mount_point=mount_point, - name=name, - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def list_roles(self, mount_point=DEFAULT_MOUNT_POINT): - """List all of the roles that are registered with the plugin. - - Supported methods: - LIST: /{mount_point}/roles. Produces: 200 application/json - - - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The data key from the JSON response of the request. - :rtype: dict - """ - api_path = utils.format_url("/v1/{mount_point}/roles", mount_point=mount_point) - response = self._adapter.list( - url=api_path, - ) - return response.get("data") - - def generate_credentials(self, name, mount_point=DEFAULT_MOUNT_POINT): - """Generate a new service principal based on the named role. - - Supported methods: - GET: /{mount_point}/creds/{name}. Produces: 200 application/json - - - :param name: Specifies the name of the role to create credentials against. - :type name: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The data key from the JSON response of the request. - :rtype: dict - """ - api_path = utils.format_url( - "/v1/{mount_point}/creds/{name}", - mount_point=mount_point, - name=name, - ) - response = self._adapter.get( - url=api_path, - ) - return response.get("data") diff --git a/.venv/lib/python3.12/site-packages/hvac/api/secrets_engines/consul.py b/.venv/lib/python3.12/site-packages/hvac/api/secrets_engines/consul.py deleted file mode 100644 index 13376a0..0000000 --- a/.venv/lib/python3.12/site-packages/hvac/api/secrets_engines/consul.py +++ /dev/null @@ -1,171 +0,0 @@ -#!/usr/bin/env python -"""Consul methods module.""" -from hvac import utils -from hvac.api.vault_api_base import VaultApiBase - -DEFAULT_MOUNT_POINT = "consul" - - -class Consul(VaultApiBase): - """Copnsul Secrets Engine (API). - - Reference: https://www.vaultproject.io/api/secret/consul/index.html - """ - - def configure_access( - self, address, token, scheme=None, mount_point=DEFAULT_MOUNT_POINT - ): - """This endpoint configures the access information for Consul. - This access information is used so that Vault can communicate with Consul and generate Consul tokens. - - :param address: Specifies the address of the Consul instance, provided as "host:port" like "127.0.0.1:8500". - :type address: str | unicode - :param token: Specifies the Consul ACL token to use. This must be a management type token. - :type token: str | unicode - :param scheme: Specifies the URL scheme to use. - :type scheme: str | unicode - :param mount_point: Specifies the place where the secrets engine will be accessible (default: consul). - :type mount_point: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - params = { - "address": address, - "token": token, - } - params.update( - utils.remove_nones( - { - "scheme": scheme, - } - ) - ) - - api_path = utils.format_url("/v1/{}/config/access", mount_point) - return self._adapter.post( - url=api_path, - json=params, - ) - - def create_or_update_role( - self, - name, - policy=None, - policies=None, - token_type=None, - local=None, - ttl=None, - max_ttl=None, - mount_point=DEFAULT_MOUNT_POINT, - ): - """This endpoint creates or updates the Consul role definition. - If the role does not exist, it will be created. - If the role already exists, it will receive updated attributes. - - :param name: Specifies the name of an existing role against which to create this Consul credential. - :type name: str | unicode - :param token_type: Specifies the type of token to create when using this role. - Valid values are "client" or "management". - :type token_type: str | unicode - :param policy: Specifies the base64 encoded ACL policy. - The ACL format can be found in the Consul ACL documentation (https://www.consul.io/docs/internals/acl.html). - This is required unless the token_type is management. - :type policy: str | unicode - :param policies: The list of policies to assign to the generated token. - This is only available in Consul 1.4 and greater. - :type policies: list - :param local: Indicates that the token should not be replicated globally - and instead be local to the current datacenter. Only available in Consul 1.4 and greater. - :type local: bool - :param ttl: Specifies the TTL for this role. - This is provided as a string duration with a time suffix like "30s" or "1h" or as seconds. - If not provided, the default Vault TTL is used. - :type ttl: str | unicode - :param max_ttl: Specifies the max TTL for this role. - This is provided as a string duration with a time suffix like "30s" or "1h" or as seconds. - If not provided, the default Vault Max TTL is used. - :type max_ttl: str | unicode - :param mount_point: Specifies the place where the secrets engine will be accessible (default: consul). - :type mount_point: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url("/v1/{}/roles/{}", mount_point, name) - - params = utils.remove_nones( - { - "token_type": token_type, - "policy": policy, - "policies": policies, - "local": local, - "ttl": ttl, - "max_ttl": max_ttl, - } - ) - - return self._adapter.post( - url=api_path, - json=params, - ) - - def read_role(self, name, mount_point=DEFAULT_MOUNT_POINT): - """This endpoint queries for information about a Consul role with the given name. - If no role exists with that name, a 404 is returned. - - :param name: Specifies the name of the role to query. - :type name: str | unicode - :param mount_point: Specifies the place where the secrets engine will be accessible (default: consul). - :type mount_point: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - - api_path = utils.format_url("/v1/{}/roles/{}", mount_point, name) - - return self._adapter.get( - url=api_path, - ) - - def list_roles(self, mount_point=DEFAULT_MOUNT_POINT): - """This endpoint lists all existing roles in the secrets engine. - - :return: The response of the request. - :rtype: requests.Response - """ - - api_path = utils.format_url("/v1/{}/roles", mount_point) - return self._adapter.list( - url=api_path, - ) - - def delete_role(self, name, mount_point=DEFAULT_MOUNT_POINT): - """This endpoint deletes a Consul role with the given name. - Even if the role does not exist, this endpoint will still return a successful response. - - :param name: Specifies the name of the role to delete. - :type name: str | unicode - :param mount_point: Specifies the place where the secrets engine will be accessible (default: consul). - :type mount_point: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url("/v1/{}/roles/{}", mount_point, name) - return self._adapter.delete( - url=api_path, - ) - - def generate_credentials(self, name, mount_point=DEFAULT_MOUNT_POINT): - """This endpoint generates a dynamic Consul token based on the given role definition. - - :param name: Specifies the name of an existing role against which to create this Consul credential. - :type name: str | unicode - :param mount_point: Specifies the place where the secrets engine will be accessible (default: consul). - :type mount_point: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url("/v1/{}/creds/{}", mount_point, name) - - return self._adapter.get( - url=api_path, - ) diff --git a/.venv/lib/python3.12/site-packages/hvac/api/secrets_engines/database.py b/.venv/lib/python3.12/site-packages/hvac/api/secrets_engines/database.py deleted file mode 100644 index cac8e94..0000000 --- a/.venv/lib/python3.12/site-packages/hvac/api/secrets_engines/database.py +++ /dev/null @@ -1,405 +0,0 @@ -#!/usr/bin/env python -"""Database methods module.""" -from hvac import utils -from hvac.api.vault_api_base import VaultApiBase - -DEFAULT_MOUNT_POINT = "database" - - -class Database(VaultApiBase): - """Database Secrets Engine (API). - - Reference: https://www.vaultproject.io/api/secret/databases/index.html - """ - - def configure( - self, - name, - plugin_name, - verify_connection=None, - allowed_roles=None, - root_rotation_statements=None, - mount_point=DEFAULT_MOUNT_POINT, - *args, - **kwargs - ): - """This endpoint configures the connection string used to communicate with the desired database. - In addition to the parameters listed here, each Database plugin has additional, - database plugin specific, parameters for this endpoint. - Please read the HTTP API for the plugin you'd wish to configure to see the full list of additional parameters. - - :param name: Specifies the name for this database connection. This is specified as part of the URL. - :type name: str | unicode - :param plugin_name: Specifies the name of the plugin to use for this connection. - :type plugin_name: str | unicode - :param verify_connection: Specifies if the connection is verified during initial configuration. - :type verify_connection: bool - :param allowed_roles: List of the roles allowed to use this connection. Defaults to empty (no roles), - if contains a "*" any role can use this connection. - :type allowed_roles: list - :param root_rotation_statements: Specifies the database statements to be executed to rotate - the root user's credentials. - :type root_rotation_statements: list - :return: The response of the request. - :rtype: requests.Response - """ - params = { - "plugin_name": plugin_name, - } - params.update( - utils.remove_nones( - { - "allowed_roles": allowed_roles, - "verify_connection": verify_connection, - "root_rotation_statements": root_rotation_statements, - } - ) - ) - - params.update(kwargs) - - api_path = utils.format_url( - "/v1/{mount_point}/config/{name}", mount_point=mount_point, name=name - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def rotate_root_credentials(self, name, mount_point=DEFAULT_MOUNT_POINT): - """This endpoint is used to rotate the root superuser credentials stored for the database connection. - This user must have permissions to update its own password. - - :param name: Specifies the name of the connection to rotate. - :type name: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url( - "/v1/{mount_point}/rotate-root/{name}", mount_point=mount_point, name=name - ) - return self._adapter.post( - url=api_path, - ) - - def read_connection(self, name, mount_point=DEFAULT_MOUNT_POINT): - """This endpoint returns the configuration settings for a connection. - - :param name: Specifies the name of the connection to read. - :type name: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - - api_path = utils.format_url( - "/v1/{mount_point}/config/{name}", mount_point=mount_point, name=name - ) - - return self._adapter.get( - url=api_path, - ) - - def list_connections(self, mount_point=DEFAULT_MOUNT_POINT): - """This endpoint returns a list of available connections. - - :return: The response of the request. - :rtype: requests.Response - """ - - api_path = utils.format_url("/v1/{mount_point}/config", mount_point=mount_point) - return self._adapter.list( - url=api_path, - ) - - def delete_connection(self, name, mount_point=DEFAULT_MOUNT_POINT): - """This endpoint deletes a connection. - - - :param name: Specifies the name of the connection to delete. - :type name: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url( - "/v1/{mount_point}/config/{name}", mount_point=mount_point, name=name - ) - return self._adapter.delete( - url=api_path, - ) - - def reset_connection(self, name, mount_point=DEFAULT_MOUNT_POINT): - """This endpoint closes a connection and it's underlying plugin and - restarts it with the configuration stored in the barrier. - - :param name: Specifies the name of the connection to reset. - :type name: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url( - "/v1/{mount_point}/reset/{name}", mount_point=mount_point, name=name - ) - return self._adapter.post( - url=api_path, - ) - - def create_role( - self, - name, - db_name, - creation_statements, - default_ttl=None, - max_ttl=None, - revocation_statements=None, - rollback_statements=None, - renew_statements=None, - mount_point=DEFAULT_MOUNT_POINT, - ): - """This endpoint creates or updates a role definition. - - :param name: Specifies the database role to manage. - :type name: str | unicode - :param db_name: The name of the database connection to use for this role. - :type db_name: str | unicode - :param creation_statements: Specifies the database statements executed to create and configure a user. - :type creation_statements: list - :param default_ttl: Specifies the TTL for the leases associated with this role. - :type default_ttl: int - :param max_ttl: Specifies the maximum TTL for the leases associated with this role. - :type max_ttl: int - :param revocation_statements: Specifies the database statements to be executed to revoke a user. - :type revocation_statements: list - :param rollback_statements: Specifies the database statements to be executed to rollback - a create operation in the event of an error. - :type rollback_statements: list - :param renew_statements: Specifies the database statements to be executed to renew a user. - :type renew_statements: list - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - - params = { - "db_name": db_name, - "creation_statements": creation_statements, - } - params.update( - utils.remove_nones( - { - "default_ttl": default_ttl, - "max_ttl": max_ttl, - "revocation_statements": revocation_statements, - "rollback_statements": rollback_statements, - "renew_statements": renew_statements, - } - ) - ) - - api_path = utils.format_url( - "/v1/{mount_point}/roles/{name}", mount_point=mount_point, name=name - ) - return self._adapter.post(url=api_path, json=params) - - def create_static_role( - self, - name, - db_name, - username, - rotation_statements, - rotation_period=86400, - mount_point=DEFAULT_MOUNT_POINT, - ): - """This endpoint creates or updates a static role definition. - - :param name: Specifies the name of the role to create. - :type name: str | unicode - :param db_name: The name of the database connection to use for this role. - :type db_name: str | unicode - :param username: Specifies the database username that the Vault role `name` above corresponds to. - :type username: str | unicode - :param rotation_statements: Specifies the database statements to be executed to rotate the password for the configured database user. - Not every plugin type will support this functionality. See the plugin's API page for more information on support and - formatting for this parameter. - :type rotation_statements: list - :param rotation_period: Specifies the amount of time Vault should wait before rotating the password. The minimum is 5 seconds. - :type rotation_period: int - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - - params = { - "db_name": db_name, - "username": username, - "rotation_statements": rotation_statements, - "rotation_period": rotation_period, - } - - api_path = utils.format_url( - "/v1/{mount_point}/static-roles/{name}", mount_point=mount_point, name=name - ) - return self._adapter.post(url=api_path, json=params) - - def read_role(self, name, mount_point=DEFAULT_MOUNT_POINT): - """This endpoint queries the role definition. - - :param name: Specifies the name of the role to read. - :type name: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - - api_path = utils.format_url( - "/v1/{mount_point}/roles/{name}", mount_point=mount_point, name=name - ) - - return self._adapter.get( - url=api_path, - ) - - def read_static_role(self, name, mount_point=DEFAULT_MOUNT_POINT): - """This endpoint queries the static role definition. - - :param name: Specifies the name of the role to read. - :type name: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - - api_path = utils.format_url( - "/v1/{mount_point}/static-roles/{name}", mount_point=mount_point, name=name - ) - - return self._adapter.get( - url=api_path, - ) - - def list_roles(self, mount_point=DEFAULT_MOUNT_POINT): - """This endpoint returns a list of available roles. - - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - - api_path = utils.format_url("/v1/{mount_point}/roles", mount_point=mount_point) - return self._adapter.list( - url=api_path, - ) - - def list_static_roles(self, mount_point=DEFAULT_MOUNT_POINT): - """This endpoint returns a list of available static roles. - - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - - api_path = utils.format_url( - "/v1/{mount_point}/static-roles", mount_point=mount_point - ) - return self._adapter.list( - url=api_path, - ) - - def delete_role(self, name, mount_point=DEFAULT_MOUNT_POINT): - """This endpoint deletes the role definition. - - :param name: Specifies the name of the role to delete. - :type name: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url( - "/v1/{mount_point}/roles/{name}", mount_point=mount_point, name=name - ) - return self._adapter.delete( - url=api_path, - ) - - def delete_static_role(self, name, mount_point=DEFAULT_MOUNT_POINT): - """This endpoint deletes the static role definition. - - :param name: Specifies the name of the role to delete. - :type name: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url( - "/v1/{mount_point}/static-roles/{name}", mount_point=mount_point, name=name - ) - return self._adapter.delete( - url=api_path, - ) - - def generate_credentials(self, name, mount_point=DEFAULT_MOUNT_POINT): - """This endpoint generates a new set of dynamic credentials based on the named role. - - :param name: Specifies the name of the role to create credentials against - :type name: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - - api_path = utils.format_url( - "/v1/{mount_point}/creds/{name}", mount_point=mount_point, name=name - ) - - return self._adapter.get( - url=api_path, - ) - - def get_static_credentials(self, name, mount_point=DEFAULT_MOUNT_POINT): - """This endpoint returns the current credentials based on the named static role. - - :param name: Specifies the name of the role to create credentials against - :type name: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - - api_path = utils.format_url( - "/v1/{mount_point}/static-creds/{name}", mount_point=mount_point, name=name - ) - - return self._adapter.get( - url=api_path, - ) - - def rotate_static_role_credentials(self, name, mount_point=DEFAULT_MOUNT_POINT): - """This endpoint is used to rotate the Static Role credentials stored for a given role name. - While Static Roles are rotated automatically by Vault at configured rotation periods, - users can use this endpoint to manually trigger a rotation to change the stored password and - reset the TTL of the Static Role's password. - - :param name: Specifies the name of the role to create credentials against - :type name: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - - api_path = utils.format_url( - "/v1/{mount_point}/rotate-role/{name}", mount_point=mount_point, name=name - ) - - return self._adapter.post( - url=api_path, - ) diff --git a/.venv/lib/python3.12/site-packages/hvac/api/secrets_engines/gcp.py b/.venv/lib/python3.12/site-packages/hvac/api/secrets_engines/gcp.py deleted file mode 100644 index eb1f2c9..0000000 --- a/.venv/lib/python3.12/site-packages/hvac/api/secrets_engines/gcp.py +++ /dev/null @@ -1,746 +0,0 @@ -#!/usr/bin/env python -"""Gcp methods module.""" -import json -import logging - -from hvac import exceptions, utils -from hvac.api.vault_api_base import VaultApiBase -from hvac.constants.gcp import ( - ALLOWED_SECRETS_TYPES, - SERVICE_ACCOUNT_KEY_ALGORITHMS, - SERVICE_ACCOUNT_KEY_TYPES, -) - -DEFAULT_MOUNT_POINT = "gcp" - - -class Gcp(VaultApiBase): - """Google Cloud Secrets Engine (API). - - Reference: https://www.vaultproject.io/api/secret/gcp/index.html - """ - - def configure( - self, credentials=None, ttl=None, max_ttl=None, mount_point=DEFAULT_MOUNT_POINT - ): - """Configure shared information for the Gcp secrets engine. - - Supported methods: - POST: /{mount_point}/config. Produces: 204 (empty body) - - :param credentials: JSON credentials (either file contents or '@path/to/file') See docs for alternative ways to - pass in to this parameter, as well as the required permissions. - :type credentials: str | unicode - :param ttl: – Specifies default config TTL for long-lived credentials (i.e. service account keys). Accepts - integer number of seconds or Go duration format string. - :type ttl: int | str - :param max_ttl: Specifies the maximum config TTL for long-lived credentials (i.e. service account keys). Accepts - integer number of seconds or Go duration format string.** - :type max_ttl: int | str - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - params = utils.remove_nones( - { - "credentials": credentials, - "ttl": ttl, - "max_ttl": max_ttl, - } - ) - api_path = utils.format_url("/v1/{mount_point}/config", mount_point=mount_point) - return self._adapter.post( - url=api_path, - json=params, - ) - - def rotate_root_credentials(self, mount_point=DEFAULT_MOUNT_POINT): - """Rotate the GCP service account credentials used by Vault for this mount. - - A new key will be generated for the service account, replacing the internal value, and then a deletion of the - old service account key is scheduled. Note that this does not create a new service account, only a new version - of the service account key. - - Supported methods: - POST: /{mount_point}/config/rotate-root. Produces: 200 application/json - - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the request. - :rtype: dict - """ - api_path = utils.format_url( - "/v1/{mount_point}/config/rotate-root", - mount_point=mount_point, - ) - return self._adapter.post( - url=api_path, - ) - - def read_config(self, mount_point=DEFAULT_MOUNT_POINT): - """Read the configured shared information for the Gcp secrets engine. - - Credentials will be omitted from returned data. - - Supported methods: - GET: /{mount_point}/config. Produces: 200 application/json - - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the request. - :rtype: dict - """ - api_path = utils.format_url("/v1/{mount_point}/config", mount_point=mount_point) - return self._adapter.get( - url=api_path, - ) - - def create_or_update_roleset( - self, - name, - project, - bindings, - secret_type=None, - token_scopes=None, - mount_point=DEFAULT_MOUNT_POINT, - ): - """Create a roleset or update an existing roleset. - - See roleset docs for the GCP secrets backend to learn more about what happens when you create or update a - roleset. - - Supported methods: - POST: /{mount_point}/roleset/{name}. Produces: 204 (empty body) - - :param name: Name of the role. Cannot be updated. - :type name: str | unicode - :param project: Name of the GCP project that this roleset's service account will belong to. Cannot be updated. - :type project: str | unicode - :param bindings: Bindings configuration string (expects HCL or JSON format in raw or base64-encoded string) - :type bindings: str | unicode - :param secret_type: Cannot be updated. - :type secret_type: str | unicode - :param token_scopes: List of OAuth scopes to assign to access_token secrets generated under this role set - (access_token role sets only) - :type token_scopes: list[str] - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - if secret_type is not None and secret_type not in ALLOWED_SECRETS_TYPES: - error_msg = 'unsupported secret_type argument provided "{arg}", supported types: "{secret_type}"' - raise exceptions.ParamValidationError( - error_msg.format( - arg=secret_type, - secret_type=",".join(ALLOWED_SECRETS_TYPES), - ) - ) - - if isinstance(bindings, dict): - bindings = json.dumps(bindings).replace(" ", "") - logging.debug("bindings: %s" % bindings) - - params = { - "project": project, - "bindings": bindings, - } - params.update( - utils.remove_nones( - { - "secret_type": secret_type, - "token_scopes": token_scopes, - } - ) - ) - - api_path = utils.format_url( - "/v1/{mount_point}/roleset/{name}", - mount_point=mount_point, - name=name, - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def rotate_roleset_account(self, name, mount_point=DEFAULT_MOUNT_POINT): - """Rotate the service account this roleset uses to generate secrets. - - This also replaces the key access_token roleset. This can be used to invalidate old secrets generated by the - roleset or fix issues if a roleset's service account (and/or keys) was changed outside of Vault (i.e. - through GCP APIs/cloud console). - - Supported methods: - POST: /{mount_point}/roleset/{name}/rotate. Produces: 204 (empty body) - - :param name: Name of the role. - :type name: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url( - "/v1/{mount_point}/roleset/{name}/rotate", - mount_point=mount_point, - name=name, - ) - return self._adapter.post( - url=api_path, - ) - - def rotate_roleset_account_key(self, name, mount_point=DEFAULT_MOUNT_POINT): - """Rotate the service account key this roleset uses to generate access tokens. - - This does not recreate the roleset service account. - - Supported methods: - POST: /{mount_point}/roleset/{name}/rotate-key. Produces: 204 (empty body) - - :param name: Name of the role. - :type name: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url( - "/v1/{mount_point}/roleset/{name}/rotate-key", - mount_point=mount_point, - name=name, - ) - return self._adapter.post( - url=api_path, - ) - - def read_roleset(self, name, mount_point=DEFAULT_MOUNT_POINT): - """Read a roleset. - - Supported methods: - GET: /{mount_point}/roleset/{name}. Produces: 200 application/json - - :param name: Name of the role. - :type name: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the request. - :rtype: dict - """ - api_path = utils.format_url( - "/v1/{mount_point}/roleset/{name}", - mount_point=mount_point, - name=name, - ) - return self._adapter.get( - url=api_path, - ) - - def list_rolesets(self, mount_point=DEFAULT_MOUNT_POINT): - """List configured rolesets. - - Supported methods: - LIST: /{mount_point}/rolesets. Produces: 200 application/json - - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the request. - :rtype: dict - """ - api_path = utils.format_url( - "/v1/{mount_point}/rolesets", mount_point=mount_point - ) - return self._adapter.list( - url=api_path, - ) - - def delete_roleset(self, name, mount_point=DEFAULT_MOUNT_POINT): - """Delete an existing roleset by the given name. - - Supported methods: - DELETE: /{mount_point}/roleset/{name} Produces: 200 application/json - - :param name: Name of the role. - :type name: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url( - "/v1/{mount_point}/roleset/{name}", - name=name, - mount_point=mount_point, - ) - return self._adapter.delete( - url=api_path, - ) - - def generate_oauth2_access_token(self, roleset, mount_point=DEFAULT_MOUNT_POINT): - """Generate an OAuth2 token with the scopes defined on the roleset. - - This OAuth access token can be used in GCP API calls, e.g. curl -H "Authorization: Bearer $TOKEN" ... - - Supported methods: - GET: /{mount_point}/token/{roleset}. Produces: 200 application/json - - :param roleset: Name of an roleset with secret type access_token to generate access_token under. - :type roleset: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the request. - :rtype: dict - """ - api_path = utils.format_url( - "/v1/{mount_point}/token/{roleset}", - mount_point=mount_point, - roleset=roleset, - ) - return self._adapter.get( - url=api_path, - ) - - def generate_service_account_key( - self, - roleset, - key_algorithm="KEY_ALG_RSA_2048", - key_type="TYPE_GOOGLE_CREDENTIALS_FILE", - method="POST", - mount_point=DEFAULT_MOUNT_POINT, - ): - """Generate Secret (IAM Service Account Creds): Service Account Key - - If using GET ('read'), the optional parameters will be set to their defaults. Use POST if you want to specify - different values for these params. - - :param roleset: Name of an roleset with secret type service_account_key to generate key under. - :type roleset: str | unicode - :param key_algorithm: Key algorithm used to generate key. Defaults to 2k RSA key You probably should not choose - other values (i.e. 1k), - :type key_algorithm: str | unicode - :param key_type: Private key type to generate. Defaults to JSON credentials file. - :type key_type: str | unicode - :param method: Supported methods: - POST: /{mount_point}/key/{roleset}. Produces: 200 application/json - GET: /{mount_point}/key/{roleset}. Produces: 200 application/json - :type method: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the request. - :rtype: dict - """ - api_path = utils.format_url( - "/v1/{mount_point}/key/{roleset}", - mount_point=mount_point, - roleset=roleset, - ) - - return self._generate_service_account_key( - api_path, key_algorithm, key_type, method - ) - - def create_or_update_static_account( - self, - name, - service_account_email, - bindings=None, - secret_type=None, - token_scopes=None, - mount_point=DEFAULT_MOUNT_POINT, - ): - """Create a static account or update an existing static account. - - See static account docs for the GCP secrets backend to learn more about what happens when you create or update a - static account. - - Supported methods: - POST: /{mount_point}/static-account/{name}. Produces: 204 (empty body) - - :param name: Name of the static account. Cannot be updated. - :type name: str | unicode - :param service_account_email: Email of the GCP service account to manage. Cannot be updated. - :type service_account_email: str | unicode - :param bindings: Bindings configuration string (expects HCL or JSON format in raw or base64-encoded string) - :type bindings: str | unicode - :param secret_type: Type of secret generated for this static account. Accepted values: access_token, - service_account_key. Cannot be updated. - :type secret_type: str | unicode - :param token_scopes: List of OAuth scopes to assign to access_token secrets generated under this static account - (access_token static accounts only) - :type token_scopes: list[str] - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - if secret_type is not None and secret_type not in ALLOWED_SECRETS_TYPES: - error_msg = 'unsupported secret_type argument provided "{arg}", supported types: "{secret_type}"' - raise exceptions.ParamValidationError( - error_msg.format( - arg=secret_type, - secret_type=",".join(ALLOWED_SECRETS_TYPES), - ) - ) - - if isinstance(bindings, dict): - bindings = json.dumps(bindings).replace(" ", "") - logging.debug("bindings: %s" % bindings) - - params = { - "service_account_email": service_account_email, - } - params.update( - utils.remove_nones( - { - "bindings": bindings, - "secret_type": secret_type, - "token_scopes": token_scopes, - } - ) - ) - api_path = utils.format_url( - "/v1/{mount_point}/static-account/{name}", - mount_point=mount_point, - name=name, - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def rotate_static_account_key(self, name, mount_point=DEFAULT_MOUNT_POINT): - """Rotate the service account key this static account uses to generate access tokens. - - This does not recreate the service account. - - Supported methods: - POST: /{mount_point}/static-account/{name}/rotate-key. Produces: 204 (empty body) - - :param name: Name of the static account. - :type name: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url( - "/v1/{mount_point}/static-account/{name}/rotate-key", - mount_point=mount_point, - name=name, - ) - return self._adapter.post( - url=api_path, - ) - - def read_static_account(self, name, mount_point=DEFAULT_MOUNT_POINT): - """Read a static account. - - Supported methods: - GET: /{mount_point}/static-account/{name}. Produces: 200 application/json - - :param name: Name of the static account. - :type name: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the request. - :rtype: dict - """ - api_path = utils.format_url( - "/v1/{mount_point}/static-account/{name}", - mount_point=mount_point, - name=name, - ) - return self._adapter.get( - url=api_path, - ) - - def list_static_accounts(self, mount_point=DEFAULT_MOUNT_POINT): - """List configured static accounts. - - Supported methods: - LIST: /{mount_point}/static-accounts. Produces: 200 application/json - - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the request. - :rtype: dict - """ - api_path = utils.format_url( - "/v1/{mount_point}/static-accounts", mount_point=mount_point - ) - return self._adapter.list( - url=api_path, - ) - - def delete_static_account(self, name, mount_point=DEFAULT_MOUNT_POINT): - """Delete an existing static account by the given name. - - Supported methods: - DELETE: /{mount_point}/static-account/{name} Produces: 204 (empty body) - - :param name: Name of the static account. - :type name: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url( - "/v1/{mount_point}/static-account/{name}", - name=name, - mount_point=mount_point, - ) - return self._adapter.delete( - url=api_path, - ) - - def generate_static_account_oauth2_access_token( - self, name, mount_point=DEFAULT_MOUNT_POINT - ): - """Generate an OAuth2 token with the scopes defined on the static account. - - This OAuth access token can be used in GCP API calls, e.g. curl -H "Authorization: Bearer $TOKEN" ... - - Supported methods: - GET: /{mount_point}/static-account/{name}/token. Produces: 200 application/json - - :param name: Name of a static account with secret type access_token to generate access_token under. - :type name: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the request. - :rtype: dict - """ - api_path = utils.format_url( - "/v1/{mount_point}/static-account/{name}/token", - mount_point=mount_point, - name=name, - ) - return self._adapter.get( - url=api_path, - ) - - def generate_static_account_service_account_key( - self, - name, - key_algorithm="KEY_ALG_RSA_2048", - key_type="TYPE_GOOGLE_CREDENTIALS_FILE", - method="POST", - mount_point=DEFAULT_MOUNT_POINT, - ): - """Generate Secret (IAM Service Account Creds): Service Account Key - - If using GET ('read'), the optional parameters will be set to their defaults. Use POST if you want to specify - different values for these params. - - :param name: Name of a static account with secret type service_account_key to generate key under. - :type name: str | unicode - :param key_algorithm: Key algorithm used to generate key. Defaults to 2k RSA key You probably should not choose - other values (i.e. 1k), - :type key_algorithm: str | unicode - :param key_type: Private key type to generate. Defaults to JSON credentials file. - :type key_type: str | unicode - :param method: Supported methods: - POST: /v1/{mount_point}/static-account/{name}/key. Produces: 200 application/json - GET: /v1/{mount_point}/static-account/{name}/key. Produces: 200 application/json - :type method: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the request. - :rtype: dict - """ - api_path = utils.format_url( - "/v1/{mount_point}/static-account/{name}/key", - mount_point=mount_point, - name=name, - ) - - return self._generate_service_account_key( - api_path, key_algorithm, key_type, method - ) - - def create_or_update_impersonated_account( - self, - name, - service_account_email, - token_scopes=None, - ttl=None, - mount_point=DEFAULT_MOUNT_POINT, - ): - """Create an impersonated account or update an existing impersonated account. - - See impersonated account docs for the GCP secrets backend to learn more about what happens when you create or update an - impersonated account. - - Supported methods: - POST: /{mount_point}/impersonated-account/{name}. Produces: 204 (empty body) - - :param name: Name of the impersonated account. Cannot be updated. - :type name: str | unicode - :param service_account_email: Email of the GCP service account to manage. Cannot be updated. - :type service_account_email: str | unicode - :param token_scopes: List of OAuth scopes to assign to access tokens generated under this impersonated account - :type token_scopes: list[str] - :param ttl: Lifetime of the token generated. Defaults to 1 hour and is limited to a maximum of 12 hours. - Uses duration format strings. - :type ttl: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - params = { - "service_account_email": service_account_email, - } - params.update( - utils.remove_nones( - { - "token_scopes": token_scopes, - "ttl": ttl, - } - ) - ) - api_path = utils.format_url( - "/v1/{mount_point}/impersonated-account/{name}", - mount_point=mount_point, - name=name, - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def read_impersonated_account(self, name, mount_point=DEFAULT_MOUNT_POINT): - """Read an impersonated account. - - Supported methods: - GET: /{mount_point}/impersonated-account/{name}. Produces: 200 application/json - - :param name: Name of the impersonated account. - :type name: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the request. - :rtype: dict - """ - api_path = utils.format_url( - "/v1/{mount_point}/impersonated-account/{name}", - mount_point=mount_point, - name=name, - ) - return self._adapter.get( - url=api_path, - ) - - def list_impersonated_accounts(self, mount_point=DEFAULT_MOUNT_POINT): - """List configured impersonated accounts. - - Supported methods: - LIST: /{mount_point}/impersonated-accounts. Produces: 200 application/json - - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the request. - :rtype: dict - """ - api_path = utils.format_url( - "/v1/{mount_point}/impersonated-accounts", mount_point=mount_point - ) - return self._adapter.list( - url=api_path, - ) - - def delete_impersonated_account(self, name, mount_point=DEFAULT_MOUNT_POINT): - """Delete an existing impersonated account by the given name. - - Supported methods: - DELETE: /{mount_point}/impersonated-account/{name} Produces: 204 (empty body) - - :param name: Name of the impersonated account. - :type name: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url( - "/v1/{mount_point}/impersonated-account/{name}", - name=name, - mount_point=mount_point, - ) - return self._adapter.delete( - url=api_path, - ) - - def generate_impersonated_account_oauth2_access_token( - self, name, mount_point=DEFAULT_MOUNT_POINT - ): - """Generate an OAuth2 token with the scopes defined on the impersonated account. - - This OAuth access token can be used in GCP API calls, e.g. curl -H "Authorization: Bearer $TOKEN" ... - - Supported methods: - GET: /{mount_point}/impersonated-account/{name}/token. Produces: 200 application/json - - :param name: Name of the impersonated account to generate an access token under. - :type name: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the request. - :rtype: dict - """ - api_path = utils.format_url( - "/v1/{mount_point}/impersonated-account/{name}/token", - mount_point=mount_point, - name=name, - ) - return self._adapter.get( - url=api_path, - ) - - def _generate_service_account_key( - self, - api_path, - key_algorithm="KEY_ALG_RSA_2048", - key_type="TYPE_GOOGLE_CREDENTIALS_FILE", - method="POST", - ): - if method == "POST": - if key_algorithm not in SERVICE_ACCOUNT_KEY_ALGORITHMS: - error_msg = 'unsupported key_algorithm argument provided "{arg}", supported algorithms: "{algorithms}"' - raise exceptions.ParamValidationError( - error_msg.format( - arg=key_algorithm, - algorithms=",".join(SERVICE_ACCOUNT_KEY_ALGORITHMS), - ) - ) - if key_type not in SERVICE_ACCOUNT_KEY_TYPES: - error_msg = 'unsupported key_type argument provided "{arg}", supported types: "{key_types}"' - raise exceptions.ParamValidationError( - error_msg.format( - arg=key_type, - key_types=",".join(SERVICE_ACCOUNT_KEY_TYPES), - ) - ) - - params = { - "key_algorithm": key_algorithm, - "key_type": key_type, - } - - response = self._adapter.post( - url=api_path, - json=params, - ) - elif method == "GET": - response = self._adapter.get( - url=api_path, - ) - else: - error_message = '"method" parameter provided invalid value; POST or GET allowed, "{method}" provided'.format( - method=method - ) - raise exceptions.ParamValidationError(error_message) - - return response diff --git a/.venv/lib/python3.12/site-packages/hvac/api/secrets_engines/identity.py b/.venv/lib/python3.12/site-packages/hvac/api/secrets_engines/identity.py deleted file mode 100644 index 34d02c9..0000000 --- a/.venv/lib/python3.12/site-packages/hvac/api/secrets_engines/identity.py +++ /dev/null @@ -1,1642 +0,0 @@ -#!/usr/bin/env python -"""Identity secret engine module.""" -import logging - -from hvac import exceptions, utils -from hvac.api.vault_api_base import VaultApiBase -from hvac.constants.identity import ALLOWED_GROUP_TYPES, DEFAULT_MOUNT_POINT - -logger = logging.getLogger(__name__) - - -class Identity(VaultApiBase): - """Identity Secrets Engine (API). - - Reference: https://www.vaultproject.io/api/secret/identity/entity.html - """ - - def create_or_update_entity( - self, - name, - entity_id=None, - metadata=None, - policies=None, - disabled=None, - mount_point=DEFAULT_MOUNT_POINT, - ): - """Create or update an Entity. - - Supported methods: - POST: /{mount_point}/entity. Produces: 200 application/json - - :param entity_id: ID of the entity. If set, updates the corresponding existing entity. - :type entity_id: str | unicode - :param name: Name of the entity. - :type name: str | unicode - :param metadata: Metadata to be associated with the entity. - :type metadata: dict - :param policies: Policies to be tied to the entity. - :type policies: str | unicode - :param disabled: Whether the entity is disabled. Disabled entities' associated tokens cannot be used, but are - not revoked. - :type disabled: bool - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response for creates, the generic response object for updates, of the request. - :rtype: dict | requests.Response - """ - if metadata is not None and not isinstance(metadata, dict): - error_msg = 'unsupported metadata argument provided "{arg}" ({arg_type}), required type: dict"' - raise exceptions.ParamValidationError( - error_msg.format( - arg=metadata, - arg_type=type(metadata), - ) - ) - params = utils.remove_nones( - { - "id": entity_id, - "name": name, - "metadata": metadata, - "policies": policies, - "disabled": disabled, - } - ) - api_path = utils.format_url("/v1/{mount_point}/entity", mount_point=mount_point) - return self._adapter.post( - url=api_path, - json=params, - ) - - def create_or_update_entity_by_name( - self, - name, - metadata=None, - policies=None, - disabled=None, - mount_point=DEFAULT_MOUNT_POINT, - ): - """Create or update an entity by a given name. - - Supported methods: - POST: /{mount_point}/entity/name/{name}. Produces: 200 application/json - - :param name: Name of the entity. - :type name: str | unicode - :param metadata: Metadata to be associated with the entity. - :type metadata: dict - :param policies: Policies to be tied to the entity. - :type policies: str | unicode - :param disabled: Whether the entity is disabled. Disabled - entities' associated tokens cannot be used, but are not revoked. - :type disabled: bool - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response for creates, the generic response of the request for updates. - :rtype: requests.Response | dict - """ - if metadata is not None and not isinstance(metadata, dict): - error_msg = 'unsupported metadata argument provided "{arg}" ({arg_type}), required type: dict"' - raise exceptions.ParamValidationError( - error_msg.format( - arg=metadata, - arg_type=type(metadata), - ) - ) - params = utils.remove_nones( - { - "metadata": metadata, - "policies": policies, - "disabled": disabled, - } - ) - api_path = utils.format_url( - "/v1/{mount_point}/entity/name/{name}", - mount_point=mount_point, - name=name, - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def read_entity(self, entity_id, mount_point=DEFAULT_MOUNT_POINT): - """Query an entity by its identifier. - - Supported methods: - GET: /auth/{mount_point}/entity/id/{id}. Produces: 200 application/json - - :param entity_id: Identifier of the entity. - :type entity_id: str - :param mount_point: The "path" the secret engine was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the request. - :rtype: dict - """ - api_path = utils.format_url( - "/v1/{mount_point}/entity/id/{id}", - mount_point=mount_point, - id=entity_id, - ) - return self._adapter.get(url=api_path) - - def read_entity_by_name(self, name, mount_point=DEFAULT_MOUNT_POINT): - """Query an entity by its name. - - Supported methods: - GET: /{mount_point}/entity/name/{name}. Produces: 200 application/json - - :param name: Name of the entity. - :type name: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url( - "/v1/{mount_point}/entity/name/{name}", - mount_point=mount_point, - name=name, - ) - return self._adapter.get( - url=api_path, - ) - - def update_entity( - self, - entity_id, - name=None, - metadata=None, - policies=None, - disabled=None, - mount_point=DEFAULT_MOUNT_POINT, - ): - """Update an existing entity. - - Supported methods: - POST: /{mount_point}/entity/id/{id}. Produces: 200 application/json - - :param entity_id: Identifier of the entity. - :type entity_id: str | unicode - :param name: Name of the entity. - :type name: str | unicode - :param metadata: Metadata to be associated with the entity. - :type metadata: dict - :param policies: Policies to be tied to the entity. - :type policies: str | unicode - :param disabled: Whether the entity is disabled. Disabled entities' associated tokens cannot be used, but - are not revoked. - :type disabled: bool - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response where available, otherwise the generic response object, of the request. - :rtype: dict | requests.Response - """ - if metadata is not None and not isinstance(metadata, dict): - error_msg = 'unsupported metadata argument provided "{arg}" ({arg_type}), required type: dict"' - raise exceptions.ParamValidationError( - error_msg.format( - arg=metadata, - arg_type=type(metadata), - ) - ) - params = utils.remove_nones( - { - "name": name, - "metadata": metadata, - "policies": policies, - "disabled": disabled, - } - ) - api_path = utils.format_url( - "/v1/{mount_point}/entity/id/{id}", - mount_point=mount_point, - id=entity_id, - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def delete_entity(self, entity_id, mount_point=DEFAULT_MOUNT_POINT): - """Delete an entity and all its associated aliases. - - Supported methods: - DELETE: /{mount_point}/entity/id/:id. Produces: 204 (empty body) - - :param entity_id: Identifier of the entity. - :type entity_id: str - :param mount_point: The "path" the secret engine was mounted on. - :type mount_point: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url( - "/v1/{mount_point}/entity/id/{id}", - mount_point=mount_point, - id=entity_id, - ) - return self._adapter.delete( - url=api_path, - ) - - def delete_entity_by_name(self, name, mount_point=DEFAULT_MOUNT_POINT): - """Delete an entity and all its associated aliases, given the entity name. - - Supported methods: - DELETE: /{mount_point}/entity/name/{name}. Produces: 204 (empty body) - - :param name: Name of the entity. - :type name: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url( - "/v1/{mount_point}/entity/name/{name}", - mount_point=mount_point, - name=name, - ) - return self._adapter.delete( - url=api_path, - ) - - def list_entities(self, method="LIST", mount_point=DEFAULT_MOUNT_POINT): - """List available entities entities by their identifiers. - - :param method: Supported methods: - LIST: /{mount_point}/entity/id. Produces: 200 application/json - GET: /{mount_point}/entity/id?list=true. Produces: 200 application/json - :type method: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the request. - :rtype: dict - """ - if method == "LIST": - api_path = utils.format_url( - "/v1/{mount_point}/entity/id", mount_point=mount_point - ) - response = self._adapter.list( - url=api_path, - ) - - elif method == "GET": - api_path = utils.format_url( - "/v1/{mount_point}/entity/id?list=true", mount_point=mount_point - ) - response = self._adapter.get( - url=api_path, - ) - else: - error_message = '"method" parameter provided invalid value; LIST or GET allowed, "{method}" provided'.format( - method=method - ) - raise exceptions.ParamValidationError(error_message) - - return response - - def list_entities_by_name(self, method="LIST", mount_point=DEFAULT_MOUNT_POINT): - """List available entities by their names. - - :param method: Supported methods: - LIST: /{mount_point}/entity/name. Produces: 200 application/json - GET: /{mount_point}/entity/name?list=true. Produces: 200 application/json - :type method: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the request. - :rtype: dict - """ - if method == "LIST": - api_path = utils.format_url( - "/v1/{mount_point}/entity/name", mount_point=mount_point - ) - response = self._adapter.list( - url=api_path, - ) - - elif method == "GET": - api_path = utils.format_url( - "/v1/{mount_point}/entity/name?list=true", mount_point=mount_point - ) - response = self._adapter.get( - url=api_path, - ) - else: - error_message = '"method" parameter provided invalid value; LIST or GET allowed, "{method}" provided'.format( - method=method - ) - raise exceptions.ParamValidationError(error_message) - - return response - - def merge_entities( - self, - from_entity_ids, - to_entity_id, - force=None, - mount_point=DEFAULT_MOUNT_POINT, - conflicting_alias_ids_to_keep=None, - ): - """Merge many entities into one entity. - - Supported methods: - POST: /{mount_point}/entity/merge. Produces: 204 (empty body) - - :param from_entity_ids: Entity IDs which needs to get merged. - :type from_entity_ids: array - :param to_entity_id: Entity ID into which all the other entities need to get merged. - :type to_entity_id: str | unicode - :param force: Setting this will follow the 'mine' strategy for merging MFA secrets. If there are secrets of the - same type both in entities that are merged from and in entity into which all others are getting merged, - secrets in the destination will be unaltered. If not set, this API will throw an error containing all the - conflicts. - :type force: bool - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :param conflicting_alias_ids_to_keep: A list of entity aliases to keep in the case where the to-Entity and - from-Entity have aliases with the same mount accessor. In the case where alias share mount accessors, the - alias ID given in this list will be kept or merged, and the other alias will be deleted. Note that merges - requiring this parameter must have only one from-Entity. - Requires Vault 1.12 or higher - :type conflicting_alias_ids_to_keep: list - :return: The response of the request. - :rtype: requests.Response - """ - params = utils.remove_nones( - { - "from_entity_ids": from_entity_ids, - "to_entity_id": to_entity_id, - "force": force, - "conflicting_alias_ids_to_keep": conflicting_alias_ids_to_keep, - } - ) - api_path = utils.format_url( - "/v1/{mount_point}/entity/merge", mount_point=mount_point - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def create_or_update_entity_alias( - self, - name, - canonical_id, - mount_accessor, - alias_id=None, - mount_point=DEFAULT_MOUNT_POINT, - ): - """Create a new alias for an entity. - - Supported methods: - POST: /{mount_point}/entity-alias. Produces: 200 application/json - - :param name: Name of the alias. Name should be the identifier of the client in the authentication source. For - example, if the alias belongs to userpass backend, the name should be a valid username within userpass - backend. If alias belongs to GitHub, it should be the GitHub username. - :type name: str | unicode - :param alias_id: ID of the entity alias. If set, updates the corresponding entity alias. - :type alias_id: str | unicode - :param canonical_id: Entity ID to which this alias belongs to. - :type canonical_id: str | unicode - :param mount_accessor: Accessor of the mount to which the alias should belong to. - :type mount_accessor: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the request. - :rtype: requests.Response - """ - params = utils.remove_nones( - { - "id": alias_id, - "name": name, - "canonical_id": canonical_id, - "mount_accessor": mount_accessor, - } - ) - api_path = utils.format_url( - "/v1/{mount_point}/entity-alias", mount_point=mount_point - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def read_entity_alias(self, alias_id, mount_point=DEFAULT_MOUNT_POINT): - """Query the entity alias by its identifier. - - Supported methods: - GET: /{mount_point}/entity-alias/id/{id}. Produces: 200 application/json - - :param alias_id: Identifier of entity alias. - :type alias_id: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the request. - :rtype: dict - """ - api_path = utils.format_url( - "/v1/{mount_point}/entity-alias/id/{id}", - mount_point=mount_point, - id=alias_id, - ) - return self._adapter.get( - url=api_path, - ) - - def update_entity_alias( - self, - alias_id, - name, - canonical_id, - mount_accessor, - mount_point=DEFAULT_MOUNT_POINT, - ): - """Update an existing entity alias. - - Supported methods: - POST: /{mount_point}/entity-alias/id/{id}. Produces: 200 application/json - - :param alias_id: Identifier of the entity alias. - :type alias_id: str | unicode - :param name: Name of the alias. Name should be the identifier of the client in the authentication source. For - example, if the alias belongs to userpass backend, the name should be a valid username within userpass - backend. If alias belongs to GitHub, it should be the GitHub username. - :type name: str | unicode - :param canonical_id: Entity ID to which this alias belongs to. - :type canonical_id: str | unicode - :param mount_accessor: Accessor of the mount to which the alias should belong to. - :type mount_accessor: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response where available, otherwise the generic response object, of the request. - :rtype: dict | requests.Response - """ - params = utils.remove_nones( - { - "name": name, - "canonical_id": canonical_id, - "mount_accessor": mount_accessor, - } - ) - api_path = utils.format_url( - "/v1/{mount_point}/entity-alias/id/{id}", - mount_point=mount_point, - id=alias_id, - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def list_entity_aliases(self, method="LIST", mount_point=DEFAULT_MOUNT_POINT): - """List available entity aliases by their identifiers. - - :param method: Supported methods: - LIST: /{mount_point}/entity-alias/id. Produces: 200 application/json - GET: /{mount_point}/entity-alias/id?list=true. Produces: 200 application/json - :type method: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The the JSON response of the request. - :rtype: dict - """ - - if method == "LIST": - api_path = utils.format_url( - "/v1/{mount_point}/entity-alias/id", mount_point=mount_point - ) - response = self._adapter.list( - url=api_path, - ) - - elif method == "GET": - api_path = utils.format_url( - "/v1/{mount_point}/entity-alias/id?list=true", mount_point=mount_point - ) - response = self._adapter.get( - url=api_path, - ) - else: - error_message = '"method" parameter provided invalid value; LIST or GET allowed, "{method}" provided'.format( - method=method - ) - raise exceptions.ParamValidationError(error_message) - - return response - - def delete_entity_alias(self, alias_id, mount_point=DEFAULT_MOUNT_POINT): - """Delete a entity alias. - - Supported methods: - DELETE: /{mount_point}/entity-alias/id/{alias_id}. Produces: 204 (empty body) - - :param alias_id: Identifier of the entity. - :type alias_id: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url( - "/v1/{mount_point}/entity-alias/id/{id}", - mount_point=mount_point, - id=alias_id, - ) - return self._adapter.delete( - url=api_path, - ) - - @staticmethod - def validate_member_id_params_for_group_type( - group_type, params, member_group_ids, member_entity_ids - ): - """Determine whether member ID parameters can be sent with a group create / update request. - - These parameters are only allowed for the internal group type. If they're set for an external group type, Vault - returns a "error" response. - - :param group_type: Type of the group, internal or external - :type group_type: str | unicode - :param params: Params dict to conditionally add the member entity/group ID's to. - :type params: dict - :param member_group_ids: Group IDs to be assigned as group members. - :type member_group_ids: str | unicode - :param member_entity_ids: Entity IDs to be assigned as group members. - :type member_entity_ids: str | unicode - :return: Params dict with conditionally added member entity/group ID's. - :rtype: dict - """ - if group_type == "external": - if member_entity_ids is not None: - logger.warning( - "InvalidRequest: member entities can't be set manually for external groups ignoring member_entity_ids argument." - ) - else: - params["member_entity_ids"] = member_entity_ids - - if group_type == "external": - if member_group_ids is not None: - logger.warning( - "InvalidRequest: member groups can't be set for external groups; ignoring member_group_ids argument." - ) - else: - params["member_group_ids"] = member_group_ids - - return params - - def create_or_update_group( - self, - name, - group_id=None, - group_type="internal", - metadata=None, - policies=None, - member_group_ids=None, - member_entity_ids=None, - mount_point=DEFAULT_MOUNT_POINT, - ): - """Create or update a Group. - - Supported methods: - POST: /{mount_point}/group. Produces: 200 application/json - - :param name: Name of the group. - :type name: str | unicode - :param group_id: ID of the group. If set, updates the corresponding existing group. - :type group_id: str | unicode - :param group_type: Type of the group, internal or external. Defaults to internal. - :type group_type: str | unicode - :param metadata: Metadata to be associated with the group. - :type metadata: dict - :param policies: Policies to be tied to the group. - :type policies: str | unicode - :param member_group_ids: Group IDs to be assigned as group members. - :type member_group_ids: str | unicode - :param member_entity_ids: Entity IDs to be assigned as group members. - :type member_entity_ids: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response where available, otherwise the generic response object, of the request. - :rtype: dict | requests.Response - """ - if metadata is not None and not isinstance(metadata, dict): - error_msg = 'unsupported metadata argument provided "{arg}" ({arg_type}), required type: dict"' - raise exceptions.ParamValidationError( - error_msg.format( - arg=metadata, - arg_type=type(metadata), - ) - ) - if group_type not in ALLOWED_GROUP_TYPES: - error_msg = 'unsupported group_type argument provided "{arg}", allowed values: ({allowed_values})' - raise exceptions.ParamValidationError( - error_msg.format( - arg=group_type, - allowed_values=ALLOWED_GROUP_TYPES, - ) - ) - params = utils.remove_nones( - { - "id": group_id, - "name": name, - "type": group_type, - "metadata": metadata, - "policies": policies, - } - ) - - Identity.validate_member_id_params_for_group_type( - group_type=group_type, - params=params, - member_group_ids=member_group_ids, - member_entity_ids=member_entity_ids, - ) - - api_path = utils.format_url("/v1/{mount_point}/group", mount_point=mount_point) - return self._adapter.post( - url=api_path, - json=params, - ) - - def read_group(self, group_id, mount_point=DEFAULT_MOUNT_POINT): - """Query the group by its identifier. - - Supported methods: - GET: /{mount_point}/group/id/{id}. Produces: 200 application/json - - :param group_id: Identifier of the group. - :type group_id: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url( - "/v1/{mount_point}/group/id/{id}", - mount_point=mount_point, - id=group_id, - ) - return self._adapter.get( - url=api_path, - ) - - def update_group( - self, - group_id, - name, - group_type="internal", - metadata=None, - policies=None, - member_group_ids=None, - member_entity_ids=None, - mount_point=DEFAULT_MOUNT_POINT, - ): - """Update an existing group. - - Supported methods: - POST: /{mount_point}/group/id/{id}. Produces: 200 application/json - - :param group_id: Identifier of the entity. - :type group_id: str | unicode - :param name: Name of the group. - :type name: str | unicode - :param group_type: Type of the group, internal or external. Defaults to internal. - :type group_type: str | unicode - :param metadata: Metadata to be associated with the group. - :type metadata: dict - :param policies: Policies to be tied to the group. - :type policies: str | unicode - :param member_group_ids: Group IDs to be assigned as group members. - :type member_group_ids: str | unicode - :param member_entity_ids: Entity IDs to be assigned as group members. - :type member_entity_ids: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response where available, otherwise the generic response object, of the request. - :rtype: dict | requests.Response - """ - if metadata is not None and not isinstance(metadata, dict): - error_msg = 'unsupported metadata argument provided "{arg}" ({arg_type}), required type: dict"' - raise exceptions.ParamValidationError( - error_msg.format( - arg=metadata, - arg_type=type(metadata), - ) - ) - if group_type not in ALLOWED_GROUP_TYPES: - error_msg = 'unsupported group_type argument provided "{arg}", allowed values: ({allowed_values})' - raise exceptions.ParamValidationError( - error_msg.format( - arg=group_type, - allowed_values=ALLOWED_GROUP_TYPES, - ) - ) - params = utils.remove_nones( - { - "name": name, - "type": group_type, - "metadata": metadata, - "policies": policies, - } - ) - - Identity.validate_member_id_params_for_group_type( - group_type=group_type, - params=params, - member_group_ids=member_group_ids, - member_entity_ids=member_entity_ids, - ) - - api_path = utils.format_url( - "/v1/{mount_point}/group/id/{id}", - mount_point=mount_point, - id=group_id, - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def delete_group(self, group_id, mount_point=DEFAULT_MOUNT_POINT): - """Delete a group. - - Supported methods: - DELETE: /{mount_point}/group/id/{id}. Produces: 204 (empty body) - - :param group_id: Identifier of the entity. - :type group_id: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url( - "/v1/{mount_point}/group/id/{id}", - mount_point=mount_point, - id=group_id, - ) - return self._adapter.delete( - url=api_path, - ) - - def list_groups(self, method="LIST", mount_point=DEFAULT_MOUNT_POINT): - """List available groups by their identifiers. - - :param method: Supported methods: - LIST: /{mount_point}/group/id. Produces: 200 application/json - GET: /{mount_point}/group/id?list=true. Produces: 200 application/json - :type method: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the request. - :rtype: dict - """ - - if method == "LIST": - api_path = utils.format_url( - "/v1/{mount_point}/group/id", mount_point=mount_point - ) - response = self._adapter.list( - url=api_path, - ) - - elif method == "GET": - api_path = utils.format_url( - "/v1/{mount_point}/group/id?list=true", mount_point=mount_point - ) - response = self._adapter.get( - url=api_path, - ) - else: - error_message = '"method" parameter provided invalid value; LIST or GET allowed, "{method}" provided'.format( - method=method - ) - raise exceptions.ParamValidationError(error_message) - - return response - - def list_groups_by_name(self, method="LIST", mount_point=DEFAULT_MOUNT_POINT): - """List available groups by their names. - - :param method: Supported methods: - LIST: /{mount_point}/group/name. Produces: 200 application/json - GET: /{mount_point}/group/name?list=true. Produces: 200 application/json - :type method: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the request. - :rtype: dict - """ - - if method == "LIST": - api_path = utils.format_url( - "/v1/{mount_point}/group/name", mount_point=mount_point - ) - response = self._adapter.list( - url=api_path, - ) - - elif method == "GET": - api_path = utils.format_url( - "/v1/{mount_point}/group/name?list=true", mount_point=mount_point - ) - response = self._adapter.get( - url=api_path, - ) - else: - error_message = '"method" parameter provided invalid value; LIST or GET allowed, "{method}" provided'.format( - method=method - ) - raise exceptions.ParamValidationError(error_message) - - return response - - def create_or_update_group_by_name( - self, - name, - group_type="internal", - metadata=None, - policies=None, - member_group_ids=None, - member_entity_ids=None, - mount_point=DEFAULT_MOUNT_POINT, - ): - """Create or update a group by its name. - - Supported methods: - POST: /{mount_point}/group/name/{name}. Produces: 200 application/json - - :param name: Name of the group. - :type name: str | unicode - :param group_type: Type of the group, internal or external. Defaults to internal. - :type group_type: str | unicode - :param metadata: Metadata to be associated with the group. - :type metadata: dict - :param policies: Policies to be tied to the group. - :type policies: str | unicode - :param member_group_ids: Group IDs to be assigned as group members. - :type member_group_ids: str | unicode - :param member_entity_ids: Entity IDs to be assigned as group members. - :type member_entity_ids: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - - if metadata is not None and not isinstance(metadata, dict): - error_msg = 'unsupported metadata argument provided "{arg}" ({arg_type}), required type: dict"' - raise exceptions.ParamValidationError( - error_msg.format( - arg=metadata, - arg_type=type(metadata), - ) - ) - if group_type not in ALLOWED_GROUP_TYPES: - error_msg = 'unsupported group_type argument provided "{arg}", allowed values: ({allowed_values})' - raise exceptions.ParamValidationError( - error_msg.format( - arg=group_type, - allowed_values=ALLOWED_GROUP_TYPES, - ) - ) - params = utils.remove_nones( - { - "type": group_type, - "metadata": metadata, - "policies": policies, - } - ) - if group_type != "external": - external_only_params = utils.remove_nones( - { - "member_group_ids": member_group_ids, - "member_entity_ids": member_entity_ids, - } - ) - params.update(external_only_params) - api_path = utils.format_url( - "/v1/{mount_point}/group/name/{name}", - mount_point=mount_point, - name=name, - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def read_group_by_name(self, name, mount_point=DEFAULT_MOUNT_POINT): - """Query a group by its name. - - Supported methods: - GET: /{mount_point}/group/name/{name}. Produces: 200 application/json - - :param name: Name of the group. - :type name: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the request. - :rtype: dict - """ - api_path = utils.format_url( - "/v1/{mount_point}/group/name/{name}", - mount_point=mount_point, - name=name, - ) - return self._adapter.get( - url=api_path, - ) - - def delete_group_by_name(self, name, mount_point=DEFAULT_MOUNT_POINT): - """Delete a group, given its name. - - Supported methods: - DELETE: /{mount_point}/group/name/{name}. Produces: 204 (empty body) - - :param name: Name of the group. - :type name: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url( - "/v1/{mount_point}/group/name/{name}", - mount_point=mount_point, - name=name, - ) - return self._adapter.delete( - url=api_path, - ) - - def create_or_update_group_alias( - self, - name, - alias_id=None, - mount_accessor=None, - canonical_id=None, - mount_point=DEFAULT_MOUNT_POINT, - ): - """Creates or update a group alias. - - Supported methods: - POST: /{mount_point}/group-alias. Produces: 200 application/json - - :param alias_id: ID of the group alias. If set, updates the corresponding existing group alias. - :type alias_id: str | unicode - :param name: Name of the group alias. - :type name: str | unicode - :param mount_accessor: Mount accessor to which this alias belongs to - :type mount_accessor: str | unicode - :param canonical_id: ID of the group to which this is an alias. - :type canonical_id: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the request. - :rtype: requests.Response - """ - params = utils.remove_nones( - { - "id": alias_id, - "name": name, - "mount_accessor": mount_accessor, - "canonical_id": canonical_id, - } - ) - api_path = utils.format_url( - "/v1/{mount_point}/group-alias", mount_point=mount_point - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def update_group_alias( - self, - entity_id, - name, - mount_accessor=None, - canonical_id=None, - mount_point=DEFAULT_MOUNT_POINT, - ): - """Update an existing group alias. - - Supported methods: - POST: /{mount_point}/group-alias/id/{id}. Produces: 200 application/json - - :param entity_id: ID of the group alias. - :type entity_id: str | unicode - :param name: Name of the group alias. - :type name: str | unicode - :param mount_accessor: Mount accessor to which this alias belongs - toMount accessor to which this alias belongs to. - :type mount_accessor: str | unicode - :param canonical_id: ID of the group to which this is an alias. - :type canonical_id: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - params = utils.remove_nones( - { - "name": name, - "mount_accessor": mount_accessor, - "canonical_id": canonical_id, - } - ) - api_path = utils.format_url( - "/v1/{mount_point}/group-alias/id/{id}", - mount_point=mount_point, - id=entity_id, - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def read_group_alias(self, alias_id, mount_point=DEFAULT_MOUNT_POINT): - """Query the group alias by its identifier. - - Supported methods: - GET: /{mount_point}/group-alias/id/:id. Produces: 200 application/json - - :param alias_id: ID of the group alias. - :type alias_id: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the request. - :rtype: dict - """ - api_path = utils.format_url( - "/v1/{mount_point}/group-alias/id/{id}", - mount_point=mount_point, - id=alias_id, - ) - return self._adapter.get( - url=api_path, - ) - - def delete_group_alias(self, entity_id, mount_point=DEFAULT_MOUNT_POINT): - """Delete a group alias. - - Supported methods: - DELETE: /{mount_point}/group-alias/id/{id}. Produces: 204 (empty body) - - :param entity_id: ID of the group alias. - :type entity_id: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url( - "/v1/{mount_point}/group-alias/id/{id}", - mount_point=mount_point, - id=entity_id, - ) - return self._adapter.delete( - url=api_path, - ) - - def list_group_aliases(self, method="LIST", mount_point=DEFAULT_MOUNT_POINT): - """List available group aliases by their identifiers. - - :param method: Supported methods: - LIST: /{mount_point}/group-alias/id. Produces: 200 application/json - GET: /{mount_point}/group-alias/id?list=true. Produces: 200 application/json - :type method: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The "data" key from the JSON response of the request. - :rtype: dict - """ - - if method == "LIST": - api_path = utils.format_url( - "/v1/{mount_point}/group-alias/id", mount_point=mount_point - ) - response = self._adapter.list( - url=api_path, - ) - elif method == "GET": - api_path = utils.format_url( - "/v1/{mount_point}/group-alias/id?list=true", mount_point=mount_point - ) - response = self._adapter.get( - url=api_path, - ) - else: - error_message = '"method" parameter provided invalid value; LIST or GET allowed, "{method}" provided'.format( - method=method - ) - raise exceptions.ParamValidationError(error_message) - - return response - - def lookup_entity( - self, - name=None, - entity_id=None, - alias_id=None, - alias_name=None, - alias_mount_accessor=None, - mount_point=DEFAULT_MOUNT_POINT, - ): - """Query an entity based on the given criteria. - - The criteria can be name, id, alias_id, or a combination of alias_name and alias_mount_accessor. - - Supported methods: - POST: /{mount_point}/lookup/entity. Produces: 200 application/json - - :param name: Name of the entity. - :type name: str | unicode - :param entity_id: ID of the entity. - :type entity_id: str | unicode - :param alias_id: ID of the alias. - :type alias_id: str | unicode - :param alias_name: Name of the alias. This should be supplied in conjunction with alias_mount_accessor. - :type alias_name: str | unicode - :param alias_mount_accessor: Accessor of the mount to which the alias belongs to. This should be supplied in conjunction with alias_name. - :type alias_mount_accessor: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the request if a entity / entity alias is found in the lookup, None otherwise. - :rtype: dict | None - """ - params = {} - if name is not None: - params["name"] = name - elif entity_id is not None: - params["id"] = entity_id - elif alias_id is not None: - params["alias_id"] = alias_id - elif alias_name is not None and alias_mount_accessor is not None: - params["alias_name"] = alias_name - params["alias_mount_accessor"] = alias_mount_accessor - api_path = utils.format_url( - "/v1/{mount_point}/lookup/entity", mount_point=mount_point - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def lookup_group( - self, - name=None, - group_id=None, - alias_id=None, - alias_name=None, - alias_mount_accessor=None, - mount_point=DEFAULT_MOUNT_POINT, - ): - """Query a group based on the given criteria. - - The criteria can be name, id, alias_id, or a combination of alias_name and alias_mount_accessor. - - Supported methods: - POST: /{mount_point}/lookup/group. Produces: 200 application/json - - :param name: Name of the group. - :type name: str | unicode - :param group_id: ID of the group. - :type group_id: str | unicode - :param alias_id: ID of the alias. - :type alias_id: str | unicode - :param alias_name: Name of the alias. This should be supplied in conjunction with alias_mount_accessor. - :type alias_name: str | unicode - :param alias_mount_accessor: Accessor of the mount to which the alias belongs to. This should be supplied in conjunction with alias_name. - :type alias_mount_accessor: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the request if a group / group alias is found in the lookup, None otherwise. - :rtype: dict | None - """ - params = {} - if name is not None: - params["name"] = name - elif group_id is not None: - params["id"] = group_id - elif alias_id is not None: - params["alias_id"] = alias_id - elif alias_name is not None and alias_mount_accessor is not None: - params["alias_name"] = alias_name - params["alias_mount_accessor"] = alias_mount_accessor - api_path = utils.format_url( - "/v1/{mount_point}/lookup/group", mount_point=mount_point - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def configure_tokens_backend(self, issuer=None, mount_point=DEFAULT_MOUNT_POINT): - """Update configurations for OIDC-compliant identity tokens issued by Vault. - - Supported methods: - POST: {mount_point}/oidc/config. - - :param issuer: Issuer URL to be used in the iss claim of the token. If not set, Vault's api_addr will be used. - The issuer is a case sensitive URL using the https scheme that contains scheme, host, and optionally, port - number and path components, but no query or fragment components. - :type issuer: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The a dict or the response of the configure_tokens_backend request. dict returned when messages - are included in the response body. - :rtype: requests.Response - """ - params = utils.remove_nones( - { - "issuer": issuer, - } - ) - - api_path = utils.format_url( - "/v1/{mount_point}/oidc/config", - mount_point=mount_point, - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def read_tokens_backend_configuration(self, mount_point=DEFAULT_MOUNT_POINT): - """Query vault identity tokens configurations. - - Supported methods: - GET: {mount_point}/oidc/config. - - :return: The response of the read_tokens_backend_configuration request. - :rtype: dict - """ - api_path = utils.format_url( - "/v1/{mount_point}/oidc/config", - mount_point=mount_point, - ) - return self._adapter.get( - url=api_path, - ) - - def create_named_key( - self, - name, - rotation_period="24h", - verification_ttl="24h", - allowed_client_ids=None, - algorithm="RS256", - mount_point=DEFAULT_MOUNT_POINT, - ): - """Create or update a named key which is used by a role to sign tokens. - - Supported methods: - POST: {mount_point}/oidc/key/:name. - - :param name: Name of the named key. - :type name: str | unicode - :param rotation_period: How often to generate a new signing key. Can be specified as a number of seconds or as - a time string like "30m" or "6h". - :type rotation_period: str | unicode - :param verification_ttl: Controls how long the public portion of a signing key will be available for - verification after being rotated. - :type verification_ttl: str | unicode - :param allowed_client_ids: List of role client ids allowed to use this key for signing. - If empty, no roles are allowed. If "*", all roles are allowed. - :type allowed_client_ids: list - :param algorithm: Signing algorithm to use. Allowed values are: RS256 (default), RS384, RS512, ES256, ES384, - ES512, EdDSA. - :type algorithm: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The response of the create_a_named_key request. - :rtype: dict - """ - params = { - "name": name, - "rotation_period": rotation_period, - "verification_ttl": verification_ttl, - "allowed_client_ids": allowed_client_ids, - "algorithm": algorithm, - } - - api_path = utils.format_url( - "/v1/{mount_point}/oidc/key/{name}", - mount_point=mount_point, - name=name, - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def read_named_key(self, name, mount_point=DEFAULT_MOUNT_POINT): - """Query a named key and returns its configurations. - - Supported methods: - GET: {mount_point}/oidc/key/:name. - - :param name: Name of the key. - :type name: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The response of the read_a_named_key request. - :rtype: dict - """ - api_path = utils.format_url( - "/v1/{mount_point}/oidc/key/{name}", - mount_point=mount_point, - name=name, - ) - return self._adapter.get( - url=api_path, - ) - - def delete_named_key(self, name, mount_point=DEFAULT_MOUNT_POINT): - """Delete a named key. - - Supported methods: - DELETE: {mount_point}/oidc/key/:name. - - :param name: Name of the key. - :type name: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The response of the delete_a_named_key request. - :rtype: dict - """ - api_path = utils.format_url( - "/v1/{mount_point}/oidc/key/{name}", - mount_point=mount_point, - name=name, - ) - return self._adapter.delete( - url=api_path, - ) - - def list_named_keys(self, mount_point=DEFAULT_MOUNT_POINT): - """List all named keys. - - Supported methods: - LIST: {mount_point}/oidc/key. - - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The response of the list_named_keys request. - :rtype: dict - """ - api_path = utils.format_url( - "/v1/{mount_point}/oidc/key", - mount_point=mount_point, - ) - return self._adapter.list( - url=api_path, - ) - - def rotate_named_key(self, name, verification_ttl, mount_point=DEFAULT_MOUNT_POINT): - """Rotate a named key. - - Supported methods: - POST: {mount_point}/oidc/key/:name/rotate. - - :param name: Name of the key to be rotated. - :type name: str | unicode - :param verification_ttl: Controls how long the public portion of the key will be available for verification after being rotated. - Setting verification_ttl here will override the verification_ttl set on the key. - :type verification_ttl: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The response of the rotate_a_named_key request. - :rtype: dict - """ - params = { - "verification_ttl": verification_ttl, - } - api_path = utils.format_url( - "/v1/{mount_point}/oidc/key/{name}", - mount_point=mount_point, - name=name, - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def create_or_update_role( - self, - name, - key, - template=None, - client_id=None, - ttl="24h", - mount_point=DEFAULT_MOUNT_POINT, - ): - """Create or update a role. - - ID tokens are generated against a role and signed against a named key. - - Supported methods: - POST: {mount_point}/oidc/role/:name. - - :param name: Name of the role. - :type name: str | unicode - :param key: A configured named key, the key must already exist. - :type key: str | unicode - :param template: The template string to use for generating tokens. This may be in stringified JSON or - base64 format. - :type template: str | unicode - :param client_id: Optional client ID. A random ID will be generated if left unset. - :type client_id: str | unicode - :param ttl: TTL of the tokens generated against the role. Can be specified as a number of seconds or as a time - string like "30m" or "6h". - :type ttl: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The response of the create_or_update_a_role request. - :rtype: dict - """ - params = utils.remove_nones( - { - "key": key, - "template": template, - "client_id": client_id, - "ttl": ttl, - } - ) - api_path = utils.format_url( - "/v1/{mount_point}/oidc/role/{name}", - mount_point=mount_point, - name=name, - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def read_role(self, name, mount_point=DEFAULT_MOUNT_POINT): - """Query a role and returns its configuration. - - Supported methods: - GET: {mount_point}/oidc/role/:name. - - :param name: Name of the role. - :type name: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The response of the read_a_role request. - :rtype: dict - """ - api_path = utils.format_url( - "/v1/{mount_point}/oidc/role/{name}", - mount_point=mount_point, - name=name, - ) - return self._adapter.get( - url=api_path, - ) - - def delete_role(self, name, mount_point=DEFAULT_MOUNT_POINT): - """Deletes a role. - - Supported methods: - DELETE: {mount_point}/oidc/role/:name. - - - :param name: Name of the role. - :type name: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The response of the delete_a_role request. - :rtype: dict - """ - api_path = utils.format_url( - "/v1/{mount_point}/oidc/role/{name}", - mount_point=mount_point, - name=name, - ) - return self._adapter.delete( - url=api_path, - ) - - def list_roles(self, mount_point=DEFAULT_MOUNT_POINT): - """ - This endpoint will list all signing keys. - - Supported methods: - LIST: {mount_point}/oidc/role. - - - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The response of the list_roles request. - :rtype: dict - """ - api_path = utils.format_url( - "/v1/{mount_point}/oidc/role", - mount_point=mount_point, - ) - return self._adapter.list( - url=api_path, - ) - - def generate_signed_id_token(self, name, mount_point=DEFAULT_MOUNT_POINT): - """Generate a signed ID (OIDC) token. - - Supported methods: - GET: {mount_point}/oidc/token/:name. - - :param name: The name of the role against which to generate a signed ID token - :type name: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The response of the generate_a_signed_id_token request. - :rtype: dict - """ - api_path = utils.format_url( - "/v1/{mount_point}/oidc/token/{name}", - mount_point=mount_point, - name=name, - ) - return self._adapter.get( - url=api_path, - ) - - def introspect_signed_id_token( - self, token, client_id=None, mount_point=DEFAULT_MOUNT_POINT - ): - """Verify the authenticity and active state of a signed ID token. - - Supported methods: - POST: {mount_point}/oidc/introspect. - - - :param token: A signed OIDC compliant ID token - :type token: str | unicode - :param client_id: Specifying the client ID optimizes validation time - :type client_id: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The response of the introspect_a_signed_id_token request. - :rtype: dict - """ - params = utils.remove_nones( - { - "token": token, - "client_id": client_id, - } - ) - api_path = utils.format_url( - "/v1/{mount_point}/oidc/introspect", - mount_point=mount_point, - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def read_well_known_configurations(self, mount_point=DEFAULT_MOUNT_POINT): - """Retrieve a set of claims about the identity tokens' configuration. - - The response is a compliant OpenID Provider Configuration Response. - - Supported methods: - GET: {mount_point}/oidc/.well-known/openid-configuration. - - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The response of the read_well_known_configurations request. - :rtype: dict - """ - api_path = utils.format_url( - "/v1/{mount_point}/oidc/.well-known/openid-configuration", - mount_point=mount_point, - ) - return self._adapter.get( - url=api_path, - ) - - def read_active_public_keys(self, mount_point=DEFAULT_MOUNT_POINT): - """Retrieve the public portion of named keys. - - Clients can use this to validate the authenticity of an identity token. - - Supported methods: - GET: {mount_point}/oidc/.well-known/openid-configuration. - - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The response of the read_active_public_keys request. - :rtype: dict - """ - api_path = utils.format_url( - "/v1/{mount_point}/oidc/.well-known/keys", - mount_point=mount_point, - ) - return self._adapter.get( - url=api_path, - ) diff --git a/.venv/lib/python3.12/site-packages/hvac/api/secrets_engines/kv.py b/.venv/lib/python3.12/site-packages/hvac/api/secrets_engines/kv.py deleted file mode 100644 index 3e039c1..0000000 --- a/.venv/lib/python3.12/site-packages/hvac/api/secrets_engines/kv.py +++ /dev/null @@ -1,80 +0,0 @@ -"""Kv secret backend methods module.""" - -import logging - -from hvac.api.secrets_engines import kv_v1, kv_v2 -from hvac.api.vault_api_base import VaultApiBase - -logger = logging.getLogger(__name__) - - -class Kv(VaultApiBase): - """Class containing methods for the key/value secrets_engines backend API routes. - Reference: https://www.vaultproject.io/docs/secrets/kv/index.html - - """ - - allowed_kv_versions = ["1", "2"] - - def __init__(self, adapter, default_kv_version="2"): - """Create a new Kv instance. - - :param adapter: Instance of :py:class:`hvac.adapters.Adapter`; used for performing HTTP requests. - :type adapter: hvac.adapters.Adapter - :param default_kv_version: KV version number (e.g., '1') to use as the default when accessing attributes/methods - under this class. - :type default_kv_version: str | unicode - """ - super().__init__(adapter=adapter) - self._default_kv_version = default_kv_version - - self._kv_v1 = kv_v1.KvV1(adapter=self._adapter) - self._kv_v2 = kv_v2.KvV2(adapter=self._adapter) - - @property - def v1(self): - """Accessor for kv version 1 class / method. Provided via the :py:class:`hvac.api.secrets_engines.kv_v1.KvV1` class. - - :return: This Kv instance's associated KvV1 instance. - :rtype: hvac.api.secrets_engines.kv_v1.KvV1 - """ - return self._kv_v1 - - @property - def v2(self): - """Accessor for kv version 2 class / method. Provided via the :py:class:`hvac.api.secrets_engines.kv_v2.KvV2` class. - - :return: This Kv instance's associated KvV2 instance. - :rtype: hvac.api.secrets_engines.kv_v2.KvV2 - """ - return self._kv_v2 - - @property - def default_kv_version(self): - return self._default_kv_version - - @default_kv_version.setter - def default_kv_version(self, default_kv_version): - if str(default_kv_version) not in self.allowed_kv_versions: - error_message = 'Invalid "default_kv_version"; "{allowed}" allowed, "{provided}" provided'.format( - allowed=",".join(self.allowed_kv_versions), provided=default_kv_version - ) - raise ValueError(error_message) - self._default_kv_version = str(default_kv_version) - - def __getattr__(self, item): - """Overridden magic method used to direct method calls to the appropriate KV version's hvac class. - - :param item: Name of the attribute/method being accessed - :type item: str | unicode - :return: The selected secrets_engines class corresponding to this instance's default_kv_version setting - :rtype: hvac.api.vault_api_base.VaultApiBase - """ - if item in ["_default_kv_version", "default_kv_version"]: - raise AttributeError - if self.default_kv_version == "1": - return getattr(self._kv_v1, item) - elif self.default_kv_version == "2": - return getattr(self._kv_v2, item) - - raise AttributeError diff --git a/.venv/lib/python3.12/site-packages/hvac/api/secrets_engines/kv_v1.py b/.venv/lib/python3.12/site-packages/hvac/api/secrets_engines/kv_v1.py deleted file mode 100644 index 9ba0afb..0000000 --- a/.venv/lib/python3.12/site-packages/hvac/api/secrets_engines/kv_v1.py +++ /dev/null @@ -1,144 +0,0 @@ -#!/usr/bin/env python -"""KvV1 methods module.""" -from hvac import exceptions, utils -from hvac.api.vault_api_base import VaultApiBase - -DEFAULT_MOUNT_POINT = "secret" - - -class KvV1(VaultApiBase): - """KV Secrets Engine - Version 1 (API). - - Reference: https://www.vaultproject.io/api/secrets/kv/kv-v1.html - """ - - def read_secret(self, path, mount_point=DEFAULT_MOUNT_POINT): - """Retrieve the secret at the specified location. - - Supported methods: - GET: /{mount_point}/{path}. Produces: 200 application/json - - - :param path: Specifies the path of the secret to read. This is specified as part of the URL. - :type path: str | unicode - :param mount_point: The "path" the secret engine was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the read_secret request. - :rtype: dict - """ - api_path = utils.format_url( - "/v1/{mount_point}/{path}", mount_point=mount_point, path=path - ) - return self._adapter.get( - url=api_path, - ) - - def list_secrets(self, path, mount_point=DEFAULT_MOUNT_POINT): - """Return a list of key names at the specified location. - - Folders are suffixed with /. The input must be a folder; list on a file will not return a value. Note that no - policy-based filtering is performed on keys; do not encode sensitive information in key names. The values - themselves are not accessible via this command. - - Supported methods: - LIST: /{mount_point}/{path}. Produces: 200 application/json - - :param path: Specifies the path of the secrets to list. - This is specified as part of the URL. - :type path: str | unicode - :param mount_point: The "path" the secret engine was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the list_secrets request. - :rtype: dict - """ - api_path = utils.format_url( - "/v1/{mount_point}/{path}", mount_point=mount_point, path=path - ) - return self._adapter.list( - url=api_path, - ) - - def create_or_update_secret( - self, path, secret, method=None, mount_point=DEFAULT_MOUNT_POINT - ): - """Store a secret at the specified location. - - If the value does not yet exist, the calling token must have an ACL policy granting the create capability. - If the value already exists, the calling token must have an ACL policy granting the update capability. - - Supported methods: - POST: /{mount_point}/{path}. Produces: 204 (empty body) - PUT: /{mount_point}/{path}. Produces: 204 (empty body) - - :param path: Specifies the path of the secrets to create/update. This is specified as part of the URL. - :type path: str | unicode - :param secret: Specifies keys, paired with associated values, to be held at the given location. Multiple - key/value pairs can be specified, and all will be returned on a read operation. A key called ttl will - trigger some special behavior. See the Vault KV secrets engine documentation for details. - :type secret: dict - :param method: Optional parameter to explicitly request a POST (create) or PUT (update) request to the selected - kv secret engine. If no argument is provided for this parameter, hvac attempts to intelligently determine - which method is appropriate. - :type method: str | unicode - :param mount_point: The "path" the secret engine was mounted on. - :type mount_point: str | unicode - :return: The response of the create_or_update_secret request. - :rtype: requests.Response - """ - if method is None: - # If no method was selected by the caller, use the result of a `read_secret()` call to determine if we need - # to perform an update (PUT) or creation (POST) request. - try: - self.read_secret( - path=path, - mount_point=mount_point, - ) - method = "PUT" - except exceptions.InvalidPath: - method = "POST" - - if method == "POST": - api_path = utils.format_url( - "/v1/{mount_point}/{path}", mount_point=mount_point, path=path - ) - return self._adapter.post( - url=api_path, - json=secret, - ) - - elif method == "PUT": - api_path = utils.format_url( - "/v1/{mount_point}/{path}", mount_point=mount_point, path=path - ) - return self._adapter.put( - url=api_path, - json=secret, - ) - - else: - error_message = '"method" parameter provided invalid value; POST or PUT allowed, "{method}" provided'.format( - method=method - ) - raise exceptions.ParamValidationError(error_message) - - def delete_secret(self, path, mount_point=DEFAULT_MOUNT_POINT): - """Delete the secret at the specified location. - - Supported methods: - DELETE: /{mount_point}/{path}. Produces: 204 (empty body) - - - :param path: Specifies the path of the secret to delete. - This is specified as part of the URL. - :type path: str | unicode - :param mount_point: The "path" the secret engine was mounted on. - :type mount_point: str | unicode - :return: The response of the delete_secret request. - :rtype: requests.Response - """ - api_path = utils.format_url( - "/v1/{mount_point}/{path}", mount_point=mount_point, path=path - ) - return self._adapter.delete( - url=api_path, - ) diff --git a/.venv/lib/python3.12/site-packages/hvac/api/secrets_engines/kv_v2.py b/.venv/lib/python3.12/site-packages/hvac/api/secrets_engines/kv_v2.py deleted file mode 100644 index 6a69bc5..0000000 --- a/.venv/lib/python3.12/site-packages/hvac/api/secrets_engines/kv_v2.py +++ /dev/null @@ -1,509 +0,0 @@ -#!/usr/bin/env python -"""KvV2 methods module.""" - -import warnings - -from hvac import exceptions, utils -from hvac.api.vault_api_base import VaultApiBase - -DEFAULT_MOUNT_POINT = "secret" - - -class KvV2(VaultApiBase): - """KV Secrets Engine - Version 2 (API). - - Reference: https://www.vaultproject.io/api/secret/kv/kv-v2.html - """ - - def configure( - self, - max_versions=10, - cas_required=None, - delete_version_after="0s", - mount_point=DEFAULT_MOUNT_POINT, - ): - """Configure backend level settings that are applied to every key in the key-value store. - - Supported methods: - POST: /{mount_point}/config. Produces: 204 (empty body) - - - :param max_versions: The number of versions to keep per key. This value applies to all keys, but a key's - metadata setting can overwrite this value. Once a key has more than the configured allowed versions the - oldest version will be permanently deleted. Defaults to 10. - :type max_versions: int - :param cas_required: If true all keys will require the cas parameter to be set on all write requests. - :type cas_required: bool - :param mount_point: The "path" the secret engine was mounted on. - :type mount_point: str | unicode - :param delete_version_after: Specifies the length of time before a version is deleted. Accepts Go duration format string. - Defaults to "0s" (i.e., disabled). - :type delete_version_after: str - :return: The response of the request. - :rtype: requests.Response - """ - params = { - "max_versions": max_versions, - "delete_version_after": delete_version_after, - } - if cas_required is not None: - params["cas_required"] = cas_required - api_path = utils.format_url("/v1/{mount_point}/config", mount_point=mount_point) - return self._adapter.post( - url=api_path, - json=params, - ) - - def read_configuration(self, mount_point=DEFAULT_MOUNT_POINT): - """Read the KV Version 2 configuration. - - Supported methods: - GET: /auth/{mount_point}/config. Produces: 200 application/json - - - :param mount_point: The "path" the secret engine was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the request. - :rtype: dict - """ - api_path = utils.format_url( - "/v1/{mount_point}/config", - mount_point=mount_point, - ) - return self._adapter.get(url=api_path) - - def read_secret( - self, path, mount_point=DEFAULT_MOUNT_POINT, raise_on_deleted_version=None - ): - """Retrieve the secret at the specified location. - - Equivalent to calling read_secret_version with version=None. - - Supported methods: - GET: /{mount_point}/data/{path}. Produces: 200 application/json - - - :param path: Specifies the path of the secret to read. This is specified as part of the URL. - :type path: str | unicode - :param mount_point: The "path" the secret engine was mounted on. - :type mount_point: str | unicode - :param raise_on_deleted_version: Changes the behavior when the requested version is deleted. - If True an exception will be raised. - If False, some metadata about the deleted secret is returned. - If None (pre-v3), a default of True will be used and a warning will be issued. - :type raise_on_deleted_version: bool - :return: The JSON response of the request. - :rtype: dict - """ - return self.read_secret_version( - path, - mount_point=mount_point, - raise_on_deleted_version=raise_on_deleted_version, - ) - - def read_secret_version( - self, - path, - version=None, - mount_point=DEFAULT_MOUNT_POINT, - raise_on_deleted_version=None, - ): - """Retrieve the secret at the specified location, with the specified version. - - Supported methods: - GET: /{mount_point}/data/{path}. Produces: 200 application/json - - - :param path: Specifies the path of the secret to read. This is specified as part of the URL. - :type path: str | unicode - :param version: Specifies the version to return. If not set the latest version is returned. - :type version: int - :param mount_point: The "path" the secret engine was mounted on. - :type mount_point: str | unicode - :param raise_on_deleted_version: Changes the behavior when the requested version is deleted. - If True an exception will be raised. - If False, some metadata about the deleted secret is returned. - If None (pre-v3), a default of True will be used and a warning will be issued. - :type raise_on_deleted_version: bool - :return: The JSON response of the request. - :rtype: dict - """ - - if raise_on_deleted_version is None: - msg = ( - "The raise_on_deleted_version parameter will change its default value to False in hvac v3.0.0. " - "The current default of True will presere previous behavior. " - "To use the old behavior with no warning, explicitly set this value to True. " - "See https://github.com/hvac/hvac/pull/907" - ) - warnings.warn( - message=msg, - category=DeprecationWarning, - stacklevel=2, - ) - raise_on_deleted_version = True - - params = {} - if version is not None: - params["version"] = version - api_path = utils.format_url( - "/v1/{mount_point}/data/{path}", mount_point=mount_point, path=path - ) - try: - return self._adapter.get( - url=api_path, - params=params, - ) - except exceptions.InvalidPath as e: - if not raise_on_deleted_version: - try: - if ( - e.json is not None - and e.json["data"]["metadata"]["deletion_time"] != "" - ): - return e.json - except KeyError: - pass - - raise - - def create_or_update_secret( - self, path, secret, cas=None, mount_point=DEFAULT_MOUNT_POINT - ): - """Create a new version of a secret at the specified location. - - If the value does not yet exist, the calling token must have an ACL policy granting the create capability. If - the value already exists, the calling token must have an ACL policy granting the update capability. - - Supported methods: - POST: /{mount_point}/data/{path}. Produces: 200 application/json - - :param path: Path - :type path: str | unicode - :param cas: Set the "cas" value to use a Check-And-Set operation. If not set the write will be allowed. If set - to 0 a write will only be allowed if the key doesn't exist. If the index is non-zero the write will only be - allowed if the key's current version matches the version specified in the cas parameter. - :type cas: int - :param secret: The contents of the "secret" dict will be stored and returned on read. - :type secret: dict - :param mount_point: The "path" the secret engine was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the request. - :rtype: dict - """ - params = { - "options": {}, - "data": secret, - } - - if cas is not None: - params["options"]["cas"] = cas - - api_path = utils.format_url( - "/v1/{mount_point}/data/{path}", mount_point=mount_point, path=path - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def patch(self, path, secret, mount_point=DEFAULT_MOUNT_POINT): - """Set or update data in the KV store without overwriting. - - :param path: Path - :type path: str | unicode - :param secret: The contents of the "secret" dict will be stored and returned on read. - :type secret: dict - :param mount_point: The "path" the secret engine was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the create_or_update_secret request. - :rtype: dict - """ - # First, do a read. - try: - current_secret_version = self.read_secret_version( - path=path, - mount_point=mount_point, - ) - except exceptions.InvalidPath: - raise exceptions.InvalidPath( - 'No value found at "{path}"; patch only works on existing data.'.format( - path=path - ) - ) - - # Update existing secret dict. - patched_secret = current_secret_version["data"]["data"] - patched_secret.update(secret) - - # Write back updated secret. - return self.create_or_update_secret( - path=path, - cas=current_secret_version["data"]["metadata"]["version"], - secret=patched_secret, - mount_point=mount_point, - ) - - def delete_latest_version_of_secret(self, path, mount_point=DEFAULT_MOUNT_POINT): - """Issue a soft delete of the secret's latest version at the specified location. - - This marks the version as deleted and will stop it from being returned from reads, but the underlying data will - not be removed. A delete can be undone using the undelete path. - - Supported methods: - DELETE: /{mount_point}/data/{path}. Produces: 204 (empty body) - - - :param path: Specifies the path of the secret to delete. This is specified as part of the URL. - :type path: str | unicode - :param mount_point: The "path" the secret engine was mounted on. - :type mount_point: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url( - "/v1/{mount_point}/data/{path}", mount_point=mount_point, path=path - ) - return self._adapter.delete( - url=api_path, - ) - - def delete_secret_versions(self, path, versions, mount_point=DEFAULT_MOUNT_POINT): - """Issue a soft delete of the specified versions of the secret. - - This marks the versions as deleted and will stop them from being returned from reads, - but the underlying data will not be removed. A delete can be undone using the - undelete path. - - Supported methods: - POST: /{mount_point}/delete/{path}. Produces: 204 (empty body) - - - :param path: Specifies the path of the secret to delete. This is specified as part of the URL. - :type path: str | unicode - :param versions: The versions to be deleted. The versioned data will not be deleted, but it will no longer be - returned in normal get requests. - :type versions: int - :param mount_point: The "path" the secret engine was mounted on. - :type mount_point: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - if not isinstance(versions, list) or len(versions) == 0: - error_msg = 'argument to "versions" must be a list containing one or more integers, "{versions}" provided.'.format( - versions=versions - ) - raise exceptions.ParamValidationError(error_msg) - params = { - "versions": versions, - } - api_path = utils.format_url( - "/v1/{mount_point}/delete/{path}", mount_point=mount_point, path=path - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def undelete_secret_versions(self, path, versions, mount_point=DEFAULT_MOUNT_POINT): - """Undelete the data for the provided version and path in the key-value store. - - This restores the data, allowing it to be returned on get requests. - - Supported methods: - POST: /{mount_point}/undelete/{path}. Produces: 204 (empty body) - - - :param path: Specifies the path of the secret to undelete. This is specified as part of the URL. - :type path: str | unicode - :param versions: The versions to undelete. The versions will be restored and their data will be returned on - normal get requests. - :type versions: list of int - :param mount_point: The "path" the secret engine was mounted on. - :type mount_point: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - if not isinstance(versions, list) or len(versions) == 0: - error_msg = 'argument to "versions" must be a list containing one or more integers, "{versions}" provided.'.format( - versions=versions - ) - raise exceptions.ParamValidationError(error_msg) - params = { - "versions": versions, - } - api_path = utils.format_url( - "/v1/{mount_point}/undelete/{path}", mount_point=mount_point, path=path - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def destroy_secret_versions(self, path, versions, mount_point=DEFAULT_MOUNT_POINT): - """Permanently remove the specified version data and numbers for the provided path from the key-value store. - - Supported methods: - POST: /{mount_point}/destroy/{path}. Produces: 204 (empty body) - - - :param path: Specifies the path of the secret to destroy. - This is specified as part of the URL. - :type path: str | unicode - :param versions: The versions to destroy. Their data will be - permanently deleted. - :type versions: list of int - :param mount_point: The "path" the secret engine was mounted on. - :type mount_point: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - if not isinstance(versions, list) or len(versions) == 0: - error_msg = 'argument to "versions" must be a list containing one or more integers, "{versions}" provided.'.format( - versions=versions - ) - raise exceptions.ParamValidationError(error_msg) - params = { - "versions": versions, - } - api_path = utils.format_url( - "/v1/{mount_point}/destroy/{path}", mount_point=mount_point, path=path - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def list_secrets(self, path, mount_point=DEFAULT_MOUNT_POINT): - """Return a list of key names at the specified location. - - Folders are suffixed with /. The input must be a folder; list on a file will not return a value. Note that no - policy-based filtering is performed on keys; do not encode sensitive information in key names. The values - themselves are not accessible via this command. - - Supported methods: - LIST: /{mount_point}/metadata/{path}. Produces: 200 application/json - - - :param path: Specifies the path of the secrets to list. This is specified as part of the URL. - :type path: str | unicode - :param mount_point: The "path" the secret engine was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the request. - :rtype: dict - """ - api_path = utils.format_url( - "/v1/{mount_point}/metadata/{path}", mount_point=mount_point, path=path - ) - return self._adapter.list( - url=api_path, - ) - - def read_secret_metadata(self, path, mount_point=DEFAULT_MOUNT_POINT): - """Retrieve the metadata and versions for the secret at the specified path. - - Supported methods: - GET: /{mount_point}/metadata/{path}. Produces: 200 application/json - - - :param path: Specifies the path of the secret to read. This is specified as part of the URL. - :type path: str | unicode - :param mount_point: The "path" the secret engine was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the request. - :rtype: dict - """ - api_path = utils.format_url( - "/v1/{mount_point}/metadata/{path}", mount_point=mount_point, path=path - ) - return self._adapter.get( - url=api_path, - ) - - def update_metadata( - self, - path, - max_versions=None, - cas_required=None, - delete_version_after="0s", - mount_point=DEFAULT_MOUNT_POINT, - custom_metadata=None, - ): - """Updates the max_versions of cas_required setting on an existing path. - - Supported methods: - POST: /{mount_point}/metadata/{path}. Produces: 204 (empty body) - - - :param path: Path - :type path: str | unicode - :param max_versions: The number of versions to keep per key. If not set, the backend's configured max version is - used. Once a key has more than the configured allowed versions the oldest version will be permanently - deleted. - :type max_versions: int - :param cas_required: If true the key will require the cas parameter to be set on all write requests. If false, - the backend's configuration will be used. - :type cas_required: bool - :param delete_version_after: Specifies the length of time before a version is deleted. Accepts Go duration format string. - Defaults to "0s" (i.e., disabled). - :type delete_version_after: str - :param mount_point: The "path" the secret engine was mounted on. - :type mount_point: str | unicode - :param custom_metadata: A dictionary of key/value metadata to describe the secret. Requires Vault 1.9.0 or greater. - :type custom_metadata: dict - :return: The response of the request. - :rtype: requests.Response - """ - params = { - "delete_version_after": delete_version_after, - } - if max_versions is not None: - params["max_versions"] = max_versions - if cas_required is not None: - if not isinstance(cas_required, bool): - error_msg = ( - "bool expected for cas_required param, {type} received".format( - type=type(cas_required) - ) - ) - raise exceptions.ParamValidationError(error_msg) - params["cas_required"] = cas_required - if custom_metadata is not None: - if not isinstance(custom_metadata, dict): - error_msg = ( - "dict expected for custom_metadata param, {type} received".format( - type=type(custom_metadata) - ) - ) - raise exceptions.ParamValidationError(error_msg) - params["custom_metadata"] = custom_metadata - api_path = utils.format_url( - "/v1/{mount_point}/metadata/{path}", mount_point=mount_point, path=path - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def delete_metadata_and_all_versions(self, path, mount_point=DEFAULT_MOUNT_POINT): - """Delete (permanently) the key metadata and all version data for the specified key. - - All version history will be removed. - - Supported methods: - DELETE: /{mount_point}/metadata/{path}. Produces: 204 (empty body) - - - :param path: Specifies the path of the secret to delete. This is specified as part of the URL. - :type path: str | unicode - :param mount_point: The "path" the secret engine was mounted on. - :type mount_point: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url( - "/v1/{mount_point}/metadata/{path}", mount_point=mount_point, path=path - ) - return self._adapter.delete( - url=api_path, - ) diff --git a/.venv/lib/python3.12/site-packages/hvac/api/secrets_engines/ldap.py b/.venv/lib/python3.12/site-packages/hvac/api/secrets_engines/ldap.py deleted file mode 100644 index 1d8c133..0000000 --- a/.venv/lib/python3.12/site-packages/hvac/api/secrets_engines/ldap.py +++ /dev/null @@ -1,236 +0,0 @@ -#!/usr/bin/env python -"""LDAP methods module.""" - -from hvac import utils -from hvac.api.vault_api_base import VaultApiBase - -DEFAULT_MOUNT_POINT = "ldap" - - -class Ldap(VaultApiBase): - """LDAP Secrets Engine (API). - Reference: https://www.vaultproject.io/api/secret/ldap/index.html - """ - - def configure( - self, - binddn=None, - bindpass=None, - url=None, - password_policy=None, - schema=None, - userdn=None, - userattr=None, - upndomain=None, - connection_timeout=None, - request_timeout=None, - starttls=None, - insecure_tls=None, - certificate=None, - client_tls_cert=None, - client_tls_key=None, - mount_point=DEFAULT_MOUNT_POINT, - ): - """Configure shared information for the ldap secrets engine. - - Supported methods: - POST: /{mount_point}/config. Produces: 204 (empty body) - - :param binddn: Distinguished name of object to bind when performing user and group search. - :type binddn: str | unicode - :param bindpass: Password to use along with binddn when performing user search. - :type bindpass: str | unicode - :param url: Base DN under which to perform user search. - :type url: str | unicode - :param userdn: Base DN under which to perform user search. - :type userdn: str | unicode - :param upndomain: userPrincipalDomain used to construct the UPN string for the authenticating user. - :type upndomain: str | unicode - :param password_policy: The name of the password policy to use to generate passwords. - :type password_policy: str | unicode - :param schema: The LDAP schema to use when storing entry passwords. Valid schemas include ``openldap``, ``ad``, and ``racf``. - :type schema: str | unicode - :param connection_timeout: Timeout, in seconds, when attempting to connect to the LDAP server before trying the next URL in the configuration. - :type connection_timeout: int | str - :param request_timeout: Timeout, in seconds, for the connection when making requests against the server before returning back an error. - :type request_timeout: int | str - :param starttls: If true, issues a StartTLS command after establishing an unencrypted connection. - :type starttls: bool - :param insecure_tls: If true, skips LDAP server SSL certificate verification - insecure, use with caution! - :type insecure_tls: bool - :param certificate: CA certificate to use when verifying LDAP server certificate, must be x509 PEM encoded. - :type certificate: str | unicode - :param client_tls_cert: Client certificate to provide to the LDAP server, must be x509 PEM encoded. - :type client_tls_cert: str | unicode - :param client_tls_key: Client key to provide to the LDAP server, must be x509 PEM encoded. - :type client_tls_key: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - params = utils.remove_nones( - { - "binddn": binddn, - "bindpass": bindpass, - "url": url, - "userdn": userdn, - "userattr": userattr, - "upndomain": upndomain, - "password_policy": password_policy, - "schema": schema, - "connection_timeout": connection_timeout, - "request_timeout": request_timeout, - "starttls": starttls, - "insecure_tls": insecure_tls, - "certificate": certificate, - "client_tls_cert": client_tls_cert, - "client_tls_key": client_tls_key, - } - ) - - api_path = utils.format_url("/v1/{mount_point}/config", mount_point=mount_point) - return self._adapter.post( - url=api_path, - json=params, - ) - - def read_config(self, mount_point=DEFAULT_MOUNT_POINT): - """Read the configured shared information for the ldap secrets engine. - - Credentials will be omitted from returned data. - - Supported methods: - GET: /{mount_point}/config. Produces: 200 application/json - - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the request. - :rtype: dict - """ - api_path = utils.format_url("/v1/{mount_point}/config", mount_point=mount_point) - return self._adapter.get( - url=api_path, - ) - - def rotate_root(self, mount_point=DEFAULT_MOUNT_POINT): - """Rotate the root password for the binddn entry used to manage the ldap secrets engine. - - Supported methods: - POST: /{mount_point}/rotate root. Produces: 200 application/json - - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the request. - :rtype: dict - """ - api_path = utils.format_url( - "/v1/{mount_point}/rotate-root", mount_point=mount_point - ) - return self._adapter.post(url=api_path) - - def create_or_update_static_role( - self, - name, - username=None, - dn=None, - rotation_period=None, - mount_point=DEFAULT_MOUNT_POINT, - ): - """This endpoint creates or updates the ldap static role definition. - - :param name: Specifies the name of an existing static role against which to create this ldap credential. - :type name: str | unicode - :param username: The name of a pre-existing service account in LDAP that maps to this static role. - This value is required on create and cannot be updated. - :type username: str | unicode - :param dn: Distinguished name of the existing LDAP entry to manage password rotation for (takes precedence over username). - Optional but cannot be modified after creation. - :type dn: str | unicode - :param rotation_period: How often Vault should rotate the password. - This is provided as a string duration with a time suffix like "30s" or "1h" or as seconds. - If not provided, the default Vault rotation_period is used. - :type rotation_period: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url("/v1/{}/static-role/{}", mount_point, name) - params = {"username": username, "rotation_period": rotation_period} - params.update(utils.remove_nones({"dn": dn})) - return self._adapter.post( - url=api_path, - json=params, - ) - - def read_static_role(self, name, mount_point=DEFAULT_MOUNT_POINT): - """This endpoint queries for information about an ldap static role with the given name. - If no role exists with that name, a 404 is returned. - :param name: Specifies the name of the static role to query. - :type name: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url("/v1/{}/static-role/{}", mount_point, name) - return self._adapter.get( - url=api_path, - ) - - def list_static_roles(self, mount_point=DEFAULT_MOUNT_POINT): - """This endpoint lists all existing static roles in the secrets engine. - :return: The response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url("/v1/{}/static-role", mount_point) - return self._adapter.list( - url=api_path, - ) - - def delete_static_role(self, name, mount_point=DEFAULT_MOUNT_POINT): - """This endpoint deletes an ldap static role with the given name. - Even if the role does not exist, this endpoint will still return a successful response. - :param name: Specifies the name of the role to delete. - :type name: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url("/v1/{}/static-role/{}", mount_point, name) - return self._adapter.delete( - url=api_path, - ) - - def generate_static_credentials(self, name, mount_point=DEFAULT_MOUNT_POINT): - """This endpoint retrieves the previous and current LDAP password for - the associated account (or rotate if required) - - :param name: Specifies the name of the static role to request credentials from. - :type name: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url("/v1/{}/static-cred/{}", mount_point, name) - return self._adapter.get( - url=api_path, - ) - - def rotate_static_credentials(self, name, mount_point=DEFAULT_MOUNT_POINT): - """This endpoint rotates the password of an existing static role. - - :param name: Specifies the name of the static role to rotate credentials for. - :type name: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url("/v1/{}/rotate-role/{}", mount_point, name) - return self._adapter.post( - url=api_path, - ) diff --git a/.venv/lib/python3.12/site-packages/hvac/api/secrets_engines/pki.py b/.venv/lib/python3.12/site-packages/hvac/api/secrets_engines/pki.py deleted file mode 100644 index dd3571e..0000000 --- a/.venv/lib/python3.12/site-packages/hvac/api/secrets_engines/pki.py +++ /dev/null @@ -1,878 +0,0 @@ -#!/usr/bin/env python -"""PKI methods module.""" -from hvac import utils -from hvac.api.vault_api_base import VaultApiBase - -DEFAULT_MOUNT_POINT = "pki" - - -class Pki(VaultApiBase): - """Pki Secrets Engine (API). - - Reference: https://www.vaultproject.io/api/secret/pki/index.html - """ - - def read_ca_certificate(self, mount_point=DEFAULT_MOUNT_POINT): - """Read CA Certificate. - - Retrieves the CA certificate in raw DER-encoded form. - - Supported methods: - GET: /{mount_point}/ca/pem. Produces: String - - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The certificate as pem. - :rtype: str - """ - api_path = utils.format_url("/v1/{mount_point}/ca/pem", mount_point=mount_point) - response = self._adapter.get( - url=api_path, - ) - return str(response.text) - - def read_ca_certificate_chain(self, mount_point=DEFAULT_MOUNT_POINT): - """Read CA Certificate Chain. - - Retrieves the CA certificate chain, including the CA in PEM format. - - Supported methods: - GET: /{mount_point}/ca_chain. Produces: String - - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The certificate chain as pem. - :rtype: str - """ - api_path = utils.format_url( - "/v1/{mount_point}/ca_chain", mount_point=mount_point - ) - response = self._adapter.get( - url=api_path, - ) - return str(response.text) - - def read_certificate(self, serial, mount_point=DEFAULT_MOUNT_POINT): - """Read Certificate. - - Retrieves one of a selection of certificates. - - Supported methods: - GET: /{mount_point}/cert/{serial}. Produces: 200 application/json - - :param serial: the serial of the key to read. - :type serial: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the request. - :rtype: dict - """ - api_path = utils.format_url( - "/v1/{mount_point}/cert/{serial}", - mount_point=mount_point, - serial=serial, - ) - return self._adapter.get( - url=api_path, - ) - - def list_certificates(self, mount_point=DEFAULT_MOUNT_POINT): - """List Certificates. - - The list of the current certificates by serial number only. - - Supported methods: - LIST: /{mount_point}/certs. Produces: 200 application/json - - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the request. - :rtype: dict - """ - api_path = utils.format_url("/v1/{mount_point}/certs", mount_point=mount_point) - return self._adapter.list( - url=api_path, - ) - - def submit_ca_information(self, pem_bundle, mount_point=DEFAULT_MOUNT_POINT): - """Submit CA Information. - - Submitting the CA information for the backend. - - Supported methods: - POST: /{mount_point}/config/ca. Produces: 200 application/json - - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the request. - :rtype: requests.Response - """ - params = { - "pem_bundle": pem_bundle, - } - api_path = utils.format_url( - "/v1/{mount_point}/config/ca", mount_point=mount_point - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def read_crl_configuration(self, mount_point=DEFAULT_MOUNT_POINT): - """Read CRL Configuration. - - Getting the duration for which the generated CRL should be marked valid. - - Supported methods: - GET: /{mount_point}/config/crl. Produces: 200 application/json - - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the request. - :rtype: dict - """ - api_path = utils.format_url( - "/v1/{mount_point}/config/crl", mount_point=mount_point - ) - return self._adapter.get( - url=api_path, - ) - - def set_crl_configuration( - self, - expiry=None, - disable=None, - extra_params=None, - mount_point=DEFAULT_MOUNT_POINT, - ): - """Set CRL Configuration. - - Setting the duration for which the generated CRL should be marked valid. - If the CRL is disabled, it will return a signed but zero-length CRL for any - request. If enabled, it will re-build the CRL. - - Supported methods: - POST: /{mount_point}/config/crl. Produces: 200 application/json - - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the request. - :rtype: requests.Response - """ - if extra_params is None: - extra_params = {} - api_path = utils.format_url( - "/v1/{mount_point}/config/crl", mount_point=mount_point - ) - params = extra_params - params.update( - utils.remove_nones( - { - "expiry": expiry, - "disable": disable, - } - ) - ) - - return self._adapter.post( - url=api_path, - json=params, - ) - - def read_urls(self, mount_point=DEFAULT_MOUNT_POINT): - """Read URLs. - - Fetches the URLs to be encoded in generated certificates. - - Supported methods: - GET: /{mount_point}/config/urls. Produces: 200 application/json - - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the request. - :rtype: dict - """ - api_path = utils.format_url( - "/v1/{mount_point}/config/urls", mount_point=mount_point - ) - return self._adapter.get( - url=api_path, - ) - - def set_urls(self, params, mount_point=DEFAULT_MOUNT_POINT): - """Set URLs. - - Setting the issuing certificate endpoints, CRL distribution points, and OCSP server endpoints that will be - encoded into issued certificates. You can update any of the values at any time without affecting the other - existing values. To remove the values, simply use a blank string as the parameter. - - Supported methods: - POST: /{mount_point}/config/urls. Produces: 200 application/json - - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url( - "/v1/{mount_point}/config/urls", mount_point=mount_point - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def read_crl(self, mount_point=DEFAULT_MOUNT_POINT): - """Read CRL. - - Retrieves the current CRL in PEM format. - This endpoint is an unauthenticated. - - Supported methods: - GET: /{mount_point}/crl/pem. Produces: 200 application/pkix-crl - - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The content of the request e.g. CRL string representation. - :rtype: str - """ - api_path = utils.format_url( - "/v1/{mount_point}/crl/pem", mount_point=mount_point - ) - response = self._adapter.get( - url=api_path, - ) - # python2.7 uses unicode - return str(response.text) - - def rotate_crl(self, mount_point=DEFAULT_MOUNT_POINT): - """Rotate CRLs. - - Forces a rotation of the CRL. - - Supported methods: - GET: /{mount_point}/crl/rotate. Produces: 200 application/json - - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the request. - :rtype: dict - """ - api_path = utils.format_url( - "/v1/{mount_point}/crl/rotate", mount_point=mount_point - ) - return self._adapter.get( - url=api_path, - ) - - def generate_intermediate( - self, - type, - common_name, - extra_params=None, - mount_point=DEFAULT_MOUNT_POINT, - wrap_ttl=None, - ): - """Generate Intermediate. - - Generates a new private key and a CSR for signing. - - Supported methods: - POST: /{mount_point}/intermediate/generate/{type}. Produces: 200 application/json - - :param type: Specifies the type to create. `exported` (private key also exported) or `internal`. - :type type: str | unicode - :param common_name: Specifies the requested CN for the certificate. - :type common_name: str | unicode - :param extra_params: Dictionary with extra parameters. - :type extra_params: dict - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :param wrap_ttl: Specifies response wrapping token creation with duration. IE: '15s', '20m', '25h'. - :type wrap_ttl: str | unicode - :return: The JSON response of the request. - :rtype: requests.Response - """ - if extra_params is None: - extra_params = {} - api_path = utils.format_url( - "/v1/{mount_point}/intermediate/generate/{type}", - mount_point=mount_point, - type=type, - ) - - params = extra_params - params["common_name"] = common_name - - return self._adapter.post( - url=api_path, - json=params, - wrap_ttl=wrap_ttl, - ) - - def set_signed_intermediate(self, certificate, mount_point=DEFAULT_MOUNT_POINT): - """Set Signed Intermediate. - - Allows submitting the signed CA certificate corresponding to a private key generated via "Generate Intermediate" - - Supported methods: - POST: /{mount_point}/intermediate/set-signed. Produces: 200 application/json - - :param certificate: Specifies the certificate in PEM format. - :type certificate: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url( - "/v1/{mount_point}/intermediate/set-signed", - mount_point=mount_point, - ) - - params = {} - params["certificate"] = certificate - - return self._adapter.post( - url=api_path, - json=params, - ) - - def generate_certificate( - self, - name, - common_name, - extra_params=None, - mount_point=DEFAULT_MOUNT_POINT, - wrap_ttl=None, - ): - """Generate Certificate. - - Generates a new set of credentials (private key and certificate) based on the role named in the endpoint. - - Supported methods: - POST: /{mount_point}/issue/{name}. Produces: 200 application/json - - :param name: The name of the role to create the certificate against. - :name name: str | unicode - :param common_name: The requested CN for the certificate. - :name common_name: str | unicode - :param extra_params: A dictionary with extra parameters. - :name extra_params: dict - :param mount_point: The "path" the method/backend was mounted on. - :name mount_point: str | unicode - :param wrap_ttl: Specifies response wrapping token creation with duration. IE: '15s', '20m', '25h'. - :type wrap_ttl: str | unicode - :return: The JSON response of the request. - :rtype: requests.Response - """ - if extra_params is None: - extra_params = {} - api_path = utils.format_url( - "/v1/{mount_point}/issue/{name}", - mount_point=mount_point, - name=name, - ) - - params = extra_params - params["common_name"] = common_name - - return self._adapter.post( - url=api_path, - json=params, - wrap_ttl=wrap_ttl, - ) - - def revoke_certificate(self, serial_number, mount_point=DEFAULT_MOUNT_POINT): - """Revoke Certificate. - - Revokes a certificate using its serial number. - - Supported methods: - POST: /{mount_point}/revoke. Produces: 200 application/json - - :param serial_number: The serial number of the certificate to revoke. - :name serial_number: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :name mount_point: str | unicode - :return: The JSON response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url("/v1/{mount_point}/revoke", mount_point=mount_point) - - params = {} - params["serial_number"] = serial_number - - return self._adapter.post( - url=api_path, - json=params, - ) - - def create_or_update_role( - self, name, extra_params=None, mount_point=DEFAULT_MOUNT_POINT - ): - """Create/Update Role. - - Creates or updates the role definition. - - Supported methods: - POST: /{mount_point}/roles/{name}. Produces: 200 application/json - - :param name: The name of the role to create. - :name name: str | unicode - :param extra_params: A dictionary with extra parameters. - :name extra_params: dict - :param mount_point: The "path" the method/backend was mounted on. - :name mount_point: str | unicode - :return: The JSON response of the request. - :rname: requests.Response - """ - if extra_params is None: - extra_params = {} - api_path = utils.format_url( - "/v1/{mount_point}/roles/{name}", - mount_point=mount_point, - name=name, - ) - - params = extra_params - params["name"] = name - - return self._adapter.post( - url=api_path, - json=params, - ) - - def read_role(self, name, mount_point=DEFAULT_MOUNT_POINT): - """Read Role. - - Queries the role definition. - - Supported methods: - GET: /{mount_point}/roles/{name}. Produces: 200 application/json - - :param name: The name of the role to read. - :type name: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the request. - :rtype: dict - """ - api_path = utils.format_url( - "/v1/{mount_point}/roles/{name}", - mount_point=mount_point, - name=name, - ) - return self._adapter.get( - url=api_path, - ) - - def list_roles(self, mount_point=DEFAULT_MOUNT_POINT): - """List Roles. - - Get a list of available roles. - - Supported methods: - LIST: /{mount_point}/roles. Produces: 200 application/json - - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the request. - :rtype: dict - """ - api_path = utils.format_url("/v1/{mount_point}/roles", mount_point=mount_point) - return self._adapter.list( - url=api_path, - ) - - def delete_role(self, name, mount_point=DEFAULT_MOUNT_POINT): - """Delete Role. - - Deletes the role definition. - - Supported methods: - DELETE: /{mount_point}/roles/{name}. Produces: 200 application/json - - :param name: The name of the role to delete. - :name name: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :name mount_point: str | unicode - :return: The JSON response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url( - "/v1/{mount_point}/roles/{name}", - mount_point=mount_point, - name=name, - ) - - return self._adapter.delete( - url=api_path, - ) - - def generate_root( - self, - type, - common_name, - extra_params=None, - mount_point=DEFAULT_MOUNT_POINT, - wrap_ttl=None, - ): - """Generate Root. - - Generates a new self-signed CA certificate and private key. - - Supported methods: - POST: /{mount_point}/root/generate/{type}. Produces: 200 application/json - - :param type: Specifies the type to create. `exported` (private key also exported) or `internal`. - :type type: str | unicode - :param common_name: The requested CN for the certificate. - :type common_name: str | unicode - :param extra_params: A dictionary with extra parameters. - :type extra_params: dict - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :param wrap_ttl: Specifies response wrapping token creation with duration. IE: '15s', '20m', '25h'. - :type wrap_ttl: str | unicode - :return: The JSON response of the request. - :rtype: requests.Response - """ - if extra_params is None: - extra_params = {} - api_path = utils.format_url( - "/v1/{mount_point}/root/generate/{type}", - mount_point=mount_point, - type=type, - ) - - params = extra_params - params["common_name"] = common_name - - return self._adapter.post( - url=api_path, - json=params, - wrap_ttl=wrap_ttl, - ) - - def delete_root(self, mount_point=DEFAULT_MOUNT_POINT): - """Delete Root. - - Deletes the current CA key. - - Supported methods: - DELETE: /{mount_point}/root. Produces: 200 application/json - - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url( - "/v1/{mount_point}/root", - mount_point=mount_point, - ) - - return self._adapter.delete( - url=api_path, - ) - - def sign_intermediate( - self, csr, common_name, extra_params=None, mount_point=DEFAULT_MOUNT_POINT - ): - """Sign Intermediate. - - Issue a certificate with appropriate values for acting as an intermediate CA. - - Supported methods: - POST: /{mount_point}/root/sign-intermediate. Produces: 200 application/json - - :param csr: The PEM-encoded CSR. - :type csr: str | unicode - :param common_name: The requested CN for the certificate. - :type common_name: str | unicode - :param extra_params: Dictionary with extra parameters. - :type extra_params: dict - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the request. - :rtype: requests.Response - """ - if extra_params is None: - extra_params = {} - api_path = utils.format_url( - "/v1/{mount_point}/root/sign-intermediate", mount_point=mount_point - ) - - params = extra_params - params["csr"] = csr - params["common_name"] = common_name - - return self._adapter.post( - url=api_path, - json=params, - ) - - def sign_self_issued(self, certificate, mount_point=DEFAULT_MOUNT_POINT): - """Sign Self-Issued. - - Sign a self-issued certificate. - - Supported methods: - POST: /{mount_point}/root/sign-self-issued. Produces: 200 application/json - - :param certificate: The PEM-encoded self-issued certificate. - :type certificate: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url( - "/v1/{mount_point}/root/sign-self-issued", mount_point=mount_point - ) - - params = {} - params["certificate"] = certificate - - return self._adapter.post( - url=api_path, - json=params, - ) - - def sign_certificate( - self, name, csr, common_name, extra_params=None, mount_point=DEFAULT_MOUNT_POINT - ): - """Sign Certificate. - - Signs a new certificate based upon the provided CSR and the supplied parameters. - - Supported methods: - POST: /{mount_point}/sign/{name}. Produces: 200 application/json - - :param name: The role to sign the certificate. - :type name: str | unicode - :param csr: The PEM-encoded CSR. - :type csr: str | unicode - :param common_name: The requested CN for the certificate. If the CN is allowed by role policy, it will be issued. - :type common_name: str | unicode - :param extra_params: A dictionary with extra parameters. - :type extra_params: dict - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the request. - :rtype: requests.Response - """ - if extra_params is None: - extra_params = {} - api_path = utils.format_url( - "/v1/{mount_point}/sign/{name}", - mount_point=mount_point, - name=name, - ) - - params = extra_params - params["csr"] = csr - params["common_name"] = common_name - - return self._adapter.post( - url=api_path, - json=params, - ) - - def sign_verbatim( - self, csr, name=False, extra_params=None, mount_point=DEFAULT_MOUNT_POINT - ): - """Sign Verbatim. - - Signs a new certificate based upon the provided CSR. - - Supported methods: - POST: /{mount_point}/sign-verbatim. Produces: 200 application/json - - :param csr: The PEM-encoded CSR. - :type csr: str | unicode - :param name: Specifies a role. - :type name: str | unicode - :param extra_params: A dictionary with extra parameters. - :type extra_params: dict - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the request. - :rtype: requests.Response - """ - if extra_params is None: - extra_params = {} - url_to_transform = "/v1/{mount_point}/sign-verbatim" - if name: - url_to_transform = url_to_transform + "/{name}" - - api_path = utils.format_url( - url_to_transform, - mount_point=mount_point, - name=name, - ) - - params = extra_params - params["csr"] = csr - - return self._adapter.post( - url=api_path, - json=params, - ) - - def tidy(self, extra_params=None, mount_point=DEFAULT_MOUNT_POINT): - """Tidy. - - Allows tidying up the storage backend and/or CRL by removing certificates that have - expired and are past a certain buffer period beyond their expiration time. - - Supported methods: - POST: /{mount_point}/tidy. Produces: 200 application/json - - :param extra_params: A dictionary with extra parameters. - :type extra_params: dict - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the request. - :rtype: requests.Response - """ - if extra_params is None: - extra_params = {} - api_path = utils.format_url( - "/v1/{mount_point}/tidy", - mount_point=mount_point, - ) - - params = extra_params - - return self._adapter.post( - url=api_path, - json=params, - ) - - def read_issuer(self, issuer_ref, mount_point=DEFAULT_MOUNT_POINT): - """Read issuer. - - Get configuration of a issuer by its reference ID. - - Supported methods: - GET: /{mount_point}/issuer/{issuer_ref}. Produces: 200 application/json - - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :param issuer_ref: The reference ID of the issuer to get - :type issuer_ref: str | unicode - :return: The JSON response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url( - "/v1/{mount_point}/issuer/{issuer_ref}", - mount_point=mount_point, - issuer_ref=issuer_ref, - ) - - return self._adapter.get( - url=api_path, - ) - - def list_issuers(self, mount_point=DEFAULT_MOUNT_POINT): - """List issuers. - - Get list of all issuers for a given pki mount. - - Supported methods: - LIST: /{mount_point}/issuers. Produces: 200 application/json - - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url( - "/v1/{mount_point}/issuers", - mount_point=mount_point, - ) - - return self._adapter.list( - url=api_path, - ) - - def update_issuer( - self, issuer_ref, extra_params=None, mount_point=DEFAULT_MOUNT_POINT - ): - """Update issuer. - - Update a given issuer. - - Supported methods: - POST: /{mount_point}/issuer/{issuer_ref}. Produces: 200 application/json - - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :param issuer_ref: The reference ID of the issuer to update - :type issuer_ref: str | unicode - :param extra_params: Dictionary with extra parameters. - :type extra_params: dict - :return: The JSON response of the request. - :rtype: requests.Response - """ - params = extra_params - - api_path = utils.format_url( - "/v1/{mount_point}/issuer/{issuer_ref}", - mount_point=mount_point, - issuer_ref=issuer_ref, - ) - - return self._adapter.post(url=api_path, json=params) - - def revoke_issuer(self, issuer_ref, mount_point=DEFAULT_MOUNT_POINT): - """Revoke issuer. - - Revokes a given issuer. - - Supported methods: - POST: /{mount_point}/issuer/{issuer_ref}/revoke. Produces: 200 application/json - - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :param issuer_ref: The reference ID of the issuer to revoke - :type issuer_ref: str | unicode - :return: The JSON response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url( - "/v1/{mount_point}/issuer/{issuer_ref}/revoke", - mount_point=mount_point, - issuer_ref=issuer_ref, - ) - - return self._adapter.post( - url=api_path, - ) - - def delete_issuer(self, issuer_ref, mount_point=DEFAULT_MOUNT_POINT): - """Delete issuer. - - Delete a given issuer. Deleting the default issuer will result in a warning - - Supported methods: - DELETE: /{mount_point}/issuer/{issuer_ref}. Produces: 200 application/json - - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :param issuer_ref: The reference ID of the issuer to delete - :type issuer_ref: str | unicode - :return: The JSON response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url( - "/v1/{mount_point}/issuer/{issuer_ref}", - mount_point=mount_point, - issuer_ref=issuer_ref, - ) - - return self._adapter.delete( - url=api_path, - ) diff --git a/.venv/lib/python3.12/site-packages/hvac/api/secrets_engines/rabbitmq.py b/.venv/lib/python3.12/site-packages/hvac/api/secrets_engines/rabbitmq.py deleted file mode 100644 index 1d8ac6c..0000000 --- a/.venv/lib/python3.12/site-packages/hvac/api/secrets_engines/rabbitmq.py +++ /dev/null @@ -1,147 +0,0 @@ -#!/usr/bin/env python -"""RabbitMQ vault secrets backend module.""" - -from hvac import utils -from hvac.api.vault_api_base import VaultApiBase - -DEFAULT_MOUNT_POINT = "rabbitmq" - - -class RabbitMQ(VaultApiBase): - """RabbitMQ Secrets Engine (API). - Reference: https://www.vaultproject.io/api/secret/rabbitmq/index.html - """ - - def configure( - self, - connection_uri="", - username="", - password="", - verify_connection=True, - mount_point=DEFAULT_MOUNT_POINT, - ): - """Configure shared information for the rabbitmq secrets engine. - - Supported methods: - POST: /{mount_point}/config/connection. Produces: 204 (empty body) - - :param connection_uri: Specifies the RabbitMQ connection URI. - :type connection_uri: str | unicode - :param username: Specifies the RabbitMQ management administrator username. - :type username: str | unicode - :password: Specifies the RabbitMQ management administrator password. - :type password: str | unicode - :verify_connection: Specifies whether to verify connection URI, username, and password. - :type verify_connection: bool - :param mount_point: Specifies the place where the secrets engine will be accessible (default: rabbitmq). - :type mount_point: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - params = { - "connection_uri": connection_uri, - "verify_connection": verify_connection, - "username": username, - "password": password, - } - - api_path = utils.format_url( - "/v1/{mount_point}/config/connection", mount_point=mount_point - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def configure_lease(self, ttl, max_ttl, mount_point=DEFAULT_MOUNT_POINT): - """This endpoint configures the lease settings for generated credentials. - - :param ttl: Specifies the lease ttl provided in seconds. - :type ttl: int - :param max_ttl: Specifies the maximum ttl provided in seconds. - :type max_ttl: int - :param mount_point: Specifies the place where the secrets engine will be accessible (default: rabbitmq). - :type mount_point: str | unicode - :return: The JSON response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url("/v1/{}/config/lease", mount_point) - params = { - "ttl": ttl, - "max_ttl": max_ttl, - } - return self._adapter.post( - url=api_path, - json=params, - ) - - def create_role( - self, name, tags="", vhosts="", vhost_topics="", mount_point=DEFAULT_MOUNT_POINT - ): - """This endpoint creates or updates the role definition. - - :param name: Specifies the name of the role to create. - :type name: str | unicode - :param tags: Specifies a comma-separated RabbitMQ management tags. - :type tags: str | unicode - :param vhosts: pecifies a map of virtual hosts to permissions. - :type vhosts: str | unicode - :param vhost_topics: Specifies a map of virtual hosts and exchanges to topic permissions. - :type vhost_topics: str | unicode - :param mount_point: Specifies the place where the secrets engine will be accessible (default: rabbitmq). - :type mount_point: str | unicode - :return: The JSON response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url("/v1/{}/roles/{}", mount_point, name) - params = {"tags": tags, "vhosts": vhosts, "vhost_topics": vhost_topics} - return self._adapter.post( - url=api_path, - json=params, - ) - - def read_role(self, name, mount_point=DEFAULT_MOUNT_POINT): - """This endpoint queries the role definition. - - :param name: Specifies the name of the role to read. - :type name: str | unicode - :param mount_point: Specifies the place where the secrets engine will be accessible (default: rabbitmq). - :type mount_point: str | unicode - :return: The JSON response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url("/v1/{}/roles/{}", mount_point, name) - return self._adapter.get( - url=api_path, - ) - - def delete_role(self, name, mount_point=DEFAULT_MOUNT_POINT): - """This endpoint deletes the role definition. - Even if the role does not exist, this endpoint will still return a successful response. - - :param name: Specifies the name of the role to delete. - :type name: str | unicode - :param mount_point: Specifies the place where the secrets engine will be accessible (default: rabbitmq). - :type mount_point: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url("/v1/{}/roles/{}", mount_point, name) - return self._adapter.delete( - url=api_path, - ) - - def generate_credentials(self, name, mount_point=DEFAULT_MOUNT_POINT): - """This endpoint generates a new set of dynamic credentials based on the named role. - - :param name: Specifies the name of the role to create credentials against. - :type name: str | unicode - :param mount_point: Specifies the place where the secrets engine will be accessible (default: rabbitmq). - :type mount_point: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url("/v1/{}/creds/{}", mount_point, name) - return self._adapter.get( - url=api_path, - ) diff --git a/.venv/lib/python3.12/site-packages/hvac/api/secrets_engines/ssh.py b/.venv/lib/python3.12/site-packages/hvac/api/secrets_engines/ssh.py deleted file mode 100644 index 8fa4bf4..0000000 --- a/.venv/lib/python3.12/site-packages/hvac/api/secrets_engines/ssh.py +++ /dev/null @@ -1,557 +0,0 @@ -#!/usr/bin/env python -"""SSH vault secrets backend module.""" - -from hvac import utils -from hvac.api.vault_api_base import VaultApiBase - -DEFAULT_MOUNT_POINT = "ssh" - -# TODO Fix return types for GET and LIST API calls - - -class Ssh(VaultApiBase): - """SSH Secrets Engine (API). - Reference: https://www.vaultproject.io/api-docs/secret/ssh - """ - - # TODO: deprecate all dynamic SSH keys methods from hvac - def create_or_update_key( - self, - name="", - key="", - mount_point=DEFAULT_MOUNT_POINT, - ): - """This endpoint updates a named key. This method uses deprecated functionality that was removed in Vault 1.13.0. - - :param name: Specifies the name of the key to create. - :type name: str | unicode - :param key: Specifies an SSH private key with appropriate privileges on remote hosts. - :type key: str | unicode - :param mount_point: Specifies the place where the secrets engine will be accessible (default: ssh). - :type mount_point: str | unicode - :return: The JSON response of the request - :rtype: requests.Response - """ - params = { - "key": key, - } - - api_path = utils.format_url( - "/v1/{mount_point}/keys/{name}", - mount_point=mount_point, - name=name, - ) - - return self._adapter.post( - url=api_path, - json=params, - ) - - # TODO: deprecate all dynamic SSH keys methods from hvac - def delete_key( - self, - name="", - mount_point=DEFAULT_MOUNT_POINT, - ): - """This endpoint deletes a named key. This method uses deprecated functionality that was removed in Vault 1.13.0. - - :param name: Specifies the name of the key to delete. - :type name: str | unicode - :param mount_point: Specifies the place where the secrets engine will be accessible (default: ssh). - :type mount_point: str | unicode - :return: The JSON response of the request - :rtype: requests.Response - """ - api_path = utils.format_url( - "/v1/{mount_point}/keys/{name}", - mount_point=mount_point, - name=name, - ) - - return self._adapter.delete(url=api_path) - - def create_role( - self, - name="", - key="", - admin_user="", - default_user="", - cidr_list="", - exclude_cidr_list="", - port=22, - key_type="", - key_bits=1024, - install_script="", - allowed_users="", - allowed_users_template="", - allowed_domains="", - key_option_specs="", - ttl="", - max_ttl="", - allowed_critical_options="", - allowed_extensions="", - default_critical_options=None, - default_extensions=None, - allow_user_certificates="", - allow_host_certificates=False, - allow_bare_domains=False, - allow_subdomains=False, - allow_user_key_ids=False, - key_id_format="", - allowed_user_key_lengths=None, - algorithm_signer="", - mount_point=DEFAULT_MOUNT_POINT, - ): - """This endpoint creates or updates a named role. - - :param name: Specifies the name of the role to create. - :type name: str | unicode - :param key: Specifies the name of the registered key in Vault. - :type key: str | unicode - :param admin_user: Specifies the admin user at remote host. - :type admin_user: str | unicode - :param default_user: Specifies the default username for which a credential will be generated. - :type default_user: str | unicode - :param cidr_list: Specifies a comma separated list of CIDR blocks for which the role is applicable for. - :type cidr_list: str | unicode - :param exclude_cidr_list: Specifies a comma-separated list of CIDR blocks. - :type exclude_cidr_list: str | unicode - :param port: Specifies the port number for SSH connection. - :type port: int - :param key_type: Specifies the type of credentials generated by this role. - :type key_type: str | unicode - :param key_bits: Specifies the length of the RSA dynamic key in bits. (default: 1024) - :type key_bits: int - :param install_script: Specifies the script used to install and uninstall public keys in the target machine. - :type install_script: str | unicode - :param allowed_users: If only certain usernames are to be allowed, then this list enforces it. - :type allowed_users: str | unicode - :param allowed_users_template: If set, allowed_users can be specified using identity template policies. - (default: false) - :type allowed_users_template: bool - :param allowed_domains: The list of domains for which a client can request a host certificate. - :type allowed_domains: str | unicode - :param key_option_specs: Specifies a comma separated option specification which will be prefixed to RSA keys in - the remote host's authorized_keys file. - :type key_option_specs: str | unicode - :param ttl: Specifies the Time To Live value provided as a string duration with time suffix. - :type ttl: string | unicode - :param max_ttl: Specifies the Time To Live value provided as a string duration with time suffix. - :type max_ttl: str | unicode - :param allowed_critical_options: Specifies a comma-separated list of critical options that certificates can have - when signed. - :type allowed_critical_options: str | unicode - :param allowed_extensions: Specifies a comma-separated list of extensions that certificates can have when - signed. - :type allowed_extensions: str | unicode - :param default_critical_options: Specifies a map of critical options certificates should have if none are - provided when signing. - :type default_critical_options: dict - :param default_extensions: Specifies a map of extensions certificates should have if none are provided when - signing. - :type default_extensions: dict - :param allow_user_certificates: Specifies if certificates are allowed to be signed for use as a 'user'. - (default: False) - :type allow_user_certificates: bool - :param allow_host_certificates: Specifies if certificates are allowed to be signed for use as a 'host'. - (default: False) - :type allow_host_certificates: bool - :param allow_bare_domains: Specifies if host certificates that are requested are allowed to use the base domains - listed in allowed_domains, e.g. "example.com". (default: False) - :type allow_bare_domains: bool - :param allow_subdomains: Specifies if host certificates that are requested are allowed to be subdomains of those - listed in allowed_domains. (default: False) - :type allow_subdomains: bool - :param allow_user_key_ids: Specifies if users can override the key ID for a signed certificate with the "key_id" - field. (default: False) - :type allow_user_key_ids: bool - :param key_id_format: When supplied, this value specifies a custom format for the key id of a signed - certificate. - :type key_id_format: str | unicode - :param allowed_user_key_lengths: Specifies a map of ssh key types and their expected sizes which are allowed to - be signed by the CA type. - :type allowed_user_key_lengths: dict - :param algorithm_signer: Algorithm to sign keys with. (default: "default") - :type algorithm_signer: str | unicode - :param mount_point: Specifies the place where the secrets engine will be accessible (default: ssh). - :type mount_point: str | unicode - :return: The JSON response of the request - :rtype: requests.Response - """ - params = { - "key": key, - "admin_user": admin_user, - "default_user": default_user, - "cidr_list": cidr_list, - "exclude_cidr_list": exclude_cidr_list, - "port": port, - "key_type": key_type, - "key_bits": key_bits, - "install_script": install_script, - "allowed_users": allowed_users, - "allowed_users_template": allowed_users_template, - "allowed_domains": allowed_domains, - "key_option_specs": key_option_specs, - "ttl": ttl, - "max_ttl": max_ttl, - "allowed_critical_options": allowed_critical_options, - "allowed_extensions": allowed_extensions, - "default_critical_options": default_critical_options, - "default_extensions": default_extensions, - "allow_user_certificates": allow_user_certificates, - "allow_host_certificates": allow_host_certificates, - "allow_bare_domains": allow_bare_domains, - "allow_subdomains": allow_subdomains, - "allow_user_key_ids": allow_user_key_ids, - "key_id_format": key_id_format, - "allowed_user_key_lengths": allowed_user_key_lengths, - "algorithm_signer": algorithm_signer, - } - - api_path = utils.format_url( - "/v1/{mount_point}/roles/{name}", mount_point=mount_point, name=name - ) - - return self._adapter.post(url=api_path, json=params) - - def read_role( - self, - name="", - mount_point=DEFAULT_MOUNT_POINT, - ): - """This endpoint queries a named role. - - :param name: Specifies the name of the role to read. - :type name: str | unicode - :param mount_point: Specifies the place where the secrets engine will be accessible (default: ssh). - :type mount_point: str | unicode - :return: The JSON response of the request - :rtype: requests.Response - """ - api_path = utils.format_url( - "/v1/{mount_point}/roles/{name}", - mount_point=mount_point, - name=name, - ) - - return self._adapter.get(url=api_path) - - def list_roles( - self, - mount_point=DEFAULT_MOUNT_POINT, - ): - """This endpoint returns a list of available roles. Only the role names are returned, not any values. - - :param mount_point: Specifies the place where the secrets engine will be accessible (default: ssh). - :type mount_point: str | unicode - :return: The JSON response of the request - :rtype: requests.Response - """ - api_path = utils.format_url("/v1/{mount_point}/roles", mount_point=mount_point) - - return self._adapter.list(url=api_path) - - def delete_role(self, name="", mount_point=DEFAULT_MOUNT_POINT): - """This endpoint deletes a named role. - - :param name: - :type name: str | unicode - :param mount_point: Specifies the place where the secrets engine will be accessible (default: ssh). - :type mount_point: str | unicode - :return: The JSON response of the request - :rtype: requests.Response - """ - api_path = utils.format_url( - "/v1/{mount_point}/roles/{name}", - mount_point=mount_point, - name=name, - ) - - return self._adapter.delete(url=api_path) - - def list_zeroaddress_roles( - self, - mount_point=DEFAULT_MOUNT_POINT, - ): - """This endpoint returns the list of configured zero-address roles. - - :param mount_point: Specifies the place where the secrets engine will be accessible (default: ssh). - :type mount_point: str | unicode - :return: The JSON response of the request - :rtype: requests.Response - """ - api_path = utils.format_url( - "/v1/{mount_point}/config/zeroaddress", - mount_point=mount_point, - ) - - return self._adapter.get(url=api_path) - - def configure_zeroaddress_roles( - self, - roles="", - mount_point=DEFAULT_MOUNT_POINT, - ): - """This endpoint configures zero-address roles. - - :param roles: Specifies a string containing comma separated list of role names which allows credentials to be requested for any IP address. - :type roles: str | unicode - :param mount_point: Specifies the place where the secrets engine will be accessible (default: ssh). - :type mount_point: str | unicode - :return: The JSON response of the request - :rtype: requests.Response - """ - params = { - "roles": roles, - } - - api_path = utils.format_url( - "/v1/{mount_point}/config/zeroaddress", - mount_point=mount_point, - ) - - return self._adapter.post( - url=api_path, - json=params, - ) - - def delete_zeroaddress_role(self, mount_point=DEFAULT_MOUNT_POINT): - """This endpoint deletes the zero-address roles configuration. - - :param mount_point: Specifies the place where the secrets engine will be accessible (default: ssh). - :type mount_point: str | unicode - :return: The JSON response of the request - :rtype: requests.Response - """ - api_path = utils.format_url( - "/v1/{mount_point}/config/zeroaddress", mount_point=mount_point - ) - - return self._adapter.delete( - url=api_path, - ) - - def generate_ssh_credentials( - self, - name="", - username="", - ip="", - mount_point=DEFAULT_MOUNT_POINT, - ): - """This endpoint creates credentials for a specific username and IP with the parameters defined in the given role. - - :param name: Specifies the name of the role to create credentials against. This is part of the request URL. - :type name: str | unicode - :param username: Specifies the username on the remote host. - :type username: str | unicode - :param ip: Specifies the IP of the remote host. - :type ip: str | unicode - :param mount_point: Specifies the place where the secrets engine will be accessible (default: ssh). - :type mount_point: str | unicode - :return: The JSON response of the request - :rtype: requests.Response - """ - params = { - "username": username, - "ip": ip, - } - - api_path = utils.format_url( - "/v1/{mount_point}/creds/{name}", - mount_point=mount_point, - name=name, - ) - - return self._adapter.post(url=api_path, json=params) - - def list_roles_by_ip( - self, - ip="", - mount_point=DEFAULT_MOUNT_POINT, - ): - """This endpoint lists all of the roles with which the given IP is associated. - - :param ip: Specifies the IP of the remote host. - :type ip: str | unicode - :param mount_point: Specifies the place where the secrets engine will be accessible (default: ssh). - :type mount_point: str | unicode - :return: The JSON response of the request - :rtype: requests.Response - """ - params = { - "ip": ip, - } - - api_path = utils.format_url( - "/v1/{mount_point}/lookup", - mount_point=mount_point, - ) - - return self._adapter.post( - url=api_path, - json=params, - ) - - def verify_ssh_otp( - self, - otp, - mount_point=DEFAULT_MOUNT_POINT, - ): - """This endpoint verifies if the given OTP is valid. This is an unauthenticated endpoint. - - :param otp: Specifies the One-Time-Key that needs to be validated. - :type otp: str | unicode - :param mount_point: Specifies the place where the secrets engine will be accessible (default: ssh). - :type mount_point: str | unicode - :return: The JSON response of the request - :rtype: requests.Response - """ - params = { - "otp": otp, - } - - api_path = utils.format_url( - "v1/{mount_point}/verify", - mount_point=mount_point, - ) - - return self._adapter.post( - url=api_path, - json=params, - ) - - def submit_ca_information( - self, - private_key="", - public_key="", - generate_signing_key=True, - key_type="ssh-rsa", - key_bits=0, - mount_point=DEFAULT_MOUNT_POINT, - ): - """This endpoint allows submitting the CA information for the secrets engine via an SSH key pair. - - :param private_key: Specifies the private key part the SSH CA key pair. - :type private_key: str | unicode - :param public_key: Specifies the public key part of the SSH CA key pair. - :type public_key: str | unicode - :param generate_signing_key: Specifies if Vault should generate the signing key pair internally. (default: True) - :type generate_signing_key: bool - :param key_type: Specifies the desired key type for the generated SSH CA key when generate_signing_key is set to true. (default: ssh-rsa) - :type key_type: str | unicode - :param key_bits: Specifies the desired key bits for the generated SSH CA key when generate_signing_key is set to true. (default: 0) - :type key_bits: int - :param mount_point: Specifies the place where the secrets engine will be accessible (default: ssh). - :type mount_point: str | unicode - :return: The JSON response of the request - :rtype: requests.Response - """ - params = { - "private_key": private_key, - "public_key": public_key, - "generate_signing_key": generate_signing_key, - "key_type": key_type, - "key_bits": key_bits, - } - - api_path = utils.format_url( - "/v1/{mount_point}/config/ca", - mount_point=mount_point, - ) - - return self._adapter.post( - url=api_path, - json=params, - ) - - def delete_ca_information( - self, - mount_point=DEFAULT_MOUNT_POINT, - ): - """This endpoint deletes the CA information for the backend via an SSH key pair. - - :param mount_point: Specifies the place where the secrets engine will be accessible (default: ssh). - :type mount_point: str | unicode - :return: The JSON response of the request - :rtype: requests.Response - """ - api_path = utils.format_url( - "/v1/{mount_point}/config/ca", - mount_point=mount_point, - ) - - return self._adapter.delete(url=api_path) - - def read_public_key( - self, - mount_point=DEFAULT_MOUNT_POINT, - ): - """This endpoint reads the configured/generated public key. - - :param mount_point: Specifies the place where the secrets engine will be accessible (default: ssh). - :type mount_point: str | unicode - :return: The JSON response of the request - :rtype: requests.Response - """ - # TODO Consider if the unauthenticated endpoint could be used if not authenticated - api_path = utils.format_url( - "/v1/{mount_point}/config/ca", - mount_point=mount_point, - ) - - return self._adapter.get(url=api_path) - - def sign_ssh_key( - self, - name="", - public_key="", - ttl="", - valid_principals="", - cert_type="user", - key_id="", - critical_options=None, - extensions=None, - mount_point=DEFAULT_MOUNT_POINT, - ): - """This endpoint signs an SSH public key based on the supplied parameters, - subject to the restrictions contained in the role named in the endpoint. - - :param name: Specifies the name of the role to sign. This is part of the request URL. - :type name: str | unicode - :param public_key: Specifies the SSH public key that should be signed. - :type public_key: str | unicode - :param ttl: Specifies the Requested Time To Live. - :type ttl: str | unicode - :param valid_principals: Specifies valid principals that the certificate should be signed for. - :type valid_principals: str | unicode - :param cert_type: Specifies the type of certificate to be created; either "user" or "host". (default: user) - :type cert_type: str | unicode - :param key_id: Specifies the key id that the created certificate should have. - :type key_id: str | unicode - :param critical_options: Specifies a map of the critical options that the certificate should be signed for. - :type critical_options: dict - :param extensions: Specifies a map of the extensions that the certificate should be signed for. - :type extensions: dict - :param mount_point: Specifies the place where the secrets engine will be accessible (default: ssh). - :type mount_point: str | unicode - :return: The JSON response of the request - :rtype: requests.Response - """ - params = { - "public_key": public_key, - "ttl": ttl, - "valid_principals": valid_principals, - "cert_type": cert_type, - "key_id": key_id, - "critical_options": critical_options, - "extensions": extensions, - } - - api_path = utils.format_url( - "/v1/{mount_point}/sign/{name}", mount_point=mount_point, name=name - ) - - return self._adapter.post( - url=api_path, - json=params, - ) diff --git a/.venv/lib/python3.12/site-packages/hvac/api/secrets_engines/transform.py b/.venv/lib/python3.12/site-packages/hvac/api/secrets_engines/transform.py deleted file mode 100644 index 8a4b4ea..0000000 --- a/.venv/lib/python3.12/site-packages/hvac/api/secrets_engines/transform.py +++ /dev/null @@ -1,1174 +0,0 @@ -#!/usr/bin/env python -"""Transform secrets engine methods module.""" -from hvac import utils -from hvac.api.vault_api_base import VaultApiBase - -DEFAULT_MOUNT_POINT = "transform" - - -class Transform(VaultApiBase): - """Transform Secrets Engine (API). - - Reference: https://www.vaultproject.io/api-docs/secret/transform - """ - - def create_or_update_role( - self, name, transformations, mount_point=DEFAULT_MOUNT_POINT - ): - """Creates or update the role with the given name. - - If a role with the name does not exist, it will be created. If the role exists, it will be - updated with the new attributes. - - Supported methods: - POST: /{mount_point}/role/:name. - - :param name: the name of the role to create. This is part of the request URL. - :type name: str | unicode - :param transformations: Specifies the transformations that can be used with this role. - At least one transformation is required. - :type transformations: list - :param mount_point: The "path" the secrets engine was mounted on. - :type mount_point: str | unicode - :return: The response of the create_or_update_role request. - :rtype: requests.Response - """ - params = { - "transformations": transformations, - } - api_path = "/v1/{mount_point}/role/{name}".format( - mount_point=mount_point, - name=name, - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def read_role(self, name, mount_point=DEFAULT_MOUNT_POINT): - """Query an existing role by the given name. - - Supported methods: - GET: /{mount_point}/role/:name. - - :param name: the name of the role to read. This is part of the request URL. - :type name: str | unicode - :param mount_point: The "path" the secrets engine was mounted on. - :type mount_point: str | unicode - :return: The response of the read_role request. - :rtype: requests.Response - """ - api_path = "/v1/{mount_point}/role/{name}".format( - mount_point=mount_point, - name=name, - ) - return self._adapter.get( - url=api_path, - ) - - def list_roles(self, mount_point=DEFAULT_MOUNT_POINT): - """List all existing roles in the secrets engine. - - Supported methods: - LIST: /{mount_point}/role. - - :param mount_point: The "path" the secrets engine was mounted on. - :type mount_point: str | unicode - :return: The response of the list_roles request. - :rtype: requests.Response - """ - api_path = f"/v1/{mount_point}/role" - return self._adapter.list( - url=api_path, - ) - - def delete_role(self, name, mount_point=DEFAULT_MOUNT_POINT): - """Delete an existing role by the given name. - - Supported methods: - DELETE: /{mount_point}/role/:name. - - :param name: the name of the role to delete. This is part of the request URL. - :type name: str | unicode - :param mount_point: The "path" the secrets engine was mounted on. - :type mount_point: str | unicode - :return: The response of the delete_role request. - :rtype: requests.Response - """ - api_path = "/v1/{mount_point}/role/{name}".format( - mount_point=mount_point, - name=name, - ) - return self._adapter.delete( - url=api_path, - ) - - def create_or_update_transformation( - self, - name, - transform_type, - template, - tweak_source="supplied", - masking_character="*", - allowed_roles=None, - mount_point=DEFAULT_MOUNT_POINT, - ): - """Create or update a transformation with the given name. - - If a transformation with the name does not exist, it will be created. If the - transformation exists, it will be updated with the new attributes. - - Supported methods: - POST: /{mount_point}/transformation/:name. - - :param name: the name of the transformation to create or update. This is part of - the request URL. - :type name: str | unicode - :param transform_type: Specifies the type of transformation to perform. - The types currently supported by this backend are fpe and masking. - This value cannot be modified by an update operation after creation. - :type transform_type: str | unicode - :param template: the template name to use for matching value on encode and decode - operations when using this transformation. - :type template: str | unicode - :param tweak_source: Only used when the type is FPE. - :type tweak_source: str | unicode - :param masking_character: the character to use for masking. If multiple characters are - provided, only the first one is used and the rest is ignored. Only used when - the type is masking. - :type masking_character: str | unicode - :param allowed_roles: a list of allowed roles that this transformation can be assigned to. - A role using this transformation must exist in this list in order for - encode and decode operations to properly function. - :type allowed_roles: list - :param mount_point: The "path" the secrets engine was mounted on. - :type mount_point: str | unicode - :return: The response of the create_or_update_ation request. - :rtype: requests.Response - """ - params = { - "type": transform_type, - "template": template, - "tweak_source": tweak_source, - "masking_character": masking_character, - } - params.update( - utils.remove_nones( - { - "allowed_roles": allowed_roles, - } - ) - ) - api_path = "/v1/{mount_point}/transformation/{name}".format( - mount_point=mount_point, - name=name, - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def create_or_update_fpe_transformation( - self, - name, - template, - tweak_source="supplied", - allowed_roles=None, - mount_point=DEFAULT_MOUNT_POINT, - ): - """Creates or update an FPE transformation with the given name. - - If a transformation with the name does not exist, it will be created. If the transformation exists, it will be - updated with the new attributes. - - Supported methods: - POST: /{mount_point}/transformations/fpe/:name. - - - :param name: The name of the transformation to create or update. This is part of - the request URL. - :type name: str - :param template: The template name to use for matching value on encode and decode - operations when using this transformation. - :type template: str - :param tweak_source: Specifies the source of where the tweak value comes from. Valid sources are: - supplied, generated, and internal. - :type tweak_source: str - :param allowed_roles: A list of allowed roles that this transformation can be assigned to. - A role using this transformation must exist in this list in order for - encode and decode operations to properly function. - :type allowed_roles: list - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str - :return: The response of the create_or_update_fpe_transformation request. - :rtype: requests.Response - """ - params = utils.remove_nones( - { - "template": template, - "tweak_source": tweak_source, - "allowed_roles": allowed_roles, - } - ) - api_path = "/v1/{mount_point}/transformations/fpe/{name}".format( - mount_point=mount_point, - name=name, - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def create_or_update_masking_transformation( - self, - name, - template, - masking_character="*", - allowed_roles=None, - mount_point=DEFAULT_MOUNT_POINT, - ): - """Creates or update a masking transformation with the given name. If a - transformation with the name does not exist, it will be created. If the - transformation exists, it will be updated with the new attributes. - - Supported methods: - POST: /{mount_point}/transformations/masking/:name. - - - :param name: The name of the transformation to create or update. This is part of - the request URL. - :type name: str - :param template: The template name to use for matching value on encode and decode - operations when using this transformation. - :type template: str - :param masking_character: The character to use for masking. If multiple characters are - provided, only the first one is used and the rest is ignored. Only used when - the type is masking. - :type masking_character: str - :param allowed_roles: A list of allowed roles that this transformation can be assigned to. - A role using this transformation must exist in this list in order for - encode and decode operations to properly function. - :type allowed_roles: list - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str - :return: The response of the create_or_update_masking_transformation request. - :rtype: requests.Response - """ - params = utils.remove_nones( - { - "template": template, - "masking_character": masking_character, - "allowed_roles": allowed_roles, - } - ) - api_path = "/v1/{mount_point}/transformations/masking/{name}".format( - mount_point=mount_point, - name=name, - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def create_or_update_tokenization_transformation( - self, - name, - max_ttl=0, - mapping_mode="default", - allowed_roles=None, - stores=None, - mount_point=DEFAULT_MOUNT_POINT, - ): - """ - This endpoint creates or updates a tokenization transformation with the given name. If a - transformation with the name does not exist, it will be created. If the - transformation exists, it will be updated with the new attributes. - - Supported methods: - POST: /{mount_point}/transformations/tokenization/:name. - - :param max_ttl: The maximum TTL of a token. If 0 or unspecified, tokens may have no expiration. - :type max_ttl: str - :param mapping_mode: Specifies the mapping mode for stored tokenization values. - - * `default` is strongly recommended for highest security - * `exportable` exportable allows for all plaintexts to be decoded via the export-decoded endpoint in an emergency. - - :type mapping_mode: str - :param allowed_roles: aAlist of allowed roles that this transformation can be assigned to. - A role using this transformation must exist in this list in order for - encode and decode operations to properly function. - :type allowed_roles: list - :param stores: list of tokenization stores to use for tokenization state. Vault's - internal storage is used by default. - :type stores: list - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str - :return: The response of the create_or_update_tokenization_transformation request. - :rtype: requests.Response - """ - if stores is None: - stores = ["builtin/internal"] - params = utils.remove_nones( - { - "max_ttl": max_ttl, - "mapping_mode": mapping_mode, - "allowed_roles": allowed_roles, - "stores": stores, - } - ) - api_path = "/v1/{mount_point}/transformations/tokenization/{name}".format( - mount_point=mount_point, - name=name, - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def read_transformation(self, name, mount_point=DEFAULT_MOUNT_POINT): - """Query an existing transformation by the given name. - - Supported methods: - GET: /{mount_point}/transformation/:name. - - :param name: Specifies the name of the role to read. - :type name: str | unicode - :param mount_point: The "path" the secrets engine was mounted on. - :type mount_point: str | unicode - :return: The response of the read_ation request. - :rtype: requests.Response - """ - api_path = "/v1/{mount_point}/transformation/{name}".format( - mount_point=mount_point, - name=name, - ) - return self._adapter.get( - url=api_path, - ) - - def list_transformations(self, mount_point=DEFAULT_MOUNT_POINT): - """List all existing transformations in the secrets engine. - - Supported methods: - LIST: /{mount_point}/transformation. - - :param mount_point: The "path" the secrets engine was mounted on. - :type mount_point: str | unicode - :return: The response of the list_ation request. - :rtype: requests.Response - """ - api_path = f"/v1/{mount_point}/transformation" - return self._adapter.list( - url=api_path, - ) - - def delete_transformation(self, name, mount_point=DEFAULT_MOUNT_POINT): - """Delete an existing transformation by the given name. - - Supported methods: - DELETE: /{mount_point}/transformation/:name. - - :param name: the name of the transformation to delete. This is part of the - request URL. - :type name: str | unicode - :param mount_point: The "path" the secrets engine was mounted on. - :type mount_point: str | unicode - :return: The response of the delete_ation request. - :rtype: requests.Response - """ - api_path = "/v1/{mount_point}/transformation/{name}".format( - mount_point=mount_point, - name=name, - ) - return self._adapter.delete( - url=api_path, - ) - - def create_or_update_template( - self, name, template_type, pattern, alphabet, mount_point=DEFAULT_MOUNT_POINT - ): - """Creates or update a template with the given name. - - If a template with the name does not exist, it will be created. If the - template exists, it will be updated with the new attributes. - - Supported methods: - POST: /{mount_point}/template/:name. - - :param name: the name of the template to create. - :type name: str | unicode - :param template_type: Specifies the type of pattern matching to perform. - The only type currently supported by this backend is regex. - :type template_type: str | unicode - :param pattern: the pattern used to match a particular value. For regex type - matching, capture group determines the set of character that should be matched - against. Any matches outside of capture groups are retained - post-transformation. - :type pattern: str | unicode - :param alphabet: the name of the alphabet to use when this template is used for FPE - encoding and decoding operations. - :type alphabet: str | unicode - :param mount_point: The "path" the secrets engine was mounted on. - :type mount_point: str | unicode - :return: The response of the create_or_update_template request. - :rtype: requests.Response - """ - params = { - "type": template_type, - "pattern": pattern, - "alphabet": alphabet, - } - api_path = "/v1/{mount_point}/template/{name}".format( - mount_point=mount_point, - name=name, - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def read_template(self, name, mount_point=DEFAULT_MOUNT_POINT): - """Query an existing template by the given name. - - Supported methods: - GET: /{mount_point}/template/:name. - - :param name: Specifies the name of the role to read. - :type name: str | unicode - :param mount_point: The "path" the secrets engine was mounted on. - :type mount_point: str | unicode - :return: The response of the read_template request. - :rtype: requests.Response - """ - api_path = "/v1/{mount_point}/template/{name}".format( - mount_point=mount_point, - name=name, - ) - return self._adapter.get( - url=api_path, - ) - - def list_templates(self, mount_point=DEFAULT_MOUNT_POINT): - """List all existing templates in the secrets engine. - - Supported methods: - LIST: /{mount_point}/transformation. - - :param mount_point: The "path" the secrets engine was mounted on. - :type mount_point: str | unicode - :return: The response of the list_template request. - :rtype: requests.Response - """ - api_path = f"/v1/{mount_point}/template" - return self._adapter.list( - url=api_path, - ) - - def delete_template(self, name, mount_point=DEFAULT_MOUNT_POINT): - """Delete an existing template by the given name. - - Supported methods: - DELETE: /{mount_point}/template/:name. - - :param name: the name of the template to delete. This is part of the - request URL. - :type name: str | unicode - :param mount_point: The "path" the secrets engine was mounted on. - :type mount_point: str | unicode - :return: The response of the delete_template request. - :rtype: requests.Response - """ - params = { - "name": name, - } - api_path = "/v1/{mount_point}/template/{name}".format( - mount_point=mount_point, - name=name, - ) - return self._adapter.delete( - url=api_path, - json=params, - ) - - def create_or_update_alphabet( - self, name, alphabet, mount_point=DEFAULT_MOUNT_POINT - ): - """Create or update an alphabet with the given name. - - If an alphabet with the name does not exist, it will be created. If the - alphabet exists, it will be updated with the new attributes. - - Supported methods: - POST: /{mount_point}/alphabet/:name. - - :param name: Specifies the name of the transformation alphabet to create. - :type name: str | unicode - :param alphabet: the set of characters that can exist within the provided value - and the encoded or decoded value for a FPE transformation. - :type alphabet: str | unicode - :param mount_point: The "path" the secrets engine was mounted on. - :type mount_point: str | unicode - :return: The response of the create_or_update_alphabet request. - :rtype: requests.Response - """ - params = { - "alphabet": alphabet, - } - api_path = "/v1/{mount_point}/alphabet/{name}".format( - mount_point=mount_point, - name=name, - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def read_alphabet(self, name, mount_point=DEFAULT_MOUNT_POINT): - """Queries an existing alphabet by the given name. - - Supported methods: - GET: /{mount_point}/alphabet/:name. - - - :param name: the name of the alphabet to delete. This is part of the request URL. - :type name: str | unicode - :param mount_point: The "path" the secrets engine was mounted on. - :type mount_point: str | unicode - :return: The response of the read_alphabet request. - :rtype: requests.Response - """ - api_path = "/v1/{mount_point}/alphabet/{name}".format( - mount_point=mount_point, - name=name, - ) - return self._adapter.get( - url=api_path, - ) - - def list_alphabets(self, mount_point=DEFAULT_MOUNT_POINT): - """List all existing alphabets in the secrets engine. - - Supported methods: - LIST: /{mount_point}/alphabet. - - :param mount_point: The "path" the secrets engine was mounted on. - :type mount_point: str | unicode - :return: The response of the list_alphabets request. - :rtype: requests.Response - """ - api_path = f"/v1/{mount_point}/alphabet" - return self._adapter.list( - url=api_path, - ) - - def delete_alphabet(self, name, mount_point=DEFAULT_MOUNT_POINT): - """Delete an existing alphabet by the given name. - - Supported methods: - DELETE: /{mount_point}/alphabet/:name. - - :param name: the name of the alphabet to delete. This is part of the request URL. - :type name: str | unicode - :param mount_point: The "path" the secrets engine was mounted on. - :type mount_point: str | unicode - :return: The response of the delete_alphabet request. - :rtype: requests.Response - """ - api_path = "/v1/{mount_point}/alphabet/{name}".format( - mount_point=mount_point, - name=name, - ) - return self._adapter.delete( - url=api_path, - ) - - def create_or_update_tokenization_store( - self, - name, - driver, - connection_string, - username=None, - password=None, - type="sql", - supported_transformations=None, - schema="public", - max_open_connections=4, - max_idle_connections=4, - max_connection_lifetime=0, - mount_point=DEFAULT_MOUNT_POINT, - ): - """Create or update a storage configuration for use with tokenization. - The database user configured here should only have permission to SELECT, INSERT, and UPDATE rows in the tables. - - Supported methods: - POST: /{mount_point}/store/:name. - - :param name: The name of the store to create or update. - :type name: str - :param type: Specifies the type of store. Currently only `sql` is supported. - :type type: str - :param driver: Specifies the database driver to use, and thus which SQL database type. - Currently the supported options are `postgres` or `mysql` - :type driver: str - :param supported_transformations: The types of transformations this store can host. Currently only `tokenization` is supported. - :type supported_transformations: list(str) - :param connection_string: database connection string with template slots for username and password that - Vault will use for locating and connecting to a database. Each - database driver type has a different syntax for its connection strings. - :type connection_string: str - :param username: username value to use when connecting to the database. - :type username: str - :param password: password value to use when connecting to the database. - :type password: str - :param schema: schema within the database to expect tokenization state tables. - :type schema: str - :param max_open_connections: maximum number of connections to the database at any given time. - :type max_open_connections: int - :param max_idle_connections: maximum number of idle connections to the database at any given time. - :type max_idle_connections: int - :param max_connection_lifetime: means no limit. - :type max_connection_lifetime: duration - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str - :return: The response of the create_or_update_tokenization_store request. - :rtype: requests.Response - """ - if supported_transformations is None: - supported_transformations = ["tokenization"] - params = utils.remove_nones( - { - "type": type, - "driver": driver, - "supported_transformations:": supported_transformations, - "connection_string": connection_string, - "username": username, - "password": password, - "schema": schema, - "max_open_connections": max_open_connections, - "max_idle_connections": max_idle_connections, - "max_connection_lifetime": max_connection_lifetime, - } - ) - api_path = "/v1/{mount_point}/store/{name}".format( - mount_point=mount_point, - name=name, - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def encode( - self, - role_name, - value=None, - transformation=None, - tweak=None, - batch_input=None, - mount_point=DEFAULT_MOUNT_POINT, - ): - """Encode the provided value using a named role. - - Supported methods: - POST: /{mount_point}/encode/:role_name. - - :param role_name: the role name to use for this operation. This is specified as part - of the URL. - :type role_name: str | unicode - :param value: the value to be encoded. - :type value: str | unicode - :param transformation: the transformation within the role that should be used for this - encode operation. If a single transformation exists for role, this parameter - may be skipped and will be inferred. If multiple transformations exist, one - must be specified. - :type transformation: str | unicode - :param tweak: the tweak source. - :type tweak: str | unicode - :param batch_input: a list of items to be encoded in a single batch. When this - parameter is set, the 'value', 'transformation' and 'tweak' parameters are - ignored. Instead, the aforementioned parameters should be provided within - each object in the list. - :type batch_input: list - :param mount_point: The "path" the secrets engine was mounted on. - :type mount_point: str | unicode - :return: The response of the encode request. - :rtype: requests.Response - """ - params = utils.remove_nones( - { - "value": value, - "transformation": transformation, - "tweak": tweak, - "batch_input": batch_input, - } - ) - api_path = "/v1/{mount_point}/encode/{role_name}".format( - mount_point=mount_point, - role_name=role_name, - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def decode( - self, - role_name, - value=None, - transformation=None, - tweak=None, - batch_input=None, - mount_point=DEFAULT_MOUNT_POINT, - ): - """Decode the provided value using a named role. - - Supported methods: - POST: /{mount_point}/decode/:role_name. - - :param role_name: the role name to use for this operation. This is specified as part - of the URL. - :type role_name: str | unicode - :param value: the value to be decoded. - :type value: str | unicode - :param transformation: the transformation within the role that should be used for this - decode operation. If a single transformation exists for role, this parameter - may be skipped and will be inferred. If multiple transformations exist, one - must be specified. - :type transformation: str | unicode - :param tweak: the tweak source. - :type tweak: str | unicode - :param batch_input: a list of items to be decoded in a single batch. When this - parameter is set, the 'value', 'transformation' and 'tweak' parameters are - ignored. Instead, the aforementioned parameters should be provided within - each object in the list. - :type batch_input: array - :param mount_point: The "path" the secrets engine was mounted on. - :type mount_point: str | unicode - :return: The response of the decode request. - :rtype: requests.Response - """ - params = utils.remove_nones( - { - "value": value, - "transformation": transformation, - "tweak": tweak, - "batch_input": batch_input, - } - ) - api_path = "/v1/{mount_point}/decode/{role_name}".format( - mount_point=mount_point, - role_name=role_name, - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def validate_token( - self, - role_name, - value, - transformation, - batch_input=None, - mount_point=DEFAULT_MOUNT_POINT, - ): - """Determine if a provided tokenized value is valid and unexpired. - Only valid for tokenization transformations. - - Supported methods: - POST: /{mount_point}/validate/:role_name. - - - :param role_name: the role name to use for this operation. This is specified as part - of the URL. - :type role_name: str - :param value: the token for which to check validity. - :type value: str - :param transformation: the transformation within the role that should be used for this - decode operation. If a single transformation exists for role, this parameter - may be skipped and will be inferred. If multiple transformations exist, one - must be specified. - :type transformation: str - :param batch_input: a list of items to be decoded in a single batch. When this - parameter is set, the 'value' parameter is - ignored. Instead, the aforementioned parameters should be provided within - each object in the list. - :type batch_input: list - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str - :return: The response of the validate_token request. - :rtype: requests.Response - """ - params = utils.remove_nones( - { - "value": value, - "transformation": transformation, - "batch_input": batch_input, - } - ) - api_path = "/v1/{mount_point}/validate/{role_name}".format( - mount_point=mount_point, - role_name=role_name, - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def check_tokenization( - self, - role_name, - value, - transformation, - batch_input=None, - mount_point=DEFAULT_MOUNT_POINT, - ): - """Determine if a provided plaintext value has an valid, unexpired tokenized value. - Note that this cannot return the token, just confirm that a - tokenized value exists. This endpoint is only valid for tokenization - transformations. - - Supported methods: - POST: /{mount_point}/tokenized/:role_name. - - - :param role_name: the role name to use for this operation. This is specified as part - of the URL. - :type role_name: str - :param value: the token to test for whether it has a valid tokenization. - :type value: str - :param transformation: the transformation within the role that should be used for this - decode operation. If a single transformation exists for role, this parameter - may be skipped and will be inferred. If multiple transformations exist, one - must be specified. - :type transformation: str - :param batch_input: a list of items to be decoded in a single batch. When this - parameter is set, the 'value' parameter is - ignored. Instead, the aforementioned parameters should be provided within - each object in the list. - :type batch_input: list - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str - :return: The response of the check_tokenization request. - :rtype: requests.Response - """ - params = utils.remove_nones( - { - "value": value, - "transformation": transformation, - "batch_input": batch_input, - } - ) - api_path = "/v1/{mount_point}/tokenized/{role_name}".format( - mount_point=mount_point, - role_name=role_name, - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def retrieve_token_metadata( - self, - role_name, - value, - transformation, - batch_input=None, - mount_point=DEFAULT_MOUNT_POINT, - ): - """ - This endpoint retrieves metadata for a tokenized value using a named role. - Only valid for tokenization transformations. - - Supported methods: - POST: /{mount_point}/metadata/:role_name. - - - :param role_name: the role name to use for this operation. This is specified as part - of the URL. - :type role_name: str - :param value: the token for which to retrieve metadata. - :type value: str - :param transformation: the transformation within the role that should be used for this - decode operation. If a single transformation exists for role, this parameter - may be skipped and will be inferred. If multiple transformations exist, one - must be specified. - :type transformation: str - :param batch_input: a list of items to be decoded in a single batch. When this - parameter is set, the 'value' parameter is - ignored. Instead, the aforementioned parameters should be provided within - each object in the list. - :type batch_input: list - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str - :return: The response of the retrieve_token_metadata request. - :rtype: requests.Response - """ - params = utils.remove_nones( - { - "value": value, - "transformation": transformation, - "batch_input": batch_input, - } - ) - api_path = "/v1/{mount_point}/metadata/{role_name}".format( - mount_point=mount_point, - role_name=role_name, - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def snapshot_tokenization_state( - self, name, limit=1000, continuation="", mount_point=DEFAULT_MOUNT_POINT - ): - """ - This endpoint starts or continues retrieving a snapshot of the stored - state of a tokenization transform. This state is protected as it is - in the underlying store, and so is safe for storage or transport. Snapshots - may be used for backup purposes or to migrate from one store to another. - If more than one store is configured for a tokenization transform, the - snapshot data contains the contents of the first store. - - Supported methods: - POST: /{mount_point}/transformations/tokenization/snapshot/:name. - - - :param name: the name of the transformation to snapshot. - :type name: str - :param limit: maximum number of tokenized value states to return on this call. - :type limit: int - :param continuation: absent or empty, a new snapshot is started. If present, the - snapshot should continue at the next available value. - :type continuation: str - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str - :return: The response of the snapshot_tokenization_state request. - :rtype: requests.Response - """ - params = utils.remove_nones( - { - "limit": limit, - "continuation": continuation, - } - ) - api_path = ( - "/v1/{mount_point}/transformations/tokenization/snapshot/{name}".format( - mount_point=mount_point, - name=name, - ) - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def restore_tokenization_state(self, name, values, mount_point=DEFAULT_MOUNT_POINT): - """ - This endpoint restores previously snapshotted tokenization state values - to the underlying store(s) of a tokenization transform. Calls to this - endpoint are idempotent, so multiple outputs from a snapshot run can - be applied via restore in any order and duplicates will not cause a problem. - - Supported methods: - POST: /{mount_point}/transformations/tokenization/restore/:name. - - - :param name: the name of the transformation to restore. - :type name: str - :param values: number of tokenization state values from a previous snapshot call. - :type values: str - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str - :return: The response of the restore_tokenization_state request. - :rtype: requests.Response - """ - params = { - "values": values, - } - api_path = ( - "/v1/{mount_point}/transformations/tokenization/restore/{name}".format( - mount_point=mount_point, - name=name, - ) - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def export_decoded_tokenization_state( - self, name, limit=1000, continuation="", mount_point=DEFAULT_MOUNT_POINT - ): - """Start or continue retrieving an export of tokenization state, including the tokens and their decoded values. - This call is only supported on tokenization stores configured with the exportable mapping mode. - Refer to the Tokenization documentation for when to use the exportable mapping mode. - Decoded values are in Base64 representation. - - Supported methods: - POST: /{mount_point}/transformations/tokenization/export-decoded/:name. - - - :param name: the name of the transformation to export. - :type name: str - :param limit: maximum number of tokenized value states to return on this call. - :type limit: int - :param continuation: absent or empty, a new export is started. If present, the - export should continue at the next available value. - :type continuation: str - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str - :return: The response of the export_decoded_tokenization_state request. - :rtype: requests.Response - """ - params = utils.remove_nones( - { - "limit": limit, - "continuation": continuation, - } - ) - api_path = "/v1/{mount_point}/transformations/tokenization/export-decoded/{name}".format( - mount_point=mount_point, - name=name, - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def rotate_tokenization_key(self, transform_name, mount_point=DEFAULT_MOUNT_POINT): - """Rotate the version of the named key. - After rotation, new requests will be encoded with the new version of the key. - - Supported methods: - POST: /{mount_point}/tokenization/keys/{transform_name}/rotate. - - - :param transform_name: the transform name to use for this operation. This is specified as part - of the URL. - :type transform_name: str - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str - :return: The response of the rotate_tokenization_key request. - :rtype: requests.Response - """ - api_path = "/v1/{mount_point}/tokenization/keys/{transform_name}/rotate".format( - mount_point=mount_point, - transform_name=transform_name, - ) - return self._adapter.post( - url=api_path, - ) - - def update_tokenization_key_config( - self, transform_name, min_decryption_version, mount_point=DEFAULT_MOUNT_POINT - ): - """Allow the minimum key version to be set for decode operations. - Only valid for tokenization transformations. - - Supported methods: - POST: /{mount_point}/tokenization/keys/{transform_name}/config. - - - :param transform_name: the transform name to use for this operation. This is specified as part - of the URL. - :type transform_name: str - :param min_decryption_version: the minimum key version that vault can use to decode values for the - corresponding transform. - :type min_decryption_version: int - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str - :return: The response of the update_tokenization_key_config request. - :rtype: requests.Response - """ - params = { - "transform_name": transform_name, - "min_decryption_version": min_decryption_version, - } - api_path = "/v1/{mount_point}/tokenization/keys/{transform_name}/config".format( - mount_point=mount_point, - transform_name=transform_name, - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def list_tokenization_key_configuration(self, mount_point=DEFAULT_MOUNT_POINT): - """List all tokenization keys. - Only valid for tokenization transformations. - - Supported methods: - LIST: /{mount_point}/tokenization/keys/. - - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str - :return: The response of the list_tokenization_key_configuration request. - :rtype: requests.Response - """ - api_path = "/v1/{mount_point}/tokenization/keys/".format( - mount_point=mount_point, - ) - return self._adapter.list( - url=api_path, - ) - - def read_tokenization_key_configuration( - self, transform_name, mount_point=DEFAULT_MOUNT_POINT - ): - """Read tokenization key configuration for a particular transform. - Only valid for tokenization transformations. - - Supported methods: - GET: /{mount_point}/tokenization/keys/:{mount_point}_name. - - - :param transform_name: the transform name to use for this operation. This is specified as part - of the URL. - :type transform_name: str - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str - :return: The response of the read_tokenization_key_configuration request. - :rtype: requests.Response - """ - api_path = "/v1/{mount_point}/tokenization/keys/{transform_name}".format( - mount_point=mount_point, - transform_name=transform_name, - ) - return self._adapter.get( - url=api_path, - ) - - def trim_tokenization_key_version( - self, transform_name, min_available_version, mount_point=DEFAULT_MOUNT_POINT - ): - """Trim older key versions setting a minimum version for the keyring. - Once trimmed, previous versions of the key cannot be recovered. - - Supported methods: - POST: /{mount_point}/tokenization/keys/{transform_name}/trim. - - - :param transform_name: the transform name to use for this operation. This is specified as part - of the URL. - :type transform_name: str - :param min_available_version: - :type min_available_version: int - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str - :return: The response of the trim_tokenization_key_version request. - :rtype: requests.Response - """ - params = { - "min_available_version": min_available_version, - } - api_path = "/v1/{mount_point}/tokenization/keys/{transform_name}/trim".format( - mount_point=mount_point, - transform_name=transform_name, - ) - return self._adapter.post( - url=api_path, - json=params, - ) diff --git a/.venv/lib/python3.12/site-packages/hvac/api/secrets_engines/transit.py b/.venv/lib/python3.12/site-packages/hvac/api/secrets_engines/transit.py deleted file mode 100644 index 77185bc..0000000 --- a/.venv/lib/python3.12/site-packages/hvac/api/secrets_engines/transit.py +++ /dev/null @@ -1,1163 +0,0 @@ -#!/usr/bin/env python -"""Transit methods module.""" -from hvac import exceptions, utils -from hvac.api.vault_api_base import VaultApiBase -from hvac.constants import transit as transit_constants - -DEFAULT_MOUNT_POINT = "transit" - - -class Transit(VaultApiBase): - """Transit Secrets Engine (API). - - Reference: https://www.vaultproject.io/api/secret/transit/index.html - """ - - def create_key( - self, - name, - convergent_encryption=None, - derived=None, - exportable=None, - allow_plaintext_backup=None, - key_type=None, - mount_point=DEFAULT_MOUNT_POINT, - auto_rotate_period=None, - ): - """Create a new named encryption key of the specified type. - - The values set here cannot be changed after key creation. - - Supported methods: - POST: /{mount_point}/keys/{name}. Produces: 204 (empty body) - - :param name: Specifies the name of the encryption key to create. This is specified as part of the URL. - :type name: str | unicode - :param convergent_encryption: If enabled, the key will support convergent encryption, where the same plaintext - creates the same ciphertext. This requires derived to be set to true. When enabled, each - encryption(/decryption/rewrap/datakey) operation will derive a nonce value rather than randomly generate it. - :type convergent_encryption: bool - :param derived: Specifies if key derivation is to be used. If enabled, all encrypt/decrypt requests to this - named key must provide a context which is used for key derivation. - :type derived: bool - :param exportable: Enables keys to be exportable. This allows for all the valid keys in the key ring to be - exported. Once set, this cannot be disabled. - :type exportable: bool - :param allow_plaintext_backup: If set, enables taking backup of named key in the plaintext format. Once set, - this cannot be disabled. - :type allow_plaintext_backup: bool - :param key_type: Specifies the type of key to create. The currently-supported types are: - - * **aes256-gcm96**: AES-256 wrapped with GCM using a 96-bit nonce size AEAD - * **chacha20-poly1305**: ChaCha20-Poly1305 AEAD (symmetric, supports derivation and convergent encryption) - * **ed25519**: ED25519 (asymmetric, supports derivation). - * **ecdsa-p256**: ECDSA using the P-256 elliptic curve (asymmetric) - * **ecdsa-p384**: ECDSA using the P-384 elliptic curve (asymmetric) - * **ecdsa-p521**: ECDSA using the P-521 elliptic curve (asymmetric) - * **rsa-2048**: RSA with bit size of 2048 (asymmetric) - * **rsa-3072**: RSA with bit size of 3072 (asymmetric) - * **rsa-4096**: RSA with bit size of 4096 (asymmetric) - :type key_type: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :param auto_rotate_period: The period at which this key should be rotated automatically. Requires Vault 1.10.x or higher. - :type auto_rotate_period: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - if convergent_encryption and not derived: - raise exceptions.ParamValidationError( - "derived must be set to True when convergent_encryption is True" - ) - if key_type is not None and key_type not in transit_constants.ALLOWED_KEY_TYPES: - error_msg = 'invalid key_type argument provided "{arg}", supported types: "{allowed_types}"' - raise exceptions.ParamValidationError( - error_msg.format( - arg=key_type, - allowed_types=", ".join(transit_constants.ALLOWED_KEY_TYPES), - ) - ) - params = utils.remove_nones( - { - "convergent_encryption": convergent_encryption, - "derived": derived, - "exportable": exportable, - "allow_plaintext_backup": allow_plaintext_backup, - "type": key_type, - "auto_rotate_period": auto_rotate_period, - } - ) - api_path = utils.format_url( - "/v1/{mount_point}/keys/{name}", - mount_point=mount_point, - name=name, - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def read_key(self, name, mount_point=DEFAULT_MOUNT_POINT): - """Read information about a named encryption key. - - The keys object shows the creation time of each key version; the values are not the keys themselves. Depending - on the type of key, different information may be returned, e.g. an asymmetric key will return its public key in - a standard format for the type. - - Supported methods: - GET: /{mount_point}/keys/{name}. Produces: 200 application/json - - :param name: Specifies the name of the encryption key to read. This is specified as part of the URL. - :type name: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the read_key request. - :rtype: dict - """ - api_path = utils.format_url( - "/v1/{mount_point}/keys/{name}", - mount_point=mount_point, - name=name, - ) - return self._adapter.get( - url=api_path, - ) - - def list_keys(self, mount_point=DEFAULT_MOUNT_POINT): - """List keys (if there are any). - - Only the key names are returned (not the actual keys themselves). - - An exception is thrown if there are no keys. - - Supported methods: - LIST: /{mount_point}/keys. Produces: 200 application/json - - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the request. - :rtype: dict - """ - api_path = utils.format_url("/v1/{mount_point}/keys", mount_point=mount_point) - return self._adapter.list(url=api_path) - - def delete_key(self, name, mount_point=DEFAULT_MOUNT_POINT): - """Delete a named encryption key. - - It will no longer be possible to decrypt any data encrypted with the named key. Because this is a potentially - catastrophic operation, the deletion_allowed tunable must be set in the key's /config endpoint. - - Supported methods: - DELETE: /{mount_point}/keys/{name}. Produces: 204 (empty body) - - :param name: Specifies the name of the encryption key to delete. This is specified as part of the URL. - :type name: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url( - "/v1/{mount_point}/keys/{name}", - mount_point=mount_point, - name=name, - ) - return self._adapter.delete( - url=api_path, - ) - - def update_key_configuration( - self, - name, - min_decryption_version=None, - min_encryption_version=None, - deletion_allowed=None, - exportable=None, - allow_plaintext_backup=None, - mount_point=DEFAULT_MOUNT_POINT, - auto_rotate_period=None, - ): - """Tune configuration values for a given key. - - These values are returned during a read operation on the named key. - - Supported methods: - POST: /{mount_point}/keys/{name}/config. Produces: 204 (empty body) - - :param name: Specifies the name of the encryption key to update configuration for. - :type name: str | unicode - :param min_decryption_version: Specifies the minimum version of ciphertext allowed to be decrypted. Adjusting - this as part of a key rotation policy can prevent old copies of ciphertext from being decrypted, should they - fall into the wrong hands. For signatures, this value controls the minimum version of signature that can be - verified against. For HMACs, this controls the minimum version of a key allowed to be used as the key for - verification. - :type min_decryption_version: int - :param min_encryption_version: Specifies the minimum version of the key that can be used to encrypt plaintext, - sign payloads, or generate HMACs. Must be 0 (which will use the latest version) or a value greater or equal - to min_decryption_version. - :type min_encryption_version: int - :param deletion_allowed: Specifies if the key is allowed to be deleted. - :type deletion_allowed: bool - :param exportable: Enables keys to be exportable. This allows for all the valid keys in the key ring to be - exported. Once set, this cannot be disabled. - :type exportable: bool - :param allow_plaintext_backup: If set, enables taking backup of named key in the plaintext format. Once set, - this cannot be disabled. - :type allow_plaintext_backup: bool - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :param auto_rotate_period: The period at which this key should be rotated automatically. Requires Vault 1.10.x or higher. - :type auto_rotate_period: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - if min_encryption_version is not None and min_decryption_version is not None: - if ( - min_encryption_version != 0 - and min_encryption_version <= min_decryption_version - ): - raise exceptions.ParamValidationError( - "min_encryption_version must be 0 or > min_decryption_version" - ) - params = utils.remove_nones( - { - "min_decryption_version": min_decryption_version, - "min_encryption_version": min_encryption_version, - "deletion_allowed": deletion_allowed, - "exportable": exportable, - "allow_plaintext_backup": allow_plaintext_backup, - "auto_rotate_period": auto_rotate_period, - } - ) - api_path = utils.format_url( - "/v1/{mount_point}/keys/{name}/config", - mount_point=mount_point, - name=name, - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def rotate_key(self, name, mount_point=DEFAULT_MOUNT_POINT): - """Rotate the version of the named key. - - After rotation, new plaintext requests will be encrypted with the new version of the key. To upgrade ciphertext - to be encrypted with the latest version of the key, use the rewrap endpoint. This is only supported with keys - that support encryption and decryption operations. - - Supported methods: - POST: /{mount_point}/keys/{name}/rotate. Produces: 204 (empty body) - - :param name: Specifies the name of the key to read information about. This is specified as part of the URL. - :type name: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url( - "/v1/{mount_point}/keys/{name}/rotate", - mount_point=mount_point, - name=name, - ) - return self._adapter.post( - url=api_path, - ) - - def export_key(self, name, key_type, version=None, mount_point=DEFAULT_MOUNT_POINT): - """Return the named key. - - The keys object shows the value of the key for each version. If version is specified, the specific version will - be returned. If latest is provided as the version, the current key will be provided. Depending on the type of - key, different information may be returned. The key must be exportable to support this operation and the version - must still be valid. - - Supported methods: - GET: /{mount_point}/export/{key_type}/{name}(/{version}). Produces: 200 application/json - - :param name: Specifies the name of the key to read information about. This is specified as part of the URL. - :type name: str | unicode - :param key_type: Specifies the type of the key to export. This is specified as part of the URL. Valid values are: - encryption-key - signing-key - hmac-key - :type key_type: str | unicode - :param version: Specifies the version of the key to read. If omitted, all versions of the key will be returned. - If the version is set to latest, the current key will be returned. - :type version: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the request. - :rtype: dict - """ - if key_type not in transit_constants.ALLOWED_EXPORT_KEY_TYPES: - error_msg = 'invalid key_type argument provided "{arg}", supported types: "{allowed_types}"' - raise exceptions.ParamValidationError( - error_msg.format( - arg=key_type, - allowed_types=", ".join(transit_constants.ALLOWED_EXPORT_KEY_TYPES), - ) - ) - api_path = utils.format_url( - "/v1/{mount_point}/export/{key_type}/{name}", - mount_point=mount_point, - key_type=key_type, - name=name, - ) - if version is not None: - api_path = self._adapter.urljoin(api_path, version) - return self._adapter.get( - url=api_path, - ) - - def encrypt_data( - self, - name, - plaintext=None, - context=None, - key_version=None, - nonce=None, - batch_input=None, - type=None, - convergent_encryption=None, - mount_point=DEFAULT_MOUNT_POINT, - associated_data=None, - ): - """Encrypt the provided plaintext using the named key. - - This path supports the create and update policy capabilities as follows: if the user has the create capability - for this endpoint in their policies, and the key does not exist, it will be upserted with default values - (whether the key requires derivation depends on whether the context parameter is empty or not). If the user only - has update capability and the key does not exist, an error will be returned. - - Supported methods: - POST: /{mount_point}/encrypt/{name}. Produces: 200 application/json - - :param name: Specifies the name of the encryption key to encrypt against. This is specified as part of the URL. - :type name: str | unicode - :param plaintext: Specifies base64 encoded plaintext to be encoded. Ignored if ``batch_input`` is set, otherwise required. - :type plaintext: str | unicode - :param context: Specifies the base64 encoded context for key derivation. This is required if key derivation is - enabled for this key. - :type context: str | unicode - :param associated_data: Specifies base64 encoded associated data (also known as additional data or AAD) to also be authenticated - with AEAD ciphers (aes128-gcm96, aes256-gcm, and chacha20-poly1305) - :type associated_data: str | unicode - :param key_version: Specifies the version of the key to use for encryption. If not set, uses the latest version. - Must be greater than or equal to the key's min_encryption_version, if set. - :type key_version: int - :param nonce: Specifies the base64 encoded nonce value. This must be provided if convergent encryption is - enabled for this key and the key was generated with Vault 0.6.1. Not required for keys created in 0.6.2+. - The value must be exactly 96 bits (12 bytes) long and the user must ensure that for any given context (and - thus, any given encryption key) this nonce value is never reused. - :type nonce: str | unicode - :param batch_input: Specifies a list of items to be encrypted in a single batch. When this parameter is set, if - the parameters 'plaintext', 'context' and 'nonce' are also set, they will be ignored. The format for the - input is: [dict(context="b64_context", plaintext="b64_plaintext"), ...] - :type batch_input: List[dict] - :param type: This parameter is required when encryption key is expected to be created. When performing an - upsert operation, the type of key to create. - :type type: str | unicode - :param convergent_encryption: This parameter will only be used when a key is expected to be created. Whether to - support convergent encryption. This is only supported when using a key with key derivation enabled and will - require all requests to carry both a context and 96-bit (12-byte) nonce. The given nonce will be used in - place of a randomly generated nonce. As a result, when the same context and nonce are supplied, the same - ciphertext is generated. It is very important when using this mode that you ensure that all nonces are - unique for a given context. Failing to do so will severely impact the ciphertext's security. - :type convergent_encryption: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the request. - :rtype: dict - """ - if plaintext is None and batch_input is None: - raise ValueError("plaintext must be specified unless batch_input is set") - params = { - "plaintext": plaintext, - } - params.update( - utils.remove_nones( - { - "context": context, - "associated_data": associated_data, - "key_version": key_version, - "nonce": nonce, - "batch_input": batch_input, - "type": type, - "convergent_encryption": convergent_encryption, - } - ) - ) - api_path = utils.format_url( - "/v1/{mount_point}/encrypt/{name}", - mount_point=mount_point, - name=name, - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def decrypt_data( - self, - name, - ciphertext=None, - context=None, - nonce=None, - batch_input=None, - mount_point=DEFAULT_MOUNT_POINT, - associated_data=None, - ): - """Decrypt the provided ciphertext using the named key. - - Supported methods: - POST: /{mount_point}/decrypt/{name}. Produces: 200 application/json - - :param name: Specifies the name of the encryption key to decrypt against. This is specified as part of the URL. - :type name: str | unicode - :param ciphertext: The ciphertext to decrypt. Ignored if ``batch_input`` is set, otherwise required. - :type ciphertext: str | unicode - :param context: Specifies the base64 encoded context for key derivation. This is required if key derivation is - enabled. - :type context: str | unicode - :param associated_data: Specifies base64 encoded associated data (also known as additional data or AAD) to also - be authenticated with AEAD ciphers (aes128-gcm96, aes256-gcm, and chacha20-poly1305) - :type associated_data: str | unicode - :param nonce: Specifies a base64 encoded nonce value used during encryption. Must be provided if convergent - encryption is enabled for this key and the key was generated with Vault 0.6.1. Not required for keys created - in 0.6.2+. - :type nonce: str | unicode - :param batch_input: Specifies a list of items to be decrypted in a single batch. When this parameter is set, if - the parameters 'ciphertext', 'context' and 'nonce' are also set, they will be ignored. Format for the input - goes like this: [dict(context="b64_context", ciphertext="b64_plaintext"), ...] - :type batch_input: List[dict] - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the request. - :rtype: dict - """ - if ciphertext is None and batch_input is None: - raise ValueError("ciphertext must be specified unless batch_input is set") - params = { - "ciphertext": ciphertext, - } - params.update( - utils.remove_nones( - { - "context": context, - "associated_data": associated_data, - "nonce": nonce, - "batch_input": batch_input, - } - ) - ) - api_path = utils.format_url( - "/v1/{mount_point}/decrypt/{name}", - mount_point=mount_point, - name=name, - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def rewrap_data( - self, - name, - ciphertext, - context=None, - key_version=None, - nonce=None, - batch_input=None, - mount_point=DEFAULT_MOUNT_POINT, - ): - """Rewrap the provided ciphertext using the latest version of the named key. - - Because this never returns plaintext, it is possible to delegate this functionality to untrusted users or scripts. - - Supported methods: - POST: /{mount_point}/rewrap/{name}. Produces: 200 application/json - - :param name: Specifies the name of the encryption key to re-encrypt against. This is specified as part of the URL. - :type name: str | unicode - :param ciphertext: Specifies the ciphertext to re-encrypt. - :type ciphertext: str | unicode - :param context: Specifies the base64 encoded context for key derivation. This is required if key derivation is - enabled. - :type context: str | unicode - :param key_version: Specifies the version of the key to use for the operation. If not set, uses the latest - version. Must be greater than or equal to the key's min_encryption_version, if set. - :type key_version: int - :param nonce: Specifies a base64 encoded nonce value used during encryption. Must be provided if convergent - encryption is enabled for this key and the key was generated with Vault 0.6.1. Not required for keys created - in 0.6.2+. - :type nonce: str | unicode - :param batch_input: Specifies a list of items to be decrypted in a single batch. When this parameter is set, if - the parameters 'ciphertext', 'context' and 'nonce' are also set, they will be ignored. Format for the input - goes like this: [dict(context="b64_context", ciphertext="b64_plaintext"), ...] - :type batch_input: List[dict] - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the request. - :rtype: dict - """ - params = { - "ciphertext": ciphertext, - } - params.update( - utils.remove_nones( - { - "context": context, - "key_version": key_version, - "nonce": nonce, - "batch_input": batch_input, - } - ) - ) - api_path = utils.format_url( - "/v1/{mount_point}/rewrap/{name}", - mount_point=mount_point, - name=name, - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def generate_data_key( - self, - name, - key_type, - context=None, - nonce=None, - bits=None, - mount_point=DEFAULT_MOUNT_POINT, - ): - """Generates a new high-entropy key and the value encrypted with the named key. - - Optionally return the plaintext of the key as well. Whether plaintext is returned depends on the path; as a - result, you can use Vault ACL policies to control whether a user is allowed to retrieve the plaintext value of a - key. This is useful if you want an untrusted user or operation to generate keys that are then made available to - trusted users. - - Supported methods: - POST: /{mount_point}/datakey/{key_type}/{name}. Produces: 200 application/json - - :param name: Specifies the name of the encryption key to use to encrypt the datakey. This is specified as part - of the URL. - :type name: str | unicode - :param key_type: Specifies the type of key to generate. If plaintext, the plaintext key will be returned along - with the ciphertext. If wrapped, only the ciphertext value will be returned. This is specified as part of - the URL. - :type key_type: str | unicode - :param context: Specifies the key derivation context, provided as a base64-encoded string. This must be provided - if derivation is enabled. - :type context: str | unicode - :param nonce: Specifies a nonce value, provided as base64 encoded. Must be provided if convergent encryption is - enabled for this key and the key was generated with Vault 0.6.1. Not required for keys created in 0.6.2+. - The value must be exactly 96 bits (12 bytes) long and the user must ensure that for any given context (and - thus, any given encryption key) this nonce value is never reused. - :type nonce: str | unicode - :param bits: Specifies the number of bits in the desired key. Can be 128, 256, or 512. - :type bits: int - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the request. - :rtype: dict - """ - if key_type not in transit_constants.ALLOWED_DATA_KEY_TYPES: - error_msg = 'invalid key_type argument provided "{arg}", supported types: "{allowed_types}"' - raise exceptions.ParamValidationError( - error_msg.format( - arg=key_type, - allowed_types=", ".join(transit_constants.ALLOWED_DATA_KEY_TYPES), - ) - ) - if bits is not None and bits not in transit_constants.ALLOWED_DATA_KEY_BITS: - error_msg = 'invalid bits argument provided "{arg}", supported values: "{allowed_values}"' - raise exceptions.ParamValidationError( - error_msg.format( - arg=bits, - allowed_values=", ".join( - [str(b) for b in transit_constants.ALLOWED_DATA_KEY_BITS] - ), - ) - ) - params = utils.remove_nones( - { - "context": context, - "nonce": nonce, - "bits": bits, - } - ) - api_path = utils.format_url( - "/v1/{mount_point}/datakey/{key_type}/{name}", - mount_point=mount_point, - key_type=key_type, - name=name, - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def generate_random_bytes( - self, n_bytes=None, output_format=None, mount_point=DEFAULT_MOUNT_POINT - ): - """Return high-quality random bytes of the specified length. - - Supported methods: - POST: /{mount_point}/random(/{bytes}). Produces: 200 application/json - - :param n_bytes: Specifies the number of bytes to return. This value can be specified either in the request body, - or as a part of the URL. - :type n_bytes: int - :param output_format: Specifies the output encoding. Valid options are hex or base64. - :type output_format: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the request. - :rtype: dict - """ - params = utils.remove_nones( - { - "bytes": n_bytes, - "format": output_format, - } - ) - api_path = utils.format_url("/v1/{mount_point}/random", mount_point=mount_point) - return self._adapter.post( - url=api_path, - json=params, - ) - - def hash_data( - self, - hash_input, - algorithm=None, - output_format=None, - mount_point=DEFAULT_MOUNT_POINT, - ): - """Return the cryptographic hash of given data using the specified algorithm. - - Supported methods: - POST: /{mount_point}/hash(/{algorithm}). Produces: 200 application/json - - :param hash_input: Specifies the base64 encoded input data. - :type hash_input: str | unicode - :param algorithm: Specifies the hash algorithm to use. This can also be specified as part of the URL. - Currently-supported algorithms are: sha2-224, sha2-256, sha2-384, sha2-512 - :type algorithm: str | unicode - :param output_format: Specifies the output encoding. This can be either hex or base64. - :type output_format: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the request. - :rtype: dict - """ - if ( - algorithm is not None - and algorithm not in transit_constants.ALLOWED_HASH_DATA_ALGORITHMS - ): - error_msg = 'invalid algorithm argument provided "{arg}", supported types: "{allowed_types}"' - raise exceptions.ParamValidationError( - error_msg.format( - arg=algorithm, - allowed_types=", ".join( - transit_constants.ALLOWED_HASH_DATA_ALGORITHMS - ), - ) - ) - if ( - output_format is not None - and output_format not in transit_constants.ALLOWED_HASH_DATA_FORMATS - ): - error_msg = 'invalid output_format argument provided "{arg}", supported types: "{allowed_types}"' - raise exceptions.ParamValidationError( - error_msg.format( - arg=output_format, - allowed_types=", ".join( - transit_constants.ALLOWED_HASH_DATA_FORMATS - ), - ) - ) - params = { - "input": hash_input, - } - params.update( - utils.remove_nones( - { - "algorithm": algorithm, - "format": output_format, - } - ) - ) - api_path = utils.format_url("/v1/{mount_point}/hash", mount_point=mount_point) - return self._adapter.post( - url=api_path, - json=params, - ) - - def generate_hmac( - self, - name, - hash_input, - key_version=None, - algorithm=None, - mount_point=DEFAULT_MOUNT_POINT, - ): - """Return the digest of given data using the specified hash algorithm and the named key. - - The key can be of any type supported by transit; the raw key will be marshaled into bytes to be used for the - HMAC function. If the key is of a type that supports rotation, the latest (current) version will be used. - - Supported methods: - POST: /{mount_point}/hmac/{name}(/{algorithm}). Produces: 200 application/json - - :param name: Specifies the name of the encryption key to generate hmac against. This is specified as part of the - URL. - :type name: str | unicode - :param hash_input: Specifies the base64 encoded input data. - :type input: str | unicode - :param key_version: Specifies the version of the key to use for the operation. If not set, uses the latest - version. Must be greater than or equal to the key's min_encryption_version, if set. - :type key_version: int - :param algorithm: Specifies the hash algorithm to use. This can also be specified as part of the URL. - Currently-supported algorithms are: sha2-224, sha2-256, sha2-384, sha2-512 - :type algorithm: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the request. - :rtype: dict - """ - if ( - algorithm is not None - and algorithm not in transit_constants.ALLOWED_HASH_DATA_ALGORITHMS - ): - error_msg = 'invalid algorithm argument provided "{arg}", supported types: "{allowed_types}"' - raise exceptions.ParamValidationError( - error_msg.format( - arg=algorithm, - allowed_types=", ".join( - transit_constants.ALLOWED_HASH_DATA_ALGORITHMS - ), - ) - ) - params = { - "input": hash_input, - } - params.update( - utils.remove_nones( - { - "key_version": key_version, - "algorithm": algorithm, - } - ) - ) - api_path = utils.format_url( - "/v1/{mount_point}/hmac/{name}", - mount_point=mount_point, - name=name, - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def sign_data( - self, - name, - hash_input=None, - key_version=None, - hash_algorithm=None, - context=None, - prehashed=None, - signature_algorithm=None, - marshaling_algorithm=None, - salt_length=None, - mount_point=DEFAULT_MOUNT_POINT, - batch_input=None, - ): - """Return the cryptographic signature of the given data using the named key and the specified hash algorithm. - - The key must be of a type that supports signing. - - Supported methods: - POST: /{mount_point}/sign/{name}(/{hash_algorithm}). Produces: 200 application/json - - :param name: Specifies the name of the encryption key to use for signing. This is specified as part of the URL. - :type name: str | unicode - :param hash_input: Specifies the base64 encoded input data. - This parameter is mutually exclusive with the ``batch_results`` parameter, but one of them must be supplied. - If both are set, or neither are set, an exception will be raised. - :type hash_input: str | unicode - :param key_version: Specifies the version of the key to use for signing. If not set, uses the latest version. - Must be greater than or equal to the key's min_encryption_version, if set. - :type key_version: int - :param hash_algorithm: Specifies the hash algorithm to use for supporting key types (notably, not including - ed25519 which specifies its own hash algorithm). This can also be specified as part of the URL. - Currently-supported algorithms are: sha2-224, sha2-256, sha2-384, sha2-512 - :type hash_algorithm: str | unicode - :param context: Base64 encoded context for key derivation. Required if key derivation is enabled; currently only - available with ed25519 keys. - :type context: str | unicode - :param prehashed: Set to true when the input is already hashed. If the key type is rsa-2048 or rsa-4096, then - the algorithm used to hash the input should be indicated by the hash_algorithm parameter. Just as the value - to sign should be the base64-encoded representation of the exact binary data you want signed, when set, input - is expected to be base64-encoded binary hashed data, not hex-formatted. (As an example, on the command line, - you could generate a suitable input via openssl dgst -sha256 -binary | base64.) - :type prehashed: bool - :param signature_algorithm: When using a RSA key, specifies the RSA signature algorithm to use for signing. - Supported signature types are: pss, pkcs1v15 - :type signature_algorithm: str | unicode - :param marshaling_algorithm: Specifies the way in which the signature should be marshaled. This currently only applies to ECDSA keys. - Supported types are: asn1, jws - :type marshaling_algorithm: str | unicode - :param salt_length: The salt length used to sign. Currently only applies to the RSA PSS signature scheme. - Options are 'auto' (the default used by Golang, causing the salt to be as large as possible when signing), - 'hash' (causes the salt length to equal the length of the hash used in the signature), - or an integer between the minimum and the maximum permissible salt lengths for the given RSA key size. - Defaults to 'auto'. - :type salt_length: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :param batch_input: Specifies a list of items for processing. - Any batch output will preserve the order of the batch input. - If the input data value of an item is invalid, the corresponding item in the ``batch_results`` - will have the key ``error`` with a value describing the error. - This parameter is mutually exclusive with the ``hash_input`` parameter, but one of them must be supplied. - If both are set, or neither are set, an exception will be raised. - Responses are returned in the ``batch_results`` array component of the ``data`` element of the response. - :type batch_input: List[Dict[str, str]] - :return: The JSON response of the request. - :rtype: dict - """ - if ( - hash_algorithm is not None - and hash_algorithm not in transit_constants.ALLOWED_HASH_DATA_ALGORITHMS - ): - error_msg = 'invalid hash_algorithm argument provided "{arg}", supported types: "{allowed_types}"' - raise exceptions.ParamValidationError( - error_msg.format( - arg=hash_algorithm, - allowed_types=", ".join( - transit_constants.ALLOWED_HASH_DATA_ALGORITHMS - ), - ) - ) - if ( - signature_algorithm is not None - and signature_algorithm - not in transit_constants.ALLOWED_SIGNATURE_ALGORITHMS - ): - error_msg = 'invalid signature_algorithm argument provided "{arg}", supported types: "{allowed_types}"' - raise exceptions.ParamValidationError( - error_msg.format( - arg=signature_algorithm, - allowed_types=", ".join( - transit_constants.ALLOWED_SIGNATURE_ALGORITHMS - ), - ) - ) - if ( - marshaling_algorithm is not None - and marshaling_algorithm - not in transit_constants.ALLOWED_MARSHALING_ALGORITHMS - ): - error_msg = 'invalid marshaling_algorithm argument provided "{arg}", supported types: "{allowed_types}"' - raise exceptions.ParamValidationError( - error_msg.format( - arg=marshaling_algorithm, - allowed_types=", ".join( - transit_constants.ALLOWED_MARSHALING_ALGORITHMS - ), - ) - ) - if ( - salt_length is not None - and not transit_constants.ALLOWED_SALT_LENGTHS.fullmatch(salt_length) - ): - error_msg = 'invalid salt_length argument provided "{arg}", supported types: "{allowed_types}"' - raise exceptions.ParamValidationError( - error_msg.format( - arg=salt_length, - allowed_types=transit_constants.ALLOWED_SALT_LENGTHS.pattern, - ) - ) - - if hash_input is None and batch_input is None: - error_msg = "Invalid parameter combination: Please provide only one of the following parameters: 'hash_input' or 'batch_input'." - raise exceptions.ParamValidationError(message=error_msg) - - if hash_input is not None and batch_input is not None: - error_msg = "Invalid parameter combination: 'hash_input' or 'batch_input' should be provided, not both." - raise exceptions.ParamValidationError(message=error_msg) - - params = { - "input": hash_input, - } - params.update( - utils.remove_nones( - { - "key_version": key_version, - "hash_algorithm": hash_algorithm, - "context": context, - "prehashed": prehashed, - "signature_algorithm": signature_algorithm, - "marshaling_algorithm": marshaling_algorithm, - "salt_length": salt_length, - "batch_input": batch_input, - } - ) - ) - - api_path = utils.format_url( - "/v1/{mount_point}/sign/{name}", - mount_point=mount_point, - name=name, - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def verify_signed_data( - self, - name, - hash_input, - signature=None, - hmac=None, - hash_algorithm=None, - context=None, - prehashed=None, - signature_algorithm=None, - salt_length=None, - marshaling_algorithm=None, - mount_point=DEFAULT_MOUNT_POINT, - ): - """Return whether the provided signature is valid for the given data. - - Supported methods: - POST: /{mount_point}/verify/{name}(/{hash_algorithm}). Produces: 200 application/json - - :param name: Specifies the name of the encryption key that was used to generate the signature or HMAC. - :type name: str | unicode - :param hash_input: Specifies the base64 encoded input data. - :type input: str | unicode - :param signature: Specifies the signature output from the /transit/sign function. Either this must be supplied - or hmac must be supplied. - :type signature: str | unicode - :param hmac: Specifies the signature output from the /transit/hmac function. Either this must be supplied or - signature must be supplied. - :type hmac: str | unicode - :param hash_algorithm: Specifies the hash algorithm to use. This can also be specified as part of the URL. - Currently-supported algorithms are: sha2-224, sha2-256, sha2-384, sha2-512 - :type hash_algorithm: str | unicode - :param context: Base64 encoded context for key derivation. Required if key derivation is enabled; currently only - available with ed25519 keys. - :type context: str | unicode - :param prehashed: Set to true when the input is already hashed. If the key type is rsa-2048 or rsa-4096, then - the algorithm used to hash the input should be indicated by the hash_algorithm parameter. - :type prehashed: bool - :param signature_algorithm: When using a RSA key, specifies the RSA signature algorithm to use for signature - verification. Supported signature types are: pss, pkcs1v15 - :type signature_algorithm: str | unicode - :param marshaling_algorithm: Specifies the way in which the signature should be marshaled. This currently only applies to ECDSA keys. - Supported types are: asn1, jws - :type marshaling_algorithm: str | unicode - :param salt_length: The salt length used to sign. Currently only applies to the RSA PSS signature scheme. - Options are 'auto' (the default used by Golang, causing the salt to be as large as possible when signing), - 'hash' (causes the salt length to equal the length of the hash used in the signature), - or an integer between the minimum and the maximum permissible salt lengths for the given RSA key size. - Defaults to 'auto'. - :type salt_length: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the request. - :rtype: dict - """ - if (signature is None and hmac is None) or ( - signature is not None and hmac is not None - ): - error_msg = 'either "signature" or "hmac" argument (but not both) must be provided to verify signature' - raise exceptions.ParamValidationError(error_msg) - if ( - hash_algorithm is not None - and hash_algorithm not in transit_constants.ALLOWED_HASH_DATA_ALGORITHMS - ): - error_msg = 'invalid hash_algorithm argument provided "{arg}", supported types: "{allowed_types}"' - raise exceptions.ParamValidationError( - error_msg.format( - arg=hash_algorithm, - allowed_types=", ".join( - transit_constants.ALLOWED_HASH_DATA_ALGORITHMS - ), - ) - ) - if ( - signature_algorithm is not None - and signature_algorithm - not in transit_constants.ALLOWED_SIGNATURE_ALGORITHMS - ): - error_msg = 'invalid signature_algorithm argument provided "{arg}", supported types: "{allowed_types}"' - raise exceptions.ParamValidationError( - error_msg.format( - arg=signature_algorithm, - allowed_types=", ".join( - transit_constants.ALLOWED_SIGNATURE_ALGORITHMS - ), - ) - ) - if ( - marshaling_algorithm is not None - and marshaling_algorithm - not in transit_constants.ALLOWED_MARSHALING_ALGORITHMS - ): - error_msg = 'invalid marshaling_algorithm argument provided "{arg}", supported types: "{allowed_types}"' - raise exceptions.ParamValidationError( - error_msg.format( - arg=marshaling_algorithm, - allowed_types=", ".join( - transit_constants.ALLOWED_MARSHALING_ALGORITHMS - ), - ) - ) - if ( - salt_length is not None - and not transit_constants.ALLOWED_SALT_LENGTHS.fullmatch(salt_length) - ): - error_msg = 'invalid salt_length argument provided "{arg}", supported types: "{allowed_types}"' - raise exceptions.ParamValidationError( - error_msg.format( - arg=salt_length, - allowed_types=transit_constants.ALLOWED_SALT_LENGTHS.pattern, - ) - ) - params = { - "name": name, - "input": hash_input, - } - params.update( - utils.remove_nones( - { - "hash_algorithm": hash_algorithm, - "signature": signature, - "hmac": hmac, - "context": context, - "prehashed": prehashed, - "signature_algorithm": signature_algorithm, - "marshaling_algorithm": marshaling_algorithm, - "salt_length": salt_length, - } - ) - ) - api_path = utils.format_url( - "/v1/{mount_point}/verify/{name}", mount_point=mount_point, name=name - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def backup_key(self, name, mount_point=DEFAULT_MOUNT_POINT): - """Return a plaintext backup of a named key. - - The backup contains all the configuration data and keys of all the versions along with the HMAC key. The - response from this endpoint can be used with the /restore endpoint to restore the key. - - Supported methods: - GET: /{mount_point}/backup/{name}. Produces: 200 application/json - - :param name: Name of the key. - :type name: str | unicode - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The JSON response of the request. - :rtype: dict - """ - api_path = utils.format_url( - "/v1/{mount_point}/backup/{name}", - mount_point=mount_point, - name=name, - ) - return self._adapter.get( - url=api_path, - ) - - def restore_key( - self, backup, name=None, force=None, mount_point=DEFAULT_MOUNT_POINT - ): - """Restore the backup as a named key. - - This will restore the key configurations and all the versions of the named key along with HMAC keys. The input - to this endpoint should be the output of /backup endpoint. For safety, by default the backend will refuse to - restore to an existing key. If you want to reuse a key name, it is recommended you delete the key before - restoring. It is a good idea to attempt restoring to a different key name first to verify that the operation - successfully completes. - - Supported methods: - POST: /{mount_point}/restore(/name). Produces: 204 (empty body) - - :param backup: Backed up key data to be restored. This should be the output from the /backup endpoint. - :type backup: str | unicode - :param name: If set, this will be the name of the restored key. - :type name: str | unicode - :param force: If set, force the restore to proceed even if a key by this name already exists. - :type force: bool - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - params = { - "backup": backup, - } - params.update( - utils.remove_nones( - { - "force": force, - } - ) - ) - api_path = utils.format_url( - "/v1/{mount_point}/restore", mount_point=mount_point - ) - if name is not None: - api_path = self._adapter.urljoin(api_path, name) - return self._adapter.post( - url=api_path, - json=params, - ) - - def trim_key(self, name, min_version, mount_point=DEFAULT_MOUNT_POINT): - """Trims older key versions setting a minimum version for the keyring. - - Once trimmed, previous versions of the key cannot be recovered. - - Supported methods: - POST: /{mount_point}/keys/{name}/trim. Produces: 200 application/json - - :param name: Specifies the name of the key to be trimmed. - :type name: str | unicode - :param min_version: The minimum version for the key ring. All versions before this version will be permanently - deleted. This value can at most be equal to the lesser of min_decryption_version and min_encryption_version. - This is not allowed to be set when either min_encryption_version or min_decryption_version is set to zero. - :type min_version: int - :param mount_point: The "path" the method/backend was mounted on. - :type mount_point: str | unicode - :return: The response of the request. - :rtype: dict - """ - params = { - "min_available_version": min_version, - } - api_path = utils.format_url( - "/v1/{mount_point}/keys/{name}/trim", - mount_point=mount_point, - name=name, - ) - return self._adapter.post( - url=api_path, - json=params, - ) diff --git a/.venv/lib/python3.12/site-packages/hvac/api/system_backend/__init__.py b/.venv/lib/python3.12/site-packages/hvac/api/system_backend/__init__.py deleted file mode 100644 index 970a5dc..0000000 --- a/.venv/lib/python3.12/site-packages/hvac/api/system_backend/__init__.py +++ /dev/null @@ -1,85 +0,0 @@ -"""Collection of Vault system backend API endpoint classes.""" -import logging - -from hvac.api.system_backend.audit import Audit -from hvac.api.system_backend.auth import Auth -from hvac.api.system_backend.capabilities import Capabilities -from hvac.api.system_backend.health import Health -from hvac.api.system_backend.init import Init -from hvac.api.system_backend.key import Key -from hvac.api.system_backend.leader import Leader -from hvac.api.system_backend.lease import Lease -from hvac.api.system_backend.mount import Mount -from hvac.api.system_backend.namespace import Namespace -from hvac.api.system_backend.policies import Policies -from hvac.api.system_backend.policy import Policy -from hvac.api.system_backend.quota import Quota -from hvac.api.system_backend.raft import Raft -from hvac.api.system_backend.seal import Seal -from hvac.api.system_backend.system_backend_mixin import SystemBackendMixin -from hvac.api.system_backend.wrapping import Wrapping -from hvac.api.vault_api_category import VaultApiCategory - -__all__ = ( - "Audit", - "Auth", - "Capabilities", - "Health", - "Init", - "Key", - "Leader", - "Lease", - "Mount", - "Namespace", - "Policies", - "Policy", - "Quota", - "Raft", - "Seal", - "SystemBackend", - "SystemBackendMixin", - "Wrapping", -) - - -logger = logging.getLogger(__name__) - - -class SystemBackend( - VaultApiCategory, - Audit, - Auth, - Capabilities, - Health, - Init, - Key, - Leader, - Lease, - Mount, - Namespace, - Policies, - Policy, - Quota, - Raft, - Seal, - Wrapping, -): - implemented_classes = [ - Audit, - Auth, - Capabilities, - Health, - Init, - Key, - Leader, - Lease, - Mount, - Namespace, - Policies, - Policy, - Quota, - Raft, - Seal, - Wrapping, - ] - unimplemented_classes = [] diff --git a/.venv/lib/python3.12/site-packages/hvac/api/system_backend/__pycache__/__init__.cpython-312.pyc b/.venv/lib/python3.12/site-packages/hvac/api/system_backend/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index 9d964ec3e72a235cbc5efdbc0f18138b687fcbdd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2145 zcmb_dPj4GV6rZ)%_OAcMf9ocWV}~TDrj3{KHwUN`f+$tnP#OuOxhxxdVlSE5-R`af zMndYL2fjh!3m~C>1HJ+mDh`-MIUx?*ECnt-@#fi~L}G7@#&3Qz^JezVd%ySmL!po* z&_4M7+tDW(LVlBz^HyJgv-cE29+Lr~WS|TZT%ih#NuCf%npEVP%2kn~Da0wB78#mB zoaUO)sg5|qvm!@xh&7%U1zJF?^P*UyONg_)B+9gmIL9lZN~?(Tye8_jj<~=ti3V*T zF7nG_nJyz<;wz#_n}|z%RkUaeahb1)HfxirT1+hUl5ZCyo*rHp2>-5D0 zValib=T3M&vMW!(53>LMA$gR{xkegU;@~TOAlZ*LK2ApIbq| zg5DqUn*FX4rFO>yI|QKaj>8d*`8~_C4sC9SHVa^$exF$!chp-BY9?>9iQKrutO4@@ zr2qv?g1he6k(cTFmSBNr_2sH|&*gT1aT{WJJoVw&4J`obed`DfIDikqymEl{zcV-g zuKl^~$V)!b0ebJw%?tdI>|f6}e^NqCR1N|BNxEd_9p_?i^D6q1~NPKvw~ z1u2SBEJ;z4q6{J`Trj||$PMZCKK%Y^QeC#Q*FZcbi~x@bO+frqh+rCGs6iC75XU@3 zvIwy(K{PAF60Hsitxc3}!k0O*->pZQX*%F9(~PpFDcr%BOPn{&2V;xRcmBus;aj4r zEj-Qyb3!&S7p#ctW9L7XzawYzrO&=JMy_B+z{kdY=DC3#x;{j8`=%Wld#)4uE;sul z%Ner3Jg^QY=8@|QD>Qm1%sDZ*eQ0=-aO66#_O8ETz-hJ(1Ua@q-58x%eZ%r>W6oW3 z!Ck{NZQz_~_Phyt3&qP|OzTAb<#^AMRG|4HdCv85teq*J;tc*HwdfuXlVBW^tj%pLk>v+2!$kKypAMZ&YsuC83c$EMmGA|j| z;;g>N8dJz>h7~3Lp`R@Z-8@g9hw(%fcN3^+_7`Q(uK{-@X)VrywEB>RcYwFd_ZxB} zElCU$S!VoIDUj=HfSze@&Fjn!{|%VRzoOt95VNGBD8G;!zmnqb#5g6}r{wKZavi}{ z1h5GG%~SIF`4n`Z-^P`lnOe;y9%g3ONVfS^<7a*4slM{{&QJR0!}Oo&Eu}qGYg1L9 gs@ha7P1P)d3<6k$UYM%+^C{>+&;PXn=g{=O0k~>t&j0`b diff --git a/.venv/lib/python3.12/site-packages/hvac/api/system_backend/__pycache__/audit.cpython-312.pyc b/.venv/lib/python3.12/site-packages/hvac/api/system_backend/__pycache__/audit.cpython-312.pyc deleted file mode 100644 index 20aca3ef7bda70c04c881cbc23787445ce267d19..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4562 zcmcIoO>7&-6`uVeMKhu$TZ$W}jXbu3#zZ1Ac7mcM>;`G9I*os8DLD`*7NgyfIO=kD zGqWq3Dh2r9gL6u5zO+S71q}O;bJ0W2?L|TYSRfLhMNhpck#g~=@9i#EOUjYrAXz}e z*_nAWZ)U#ldvEoxN~KKTx%T(Jwf=ILkpJRK|0$%E?O#CU9&t#MIGUroT3c`G8rBWh zXq!z_BRaWA9P!^^o z>2H|*NA5ZF3J+VpqiX-d8LC>Z5QV~3P&t|mOvhajw}fXWt0bkKzHFa{%00qKQv-K( zN4rCs#v$Sq9pjGHG||Oo!6`sl?C8~zULp3!)^c;9_xQK{%Xq3TSKEH!TpDXJ5A$8G!xh`cZOt@$_ zY}U7$ZwUocJAp5}kV^i3BqU6tBFCpT3)q5iMcARjqs)PIh40bOr_AfnfQ79Y6>wWD z3VU~~7;q}RG;q6}+({$z7d^N*JKvyn)lv0$S2cQF`c4G8uXpHYgfT-75JXw)L*1wi^tpGDy(H|HDuTcc!N5^4ztG9N`2+b?&4Lw zSF)JHf{@FevBX2bi>bJ~sPH=I-wUPhT6T+h zOI%rVY@uTTP}?l5*H*Z!vRq>ajLpP(o|l zmz>&uJ8=1}S6~&m);)6_z>Vwg4sfIXCtP=JkRq?s)4Ux3KNozbQ_ayMV3M^{k+2f% z&m~j^awA2stxuP{qU1Oe4@pp#PN70cyEO8I?K?c@hSa8WEpG8PM(HltJpOu>%*c+>ffQV}A#Ycy6sp|b6u zE;&2^$2lk>>Kz={fF&Nx@Hu6U?CUOGVS^6dL<}d;*PAV2x6sps=6jaSJcTVm81xqh zJkH4;efP%YVfT`S_w~*7ZRX~k6N#7(Y#o9Hqwz>M8MiaMOghJc@4K0InN%ZpzOzze zBm&l`+Kp7(v-x@^o`2QoJ(ELKZzR2dULp43@#KKEr{uX0ijF67U+)=_bbBTSm1?n9 zi~qemW%PHl`%{d>B$dE)1rFP!>n#5{6z+bC8J z?-->+<()|~dHm7D^v1;W`iqTECqJL~?cLJm*hCT~PHv2y{J8bWd+TE-KN~x@UOFc$ zu(I9Hlb}ve>G9yUTTt91VHOvb^P`{-AB-Ol^}Zgj>7e9Kh!o2s$>@C9)gNYY19aSE zm~CAUDo$?pP&AeCB>};ASi=v{-3zmqXXj`0Y03AI-h^-nd8|E2^pNTfcX`P7Fgxac z%7CY4b3Zfsf#@bD;1=X06je?B1b@t!C-SG*9#f*2Y@=$#q)5ipxJ`DB?FZ87jj`#?@#nS-GXCN=(Z|bML_btckcuw!pA4xITHr%O z>*|op7zZF0@*Y55Kld=70Ar*ZiLQls?bYK0@iTuJu@*>-LVJ`z{tR0SyE4$L4D3WsLBEWp0skog($J5A zhavZ{BNr|tKB?8oL>2~H=fFn20R=?9Q=~Ha(I3)iw^Pc=!yBJEpHEymFospltMI_L zd&#meZ?~*o*|OU3`RQVP)Uw`>n49#-QS_T)F^$DbP~0c6z{DY3;x|iNVBk`?%RA(2 zeY9|PYl>Xaey?pCFBi^#-P8^j%G>nW!uiA$t*%1)F=APcZ^NP{eh4O6$SYW_LDoIEpa3{BJiLw@xoIrb&Fv{Pi7 Oc7AKlTU*!=&W2k3|Z diff --git a/.venv/lib/python3.12/site-packages/hvac/api/system_backend/__pycache__/auth.cpython-312.pyc b/.venv/lib/python3.12/site-packages/hvac/api/system_backend/__pycache__/auth.cpython-312.pyc deleted file mode 100644 index 2d0127ccf53e9ddc205cd6e98a970c78eeb706bd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9657 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 TJIS-LNP2x>-#-MrVKe*_+4IR$ diff --git a/.venv/lib/python3.12/site-packages/hvac/api/system_backend/__pycache__/capabilities.cpython-312.pyc b/.venv/lib/python3.12/site-packages/hvac/api/system_backend/__pycache__/capabilities.cpython-312.pyc deleted file mode 100644 index 123547db54c88c74d110ce35ffaaf41439e28349..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1808 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 diff --git a/.venv/lib/python3.12/site-packages/hvac/api/system_backend/__pycache__/leader.cpython-312.pyc b/.venv/lib/python3.12/site-packages/hvac/api/system_backend/__pycache__/leader.cpython-312.pyc deleted file mode 100644 index 729648af4e50c2b5a8b1bac46eb74667189e4822..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1827 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 diff --git a/.venv/lib/python3.12/site-packages/hvac/api/system_backend/__pycache__/policies.cpython-312.pyc b/.venv/lib/python3.12/site-packages/hvac/api/system_backend/__pycache__/policies.cpython-312.pyc deleted file mode 100644 index 565d0c31211a9d26e011958b1d61fc88a85a0d05..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9648 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 G;{H3FV#8zr diff --git a/.venv/lib/python3.12/site-packages/hvac/api/system_backend/__pycache__/quota.cpython-312.pyc b/.venv/lib/python3.12/site-packages/hvac/api/system_backend/__pycache__/quota.cpython-312.pyc deleted file mode 100644 index 3d975ca0a9eb6352e78258265c79af574e5b29c2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4466 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 Bcc}mX diff --git a/.venv/lib/python3.12/site-packages/hvac/api/system_backend/__pycache__/system_backend_mixin.cpython-312.pyc b/.venv/lib/python3.12/site-packages/hvac/api/system_backend/__pycache__/system_backend_mixin.cpython-312.pyc deleted file mode 100644 index e0823eab5fc861ff46bc6df021a42c3c1c5ecd7a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 696 zcmZ8ezl+pB6rM?P$>!V@IfRA9B8AO@m+=Rv#UbooaR}Zi9$2IqW|J`+on&GryBI5r zEA%h8`wIj)3v2%cE3ps)f^b;a2`d&?`6kIWPVwgZX5M_?y!Sp22Ac@h!%y$#E=K4~ zll8JYu$lolMiGjzK!M&3fm0(eu*Rk^Q!B7AG7v}48nv}RyL0;#l=TW61MQ*6IzrI~ zx47}aKDD}=UWLcbFHH`{xOOJf-F;p%fc+X`rKyY-LgPNAFBVL6Hx8wd3@Lq&R{Ce>Z^>MyoG7s%k9jUtQpzIXYI`p! z$*#=GLJAtrSr&6e5814u@RO94#9#7kNklRuc~#D3cFVtUlfY}fokI-_(#d?uLc;Qd zsHQeLYm57j(o`4g=T)Ic*aSTnwE^J>)zQ2%v#>BB ztsZJqA58tF9t8yizKR!mcC{Px@&UZzMd4^}YXKmQ^960wcntuZ_jcM2-YYHx)$>z6 wgx@B{_zYeAj)p(c^&jr&&G4H$`r?jG?tXQzzPA6^7~eU$@^SbV0ciC80X37mdH?_b diff --git a/.venv/lib/python3.12/site-packages/hvac/api/system_backend/__pycache__/wrapping.cpython-312.pyc b/.venv/lib/python3.12/site-packages/hvac/api/system_backend/__pycache__/wrapping.cpython-312.pyc deleted file mode 100644 index 89727a1ae38a8992c3a37d1b1ba1907161766679..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2416 zcmb_e&2QX96d&8WX|ioe+O#Bxs!Tyb7$xhpAR(?`z)g zXa9Qqc!fZl`|-Qx2S*6`3n%?n?hU%H!(fYW!mW_BtVPQrHn~Q)eV=egSPz{-ZqaU+ z-0~BgxK?(u-quF6-ebWX5%Evu7cvS8xuUmwlkOQ9Y!N{gElw6~UIMk&qQlGFfoG|0 zxkK6TEya>VM$5B7{}`Sw!5?jR=b_sol5E%=>#K6d>e$@62y5Kla5`iKMu*!<&*%N? z9j9YIavt_9)QMYSU6{-Zld6cCrl7Hs%Q9jiRYE6mqy?3cmR#hU%W_pjbgkzpH8I3p ztyE~Q-H1YYM^G(WN!SJjj6*y$NE?lIGY*9}Q2EAMQwB{cHRU2vB49>vcM43v3S=^g zWn^fg;#DxLDdSuk8KYCHER>w#WMDLCir|i>ap8XM(iGUnfb_wL;BX277J_S1391-` ztU!uIl+lmsbF)+%g-$E51eSvD z(_y^4Ecm`m)zc)26+}&2!Zc&9YXiNQ%jTh}wArUsq1qbdGB5)@SvfbeKH;sN|F=ZDcIKoi z%u1M5m<;=jv&0CMm6BK+x0IE%2$vKP3dx4@T^;B~wk>*-%k7>!Y`Npsf}Q$b0${boa~nSHF4Z!QA8Vsm`J0~V~%Vg};E^)>xyTlo( zbU_6P_A|{eEaZ$8!eEPZta~=Fmc^|XN7KNS(*I+ z8yF~X2Gv4IV2gFu2t|JN$RMiSr!#h_EdLugvBX~(nh9%%G2@593H-*OkbzZnGfqQJ z8$AdiDEGLyN4{8O*lIa+1}YEKdY=kRSiojs;S*%E0xU?Bp!pz3_kpK?BpwA)9>Aye zKf!SQ^mF(_Pu9mipT5b`&`jfXPJ_ei_Lm#3qp-Tv2z1$zCcIyS(y)lHcXbpOhYIw# zC3P&9>E$DHj0x3CurvUs8byIpZtOT3!FO*Jr>~&cRp(vD(VENa;;g{o_&HZY_|+t;zz6{ zd_SxBehcV4#PKoTznikK*imC3swSZOp5z*Ge-*+Z?~q?K#(1A}?a6ZG>D#Bug{gdd z)^)Ne Specifies if the auth method is a local only. Local auth methods are not - replicated nor (if a secondary) removed by replication. - :type local: bool - :param path: The path to mount the method on. If not provided, defaults to the value of the "method_type" - argument. - :type path: str | unicode - :param kwargs: All dicts are accepted and passed to vault. See your specific secret engine for details on which - extra key-word arguments you might want to pass. - :type kwargs: dict - :return: The response of the request. - :rtype: requests.Response - """ - if path is None: - path = method_type - - params = { - "type": method_type, - } - params.update( - utils.remove_nones( - { - "description": description, - "config": config, - "plugin_name": plugin_name, - "local": local, - } - ) - ) - params.update(kwargs) - api_path = utils.format_url("/v1/sys/auth/{path}", path=path) - return self._adapter.post(url=api_path, json=params) - - def disable_auth_method(self, path): - """Disable the auth method at the given auth path. - - Supported methods: - DELETE: /sys/auth/{path}. Produces: 204 (empty body) - - :param path: The path the method was mounted on. If not provided, defaults to the value of the "method_type" - argument. - :type path: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url("/v1/sys/auth/{path}", path=path) - return self._adapter.delete( - url=api_path, - ) - - def read_auth_method_tuning(self, path): - """Read the given auth path's configuration. - - This endpoint requires sudo capability on the final path, but the same functionality can be achieved without - sudo via sys/mounts/auth/[auth-path]/tune. - - Supported methods: - GET: /sys/auth/{path}/tune. Produces: 200 application/json - - :param path: The path the method was mounted on. If not provided, defaults to the value of the "method_type" - argument. - :type path: str | unicode - :return: The JSON response of the request. - :rtype: dict - """ - api_path = utils.format_url( - "/v1/sys/auth/{path}/tune", - path=path, - ) - return self._adapter.get( - url=api_path, - ) - - def tune_auth_method( - self, - path, - default_lease_ttl=None, - max_lease_ttl=None, - description=None, - audit_non_hmac_request_keys=None, - audit_non_hmac_response_keys=None, - listing_visibility=None, - passthrough_request_headers=None, - **kwargs - ): - """Tune configuration parameters for a given auth path. - - This endpoint requires sudo capability on the final path, but the same functionality can be achieved without - sudo via sys/mounts/auth/[auth-path]/tune. - - Supported methods: - POST: /sys/auth/{path}/tune. Produces: 204 (empty body) - - :param path: The path the method was mounted on. If not provided, defaults to the value of the "method_type" - argument. - :type path: str | unicode - :param default_lease_ttl: Specifies the default time-to-live. If set on a specific auth path, this overrides the - global default. - :type default_lease_ttl: int - :param max_lease_ttl: The maximum time-to-live. If set on a specific auth path, this overrides the global - default. - :type max_lease_ttl: int - :param description: Specifies the description of the mount. This overrides the current stored value, if any. - :type description: str | unicode - :param audit_non_hmac_request_keys: Specifies the list of keys that will not be HMAC'd by audit devices in the - request data object. - :type audit_non_hmac_request_keys: array - :param audit_non_hmac_response_keys: Specifies the list of keys that will not be HMAC'd by audit devices in the - response data object. - :type audit_non_hmac_response_keys: list - :param listing_visibility: Specifies whether to show this mount in the UI-specific listing endpoint. Valid - values are "unauth" or "". - :type listing_visibility: list - :param passthrough_request_headers: List of headers to whitelist and pass from the request to the backend. - :type passthrough_request_headers: list - :param kwargs: All dicts are accepted and passed to vault. See your specific secret engine for details on which - extra key-word arguments you might want to pass. - :type kwargs: dict - :return: The response of the request. - :rtype: requests.Response - """ - - if listing_visibility is not None and listing_visibility not in ["unauth", ""]: - error_msg = 'invalid listing_visibility argument provided: "{arg}"; valid values: "unauth" or ""'.format( - arg=listing_visibility, - ) - raise exceptions.ParamValidationError(error_msg) - - # All parameters are optional for this method. Until/unless we include input validation, we simply loop over the - # parameters and add which parameters are set. - optional_parameters = { - "default_lease_ttl": {}, - "max_lease_ttl": {}, - "description": {}, - "audit_non_hmac_request_keys": dict(comma_delimited_list=True), - "audit_non_hmac_response_keys": dict(comma_delimited_list=True), - "listing_visibility": {}, - "passthrough_request_headers": dict(comma_delimited_list=True), - } - params = {} - for optional_parameter, parameter_specification in optional_parameters.items(): - if locals().get(optional_parameter) is not None: - if parameter_specification.get("comma_delimited_list"): - argument = locals().get(optional_parameter) - validate_list_of_strings_param(optional_parameter, argument) - params[optional_parameter] = list_to_comma_delimited(argument) - else: - params[optional_parameter] = locals().get(optional_parameter) - params.update(kwargs) - api_path = utils.format_url("/v1/sys/auth/{path}/tune", path=path) - return self._adapter.post( - url=api_path, - json=params, - ) diff --git a/.venv/lib/python3.12/site-packages/hvac/api/system_backend/capabilities.py b/.venv/lib/python3.12/site-packages/hvac/api/system_backend/capabilities.py deleted file mode 100644 index 0d25c23..0000000 --- a/.venv/lib/python3.12/site-packages/hvac/api/system_backend/capabilities.py +++ /dev/null @@ -1,43 +0,0 @@ -from hvac.api.system_backend.system_backend_mixin import SystemBackendMixin - - -class Capabilities(SystemBackendMixin): - def get_capabilities(self, paths, token=None, accessor=None): - """Get the capabilities associated with a token. - - Supported methods: - POST: /sys/capabilities-self. Produces: 200 application/json - POST: /sys/capabilities. Produces: 200 application/json - POST: /sys/capabilities-accessor. Produces: 200 application/json - - :param paths: Paths on which capabilities are being queried. - :type paths: List[str] - :param token: Token for which capabilities are being queried. - :type token: str - :param accessor: Accessor of the token for which capabilities are being queried. - :type accessor: str - :return: The JSON response of the request. - :rtype: dict - """ - params = { - "paths": paths, - } - - if token and accessor: - raise ValueError("You can specify either token or accessor, not both.") - elif token: - # https://www.vaultproject.io/api/system/capabilities.html - params["token"] = token - api_path = "/v1/sys/capabilities" - elif accessor: - # https://www.vaultproject.io/api/system/capabilities-accessor.html - params["accessor"] = accessor - api_path = "/v1/sys/capabilities-accessor" - else: - # https://www.vaultproject.io/api/system/capabilities-self.html - api_path = "/v1/sys/capabilities-self" - - return self._adapter.post( - url=api_path, - json=params, - ) diff --git a/.venv/lib/python3.12/site-packages/hvac/api/system_backend/health.py b/.venv/lib/python3.12/site-packages/hvac/api/system_backend/health.py deleted file mode 100644 index b3e35c0..0000000 --- a/.venv/lib/python3.12/site-packages/hvac/api/system_backend/health.py +++ /dev/null @@ -1,83 +0,0 @@ -#!/usr/bin/env python -"""Support for "Health"-related System Backend Methods.""" -from hvac import exceptions, utils -from hvac.api.system_backend.system_backend_mixin import SystemBackendMixin - - -class Health(SystemBackendMixin): - """. - - Reference: https://www.vaultproject.io/api-docs/system/health - """ - - def read_health_status( - self, - standby_ok=None, - active_code=None, - standby_code=None, - dr_secondary_code=None, - performance_standby_code=None, - sealed_code=None, - uninit_code=None, - method="HEAD", - ): - """Read the health status of Vault. - - This matches the semantics of a Consul HTTP health check and provides a simple way to monitor the health of a - Vault instance. - - - :param standby_ok: Specifies if being a standby should still return the active status code instead of the - standby status code. This is useful when Vault is behind a non-configurable load balance that just wants a - 200-level response. - :type standby_ok: bool - :param active_code: The status code that should be returned for an active node. - :type active_code: int - :param standby_code: Specifies the status code that should be returned for a standby node. - :type standby_code: int - :param dr_secondary_code: Specifies the status code that should be returned for a DR secondary node. - :type dr_secondary_code: int - :param performance_standby_code: Specifies the status code that should be returned for a performance standby - node. - :type performance_standby_code: int - :param sealed_code: Specifies the status code that should be returned for a sealed node. - :type sealed_code: int - :param uninit_code: Specifies the status code that should be returned for a uninitialized node. - :type uninit_code: int - :param method: Supported methods: - HEAD: /sys/health. Produces: 000 (empty body) - GET: /sys/health. Produces: 000 application/json - :type method: str | unicode - :return: The JSON response of the request. - :rtype: requests.Response - """ - params = utils.remove_nones( - { - "standbyok": standby_ok, - "activecode": active_code, - "standbycode": standby_code, - "drsecondarycode": dr_secondary_code, - "performancestandbycode": performance_standby_code, - "sealedcode": sealed_code, - "uninitcode": uninit_code, - } - ) - - if method == "HEAD": - api_path = utils.format_url("/v1/sys/health") - return self._adapter.head( - url=api_path, - raise_exception=False, - ) - elif method == "GET": - api_path = utils.format_url("/v1/sys/health") - return self._adapter.get( - url=api_path, - params=params, - raise_exception=False, - ) - else: - error_message = '"method" parameter provided invalid value; HEAD or GET allowed, "{method}" provided'.format( - method=method - ) - raise exceptions.ParamValidationError(error_message) diff --git a/.venv/lib/python3.12/site-packages/hvac/api/system_backend/init.py b/.venv/lib/python3.12/site-packages/hvac/api/system_backend/init.py deleted file mode 100644 index 3c4e232..0000000 --- a/.venv/lib/python3.12/site-packages/hvac/api/system_backend/init.py +++ /dev/null @@ -1,146 +0,0 @@ -import warnings -from hvac.api.system_backend.system_backend_mixin import SystemBackendMixin -from hvac.exceptions import ParamValidationError - - -class Init(SystemBackendMixin): - def read_init_status(self): - """Read the initialization status of Vault. - - Supported methods: - GET: /sys/init. Produces: 200 application/json - - :return: The JSON response of the request. - :rtype: dict - """ - api_path = "/v1/sys/init" - return self._adapter.get( - url=api_path, - ) - - def is_initialized(self): - """Determine is Vault is initialized or not. - - :return: True if Vault is initialized, False otherwise. - :rtype: bool - """ - status = self.read_init_status() - return status["initialized"] - - def initialize( - self, - secret_shares=None, - secret_threshold=None, - pgp_keys=None, - root_token_pgp_key=None, - stored_shares=None, - recovery_shares=None, - recovery_threshold=None, - recovery_pgp_keys=None, - ): - """Initialize a new Vault. - - The Vault must not have been previously initialized. The recovery options, as well as the stored shares option, - are only available when using Vault HSM. - - Supported methods: - PUT: /sys/init. Produces: 200 application/json - - :param secret_shares: The number of shares to split the master key into. - :type secret_shares: int - :param secret_threshold: Specifies the number of shares required to reconstruct the master key. This must be - less than or equal secret_shares. If using Vault HSM with auto-unsealing, this value must be the same as - secret_shares, or omitted, depending on the version of Vault and the seal type. - :type secret_threshold: int - :param pgp_keys: List of PGP public keys used to encrypt the output unseal keys. - Ordering is preserved. The keys must be base64-encoded from their original binary representation. - The size of this array must be the same as secret_shares. - :type pgp_keys: list - :param root_token_pgp_key: Specifies a PGP public key used to encrypt the initial root token. The - key must be base64-encoded from its original binary representation. - :type root_token_pgp_key: str | unicode - :param stored_shares: Specifies the number of shares that should be encrypted by the HSM and - stored for auto-unsealing. Currently must be the same as secret_shares. - :type stored_shares: int - :param recovery_shares: Specifies the number of shares to split the recovery key into. - :type recovery_shares: int - :param recovery_threshold: Specifies the number of shares required to reconstruct the recovery - key. This must be less than or equal to recovery_shares. - :type recovery_threshold: int - :param recovery_pgp_keys: Specifies an array of PGP public keys used to encrypt the output - recovery keys. Ordering is preserved. The keys must be base64-encoded from their original binary - representation. The size of this array must be the same as recovery_shares. - :type recovery_pgp_keys: list - :return: The JSON response of the request. - :rtype: dict - """ - - # TODO(v3.0.0): remove this - if recovery_shares is None and secret_shares is None: - msg = ( - "The secret_shares parameter will default to None in hvac v3.0.0. " - "To use the old default with no warning, explicitly set this value to 5. " - "See https://github.com/hvac/hvac/issues/1030" - ) - warnings.warn( - message=msg, - category=DeprecationWarning, - stacklevel=2, - ) - secret_shares = 5 - - # TODO(v3.0.0): remove this - if recovery_threshold is None and secret_threshold is None: - msg = ( - "The secret_threshold parameter will default to None in hvac v3.0.0. " - "To use the old default with no warning, explicitly set this value to 3. " - "See https://github.com/hvac/hvac/issues/1030" - ) - warnings.warn( - message=msg, - category=DeprecationWarning, - stacklevel=2, - ) - secret_threshold = 3 - - params = { - "secret_shares": secret_shares, - "secret_threshold": secret_threshold, - "root_token_pgp_key": root_token_pgp_key, - } - - if pgp_keys is not None and secret_shares is not None: - if len(pgp_keys) != secret_shares: - raise ParamValidationError( - "length of pgp_keys list argument must equal secret_shares value" - ) - params["pgp_keys"] = pgp_keys - - if stored_shares is not None and secret_shares is not None: - if stored_shares != secret_shares: - raise ParamValidationError( - "value for stored_shares argument must equal secret_shares argument" - ) - params["stored_shares"] = stored_shares - - if recovery_shares is not None: - params["recovery_shares"] = recovery_shares - - if recovery_threshold is not None: - if recovery_threshold > recovery_shares: - error_msg = "value for recovery_threshold argument must be less than or equal to recovery_shares argument" - raise ParamValidationError(error_msg) - params["recovery_threshold"] = recovery_threshold - - if recovery_pgp_keys is not None: - if len(recovery_pgp_keys) != recovery_shares: - raise ParamValidationError( - "length of recovery_pgp_keys list argument must equal recovery_shares value" - ) - params["recovery_pgp_keys"] = recovery_pgp_keys - - api_path = "/v1/sys/init" - return self._adapter.put( - url=api_path, - json=params, - ) diff --git a/.venv/lib/python3.12/site-packages/hvac/api/system_backend/key.py b/.venv/lib/python3.12/site-packages/hvac/api/system_backend/key.py deleted file mode 100644 index 16b86e7..0000000 --- a/.venv/lib/python3.12/site-packages/hvac/api/system_backend/key.py +++ /dev/null @@ -1,407 +0,0 @@ -from hvac.api.system_backend.system_backend_mixin import SystemBackendMixin -from hvac.exceptions import ParamValidationError - - -class Key(SystemBackendMixin): - def read_root_generation_progress(self): - """Read the configuration and process of the current root generation attempt. - - Supported methods: - GET: /sys/generate-root/attempt. Produces: 200 application/json - - :return: The JSON response of the request. - :rtype: dict - """ - api_path = "/v1/sys/generate-root/attempt" - return self._adapter.get( - url=api_path, - ) - - def start_root_token_generation(self, otp=None, pgp_key=None): - """Initialize a new root generation attempt. - - Only a single root generation attempt can take place at a time. One (and only one) of otp or pgp_key are - required. - - Supported methods: - PUT: /sys/generate-root/attempt. Produces: 200 application/json - - :param otp: Specifies a base64-encoded 16-byte value. The raw bytes of the token will be XOR'd with this value - before being returned to the final unseal key provider. - :type otp: str | unicode - :param pgp_key: Specifies a base64-encoded PGP public key. The raw bytes of the token will be encrypted with - this value before being returned to the final unseal key provider. - :type pgp_key: str | unicode - :return: The JSON response of the request. - :rtype: dict - """ - params = {} - if otp is not None and pgp_key is not None: - raise ParamValidationError( - "one (and only one) of otp or pgp_key arguments are required" - ) - if otp is not None: - params["otp"] = otp - if pgp_key is not None: - params["pgp_key"] = pgp_key - - api_path = "/v1/sys/generate-root/attempt" - return self._adapter.put(url=api_path, json=params) - - def generate_root(self, key, nonce): - """Enter a single master key share to progress the root generation attempt. - - If the threshold number of master key shares is reached, Vault will complete the root generation and issue the - new token. Otherwise, this API must be called multiple times until that threshold is met. The attempt nonce must - be provided with each call. - - Supported methods: - PUT: /sys/generate-root/update. Produces: 200 application/json - - :param key: Specifies a single master key share. - :type key: str | unicode - :param nonce: The nonce of the attempt. - :type nonce: str | unicode - :return: The JSON response of the request. - :rtype: dict - """ - params = { - "key": key, - "nonce": nonce, - } - api_path = "/v1/sys/generate-root/update" - return self._adapter.put( - url=api_path, - json=params, - ) - - def cancel_root_generation(self): - """Cancel any in-progress root generation attempt. - - This clears any progress made. This must be called to change the OTP or PGP key being used. - - Supported methods: - DELETE: /sys/generate-root/attempt. Produces: 204 (empty body) - - :return: The response of the request. - :rtype: request.Response - """ - api_path = "/v1/sys/generate-root/attempt" - return self._adapter.delete( - url=api_path, - ) - - def get_encryption_key_status(self): - """Read information about the current encryption key used by Vault. - - Supported methods: - GET: /sys/key-status. Produces: 200 application/json - - :return: JSON response with information regarding the current encryption key used by Vault. - :rtype: dict - """ - api_path = "/v1/sys/key-status" - return self._adapter.get( - url=api_path, - ) - - def rotate_encryption_key(self): - """Trigger a rotation of the backend encryption key. - - This is the key that is used to encrypt data written to the storage backend, and is not provided to operators. - This operation is done online. Future values are encrypted with the new key, while old values are decrypted with - previous encryption keys. - - This path requires sudo capability in addition to update. - - Supported methods: - PUT: /sys/rorate. Produces: 204 (empty body) - - :return: The response of the request. - :rtype: requests.Response - """ - api_path = "/v1/sys/rotate" - return self._adapter.put( - url=api_path, - ) - - def read_rekey_progress(self, recovery_key=False): - """Read the configuration and progress of the current rekey attempt. - - Supported methods: - GET: /sys/rekey-recovery-key/init. Produces: 200 application/json - GET: /sys/rekey/init. Produces: 200 application/json - - :param recovery_key: If true, send requests to "rekey-recovery-key" instead of "rekey" api path. - :type recovery_key: bool - :return: The JSON response of the request. - :rtype: requests.Response - """ - api_path = "/v1/sys/rekey/init" - if recovery_key: - api_path = "/v1/sys/rekey-recovery-key/init" - return self._adapter.get( - url=api_path, - ) - - def start_rekey( - self, - secret_shares=5, - secret_threshold=3, - pgp_keys=None, - backup=False, - require_verification=False, - recovery_key=False, - ): - """Initializes a new rekey attempt. - - Only a single recovery key rekeyattempt can take place at a time, and changing the parameters of a rekey - requires canceling and starting a new rekey, which will also provide a new nonce. - - Supported methods: - PUT: /sys/rekey/init. Produces: 204 (empty body) - PUT: /sys/rekey-recovery-key/init. Produces: 204 (empty body) - - :param secret_shares: Specifies the number of shares to split the master key into. - :type secret_shares: int - :param secret_threshold: Specifies the number of shares required to reconstruct the master key. This must be - less than or equal to secret_shares. - :type secret_threshold: int - :param pgp_keys: Specifies an array of PGP public keys used to encrypt the output unseal keys. Ordering is - preserved. The keys must be base64-encoded from their original binary representation. The size of this array - must be the same as secret_shares. - :type pgp_keys: list - :param backup: Specifies if using PGP-encrypted keys, whether Vault should also store a plaintext backup of the - PGP-encrypted keys at core/unseal-keys-backup in the physical storage backend. These can then be retrieved - and removed via the sys/rekey/backup endpoint. - :type backup: bool - :param require_verification: This turns on verification functionality. When verification is turned on, after - successful authorization with the current unseal keys, the new unseal keys are returned but the master key - is not actually rotated. The new keys must be provided to authorize the actual rotation of the master key. - This ensures that the new keys have been successfully saved and protects against a risk of the keys being - lost after rotation but before they can be persisted. This can be used with without pgp_keys, and when used - with it, it allows ensuring that the returned keys can be successfully decrypted before committing to the - new shares, which the backup functionality does not provide. - :param recovery_key: If true, send requests to "rekey-recovery-key" instead of "rekey" api path. - :type recovery_key: bool - :type require_verification: bool - :return: The JSON dict of the response. - :rtype: dict | request.Response - """ - params = { - "secret_shares": secret_shares, - "secret_threshold": secret_threshold, - "require_verification": require_verification, - } - - if pgp_keys: - if len(pgp_keys) != secret_shares: - raise ParamValidationError( - "length of pgp_keys argument must equal secret shares value" - ) - - params["pgp_keys"] = pgp_keys - params["backup"] = backup - - api_path = "/v1/sys/rekey/init" - if recovery_key: - api_path = "/v1/sys/rekey-recovery-key/init" - return self._adapter.put( - url=api_path, - json=params, - ) - - def cancel_rekey(self, recovery_key=False): - """Cancel any in-progress rekey. - - This clears the rekey settings as well as any progress made. This must be called to change the parameters of the - rekey. - - Note: Verification is still a part of a rekey. If rekeying is canceled during the verification flow, the current - unseal keys remain valid. - - Supported methods: - DELETE: /sys/rekey/init. Produces: 204 (empty body) - DELETE: /sys/rekey-recovery-key/init. Produces: 204 (empty body) - - :param recovery_key: If true, send requests to "rekey-recovery-key" instead of "rekey" api path. - :type recovery_key: bool - :return: The response of the request. - :rtype: requests.Response - """ - api_path = "/v1/sys/rekey/init" - if recovery_key: - api_path = "/v1/sys/rekey-recovery-key/init" - return self._adapter.delete( - url=api_path, - ) - - def rekey(self, key, nonce=None, recovery_key=False): - """Enter a single recovery key share to progress the rekey of the Vault. - - If the threshold number of 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 nonce operation must be provided with each - call. - - Supported methods: - PUT: /sys/rekey/update. Produces: 200 application/json - PUT: /sys/rekey-recovery-key/update. Produces: 200 application/json - - :param key: Specifies a single recovery share key. - :type key: str | unicode - :param nonce: Specifies the nonce of the rekey operation. - :type nonce: str | unicode - :param recovery_key: If true, send requests to "rekey-recovery-key" instead of "rekey" api path. - :type recovery_key: bool - :return: The JSON response of the request. - :rtype: dict - """ - params = { - "key": key, - } - - if nonce is not None: - params["nonce"] = nonce - - api_path = "/v1/sys/rekey/update" - if recovery_key: - api_path = "/v1/sys/rekey-recovery-key/update" - return self._adapter.put( - url=api_path, - json=params, - ) - - def rekey_multi(self, keys, nonce=None, recovery_key=False): - """Enter multiple recovery key shares to progress the rekey of the Vault. - - If the threshold number of recovery key shares is reached, Vault will complete the rekey. - - :param keys: Specifies multiple recovery share keys. - :type keys: list - :param nonce: Specifies the nonce of the rekey operation. - :type nonce: str | unicode - :param recovery_key: If true, send requests to "rekey-recovery-key" instead of "rekey" api path. - :type recovery_key: bool - :return: The last response of the rekey request. - :rtype: response.Request - """ - result = None - - for key in keys: - result = self.rekey( - key=key, - nonce=nonce, - recovery_key=recovery_key, - ) - if result.get("complete"): - break - - return result - - def read_backup_keys(self, recovery_key=False): - """Retrieve the backup copy of PGP-encrypted unseal keys. - - The returned value is the nonce of the rekey operation and a map of PGP key fingerprint to hex-encoded - PGP-encrypted key. - - Supported methods: - PUT: /sys/rekey/backup. Produces: 200 application/json - PUT: /sys/rekey-recovery-key/backup. Produces: 200 application/json - - :param recovery_key: If true, send requests to "rekey-recovery-key" instead of "rekey" api path. - :type recovery_key: bool - :return: The JSON response of the request. - :rtype: dict - """ - api_path = "/v1/sys/rekey/backup" - if recovery_key: - api_path = "/v1/sys/rekey/recovery-key-backup" - 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 --git a/.venv/lib/python3.12/site-packages/hvac/api/system_backend/leader.py b/.venv/lib/python3.12/site-packages/hvac/api/system_backend/leader.py deleted file mode 100644 index 9366bc8..0000000 --- a/.venv/lib/python3.12/site-packages/hvac/api/system_backend/leader.py +++ /dev/null @@ -1,35 +0,0 @@ -from hvac.api.system_backend.system_backend_mixin import SystemBackendMixin - - -class Leader(SystemBackendMixin): - def read_leader_status(self): - """Read the high availability status and current leader instance of Vault. - - Supported methods: - GET: /sys/leader. Produces: 200 application/json - - :return: The JSON response of the request. - :rtype: dict - """ - api_path = "/v1/sys/leader" - return self._adapter.get( - url=api_path, - ) - - def step_down(self): - """Force the node to give up active status. - - When executed against a non-active node, i.e. a standby or performance - standby node, the request will be forwarded to the active node. - Note that the node will sleep for ten seconds before attempting to grab - the active lock again, but if no standby nodes grab the active lock in - the interim, the same node may become the active node again. Requires a - token with root policy or sudo capability on the path. - - :return: The JSON response of the request. - :rtype: dict - """ - api_path = "/v1/sys/step-down" - return self._adapter.put( - url=api_path, - ) diff --git a/.venv/lib/python3.12/site-packages/hvac/api/system_backend/lease.py b/.venv/lib/python3.12/site-packages/hvac/api/system_backend/lease.py deleted file mode 100644 index 6df50c5..0000000 --- a/.venv/lib/python3.12/site-packages/hvac/api/system_backend/lease.py +++ /dev/null @@ -1,131 +0,0 @@ -from hvac import utils -from hvac.api.system_backend.system_backend_mixin import SystemBackendMixin - - -class Lease(SystemBackendMixin): - def read_lease(self, lease_id): - """Retrieve lease metadata. - - Supported methods: - PUT: /sys/leases/lookup. Produces: 200 application/json - - :param lease_id: the ID of the lease to lookup. - :type lease_id: str | unicode - :return: Parsed JSON response from the leases PUT request - :rtype: dict. - """ - params = {"lease_id": lease_id} - api_path = "/v1/sys/leases/lookup" - return self._adapter.put(url=api_path, json=params) - - def list_leases(self, prefix): - """Retrieve a list of lease ids. - - Supported methods: - LIST: /sys/leases/lookup/{prefix}. Produces: 200 application/json - - :param prefix: Lease prefix to filter list by. - :type prefix: str | unicode - :return: The JSON response of the request. - :rtype: dict - """ - api_path = utils.format_url("/v1/sys/leases/lookup/{prefix}", prefix=prefix) - return self._adapter.list( - url=api_path, - ) - - def renew_lease(self, lease_id, increment=None): - """Renew a lease, requesting to extend the lease. - - Supported methods: - PUT: /sys/leases/renew. Produces: 200 application/json - - :param lease_id: The ID of the lease to extend. - :type lease_id: str | unicode - :param increment: The requested amount of time (in seconds) to extend the lease. - :type increment: int - :return: The JSON response of the request - :rtype: dict - """ - params = { - "lease_id": lease_id, - "increment": increment, - } - api_path = "/v1/sys/leases/renew" - return self._adapter.put( - url=api_path, - json=params, - ) - - def revoke_lease(self, lease_id): - """Revoke a lease immediately. - - Supported methods: - PUT: /sys/leases/revoke. Produces: 204 (empty body) - - :param lease_id: Specifies the ID of the lease to revoke. - :type lease_id: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - params = { - "lease_id": lease_id, - } - api_path = "/v1/sys/leases/revoke" - return self._adapter.put( - url=api_path, - json=params, - ) - - def revoke_prefix(self, prefix): - """Revoke all secrets (via a lease ID prefix) or tokens (via the tokens' path property) generated under a given - prefix immediately. - - This requires sudo capability and access to it should be tightly controlled as it can be used to revoke very - large numbers of secrets/tokens at once. - - Supported methods: - PUT: /sys/leases/revoke-prefix/{prefix}. Produces: 204 (empty body) - - - :param prefix: The prefix to revoke. - :type prefix: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - params = { - "prefix": prefix, - } - api_path = utils.format_url( - "/v1/sys/leases/revoke-prefix/{prefix}", prefix=prefix - ) - return self._adapter.put( - url=api_path, - json=params, - ) - - def revoke_force(self, prefix): - """Revoke all secrets or tokens generated under a given prefix immediately. - - Unlike revoke_prefix, this path ignores backend errors encountered during revocation. This is potentially very - dangerous and should only be used in specific emergency situations where errors in the backend or the connected - backend service prevent normal revocation. - - Supported methods: - PUT: /sys/leases/revoke-force/{prefix}. Produces: 204 (empty body) - - :param prefix: The prefix to revoke. - :type prefix: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - params = { - "prefix": prefix, - } - api_path = utils.format_url( - "/v1/sys/leases/revoke-force/{prefix}", prefix=prefix - ) - return self._adapter.put( - url=api_path, - json=params, - ) diff --git a/.venv/lib/python3.12/site-packages/hvac/api/system_backend/mount.py b/.venv/lib/python3.12/site-packages/hvac/api/system_backend/mount.py deleted file mode 100644 index 6cd34b0..0000000 --- a/.venv/lib/python3.12/site-packages/hvac/api/system_backend/mount.py +++ /dev/null @@ -1,239 +0,0 @@ -from hvac import utils -from hvac.api.system_backend.system_backend_mixin import SystemBackendMixin - - -class Mount(SystemBackendMixin): - def list_mounted_secrets_engines(self): - """Lists all the mounted secrets engines. - - Supported methods: - POST: /sys/mounts. Produces: 200 application/json - - :return: JSON response of the request. - :rtype: dict - """ - return self._adapter.get("/v1/sys/mounts") - - def retrieve_mount_option(self, mount_point, option_name, default_value=None): - secrets_engine_path = f"{mount_point}/" - secrets_engines_list = self.list_mounted_secrets_engines()["data"] - mount_options = secrets_engines_list[secrets_engine_path].get("options") - if mount_options is None: - return default_value - - return mount_options.get(option_name, default_value) - - def enable_secrets_engine( - self, - backend_type, - path=None, - description=None, - config=None, - plugin_name=None, - options=None, - local=False, - seal_wrap=False, - **kwargs, - ): - """Enable a new secrets engine at the given path. - - Supported methods: - POST: /sys/mounts/{path}. Produces: 204 (empty body) - - :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 "backend_type" - argument. - :type path: str | unicode - :param description: A human-friendly description of the mount. - :type description: str | unicode - :param config: Configuration options for this mount. These are the possible values: - - * **default_lease_ttl**: The default lease duration, specified as a string duration like "5s" or "30m". - * **max_lease_ttl**: The maximum lease duration, specified as a string duration like "5s" or "30m". - * **force_no_cache**: Disable caching. - * **plugin_name**: The name of the plugin in the plugin catalog to use. - * **audit_non_hmac_request_keys**: Comma-separated list of keys that will not be HMAC'd by audit devices in - the request data object. - * **audit_non_hmac_response_keys**: Comma-separated list of keys that will not be HMAC'd by audit devices in - the response data object. - * **listing_visibility**: Specifies whether to show this mount in the UI-specific listing endpoint. ("unauth" or "hidden") - * **passthrough_request_headers**: Comma-separated list of headers to whitelist and pass from the request to - the backend. - :type config: dict - :param options: Specifies mount type specific options that are passed to the backend. - - * **version**: The version of the KV to mount. Set to "2" for mount KV v2. - :type options: dict - :param plugin_name: Specifies the name of the plugin to use based from the name in the plugin catalog. Applies only to plugin backends. - :type plugin_name: str | unicode - :param local: Specifies if the auth method is a local only. Local auth methods are not - replicated nor (if a secondary) removed by replication. - :type local: bool - :param seal_wrap: Enable seal wrapping for the mount. - :type seal_wrap: bool - :param kwargs: All dicts are accepted and passed to vault. See your specific secret engine for details on which - extra key-word arguments you might want to pass. - :type kwargs: dict - :return: The response of the request. - :rtype: requests.Response - """ - if path is None: - path = backend_type - - params = { - "type": backend_type, - "description": description, - "config": config, - "options": options, - "plugin_name": plugin_name, - "local": local, - "seal_wrap": seal_wrap, - } - - params.update(kwargs) - - api_path = utils.format_url("/v1/sys/mounts/{path}", path=path) - return self._adapter.post( - url=api_path, - json=params, - ) - - def disable_secrets_engine(self, path): - """Disable the mount point specified by the provided path. - - Supported methods: - DELETE: /sys/mounts/{path}. Produces: 204 (empty body) - - :param path: Specifies the path where the secrets engine will be mounted. This is specified as part of the URL. - :type path: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url("/v1/sys/mounts/{path}", path=path) - return self._adapter.delete( - url=api_path, - ) - - def read_mount_configuration(self, path): - """Read the given mount's configuration. - - Unlike the mounts endpoint, this will return the current time in seconds for each TTL, which may be the system - default or a mount-specific value. - - Supported methods: - GET: /sys/mounts/{path}/tune. Produces: 200 application/json - - :param path: Specifies the path where the secrets engine will be mounted. This is specified as part of the URL. - :type path: str | unicode - :return: The JSON response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url("/v1/sys/mounts/{path}/tune", path=path) - return self._adapter.get( - url=api_path, - ) - - def tune_mount_configuration( - self, - path, - default_lease_ttl=None, - max_lease_ttl=None, - description=None, - audit_non_hmac_request_keys=None, - audit_non_hmac_response_keys=None, - listing_visibility=None, - passthrough_request_headers=None, - options=None, - force_no_cache=None, - **kwargs, - ): - """Tune configuration parameters for a given mount point. - - Supported methods: - POST: /sys/mounts/{path}/tune. Produces: 204 (empty body) - - :param path: Specifies the path where the secrets engine will be mounted. This is specified as part of the URL. - :type path: str | unicode - :param mount_point: The path the associated secret backend is mounted - :type mount_point: str - :param description: Specifies the description of the mount. This overrides the current stored value, if any. - :type description: str - :param default_lease_ttl: Default time-to-live. This overrides the global default. A value of 0 is equivalent to - the system default TTL - :type default_lease_ttl: int - :param max_lease_ttl: Maximum time-to-live. This overrides the global default. A value of 0 are equivalent and - set to the system max TTL. - :type max_lease_ttl: int - :param audit_non_hmac_request_keys: Specifies the comma-separated list of keys that will not be HMAC'd by audit - devices in the request data object. - :type audit_non_hmac_request_keys: list - :param audit_non_hmac_response_keys: Specifies the comma-separated list of keys that will not be HMAC'd by audit - devices in the response data object. - :type audit_non_hmac_response_keys: list - :param listing_visibility: Specifies whether to show this mount in the UI-specific listing endpoint. Valid - values are "unauth" or "". - :type listing_visibility: str - :param passthrough_request_headers: Comma-separated list of headers to whitelist and pass from the request - to the backend. - :type passthrough_request_headers: str - :param options: Specifies mount type specific options that are passed to the backend. - - * **version**: The version of the KV to mount. Set to "2" for mount KV v2. - :type options: dict - :param force_no_cache: Disable caching. - :type force_no_cache: bool - :param kwargs: All dicts are accepted and passed to vault. See your specific secret engine for details on which - extra key-word arguments you might want to pass. - :type kwargs: dict - :return: The response from the request. - :rtype: request.Response - """ - # All parameters are optional for this method. Until/unless we include input validation, we simply loop over the - # parameters and add which parameters are set. - optional_parameters = [ - "default_lease_ttl", - "max_lease_ttl", - "description", - "audit_non_hmac_request_keys", - "audit_non_hmac_response_keys", - "listing_visibility", - "passthrough_request_headers", - "force_no_cache", - "options", - ] - params = {} - for optional_parameter in optional_parameters: - if locals().get(optional_parameter) is not None: - params[optional_parameter] = locals().get(optional_parameter) - - params.update(kwargs) - - api_path = utils.format_url("/v1/sys/mounts/{path}/tune", path=path) - return self._adapter.post( - url=api_path, - json=params, - ) - - def move_backend(self, from_path, to_path): - """Move an already-mounted backend to a new mount point. - - Supported methods: - POST: /sys/remount. Produces: 204 (empty body) - - :param from_path: Specifies the previous mount point. - :type from_path: str | unicode - :param to_path: Specifies the new destination mount point. - :type to_path: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - params = { - "from": from_path, - "to": to_path, - } - api_path = "/v1/sys/remount" - return self._adapter.post( - url=api_path, - json=params, - ) diff --git a/.venv/lib/python3.12/site-packages/hvac/api/system_backend/namespace.py b/.venv/lib/python3.12/site-packages/hvac/api/system_backend/namespace.py deleted file mode 100644 index d69c76a..0000000 --- a/.venv/lib/python3.12/site-packages/hvac/api/system_backend/namespace.py +++ /dev/null @@ -1,46 +0,0 @@ -from hvac import utils -from hvac.api.system_backend.system_backend_mixin import SystemBackendMixin - - -class Namespace(SystemBackendMixin): - def create_namespace(self, path): - """Create a namespace at the given path. - - Supported methods: - POST: /sys/namespaces/{path}. Produces: 200 application/json - - :return: The response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url("/v1/sys/namespaces/{path}", path=path) - return self._adapter.post( - url=api_path, - ) - - def list_namespaces(self): - """Lists all the namespaces. - - Supported methods: - LIST: /sys/namespaces. Produces: 200 application/json - - :return: The JSON response of the request. - :rtype: dict - """ - api_path = "/v1/sys/namespaces/" - return self._adapter.list( - url=api_path, - ) - - def delete_namespace(self, path): - """Delete a namespaces. You cannot delete a namespace with existing child namespaces. - - Supported methods: - DELETE: /sys/namespaces. Produces: 204 (empty body) - - :return: The response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url("/v1/sys/namespaces/{path}", path=path) - return self._adapter.delete( - url=api_path, - ) diff --git a/.venv/lib/python3.12/site-packages/hvac/api/system_backend/policies.py b/.venv/lib/python3.12/site-packages/hvac/api/system_backend/policies.py deleted file mode 100644 index 8551a5c..0000000 --- a/.venv/lib/python3.12/site-packages/hvac/api/system_backend/policies.py +++ /dev/null @@ -1,236 +0,0 @@ -import json - -from hvac import utils -from hvac.api.system_backend.system_backend_mixin import SystemBackendMixin - - -class Policies(SystemBackendMixin): - def list_acl_policies(self): - """List all configured acl policies. - - Supported methods: - GET: /sys/policies/acl. Produces: 200 application/json - - :return: The JSON response of the request. - :rtype: dict - """ - api_path = "/v1/sys/policies/acl" - return self._adapter.list( - url=api_path, - ) - - def read_acl_policy(self, name): - """Retrieve the policy body for the named acl policy. - - Supported methods: - GET: /sys/policies/acl/{name}. Produces: 200 application/json - - :param name: The name of the acl policy to retrieve. - :type name: str | unicode - :return: The response of the request - :rtype: dict - """ - api_path = utils.format_url("/v1/sys/policies/acl/{name}", name=name) - return self._adapter.get( - url=api_path, - ) - - def create_or_update_acl_policy(self, name, policy, pretty_print=True): - """Add a new or update an existing acl policy. - - Once a policy is updated, it takes effect immediately to all associated users. - - Supported methods: - PUT: /sys/policies/acl/{name}. Produces: 204 (empty body) - - :param name: Specifies the name of the policy to create. - :type name: str | unicode - :param policy: Specifies the policy to create or update. - :type policy: str | unicode | dict - :param pretty_print: If True, and provided a dict for the policy argument, send the policy JSON to Vault with - "pretty" formatting. - :type pretty_print: bool - :return: The response of the request. - :rtype: requests.Response - """ - if isinstance(policy, dict): - if pretty_print: - policy = json.dumps(policy, indent=4, sort_keys=True) - else: - policy = json.dumps(policy) - params = { - "policy": policy, - } - api_path = utils.format_url(f"/v1/sys/policies/acl/{name}", name=name) - return self._adapter.put( - url=api_path, - json=params, - ) - - def delete_acl_policy(self, name): - """Delete the acl policy with the given name. - - This will immediately affect all users associated with this policy. - - Supported methods: - DELETE: /sys/policies/acl/{name}. Produces: 204 (empty body) - - :param name: Specifies the name of the policy to delete. - :type name: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url("/v1/sys/policies/acl/{name}", name=name) - return self._adapter.delete( - url=api_path, - ) - - def list_rgp_policies(self): - """List all configured rgp policies. - - Supported methods: - GET: /sys/policies/rgp. Produces: 200 application/json - - :return: The JSON response of the request. - :rtype: dict - """ - api_path = "/v1/sys/policies/rgp" - return self._adapter.list( - url=api_path, - ) - - def read_rgp_policy(self, name): - """Retrieve the policy body for the named rgp policy. - - Supported methods: - GET: /sys/policies/rgp/{name}. Produces: 200 application/json - - :param name: The name of the rgp policy to retrieve. - :type name: str | unicode - :return: The response of the request - :rtype: dict - """ - api_path = utils.format_url("/v1/sys/policies/rgp/{name}", name=name) - return self._adapter.get( - url=api_path, - ) - - def create_or_update_rgp_policy(self, name, policy, enforcement_level): - """Add a new or update an existing rgp policy. - - Once a policy is updated, it takes effect immediately to all associated users. - - Supported methods: - PUT: /sys/policies/rgp/{name}. Produces: 204 (empty body) - - :param name: Specifies the name of the policy to create. - :type name: str | unicode - :param policy: Specifies the policy to create or update. - :type policy: str | unicode - :param enforcement_level: Specifies the enforcement level to use. This must be one of advisory, soft-mandatory, or hard-mandatory - :type enforcement_level: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - params = {"policy": policy, "enforcement_level": enforcement_level} - api_path = utils.format_url(f"/v1/sys/policies/rgp/{name}", name=name) - return self._adapter.put( - url=api_path, - json=params, - ) - - def delete_rgp_policy(self, name): - """Delete the rgp policy with the given name. - - This will immediately affect all users associated with this policy. - - Supported methods: - DELETE: /sys/policies/rgp/{name}. Produces: 204 (empty body) - - :param name: Specifies the name of the policy to delete. - :type name: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url("/v1/sys/policies/rgp/{name}", name=name) - return self._adapter.delete( - url=api_path, - ) - - def list_egp_policies(self): - """List all configured egp policies. - - Supported methods: - GET: /sys/policies/egp. Produces: 200 application/json - - :return: The JSON response of the request. - :rtype: dict - """ - api_path = "/v1/sys/policies/egp" - return self._adapter.list( - url=api_path, - ) - - def read_egp_policy(self, name): - """Retrieve the policy body for the named egp policy. - - Supported methods: - GET: /sys/policies/egp/{name}. Produces: 200 application/json - - :param name: The name of the egp policy to retrieve. - :type name: str | unicode - :return: The response of the request - :rtype: dict - """ - api_path = utils.format_url("/v1/sys/policies/egp/{name}", name=name) - return self._adapter.get( - url=api_path, - ) - - def create_or_update_egp_policy(self, name, policy, enforcement_level, paths): - """Add a new or update an existing egp policy. - - Once a policy is updated, it takes effect immediately to all associated users. - - Supported methods: - PUT: /sys/policies/egp/{name}. Produces: 204 (empty body) - - :param name: Specifies the name of the policy to create. - :type name: str | unicode - :param policy: Specifies the policy to create or update. - :type policy: str | unicode - :param enforcement_level: Specifies the enforcement level to use. This must be one of advisory, soft-mandatory, or hard-mandatory - :type enforcement_level: str | unicode - :param paths: Specifies the paths on which this EGP should be applied. - :type paths: list - :return: The response of the request. - :rtype: requests.Response - """ - params = { - "policy": policy, - "enforcement_level": enforcement_level, - "paths": paths, - } - api_path = utils.format_url(f"/v1/sys/policies/egp/{name}", name=name) - return self._adapter.put( - url=api_path, - json=params, - ) - - def delete_egp_policy(self, name): - """Delete the egp policy with the given name. - - This will immediately affect all users associated with this policy. - - Supported methods: - DELETE: /sys/policies/egp/{name}. Produces: 204 (empty body) - - :param name: Specifies the name of the policy to delete. - :type name: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url("/v1/sys/policies/egp/{name}", name=name) - return self._adapter.delete( - url=api_path, - ) diff --git a/.venv/lib/python3.12/site-packages/hvac/api/system_backend/policy.py b/.venv/lib/python3.12/site-packages/hvac/api/system_backend/policy.py deleted file mode 100644 index b27441c..0000000 --- a/.venv/lib/python3.12/site-packages/hvac/api/system_backend/policy.py +++ /dev/null @@ -1,86 +0,0 @@ -import json - -from hvac import utils -from hvac.api.system_backend.system_backend_mixin import SystemBackendMixin - - -class Policy(SystemBackendMixin): - def list_policies(self): - """List all configured policies. - - Supported methods: - GET: /sys/policy. Produces: 200 application/json - - :return: The JSON response of the request. - :rtype: dict - """ - api_path = "/v1/sys/policy" - return self._adapter.get( - url=api_path, - ) - - def read_policy(self, name): - """Retrieve the policy body for the named policy. - - Supported methods: - GET: /sys/policy/{name}. Produces: 200 application/json - - :param name: The name of the policy to retrieve. - :type name: str | unicode - :return: The response of the request - :rtype: dict - """ - api_path = utils.format_url("/v1/sys/policy/{name}", name=name) - return self._adapter.get( - url=api_path, - ) - - def create_or_update_policy(self, name, policy, pretty_print=True): - """Add a new or update an existing policy. - - Once a policy is updated, it takes effect immediately to all associated users. - - Supported methods: - PUT: /sys/policy/{name}. Produces: 204 (empty body) - - :param name: Specifies the name of the policy to create. - :type name: str | unicode - :param policy: Specifies the policy document. - :type policy: str | unicode | dict - :param pretty_print: If True, and provided a dict for the policy argument, send the policy JSON to Vault with - "pretty" formatting. - :type pretty_print: bool - :return: The response of the request. - :rtype: requests.Response - """ - if isinstance(policy, dict): - if pretty_print: - policy = json.dumps(policy, indent=4, sort_keys=True) - else: - policy = json.dumps(policy) - params = { - "policy": policy, - } - api_path = utils.format_url("/v1/sys/policy/{name}", name=name) - return self._adapter.put( - url=api_path, - json=params, - ) - - def delete_policy(self, name): - """Delete the policy with the given name. - - This will immediately affect all users associated with this policy. - - Supported methods: - DELETE: /sys/policy/{name}. Produces: 204 (empty body) - - :param name: Specifies the name of the policy to delete. - :type name: str | unicode - :return: The response of the request. - :rtype: requests.Response - """ - api_path = utils.format_url("/v1/sys/policy/{name}", name=name) - return self._adapter.delete( - url=api_path, - ) diff --git a/.venv/lib/python3.12/site-packages/hvac/api/system_backend/quota.py b/.venv/lib/python3.12/site-packages/hvac/api/system_backend/quota.py deleted file mode 100644 index 40228e3..0000000 --- a/.venv/lib/python3.12/site-packages/hvac/api/system_backend/quota.py +++ /dev/null @@ -1,101 +0,0 @@ -from hvac import utils -from hvac.api.system_backend.system_backend_mixin import SystemBackendMixin - - -class Quota(SystemBackendMixin): - def read_quota(self, name): - """Read quota. Only works when calling on the root namespace. - - Supported methods: - GET: /sys/quotas/rate-limit/:name. Produces: 200 application/json - - :param name: the name of the quota to look up. - :type name: str | unicode - :return: JSON response from API request. - :rtype: requests.Response - """ - api_path = utils.format_url(f"/v1/sys/quotas/rate-limit/{name}", name=name) - return self._adapter.get(url=api_path) - - def list_quotas(self): - """Retrieve a list of quotas by name. Only works when calling on the root namespace. - - Supported methods: - LIST: /sys/quotas/rate-limit. Produces: 200 application/json - - :return: JSON response from API request. - :rtype: requests.Response - """ - api_path = "/v1/sys/quotas/rate-limit" - return self._adapter.list( - url=api_path, - ) - - def create_or_update_quota( - self, - name, - rate, - path=None, - interval=None, - block_interval=None, - role=None, - rate_limit_type=None, - inheritable=None, - ): - """Create quota if it doesn't exist or update if already created. Only works when calling on the root namespace. - - Supported methods: - POST: /sys/quotas/rate-limit. Produces: 204 (empty body) - - :param name: The name of the quota to create or update. - :type name: str | unicode - :param path: Path of the mount or namespace to apply the quota. - :type path: str | unicode - :param rate: The maximum number of requests in a given interval to be allowed. Must be positive. - :type rate: float - :param interval: The duration to enforce rate limit. Default is "1s". - :type interval: str | unicode - :param block_interval: If rate limit is reached, how long before client can send requests again. - :type block_interval: str | unicode - :param role: If quota is set on an auth mount path, restrict login requests that are made with a specified role. - :type role: str | unicode - :param rate_limit_type: Type of rate limit quota. Can be lease-count or rate-limit. - :type rate_limit_type: str | unicode - :param inheritable: If set to true on a path that is a namespace, quota will be applied to all child namespaces - :type inheritable: bool - :return: API status code from request. - :rtype: requests.Response - """ - api_path = utils.format_url("/v1/sys/quotas/rate-limit/{name}", name=name) - params = utils.remove_nones( - { - "name": name, - "path": path, - "rate": rate, - "interval": interval, - "block_interval": block_interval, - "role": role, - "type": rate_limit_type, - "inheritable": inheritable, - } - ) - return self._adapter.post( - url=api_path, - json=params, - ) - - def delete_quota(self, name): - """Delete a given quota. Only works when calling on the root namespace. - - Supported methods: - DELETE: /sys/quotas/rate-limit. Produces: 204 (empty body) - - :param name: Name of the quota to delete - :type name: str | unicode - :return: API status code from request. - :rtype: requests.Response - """ - api_path = utils.format_url(f"/v1/sys/quotas/rate-limit/{name}", name=name) - return self._adapter.delete( - url=api_path, - ) diff --git a/.venv/lib/python3.12/site-packages/hvac/api/system_backend/raft.py b/.venv/lib/python3.12/site-packages/hvac/api/system_backend/raft.py deleted file mode 100644 index 0720c9c..0000000 --- a/.venv/lib/python3.12/site-packages/hvac/api/system_backend/raft.py +++ /dev/null @@ -1,253 +0,0 @@ -#!/usr/bin/env python -"""Raft methods module.""" -from hvac.api.system_backend.system_backend_mixin import SystemBackendMixin -from hvac import utils, adapters - - -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. - - This endpoint will ignore your chosen adapter and always uses a RawAdapter. - - Supported methods: - GET: /sys/storage/raft/snapshot. - - :return: The response of the snapshot request. - :rtype: requests.Response - """ - api_path = "/v1/sys/storage/raft/snapshot" - raw_adapter = adapters.RawAdapter.from_adapter(self._adapter) - return raw_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, - ) - - def read_raft_auto_snapshot_status(self, name): - """Read the status of the raft auto snapshot. - - Supported methods: - GET: /sys/storage/raft/snapshot-auto/status/:name. Produces: 200 application/json - - :param name: The name of the snapshot configuration. - :type name: str - :return: The response of the read_raft_auto_snapshot_status request. - :rtype: requests.Response - """ - api_path = f"/v1/sys/storage/raft/snapshot-auto/status/{name}" - return self._adapter.get( - url=api_path, - ) - - def read_raft_auto_snapshot_config(self, name): - """Read the configuration of the raft auto snapshot. - - Supported methods: - GET: /sys/storage/raft/snapshot-auto/config/:name. Produces: 200 application/json - - :param name: The name of the snapshot configuration. - :type name: str - :return: The response of the read_raft_auto_snapshot_config request. - :rtype: requests.Response - """ - api_path = f"/v1/sys/storage/raft/snapshot-auto/config/{name}" - return self._adapter.get( - url=api_path, - ) - - def list_raft_auto_snapshot_configs(self): - """List the configurations of the raft auto snapshot. - - Supported methods: - LIST: /sys/storage/raft/snapshot-auto/config. Produces: 200 application/json - - :return: The response of the list_raft_auto_snapshot_configs request. - :rtype: requests.Response - """ - api_path = "/v1/sys/storage/raft/snapshot-auto/config" - return self._adapter.list( - url=api_path, - ) - - def create_or_update_raft_auto_snapshot_config( - self, name, interval, storage_type, retain=1, **kwargs - ): - """Create or update the configuration of the raft auto snapshot. - - Supported methods: - POST: /sys/storage/raft/snapshot-auto/config/:name. Produces: 204 application/json - - :param name: The name of the snapshot configuration. - :type name: str - :param interval: The interval at which snapshots should be taken. - :type interval: str - :param storage_type: The type of storage to use for the snapshot. - :type storage_type: str - :param retain: The number of snapshots to retain. Default is 1 - :type retain: int - :param kwargs: Additional parameters to send in the request. Should be params specific to the storage type. - :type kwargs: dict - :return: The response of the create_or_update_raft_auto_snapshot_config request. - :rtype: requests.Response - """ - params = utils.remove_nones( - { - "interval": interval, - "storage_type": storage_type, - "retain": retain, - **kwargs, - } - ) - - api_path = f"/v1/sys/storage/raft/snapshot-auto/config/{name}" - return self._adapter.post( - url=api_path, - json=params, - ) - - def delete_raft_auto_snapshot_config(self, name): - """Delete the configuration of the raft auto snapshot. - - Supported methods: - DELETE: /sys/storage/raft/snapshot-auto/config/:name. Produces: 204 application/json - - :param name: The name of the snapshot configuration. - :type name: str - :return: The response of the delete_raft_auto_snapshot_config request. - :rtype: requests.Response - """ - api_path = f"/v1/sys/storage/raft/snapshot-auto/config/{name}" - return self._adapter.delete( - url=api_path, - ) diff --git a/.venv/lib/python3.12/site-packages/hvac/api/system_backend/seal.py b/.venv/lib/python3.12/site-packages/hvac/api/system_backend/seal.py deleted file mode 100644 index 9ce2f5f..0000000 --- a/.venv/lib/python3.12/site-packages/hvac/api/system_backend/seal.py +++ /dev/null @@ -1,104 +0,0 @@ -from hvac.api.system_backend.system_backend_mixin import SystemBackendMixin - - -class Seal(SystemBackendMixin): - def is_sealed(self): - """Determine if Vault is sealed. - - :return: True if Vault is seal, False otherwise. - :rtype: bool - """ - seal_status = self.read_seal_status() - return seal_status["sealed"] - - def read_seal_status(self): - """Read the seal status of the Vault. - - This is an unauthenticated endpoint. - - Supported methods: - GET: /sys/seal-status. Produces: 200 application/json - - :return: The JSON response of the request. - :rtype: dict - """ - api_path = "/v1/sys/seal-status" - return self._adapter.get( - url=api_path, - ) - - def seal(self): - """Seal the Vault. - - In HA mode, only an active node can be sealed. Standby nodes should be restarted to get the same effect. - Requires a token with root policy or sudo capability on the path. - - Supported methods: - PUT: /sys/seal. Produces: 204 (empty body) - - :return: The response of the request. - :rtype: requests.Response - """ - api_path = "/v1/sys/seal" - return self._adapter.put( - url=api_path, - ) - - def submit_unseal_key(self, key=None, reset=False, migrate=False): - """Enter a single master key share to progress the unsealing of the Vault. - - If the threshold number of master key shares is reached, Vault will attempt to unseal the Vault. Otherwise, this - API must be called multiple times until that threshold is met. - - Either the key or reset parameter must be provided; if both are provided, reset takes precedence. - - Supported methods: - PUT: /sys/unseal. Produces: 200 application/json - - :param key: Specifies a single master key share. This is required unless reset is true. - :type key: str | unicode - :param reset: Specifies if previously-provided unseal keys are discarded and the unseal process is reset. - :type reset: bool - :param migrate: Available in 1.0 Beta - Used to migrate the seal from shamir to autoseal or autoseal to shamir. - Must be provided on all unseal key calls. - :type: migrate: bool - :return: The JSON response of the request. - :rtype: dict - """ - - params = { - "migrate": migrate, - } - if not reset and key is not None: - params["key"] = key - elif reset: - params["reset"] = reset - - api_path = "/v1/sys/unseal" - return self._adapter.put( - url=api_path, - json=params, - ) - - def submit_unseal_keys(self, keys, migrate=False): - """Enter multiple master key share to progress the unsealing of the Vault. - - :param keys: List of master key shares. - :type keys: List[str] - :param migrate: Available in 1.0 Beta - Used to migrate the seal from shamir to autoseal or autoseal to shamir. - Must be provided on all unseal key calls. - :type: migrate: bool - :return: The JSON response of the last unseal request. - :rtype: dict - """ - result = None - - for key in keys: - result = self.submit_unseal_key( - key=key, - migrate=migrate, - ) - if not result["sealed"]: - break - - return result diff --git a/.venv/lib/python3.12/site-packages/hvac/api/system_backend/system_backend_mixin.py b/.venv/lib/python3.12/site-packages/hvac/api/system_backend/system_backend_mixin.py deleted file mode 100644 index 4520cfb..0000000 --- a/.venv/lib/python3.12/site-packages/hvac/api/system_backend/system_backend_mixin.py +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/env python -import logging -from abc import ABCMeta - -from hvac.api.vault_api_base import VaultApiBase - -logger = logging.getLogger(__name__) - - -class SystemBackendMixin(VaultApiBase, metaclass=ABCMeta): - """Base class for System Backend API endpoints.""" diff --git a/.venv/lib/python3.12/site-packages/hvac/api/system_backend/wrapping.py b/.venv/lib/python3.12/site-packages/hvac/api/system_backend/wrapping.py deleted file mode 100644 index 90fe9fb..0000000 --- a/.venv/lib/python3.12/site-packages/hvac/api/system_backend/wrapping.py +++ /dev/null @@ -1,51 +0,0 @@ -from hvac.api.system_backend.system_backend_mixin import SystemBackendMixin - - -class Wrapping(SystemBackendMixin): - def unwrap(self, token=None): - """Return the original response inside the given wrapping token. - - Unlike simply reading cubbyhole/response (which is deprecated), this endpoint provides additional validation - checks on the token, returns the original value on the wire rather than a JSON string representation of it, and - ensures that the response is properly audit-logged. - - Supported methods: - POST: /sys/wrapping/unwrap. Produces: 200 application/json - - :param token: Specifies the wrapping token ID. This is required if the client token is not the wrapping token. - Do not use the wrapping token in both locations. - :type token: str | unicode - :return: The JSON response of the request. - :rtype: dict - """ - params = {} - if token is not None: - params["token"] = token - - api_path = "/v1/sys/wrapping/unwrap" - return self._adapter.post( - url=api_path, - json=params, - ) - - def wrap(self, payload=None, ttl=60): - """Wraps a serializable dictionary inside a wrapping token. - - Supported methods: - POST: /sys/wrapping/wrap. Produces: 200 application/json - - :param payload: Specifies the data that should be wrapped inside the token. - :type payload: dict - :param ttl: The TTL of the returned wrapping token. - :type ttl: int - :return: The JSON response of the request. - :rtype: dict - """ - - if payload is None: - payload = {} - - api_path = "/v1/sys/wrapping/wrap" - return self._adapter.post( - url=api_path, json=payload, headers={"X-Vault-Wrap-TTL": "{}".format(ttl)} - ) diff --git a/.venv/lib/python3.12/site-packages/hvac/api/vault_api_base.py b/.venv/lib/python3.12/site-packages/hvac/api/vault_api_base.py deleted file mode 100644 index d73ac70..0000000 --- a/.venv/lib/python3.12/site-packages/hvac/api/vault_api_base.py +++ /dev/null @@ -1,17 +0,0 @@ -"""Base class used by all hvac "api" classes.""" -import logging -from abc import ABCMeta - -logger = logging.getLogger(__name__) - - -class VaultApiBase(metaclass=ABCMeta): - """Base class for API endpoints.""" - - def __init__(self, adapter): - """Default api class constructor. - - :param adapter: Instance of :py:class:`hvac.adapters.Adapter`; used for performing HTTP requests. - :type adapter: hvac.adapters.Adapter - """ - self._adapter = adapter diff --git a/.venv/lib/python3.12/site-packages/hvac/api/vault_api_category.py b/.venv/lib/python3.12/site-packages/hvac/api/vault_api_category.py deleted file mode 100644 index f9424bd..0000000 --- a/.venv/lib/python3.12/site-packages/hvac/api/vault_api_category.py +++ /dev/null @@ -1,100 +0,0 @@ -"""Base class used by all hvac api "category" classes.""" -import logging -from abc import ABCMeta, abstractmethod - -from hvac.api.vault_api_base import VaultApiBase - -logger = logging.getLogger(__name__) - - -class VaultApiCategory(VaultApiBase, metaclass=ABCMeta): - """Base class for API categories.""" - - def __init__(self, adapter): - """API Category class constructor. - - :param adapter: Instance of :py:class:`hvac.adapters.Adapter`; used for performing HTTP requests. - :type adapter: hvac.adapters.Adapter - """ - self._adapter = adapter - self.implemented_class_names = [] - for implemented_class in self.implemented_classes: - class_name = implemented_class.__name__.lower() - self.implemented_class_names.append(class_name) - auth_method_instance = implemented_class(adapter=adapter) - setattr(self, self.get_private_attr_name(class_name), auth_method_instance) - - super().__init__(adapter=adapter) - - def __getattr__(self, item): - """Get an instance of an class instance in this category where available. - - :param item: Name of the class being requested. - :type item: str | unicode - :return: The requested class instance where available. - :rtype: hvac.api.VaultApiBase - """ - if item == "implemented_class_names": - raise AttributeError - if item in self.implemented_class_names: - private_attr_name = self.get_private_attr_name(item) - return getattr(self, private_attr_name) - if item in [u.lower() for u in self.unimplemented_classes]: - raise NotImplementedError( - '"%s" auth method class not currently implemented.' % item - ) - raise AttributeError - - @property - def adapter(self): - """Retrieve the adapter instance under the "_adapter" property in use by this class. - - :return: The adapter instance in use by this class. - :rtype: hvac.adapters.Adapter - """ - return self._adapter - - @adapter.setter - def adapter(self, adapter): - """Sets the adapter instance under the "_adapter" property in use by this class. - - Also sets the adapter property for all implemented classes under this category. - - :param adapter: New adapter instance to set for this class and all implemented classes under this category. - :type adapter: hvac.adapters.Adapter - """ - self._adapter = adapter - for implemented_class in self.implemented_classes: - class_name = implemented_class.__name__.lower() - getattr(self, self.get_private_attr_name(class_name)).adapter = adapter - - @property - @abstractmethod - def implemented_classes(self): - """List of implemented classes under this category. - - :return: List of implemented classes under this category. - :rtype: List[hvac.api.VaultApiBase] - """ - raise NotImplementedError - - @property - def unimplemented_classes(self): - """List of known unimplemented classes under this category. - - :return: List of known unimplemented classes under this category. - :rtype: List[str] - """ - raise NotImplementedError - - @staticmethod - def get_private_attr_name(class_name): - """Helper method to prepend a leading underscore to a provided class name. - - :param class_name: Name of a class under this category. - :type class_name: str|unicode - :return: The private attribute label for the provided class. - :rtype: str - """ - private_attr_name = f"_{class_name}" - return private_attr_name diff --git a/.venv/lib/python3.12/site-packages/hvac/aws_utils.py b/.venv/lib/python3.12/site-packages/hvac/aws_utils.py deleted file mode 100644 index b17b84f..0000000 --- a/.venv/lib/python3.12/site-packages/hvac/aws_utils.py +++ /dev/null @@ -1,81 +0,0 @@ -import hmac -from datetime import datetime -from hashlib import sha256 -import requests - - -class SigV4Auth: - def __init__(self, access_key, secret_key, session_token=None, region="us-east-1"): - self.access_key = access_key - self.secret_key = secret_key - self.session_token = session_token - self.region = region - - def add_auth(self, request): - timestamp = datetime.utcnow().strftime("%Y%m%dT%H%M%SZ") - request.headers["X-Amz-Date"] = timestamp - - if self.session_token: - request.headers["X-Amz-Security-Token"] = self.session_token - - # https://docs.aws.amazon.com/general/latest/gr/sigv4-create-canonical-request.html - canonical_headers = "".join( - f"{k.lower()}:{request.headers[k]}\n" for k in sorted(request.headers) - ) - signed_headers = ";".join(k.lower() for k in sorted(request.headers)) - payload_hash = sha256(request.body.encode("utf-8")).hexdigest() - canonical_request = "\n".join( - [request.method, "/", "", canonical_headers, signed_headers, payload_hash] - ) - - # https://docs.aws.amazon.com/general/latest/gr/sigv4-create-string-to-sign.html - algorithm = "AWS4-HMAC-SHA256" - credential_scope = "/".join( - [timestamp[0:8], self.region, "sts", "aws4_request"] - ) - canonical_request_hash = sha256(canonical_request.encode("utf-8")).hexdigest() - string_to_sign = "\n".join( - [algorithm, timestamp, credential_scope, canonical_request_hash] - ) - - # https://docs.aws.amazon.com/general/latest/gr/sigv4-calculate-signature.html - key = f"AWS4{self.secret_key}".encode() - key = hmac.new(key, timestamp[0:8].encode("utf-8"), sha256).digest() - key = hmac.new(key, self.region.encode("utf-8"), sha256).digest() - key = hmac.new(key, b"sts", sha256).digest() - key = hmac.new(key, b"aws4_request", sha256).digest() - signature = hmac.new(key, string_to_sign.encode("utf-8"), sha256).hexdigest() - - # https://docs.aws.amazon.com/general/latest/gr/sigv4-add-signature-to-request.html - authorization = "{} Credential={}/{}, SignedHeaders={}, Signature={}".format( - algorithm, self.access_key, credential_scope, signed_headers, signature - ) - request.headers["Authorization"] = authorization - - -def generate_sigv4_auth_request(header_value=None): - """Helper function to prepare a AWS API request to subsequently generate a "AWS Signature Version 4" header. - - :param header_value: Vault allows you to require an additional header, X-Vault-AWS-IAM-Server-ID, to be present - to mitigate against different types of replay attacks. Depending on the configuration of the AWS auth - backend, providing a argument to this optional parameter may be required. - :type header_value: str - :return: A PreparedRequest instance, optionally containing the provided header value under a - 'X-Vault-AWS-IAM-Server-ID' header name pointed to AWS's simple token service with action "GetCallerIdentity" - :rtype: requests.PreparedRequest - """ - request = requests.Request( - method="POST", - url="https://sts.amazonaws.com/", - headers={ - "Content-Type": "application/x-www-form-urlencoded; charset=utf-8", - "Host": "sts.amazonaws.com", - }, - data="Action=GetCallerIdentity&Version=2011-06-15", - ) - - if header_value: - request.headers["X-Vault-AWS-IAM-Server-ID"] = header_value - - prepared_request = request.prepare() - return prepared_request diff --git a/.venv/lib/python3.12/site-packages/hvac/constants/__init__.py b/.venv/lib/python3.12/site-packages/hvac/constants/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/.venv/lib/python3.12/site-packages/hvac/constants/__pycache__/__init__.cpython-312.pyc b/.venv/lib/python3.12/site-packages/hvac/constants/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index c39958cb6861ce42fb69a30f545c471a994d3b35..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 213 zcmZ8bK?=e!5Nxc12z`i$c2Te5#e+8meLzTSG{H1ml5L?c@dtum@C!b}7f5eCnO+^3 zo!Mm;=A9(7DB$pVs6ju&_(wMmmwVJkbGCm*ZWOj|$n*pXO9|f8aFi8#P3W}r=}r@D z(UL>M3nlDTdVUgl%P;6kL69}lHehrPRZ9x(DqAcee9N>F#Z81bs74e}p!FmydEi`I dO`K;{+fUaeo@*mFZW2ncKtGso%ouZVa6eacJOBUy diff --git a/.venv/lib/python3.12/site-packages/hvac/constants/__pycache__/approle.cpython-312.pyc b/.venv/lib/python3.12/site-packages/hvac/constants/__pycache__/approle.cpython-312.pyc deleted file mode 100644 index bf34faac091bb500aa1f25bd378e6a011740ecbf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 408 zcmXw0!AiqG5Z$EKh*&&C>d{<#NEYo?gkqzJF$ryo*vqm_woNd}hU_+w{)l%Eg1_J| zc+qR{p!fq~Z#}t{bYN!Q3~ylG%xkN)3xqi@PvM8i-|J#yat)RT0z7~Kj6oocr5On1 zM`VTZf|@dHTRb;V7f;^BqQ@jb_~@3BAa?A%5$h9BRjGY_Hf>&49|{U%qB zfxJNsjS=(49xE|_S{j$8h;6;|#y(&fa0_r7u)M6as;>__N*YV0HG$?CwVVZ31vceD zco7G*uxXHUn<^Gi$*|Ia;fdzp=5i_|Z#$p9GOi3YW}I)VY5A@yXif^lwYy7=DRRz; zRvCBqCY*6itx%F!HRBSzm9;_ybGHg9UKSf#ofKI{s0LkEp(S@mZ0?x+QbkUuYc^998#xklLU4=6}H~m_&o_rXIW6zryInX%zo) z_renr_IqJW{u83k{@=m}bhS?YTH#dX9Gk4bXMC=Vuu2PV_MQuiAzlkDk|d>a$_ z<&sR4&Z))i1(yq)iAy|RLd5cE`^i3r-F$COlNmH=aJrxgPHvtEL)Pv2^1AvgSFFhR zfv&^(@EwqO1k(@S^So~;`dZ&zq1u<-2XCWQ^Wh3LT>Tgdu6eNL&7;q#q3?tLCx7t3 A?f?J) diff --git a/.venv/lib/python3.12/site-packages/hvac/constants/__pycache__/azure.cpython-312.pyc b/.venv/lib/python3.12/site-packages/hvac/constants/__pycache__/azure.cpython-312.pyc deleted file mode 100644 index 5ec6cf4237df2ee869d52d8a2ab14dba091ccdd6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 405 zcmXw#PfNov7{=Rf;y;GN!_K+xum<%i!kD8Bw3AJD*d=7m>soA+nxuv9i+J}S_!ayL zp1c-3h+jb5Z6~wNy%6%|$Mf>$dEOh11IyI#?Irv)_xJj-E$6>kHcj(nF>7kgEoML4 zQ@e25wMDllxYCqsg(SpO14CLM9RlhuG6{%gIz$QRP%uO}!$Kkjfdr!mK94xK?Rwd) zv^Uu-j)Gn+GFG-KayRxw4w5Ip^@bl+ycb5CZop>L1DQ}>5x?z}yM!tis z()TBW(a^u{`?up)Yq_?xdc>hf0IN8|BS?jcw2%>~ju&ZcJZULn5`>h`L6I??735x+ z9U8ki@Epg{45x*0#n0T6Q*5T8lhWXU8aWPg8sK1?3#RKJ+_YHjohO22F5gQ9L8nmwQECKTEmuIeAotIi`AD)DWwn`Zz~IJaMQueK&ZA>n< ziu1aCubNX301pIOpi^z2d%6Z9;1z;`SJVN~gW`qu+w7HcE={?db9u^@oGVkVj;hU> z2R+~`J;l%YYLM&Y{Jg&)Q4N5<_(kdEB^D$u_)ERT@x4m%d|ziV7bF&3 zOKG17>T7~&BBWYN?`UKwLTx}r$b5~&K4huJsh3jun#MsC(`u#$UXrO18B9+!yH7li za*hQ%rEyl~G#y1A#gb*iSm0ASuBci05FO)&*}~nn(?Pm%V4!BUGAC`Pfot3K-MdVE zd-u64U2%^)=x*JN=^W}#t&R^26J?KPOv|!bCc?UnnyBp>4bz$3o<9qPNcal~&(6-O z0b@a*k|g3)j}0K34qS($9q7?i@OGt;6)^UhhjCVJqJu`)bn%hZZM(Q*8ErQ!HB8fb zhnm>7q}Ei|$yVo_gQU3Y+|rv4vfmmy!VO)Yb-10^vJLmmk&~_e@BUxMlJo-W$dR-!K@m0foFjgf>kWj|592%C}mPfYMr#vOe}g5(kuHhn$S@2bKE(d=!#>?hA4q*gF8)ex zm#U&DzXAHSwlM+ai?xl<-H-1lpmeeRbW+)yJlvmv)vH|oNp1o*uZsD{64x(_VC}W? K6O__b+2Jpm$?2T{ diff --git a/.venv/lib/python3.12/site-packages/hvac/constants/__pycache__/identity.cpython-312.pyc b/.venv/lib/python3.12/site-packages/hvac/constants/__pycache__/identity.cpython-312.pyc deleted file mode 100644 index 6c135ca0ec204513ea650fa1e9a68c987c751f40..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 385 zcmXw!!AiqG5QaBNt5K;QBJ>)MJv2-8;6;RDYbn&Gv?*dQ%QhLCV7ePN+hTkX-$2ku z@D;r1O>z@oAkdp9x6lsE%sc8t@8~R49j+J;u0h*vd3-p;j z(E?+lXQf*Csd2?wDk+nxEg+^60$XxhhG2ICU^0@Koq{hw?SaiA22O59OoCuE&P{mS zs%Ycx*Nl9ZkbwJyzznq1u6xPi62rngOrTuG$Z$1%&ElA64(;Q(G(|{3^_Y< z8mCxYLp`DX166h$E~$_G?X!5x>m=Eqc`@g~B8E$Gpdd7rsjW(3Xqxte&WjyXKKd>l V7GyQ0#gKciQN!5!*vNTy+9f%NJZHL_|O++n1_?GXp$(AM|Up8&n z!GnK*p1g_&LHrN=7ra!wjND|W-Nts?$+xSOf-fP@`@GNdhBxs1n4HWasK)m%);k`d zqdplH@QXSN0X`yvT8MBY;czXkjR^mlYb5{$K%OMYSUb@YfTw^b0n>nEBtx<=Pmysl z0hlI}WC}2oK$P2={rmk9AeX*z1KJwzCi2r!;i2cU5W6AE1=PVICArYcg%-`}0d|=k z<`^{t3Nm%uwo6xz`|DfzOf-QhQ%YsAZFbhm(Tr(fc$9+ZdrntgEtKLEB}%CzuSHpE z5{5+|-2eL3yTyNfNs*&;01l;4ygTSt3wM-3S1hcR^L#W#T{GzVq3yZiF6~C+%x=53 z+rA)atAovc7iWA2+ipnTgmLP1fPJ5mJb(NaPCiEP<2Fhlloz5jgHuICDGochY%uHJ zHRwvR67v>)6OV0UM$5&R_Zf@R{;tX7eYq41n7MMy@4RNwG~Nrn0}C_jK$H(&lH2)- zIAs{bGYun71T>ye>-EO7%DVBm^1{$xJgI2$!f;f1{-n{=N0j-Yvaagt$b9a<`GXBz zi$*{|Y*qD|_7$D=V{*D{BCG@?&^xHNU%*sADg=v?2@&QP01XFR|*Gd zUGcl;>3bcI>^by)unaf! - - :param path: - :type path: - :param wrap_ttl: - :type wrap_ttl: - :return: - :rtype: - """ - try: - return self._adapter.get(f"/v1/{path}", wrap_ttl=wrap_ttl) - except exceptions.InvalidPath: - return None - - def list(self, path): - """GET /?list=true - - :param path: - :type path: - :return: - :rtype: - """ - try: - payload = {"list": True} - return self._adapter.get(f"/v1/{path}", params=payload) - except exceptions.InvalidPath: - return None - - # TODO(v4.0.0): remove overload when write doesn't use args and kwargs anymore - @t.overload - def write(self, path: str, wrap_ttl: t.Optional[str], **kwargs: t.Dict[str, t.Any]): - pass - - def write(self, *args: list, **kwargs: t.Dict[str, t.Any]): - """POST / - - Write data to a path. Because this method uses kwargs for the data to write, "path" and "wrap_ttl" data keys cannot be used. - If these names are needed, or if the key names are not known at design time, consider using the write_data method. - - :param path: - :type path: str - :param wrap_ttl: - :type wrap_ttl: str | None - :param kwargs: - :type kwargs: dict - :return: - :rtype: - """ - - try: - path = args[0] - except IndexError: - path = _sentinel - - path = _smart_pop(kwargs, "path", posvalue=path) - - try: - wrap_ttl = args[1] - except IndexError: - wrap_ttl = _sentinel - - wrap_ttl = _smart_pop(kwargs, "wrap_ttl", default=None, posvalue=wrap_ttl) - - if "data" in kwargs: - warn( - ( - "write() argument 'data' was supplied as a keyword argument." - " In v3.0.0 the 'data' key will be treated specially. Consider using the write_data() method instead." - " For more information see: https://github.com/hvac/hvac/issues/1034" - ), - PendingDeprecationWarning, - stacklevel=2, - ) - - return self.write_data(path, wrap_ttl=wrap_ttl, data=kwargs) - - def write_data( - self, - path: str, - *, - data: t.Optional[t.Dict[str, t.Any]] = None, - wrap_ttl: t.Optional[str] = None, - ): - """Write data to a path. Similar to write() without restrictions on data keys. - - Supported methods: - POST / - - :param path: - :type path: str - :param data: - :type data: dict | None - :param wrap_ttl: - :type wrap_ttl: str | None - :return: - :rtype: - """ - return self._adapter.post(f"/v1/{path}", json=data, wrap_ttl=wrap_ttl) - - def delete(self, path): - """DELETE / - - :param path: - :type path: - :return: - :rtype: - """ - self._adapter.delete(f"/v1/{path}") - - def get_policy(self, name, parse=False): - """Retrieve the policy body for the named policy. - - :param name: The name of the policy to retrieve. - :type name: str | unicode - :param parse: Specifies whether to parse the policy body using pyhcl or not. - :type parse: bool - :return: The (optionally parsed) policy body for the specified policy. - :rtype: str | dict - """ - try: - policy = self.sys.read_policy(name=name)["data"]["rules"] - except exceptions.InvalidPath: - return None - - if parse: - if not has_hcl_parser: - raise ImportError("pyhcl is required for policy parsing") - policy = hcl.loads(policy) - - return policy - - def lookup_token(self, token=None, accessor=False, wrap_ttl=None): - """GET /auth/token/lookup/ - - GET /auth/token/lookup-accessor/ - - GET /auth/token/lookup-self - - :param token: - :type token: str. - :param accessor: - :type accessor: str. - :param wrap_ttl: - :type wrap_ttl: int. - :return: - :rtype: - """ - token_param = { - "token": token, - } - accessor_param = { - "accessor": token, - } - if token: - if accessor: - path = "/v1/auth/token/lookup-accessor" - return self._adapter.post(path, json=accessor_param, wrap_ttl=wrap_ttl) - else: - path = "/v1/auth/token/lookup" - return self._adapter.post(path, json=token_param) - else: - path = "/v1/auth/token/lookup-self" - return self._adapter.get(path, wrap_ttl=wrap_ttl) - - def revoke_token(self, token, orphan=False, accessor=False): - """POST /auth/token/revoke - - POST /auth/token/revoke-orphan - - POST /auth/token/revoke-accessor - - :param token: - :type token: - :param orphan: - :type orphan: - :param accessor: - :type accessor: - :return: - :rtype: - """ - if accessor and orphan: - msg = "revoke_token does not support 'orphan' and 'accessor' flags together" - raise exceptions.InvalidRequest(msg) - elif accessor: - params = {"accessor": token} - self._adapter.post("/v1/auth/token/revoke-accessor", json=params) - elif orphan: - params = {"token": token} - self._adapter.post("/v1/auth/token/revoke-orphan", json=params) - else: - params = {"token": token} - self._adapter.post("/v1/auth/token/revoke", json=params) - - def renew_token(self, token, increment=None, wrap_ttl=None): - """POST /auth/token/renew - - POST /auth/token/renew-self - - :param token: - :type token: - :param increment: - :type increment: - :param wrap_ttl: - :type wrap_ttl: - :return: - :rtype: - - For calls expecting to hit the renew-self endpoint please use the "renew_self" method on "hvac_client.auth.token" instead - """ - params = { - "increment": increment, - } - - params["token"] = token - return self._adapter.post( - "/v1/auth/token/renew", json=params, wrap_ttl=wrap_ttl - ) - - def logout(self, revoke_token=False): - """Clears the token used for authentication, optionally revoking it before doing so. - - :param revoke_token: - :type revoke_token: - :return: - :rtype: - """ - if revoke_token: - self.auth.token.revoke_self() - - self.token = None - - def is_authenticated(self): - """Helper method which returns the authentication status of the client - - :return: - :rtype: - """ - if not self.token: - return False - - try: - self.lookup_token() - return True - except exceptions.Forbidden: - return False - except exceptions.InvalidPath: - return False - except exceptions.InvalidRequest: - return False - - def auth_cubbyhole(self, token): - """Perform a login request with a wrapped token. - - Stores the unwrapped token in the resulting Vault response for use by the :py:meth:`hvac.adapters.Adapter` - instance under the _adapter Client attribute. - - :param token: Wrapped token - :type token: str | unicode - :return: The (JSON decoded) response of the auth request - :rtype: dict - """ - self.token = token - return self.login("/v1/sys/wrapping/unwrap") - - def login(self, url, use_token=True, **kwargs): - """Perform a login request. - - Associated request is typically to a path prefixed with "/v1/auth") and optionally stores the client token sent - in the resulting Vault response for use by the :py:meth:`hvac.adapters.Adapter` instance under the _adapter - Client attribute. - - :param url: Path to send the authentication request to. - :type url: str | unicode - :param use_token: if True, uses the token in the response received from the auth request to set the "token" - attribute on the the :py:meth:`hvac.adapters.Adapter` instance under the _adapter Client attribute. - :type use_token: bool - :param kwargs: Additional keyword arguments to include in the params sent with the request. - :type kwargs: dict - :return: The response of the auth request. - :rtype: requests.Response - """ - return self._adapter.login(url=url, use_token=use_token, **kwargs) diff --git a/.venv/lib/python3.12/site-packages/hvac/v1/__pycache__/__init__.cpython-312.pyc b/.venv/lib/python3.12/site-packages/hvac/v1/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index e9a642c144137a7ccce33945e2085539d26a7c30..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 21129 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