удаляю папку venv
parent
0740e6c214
commit
be5f61008f
|
|
@ -1 +0,0 @@
|
|||
pip
|
||||
|
|
@ -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.
|
||||
|
||||
|
|
@ -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
|
||||
|
||||

|
||||
|
||||
[HashiCorp](https://hashicorp.com/) [Vault](https://www.vaultproject.io) API client for Python 3.x
|
||||
|
||||
[](https://github.com/hvac/hvac/actions/workflows/build-test.yml)
|
||||
[](https://github.com/hvac/hvac/actions/workflows/lint-and-test.yml)
|
||||
[](https://codecov.io/gh/hvac/hvac)
|
||||
[](https://hvac.readthedocs.io/en/latest/?badge=latest)
|
||||
[](https://badge.fury.io/py/hvac)
|
||||
[](https://twitter.com/python_hvac)
|
||||
[](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)
|
||||
|
||||
|
|
@ -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,,
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
Wheel-Version: 1.0
|
||||
Generator: poetry-core 1.7.0
|
||||
Root-Is-Purelib: true
|
||||
Tag: py3-none-any
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
from hvac.v1 import Client
|
||||
|
||||
__all__ = ("Client",)
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -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
|
||||
|
|
@ -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",
|
||||
)
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -1,64 +0,0 @@
|
|||
"""Collection of classes for various Vault auth methods."""
|
||||
|
||||
from hvac.api.auth_methods.approle import AppRole
|
||||
from hvac.api.auth_methods.azure import Azure
|
||||
from hvac.api.auth_methods.gcp import Gcp
|
||||
from hvac.api.auth_methods.github import Github
|
||||
from hvac.api.auth_methods.jwt import JWT
|
||||
from hvac.api.auth_methods.kubernetes import Kubernetes
|
||||
from hvac.api.auth_methods.ldap import Ldap
|
||||
from hvac.api.auth_methods.userpass import Userpass
|
||||
from hvac.api.auth_methods.legacy_mfa import LegacyMfa
|
||||
from hvac.api.auth_methods.oidc import OIDC
|
||||
from hvac.api.auth_methods.okta import Okta
|
||||
from hvac.api.auth_methods.radius import Radius
|
||||
from hvac.api.auth_methods.token import Token
|
||||
from hvac.api.auth_methods.aws import Aws
|
||||
from hvac.api.auth_methods.cert import Cert
|
||||
from hvac.api.vault_api_category import VaultApiCategory
|
||||
|
||||
__all__ = (
|
||||
"AuthMethods",
|
||||
"AppRole",
|
||||
"Azure",
|
||||
"Gcp",
|
||||
"Github",
|
||||
"JWT",
|
||||
"Kubernetes",
|
||||
"Ldap",
|
||||
"Userpass",
|
||||
"LegacyMfa",
|
||||
"OIDC",
|
||||
"Okta",
|
||||
"Radius",
|
||||
"Token",
|
||||
"Aws",
|
||||
"Cert",
|
||||
)
|
||||
|
||||
|
||||
class AuthMethods(VaultApiCategory):
|
||||
"""Auth Methods."""
|
||||
|
||||
implemented_classes = [
|
||||
AppRole,
|
||||
Azure,
|
||||
Github,
|
||||
Gcp,
|
||||
JWT,
|
||||
Kubernetes,
|
||||
Ldap,
|
||||
Userpass,
|
||||
LegacyMfa,
|
||||
OIDC,
|
||||
Okta,
|
||||
Radius,
|
||||
Token,
|
||||
Aws,
|
||||
Cert,
|
||||
]
|
||||
unimplemented_classes = [
|
||||
"AppId",
|
||||
"AliCloud",
|
||||
"Mfa",
|
||||
]
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -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,
|
||||
)
|
||||
|
|
@ -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::<account_id>:user/<optional_path/><user_name> or
|
||||
arn:aws:sts::<account_id>:assumed-role/<role_name_without_path>/<role_session_name>. 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/<instance_id> 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/<instance_id> 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)
|
||||
|
|
@ -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,
|
||||
)
|
||||
|
|
@ -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/<mount point>/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/<mount point>/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/<mount point>/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/<mount point>/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/<mount point>/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
|
||||
|
|
@ -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: <required for iam> 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: <iam only> 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: <iam only> 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: <gce only> 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: <gce only> 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: <gce only> 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: <gce only> 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,
|
||||
)
|
||||
|
|
@ -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,
|
||||
)
|
||||
|
|
@ -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,
|
||||
)
|
||||
|
|
@ -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
|
||||
|
|
@ -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,
|
||||
)
|
||||
|
|
@ -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)
|
||||
|
|
@ -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,
|
||||
)
|
||||
|
|
@ -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,
|
||||
)
|
||||
|
|
@ -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,
|
||||
)
|
||||
|
|
@ -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,
|
||||
)
|
||||
|
|
@ -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,
|
||||
)
|
||||
|
|
@ -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",
|
||||
]
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -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,
|
||||
)
|
||||
|
|
@ -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,
|
||||
)
|
||||
|
|
@ -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")
|
||||
|
|
@ -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,
|
||||
)
|
||||
|
|
@ -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,
|
||||
)
|
||||
|
|
@ -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
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -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
|
||||
|
|
@ -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,
|
||||
)
|
||||
|
|
@ -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,
|
||||
)
|
||||
|
|
@ -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,
|
||||
)
|
||||
|
|
@ -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,
|
||||
)
|
||||
|
|
@ -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,
|
||||
)
|
||||
|
|
@ -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,
|
||||
)
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -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 = []
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue