diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 7627fdade..405ee2a89 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.10.14 +current_version = 0.11.0 commit = True tag = True diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 000000000..2d6cad635 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1 @@ +ko_fi: jeffwecan diff --git a/.github/workflows/lint-and-test.yml b/.github/workflows/lint-and-test.yml new file mode 100644 index 000000000..285290166 --- /dev/null +++ b/.github/workflows/lint-and-test.yml @@ -0,0 +1,154 @@ +name: Lint and Test + +on: + push: + branches: + - main + - develop + pull_request: + branches: + - main + - develop + +jobs: + lint: + name: Lint + runs-on: ubuntu-latest + strategy: + matrix: + python-version: + - 3.6 + - 3.7 + - 3.8 + - 3.9 + + steps: + - uses: actions/checkout@v2 + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} + + - name: Install `black` and `flake8` + run: | + pip install \ + black \ + flake8 \ + ; + + - name: Check formatting with `black` + run: black --check . + + - name: Lint with `flake8` + run: flake8 . --count --statistics + + unit-tests: + name: Unit Tests + runs-on: ubuntu-latest + strategy: + matrix: + python-version: + - 3.6 + - 3.7 + - 3.8 + - 3.9 + + steps: + - uses: actions/checkout@v2 + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} + + - name: Install Python dependencies + run: pip install -r requirements-dev.txt + + - name: pytest tests/unit_tests + run: | + pytest \ + --cov=hvac \ + --cov-report=xml \ + tests/unit_tests + + - name: Upload unit tests coverage artifacts + uses: actions/upload-artifact@v2 + with: + name: unit_tests-coverage.xml + path: coverage.xml + if-no-files-found: error + + integration-tests: + name: Integration Tests + runs-on: ubuntu-latest + strategy: + matrix: + python-version: + - 3.6 + vault-version: + - 1.4.7 + - 1.5.9 + - 1.6.5 + - 1.7.2 + + steps: + - uses: actions/checkout@v2 + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} + + - name: Install Python dependencies + run: pip install -r requirements-dev.txt + + - name: Install Vault and Consul (for integration tests) + run: | + curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo apt-key add - + echo "deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main" \ + | sudo tee /etc/apt/sources.list.d/hashicorp.list + + sudo apt update \ + -o Dir::Etc::sourceparts="-" \ + -o APT::Get::List-Cleanup="0" \ + -o Dir::Etc::sourcelist="sources.list.d/hashicorp.list" + + sudo apt install \ + consul \ + vault-enterprise \ + ; + + # We disble cap_ipc_lock here as its generally incompatabile with GitHub + # Actions' runtime environments. + sudo setcap cap_ipc_lock= /usr/bin/vault + + - name: pytest tests/integration_tests + run: | + pytest \ + --cov=hvac \ + --cov-report=xml \ + tests/integration_tests + + - name: Upload integration tests coverage artifacts + uses: actions/upload-artifact@v2 + with: + name: integration_tests-coverage.xml + path: coverage.xml + if-no-files-found: error + + upload-to-codecov: + name: Upload to Codecov + runs-on: ubuntu-latest + needs: + - unit-tests + - integration-tests + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Download artifacts + uses: actions/download-artifact@v2 + + - name: Upload to Codecov + uses: codecov/codecov-action@v1 diff --git a/.github/workflows/python-package.yml b/.github/workflows/python-package.yml deleted file mode 100644 index 68db0e92f..000000000 --- a/.github/workflows/python-package.yml +++ /dev/null @@ -1,42 +0,0 @@ -name: Test - -on: - push: - branches: [ develop ] - pull_request: - branches: [ develop ] - -jobs: - build: - - runs-on: ubuntu-latest - strategy: - matrix: - python-version: [3.6] - vault-version: [1.4.7, 1.5.8, 1.6.4, 1.7.1] - steps: - - uses: actions/checkout@v2 - - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 - with: - python-version: ${{ matrix.python-version }} - - - name: Install dependencies - run: | - tests/scripts/install-consul.sh - tests/scripts/install-vault.sh ${{ matrix.vault-version }} enterprise - pip install -r requirements-dev.txt - echo "$HOME/.local/bin" >> $GITHUB_PATH - - - name: Lint with flake8 - run: flake8 . --count --exit-zero --statistics - - - name: Test with pytest - run: pytest --cov=hvac tests/ - - - name: Codecov - Process coverage - uses: codecov/codecov-action@v1 - with: - fail_ci_if_error: true - verbose: true diff --git a/CHANGELOG.md b/CHANGELOG.md index a5a4349d3..f038d0764 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,37 @@ # Changelog +## 0.11.0 (July 12th, 2021) + +### 💥 Breaking Changes + +- **Note**: This is intended to by the last hvac release supporting Python 2.7. + + **_Starting with hvac version `1.0.0`, Python versions `>=3.6` will be the only explictly supported versions._** +- Userpass: Add `use_token` param on `login()`, Accept passthrough `**kwargs` on create user . GH-733 + +### 🚀 Features + +- Support CA-related Environment Variables. GH-735 +- Migrate Token Auth Methods to Dedicated Class. GH-734 +- Allow Omission of Password Argument on Userpass `create_or_update_user()`. GH-714 +- Add `token_ttl` & `token_max_ttl` Arguments to `ldap.configure()`. GH-707 + +### 🐛 Bug Fixes + +- Fix Cert.login() handling of use_token argument. GH-720 +- Use PUTs for AWS Secrets Engine STS Requests. GH-718 + +### 🧰 Miscellaneous + +- Add deprecation notices for `Client()` k8s methods. GH-732 +- Add deprecation notices for `Client()` approle methods. GH-731 +- Deprecate AppID-related `Client()` Methods. GH-730 +- Update Deprecated Usage In Documentation & Tests. GH-728 +- Add `python_requires='>=2.7'` to setuptools Metadata. GH-727 +- Transition to `black` Formatting + Updated PR Actions Workflow. GH-726 + +Thanks to @el-deano, @intgr, @jeffwecan, @pjaudiomv, @tp6783 and tyhess for their lovely contributions. + ## 0.10.14 (May 21st, 2021) ### 🐛 Bug Fixes diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b71a6e269..5f1f88abb 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -18,7 +18,7 @@ pip install -e . Integration tests will automatically start a Vault server in the background. Just make sure the latest `vault` binary is available in your `PATH`. -1. [Install Vault](https://vaultproject.io/docs/install/index.html) or execute `tests/scripts/install-vault.sh`. Note: by default this script installs the OSS version of Vault. An enterprise trial version of the Vault binary is available for testing (but has an explicitly limited runtime). To run integration test cases requiring enterprise Vault, you can invoke the installation script with: `install-vault.sh 'enterprise'` +1. [Install Vault](https://vaultproject.io/docs/install/index.html) 2. Install requirements ``` diff --git a/docs/conf.py b/docs/conf.py index 05cd35300..16e9101d5 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -6,60 +6,61 @@ # Set up import path to allow the autodoc extension to find the local module code. import os import sys -sys.path.insert(0, os.path.abspath('..')) + +sys.path.insert(0, os.path.abspath("..")) # -- Project information ----------------------------------------------------- -project = u'hvac' -copyright = u'2018-2020, Ian Unruh, Jeffrey Hogan' -author = u'Ian Unruh, Jeffrey Hogan' +project = u"hvac" +copyright = u"2018-2020, Ian Unruh, Jeffrey Hogan" +author = u"Ian Unruh, Jeffrey Hogan" # The short X.Y version -version = '0.10.14' +version = "0.11.0" # The full version, including alpha/beta/rc tags -release = '0.10.14' +release = "0.11.0" # -- General configuration --------------------------------------------------- extensions = [ - 'docs.ext.hvac_doctest', - 'sphinx.ext.autodoc', - 'sphinx.ext.coverage', - 'sphinx.ext.viewcode', - 'sphinx.ext.githubpages', - 'm2r2', - 'autodocsumm', + "docs.ext.hvac_doctest", + "sphinx.ext.autodoc", + "sphinx.ext.coverage", + "sphinx.ext.viewcode", + "sphinx.ext.githubpages", + "m2r2", + "autodocsumm", ] # Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] +templates_path = ["_templates"] -source_suffix = ['.rst', '.md'] +source_suffix = [".rst", ".md"] # The master toctree document. -master_doc = 'index' +master_doc = "index" language = None -exclude_patterns = [u'_build', 'Thumbs.db', '.DS_Store'] -pygments_style = 'sphinx' +exclude_patterns = [u"_build", "Thumbs.db", ".DS_Store"] +pygments_style = "sphinx" # -- Options for HTML output ------------------------------------------------- -html_theme = 'sphinx_rtd_theme' -html_static_path = ['_static'] -html_context = {'no_skippy': True} +html_theme = "sphinx_rtd_theme" +html_static_path = ["_static"] +html_context = {"no_skippy": True} html_theme_options = { # Toc options - 'collapse_navigation': False, + "collapse_navigation": False, } # -- Options for HTMLHelp output --------------------------------------------- # Output file base name for HTML help builder. -htmlhelp_basename = 'hvacdoc' +htmlhelp_basename = "hvacdoc" # -- Options for Epub output ------------------------------------------------- @@ -70,13 +71,13 @@ epub_copyright = copyright # A list of files that should not be packed into the epub file. -epub_exclude_files = ['search.html'] +epub_exclude_files = ["search.html"] # -- doctest configuration ------------------------------------------------- -if os.getenv('READ_THE_DOCS_BUILD') is not None: +if os.getenv("READ_THE_DOCS_BUILD") is not None: doctest_global_enabled = False -doctest_global_setup = ''' +doctest_global_setup = """ import os from pprint import pprint, pformat @@ -93,17 +94,17 @@ manager, mocker = doctest_global_setup() client = manager.client -''' +""" -doctest_global_cleanup = ''' +doctest_global_cleanup = """ mocker.stop() manager.stop() -''' +""" # -- Autodoc configuration ------------------------------------------------- autodoc_default_options = { - 'autosummary': True, + "autosummary": True, } diff --git a/docs/ext/hvac_doctest.py b/docs/ext/hvac_doctest.py index 712d5c524..9dd6f707c 100644 --- a/docs/ext/hvac_doctest.py +++ b/docs/ext/hvac_doctest.py @@ -35,23 +35,38 @@ if False: # For type annotation - from typing import Any, Callable, Dict, IO, Iterable, List, Optional, Sequence, Set, Tuple # NOQA + from typing import ( + Any, + Callable, + Dict, + IO, + Iterable, + List, + Optional, + Sequence, + Set, + Tuple, + ) # NOQA from sphinx.application import Sphinx # NOQA logger = logging.getLogger(__name__) -blankline_re = re.compile(r'^\s*', re.MULTILINE) -doctestopt_re = re.compile(r'#\s*doctest:.+$', re.MULTILINE) +blankline_re = re.compile(r"^\s*", re.MULTILINE) +doctestopt_re = re.compile(r"#\s*doctest:.+$", re.MULTILINE) if PY2: + def doctest_encode(text, encoding): # type: (str, unicode) -> unicode if isinstance(text, text_type): text = text.encode(encoding) if text.startswith(codecs.BOM_UTF8): - text = text[len(codecs.BOM_UTF8):] + text = text[len(codecs.BOM_UTF8) :] return text + + else: + def doctest_encode(text, encoding): # type: (unicode, unicode) -> unicode return text @@ -87,6 +102,7 @@ def check_output(self, want, got, optionflags): # set up the necessary directives + class TestDirective(SphinxDirective): """ Base class for doctest-related directives. @@ -99,8 +115,8 @@ class TestDirective(SphinxDirective): def run(self): # type: () -> List[nodes.Node] - if 'skipif' in self.options: - condition = self.options['skipif'] + if "skipif" in self.options: + condition = self.options["skipif"] context = {} # type: Dict[str, Any] if self.config.doctest_global_enabled: if self.config.doctest_global_setup: @@ -112,99 +128,101 @@ def run(self): return [] # use ordinary docutils nodes for test code: they get special attributes # so that our builder recognizes them, and the other builders are happy. - code = '\n'.join(self.content) + code = "\n".join(self.content) test = None - if self.name == 'doctest': - if '' in code: + if self.name == "doctest": + if "" in code: # convert s to ordinary blank lines for presentation test = code - code = blankline_re.sub('', code) + code = blankline_re.sub("", code) if doctestopt_re.search(code): if not test: test = code - code = doctestopt_re.sub('', code) + code = doctestopt_re.sub("", code) nodetype = nodes.literal_block - if self.name in ('testsetup', 'testcleanup') or 'hide' in self.options: + if self.name in ("testsetup", "testcleanup") or "hide" in self.options: nodetype = nodes.comment if self.arguments: - groups = [x.strip() for x in self.arguments[0].split(',')] + groups = [x.strip() for x in self.arguments[0].split(",")] else: - groups = ['default'] + groups = ["default"] node = nodetype(code, code, testnodetype=self.name, groups=groups) set_source_info(self, node) if test is not None: # only save if it differs from code - node['test'] = test - if self.name == 'doctest': - node['language'] = 'pycon' - elif self.name == 'testcode': - node['language'] = 'python' - elif self.name == 'testoutput': + node["test"] = test + if self.name == "doctest": + node["language"] = "pycon" + elif self.name == "testcode": + node["language"] = "python" + elif self.name == "testoutput": # don't try to highlight output - node['language'] = 'none' - node['options'] = {} - if self.name in ('doctest', 'testoutput') and 'options' in self.options: + node["language"] = "none" + node["options"] = {} + if self.name in ("doctest", "testoutput") and "options" in self.options: # parse doctest-like output comparison flags - option_strings = self.options['options'].replace(',', ' ').split() + option_strings = self.options["options"].replace(",", " ").split() for option in option_strings: prefix, option_name = option[0], option[1:] - if prefix not in '+-': + if prefix not in "+-": self.state.document.reporter.warning( __("missing '+' or '-' in '%s' option.") % option, - line=self.lineno) + line=self.lineno, + ) continue if option_name not in doctest.OPTIONFLAGS_BY_NAME: self.state.document.reporter.warning( __("'%s' is not a valid option.") % option_name, - line=self.lineno) + line=self.lineno, + ) continue flag = doctest.OPTIONFLAGS_BY_NAME[option[1:]] - node['options'][flag] = (option[0] == '+') - if self.name == 'doctest' and 'pyversion' in self.options: + node["options"][flag] = option[0] == "+" + if self.name == "doctest" and "pyversion" in self.options: try: - spec = self.options['pyversion'] - python_version = '.'.join([str(v) for v in sys.version_info[:3]]) + spec = self.options["pyversion"] + python_version = ".".join([str(v) for v in sys.version_info[:3]]) if not is_allowed_version(spec, python_version): - flag = doctest.OPTIONFLAGS_BY_NAME['SKIP'] - node['options'][flag] = True # Skip the test + flag = doctest.OPTIONFLAGS_BY_NAME["SKIP"] + node["options"][flag] = True # Skip the test except InvalidSpecifier: self.state.document.reporter.warning( - __("'%s' is not a valid pyversion option") % spec, - line=self.lineno) + __("'%s' is not a valid pyversion option") % spec, line=self.lineno + ) return [node] class TestsetupDirective(TestDirective): - option_spec = {'skipif': directives.unchanged_required} # type: Dict + option_spec = {"skipif": directives.unchanged_required} # type: Dict class TestcleanupDirective(TestDirective): - option_spec = {'skipif': directives.unchanged_required} # type: Dict + option_spec = {"skipif": directives.unchanged_required} # type: Dict class DoctestDirective(TestDirective): option_spec = { - 'hide': directives.flag, - 'options': directives.unchanged, - 'pyversion': directives.unchanged_required, - 'skipif': directives.unchanged_required, + "hide": directives.flag, + "options": directives.unchanged, + "pyversion": directives.unchanged_required, + "skipif": directives.unchanged_required, } class TestcodeDirective(TestDirective): option_spec = { - 'hide': directives.flag, - 'pyversion': directives.unchanged_required, - 'skipif': directives.unchanged_required, + "hide": directives.flag, + "pyversion": directives.unchanged_required, + "skipif": directives.unchanged_required, } class TestoutputDirective(TestDirective): option_spec = { - 'hide': directives.flag, - 'options': directives.unchanged, - 'pyversion': directives.unchanged_required, - 'skipif': directives.unchanged_required, + "hide": directives.flag, + "options": directives.unchanged, + "pyversion": directives.unchanged_required, + "skipif": directives.unchanged_required, } @@ -213,37 +231,42 @@ class TestoutputDirective(TestDirective): # helper classes + class TestGroup(object): def __init__(self, name): # type: (unicode) -> None self.name = name - self.setup = [] # type: List[TestCode] - self.tests = [] # type: List[List[TestCode]] - self.cleanup = [] # type: List[TestCode] + self.setup = [] # type: List[TestCode] + self.tests = [] # type: List[List[TestCode]] + self.cleanup = [] # type: List[TestCode] def add_code(self, code, prepend=False): # type: (TestCode, bool) -> None - if code.type == 'testsetup': + if code.type == "testsetup": if prepend: self.setup.insert(0, code) else: self.setup.append(code) - elif code.type == 'testcleanup': + elif code.type == "testcleanup": self.cleanup.append(code) - elif code.type == 'doctest': + elif code.type == "doctest": self.tests.append([code]) - elif code.type == 'testcode': + elif code.type == "testcode": self.tests.append([code, None]) - elif code.type == 'testoutput': + elif code.type == "testoutput": if self.tests and len(self.tests[-1]) == 2: self.tests[-1][1] = code else: - raise RuntimeError(__('invalid TestCode type')) + raise RuntimeError(__("invalid TestCode type")) def __repr__(self): # type: ignore # type: () -> unicode - return 'TestGroup(name=%r, setup=%r, cleanup=%r, tests=%r)' % ( - self.name, self.setup, self.cleanup, self.tests) + return "TestGroup(name=%r, setup=%r, cleanup=%r, tests=%r)" % ( + self.name, + self.setup, + self.cleanup, + self.tests, + ) class TestCode(object): @@ -257,12 +280,16 @@ def __init__(self, code, type, filename, lineno, options=None): def __repr__(self): # type: ignore # type: () -> unicode - return 'TestCode(%r, %r, filename=%r, lineno=%r, options=%r)' % ( - self.code, self.type, self.filename, self.lineno, self.options) + return "TestCode(%r, %r, filename=%r, lineno=%r, options=%r)" % ( + self.code, + self.type, + self.filename, + self.lineno, + self.options, + ) class SphinxDocTestRunner(doctest.DocTestRunner): - def __init__(self, *args, **kwargs): # HACK: workaround unicode issues for testcode directives on Python 2.7 versus 3.x doctest.DocTestRunner.__init__(self, *args, checker=Py23DocChecker(), **kwargs) @@ -279,14 +306,13 @@ def summarize(self, out, verbose=None): # type: ignore out(string_io.getvalue()) return res - def _DocTestRunner__patched_linecache_getlines(self, filename, - module_globals=None): + def _DocTestRunner__patched_linecache_getlines(self, filename, module_globals=None): # type: (unicode, Any) -> Any # this is overridden from DocTestRunner adding the try-except below m = self._DocTestRunner__LINECACHE_FILENAME_RE.match(filename) # type: ignore - if m and m.group('name') == self.test.name: + if m and m.group("name") == self.test.name: try: - example = self.test.examples[int(m.group('examplenum'))] + example = self.test.examples[int(m.group("examplenum"))] # because we compile multiple doctest blocks with the same name # (viz. the group name) this might, for outer stack frames in a # traceback, get the wrong test which might not have enough examples @@ -299,13 +325,17 @@ def _DocTestRunner__patched_linecache_getlines(self, filename, # the new builder -- use sphinx-build.py -b doctest to run + class DocTestBuilder(Builder): """ Runs test snippets in the documentation. """ - name = 'doctest' - epilog = __('Testing of doctests in the sources finished, look at the ' - 'results in %(outdir)s/output.txt.') + + name = "doctest" + epilog = __( + "Testing of doctests in the sources finished, look at the " + "results in %(outdir)s/output.txt." + ) def init(self): # type: () -> None @@ -321,7 +351,7 @@ def init(self): sys.path[0:0] = self.config.doctest_path - self.type = 'single' + self.type = "single" self.total_failures = 0 self.total_tries = 0 @@ -330,14 +360,19 @@ def init(self): self.cleanup_failures = 0 self.cleanup_tries = 0 - date = time.strftime('%Y-%m-%d %H:%M:%S') + date = time.strftime("%Y-%m-%d %H:%M:%S") self.outfile = None # type: IO - self.outfile = codecs.open(path.join(self.outdir, 'output.txt'), # type: ignore - 'w', encoding='utf-8') - self.outfile.write(('Results of doctest builder run on %s\n' - '==================================%s\n') % - (date, '=' * len(date))) + self.outfile = codecs.open( + path.join(self.outdir, "output.txt"), "w", encoding="utf-8" # type: ignore + ) + self.outfile.write( + ( + "Results of doctest builder run on %s\n" + "==================================%s\n" + ) + % (date, "=" * len(date)) + ) def _out(self, text): # type: (unicode) -> None @@ -356,7 +391,7 @@ def _warn_out(self, text): def get_target_uri(self, docname, typ=None): # type: (unicode, unicode) -> unicode - return '' + return "" def get_outdated_docs(self): # type: () -> Set[unicode] @@ -367,30 +402,40 @@ def finish(self): # write executive summary def s(v): # type: (int) -> unicode - return v != 1 and 's' or '' - repl = (self.total_tries, s(self.total_tries), - self.total_failures, s(self.total_failures), - self.setup_failures, s(self.setup_failures), - self.cleanup_failures, s(self.cleanup_failures)) - self._out(''' + return v != 1 and "s" or "" + + repl = ( + self.total_tries, + s(self.total_tries), + self.total_failures, + s(self.total_failures), + self.setup_failures, + s(self.setup_failures), + self.cleanup_failures, + s(self.cleanup_failures), + ) + self._out( + """ Doctest summary =============== %5d test%s %5d failure%s in tests %5d failure%s in setup code %5d failure%s in cleanup code -''' % repl) +""" + % repl + ) self.outfile.close() if self.total_failures or self.setup_failures or self.cleanup_failures: self.app.statuscode = 1 - def write(self, build_docnames, updated_docnames, method='update'): + def write(self, build_docnames, updated_docnames, method="update"): # type: (Iterable[unicode], Sequence[unicode], unicode) -> None if build_docnames is None: build_docnames = sorted(self.env.all_docs) - logger.info(bold('running tests...')) + logger.info(bold("running tests...")) for docname in build_docnames: # no need to resolve the doctree doctree = self.env.get_doctree(docname) @@ -401,8 +446,9 @@ def get_filename_for_node(self, node, docname): """Try to get the file which actually contains the doctest, not the filename of the document it's included in.""" try: - filename = relpath(node.source, self.env.srcdir)\ - .rsplit(':docstring of ', maxsplit=1)[0] + filename = relpath(node.source, self.env.srcdir).rsplit( + ":docstring of ", maxsplit=1 + )[0] except Exception: filename = self.env.doc2path(docname, base=None) if PY2: @@ -415,7 +461,7 @@ def get_line_number(node): """Get the real line number or admit we don't know.""" # TODO: Work out how to store or calculate real (file-relative) # line numbers for doctest blocks in docstrings. - if ':docstring of ' in path.basename(node.source or ''): + if ":docstring of " in path.basename(node.source or ""): # The line number is given relative to the stripped docstring, # not the file. This is correct where it is set, in # `docutils.nodes.Node.setup_child`, but Sphinx should report @@ -430,40 +476,51 @@ def test_doc(self, docname, doctree): # type: (unicode, nodes.Node) -> None groups = {} # type: Dict[unicode, TestGroup] add_to_all_groups = [] - self.setup_runner = SphinxDocTestRunner(verbose=False, - optionflags=self.opt) - self.test_runner = SphinxDocTestRunner(verbose=False, - optionflags=self.opt) - self.cleanup_runner = SphinxDocTestRunner(verbose=False, - optionflags=self.opt) + self.setup_runner = SphinxDocTestRunner(verbose=False, optionflags=self.opt) + self.test_runner = SphinxDocTestRunner(verbose=False, optionflags=self.opt) + self.cleanup_runner = SphinxDocTestRunner(verbose=False, optionflags=self.opt) self.test_runner._fakeout = self.setup_runner._fakeout # type: ignore self.cleanup_runner._fakeout = self.setup_runner._fakeout # type: ignore if self.config.doctest_test_doctest_blocks: + def condition(node): # type: (nodes.Node) -> bool - return (isinstance(node, (nodes.literal_block, nodes.comment)) and - 'testnodetype' in node) or \ - isinstance(node, nodes.doctest_block) + return ( + isinstance(node, (nodes.literal_block, nodes.comment)) + and "testnodetype" in node + ) or isinstance(node, nodes.doctest_block) + else: + def condition(node): # type: (nodes.Node) -> bool - return isinstance(node, (nodes.literal_block, nodes.comment)) \ - and 'testnodetype' in node + return ( + isinstance(node, (nodes.literal_block, nodes.comment)) + and "testnodetype" in node + ) + for node in doctree.traverse(condition): - source = node['test'] if 'test' in node else node.astext() + source = node["test"] if "test" in node else node.astext() filename = self.get_filename_for_node(node, docname) line_number = self.get_line_number(node) if not source: - logger.warning(__('no code/output in %s block at %s:%s'), - node.get('testnodetype', 'doctest'), - filename, line_number) - code = TestCode(source, type=node.get('testnodetype', 'doctest'), - filename=filename, lineno=line_number, - options=node.get('options')) - node_groups = node.get('groups', ['default']) - if '*' in node_groups: + logger.warning( + __("no code/output in %s block at %s:%s"), + node.get("testnodetype", "doctest"), + filename, + line_number, + ) + code = TestCode( + source, + type=node.get("testnodetype", "doctest"), + filename=filename, + lineno=line_number, + options=node.get("options"), + ) + node_groups = node.get("groups", ["default"]) + if "*" in node_groups: add_to_all_groups.append(code) continue for groupname in node_groups: @@ -474,20 +531,24 @@ def condition(node): for group in itervalues(groups): group.add_code(code) if self.config.doctest_global_setup: - code = TestCode(self.config.doctest_global_setup, - 'testsetup', filename=None, lineno=0) + code = TestCode( + self.config.doctest_global_setup, "testsetup", filename=None, lineno=0 + ) for group in itervalues(groups): group.add_code(code, prepend=True) if self.config.doctest_global_cleanup: - code = TestCode(self.config.doctest_global_cleanup, - 'testcleanup', filename=None, lineno=0) + code = TestCode( + self.config.doctest_global_cleanup, + "testcleanup", + filename=None, + lineno=0, + ) for group in itervalues(groups): group.add_code(code) if not groups: return - self._out('\nDocument: %s\n----------%s\n' % - (docname, '-' * len(docname))) + self._out("\nDocument: %s\n----------%s\n" % (docname, "-" * len(docname))) for group in itervalues(groups): self.test_group(group) # Separately count results from setup code @@ -499,8 +560,7 @@ def condition(node): self.total_failures += res_f self.total_tries += res_t if self.cleanup_runner.tries: - res_f, res_t = self.cleanup_runner.summarize(self._out, - verbose=True) + res_f, res_t = self.cleanup_runner.summarize(self._out, verbose=True) self.cleanup_failures += res_f self.cleanup_tries += res_t @@ -519,25 +579,34 @@ def run_setup_cleanup(runner, testcodes, what): # type: (Any, List[TestCode], Any) -> bool examples = [] for testcode in testcodes: - examples.append(doctest.Example( # type: ignore - doctest_encode(testcode.code, self.env.config.source_encoding), '', # type: ignore # NOQA - lineno=testcode.lineno)) + examples.append( + doctest.Example( # type: ignore + doctest_encode(testcode.code, self.env.config.source_encoding), + "", # type: ignore # NOQA + lineno=testcode.lineno, + ) + ) if not examples: return True # simulate a doctest with the code - sim_doctest = doctest.DocTest(examples, {}, - '%s (%s code)' % (group.name, what), - testcodes[0].filename, 0, None) + sim_doctest = doctest.DocTest( + examples, + {}, + "%s (%s code)" % (group.name, what), + testcodes[0].filename, + 0, + None, + ) sim_doctest.globs = ns old_f = runner.failures - self.type = 'exec' # the snippet may contain multiple statements + self.type = "exec" # the snippet may contain multiple statements runner.run(sim_doctest, out=self._warn_out, clear_globs=False) if runner.failures > old_f: return False return True # run the setup code - if not run_setup_cleanup(self.setup_runner, group.setup, 'setup'): + if not run_setup_cleanup(self.setup_runner, group.setup, "setup"): # if setup failed, don't run the group return @@ -547,11 +616,18 @@ def run_setup_cleanup(runner, testcodes, what): # ordinary doctests (code/output interleaved) try: test = parser.get_doctest( # type: ignore - doctest_encode(code[0].code, self.env.config.source_encoding), {}, # type: ignore # NOQA - group.name, code[0].filename, code[0].lineno) + doctest_encode(code[0].code, self.env.config.source_encoding), + {}, # type: ignore # NOQA + group.name, + code[0].filename, + code[0].lineno, + ) except Exception: - logger.warning(__('ignoring invalid doctest code: %r'), code[0].code, - location=(code[0].filename, code[0].lineno)) + logger.warning( + __("ignoring invalid doctest code: %r"), + code[0].code, + location=(code[0].filename, code[0].lineno), + ) continue if not test.examples: continue @@ -560,27 +636,35 @@ def run_setup_cleanup(runner, testcodes, what): new_opt = code[0].options.copy() new_opt.update(example.options) example.options = new_opt - self.type = 'single' # as for ordinary doctests + self.type = "single" # as for ordinary doctests else: # testcode and output separate - output = code[1] and code[1].code or '' + output = code[1] and code[1].code or "" options = code[1] and code[1].options or {} # disable processing as it is not needed options[doctest.DONT_ACCEPT_BLANKLINE] = True # find out if we're testing an exception m = parser._EXCEPTION_RE.match(output) # type: ignore if m: - exc_msg = m.group('msg') + exc_msg = m.group("msg") else: exc_msg = None example = doctest.Example( # type: ignore - doctest_encode(code[0].code, self.env.config.source_encoding), output, # type: ignore # NOQA + doctest_encode(code[0].code, self.env.config.source_encoding), + output, # type: ignore # NOQA exc_msg=exc_msg, lineno=code[0].lineno, - options=options) - test = doctest.DocTest([example], {}, group.name, # type: ignore - code[0].filename, code[0].lineno, None) - self.type = 'exec' # multiple statements again + options=options, + ) + test = doctest.DocTest( + [example], + {}, + group.name, # type: ignore + code[0].filename, + code[0].lineno, + None, + ) + self.type = "exec" # multiple statements again # DocTest.__init__ copies the globs namespace, which we don't want test.globs = ns # also don't clear the globs namespace after running the doctest @@ -588,25 +672,28 @@ def run_setup_cleanup(runner, testcodes, what): self.test_runner.run(test, out=self._warn_out, clear_globs=False) # run the cleanup - run_setup_cleanup(self.cleanup_runner, group.cleanup, 'cleanup') + run_setup_cleanup(self.cleanup_runner, group.cleanup, "cleanup") def setup(app): # type: (Sphinx) -> Dict[unicode, Any] - app.add_directive('testsetup', TestsetupDirective) - app.add_directive('testcleanup', TestcleanupDirective) - app.add_directive('doctest', DoctestDirective) - app.add_directive('testcode', TestcodeDirective) - app.add_directive('testoutput', TestoutputDirective) + app.add_directive("testsetup", TestsetupDirective) + app.add_directive("testcleanup", TestcleanupDirective) + app.add_directive("doctest", DoctestDirective) + app.add_directive("testcode", TestcodeDirective) + app.add_directive("testoutput", TestoutputDirective) app.add_builder(DocTestBuilder) # this config value adds to sys.path - app.add_config_value('doctest_path', [], False) - app.add_config_value('doctest_test_doctest_blocks', 'default', False) - app.add_config_value('doctest_global_setup', '', False) - app.add_config_value('doctest_global_cleanup', '', False) - app.add_config_value('doctest_global_enabled', True, False) + app.add_config_value("doctest_path", [], False) + app.add_config_value("doctest_test_doctest_blocks", "default", False) + app.add_config_value("doctest_global_setup", "", False) + app.add_config_value("doctest_global_cleanup", "", False) + app.add_config_value("doctest_global_enabled", True, False) app.add_config_value( - 'doctest_default_flags', - doctest.DONT_ACCEPT_TRUE_FOR_1 | doctest.ELLIPSIS | doctest.IGNORE_EXCEPTION_DETAIL, - False) - return {'version': sphinx.__display_version__, 'parallel_read_safe': True} + "doctest_default_flags", + doctest.DONT_ACCEPT_TRUE_FOR_1 + | doctest.ELLIPSIS + | doctest.IGNORE_EXCEPTION_DETAIL, + False, + ) + return {"version": sphinx.__display_version__, "parallel_read_safe": True} diff --git a/docs/usage/auth_methods/azure.rst b/docs/usage/auth_methods/azure.rst index b49724102..91de08c53 100644 --- a/docs/usage/auth_methods/azure.rst +++ b/docs/usage/auth_methods/azure.rst @@ -19,14 +19,14 @@ Enabling the Auth Method azure_auth_path = 'company-azure' description = 'Auth method for use by team members in our company's Azure organization' - if '%s/' % azure_auth_path not in vault_client.list_auth_backends(): + if '%s/' % azure_auth_path not in vault_client.sys.list_auth_methods()['data']: print('Enabling the azure auth backend at mount_point: {path}'.format( path=azure_auth_path, )) - client.enable_auth_backend( - backend_type='azure', + client.sys.enable_auth_method( + method_type='azure', description=description, - mount_point=azure_auth_path, + path=azure_auth_path, ) diff --git a/docs/usage/auth_methods/gcp.rst b/docs/usage/auth_methods/gcp.rst index 7149c8807..b24598711 100644 --- a/docs/usage/auth_methods/gcp.rst +++ b/docs/usage/auth_methods/gcp.rst @@ -19,14 +19,14 @@ Source reference: :py:meth:`hvac.v1.Client.enable_auth_backend` gcp_auth_path = 'company-gcp' description = 'Auth method for use by team members in our company's Gcp organization' - if '%s/' % gcp_auth_path not in vault_client.list_auth_backends(): + if '%s/' % gcp_auth_path not in vault_client.sys.list_auth_methods()['data']: print('Enabling the gcp auth backend at mount_point: {path}'.format( path=gcp_auth_path, )) - client.enable_auth_backend( - backend_type='gcp', + client.sys.enable_auth_method( + method_type='gcp', description=description, - mount_point=gcp_auth_path, + path=gcp_auth_path, ) diff --git a/docs/usage/auth_methods/github.rst b/docs/usage/auth_methods/github.rst index 0df4ff65f..39ca0d1fa 100644 --- a/docs/usage/auth_methods/github.rst +++ b/docs/usage/auth_methods/github.rst @@ -17,14 +17,14 @@ Enabling the Auth Method github_auth_path = 'company-github' description = 'Auth method for use by team members in our company's Github organization' - if '%s/' % github_auth_path not in vault_client.list_auth_backends(): + if '%s/' % github_auth_path not in vault_client.sys.list_auth_methods()['data']: print('Enabling the github auth backend at mount_point: {path}'.format( path=github_auth_path, )) - client.enable_auth_backend( - backend_type='github', + client.sys.enable_auth_method( + method_type='github', description=description, - mount_point=github_auth_path, + path=github_auth_path, ) Configure Connection Parameters @@ -149,6 +149,3 @@ Log in and automatically update the underlying "token" attribute on the :py:meth import hvac client = hvac.Client() login_response = client.auth.github.login(token='some personal github token') - - - diff --git a/docs/usage/auth_methods/ldap.rst b/docs/usage/auth_methods/ldap.rst index 569bd07ce..60b23c724 100644 --- a/docs/usage/auth_methods/ldap.rst +++ b/docs/usage/auth_methods/ldap.rst @@ -17,14 +17,14 @@ Enabling the LDAP Auth Method ldap_auth_path = 'company-ldap' description = "Auth method for use by team members in our company's LDAP organization" - if '%s/' % ldap_auth_path not in vault_client.sys.list_auth_methods(): + if '%s/' % ldap_auth_path not in vault_client.sys.list_auth_methods()['data']: print('Enabling the ldap auth backend at mount_point: {path}'.format( path=ldap_auth_path, )) - client.enable_auth_backend( - backend_type='ldap', + client.sys.enable_auth_method( + method_type='ldap', description=description, - mount_point=ldap_auth_path, + path=ldap_auth_path, ) diff --git a/docs/usage/auth_methods/mfa.rst b/docs/usage/auth_methods/mfa.rst index 85fb1d98a..ea241bb38 100644 --- a/docs/usage/auth_methods/mfa.rst +++ b/docs/usage/auth_methods/mfa.rst @@ -18,13 +18,13 @@ Configure MFA Auth Method Settings userpass_auth_path = 'some-userpass' - if '%s/' % userpass_auth_path not in vault_client.list_auth_backends(): + if '%s/' % userpass_auth_path not in vault_client.sys.list_auth_methods()['data']: print('Enabling the userpass auth backend at mount_point: {path}'.format( path=userpass_auth_path, )) - client.enable_auth_backend( - backend_type='userpass', - mount_point=userpass_auth_path, + client.sys.enable_auth_method( + method_type='userpass', + path=userpass_auth_path, ) client.auth.mfa.configure( diff --git a/docs/usage/auth_methods/okta.rst b/docs/usage/auth_methods/okta.rst index 95fdb8f3a..6aadc174e 100644 --- a/docs/usage/auth_methods/okta.rst +++ b/docs/usage/auth_methods/okta.rst @@ -7,7 +7,7 @@ Okta Enabling the Auth Method ------------------------ -Source reference: :py:meth:`hvac.v1.Client.enable_secret_backend` +Source reference: :py:meth:`hvac.v1.client.sys.enable_secrets_engine` .. code:: python @@ -17,14 +17,14 @@ Source reference: :py:meth:`hvac.v1.Client.enable_secret_backend` okta_path = 'company-okta' description = 'Auth method for use by team members in our company's Okta organization' - if '%s/' % okta_path not in vault_client.sys.list_auth_methods(): + if '%s/' % okta_path not in vault_client.sys.list_auth_methods()['data']: print('Enabling the okta secret backend at mount_point: {path}'.format( path=okta_secret_path, )) - client.enable_secret_backend( - backend_type='okta', + client.sys.enable_auth_method( + method_type='okta', description=description, - mount_point=okta_secret_path, + path=okta_secret_path, ) diff --git a/docs/usage/auth_methods/token.rst b/docs/usage/auth_methods/token.rst index 9382876bc..70ad8479f 100644 --- a/docs/usage/auth_methods/token.rst +++ b/docs/usage/auth_methods/token.rst @@ -17,35 +17,33 @@ Token creation and revocation: .. code:: python - token = client.create_token(policies=['root'], lease='1h') + token = client.auth.token.create(policies=['root'], lease='1h') - current_token = client.lookup_token() - some_other_token = client.lookup_token('xxx') + current_token = client.auth.token.lookup() + some_other_token = client.auth.token.lookup('xxx') - client.revoke_token('xxx') - client.revoke_token('yyy', orphan=True) + client.auth.token.revoke('xxx') + client.auth.token.revoke('yyy', orphan=True) - client.revoke_token_prefix('zzz') - - client.renew_token('aaa') + client.auth.token.renew('aaa') Lookup and revoke tokens via a token accessor: .. code:: python - token = client.create_token(policies=['root'], lease='1h') + token = client.auth.token.create(policies=['root'], lease='1h') token_accessor = token['auth']['accessor'] - same_token = client.lookup_token(token_accessor, accessor=True) - client.revoke_token(token_accessor, accessor=True) + same_token = client.auth.token.lookup(token_accessor, accessor=True) + client.auth.token.revoke(token_accessor, accessor=True) Wrapping/unwrapping a token: .. code:: python - wrap = client.create_token(policies=['root'], lease='1h', wrap_ttl='1m') + wrap = client.auth.token.create(policies=['root'], lease='1h', wrap_ttl='1m') result = self.client.unwrap(wrap['wrap_info']['token']) @@ -53,7 +51,7 @@ Login with a wrapped token: .. code:: python - wrap = client.create_token(policies=['root'], lease='1h', wrap_ttl='1m') + wrap = client.auth.token.create(policies=['root'], lease='1h', wrap_ttl='1m') new_client = hvac.Client() new_client.auth_cubbyhole(wrap['wrap_info']['token']) assert new_client.token != wrapped_token['wrap_info']['token'] diff --git a/hvac/__init__.py b/hvac/__init__.py index 640719bfc..b8594ac28 100644 --- a/hvac/__init__.py +++ b/hvac/__init__.py @@ -1,5 +1,3 @@ from hvac.v1 import Client -__all__ = ( - 'Client', -) +__all__ = ("Client",) diff --git a/hvac/adapters.py b/hvac/adapters.py index 9963ab228..ec50ad994 100644 --- a/hvac/adapters.py +++ b/hvac/adapters.py @@ -9,16 +9,28 @@ import requests.exceptions from hvac import utils - -DEFAULT_BASE_URI = 'http://localhost:8200' +from hvac.constants.client import DEFAULT_URL class Adapter(object): """Abstract base class used when constructing adapters for use with the Client class.""" + __metaclass__ = ABCMeta - def __init__(self, base_uri=DEFAULT_BASE_URI, token=None, cert=None, verify=True, timeout=30, proxies=None, - allow_redirects=True, session=None, namespace=None, ignore_exceptions=False, strict_http=False): + 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, + ): """Create a new request adapter instance. :param base_uri: Base URL for the Vault instance being addressed. @@ -60,10 +72,10 @@ def __init__(self, base_uri=DEFAULT_BASE_URI, token=None, cert=None, verify=True self.strict_http = strict_http self._kwargs = { - 'cert': cert, - 'verify': verify, - 'timeout': timeout, - 'proxies': proxies, + "cert": cert, + "verify": verify, + "timeout": timeout, + "proxies": proxies, } @staticmethod @@ -76,11 +88,10 @@ def urljoin(*args): :rtype: str | unicode """ - return '/'.join(map(lambda x: str(x).strip('/'), args)) + return "/".join(map(lambda x: str(x).strip("/"), args)) def close(self): - """Close the underlying Requests session. - """ + """Close the underlying Requests session.""" self.session.close() def get(self, url, **kwargs): @@ -94,7 +105,7 @@ def get(self, url, **kwargs): :return: The response of the request. :rtype: requests.Response """ - return self.request('get', url, **kwargs) + return self.request("get", url, **kwargs) def post(self, url, **kwargs): """Performs a POST request. @@ -107,7 +118,7 @@ def post(self, url, **kwargs): :return: The response of the request. :rtype: requests.Response """ - return self.request('post', url, **kwargs) + return self.request("post", url, **kwargs) def put(self, url, **kwargs): """Performs a PUT request. @@ -120,7 +131,7 @@ def put(self, url, **kwargs): :return: The response of the request. :rtype: requests.Response """ - return self.request('put', url, **kwargs) + return self.request("put", url, **kwargs) def delete(self, url, **kwargs): """Performs a DELETE request. @@ -133,7 +144,7 @@ def delete(self, url, **kwargs): :return: The response of the request. :rtype: requests.Response """ - return self.request('delete', url, **kwargs) + return self.request("delete", url, **kwargs) def list(self, url, **kwargs): """Performs a LIST request. @@ -146,7 +157,7 @@ def list(self, url, **kwargs): :return: The response of the request. :rtype: requests.Response """ - return self.request('list', url, **kwargs) + return self.request("list", url, **kwargs) def head(self, url, **kwargs): """Performs a HEAD request. @@ -159,7 +170,7 @@ def head(self, url, **kwargs): :return: The response of the request. :rtype: requests.Response """ - return self.request('head', url, **kwargs) + return self.request("head", url, **kwargs) def login(self, url, use_token=True, **kwargs): """Perform a login request. @@ -196,15 +207,11 @@ def get_login_token(self, response): return NotImplementedError @utils.deprecated_method( - to_be_removed_in_version='0.9.0', + to_be_removed_in_version="0.9.0", new_method=login, ) def auth(self, url, use_token=True, **kwargs): - return self.login( - url=url, - use_token=use_token, - **kwargs - ) + return self.login(url=url, use_token=use_token, **kwargs) @abstractmethod def request(self, method, url, headers=None, raise_exception=True, **kwargs): @@ -244,7 +251,7 @@ def get_login_token(self, response): :rtype: str """ response_json = response.json() - return response_json['auth']['client_token'] + 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. @@ -264,10 +271,10 @@ def request(self, method, url, headers=None, raise_exception=True, **kwargs): :return: The response of the request. :rtype: requests.Response """ - while '//' in url: + 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 = url.replace("//", "/") url = self.urljoin(self.base_uri, url) @@ -275,25 +282,25 @@ def request(self, method, url, headers=None, raise_exception=True, **kwargs): headers = {} if self.token: - headers['X-Vault-Token'] = self.token + headers["X-Vault-Token"] = self.token if self.namespace: - headers['X-Vault-Namespace'] = self.namespace + headers["X-Vault-Namespace"] = self.namespace - wrap_ttl = kwargs.pop('wrap_ttl', None) + wrap_ttl = kwargs.pop("wrap_ttl", None) if wrap_ttl: - headers['X-Vault-Wrap-TTL'] = str(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',): + 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 + params = _kwargs.get("params", {}) + if method.lower() == "list": + method = "get" + params.update({"list": "true"}) + _kwargs["params"] = params response = self.session.request( method=method, @@ -305,19 +312,15 @@ def request(self, method, url, headers=None, raise_exception=True, **kwargs): if not response.ok and (raise_exception and not self.ignore_exceptions): text = errors = None - if response.headers.get('Content-Type') == 'application/json': + if response.headers.get("Content-Type") == "application/json": try: - errors = response.json().get('errors') + errors = response.json().get("errors") except Exception: pass if errors is None: text = response.text utils.raise_for_error( - method, - url, - response.status_code, - text, - errors=errors + method, url, response.status_code, text, errors=errors ) return response @@ -338,7 +341,7 @@ def get_login_token(self, response): :return: A client token. :rtype: str """ - return response['auth']['client_token'] + return response["auth"]["client_token"] def request(self, *args, **kwargs): """Main method for routing HTTP requests to the configured Vault base_uri. diff --git a/hvac/api/__init__.py b/hvac/api/__init__.py index 2160129b6..d8d3d9391 100644 --- a/hvac/api/__init__.py +++ b/hvac/api/__init__.py @@ -6,9 +6,9 @@ from hvac.api.vault_api_category import VaultApiCategory __all__ = ( - 'AuthMethods', - 'SecretsEngines', - 'SystemBackend', - 'VaultApiBase', - 'VaultApiCategory', + "AuthMethods", + "SecretsEngines", + "SystemBackend", + "VaultApiBase", + "VaultApiCategory", ) diff --git a/hvac/api/auth_methods/__init__.py b/hvac/api/auth_methods/__init__.py index 1c77ffb83..a979b6670 100644 --- a/hvac/api/auth_methods/__init__.py +++ b/hvac/api/auth_methods/__init__.py @@ -14,32 +14,35 @@ 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 from hvac.utils import generate_method_deprecation_message __all__ = ( - 'AuthMethods', - 'AppRole', - 'Azure', - 'Gcp', - 'Github', - 'JWT', - 'Kubernetes', - 'Ldap', - 'Userpass', - 'Mfa', - 'OIDC', - 'Okta', - 'Radius', - 'Aws', - 'Cert', + "AuthMethods", + "AppRole", + "Azure", + "Gcp", + "Github", + "JWT", + "Kubernetes", + "Ldap", + "Userpass", + "Mfa", + "OIDC", + "Okta", + "Radius", + "Token", + "Aws", + "Cert", ) class AuthMethods(VaultApiCategory): """Auth Methods.""" + implemented_classes = [ AppRole, Azure, @@ -53,13 +56,13 @@ class AuthMethods(VaultApiCategory): OIDC, Okta, Radius, + Token, Aws, Cert, ] unimplemented_classes = [ - 'AppId', - 'AliCloud', - 'Token', + "AppId", + "AliCloud", ] def __call__(self, *args, **kwargs): @@ -69,17 +72,17 @@ def __call__(self, *args, **kwargs): this class. """ deprecation_message = generate_method_deprecation_message( - to_be_removed_in_version='0.9.0', - old_method_name='auth', - method_name='login', - module_name='adapters.Request', + to_be_removed_in_version="0.9.0", + old_method_name="auth", + method_name="login", + module_name="adapters.Request", ) - warnings.simplefilter('always', DeprecationWarning) + warnings.simplefilter("always", DeprecationWarning) warnings.warn( message=deprecation_message, category=DeprecationWarning, stacklevel=2, ) - warnings.simplefilter('default', DeprecationWarning) + warnings.simplefilter("default", DeprecationWarning) return self._adapter.login(*args, **kwargs) diff --git a/hvac/api/auth_methods/approle.py b/hvac/api/auth_methods/approle.py index 1fa94260d..5006c9d49 100644 --- a/hvac/api/auth_methods/approle.py +++ b/hvac/api/auth_methods/approle.py @@ -13,12 +13,25 @@ class AppRole(VaultApiBase): 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): + 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. @@ -67,17 +80,19 @@ def create_or_update_approle(self, role_name, bind_secret_id=None, secret_id_bou :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 + "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), - )) + raise exceptions.ParamValidationError( + error_msg.format( + arg=token_type, + token_types=",".join(ALLOWED_TOKEN_TYPES), + ) + ) params = dict() @@ -90,25 +105,27 @@ def create_or_update_approle(self, role_name, bind_secret_id=None, secret_id_bou 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 - }) + 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}', + "/v1/auth/{mount_point}/role/{name}", mount_point=mount_point, - name=role_name + name=role_name, ) return self._adapter.post(url=api_path, json=params) @@ -125,8 +142,7 @@ def list_roles(self, mount_point=DEFAULT_MOUNT_POINT): :rtype: dict """ api_path = utils.format_url( - '/v1/auth/{mount_point}/role', - mount_point=mount_point + "/v1/auth/{mount_point}/role", mount_point=mount_point ) return self._adapter.list(url=api_path) @@ -145,9 +161,9 @@ def read_role(self, role_name, mount_point=DEFAULT_MOUNT_POINT): :rtype: dict """ api_path = utils.format_url( - '/v1/auth/{mount_point}/role/{role_name}', + "/v1/auth/{mount_point}/role/{role_name}", mount_point=mount_point, - role_name=role_name + role_name=role_name, ) return self._adapter.get(url=api_path) @@ -164,9 +180,9 @@ def delete_role(self, role_name, mount_point=DEFAULT_MOUNT_POINT): :type mount_point: str | unicode """ api_path = utils.format_url( - '/v1/auth/{mount_point}/role/{role_name}', + "/v1/auth/{mount_point}/role/{role_name}", mount_point=mount_point, - role_name=role_name + role_name=role_name, ) return self._adapter.delete(url=api_path) @@ -185,9 +201,9 @@ def read_role_id(self, role_name, mount_point=DEFAULT_MOUNT_POINT): :rtype: dict """ api_path = utils.format_url( - '/v1/auth/{mount_point}/role/{role_name}/role-id', + "/v1/auth/{mount_point}/role/{role_name}/role-id", mount_point=mount_point, - role_name=role_name + role_name=role_name, ) return self._adapter.get(url=api_path) @@ -207,18 +223,23 @@ def update_role_id(self, role_name, role_id, mount_point=DEFAULT_MOUNT_POINT): :return: The JSON response of the read_role_id request. :rtype: dict """ - params = { - 'role_id': role_id - } + params = {"role_id": role_id} api_path = utils.format_url( - '/v1/auth/{mount_point}/role/{role_name}/role-id', + "/v1/auth/{mount_point}/role/{role_name}/role-id", mount_point=mount_point, - role_name=role_name + 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): + def generate_secret_id( + self, + role_name, + metadata=None, + cidr_list=None, + token_bound_cidrs=None, + mount_point=DEFAULT_MOUNT_POINT, + ): """ Generates and issues a new Secret ID on a role in the auth method. @@ -240,18 +261,18 @@ def generate_secret_id(self, role_name, metadata=None, cidr_list=None, token_bou """ 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), - )) + raise exceptions.ParamValidationError( + error_msg.format( + arg=metadata, + arg_type=type(metadata), + ) + ) - params = { - 'metadata': json.dumps(metadata) if metadata else metadata - } + params = {"metadata": json.dumps(metadata) if metadata else metadata} list_of_strings_params = { - 'cidr_list': cidr_list, - 'token_bound_cidrs': token_bound_cidrs + "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( @@ -262,14 +283,21 @@ def generate_secret_id(self, role_name, metadata=None, cidr_list=None, token_bou params[param_name] = list_to_comma_delimited(param_argument) api_path = utils.format_url( - '/v1/auth/{mount_point}/role/{role_name}/secret-id', + "/v1/auth/{mount_point}/role/{role_name}/secret-id", mount_point=mount_point, - role_name=role_name + role_name=role_name, ) return self._adapter.post(url=api_path, json=params) - def create_custom_secret_id(self, role_name, secret_id, metadata=None, cidr_list=None, token_bound_cidrs=None, - mount_point=DEFAULT_MOUNT_POINT): + def create_custom_secret_id( + self, + role_name, + secret_id, + metadata=None, + cidr_list=None, + token_bound_cidrs=None, + mount_point=DEFAULT_MOUNT_POINT, + ): """ Generates and issues a new Secret ID on a role in the auth method. @@ -293,19 +321,18 @@ def create_custom_secret_id(self, role_name, secret_id, metadata=None, cidr_list """ 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, - 'metadata': metadata - } + raise exceptions.ParamValidationError( + error_msg.format( + arg=metadata, + arg_type=type(metadata), + ) + ) + + params = {"secret_id": secret_id, "metadata": metadata} list_of_strings_params = { - 'cidr_list': cidr_list, - 'token_bound_cidrs': token_bound_cidrs + "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( @@ -316,9 +343,9 @@ def create_custom_secret_id(self, role_name, secret_id, metadata=None, cidr_list params[param_name] = list_to_comma_delimited(param_argument) api_path = utils.format_url( - '/v1/auth/{mount_point}/role/{role_name}/custom-secret-id', + "/v1/auth/{mount_point}/role/{role_name}/custom-secret-id", mount_point=mount_point, - role_name=role_name + role_name=role_name, ) return self._adapter.post(url=api_path, json=params) @@ -338,13 +365,11 @@ def read_secret_id(self, role_name, secret_id, mount_point=DEFAULT_MOUNT_POINT): :return: The JSON response of the read_role_id request. :rtype: dict """ - params = { - 'secret_id': secret_id - } + params = {"secret_id": secret_id} api_path = utils.format_url( - '/v1/auth/{mount_point}/role/{role_name}/secret-id/lookup', + "/v1/auth/{mount_point}/role/{role_name}/secret-id/lookup", mount_point=mount_point, - role_name=role_name + role_name=role_name, ) return self._adapter.post(url=api_path, json=params) @@ -362,13 +387,11 @@ def destroy_secret_id(self, role_name, secret_id, mount_point=DEFAULT_MOUNT_POIN :param mount_point: The "path" the method/backend was mounted on. :type mount_point: str | unicode """ - params = { - 'secret_id': secret_id - } + params = {"secret_id": secret_id} api_path = utils.format_url( - '/v1/auth/{mount_point}/role/{role_name}/secret-id/destroy', + "/v1/auth/{mount_point}/role/{role_name}/secret-id/destroy", mount_point=mount_point, - role_name=role_name + role_name=role_name, ) return self._adapter.post(url=api_path, json=params) @@ -387,13 +410,15 @@ def list_secret_id_accessors(self, role_name, mount_point=DEFAULT_MOUNT_POINT): :rtype: dict """ api_path = utils.format_url( - '/v1/auth/{mount_point}/role/{role_name}/secret-id', + "/v1/auth/{mount_point}/role/{role_name}/secret-id", mount_point=mount_point, - role_name=role_name + 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): + 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. @@ -409,17 +434,17 @@ def read_secret_id_accessor(self, role_name, secret_id_accessor, mount_point=DEF :return: The JSON response of the read_role_id request. :rtype: dict """ - params = { - 'secret_id_accessor': secret_id_accessor - } + params = {"secret_id_accessor": secret_id_accessor} api_path = utils.format_url( - '/v1/auth/{mount_point}/role/{role_name}/secret-id-accessor/lookup', + "/v1/auth/{mount_point}/role/{role_name}/secret-id-accessor/lookup", mount_point=mount_point, - role_name=role_name + 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): + 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. @@ -433,17 +458,17 @@ def destroy_secret_id_accessor(self, role_name, secret_id_accessor, mount_point= :param mount_point: The "path" the method/backend was mounted on. :type mount_point: str | unicode """ - params = { - 'secret_id_accessor': secret_id_accessor - } + params = {"secret_id_accessor": secret_id_accessor} api_path = utils.format_url( - '/v1/auth/{mount_point}/role/{role_name}/secret-id-accessor/destroy', + "/v1/auth/{mount_point}/role/{role_name}/secret-id-accessor/destroy", mount_point=mount_point, - role_name=role_name + 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): + def login( + self, role_id, secret_id=None, use_token=True, mount_point=DEFAULT_MOUNT_POINT + ): """ Login with APPROLE credentials. @@ -462,13 +487,9 @@ def login(self, role_id, secret_id=None, use_token=True, mount_point=DEFAULT_MOU :return: The JSON response of the read_role_id request. :rtype: dict """ - params = { - 'role_id': role_id, - 'secret_id': secret_id - } + params = {"role_id": role_id, "secret_id": secret_id} api_path = utils.format_url( - '/v1/auth/{mount_point}/login', - mount_point=mount_point + "/v1/auth/{mount_point}/login", mount_point=mount_point ) return self._adapter.login( url=api_path, diff --git a/hvac/api/auth_methods/aws.py b/hvac/api/auth_methods/aws.py index a3571fe6c..928ee2897 100644 --- a/hvac/api/auth_methods/aws.py +++ b/hvac/api/auth_methods/aws.py @@ -19,8 +19,17 @@ class Aws(VaultApiBase): 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): + 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, + ): """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. @@ -65,16 +74,20 @@ def configure(self, max_retries=None, access_key=None, secret_key=None, endpoint :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, - }) - api_path = utils.format_url('/v1/auth/{mount_point}/config/client', mount_point=mount_point) + 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, + } + ) + api_path = utils.format_url( + "/v1/auth/{mount_point}/config/client", mount_point=mount_point + ) return self._adapter.post( url=api_path, json=params, @@ -91,11 +104,13 @@ def read_config(self, mount_point=AWS_DEFAULT_MOUNT_POINT): :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) + 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') + return response.get("data") def delete_config(self, mount_point=AWS_DEFAULT_MOUNT_POINT): """Delete previously configured AWS access credentials, @@ -108,13 +123,14 @@ def delete_config(self, mount_point=AWS_DEFAULT_MOUNT_POINT): :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 + 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): + def configure_identity_integration( + self, iam_alias=None, ec2_alias=None, mount_point=AWS_DEFAULT_MOUNT_POINT + ): """Configure the way that Vault interacts with the Identity store. The default (as of Vault 1.0.3) is role_id for both values. @@ -143,21 +159,27 @@ def configure_identity_integration(self, iam_alias=None, ec2_alias=None, """ if iam_alias is not None and iam_alias not in ALLOWED_IAM_ALIAS_TYPES: error_msg = 'invalid iam alias type provided: "{arg}"; supported iam alias types: "{alias_types}"' - raise exceptions.ParamValidationError(error_msg.format( - arg=iam_alias, - environments=','.join(ALLOWED_IAM_ALIAS_TYPES) - )) + raise exceptions.ParamValidationError( + error_msg.format( + arg=iam_alias, environments=",".join(ALLOWED_IAM_ALIAS_TYPES) + ) + ) if ec2_alias is not None and ec2_alias not in ALLOWED_EC2_ALIAS_TYPES: error_msg = 'invalid ec2 alias type provided: "{arg}"; supported ec2 alias types: "{alias_types}"' - raise exceptions.ParamValidationError(error_msg.format( - arg=ec2_alias, - environments=','.join(ALLOWED_EC2_ALIAS_TYPES) - )) - params = utils.remove_nones({ - 'iam_alias': iam_alias, - 'ec2_alias': ec2_alias, - }) - api_auth = '/v1/auth/{mount_point}/config/identity'.format(mount_point=mount_point) + raise exceptions.ParamValidationError( + error_msg.format( + arg=ec2_alias, environments=",".join(ALLOWED_EC2_ALIAS_TYPES) + ) + ) + params = utils.remove_nones( + { + "iam_alias": iam_alias, + "ec2_alias": ec2_alias, + } + ) + api_auth = "/v1/auth/{mount_point}/config/identity".format( + mount_point=mount_point + ) return self._adapter.post( url=api_auth, json=params, @@ -174,13 +196,21 @@ def read_identity_integration(self, mount_point=AWS_DEFAULT_MOUNT_POINT): :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) + 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') + return response.get("data") - def create_certificate_configuration(self, cert_name, aws_public_cert, document_type=None, mount_point=AWS_DEFAULT_MOUNT_POINT): + 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 @@ -203,21 +233,27 @@ def create_certificate_configuration(self, cert_name, aws_public_cert, document_ :rtype: request.Response """ params = { - 'cert_name': cert_name, - 'aws_public_cert': aws_public_cert, + "cert_name": cert_name, + "aws_public_cert": aws_public_cert, } params.update( - utils.remove_nones({ - 'document_type': document_type, - }) + utils.remove_nones( + { + "document_type": document_type, + } + ) + ) + api_path = utils.format_url( + "/v1/auth/{0}/config/certificate/{1}", mount_point, cert_name ) - 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): + def read_certificate_configuration( + self, cert_name, mount_point=AWS_DEFAULT_MOUNT_POINT + ): """Return previously configured AWS public key. Supported methods: @@ -229,13 +265,17 @@ def read_certificate_configuration(self, cert_name, mount_point=AWS_DEFAULT_MOUN :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) + 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') + return response.get("data") - def delete_certificate_configuration(self, cert_name, mount_point=AWS_DEFAULT_MOUNT_POINT): + def delete_certificate_configuration( + self, cert_name, mount_point=AWS_DEFAULT_MOUNT_POINT + ): """Remove previously configured AWS public key. Supported methods: @@ -248,7 +288,9 @@ def delete_certificate_configuration(self, cert_name, mount_point=AWS_DEFAULT_MO :return: The response of the request :rtype: request.Response """ - api_path = utils.format_url('/v1/auth/{0}/config/certificate/{1}', mount_point, cert_name) + api_path = utils.format_url( + "/v1/auth/{0}/config/certificate/{1}", mount_point, cert_name + ) return self._adapter.delete( url=api_path, ) @@ -264,13 +306,17 @@ def list_certificate_configurations(self, mount_point=AWS_DEFAULT_MOUNT_POINT): :return: The response of the request. :rtype: requests.Response """ - api_path = utils.format_url('/v1/auth/{mount_point}/config/certificates', mount_point=mount_point) + 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') + return response.get("data") - def create_sts_role(self, account_id, sts_role, mount_point=AWS_DEFAULT_MOUNT_POINT): + 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.) @@ -291,10 +337,12 @@ def create_sts_role(self, account_id, sts_role, mount_point=AWS_DEFAULT_MOUNT_PO :return: The response of the request. :rtype: requests.Response """ - api_path = utils.format_url('/v1/auth/{0}/config/sts/{1}', mount_point, account_id) + api_path = utils.format_url( + "/v1/auth/{0}/config/sts/{1}", mount_point, account_id + ) params = { - 'account_id': account_id, - 'sts_role': sts_role, + "account_id": account_id, + "sts_role": sts_role, } return self._adapter.post( url=api_path, @@ -311,11 +359,13 @@ def read_sts_role(self, account_id, mount_point=AWS_DEFAULT_MOUNT_POINT): :return: The response of the request. :rtype: requests.Response """ - api_path = utils.format_url('/v1/auth/{0}/config/sts/{1}', mount_point, account_id) + 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') + 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. @@ -325,11 +375,11 @@ def list_sts_roles(self, mount_point=AWS_DEFAULT_MOUNT_POINT): :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 + api_path = utils.format_url( + "/v1/auth/{mount_point}/config/sts", mount_point=mount_point ) - return response.get('data') + 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. @@ -340,13 +390,19 @@ def delete_sts_role(self, account_id, mount_point=AWS_DEFAULT_MOUNT_POINT): :return: The response of the request. :rtype: requests.Response """ - api_path = utils.format_url('/v1/auth/{0}/config/sts/{1}', mount_point, account_id) + 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): + 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 @@ -359,11 +415,16 @@ def configure_identity_whitelist_tidy(self, safety_buffer=None, disable_periodic :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, - }) + 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, @@ -377,11 +438,12 @@ def read_identity_whitelist_tidy(self, mount_point=AWS_DEFAULT_MOUNT_POINT): :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 + api_path = utils.format_url( + "/v1/auth/{mount_point}/config/tidy/identity-whitelist", + mount_point=mount_point, ) - return response.get('data') + 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. @@ -391,13 +453,20 @@ def delete_identity_whitelist_tidy(self, mount_point=AWS_DEFAULT_MOUNT_POINT): :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) + 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): + 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 @@ -410,11 +479,16 @@ def configure_role_tag_blacklist_tidy(self, safety_buffer=None, disable_periodic :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, - }) + 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, @@ -428,11 +502,12 @@ def read_role_tag_blacklist_tidy(self, mount_point=AWS_DEFAULT_MOUNT_POINT): :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 + api_path = utils.format_url( + "/v1/auth/{mount_point}/config/tidy/roletag-blacklist", + mount_point=mount_point, ) - return response.get('data') + 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. @@ -442,18 +517,37 @@ def delete_role_tag_blacklist_tidy(self, mount_point=AWS_DEFAULT_MOUNT_POINT): :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): + 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: @@ -482,33 +576,35 @@ def create_role(self, role, auth_type=None, bound_ami_id=None, bound_account_id= :return: The response of the request. :rtype: requests.Response """ - api_path = utils.format_url('/v1/auth/{0}/role/{1}', mount_point, role) + api_path = utils.format_url("/v1/auth/{0}/role/{1}", mount_point, role) params = { - 'role': role, + "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, - }) + 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, @@ -524,11 +620,9 @@ def read_role(self, role, mount_point=AWS_DEFAULT_MOUNT_POINT): :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') + 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 @@ -538,11 +632,13 @@ def list_roles(self, mount_point=AWS_DEFAULT_MOUNT_POINT): :return: The response of the request. :rtype: requests.Response """ - api_path = utils.format_url('/v1/auth/{mount_point}/roles', mount_point=mount_point) + 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') + return response.get("data") def delete_role(self, role, mount_point=AWS_DEFAULT_MOUNT_POINT): """Deletes the previously registered role @@ -553,13 +649,21 @@ def delete_role(self, role, mount_point=AWS_DEFAULT_MOUNT_POINT): :return: The response of the request. :rtype: requests.Response """ - api_path = utils.format_url('/v1/auth/{0}/role/{1}', mount_point, role) + 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): + 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 @@ -596,23 +700,34 @@ def create_role_tags(self, role, policies=None, max_ttl=None, instance_id=None, :return: The create role tag response. :rtype: dict """ - api_path = utils.format_url('/v1/auth/{0}/role/{1}/tag', mount_point, role) + 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, - }) + 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): + 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 @@ -631,7 +746,9 @@ def iam_login(self, access_key, secret_key, session_token=None, header_value=Non :return: The response of the request. :rtype: requests.Response """ - api_path = utils.format_url('/v1/auth/{mount_point}/login', mount_point=mount_point) + 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) @@ -640,11 +757,11 @@ def iam_login(self, access_key, secret_key, session_token=None, header_value=Non # 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, + "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( @@ -653,7 +770,14 @@ def iam_login(self, access_key, secret_key, session_token=None, header_value=Non json=params, ) - def ec2_login(self, pkcs7, nonce=None, role=None, use_token=True, mount_point=AWS_DEFAULT_MOUNT_POINT): + 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. @@ -670,14 +794,14 @@ def ec2_login(self, pkcs7, nonce=None, role=None, use_token=True, mount_point=AW :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 - } + api_path = utils.format_url( + "/v1/auth/{mount_point}/login", mount_point=mount_point + ) + params = {"pkcs7": pkcs7} if nonce: - params['nonce'] = nonce + params["nonce"] = nonce if role: - params['role'] = role + params["role"] = role return self._adapter.login( url=api_path, @@ -685,7 +809,9 @@ def ec2_login(self, pkcs7, nonce=None, role=None, use_token=True, mount_point=AW json=params, ) - def place_role_tags_in_blacklist(self, role_tag, mount_point=AWS_DEFAULT_MOUNT_POINT): + 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 @@ -698,10 +824,10 @@ def place_role_tags_in_blacklist(self, role_tag, mount_point=AWS_DEFAULT_MOUNT_P :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 + 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 @@ -712,11 +838,11 @@ def read_role_tag_blacklist(self, role_tag, mount_point=AWS_DEFAULT_MOUNT_POINT) :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 + api_path = utils.format_url( + "/v1/auth/{0}/roletag-blacklist/{1}", mount_point, role_tag ) - return response.get('data') + 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 @@ -726,11 +852,13 @@ def list_blacklist_tags(self, mount_point=AWS_DEFAULT_MOUNT_POINT): :return: The response of the request. :rtype: requests.Response """ - api_path = utils.format_url('/v1/auth/{mount_point}/roletag-blacklist', mount_point=mount_point) + 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') + return response.get("data") def delete_blacklist_tags(self, role_tag, mount_point=AWS_DEFAULT_MOUNT_POINT): """Deletes a blacklisted role tag @@ -741,12 +869,16 @@ def delete_blacklist_tags(self, role_tag, mount_point=AWS_DEFAULT_MOUNT_POINT): :return: The response of the request. :rtype: requests.Response """ - api_path = utils.format_url('/v1/auth/{0}/roletag-blacklist/{1}', mount_point, role_tag) + api_path = utils.format_url( + "/v1/auth/{0}/roletag-blacklist/{1}", mount_point, role_tag + ) return self._adapter.delete( url=api_path, ) - def tidy_blacklist_tags(self, saftey_buffer='72h', mount_point=AWS_DEFAULT_MOUNT_POINT): + def tidy_blacklist_tags( + self, saftey_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 saftey_buffer: @@ -755,9 +887,11 @@ def tidy_blacklist_tags(self, saftey_buffer='72h', mount_point=AWS_DEFAULT_MOUNT :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) + api_path = utils.format_url( + "/v1/auth/{mount_point}/tidy/roletag-blacklist", mount_point=mount_point + ) params = { - 'safety_buffer': saftey_buffer, + "safety_buffer": saftey_buffer, } return self._adapter.post( url=api_path, @@ -773,11 +907,11 @@ def read_identity_whitelist(self, instance_id, mount_point=AWS_DEFAULT_MOUNT_POI :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 + api_path = utils.format_url( + "/v1/auth/{0}/identity-whitelist/{1}", mount_point, instance_id ) - return response.get('data') + 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 @@ -787,13 +921,17 @@ def list_identity_whitelist(self, mount_point=AWS_DEFAULT_MOUNT_POINT): :return: The response of the request. :rtype: requests.Response """ - api_path = utils.format_url('/v1/auth/{mount_point}/identity-whitelist', mount_point=mount_point) + 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') + return response.get("data") - def delete_identity_whitelist_entries(self, instance_id, mount_point=AWS_DEFAULT_MOUNT_POINT): + 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: @@ -802,12 +940,16 @@ def delete_identity_whitelist_entries(self, instance_id, mount_point=AWS_DEFAULT :return: The response of the request. :rtype: requests.Response """ - api_path = utils.format_url('/v1/auth/{0}/identity-whitelist/{1}', mount_point, instance_id) + api_path = utils.format_url( + "/v1/auth/{0}/identity-whitelist/{1}", mount_point, instance_id + ) return self._adapter.delete( url=api_path, ) - def tidy_identity_whitelist_entries(self, saftey_buffer='72h', mount_point=AWS_DEFAULT_MOUNT_POINT): + def tidy_identity_whitelist_entries( + self, saftey_buffer="72h", mount_point=AWS_DEFAULT_MOUNT_POINT + ): """Cleans up the entries in the whitelist based on expiration time and safety_buffer :param saftey_buffer: @@ -816,11 +958,10 @@ def tidy_identity_whitelist_entries(self, saftey_buffer='72h', mount_point=AWS_D :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) + api_path = utils.format_url( + "/v1/auth/{mount_point}/tidy/identity-whitelist", mount_point=mount_point + ) params = { - 'safety_buffer': saftey_buffer, + "safety_buffer": saftey_buffer, } - return self._adapter.post( - url=api_path, - json=params - ) + return self._adapter.post(url=api_path, json=params) diff --git a/hvac/api/auth_methods/azure.py b/hvac/api/auth_methods/azure.py index ae4fcc388..1d49ebb80 100644 --- a/hvac/api/auth_methods/azure.py +++ b/hvac/api/auth_methods/azure.py @@ -7,7 +7,7 @@ from hvac.api.vault_api_base import VaultApiBase from hvac.constants.azure import VALID_ENVIRONMENTS -DEFAULT_MOUNT_POINT = 'azure' +DEFAULT_MOUNT_POINT = "azure" logger = logging.getLogger(__name__) @@ -17,8 +17,15 @@ class Azure(VaultApiBase): 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): + 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. @@ -45,22 +52,28 @@ def configure(self, tenant_id, resource, environment=None, client_id=None, clien """ 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), - )) + raise exceptions.ParamValidationError( + error_msg.format( + arg=environment, + environments=",".join(VALID_ENVIRONMENTS), + ) + ) params = { - 'tenant_id': tenant_id, - 'resource': resource, + "tenant_id": tenant_id, + "resource": resource, } params.update( - utils.remove_nones({ - 'environment': environment, - 'client_id': client_id, - 'client_secret': client_secret, - }) + 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 ) - api_path = utils.format_url('/v1/auth/{mount_point}/config', mount_point=mount_point) return self._adapter.post( url=api_path, json=params, @@ -77,11 +90,13 @@ def read_config(self, mount_point=DEFAULT_MOUNT_POINT): :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) + 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') + return response.get("data") def delete_config(self, mount_point=DEFAULT_MOUNT_POINT): """Delete the previously configured Azure config and credentials. @@ -94,14 +109,29 @@ def delete_config(self, mount_point=DEFAULT_MOUNT_POINT): :return: The response of the request. :rtype: requests.Response """ - api_path = utils.format_url('/v1/auth/{mount_point}/config', mount_point=mount_point) + 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): + 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 @@ -145,28 +175,37 @@ def create_role(self, name, policies=None, ttl=None, max_ttl=None, period=None, if policies is not None: if not ( isinstance(policies, str) - or (isinstance(policies, list) and all(isinstance(p, str) for p in policies)) + 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) + 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, @@ -187,14 +226,14 @@ def read_role(self, name, mount_point=DEFAULT_MOUNT_POINT): :rtype: dict """ api_path = utils.format_url( - '/v1/auth/{mount_point}/role/{name}', + "/v1/auth/{mount_point}/role/{name}", mount_point=mount_point, name=name, ) response = self._adapter.get( url=api_path, ) - return response.get('data') + return response.get("data") def list_roles(self, mount_point=DEFAULT_MOUNT_POINT): """List all the roles that are registered with the plugin. @@ -208,11 +247,11 @@ def list_roles(self, mount_point=DEFAULT_MOUNT_POINT): :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 + api_path = utils.format_url( + "/v1/auth/{mount_point}/role", mount_point=mount_point ) - return response.get('data') + 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. @@ -229,7 +268,7 @@ def delete_role(self, name, mount_point=DEFAULT_MOUNT_POINT): :rtype: requests.Response """ api_path = utils.format_url( - '/v1/auth/{mount_point}/role/{name}', + "/v1/auth/{mount_point}/role/{name}", mount_point=mount_point, name=name, ) @@ -237,8 +276,17 @@ def delete_role(self, name, mount_point=DEFAULT_MOUNT_POINT): 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): + 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 @@ -273,18 +321,22 @@ def login(self, role, jwt, subscription_id=None, resource_group_name=None, vm_na :rtype: dict """ params = { - 'role': role, - 'jwt': jwt, + "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, - }) + 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 ) - 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, diff --git a/hvac/api/auth_methods/cert.py b/hvac/api/auth_methods/cert.py index 402321b74..d78fea6f6 100644 --- a/hvac/api/auth_methods/cert.py +++ b/hvac/api/auth_methods/cert.py @@ -13,12 +13,30 @@ class Cert(VaultApiBase): Reference: https://www.vaultproject.io/api/auth/cert/index.html """ - def create_ca_certificate_role(self, name, certificate, 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 + def create_ca_certificate_role( + self, + name, + certificate, + 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: @@ -29,43 +47,66 @@ def create_ca_certificate_role(self, name, certificate, allowed_common_names="", :type name: str :param certificate: The PEM-format CA certificate. :type certificate: 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. + :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. + :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. + :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. + :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. + :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. + :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. + :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. + :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. + :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. + :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. + :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. + :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. + :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. + :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. + :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: """ try: - with open(certificate, 'r') as f_cert: + with open(certificate, "r") as f_cert: cert = f_cert.read() except FileNotFoundError: cert = certificate @@ -93,13 +134,15 @@ def create_ca_certificate_role(self, name, certificate, allowed_common_names="", } ) - api_path = '/v1/auth/{mount_point}/certs/{name}'.format(mount_point=mount_point, name=name) + 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'): + def read_ca_certificate_role(self, name, mount_point="cert"): """ Gets information associated with the named role. @@ -114,15 +157,17 @@ def read_ca_certificate_role(self, name, mount_point='cert'): :rtype: dict """ params = { - 'name': name, + "name": name, } - api_path = '/v1/auth/{mount_point}/certs/{name}'.format(mount_point=mount_point, 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'): + def list_certificate_roles(self, mount_point="cert"): """ Lists configured certificate names. @@ -134,12 +179,10 @@ def list_certificate_roles(self, mount_point='cert'): :return: The response of the list_certificate request. :rtype: requests.Response """ - api_path = '/v1/auth/{mount_point}/certs'.format(mount_point=mount_point) - return self._adapter.list( - url=api_path - ) + api_path = "/v1/auth/{mount_point}/certs".format(mount_point=mount_point) + return self._adapter.list(url=api_path) - def delete_certificate_role(self, name, mount_point='cert'): + def delete_certificate_role(self, name, mount_point="cert"): """ List existing LDAP existing groups that have been created in this auth method. @@ -151,12 +194,14 @@ def delete_certificate_role(self, name, mount_point='cert'): :param mount_point: :type mount_point: """ - api_path = '/v1/auth/{mount_point}/certs/{name}'.format(mount_point=mount_point, name=name) + 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): + def configure_tls_certificate(self, mount_point="cert", disable_binding=False): """ Configure options for the method. @@ -171,15 +216,23 @@ def configure_tls_certificate(self, mount_point='cert', disable_binding=False): :type mount_point: """ params = { - 'disable_binding': disable_binding, + "disable_binding": disable_binding, } - api_path = '/v1/auth/{mount_point}/config'.format(mount_point=mount_point) + api_path = "/v1/auth/{mount_point}/config".format(mount_point=mount_point) 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): + 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. @@ -207,19 +260,21 @@ def login(self, name="", cacert=False, cert_pem="", key_pem="", mount_point='cer :return: The response of the login request. :rtype: requests.Response """ - params = {'use_token': use_token} + params = {} if name != "": - params['name'] = name - api_path = '/v1/auth/{mount_point}/login'.format(mount_point=mount_point) + params["name"] = name + api_path = "/v1/auth/{mount_point}/login".format(mount_point=mount_point) # 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.") + 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') + cacert = self._adapter._kwargs.get("verify") else: validate_pem_format(cacert, "verify") # 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 @@ -229,10 +284,10 @@ def login(self, name="", cacert=False, cert_pem="", key_pem="", mount_point='cer except exceptions.VaultError as e: if isinstance(e, type(exceptions.ParamValidationError())): tls_update = {} - if not (os.path.exists(cert_pem) or self._adapter._kwargs.get('cert')): + if not (os.path.exists(cert_pem) or self._adapter._kwargs.get("cert")): raise FileNotFoundError("Can't find the certificate.") try: - for tls_part, value in {'cert_pem': cert_pem, 'key_pem': key_pem}: + for tls_part, value in {"cert_pem": cert_pem, "key_pem": key_pem}: if value != "": tls_update[tls_part] = value except ValueError: @@ -249,9 +304,7 @@ def login(self, name="", cacert=False, cert_pem="", key_pem="", mount_point='cer } return self._adapter.login( - url=api_path, - json=params, - **additional_request_kwargs + url=api_path, use_token=use_token, json=params, **additional_request_kwargs ) class CertificateAuthError(Exception): diff --git a/hvac/api/auth_methods/gcp.py b/hvac/api/auth_methods/gcp.py index e8885c832..fde05c4e7 100644 --- a/hvac/api/auth_methods/gcp.py +++ b/hvac/api/auth_methods/gcp.py @@ -8,7 +8,7 @@ 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' +DEFAULT_MOUNT_POINT = "gcp" logger = logging.getLogger(__name__) @@ -19,7 +19,12 @@ class Gcp(VaultApiBase): 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): + 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 @@ -42,11 +47,15 @@ def configure(self, credentials=None, google_certs_endpoint=GCP_CERTS_ENDPOINT, :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) + 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, @@ -63,11 +72,13 @@ def read_config(self, mount_point=DEFAULT_MOUNT_POINT): :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) + 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') + return response.get("data") def delete_config(self, mount_point=DEFAULT_MOUNT_POINT): """Delete all GCP configuration data. This operation is idempotent. @@ -81,14 +92,31 @@ def delete_config(self, mount_point=DEFAULT_MOUNT_POINT): :return: The response of the request. :rtype: requests.Response """ - api_path = utils.format_url('/v1/auth/{mount_point}/config', mount_point=mount_point) + 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): + 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 @@ -152,26 +180,25 @@ def create_role(self, name, role_type, project_id, ttl=None, max_ttl=None, perio :rtype: requests.Response """ type_specific_params = { - 'iam': { - 'max_jwt_exp': None, - 'allow_gce_inference': None, + "iam": { + "max_jwt_exp": None, + "allow_gce_inference": None, }, - 'gce': { - 'bound_zones': None, - 'bound_regions': None, - 'bound_instance_groups': None, - 'bound_labels': 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, - + "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( @@ -181,48 +208,58 @@ def create_role(self, name, role_type, project_id, ttl=None, max_ttl=None, perio 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), - )) + 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), + "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, - }) + 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["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, - }) + 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(): + 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': + elif role_type == "gce": if bound_zones is not None: - params['bound_zones'] = list_to_comma_delimited(bound_zones) + params["bound_zones"] = list_to_comma_delimited(bound_zones) if bound_regions is not None: - params['bound_regions'] = list_to_comma_delimited(bound_regions) + 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) + 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(): + 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 @@ -230,7 +267,7 @@ def create_role(self, name, role_type, project_id, ttl=None, max_ttl=None, perio logger.warning(warning_msg) api_path = utils.format_url( - '/v1/auth/{mount_point}/role/{name}', + "/v1/auth/{mount_point}/role/{name}", mount_point=mount_point, name=name, ) @@ -239,7 +276,9 @@ def create_role(self, name, role_type, project_id, ttl=None, max_ttl=None, perio json=params, ) - def edit_service_accounts_on_iam_role(self, name, add=None, remove=None, mount_point=DEFAULT_MOUNT_POINT): + 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. @@ -259,12 +298,14 @@ def edit_service_accounts_on_iam_role(self, name, add=None, remove=None, mount_p :return: The response of the request. :rtype: requests.Response """ - params = utils.remove_nones({ - 'add': add, - 'remove': remove, - }) + params = utils.remove_nones( + { + "add": add, + "remove": remove, + } + ) api_path = utils.format_url( - '/v1/auth/{mount_point}/role/{name}/service-accounts', + "/v1/auth/{mount_point}/role/{name}/service-accounts", mount_point=mount_point, name=name, ) @@ -273,7 +314,9 @@ def edit_service_accounts_on_iam_role(self, name, add=None, remove=None, mount_p json=params, ) - def edit_labels_on_gce_role(self, name, add=None, remove=None, mount_point=DEFAULT_MOUNT_POINT): + 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. @@ -294,12 +337,14 @@ def edit_labels_on_gce_role(self, name, add=None, remove=None, mount_point=DEFAU :return: The response of the edit_labels_on_gce_role request. :rtype: requests.Response """ - params = utils.remove_nones({ - 'add': add, - 'remove': remove, - }) + params = utils.remove_nones( + { + "add": add, + "remove": remove, + } + ) api_path = utils.format_url( - '/v1/auth/{mount_point}/role/{name}/labels', + "/v1/auth/{mount_point}/role/{name}/labels", mount_point=mount_point, name=name, ) @@ -323,10 +368,10 @@ def read_role(self, name, mount_point=DEFAULT_MOUNT_POINT): :rtype: JSON """ params = { - 'name': name, + "name": name, } api_path = utils.format_url( - '/v1/auth/{mount_point}/role/{name}', + "/v1/auth/{mount_point}/role/{name}", mount_point=mount_point, name=name, ) @@ -334,7 +379,7 @@ def read_role(self, name, mount_point=DEFAULT_MOUNT_POINT): url=api_path, json=params, ) - return response.get('data') + return response.get("data") def list_roles(self, mount_point=DEFAULT_MOUNT_POINT): """List all the roles that are registered with the plugin. @@ -348,11 +393,13 @@ def list_roles(self, mount_point=DEFAULT_MOUNT_POINT): :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) + 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') + return response.get("data") def delete_role(self, role, mount_point=DEFAULT_MOUNT_POINT): """Delete the previously registered role. @@ -369,10 +416,10 @@ def delete_role(self, role, mount_point=DEFAULT_MOUNT_POINT): :rtype: requests.Response """ params = { - 'role': role, + "role": role, } api_path = utils.format_url( - '/v1/auth/{mount_point}/role/{role}', + "/v1/auth/{mount_point}/role/{role}", mount_point=mount_point, role=role, ) @@ -404,10 +451,12 @@ def login(self, role, jwt, use_token=True, mount_point=DEFAULT_MOUNT_POINT): :rtype: dict """ params = { - 'role': role, - 'jwt': jwt, + "role": role, + "jwt": jwt, } - api_path = utils.format_url('/v1/auth/{mount_point}/login', mount_point=mount_point) + 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, diff --git a/hvac/api/auth_methods/github.py b/hvac/api/auth_methods/github.py index fbce6dbb7..d2ad61eec 100644 --- a/hvac/api/auth_methods/github.py +++ b/hvac/api/auth_methods/github.py @@ -4,7 +4,7 @@ from hvac import exceptions, utils from hvac.api.vault_api_base import VaultApiBase -DEFAULT_MOUNT_POINT = 'github' +DEFAULT_MOUNT_POINT = "github" class Github(VaultApiBase): @@ -13,7 +13,14 @@ class Github(VaultApiBase): 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): + 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. @@ -38,17 +45,19 @@ def configure(self, organization, base_url=None, ttl=None, max_ttl=None, mount_p :rtype: requests.Response """ params = { - 'organization': organization, + "organization": organization, } params.update( - utils.remove_nones({ - 'base_url': base_url, - 'ttl': ttl, - 'max_ttl': max_ttl, - }) + utils.remove_nones( + { + "base_url": base_url, + "ttl": ttl, + "max_ttl": max_ttl, + } + ) ) api_path = utils.format_url( - '/v1/auth/{mount_point}/config', + "/v1/auth/{mount_point}/config", mount_point=mount_point, ) return self._adapter.post( @@ -69,7 +78,7 @@ def read_configuration(self, mount_point=DEFAULT_MOUNT_POINT): :rtype: dict """ api_path = utils.format_url( - '/v1/auth/{mount_point}/config', + "/v1/auth/{mount_point}/config", mount_point=mount_point, ) return self._adapter.get(url=api_path) @@ -93,18 +102,22 @@ def map_team(self, team_name, policies=None, mount_point=DEFAULT_MOUNT_POINT): # First, perform parameter validation. if policies is None: policies = [] - if not isinstance(policies, list) or not all(isinstance(p, str) for p in 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), - )) + raise exceptions.ParamValidationError( + error_msg.format( + arg=policies, + arg_type=type(policies), + ) + ) # Then, perform request. params = { - 'value': ','.join(policies), + "value": ",".join(policies), } api_path = utils.format_url( - '/v1/auth/{mount_point}/map/teams/{team_name}', + "/v1/auth/{mount_point}/map/teams/{team_name}", mount_point=mount_point, team_name=team_name, ) @@ -128,7 +141,7 @@ def read_team_mapping(self, team_name, mount_point=DEFAULT_MOUNT_POINT): :rtype: dict """ api_path = utils.format_url( - '/v1/auth/{mount_point}/map/teams/{team_name}', + "/v1/auth/{mount_point}/map/teams/{team_name}", mount_point=mount_point, team_name=team_name, ) @@ -153,19 +166,23 @@ def map_user(self, user_name, policies=None, mount_point=DEFAULT_MOUNT_POINT): # First, perform parameter validation. if policies is None: policies = [] - if not isinstance(policies, list) or not all(isinstance(p, str) for p in 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), - )) + raise exceptions.ParamValidationError( + error_msg.format( + arg=policies, + arg_type=type(policies), + ) + ) # Then, perform request. params = { - 'value': ','.join(policies), + "value": ",".join(policies), } api_path = utils.format_url( - '/v1/auth/{mount_point}/map/users/{user_name}', + "/v1/auth/{mount_point}/map/users/{user_name}", mount_point=mount_point, user_name=user_name, ) @@ -189,7 +206,7 @@ def read_user_mapping(self, user_name, mount_point=DEFAULT_MOUNT_POINT): :rtype: dict """ api_path = utils.format_url( - '/v1/auth/{mount_point}/map/users/{user_name}', + "/v1/auth/{mount_point}/map/users/{user_name}", mount_point=mount_point, user_name=user_name, ) @@ -213,9 +230,11 @@ def login(self, token, use_token=True, mount_point=DEFAULT_MOUNT_POINT): :rtype: dict """ params = { - 'token': token, + "token": token, } - api_path = utils.format_url('/v1/auth/{mount_point}/login', mount_point=mount_point) + 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, diff --git a/hvac/api/auth_methods/jwt.py b/hvac/api/auth_methods/jwt.py index 3d61d1cc1..b3d046c59 100644 --- a/hvac/api/auth_methods/jwt.py +++ b/hvac/api/auth_methods/jwt.py @@ -15,7 +15,8 @@ class JWT(VaultApiBase): Reference: https://www.vaultproject.io/api/auth/jwt """ - DEFAULT_PATH = 'jwt' + + DEFAULT_PATH = "jwt" def resolve_path(self, path): """Return the class's default path if no explicit path is specified. @@ -27,10 +28,23 @@ def resolve_path(self, path): """ 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): + 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, + ): """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. @@ -76,23 +90,25 @@ def configure(self, oidc_discovery_url=None, oidc_discovery_ca_pem=None, oidc_cl :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, - }) + 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, + } + ) api_path = utils.format_url( - '/v1/auth/{path}/config', + "/v1/auth/{path}/config", path=self.resolve_path(path), ) return self._adapter.post( @@ -100,7 +116,7 @@ def configure(self, oidc_discovery_url=None, oidc_discovery_ca_pem=None, oidc_cl json=params, ) - def read_config(self, path=None): + def read_config(self, path=None): """Read the previously configured config. Supported methods: @@ -110,20 +126,41 @@ def read_config(self, path=None): :rtype: dict """ api_path = utils.format_url( - '/v1/auth/{path}/config', + "/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): + 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, + ): """Register a role in the JWT method. Role types have specific entities that can perform login operations against this endpoint. Constraints @@ -207,34 +244,36 @@ def create_role(self, name, user_claim, allowed_redirect_uris, role_type='jwt', :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, - }) + 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, + } + ) api_path = utils.format_url( - '/v1/auth/{path}/role/{name}', + "/v1/auth/{path}/role/{name}", path=self.resolve_path(path), name=name, ) @@ -257,7 +296,7 @@ def read_role(self, name, path=None): :rtype: dict """ api_path = utils.format_url( - '/v1/auth/{path}/role/{name}', + "/v1/auth/{path}/role/{name}", path=self.resolve_path(path), name=name, ) @@ -277,7 +316,7 @@ def list_roles(self, path=None): :rtype: dict """ api_path = utils.format_url( - '/v1/auth/{path}/role', + "/v1/auth/{path}/role", path=self.resolve_path(path), ) return self._adapter.list( @@ -298,7 +337,7 @@ def delete_role(self, name, path=None): :rtype: requests.Response """ api_path = utils.format_url( - '/v1/auth/{path}/role/{name}', + "/v1/auth/{path}/role/{name}", path=self.resolve_path(path), name=name, ) @@ -322,11 +361,11 @@ def oidc_authorization_url_request(self, role, redirect_uri, path=None): :rtype: requests.Response """ params = { - 'role': role, - 'redirect_uri': redirect_uri, + "role": role, + "redirect_uri": redirect_uri, } api_path = utils.format_url( - '/v1/auth/{path}/oidc/auth_url', + "/v1/auth/{path}/oidc/auth_url", path=self.resolve_path(path), ) return self._adapter.post( @@ -357,16 +396,16 @@ def oidc_callback(self, state, nonce, code, path=None): :rtype: requests.Response """ params = { - 'state': state, - 'nonce': nonce, - 'code': code, + "state": state, + "nonce": nonce, + "code": code, } api_path = utils.format_url( - '/v1/auth/{path}/oidc/callback?state={state}&nonce={nonce}&code={code}', + "/v1/auth/{path}/oidc/callback?state={state}&nonce={nonce}&code={code}", path=self.resolve_path(path), state=state, nonce=nonce, - code=code + code=code, ) return self._adapter.get( url=api_path, @@ -393,11 +432,11 @@ def jwt_login(self, role, jwt, path=None): :rtype: requests.Response """ params = { - 'role': role, - 'jwt': jwt, + "role": role, + "jwt": jwt, } api_path = utils.format_url( - '/v1/auth/{path}/login', + "/v1/auth/{path}/login", path=self.resolve_path(path), ) return self._adapter.post( diff --git a/hvac/api/auth_methods/kubernetes.py b/hvac/api/auth_methods/kubernetes.py index af91c2e69..f0c6db316 100644 --- a/hvac/api/auth_methods/kubernetes.py +++ b/hvac/api/auth_methods/kubernetes.py @@ -1,11 +1,15 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- """Kubernetes methods module.""" -from hvac import exceptions, utils +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 +from hvac.utils import ( + validate_list_of_strings_param, + comma_delimited_to_list, + validate_pem_format, +) -DEFAULT_MOUNT_POINT = 'kubernetes' +DEFAULT_MOUNT_POINT = "kubernetes" class Kubernetes(VaultApiBase): @@ -13,8 +17,16 @@ class Kubernetes(VaultApiBase): 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): + + def configure( + self, + kubernetes_host, + kubernetes_ca_cert=None, + token_reviewer_jwt=None, + pem_keys=None, + issuer=None, + mount_point=DEFAULT_MOUNT_POINT, + ): """Configure the connection parameters for Kubernetes. This path honors the distinction between the create and update capabilities inside ACL policies. @@ -43,8 +55,8 @@ def configure(self, kubernetes_host, kubernetes_ca_cert=None, token_reviewer_jwt :rtype: requests.Response """ list_of_pem_params = { - 'kubernetes_ca_cert': kubernetes_ca_cert, - 'pem_keys': pem_keys + "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: @@ -54,19 +66,20 @@ def configure(self, kubernetes_host, kubernetes_ca_cert=None, token_reviewer_jwt ) params = { - 'kubernetes_host': kubernetes_host, + "kubernetes_host": kubernetes_host, } params.update( - utils.remove_nones({ - 'kubernetes_ca_cert': kubernetes_ca_cert, - 'token_reviewer_jwt': token_reviewer_jwt, - 'pem_keys': pem_keys, - 'issuer': issuer, - }) + 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 + "/v1/auth/{mount_point}/config", mount_point=mount_point ) return self._adapter.post( url=api_path, @@ -84,14 +97,25 @@ def read_config(self, mount_point=DEFAULT_MOUNT_POINT): :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) + 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, mount_point=DEFAULT_MOUNT_POINT): + 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, + mount_point=DEFAULT_MOUNT_POINT, + ): """Create a role in the method. Registers a role in the auth method. Role types have specific entities that can perform login operations @@ -125,9 +149,9 @@ def create_role(self, name, bound_service_account_names, bound_service_account_n :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 + "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( @@ -136,20 +160,28 @@ def create_role(self, name, bound_service_account_names, bound_service_account_n ) 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), + "bound_service_account_names": comma_delimited_to_list( + bound_service_account_names + ), + "bound_service_account_namespaces": comma_delimited_to_list( + bound_service_account_namespaces + ), } params.update( - utils.remove_nones({ - 'ttl': ttl, - 'max_ttl': max_ttl, - 'period': period, - }) + utils.remove_nones( + { + "ttl": ttl, + "max_ttl": max_ttl, + "period": period, + } + ) ) if policies is not None: - params['policies'] = comma_delimited_to_list(policies) + params["policies"] = comma_delimited_to_list(policies) - api_path = utils.format_url('/v1/auth/{mount_point}/role/{name}', mount_point=mount_point, name=name) + 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, @@ -169,14 +201,14 @@ def read_role(self, name, mount_point=DEFAULT_MOUNT_POINT): :rtype: dict """ api_path = utils.format_url( - '/v1/auth/{mount_point}/role/{name}', + "/v1/auth/{mount_point}/role/{name}", mount_point=mount_point, name=name, ) response = self._adapter.get( url=api_path, ) - return response.get('data') + return response.get("data") def list_roles(self, mount_point=DEFAULT_MOUNT_POINT): """List all the roles that are registered with the plugin. @@ -189,11 +221,13 @@ def list_roles(self, mount_point=DEFAULT_MOUNT_POINT): :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) + 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') + return response.get("data") def delete_role(self, name, mount_point=DEFAULT_MOUNT_POINT): """Delete the previously registered role. @@ -210,7 +244,7 @@ def delete_role(self, name, mount_point=DEFAULT_MOUNT_POINT): :rtype: requests.Response """ api_path = utils.format_url( - '/v1/auth/{mount_point}/role/{name}', + "/v1/auth/{mount_point}/role/{name}", mount_point=mount_point, name=name, ) @@ -240,11 +274,13 @@ def login(self, role, jwt, use_token=True, mount_point=DEFAULT_MOUNT_POINT): :rtype: dict """ params = { - 'role': role, - 'jwt': jwt, + "role": role, + "jwt": jwt, } - api_path = utils.format_url('/v1/auth/{mount_point}/login', mount_point=mount_point) + 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, diff --git a/hvac/api/auth_methods/ldap.py b/hvac/api/auth_methods/ldap.py index e758191f9..2d188972c 100644 --- a/hvac/api/auth_methods/ldap.py +++ b/hvac/api/auth_methods/ldap.py @@ -4,7 +4,7 @@ from hvac import exceptions, utils from hvac.api.vault_api_base import VaultApiBase -DEFAULT_MOUNT_POINT = 'ldap' +DEFAULT_MOUNT_POINT = "ldap" class Ldap(VaultApiBase): @@ -13,10 +13,30 @@ class Ldap(VaultApiBase): Reference: https://www.vaultproject.io/api/auth/ldap/index.html """ - def configure(self, user_dn=None, group_dn=None, url=None, case_sensitive_names=None, starttls=None, - tls_min_version=None, tls_max_version=None, insecure_tls=None, certificate=None, bind_dn=None, - bind_pass=None, user_attr=None, discover_dn=None, deny_null_bind=True, upn_domain=None, - group_filter=None, group_attr=None, use_token_groups=None, mount_point=DEFAULT_MOUNT_POINT): + def configure( + self, + user_dn=None, + group_dn=None, + url=None, + case_sensitive_names=None, + starttls=None, + tls_min_version=None, + tls_max_version=None, + insecure_tls=None, + certificate=None, + bind_dn=None, + bind_pass=None, + user_attr=None, + discover_dn=None, + deny_null_bind=True, + upn_domain=None, + group_filter=None, + group_attr=None, + use_token_groups=None, + token_ttl=None, + token_max_ttl=None, + mount_point=DEFAULT_MOUNT_POINT, + ): """ Configure the LDAP auth method. @@ -75,34 +95,44 @@ def configure(self, user_dn=None, group_dn=None, url=None, case_sensitive_names= :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, - 'userdn': user_dn, - 'groupdn': group_dn, - 'case_sensitive_names': case_sensitive_names, - 'starttls': starttls, - 'tls_min_version': tls_min_version, - 'tls_max_version': tls_max_version, - 'insecure_tls': insecure_tls, - 'certificate': certificate, - 'userattr': user_attr, - 'discoverdn': discover_dn, - 'deny_null_bind': deny_null_bind, - 'groupfilter': group_filter, - 'groupattr': group_attr, - 'upndomain': upn_domain, - 'binddn': bind_dn, - 'bindpass': bind_pass, - 'certificate': certificate, - 'use_token_groups': use_token_groups, - }) - - api_path = utils.format_url('/v1/auth/{mount_point}/config', mount_point=mount_point) + params = utils.remove_nones( + { + "url": url, + "userdn": user_dn, + "groupdn": group_dn, + "case_sensitive_names": case_sensitive_names, + "starttls": starttls, + "tls_min_version": tls_min_version, + "tls_max_version": tls_max_version, + "insecure_tls": insecure_tls, + "certificate": certificate, + "userattr": user_attr, + "discoverdn": discover_dn, + "deny_null_bind": deny_null_bind, + "groupfilter": group_filter, + "groupattr": group_attr, + "upndomain": upn_domain, + "binddn": bind_dn, + "bindpass": bind_pass, + "certificate": certificate, + "use_token_groups": use_token_groups, + "token_ttl": token_ttl, + "token_max_ttl": token_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, @@ -120,12 +150,16 @@ def read_configuration(self, mount_point=DEFAULT_MOUNT_POINT): :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) + 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): + def create_or_update_group( + self, name, policies=None, mount_point=DEFAULT_MOUNT_POINT + ): """ Create or update LDAP group policies. @@ -151,9 +185,9 @@ def create_or_update_group(self, name, policies=None, mount_point=DEFAULT_MOUNT_ params = {} if policies is not None: - params['policies'] = ','.join(policies) + params["policies"] = ",".join(policies) api_path = utils.format_url( - '/v1/auth/{mount_point}/groups/{name}', + "/v1/auth/{mount_point}/groups/{name}", mount_point=mount_point, name=name, ) @@ -175,7 +209,9 @@ def list_groups(self, mount_point=DEFAULT_MOUNT_POINT): :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) + api_path = utils.format_url( + "/v1/auth/{mount_point}/groups", mount_point=mount_point + ) return self._adapter.list( url=api_path, ) @@ -196,10 +232,10 @@ def read_group(self, name, mount_point=DEFAULT_MOUNT_POINT): :rtype: dict """ params = { - 'name': name, + "name": name, } api_path = utils.format_url( - '/v1/auth/{mount_point}/groups/{name}', + "/v1/auth/{mount_point}/groups/{name}", mount_point=mount_point, name=name, ) @@ -224,7 +260,7 @@ def delete_group(self, name, mount_point=DEFAULT_MOUNT_POINT): :rtype: requests.Response """ api_path = utils.format_url( - '/v1/auth/{mount_point}/groups/{name}', + "/v1/auth/{mount_point}/groups/{name}", mount_point=mount_point, name=name, ) @@ -232,7 +268,9 @@ def delete_group(self, name, mount_point=DEFAULT_MOUNT_POINT): url=api_path, ) - def create_or_update_user(self, username, policies=None, groups=None, mount_point=DEFAULT_MOUNT_POINT): + 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. @@ -254,8 +292,8 @@ def create_or_update_user(self, username, policies=None, groups=None, mount_poin :rtype: requests.Response """ list_required_params = { - 'policies': policies, - 'groups': groups, + "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): @@ -267,11 +305,11 @@ def create_or_update_user(self, username, policies=None, groups=None, mount_poin params = {} if policies is not None: - params['policies'] = ','.join(policies) + params["policies"] = ",".join(policies) if groups is not None: - params['groups'] = ','.join(groups) + params["groups"] = ",".join(groups) api_path = utils.format_url( - '/v1/auth/{mount_point}/users/{username}', + "/v1/auth/{mount_point}/users/{username}", mount_point=mount_point, username=username, ) @@ -293,7 +331,9 @@ def list_users(self, mount_point=DEFAULT_MOUNT_POINT): :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) + api_path = utils.format_url( + "/v1/auth/{mount_point}/users", mount_point=mount_point + ) return self._adapter.list( url=api_path, ) @@ -314,7 +354,7 @@ def read_user(self, username, mount_point=DEFAULT_MOUNT_POINT): :rtype: dict """ api_path = utils.format_url( - '/v1/auth/{mount_point}/users/{username}', + "/v1/auth/{mount_point}/users/{username}", mount_point=mount_point, username=username, ) @@ -338,7 +378,7 @@ def delete_user(self, username, mount_point=DEFAULT_MOUNT_POINT): :rtype: requests.Response """ api_path = utils.format_url( - '/v1/auth/{mount_point}/users/{username}', + "/v1/auth/{mount_point}/users/{username}", mount_point=mount_point, username=username, ) @@ -346,7 +386,9 @@ def delete_user(self, username, mount_point=DEFAULT_MOUNT_POINT): url=api_path, ) - def login(self, username, password, use_token=True, mount_point=DEFAULT_MOUNT_POINT): + def login( + self, username, password, use_token=True, mount_point=DEFAULT_MOUNT_POINT + ): """ Log in with LDAP credentials. @@ -367,10 +409,10 @@ def login(self, username, password, use_token=True, mount_point=DEFAULT_MOUNT_PO :rtype: requests.Response """ params = { - 'password': password, + "password": password, } api_path = utils.format_url( - '/v1/auth/{mount_point}/login/{username}', + "/v1/auth/{mount_point}/login/{username}", mount_point=mount_point, username=username, ) diff --git a/hvac/api/auth_methods/mfa.py b/hvac/api/auth_methods/mfa.py index dffb433e2..435579052 100644 --- a/hvac/api/auth_methods/mfa.py +++ b/hvac/api/auth_methods/mfa.py @@ -5,14 +5,9 @@ from hvac import exceptions, utils SUPPORTED_MFA_TYPES = [ - 'duo', -] -SUPPORTED_AUTH_METHODS = [ - 'ldap', - 'okta', - 'radius', - 'userpass' + "duo", ] +SUPPORTED_AUTH_METHODS = ["ldap", "okta", "radius", "userpass"] class Mfa(VaultApiBase): @@ -25,7 +20,7 @@ class Mfa(VaultApiBase): Reference: https://www.vaultproject.io/docs/auth/mfa.html """ - def configure(self, mount_point, mfa_type='duo', force=False): + 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. @@ -44,21 +39,22 @@ def configure(self, mount_point, mfa_type='duo', force=False): :return: The response of the configure MFA request. :rtype: requests.Response """ - if mfa_type != 'duo' and not force: + 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, - )) + raise exceptions.ParamValidationError( + error_msg.format( + mfa_types=",".join(SUPPORTED_MFA_TYPES), + arg=mfa_type, + ) + ) params = { - 'type': mfa_type, + "type": mfa_type, } api_path = utils.format_url( - '/v1/auth/{mount_point}/mfa_config', - mount_point=mount_point + "/v1/auth/{mount_point}/mfa_config", mount_point=mount_point ) return self._adapter.post( url=api_path, @@ -78,7 +74,7 @@ def read_configuration(self, mount_point): :rtype: dict """ api_path = utils.format_url( - '/v1/auth/{mount_point}/mfa_config', + "/v1/auth/{mount_point}/mfa_config", mount_point=mount_point, ) return self._adapter.get(url=api_path) @@ -104,12 +100,12 @@ def configure_duo_access(self, mount_point, host, integration_key, secret_key): :rtype: requests.Response """ params = { - 'host': host, - 'ikey': integration_key, - 'skey': secret_key, + "host": host, + "ikey": integration_key, + "skey": secret_key, } api_path = utils.format_url( - '/v1/auth/{mount_point}/duo/access', + "/v1/auth/{mount_point}/duo/access", mount_point=mount_point, ) return self._adapter.post( @@ -117,7 +113,9 @@ def configure_duo_access(self, mount_point, host, integration_key, secret_key): json=params, ) - def configure_duo_behavior(self, mount_point, push_info=None, user_agent=None, username_format='%s'): + 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 @@ -141,14 +139,14 @@ def configure_duo_behavior(self, mount_point, push_info=None, user_agent=None, u :rtype: requests.Response """ params = { - 'username_format': username_format, + "username_format": username_format, } if push_info is not None: - params['push_info'] = push_info + params["push_info"] = push_info if user_agent is not None: - params['user_agent'] = user_agent + params["user_agent"] = user_agent api_path = utils.format_url( - '/v1/auth/{mount_point}/duo/config', + "/v1/auth/{mount_point}/duo/config", mount_point=mount_point, ) return self._adapter.post( @@ -169,7 +167,7 @@ def read_duo_behavior_configuration(self, mount_point): :rtype: dict """ api_path = utils.format_url( - '/v1/auth/{mount_point}/duo/config', + "/v1/auth/{mount_point}/duo/config", mount_point=mount_point, ) return self._adapter.get(url=api_path) diff --git a/hvac/api/auth_methods/oidc.py b/hvac/api/auth_methods/oidc.py index 45335f7e9..ded9aa9c0 100644 --- a/hvac/api/auth_methods/oidc.py +++ b/hvac/api/auth_methods/oidc.py @@ -16,15 +16,37 @@ class OIDC(JWT): 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): + 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, + ): """Register a role in the OIDC method. Role types have specific entities that can perform login operations against this endpoint. Constraints diff --git a/hvac/api/auth_methods/okta.py b/hvac/api/auth_methods/okta.py index 9da3cbf4d..e1cb6a1e8 100644 --- a/hvac/api/auth_methods/okta.py +++ b/hvac/api/auth_methods/okta.py @@ -4,7 +4,7 @@ from hvac import utils from hvac.api.vault_api_base import VaultApiBase -DEFAULT_MOUNT_POINT = 'okta' +DEFAULT_MOUNT_POINT = "okta" class Okta(VaultApiBase): @@ -13,8 +13,16 @@ class Okta(VaultApiBase): 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): + 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. @@ -44,18 +52,22 @@ def configure(self, org_name, api_token=None, base_url=None, ttl=None, max_ttl=N :rtype: requests.Response """ params = { - 'org_name': org_name, + "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, - }) + 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 ) - api_path = utils.format_url('/v1/auth/{mount_point}/config', mount_point=mount_point) return self._adapter.post( url=api_path, json=params, @@ -72,7 +84,9 @@ def read_config(self, mount_point=DEFAULT_MOUNT_POINT): :return: The JSON response of the request. :rtype: dict """ - api_path = utils.format_url('/v1/auth/{mount_point}/config', mount_point=mount_point) + api_path = utils.format_url( + "/v1/auth/{mount_point}/config", mount_point=mount_point + ) return self._adapter.get( url=api_path, ) @@ -88,12 +102,16 @@ def list_users(self, mount_point=DEFAULT_MOUNT_POINT): :return: The JSON response of the request. :rtype: dict """ - api_path = utils.format_url('/v1/auth/{mount_point}/users', mount_point=mount_point) + 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): + 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: @@ -111,16 +129,18 @@ def register_user(self, username, groups=None, policies=None, mount_point=DEFAUL :rtype: requests.Response """ params = { - 'username': username, + "username": username, } params.update( - utils.remove_nones({ - 'groups': groups, - 'policies': policies, - }) + utils.remove_nones( + { + "groups": groups, + "policies": policies, + } + ) ) api_path = utils.format_url( - '/v1/auth/{mount_point}/users/{username}', + "/v1/auth/{mount_point}/users/{username}", mount_point=mount_point, username=username, ) @@ -143,10 +163,10 @@ def read_user(self, username, mount_point=DEFAULT_MOUNT_POINT): :rtype: dict """ params = { - 'username': username, + "username": username, } api_path = utils.format_url( - '/v1/auth/{mount_point}/users/{username}', + "/v1/auth/{mount_point}/users/{username}", mount_point=mount_point, username=username, ) @@ -169,10 +189,10 @@ def delete_user(self, username, mount_point=DEFAULT_MOUNT_POINT): :rtype: requests.Response """ params = { - 'username': username, + "username": username, } api_path = utils.format_url( - '/v1/auth/{mount_point}/users/{username}', + "/v1/auth/{mount_point}/users/{username}", mount_point=mount_point, username=username, ) @@ -192,7 +212,9 @@ def list_groups(self, mount_point=DEFAULT_MOUNT_POINT): :return: The JSON response of the request. :rtype: dict """ - api_path = utils.format_url('/v1/auth/{mount_point}/groups', mount_point=mount_point) + api_path = utils.format_url( + "/v1/auth/{mount_point}/groups", mount_point=mount_point + ) return self._adapter.list( url=api_path, ) @@ -212,11 +234,13 @@ def register_group(self, name, policies=None, mount_point=DEFAULT_MOUNT_POINT): :return: The response of the request. :rtype: requests.Response """ - params = utils.remove_nones({ - 'policies': policies, - }) + params = utils.remove_nones( + { + "policies": policies, + } + ) api_path = utils.format_url( - '/v1/auth/{mount_point}/groups/{name}', + "/v1/auth/{mount_point}/groups/{name}", mount_point=mount_point, name=name, ) @@ -239,7 +263,7 @@ def read_group(self, name, mount_point=DEFAULT_MOUNT_POINT): :rtype: dict """ api_path = utils.format_url( - '/v1/auth/{mount_point}/groups/{name}', + "/v1/auth/{mount_point}/groups/{name}", mount_point=mount_point, name=name, ) @@ -261,10 +285,10 @@ def delete_group(self, name, mount_point=DEFAULT_MOUNT_POINT): :rtype: requests.Response """ params = { - 'name': name, + "name": name, } api_path = utils.format_url( - '/v1/auth/{mount_point}/groups/{name}', + "/v1/auth/{mount_point}/groups/{name}", mount_point=mount_point, name=name, ) @@ -273,7 +297,9 @@ def delete_group(self, name, mount_point=DEFAULT_MOUNT_POINT): json=params, ) - def login(self, username, password, use_token=True, mount_point=DEFAULT_MOUNT_POINT): + def login( + self, username, password, use_token=True, mount_point=DEFAULT_MOUNT_POINT + ): """Login with the username and password. Supported methods: @@ -292,11 +318,11 @@ def login(self, username, password, use_token=True, mount_point=DEFAULT_MOUNT_PO :rtype: dict """ params = { - 'username': username, - 'password': password, + "username": username, + "password": password, } api_path = utils.format_url( - '/v1/auth/{mount_point}/login/{username}', + "/v1/auth/{mount_point}/login/{username}", mount_point=mount_point, username=username, ) diff --git a/hvac/api/auth_methods/radius.py b/hvac/api/auth_methods/radius.py index 13830d7b7..6d7217cb3 100644 --- a/hvac/api/auth_methods/radius.py +++ b/hvac/api/auth_methods/radius.py @@ -4,7 +4,7 @@ from hvac import exceptions, utils from hvac.api.vault_api_base import VaultApiBase -DEFAULT_MOUNT_POINT = 'radius' +DEFAULT_MOUNT_POINT = "radius" class Radius(VaultApiBase): @@ -13,8 +13,16 @@ class Radius(VaultApiBase): 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): + 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. @@ -39,15 +47,17 @@ def configure(self, host, secret, port=None, unregistered_user_policies=None, di :rtype: requests.Response """ params = { - 'host': host, - 'secret': secret, + "host": host, + "secret": secret, } params.update( - utils.remove_nones({ - 'port': port, - 'dial_timeout': dial_timeout, - 'nas_port': nas_port, - }) + 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: @@ -58,9 +68,11 @@ def configure(self, host, secret, port=None, unregistered_user_policies=None, di ).format(unregistered_user_policies=type(unregistered_user_policies)) raise exceptions.ParamValidationError(error_msg) - params['unregistered_user_policies'] = ','.join(unregistered_user_policies) + params["unregistered_user_policies"] = ",".join(unregistered_user_policies) - api_path = utils.format_url('/v1/auth/{mount_point}/config', mount_point=mount_point) + api_path = utils.format_url( + "/v1/auth/{mount_point}/config", mount_point=mount_point + ) return self._adapter.post( url=api_path, json=params, @@ -78,7 +90,9 @@ def read_configuration(self, mount_point=DEFAULT_MOUNT_POINT): :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) + api_path = utils.format_url( + "/v1/auth/{mount_point}/config", mount_point=mount_point + ) return self._adapter.get( url=api_path, ) @@ -108,9 +122,9 @@ def register_user(self, username, policies=None, mount_point=DEFAULT_MOUNT_POINT params = {} if policies is not None: - params['policies'] = ','.join(policies) + params["policies"] = ",".join(policies) api_path = utils.format_url( - '/v1/auth/{mount_point}/users/{name}', + "/v1/auth/{mount_point}/users/{name}", mount_point=mount_point, name=username, ) @@ -132,7 +146,9 @@ def list_users(self, mount_point=DEFAULT_MOUNT_POINT): :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) + api_path = utils.format_url( + "/v1/auth/{mount_point}/users", mount_point=mount_point + ) return self._adapter.list( url=api_path, ) @@ -153,7 +169,7 @@ def read_user(self, username, mount_point=DEFAULT_MOUNT_POINT): :rtype: dict """ api_path = utils.format_url( - '/v1/auth/{mount_point}/users/{username}', + "/v1/auth/{mount_point}/users/{username}", mount_point=mount_point, username=username, ) @@ -177,7 +193,7 @@ def delete_user(self, username, mount_point=DEFAULT_MOUNT_POINT): :rtype: requests.Response """ api_path = utils.format_url( - '/v1/auth/{mount_point}/users/{username}', + "/v1/auth/{mount_point}/users/{username}", mount_point=mount_point, username=username, ) @@ -185,7 +201,9 @@ def delete_user(self, username, mount_point=DEFAULT_MOUNT_POINT): url=api_path, ) - def login(self, username, password, use_token=True, mount_point=DEFAULT_MOUNT_POINT): + def login( + self, username, password, use_token=True, mount_point=DEFAULT_MOUNT_POINT + ): """ Log in with RADIUS credentials. @@ -206,10 +224,10 @@ def login(self, username, password, use_token=True, mount_point=DEFAULT_MOUNT_PO :rtype: requests.Response """ params = { - 'password': password, + "password": password, } api_path = utils.format_url( - '/v1/auth/{mount_point}/login/{username}', + "/v1/auth/{mount_point}/login/{username}", mount_point=mount_point, username=username, ) diff --git a/hvac/api/auth_methods/token.py b/hvac/api/auth_methods/token.py new file mode 100644 index 000000000..8d3c9ec43 --- /dev/null +++ b/hvac/api/auth_methods/token.py @@ -0,0 +1,565 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +"""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, + } + ) + + if role_name is not None: + api_path = "/v1/auth/{mount_point}/create/{role_name}".format( + mount_point=mount_point, + role_name=role_name, + ) + return self._adapter.post( + url=api_path, + json=params, + ) + + api_path = "/v1/auth/{mount_point}/create".format(mount_point=mount_point) + 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 = "/v1/auth/{mount_point}/accessors".format(mount_point=mount_point) + 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 = "/v1/auth/{mount_point}/lookup".format(mount_point=mount_point) + 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 = "/v1/auth/{mount_point}/lookup-self".format(mount_point=mount_point) + 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 = "/v1/auth/{mount_point}/renew".format(mount_point=mount_point) + 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 = "/v1/auth/{mount_point}/renew-self".format(mount_point=mount_point) + 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 = "/v1/auth/{mount_point}/revoke".format(mount_point=mount_point) + return self._adapter.post( + url=api_path, + json=params, + ) + + def revoke_self(self, accessor, 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 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_self request. + :rtype: requests.Response + """ + params = { + "accessor": accessor, + } + api_path = "/v1/auth/{mount_point}/revoke-self".format(mount_point=mount_point) + return self._adapter.post( + url=api_path, + json=params, + ) + + 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 = "/v1/auth/{mount_point}/roles".format(mount_point=mount_point) + 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, + ): + """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 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, + } + ) + 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 = "/v1/auth/{mount_point}/tidy".format(mount_point=mount_point) + return self._adapter.post( + url=api_path, + ) diff --git a/hvac/api/auth_methods/userpass.py b/hvac/api/auth_methods/userpass.py index c6164f8a6..092e31de1 100644 --- a/hvac/api/auth_methods/userpass.py +++ b/hvac/api/auth_methods/userpass.py @@ -4,7 +4,7 @@ from hvac import utils from hvac.api.vault_api_base import VaultApiBase -DEFAULT_MOUNT_POINT = 'userpass' +DEFAULT_MOUNT_POINT = "userpass" class Userpass(VaultApiBase): @@ -12,7 +12,14 @@ class Userpass(VaultApiBase): Reference: https://www.vaultproject.io/api/auth/userpass/index.html """ - def create_or_update_user(self, username, password, policies=None, mount_point=DEFAULT_MOUNT_POINT): + def create_or_update_user( + self, + username, + password=None, + policies=None, + mount_point=DEFAULT_MOUNT_POINT, + **kwargs + ): """ Create/update user in userpass. @@ -27,16 +34,20 @@ def create_or_update_user(self, username, password, policies=None, mount_point=D :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 = { - 'password': password, - } - params.update( - utils.remove_nones({ - 'policies': policies, - }) + 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 ) - api_path = '/v1/auth/{mount_point}/users/{username}'.format(mount_point=mount_point, username=username) return self._adapter.post( url=api_path, json=params, @@ -54,7 +65,7 @@ def list_user(self, mount_point=DEFAULT_MOUNT_POINT): :return: The JSON response of the list_groups request. :rtype: dict """ - api_path = '/v1/auth/{mount_point}/users'.format(mount_point=mount_point) + api_path = "/v1/auth/{mount_point}/users".format(mount_point=mount_point) return self._adapter.list( url=api_path, ) @@ -73,7 +84,9 @@ def read_user(self, username, mount_point=DEFAULT_MOUNT_POINT): :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) + api_path = "/v1/auth/{mount_point}/users/{username}".format( + mount_point=mount_point, username=username + ) return self._adapter.get( url=api_path, ) @@ -92,12 +105,16 @@ def delete_user(self, username, mount_point=DEFAULT_MOUNT_POINT): :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) + 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): + def update_password_on_user( + self, username, password, mount_point=DEFAULT_MOUNT_POINT + ): """ update password for the user in userpass. @@ -112,15 +129,19 @@ def update_password_on_user(self, username, password, mount_point=DEFAULT_MOUNT_ :type mount_point: str | unicode """ params = { - 'password': password, + "password": password, } - api_path = '/v1/auth/{mount_point}/users/{username}/password'.format(mount_point=mount_point, username=username) + 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, mount_point=DEFAULT_MOUNT_POINT): + def login( + self, username, password, use_token=True, mount_point=DEFAULT_MOUNT_POINT + ): """ Log in with USERPASS credentials. @@ -135,10 +156,13 @@ def login(self, username, password, mount_point=DEFAULT_MOUNT_POINT): :type mount_point: str | unicode """ params = { - 'password': password, + "password": password, } - api_path = '/v1/auth/{mount_point}/login/{username}'.format(mount_point=mount_point, username=username) - return self._adapter.post( + api_path = "/v1/auth/{mount_point}/login/{username}".format( + mount_point=mount_point, username=username + ) + return self._adapter.login( url=api_path, + use_token=use_token, json=params, ) diff --git a/hvac/api/secrets_engines/__init__.py b/hvac/api/secrets_engines/__init__.py index fb3dfeec3..638e2eac4 100644 --- a/hvac/api/secrets_engines/__init__.py +++ b/hvac/api/secrets_engines/__init__.py @@ -16,20 +16,20 @@ from hvac.api.vault_api_category import VaultApiCategory __all__ = ( - 'Aws', - 'Azure', - 'Gcp', - 'ActiveDirectory', - 'Identity', - 'Kv', - 'KvV1', - 'KvV2', - 'Pki', - 'Transform', - 'Transit', - 'SecretsEngines', - 'Database', - 'RabbitMQ' + "Aws", + "Azure", + "Gcp", + "ActiveDirectory", + "Identity", + "Kv", + "KvV1", + "KvV2", + "Pki", + "Transform", + "Transit", + "SecretsEngines", + "Database", + "RabbitMQ", ) @@ -51,15 +51,15 @@ class SecretsEngines(VaultApiCategory): RabbitMQ, ] unimplemented_classes = [ - 'AliCloud', - 'Azure', - 'GcpKms', - 'Nomad', - 'Ssh', - 'TOTP', - 'Cassandra', - 'MongoDb', - 'Mssql', - 'MySql', - 'PostgreSql', + "AliCloud", + "Azure", + "GcpKms", + "Nomad", + "Ssh", + "TOTP", + "Cassandra", + "MongoDb", + "Mssql", + "MySql", + "PostgreSql", ] diff --git a/hvac/api/secrets_engines/active_directory.py b/hvac/api/secrets_engines/active_directory.py index 49e3488f5..0d1b55cf4 100644 --- a/hvac/api/secrets_engines/active_directory.py +++ b/hvac/api/secrets_engines/active_directory.py @@ -5,7 +5,7 @@ from hvac import utils from hvac.api.vault_api_base import VaultApiBase -DEFAULT_MOUNT_POINT = 'ad' +DEFAULT_MOUNT_POINT = "ad" class ActiveDirectory(VaultApiBase): @@ -13,8 +13,19 @@ class ActiveDirectory(VaultApiBase): 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): + 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: @@ -40,19 +51,21 @@ def configure(self, binddn=None, bindpass=None, url=None, userdn=None, upndomain :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 = 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) + api_path = utils.format_url("/v1/{mount_point}/config", mount_point=mount_point) return self._adapter.post( url=api_path, json=params, @@ -71,12 +84,14 @@ def read_config(self, mount_point=DEFAULT_MOUNT_POINT): :return: The JSON response of the request. :rtype: dict """ - api_path = utils.format_url('/v1/{mount_point}/config', mount_point=mount_point) + 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): + 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. @@ -98,10 +113,12 @@ def create_or_update_role(self, name, service_account_name=None, ttl=None, mount "name": name, } params.update( - utils.remove_nones({ - "service_account_name": service_account_name, - "ttl": ttl, - }) + utils.remove_nones( + { + "service_account_name": service_account_name, + "ttl": ttl, + } + ) ) return self._adapter.post( url=api_path, diff --git a/hvac/api/secrets_engines/aws.py b/hvac/api/secrets_engines/aws.py index 6eb1caaa3..ac36de614 100644 --- a/hvac/api/secrets_engines/aws.py +++ b/hvac/api/secrets_engines/aws.py @@ -5,7 +5,11 @@ 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 +from hvac.constants.aws import ( + DEFAULT_MOUNT_POINT, + ALLOWED_CREDS_ENDPOINTS, + ALLOWED_CREDS_TYPES, +) class Aws(VaultApiBase): @@ -14,8 +18,16 @@ class Aws(VaultApiBase): 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): + 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 @@ -54,18 +66,22 @@ def configure_root_iam_credentials(self, access_key, secret_key, region=None, ia :rtype: requests.Response """ params = { - 'access_key': access_key, - 'secret_key': secret_key, - 'max_retries': max_retries, + "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, - }) + 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 ) - api_path = utils.format_url('/v1/{mount_point}/config/root', mount_point=mount_point) return self._adapter.post( url=api_path, json=params, @@ -88,7 +104,9 @@ def rotate_root_iam_credentials(self, mount_point=DEFAULT_MOUNT_POINT): :return: The JSON response of the request. :rtype: dict """ - api_path = utils.format_url('/v1/{mount_point}/config/rotate-root', mount_point=mount_point) + api_path = utils.format_url( + "/v1/{mount_point}/config/rotate-root", mount_point=mount_point + ) return self._adapter.post( url=api_path, ) @@ -113,10 +131,12 @@ def configure_lease(self, lease, lease_max, mount_point=DEFAULT_MOUNT_POINT): :rtype: requests.Response """ params = { - 'lease': lease, - 'lease_max': lease_max, + "lease": lease, + "lease_max": lease_max, } - api_path = utils.format_url('/v1/{mount_point}/config/lease', mount_point=mount_point) + api_path = utils.format_url( + "/v1/{mount_point}/config/lease", mount_point=mount_point + ) return self._adapter.post( url=api_path, json=params, @@ -133,13 +153,26 @@ def read_lease_config(self, mount_point=DEFAULT_MOUNT_POINT): :return: The JSON response of the request. :rtype: dict """ - api_path = utils.format_url('/v1/{mount_point}/config/lease', mount_point=mount_point) + 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): + 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 @@ -186,35 +219,39 @@ def create_or_update_role(self, name, credential_type, policy_document=None, def """ 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), - )) + 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, + "policy": policy_document, + "arn": policy_arns[0] if isinstance(policy_arns, list) else policy_arns, } else: params = { - 'credential_type': credential_type, + "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, - }) + 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}', + "/v1/{mount_point}/roles/{name}", mount_point=mount_point, name=name, ) @@ -239,7 +276,7 @@ def read_role(self, name, mount_point=DEFAULT_MOUNT_POINT): :rtype: dict """ api_path = utils.format_url( - '/v1/{mount_point}/roles/{name}', + "/v1/{mount_point}/roles/{name}", mount_point=mount_point, name=name, ) @@ -258,7 +295,7 @@ def list_roles(self, mount_point=DEFAULT_MOUNT_POINT): :return: The JSON response of the request. :rtype: dict """ - api_path = utils.format_url('/v1/{mount_point}/roles', mount_point=mount_point) + api_path = utils.format_url("/v1/{mount_point}/roles", mount_point=mount_point) return self._adapter.list( url=api_path, ) @@ -280,7 +317,7 @@ def delete_role(self, name, mount_point=DEFAULT_MOUNT_POINT): :rtype: requests.Response """ api_path = utils.format_url( - '/v1/{mount_point}/roles/{name}', + "/v1/{mount_point}/roles/{name}", mount_point=mount_point, name=name, ) @@ -288,7 +325,14 @@ def delete_role(self, name, mount_point=DEFAULT_MOUNT_POINT): url=api_path, ) - def generate_credentials(self, name, role_arn=None, ttl=None, endpoint='creds', mount_point=DEFAULT_MOUNT_POINT): + def generate_credentials( + self, + name, + role_arn=None, + ttl=None, + endpoint="creds", + mount_point=DEFAULT_MOUNT_POINT, + ): """Generates credential based on the named role. This role must be created before queried. @@ -313,7 +357,7 @@ def generate_credentials(self, name, role_arn=None, ttl=None, endpoint='creds', :type ttl: str | unicode :param endpoint: Supported endpoints: GET: /{mount_point}/creds/{name}. Produces: 200 application/json - GET: /{mount_point}/sts/{name}. Produces: 200 application/json + PUT: /{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 @@ -322,27 +366,37 @@ def generate_credentials(self, name, role_arn=None, ttl=None, endpoint='creds', """ 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), - )) + raise exceptions.ParamValidationError( + error_msg.format( + arg=endpoint, + allowed_endpoints=", ".join(ALLOWED_CREDS_ENDPOINTS), + ) + ) params = { - 'name': name, + "name": name, } params.update( - utils.remove_nones({ - 'role_arn': role_arn, - 'ttl': ttl, - }) + utils.remove_nones( + { + "role_arn": role_arn, + "ttl": ttl, + } + ) ) api_path = utils.format_url( - '/v1/{mount_point}/{endpoint}/{name}', + "/v1/{mount_point}/{endpoint}/{name}", mount_point=mount_point, endpoint=endpoint, name=name, ) - return self._adapter.get( - url=api_path, - params=params, - ) + if endpoint == "sts": + return self._adapter.put( + url=api_path, + params=params, + ) + else: + return self._adapter.get( + url=api_path, + params=params, + ) diff --git a/hvac/api/secrets_engines/azure.py b/hvac/api/secrets_engines/azure.py index 360f83c4e..aafe13f19 100644 --- a/hvac/api/secrets_engines/azure.py +++ b/hvac/api/secrets_engines/azure.py @@ -7,7 +7,7 @@ from hvac.api.vault_api_base import VaultApiBase from hvac.constants.azure import VALID_ENVIRONMENTS -DEFAULT_MOUNT_POINT = 'azure' +DEFAULT_MOUNT_POINT = "azure" class Azure(VaultApiBase): @@ -16,8 +16,15 @@ class Azure(VaultApiBase): 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): + 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 @@ -44,22 +51,26 @@ def configure(self, subscription_id, tenant_id, client_id=None, client_secret=No """ 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), - )) + raise exceptions.ParamValidationError( + error_msg.format( + arg=environment, + environments=",".join(VALID_ENVIRONMENTS), + ) + ) params = { - 'subscription_id': subscription_id, - 'tenant_id': tenant_id, + "subscription_id": subscription_id, + "tenant_id": tenant_id, } params.update( - utils.remove_nones({ - 'client_id': client_id, - 'client_secret': client_secret, - 'environment': environment, - }) + 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) + api_path = utils.format_url("/v1/{mount_point}/config", mount_point=mount_point) return self._adapter.post( url=api_path, json=params, @@ -77,11 +88,11 @@ def read_config(self, mount_point=DEFAULT_MOUNT_POINT): :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) + api_path = utils.format_url("/v1/{mount_point}/config", mount_point=mount_point) response = self._adapter.get( url=api_path, ) - return response.get('data') + return response.get("data") def delete_config(self, mount_point=DEFAULT_MOUNT_POINT): """Delete the stored Azure configuration and credentials. @@ -95,12 +106,14 @@ def delete_config(self, mount_point=DEFAULT_MOUNT_POINT): :return: The response of the request. :rtype: requests.Response """ - api_path = utils.format_url('/v1/{mount_point}/config', mount_point=mount_point) + 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): + 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 @@ -126,16 +139,18 @@ def create_or_update_role(self, name, azure_roles, ttl=None, max_ttl=None, mount :rtype: requests.Response """ params = { - 'azure_roles': json.dumps(azure_roles), + "azure_roles": json.dumps(azure_roles), } params.update( - utils.remove_nones({ - 'ttl': ttl, - 'max_ttl': max_ttl, - }) + utils.remove_nones( + { + "ttl": ttl, + "max_ttl": max_ttl, + } + ) ) api_path = utils.format_url( - '/v1/{mount_point}/roles/{name}', + "/v1/{mount_point}/roles/{name}", mount_point=mount_point, name=name, ) @@ -156,11 +171,11 @@ def list_roles(self, mount_point=DEFAULT_MOUNT_POINT): :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) + api_path = utils.format_url("/v1/{mount_point}/roles", mount_point=mount_point) response = self._adapter.list( url=api_path, ) - return response.get('data') + return response.get("data") def generate_credentials(self, name, mount_point=DEFAULT_MOUNT_POINT): """Generate a new service principal based on the named role. @@ -177,11 +192,11 @@ def generate_credentials(self, name, mount_point=DEFAULT_MOUNT_POINT): :rtype: dict """ api_path = utils.format_url( - '/v1/{mount_point}/creds/{name}', + "/v1/{mount_point}/creds/{name}", mount_point=mount_point, name=name, ) response = self._adapter.get( url=api_path, ) - return response.get('data') + return response.get("data") diff --git a/hvac/api/secrets_engines/consul.py b/hvac/api/secrets_engines/consul.py index fd54e18c8..9841b4a02 100644 --- a/hvac/api/secrets_engines/consul.py +++ b/hvac/api/secrets_engines/consul.py @@ -13,7 +13,9 @@ class Consul(VaultApiBase): Reference: https://www.vaultproject.io/api/secret/consul/index.html """ - def configure_access(self, address, token, scheme=None, mount_point=DEFAULT_MOUNT_POINT): + 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. @@ -33,9 +35,11 @@ def configure_access(self, address, token, scheme=None, mount_point=DEFAULT_MOUN "token": token, } params.update( - utils.remove_nones({ - "scheme": scheme, - }) + utils.remove_nones( + { + "scheme": scheme, + } + ) ) api_path = utils.format_url("/v1/{}/config/access", mount_point) @@ -44,8 +48,17 @@ def configure_access(self, address, token, scheme=None, mount_point=DEFAULT_MOUN 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): + 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. @@ -80,14 +93,16 @@ def create_or_update_role(self, name, policy=None, policies=None, token_type=Non """ 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 - }) + 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, diff --git a/hvac/api/secrets_engines/database.py b/hvac/api/secrets_engines/database.py index 17c458c2b..ff0339e00 100644 --- a/hvac/api/secrets_engines/database.py +++ b/hvac/api/secrets_engines/database.py @@ -13,8 +13,17 @@ class Database(VaultApiBase): 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): + 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. @@ -39,16 +48,20 @@ def configure(self, name, plugin_name, verify_connection=None, allowed_roles=Non "plugin_name": plugin_name, } params.update( - utils.remove_nones({ - "allowed_roles": allowed_roles, - "verify_connection": verify_connection, - "root_rotation_statements": root_rotation_statements, - }) + 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) + 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, @@ -63,7 +76,9 @@ def rotate_root_credentials(self, name, mount_point=DEFAULT_MOUNT_POINT): :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) + api_path = utils.format_url( + "/v1/{mount_point}/rotate-root/{name}", mount_point=mount_point, name=name + ) return self._adapter.post( url=api_path, ) @@ -77,7 +92,9 @@ def read_connection(self, name, mount_point=DEFAULT_MOUNT_POINT): :rtype: requests.Response """ - api_path = utils.format_url('/v1/{mount_point}/config/{name}', mount_point=mount_point, name=name) + api_path = utils.format_url( + "/v1/{mount_point}/config/{name}", mount_point=mount_point, name=name + ) return self._adapter.get( url=api_path, @@ -90,7 +107,7 @@ def list_connections(self, mount_point=DEFAULT_MOUNT_POINT): :rtype: requests.Response """ - api_path = utils.format_url('/v1/{mount_point}/config', mount_point=mount_point) + api_path = utils.format_url("/v1/{mount_point}/config", mount_point=mount_point) return self._adapter.list( url=api_path, ) @@ -104,7 +121,9 @@ def delete_connection(self, name, mount_point=DEFAULT_MOUNT_POINT): :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) + api_path = utils.format_url( + "/v1/{mount_point}/config/{name}", mount_point=mount_point, name=name + ) return self._adapter.delete( url=api_path, ) @@ -118,14 +137,25 @@ def reset_connection(self, name, mount_point=DEFAULT_MOUNT_POINT): :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) + 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): + 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. @@ -156,23 +186,31 @@ def create_role(self, name, db_name, creation_statements, default_ttl=None, max_ "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, - }) + 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 + 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): + 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. @@ -216,7 +254,9 @@ def read_role(self, name, mount_point=DEFAULT_MOUNT_POINT): :rtype: requests.Response """ - api_path = utils.format_url('/v1/{mount_point}/roles/{name}', mount_point=mount_point, name=name) + api_path = utils.format_url( + "/v1/{mount_point}/roles/{name}", mount_point=mount_point, name=name + ) return self._adapter.get( url=api_path, @@ -231,7 +271,7 @@ def list_roles(self, mount_point=DEFAULT_MOUNT_POINT): :rtype: requests.Response """ - api_path = utils.format_url('/v1/{mount_point}/roles', mount_point=mount_point) + api_path = utils.format_url("/v1/{mount_point}/roles", mount_point=mount_point) return self._adapter.list( url=api_path, ) @@ -248,7 +288,9 @@ def list_static_roles(self, mount_point=DEFAULT_MOUNT_POINT): api_path = utils.format_url( "/v1/{mount_point}/static-roles", mount_point=mount_point ) - return self._adapter.list(url=api_path,) + return self._adapter.list( + url=api_path, + ) def delete_role(self, name, mount_point=DEFAULT_MOUNT_POINT): """This endpoint deletes the role definition. @@ -260,7 +302,9 @@ def delete_role(self, name, mount_point=DEFAULT_MOUNT_POINT): :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) + api_path = utils.format_url( + "/v1/{mount_point}/roles/{name}", mount_point=mount_point, name=name + ) return self._adapter.delete( url=api_path, ) @@ -278,7 +322,9 @@ def delete_static_role(self, name, mount_point=DEFAULT_MOUNT_POINT): api_path = utils.format_url( "/v1/{mount_point}/static-roles/{name}", mount_point=mount_point, name=name ) - return self._adapter.delete(url=api_path,) + 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. @@ -291,7 +337,9 @@ def generate_credentials(self, name, mount_point=DEFAULT_MOUNT_POINT): :rtype: requests.Response """ - api_path = utils.format_url('/v1/{mount_point}/creds/{name}', mount_point=mount_point, name=name) + api_path = utils.format_url( + "/v1/{mount_point}/creds/{name}", mount_point=mount_point, name=name + ) return self._adapter.get( url=api_path, diff --git a/hvac/api/secrets_engines/gcp.py b/hvac/api/secrets_engines/gcp.py index f71a191b2..6884321df 100644 --- a/hvac/api/secrets_engines/gcp.py +++ b/hvac/api/secrets_engines/gcp.py @@ -6,9 +6,13 @@ 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 +from hvac.constants.gcp import ( + ALLOWED_SECRETS_TYPES, + SERVICE_ACCOUNT_KEY_ALGORITHMS, + SERVICE_ACCOUNT_KEY_TYPES, +) -DEFAULT_MOUNT_POINT = 'gcp' +DEFAULT_MOUNT_POINT = "gcp" class Gcp(VaultApiBase): @@ -17,7 +21,9 @@ class Gcp(VaultApiBase): 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): + 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: @@ -37,12 +43,14 @@ def configure(self, credentials=None, ttl=None, max_ttl=None, mount_point=DEFAUL :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) + 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, @@ -61,13 +69,20 @@ def read_config(self, mount_point=DEFAULT_MOUNT_POINT): :return: The JSON response of the request. :rtype: dict """ - api_path = utils.format_url('/v1/{mount_point}/config', mount_point=mount_point) + 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): + 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 @@ -94,28 +109,32 @@ def create_or_update_roleset(self, name, project, bindings, secret_type=None, to """ 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), - )) + 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) + bindings = json.dumps(bindings).replace(" ", "") + logging.debug("bindings: %s" % bindings) params = { - 'project': project, - 'bindings': bindings, + "project": project, + "bindings": bindings, } params.update( - utils.remove_nones({ - 'secret_type': secret_type, - 'token_scopes': token_scopes, - }) + utils.remove_nones( + { + "secret_type": secret_type, + "token_scopes": token_scopes, + } + ) ) api_path = utils.format_url( - '/v1/{mount_point}/roleset/{name}', + "/v1/{mount_point}/roleset/{name}", mount_point=mount_point, name=name, ) @@ -142,7 +161,7 @@ def rotate_roleset_account(self, name, mount_point=DEFAULT_MOUNT_POINT): :rtype: requests.Response """ api_path = utils.format_url( - '/v1/{mount_point}/roleset/{name}/rotate', + "/v1/{mount_point}/roleset/{name}/rotate", mount_point=mount_point, name=name, ) @@ -166,9 +185,9 @@ def rotate_roleset_account_key(self, name, mount_point=DEFAULT_MOUNT_POINT): :rtype: requests.Response """ api_path = utils.format_url( - '/v1/{mount_point}/roleset/{name}/rotate-key', + "/v1/{mount_point}/roleset/{name}/rotate-key", mount_point=mount_point, - name=name + name=name, ) return self._adapter.post( url=api_path, @@ -188,7 +207,7 @@ def read_roleset(self, name, mount_point=DEFAULT_MOUNT_POINT): :rtype: dict """ api_path = utils.format_url( - '/v1/{mount_point}/roleset/{name}', + "/v1/{mount_point}/roleset/{name}", mount_point=mount_point, name=name, ) @@ -207,7 +226,9 @@ def list_rolesets(self, mount_point=DEFAULT_MOUNT_POINT): :return: The JSON response of the request. :rtype: dict """ - api_path = utils.format_url('/v1/{mount_point}/rolesets', mount_point=mount_point) + api_path = utils.format_url( + "/v1/{mount_point}/rolesets", mount_point=mount_point + ) return self._adapter.list( url=api_path, ) @@ -226,7 +247,7 @@ def delete_roleset(self, name, mount_point=DEFAULT_MOUNT_POINT): :rtype: requests.Response """ api_path = utils.format_url( - '/v1/{mount_point}/roleset/{name}', + "/v1/{mount_point}/roleset/{name}", name=name, mount_point=mount_point, ) @@ -250,7 +271,7 @@ def generate_oauth2_access_token(self, roleset, mount_point=DEFAULT_MOUNT_POINT) :rtype: dict """ api_path = utils.format_url( - '/v1/{mount_point}/token/{roleset}', + "/v1/{mount_point}/token/{roleset}", mount_point=mount_point, roleset=roleset, ) @@ -258,9 +279,14 @@ def generate_oauth2_access_token(self, roleset, mount_point=DEFAULT_MOUNT_POINT) 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): + 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 @@ -283,40 +309,46 @@ def generate_service_account_key(self, roleset, key_algorithm='KEY_ALG_RSA_2048' :rtype: dict """ api_path = utils.format_url( - '/v1/{mount_point}/key/{roleset}', + "/v1/{mount_point}/key/{roleset}", mount_point=mount_point, roleset=roleset, ) - if 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), - )) + 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), - )) + 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, + "key_algorithm": key_algorithm, + "key_type": key_type, } response = self._adapter.post( url=api_path, json=params, ) - elif method == 'GET': + 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) + error_message = '"method" parameter provided invalid value; POST or GET allowed, "{method}" provided'.format( + method=method + ) raise exceptions.ParamValidationError(error_message) return response diff --git a/hvac/api/secrets_engines/identity.py b/hvac/api/secrets_engines/identity.py index 443e98b3e..a4a21bf45 100644 --- a/hvac/api/secrets_engines/identity.py +++ b/hvac/api/secrets_engines/identity.py @@ -7,7 +7,7 @@ from hvac.api.vault_api_base import VaultApiBase from hvac.constants.identity import ALLOWED_GROUP_TYPES -DEFAULT_MOUNT_POINT = 'identity' +DEFAULT_MOUNT_POINT = "identity" logger = logging.getLogger(__name__) @@ -18,8 +18,15 @@ class Identity(VaultApiBase): Reference: https://www.vaultproject.io/api/secret/identity/entity.html """ - def create_or_update_entity(self, name, entity_id=None, metadata=None, policies=None, disabled=None, - mount_point=DEFAULT_MOUNT_POINT): + def create_or_update_entity( + self, + name, + entity_id=None, + metadata=None, + policies=None, + disabled=None, + mount_point=DEFAULT_MOUNT_POINT, + ): """Create or update an Entity. Supported methods: @@ -43,25 +50,35 @@ def create_or_update_entity(self, name, entity_id=None, metadata=None, policies= """ if metadata is not None and not isinstance(metadata, dict): error_msg = 'unsupported metadata argument provided "{arg}" ({arg_type}), required type: dict"' - raise exceptions.ParamValidationError(error_msg.format( - arg=metadata, - arg_type=type(metadata), - )) - params = utils.remove_nones({ - 'id': entity_id, - 'name': name, - 'metadata': metadata, - 'policies': policies, - 'disabled': disabled, - }) - api_path = utils.format_url('/v1/{mount_point}/entity', mount_point=mount_point) + raise exceptions.ParamValidationError( + error_msg.format( + arg=metadata, + arg_type=type(metadata), + ) + ) + params = utils.remove_nones( + { + "id": entity_id, + "name": name, + "metadata": metadata, + "policies": policies, + "disabled": disabled, + } + ) + api_path = utils.format_url("/v1/{mount_point}/entity", mount_point=mount_point) return self._adapter.post( url=api_path, json=params, ) - def create_or_update_entity_by_name(self, name, metadata=None, policies=None, disabled=None, - mount_point=DEFAULT_MOUNT_POINT): + def create_or_update_entity_by_name( + self, + name, + metadata=None, + policies=None, + disabled=None, + mount_point=DEFAULT_MOUNT_POINT, + ): """Create or update an entity by a given name. Supported methods: @@ -83,17 +100,21 @@ def create_or_update_entity_by_name(self, name, metadata=None, policies=None, di """ if metadata is not None and not isinstance(metadata, dict): error_msg = 'unsupported metadata argument provided "{arg}" ({arg_type}), required type: dict"' - raise exceptions.ParamValidationError(error_msg.format( - arg=metadata, - arg_type=type(metadata), - )) - params = utils.remove_nones({ - 'metadata': metadata, - 'policies': policies, - 'disabled': disabled, - }) + raise exceptions.ParamValidationError( + error_msg.format( + arg=metadata, + arg_type=type(metadata), + ) + ) + params = utils.remove_nones( + { + "metadata": metadata, + "policies": policies, + "disabled": disabled, + } + ) api_path = utils.format_url( - '/v1/{mount_point}/entity/name/{name}', + "/v1/{mount_point}/entity/name/{name}", mount_point=mount_point, name=name, ) @@ -116,7 +137,7 @@ def read_entity(self, entity_id, mount_point=DEFAULT_MOUNT_POINT): :rtype: dict """ api_path = utils.format_url( - '/v1/{mount_point}/entity/id/{id}', + "/v1/{mount_point}/entity/id/{id}", mount_point=mount_point, id=entity_id, ) @@ -136,7 +157,7 @@ def read_entity_by_name(self, name, mount_point=DEFAULT_MOUNT_POINT): :rtype: requests.Response """ api_path = utils.format_url( - '/v1/{mount_point}/entity/name/{name}', + "/v1/{mount_point}/entity/name/{name}", mount_point=mount_point, name=name, ) @@ -144,8 +165,15 @@ def read_entity_by_name(self, name, mount_point=DEFAULT_MOUNT_POINT): url=api_path, ) - def update_entity(self, entity_id, name=None, metadata=None, policies=None, disabled=None, - mount_point=DEFAULT_MOUNT_POINT): + def update_entity( + self, + entity_id, + name=None, + metadata=None, + policies=None, + disabled=None, + mount_point=DEFAULT_MOUNT_POINT, + ): """Update an existing entity. Supported methods: @@ -169,18 +197,22 @@ def update_entity(self, entity_id, name=None, metadata=None, policies=None, disa """ if metadata is not None and not isinstance(metadata, dict): error_msg = 'unsupported metadata argument provided "{arg}" ({arg_type}), required type: dict"' - raise exceptions.ParamValidationError(error_msg.format( - arg=metadata, - arg_type=type(metadata), - )) - params = utils.remove_nones({ - 'name': name, - 'metadata': metadata, - 'policies': policies, - 'disabled': disabled, - }) + raise exceptions.ParamValidationError( + error_msg.format( + arg=metadata, + arg_type=type(metadata), + ) + ) + params = utils.remove_nones( + { + "name": name, + "metadata": metadata, + "policies": policies, + "disabled": disabled, + } + ) api_path = utils.format_url( - '/v1/{mount_point}/entity/id/{id}', + "/v1/{mount_point}/entity/id/{id}", mount_point=mount_point, id=entity_id, ) @@ -203,7 +235,7 @@ def delete_entity(self, entity_id, mount_point=DEFAULT_MOUNT_POINT): :rtype: requests.Response """ api_path = utils.format_url( - '/v1/{mount_point}/entity/id/{id}', + "/v1/{mount_point}/entity/id/{id}", mount_point=mount_point, id=entity_id, ) @@ -225,7 +257,7 @@ def delete_entity_by_name(self, name, mount_point=DEFAULT_MOUNT_POINT): :rtype: requests.Response """ api_path = utils.format_url( - '/v1/{mount_point}/entity/name/{name}', + "/v1/{mount_point}/entity/name/{name}", mount_point=mount_point, name=name, ) @@ -233,7 +265,7 @@ def delete_entity_by_name(self, name, mount_point=DEFAULT_MOUNT_POINT): url=api_path, ) - def list_entities(self, method='LIST', mount_point=DEFAULT_MOUNT_POINT): + def list_entities(self, method="LIST", mount_point=DEFAULT_MOUNT_POINT): """List available entities entities by their identifiers. :param method: Supported methods: @@ -245,24 +277,30 @@ def list_entities(self, method='LIST', mount_point=DEFAULT_MOUNT_POINT): :return: The JSON response of the request. :rtype: dict """ - if method == 'LIST': - api_path = utils.format_url('/v1/{mount_point}/entity/id', mount_point=mount_point) + if method == "LIST": + api_path = utils.format_url( + "/v1/{mount_point}/entity/id", mount_point=mount_point + ) response = self._adapter.list( url=api_path, ) - elif method == 'GET': - api_path = utils.format_url('/v1/{mount_point}/entity/id?list=true', mount_point=mount_point) + elif method == "GET": + api_path = utils.format_url( + "/v1/{mount_point}/entity/id?list=true", mount_point=mount_point + ) response = self._adapter.get( url=api_path, ) else: - error_message = '"method" parameter provided invalid value; LIST or GET allowed, "{method}" provided'.format(method=method) + error_message = '"method" parameter provided invalid value; LIST or GET allowed, "{method}" provided'.format( + method=method + ) raise exceptions.ParamValidationError(error_message) return response - def list_entities_by_name(self, method='LIST', mount_point=DEFAULT_MOUNT_POINT): + def list_entities_by_name(self, method="LIST", mount_point=DEFAULT_MOUNT_POINT): """List available entities by their names. :param method: Supported methods: @@ -274,24 +312,32 @@ def list_entities_by_name(self, method='LIST', mount_point=DEFAULT_MOUNT_POINT): :return: The JSON response of the request. :rtype: dict """ - if method == 'LIST': - api_path = utils.format_url('/v1/{mount_point}/entity/name', mount_point=mount_point) + if method == "LIST": + api_path = utils.format_url( + "/v1/{mount_point}/entity/name", mount_point=mount_point + ) response = self._adapter.list( url=api_path, ) - elif method == 'GET': - api_path = utils.format_url('/v1/{mount_point}/entity/name?list=true', mount_point=mount_point) + elif method == "GET": + api_path = utils.format_url( + "/v1/{mount_point}/entity/name?list=true", mount_point=mount_point + ) response = self._adapter.get( url=api_path, ) else: - error_message = '"method" parameter provided invalid value; LIST or GET allowed, "{method}" provided'.format(method=method) + error_message = '"method" parameter provided invalid value; LIST or GET allowed, "{method}" provided'.format( + method=method + ) raise exceptions.ParamValidationError(error_message) return response - def merge_entities(self, from_entity_ids, to_entity_id, force=None, mount_point=DEFAULT_MOUNT_POINT): + def merge_entities( + self, from_entity_ids, to_entity_id, force=None, mount_point=DEFAULT_MOUNT_POINT + ): """Merge many entities into one entity. Supported methods: @@ -311,18 +357,29 @@ def merge_entities(self, from_entity_ids, to_entity_id, force=None, mount_point= :return: The response of the request. :rtype: requests.Response """ - params = utils.remove_nones({ - 'from_entity_ids': from_entity_ids, - 'to_entity_id': to_entity_id, - 'force': force, - }) - api_path = utils.format_url('/v1/{mount_point}/entity/merge', mount_point=mount_point) + params = utils.remove_nones( + { + "from_entity_ids": from_entity_ids, + "to_entity_id": to_entity_id, + "force": force, + } + ) + api_path = utils.format_url( + "/v1/{mount_point}/entity/merge", mount_point=mount_point + ) return self._adapter.post( url=api_path, json=params, ) - def create_or_update_entity_alias(self, name, canonical_id, mount_accessor, alias_id=None, mount_point=DEFAULT_MOUNT_POINT): + def create_or_update_entity_alias( + self, + name, + canonical_id, + mount_accessor, + alias_id=None, + mount_point=DEFAULT_MOUNT_POINT, + ): """Create a new alias for an entity. Supported methods: @@ -343,13 +400,17 @@ def create_or_update_entity_alias(self, name, canonical_id, mount_accessor, alia :return: The JSON response of the request. :rtype: requests.Response """ - params = utils.remove_nones({ - 'id': alias_id, - 'name': name, - 'canonical_id': canonical_id, - 'mount_accessor': mount_accessor, - }) - api_path = utils.format_url('/v1/{mount_point}/entity-alias', mount_point=mount_point) + params = utils.remove_nones( + { + "id": alias_id, + "name": name, + "canonical_id": canonical_id, + "mount_accessor": mount_accessor, + } + ) + api_path = utils.format_url( + "/v1/{mount_point}/entity-alias", mount_point=mount_point + ) return self._adapter.post( url=api_path, json=params, @@ -369,7 +430,7 @@ def read_entity_alias(self, alias_id, mount_point=DEFAULT_MOUNT_POINT): :rtype: dict """ api_path = utils.format_url( - '/v1/{mount_point}/entity-alias/id/{id}', + "/v1/{mount_point}/entity-alias/id/{id}", mount_point=mount_point, id=alias_id, ) @@ -377,7 +438,14 @@ def read_entity_alias(self, alias_id, mount_point=DEFAULT_MOUNT_POINT): url=api_path, ) - def update_entity_alias(self, alias_id, name, canonical_id, mount_accessor, mount_point=DEFAULT_MOUNT_POINT): + def update_entity_alias( + self, + alias_id, + name, + canonical_id, + mount_accessor, + mount_point=DEFAULT_MOUNT_POINT, + ): """Update an existing entity alias. Supported methods: @@ -398,13 +466,15 @@ def update_entity_alias(self, alias_id, name, canonical_id, mount_accessor, moun :return: The JSON response where available, otherwise the generic response object, of the request. :rtype: dict | requests.Response """ - params = utils.remove_nones({ - 'name': name, - 'canonical_id': canonical_id, - 'mount_accessor': mount_accessor, - }) + params = utils.remove_nones( + { + "name": name, + "canonical_id": canonical_id, + "mount_accessor": mount_accessor, + } + ) api_path = utils.format_url( - '/v1/{mount_point}/entity-alias/id/{id}', + "/v1/{mount_point}/entity-alias/id/{id}", mount_point=mount_point, id=alias_id, ) @@ -413,7 +483,7 @@ def update_entity_alias(self, alias_id, name, canonical_id, mount_accessor, moun json=params, ) - def list_entity_aliases(self, method='LIST', mount_point=DEFAULT_MOUNT_POINT): + def list_entity_aliases(self, method="LIST", mount_point=DEFAULT_MOUNT_POINT): """List available entity aliases by their identifiers. :param method: Supported methods: @@ -426,19 +496,25 @@ def list_entity_aliases(self, method='LIST', mount_point=DEFAULT_MOUNT_POINT): :rtype: dict """ - if method == 'LIST': - api_path = utils.format_url('/v1/{mount_point}/entity-alias/id', mount_point=mount_point) + if method == "LIST": + api_path = utils.format_url( + "/v1/{mount_point}/entity-alias/id", mount_point=mount_point + ) response = self._adapter.list( url=api_path, ) - elif method == 'GET': - api_path = utils.format_url('/v1/{mount_point}/entity-alias/id?list=true', mount_point=mount_point) + elif method == "GET": + api_path = utils.format_url( + "/v1/{mount_point}/entity-alias/id?list=true", mount_point=mount_point + ) response = self._adapter.get( url=api_path, ) else: - error_message = '"method" parameter provided invalid value; LIST or GET allowed, "{method}" provided'.format(method=method) + error_message = '"method" parameter provided invalid value; LIST or GET allowed, "{method}" provided'.format( + method=method + ) raise exceptions.ParamValidationError(error_message) return response @@ -457,7 +533,7 @@ def delete_entity_alias(self, alias_id, mount_point=DEFAULT_MOUNT_POINT): :rtype: requests.Response """ api_path = utils.format_url( - '/v1/{mount_point}/entity-alias/id/{id}', + "/v1/{mount_point}/entity-alias/id/{id}", mount_point=mount_point, id=alias_id, ) @@ -466,7 +542,9 @@ def delete_entity_alias(self, alias_id, mount_point=DEFAULT_MOUNT_POINT): ) @staticmethod - def validate_member_id_params_for_group_type(group_type, params, member_group_ids, member_entity_ids): + def validate_member_id_params_for_group_type( + group_type, params, member_group_ids, member_entity_ids + ): """Determine whether member ID parameters can be sent with a group create / update request. These parameters are only allowed for the internal group type. If they're set for an external group type, Vault @@ -483,22 +561,35 @@ def validate_member_id_params_for_group_type(group_type, params, member_group_id :return: Params dict with conditionally added member entity/group ID's. :rtype: dict """ - if group_type == 'external': + if group_type == "external": if member_entity_ids is not None: - logger.warning("InvalidRequest: member entities can't be set manually for external groups ignoring member_entity_ids argument.") + logger.warning( + "InvalidRequest: member entities can't be set manually for external groups ignoring member_entity_ids argument." + ) else: - params['member_entity_ids'] = member_entity_ids + params["member_entity_ids"] = member_entity_ids - if group_type == 'external': + if group_type == "external": if member_group_ids is not None: - logger.warning("InvalidRequest: member groups can't be set for external groups; ignoring member_group_ids argument.") + logger.warning( + "InvalidRequest: member groups can't be set for external groups; ignoring member_group_ids argument." + ) else: - params['member_group_ids'] = member_group_ids + params["member_group_ids"] = member_group_ids return params - def create_or_update_group(self, name, group_id=None, group_type='internal', metadata=None, policies=None, - member_group_ids=None, member_entity_ids=None, mount_point=DEFAULT_MOUNT_POINT): + def create_or_update_group( + self, + name, + group_id=None, + group_type="internal", + metadata=None, + policies=None, + member_group_ids=None, + member_entity_ids=None, + mount_point=DEFAULT_MOUNT_POINT, + ): """Create or update a Group. Supported methods: @@ -525,23 +616,29 @@ def create_or_update_group(self, name, group_id=None, group_type='internal', met """ 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), - )) + raise exceptions.ParamValidationError( + error_msg.format( + arg=metadata, + arg_type=type(metadata), + ) + ) if group_type not in ALLOWED_GROUP_TYPES: error_msg = 'unsupported group_type argument provided "{arg}", allowed values: ({allowed_values})' - raise exceptions.ParamValidationError(error_msg.format( - arg=group_type, - allowed_values=ALLOWED_GROUP_TYPES, - )) - params = utils.remove_nones({ - 'id': group_id, - 'name': name, - 'type': group_type, - 'metadata': metadata, - 'policies': policies, - }) + raise exceptions.ParamValidationError( + error_msg.format( + arg=group_type, + allowed_values=ALLOWED_GROUP_TYPES, + ) + ) + params = utils.remove_nones( + { + "id": group_id, + "name": name, + "type": group_type, + "metadata": metadata, + "policies": policies, + } + ) Identity.validate_member_id_params_for_group_type( group_type=group_type, @@ -550,7 +647,7 @@ def create_or_update_group(self, name, group_id=None, group_type='internal', met member_entity_ids=member_entity_ids, ) - api_path = utils.format_url('/v1/{mount_point}/group', mount_point=mount_point) + api_path = utils.format_url("/v1/{mount_point}/group", mount_point=mount_point) return self._adapter.post( url=api_path, json=params, @@ -570,7 +667,7 @@ def read_group(self, group_id, mount_point=DEFAULT_MOUNT_POINT): :rtype: requests.Response """ api_path = utils.format_url( - '/v1/{mount_point}/group/id/{id}', + "/v1/{mount_point}/group/id/{id}", mount_point=mount_point, id=group_id, ) @@ -578,8 +675,17 @@ def read_group(self, group_id, mount_point=DEFAULT_MOUNT_POINT): url=api_path, ) - def update_group(self, group_id, name, group_type='internal', metadata=None, policies=None, member_group_ids=None, - member_entity_ids=None, mount_point=DEFAULT_MOUNT_POINT): + def update_group( + self, + group_id, + name, + group_type="internal", + metadata=None, + policies=None, + member_group_ids=None, + member_entity_ids=None, + mount_point=DEFAULT_MOUNT_POINT, + ): """Update an existing group. Supported methods: @@ -606,22 +712,28 @@ def update_group(self, group_id, name, group_type='internal', metadata=None, pol """ 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), - )) + raise exceptions.ParamValidationError( + error_msg.format( + arg=metadata, + arg_type=type(metadata), + ) + ) if group_type not in ALLOWED_GROUP_TYPES: error_msg = 'unsupported group_type argument provided "{arg}", allowed values: ({allowed_values})' - raise exceptions.ParamValidationError(error_msg.format( - arg=group_type, - allowed_values=ALLOWED_GROUP_TYPES, - )) - params = utils.remove_nones({ - 'name': name, - 'type': group_type, - 'metadata': metadata, - 'policies': policies, - }) + raise exceptions.ParamValidationError( + error_msg.format( + arg=group_type, + allowed_values=ALLOWED_GROUP_TYPES, + ) + ) + params = utils.remove_nones( + { + "name": name, + "type": group_type, + "metadata": metadata, + "policies": policies, + } + ) Identity.validate_member_id_params_for_group_type( group_type=group_type, @@ -631,7 +743,7 @@ def update_group(self, group_id, name, group_type='internal', metadata=None, pol ) api_path = utils.format_url( - '/v1/{mount_point}/group/id/{id}', + "/v1/{mount_point}/group/id/{id}", mount_point=mount_point, id=group_id, ) @@ -654,7 +766,7 @@ def delete_group(self, group_id, mount_point=DEFAULT_MOUNT_POINT): :rtype: requests.Response """ api_path = utils.format_url( - '/v1/{mount_point}/group/id/{id}', + "/v1/{mount_point}/group/id/{id}", mount_point=mount_point, id=group_id, ) @@ -662,7 +774,7 @@ def delete_group(self, group_id, mount_point=DEFAULT_MOUNT_POINT): url=api_path, ) - def list_groups(self, method='LIST', mount_point=DEFAULT_MOUNT_POINT): + def list_groups(self, method="LIST", mount_point=DEFAULT_MOUNT_POINT): """List available groups by their identifiers. :param method: Supported methods: @@ -675,24 +787,30 @@ def list_groups(self, method='LIST', mount_point=DEFAULT_MOUNT_POINT): :rtype: dict """ - if method == 'LIST': - api_path = utils.format_url('/v1/{mount_point}/group/id', mount_point=mount_point) + if method == "LIST": + api_path = utils.format_url( + "/v1/{mount_point}/group/id", mount_point=mount_point + ) response = self._adapter.list( url=api_path, ) - elif method == 'GET': - api_path = utils.format_url('/v1/{mount_point}/group/id?list=true', mount_point=mount_point) + elif method == "GET": + api_path = utils.format_url( + "/v1/{mount_point}/group/id?list=true", mount_point=mount_point + ) response = self._adapter.get( url=api_path, ) else: - error_message = '"method" parameter provided invalid value; LIST or GET allowed, "{method}" provided'.format(method=method) + error_message = '"method" parameter provided invalid value; LIST or GET allowed, "{method}" provided'.format( + method=method + ) raise exceptions.ParamValidationError(error_message) return response - def list_groups_by_name(self, method='LIST', mount_point=DEFAULT_MOUNT_POINT): + def list_groups_by_name(self, method="LIST", mount_point=DEFAULT_MOUNT_POINT): """List available groups by their names. :param method: Supported methods: @@ -705,25 +823,39 @@ def list_groups_by_name(self, method='LIST', mount_point=DEFAULT_MOUNT_POINT): :rtype: dict """ - if method == 'LIST': - api_path = utils.format_url('/v1/{mount_point}/group/name', mount_point=mount_point) + if method == "LIST": + api_path = utils.format_url( + "/v1/{mount_point}/group/name", mount_point=mount_point + ) response = self._adapter.list( url=api_path, ) - elif method == 'GET': - api_path = utils.format_url('/v1/{mount_point}/group/name?list=true', mount_point=mount_point) + elif method == "GET": + api_path = utils.format_url( + "/v1/{mount_point}/group/name?list=true", mount_point=mount_point + ) response = self._adapter.get( url=api_path, ) else: - error_message = '"method" parameter provided invalid value; LIST or GET allowed, "{method}" provided'.format(method=method) + error_message = '"method" parameter provided invalid value; LIST or GET allowed, "{method}" provided'.format( + method=method + ) raise exceptions.ParamValidationError(error_message) return response - def create_or_update_group_by_name(self, name, group_type='internal', metadata=None, policies=None, member_group_ids=None, - member_entity_ids=None, mount_point=DEFAULT_MOUNT_POINT): + def create_or_update_group_by_name( + self, + name, + group_type="internal", + metadata=None, + policies=None, + member_group_ids=None, + member_entity_ids=None, + mount_point=DEFAULT_MOUNT_POINT, + ): """Create or update a group by its name. Supported methods: @@ -749,29 +881,37 @@ def create_or_update_group_by_name(self, name, group_type='internal', metadata=N 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), - )) + raise exceptions.ParamValidationError( + error_msg.format( + arg=metadata, + arg_type=type(metadata), + ) + ) if group_type not in ALLOWED_GROUP_TYPES: error_msg = 'unsupported group_type argument provided "{arg}", allowed values: ({allowed_values})' - raise exceptions.ParamValidationError(error_msg.format( - arg=group_type, - allowed_values=ALLOWED_GROUP_TYPES, - )) - params = utils.remove_nones({ - 'type': group_type, - 'metadata': metadata, - 'policies': policies, - }) - if group_type != 'external': - external_only_params = utils.remove_nones({ - 'member_group_ids': member_group_ids, - 'member_entity_ids': member_entity_ids, - }) + raise exceptions.ParamValidationError( + error_msg.format( + arg=group_type, + allowed_values=ALLOWED_GROUP_TYPES, + ) + ) + params = utils.remove_nones( + { + "type": group_type, + "metadata": metadata, + "policies": policies, + } + ) + if group_type != "external": + external_only_params = utils.remove_nones( + { + "member_group_ids": member_group_ids, + "member_entity_ids": member_entity_ids, + } + ) params.update(external_only_params) api_path = utils.format_url( - '/v1/{mount_point}/group/name/{name}', + "/v1/{mount_point}/group/name/{name}", mount_point=mount_point, name=name, ) @@ -794,7 +934,7 @@ def read_group_by_name(self, name, mount_point=DEFAULT_MOUNT_POINT): :rtype: dict """ api_path = utils.format_url( - '/v1/{mount_point}/group/name/{name}', + "/v1/{mount_point}/group/name/{name}", mount_point=mount_point, name=name, ) @@ -816,7 +956,7 @@ def delete_group_by_name(self, name, mount_point=DEFAULT_MOUNT_POINT): :rtype: requests.Response """ api_path = utils.format_url( - '/v1/{mount_point}/group/name/{name}', + "/v1/{mount_point}/group/name/{name}", mount_point=mount_point, name=name, ) @@ -824,7 +964,14 @@ def delete_group_by_name(self, name, mount_point=DEFAULT_MOUNT_POINT): url=api_path, ) - def create_or_update_group_alias(self, name, alias_id=None, mount_accessor=None, canonical_id=None, mount_point=DEFAULT_MOUNT_POINT): + def create_or_update_group_alias( + self, + name, + alias_id=None, + mount_accessor=None, + canonical_id=None, + mount_point=DEFAULT_MOUNT_POINT, + ): """Creates or update a group alias. Supported methods: @@ -843,19 +990,30 @@ def create_or_update_group_alias(self, name, alias_id=None, mount_accessor=None, :return: The JSON response of the request. :rtype: requests.Response """ - params = utils.remove_nones({ - 'id': alias_id, - 'name': name, - 'mount_accessor': mount_accessor, - 'canonical_id': canonical_id, - }) - api_path = utils.format_url('/v1/{mount_point}/group-alias', mount_point=mount_point) + params = utils.remove_nones( + { + "id": alias_id, + "name": name, + "mount_accessor": mount_accessor, + "canonical_id": canonical_id, + } + ) + api_path = utils.format_url( + "/v1/{mount_point}/group-alias", mount_point=mount_point + ) return self._adapter.post( url=api_path, json=params, ) - def update_group_alias(self, entity_id, name, mount_accessor=None, canonical_id=None, mount_point=DEFAULT_MOUNT_POINT): + def update_group_alias( + self, + entity_id, + name, + mount_accessor=None, + canonical_id=None, + mount_point=DEFAULT_MOUNT_POINT, + ): """Update an existing group alias. Supported methods: @@ -875,13 +1033,15 @@ def update_group_alias(self, entity_id, name, mount_accessor=None, canonical_id= :return: The response of the request. :rtype: requests.Response """ - params = utils.remove_nones({ - 'name': name, - 'mount_accessor': mount_accessor, - 'canonical_id': canonical_id, - }) + params = utils.remove_nones( + { + "name": name, + "mount_accessor": mount_accessor, + "canonical_id": canonical_id, + } + ) api_path = utils.format_url( - '/v1/{mount_point}/group-alias/id/{id}', + "/v1/{mount_point}/group-alias/id/{id}", mount_point=mount_point, id=entity_id, ) @@ -904,7 +1064,7 @@ def read_group_alias(self, alias_id, mount_point=DEFAULT_MOUNT_POINT): :rtype: dict """ api_path = utils.format_url( - '/v1/{mount_point}/group-alias/id/{id}', + "/v1/{mount_point}/group-alias/id/{id}", mount_point=mount_point, id=alias_id, ) @@ -926,7 +1086,7 @@ def delete_group_alias(self, entity_id, mount_point=DEFAULT_MOUNT_POINT): :rtype: requests.Response """ api_path = utils.format_url( - '/v1/{mount_point}/group-alias/id/{id}', + "/v1/{mount_point}/group-alias/id/{id}", mount_point=mount_point, id=entity_id, ) @@ -934,7 +1094,7 @@ def delete_group_alias(self, entity_id, mount_point=DEFAULT_MOUNT_POINT): url=api_path, ) - def list_group_aliases(self, method='LIST', mount_point=DEFAULT_MOUNT_POINT): + def list_group_aliases(self, method="LIST", mount_point=DEFAULT_MOUNT_POINT): """List available group aliases by their identifiers. :param method: Supported methods: @@ -947,23 +1107,37 @@ def list_group_aliases(self, method='LIST', mount_point=DEFAULT_MOUNT_POINT): :rtype: dict """ - if method == 'LIST': - api_path = utils.format_url('/v1/{mount_point}/group-alias/id', mount_point=mount_point) + if method == "LIST": + api_path = utils.format_url( + "/v1/{mount_point}/group-alias/id", mount_point=mount_point + ) response = self._adapter.list( url=api_path, ) - elif method == 'GET': - api_path = utils.format_url('/v1/{mount_point}/group-alias/id?list=true', mount_point=mount_point) + elif method == "GET": + api_path = utils.format_url( + "/v1/{mount_point}/group-alias/id?list=true", mount_point=mount_point + ) response = self._adapter.get( url=api_path, ) else: - error_message = '"method" parameter provided invalid value; LIST or GET allowed, "{method}" provided'.format(method=method) + error_message = '"method" parameter provided invalid value; LIST or GET allowed, "{method}" provided'.format( + method=method + ) raise exceptions.ParamValidationError(error_message) return response - def lookup_entity(self, name=None, entity_id=None, alias_id=None, alias_name=None, alias_mount_accessor=None, mount_point=DEFAULT_MOUNT_POINT): + def lookup_entity( + self, + name=None, + entity_id=None, + alias_id=None, + alias_name=None, + alias_mount_accessor=None, + mount_point=DEFAULT_MOUNT_POINT, + ): """Query an entity based on the given criteria. The criteria can be name, id, alias_id, or a combination of alias_name and alias_mount_accessor. @@ -988,21 +1162,31 @@ def lookup_entity(self, name=None, entity_id=None, alias_id=None, alias_name=Non """ params = {} if name is not None: - params['name'] = name + params["name"] = name elif entity_id is not None: - params['id'] = entity_id + params["id"] = entity_id elif alias_id is not None: - params['alias_id'] = alias_id + params["alias_id"] = alias_id elif alias_name is not None and alias_mount_accessor is not None: - params['alias_name'] = alias_name - params['alias_mount_accessor'] = alias_mount_accessor - api_path = utils.format_url('/v1/{mount_point}/lookup/entity', mount_point=mount_point) + params["alias_name"] = alias_name + params["alias_mount_accessor"] = alias_mount_accessor + api_path = utils.format_url( + "/v1/{mount_point}/lookup/entity", mount_point=mount_point + ) return self._adapter.post( url=api_path, json=params, ) - def lookup_group(self, name=None, group_id=None, alias_id=None, alias_name=None, alias_mount_accessor=None, mount_point=DEFAULT_MOUNT_POINT): + def lookup_group( + self, + name=None, + group_id=None, + alias_id=None, + alias_name=None, + alias_mount_accessor=None, + mount_point=DEFAULT_MOUNT_POINT, + ): """Query a group based on the given criteria. The criteria can be name, id, alias_id, or a combination of alias_name and alias_mount_accessor. @@ -1027,15 +1211,17 @@ def lookup_group(self, name=None, group_id=None, alias_id=None, alias_name=None, """ params = {} if name is not None: - params['name'] = name + params["name"] = name elif group_id is not None: - params['id'] = group_id + params["id"] = group_id elif alias_id is not None: - params['alias_id'] = alias_id + params["alias_id"] = alias_id elif alias_name is not None and alias_mount_accessor is not None: - params['alias_name'] = alias_name - params['alias_mount_accessor'] = alias_mount_accessor - api_path = utils.format_url('/v1/{mount_point}/lookup/group', mount_point=mount_point) + params["alias_name"] = alias_name + params["alias_mount_accessor"] = alias_mount_accessor + api_path = utils.format_url( + "/v1/{mount_point}/lookup/group", mount_point=mount_point + ) return self._adapter.post( url=api_path, json=params, @@ -1057,12 +1243,14 @@ def configure_tokens_backend(self, issuer=None, mount_point=DEFAULT_MOUNT_POINT) are included in the response body. :rtype: requests.Response """ - params = utils.remove_nones({ - 'issuer': issuer, - }) + params = utils.remove_nones( + { + "issuer": issuer, + } + ) api_path = utils.format_url( - '/v1/{mount_point}/oidc/config', + "/v1/{mount_point}/oidc/config", mount_point=mount_point, ) return self._adapter.post( @@ -1080,15 +1268,22 @@ def read_tokens_backend_configuration(self, mount_point=DEFAULT_MOUNT_POINT): :rtype: dict """ api_path = utils.format_url( - '/v1/{mount_point}/oidc/config', + "/v1/{mount_point}/oidc/config", mount_point=mount_point, ) return self._adapter.get( url=api_path, ) - def create_named_key(self, name, rotation_period="24h", verification_ttl="24h", allowed_client_ids=None, - algorithm="RS256", mount_point=DEFAULT_MOUNT_POINT): + def create_named_key( + self, + name, + rotation_period="24h", + verification_ttl="24h", + allowed_client_ids=None, + algorithm="RS256", + mount_point=DEFAULT_MOUNT_POINT, + ): """Create or update a named key which is used by a role to sign tokens. Supported methods: @@ -1114,15 +1309,15 @@ def create_named_key(self, name, rotation_period="24h", verification_ttl="24h", :rtype: dict """ params = { - 'name': name, - 'rotation_period': rotation_period, - 'verification_ttl': verification_ttl, - 'allowed_client_ids': allowed_client_ids, - 'algorithm': algorithm, + "name": name, + "rotation_period": rotation_period, + "verification_ttl": verification_ttl, + "allowed_client_ids": allowed_client_ids, + "algorithm": algorithm, } api_path = utils.format_url( - '/v1/{mount_point}/oidc/key/{name}', + "/v1/{mount_point}/oidc/key/{name}", mount_point=mount_point, name=name, ) @@ -1145,7 +1340,7 @@ def read_named_key(self, name, mount_point=DEFAULT_MOUNT_POINT): :rtype: dict """ api_path = utils.format_url( - '/v1/{mount_point}/oidc/key/{name}', + "/v1/{mount_point}/oidc/key/{name}", mount_point=mount_point, name=name, ) @@ -1167,7 +1362,7 @@ def delete_named_key(self, name, mount_point=DEFAULT_MOUNT_POINT): :rtype: dict """ api_path = utils.format_url( - '/v1/{mount_point}/oidc/key/{name}', + "/v1/{mount_point}/oidc/key/{name}", mount_point=mount_point, name=name, ) @@ -1187,7 +1382,7 @@ def list_named_keys(self, mount_point=DEFAULT_MOUNT_POINT): :rtype: dict """ api_path = utils.format_url( - '/v1/{mount_point}/oidc/key', + "/v1/{mount_point}/oidc/key", mount_point=mount_point, ) return self._adapter.list( @@ -1211,10 +1406,10 @@ def rotate_named_key(self, name, verification_ttl, mount_point=DEFAULT_MOUNT_POI :rtype: dict """ params = { - 'verification_ttl': verification_ttl, + "verification_ttl": verification_ttl, } api_path = utils.format_url( - '/v1/{mount_point}/oidc/key/{name}', + "/v1/{mount_point}/oidc/key/{name}", mount_point=mount_point, name=name, ) @@ -1223,7 +1418,15 @@ def rotate_named_key(self, name, verification_ttl, mount_point=DEFAULT_MOUNT_POI json=params, ) - def create_or_update_role(self, name, key, template=None, client_id=None, ttl="24h", mount_point=DEFAULT_MOUNT_POINT): + def create_or_update_role( + self, + name, + key, + template=None, + client_id=None, + ttl="24h", + mount_point=DEFAULT_MOUNT_POINT, + ): """Create or update a role. ID tokens are generated against a role and signed against a named key. @@ -1248,14 +1451,16 @@ def create_or_update_role(self, name, key, template=None, client_id=None, ttl="2 :return: The response of the create_or_update_a_role request. :rtype: dict """ - params = utils.remove_nones({ - 'key': key, - 'template': template, - 'client_id': client_id, - 'ttl': ttl, - }) + params = utils.remove_nones( + { + "key": key, + "template": template, + "client_id": client_id, + "ttl": ttl, + } + ) api_path = utils.format_url( - '/v1/{mount_point}/oidc/role/{name}', + "/v1/{mount_point}/oidc/role/{name}", mount_point=mount_point, name=name, ) @@ -1278,7 +1483,7 @@ def read_role(self, name, mount_point=DEFAULT_MOUNT_POINT): :rtype: dict """ api_path = utils.format_url( - '/v1/{mount_point}/oidc/role/{name}', + "/v1/{mount_point}/oidc/role/{name}", mount_point=mount_point, name=name, ) @@ -1301,7 +1506,7 @@ def delete_role(self, name, mount_point=DEFAULT_MOUNT_POINT): :rtype: dict """ api_path = utils.format_url( - '/v1/{mount_point}/oidc/role/{name}', + "/v1/{mount_point}/oidc/role/{name}", mount_point=mount_point, name=name, ) @@ -1323,7 +1528,7 @@ def list_roles(self, mount_point=DEFAULT_MOUNT_POINT): :rtype: dict """ api_path = utils.format_url( - '/v1/{mount_point}/oidc/role', + "/v1/{mount_point}/oidc/role", mount_point=mount_point, ) return self._adapter.list( @@ -1344,7 +1549,7 @@ def generate_signed_id_token(self, name, mount_point=DEFAULT_MOUNT_POINT): :rtype: dict """ api_path = utils.format_url( - '/v1/{mount_point}/oidc/token/{name}', + "/v1/{mount_point}/oidc/token/{name}", mount_point=mount_point, name=name, ) @@ -1352,7 +1557,9 @@ def generate_signed_id_token(self, name, mount_point=DEFAULT_MOUNT_POINT): url=api_path, ) - def introspect_signed_id_token(self, token, client_id=None, mount_point=DEFAULT_MOUNT_POINT): + def introspect_signed_id_token( + self, token, client_id=None, mount_point=DEFAULT_MOUNT_POINT + ): """Verify the authenticity and active state of a signed ID token. Supported methods: @@ -1368,12 +1575,14 @@ def introspect_signed_id_token(self, token, client_id=None, mount_point=DEFAULT_ :return: The response of the introspect_a_signed_id_token request. :rtype: dict """ - params = utils.remove_nones({ - 'token': token, - 'client_id': client_id, - }) + params = utils.remove_nones( + { + "token": token, + "client_id": client_id, + } + ) api_path = utils.format_url( - '/v1/{mount_point}/oidc/introspect', + "/v1/{mount_point}/oidc/introspect", mount_point=mount_point, ) return self._adapter.post( @@ -1395,7 +1604,7 @@ def read_well_known_configurations(self, mount_point=DEFAULT_MOUNT_POINT): :rtype: dict """ api_path = utils.format_url( - '/v1/{mount_point}/oidc/.well-known/openid-configuration', + "/v1/{mount_point}/oidc/.well-known/openid-configuration", mount_point=mount_point, ) return self._adapter.get( @@ -1416,7 +1625,7 @@ def read_active_public_keys(self, mount_point=DEFAULT_MOUNT_POINT): :rtype: dict """ api_path = utils.format_url( - '/v1/{mount_point}/oidc/.well-known/keys', + "/v1/{mount_point}/oidc/.well-known/keys", mount_point=mount_point, ) return self._adapter.get( diff --git a/hvac/api/secrets_engines/kv.py b/hvac/api/secrets_engines/kv.py index 0b327f085..df4e49c77 100644 --- a/hvac/api/secrets_engines/kv.py +++ b/hvac/api/secrets_engines/kv.py @@ -13,9 +13,10 @@ class Kv(VaultApiBase): Reference: https://www.vaultproject.io/docs/secrets/kv/index.html """ - allowed_kv_versions = ['1', '2'] - def __init__(self, adapter, default_kv_version='2'): + 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. @@ -56,8 +57,7 @@ def default_kv_version(self): 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 + allowed=",".join(self.allowed_kv_versions), provided=default_kv_version ) raise ValueError(error_message) self._default_kv_version = str(default_kv_version) @@ -70,9 +70,9 @@ def __getattr__(self, item): :return: The selected secrets_engines class corresponding to this instance's default_kv_version setting :rtype: hvac.api.vault_api_base.VaultApiBase """ - if self.default_kv_version == '1': + if self.default_kv_version == "1": return getattr(self._kv_v1, item) - elif self.default_kv_version == '2': + elif self.default_kv_version == "2": return getattr(self._kv_v2, item) raise AttributeError diff --git a/hvac/api/secrets_engines/kv_v1.py b/hvac/api/secrets_engines/kv_v1.py index 3feb58b97..17c940387 100644 --- a/hvac/api/secrets_engines/kv_v1.py +++ b/hvac/api/secrets_engines/kv_v1.py @@ -4,7 +4,7 @@ from hvac import exceptions, utils from hvac.api.vault_api_base import VaultApiBase -DEFAULT_MOUNT_POINT = 'secret' +DEFAULT_MOUNT_POINT = "secret" class KvV1(VaultApiBase): @@ -27,7 +27,9 @@ def read_secret(self, path, mount_point=DEFAULT_MOUNT_POINT): :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) + api_path = utils.format_url( + "/v1/{mount_point}/{path}", mount_point=mount_point, path=path + ) return self._adapter.get( url=api_path, ) @@ -50,12 +52,16 @@ def list_secrets(self, path, mount_point=DEFAULT_MOUNT_POINT): :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) + 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): + 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. @@ -88,26 +94,32 @@ def create_or_update_secret(self, path, secret, method=None, mount_point=DEFAULT path=path, mount_point=mount_point, ) - method = 'PUT' + method = "PUT" except exceptions.InvalidPath: - method = 'POST' + method = "POST" - if method == 'POST': - api_path = utils.format_url('/v1/{mount_point}/{path}', mount_point=mount_point, path=path) + 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) + 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) + 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): @@ -125,7 +137,9 @@ def delete_secret(self, path, mount_point=DEFAULT_MOUNT_POINT): :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) + api_path = utils.format_url( + "/v1/{mount_point}/{path}", mount_point=mount_point, path=path + ) return self._adapter.delete( url=api_path, ) diff --git a/hvac/api/secrets_engines/kv_v2.py b/hvac/api/secrets_engines/kv_v2.py index 1c7413ae7..8d5ab8a9c 100644 --- a/hvac/api/secrets_engines/kv_v2.py +++ b/hvac/api/secrets_engines/kv_v2.py @@ -4,7 +4,7 @@ from hvac import exceptions, utils from hvac.api.vault_api_base import VaultApiBase -DEFAULT_MOUNT_POINT = 'secret' +DEFAULT_MOUNT_POINT = "secret" class KvV2(VaultApiBase): @@ -13,7 +13,13 @@ class KvV2(VaultApiBase): 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): + 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: @@ -35,12 +41,12 @@ def configure(self, max_versions=10, cas_required=None, delete_version_after="0s :rtype: requests.Response """ params = { - 'max_versions': max_versions, - 'delete_version_after': delete_version_after, + "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) + 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, @@ -59,7 +65,7 @@ def read_configuration(self, mount_point=DEFAULT_MOUNT_POINT): :rtype: dict """ api_path = utils.format_url( - '/v1/{mount_point}/config', + "/v1/{mount_point}/config", mount_point=mount_point, ) return self._adapter.get(url=api_path) @@ -85,14 +91,18 @@ def read_secret_version(self, path, version=None, mount_point=DEFAULT_MOUNT_POIN """ 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) + params["version"] = version + api_path = utils.format_url( + "/v1/{mount_point}/data/{path}", mount_point=mount_point, path=path + ) return self._adapter.get( url=api_path, params=params, ) - def create_or_update_secret(self, path, secret, cas=None, mount_point=DEFAULT_MOUNT_POINT): + 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 @@ -115,14 +125,16 @@ def create_or_update_secret(self, path, secret, cas=None, mount_point=DEFAULT_MO :rtype: dict """ params = { - 'options': {}, - 'data': secret, + "options": {}, + "data": secret, } if cas is not None: - params['options']['cas'] = cas + params["options"]["cas"] = cas - api_path = utils.format_url('/v1/{mount_point}/data/{path}', mount_point=mount_point, path=path) + 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, @@ -147,16 +159,20 @@ def patch(self, path, secret, mount_point=DEFAULT_MOUNT_POINT): mount_point=mount_point, ) except exceptions.InvalidPath: - raise exceptions.InvalidPath('No value found at "{path}"; patch only works on existing data.'.format(path=path)) + 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 = 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'], + cas=current_secret_version["data"]["metadata"]["version"], secret=patched_secret, mount_point=mount_point, ) @@ -178,7 +194,9 @@ def delete_latest_version_of_secret(self, path, mount_point=DEFAULT_MOUNT_POINT) :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) + api_path = utils.format_url( + "/v1/{mount_point}/data/{path}", mount_point=mount_point, path=path + ) return self._adapter.delete( url=api_path, ) @@ -210,9 +228,11 @@ def delete_secret_versions(self, path, versions, mount_point=DEFAULT_MOUNT_POINT ) raise exceptions.ParamValidationError(error_msg) params = { - 'versions': versions, + "versions": versions, } - api_path = utils.format_url('/v1/{mount_point}/delete/{path}', mount_point=mount_point, path=path) + 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, @@ -243,9 +263,11 @@ def undelete_secret_versions(self, path, versions, mount_point=DEFAULT_MOUNT_POI ) raise exceptions.ParamValidationError(error_msg) params = { - 'versions': versions, + "versions": versions, } - api_path = utils.format_url('/v1/{mount_point}/undelete/{path}', mount_point=mount_point, path=path) + 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, @@ -275,9 +297,11 @@ def destroy_secret_versions(self, path, versions, mount_point=DEFAULT_MOUNT_POIN ) raise exceptions.ParamValidationError(error_msg) params = { - 'versions': versions, + "versions": versions, } - api_path = utils.format_url('/v1/{mount_point}/destroy/{path}', mount_point=mount_point, path=path) + 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, @@ -301,7 +325,9 @@ def list_secrets(self, path, mount_point=DEFAULT_MOUNT_POINT): :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) + api_path = utils.format_url( + "/v1/{mount_point}/metadata/{path}", mount_point=mount_point, path=path + ) return self._adapter.list( url=api_path, ) @@ -320,12 +346,21 @@ def read_secret_metadata(self, path, mount_point=DEFAULT_MOUNT_POINT): :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) + 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): + def update_metadata( + self, + path, + max_versions=None, + cas_required=None, + delete_version_after="0s", + mount_point=DEFAULT_MOUNT_POINT, + ): """Updates the max_versions of cas_required setting on an existing path. Supported methods: @@ -350,16 +385,22 @@ def update_metadata(self, path, max_versions=None, cas_required=None, delete_ver :rtype: requests.Response """ params = { - 'delete_version_after': delete_version_after, + "delete_version_after": delete_version_after, } if max_versions is not None: - params['max_versions'] = max_versions + 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)) + 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 - api_path = utils.format_url('/v1/{mount_point}/metadata/{path}', mount_point=mount_point, path=path) + params["cas_required"] = cas_required + 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, @@ -381,7 +422,9 @@ def delete_metadata_and_all_versions(self, path, mount_point=DEFAULT_MOUNT_POINT :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) + api_path = utils.format_url( + "/v1/{mount_point}/metadata/{path}", mount_point=mount_point, path=path + ) return self._adapter.delete( url=api_path, ) diff --git a/hvac/api/secrets_engines/pki.py b/hvac/api/secrets_engines/pki.py index 2c3638cad..8094321d5 100644 --- a/hvac/api/secrets_engines/pki.py +++ b/hvac/api/secrets_engines/pki.py @@ -4,7 +4,7 @@ from hvac import utils from hvac.api.vault_api_base import VaultApiBase -DEFAULT_MOUNT_POINT = 'pki' +DEFAULT_MOUNT_POINT = "pki" class Pki(VaultApiBase): @@ -26,7 +26,7 @@ def read_ca_certificate(self, mount_point=DEFAULT_MOUNT_POINT): :return: The certificate as pem. :rtype: str """ - api_path = utils.format_url('/v1/{mount_point}/ca/pem', mount_point=mount_point) + api_path = utils.format_url("/v1/{mount_point}/ca/pem", mount_point=mount_point) response = self._adapter.get( url=api_path, ) @@ -45,7 +45,9 @@ def read_ca_certificate_chain(self, mount_point=DEFAULT_MOUNT_POINT): :return: The certificate chain as pem. :rtype: str """ - api_path = utils.format_url('/v1/{mount_point}/ca_chain', mount_point=mount_point) + api_path = utils.format_url( + "/v1/{mount_point}/ca_chain", mount_point=mount_point + ) response = self._adapter.get( url=api_path, ) @@ -67,7 +69,7 @@ def read_certificate(self, serial, mount_point=DEFAULT_MOUNT_POINT): :rtype: dict """ api_path = utils.format_url( - '/v1/{mount_point}/cert/{serial}', + "/v1/{mount_point}/cert/{serial}", mount_point=mount_point, serial=serial, ) @@ -88,7 +90,7 @@ def list_certificates(self, mount_point=DEFAULT_MOUNT_POINT): :return: The JSON response of the request. :rtype: dict """ - api_path = utils.format_url('/v1/{mount_point}/certs', mount_point=mount_point) + api_path = utils.format_url("/v1/{mount_point}/certs", mount_point=mount_point) return self._adapter.list( url=api_path, ) @@ -107,9 +109,11 @@ def submit_ca_information(self, pem_bundle, mount_point=DEFAULT_MOUNT_POINT): :rtype: requests.Response """ params = { - 'pem_bundle': pem_bundle, + "pem_bundle": pem_bundle, } - api_path = utils.format_url('/v1/{mount_point}/config/ca', mount_point=mount_point) + api_path = utils.format_url( + "/v1/{mount_point}/config/ca", mount_point=mount_point + ) return self._adapter.post( url=api_path, json=params, @@ -128,12 +132,20 @@ def read_crl_configuration(self, mount_point=DEFAULT_MOUNT_POINT): :return: The JSON response of the request. :rtype: dict """ - api_path = utils.format_url('/v1/{mount_point}/config/crl', mount_point=mount_point) + 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): + 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. @@ -150,13 +162,17 @@ def set_crl_configuration(self, expiry=None, disable=None, extra_params=None, mo """ if extra_params is None: extra_params = {} - api_path = utils.format_url('/v1/{mount_point}/config/crl', mount_point=mount_point) + 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, - }) + utils.remove_nones( + { + "expiry": expiry, + "disable": disable, + } + ) ) return self._adapter.post( @@ -177,7 +193,9 @@ def read_urls(self, mount_point=DEFAULT_MOUNT_POINT): :return: The JSON response of the request. :rtype: dict """ - api_path = utils.format_url('/v1/{mount_point}/config/urls', mount_point=mount_point) + api_path = utils.format_url( + "/v1/{mount_point}/config/urls", mount_point=mount_point + ) return self._adapter.get( url=api_path, ) @@ -197,7 +215,9 @@ def set_urls(self, params, mount_point=DEFAULT_MOUNT_POINT): :return: The JSON response of the request. :rtype: requests.Response """ - api_path = utils.format_url('/v1/{mount_point}/config/urls', mount_point=mount_point) + api_path = utils.format_url( + "/v1/{mount_point}/config/urls", mount_point=mount_point + ) return self._adapter.post( url=api_path, json=params, @@ -217,7 +237,9 @@ def read_crl(self, mount_point=DEFAULT_MOUNT_POINT): :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) + api_path = utils.format_url( + "/v1/{mount_point}/crl/pem", mount_point=mount_point + ) response = self._adapter.get( url=api_path, ) @@ -237,12 +259,21 @@ def rotate_crl(self, mount_point=DEFAULT_MOUNT_POINT): :return: The JSON response of the request. :rtype: dict """ - api_path = utils.format_url('/v1/{mount_point}/crl/rotate', mount_point=mount_point) + 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): + 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. @@ -266,13 +297,13 @@ def generate_intermediate(self, type, common_name, extra_params=None, mount_poin if extra_params is None: extra_params = {} api_path = utils.format_url( - '/v1/{mount_point}/intermediate/generate/{type}', + "/v1/{mount_point}/intermediate/generate/{type}", mount_point=mount_point, type=type, ) params = extra_params - params['common_name'] = common_name + params["common_name"] = common_name return self._adapter.post( url=api_path, @@ -296,19 +327,26 @@ def set_signed_intermediate(self, certificate, mount_point=DEFAULT_MOUNT_POINT): :rtype: requests.Response """ api_path = utils.format_url( - '/v1/{mount_point}/intermediate/set-signed', + "/v1/{mount_point}/intermediate/set-signed", mount_point=mount_point, ) params = {} - params['certificate'] = certificate + 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): + 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. @@ -332,13 +370,13 @@ def generate_certificate(self, name, common_name, extra_params=None, mount_point if extra_params is None: extra_params = {} api_path = utils.format_url( - '/v1/{mount_point}/issue/{name}', + "/v1/{mount_point}/issue/{name}", mount_point=mount_point, name=name, ) params = extra_params - params['common_name'] = common_name + params["common_name"] = common_name return self._adapter.post( url=api_path, @@ -361,17 +399,19 @@ def revoke_certificate(self, serial_number, mount_point=DEFAULT_MOUNT_POINT): :return: The JSON response of the request. :rtype: requests.Response """ - api_path = utils.format_url('/v1/{mount_point}/revoke', mount_point=mount_point) + api_path = utils.format_url("/v1/{mount_point}/revoke", mount_point=mount_point) params = {} - params['serial_number'] = serial_number + 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): + def create_or_update_role( + self, name, extra_params=None, mount_point=DEFAULT_MOUNT_POINT + ): """Create/Update Role. Creates or updates the role definition. @@ -391,13 +431,13 @@ def create_or_update_role(self, name, extra_params=None, mount_point=DEFAULT_MOU if extra_params is None: extra_params = {} api_path = utils.format_url( - '/v1/{mount_point}/roles/{name}', + "/v1/{mount_point}/roles/{name}", mount_point=mount_point, name=name, ) params = extra_params - params['name'] = name + params["name"] = name return self._adapter.post( url=api_path, @@ -420,7 +460,7 @@ def read_role(self, name, mount_point=DEFAULT_MOUNT_POINT): :rtype: dict """ api_path = utils.format_url( - '/v1/{mount_point}/roles/{name}', + "/v1/{mount_point}/roles/{name}", mount_point=mount_point, name=name, ) @@ -441,7 +481,7 @@ def list_roles(self, mount_point=DEFAULT_MOUNT_POINT): :return: The JSON response of the request. :rtype: dict """ - api_path = utils.format_url('/v1/{mount_point}/roles', mount_point=mount_point) + api_path = utils.format_url("/v1/{mount_point}/roles", mount_point=mount_point) return self._adapter.list( url=api_path, ) @@ -462,7 +502,7 @@ def delete_role(self, name, mount_point=DEFAULT_MOUNT_POINT): :rtype: requests.Response """ api_path = utils.format_url( - '/v1/{mount_point}/roles/{name}', + "/v1/{mount_point}/roles/{name}", mount_point=mount_point, name=name, ) @@ -471,7 +511,14 @@ def delete_role(self, name, mount_point=DEFAULT_MOUNT_POINT): url=api_path, ) - def generate_root(self, type, common_name, extra_params=None, mount_point=DEFAULT_MOUNT_POINT, wrap_ttl=None): + 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. @@ -495,13 +542,13 @@ def generate_root(self, type, common_name, extra_params=None, mount_point=DEFAUL if extra_params is None: extra_params = {} api_path = utils.format_url( - '/v1/{mount_point}/root/generate/{type}', + "/v1/{mount_point}/root/generate/{type}", mount_point=mount_point, type=type, ) params = extra_params - params['common_name'] = common_name + params["common_name"] = common_name return self._adapter.post( url=api_path, @@ -523,7 +570,7 @@ def delete_root(self, mount_point=DEFAULT_MOUNT_POINT): :rtype: requests.Response """ api_path = utils.format_url( - '/v1/{mount_point}/root', + "/v1/{mount_point}/root", mount_point=mount_point, ) @@ -531,7 +578,9 @@ def delete_root(self, mount_point=DEFAULT_MOUNT_POINT): url=api_path, ) - def sign_intermediate(self, csr, common_name, extra_params=None, mount_point=DEFAULT_MOUNT_POINT): + 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. @@ -552,11 +601,13 @@ def sign_intermediate(self, csr, common_name, extra_params=None, mount_point=DEF """ if extra_params is None: extra_params = {} - api_path = utils.format_url('/v1/{mount_point}/root/sign-intermediate', mount_point=mount_point) + 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 + params["csr"] = csr + params["common_name"] = common_name return self._adapter.post( url=api_path, @@ -578,17 +629,21 @@ def sign_self_issued(self, certificate, mount_point=DEFAULT_MOUNT_POINT): :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) + api_path = utils.format_url( + "/v1/{mount_point}/root/sign-self-issued", mount_point=mount_point + ) params = {} - params['certificate'] = certificate + 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): + 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. @@ -612,21 +667,23 @@ def sign_certificate(self, name, csr, common_name, extra_params=None, mount_poin if extra_params is None: extra_params = {} api_path = utils.format_url( - '/v1/{mount_point}/sign/{name}', + "/v1/{mount_point}/sign/{name}", mount_point=mount_point, name=name, ) params = extra_params - params['csr'] = csr - params['common_name'] = common_name + 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): + 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. @@ -647,9 +704,9 @@ def sign_verbatim(self, csr, name=False, extra_params=None, mount_point=DEFAULT_ """ if extra_params is None: extra_params = {} - url_to_transform = '/v1/{mount_point}/sign-verbatim' + url_to_transform = "/v1/{mount_point}/sign-verbatim" if name: - url_to_transform = url_to_transform + '/{name}' + url_to_transform = url_to_transform + "/{name}" api_path = utils.format_url( url_to_transform, @@ -658,7 +715,7 @@ def sign_verbatim(self, csr, name=False, extra_params=None, mount_point=DEFAULT_ ) params = extra_params - params['csr'] = csr + params["csr"] = csr return self._adapter.post( url=api_path, @@ -684,7 +741,7 @@ def tidy(self, extra_params=None, mount_point=DEFAULT_MOUNT_POINT): if extra_params is None: extra_params = {} api_path = utils.format_url( - '/v1/{mount_point}/tidy', + "/v1/{mount_point}/tidy", mount_point=mount_point, ) diff --git a/hvac/api/secrets_engines/rabbitmq.py b/hvac/api/secrets_engines/rabbitmq.py index c8c936d60..1d8ac6c4c 100644 --- a/hvac/api/secrets_engines/rabbitmq.py +++ b/hvac/api/secrets_engines/rabbitmq.py @@ -4,16 +4,22 @@ from hvac import utils from hvac.api.vault_api_base import VaultApiBase -DEFAULT_MOUNT_POINT = 'rabbitmq' +DEFAULT_MOUNT_POINT = "rabbitmq" class RabbitMQ(VaultApiBase): """RabbitMQ Secrets Engine (API). - Reference: https://www.vaultproject.io/api/secret/rabbitmq/index.html + 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): + 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: @@ -33,13 +39,15 @@ def configure(self, connection_uri="", username="", password="", verify_connecti :rtype: requests.Response """ params = { - "connection_uri": connection_uri, - "verify_connection": verify_connection, - "username": username, - "password": password + "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) + api_path = utils.format_url( + "/v1/{mount_point}/config/connection", mount_point=mount_point + ) return self._adapter.post( url=api_path, json=params, @@ -67,7 +75,9 @@ def configure_lease(self, ttl, max_ttl, mount_point=DEFAULT_MOUNT_POINT): json=params, ) - def create_role(self, name, tags="", vhosts="", vhost_topics="", mount_point=DEFAULT_MOUNT_POINT): + 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. @@ -84,11 +94,7 @@ def create_role(self, name, tags="", vhosts="", vhost_topics="", mount_point=DEF :rtype: requests.Response """ api_path = utils.format_url("/v1/{}/roles/{}", mount_point, name) - params = { - "tags": tags, - "vhosts": vhosts, - "vhost_topics": vhost_topics - } + params = {"tags": tags, "vhosts": vhosts, "vhost_topics": vhost_topics} return self._adapter.post( url=api_path, json=params, diff --git a/hvac/api/secrets_engines/transit.py b/hvac/api/secrets_engines/transit.py index e9157c72d..5260c1558 100644 --- a/hvac/api/secrets_engines/transit.py +++ b/hvac/api/secrets_engines/transit.py @@ -5,7 +5,7 @@ from hvac.api.vault_api_base import VaultApiBase from hvac.constants import transit as transit_constants -DEFAULT_MOUNT_POINT = 'transit' +DEFAULT_MOUNT_POINT = "transit" class Transit(VaultApiBase): @@ -14,8 +14,16 @@ class Transit(VaultApiBase): Reference: https://www.vaultproject.io/api/secret/transit/index.html """ - def create_key(self, name, convergent_encryption=None, derived=None, exportable=None, allow_plaintext_backup=None, - key_type=None, mount_point=DEFAULT_MOUNT_POINT): + def create_key( + self, + name, + convergent_encryption=None, + derived=None, + exportable=None, + allow_plaintext_backup=None, + key_type=None, + mount_point=DEFAULT_MOUNT_POINT, + ): """Create a new named encryption key of the specified type. The values set here cannot be changed after key creation. @@ -56,22 +64,28 @@ def create_key(self, name, convergent_encryption=None, derived=None, exportable= :rtype: requests.Response """ if convergent_encryption and not derived: - raise exceptions.ParamValidationError('derived must be set to True when convergent_encryption is True') + raise exceptions.ParamValidationError( + "derived must be set to True when convergent_encryption is True" + ) if key_type is not None and key_type not in transit_constants.ALLOWED_KEY_TYPES: error_msg = 'invalid key_type argument provided "{arg}", supported types: "{allowed_types}"' - raise exceptions.ParamValidationError(error_msg.format( - arg=key_type, - allowed_types=', '.join(transit_constants.ALLOWED_KEY_TYPES), - )) - params = utils.remove_nones({ - 'convergent_encryption': convergent_encryption, - 'derived': derived, - 'exportable': exportable, - 'allow_plaintext_backup': allow_plaintext_backup, - 'type': key_type, - }) + raise exceptions.ParamValidationError( + error_msg.format( + arg=key_type, + allowed_types=", ".join(transit_constants.ALLOWED_KEY_TYPES), + ) + ) + params = utils.remove_nones( + { + "convergent_encryption": convergent_encryption, + "derived": derived, + "exportable": exportable, + "allow_plaintext_backup": allow_plaintext_backup, + "type": key_type, + } + ) api_path = utils.format_url( - '/v1/{mount_point}/keys/{name}', + "/v1/{mount_point}/keys/{name}", mount_point=mount_point, name=name, ) @@ -98,7 +112,7 @@ def read_key(self, name, mount_point=DEFAULT_MOUNT_POINT): :rtype: dict """ api_path = utils.format_url( - '/v1/{mount_point}/keys/{name}', + "/v1/{mount_point}/keys/{name}", mount_point=mount_point, name=name, ) @@ -121,10 +135,8 @@ def list_keys(self, mount_point=DEFAULT_MOUNT_POINT): :return: The JSON response of the request. :rtype: dict """ - api_path = utils.format_url('/v1/{mount_point}/keys', mount_point=mount_point) - return self._adapter.list( - url=api_path - ) + api_path = utils.format_url("/v1/{mount_point}/keys", mount_point=mount_point) + return self._adapter.list(url=api_path) def delete_key(self, name, mount_point=DEFAULT_MOUNT_POINT): """Delete a named encryption key. @@ -143,7 +155,7 @@ def delete_key(self, name, mount_point=DEFAULT_MOUNT_POINT): :rtype: requests.Response """ api_path = utils.format_url( - '/v1/{mount_point}/keys/{name}', + "/v1/{mount_point}/keys/{name}", mount_point=mount_point, name=name, ) @@ -151,8 +163,16 @@ def delete_key(self, name, mount_point=DEFAULT_MOUNT_POINT): url=api_path, ) - def update_key_configuration(self, name, min_decryption_version=None, min_encryption_version=None, deletion_allowed=None, - exportable=None, allow_plaintext_backup=None, mount_point=DEFAULT_MOUNT_POINT): + def update_key_configuration( + self, + name, + min_decryption_version=None, + min_encryption_version=None, + deletion_allowed=None, + exportable=None, + allow_plaintext_backup=None, + mount_point=DEFAULT_MOUNT_POINT, + ): """Tune configuration values for a given key. These values are returned during a read operation on the named key. @@ -186,17 +206,24 @@ def update_key_configuration(self, name, min_decryption_version=None, min_encryp :rtype: requests.Response """ if min_encryption_version is not None and min_decryption_version is not None: - if min_encryption_version != 0 and min_encryption_version <= min_decryption_version: - raise exceptions.ParamValidationError('min_encryption_version must be 0 or > min_decryption_version') - params = utils.remove_nones({ - 'min_decryption_version': min_decryption_version, - 'min_encryption_version': min_encryption_version, - 'deletion_allowed': deletion_allowed, - 'exportable': exportable, - 'allow_plaintext_backup': allow_plaintext_backup, - }) + if ( + min_encryption_version != 0 + and min_encryption_version <= min_decryption_version + ): + raise exceptions.ParamValidationError( + "min_encryption_version must be 0 or > min_decryption_version" + ) + params = utils.remove_nones( + { + "min_decryption_version": min_decryption_version, + "min_encryption_version": min_encryption_version, + "deletion_allowed": deletion_allowed, + "exportable": exportable, + "allow_plaintext_backup": allow_plaintext_backup, + } + ) api_path = utils.format_url( - '/v1/{mount_point}/keys/{name}/config', + "/v1/{mount_point}/keys/{name}/config", mount_point=mount_point, name=name, ) @@ -223,7 +250,7 @@ def rotate_key(self, name, mount_point=DEFAULT_MOUNT_POINT): :rtype: requests.Response """ api_path = utils.format_url( - '/v1/{mount_point}/keys/{name}/rotate', + "/v1/{mount_point}/keys/{name}/rotate", mount_point=mount_point, name=name, ) @@ -259,12 +286,14 @@ def export_key(self, name, key_type, version=None, mount_point=DEFAULT_MOUNT_POI """ if key_type not in transit_constants.ALLOWED_EXPORT_KEY_TYPES: error_msg = 'invalid key_type argument provided "{arg}", supported types: "{allowed_types}"' - raise exceptions.ParamValidationError(error_msg.format( - arg=key_type, - allowed_types=', '.join(transit_constants.ALLOWED_EXPORT_KEY_TYPES), - )) + raise exceptions.ParamValidationError( + error_msg.format( + arg=key_type, + allowed_types=", ".join(transit_constants.ALLOWED_EXPORT_KEY_TYPES), + ) + ) api_path = utils.format_url( - '/v1/{mount_point}/export/{key_type}/{name}', + "/v1/{mount_point}/export/{key_type}/{name}", mount_point=mount_point, key_type=key_type, name=name, @@ -275,8 +304,18 @@ def export_key(self, name, key_type, version=None, mount_point=DEFAULT_MOUNT_POI url=api_path, ) - def encrypt_data(self, name, plaintext, context=None, key_version=None, nonce=None, batch_input=None, type=None, - convergent_encryption=None, mount_point=DEFAULT_MOUNT_POINT): + def encrypt_data( + self, + name, + plaintext, + context=None, + key_version=None, + nonce=None, + batch_input=None, + type=None, + convergent_encryption=None, + mount_point=DEFAULT_MOUNT_POINT, + ): """Encrypt the provided plaintext using the named key. This path supports the create and update policy capabilities as follows: if the user has the create capability @@ -322,20 +361,22 @@ def encrypt_data(self, name, plaintext, context=None, key_version=None, nonce=No :rtype: dict """ params = { - 'plaintext': plaintext, + "plaintext": plaintext, } params.update( - utils.remove_nones({ - 'context': context, - 'key_version': key_version, - 'nonce': nonce, - 'batch_input': batch_input, - 'type': type, - 'convergent_encryption': convergent_encryption, - }) + utils.remove_nones( + { + "context": context, + "key_version": key_version, + "nonce": nonce, + "batch_input": batch_input, + "type": type, + "convergent_encryption": convergent_encryption, + } + ) ) api_path = utils.format_url( - '/v1/{mount_point}/encrypt/{name}', + "/v1/{mount_point}/encrypt/{name}", mount_point=mount_point, name=name, ) @@ -344,7 +385,15 @@ def encrypt_data(self, name, plaintext, context=None, key_version=None, nonce=No json=params, ) - def decrypt_data(self, name, ciphertext, context=None, nonce=None, batch_input=None, mount_point=DEFAULT_MOUNT_POINT): + def decrypt_data( + self, + name, + ciphertext, + context=None, + nonce=None, + batch_input=None, + mount_point=DEFAULT_MOUNT_POINT, + ): """Decrypt the provided ciphertext using the named key. Supported methods: @@ -371,17 +420,19 @@ def decrypt_data(self, name, ciphertext, context=None, nonce=None, batch_input=N :rtype: dict """ params = { - 'ciphertext': ciphertext, + "ciphertext": ciphertext, } params.update( - utils.remove_nones({ - 'context': context, - 'nonce': nonce, - 'batch_input': batch_input, - }) + utils.remove_nones( + { + "context": context, + "nonce": nonce, + "batch_input": batch_input, + } + ) ) api_path = utils.format_url( - '/v1/{mount_point}/decrypt/{name}', + "/v1/{mount_point}/decrypt/{name}", mount_point=mount_point, name=name, ) @@ -390,8 +441,16 @@ def decrypt_data(self, name, ciphertext, context=None, nonce=None, batch_input=N json=params, ) - def rewrap_data(self, name, ciphertext, context=None, key_version=None, nonce=None, batch_input=None, - mount_point=DEFAULT_MOUNT_POINT): + def rewrap_data( + self, + name, + ciphertext, + context=None, + key_version=None, + nonce=None, + batch_input=None, + mount_point=DEFAULT_MOUNT_POINT, + ): """Rewrap the provided ciphertext using the latest version of the named key. Because this never returns plaintext, it is possible to delegate this functionality to untrusted users or scripts. @@ -423,18 +482,20 @@ def rewrap_data(self, name, ciphertext, context=None, key_version=None, nonce=No :rtype: dict """ params = { - 'ciphertext': ciphertext, + "ciphertext": ciphertext, } params.update( - utils.remove_nones({ - 'context': context, - 'key_version': key_version, - 'nonce': nonce, - 'batch_input': batch_input, - }) + utils.remove_nones( + { + "context": context, + "key_version": key_version, + "nonce": nonce, + "batch_input": batch_input, + } + ) ) api_path = utils.format_url( - '/v1/{mount_point}/rewrap/{name}', + "/v1/{mount_point}/rewrap/{name}", mount_point=mount_point, name=name, ) @@ -443,7 +504,15 @@ def rewrap_data(self, name, ciphertext, context=None, key_version=None, nonce=No json=params, ) - def generate_data_key(self, name, key_type, context=None, nonce=None, bits=None, mount_point=DEFAULT_MOUNT_POINT): + def generate_data_key( + self, + name, + key_type, + context=None, + nonce=None, + bits=None, + mount_point=DEFAULT_MOUNT_POINT, + ): """Generates a new high-entropy key and the value encrypted with the named key. Optionally return the plaintext of the key as well. Whether plaintext is returned depends on the path; as a @@ -478,23 +547,31 @@ def generate_data_key(self, name, key_type, context=None, nonce=None, bits=None, """ if key_type not in transit_constants.ALLOWED_DATA_KEY_TYPES: error_msg = 'invalid key_type argument provided "{arg}", supported types: "{allowed_types}"' - raise exceptions.ParamValidationError(error_msg.format( - arg=key_type, - allowed_types=', '.join(transit_constants.ALLOWED_DATA_KEY_TYPES), - )) + raise exceptions.ParamValidationError( + error_msg.format( + arg=key_type, + allowed_types=", ".join(transit_constants.ALLOWED_DATA_KEY_TYPES), + ) + ) if bits is not None and bits not in transit_constants.ALLOWED_DATA_KEY_BITS: error_msg = 'invalid bits argument provided "{arg}", supported values: "{allowed_values}"' - raise exceptions.ParamValidationError(error_msg.format( - arg=bits, - allowed_values=', '.join([str(b) for b in transit_constants.ALLOWED_DATA_KEY_BITS]), - )) - params = utils.remove_nones({ - 'context': context, - 'nonce': nonce, - 'bits': bits, - }) + raise exceptions.ParamValidationError( + error_msg.format( + arg=bits, + allowed_values=", ".join( + [str(b) for b in transit_constants.ALLOWED_DATA_KEY_BITS] + ), + ) + ) + params = utils.remove_nones( + { + "context": context, + "nonce": nonce, + "bits": bits, + } + ) api_path = utils.format_url( - '/v1/{mount_point}/datakey/{key_type}/{name}', + "/v1/{mount_point}/datakey/{key_type}/{name}", mount_point=mount_point, key_type=key_type, name=name, @@ -504,7 +581,9 @@ def generate_data_key(self, name, key_type, context=None, nonce=None, bits=None, json=params, ) - def generate_random_bytes(self, n_bytes=None, output_format=None, mount_point=DEFAULT_MOUNT_POINT): + def generate_random_bytes( + self, n_bytes=None, output_format=None, mount_point=DEFAULT_MOUNT_POINT + ): """Return high-quality random bytes of the specified length. Supported methods: @@ -520,17 +599,25 @@ def generate_random_bytes(self, n_bytes=None, output_format=None, mount_point=DE :return: The JSON response of the request. :rtype: dict """ - params = utils.remove_nones({ - 'bytes': n_bytes, - 'format': output_format, - }) - api_path = utils.format_url('/v1/{mount_point}/random', mount_point=mount_point) + params = utils.remove_nones( + { + "bytes": n_bytes, + "format": output_format, + } + ) + api_path = utils.format_url("/v1/{mount_point}/random", mount_point=mount_point) return self._adapter.post( url=api_path, json=params, ) - def hash_data(self, hash_input, algorithm=None, output_format=None, mount_point=DEFAULT_MOUNT_POINT): + def hash_data( + self, + hash_input, + algorithm=None, + output_format=None, + mount_point=DEFAULT_MOUNT_POINT, + ): """Return the cryptographic hash of given data using the specified algorithm. Supported methods: @@ -548,34 +635,57 @@ def hash_data(self, hash_input, algorithm=None, output_format=None, mount_point= :return: The JSON response of the request. :rtype: dict """ - if algorithm is not None and algorithm not in transit_constants.ALLOWED_HASH_DATA_ALGORITHMS: + if ( + algorithm is not None + and algorithm not in transit_constants.ALLOWED_HASH_DATA_ALGORITHMS + ): error_msg = 'invalid algorithm argument provided "{arg}", supported types: "{allowed_types}"' - raise exceptions.ParamValidationError(error_msg.format( - arg=algorithm, - allowed_types=', '.join(transit_constants.ALLOWED_HASH_DATA_ALGORITHMS), - )) - if output_format is not None and output_format not in transit_constants.ALLOWED_HASH_DATA_FORMATS: + raise exceptions.ParamValidationError( + error_msg.format( + arg=algorithm, + allowed_types=", ".join( + transit_constants.ALLOWED_HASH_DATA_ALGORITHMS + ), + ) + ) + if ( + output_format is not None + and output_format not in transit_constants.ALLOWED_HASH_DATA_FORMATS + ): error_msg = 'invalid output_format argument provided "{arg}", supported types: "{allowed_types}"' - raise exceptions.ParamValidationError(error_msg.format( - arg=output_format, - allowed_types=', '.join(transit_constants.ALLOWED_HASH_DATA_FORMATS), - )) + raise exceptions.ParamValidationError( + error_msg.format( + arg=output_format, + allowed_types=", ".join( + transit_constants.ALLOWED_HASH_DATA_FORMATS + ), + ) + ) params = { - 'input': hash_input, + "input": hash_input, } params.update( - utils.remove_nones({ - 'algorithm': algorithm, - 'format': output_format, - }) + utils.remove_nones( + { + "algorithm": algorithm, + "format": output_format, + } + ) ) - api_path = utils.format_url('/v1/{mount_point}/hash', mount_point=mount_point) + api_path = utils.format_url("/v1/{mount_point}/hash", mount_point=mount_point) return self._adapter.post( url=api_path, json=params, ) - def generate_hmac(self, name, hash_input, key_version=None, algorithm=None, mount_point=DEFAULT_MOUNT_POINT): + def generate_hmac( + self, + name, + hash_input, + key_version=None, + algorithm=None, + mount_point=DEFAULT_MOUNT_POINT, + ): """Return the digest of given data using the specified hash algorithm and the named key. The key can be of any type supported by transit; the raw key will be marshaled into bytes to be used for the @@ -600,23 +710,32 @@ def generate_hmac(self, name, hash_input, key_version=None, algorithm=None, moun :return: The JSON response of the request. :rtype: dict """ - if algorithm is not None and algorithm not in transit_constants.ALLOWED_HASH_DATA_ALGORITHMS: + if ( + algorithm is not None + and algorithm not in transit_constants.ALLOWED_HASH_DATA_ALGORITHMS + ): error_msg = 'invalid algorithm argument provided "{arg}", supported types: "{allowed_types}"' - raise exceptions.ParamValidationError(error_msg.format( - arg=algorithm, - allowed_types=', '.join(transit_constants.ALLOWED_HASH_DATA_ALGORITHMS), - )) + raise exceptions.ParamValidationError( + error_msg.format( + arg=algorithm, + allowed_types=", ".join( + transit_constants.ALLOWED_HASH_DATA_ALGORITHMS + ), + ) + ) params = { - 'input': hash_input, + "input": hash_input, } params.update( - utils.remove_nones({ - 'key_version': key_version, - 'algorithm': algorithm, - }) + utils.remove_nones( + { + "key_version": key_version, + "algorithm": algorithm, + } + ) ) api_path = utils.format_url( - '/v1/{mount_point}/hmac/{name}', + "/v1/{mount_point}/hmac/{name}", mount_point=mount_point, name=name, ) @@ -625,8 +744,18 @@ def generate_hmac(self, name, hash_input, key_version=None, algorithm=None, moun json=params, ) - def sign_data(self, name, hash_input, key_version=None, hash_algorithm=None, context=None, prehashed=None, - signature_algorithm=None, marshaling_algorithm=None, mount_point=DEFAULT_MOUNT_POINT): + def sign_data( + self, + name, + hash_input, + key_version=None, + hash_algorithm=None, + context=None, + prehashed=None, + signature_algorithm=None, + marshaling_algorithm=None, + mount_point=DEFAULT_MOUNT_POINT, + ): """Return the cryptographic signature of the given data using the named key and the specified hash algorithm. The key must be of a type that supports signing. @@ -665,39 +794,64 @@ def sign_data(self, name, hash_input, key_version=None, hash_algorithm=None, con :return: The JSON response of the request. :rtype: dict """ - if hash_algorithm is not None and hash_algorithm not in transit_constants.ALLOWED_HASH_DATA_ALGORITHMS: + if ( + hash_algorithm is not None + and hash_algorithm not in transit_constants.ALLOWED_HASH_DATA_ALGORITHMS + ): error_msg = 'invalid hash_algorithm argument provided "{arg}", supported types: "{allowed_types}"' - raise exceptions.ParamValidationError(error_msg.format( - arg=hash_algorithm, - allowed_types=', '.join(transit_constants.ALLOWED_HASH_DATA_ALGORITHMS), - )) - if signature_algorithm is not None and signature_algorithm not in transit_constants.ALLOWED_SIGNATURE_ALGORITHMS: + raise exceptions.ParamValidationError( + error_msg.format( + arg=hash_algorithm, + allowed_types=", ".join( + transit_constants.ALLOWED_HASH_DATA_ALGORITHMS + ), + ) + ) + if ( + signature_algorithm is not None + and signature_algorithm + not in transit_constants.ALLOWED_SIGNATURE_ALGORITHMS + ): error_msg = 'invalid signature_algorithm argument provided "{arg}", supported types: "{allowed_types}"' - raise exceptions.ParamValidationError(error_msg.format( - arg=signature_algorithm, - allowed_types=', '.join(transit_constants.ALLOWED_SIGNATURE_ALGORITHMS), - )) - if marshaling_algorithm is not None and marshaling_algorithm not in transit_constants.ALLOWED_MARSHALING_ALGORITHMS: + raise exceptions.ParamValidationError( + error_msg.format( + arg=signature_algorithm, + allowed_types=", ".join( + transit_constants.ALLOWED_SIGNATURE_ALGORITHMS + ), + ) + ) + if ( + marshaling_algorithm is not None + and marshaling_algorithm + not in transit_constants.ALLOWED_MARSHALING_ALGORITHMS + ): error_msg = 'invalid marshaling_algorithm argument provided "{arg}", supported types: "{allowed_types}"' - raise exceptions.ParamValidationError(error_msg.format( - arg=marshaling_algorithm, - allowed_types=', '.join(transit_constants.ALLOWED_MARSHALING_ALGORITHMS), - )) + raise exceptions.ParamValidationError( + error_msg.format( + arg=marshaling_algorithm, + allowed_types=", ".join( + transit_constants.ALLOWED_MARSHALING_ALGORITHMS + ), + ) + ) params = { - 'input': hash_input, + "input": hash_input, } params.update( - utils.remove_nones({ - 'key_version': key_version, - 'hash_algorithm': hash_algorithm, - 'context': context, - 'prehashed': prehashed, - 'signature_algorithm': signature_algorithm, - 'marshaling_algorithm': marshaling_algorithm, - }) + utils.remove_nones( + { + "key_version": key_version, + "hash_algorithm": hash_algorithm, + "context": context, + "prehashed": prehashed, + "signature_algorithm": signature_algorithm, + "marshaling_algorithm": marshaling_algorithm, + } + ) ) api_path = utils.format_url( - '/v1/{mount_point}/sign/{name}', + "/v1/{mount_point}/sign/{name}", mount_point=mount_point, name=name, ) @@ -706,8 +860,19 @@ def sign_data(self, name, hash_input, key_version=None, hash_algorithm=None, con json=params, ) - def verify_signed_data(self, name, hash_input, signature=None, hmac=None, hash_algorithm=None, context=None, - prehashed=None, signature_algorithm=None, marshaling_algorithm=None, mount_point=DEFAULT_MOUNT_POINT): + def verify_signed_data( + self, + name, + hash_input, + signature=None, + hmac=None, + hash_algorithm=None, + context=None, + prehashed=None, + signature_algorithm=None, + marshaling_algorithm=None, + mount_point=DEFAULT_MOUNT_POINT, + ): """Return whether the provided signature is valid for the given data. Supported methods: @@ -743,43 +908,72 @@ def verify_signed_data(self, name, hash_input, signature=None, hmac=None, hash_a :return: The JSON response of the request. :rtype: dict """ - if (signature is None and hmac is None) or (signature is not None and hmac is not None): + if (signature is None and hmac is None) or ( + signature is not None and hmac is not None + ): error_msg = 'either "signature" or "hmac" argument (but not both) must be provided to verify signature' raise exceptions.ParamValidationError(error_msg) - if hash_algorithm is not None and hash_algorithm not in transit_constants.ALLOWED_HASH_DATA_ALGORITHMS: + if ( + hash_algorithm is not None + and hash_algorithm not in transit_constants.ALLOWED_HASH_DATA_ALGORITHMS + ): error_msg = 'invalid hash_algorithm argument provided "{arg}", supported types: "{allowed_types}"' - raise exceptions.ParamValidationError(error_msg.format( - arg=hash_algorithm, - allowed_types=', '.join(transit_constants.ALLOWED_HASH_DATA_ALGORITHMS), - )) - if signature_algorithm is not None and signature_algorithm not in transit_constants.ALLOWED_SIGNATURE_ALGORITHMS: + raise exceptions.ParamValidationError( + error_msg.format( + arg=hash_algorithm, + allowed_types=", ".join( + transit_constants.ALLOWED_HASH_DATA_ALGORITHMS + ), + ) + ) + if ( + signature_algorithm is not None + and signature_algorithm + not in transit_constants.ALLOWED_SIGNATURE_ALGORITHMS + ): error_msg = 'invalid signature_algorithm argument provided "{arg}", supported types: "{allowed_types}"' - raise exceptions.ParamValidationError(error_msg.format( - arg=signature_algorithm, - allowed_types=', '.join(transit_constants.ALLOWED_SIGNATURE_ALGORITHMS), - )) - if marshaling_algorithm is not None and marshaling_algorithm not in transit_constants.ALLOWED_MARSHALING_ALGORITHMS: + raise exceptions.ParamValidationError( + error_msg.format( + arg=signature_algorithm, + allowed_types=", ".join( + transit_constants.ALLOWED_SIGNATURE_ALGORITHMS + ), + ) + ) + if ( + marshaling_algorithm is not None + and marshaling_algorithm + not in transit_constants.ALLOWED_MARSHALING_ALGORITHMS + ): error_msg = 'invalid marshaling_algorithm argument provided "{arg}", supported types: "{allowed_types}"' - raise exceptions.ParamValidationError(error_msg.format( - arg=marshaling_algorithm, - allowed_types=', '.join(transit_constants.ALLOWED_MARSHALING_ALGORITHMS), - )) + raise exceptions.ParamValidationError( + error_msg.format( + arg=marshaling_algorithm, + allowed_types=", ".join( + transit_constants.ALLOWED_MARSHALING_ALGORITHMS + ), + ) + ) params = { - 'name': name, - 'input': hash_input, + "name": name, + "input": hash_input, } params.update( - utils.remove_nones({ - 'hash_algorithm': hash_algorithm, - 'signature': signature, - 'hmac': hmac, - 'context': context, - 'prehashed': prehashed, - 'signature_algorithm': signature_algorithm, - 'marshaling_algorithm': marshaling_algorithm, - }) - ) - api_path = utils.format_url('/v1/{mount_point}/verify/{name}', mount_point=mount_point, name=name) + utils.remove_nones( + { + "hash_algorithm": hash_algorithm, + "signature": signature, + "hmac": hmac, + "context": context, + "prehashed": prehashed, + "signature_algorithm": signature_algorithm, + "marshaling_algorithm": marshaling_algorithm, + } + ) + ) + api_path = utils.format_url( + "/v1/{mount_point}/verify/{name}", mount_point=mount_point, name=name + ) return self._adapter.post( url=api_path, json=params, @@ -802,7 +996,7 @@ def backup_key(self, name, mount_point=DEFAULT_MOUNT_POINT): :rtype: dict """ api_path = utils.format_url( - '/v1/{mount_point}/backup/{name}', + "/v1/{mount_point}/backup/{name}", mount_point=mount_point, name=name, ) @@ -810,7 +1004,9 @@ def backup_key(self, name, mount_point=DEFAULT_MOUNT_POINT): url=api_path, ) - def restore_key(self, backup, name=None, force=None, mount_point=DEFAULT_MOUNT_POINT): + def restore_key( + self, backup, name=None, force=None, mount_point=DEFAULT_MOUNT_POINT + ): """Restore the backup as a named key. This will restore the key configurations and all the versions of the named key along with HMAC keys. The input @@ -834,14 +1030,18 @@ def restore_key(self, backup, name=None, force=None, mount_point=DEFAULT_MOUNT_P :rtype: requests.Response """ params = { - 'backup': backup, + "backup": backup, } params.update( - utils.remove_nones({ - 'force': force, - }) + utils.remove_nones( + { + "force": force, + } + ) + ) + api_path = utils.format_url( + "/v1/{mount_point}/restore", mount_point=mount_point ) - api_path = utils.format_url('/v1/{mount_point}/restore', mount_point=mount_point) if name is not None: api_path = self._adapter.urljoin(api_path, name) return self._adapter.post( @@ -869,10 +1069,10 @@ def trim_key(self, name, min_version, mount_point=DEFAULT_MOUNT_POINT): :rtype: dict """ params = { - 'min_available_version': min_version, + "min_available_version": min_version, } api_path = utils.format_url( - '/v1/{mount_point}/keys/{name}/trim', + "/v1/{mount_point}/keys/{name}/trim", mount_point=mount_point, name=name, ) diff --git a/hvac/api/system_backend/__init__.py b/hvac/api/system_backend/__init__.py index b779b349f..a4519790c 100644 --- a/hvac/api/system_backend/__init__.py +++ b/hvac/api/system_backend/__init__.py @@ -19,30 +19,45 @@ from hvac.api.vault_api_category import VaultApiCategory __all__ = ( - 'Audit', - 'Auth', - 'Capabilities', - 'Health', - 'Init', - 'Key', - 'Leader', - 'Lease', - 'Mount', - 'Namespace', - 'Policy', - 'Raft', - 'Seal', - 'SystemBackend', - 'SystemBackendMixin', - 'Wrapping', + "Audit", + "Auth", + "Capabilities", + "Health", + "Init", + "Key", + "Leader", + "Lease", + "Mount", + "Namespace", + "Policy", + "Raft", + "Seal", + "SystemBackend", + "SystemBackendMixin", + "Wrapping", ) logger = logging.getLogger(__name__) -class SystemBackend(VaultApiCategory, Audit, Auth, Capabilities, Health, Init, Key, Leader, Lease, Mount, Namespace, - Policy, Raft, Seal, Wrapping): +class SystemBackend( + VaultApiCategory, + Audit, + Auth, + Capabilities, + Health, + Init, + Key, + Leader, + Lease, + Mount, + Namespace, + Policy, + Raft, + Seal, + Wrapping, +): implemented_classes = [ Audit, Auth, diff --git a/hvac/api/system_backend/audit.py b/hvac/api/system_backend/audit.py index 7ad56a9cd..6f70224ca 100644 --- a/hvac/api/system_backend/audit.py +++ b/hvac/api/system_backend/audit.py @@ -6,7 +6,6 @@ class Audit(SystemBackendMixin): - def list_enabled_audit_devices(self): """List enabled audit devices. @@ -19,9 +18,11 @@ def list_enabled_audit_devices(self): :return: JSON response of the request. :rtype: dict """ - return self._adapter.get('/v1/sys/audit') + return self._adapter.get("/v1/sys/audit") - def enable_audit_device(self, device_type, description=None, options=None, path=None, local=None): + def enable_audit_device( + self, device_type, description=None, options=None, path=None, local=None + ): """Enable a new audit device at the supplied path. The path can be a single word name or a more complex, nested path. @@ -49,21 +50,20 @@ def enable_audit_device(self, device_type, description=None, options=None, path= path = device_type params = { - 'type': device_type, + "type": device_type, } params.update( - utils.remove_nones({ - 'description': description, - 'options': options, - 'local': local, - }) + utils.remove_nones( + { + "description": description, + "options": options, + "local": local, + } + ) ) - api_path = utils.format_url('/v1/sys/audit/{path}', path=path) - return self._adapter.post( - url=api_path, - json=params - ) + api_path = utils.format_url("/v1/sys/audit/{path}", path=path) + return self._adapter.post(url=api_path, json=params) def disable_audit_device(self, path): """Disable the audit device at the given path. @@ -76,7 +76,7 @@ def disable_audit_device(self, path): :return: The response of the request. :rtype: requests.Response """ - api_path = utils.format_url('/v1/sys/audit/{path}', path=path) + api_path = utils.format_url("/v1/sys/audit/{path}", path=path) return self._adapter.delete( url=api_path, ) @@ -98,11 +98,8 @@ def calculate_hash(self, path, input_to_hash): :rtype: requests.Response """ params = { - 'input': input_to_hash, + "input": input_to_hash, } - api_path = utils.format_url('/v1/sys/audit-hash/{path}', path=path) - return self._adapter.post( - url=api_path, - json=params - ) + api_path = utils.format_url("/v1/sys/audit-hash/{path}", path=path) + return self._adapter.post(url=api_path, json=params) diff --git a/hvac/api/system_backend/auth.py b/hvac/api/system_backend/auth.py index 2b4a63302..602ba5258 100644 --- a/hvac/api/system_backend/auth.py +++ b/hvac/api/system_backend/auth.py @@ -7,7 +7,6 @@ class Auth(SystemBackendMixin): - def list_auth_methods(self): """List all enabled auth methods. @@ -17,12 +16,21 @@ def list_auth_methods(self): :return: The JSON response of the request. :rtype: dict """ - api_path = '/v1/sys/auth' + api_path = "/v1/sys/auth" return self._adapter.get( url=api_path, ) - def enable_auth_method(self, method_type, description=None, config=None, plugin_name=None, local=False, path=None, **kwargs): + def enable_auth_method( + self, + method_type, + description=None, + config=None, + plugin_name=None, + local=False, + path=None, + **kwargs + ): """Enable a new auth method. After enabling, the auth method can be accessed and configured via the auth path specified as part of the URL. @@ -66,22 +74,21 @@ def enable_auth_method(self, method_type, description=None, config=None, plugin_ path = method_type params = { - 'type': method_type, + "type": method_type, } params.update( - utils.remove_nones({ - 'description': description, - 'config': config, - 'plugin_name': plugin_name, - 'local': local, - }) + utils.remove_nones( + { + "description": description, + "config": config, + "plugin_name": plugin_name, + "local": local, + } + ) ) params.update(kwargs) - api_path = utils.format_url('/v1/sys/auth/{path}', path=path) - return self._adapter.post( - url=api_path, - json=params - ) + api_path = utils.format_url("/v1/sys/auth/{path}", path=path) + return self._adapter.post(url=api_path, json=params) def disable_auth_method(self, path): """Disable the auth method at the given auth path. @@ -95,7 +102,7 @@ def disable_auth_method(self, path): :return: The response of the request. :rtype: requests.Response """ - api_path = utils.format_url('/v1/sys/auth/{path}', path=path) + api_path = utils.format_url("/v1/sys/auth/{path}", path=path) return self._adapter.delete( url=api_path, ) @@ -116,16 +123,25 @@ def read_auth_method_tuning(self, path): :rtype: dict """ api_path = utils.format_url( - '/v1/sys/auth/{path}/tune', + "/v1/sys/auth/{path}/tune", path=path, ) return self._adapter.get( url=api_path, ) - def tune_auth_method(self, path, default_lease_ttl=None, max_lease_ttl=None, description=None, - audit_non_hmac_request_keys=None, audit_non_hmac_response_keys=None, listing_visibility=None, - passthrough_request_headers=None, **kwargs): + def tune_auth_method( + self, + path, + default_lease_ttl=None, + max_lease_ttl=None, + description=None, + audit_non_hmac_request_keys=None, + audit_non_hmac_response_keys=None, + listing_visibility=None, + passthrough_request_headers=None, + **kwargs + ): """Tune configuration parameters for a given auth path. This endpoint requires sudo capability on the final path, but the same functionality can be achieved without @@ -163,7 +179,7 @@ def tune_auth_method(self, path, default_lease_ttl=None, max_lease_ttl=None, des :rtype: requests.Response """ - if listing_visibility is not None and listing_visibility not in ['unauth', '']: + if listing_visibility is not None and listing_visibility not in ["unauth", ""]: error_msg = 'invalid listing_visibility argument provided: "{arg}"; valid values: "unauth" or ""'.format( arg=listing_visibility, ) @@ -172,25 +188,25 @@ def tune_auth_method(self, path, default_lease_ttl=None, max_lease_ttl=None, des # All parameters are optional for this method. Until/unless we include input validation, we simply loop over the # parameters and add which parameters are set. optional_parameters = { - 'default_lease_ttl': {}, - 'max_lease_ttl': {}, - 'description': {}, - 'audit_non_hmac_request_keys': dict(comma_delimited_list=True), - 'audit_non_hmac_response_keys': dict(comma_delimited_list=True), - 'listing_visibility': {}, - 'passthrough_request_headers': dict(comma_delimited_list=True), + "default_lease_ttl": {}, + "max_lease_ttl": {}, + "description": {}, + "audit_non_hmac_request_keys": dict(comma_delimited_list=True), + "audit_non_hmac_response_keys": dict(comma_delimited_list=True), + "listing_visibility": {}, + "passthrough_request_headers": dict(comma_delimited_list=True), } params = {} for optional_parameter, parameter_specification in optional_parameters.items(): if locals().get(optional_parameter) is not None: - if parameter_specification.get('comma_delimited_list'): + if parameter_specification.get("comma_delimited_list"): argument = locals().get(optional_parameter) validate_list_of_strings_param(optional_parameter, argument) params[optional_parameter] = list_to_comma_delimited(argument) else: params[optional_parameter] = locals().get(optional_parameter) params.update(kwargs) - api_path = utils.format_url('/v1/sys/auth/{path}/tune', path=path) + api_path = utils.format_url("/v1/sys/auth/{path}/tune", path=path) return self._adapter.post( url=api_path, json=params, diff --git a/hvac/api/system_backend/capabilities.py b/hvac/api/system_backend/capabilities.py index e99fae382..0d25c235f 100644 --- a/hvac/api/system_backend/capabilities.py +++ b/hvac/api/system_backend/capabilities.py @@ -2,7 +2,6 @@ class Capabilities(SystemBackendMixin): - def get_capabilities(self, paths, token=None, accessor=None): """Get the capabilities associated with a token. @@ -21,22 +20,22 @@ def get_capabilities(self, paths, token=None, accessor=None): :rtype: dict """ params = { - 'paths': paths, + "paths": paths, } if token and accessor: raise ValueError("You can specify either token or accessor, not both.") elif token: # https://www.vaultproject.io/api/system/capabilities.html - params['token'] = token - api_path = '/v1/sys/capabilities' + params["token"] = token + api_path = "/v1/sys/capabilities" elif accessor: # https://www.vaultproject.io/api/system/capabilities-accessor.html - params['accessor'] = accessor - api_path = '/v1/sys/capabilities-accessor' + params["accessor"] = accessor + api_path = "/v1/sys/capabilities-accessor" else: # https://www.vaultproject.io/api/system/capabilities-self.html - api_path = '/v1/sys/capabilities-self' + api_path = "/v1/sys/capabilities-self" return self._adapter.post( url=api_path, diff --git a/hvac/api/system_backend/health.py b/hvac/api/system_backend/health.py index ab49dfe5d..f47840a31 100644 --- a/hvac/api/system_backend/health.py +++ b/hvac/api/system_backend/health.py @@ -11,8 +11,17 @@ class Health(SystemBackendMixin): Reference: https://www.vaultproject.io/api-docs/system/health """ - def read_health_status(self, standby_ok=None, active_code=None, standby_code=None, dr_secondary_code=None, - performance_standby_code=None, sealed_code=None, uninit_code=None, method='HEAD'): + def read_health_status( + self, + standby_ok=None, + active_code=None, + standby_code=None, + dr_secondary_code=None, + performance_standby_code=None, + sealed_code=None, + uninit_code=None, + method="HEAD", + ): """Read the health status of Vault. This matches the semantics of a Consul HTTP health check and provides a simple way to monitor the health of a @@ -43,29 +52,33 @@ def read_health_status(self, standby_ok=None, active_code=None, standby_code=Non :return: The JSON response of the request. :rtype: requests.Response """ - params = utils.remove_nones({ - 'standbyok': standby_ok, - 'activecode': active_code, - 'standbycode': standby_code, - 'drsecondarycode': dr_secondary_code, - 'performancestandbycode': performance_standby_code, - 'sealedcode': sealed_code, - 'uninitcode': uninit_code, - }) + params = utils.remove_nones( + { + "standbyok": standby_ok, + "activecode": active_code, + "standbycode": standby_code, + "drsecondarycode": dr_secondary_code, + "performancestandbycode": performance_standby_code, + "sealedcode": sealed_code, + "uninitcode": uninit_code, + } + ) - if method == 'HEAD': - api_path = utils.format_url('/v1/sys/health') + if method == "HEAD": + api_path = utils.format_url("/v1/sys/health") return self._adapter.head( url=api_path, raise_exception=False, ) - elif method == 'GET': - api_path = utils.format_url('/v1/sys/health') + elif method == "GET": + api_path = utils.format_url("/v1/sys/health") return self._adapter.get( url=api_path, params=params, raise_exception=False, ) else: - error_message = '"method" parameter provided invalid value; HEAD or GET allowed, "{method}" provided'.format(method=method) + error_message = '"method" parameter provided invalid value; HEAD or GET allowed, "{method}" provided'.format( + method=method + ) raise exceptions.ParamValidationError(error_message) diff --git a/hvac/api/system_backend/init.py b/hvac/api/system_backend/init.py index 87998032d..0bd69a2e4 100644 --- a/hvac/api/system_backend/init.py +++ b/hvac/api/system_backend/init.py @@ -3,7 +3,6 @@ class Init(SystemBackendMixin): - def read_init_status(self): """Read the initialization status of Vault. @@ -13,7 +12,7 @@ def read_init_status(self): :return: The JSON response of the request. :rtype: dict """ - api_path = '/v1/sys/init' + api_path = "/v1/sys/init" return self._adapter.get( url=api_path, ) @@ -25,10 +24,19 @@ def is_initialized(self): :rtype: bool """ status = self.read_init_status() - return status['initialized'] - - def initialize(self, secret_shares=5, secret_threshold=3, pgp_keys=None, root_token_pgp_key=None, - stored_shares=None, recovery_shares=None, recovery_threshold=None, recovery_pgp_keys=None): + return status["initialized"] + + def initialize( + self, + secret_shares=5, + secret_threshold=3, + pgp_keys=None, + root_token_pgp_key=None, + stored_shares=None, + recovery_shares=None, + recovery_threshold=None, + recovery_pgp_keys=None, + ): """Initialize a new Vault. The Vault must not have been previously initialized. The recovery options, as well as the stored shares option, @@ -66,36 +74,42 @@ def initialize(self, secret_shares=5, secret_threshold=3, pgp_keys=None, root_to :rtype: dict """ params = { - 'secret_shares': secret_shares, - 'secret_threshold': secret_threshold, - 'root_token_pgp_key': root_token_pgp_key, + "secret_shares": secret_shares, + "secret_threshold": secret_threshold, + "root_token_pgp_key": root_token_pgp_key, } if pgp_keys is not None: if len(pgp_keys) != secret_shares: - raise ParamValidationError('length of pgp_keys list argument must equal secret_shares value') - params['pgp_keys'] = pgp_keys + raise ParamValidationError( + "length of pgp_keys list argument must equal secret_shares value" + ) + params["pgp_keys"] = pgp_keys if stored_shares is not None: if stored_shares != secret_shares: - raise ParamValidationError('value for stored_shares argument must equal secret_shares argument') - params['stored_shares'] = stored_shares + raise ParamValidationError( + "value for stored_shares argument must equal secret_shares argument" + ) + params["stored_shares"] = stored_shares if recovery_shares is not None: - params['recovery_shares'] = recovery_shares + params["recovery_shares"] = recovery_shares if recovery_threshold is not None: if recovery_threshold > recovery_shares: - error_msg = 'value for recovery_threshold argument be less than or equal to recovery_shares argument' + error_msg = "value for recovery_threshold argument be less than or equal to recovery_shares argument" raise ParamValidationError(error_msg) - params['recovery_threshold'] = recovery_threshold + params["recovery_threshold"] = recovery_threshold if recovery_pgp_keys is not None: if len(recovery_pgp_keys) != recovery_shares: - raise ParamValidationError('length of recovery_pgp_keys list argument must equal recovery_shares value') - params['recovery_pgp_keys'] = recovery_pgp_keys + raise ParamValidationError( + "length of recovery_pgp_keys list argument must equal recovery_shares value" + ) + params["recovery_pgp_keys"] = recovery_pgp_keys - api_path = '/v1/sys/init' + api_path = "/v1/sys/init" return self._adapter.put( url=api_path, json=params, diff --git a/hvac/api/system_backend/key.py b/hvac/api/system_backend/key.py index ee6cc912e..8933496e7 100644 --- a/hvac/api/system_backend/key.py +++ b/hvac/api/system_backend/key.py @@ -3,7 +3,6 @@ class Key(SystemBackendMixin): - def read_root_generation_progress(self): """Read the configuration and process of the current root generation attempt. @@ -13,7 +12,7 @@ def read_root_generation_progress(self): :return: The JSON response of the request. :rtype: dict """ - api_path = '/v1/sys/generate-root/attempt' + api_path = "/v1/sys/generate-root/attempt" return self._adapter.get( url=api_path, ) @@ -38,17 +37,16 @@ def start_root_token_generation(self, otp=None, pgp_key=None): """ params = {} if otp is not None and pgp_key is not None: - raise ParamValidationError('one (and only one) of otp or pgp_key arguments are required') + raise ParamValidationError( + "one (and only one) of otp or pgp_key arguments are required" + ) if otp is not None: - params['otp'] = otp + params["otp"] = otp if pgp_key is not None: - params['pgp_key'] = pgp_key + params["pgp_key"] = pgp_key - api_path = '/v1/sys/generate-root/attempt' - return self._adapter.put( - url=api_path, - json=params - ) + api_path = "/v1/sys/generate-root/attempt" + return self._adapter.put(url=api_path, json=params) def generate_root(self, key, nonce): """Enter a single master key share to progress the root generation attempt. @@ -68,10 +66,10 @@ def generate_root(self, key, nonce): :rtype: dict """ params = { - 'key': key, - 'nonce': nonce, + "key": key, + "nonce": nonce, } - api_path = '/v1/sys/generate-root/update' + api_path = "/v1/sys/generate-root/update" return self._adapter.put( url=api_path, json=params, @@ -88,7 +86,7 @@ def cancel_root_generation(self): :return: The response of the request. :rtype: request.Response """ - api_path = '/v1/sys/generate-root/attempt' + api_path = "/v1/sys/generate-root/attempt" return self._adapter.delete( url=api_path, ) @@ -102,7 +100,7 @@ def get_encryption_key_status(self): :return: JSON response with information regarding the current encryption key used by Vault. :rtype: dict """ - api_path = '/v1/sys/key-status' + api_path = "/v1/sys/key-status" return self._adapter.get( url=api_path, ) @@ -122,7 +120,7 @@ def rotate_encryption_key(self): :return: The response of the request. :rtype: requests.Response """ - api_path = '/v1/sys/rotate' + api_path = "/v1/sys/rotate" return self._adapter.put( url=api_path, ) @@ -139,14 +137,22 @@ def read_rekey_progress(self, recovery_key=False): :return: The JSON response of the request. :rtype: requests.Response """ - api_path = '/v1/sys/rekey/init' + api_path = "/v1/sys/rekey/init" if recovery_key: - api_path = '/v1/sys/rekey-recovery-key/init' + api_path = "/v1/sys/rekey-recovery-key/init" return self._adapter.get( url=api_path, ) - def start_rekey(self, secret_shares=5, secret_threshold=3, pgp_keys=None, backup=False, require_verification=False, recovery_key=False): + def start_rekey( + self, + secret_shares=5, + secret_threshold=3, + pgp_keys=None, + backup=False, + require_verification=False, + recovery_key=False, + ): """Initializes a new rekey attempt. Only a single recovery key rekeyattempt can take place at a time, and changing the parameters of a rekey @@ -183,21 +189,23 @@ def start_rekey(self, secret_shares=5, secret_threshold=3, pgp_keys=None, backup :rtype: dict | request.Response """ params = { - 'secret_shares': secret_shares, - 'secret_threshold': secret_threshold, - 'require_verification': require_verification, + "secret_shares": secret_shares, + "secret_threshold": secret_threshold, + "require_verification": require_verification, } if pgp_keys: if len(pgp_keys) != secret_shares: - raise ParamValidationError('length of pgp_keys argument must equal secret shares value') + raise ParamValidationError( + "length of pgp_keys argument must equal secret shares value" + ) - params['pgp_keys'] = pgp_keys - params['backup'] = backup + params["pgp_keys"] = pgp_keys + params["backup"] = backup - api_path = '/v1/sys/rekey/init' + api_path = "/v1/sys/rekey/init" if recovery_key: - api_path = '/v1/sys/rekey-recovery-key/init' + api_path = "/v1/sys/rekey-recovery-key/init" return self._adapter.put( url=api_path, json=params, @@ -221,9 +229,9 @@ def cancel_rekey(self, recovery_key=False): :return: The response of the request. :rtype: requests.Response """ - api_path = '/v1/sys/rekey/init' + api_path = "/v1/sys/rekey/init" if recovery_key: - api_path = '/v1/sys/rekey-recovery-key/init' + api_path = "/v1/sys/rekey-recovery-key/init" return self._adapter.delete( url=api_path, ) @@ -249,15 +257,15 @@ def rekey(self, key, nonce=None, recovery_key=False): :rtype: dict """ params = { - 'key': key, + "key": key, } if nonce is not None: - params['nonce'] = nonce + params["nonce"] = nonce - api_path = '/v1/sys/rekey/update' + api_path = "/v1/sys/rekey/update" if recovery_key: - api_path = '/v1/sys/rekey-recovery-key/update' + api_path = "/v1/sys/rekey-recovery-key/update" return self._adapter.put( url=api_path, json=params, @@ -285,7 +293,7 @@ def rekey_multi(self, keys, nonce=None, recovery_key=False): nonce=nonce, recovery_key=recovery_key, ) - if result.get('complete'): + if result.get("complete"): break return result @@ -305,9 +313,9 @@ def read_backup_keys(self, recovery_key=False): :return: The JSON response of the request. :rtype: dict """ - api_path = '/v1/sys/rekey/backup' + api_path = "/v1/sys/rekey/backup" if recovery_key: - api_path = '/v1/sys/rekey-recovery-key/backup' + api_path = "/v1/sys/rekey-recovery-key/backup" return self._adapter.get( url=api_path, ) @@ -324,7 +332,7 @@ def cancel_rekey_verify(self): :return: The response of the request. :rtype: requests.Response """ - api_path = '/v1/sys/rekey/verify' + api_path = "/v1/sys/rekey/verify" return self._adapter.delete( url=api_path, ) @@ -346,11 +354,11 @@ def rekey_verify(self, key, nonce): :rtype: dict """ params = { - 'key': key, - 'nonce': nonce, + "key": key, + "nonce": nonce, } - api_path = '/v1/sys/rekey/verify' + api_path = "/v1/sys/rekey/verify" return self._adapter.put( url=api_path, json=params, @@ -379,7 +387,7 @@ def rekey_verify_multi(self, keys, nonce): key=key, nonce=nonce, ) - if result.get('complete'): + if result.get("complete"): break return result @@ -393,7 +401,7 @@ def read_rekey_verify_progress(self): :return: The JSON response of the request. :rtype: requests.Response """ - api_path = '/v1/sys/rekey/verify' + api_path = "/v1/sys/rekey/verify" return self._adapter.get( url=api_path, ) diff --git a/hvac/api/system_backend/leader.py b/hvac/api/system_backend/leader.py index d94c6ba41..2e3844e90 100644 --- a/hvac/api/system_backend/leader.py +++ b/hvac/api/system_backend/leader.py @@ -2,7 +2,6 @@ class Leader(SystemBackendMixin): - def read_leader_status(self): """Read the high availability status and current leader instance of Vault. @@ -12,7 +11,7 @@ def read_leader_status(self): :return: The JSON response of the request. :rtype: dict """ - api_path = '/v1/sys/leader' + api_path = "/v1/sys/leader" return self._adapter.get( url=api_path, ) @@ -29,7 +28,7 @@ def step_down(self): :return: The JSON response of the request. :rtype: dict """ - api_path = '/v1/sys/step-down' + api_path = "/v1/sys/step-down" return self._adapter.put( url=api_path, ) diff --git a/hvac/api/system_backend/lease.py b/hvac/api/system_backend/lease.py index 8685930b3..6df50c536 100644 --- a/hvac/api/system_backend/lease.py +++ b/hvac/api/system_backend/lease.py @@ -3,7 +3,6 @@ class Lease(SystemBackendMixin): - def read_lease(self, lease_id): """Retrieve lease metadata. @@ -15,14 +14,9 @@ def read_lease(self, lease_id): :return: Parsed JSON response from the leases PUT request :rtype: dict. """ - params = { - 'lease_id': lease_id - } - api_path = '/v1/sys/leases/lookup' - return self._adapter.put( - url=api_path, - json=params - ) + params = {"lease_id": lease_id} + api_path = "/v1/sys/leases/lookup" + return self._adapter.put(url=api_path, json=params) def list_leases(self, prefix): """Retrieve a list of lease ids. @@ -35,7 +29,7 @@ def list_leases(self, prefix): :return: The JSON response of the request. :rtype: dict """ - api_path = utils.format_url('/v1/sys/leases/lookup/{prefix}', prefix=prefix) + api_path = utils.format_url("/v1/sys/leases/lookup/{prefix}", prefix=prefix) return self._adapter.list( url=api_path, ) @@ -54,10 +48,10 @@ def renew_lease(self, lease_id, increment=None): :rtype: dict """ params = { - 'lease_id': lease_id, - 'increment': increment, + "lease_id": lease_id, + "increment": increment, } - api_path = '/v1/sys/leases/renew' + api_path = "/v1/sys/leases/renew" return self._adapter.put( url=api_path, json=params, @@ -75,9 +69,9 @@ def revoke_lease(self, lease_id): :rtype: requests.Response """ params = { - 'lease_id': lease_id, + "lease_id": lease_id, } - api_path = '/v1/sys/leases/revoke' + api_path = "/v1/sys/leases/revoke" return self._adapter.put( url=api_path, json=params, @@ -100,9 +94,11 @@ def revoke_prefix(self, prefix): :rtype: requests.Response """ params = { - 'prefix': prefix, + "prefix": prefix, } - api_path = utils.format_url('/v1/sys/leases/revoke-prefix/{prefix}', prefix=prefix) + api_path = utils.format_url( + "/v1/sys/leases/revoke-prefix/{prefix}", prefix=prefix + ) return self._adapter.put( url=api_path, json=params, @@ -124,9 +120,11 @@ def revoke_force(self, prefix): :rtype: requests.Response """ params = { - 'prefix': prefix, + "prefix": prefix, } - api_path = utils.format_url('/v1/sys/leases/revoke-force/{prefix}', prefix=prefix) + api_path = utils.format_url( + "/v1/sys/leases/revoke-force/{prefix}", prefix=prefix + ) return self._adapter.put( url=api_path, json=params, diff --git a/hvac/api/system_backend/mount.py b/hvac/api/system_backend/mount.py index 157883d5a..569701c82 100644 --- a/hvac/api/system_backend/mount.py +++ b/hvac/api/system_backend/mount.py @@ -3,7 +3,6 @@ class Mount(SystemBackendMixin): - def list_mounted_secrets_engines(self): """Lists all the mounted secrets engines. @@ -13,19 +12,29 @@ def list_mounted_secrets_engines(self): :return: JSON response of the request. :rtype: dict """ - return self._adapter.get('/v1/sys/mounts') + return self._adapter.get("/v1/sys/mounts") def retrieve_mount_option(self, mount_point, option_name, default_value=None): - secrets_engine_path = '{mount_point}/'.format(mount_point=mount_point) - secrets_engines_list = self.list_mounted_secrets_engines()['data'] - mount_options = secrets_engines_list[secrets_engine_path].get('options') + secrets_engine_path = "{mount_point}/".format(mount_point=mount_point) + secrets_engines_list = self.list_mounted_secrets_engines()["data"] + mount_options = secrets_engines_list[secrets_engine_path].get("options") if mount_options is None: return default_value return mount_options.get(option_name, default_value) - def enable_secrets_engine(self, backend_type, path=None, description=None, config=None, plugin_name=None, - options=None, local=False, seal_wrap=False, **kwargs): + def enable_secrets_engine( + self, + backend_type, + path=None, + description=None, + config=None, + plugin_name=None, + options=None, + local=False, + seal_wrap=False, + **kwargs + ): """Enable a new secrets engine at the given path. Supported methods: @@ -73,18 +82,18 @@ def enable_secrets_engine(self, backend_type, path=None, description=None, confi path = backend_type params = { - 'type': backend_type, - 'description': description, - 'config': config, - 'options': options, - 'plugin_name': plugin_name, - 'local': local, - 'seal_wrap': seal_wrap, + "type": backend_type, + "description": description, + "config": config, + "options": options, + "plugin_name": plugin_name, + "local": local, + "seal_wrap": seal_wrap, } params.update(kwargs) - api_path = utils.format_url('/v1/sys/mounts/{path}', path=path) + api_path = utils.format_url("/v1/sys/mounts/{path}", path=path) return self._adapter.post( url=api_path, json=params, @@ -101,7 +110,7 @@ def disable_secrets_engine(self, path): :return: The response of the request. :rtype: requests.Response """ - api_path = utils.format_url('/v1/sys/mounts/{path}', path=path) + api_path = utils.format_url("/v1/sys/mounts/{path}", path=path) return self._adapter.delete( url=api_path, ) @@ -120,14 +129,25 @@ def read_mount_configuration(self, path): :return: The JSON response of the request. :rtype: requests.Response """ - api_path = utils.format_url('/v1/sys/mounts/{path}/tune', path=path) + api_path = utils.format_url("/v1/sys/mounts/{path}/tune", path=path) return self._adapter.get( url=api_path, ) - def tune_mount_configuration(self, path, default_lease_ttl=None, max_lease_ttl=None, description=None, - audit_non_hmac_request_keys=None, audit_non_hmac_response_keys=None, - listing_visibility=None, passthrough_request_headers=None, options=None, force_no_cache=None, **kwargs): + def tune_mount_configuration( + self, + path, + default_lease_ttl=None, + max_lease_ttl=None, + description=None, + audit_non_hmac_request_keys=None, + audit_non_hmac_response_keys=None, + listing_visibility=None, + passthrough_request_headers=None, + options=None, + force_no_cache=None, + **kwargs + ): """Tune configuration parameters for a given mount point. Supported methods: @@ -172,15 +192,15 @@ def tune_mount_configuration(self, path, default_lease_ttl=None, max_lease_ttl=N # All parameters are optional for this method. Until/unless we include input validation, we simply loop over the # parameters and add which parameters are set. optional_parameters = [ - 'default_lease_ttl', - 'max_lease_ttl', - 'description', - 'audit_non_hmac_request_keys', - 'audit_non_hmac_response_keys', - 'listing_visibility', - 'passthrough_request_headers', - 'force_no_cache', - 'options', + "default_lease_ttl", + "max_lease_ttl", + "description", + "audit_non_hmac_request_keys", + "audit_non_hmac_response_keys", + "listing_visibility", + "passthrough_request_headers", + "force_no_cache", + "options", ] params = {} for optional_parameter in optional_parameters: @@ -189,7 +209,7 @@ def tune_mount_configuration(self, path, default_lease_ttl=None, max_lease_ttl=N params.update(kwargs) - api_path = utils.format_url('/v1/sys/mounts/{path}/tune', path=path) + api_path = utils.format_url("/v1/sys/mounts/{path}/tune", path=path) return self._adapter.post( url=api_path, json=params, @@ -209,10 +229,10 @@ def move_backend(self, from_path, to_path): :rtype: requests.Response """ params = { - 'from': from_path, - 'to': to_path, + "from": from_path, + "to": to_path, } - api_path = '/v1/sys/remount' + api_path = "/v1/sys/remount" return self._adapter.post( url=api_path, json=params, diff --git a/hvac/api/system_backend/namespace.py b/hvac/api/system_backend/namespace.py index fe7f145df..d69c76aaf 100644 --- a/hvac/api/system_backend/namespace.py +++ b/hvac/api/system_backend/namespace.py @@ -3,7 +3,6 @@ class Namespace(SystemBackendMixin): - def create_namespace(self, path): """Create a namespace at the given path. @@ -13,7 +12,7 @@ def create_namespace(self, path): :return: The response of the request. :rtype: requests.Response """ - api_path = utils.format_url('/v1/sys/namespaces/{path}', path=path) + api_path = utils.format_url("/v1/sys/namespaces/{path}", path=path) return self._adapter.post( url=api_path, ) @@ -27,7 +26,7 @@ def list_namespaces(self): :return: The JSON response of the request. :rtype: dict """ - api_path = '/v1/sys/namespaces/' + api_path = "/v1/sys/namespaces/" return self._adapter.list( url=api_path, ) @@ -41,7 +40,7 @@ def delete_namespace(self, path): :return: The response of the request. :rtype: requests.Response """ - api_path = utils.format_url('/v1/sys/namespaces/{path}', path=path) + api_path = utils.format_url("/v1/sys/namespaces/{path}", path=path) return self._adapter.delete( url=api_path, ) diff --git a/hvac/api/system_backend/policy.py b/hvac/api/system_backend/policy.py index 2f62aa94e..b27441c0b 100644 --- a/hvac/api/system_backend/policy.py +++ b/hvac/api/system_backend/policy.py @@ -5,7 +5,6 @@ class Policy(SystemBackendMixin): - def list_policies(self): """List all configured policies. @@ -15,7 +14,7 @@ def list_policies(self): :return: The JSON response of the request. :rtype: dict """ - api_path = '/v1/sys/policy' + api_path = "/v1/sys/policy" return self._adapter.get( url=api_path, ) @@ -31,7 +30,7 @@ def read_policy(self, name): :return: The response of the request :rtype: dict """ - api_path = utils.format_url('/v1/sys/policy/{name}', name=name) + api_path = utils.format_url("/v1/sys/policy/{name}", name=name) return self._adapter.get( url=api_path, ) @@ -60,9 +59,9 @@ def create_or_update_policy(self, name, policy, pretty_print=True): else: policy = json.dumps(policy) params = { - 'policy': policy, + "policy": policy, } - api_path = utils.format_url('/v1/sys/policy/{name}', name=name) + api_path = utils.format_url("/v1/sys/policy/{name}", name=name) return self._adapter.put( url=api_path, json=params, @@ -81,7 +80,7 @@ def delete_policy(self, name): :return: The response of the request. :rtype: requests.Response """ - api_path = utils.format_url('/v1/sys/policy/{name}', name=name) + api_path = utils.format_url("/v1/sys/policy/{name}", name=name) return self._adapter.delete( url=api_path, ) diff --git a/hvac/api/system_backend/raft.py b/hvac/api/system_backend/raft.py index d3fdfe90c..ec834dc4b 100644 --- a/hvac/api/system_backend/raft.py +++ b/hvac/api/system_backend/raft.py @@ -16,7 +16,14 @@ class Raft(SystemBackendMixin): Reference: https://www.vaultproject.io/api-docs/system/storage/raft """ - def join_raft_cluster(self, leader_api_addr, retry=False, leader_ca_cert=None, leader_client_cert=None, leader_client_key=None): + def join_raft_cluster( + self, + leader_api_addr, + retry=False, + leader_ca_cert=None, + leader_client_cert=None, + leader_client_key=None, + ): """Join a new server node to the Raft cluster. When using Shamir seal, as soon as the Vault server is brought up, this API should be invoked @@ -41,14 +48,16 @@ def join_raft_cluster(self, leader_api_addr, retry=False, leader_ca_cert=None, l :return: The response of the join_raft_cluster request. :rtype: requests.Response """ - params = utils.remove_nones({ - 'leader_api_addr': leader_api_addr, - 'retry': retry, - 'leader_ca_cert': leader_ca_cert, - 'leader_client_cert': leader_client_cert, - 'leader_client_key': leader_client_key, - }) - api_path = '/v1/sys/storage/raft/join' + params = utils.remove_nones( + { + "leader_api_addr": leader_api_addr, + "retry": retry, + "leader_ca_cert": leader_ca_cert, + "leader_client_cert": leader_client_cert, + "leader_client_key": leader_client_key, + } + ) + api_path = "/v1/sys/storage/raft/join" return self._adapter.post( url=api_path, json=params, @@ -63,7 +72,7 @@ def read_raft_config(self): :return: The response of the read_raft_config request. :rtype: requests.Response """ - api_path = '/v1/sys/storage/raft/configuration' + api_path = "/v1/sys/storage/raft/configuration" return self._adapter.get( url=api_path, ) @@ -80,9 +89,9 @@ def remove_raft_node(self, server_id): :rtype: requests.Response """ params = { - 'server_id': server_id, + "server_id": server_id, } - api_path = '/v1/sys/storage/raft/remove-peer' + api_path = "/v1/sys/storage/raft/remove-peer" return self._adapter.post( url=api_path, json=params, @@ -99,7 +108,7 @@ def take_raft_snapshot(self): :return: The response of the s request. :rtype: requests.Response """ - api_path = '/v1/sys/storage/raft/snapshot' + api_path = "/v1/sys/storage/raft/snapshot" return self._adapter.get( url=api_path, stream=True, @@ -116,7 +125,7 @@ def restore_raft_snapshot(self, snapshot): :return: The response of the restore_raft_snapshot request. :rtype: requests.Response """ - api_path = '/v1/sys/storage/raft/snapshot' + api_path = "/v1/sys/storage/raft/snapshot" return self._adapter.post( url=api_path, data=snapshot, @@ -136,7 +145,7 @@ def force_restore_raft_snapshot(self, snapshot): :return: The response of the force_restore_raft_snapshot request. :rtype: requests.Response """ - api_path = '/v1/sys/storage/raft/snapshot-force' + api_path = "/v1/sys/storage/raft/snapshot-force" return self._adapter.post( url=api_path, data=snapshot, diff --git a/hvac/api/system_backend/seal.py b/hvac/api/system_backend/seal.py index 74b45d467..9ce2f5f4b 100644 --- a/hvac/api/system_backend/seal.py +++ b/hvac/api/system_backend/seal.py @@ -2,7 +2,6 @@ class Seal(SystemBackendMixin): - def is_sealed(self): """Determine if Vault is sealed. @@ -10,7 +9,7 @@ def is_sealed(self): :rtype: bool """ seal_status = self.read_seal_status() - return seal_status['sealed'] + return seal_status["sealed"] def read_seal_status(self): """Read the seal status of the Vault. @@ -23,7 +22,7 @@ def read_seal_status(self): :return: The JSON response of the request. :rtype: dict """ - api_path = '/v1/sys/seal-status' + api_path = "/v1/sys/seal-status" return self._adapter.get( url=api_path, ) @@ -40,7 +39,7 @@ def seal(self): :return: The response of the request. :rtype: requests.Response """ - api_path = '/v1/sys/seal' + api_path = "/v1/sys/seal" return self._adapter.put( url=api_path, ) @@ -68,14 +67,14 @@ def submit_unseal_key(self, key=None, reset=False, migrate=False): """ params = { - 'migrate': migrate, + "migrate": migrate, } if not reset and key is not None: - params['key'] = key + params["key"] = key elif reset: - params['reset'] = reset + params["reset"] = reset - api_path = '/v1/sys/unseal' + api_path = "/v1/sys/unseal" return self._adapter.put( url=api_path, json=params, @@ -99,7 +98,7 @@ def submit_unseal_keys(self, keys, migrate=False): key=key, migrate=migrate, ) - if not result['sealed']: + if not result["sealed"]: break return result diff --git a/hvac/api/system_backend/wrapping.py b/hvac/api/system_backend/wrapping.py index da1b212c4..142561c1a 100644 --- a/hvac/api/system_backend/wrapping.py +++ b/hvac/api/system_backend/wrapping.py @@ -2,7 +2,6 @@ class Wrapping(SystemBackendMixin): - def unwrap(self, token=None): """Return the original response inside the given wrapping token. @@ -21,9 +20,9 @@ def unwrap(self, token=None): """ params = {} if token is not None: - params['token'] = token + params["token"] = token - api_path = '/v1/sys/wrapping/unwrap' + api_path = "/v1/sys/wrapping/unwrap" return self._adapter.post( url=api_path, json=params, diff --git a/hvac/api/vault_api_category.py b/hvac/api/vault_api_category.py index 0686633cb..ad63f6a7a 100644 --- a/hvac/api/vault_api_category.py +++ b/hvac/api/vault_api_category.py @@ -9,6 +9,7 @@ class VaultApiCategory(VaultApiBase): """Base class for API categories.""" + __metaclass__ = ABCMeta def __init__(self, adapter): @@ -39,7 +40,9 @@ def __getattr__(self, item): private_attr_name = self.get_private_attr_name(item) return getattr(self, private_attr_name) if item in [u.lower() for u in self.unimplemented_classes]: - raise NotImplementedError('"%s" auth method class not currently implemented.' % item) + raise NotImplementedError( + '"%s" auth method class not currently implemented.' % item + ) raise AttributeError @property @@ -92,5 +95,5 @@ def get_private_attr_name(class_name): :return: The private attribute label for the provided class. :rtype: str """ - private_attr_name = '_{class_name}'.format(class_name=class_name) + private_attr_name = "_{class_name}".format(class_name=class_name) return private_attr_name diff --git a/hvac/aws_utils.py b/hvac/aws_utils.py index 9948b0c38..ef5cea9cb 100644 --- a/hvac/aws_utils.py +++ b/hvac/aws_utils.py @@ -5,43 +5,55 @@ class SigV4Auth(object): - def __init__(self, access_key, secret_key, session_token=None, region='us-east-1'): + def __init__(self, access_key, secret_key, session_token=None, region="us-east-1"): self.access_key = access_key self.secret_key = secret_key self.session_token = session_token self.region = region def add_auth(self, request): - timestamp = datetime.utcnow().strftime('%Y%m%dT%H%M%SZ') - request.headers['X-Amz-Date'] = timestamp + timestamp = datetime.utcnow().strftime("%Y%m%dT%H%M%SZ") + request.headers["X-Amz-Date"] = timestamp if self.session_token: - request.headers['X-Amz-Security-Token'] = self.session_token + request.headers["X-Amz-Security-Token"] = self.session_token # https://docs.aws.amazon.com/general/latest/gr/sigv4-create-canonical-request.html - canonical_headers = ''.join('{0}:{1}\n'.format(k.lower(), request.headers[k]) for k in sorted(request.headers)) - signed_headers = ';'.join(k.lower() for k in sorted(request.headers)) - payload_hash = sha256(request.body.encode('utf-8')).hexdigest() - canonical_request = '\n'.join([request.method, '/', '', canonical_headers, signed_headers, payload_hash]) + canonical_headers = "".join( + "{0}:{1}\n".format(k.lower(), request.headers[k]) + for k in sorted(request.headers) + ) + signed_headers = ";".join(k.lower() for k in sorted(request.headers)) + payload_hash = sha256(request.body.encode("utf-8")).hexdigest() + canonical_request = "\n".join( + [request.method, "/", "", canonical_headers, signed_headers, payload_hash] + ) # https://docs.aws.amazon.com/general/latest/gr/sigv4-create-string-to-sign.html - algorithm = 'AWS4-HMAC-SHA256' - credential_scope = '/'.join([timestamp[0:8], self.region, 'sts', 'aws4_request']) - canonical_request_hash = sha256(canonical_request.encode('utf-8')).hexdigest() - string_to_sign = '\n'.join([algorithm, timestamp, credential_scope, canonical_request_hash]) + algorithm = "AWS4-HMAC-SHA256" + credential_scope = "/".join( + [timestamp[0:8], self.region, "sts", "aws4_request"] + ) + canonical_request_hash = sha256(canonical_request.encode("utf-8")).hexdigest() + string_to_sign = "\n".join( + [algorithm, timestamp, credential_scope, canonical_request_hash] + ) # https://docs.aws.amazon.com/general/latest/gr/sigv4-calculate-signature.html - key = 'AWS4{0}'.format(self.secret_key).encode('utf-8') - key = hmac.new(key, timestamp[0:8].encode('utf-8'), sha256).digest() - key = hmac.new(key, self.region.encode('utf-8'), sha256).digest() - key = hmac.new(key, 'sts'.encode('utf-8'), sha256).digest() - key = hmac.new(key, 'aws4_request'.encode('utf-8'), sha256).digest() - signature = hmac.new(key, string_to_sign.encode('utf-8'), sha256).hexdigest() + key = "AWS4{0}".format(self.secret_key).encode("utf-8") + key = hmac.new(key, timestamp[0:8].encode("utf-8"), sha256).digest() + key = hmac.new(key, self.region.encode("utf-8"), sha256).digest() + key = hmac.new(key, "sts".encode("utf-8"), sha256).digest() + key = hmac.new(key, "aws4_request".encode("utf-8"), sha256).digest() + signature = hmac.new(key, string_to_sign.encode("utf-8"), sha256).hexdigest() # https://docs.aws.amazon.com/general/latest/gr/sigv4-add-signature-to-request.html - authorization = '{0} Credential={1}/{2}, SignedHeaders={3}, Signature={4}'.format( - algorithm, self.access_key, credential_scope, signed_headers, signature) - request.headers['Authorization'] = authorization + authorization = ( + "{0} Credential={1}/{2}, SignedHeaders={3}, Signature={4}".format( + algorithm, self.access_key, credential_scope, signed_headers, signature + ) + ) + request.headers["Authorization"] = authorization def generate_sigv4_auth_request(header_value=None): @@ -56,14 +68,17 @@ def generate_sigv4_auth_request(header_value=None): :rtype: requests.PreparedRequest """ request = requests.Request( - method='POST', - url='https://sts.amazonaws.com/', - headers={'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8', 'Host': 'sts.amazonaws.com'}, - data='Action=GetCallerIdentity&Version=2011-06-15', + method="POST", + url="https://sts.amazonaws.com/", + headers={ + "Content-Type": "application/x-www-form-urlencoded; charset=utf-8", + "Host": "sts.amazonaws.com", + }, + data="Action=GetCallerIdentity&Version=2011-06-15", ) if header_value: - request.headers['X-Vault-AWS-IAM-Server-ID'] = header_value + request.headers["X-Vault-AWS-IAM-Server-ID"] = header_value prepared_request = request.prepare() return prepared_request diff --git a/hvac/constants/approle.py b/hvac/constants/approle.py index 4722b8318..7cf09fd00 100644 --- a/hvac/constants/approle.py +++ b/hvac/constants/approle.py @@ -2,5 +2,11 @@ # -*- coding: utf-8 -*- """Constants related to the APPROLE auth method.""" -DEFAULT_MOUNT_POINT = 'approle' -ALLOWED_TOKEN_TYPES = ['service', 'batch', 'default', 'default-service', 'default-batch'] +DEFAULT_MOUNT_POINT = "approle" +ALLOWED_TOKEN_TYPES = [ + "service", + "batch", + "default", + "default-service", + "default-batch", +] diff --git a/hvac/constants/aws.py b/hvac/constants/aws.py index 2ff49106d..dc46040ae 100644 --- a/hvac/constants/aws.py +++ b/hvac/constants/aws.py @@ -2,8 +2,8 @@ # -*- coding: utf-8 -*- """Constants related to the AWS auth method and/or secrets engine.""" -DEFAULT_MOUNT_POINT = 'aws' -ALLOWED_CREDS_ENDPOINTS = ['creds', 'sts'] -ALLOWED_CREDS_TYPES = ['iam_user', 'assumed_role', 'federation_token'] -ALLOWED_IAM_ALIAS_TYPES = ['role_id', 'unique_id', 'full_arn'] -ALLOWED_EC2_ALIAS_TYPES = ['role_id', 'instance_id', 'image_id'] +DEFAULT_MOUNT_POINT = "aws" +ALLOWED_CREDS_ENDPOINTS = ["creds", "sts"] +ALLOWED_CREDS_TYPES = ["iam_user", "assumed_role", "federation_token"] +ALLOWED_IAM_ALIAS_TYPES = ["role_id", "unique_id", "full_arn"] +ALLOWED_EC2_ALIAS_TYPES = ["role_id", "instance_id", "image_id"] diff --git a/hvac/constants/azure.py b/hvac/constants/azure.py index 2f8defc1f..45f832645 100644 --- a/hvac/constants/azure.py +++ b/hvac/constants/azure.py @@ -3,8 +3,8 @@ """Constants related to the Azure auth method and/or secrets engine.""" VALID_ENVIRONMENTS = [ - 'AzurePublicCloud', - 'AzureUSGovernmentCloud', - 'AzureChinaCloud', - 'AzureGermanCloud', + "AzurePublicCloud", + "AzureUSGovernmentCloud", + "AzureChinaCloud", + "AzureGermanCloud", ] diff --git a/hvac/constants/client.py b/hvac/constants/client.py index ee61c0c12..ae5b3e583 100644 --- a/hvac/constants/client.py +++ b/hvac/constants/client.py @@ -2,23 +2,29 @@ # -*- coding: utf-8 -*- """Constants related to the hvac.Client class.""" +from os import getenv + DEPRECATED_PROPERTIES = { - 'github': dict( - to_be_removed_in_version='0.9.0', - client_property='auth', + "github": dict( + to_be_removed_in_version="0.9.0", + client_property="auth", ), - 'ldap': dict( - to_be_removed_in_version='0.9.0', - client_property='auth', + "ldap": dict( + to_be_removed_in_version="0.9.0", + client_property="auth", ), - 'mfa': dict( - to_be_removed_in_version='0.9.0', - client_property='auth', + "mfa": dict( + to_be_removed_in_version="0.9.0", + client_property="auth", ), - 'kv': dict( - to_be_removed_in_version='0.9.0', - client_property='secrets', + "kv": dict( + to_be_removed_in_version="0.9.0", + client_property="secrets", ), } -DEFAULT_URL = 'http://localhost:8200' +DEFAULT_URL = "http://localhost:8200" +VAULT_CACERT = getenv("VAULT_CACERT") +VAULT_CAPATH = getenv("VAULT_CAPATH") +VAULT_CLIENT_CERT = getenv("VAULT_CLIENT_CERT") +VAULT_CLIENT_KEY = getenv("VAULT_CLIENT_KEY") diff --git a/hvac/constants/gcp.py b/hvac/constants/gcp.py index ff8ee5da4..1b6b3d914 100644 --- a/hvac/constants/gcp.py +++ b/hvac/constants/gcp.py @@ -2,17 +2,17 @@ # -*- coding: utf-8 -*- """Constants related to the GCP auth method and/or secrets engine.""" -DEFAULT_MOUNT_POINT = 'gcp' -ALLOWED_ROLE_TYPES = ['iam', 'gce'] -ALLOWED_SECRETS_TYPES = ['access_token', 'service_account_key'] +DEFAULT_MOUNT_POINT = "gcp" +ALLOWED_ROLE_TYPES = ["iam", "gce"] +ALLOWED_SECRETS_TYPES = ["access_token", "service_account_key"] SERVICE_ACCOUNT_KEY_ALGORITHMS = [ - 'KEY_ALG_UNSPECIFIED', - 'KEY_ALG_RSA_1024', - 'KEY_ALG_RSA_2048', + "KEY_ALG_UNSPECIFIED", + "KEY_ALG_RSA_1024", + "KEY_ALG_RSA_2048", ] SERVICE_ACCOUNT_KEY_TYPES = [ - 'TYPE_UNSPECIFIED', - 'TYPE_PKCS12_FILE', - 'TYPE_GOOGLE_CREDENTIALS_FILE', + "TYPE_UNSPECIFIED", + "TYPE_PKCS12_FILE", + "TYPE_GOOGLE_CREDENTIALS_FILE", ] -GCP_CERTS_ENDPOINT = 'https://www.googleapis.com/oauth2/v3/certs' +GCP_CERTS_ENDPOINT = "https://www.googleapis.com/oauth2/v3/certs" diff --git a/hvac/constants/identity.py b/hvac/constants/identity.py index 2926bff21..33ba3cf23 100644 --- a/hvac/constants/identity.py +++ b/hvac/constants/identity.py @@ -3,6 +3,6 @@ """Constants related to the Identity secrets engine.""" ALLOWED_GROUP_TYPES = [ - 'internal', - 'external', + "internal", + "external", ] diff --git a/hvac/constants/transit.py b/hvac/constants/transit.py index a1d9af3c5..17f410a8d 100644 --- a/hvac/constants/transit.py +++ b/hvac/constants/transit.py @@ -3,52 +3,45 @@ """Constants related to the Transit secrets engine.""" ALLOWED_KEY_TYPES = [ - 'aes256-gcm96', - 'chacha20-poly1305', - 'ed25519', - 'ecdsa-p256', - 'ecdsa-p384', - 'ecdsa-p521', - 'rsa-2048', - 'rsa-3072', - 'rsa-4096', + "aes256-gcm96", + "chacha20-poly1305", + "ed25519", + "ecdsa-p256", + "ecdsa-p384", + "ecdsa-p521", + "rsa-2048", + "rsa-3072", + "rsa-4096", ] ALLOWED_EXPORT_KEY_TYPES = [ - 'encryption-key', - 'signing-key', - 'hmac-key', + "encryption-key", + "signing-key", + "hmac-key", ] ALLOWED_DATA_KEY_TYPES = [ - 'plaintext', - 'wrapped', + "plaintext", + "wrapped", ] -ALLOWED_DATA_KEY_BITS = [ - 128, - 256, - 512 -] +ALLOWED_DATA_KEY_BITS = [128, 256, 512] ALLOWED_HASH_DATA_ALGORITHMS = [ - 'sha2-224', - 'sha2-256', - 'sha2-384', - 'sha2-512', + "sha2-224", + "sha2-256", + "sha2-384", + "sha2-512", ] -ALLOWED_HASH_DATA_FORMATS = [ - 'hex', - 'base64' -] +ALLOWED_HASH_DATA_FORMATS = ["hex", "base64"] ALLOWED_SIGNATURE_ALGORITHMS = [ - 'pss', - 'pkcs1v15', + "pss", + "pkcs1v15", ] ALLOWED_MARSHALING_ALGORITHMS = [ - 'asn1', - 'jws', + "asn1", + "jws", ] diff --git a/hvac/exceptions.py b/hvac/exceptions.py index 8014be584..7ca9b252c 100644 --- a/hvac/exceptions.py +++ b/hvac/exceptions.py @@ -1,7 +1,7 @@ class VaultError(Exception): def __init__(self, message=None, errors=None, method=None, url=None): if errors: - message = ', '.join(errors) + message = ", ".join(errors) self.errors = errors self.method = method diff --git a/hvac/utils.py b/hvac/utils.py index 38e50f341..c9cf6208c 100644 --- a/hvac/utils.py +++ b/hvac/utils.py @@ -42,11 +42,17 @@ def raise_for_error(method, url, status_code, message=None, errors=None): elif status_code == 404: raise exceptions.InvalidPath(message, errors=errors, method=method, url=url) elif status_code == 429: - raise exceptions.RateLimitExceeded(message, errors=errors, method=method, url=url) + raise exceptions.RateLimitExceeded( + message, errors=errors, method=method, url=url + ) elif status_code == 500: - raise exceptions.InternalServerError(message, errors=errors, method=method, url=url) + raise exceptions.InternalServerError( + message, errors=errors, method=method, url=url + ) elif status_code == 501: - raise exceptions.VaultNotInitialized(message, errors=errors, method=method, url=url) + raise exceptions.VaultNotInitialized( + message, errors=errors, method=method, url=url + ) elif status_code == 502: raise exceptions.BadGateway(message, errors=errors, method=method, url=url) elif status_code == 503: @@ -55,7 +61,9 @@ def raise_for_error(method, url, status_code, message=None, errors=None): raise exceptions.UnexpectedError(message or errors, method=method, url=url) -def generate_method_deprecation_message(to_be_removed_in_version, old_method_name, method_name=None, module_name=None): +def generate_method_deprecation_message( + to_be_removed_in_version, old_method_name, method_name=None, module_name=None +): """Generate a message to be used when warning about the use of deprecated methods. :param to_be_removed_in_version: Version of this module the deprecated method will be removed in. @@ -82,8 +90,9 @@ def generate_method_deprecation_message(to_be_removed_in_version, old_method_nam return message -def generate_property_deprecation_message(to_be_removed_in_version, old_name, new_name, new_attribute, - module_name='Client'): +def generate_property_deprecation_message( + to_be_removed_in_version, old_name, new_name, new_attribute, module_name="Client" +): """Generate a message to be used when warning about the use of deprecated properties. :param to_be_removed_in_version: Version of this module the deprecated property will be removed in. @@ -126,25 +135,31 @@ def getattr_with_deprecated_properties(obj, item, deprecated_properties): """ if item in deprecated_properties: deprecation_message = generate_property_deprecation_message( - to_be_removed_in_version=deprecated_properties[item]['to_be_removed_in_version'], + to_be_removed_in_version=deprecated_properties[item][ + "to_be_removed_in_version" + ], old_name=item, - new_name=deprecated_properties[item].get('new_property', item), - new_attribute=deprecated_properties[item]['client_property'], + new_name=deprecated_properties[item].get("new_property", item), + new_attribute=deprecated_properties[item]["client_property"], ) - warnings.simplefilter('always', DeprecationWarning) + warnings.simplefilter("always", DeprecationWarning) warnings.warn( message=deprecation_message, category=DeprecationWarning, stacklevel=2, ) - warnings.simplefilter('default', DeprecationWarning) - client_property = getattr(obj, deprecated_properties[item]['client_property']) - return getattr(client_property, deprecated_properties[item].get('new_property', item)) + warnings.simplefilter("default", DeprecationWarning) + client_property = getattr(obj, deprecated_properties[item]["client_property"]) + return getattr( + client_property, deprecated_properties[item].get("new_property", item) + ) - raise AttributeError("'{class_name}' has no attribute '{item}'".format( - class_name=obj.__class__.__name__, - item=item, - )) + raise AttributeError( + "'{class_name}' has no attribute '{item}'".format( + class_name=obj.__class__.__name__, + item=item, + ) + ) def deprecated_method(to_be_removed_in_version, new_method=None): @@ -159,43 +174,53 @@ def deprecated_method(to_be_removed_in_version, new_method=None): :return: Wrapped function that includes a deprecation warning and update docstrings from the replacement method. :rtype: types.FunctionType """ + def decorator(method): + if new_method is not None: + new_method_name = new_method.__name__ + new_module_name = inspect.getmodule(new_method).__name__ + else: + new_method_name, new_module_name = (None, None) + deprecation_message = generate_method_deprecation_message( to_be_removed_in_version=to_be_removed_in_version, old_method_name=method.__name__, - method_name=new_method.__name__, - module_name=inspect.getmodule(new_method).__name__, + method_name=new_method_name, + module_name=new_module_name, ) @functools.wraps(method) def new_func(*args, **kwargs): - warnings.simplefilter('always', DeprecationWarning) # turn off filter + warnings.simplefilter("always", DeprecationWarning) # turn off filter warnings.warn( message=deprecation_message, category=DeprecationWarning, stacklevel=2, ) - warnings.simplefilter('default', DeprecationWarning) # reset filter + warnings.simplefilter("default", DeprecationWarning) # reset filter return method(*args, **kwargs) if new_method: # Here we copy the docstring from the specified replacement method (i.e., the method to be used in place of # the one we're marking as deprecated) where available to set within the deprecated method's docstring. # If the "new" method has no docstring, we use a value of "N/A". - docstring_copy = new_method.__doc__ if new_method.__doc__ is not None else "N/A" + docstring_copy = ( + new_method.__doc__ if new_method.__doc__ is not None else "N/A" + ) if new_method.__doc__ is not None: new_func.__doc__ = """\ {message} Docstring content from this method's replacement copied below: {docstring_copy} """.format( - message=deprecation_message, - docstring_copy=dedent(docstring_copy), - ) + message=deprecation_message, + docstring_copy=dedent(docstring_copy), + ) else: new_func.__doc__ = deprecation_message return new_func + return decorator @@ -212,14 +237,18 @@ def validate_list_of_strings_param(param_name, param_argument): if param_argument is None: param_argument = [] if isinstance(param_argument, str): - param_argument = param_argument.split(',') - if not isinstance(param_argument, list) or not all(isinstance(p, str) for p in param_argument): + param_argument = param_argument.split(",") + if not isinstance(param_argument, list) or not all( + isinstance(p, str) for p in param_argument + ): error_msg = 'unsupported {param} argument provided "{arg}" ({arg_type}), required type: List[str]' - raise exceptions.ParamValidationError(error_msg.format( - param=param_name, - arg=param_argument, - arg_type=type(param_argument), - )) + raise exceptions.ParamValidationError( + error_msg.format( + param=param_name, + arg=param_argument, + arg_type=type(param_argument), + ) + ) def list_to_comma_delimited(list_param): @@ -232,7 +261,7 @@ def list_to_comma_delimited(list_param): """ if list_param is None: list_param = [] - return ','.join(list_param) + return ",".join(list_param) def get_token_from_env(): @@ -241,11 +270,11 @@ def get_token_from_env(): :return: The vault token if set, else None :rtype: str | None """ - token = os.getenv('VAULT_TOKEN') + token = os.getenv("VAULT_TOKEN") if not token: - token_file_path = os.path.expanduser('~/.vault-token') + token_file_path = os.path.expanduser("~/.vault-token") if os.path.exists(token_file_path): - with open(token_file_path, 'r') as f_in: + with open(token_file_path, "r") as f_in: token = f_in.read().strip() if not token: @@ -265,7 +294,7 @@ def comma_delimited_to_list(list_param): if isinstance(list_param, list): return list_param if isinstance(list_param, str): - return list_param.split(',') + return list_param.split(",") else: return [] @@ -283,16 +312,21 @@ def validate_pem_format(param_name, param_argument): def _check_pem(arg): arg = arg.strip() - if not arg.startswith('-----BEGIN CERTIFICATE-----') \ - or not arg.endswith('-----END CERTIFICATE-----'): + if not arg.startswith("-----BEGIN CERTIFICATE-----") or not arg.endswith( + "-----END CERTIFICATE-----" + ): return False return True if isinstance(param_argument, str): param_argument = [param_argument] - if not isinstance(param_argument, list) or not all(_check_pem(p) for p in param_argument): - error_msg = 'unsupported {param} public key / certificate format, required type: PEM' + if not isinstance(param_argument, list) or not all( + _check_pem(p) for p in param_argument + ): + error_msg = ( + "unsupported {param} public key / certificate format, required type: PEM" + ) raise exceptions.ParamValidationError(error_msg.format(param=param_name)) @@ -305,11 +339,7 @@ def remove_nones(params): :rtype: dict """ - return { - key: value - for key, value in params.items() - if value is not None - } + return {key: value for key, value in params.items() if value is not None} def format_url(format_str, *args, **kwargs): @@ -336,7 +366,4 @@ def url_quote(maybe_str): escaped_args = [url_quote(value) for value in args] escaped_kwargs = {key: url_quote(value) for key, value in kwargs.items()} - return format_str.format( - *escaped_args, - **escaped_kwargs - ) + return format_str.format(*escaped_args, **escaped_kwargs) diff --git a/hvac/v1/__init__.py b/hvac/v1/__init__.py index a3c40d327..efbbc9b24 100644 --- a/hvac/v1/__init__.py +++ b/hvac/v1/__init__.py @@ -4,12 +4,20 @@ import os from base64 import b64encode -from hvac import aws_utils, exceptions, adapters, utils, api -from hvac.constants.client import DEPRECATED_PROPERTIES, DEFAULT_URL +from hvac import adapters, api, aws_utils, exceptions, utils +from hvac.constants.client import ( + DEFAULT_URL, + DEPRECATED_PROPERTIES, + VAULT_CACERT, + VAULT_CAPATH, + VAULT_CLIENT_CERT, + VAULT_CLIENT_KEY, +) from hvac.utils import generate_property_deprecation_message try: import hcl + has_hcl_parser = True except ImportError: has_hcl_parser = False @@ -18,10 +26,20 @@ class Client(object): """The hvac Client class for HashiCorp's Vault.""" - def __init__(self, url=None, token=None, - cert=None, verify=True, timeout=30, proxies=None, - allow_redirects=True, session=None, adapter=adapters.JSONAdapter, - namespace=None, **kwargs): + def __init__( + self, + url=None, + token=None, + cert=None, + verify=True, + timeout=30, + proxies=None, + allow_redirects=True, + session=None, + adapter=adapters.JSONAdapter, + namespace=None, + **kwargs + ): """Creates a new hvac client instance. :param url: Base URL for the Vault instance being addressed. @@ -53,7 +71,27 @@ def __init__(self, url=None, token=None, """ token = token if token is not None else utils.get_token_from_env() - url = url if url else os.getenv('VAULT_ADDR', DEFAULT_URL) + url = url if url else os.getenv("VAULT_ADDR", DEFAULT_URL) + + if cert is not None and VAULT_CLIENT_CERT: + cert = "\n".join( + [ + VAULT_CLIENT_CERT, + VAULT_CLIENT_KEY, + ] + ) + + # Consider related CA env vars _only if_ no argument is passed in under the + # `verify` parameter. + if verify is not None: + # Reference: https://www.vaultproject.io/docs/commands#vault_cacert + # Note: "[VAULT_CACERT] takes precedence over VAULT_CAPATH." and thus we + # check for VAULT_CAPATH _first_. + if VAULT_CAPATH: + verify = VAULT_CAPATH + if VAULT_CACERT: + verify = VAULT_CACERT + self._adapter = adapter( base_uri=url, token=token, @@ -74,9 +112,7 @@ def __init__(self, url=None, token=None, def __getattr__(self, name): return utils.getattr_with_deprecated_properties( - obj=self, - item=name, - deprecated_properties=DEPRECATED_PROPERTIES + obj=self, item=name, deprecated_properties=DEPRECATED_PROPERTIES ) @property @@ -157,7 +193,7 @@ def key_status(self): :return: Information about the current encryption key used by Vault. :rtype: dict """ - return self.sys.get_encryption_key_status()['data'] + return self.sys.get_encryption_key_status()["data"] @property def rekey_status(self): @@ -197,7 +233,7 @@ def read(self, path, wrap_ttl=None): :rtype: """ try: - return self._adapter.get('/v1/{0}'.format(path), wrap_ttl=wrap_ttl) + return self._adapter.get("/v1/{0}".format(path), wrap_ttl=wrap_ttl) except exceptions.InvalidPath: return None @@ -210,10 +246,8 @@ def list(self, path): :rtype: """ try: - payload = { - 'list': True - } - return self._adapter.get('/v1/{0}'.format(path), params=payload) + payload = {"list": True} + return self._adapter.get("/v1/{0}".format(path), params=payload) except exceptions.InvalidPath: return None @@ -229,7 +263,9 @@ def write(self, path, wrap_ttl=None, **kwargs): :return: :rtype: """ - return self._adapter.post('/v1/{0}'.format(path), json=kwargs, wrap_ttl=wrap_ttl) + return self._adapter.post( + "/v1/{0}".format(path), json=kwargs, wrap_ttl=wrap_ttl + ) def delete(self, path): """DELETE / @@ -239,7 +275,7 @@ def delete(self, path): :return: :rtype: """ - self._adapter.delete('/v1/{0}'.format(path)) + self._adapter.delete("/v1/{0}".format(path)) def get_policy(self, name, parse=False): """Retrieve the policy body for the named policy. @@ -252,30 +288,52 @@ def get_policy(self, name, parse=False): :rtype: str | dict """ try: - policy = self.sys.read_policy(name=name)['data']['rules'] + policy = self.sys.read_policy(name=name)["data"]["rules"] except exceptions.InvalidPath: return None if parse: if not has_hcl_parser: - raise ImportError('pyhcl is required for policy parsing') + raise ImportError("pyhcl is required for policy parsing") policy = hcl.loads(policy) return policy + @utils.deprecated_method( + to_be_removed_in_version="1.0.0", + new_method=api.auth_methods.Token.revoke_self, + ) def revoke_self_token(self): """PUT /auth/token/revoke-self :return: :rtype: """ - self._adapter.put('/v1/auth/token/revoke-self') + self._adapter.put("/v1/auth/token/revoke-self") - def create_token(self, role=None, token_id=None, policies=None, meta=None, - no_parent=False, lease=None, display_name=None, - num_uses=None, no_default_policy=False, - ttl=None, orphan=False, wrap_ttl=None, renewable=None, - explicit_max_ttl=None, period=None, token_type=None): + @utils.deprecated_method( + to_be_removed_in_version="1.0.0", + new_method=api.auth_methods.Token.create, + ) + def create_token( + self, + role=None, + token_id=None, + policies=None, + meta=None, + no_parent=False, + lease=None, + display_name=None, + num_uses=None, + no_default_policy=False, + ttl=None, + orphan=False, + wrap_ttl=None, + renewable=None, + explicit_max_ttl=None, + period=None, + token_type=None, + ): """POST /auth/token/create POST /auth/token/create/ @@ -318,36 +376,42 @@ def create_token(self, role=None, token_id=None, policies=None, meta=None, :rtype: """ params = { - 'id': token_id, - 'policies': policies, - 'meta': meta, - 'no_parent': no_parent, - 'display_name': display_name, - 'num_uses': num_uses, - 'no_default_policy': no_default_policy, - 'renewable': renewable + "id": token_id, + "policies": policies, + "meta": meta, + "no_parent": no_parent, + "display_name": display_name, + "num_uses": num_uses, + "no_default_policy": no_default_policy, + "renewable": renewable, } if lease: - params['lease'] = lease + params["lease"] = lease else: - params['ttl'] = ttl - params['explicit_max_ttl'] = explicit_max_ttl + params["ttl"] = ttl + params["explicit_max_ttl"] = explicit_max_ttl if explicit_max_ttl: - params['explicit_max_ttl'] = explicit_max_ttl + params["explicit_max_ttl"] = explicit_max_ttl if period: - params['period'] = period + params["period"] = period if token_type: - params['type'] = token_type + params["type"] = token_type if orphan: - return self._adapter.post('/v1/auth/token/create-orphan', json=params, wrap_ttl=wrap_ttl) + return self._adapter.post( + "/v1/auth/token/create-orphan", json=params, wrap_ttl=wrap_ttl + ) elif role: - return self._adapter.post('/v1/auth/token/create/{0}'.format(role), json=params, wrap_ttl=wrap_ttl) + return self._adapter.post( + "/v1/auth/token/create/{0}".format(role), json=params, wrap_ttl=wrap_ttl + ) else: - return self._adapter.post('/v1/auth/token/create', json=params, wrap_ttl=wrap_ttl) + return self._adapter.post( + "/v1/auth/token/create", json=params, wrap_ttl=wrap_ttl + ) def lookup_token(self, token=None, accessor=False, wrap_ttl=None): """GET /auth/token/lookup/ @@ -366,20 +430,20 @@ def lookup_token(self, token=None, accessor=False, wrap_ttl=None): :rtype: """ token_param = { - 'token': token, + "token": token, } accessor_param = { - 'accessor': token, + "accessor": token, } if token: if accessor: - path = '/v1/auth/token/lookup-accessor' + path = "/v1/auth/token/lookup-accessor" return self._adapter.post(path, json=accessor_param, wrap_ttl=wrap_ttl) else: - path = '/v1/auth/token/lookup' + path = "/v1/auth/token/lookup" return self._adapter.post(path, json=token_param) else: - path = '/v1/auth/token/lookup-self' + path = "/v1/auth/token/lookup-self" return self._adapter.get(path, wrap_ttl=wrap_ttl) def revoke_token(self, token, orphan=False, accessor=False): @@ -402,15 +466,18 @@ def revoke_token(self, token, orphan=False, accessor=False): msg = "revoke_token does not support 'orphan' and 'accessor' flags together" raise exceptions.InvalidRequest(msg) elif accessor: - params = {'accessor': token} - self._adapter.post('/v1/auth/token/revoke-accessor', json=params) + params = {"accessor": token} + self._adapter.post("/v1/auth/token/revoke-accessor", json=params) elif orphan: - params = {'token': token} - self._adapter.post('/v1/auth/token/revoke-orphan', json=params) + params = {"token": token} + self._adapter.post("/v1/auth/token/revoke-orphan", json=params) else: - params = {'token': token} - self._adapter.post('/v1/auth/token/revoke', json=params) + params = {"token": token} + self._adapter.post("/v1/auth/token/revoke", json=params) + @utils.deprecated_method( + to_be_removed_in_version="1.0.0", + ) def revoke_token_prefix(self, prefix): """POST /auth/token/revoke-prefix/ @@ -419,7 +486,7 @@ def revoke_token_prefix(self, prefix): :return: :rtype: """ - self._adapter.post('/v1/auth/token/revoke-prefix/{0}'.format(prefix)) + self._adapter.post("/v1/auth/token/revoke-prefix/{0}".format(prefix)) def renew_token(self, token=None, increment=None, wrap_ttl=None): """POST /auth/token/renew @@ -438,16 +505,27 @@ def renew_token(self, token=None, increment=None, wrap_ttl=None): For calls expecting to hit the renew-self endpoint please use the "renew_self_token" method instead """ params = { - 'increment': increment, + "increment": increment, } if token is not None: - params['token'] = token - return self._adapter.post('/v1/auth/token/renew', json=params, wrap_ttl=wrap_ttl) + params["token"] = token + return self._adapter.post( + "/v1/auth/token/renew", json=params, wrap_ttl=wrap_ttl + ) else: - generate_property_deprecation_message("1.0.0", "renew_token() without token param", "renew_self_token() without token param", "renew_self_token") + generate_property_deprecation_message( + "1.0.0", + "renew_token() without token param", + "renew_self_token() without token param", + "renew_self_token", + ) return self.renew_self_token(increment=increment, wrap_ttl=wrap_ttl) + @utils.deprecated_method( + to_be_removed_in_version="1.0.0", + new_method=api.auth_methods.Token.renew_self, + ) def renew_self_token(self, increment=None, wrap_ttl=None): """ POST /auth/token/renew-self @@ -460,15 +538,28 @@ def renew_self_token(self, increment=None, wrap_ttl=None): :rtype: """ params = { - 'increment': increment, + "increment": increment, } - return self._adapter.post('/v1/auth/token/renew-self', json=params, wrap_ttl=wrap_ttl) + return self._adapter.post( + "/v1/auth/token/renew-self", json=params, wrap_ttl=wrap_ttl + ) - def create_token_role(self, role, - allowed_policies=None, disallowed_policies=None, - orphan=None, period=None, renewable=None, - path_suffix=None, explicit_max_ttl=None): + @utils.deprecated_method( + to_be_removed_in_version="1.0.0", + new_method=api.auth_methods.Token.create_or_update_role, + ) + def create_token_role( + self, + role, + allowed_policies=None, + disallowed_policies=None, + orphan=None, + period=None, + renewable=None, + path_suffix=None, + explicit_max_ttl=None, + ): """POST /auth/token/roles/ :param role: @@ -491,16 +582,20 @@ def create_token_role(self, role, :rtype: """ params = { - 'allowed_policies': allowed_policies, - 'disallowed_policies': disallowed_policies, - 'orphan': orphan, - 'period': period, - 'renewable': renewable, - 'path_suffix': path_suffix, - 'explicit_max_ttl': explicit_max_ttl + "allowed_policies": allowed_policies, + "disallowed_policies": disallowed_policies, + "orphan": orphan, + "period": period, + "renewable": renewable, + "path_suffix": path_suffix, + "explicit_max_ttl": explicit_max_ttl, } - return self._adapter.post('/v1/auth/token/roles/{0}'.format(role), json=params) + return self._adapter.post("/v1/auth/token/roles/{0}".format(role), json=params) + @utils.deprecated_method( + to_be_removed_in_version="1.0.0", + new_method=api.auth_methods.Token.read_role, + ) def token_role(self, role): """Returns the named token role. @@ -509,8 +604,12 @@ def token_role(self, role): :return: :rtype: """ - return self.read('auth/token/roles/{0}'.format(role)) + return self.read("auth/token/roles/{0}".format(role)) + @utils.deprecated_method( + to_be_removed_in_version="1.0.0", + new_method=api.auth_methods.Token.delete_role, + ) def delete_token_role(self, role): """Deletes the named token role. @@ -519,15 +618,19 @@ def delete_token_role(self, role): :return: :rtype: """ - return self.delete('auth/token/roles/{0}'.format(role)) + return self.delete("auth/token/roles/{0}".format(role)) + @utils.deprecated_method( + to_be_removed_in_version="1.0.0", + new_method=api.auth_methods.Token.list_roles, + ) def list_token_roles(self): """GET /auth/token/roles?list=true :return: :rtype: """ - return self.list('auth/token/roles') + return self.list("auth/token/roles") def logout(self, revoke_token=False): """Clears the token used for authentication, optionally revoking it before doing so. @@ -561,7 +664,8 @@ def is_authenticated(self): except exceptions.InvalidRequest: return False - def auth_app_id(self, app_id, user_id, mount_point='app-id', use_token=True): + @utils.deprecated_method(to_be_removed_in_version="1.0.0") + def auth_app_id(self, app_id, user_id, mount_point="app-id", use_token=True): """POST /auth//login :param app_id: @@ -576,17 +680,19 @@ def auth_app_id(self, app_id, user_id, mount_point='app-id', use_token=True): :rtype: """ params = { - 'app_id': app_id, - 'user_id': user_id, + "app_id": app_id, + "user_id": user_id, } - return self.login('/v1/auth/{0}/login'.format(mount_point), json=params, use_token=use_token) + return self.login( + "/v1/auth/{0}/login".format(mount_point), json=params, use_token=use_token + ) @utils.deprecated_method( - to_be_removed_in_version='0.13.0', + to_be_removed_in_version="0.13.0", new_method=api.auth_methods.Cert.login, ) - def auth_tls(self, mount_point='cert', use_token=True): + def auth_tls(self, mount_point="cert", use_token=True): """POST /auth//login :param mount_point: @@ -598,7 +704,13 @@ def auth_tls(self, mount_point='cert', use_token=True): """ return self.auth.cert.login(mount_point=mount_point, use_token=use_token) - def auth_userpass(self, username, password, mount_point='userpass', use_token=True, **kwargs): + @utils.deprecated_method( + to_be_removed_in_version="1.0.0", + new_method=api.auth_methods.Userpass.login, + ) + def auth_userpass( + self, username, password, mount_point="userpass", use_token=True, **kwargs + ): """POST /auth//login/ :param username: @@ -615,18 +727,32 @@ def auth_userpass(self, username, password, mount_point='userpass', use_token=Tr :rtype: """ params = { - 'password': password, + "password": password, } params.update(kwargs) - return self.login('/v1/auth/{0}/login/{1}'.format(mount_point, username), json=params, use_token=use_token) + return self.login( + "/v1/auth/{0}/login/{1}".format(mount_point, username), + json=params, + use_token=use_token, + ) @utils.deprecated_method( - to_be_removed_in_version='0.11.2', + to_be_removed_in_version="0.11.2", new_method=api.auth_methods.Aws.iam_login, ) - def auth_aws_iam(self, access_key, secret_key, session_token=None, header_value=None, mount_point='aws', role='', use_token=True, region='us-east-1'): + def auth_aws_iam( + self, + access_key, + secret_key, + session_token=None, + header_value=None, + mount_point="aws", + role="", + use_token=True, + region="us-east-1", + ): """POST /auth//login :param access_key: AWS IAM access key ID @@ -662,20 +788,24 @@ def auth_aws_iam(self, access_key, secret_key, session_token=None, header_value= # 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, + "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.login('/v1/auth/{0}/login'.format(mount_point), json=params, use_token=use_token) + return self.login( + "/v1/auth/{0}/login".format(mount_point), json=params, use_token=use_token + ) @utils.deprecated_method( - to_be_removed_in_version='0.11.2', + to_be_removed_in_version="0.11.2", new_method=api.auth_methods.Aws.ec2_login, ) - def auth_ec2(self, pkcs7, nonce=None, role=None, use_token=True, mount_point='aws-ec2'): + def auth_ec2( + self, pkcs7, nonce=None, role=None, use_token=True, mount_point="aws-ec2" + ): """POST /auth//login :param pkcs7: PKCS#7 version of an AWS Instance Identity Document from the EC2 Metadata Service. @@ -695,15 +825,23 @@ def auth_ec2(self, pkcs7, nonce=None, role=None, use_token=True, mount_point='aw :rtype: dict. """ - params = {'pkcs7': pkcs7} + params = {"pkcs7": pkcs7} if nonce: - params['nonce'] = nonce + params["nonce"] = nonce if role: - params['role'] = role + params["role"] = role - return self.login('/v1/auth/{0}/login'.format(mount_point), json=params, use_token=use_token) + return self.login( + "/v1/auth/{0}/login".format(mount_point), json=params, use_token=use_token + ) - def create_userpass(self, username, password, policies, mount_point='userpass', **kwargs): + @utils.deprecated_method( + to_be_removed_in_version="1.0.0", + new_method=api.auth_methods.Userpass.create_or_update_user, + ) + def create_userpass( + self, username, password, policies, mount_point="userpass", **kwargs + ): """POST /auth//users/ :param username: @@ -723,17 +861,20 @@ def create_userpass(self, username, password, policies, mount_point='userpass', # Users can have more than 1 policy. It is easier for the user to pass in the # policies as a list so if they do, we need to convert to a , delimited string. if isinstance(policies, (list, set, tuple)): - policies = ','.join(policies) + policies = ",".join(policies) - params = { - 'password': password, - 'policies': policies - } + params = {"password": password, "policies": policies} params.update(kwargs) - return self._adapter.post('/v1/auth/{}/users/{}'.format(mount_point, username), json=params) + return self._adapter.post( + "/v1/auth/{}/users/{}".format(mount_point, username), json=params + ) - def list_userpass(self, mount_point='userpass'): + @utils.deprecated_method( + to_be_removed_in_version="1.0.0", + new_method=api.auth_methods.Userpass.list_user, + ) + def list_userpass(self, mount_point="userpass"): """GET /auth//users?list=true :param mount_point: @@ -742,11 +883,17 @@ def list_userpass(self, mount_point='userpass'): :rtype: """ try: - return self._adapter.get('/v1/auth/{}/users'.format(mount_point), params={'list': True}) + return self._adapter.get( + "/v1/auth/{}/users".format(mount_point), params={"list": True} + ) except exceptions.InvalidPath: return None - def read_userpass(self, username, mount_point='userpass'): + @utils.deprecated_method( + to_be_removed_in_version="1.0.0", + new_method=api.auth_methods.Userpass.read_user, + ) + def read_userpass(self, username, mount_point="userpass"): """GET /auth//users/ :param username: @@ -756,9 +903,13 @@ def read_userpass(self, username, mount_point='userpass'): :return: :rtype: """ - return self._adapter.get('/v1/auth/{}/users/{}'.format(mount_point, username)) + return self._adapter.get("/v1/auth/{}/users/{}".format(mount_point, username)) - def update_userpass_policies(self, username, policies, mount_point='userpass'): + @utils.deprecated_method( + to_be_removed_in_version="1.0.0", + new_method=api.auth_methods.Userpass.create_or_update_user, + ) + def update_userpass_policies(self, username, policies, mount_point="userpass"): """POST /auth//users//policies :param username: @@ -773,15 +924,19 @@ def update_userpass_policies(self, username, policies, mount_point='userpass'): # userpass can have more than 1 policy. It is easier for the user to pass in the # policies as a list so if they do, we need to convert to a , delimited string. if isinstance(policies, (list, set, tuple)): - policies = ','.join(policies) + policies = ",".join(policies) - params = { - 'policies': policies - } + params = {"policies": policies} - return self._adapter.post('/v1/auth/{}/users/{}/policies'.format(mount_point, username), json=params) + return self._adapter.post( + "/v1/auth/{}/users/{}/policies".format(mount_point, username), json=params + ) - def update_userpass_password(self, username, password, mount_point='userpass'): + @utils.deprecated_method( + to_be_removed_in_version="1.0.0", + new_method=api.auth_methods.Userpass.update_password_on_user, + ) + def update_userpass_password(self, username, password, mount_point="userpass"): """POST /auth//users//password :param username: @@ -793,12 +948,16 @@ def update_userpass_password(self, username, password, mount_point='userpass'): :return: :rtype: """ - params = { - 'password': password - } - return self._adapter.post('/v1/auth/{}/users/{}/password'.format(mount_point, username), json=params) + params = {"password": password} + return self._adapter.post( + "/v1/auth/{}/users/{}/password".format(mount_point, username), json=params + ) - def delete_userpass(self, username, mount_point='userpass'): + @utils.deprecated_method( + to_be_removed_in_version="1.0.0", + new_method=api.auth_methods.Userpass.delete_user, + ) + def delete_userpass(self, username, mount_point="userpass"): """DELETE /auth//users/ :param username: @@ -808,9 +967,14 @@ def delete_userpass(self, username, mount_point='userpass'): :return: :rtype: """ - return self._adapter.delete('/v1/auth/{}/users/{}'.format(mount_point, username)) + return self._adapter.delete( + "/v1/auth/{}/users/{}".format(mount_point, username) + ) - def create_app_id(self, app_id, policies, display_name=None, mount_point='app-id', **kwargs): + @utils.deprecated_method(to_be_removed_in_version="1.0.0") + def create_app_id( + self, app_id, policies, display_name=None, mount_point="app-id", **kwargs + ): """POST /auth//map/app-id/ :param app_id: @@ -830,22 +994,23 @@ def create_app_id(self, app_id, policies, display_name=None, mount_point='app-id # app-id can have more than 1 policy. It is easier for the user to pass in the # policies as a list so if they do, we need to convert to a , delimited string. if isinstance(policies, (list, set, tuple)): - policies = ','.join(policies) + policies = ",".join(policies) - params = { - 'value': policies - } + params = {"value": policies} # Only use the display_name if it has a value. Made it a named param for user # convienence instead of leaving it as part of the kwargs if display_name: - params['display_name'] = display_name + params["display_name"] = display_name params.update(kwargs) - return self._adapter.post('/v1/auth/{}/map/app-id/{}'.format(mount_point, app_id), json=params) + return self._adapter.post( + "/v1/auth/{}/map/app-id/{}".format(mount_point, app_id), json=params + ) - def get_app_id(self, app_id, mount_point='app-id', wrap_ttl=None): + @utils.deprecated_method(to_be_removed_in_version="1.0.0") + def get_app_id(self, app_id, mount_point="app-id", wrap_ttl=None): """GET /auth//map/app-id/ :param app_id: @@ -857,10 +1022,11 @@ def get_app_id(self, app_id, mount_point='app-id', wrap_ttl=None): :return: :rtype: """ - path = '/v1/auth/{0}/map/app-id/{1}'.format(mount_point, app_id) + path = "/v1/auth/{0}/map/app-id/{1}".format(mount_point, app_id) return self._adapter.get(path, wrap_ttl=wrap_ttl) - def delete_app_id(self, app_id, mount_point='app-id'): + @utils.deprecated_method(to_be_removed_in_version="1.0.0") + def delete_app_id(self, app_id, mount_point="app-id"): """DELETE /auth//map/app-id/ :param app_id: @@ -870,9 +1036,14 @@ def delete_app_id(self, app_id, mount_point='app-id'): :return: :rtype: """ - return self._adapter.delete('/v1/auth/{0}/map/app-id/{1}'.format(mount_point, app_id)) + return self._adapter.delete( + "/v1/auth/{0}/map/app-id/{1}".format(mount_point, app_id) + ) - def create_user_id(self, user_id, app_id, cidr_block=None, mount_point='app-id', **kwargs): + @utils.deprecated_method(to_be_removed_in_version="1.0.0") + def create_user_id( + self, user_id, app_id, cidr_block=None, mount_point="app-id", **kwargs + ): """POST /auth//map/user-id/ :param user_id: @@ -892,22 +1063,23 @@ def create_user_id(self, user_id, app_id, cidr_block=None, mount_point='app-id', # user-id can be associated to more than 1 app-id (aka policy). It is easier for the user to # pass in the policies as a list so if they do, we need to convert to a , delimited string. if isinstance(app_id, (list, set, tuple)): - app_id = ','.join(app_id) + app_id = ",".join(app_id) - params = { - 'value': app_id - } + params = {"value": app_id} # Only use the cidr_block if it has a value. Made it a named param for user # convienence instead of leaving it as part of the kwargs if cidr_block: - params['cidr_block'] = cidr_block + params["cidr_block"] = cidr_block params.update(kwargs) - return self._adapter.post('/v1/auth/{}/map/user-id/{}'.format(mount_point, user_id), json=params) + return self._adapter.post( + "/v1/auth/{}/map/user-id/{}".format(mount_point, user_id), json=params + ) - def get_user_id(self, user_id, mount_point='app-id', wrap_ttl=None): + @utils.deprecated_method(to_be_removed_in_version="1.0.0") + def get_user_id(self, user_id, mount_point="app-id", wrap_ttl=None): """GET /auth//map/user-id/ :param user_id: @@ -919,10 +1091,11 @@ def get_user_id(self, user_id, mount_point='app-id', wrap_ttl=None): :return: :rtype: """ - path = '/v1/auth/{0}/map/user-id/{1}'.format(mount_point, user_id) + path = "/v1/auth/{0}/map/user-id/{1}".format(mount_point, user_id) return self._adapter.get(path, wrap_ttl=wrap_ttl) - def delete_user_id(self, user_id, mount_point='app-id'): + @utils.deprecated_method(to_be_removed_in_version="1.0.0") + def delete_user_id(self, user_id, mount_point="app-id"): """DELETE /auth//map/user-id/ :param user_id: @@ -932,13 +1105,17 @@ def delete_user_id(self, user_id, mount_point='app-id'): :return: :rtype: """ - return self._adapter.delete('/v1/auth/{0}/map/user-id/{1}'.format(mount_point, user_id)) + return self._adapter.delete( + "/v1/auth/{0}/map/user-id/{1}".format(mount_point, user_id) + ) @utils.deprecated_method( - to_be_removed_in_version='0.11.2', + to_be_removed_in_version="0.11.2", new_method=api.auth_methods.Aws.configure, ) - def create_vault_ec2_client_configuration(self, access_key, secret_key, endpoint=None, mount_point='aws-ec2'): + def create_vault_ec2_client_configuration( + self, access_key, secret_key, endpoint=None, mount_point="aws-ec2" + ): """POST /auth//config/client Configure the credentials required to perform API calls to AWS as well as custom endpoints to talk to AWS APIs. @@ -967,20 +1144,19 @@ def create_vault_ec2_client_configuration(self, access_key, secret_key, endpoint :return: The response of the request. :rtype: requests.Response """ - params = { - 'access_key': access_key, - 'secret_key': secret_key - } + params = {"access_key": access_key, "secret_key": secret_key} if endpoint is not None: - params['endpoint'] = endpoint + params["endpoint"] = endpoint - return self._adapter.post('/v1/auth/{0}/config/client'.format(mount_point), json=params) + return self._adapter.post( + "/v1/auth/{0}/config/client".format(mount_point), json=params + ) @utils.deprecated_method( - to_be_removed_in_version='0.11.2', + to_be_removed_in_version="0.11.2", new_method=api.auth_methods.Aws.read_config, ) - def get_vault_ec2_client_configuration(self, mount_point='aws-ec2'): + def get_vault_ec2_client_configuration(self, mount_point="aws-ec2"): """GET /auth//config/client :param mount_point: @@ -988,13 +1164,13 @@ def get_vault_ec2_client_configuration(self, mount_point='aws-ec2'): :return: :rtype: """ - return self._adapter.get('/v1/auth/{0}/config/client'.format(mount_point)) + return self._adapter.get("/v1/auth/{0}/config/client".format(mount_point)) @utils.deprecated_method( - to_be_removed_in_version='0.11.2', + to_be_removed_in_version="0.11.2", new_method=api.auth_methods.Aws.delete_config, ) - def delete_vault_ec2_client_configuration(self, mount_point='aws-ec2'): + def delete_vault_ec2_client_configuration(self, mount_point="aws-ec2"): """DELETE /auth//config/client :param mount_point: @@ -1002,13 +1178,15 @@ def delete_vault_ec2_client_configuration(self, mount_point='aws-ec2'): :return: :rtype: """ - return self._adapter.delete('/v1/auth/{0}/config/client'.format(mount_point)) + return self._adapter.delete("/v1/auth/{0}/config/client".format(mount_point)) @utils.deprecated_method( - to_be_removed_in_version='0.11.2', + to_be_removed_in_version="0.11.2", new_method=api.auth_methods.Aws.create_certificate_configuration, ) - def create_vault_ec2_certificate_configuration(self, cert_name, aws_public_cert, mount_point='aws-ec2'): + def create_vault_ec2_certificate_configuration( + self, cert_name, aws_public_cert, mount_point="aws-ec2" + ): """POST /auth//config/certificate/ :param cert_name: @@ -1020,17 +1198,17 @@ def create_vault_ec2_certificate_configuration(self, cert_name, aws_public_cert, :return: :rtype: """ - params = { - 'cert_name': cert_name, - 'aws_public_cert': aws_public_cert - } - return self._adapter.post('/v1/auth/{0}/config/certificate/{1}'.format(mount_point, cert_name), json=params) + params = {"cert_name": cert_name, "aws_public_cert": aws_public_cert} + return self._adapter.post( + "/v1/auth/{0}/config/certificate/{1}".format(mount_point, cert_name), + json=params, + ) @utils.deprecated_method( - to_be_removed_in_version='0.11.2', + to_be_removed_in_version="0.11.2", new_method=api.auth_methods.Aws.read_certificate_configuration, ) - def get_vault_ec2_certificate_configuration(self, cert_name, mount_point='aws-ec2'): + def get_vault_ec2_certificate_configuration(self, cert_name, mount_point="aws-ec2"): """GET /auth//config/certificate/ :param cert_name: @@ -1040,13 +1218,15 @@ def get_vault_ec2_certificate_configuration(self, cert_name, mount_point='aws-ec :return: :rtype: """ - return self._adapter.get('/v1/auth/{0}/config/certificate/{1}'.format(mount_point, cert_name)) + return self._adapter.get( + "/v1/auth/{0}/config/certificate/{1}".format(mount_point, cert_name) + ) @utils.deprecated_method( - to_be_removed_in_version='0.11.2', + to_be_removed_in_version="0.11.2", new_method=api.auth_methods.Aws.list_certificate_configurations, ) - def list_vault_ec2_certificate_configurations(self, mount_point='aws-ec2'): + def list_vault_ec2_certificate_configurations(self, mount_point="aws-ec2"): """GET /auth//config/certificates?list=true :param mount_point: @@ -1054,18 +1234,36 @@ def list_vault_ec2_certificate_configurations(self, mount_point='aws-ec2'): :return: :rtype: """ - params = {'list': True} - return self._adapter.get('/v1/auth/{0}/config/certificates'.format(mount_point), params=params) + params = {"list": True} + return self._adapter.get( + "/v1/auth/{0}/config/certificates".format(mount_point), params=params + ) @utils.deprecated_method( - to_be_removed_in_version='0.11.2', + to_be_removed_in_version="0.11.2", new_method=api.auth_methods.Aws.create_role, ) - def create_ec2_role(self, role, bound_ami_id=None, bound_account_id=None, bound_iam_role_arn=None, - bound_iam_instance_profile_arn=None, bound_ec2_instance_id=None, bound_region=None, - bound_vpc_id=None, bound_subnet_id=None, role_tag=None, ttl=None, max_ttl=None, period=None, - policies=None, allow_instance_migration=False, disallow_reauthentication=False, - resolve_aws_unique_ids=None, mount_point='aws-ec2'): + def create_ec2_role( + self, + role, + bound_ami_id=None, + bound_account_id=None, + bound_iam_role_arn=None, + bound_iam_instance_profile_arn=None, + bound_ec2_instance_id=None, + bound_region=None, + bound_vpc_id=None, + bound_subnet_id=None, + role_tag=None, + ttl=None, + max_ttl=None, + period=None, + policies=None, + allow_instance_migration=False, + disallow_reauthentication=False, + resolve_aws_unique_ids=None, + mount_point="aws-ec2", + ): """POST /auth//role/ :param role: @@ -1108,54 +1306,56 @@ def create_ec2_role(self, role, bound_ami_id=None, bound_account_id=None, bound_ :rtype: """ params = { - 'role': role, - 'auth_type': 'ec2', - 'disallow_reauthentication': disallow_reauthentication, - 'allow_instance_migration': allow_instance_migration + "role": role, + "auth_type": "ec2", + "disallow_reauthentication": disallow_reauthentication, + "allow_instance_migration": allow_instance_migration, } if bound_ami_id is not None: - params['bound_ami_id'] = bound_ami_id + params["bound_ami_id"] = bound_ami_id if bound_account_id is not None: - params['bound_account_id'] = bound_account_id + params["bound_account_id"] = bound_account_id if bound_iam_role_arn is not None: - params['bound_iam_role_arn'] = bound_iam_role_arn + params["bound_iam_role_arn"] = bound_iam_role_arn if bound_ec2_instance_id is not None: - params['bound_iam_instance_profile_arn'] = bound_ec2_instance_id + params["bound_iam_instance_profile_arn"] = bound_ec2_instance_id if bound_iam_instance_profile_arn is not None: - params['bound_iam_instance_profile_arn'] = bound_iam_instance_profile_arn + params["bound_iam_instance_profile_arn"] = bound_iam_instance_profile_arn if bound_region is not None: - params['bound_region'] = bound_region + params["bound_region"] = bound_region if bound_vpc_id is not None: - params['bound_vpc_id'] = bound_vpc_id + params["bound_vpc_id"] = bound_vpc_id if bound_subnet_id is not None: - params['bound_subnet_id'] = bound_subnet_id + params["bound_subnet_id"] = bound_subnet_id if role_tag is not None: - params['role_tag'] = role_tag + params["role_tag"] = role_tag if ttl is not None: - params['ttl'] = ttl + params["ttl"] = ttl else: - params['ttl'] = 0 + params["ttl"] = 0 if max_ttl is not None: - params['max_ttl'] = max_ttl + params["max_ttl"] = max_ttl else: - params['max_ttl'] = 0 + params["max_ttl"] = 0 if period is not None: - params['period'] = period + params["period"] = period else: - params['period'] = 0 + params["period"] = 0 if policies is not None: - params['policies'] = policies + params["policies"] = policies if resolve_aws_unique_ids is not None: - params['resolve_aws_unique_ids'] = resolve_aws_unique_ids + params["resolve_aws_unique_ids"] = resolve_aws_unique_ids - return self._adapter.post('/v1/auth/{0}/role/{1}'.format(mount_point, role), json=params) + return self._adapter.post( + "/v1/auth/{0}/role/{1}".format(mount_point, role), json=params + ) @utils.deprecated_method( - to_be_removed_in_version='0.11.2', + to_be_removed_in_version="0.11.2", new_method=api.auth_methods.Aws.read_role, ) - def get_ec2_role(self, role, mount_point='aws-ec2'): + def get_ec2_role(self, role, mount_point="aws-ec2"): """GET /auth//role/ :param role: @@ -1165,13 +1365,13 @@ def get_ec2_role(self, role, mount_point='aws-ec2'): :return: :rtype: """ - return self._adapter.get('/v1/auth/{0}/role/{1}'.format(mount_point, role)) + return self._adapter.get("/v1/auth/{0}/role/{1}".format(mount_point, role)) @utils.deprecated_method( - to_be_removed_in_version='0.11.2', + to_be_removed_in_version="0.11.2", new_method=api.auth_methods.Aws.delete_role, ) - def delete_ec2_role(self, role, mount_point='aws-ec2'): + def delete_ec2_role(self, role, mount_point="aws-ec2"): """DELETE /auth//role/ :param role: @@ -1181,13 +1381,13 @@ def delete_ec2_role(self, role, mount_point='aws-ec2'): :return: :rtype: """ - return self._adapter.delete('/v1/auth/{0}/role/{1}'.format(mount_point, role)) + return self._adapter.delete("/v1/auth/{0}/role/{1}".format(mount_point, role)) @utils.deprecated_method( - to_be_removed_in_version='0.11.2', + to_be_removed_in_version="0.11.2", new_method=api.auth_methods.Aws.list_roles, ) - def list_ec2_roles(self, mount_point='aws-ec2'): + def list_ec2_roles(self, mount_point="aws-ec2"): """GET /auth//roles?list=true :param mount_point: @@ -1196,16 +1396,26 @@ def list_ec2_roles(self, mount_point='aws-ec2'): :rtype: """ try: - return self._adapter.get('/v1/auth/{0}/roles'.format(mount_point), params={'list': True}) + return self._adapter.get( + "/v1/auth/{0}/roles".format(mount_point), params={"list": True} + ) except exceptions.InvalidPath: return None @utils.deprecated_method( - to_be_removed_in_version='0.11.2', + to_be_removed_in_version="0.11.2", new_method=api.auth_methods.Aws.create_role_tags, ) - def create_ec2_role_tag(self, role, policies=None, max_ttl=None, instance_id=None, - disallow_reauthentication=False, allow_instance_migration=False, mount_point='aws-ec2'): + def create_ec2_role_tag( + self, + role, + policies=None, + max_ttl=None, + instance_id=None, + disallow_reauthentication=False, + allow_instance_migration=False, + mount_point="aws-ec2", + ): """POST /auth//role//tag :param role: Name of the role. @@ -1233,18 +1443,20 @@ def create_ec2_role_tag(self, role, policies=None, max_ttl=None, instance_id=Non :rtype: dict """ params = { - 'role': role, - 'disallow_reauthentication': disallow_reauthentication, - 'allow_instance_migration': allow_instance_migration + "role": role, + "disallow_reauthentication": disallow_reauthentication, + "allow_instance_migration": allow_instance_migration, } if max_ttl is not None: - params['max_ttl'] = max_ttl + params["max_ttl"] = max_ttl if policies is not None: - params['policies'] = policies + params["policies"] = policies if instance_id is not None: - params['instance_id'] = instance_id - return self._adapter.post('/v1/auth/{0}/role/{1}/tag'.format(mount_point, role), json=params) + params["instance_id"] = instance_id + return self._adapter.post( + "/v1/auth/{0}/role/{1}/tag".format(mount_point, role), json=params + ) def auth_cubbyhole(self, token): """Perform a login request with a wrapped token. @@ -1258,7 +1470,7 @@ def auth_cubbyhole(self, token): :rtype: dict """ self.token = token - return self.login('/v1/sys/wrapping/unwrap') + return self.login("/v1/sys/wrapping/unwrap") def login(self, url, use_token=True, **kwargs): """Perform a login request. @@ -1277,17 +1489,13 @@ def login(self, url, use_token=True, **kwargs): :return: The response of the auth request. :rtype: requests.Response """ - return self._adapter.login( - url=url, - use_token=use_token, - **kwargs - ) + return self._adapter.login(url=url, use_token=use_token, **kwargs) @utils.deprecated_method( - to_be_removed_in_version='0.12.0', + to_be_removed_in_version="0.12.0", new_method=api.auth_methods.AppRole.create_or_update_approle, ) - def create_role(self, role_name, mount_point='approle', **kwargs): + def create_role(self, role_name, mount_point="approle", **kwargs): """POST /auth//role/ :param role_name: @@ -1300,13 +1508,15 @@ def create_role(self, role_name, mount_point='approle', **kwargs): :rtype: """ - return self._adapter.post('/v1/auth/{0}/role/{1}'.format(mount_point, role_name), json=kwargs) + return self._adapter.post( + "/v1/auth/{0}/role/{1}".format(mount_point, role_name), json=kwargs + ) @utils.deprecated_method( - to_be_removed_in_version='0.12.0', + to_be_removed_in_version="0.12.0", new_method=api.auth_methods.AppRole.delete_role, ) - def delete_role(self, role_name, mount_point='approle'): + def delete_role(self, role_name, mount_point="approle"): """DELETE /auth//role/ :param role_name: @@ -1317,13 +1527,15 @@ def delete_role(self, role_name, mount_point='approle'): :rtype: """ - return self._adapter.delete('/v1/auth/{0}/role/{1}'.format(mount_point, role_name)) + return self._adapter.delete( + "/v1/auth/{0}/role/{1}".format(mount_point, role_name) + ) @utils.deprecated_method( - to_be_removed_in_version='0.12.0', + to_be_removed_in_version="0.12.0", new_method=api.auth_methods.AppRole.list_roles, ) - def list_roles(self, mount_point='approle'): + def list_roles(self, mount_point="approle"): """GET /auth//role :param mount_point: @@ -1332,13 +1544,13 @@ def list_roles(self, mount_point='approle'): :rtype: """ - return self._adapter.get('/v1/auth/{0}/role?list=true'.format(mount_point)) + return self._adapter.get("/v1/auth/{0}/role?list=true".format(mount_point)) @utils.deprecated_method( - to_be_removed_in_version='0.12.0', + to_be_removed_in_version="0.12.0", new_method=api.auth_methods.AppRole.read_role_id, ) - def get_role_id(self, role_name, mount_point='approle'): + def get_role_id(self, role_name, mount_point="approle"): """GET /auth//role//role-id :param role_name: @@ -1349,14 +1561,14 @@ def get_role_id(self, role_name, mount_point='approle'): :rtype: """ - url = '/v1/auth/{0}/role/{1}/role-id'.format(mount_point, role_name) - return self._adapter.get(url)['data']['role_id'] + url = "/v1/auth/{0}/role/{1}/role-id".format(mount_point, role_name) + return self._adapter.get(url)["data"]["role_id"] @utils.deprecated_method( - to_be_removed_in_version='0.12.0', + to_be_removed_in_version="0.12.0", new_method=api.auth_methods.AppRole.update_role_id, ) - def set_role_id(self, role_name, role_id, mount_point='approle'): + def set_role_id(self, role_name, role_id, mount_point="approle"): """POST /auth//role//role-id :param role_name: @@ -1369,17 +1581,15 @@ def set_role_id(self, role_name, role_id, mount_point='approle'): :rtype: """ - url = '/v1/auth/{0}/role/{1}/role-id'.format(mount_point, role_name) - params = { - 'role_id': role_id - } + url = "/v1/auth/{0}/role/{1}/role-id".format(mount_point, role_name) + params = {"role_id": role_id} return self._adapter.post(url, json=params) @utils.deprecated_method( - to_be_removed_in_version='0.12.0', + to_be_removed_in_version="0.12.0", new_method=api.auth_methods.AppRole.read_role, ) - def get_role(self, role_name, mount_point='approle'): + def get_role(self, role_name, mount_point="approle"): """GET /auth//role/ :param role_name: @@ -1389,13 +1599,21 @@ def get_role(self, role_name, mount_point='approle'): :return: :rtype: """ - return self._adapter.get('/v1/auth/{0}/role/{1}'.format(mount_point, role_name)) + return self._adapter.get("/v1/auth/{0}/role/{1}".format(mount_point, role_name)) @utils.deprecated_method( - to_be_removed_in_version='0.12.0', + to_be_removed_in_version="0.12.0", new_method=api.auth_methods.AppRole.generate_secret_id, ) - def create_role_secret_id(self, role_name, meta=None, cidr_list=None, token_bound_cidrs=None, wrap_ttl=None, mount_point='approle'): + def create_role_secret_id( + self, + role_name, + meta=None, + cidr_list=None, + token_bound_cidrs=None, + wrap_ttl=None, + mount_point="approle", + ): """POST /auth//role//secret-id :param role_name: @@ -1414,21 +1632,21 @@ def create_role_secret_id(self, role_name, meta=None, cidr_list=None, token_boun :rtype: """ - url = '/v1/auth/{0}/role/{1}/secret-id'.format(mount_point, role_name) + url = "/v1/auth/{0}/role/{1}/secret-id".format(mount_point, role_name) params = {} if meta is not None: - params['metadata'] = json.dumps(meta) + params["metadata"] = json.dumps(meta) if cidr_list is not None: - params['cidr_list'] = cidr_list + params["cidr_list"] = cidr_list if token_bound_cidrs is not None: - params['token_bound_cidrs'] = token_bound_cidrs + params["token_bound_cidrs"] = token_bound_cidrs return self._adapter.post(url, json=params, wrap_ttl=wrap_ttl) @utils.deprecated_method( - to_be_removed_in_version='0.12.0', + to_be_removed_in_version="0.12.0", new_method=api.auth_methods.AppRole.read_secret_id, ) - def get_role_secret_id(self, role_name, secret_id, mount_point='approle'): + def get_role_secret_id(self, role_name, secret_id, mount_point="approle"): """POST /auth//role//secret-id/lookup :param role_name: @@ -1440,17 +1658,15 @@ def get_role_secret_id(self, role_name, secret_id, mount_point='approle'): :return: :rtype: """ - url = '/v1/auth/{0}/role/{1}/secret-id/lookup'.format(mount_point, role_name) - params = { - 'secret_id': secret_id - } + url = "/v1/auth/{0}/role/{1}/secret-id/lookup".format(mount_point, role_name) + params = {"secret_id": secret_id} return self._adapter.post(url, json=params) @utils.deprecated_method( - to_be_removed_in_version='0.12.0', + to_be_removed_in_version="0.12.0", new_method=api.auth_methods.AppRole.list_secret_id_accessors, ) - def list_role_secrets(self, role_name, mount_point='approle'): + def list_role_secrets(self, role_name, mount_point="approle"): """LIST /auth//role//secret-id :param role_name: Name of the AppRole. @@ -1460,17 +1676,18 @@ def list_role_secrets(self, role_name, mount_point='approle'): :return: The JSON response of the request. :rtype: dict """ - url = '/v1/auth/{mount_point}/role/{name}/secret-id'.format( - mount_point=mount_point, - name=role_name + url = "/v1/auth/{mount_point}/role/{name}/secret-id".format( + mount_point=mount_point, name=role_name ) return self._adapter.list(url) @utils.deprecated_method( - to_be_removed_in_version='0.12.0', + to_be_removed_in_version="0.12.0", new_method=api.auth_methods.AppRole.read_secret_id_accessor, ) - def get_role_secret_id_accessor(self, role_name, secret_id_accessor, mount_point='approle'): + def get_role_secret_id_accessor( + self, role_name, secret_id_accessor, mount_point="approle" + ): """POST /auth//role//secret-id-accessor/lookup :param role_name: @@ -1482,15 +1699,17 @@ def get_role_secret_id_accessor(self, role_name, secret_id_accessor, mount_point :return: :rtype: """ - url = '/v1/auth/{0}/role/{1}/secret-id-accessor/lookup'.format(mount_point, role_name) - params = {'secret_id_accessor': secret_id_accessor} + url = "/v1/auth/{0}/role/{1}/secret-id-accessor/lookup".format( + mount_point, role_name + ) + params = {"secret_id_accessor": secret_id_accessor} return self._adapter.post(url, json=params) @utils.deprecated_method( - to_be_removed_in_version='0.12.0', + to_be_removed_in_version="0.12.0", new_method=api.auth_methods.AppRole.destroy_secret_id, ) - def delete_role_secret_id(self, role_name, secret_id, mount_point='approle'): + def delete_role_secret_id(self, role_name, secret_id, mount_point="approle"): """POST /auth//role//secret-id/destroy :param role_name: @@ -1502,17 +1721,17 @@ def delete_role_secret_id(self, role_name, secret_id, mount_point='approle'): :return: :rtype: """ - url = '/v1/auth/{0}/role/{1}/secret-id/destroy'.format(mount_point, role_name) - params = { - 'secret_id': secret_id - } + url = "/v1/auth/{0}/role/{1}/secret-id/destroy".format(mount_point, role_name) + params = {"secret_id": secret_id} return self._adapter.post(url, json=params) @utils.deprecated_method( - to_be_removed_in_version='0.12.0', + to_be_removed_in_version="0.12.0", new_method=api.auth_methods.AppRole.destroy_secret_id_accessor, ) - def delete_role_secret_id_accessor(self, role_name, secret_id_accessor, mount_point='approle'): + def delete_role_secret_id_accessor( + self, role_name, secret_id_accessor, mount_point="approle" + ): """POST /auth//role//secret-id-accessor/destroy :param role_name: @@ -1524,17 +1743,19 @@ def delete_role_secret_id_accessor(self, role_name, secret_id_accessor, mount_po :return: :rtype: """ - url = '/v1/auth/{0}/role/{1}/secret-id-accessor/destroy'.format(mount_point, role_name) - params = { - 'secret_id_accessor': secret_id_accessor - } + url = "/v1/auth/{0}/role/{1}/secret-id-accessor/destroy".format( + mount_point, role_name + ) + params = {"secret_id_accessor": secret_id_accessor} return self._adapter.post(url, json=params) @utils.deprecated_method( - to_be_removed_in_version='0.12.0', + to_be_removed_in_version="0.12.0", new_method=api.auth_methods.AppRole.create_custom_secret_id, ) - def create_role_custom_secret_id(self, role_name, secret_id, meta=None, mount_point='approle'): + def create_role_custom_secret_id( + self, role_name, secret_id, meta=None, mount_point="approle" + ): """POST /auth//role//custom-secret-id :param role_name: @@ -1548,19 +1769,19 @@ def create_role_custom_secret_id(self, role_name, secret_id, meta=None, mount_po :return: :rtype: """ - url = '/v1/auth/{0}/role/{1}/custom-secret-id'.format(mount_point, role_name) - params = { - 'secret_id': secret_id - } + url = "/v1/auth/{0}/role/{1}/custom-secret-id".format(mount_point, role_name) + params = {"secret_id": secret_id} if meta is not None: - params['meta'] = meta + params["meta"] = meta return self._adapter.post(url, json=params) @utils.deprecated_method( - to_be_removed_in_version='0.12.0', + to_be_removed_in_version="0.12.0", new_method=api.auth_methods.AppRole.login, ) - def auth_approle(self, role_id, secret_id=None, mount_point='approle', use_token=True): + def auth_approle( + self, role_id, secret_id=None, mount_point="approle", use_token=True + ): """POST /auth//login :param role_id: @@ -1574,15 +1795,26 @@ def auth_approle(self, role_id, secret_id=None, mount_point='approle', use_token :return: :rtype: """ - params = { - 'role_id': role_id - } + params = {"role_id": role_id} if secret_id is not None: - params['secret_id'] = secret_id + params["secret_id"] = secret_id - return self.login('/v1/auth/{0}/login'.format(mount_point), json=params, use_token=use_token) + return self.login( + "/v1/auth/{0}/login".format(mount_point), json=params, use_token=use_token + ) - def create_kubernetes_configuration(self, kubernetes_host, kubernetes_ca_cert=None, token_reviewer_jwt=None, pem_keys=None, mount_point='kubernetes'): + @utils.deprecated_method( + to_be_removed_in_version="1.0.0", + new_method=api.auth_methods.Kubernetes.configure, + ) + def create_kubernetes_configuration( + self, + kubernetes_host, + kubernetes_ca_cert=None, + token_reviewer_jwt=None, + pem_keys=None, + mount_point="kubernetes", + ): """POST /auth//config :param kubernetes_host: A host:port pair, or a URL to the base of the Kubernetes API server. @@ -1602,19 +1834,23 @@ def create_kubernetes_configuration(self, kubernetes_host, kubernetes_ca_cert=No :rtype: requests.Response. """ params = { - 'kubernetes_host': kubernetes_host, - 'kubernetes_ca_cert': kubernetes_ca_cert, + "kubernetes_host": kubernetes_host, + "kubernetes_ca_cert": kubernetes_ca_cert, } if token_reviewer_jwt is not None: - params['token_reviewer_jwt'] = token_reviewer_jwt + params["token_reviewer_jwt"] = token_reviewer_jwt if pem_keys is not None: - params['pem_keys'] = pem_keys + params["pem_keys"] = pem_keys - url = 'v1/auth/{0}/config'.format(mount_point) + url = "v1/auth/{0}/config".format(mount_point) return self._adapter.post(url, json=params) - def get_kubernetes_configuration(self, mount_point='kubernetes'): + @utils.deprecated_method( + to_be_removed_in_version="1.0.0", + new_method=api.auth_methods.Kubernetes.read_config, + ) + def get_kubernetes_configuration(self, mount_point="kubernetes"): """GET /auth//config :param mount_point: The "path" the k8s auth backend was mounted on. Vault currently defaults to "kubernetes". @@ -1623,11 +1859,25 @@ def get_kubernetes_configuration(self, mount_point='kubernetes'): :rtype: dict. """ - url = '/v1/auth/{0}/config'.format(mount_point) + url = "/v1/auth/{0}/config".format(mount_point) return self._adapter.get(url) - def create_kubernetes_role(self, name, bound_service_account_names, bound_service_account_namespaces, ttl="", - max_ttl="", period="", policies=None, token_type="", mount_point='kubernetes'): + @utils.deprecated_method( + to_be_removed_in_version="1.0.0", + new_method=api.auth_methods.Kubernetes.create_role, + ) + def create_kubernetes_role( + self, + name, + bound_service_account_names, + bound_service_account_namespaces, + ttl="", + max_ttl="", + period="", + policies=None, + token_type="", + mount_point="kubernetes", + ): """POST /auth//role/:name :param name: Name of the role. @@ -1654,25 +1904,32 @@ def create_kubernetes_role(self, name, bound_service_account_names, bound_servic :return: Will be an empty body with a 204 status code upon success :rtype: requests.Response. """ - if bound_service_account_names == '*' and bound_service_account_namespaces == '*': + if ( + bound_service_account_names == "*" + and bound_service_account_namespaces == "*" + ): error_message = 'bound_service_account_names and bound_service_account_namespaces can not both be set to "*"' raise exceptions.ParamValidationError(error_message) params = { - 'bound_service_account_names': bound_service_account_names, - 'bound_service_account_namespaces': bound_service_account_namespaces, - 'ttl': ttl, - 'max_ttl': max_ttl, - 'period': period, - 'policies': policies, + "bound_service_account_names": bound_service_account_names, + "bound_service_account_namespaces": bound_service_account_namespaces, + "ttl": ttl, + "max_ttl": max_ttl, + "period": period, + "policies": policies, } if token_type: - params['token_type'] = token_type - - url = 'v1/auth/{0}/role/{1}'.format(mount_point, name) + params["token_type"] = token_type + + url = "v1/auth/{0}/role/{1}".format(mount_point, name) return self._adapter.post(url, json=params) - def get_kubernetes_role(self, name, mount_point='kubernetes'): + @utils.deprecated_method( + to_be_removed_in_version="1.0.0", + new_method=api.auth_methods.Kubernetes.read_role, + ) + def get_kubernetes_role(self, name, mount_point="kubernetes"): """GET /auth//role/:name :param name: Name of the role. @@ -1683,10 +1940,14 @@ def get_kubernetes_role(self, name, mount_point='kubernetes'): :rtype: dict. """ - url = 'v1/auth/{0}/role/{1}'.format(mount_point, name) + url = "v1/auth/{0}/role/{1}".format(mount_point, name) return self._adapter.get(url) - def list_kubernetes_roles(self, mount_point='kubernetes'): + @utils.deprecated_method( + to_be_removed_in_version="1.0.0", + new_method=api.auth_methods.Kubernetes.list_roles, + ) + def list_kubernetes_roles(self, mount_point="kubernetes"): """GET /auth//role?list=true :param mount_point: The "path" the k8s auth backend was mounted on. Vault currently defaults to "kubernetes". @@ -1695,10 +1956,14 @@ def list_kubernetes_roles(self, mount_point='kubernetes'): :rtype: dict. """ - url = 'v1/auth/{0}/role?list=true'.format(mount_point) + url = "v1/auth/{0}/role?list=true".format(mount_point) return self._adapter.get(url) - def delete_kubernetes_role(self, role, mount_point='kubernetes'): + @utils.deprecated_method( + to_be_removed_in_version="1.0.0", + new_method=api.auth_methods.Kubernetes.delete_role, + ) + def delete_kubernetes_role(self, role, mount_point="kubernetes"): """DELETE /auth//role/:role :type role: Name of the role. @@ -1709,10 +1974,14 @@ def delete_kubernetes_role(self, role, mount_point='kubernetes'): :rtype: requests.Response. """ - url = 'v1/auth/{0}/role/{1}'.format(mount_point, role) + url = "v1/auth/{0}/role/{1}".format(mount_point, role) return self._adapter.delete(url) - def auth_kubernetes(self, role, jwt, use_token=True, mount_point='kubernetes'): + @utils.deprecated_method( + to_be_removed_in_version="1.0.0", + new_method=api.auth_methods.Kubernetes.login, + ) + def auth_kubernetes(self, role, jwt, use_token=True, mount_point="kubernetes"): """POST /auth//login :param role: Name of the role against which the login is being attempted. @@ -1727,19 +1996,23 @@ def auth_kubernetes(self, role, jwt, use_token=True, mount_point='kubernetes'): :return: Parsed JSON response from the config POST request. :rtype: dict. """ - params = { - 'role': role, - 'jwt': jwt - } - url = 'v1/auth/{0}/login'.format(mount_point) + params = {"role": role, "jwt": jwt} + url = "v1/auth/{0}/login".format(mount_point) return self.login(url, json=params, use_token=use_token) @utils.deprecated_method( - to_be_removed_in_version='0.9.0', + to_be_removed_in_version="0.9.0", new_method=api.secrets_engines.Transit.create_key, ) - def transit_create_key(self, name, convergent_encryption=None, derived=None, exportable=None, - key_type=None, mount_point='transit'): + def transit_create_key( + self, + name, + convergent_encryption=None, + derived=None, + exportable=None, + key_type=None, + mount_point="transit", + ): """POST //keys/ :param name: @@ -1757,24 +2030,24 @@ def transit_create_key(self, name, convergent_encryption=None, derived=None, exp :return: :rtype: """ - url = '/v1/{0}/keys/{1}'.format(mount_point, name) + url = "/v1/{0}/keys/{1}".format(mount_point, name) params = {} if convergent_encryption is not None: - params['convergent_encryption'] = convergent_encryption + params["convergent_encryption"] = convergent_encryption if derived is not None: - params['derived'] = derived + params["derived"] = derived if exportable is not None: - params['exportable'] = exportable + params["exportable"] = exportable if key_type is not None: - params['type'] = key_type + params["type"] = key_type return self._adapter.post(url, json=params) @utils.deprecated_method( - to_be_removed_in_version='0.9.0', + to_be_removed_in_version="0.9.0", new_method=api.secrets_engines.Transit.read_key, ) - def transit_read_key(self, name, mount_point='transit'): + def transit_read_key(self, name, mount_point="transit"): """GET //keys/ :param name: @@ -1784,14 +2057,14 @@ def transit_read_key(self, name, mount_point='transit'): :return: :rtype: """ - url = '/v1/{0}/keys/{1}'.format(mount_point, name) + url = "/v1/{0}/keys/{1}".format(mount_point, name) return self._adapter.get(url) @utils.deprecated_method( - to_be_removed_in_version='0.9.0', + to_be_removed_in_version="0.9.0", new_method=api.secrets_engines.Transit.list_keys, ) - def transit_list_keys(self, mount_point='transit'): + def transit_list_keys(self, mount_point="transit"): """GET //keys?list=true :param mount_point: @@ -1799,14 +2072,14 @@ def transit_list_keys(self, mount_point='transit'): :return: :rtype: """ - url = '/v1/{0}/keys?list=true'.format(mount_point) + url = "/v1/{0}/keys?list=true".format(mount_point) return self._adapter.get(url) @utils.deprecated_method( - to_be_removed_in_version='0.9.0', + to_be_removed_in_version="0.9.0", new_method=api.secrets_engines.Transit.delete_key, ) - def transit_delete_key(self, name, mount_point='transit'): + def transit_delete_key(self, name, mount_point="transit"): """DELETE //keys/ :param name: @@ -1816,15 +2089,21 @@ def transit_delete_key(self, name, mount_point='transit'): :return: :rtype: """ - url = '/v1/{0}/keys/{1}'.format(mount_point, name) + url = "/v1/{0}/keys/{1}".format(mount_point, name) return self._adapter.delete(url) @utils.deprecated_method( - to_be_removed_in_version='0.9.0', + to_be_removed_in_version="0.9.0", new_method=api.secrets_engines.Transit.update_key_configuration, ) - def transit_update_key(self, name, min_decryption_version=None, min_encryption_version=None, deletion_allowed=None, - mount_point='transit'): + def transit_update_key( + self, + name, + min_decryption_version=None, + min_encryption_version=None, + deletion_allowed=None, + mount_point="transit", + ): """POST //keys//config :param name: @@ -1840,22 +2119,22 @@ def transit_update_key(self, name, min_decryption_version=None, min_encryption_v :return: :rtype: """ - url = '/v1/{0}/keys/{1}/config'.format(mount_point, name) + url = "/v1/{0}/keys/{1}/config".format(mount_point, name) params = {} if min_decryption_version is not None: - params['min_decryption_version'] = min_decryption_version + params["min_decryption_version"] = min_decryption_version if min_encryption_version is not None: - params['min_encryption_version'] = min_encryption_version + params["min_encryption_version"] = min_encryption_version if deletion_allowed is not None: - params['deletion_allowed'] = deletion_allowed + params["deletion_allowed"] = deletion_allowed return self._adapter.post(url, json=params) @utils.deprecated_method( - to_be_removed_in_version='0.9.0', + to_be_removed_in_version="0.9.0", new_method=api.secrets_engines.Transit.rotate_key, ) - def transit_rotate_key(self, name, mount_point='transit'): + def transit_rotate_key(self, name, mount_point="transit"): """POST //keys//rotate :param name: @@ -1865,14 +2144,14 @@ def transit_rotate_key(self, name, mount_point='transit'): :return: :rtype: """ - url = '/v1/{0}/keys/{1}/rotate'.format(mount_point, name) + url = "/v1/{0}/keys/{1}/rotate".format(mount_point, name) return self._adapter.post(url) @utils.deprecated_method( - to_be_removed_in_version='0.9.0', + to_be_removed_in_version="0.9.0", new_method=api.secrets_engines.Transit.export_key, ) - def transit_export_key(self, name, key_type, version=None, mount_point='transit'): + def transit_export_key(self, name, key_type, version=None, mount_point="transit"): """GET //export//(/) :param name: @@ -1887,17 +2166,29 @@ def transit_export_key(self, name, key_type, version=None, mount_point='transit' :rtype: """ if version is not None: - url = '/v1/{0}/export/{1}/{2}/{3}'.format(mount_point, key_type, name, version) + url = "/v1/{0}/export/{1}/{2}/{3}".format( + mount_point, key_type, name, version + ) else: - url = '/v1/{0}/export/{1}/{2}'.format(mount_point, key_type, name) + url = "/v1/{0}/export/{1}/{2}".format(mount_point, key_type, name) return self._adapter.get(url) @utils.deprecated_method( - to_be_removed_in_version='0.9.0', + to_be_removed_in_version="0.9.0", new_method=api.secrets_engines.Transit.encrypt_data, ) - def transit_encrypt_data(self, name, plaintext, context=None, key_version=None, nonce=None, batch_input=None, - key_type=None, convergent_encryption=None, mount_point='transit'): + def transit_encrypt_data( + self, + name, + plaintext, + context=None, + key_version=None, + nonce=None, + batch_input=None, + key_type=None, + convergent_encryption=None, + mount_point="transit", + ): """POST //encrypt/ :param name: @@ -1921,30 +2212,36 @@ def transit_encrypt_data(self, name, plaintext, context=None, key_version=None, :return: :rtype: """ - url = '/v1/{0}/encrypt/{1}'.format(mount_point, name) - params = { - 'plaintext': plaintext - } + url = "/v1/{0}/encrypt/{1}".format(mount_point, name) + params = {"plaintext": plaintext} if context is not None: - params['context'] = context + params["context"] = context if key_version is not None: - params['key_version'] = key_version + params["key_version"] = key_version if nonce is not None: - params['nonce'] = nonce + params["nonce"] = nonce if batch_input is not None: - params['batch_input'] = batch_input + params["batch_input"] = batch_input if key_type is not None: - params['type'] = key_type + params["type"] = key_type if convergent_encryption is not None: - params['convergent_encryption'] = convergent_encryption + params["convergent_encryption"] = convergent_encryption return self._adapter.post(url, json=params) @utils.deprecated_method( - to_be_removed_in_version='0.9.0', + to_be_removed_in_version="0.9.0", new_method=api.secrets_engines.Transit.decrypt_data, ) - def transit_decrypt_data(self, name, ciphertext, context=None, nonce=None, batch_input=None, mount_point='transit'): + def transit_decrypt_data( + self, + name, + ciphertext, + context=None, + nonce=None, + batch_input=None, + mount_point="transit", + ): """POST //decrypt/ :param name: @@ -1962,25 +2259,31 @@ def transit_decrypt_data(self, name, ciphertext, context=None, nonce=None, batch :return: :rtype: """ - url = '/v1/{0}/decrypt/{1}'.format(mount_point, name) - params = { - 'ciphertext': ciphertext - } + url = "/v1/{0}/decrypt/{1}".format(mount_point, name) + params = {"ciphertext": ciphertext} if context is not None: - params['context'] = context + params["context"] = context if nonce is not None: - params['nonce'] = nonce + params["nonce"] = nonce if batch_input is not None: - params['batch_input'] = batch_input + params["batch_input"] = batch_input return self._adapter.post(url, json=params) @utils.deprecated_method( - to_be_removed_in_version='0.9.0', + to_be_removed_in_version="0.9.0", new_method=api.secrets_engines.Transit.rewrap_data, ) - def transit_rewrap_data(self, name, ciphertext, context=None, key_version=None, nonce=None, batch_input=None, - mount_point='transit'): + def transit_rewrap_data( + self, + name, + ciphertext, + context=None, + key_version=None, + nonce=None, + batch_input=None, + mount_point="transit", + ): """POST //rewrap/ :param name: @@ -2000,26 +2303,26 @@ def transit_rewrap_data(self, name, ciphertext, context=None, key_version=None, :return: :rtype: """ - url = '/v1/{0}/rewrap/{1}'.format(mount_point, name) - params = { - 'ciphertext': ciphertext - } + url = "/v1/{0}/rewrap/{1}".format(mount_point, name) + params = {"ciphertext": ciphertext} if context is not None: - params['context'] = context + params["context"] = context if key_version is not None: - params['key_version'] = key_version + params["key_version"] = key_version if nonce is not None: - params['nonce'] = nonce + params["nonce"] = nonce if batch_input is not None: - params['batch_input'] = batch_input + params["batch_input"] = batch_input return self._adapter.post(url, json=params) @utils.deprecated_method( - to_be_removed_in_version='0.9.0', + to_be_removed_in_version="0.9.0", new_method=api.secrets_engines.Transit.generate_data_key, ) - def transit_generate_data_key(self, name, key_type, context=None, nonce=None, bits=None, mount_point='transit'): + def transit_generate_data_key( + self, name, key_type, context=None, nonce=None, bits=None, mount_point="transit" + ): """POST //datakey// :param name: @@ -2037,22 +2340,24 @@ def transit_generate_data_key(self, name, key_type, context=None, nonce=None, bi :return: :rtype: """ - url = '/v1/{0}/datakey/{1}/{2}'.format(mount_point, key_type, name) + url = "/v1/{0}/datakey/{1}/{2}".format(mount_point, key_type, name) params = {} if context is not None: - params['context'] = context + params["context"] = context if nonce is not None: - params['nonce'] = nonce + params["nonce"] = nonce if bits is not None: - params['bits'] = bits + params["bits"] = bits return self._adapter.post(url, json=params) @utils.deprecated_method( - to_be_removed_in_version='0.9.0', + to_be_removed_in_version="0.9.0", new_method=api.secrets_engines.Transit.generate_random_bytes, ) - def transit_generate_rand_bytes(self, data_bytes=None, output_format=None, mount_point='transit'): + def transit_generate_rand_bytes( + self, data_bytes=None, output_format=None, mount_point="transit" + ): """POST //random(/) :param data_bytes: @@ -2065,9 +2370,9 @@ def transit_generate_rand_bytes(self, data_bytes=None, output_format=None, mount :rtype: """ if data_bytes is not None: - url = '/v1/{0}/random/{1}'.format(mount_point, data_bytes) + url = "/v1/{0}/random/{1}".format(mount_point, data_bytes) else: - url = '/v1/{0}/random'.format(mount_point) + url = "/v1/{0}/random".format(mount_point) params = {} if output_format is not None: @@ -2076,10 +2381,12 @@ def transit_generate_rand_bytes(self, data_bytes=None, output_format=None, mount return self._adapter.post(url, json=params) @utils.deprecated_method( - to_be_removed_in_version='0.9.0', + to_be_removed_in_version="0.9.0", new_method=api.secrets_engines.Transit.hash_data, ) - def transit_hash_data(self, hash_input, algorithm=None, output_format=None, mount_point='transit'): + def transit_hash_data( + self, hash_input, algorithm=None, output_format=None, mount_point="transit" + ): """POST //hash(/) :param hash_input: @@ -2094,23 +2401,23 @@ def transit_hash_data(self, hash_input, algorithm=None, output_format=None, moun :rtype: """ if algorithm is not None: - url = '/v1/{0}/hash/{1}'.format(mount_point, algorithm) + url = "/v1/{0}/hash/{1}".format(mount_point, algorithm) else: - url = '/v1/{0}/hash'.format(mount_point) + url = "/v1/{0}/hash".format(mount_point) - params = { - 'input': hash_input - } + params = {"input": hash_input} if output_format is not None: - params['format'] = output_format + params["format"] = output_format return self._adapter.post(url, json=params) @utils.deprecated_method( - to_be_removed_in_version='0.9.0', + to_be_removed_in_version="0.9.0", new_method=api.secrets_engines.Transit.generate_hmac, ) - def transit_generate_hmac(self, name, hmac_input, key_version=None, algorithm=None, mount_point='transit'): + def transit_generate_hmac( + self, name, hmac_input, key_version=None, algorithm=None, mount_point="transit" + ): """POST //hmac/(/) :param name: @@ -2127,23 +2434,30 @@ def transit_generate_hmac(self, name, hmac_input, key_version=None, algorithm=No :rtype: """ if algorithm is not None: - url = '/v1/{0}/hmac/{1}/{2}'.format(mount_point, name, algorithm) + url = "/v1/{0}/hmac/{1}/{2}".format(mount_point, name, algorithm) else: - url = '/v1/{0}/hmac/{1}'.format(mount_point, name) - params = { - 'input': hmac_input - } + url = "/v1/{0}/hmac/{1}".format(mount_point, name) + params = {"input": hmac_input} if key_version is not None: - params['key_version'] = key_version + params["key_version"] = key_version return self._adapter.post(url, json=params) @utils.deprecated_method( - to_be_removed_in_version='0.9.0', + to_be_removed_in_version="0.9.0", new_method=api.secrets_engines.Transit.sign_data, ) - def transit_sign_data(self, name, input_data, key_version=None, algorithm=None, context=None, prehashed=None, - mount_point='transit', signature_algorithm='pss'): + def transit_sign_data( + self, + name, + input_data, + key_version=None, + algorithm=None, + context=None, + prehashed=None, + mount_point="transit", + signature_algorithm="pss", + ): """POST //sign/(/) :param name: @@ -2166,29 +2480,37 @@ def transit_sign_data(self, name, input_data, key_version=None, algorithm=None, :rtype: """ if algorithm is not None: - url = '/v1/{0}/sign/{1}/{2}'.format(mount_point, name, algorithm) + url = "/v1/{0}/sign/{1}/{2}".format(mount_point, name, algorithm) else: - url = '/v1/{0}/sign/{1}'.format(mount_point, name) + url = "/v1/{0}/sign/{1}".format(mount_point, name) - params = { - 'input': input_data - } + params = {"input": input_data} if key_version is not None: - params['key_version'] = key_version + params["key_version"] = key_version if context is not None: - params['context'] = context + params["context"] = context if prehashed is not None: - params['prehashed'] = prehashed - params['signature_algorithm'] = signature_algorithm + params["prehashed"] = prehashed + params["signature_algorithm"] = signature_algorithm return self._adapter.post(url, json=params) @utils.deprecated_method( - to_be_removed_in_version='0.9.0', + to_be_removed_in_version="0.9.0", new_method=api.secrets_engines.Transit.verify_signed_data, ) - def transit_verify_signed_data(self, name, input_data, algorithm=None, signature=None, hmac=None, context=None, - prehashed=None, mount_point='transit', signature_algorithm='pss'): + def transit_verify_signed_data( + self, + name, + input_data, + algorithm=None, + signature=None, + hmac=None, + context=None, + prehashed=None, + mount_point="transit", + signature_algorithm="pss", + ): """POST //verify/(/) :param name: @@ -2213,42 +2535,40 @@ def transit_verify_signed_data(self, name, input_data, algorithm=None, signature :rtype: """ if algorithm is not None: - url = '/v1/{0}/verify/{1}/{2}'.format(mount_point, name, algorithm) + url = "/v1/{0}/verify/{1}/{2}".format(mount_point, name, algorithm) else: - url = '/v1/{0}/verify/{1}'.format(mount_point, name) + url = "/v1/{0}/verify/{1}".format(mount_point, name) - params = { - 'input': input_data - } + params = {"input": input_data} if signature is not None: - params['signature'] = signature + params["signature"] = signature if hmac is not None: - params['hmac'] = hmac + params["hmac"] = hmac if context is not None: - params['context'] = context + params["context"] = context if prehashed is not None: - params['prehashed'] = prehashed - params['signature_algorithm'] = signature_algorithm + params["prehashed"] = prehashed + params["signature_algorithm"] = signature_algorithm return self._adapter.post(url, json=params) @utils.deprecated_method( - to_be_removed_in_version='0.9.0', + to_be_removed_in_version="0.9.0", new_method=api.SystemBackend.unwrap, ) def unwrap(self, token=None): return self.sys.unwrap(token=token) @utils.deprecated_method( - to_be_removed_in_version='0.9.0', + to_be_removed_in_version="0.9.0", new_method=api.SystemBackend.list_policies, ) def list_policies(self): - policies = self.sys.list_policies()['data']['policies'] + policies = self.sys.list_policies()["data"]["policies"] return policies @utils.deprecated_method( - to_be_removed_in_version='0.9.0', + to_be_removed_in_version="0.9.0", new_method=api.SystemBackend.create_or_update_policy, ) def set_policy(self, name, rules): @@ -2267,68 +2587,75 @@ def set_policy(self, name, rules): if isinstance(rules, dict): rules = json.dumps(rules) params = { - 'rules': rules, + "rules": rules, } api_path = utils.format_url( - '/v1/sys/policy/{name}', + "/v1/sys/policy/{name}", name=name, ) self._adapter.put(api_path, json=params) @utils.deprecated_method( - to_be_removed_in_version='0.9.0', + to_be_removed_in_version="0.9.0", new_method=api.SystemBackend.delete_policy, ) def delete_policy(self, name): self.sys.delete_policy(name=name) @utils.deprecated_method( - to_be_removed_in_version='0.9.0', + to_be_removed_in_version="0.9.0", new_method=api.SystemBackend.is_sealed, ) def is_sealed(self): return self.sys.is_sealed() @utils.deprecated_method( - to_be_removed_in_version='0.9.0', + to_be_removed_in_version="0.9.0", new_method=api.SystemBackend.seal, ) def seal(self): self.sys.seal() @utils.deprecated_method( - to_be_removed_in_version='0.9.0', + to_be_removed_in_version="0.9.0", new_method=api.SystemBackend.submit_unseal_key, ) def unseal_reset(self): return self.sys.submit_unseal_key(reset=True) @utils.deprecated_method( - to_be_removed_in_version='0.9.0', + to_be_removed_in_version="0.9.0", new_method=api.SystemBackend.submit_unseal_key, ) def unseal(self, key): return self.sys.submit_unseal_key(key=key) @utils.deprecated_method( - to_be_removed_in_version='0.9.0', + to_be_removed_in_version="0.9.0", new_method=api.SystemBackend.submit_unseal_keys, ) def unseal_multi(self, keys): return self.sys.submit_unseal_keys(keys=keys) @utils.deprecated_method( - to_be_removed_in_version='0.9.0', + to_be_removed_in_version="0.9.0", new_method=api.SystemBackend.list_mounted_secrets_engines, ) def list_secret_backends(self): return self.sys.list_mounted_secrets_engines() @utils.deprecated_method( - to_be_removed_in_version='0.9.0', + to_be_removed_in_version="0.9.0", new_method=api.SystemBackend.enable_secrets_engine, ) - def enable_secret_backend(self, backend_type, description=None, mount_point=None, config=None, options=None): + def enable_secret_backend( + self, + backend_type, + description=None, + mount_point=None, + config=None, + options=None, + ): return self.sys.enable_secrets_engine( backend_type=backend_type, path=mount_point, @@ -2338,12 +2665,21 @@ def enable_secret_backend(self, backend_type, description=None, mount_point=None ) @utils.deprecated_method( - to_be_removed_in_version='0.9.0', + to_be_removed_in_version="0.9.0", new_method=api.SystemBackend.tune_mount_configuration, ) - def tune_secret_backend(self, backend_type, mount_point=None, default_lease_ttl=None, max_lease_ttl=None, description=None, - audit_non_hmac_request_keys=None, audit_non_hmac_response_keys=None, listing_visibility=None, - passthrough_request_headers=None): + def tune_secret_backend( + self, + backend_type, + mount_point=None, + default_lease_ttl=None, + max_lease_ttl=None, + description=None, + audit_non_hmac_request_keys=None, + audit_non_hmac_response_keys=None, + listing_visibility=None, + passthrough_request_headers=None, + ): if not mount_point: mount_point = backend_type @@ -2359,7 +2695,7 @@ def tune_secret_backend(self, backend_type, mount_point=None, default_lease_ttl= ) @utils.deprecated_method( - to_be_removed_in_version='0.9.0', + to_be_removed_in_version="0.9.0", new_method=api.SystemBackend.read_mount_configuration, ) def get_secret_backend_tuning(self, backend_type, mount_point=None): @@ -2379,7 +2715,7 @@ def get_secret_backend_tuning(self, backend_type, mount_point=None): ) @utils.deprecated_method( - to_be_removed_in_version='0.9.0', + to_be_removed_in_version="0.9.0", new_method=api.SystemBackend.disable_secrets_engine, ) def disable_secret_backend(self, mount_point): @@ -2388,7 +2724,7 @@ def disable_secret_backend(self, mount_point): ) @utils.deprecated_method( - to_be_removed_in_version='0.9.0', + to_be_removed_in_version="0.9.0", new_method=api.SystemBackend.move_backend, ) def remount_secret_backend(self, from_mount_point, to_mount_point): @@ -2398,7 +2734,7 @@ def remount_secret_backend(self, from_mount_point, to_mount_point): ) @utils.deprecated_method( - to_be_removed_in_version='0.9.0', + to_be_removed_in_version="0.9.0", new_method=api.SystemBackend.read_lease, ) def read_lease(self, lease_id): @@ -2407,7 +2743,7 @@ def read_lease(self, lease_id): ) @utils.deprecated_method( - to_be_removed_in_version='0.9.0', + to_be_removed_in_version="0.9.0", new_method=api.SystemBackend.renew_lease, ) def renew_secret(self, lease_id, increment=None): @@ -2417,7 +2753,7 @@ def renew_secret(self, lease_id, increment=None): ) @utils.deprecated_method( - to_be_removed_in_version='0.9.0', + to_be_removed_in_version="0.9.0", new_method=api.SystemBackend.revoke_lease, ) def revoke_secret(self, lease_id): @@ -2426,7 +2762,7 @@ def revoke_secret(self, lease_id): ) @utils.deprecated_method( - to_be_removed_in_version='0.9.0', + to_be_removed_in_version="0.9.0", new_method=api.SystemBackend.revoke_lease, ) def revoke_secret_prefix(self, path_prefix): @@ -2435,17 +2771,19 @@ def revoke_secret_prefix(self, path_prefix): ) @utils.deprecated_method( - to_be_removed_in_version='0.9.0', + to_be_removed_in_version="0.9.0", new_method=api.SystemBackend.rotate_encryption_key, ) def rotate(self): self.sys.rotate_encryption_key() @utils.deprecated_method( - to_be_removed_in_version='0.9.0', + to_be_removed_in_version="0.9.0", new_method=api.SystemBackend.start_rekey, ) - def start_rekey(self, secret_shares=5, secret_threshold=3, pgp_keys=None, backup=False): + def start_rekey( + self, secret_shares=5, secret_threshold=3, pgp_keys=None, backup=False + ): return self.sys.start_rekey( secret_shares=secret_shares, secret_threshold=secret_threshold, @@ -2454,14 +2792,14 @@ def start_rekey(self, secret_shares=5, secret_threshold=3, pgp_keys=None, backup ) @utils.deprecated_method( - to_be_removed_in_version='0.9.0', + to_be_removed_in_version="0.9.0", new_method=api.SystemBackend.cancel_rekey, ) def cancel_rekey(self): return self.sys.cancel_rekey() @utils.deprecated_method( - to_be_removed_in_version='0.9.0', + to_be_removed_in_version="0.9.0", new_method=api.SystemBackend.rekey, ) def rekey(self, key, nonce=None): @@ -2471,7 +2809,7 @@ def rekey(self, key, nonce=None): ) @utils.deprecated_method( - to_be_removed_in_version='0.9.0', + to_be_removed_in_version="0.9.0", new_method=api.SystemBackend.rekey_multi, ) def rekey_multi(self, keys, nonce=None): @@ -2481,21 +2819,21 @@ def rekey_multi(self, keys, nonce=None): ) @utils.deprecated_method( - to_be_removed_in_version='0.9.0', + to_be_removed_in_version="0.9.0", new_method=api.SystemBackend.read_backup_keys, ) def get_backed_up_keys(self): return self.sys.read_backup_keys() @utils.deprecated_method( - to_be_removed_in_version='0.9.0', + to_be_removed_in_version="0.9.0", new_method=api.SystemBackend.is_initialized, ) def is_initialized(self): return self.sys.is_initialized() @utils.deprecated_method( - to_be_removed_in_version='0.9.0', + to_be_removed_in_version="0.9.0", new_method=api.SystemBackend.initialize, ) def initialize(self, secret_shares=5, secret_threshold=3, pgp_keys=None): @@ -2506,19 +2844,19 @@ def initialize(self, secret_shares=5, secret_threshold=3, pgp_keys=None): ) @utils.deprecated_method( - to_be_removed_in_version='0.9.0', + to_be_removed_in_version="0.9.0", new_method=api.SystemBackend.start_root_token_generation, ) def start_generate_root(self, key, otp=False): params = {} if otp: - params['otp'] = key + params["otp"] = key else: - params['pgp_key'] = key + params["pgp_key"] = key return self.sys.start_root_token_generation(**params) @utils.deprecated_method( - to_be_removed_in_version='0.9.0', + to_be_removed_in_version="0.9.0", new_method=api.SystemBackend.generate_root, ) def generate_root(self, key, nonce): @@ -2528,24 +2866,31 @@ def generate_root(self, key, nonce): ) @utils.deprecated_method( - to_be_removed_in_version='0.9.0', + to_be_removed_in_version="0.9.0", new_method=api.SystemBackend.cancel_root_generation, ) def cancel_generate_root(self): return self.sys.cancel_root_generation().status_code == 204 @utils.deprecated_method( - to_be_removed_in_version='0.9.0', + to_be_removed_in_version="0.9.0", new_method=api.SystemBackend.list_auth_methods, ) def list_auth_backends(self): return self.sys.list_auth_methods() @utils.deprecated_method( - to_be_removed_in_version='0.9.0', + to_be_removed_in_version="0.9.0", new_method=api.SystemBackend.enable_auth_method, ) - def enable_auth_backend(self, backend_type, description=None, mount_point=None, config=None, plugin_name=None): + def enable_auth_backend( + self, + backend_type, + description=None, + mount_point=None, + config=None, + plugin_name=None, + ): return self.sys.enable_auth_method( method_type=backend_type, description=description, @@ -2555,12 +2900,21 @@ def enable_auth_backend(self, backend_type, description=None, mount_point=None, ) @utils.deprecated_method( - to_be_removed_in_version='0.9.0', + to_be_removed_in_version="0.9.0", new_method=api.SystemBackend.tune_auth_method, ) - def tune_auth_backend(self, backend_type, mount_point=None, default_lease_ttl=None, max_lease_ttl=None, description=None, - audit_non_hmac_request_keys=None, audit_non_hmac_response_keys=None, listing_visibility="", - passthrough_request_headers=None): + def tune_auth_backend( + self, + backend_type, + mount_point=None, + default_lease_ttl=None, + max_lease_ttl=None, + description=None, + audit_non_hmac_request_keys=None, + audit_non_hmac_response_keys=None, + listing_visibility="", + passthrough_request_headers=None, + ): if not mount_point: mount_point = backend_type return self.sys.tune_auth_method( @@ -2575,7 +2929,7 @@ def tune_auth_backend(self, backend_type, mount_point=None, default_lease_ttl=No ) @utils.deprecated_method( - to_be_removed_in_version='0.9.0', + to_be_removed_in_version="0.9.0", new_method=api.SystemBackend.read_auth_method_tuning, ) def get_auth_backend_tuning(self, backend_type, mount_point=None): @@ -2586,7 +2940,7 @@ def get_auth_backend_tuning(self, backend_type, mount_point=None): ) @utils.deprecated_method( - to_be_removed_in_version='0.9.0', + to_be_removed_in_version="0.9.0", new_method=api.SystemBackend.disable_auth_method, ) def disable_auth_backend(self, mount_point): @@ -2595,17 +2949,19 @@ def disable_auth_backend(self, mount_point): ) @utils.deprecated_method( - to_be_removed_in_version='0.9.0', + to_be_removed_in_version="0.9.0", new_method=api.SystemBackend.list_enabled_audit_devices, ) def list_audit_backends(self): return self.sys.list_enabled_audit_devices() @utils.deprecated_method( - to_be_removed_in_version='0.9.0', + to_be_removed_in_version="0.9.0", new_method=api.SystemBackend.enable_audit_device, ) - def enable_audit_backend(self, backend_type, description=None, options=None, name=None): + def enable_audit_backend( + self, backend_type, description=None, options=None, name=None + ): self.sys.enable_audit_device( device_type=backend_type, description=description, @@ -2614,7 +2970,7 @@ def enable_audit_backend(self, backend_type, description=None, options=None, nam ) @utils.deprecated_method( - to_be_removed_in_version='0.9.0', + to_be_removed_in_version="0.9.0", new_method=api.SystemBackend.disable_audit_device, ) def disable_audit_backend(self, name): @@ -2623,7 +2979,7 @@ def disable_audit_backend(self, name): ) @utils.deprecated_method( - to_be_removed_in_version='0.9.0', + to_be_removed_in_version="0.9.0", new_method=api.SystemBackend.calculate_hash, ) def audit_hash(self, name, input): @@ -2633,56 +2989,56 @@ def audit_hash(self, name, input): ) @utils.deprecated_method( - to_be_removed_in_version='0.8.0', + to_be_removed_in_version="0.8.0", new_method=api.auth_methods.Ldap.login, ) def auth_ldap(self, *args, **kwargs): return self.auth.ldap.login(*args, **kwargs) @utils.deprecated_method( - to_be_removed_in_version='0.9.0', + to_be_removed_in_version="0.9.0", new_method=api.auth_methods.Gcp.login, ) def auth_gcp(self, *args, **kwargs): return self.auth.gcp.login(*args, **kwargs) @utils.deprecated_method( - to_be_removed_in_version='0.8.0', + to_be_removed_in_version="0.8.0", new_method=api.auth_methods.Github.login, ) def auth_github(self, *args, **kwargs): return self.auth.github.login(*args, **kwargs) @utils.deprecated_method( - to_be_removed_in_version='0.8.0', + to_be_removed_in_version="0.8.0", new_method=adapters.Request.close, ) def close(self): return self._adapter.close() @utils.deprecated_method( - to_be_removed_in_version='0.8.0', + to_be_removed_in_version="0.8.0", new_method=adapters.Request.get, ) def _get(self, *args, **kwargs): return self._adapter.get(*args, **kwargs) @utils.deprecated_method( - to_be_removed_in_version='0.8.0', + to_be_removed_in_version="0.8.0", new_method=adapters.Request.post, ) def _post(self, *args, **kwargs): return self._adapter.post(*args, **kwargs) @utils.deprecated_method( - to_be_removed_in_version='0.8.0', + to_be_removed_in_version="0.8.0", new_method=adapters.Request.put, ) def _put(self, *args, **kwargs): return self._adapter.put(*args, **kwargs) @utils.deprecated_method( - to_be_removed_in_version='0.8.0', + to_be_removed_in_version="0.8.0", new_method=adapters.Request.delete, ) def _delete(self, *args, **kwargs): @@ -2690,21 +3046,21 @@ def _delete(self, *args, **kwargs): @staticmethod @utils.deprecated_method( - to_be_removed_in_version='0.8.0', + to_be_removed_in_version="0.8.0", new_method=adapters.Request.urljoin, ) def urljoin(*args): return adapters.Request.urljoin(*args) @utils.deprecated_method( - to_be_removed_in_version='0.8.0', + to_be_removed_in_version="0.8.0", new_method=adapters.Request.request, ) def __request(self, *args, **kwargs): return self._adapter.request(*args, **kwargs) @utils.deprecated_method( - to_be_removed_in_version='0.8.0', + to_be_removed_in_version="0.8.0", new_method=utils.raise_for_error, ) def __raise_error(self, *args, **kwargs): diff --git a/requirements-dev.in b/requirements-dev.in index 771a1b241..bff9fc917 100644 --- a/requirements-dev.in +++ b/requirements-dev.in @@ -1,8 +1,9 @@ -r ./requirements.txt Authlib -flake8 +black Flask Flask-SQLAlchemy +flake8 codecov coverage ipaddress diff --git a/requirements-dev.txt b/requirements-dev.txt index ec607a8a2..1394f2631 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,50 +1,140 @@ # -# This file is autogenerated by pip-compile +# This file is autogenerated by pip-compile with python 3.8 # To update, run: # # pip-compile --output-file=requirements-dev.txt requirements-dev.in # -attrs==20.3.0 # via pytest -authlib==0.14.3 # via -r requirements-dev.in -certifi==2020.6.20 # via -r ./requirements.txt, requests -cffi==1.14.0 # via cryptography -chardet==3.0.4 # via -r ./requirements.txt, requests -click==7.1.2 # via flask -codecov==2.1.8 # via -r requirements-dev.in -coverage==5.2.1 # via -r requirements-dev.in, codecov, pytest-cov -cryptography==3.3.1 # via authlib, jwcrypto -flake8==3.8.4 # via -r requirements-dev.in -flask-sqlalchemy==2.4.4 # via -r requirements-dev.in -flask==1.1.2 # via -r requirements-dev.in, flask-sqlalchemy -idna==2.10 # via -r ./requirements.txt, requests -iniconfig==1.1.1 # via pytest -ipaddress==1.0.23 # via -r requirements-dev.in -itsdangerous==1.1.0 # via flask -jinja2==2.11.2 # via flask -jwcrypto==0.7 # via python-jwt -markupsafe==1.1.1 # via jinja2 -mccabe==0.6.1 # via flake8 -mock==3.0.5 # via -r requirements-dev.in -nose==1.3.7 # via -r requirements-dev.in -packaging==20.4 # via pytest -parameterized==0.7.4 # via -r requirements-dev.in -pluggy==0.13.1 # via pytest -py4j==0.10.9 # via python-ldap-test -py==1.9.0 # via pytest -pycodestyle==2.6.0 # via flake8 -pycparser==2.20 # via cffi -pyflakes==2.2.0 # via flake8 -pyhcl==0.4.4 # via -r ./requirements.txt -pyparsing==2.4.7 # via packaging -pytest-cov==2.11.1 # via -r requirements-dev.in -pytest==6.2.2 # via -r requirements-dev.in, pytest-cov -python-jwt==3.2.6 # via -r requirements-dev.in -python-ldap-test==0.3.1 # via -r requirements-dev.in -requests-mock==1.8.0 # via -r requirements-dev.in -requests==2.24.0 # via -r ./requirements.txt, codecov, requests-mock -semantic-version==2.8.5 # via -r requirements-dev.in -six==1.15.0 # via -r ./requirements.txt, cryptography, mock, packaging, requests-mock -sqlalchemy==1.3.18 # via flask-sqlalchemy -toml==0.10.1 # via pytest -urllib3==1.25.10 # via -r ./requirements.txt, requests -werkzeug==1.0.1 # via -r requirements-dev.in, flask +appdirs==1.4.4 + # via black +attrs==21.2.0 + # via pytest +authlib==0.15.4 + # via -r requirements-dev.in +black==21.6b0 + # via -r requirements-dev.in +certifi==2020.6.20 + # via + # -r ./requirements.txt + # requests +cffi==1.14.5 + # via cryptography +chardet==3.0.4 + # via + # -r ./requirements.txt + # requests +click==8.0.1 + # via + # black + # flask +codecov==2.1.11 + # via -r requirements-dev.in +coverage==5.5 + # via + # -r requirements-dev.in + # codecov + # pytest-cov +cryptography==3.4.7 + # via + # authlib + # jwcrypto +deprecated==1.2.12 + # via jwcrypto +flake8==3.9.2 + # via -r requirements-dev.in +flask==2.0.1 + # via + # -r requirements-dev.in + # flask-sqlalchemy +flask-sqlalchemy==2.5.1 + # via -r requirements-dev.in +greenlet==1.1.0 + # via sqlalchemy +idna==2.10 + # via + # -r ./requirements.txt + # requests +iniconfig==1.1.1 + # via pytest +ipaddress==1.0.23 + # via -r requirements-dev.in +itsdangerous==2.0.1 + # via flask +jinja2==3.0.1 + # via flask +jwcrypto==0.9.1 + # via python-jwt +markupsafe==2.0.1 + # via jinja2 +mccabe==0.6.1 + # via flake8 +mock==4.0.3 + # via -r requirements-dev.in +mypy-extensions==0.4.3 + # via black +nose==1.3.7 + # via -r requirements-dev.in +packaging==21.0 + # via pytest +parameterized==0.8.1 + # via -r requirements-dev.in +pathspec==0.8.1 + # via black +pluggy==0.13.1 + # via pytest +py==1.10.0 + # via pytest +py4j==0.10.9.2 + # via python-ldap-test +pycodestyle==2.7.0 + # via flake8 +pycparser==2.20 + # via cffi +pyflakes==2.3.1 + # via flake8 +pyhcl==0.4.4 + # via -r ./requirements.txt +pyparsing==2.4.7 + # via packaging +pytest==6.2.4 + # via + # -r requirements-dev.in + # pytest-cov +pytest-cov==2.12.1 + # via -r requirements-dev.in +python-jwt==3.3.0 + # via -r requirements-dev.in +python-ldap-test==0.3.1 + # via -r requirements-dev.in +regex==2021.7.6 + # via black +requests==2.24.0 + # via + # -r ./requirements.txt + # codecov + # requests-mock +requests-mock==1.9.3 + # via -r requirements-dev.in +semantic-version==2.8.5 + # via -r requirements-dev.in +six==1.15.0 + # via + # -r ./requirements.txt + # jwcrypto + # requests-mock +sqlalchemy==1.4.20 + # via flask-sqlalchemy +toml==0.10.2 + # via + # black + # pytest + # pytest-cov +urllib3==1.25.10 + # via + # -r ./requirements.txt + # requests +werkzeug==2.0.1 + # via + # -r requirements-dev.in + # flask +wrapt==1.12.1 + # via deprecated diff --git a/setup.py b/setup.py index 32768342d..26aec7a71 100644 --- a/setup.py +++ b/setup.py @@ -9,32 +9,31 @@ def load_long_description(): setup( - name='hvac', - version='0.10.14', - description='HashiCorp Vault API client', + name="hvac", + version="0.11.0", + description="HashiCorp Vault API client", long_description=load_long_description(), long_description_content_type="text/markdown", - author='Ian Unruh , Jeffrey Hogan ', - author_email='admin@python-hvac.org', - url='https://github.com/hvac/hvac', - keywords=['hashicorp', 'vault'], + author="Ian Unruh , Jeffrey Hogan ", + author_email="admin@python-hvac.org", + url="https://github.com/hvac/hvac", + keywords=["hashicorp", "vault"], classifiers=[ - 'License :: OSI Approved :: Apache Software License', - 'Programming Language :: Python', - 'Programming Language :: Python :: 2', - 'Programming Language :: Python :: 2.7', - 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.6', - 'Programming Language :: Python :: Implementation :: CPython', + "License :: OSI Approved :: Apache Software License", + "Programming Language :: Python", + "Programming Language :: Python :: 2", + "Programming Language :: Python :: 2.7", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: Implementation :: CPython", ], - packages=find_packages(exclude=['docs*', 'tests*']), + packages=find_packages(exclude=["docs*", "tests*"]), + python_requires=">=2.7", install_requires=[ - 'requests>=2.21.0', - 'six>=1.5.0', + "requests>=2.21.0", + "six>=1.5.0", ], include_package_data=True, - package_data={'hvac': ['version']}, - extras_require={ - 'parser': ['pyhcl>=0.3.10'] - } + package_data={"hvac": ["version"]}, + extras_require={"parser": ["pyhcl>=0.3.10"]}, ) diff --git a/tests/doctest/__init__.py b/tests/doctest/__init__.py index 978b54f8d..dfe64c4f6 100644 --- a/tests/doctest/__init__.py +++ b/tests/doctest/__init__.py @@ -14,7 +14,7 @@ def doctest_global_setup(): client = test_utils.create_client() manager = ServerManager( - config_paths=[test_utils.get_config_file_path('vault-doctest.hcl')], + config_paths=[test_utils.get_config_file_path("vault-doctest.hcl")], client=client, ) manager.start() @@ -25,45 +25,52 @@ def doctest_global_setup(): mocker.start() auth_method_paths = [ - 'ldap/login/{}'.format(MockLdapServer.ldap_user_name), + "ldap/login/{}".format(MockLdapServer.ldap_user_name), ] for auth_method_path in auth_method_paths: - mock_url = 'https://127.0.0.1:8200/v1/auth/{path}'.format(path=auth_method_path) + mock_url = "https://127.0.0.1:8200/v1/auth/{path}".format(path=auth_method_path) mock_response = { "auth": { "client_token": manager.root_token, "accessor": "0e9e354a-520f-df04-6867-ee81cae3d42d", - "policies": ['default'], + "policies": ["default"], "lease_duration": 2764800, "renewable": True, }, } mocker.register_uri( - method='POST', + method="POST", url=mock_url, json=mock_response, ) client.token = manager.root_token - os.environ['VAULT_TOKEN'] = manager.root_token - os.environ['REQUESTS_CA_BUNDLE'] = test_utils.get_config_file_path('server-cert.pem') - os.environ['LDAP_USERNAME'] = MockLdapServer.ldap_user_name - os.environ['LDAP_PASSWORD'] = MockLdapServer.ldap_user_password - os.environ['AWS_LAMBDA_FUNCTION_NAME'] = 'hvac-lambda' + os.environ["VAULT_TOKEN"] = manager.root_token + os.environ["REQUESTS_CA_BUNDLE"] = test_utils.get_config_file_path( + "server-cert.pem" + ) + os.environ["LDAP_USERNAME"] = MockLdapServer.ldap_user_name + os.environ["LDAP_PASSWORD"] = MockLdapServer.ldap_user_password + os.environ["AWS_LAMBDA_FUNCTION_NAME"] = "hvac-lambda" os.environ.setdefault("LDAP_PASSWORD", MockLdapServer.ldap_user_password) - if 'secret/' not in client.sys.list_mounted_secrets_engines()['data']: + if "secret/" not in client.sys.list_mounted_secrets_engines()["data"]: client.sys.enable_secrets_engine( - backend_type='kv', - path='secret', + backend_type="kv", + path="secret", options=dict(version=2), ) attempts = 0 - while attempts < 25 and 'secret/' not in client.sys.list_mounted_secrets_engines()['data']: + while ( + attempts < 25 + and "secret/" not in client.sys.list_mounted_secrets_engines()["data"] + ): attempts += 1 - logging.debug('Waiting 1 second for KV V2 secrets engine under path {path} to become available...'.format( - path='secret', - )) + logging.debug( + "Waiting 1 second for KV V2 secrets engine under path {path} to become available...".format( + path="secret", + ) + ) sleep(1) return manager, mocker diff --git a/tests/integration_tests/api/auth_methods/test_approle.py b/tests/integration_tests/api/auth_methods/test_approle.py index 9ef06929c..da72612e9 100644 --- a/tests/integration_tests/api/auth_methods/test_approle.py +++ b/tests/integration_tests/api/auth_methods/test_approle.py @@ -8,173 +8,152 @@ from tests.utils.hvac_integration_test_case import HvacIntegrationTestCase -@skipIf(utils.vault_version_lt('0.6.2'), "AppRole endpoints standardized in version 0.6.2") +@skipIf( + utils.vault_version_lt("0.6.2"), "AppRole endpoints standardized in version 0.6.2" +) class TestAppRole(HvacIntegrationTestCase, TestCase): - TEST_MOUNT_POINT = 'approle-test' - TEST_ROLE_NAME = 'testrole' - TEST_ROLE_ID = 'test_role_id' - TEST_SECRET_ID = 'custom_secret' + TEST_MOUNT_POINT = "approle-test" + TEST_ROLE_NAME = "testrole" + TEST_ROLE_ID = "test_role_id" + TEST_SECRET_ID = "custom_secret" def setUp(self): super(TestAppRole, self).setUp() - if '%s/' % self.TEST_MOUNT_POINT not in self.client.list_auth_backends(): - self.client.enable_auth_backend( - backend_type='approle', - mount_point=self.TEST_MOUNT_POINT, + if "%s/" % self.TEST_MOUNT_POINT not in self.client.sys.list_auth_methods(): + self.client.sys.enable_auth_method( + method_type="approle", + path=self.TEST_MOUNT_POINT, ) _ = self.client.auth.approle.create_or_update_approle( role_name=self.TEST_ROLE_NAME, - token_policies=['default'], - mount_point=self.TEST_MOUNT_POINT + token_policies=["default"], + mount_point=self.TEST_MOUNT_POINT, ) _ = self.client.auth.approle.update_role_id( role_name=self.TEST_ROLE_NAME, role_id=self.TEST_ROLE_ID, - mount_point=self.TEST_MOUNT_POINT + mount_point=self.TEST_MOUNT_POINT, ) def tearDown(self): super(TestAppRole, self).tearDown() - self.client.disable_auth_backend( - mount_point=self.TEST_MOUNT_POINT - ) + self.client.sys.disable_auth_method(path=self.TEST_MOUNT_POINT) def _secret_id(self): secret_id_response = self.client.auth.approle.generate_secret_id( role_name=self.TEST_ROLE_NAME, - cidr_list=['127.0.0.1/32'], - mount_point=self.TEST_MOUNT_POINT + cidr_list=["127.0.0.1/32"], + mount_point=self.TEST_MOUNT_POINT, ) - return secret_id_response['data'] + return secret_id_response["data"] - @parameterized.expand([ - ("create test role", 'default', None), - ("bad token type", 'bad_token', exceptions.ParamValidationError) - ]) + @parameterized.expand( + [ + ("create test role", "default", None), + ("bad token type", "bad_token", exceptions.ParamValidationError), + ] + ) def test_create_or_update_approle(self, test_label, token_type, raises): if raises is not None: with self.assertRaises(raises) as cm: self.client.auth.approle.create_or_update_approle( - role_name='testrole2', - token_policies=['default'], + role_name="testrole2", + token_policies=["default"], token_type=token_type, - mount_point=self.TEST_MOUNT_POINT + mount_point=self.TEST_MOUNT_POINT, ) - self.assertIn( - member='unsupported token_type', - container=str(cm.exception) - ) + self.assertIn(member="unsupported token_type", container=str(cm.exception)) else: response = self.client.auth.approle.create_or_update_approle( - role_name='testrole2', - token_policies=['default'], - mount_point=self.TEST_MOUNT_POINT + role_name="testrole2", + token_policies=["default"], + mount_point=self.TEST_MOUNT_POINT, ) - self.assertEqual( - first=bool(response), - second=True - ) + self.assertEqual(first=bool(response), second=True) def test_list_roles(self): response = self.client.auth.approle.list_roles( mount_point=self.TEST_MOUNT_POINT ) - self.assertEqual( - first=len(response['data']['keys']), - second=1 - ) + self.assertEqual(first=len(response["data"]["keys"]), second=1) def test_read_role(self): response = self.client.auth.approle.read_role( - role_name=self.TEST_ROLE_NAME, - mount_point=self.TEST_MOUNT_POINT + role_name=self.TEST_ROLE_NAME, mount_point=self.TEST_MOUNT_POINT ) - self.assertEqual( - first=response['data']['token_type'], - second="default" - ) + self.assertEqual(first=response["data"]["token_type"], second="default") def test_delete_role(self): response = self.client.auth.approle.delete_role( - role_name=self.TEST_ROLE_NAME, - mount_point=self.TEST_MOUNT_POINT + role_name=self.TEST_ROLE_NAME, mount_point=self.TEST_MOUNT_POINT ) - self.assertEqual( - first=204, - second=response.status_code - ) + self.assertEqual(first=204, second=response.status_code) def test_read_role_id(self): response = self.client.auth.approle.read_role_id( - role_name=self.TEST_ROLE_NAME, - mount_point=self.TEST_MOUNT_POINT + role_name=self.TEST_ROLE_NAME, mount_point=self.TEST_MOUNT_POINT ) - self.assertEqual( - first=self.TEST_ROLE_ID, - second=response['data']['role_id'] - ) + self.assertEqual(first=self.TEST_ROLE_ID, second=response["data"]["role_id"]) - @parameterized.expand([ - ("good request", None), - ("bad metadata option", exceptions.ParamValidationError) - ]) + @parameterized.expand( + [ + ("good request", None), + ("bad metadata option", exceptions.ParamValidationError), + ] + ) def test_generate_secret_id(self, test_label, raises): if raises is not None: with self.assertRaises(raises) as cm: self.client.auth.approle.generate_secret_id( role_name=self.TEST_ROLE_NAME, metadata="metadata string", - mount_point=self.TEST_MOUNT_POINT + mount_point=self.TEST_MOUNT_POINT, ) self.assertIn( - member='unsupported metadata argument', - container=str(cm.exception) + member="unsupported metadata argument", container=str(cm.exception) ) else: response = self.client.auth.approle.generate_secret_id( role_name=self.TEST_ROLE_NAME, - cidr_list=['127.0.0.1/32'], - mount_point=self.TEST_MOUNT_POINT - ) - self.assertIn( - member='secret_id', - container=response['data'] + cidr_list=["127.0.0.1/32"], + mount_point=self.TEST_MOUNT_POINT, ) - - @parameterized.expand([ - ("good request", None), - ("bad metadata option", exceptions.ParamValidationError) - ]) + self.assertIn(member="secret_id", container=response["data"]) + + @parameterized.expand( + [ + ("good request", None), + ("bad metadata option", exceptions.ParamValidationError), + ] + ) def test_create_custom_secret_id(self, test_label, raises): if raises is not None: with self.assertRaises(raises) as cm: self.client.auth.approle.create_custom_secret_id( role_name=self.TEST_ROLE_NAME, secret_id=self.TEST_SECRET_ID, - cidr_list=['127.0.0.1/32'], + cidr_list=["127.0.0.1/32"], metadata="metadata string", - mount_point=self.TEST_MOUNT_POINT + mount_point=self.TEST_MOUNT_POINT, ) self.assertIn( - member='unsupported metadata argument', - container=str(cm.exception) + member="unsupported metadata argument", container=str(cm.exception) ) else: response = self.client.auth.approle.create_custom_secret_id( role_name=self.TEST_ROLE_NAME, secret_id=self.TEST_SECRET_ID, - cidr_list=['127.0.0.1/32'], - mount_point=self.TEST_MOUNT_POINT + cidr_list=["127.0.0.1/32"], + mount_point=self.TEST_MOUNT_POINT, ) self.assertEqual( - first=self.TEST_SECRET_ID, - second=response['data']['secret_id'] + first=self.TEST_SECRET_ID, second=response["data"]["secret_id"] ) def test_read_secret_id(self): @@ -182,93 +161,74 @@ def test_read_secret_id(self): response = self.client.auth.approle.read_secret_id( role_name=self.TEST_ROLE_NAME, - secret_id=secret_id_response['secret_id'], - mount_point=self.TEST_MOUNT_POINT + secret_id=secret_id_response["secret_id"], + mount_point=self.TEST_MOUNT_POINT, ) - self.assertEqual( - first=0, - second=response['data']['secret_id_num_uses'] - ) + self.assertEqual(first=0, second=response["data"]["secret_id_num_uses"]) def test_destroy_secret_id(self): secret_id_response = self._secret_id() response = self.client.auth.approle.destroy_secret_id( role_name=self.TEST_ROLE_NAME, - secret_id=secret_id_response['secret_id'], - mount_point=self.TEST_MOUNT_POINT + secret_id=secret_id_response["secret_id"], + mount_point=self.TEST_MOUNT_POINT, ) - self.assertEqual( - first=204, - second=response.status_code - ) + self.assertEqual(first=204, second=response.status_code) def test_list_secret_id_accessors(self): self._secret_id() response = self.client.auth.approle.list_secret_id_accessors( - role_name=self.TEST_ROLE_NAME, - mount_point=self.TEST_MOUNT_POINT + role_name=self.TEST_ROLE_NAME, mount_point=self.TEST_MOUNT_POINT ) - self.assertEqual( - first=1, - second=len(response['data']['keys']) - ) + self.assertEqual(first=1, second=len(response["data"]["keys"])) def test_read_secret_id_accessor(self): secret_id_response = self._secret_id() response = self.client.auth.approle.read_secret_id_accessor( role_name=self.TEST_ROLE_NAME, - secret_id_accessor=secret_id_response['secret_id_accessor'], - mount_point=self.TEST_MOUNT_POINT + secret_id_accessor=secret_id_response["secret_id_accessor"], + mount_point=self.TEST_MOUNT_POINT, ) self.assertEqual( - first=secret_id_response['secret_id_accessor'], - second=response['data']['secret_id_accessor'] - ) - self.assertEqual( - first="127.0.0.1/32", - second=response['data']['cidr_list'][0] + first=secret_id_response["secret_id_accessor"], + second=response["data"]["secret_id_accessor"], ) + self.assertEqual(first="127.0.0.1/32", second=response["data"]["cidr_list"][0]) def test_destroy_secret_id_accessor(self): secret_id_response = self._secret_id() response = self.client.auth.approle.read_secret_id_accessor( role_name=self.TEST_ROLE_NAME, - secret_id_accessor=secret_id_response['secret_id_accessor'], - mount_point=self.TEST_MOUNT_POINT + secret_id_accessor=secret_id_response["secret_id_accessor"], + mount_point=self.TEST_MOUNT_POINT, ) self.assertEqual( - first=secret_id_response['secret_id_accessor'], - second=response['data']['secret_id_accessor'] + first=secret_id_response["secret_id_accessor"], + second=response["data"]["secret_id_accessor"], ) response = self.client.auth.approle.destroy_secret_id_accessor( role_name=self.TEST_ROLE_NAME, - secret_id_accessor=secret_id_response['secret_id_accessor'], - mount_point=self.TEST_MOUNT_POINT - ) - self.assertEqual( - first=204, - second=response.status_code + secret_id_accessor=secret_id_response["secret_id_accessor"], + mount_point=self.TEST_MOUNT_POINT, ) + self.assertEqual(first=204, second=response.status_code) def test_login(self): secret_id_response = self._secret_id() response = self.client.auth.approle.login( role_id=self.TEST_ROLE_ID, - secret_id=secret_id_response['secret_id'], - mount_point=self.TEST_MOUNT_POINT + secret_id=secret_id_response["secret_id"], + mount_point=self.TEST_MOUNT_POINT, ) - self.assertIn( - member='client_token', - container=response['auth'] - ) + self.assertIn(member="client_token", container=response["auth"]) diff --git a/tests/integration_tests/api/auth_methods/test_azure.py b/tests/integration_tests/api/auth_methods/test_azure.py index d2ffe9caa..6a6faa569 100644 --- a/tests/integration_tests/api/auth_methods/test_azure.py +++ b/tests/integration_tests/api/auth_methods/test_azure.py @@ -9,43 +9,56 @@ from tests.utils.hvac_integration_test_case import HvacIntegrationTestCase -@skipIf(utils.vault_version_lt('0.10.0'), "Azure auth method not available before Vault version 0.10.0") +@skipIf( + utils.vault_version_lt("0.10.0"), + "Azure auth method not available before Vault version 0.10.0", +) class TestAzure(HvacIntegrationTestCase, TestCase): - TEST_MOUNT_POINT = 'azure-test' + TEST_MOUNT_POINT = "azure-test" def setUp(self): super(TestAzure, self).setUp() - if '%s/' % self.TEST_MOUNT_POINT not in self.client.list_auth_backends(): - self.client.enable_auth_backend( - backend_type='azure', - mount_point=self.TEST_MOUNT_POINT, + if "%s/" % self.TEST_MOUNT_POINT not in self.client.sys.list_auth_methods(): + self.client.sys.enable_auth_method( + method_type="azure", + path=self.TEST_MOUNT_POINT, ) def tearDown(self): super(TestAzure, self).tearDown() - self.client.disable_auth_backend( - mount_point=self.TEST_MOUNT_POINT, + self.client.sys.disable_auth_method( + path=self.TEST_MOUNT_POINT, ) - @parameterized.expand([ - param( - 'tenant_id and resource', - ), - param( - 'client id and secret', - client_id='my-client-id', - client_secret='my-client-secert' - ), - param( - 'invalid environment', - environment='AzurePublicCats', - raises=exceptions.ParamValidationError, - exception_message='invalid environment argument provided' - ), - ]) - def test_configure(self, label, client_id=None, client_secret=None, environment='AzurePublicCloud', raises=None, exception_message=''): - tenant_id = 'my-tenant-id' - resource = 'my-resource' + @parameterized.expand( + [ + param( + "tenant_id and resource", + ), + param( + "client id and secret", + client_id="my-client-id", + client_secret="my-client-secert", + ), + param( + "invalid environment", + environment="AzurePublicCats", + raises=exceptions.ParamValidationError, + exception_message="invalid environment argument provided", + ), + ] + ) + def test_configure( + self, + label, + client_id=None, + client_secret=None, + environment="AzurePublicCloud", + raises=None, + exception_message="", + ): + tenant_id = "my-tenant-id" + resource = "my-resource" if raises: with self.assertRaises(raises) as cm: self.client.auth.azure.configure( @@ -69,31 +82,32 @@ def test_configure(self, label, client_id=None, client_secret=None, environment= environment=environment, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('configure_response: %s' % configure_response) + logging.debug("configure_response: %s" % configure_response) self.assertEqual( first=bool(configure_response), second=True, ) - @parameterized.expand([ - param( - 'success', - ), - param( - 'no config written yet', - write_config_first=False, - raises=exceptions.InvalidPath - ) - ]) + @parameterized.expand( + [ + param( + "success", + ), + param( + "no config written yet", + write_config_first=False, + raises=exceptions.InvalidPath, + ), + ] + ) def test_read_config(self, label, write_config_first=True, raises=None): expected_config = { - 'tenant_id': 'my-tenant-id', - 'resource': 'my-resource', + "tenant_id": "my-tenant-id", + "resource": "my-resource", } if write_config_first: self.client.auth.azure.configure( - mount_point=self.TEST_MOUNT_POINT, - **expected_config + mount_point=self.TEST_MOUNT_POINT, **expected_config ) if raises is not None: with self.assertRaises(raises): @@ -104,66 +118,77 @@ def test_read_config(self, label, write_config_first=True, raises=None): read_config_response = self.client.auth.azure.read_config( mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('read_config_response: %s' % read_config_response) + logging.debug("read_config_response: %s" % read_config_response) for k, v in expected_config.items(): self.assertEqual( first=v, second=read_config_response[k], ) - @parameterized.expand([ - ('success',), - ]) + @parameterized.expand( + [ + ("success",), + ] + ) def test_delete_config(self, label): delete_config_response = self.client.auth.azure.delete_config( mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('delete_config_response: %s' % delete_config_response) + logging.debug("delete_config_response: %s" % delete_config_response) self.assertEqual( first=bool(delete_config_response), second=True, ) - @parameterized.expand([ - param( - 'success', - bound_service_principal_ids=['my-sp-id'], - ), - param( - 'CSV policies arg', - bound_service_principal_ids=['my-sp-id'], - policies='cats,dogs', - ), - param( - 'list policies arg', - bound_service_principal_ids=['my-sp-id'], - policies=['cats', 'dogs'], - ), - param( - 'no bound constraints', - raises=exceptions.InvalidRequest, - exception_message='must have at least one bound constraint when creating/updating a role', - ), - param( - 'wrong policy arg type', - bound_service_principal_ids=['my-sp-id'], - policies={'dict': 'bad'}, - raises=exceptions.ParamValidationError, - exception_message='unsupported policies argument provided', - ), - param( - 'mixed policy arg type', - bound_service_principal_ids=['my-sp-id'], - policies=['cats', 'dogs', None, 42], - raises=exceptions.ParamValidationError, - exception_message='unsupported policies argument provided', - ) - ]) - def test_create_role(self, label, policies=None, bound_service_principal_ids=None, raises=None, exception_message=''): + @parameterized.expand( + [ + param( + "success", + bound_service_principal_ids=["my-sp-id"], + ), + param( + "CSV policies arg", + bound_service_principal_ids=["my-sp-id"], + policies="cats,dogs", + ), + param( + "list policies arg", + bound_service_principal_ids=["my-sp-id"], + policies=["cats", "dogs"], + ), + param( + "no bound constraints", + raises=exceptions.InvalidRequest, + exception_message="must have at least one bound constraint when creating/updating a role", + ), + param( + "wrong policy arg type", + bound_service_principal_ids=["my-sp-id"], + policies={"dict": "bad"}, + raises=exceptions.ParamValidationError, + exception_message="unsupported policies argument provided", + ), + param( + "mixed policy arg type", + bound_service_principal_ids=["my-sp-id"], + policies=["cats", "dogs", None, 42], + raises=exceptions.ParamValidationError, + exception_message="unsupported policies argument provided", + ), + ] + ) + def test_create_role( + self, + label, + policies=None, + bound_service_principal_ids=None, + raises=None, + exception_message="", + ): if raises: with self.assertRaises(raises) as cm: self.client.auth.azure.create_role( - name='my-role', + name="my-role", policies=policies, bound_service_principal_ids=bound_service_principal_ids, mount_point=self.TEST_MOUNT_POINT, @@ -174,36 +199,45 @@ def test_create_role(self, label, policies=None, bound_service_principal_ids=Non ) else: create_role_response = self.client.auth.azure.create_role( - name='my-role', + name="my-role", policies=policies, bound_service_principal_ids=bound_service_principal_ids, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('create_role_response: %s' % create_role_response) + logging.debug("create_role_response: %s" % create_role_response) self.assertEqual( first=bool(create_role_response), second=True, ) - @parameterized.expand([ - param( - 'success', - ), - param( - 'nonexistent role name', - configure_role_first=False, - raises=exceptions.InvalidPath, - ), - ]) - def test_read_role(self, label, role_name='hvac', configure_role_first=True, raises=None, exception_message=''): - bound_service_principal_ids = ['some-dummy-sp-id'] + @parameterized.expand( + [ + param( + "success", + ), + param( + "nonexistent role name", + configure_role_first=False, + raises=exceptions.InvalidPath, + ), + ] + ) + def test_read_role( + self, + label, + role_name="hvac", + configure_role_first=True, + raises=None, + exception_message="", + ): + bound_service_principal_ids = ["some-dummy-sp-id"] if configure_role_first: create_role_response = self.client.auth.azure.create_role( name=role_name, bound_service_principal_ids=bound_service_principal_ids, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('create_role_response: %s' % create_role_response) + logging.debug("create_role_response: %s" % create_role_response) if raises is not None: with self.assertRaises(raises): @@ -216,43 +250,47 @@ def test_read_role(self, label, role_name='hvac', configure_role_first=True, rai name=role_name, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('read_role_response: %s' % read_role_response) + logging.debug("read_role_response: %s" % read_role_response) self.assertEqual( - first=read_role_response['bound_service_principal_ids'], + first=read_role_response["bound_service_principal_ids"], second=bound_service_principal_ids, ) - @parameterized.expand([ - param( - 'success', - ), - param( - 'no roles', - num_roles_to_create=0, - raises=exceptions.InvalidPath, - ), - param( - 'no config', - write_config_first=False, - ), - ]) - def test_list_roles(self, label, num_roles_to_create=1, write_config_first=True, raises=None): + @parameterized.expand( + [ + param( + "success", + ), + param( + "no roles", + num_roles_to_create=0, + raises=exceptions.InvalidPath, + ), + param( + "no config", + write_config_first=False, + ), + ] + ) + def test_list_roles( + self, label, num_roles_to_create=1, write_config_first=True, raises=None + ): if write_config_first: self.client.auth.azure.configure( - tenant_id='my-tenant-id', - resource='my-resource', + tenant_id="my-tenant-id", + resource="my-resource", mount_point=self.TEST_MOUNT_POINT, ) - roles_to_create = ['hvac%s' % n for n in range(0, num_roles_to_create)] - bound_service_principal_ids = ['some-dummy-sp-id'] - logging.debug('roles_to_create: %s' % roles_to_create) + roles_to_create = ["hvac%s" % n for n in range(0, num_roles_to_create)] + bound_service_principal_ids = ["some-dummy-sp-id"] + logging.debug("roles_to_create: %s" % roles_to_create) for role_to_create in roles_to_create: create_role_response = self.client.auth.azure.create_role( name=role_to_create, bound_service_principal_ids=bound_service_principal_ids, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('create_role_response: %s' % create_role_response) + logging.debug("create_role_response: %s" % create_role_response) if raises is not None: with self.assertRaises(raises): @@ -263,31 +301,33 @@ def test_list_roles(self, label, num_roles_to_create=1, write_config_first=True, list_roles_response = self.client.auth.azure.list_roles( mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('read_role_response: %s' % list_roles_response) + logging.debug("read_role_response: %s" % list_roles_response) self.assertEqual( - first=list_roles_response['keys'], + first=list_roles_response["keys"], second=roles_to_create, ) - @parameterized.expand([ - param( - 'success', - ), - param( - 'nonexistent role name', - configure_role_first=False, - ), - ]) + @parameterized.expand( + [ + param( + "success", + ), + param( + "nonexistent role name", + configure_role_first=False, + ), + ] + ) def test_delete_role(self, label, configure_role_first=True, raises=None): - role_name = 'hvac' - bound_service_principal_ids = ['some-dummy-sp-id'] + role_name = "hvac" + bound_service_principal_ids = ["some-dummy-sp-id"] if configure_role_first: create_role_response = self.client.auth.azure.create_role( name=role_name, bound_service_principal_ids=bound_service_principal_ids, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('create_role_response: %s' % create_role_response) + logging.debug("create_role_response: %s" % create_role_response) if raises is not None: with self.assertRaises(raises): @@ -300,7 +340,7 @@ def test_delete_role(self, label, configure_role_first=True, raises=None): name=role_name, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('delete_role_response: %s' % delete_role_response) + logging.debug("delete_role_response: %s" % delete_role_response) self.assertEqual( first=bool(delete_role_response), second=True, diff --git a/tests/integration_tests/api/auth_methods/test_cert.py b/tests/integration_tests/api/auth_methods/test_cert.py index 525ab4f14..c805eaef6 100644 --- a/tests/integration_tests/api/auth_methods/test_cert.py +++ b/tests/integration_tests/api/auth_methods/test_cert.py @@ -1,26 +1,24 @@ from unittest import TestCase -from unittest import skipIf +from hvac import exceptions from parameterized import parameterized - -from hvac import exceptions, Client from tests import utils from tests.utils.hvac_integration_test_case import HvacIntegrationTestCase -import pytest + class TestCert(HvacIntegrationTestCase, TestCase): - TEST_MOUNT_POINT = 'cert-test' - TEST_ROLE_NAME = 'testrole' - cert = utils.create_client()._adapter._kwargs.get('cert') - with open(utils.get_config_file_path('client-cert.pem')) as fp: + TEST_MOUNT_POINT = "cert-test" + TEST_ROLE_NAME = "testrole" + cert = utils.create_client()._adapter._kwargs.get("cert") + with open(utils.get_config_file_path("client-cert.pem")) as fp: TEST_CERTIFICATE = fp.read() def setUp(self): super(TestCert, self).setUp() - if '%s/' % self.TEST_MOUNT_POINT not in self.client.list_auth_backends(): - self.client.enable_auth_backend( - backend_type='cert', - mount_point=self.TEST_MOUNT_POINT, + if "%s/" % self.TEST_MOUNT_POINT not in self.client.sys.list_auth_methods(): + self.client.sys.enable_auth_method( + method_type="cert", + path=self.TEST_MOUNT_POINT, ) _ = self.client.auth.cert.create_ca_certificate_role( name=self.TEST_ROLE_NAME, @@ -33,15 +31,12 @@ def tearDown(self): def test_create_ca_certificate_role(self): response = self.client.auth.cert.create_ca_certificate_role( - name='testrole2', + name="testrole2", certificate=self.TEST_CERTIFICATE, mount_point=self.TEST_MOUNT_POINT, ) - self.assertEqual( - first=204, - second=response.status_code - ) + self.assertEqual(first=204, second=response.status_code) def test_read_ca_certificate_role(self): response = self.client.auth.cert.read_ca_certificate_role( @@ -51,7 +46,7 @@ def test_read_ca_certificate_role(self): self.assertEqual( first=self.TEST_ROLE_NAME, - second=response['data']['display_name'], + second=response["data"]["display_name"], ) def test_list_certificate_roles(self): @@ -59,49 +54,39 @@ def test_list_certificate_roles(self): mount_point=self.TEST_MOUNT_POINT, ) - self.assertEqual( - first=response['data']['keys'], - second=[self.TEST_ROLE_NAME] - ) + self.assertEqual(first=response["data"]["keys"], second=[self.TEST_ROLE_NAME]) def test_delete_certificate_role(self): self.client.auth.cert.create_ca_certificate_role( - name='testrole2', + name="testrole2", certificate=self.TEST_CERTIFICATE, mount_point=self.TEST_MOUNT_POINT, ) response = self.client.auth.cert.delete_certificate_role( - name='testrole2', + name="testrole2", mount_point=self.TEST_MOUNT_POINT, ) - self.assertEqual( - first=204, - second=response.status_code - ) + self.assertEqual(first=204, second=response.status_code) def test_configure_tls_certificate(self): - response = self.client.auth.cert.configure_tls_certificate(mount_point=self.TEST_MOUNT_POINT) - - self.assertEqual( - first=204, - second=response.status_code + response = self.client.auth.cert.configure_tls_certificate( + mount_point=self.TEST_MOUNT_POINT ) - def test_auth_tls_deprecation(self): - # In order to raise this it is just easier to expect it to fail. - with self.assertRaises(OSError): - pytest.deprecated_call(Client().auth_tls()) - - @parameterized.expand([ - (TEST_ROLE_NAME, "", cert[0], cert[1], TEST_MOUNT_POINT), - ("", "", cert[0], cert[1], TEST_MOUNT_POINT), - ("testrole2", "", cert[0], cert[1], TEST_MOUNT_POINT), - ("", "", "bad cert", cert[1], TEST_MOUNT_POINT), - ("", "bad ca", cert[0], cert[1], TEST_MOUNT_POINT), - ("", True, cert[0], cert[1], TEST_MOUNT_POINT), - ("", False, " ", " ", TEST_MOUNT_POINT) - ]) + self.assertEqual(first=204, second=response.status_code) + + @parameterized.expand( + [ + (TEST_ROLE_NAME, "", cert[0], cert[1], TEST_MOUNT_POINT), + ("", "", cert[0], cert[1], TEST_MOUNT_POINT), + ("testrole2", "", cert[0], cert[1], TEST_MOUNT_POINT), + ("", "", "bad cert", cert[1], TEST_MOUNT_POINT), + ("", "bad ca", cert[0], cert[1], TEST_MOUNT_POINT), + ("", True, cert[0], cert[1], TEST_MOUNT_POINT), + ("", False, " ", " ", TEST_MOUNT_POINT), + ] + ) def test_login(self, name, cacert, cert_pem, key_pem, mount_point): if cacert or "bad" in [cacert, cert_pem, key_pem]: with self.assertRaises(exceptions.ParamValidationError): @@ -119,9 +104,13 @@ def test_login(self, name, cacert, cert_pem, key_pem, mount_point): # cert_pem=cert_pem, # mount_point=mount_point, # ) - elif name != "" and name not in self.client.auth.cert.list_certificate_roles( - mount_point=self.TEST_MOUNT_POINT, - )['data']['keys']: + elif ( + name != "" + and name + not in self.client.auth.cert.list_certificate_roles( + mount_point=self.TEST_MOUNT_POINT, + )["data"]["keys"] + ): with self.assertRaises(exceptions.InvalidRequest): with self.assertRaises(OSError): self.client.auth.cert.login( @@ -146,6 +135,9 @@ def test_login(self, name, cacert, cert_pem, key_pem, mount_point): mount_point=mount_point, ) - if name in [self.TEST_ROLE_NAME, ""] and (cacert, cert_pem, key_pem) == ("", self.cert[0], self.cert[1]): + if name in [self.TEST_ROLE_NAME, ""] and (cacert, cert_pem, key_pem) == ( + "", + self.cert[0], + self.cert[1], + ): self.assertIsInstance(response, dict) - diff --git a/tests/integration_tests/api/auth_methods/test_gcp.py b/tests/integration_tests/api/auth_methods/test_gcp.py index 46e3781e9..7b24ec95d 100644 --- a/tests/integration_tests/api/auth_methods/test_gcp.py +++ b/tests/integration_tests/api/auth_methods/test_gcp.py @@ -10,34 +10,36 @@ class TestGcp(HvacIntegrationTestCase, TestCase): - TEST_MOUNT_POINT = 'gcp-test' + TEST_MOUNT_POINT = "gcp-test" def setUp(self): super(TestGcp, self).setUp() - if '%s/' % self.TEST_MOUNT_POINT not in self.client.list_auth_backends(): - self.client.enable_auth_backend( - backend_type='gcp', - mount_point=self.TEST_MOUNT_POINT, + if "%s/" % self.TEST_MOUNT_POINT not in self.client.sys.list_auth_methods(): + self.client.sys.enable_auth_method( + method_type="gcp", + path=self.TEST_MOUNT_POINT, ) def tearDown(self): super(TestGcp, self).tearDown() - self.client.disable_auth_backend( - mount_point=self.TEST_MOUNT_POINT, + self.client.sys.disable_auth_method( + path=self.TEST_MOUNT_POINT, ) - @parameterized.expand([ - param( - 'success', - credentials=utils.load_config_file('example.jwt.json'), - ), - param( - 'set invalid credentials', - credentials='some invalid JWT', - raises=exceptions.InvalidRequest, - ), - ]) - def test_configure(self, label, credentials='', raises=None): + @parameterized.expand( + [ + param( + "success", + credentials=utils.load_config_file("example.jwt.json"), + ), + param( + "set invalid credentials", + credentials="some invalid JWT", + raises=exceptions.InvalidRequest, + ), + ] + ) + def test_configure(self, label, credentials="", raises=None): if raises: with self.assertRaises(raises): self.client.auth.gcp.configure( @@ -49,20 +51,22 @@ def test_configure(self, label, credentials='', raises=None): credentials=credentials, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('configure_response: %s' % configure_response) + logging.debug("configure_response: %s" % configure_response) self.assertEqual( first=bool(configure_response), second=True, ) - @parameterized.expand([ - param( - 'success', - ), - ]) + @parameterized.expand( + [ + param( + "success", + ), + ] + ) def test_read_config(self, label): - credentials = utils.load_config_file('example.jwt.json') + credentials = utils.load_config_file("example.jwt.json") self.client.auth.gcp.configure( credentials=credentials, mount_point=self.TEST_MOUNT_POINT, @@ -70,13 +74,13 @@ def test_read_config(self, label): read_config_response = self.client.auth.gcp.read_config( mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('read_config_response: %s' % read_config_response) + logging.debug("read_config_response: %s" % read_config_response) creds_dict = json.loads(credentials) expected_config = { - 'project_id': creds_dict['project_id'], - 'client_email': creds_dict['client_email'], - 'private_key_id': creds_dict['private_key_id'], + "project_id": creds_dict["project_id"], + "client_email": creds_dict["client_email"], + "private_key_id": creds_dict["private_key_id"], } for k, v in expected_config.items(): self.assertEqual( @@ -84,16 +88,18 @@ def test_read_config(self, label): second=read_config_response[k], ) - @parameterized.expand([ - # param( - # 'success', # TODO: figure out why this is returning a 405 - # ), - param( - 'no existing config', - write_config_first=False, - raises=exceptions.UnexpectedError, - ), - ]) + @parameterized.expand( + [ + # param( + # 'success', # TODO: figure out why this is returning a 405 + # ), + param( + "no existing config", + write_config_first=False, + raises=exceptions.UnexpectedError, + ), + ] + ) def test_delete_config(self, label, write_config_first=True, raises=None): if write_config_first: @@ -109,38 +115,44 @@ def test_delete_config(self, label, write_config_first=True, raises=None): delete_config_response = self.client.auth.gcp.delete_config( mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('delete_config_response: %s' % delete_config_response) + logging.debug("delete_config_response: %s" % delete_config_response) self.assertEqual( first=bool(delete_config_response), second=True, ) - @parameterized.expand([ - param( - 'success iam', - role_type='iam', - bound_service_accounts=['*'] - ), - param( - 'iam no bound service account', - role_type='iam', - raises=exceptions.InvalidRequest, - exception_message='IAM role type must have at least one service account', - ), - param( - 'success gce', - role_type='gce', - ), - param( - 'invalid role type', - role_type='hvac', - raises=exceptions.ParamValidationError, - exception_message='unsupported role_type argument provided', - ), - ]) - def test_create_role(self, label, role_type, policies=None, bound_service_accounts=None, raises=None, exception_message=''): - role_name = 'hvac' - project_id = 'test-hvac-project-not-a-real-project' + @parameterized.expand( + [ + param("success iam", role_type="iam", bound_service_accounts=["*"]), + param( + "iam no bound service account", + role_type="iam", + raises=exceptions.InvalidRequest, + exception_message="IAM role type must have at least one service account", + ), + param( + "success gce", + role_type="gce", + ), + param( + "invalid role type", + role_type="hvac", + raises=exceptions.ParamValidationError, + exception_message="unsupported role_type argument provided", + ), + ] + ) + def test_create_role( + self, + label, + role_type, + policies=None, + bound_service_accounts=None, + raises=None, + exception_message="", + ): + role_name = "hvac" + project_id = "test-hvac-project-not-a-real-project" if raises: with self.assertRaises(raises) as cm: self.client.auth.gcp.create_role( @@ -164,37 +176,49 @@ def test_create_role(self, label, role_type, policies=None, bound_service_accoun bound_service_accounts=bound_service_accounts, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('create_role_response: %s' % create_role_response) + logging.debug("create_role_response: %s" % create_role_response) self.assertEqual( first=bool(create_role_response), second=True, ) - @parameterized.expand([ - param( - 'success add', - add=['test'], - ), - param( - 'success remove', - remove=['test'], - ), - param( - 'fail upon no changes', - raises=exceptions.InvalidRequest, - exception_message='must provide at least one value to add or remove', - ), - # TODO: wrong role type (gce) - ]) - def test_edit_service_accounts_on_iam_role(self, label, add=None, remove=None, create_role_first=True, raises=None, exception_message=''): - role_name = 'hvac' - project_id = 'test-hvac-project-not-a-real-project' + @parameterized.expand( + [ + param( + "success add", + add=["test"], + ), + param( + "success remove", + remove=["test"], + ), + param( + "fail upon no changes", + raises=exceptions.InvalidRequest, + exception_message="must provide at least one value to add or remove", + ), + # TODO: wrong role type (gce) + ] + ) + def test_edit_service_accounts_on_iam_role( + self, + label, + add=None, + remove=None, + create_role_first=True, + raises=None, + exception_message="", + ): + role_name = "hvac" + project_id = "test-hvac-project-not-a-real-project" if create_role_first: self.client.auth.gcp.create_role( name=role_name, - role_type='iam', + role_type="iam", project_id=project_id, - bound_service_accounts=['hvac-integration-test@appspot.gserviceaccount.com'], + bound_service_accounts=[ + "hvac-integration-test@appspot.gserviceaccount.com" + ], mount_point=self.TEST_MOUNT_POINT, ) if raises: @@ -210,43 +234,57 @@ def test_edit_service_accounts_on_iam_role(self, label, add=None, remove=None, c container=str(cm.exception), ) else: - edit_sa_on_iam_response = self.client.auth.gcp.edit_service_accounts_on_iam_role( - name=role_name, - add=add, - remove=remove, - mount_point=self.TEST_MOUNT_POINT, + edit_sa_on_iam_response = ( + self.client.auth.gcp.edit_service_accounts_on_iam_role( + name=role_name, + add=add, + remove=remove, + mount_point=self.TEST_MOUNT_POINT, + ) ) - logging.debug('create_role_response: %s' % edit_sa_on_iam_response) + logging.debug("create_role_response: %s" % edit_sa_on_iam_response) self.assertEqual( first=bool(edit_sa_on_iam_response), second=True, ) - @parameterized.expand([ - param( - 'success add', - add=['test-key:test-value'], - ), - param( - 'success remove', - remove=['test-key:test-value'], - ), - param( - 'fail upon no changes', - raises=exceptions.InvalidRequest, - exception_message='must provide at least one value to add or remove', - ), - # TODO: wrong role type (iam) - ]) - def test_edit_labels_on_gce_role(self, label, add=None, remove=None, create_role_first=True, raises=None, exception_message=''): - role_name = 'hvac' - project_id = 'test-hvac-project-not-a-real-project' + @parameterized.expand( + [ + param( + "success add", + add=["test-key:test-value"], + ), + param( + "success remove", + remove=["test-key:test-value"], + ), + param( + "fail upon no changes", + raises=exceptions.InvalidRequest, + exception_message="must provide at least one value to add or remove", + ), + # TODO: wrong role type (iam) + ] + ) + def test_edit_labels_on_gce_role( + self, + label, + add=None, + remove=None, + create_role_first=True, + raises=None, + exception_message="", + ): + role_name = "hvac" + project_id = "test-hvac-project-not-a-real-project" if create_role_first: self.client.auth.gcp.create_role( name=role_name, - role_type='gce', + role_type="gce", project_id=project_id, - bound_service_accounts=['hvac-integration-test@appspot.gserviceaccount.com'], + bound_service_accounts=[ + "hvac-integration-test@appspot.gserviceaccount.com" + ], mount_point=self.TEST_MOUNT_POINT, ) if raises: @@ -268,31 +306,37 @@ def test_edit_labels_on_gce_role(self, label, add=None, remove=None, create_role remove=remove, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('create_role_response: %s' % edit_labled_response) + logging.debug("create_role_response: %s" % edit_labled_response) self.assertEqual( first=bool(edit_labled_response), second=True, ) - @parameterized.expand([ - param( - 'success', - ), - param( - 'nonexistent role', - create_role_first=False, - raises=exceptions.InvalidPath, - ), - ]) - def test_read_role(self, label, create_role_first=True, raises=None, exception_message=''): - role_name = 'hvac' - project_id = 'test-hvac-project-not-a-real-project' + @parameterized.expand( + [ + param( + "success", + ), + param( + "nonexistent role", + create_role_first=False, + raises=exceptions.InvalidPath, + ), + ] + ) + def test_read_role( + self, label, create_role_first=True, raises=None, exception_message="" + ): + role_name = "hvac" + project_id = "test-hvac-project-not-a-real-project" if create_role_first: self.client.auth.gcp.create_role( name=role_name, - role_type='gce', + role_type="gce", project_id=project_id, - bound_service_accounts=['hvac-integration-test@appspot.gserviceaccount.com'], + bound_service_accounts=[ + "hvac-integration-test@appspot.gserviceaccount.com" + ], mount_point=self.TEST_MOUNT_POINT, ) if raises: @@ -310,45 +354,46 @@ def test_read_role(self, label, create_role_first=True, raises=None, exception_m name=role_name, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('create_role_response: %s' % read_role_response) - if utils.vault_version_ge('1.0.0'): - returned_project_id = read_role_response['bound_projects'] + logging.debug("create_role_response: %s" % read_role_response) + if utils.vault_version_ge("1.0.0"): + returned_project_id = read_role_response["bound_projects"] expected_project_id = [project_id] else: - returned_project_id = read_role_response['project_id'] + returned_project_id = read_role_response["project_id"] expected_project_id = project_id - self.assertEqual( - first=returned_project_id, - second=expected_project_id - ) + self.assertEqual(first=returned_project_id, second=expected_project_id) - @parameterized.expand([ - param( - 'success one role', - ), - param( - 'success multiple roles', - num_roles_to_create=7, - ), - param( - 'no roles', - num_roles_to_create=0, - raises=exceptions.InvalidPath, - ), - ]) + @parameterized.expand( + [ + param( + "success one role", + ), + param( + "success multiple roles", + num_roles_to_create=7, + ), + param( + "no roles", + num_roles_to_create=0, + raises=exceptions.InvalidPath, + ), + ] + ) def test_list_roles(self, label, num_roles_to_create=1, raises=None): - project_id = 'test-hvac-project-not-a-real-project' - roles_to_create = ['hvac%s' % n for n in range(0, num_roles_to_create)] - logging.debug('roles_to_create: %s' % roles_to_create) + project_id = "test-hvac-project-not-a-real-project" + roles_to_create = ["hvac%s" % n for n in range(0, num_roles_to_create)] + logging.debug("roles_to_create: %s" % roles_to_create) for role_to_create in roles_to_create: create_role_response = self.client.auth.gcp.create_role( name=role_to_create, - role_type='gce', + role_type="gce", project_id=project_id, - bound_service_accounts=['hvac-integration-test@appspot.gserviceaccount.com'], + bound_service_accounts=[ + "hvac-integration-test@appspot.gserviceaccount.com" + ], mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('create_role_response: %s' % create_role_response) + logging.debug("create_role_response: %s" % create_role_response) if raises is not None: with self.assertRaises(raises): @@ -359,33 +404,37 @@ def test_list_roles(self, label, num_roles_to_create=1, raises=None): list_roles_response = self.client.auth.gcp.list_roles( mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('list_roles_response: %s' % list_roles_response) + logging.debug("list_roles_response: %s" % list_roles_response) self.assertEqual( - first=list_roles_response['keys'], + first=list_roles_response["keys"], second=roles_to_create, ) - @parameterized.expand([ - param( - 'success', - ), - param( - 'nonexistent role name', - configure_role_first=False, - ), - ]) + @parameterized.expand( + [ + param( + "success", + ), + param( + "nonexistent role name", + configure_role_first=False, + ), + ] + ) def test_delete_role(self, label, configure_role_first=True, raises=None): - role_name = 'hvac' - project_id = 'test-hvac-project-not-a-real-project' + role_name = "hvac" + project_id = "test-hvac-project-not-a-real-project" if configure_role_first: create_role_response = self.client.auth.gcp.create_role( name=role_name, - role_type='gce', + role_type="gce", project_id=project_id, - bound_service_accounts=['hvac-integration-test@appspot.gserviceaccount.com'], + bound_service_accounts=[ + "hvac-integration-test@appspot.gserviceaccount.com" + ], mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('create_role_response: %s' % create_role_response) + logging.debug("create_role_response: %s" % create_role_response) if raises is not None: with self.assertRaises(raises): @@ -398,7 +447,7 @@ def test_delete_role(self, label, configure_role_first=True, raises=None): role=role_name, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('delete_role_response: %s' % delete_role_response) + logging.debug("delete_role_response: %s" % delete_role_response) self.assertEqual( first=bool(delete_role_response), second=True, diff --git a/tests/integration_tests/api/auth_methods/test_github.py b/tests/integration_tests/api/auth_methods/test_github.py index b45487321..c3960a4c5 100644 --- a/tests/integration_tests/api/auth_methods/test_github.py +++ b/tests/integration_tests/api/auth_methods/test_github.py @@ -1,24 +1,17 @@ import logging +from http.server import HTTPServer from threading import Thread from unittest import TestCase -from parameterized import parameterized - from hvac import exceptions +from parameterized import parameterized from tests import utils from tests.utils.hvac_integration_test_case import HvacIntegrationTestCase from tests.utils.mock_github_request_handler import MockGithubRequestHandler -try: - # Python 2.7 - from http.server import HTTPServer -except ImportError: - # Python 3.x - from BaseHTTPServer import HTTPServer - class TestGithub(HvacIntegrationTestCase, TestCase): - TEST_GITHUB_PATH = 'test-github' + TEST_GITHUB_PATH = "test-github" @classmethod def setUpClass(cls): @@ -27,7 +20,9 @@ def setUpClass(cls): # Configure mock server. cls.mock_server_port = utils.get_free_port() - cls.mock_server = HTTPServer(('localhost', cls.mock_server_port), MockGithubRequestHandler) + cls.mock_server = HTTPServer( + ("localhost", cls.mock_server_port), MockGithubRequestHandler + ) # Start running mock server in a separate thread. # Daemon threads automatically shut down when the main process exits. @@ -42,7 +37,7 @@ def setUpClass(cls): def setUp(self): super(TestGithub, self).setUp() self.client.sys.enable_auth_method( - method_type='github', + method_type="github", path=self.TEST_GITHUB_PATH, ) @@ -52,10 +47,21 @@ def tearDown(self): path=self.TEST_GITHUB_PATH, ) - @parameterized.expand([ - ("just organization", True, 'some-test-org', '', 0, 0, TEST_GITHUB_PATH), - ]) - def test_configure(self, test_label, expected_value, organization, base_url, ttl, max_ttl, mount_point): + @parameterized.expand( + [ + ("just organization", True, "some-test-org", "", 0, 0, TEST_GITHUB_PATH), + ] + ) + def test_configure( + self, + test_label, + expected_value, + organization, + base_url, + ttl, + max_ttl, + mount_point, + ): response = self.client.auth.github.configure( organization=organization, base_url=base_url, @@ -68,15 +74,19 @@ def test_configure(self, test_label, expected_value, organization, base_url, ttl second=bool(response), ) - @parameterized.expand([ - ("just organization", 'some-test-org', '/', '', ''), - ("different base url", 'some-test-org', 'https://cathub.example/', '', ''), - ("custom ttl seconds", 'some-test-org', '/', '500s', ''), - ("custom ttl minutes", 'some-test-org', '/', '500m', ''), - ("custom ttl hours", 'some-test-org', '/', '500h', ''), - ("custom max ttl", 'some-test-org', '/', '', '500s'), - ]) - def test_configure_and_read_configuration(self, test_label, organization, base_url, ttl, max_ttl): + @parameterized.expand( + [ + ("just organization", "some-test-org", "/", "", ""), + ("different base url", "some-test-org", "https://cathub.example/", "", ""), + ("custom ttl seconds", "some-test-org", "/", "500s", ""), + ("custom ttl minutes", "some-test-org", "/", "500m", ""), + ("custom ttl hours", "some-test-org", "/", "500h", ""), + ("custom max ttl", "some-test-org", "/", "", "500s"), + ] + ) + def test_configure_and_read_configuration( + self, test_label, organization, base_url, ttl, max_ttl + ): config_response = self.client.auth.github.configure( organization=organization, base_url=base_url, @@ -84,39 +94,42 @@ def test_configure_and_read_configuration(self, test_label, organization, base_u max_ttl=max_ttl, mount_point=self.TEST_GITHUB_PATH, ) - logging.debug('config_response: {}'.format(config_response)) - self.assertEqual( - first=204, - second=config_response.status_code - ) + logging.debug("config_response: {}".format(config_response)) + self.assertEqual(first=204, second=config_response.status_code) read_config_response = self.client.auth.github.read_configuration( mount_point=self.TEST_GITHUB_PATH, ) - logging.debug('read_config_response: {}'.format(read_config_response)) + logging.debug("read_config_response: {}".format(read_config_response)) self.assertEqual( - first=organization, - second=read_config_response['data']['organization'] + first=organization, second=read_config_response["data"]["organization"] ) self.assertEqual( - first=base_url, - second=read_config_response['data']['base_url'] + first=base_url, second=read_config_response["data"]["base_url"] + ) + ttl_data_key = "token_ttl" if utils.vault_version_ge("1.2.0") else "ttl" + max_ttl_data_key = ( + "token_max_ttl" if utils.vault_version_ge("1.2.0") else "max_ttl" ) - ttl_data_key = 'token_ttl' if utils.vault_version_ge('1.2.0') else 'ttl' - max_ttl_data_key = 'token_max_ttl' if utils.vault_version_ge('1.2.0') else 'max_ttl' self.assertEqual( - first=self.convert_python_ttl_value_to_expected_vault_response(ttl_value=ttl), - second=read_config_response['data'][ttl_data_key] + first=self.convert_python_ttl_value_to_expected_vault_response( + ttl_value=ttl + ), + second=read_config_response["data"][ttl_data_key], ) self.assertEqual( - first=self.convert_python_ttl_value_to_expected_vault_response(ttl_value=max_ttl), - second=read_config_response['data'][max_ttl_data_key] + first=self.convert_python_ttl_value_to_expected_vault_response( + ttl_value=max_ttl + ), + second=read_config_response["data"][max_ttl_data_key], ) - @parameterized.expand([ - ("no policies", True, 'hvac', None), - ("with policies", True, 'hvac', ['default']), - ]) + @parameterized.expand( + [ + ("no policies", True, "hvac", None), + ("with policies", True, "hvac", ["default"]), + ] + ) def test_map_team(self, test_label, expected_value, team_name, policies): response = self.client.auth.github.map_team( team_name=team_name, @@ -130,21 +143,38 @@ def test_map_team(self, test_label, expected_value, team_name, policies): def test_read_team_mapping(self): response = self.client.auth.github.read_team_mapping( - team_name='hvac', + team_name="hvac", mount_point=self.TEST_GITHUB_PATH, ) self.assertIn( - member='data', + member="data", container=response, ) - @parameterized.expand([ - ("no policies", True, 'hvac', None), - ("with policy", True, 'hvac', ['default']), - ("with policy incorrect type", True, 'hvac', 'default, root', exceptions.ParamValidationError, "unsupported policies argument provided"), - ("with policies", True, 'hvac', ['default', 'root']), - ]) - def test_map_team_and_read_mapping(self, test_label, expected_value, team_name, policies, raises=False, exception_msg=''): + @parameterized.expand( + [ + ("no policies", True, "hvac", None), + ("with policy", True, "hvac", ["default"]), + ( + "with policy incorrect type", + True, + "hvac", + "default, root", + exceptions.ParamValidationError, + "unsupported policies argument provided", + ), + ("with policies", True, "hvac", ["default", "root"]), + ] + ) + def test_map_team_and_read_mapping( + self, + test_label, + expected_value, + team_name, + policies, + raises=False, + exception_msg="", + ): if raises: with self.assertRaises(raises) as cm: @@ -173,19 +203,21 @@ def test_map_team_and_read_mapping(self, test_label, expected_value, team_name, mount_point=self.TEST_GITHUB_PATH, ) if policies is None: - expected_policies = '' + expected_policies = "" else: - expected_policies = ','.join(policies) + expected_policies = ",".join(policies) self.assertDictEqual( d1=dict(key=team_name, value=expected_policies), - d2=response['data'], + d2=response["data"], ) - @parameterized.expand([ - ("no policies", True, 'hvac-user', None), - ("with policies", True, 'hvac-user', ['default']), - ]) + @parameterized.expand( + [ + ("no policies", True, "hvac-user", None), + ("with policies", True, "hvac-user", ["default"]), + ] + ) def teat_map_user(self, test_label, expected_value, user_name, policies): response = self.client.auth.github.map_user( user_name=user_name, @@ -199,21 +231,38 @@ def teat_map_user(self, test_label, expected_value, user_name, policies): def test_read_user_mapping(self): response = self.client.auth.github.read_user_mapping( - user_name='hvac', + user_name="hvac", mount_point=self.TEST_GITHUB_PATH, ) self.assertIn( - member='data', + member="data", container=response, ) - @parameterized.expand([ - ("no policies", True, 'hvac', None), - ("with policy", True, 'hvac', ['default']), - ("with policy incorrect type", True, 'hvac', 'default, root', exceptions.ParamValidationError, "unsupported policies argument provided"), - ("with policies", True, 'hvac', ['default', 'root']), - ]) - def test_map_user_and_read_mapping(self, test_label, expected_value, user_name, policies, raises=False, exception_msg=''): + @parameterized.expand( + [ + ("no policies", True, "hvac", None), + ("with policy", True, "hvac", ["default"]), + ( + "with policy incorrect type", + True, + "hvac", + "default, root", + exceptions.ParamValidationError, + "unsupported policies argument provided", + ), + ("with policies", True, "hvac", ["default", "root"]), + ] + ) + def test_map_user_and_read_mapping( + self, + test_label, + expected_value, + user_name, + policies, + raises=False, + exception_msg="", + ): if raises: with self.assertRaises(raises) as cm: @@ -242,23 +291,30 @@ def test_map_user_and_read_mapping(self, test_label, expected_value, user_name, mount_point=self.TEST_GITHUB_PATH, ) if policies is None: - expected_policies = '' + expected_policies = "" else: - expected_policies = ','.join(policies) + expected_policies = ",".join(policies) self.assertDictEqual( d1=dict(key=user_name, value=expected_policies), - d2=response['data'], + d2=response["data"], ) - @parameterized.expand([ - ("valid token", 'valid-token', None, None), - ("invalid token not in org", "invalid-token", exceptions.InvalidRequest, 'user is not part of required org'), - ]) + @parameterized.expand( + [ + ("valid token", "valid-token", None, None), + ( + "invalid token not in org", + "invalid-token", + exceptions.InvalidRequest, + "user is not part of required org", + ), + ] + ) def test_login(self, test_label, test_token, exceptions_raised, exception_msg): self.client.auth.github.configure( - organization='hvac', - base_url='http://localhost:{port}/'.format(port=self.mock_server_port), + organization="hvac", + base_url="http://localhost:{port}/".format(port=self.mock_server_port), mount_point=self.TEST_GITHUB_PATH, ) if exceptions_raised is None: @@ -272,7 +328,4 @@ def test_login(self, test_label, test_token, exceptions_raised, exception_msg): token=test_token, mount_point=self.TEST_GITHUB_PATH, ) - self.assertIn( - member=exception_msg, - container=str(cm.exception) - ) + self.assertIn(member=exception_msg, container=str(cm.exception)) diff --git a/tests/integration_tests/api/auth_methods/test_jwt.py b/tests/integration_tests/api/auth_methods/test_jwt.py index 6a6195e62..77740d9b2 100644 --- a/tests/integration_tests/api/auth_methods/test_jwt.py +++ b/tests/integration_tests/api/auth_methods/test_jwt.py @@ -8,16 +8,16 @@ class TestJWT(HvacIntegrationTestCase, TestCase): - TEST_APPROLE_PATH = 'jwt-test-approle' - TEST_APPROLE_ROLE_ID = 'jwt-test-role-id' - TEST_JWT_PATH = 'jwt-test' - oidc_client_id = 'hvac-client-id' + TEST_APPROLE_PATH = "jwt-test-approle" + TEST_APPROLE_ROLE_ID = "jwt-test-role-id" + TEST_JWT_PATH = "jwt-test" + oidc_client_id = "hvac-client-id" oidc_server = None def setUp(self): super(TestJWT, self).setUp() self.client.sys.enable_auth_method( - method_type='jwt', + method_type="jwt", path=self.TEST_JWT_PATH, ) @@ -33,213 +33,239 @@ def tearDown(self): self.oidc_server.shutdown() self.oidc_server = None - @parameterized.expand([ - param( - 'configure using vault identity OIDC', - issuer='https://localhost:8200', - ), - ]) + @parameterized.expand( + [ + param( + "configure using vault identity OIDC", + issuer="https://localhost:8200", + ), + ] + ) def test_configure(self, label, issuer): - oidc_discovery_url = '{issuer}/v1/identity/oidc'.format(issuer=issuer) + oidc_discovery_url = "{issuer}/v1/identity/oidc".format(issuer=issuer) self.client.secrets.identity.configure_tokens_backend( issuer=issuer, ) response = self.client.auth.jwt.configure( oidc_discovery_url=oidc_discovery_url, - oidc_discovery_ca_pem=''.join(open(utils.get_config_file_path('server-cert.pem')).readlines()), + oidc_discovery_ca_pem="".join( + open(utils.get_config_file_path("server-cert.pem")).readlines() + ), path=self.TEST_JWT_PATH, ) - logging.debug('configure response: %s' % response) + logging.debug("configure response: %s" % response) self.assertEqual( first=204, second=response.status_code, ) - @parameterized.expand([ - param( - 'configure using vault identity OIDC', - issuer='https://localhost:8200', - ), - ]) + @parameterized.expand( + [ + param( + "configure using vault identity OIDC", + issuer="https://localhost:8200", + ), + ] + ) def test_read_config(self, label, issuer): - oidc_discovery_url = '{issuer}/v1/identity/oidc'.format(issuer=issuer) + oidc_discovery_url = "{issuer}/v1/identity/oidc".format(issuer=issuer) self.client.secrets.identity.configure_tokens_backend( issuer=issuer, ) configure_response = self.client.auth.jwt.configure( oidc_discovery_url=oidc_discovery_url, - oidc_discovery_ca_pem=''.join(open(utils.get_config_file_path('server-cert.pem')).readlines()), + oidc_discovery_ca_pem="".join( + open(utils.get_config_file_path("server-cert.pem")).readlines() + ), path=self.TEST_JWT_PATH, ) - logging.debug('configure response: %s' % configure_response) + logging.debug("configure response: %s" % configure_response) response = self.client.auth.jwt.read_config( path=self.TEST_JWT_PATH, ) - logging.debug('read_config response: %s' % response) + logging.debug("read_config response: %s" % response) self.assertEqual( first=oidc_discovery_url, - second=response['data']['oidc_discovery_url'], + second=response["data"]["oidc_discovery_url"], ) - @parameterized.expand([ - param( - 'success', - role_name='hvac', - allowed_redirect_uris=['https://localhost:8200/jwt-test/callback'], - user_claim='https://vault/user', - ), - ]) + @parameterized.expand( + [ + param( + "success", + role_name="hvac", + allowed_redirect_uris=["https://localhost:8200/jwt-test/callback"], + user_claim="https://vault/user", + ), + ] + ) def test_create_role(self, label, role_name, allowed_redirect_uris, user_claim): response = self.client.auth.jwt.create_role( name=role_name, allowed_redirect_uris=allowed_redirect_uris, user_claim=user_claim, - bound_audiences=['1234'], + bound_audiences=["1234"], path=self.TEST_JWT_PATH, ) - logging.debug('create_role response: %s' % response) + logging.debug("create_role response: %s" % response) self.assertIn( - member='data', + member="data", container=response, ) - @parameterized.expand([ - param( - 'success', - role_name='hvac', - allowed_redirect_uris=['https://localhost:8200/jwt-test/callback'], - user_claim='https://vault/user', - ), - ]) + @parameterized.expand( + [ + param( + "success", + role_name="hvac", + allowed_redirect_uris=["https://localhost:8200/jwt-test/callback"], + user_claim="https://vault/user", + ), + ] + ) def test_read_role(self, label, role_name, allowed_redirect_uris, user_claim): create_role_response = self.client.auth.jwt.create_role( name=role_name, allowed_redirect_uris=allowed_redirect_uris, user_claim=user_claim, - bound_audiences=['1234'], + bound_audiences=["1234"], path=self.TEST_JWT_PATH, ) - logging.debug('create_role_response: %s' % create_role_response) + logging.debug("create_role_response: %s" % create_role_response) response = self.client.auth.jwt.read_role( name=role_name, path=self.TEST_JWT_PATH, ) - logging.debug('read_role response: %s' % response) + logging.debug("read_role response: %s" % response) self.assertEqual( first=user_claim, - second=response['data']['user_claim'], + second=response["data"]["user_claim"], ) - @parameterized.expand([ - param( - 'success', - role_name='hvac', - allowed_redirect_uris=['https://localhost:8200/jwt-test/callback'], - user_claim='https://vault/user', - ), - ]) + @parameterized.expand( + [ + param( + "success", + role_name="hvac", + allowed_redirect_uris=["https://localhost:8200/jwt-test/callback"], + user_claim="https://vault/user", + ), + ] + ) def test_list_roles(self, label, role_name, allowed_redirect_uris, user_claim): create_role_response = self.client.auth.jwt.create_role( name=role_name, allowed_redirect_uris=allowed_redirect_uris, user_claim=user_claim, - bound_audiences=['1234'], + bound_audiences=["1234"], path=self.TEST_JWT_PATH, ) - logging.debug('create_role_response: %s' % create_role_response) + logging.debug("create_role_response: %s" % create_role_response) response = self.client.auth.jwt.list_roles( path=self.TEST_JWT_PATH, ) - logging.debug('list_roles response: %s' % response) + logging.debug("list_roles response: %s" % response) self.assertIn( member=role_name, - container=response['data']['keys'], + container=response["data"]["keys"], ) - @parameterized.expand([ - param( - 'success', - role_name='hvac', - allowed_redirect_uris=['https://localhost:8200/jwt-test/callback'], - user_claim='https://vault/user', - ), - ]) + @parameterized.expand( + [ + param( + "success", + role_name="hvac", + allowed_redirect_uris=["https://localhost:8200/jwt-test/callback"], + user_claim="https://vault/user", + ), + ] + ) def test_delete_role(self, label, role_name, allowed_redirect_uris, user_claim): create_role_response = self.client.auth.jwt.create_role( name=role_name, allowed_redirect_uris=allowed_redirect_uris, user_claim=user_claim, - bound_audiences=['1234'], + bound_audiences=["1234"], path=self.TEST_JWT_PATH, ) - logging.debug('create_role_response: %s' % create_role_response) + logging.debug("create_role_response: %s" % create_role_response) response = self.client.auth.jwt.delete_role( name=role_name, path=self.TEST_JWT_PATH, ) - logging.debug('delete_role response: %s' % response) + logging.debug("delete_role response: %s" % response) self.assertEqual( first=204, second=response.status_code, ) - @parameterized.expand([ - param( - 'success', - issuer='https://localhost:8200', - role_name='hvac-jwt', - allowed_redirect_uris=['https://localhost:8200/jwt-test/oidc/callback'], - user_claim='sub', - ), - ]) - def test_jwt_login(self, label, issuer, role_name, allowed_redirect_uris, user_claim): - if '%s/' % self.TEST_APPROLE_PATH not in self.client.sys.list_auth_methods(): + @parameterized.expand( + [ + param( + "success", + issuer="https://localhost:8200", + role_name="hvac-jwt", + allowed_redirect_uris=["https://localhost:8200/jwt-test/oidc/callback"], + user_claim="sub", + ), + ] + ) + def test_jwt_login( + self, label, issuer, role_name, allowed_redirect_uris, user_claim + ): + if "%s/" % self.TEST_APPROLE_PATH not in self.client.sys.list_auth_methods(): self.client.sys.enable_auth_method( - method_type='approle', + method_type="approle", path=self.TEST_APPROLE_PATH, ) - id_token_role_name = 'hvac-jwt-test' - key_name = 'jwt-test-key' + id_token_role_name = "hvac-jwt-test" + key_name = "jwt-test-key" create_named_key_response = self.client.secrets.identity.create_named_key( name=key_name, ) - logging.debug('create_named_key response: %s' % create_named_key_response) - create_or_update_role_response = self.client.secrets.identity.create_or_update_role( - name=id_token_role_name, - key=key_name, + logging.debug("create_named_key response: %s" % create_named_key_response) + create_or_update_role_response = ( + self.client.secrets.identity.create_or_update_role( + name=id_token_role_name, + key=key_name, + ) + ) + logging.debug( + "create_or_update_role response: %s" % create_or_update_role_response ) - logging.debug('create_or_update_role response: %s' % create_or_update_role_response) read_role_response = self.client.secrets.identity.read_role( name=id_token_role_name, ) - logging.debug('read_role response: %s' % read_role_response) - token_client_id = read_role_response['data']['client_id'] + logging.debug("read_role response: %s" % read_role_response) + token_client_id = read_role_response["data"]["client_id"] create_named_key_response = self.client.secrets.identity.create_named_key( name=key_name, allowed_client_ids=[ token_client_id, ], ) - logging.debug('create_named_key response: %s' % create_named_key_response) + logging.debug("create_named_key response: %s" % create_named_key_response) self.client.secrets.identity.configure_tokens_backend( - issuer='https://localhost:8200', + issuer="https://localhost:8200", ) response = self.client.auth.jwt.configure( - jwks_url='https://localhost:8200/v1/identity/oidc/.well-known/keys', - jwks_ca_pem=''.join(open(utils.get_config_file_path('server-cert.pem')).readlines()), + jwks_url="https://localhost:8200/v1/identity/oidc/.well-known/keys", + jwks_ca_pem="".join( + open(utils.get_config_file_path("server-cert.pem")).readlines() + ), path=self.TEST_JWT_PATH, ) - logging.debug('configure response: %s' % response) + logging.debug("configure response: %s" % response) create_role_response = self.client.auth.jwt.create_role( name=role_name, - role_type='jwt', + role_type="jwt", allowed_redirect_uris=allowed_redirect_uris, user_claim=user_claim, bound_audiences=[token_client_id], path=self.TEST_JWT_PATH, ) - logging.debug('create_role_response: %s' % create_role_response) + logging.debug("create_role_response: %s" % create_role_response) # Log in using a dummy approle role so our client token has an associated identity self.login_using_admin_approle_role( @@ -249,18 +275,23 @@ def test_jwt_login(self, label, issuer, role_name, allowed_redirect_uris, user_c generate_token_response = self.client.secrets.identity.generate_signed_id_token( name=id_token_role_name, ) - logging.debug('generate_token_response: %s' % generate_token_response) + logging.debug("generate_token_response: %s" % generate_token_response) - read_well_known_configurations_response = self.client.secrets.identity.read_well_known_configurations() - logging.debug('read_well_known_configurations_response: %s' % read_well_known_configurations_response) + read_well_known_configurations_response = ( + self.client.secrets.identity.read_well_known_configurations() + ) + logging.debug( + "read_well_known_configurations_response: %s" + % read_well_known_configurations_response + ) response = self.client.auth.jwt.jwt_login( role=role_name, - jwt=generate_token_response['data']['token'], + jwt=generate_token_response["data"]["token"], path=self.TEST_JWT_PATH, ) - logging.debug('jwt_login response: %s' % response) - self.client.token = response['auth']['client_token'] + logging.debug("jwt_login response: %s" % response) + self.client.token = response["auth"]["client_token"] self.assertIn( member=role_name, - container=self.client.lookup_token()['data']['meta']['role'], + container=self.client.lookup_token()["data"]["meta"]["role"], ) diff --git a/tests/integration_tests/api/auth_methods/test_kubernetes.py b/tests/integration_tests/api/auth_methods/test_kubernetes.py index a0789c61d..592c106d9 100644 --- a/tests/integration_tests/api/auth_methods/test_kubernetes.py +++ b/tests/integration_tests/api/auth_methods/test_kubernetes.py @@ -9,58 +9,67 @@ from tests.utils.hvac_integration_test_case import HvacIntegrationTestCase -@skipIf(utils.vault_version_lt('0.8.3'), "Kubernetes auth method not available before Vault version 0.8.3") +@skipIf( + utils.vault_version_lt("0.8.3"), + "Kubernetes auth method not available before Vault version 0.8.3", +) class TestKubernetes(HvacIntegrationTestCase, TestCase): - TEST_MOUNT_POINT = 'kubernetes-test' + TEST_MOUNT_POINT = "kubernetes-test" def setUp(self): super(TestKubernetes, self).setUp() - if '%s/' % self.TEST_MOUNT_POINT not in self.client.list_auth_backends(): - self.client.enable_auth_backend( - backend_type='kubernetes', - mount_point=self.TEST_MOUNT_POINT, + if "%s/" % self.TEST_MOUNT_POINT not in self.client.sys.list_auth_methods(): + self.client.sys.enable_auth_method( + method_type="kubernetes", + path=self.TEST_MOUNT_POINT, ) def tearDown(self): super(TestKubernetes, self).tearDown() - self.client.disable_auth_backend( - mount_point=self.TEST_MOUNT_POINT, + self.client.sys.disable_auth_method( + path=self.TEST_MOUNT_POINT, ) - @parameterized.expand([ - param( - 'success', - - ), - param( - 'issuer test', - issuer='bob' - ), - param( - 'set invalid kubernetes_ca_cert', - kubernetes_ca_cert='ca_cert', - raises=exceptions.ParamValidationError, - exception_message='required type: PEM' - ), - param( - 'set invalid pem_key', - kubernetes_ca_cert='-----BEGIN CERTIFICATE-----\\n.....\\n-----END CERTIFICATE-----', - pem_keys=['pem_key'], - raises=exceptions.ParamValidationError, - exception_message='required type: PEM' - ), - param( - 'set invalid token_reviewer_jwt', - kubernetes_ca_cert='-----BEGIN CERTIFICATE-----\\n.....\\n-----END CERTIFICATE-----', - token_reviewer_jwt='reviewer_jwt', - issuer='bob', - raises=exceptions.InternalServerError, - exception_message='* not a compact JWS' - ) - ]) - def test_configure(self, label, kubernetes_ca_cert=None, token_reviewer_jwt=None, pem_keys=None, - issuer=None, raises=None, exception_message=''): - kubernetes_host = 'https://192.168.99.100:8443' + @parameterized.expand( + [ + param( + "success", + ), + param("issuer test", issuer="bob"), + param( + "set invalid kubernetes_ca_cert", + kubernetes_ca_cert="ca_cert", + raises=exceptions.ParamValidationError, + exception_message="required type: PEM", + ), + param( + "set invalid pem_key", + kubernetes_ca_cert="-----BEGIN CERTIFICATE-----\\n.....\\n-----END CERTIFICATE-----", + pem_keys=["pem_key"], + raises=exceptions.ParamValidationError, + exception_message="required type: PEM", + ), + param( + "set invalid token_reviewer_jwt", + kubernetes_ca_cert="-----BEGIN CERTIFICATE-----\\n.....\\n-----END CERTIFICATE-----", + token_reviewer_jwt="reviewer_jwt", + issuer="bob", + raises=exceptions.InternalServerError, + exception_message="* not a compact JWS", + ), + ] + ) + def test_configure( + self, + label, + kubernetes_ca_cert=None, + token_reviewer_jwt=None, + pem_keys=None, + issuer=None, + raises=None, + exception_message="", + ): + kubernetes_host = "https://192.168.99.100:8443" if raises: with self.assertRaises(raises) as cm: self.client.auth.kubernetes.configure( @@ -68,44 +77,42 @@ def test_configure(self, label, kubernetes_ca_cert=None, token_reviewer_jwt=None kubernetes_ca_cert=kubernetes_ca_cert, token_reviewer_jwt=token_reviewer_jwt, pem_keys=pem_keys, - mount_point=self.TEST_MOUNT_POINT + mount_point=self.TEST_MOUNT_POINT, ) - self.assertIn( - member=exception_message, - container=str(cm.exception) - ) + self.assertIn(member=exception_message, container=str(cm.exception)) else: configure_response = self.client.auth.kubernetes.configure( kubernetes_host=kubernetes_host, - kubernetes_ca_cert='-----BEGIN CERTIFICATE-----\\n.....\\n-----END CERTIFICATE-----', + kubernetes_ca_cert="-----BEGIN CERTIFICATE-----\\n.....\\n-----END CERTIFICATE-----", mount_point=self.TEST_MOUNT_POINT, - issuer="bob" + issuer="bob", ) - logging.debug('configure_response: %s' % configure_response) + logging.debug("configure_response: %s" % configure_response) self.assertEqual( first=bool(configure_response), second=True, ) - @parameterized.expand([ - param( - 'success', - ), - param( - 'no config written yet', - write_config_first=False, - raises=exceptions.InvalidPath - ) - ]) + @parameterized.expand( + [ + param( + "success", + ), + param( + "no config written yet", + write_config_first=False, + raises=exceptions.InvalidPath, + ), + ] + ) def test_read_config(self, label, write_config_first=True, raises=None): expected_config = { - 'kubernetes_host': 'https://192.168.99.100:8443', - 'kubernetes_ca_cert': '-----BEGIN CERTIFICATE-----\\n.....\\n-----END CERTIFICATE-----', + "kubernetes_host": "https://192.168.99.100:8443", + "kubernetes_ca_cert": "-----BEGIN CERTIFICATE-----\\n.....\\n-----END CERTIFICATE-----", } if write_config_first: self.client.auth.kubernetes.configure( - mount_point=self.TEST_MOUNT_POINT, - **expected_config + mount_point=self.TEST_MOUNT_POINT, **expected_config ) if raises is not None: with self.assertRaises(raises): @@ -116,28 +123,36 @@ def test_read_config(self, label, write_config_first=True, raises=None): read_config_response = self.client.auth.kubernetes.read_config( mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('read_config_response: %s' % read_config_response) + logging.debug("read_config_response: %s" % read_config_response) for k, v in expected_config.items(): self.assertEqual( first=v, second=read_config_response[k], ) - @parameterized.expand([ - param( - 'success', - bound_service_account_names=['vault-auth'], - bound_service_account_namespaces=['default'], - ), - param( - 'both bounds wildcard permitted', - bound_service_account_names=['*'], - bound_service_account_namespaces=['*'], - ), - ]) - def test_create_role(self, label, bound_service_account_names=None, bound_service_account_namespaces=None, - raises=None, exception_message=''): - role_name = 'test-role' + @parameterized.expand( + [ + param( + "success", + bound_service_account_names=["vault-auth"], + bound_service_account_namespaces=["default"], + ), + param( + "both bounds wildcard permitted", + bound_service_account_names=["*"], + bound_service_account_namespaces=["*"], + ), + ] + ) + def test_create_role( + self, + label, + bound_service_account_names=None, + bound_service_account_namespaces=None, + raises=None, + exception_message="", + ): + role_name = "test-role" if raises: with self.assertRaises(raises) as cm: self.client.auth.kubernetes.create_role( @@ -157,35 +172,38 @@ def test_create_role(self, label, bound_service_account_names=None, bound_servic bound_service_account_namespaces=bound_service_account_namespaces, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('create_role_response: %s' % create_role_response) + logging.debug("create_role_response: %s" % create_role_response) self.assertEqual( first=bool(create_role_response), second=True, ) - @parameterized.expand([ - param( - 'success', - ), - param( - 'nonexistent role name', - create_role_first=False, - raises=exceptions.InvalidPath, - ), - ]) - def test_read_role(self, label, create_role_first=True, raises=None, exception_message=''): - role_name = 'test-role' + @parameterized.expand( + [ + param( + "success", + ), + param( + "nonexistent role name", + create_role_first=False, + raises=exceptions.InvalidPath, + ), + ] + ) + def test_read_role( + self, label, create_role_first=True, raises=None, exception_message="" + ): + role_name = "test-role" expected_role_config = { - 'name': role_name, - 'bound_service_account_names': ['vault-auth'], - 'bound_service_account_namespaces': ['default'], + "name": role_name, + "bound_service_account_names": ["vault-auth"], + "bound_service_account_namespaces": ["default"], } - role_name = 'test-role' + role_name = "test-role" if create_role_first: self.client.auth.kubernetes.create_role( - mount_point=self.TEST_MOUNT_POINT, - **expected_role_config + mount_point=self.TEST_MOUNT_POINT, **expected_role_config ) if raises: with self.assertRaises(raises) as cm: @@ -202,41 +220,47 @@ def test_read_role(self, label, create_role_first=True, raises=None, exception_m name=role_name, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('read_role_response: %s' % read_role_response) + logging.debug("read_role_response: %s" % read_role_response) self.assertEqual( - first=read_role_response['bound_service_account_names'], - second=expected_role_config['bound_service_account_names'] + first=read_role_response["bound_service_account_names"], + second=expected_role_config["bound_service_account_names"], ) self.assertEqual( - first=read_role_response['bound_service_account_namespaces'], - second=expected_role_config['bound_service_account_namespaces'] + first=read_role_response["bound_service_account_namespaces"], + second=expected_role_config["bound_service_account_namespaces"], ) - @parameterized.expand([ - param( - 'success', - ), - param( - 'no roles', - num_roles_to_create=0, - raises=exceptions.InvalidPath, - ), - param( - 'no config', - write_config_first=False, - ), - ]) - def test_list_roles(self, label, num_roles_to_create=1, write_config_first=True, raises=None): + @parameterized.expand( + [ + param( + "success", + ), + param( + "no roles", + num_roles_to_create=0, + raises=exceptions.InvalidPath, + ), + param( + "no config", + write_config_first=False, + ), + ] + ) + def test_list_roles( + self, label, num_roles_to_create=1, write_config_first=True, raises=None + ): if write_config_first: self.client.auth.kubernetes.configure( - kubernetes_host='https://192.168.99.100:8443', - kubernetes_ca_cert='-----BEGIN CERTIFICATE-----\n.....\n-----END CERTIFICATE-----', + kubernetes_host="https://192.168.99.100:8443", + kubernetes_ca_cert="-----BEGIN CERTIFICATE-----\n.....\n-----END CERTIFICATE-----", mount_point=self.TEST_MOUNT_POINT, ) - roles_to_create = ['hvac{}'.format(str(n)) for n in range(0, num_roles_to_create)] - bound_service_account_names = ['vault-auth'] - bound_service_account_namespaces = ['default'] - logging.debug('roles_to_create: %s' % roles_to_create) + roles_to_create = [ + "hvac{}".format(str(n)) for n in range(0, num_roles_to_create) + ] + bound_service_account_names = ["vault-auth"] + bound_service_account_namespaces = ["default"] + logging.debug("roles_to_create: %s" % roles_to_create) for role_to_create in roles_to_create: create_role_response = self.client.auth.kubernetes.create_role( name=role_to_create, @@ -244,7 +268,7 @@ def test_list_roles(self, label, num_roles_to_create=1, write_config_first=True, bound_service_account_namespaces=bound_service_account_namespaces, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('create_role_response: %s' % create_role_response) + logging.debug("create_role_response: %s" % create_role_response) if raises: with self.assertRaises(raises): @@ -255,25 +279,27 @@ def test_list_roles(self, label, num_roles_to_create=1, write_config_first=True, list_roles_response = self.client.auth.kubernetes.list_roles( mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('list_roles_response: %s' % list_roles_response) + logging.debug("list_roles_response: %s" % list_roles_response) self.assertEqual( - first=list_roles_response['keys'], + first=list_roles_response["keys"], second=roles_to_create, ) - @parameterized.expand([ - param( - 'success', - ), - param( - 'nonexistent role name', - configure_role_first=False, - ), - ]) + @parameterized.expand( + [ + param( + "success", + ), + param( + "nonexistent role name", + configure_role_first=False, + ), + ] + ) def test_delete_role(self, label, configure_role_first=True, raises=None): - role_name = 'test-role' - bound_service_account_names = ['vault-auth'] - bound_service_account_namespaces = ['default'] + role_name = "test-role" + bound_service_account_names = ["vault-auth"] + bound_service_account_namespaces = ["default"] if configure_role_first: create_role_response = self.client.auth.kubernetes.create_role( name=role_name, @@ -281,7 +307,7 @@ def test_delete_role(self, label, configure_role_first=True, raises=None): bound_service_account_namespaces=bound_service_account_namespaces, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('create_role_response: %s' % create_role_response) + logging.debug("create_role_response: %s" % create_role_response) if raises is not None: with self.assertRaises(raises): @@ -294,7 +320,7 @@ def test_delete_role(self, label, configure_role_first=True, raises=None): name=role_name, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('delete_role_response: %s' % delete_role_response) + logging.debug("delete_role_response: %s" % delete_role_response) self.assertEqual( first=bool(delete_role_response), second=True, diff --git a/tests/integration_tests/api/auth_methods/test_ldap.py b/tests/integration_tests/api/auth_methods/test_ldap.py index ca666d005..d053da409 100644 --- a/tests/integration_tests/api/auth_methods/test_ldap.py +++ b/tests/integration_tests/api/auth_methods/test_ldap.py @@ -11,18 +11,18 @@ class TestLdap(HvacIntegrationTestCase, TestCase): - TEST_LDAP_PATH = 'test-ldap' + TEST_LDAP_PATH = "test-ldap" ldap_server = None @classmethod def setUpClass(cls): # The mock LDAP server requires Java runtime - if not distutils.spawn.find_executable('java'): - raise SkipTest('The mock LDAP server requires Java runtime') + if not distutils.spawn.find_executable("java"): + raise SkipTest("The mock LDAP server requires Java runtime") try: super(TestLdap, cls).setUpClass() - logging.getLogger('ldap_test').setLevel(logging.ERROR) + logging.getLogger("ldap_test").setLevel(logging.ERROR) cls.mock_server_port = utils.get_free_port() cls.ldap_server = MockLdapServer() @@ -39,32 +39,54 @@ def tearDownClass(cls): def setUp(self): super(TestLdap, self).setUp() - if 'ldap/' not in self.client.list_auth_backends(): + if "ldap/" not in self.client.sys.list_auth_methods(): self.client.sys.enable_auth_method( - method_type='ldap', - path=self.TEST_LDAP_PATH + method_type="ldap", path=self.TEST_LDAP_PATH ) def tearDown(self): super(TestLdap, self).tearDown() - self.client.disable_auth_backend( - mount_point=self.TEST_LDAP_PATH, + self.client.sys.disable_auth_method( + path=self.TEST_LDAP_PATH, ) - @parameterized.expand([ - ('update url', dict(url=MockLdapServer.ldap_url)), - ('update binddn', dict(url=MockLdapServer.ldap_url, bind_dn='cn=vault,ou=Users,dc=hvac,dc=network')), - ('update upn_domain', dict(url=MockLdapServer.ldap_url, upn_domain='python-hvac.org')), - ('update certificate', dict(url=MockLdapServer.ldap_url, certificate=utils.load_config_file('server-cert.pem'))), - ('incorrect tls version', dict(url=MockLdapServer.ldap_url, tls_min_version='cats'), exceptions.InvalidRequest, - "invalid 'tls_min_version'"), - ]) - def test_configure(self, test_label, parameters, raises=None, exception_message=''): - parameters.update({ - 'user_dn': MockLdapServer.ldap_users_dn, - 'group_dn': MockLdapServer.ldap_groups_dn, - 'mount_point': self.TEST_LDAP_PATH, - }) + @parameterized.expand( + [ + ("update url", dict(url=MockLdapServer.ldap_url)), + ( + "update binddn", + dict( + url=MockLdapServer.ldap_url, + bind_dn="cn=vault,ou=Users,dc=hvac,dc=network", + ), + ), + ( + "update upn_domain", + dict(url=MockLdapServer.ldap_url, upn_domain="python-hvac.org"), + ), + ( + "update certificate", + dict( + url=MockLdapServer.ldap_url, + certificate=utils.load_config_file("server-cert.pem"), + ), + ), + ( + "incorrect tls version", + dict(url=MockLdapServer.ldap_url, tls_min_version="cats"), + exceptions.InvalidRequest, + "invalid 'tls_min_version'", + ), + ] + ) + def test_configure(self, test_label, parameters, raises=None, exception_message=""): + parameters.update( + { + "user_dn": MockLdapServer.ldap_users_dn, + "group_dn": MockLdapServer.ldap_groups_dn, + "mount_point": self.TEST_LDAP_PATH, + } + ) if raises: with self.assertRaises(raises) as cm: self.client.auth.ldap.configure(**parameters) @@ -76,19 +98,18 @@ def test_configure(self, test_label, parameters, raises=None, exception_message= expected_status_code = 204 configure_response = self.client.auth.ldap.configure(**parameters) self.assertEqual( - first=expected_status_code, - second=configure_response.status_code + first=expected_status_code, second=configure_response.status_code ) read_config_response = self.client.auth.ldap.read_configuration( mount_point=self.TEST_LDAP_PATH, ) for parameter, argument in parameters.items(): - if parameter == 'mount_point': + if parameter == "mount_point": continue self.assertIn( member=argument, - container=read_config_response['data'].values(), + container=read_config_response["data"].values(), ) def test_read_configuration(self): @@ -96,16 +117,26 @@ def test_read_configuration(self): mount_point=self.TEST_LDAP_PATH, ) self.assertIn( - member='data', + member="data", container=response, ) - @parameterized.expand([ - ('no policies', 'cats'), - ('policies as list', 'cats', ['purr-policy']), - ('policies as invalid type', 'cats', 'purr-policy', exceptions.ParamValidationError, '"policies" argument must be an instance of list'), - ]) - def test_create_or_update_group(self, test_label, name, policies=None, raises=None, exception_message=''): + @parameterized.expand( + [ + ("no policies", "cats"), + ("policies as list", "cats", ["purr-policy"]), + ( + "policies as invalid type", + "cats", + "purr-policy", + exceptions.ParamValidationError, + '"policies" argument must be an instance of list', + ), + ] + ) + def test_create_or_update_group( + self, test_label, name, policies=None, raises=None, exception_message="" + ): expected_status_code = 204 if raises: with self.assertRaises(raises) as cm: @@ -126,15 +157,23 @@ def test_create_or_update_group(self, test_label, name, policies=None, raises=No mount_point=self.TEST_LDAP_PATH, ) self.assertEqual( - first=expected_status_code, - second=create_response.status_code + first=expected_status_code, second=create_response.status_code ) - @parameterized.expand([ - ('read configured groups', 'cats'), - ('non-existent groups', 'cats', False, exceptions.InvalidPath), - ]) - def test_list_groups(self, test_label, name, configure_first=True, raises=None, exception_message=None): + @parameterized.expand( + [ + ("read configured groups", "cats"), + ("non-existent groups", "cats", False, exceptions.InvalidPath), + ] + ) + def test_list_groups( + self, + test_label, + name, + configure_first=True, + raises=None, + exception_message=None, + ): if configure_first: self.client.auth.ldap.create_or_update_group( name=name, @@ -157,14 +196,23 @@ def test_list_groups(self, test_label, name, configure_first=True, raises=None, # raise Exception(list_groups_response) self.assertDictEqual( d1=dict(keys=[name]), - d2=list_groups_response['data'], + d2=list_groups_response["data"], ) - @parameterized.expand([ - ('read configured group', 'cats'), - ('non-existent group', 'cats', False, exceptions.InvalidPath), - ]) - def test_read_group(self, test_label, name, configure_first=True, raises=None, exception_message=None): + @parameterized.expand( + [ + ("read configured group", "cats"), + ("non-existent group", "cats", False, exceptions.InvalidPath), + ] + ) + def test_read_group( + self, + test_label, + name, + configure_first=True, + raises=None, + exception_message=None, + ): if configure_first: self.client.auth.ldap.create_or_update_group( name=name, @@ -187,19 +235,43 @@ def test_read_group(self, test_label, name, configure_first=True, raises=None, e mount_point=self.TEST_LDAP_PATH, ) self.assertIn( - member='policies', - container=read_group_response['data'], + member="policies", + container=read_group_response["data"], ) - @parameterized.expand([ - ('no policies or groups', 'cats'), - ('policies as list', 'cats', ['purr-policy']), - ('policies as invalid type', 'cats', 'purr-policy', None, exceptions.ParamValidationError, '"policies" argument must be an instance of list'), - ('no groups', 'cats', ['purr-policy']), - ('groups as list', 'cats', None, ['meow-group']), - ('groups as invalid type', 'cats', None, 'meow-group', exceptions.ParamValidationError, '"groups" argument must be an instance of list'), - ]) - def test_create_or_update_user(self, test_label, username, policies=None, groups=None, raises=None, exception_message=''): + @parameterized.expand( + [ + ("no policies or groups", "cats"), + ("policies as list", "cats", ["purr-policy"]), + ( + "policies as invalid type", + "cats", + "purr-policy", + None, + exceptions.ParamValidationError, + '"policies" argument must be an instance of list', + ), + ("no groups", "cats", ["purr-policy"]), + ("groups as list", "cats", None, ["meow-group"]), + ( + "groups as invalid type", + "cats", + None, + "meow-group", + exceptions.ParamValidationError, + '"groups" argument must be an instance of list', + ), + ] + ) + def test_create_or_update_user( + self, + test_label, + username, + policies=None, + groups=None, + raises=None, + exception_message="", + ): expected_status_code = 204 if raises: with self.assertRaises(raises) as cm: @@ -222,15 +294,23 @@ def test_create_or_update_user(self, test_label, username, policies=None, groups mount_point=self.TEST_LDAP_PATH, ) self.assertEqual( - first=expected_status_code, - second=create_response.status_code + first=expected_status_code, second=create_response.status_code ) - @parameterized.expand([ - ('read configured group', 'cats'), - ('non-existent group', 'cats', False, exceptions.InvalidPath), - ]) - def test_delete_group(self, test_label, name, configure_first=True, raises=None, exception_message=None): + @parameterized.expand( + [ + ("read configured group", "cats"), + ("non-existent group", "cats", False, exceptions.InvalidPath), + ] + ) + def test_delete_group( + self, + test_label, + name, + configure_first=True, + raises=None, + exception_message=None, + ): if configure_first: self.client.auth.ldap.create_or_update_group( name=name, @@ -242,15 +322,23 @@ def test_delete_group(self, test_label, name, configure_first=True, raises=None, mount_point=self.TEST_LDAP_PATH, ) self.assertEqual( - first=expected_status_code, - second=delete_group_response.status_code + first=expected_status_code, second=delete_group_response.status_code ) - @parameterized.expand([ - ('read configured user', 'cats'), - ('non-existent user', 'cats', False, exceptions.InvalidPath), - ]) - def test_list_users(self, test_label, username, configure_first=True, raises=None, exception_message=None): + @parameterized.expand( + [ + ("read configured user", "cats"), + ("non-existent user", "cats", False, exceptions.InvalidPath), + ] + ) + def test_list_users( + self, + test_label, + username, + configure_first=True, + raises=None, + exception_message=None, + ): if configure_first: self.client.auth.ldap.create_or_update_user( username=username, @@ -272,14 +360,23 @@ def test_list_users(self, test_label, username, configure_first=True, raises=Non ) self.assertDictEqual( d1=dict(keys=[username]), - d2=list_users_response['data'], + d2=list_users_response["data"], ) - @parameterized.expand([ - ('read configured user', 'cats'), - ('non-existent user', 'cats', False, exceptions.InvalidPath), - ]) - def test_read_user(self, test_label, username, configure_first=True, raises=None, exception_message=None): + @parameterized.expand( + [ + ("read configured user", "cats"), + ("non-existent user", "cats", False, exceptions.InvalidPath), + ] + ) + def test_read_user( + self, + test_label, + username, + configure_first=True, + raises=None, + exception_message=None, + ): if configure_first: self.client.auth.ldap.create_or_update_user( username=username, @@ -302,15 +399,24 @@ def test_read_user(self, test_label, username, configure_first=True, raises=None mount_point=self.TEST_LDAP_PATH, ) self.assertIn( - member='policies', - container=read_user_response['data'], + member="policies", + container=read_user_response["data"], ) - @parameterized.expand([ - ('read configured user', 'cats'), - ('non-existent user', 'cats', False, exceptions.InvalidPath), - ]) - def test_delete_user(self, test_label, username, configure_first=True, raises=None, exception_message=None): + @parameterized.expand( + [ + ("read configured user", "cats"), + ("non-existent user", "cats", False, exceptions.InvalidPath), + ] + ) + def test_delete_user( + self, + test_label, + username, + configure_first=True, + raises=None, + exception_message=None, + ): if configure_first: self.client.auth.ldap.create_or_update_user( username=username, @@ -322,40 +428,47 @@ def test_delete_user(self, test_label, username, configure_first=True, raises=No mount_point=self.TEST_LDAP_PATH, ) self.assertEqual( - first=expected_status_code, - second=delete_user_response.status_code + first=expected_status_code, second=delete_user_response.status_code ) - @parameterized.expand([ - param( - label='working creds with policy' - ), - param( - label='invalid creds', - username='not_your_dude_pal', - password='some other dudes password', - attach_policy=False, - raises=exceptions.InvalidRequest, - ), - # The following two test cases cover either side of the associated changelog entry for LDAP auth here: - # https://github.com/hashicorp/vault/blob/master/CHANGELOG.md#0103-june-20th-2018 - param( - label='working creds no membership with Vault version >= 0.10.3', - attach_policy=False, - skip_due_to_vault_version=utils.vault_version_lt('0.10.3'), - ), - param( - label='working creds no membership with Vault version < 0.10.3', - attach_policy=False, - raises=exceptions.InvalidRequest, - exception_message='user is not a member of any authorized group', - skip_due_to_vault_version=utils.vault_version_ge('0.10.3'), - ), - ]) - def test_login(self, label, username=None, password=None, attach_policy=True, raises=None, - exception_message='', skip_due_to_vault_version=False): + @parameterized.expand( + [ + param(label="working creds with policy"), + param( + label="invalid creds", + username="not_your_dude_pal", + password="some other dudes password", + attach_policy=False, + raises=exceptions.InvalidRequest, + ), + # The following two test cases cover either side of the associated changelog entry for LDAP auth here: + # https://github.com/hashicorp/vault/blob/master/CHANGELOG.md#0103-june-20th-2018 + param( + label="working creds no membership with Vault version >= 0.10.3", + attach_policy=False, + skip_due_to_vault_version=utils.vault_version_lt("0.10.3"), + ), + param( + label="working creds no membership with Vault version < 0.10.3", + attach_policy=False, + raises=exceptions.InvalidRequest, + exception_message="user is not a member of any authorized group", + skip_due_to_vault_version=utils.vault_version_ge("0.10.3"), + ), + ] + ) + def test_login( + self, + label, + username=None, + password=None, + attach_policy=True, + raises=None, + exception_message="", + skip_due_to_vault_version=False, + ): if skip_due_to_vault_version: - self.skipTest(reason='test case does not apply to Vault version under test') + self.skipTest(reason="test case does not apply to Vault version under test") if username is None: username = self.ldap_server.ldap_user_name @@ -363,15 +476,15 @@ def test_login(self, label, username=None, password=None, attach_policy=True, ra if password is None: password = self.ldap_server.ldap_user_password - test_policy_name = 'test-ldap-policy' + test_policy_name = "test-ldap-policy" self.client.auth.ldap.configure( url=self.ldap_server.url, bind_dn=self.ldap_server.ldap_bind_dn, bind_pass=self.ldap_server.ldap_bind_password, user_dn=self.ldap_server.ldap_users_dn, - user_attr='uid', + user_attr="uid", group_dn=self.ldap_server.ldap_groups_dn, - group_attr='cn', + group_attr="cn", insecure_tls=True, mount_point=self.TEST_LDAP_PATH, ) @@ -404,17 +517,16 @@ def test_login(self, label, username=None, password=None, attach_policy=True, ra ) self.assertDictEqual( d1=dict(username=username), - d2=login_response['auth']['metadata'], + d2=login_response["auth"]["metadata"], ) self.assertEqual( - first=login_response['auth']['client_token'], + first=login_response["auth"]["client_token"], second=self.client.token, ) if attach_policy: - expected_policies = ['default', test_policy_name] + expected_policies = ["default", test_policy_name] else: - expected_policies = ['default'] + expected_policies = ["default"] self.assertEqual( - first=expected_policies, - second=login_response['auth']['policies'] + first=expected_policies, second=login_response["auth"]["policies"] ) diff --git a/tests/integration_tests/api/auth_methods/test_mfa.py b/tests/integration_tests/api/auth_methods/test_mfa.py index 076e8240c..4cfade497 100644 --- a/tests/integration_tests/api/auth_methods/test_mfa.py +++ b/tests/integration_tests/api/auth_methods/test_mfa.py @@ -5,8 +5,8 @@ from hvac import exceptions from tests.utils.hvac_integration_test_case import HvacIntegrationTestCase -TEST_AUTH_PATH = 'userpass-with-mfa' -UNSUPPORTED_AUTH_PATH = 'approle-that-can-not-have-mfa' +TEST_AUTH_PATH = "userpass-with-mfa" +UNSUPPORTED_AUTH_PATH = "approle-that-can-not-have-mfa" class TestMfa(HvacIntegrationTestCase, TestCase): @@ -22,32 +22,66 @@ def tearDownClass(cls): def setUp(self): super(TestMfa, self).setUp() - if '%s/' % TEST_AUTH_PATH not in self.client.list_auth_backends(): - self.client.enable_auth_backend( - backend_type='userpass', - mount_point=TEST_AUTH_PATH + if "%s/" % TEST_AUTH_PATH not in self.client.sys.list_auth_methods(): + self.client.sys.enable_auth_method( + method_type="userpass", path=TEST_AUTH_PATH ) - if '%s/' % UNSUPPORTED_AUTH_PATH not in self.client.list_auth_backends(): - self.client.enable_auth_backend( - backend_type='approle', - mount_point=UNSUPPORTED_AUTH_PATH + if "%s/" % UNSUPPORTED_AUTH_PATH not in self.client.sys.list_auth_methods(): + self.client.sys.enable_auth_method( + method_type="approle", path=UNSUPPORTED_AUTH_PATH ) def tearDown(self): super(TestMfa, self).tearDown() for path in [TEST_AUTH_PATH, UNSUPPORTED_AUTH_PATH]: - self.client.disable_auth_backend( - mount_point=path, - ) - - @parameterized.expand([ - ('enable mfa with supported auth method', TEST_AUTH_PATH), - ('enable mfa with unsupported mfa type', TEST_AUTH_PATH, 'cats', False, exceptions.ParamValidationError, 'Unsupported mfa_type argument provided'), - ('enable mfa with unconfigured auth method path', 'whats-all-this-then', 'duo', False, exceptions.InvalidPath, 'no handler for route'), - ('enable mfa with unsupported auth method type', UNSUPPORTED_AUTH_PATH, 'duo', False, exceptions.InvalidPath, 'unsupported path'), - ('enable mfa with unsupported auth method type forced', TEST_AUTH_PATH, 'cats', True), - ]) - def test_configure(self, test_label, mount_point, mfa_type='duo', force=False, raises=None, exception_message=''): + self.client.sys.disable_auth_method( + path=path, + ) + + @parameterized.expand( + [ + ("enable mfa with supported auth method", TEST_AUTH_PATH), + ( + "enable mfa with unsupported mfa type", + TEST_AUTH_PATH, + "cats", + False, + exceptions.ParamValidationError, + "Unsupported mfa_type argument provided", + ), + ( + "enable mfa with unconfigured auth method path", + "whats-all-this-then", + "duo", + False, + exceptions.InvalidPath, + "no handler for route", + ), + ( + "enable mfa with unsupported auth method type", + UNSUPPORTED_AUTH_PATH, + "duo", + False, + exceptions.InvalidPath, + "unsupported path", + ), + ( + "enable mfa with unsupported auth method type forced", + TEST_AUTH_PATH, + "cats", + True, + ), + ] + ) + def test_configure( + self, + test_label, + mount_point, + mfa_type="duo", + force=False, + raises=None, + exception_message="", + ): if raises: with self.assertRaises(raises) as cm: self.client.auth.mfa.configure( @@ -67,21 +101,21 @@ def test_configure(self, test_label, mount_point, mfa_type='duo', force=False, r force=force, ) self.assertEqual( - first=expected_status_code, - second=configure_response.status_code + first=expected_status_code, second=configure_response.status_code ) read_config_response = self.client.auth.mfa.read_configuration( mount_point=mount_point, ) self.assertEqual( - first=mfa_type, - second=read_config_response['data']['type'] + first=mfa_type, second=read_config_response["data"]["type"] ) - @parameterized.expand([ - ('read configured path', TEST_AUTH_PATH), - ]) + @parameterized.expand( + [ + ("read configured path", TEST_AUTH_PATH), + ] + ) def test_read_configuration(self, test_label, mount_point, add_configuration=True): if add_configuration: self.client.auth.mfa.configure( @@ -92,14 +126,25 @@ def test_read_configuration(self, test_label, mount_point, add_configuration=Tru mount_point=mount_point, ) self.assertIn( - member='data', + member="data", container=response, ) - @parameterized.expand([ - ('configure duo access success', TEST_AUTH_PATH), - ]) - def test_configure_duo_access(self, test_label, mount_point, host='', integration_key='', secret_key='', raises=None, exception_message=''): + @parameterized.expand( + [ + ("configure duo access success", TEST_AUTH_PATH), + ] + ) + def test_configure_duo_access( + self, + test_label, + mount_point, + host="", + integration_key="", + secret_key="", + raises=None, + exception_message="", + ): if raises: with self.assertRaises(raises) as cm: self.client.auth.mfa.configure_duo_access( @@ -121,14 +166,24 @@ def test_configure_duo_access(self, test_label, mount_point, host='', integratio secret_key=secret_key, ) self.assertEqual( - first=expected_status_code, - second=configure_response.status_code + first=expected_status_code, second=configure_response.status_code ) - @parameterized.expand([ - ('enable mfa with supported auth method', TEST_AUTH_PATH), - ]) - def test_configure_duo_behavior(self, test_label, mount_point, push_info='', user_agent='', username_format='%s', raises=None, exception_message=''): + @parameterized.expand( + [ + ("enable mfa with supported auth method", TEST_AUTH_PATH), + ] + ) + def test_configure_duo_behavior( + self, + test_label, + mount_point, + push_info="", + user_agent="", + username_format="%s", + raises=None, + exception_message="", + ): if raises: with self.assertRaises(raises) as cm: self.client.auth.mfa.configure_duo_behavior( @@ -150,22 +205,24 @@ def test_configure_duo_behavior(self, test_label, mount_point, push_info='', use username_format=username_format, ) self.assertEqual( - first=expected_status_code, - second=configure_response.status_code + first=expected_status_code, second=configure_response.status_code ) read_config_response = self.client.auth.mfa.read_duo_behavior_configuration( mount_point=mount_point, ) self.assertEqual( - first=push_info, - second=read_config_response['data']['push_info'] + first=push_info, second=read_config_response["data"]["push_info"] ) - @parameterized.expand([ - ('read configured path', TEST_AUTH_PATH), - ]) - def test_read_duo_behavior_configuration(self, test_label, mount_point, add_configuration=True): + @parameterized.expand( + [ + ("read configured path", TEST_AUTH_PATH), + ] + ) + def test_read_duo_behavior_configuration( + self, test_label, mount_point, add_configuration=True + ): if add_configuration: self.client.auth.mfa.configure( mount_point=mount_point, @@ -175,16 +232,25 @@ def test_read_duo_behavior_configuration(self, test_label, mount_point, add_conf mount_point=mount_point, ) self.assertIn( - member='data', + member="data", container=response, ) - @parameterized.expand([ - ('login without duo access configured', False, exceptions.InvalidRequest, "Duo access credentials haven't been configured."), - ]) - def test_login_with_mfa(self, test_label, configure_access=True, raises=None, exception_message=''): - username = 'somedude' - password = 'myverygoodpassword' + @parameterized.expand( + [ + ( + "login without duo access configured", + False, + exceptions.InvalidRequest, + "Duo access credentials haven't been configured.", + ), + ] + ) + def test_login_with_mfa( + self, test_label, configure_access=True, raises=None, exception_message="" + ): + username = "somedude" + password = "myverygoodpassword" self.client.auth.mfa.configure( mount_point=TEST_AUTH_PATH, @@ -192,15 +258,15 @@ def test_login_with_mfa(self, test_label, configure_access=True, raises=None, ex if configure_access: self.client.auth.mfa.configure_duo_access( mount_point=TEST_AUTH_PATH, - host='localhost:{port}'.format(port=self.mock_server_port), - integration_key='an-integration-key', - secret_key='valid-secret-key' + host="localhost:{port}".format(port=self.mock_server_port), + integration_key="an-integration-key", + secret_key="valid-secret-key", ) self.client.create_userpass( username=username, password=password, - policies=['defaut'], + policies=["defaut"], mount_point=TEST_AUTH_PATH, ) if raises: diff --git a/tests/integration_tests/api/auth_methods/test_oidc.py b/tests/integration_tests/api/auth_methods/test_oidc.py index a696a9245..a51912336 100644 --- a/tests/integration_tests/api/auth_methods/test_oidc.py +++ b/tests/integration_tests/api/auth_methods/test_oidc.py @@ -1,30 +1,27 @@ import logging from unittest import TestCase +from urllib.parse import parse_qs, urlparse from parameterized import param, parameterized - from tests import utils from tests.utils.hvac_integration_test_case import HvacIntegrationTestCase from tests.utils.mock_oauth_provider.mock_oauth_provider import ( - MockOauthProviderServerThread, create_user_session_and_client) - -try: - from urllib.parse import urlparse, parse_qs -except ImportError: - from urlparse import urlparse, parse_qs + MockOauthProviderServerThread, + create_user_session_and_client, +) class TestOIDC(HvacIntegrationTestCase, TestCase): - TEST_APPROLE_PATH = 'oidc-test-approle' - TEST_APPROLE_ROLE_ID = 'oidc-test-role-id' - TEST_OIDC_PATH = 'oidc-test' - oidc_client_id = 'hvac-client-id' + TEST_APPROLE_PATH = "oidc-test-approle" + TEST_APPROLE_ROLE_ID = "oidc-test-role-id" + TEST_OIDC_PATH = "oidc-test" + oidc_client_id = "hvac-client-id" oidc_server = None def setUp(self): super(TestOIDC, self).setUp() self.client.sys.enable_auth_method( - method_type='oidc', + method_type="oidc", path=self.TEST_OIDC_PATH, ) @@ -40,62 +37,72 @@ def tearDown(self): self.oidc_server.shutdown() self.oidc_server = None - @parameterized.expand([ - param( - 'configure using vault identity OIDC', - issuer='https://localhost:8200', - ), - ]) + @parameterized.expand( + [ + param( + "configure using vault identity OIDC", + issuer="https://localhost:8200", + ), + ] + ) def test_configure(self, label, issuer): - oidc_discovery_url = '{issuer}/v1/identity/oidc'.format(issuer=issuer) + oidc_discovery_url = "{issuer}/v1/identity/oidc".format(issuer=issuer) self.client.secrets.identity.configure_tokens_backend( issuer=issuer, ) response = self.client.auth.oidc.configure( oidc_discovery_url=oidc_discovery_url, - oidc_discovery_ca_pem=''.join(open(utils.get_config_file_path('server-cert.pem')).readlines()), + oidc_discovery_ca_pem="".join( + open(utils.get_config_file_path("server-cert.pem")).readlines() + ), path=self.TEST_OIDC_PATH, ) - logging.debug('configure response: %s' % response) + logging.debug("configure response: %s" % response) self.assertEqual( first=204, second=response.status_code, ) - @parameterized.expand([ - param( - 'configure using vault identity OIDC', - issuer='https://localhost:8200', - ), - ]) + @parameterized.expand( + [ + param( + "configure using vault identity OIDC", + issuer="https://localhost:8200", + ), + ] + ) def test_read_config(self, label, issuer): - oidc_discovery_url = '{issuer}/v1/identity/oidc'.format(issuer=issuer) + oidc_discovery_url = "{issuer}/v1/identity/oidc".format(issuer=issuer) self.client.secrets.identity.configure_tokens_backend( issuer=issuer, ) configure_response = self.client.auth.oidc.configure( oidc_discovery_url=oidc_discovery_url, - oidc_discovery_ca_pem=''.join(open(utils.get_config_file_path('server-cert.pem')).readlines()), + oidc_discovery_ca_pem="".join( + open(utils.get_config_file_path("server-cert.pem")).readlines() + ), path=self.TEST_OIDC_PATH, ) - logging.debug('configure response: %s' % configure_response) + logging.debug("configure response: %s" % configure_response) response = self.client.auth.oidc.read_config( path=self.TEST_OIDC_PATH, ) - logging.debug('read_config response: %s' % response) + logging.debug("read_config response: %s" % response) self.assertEqual( first=oidc_discovery_url, - second=response['data']['oidc_discovery_url'], + second=response["data"]["oidc_discovery_url"], ) - @parameterized.expand([ - param( - 'success', - role_name='hvac', - allowed_redirect_uris=['https://localhost:8200/oidc-test/callback'], - user_claim='https://vault/user', - ), - ]) + @parameterized.expand( + [ + param( + "success", + role_name="hvac", + allowed_redirect_uris=["https://localhost:8200/oidc-test/callback"], + user_claim="https://vault/user", + ), + ] + ) def test_read_role(self, label, role_name, allowed_redirect_uris, user_claim): create_role_response = self.client.auth.oidc.create_role( name=role_name, @@ -103,25 +110,27 @@ def test_read_role(self, label, role_name, allowed_redirect_uris, user_claim): user_claim=user_claim, path=self.TEST_OIDC_PATH, ) - logging.debug('create_role_response: %s' % create_role_response) + logging.debug("create_role_response: %s" % create_role_response) response = self.client.auth.oidc.read_role( name=role_name, path=self.TEST_OIDC_PATH, ) - logging.debug('read_role response: %s' % response) + logging.debug("read_role response: %s" % response) self.assertEqual( first=user_claim, - second=response['data']['user_claim'], + second=response["data"]["user_claim"], ) - @parameterized.expand([ - param( - 'success', - role_name='hvac', - allowed_redirect_uris=['https://localhost:8200/oidc-test/callback'], - user_claim='https://vault/user', - ), - ]) + @parameterized.expand( + [ + param( + "success", + role_name="hvac", + allowed_redirect_uris=["https://localhost:8200/oidc-test/callback"], + user_claim="https://vault/user", + ), + ] + ) def test_list_roles(self, label, role_name, allowed_redirect_uris, user_claim): create_role_response = self.client.auth.oidc.create_role( name=role_name, @@ -129,24 +138,26 @@ def test_list_roles(self, label, role_name, allowed_redirect_uris, user_claim): user_claim=user_claim, path=self.TEST_OIDC_PATH, ) - logging.debug('create_role_response: %s' % create_role_response) + logging.debug("create_role_response: %s" % create_role_response) response = self.client.auth.oidc.list_roles( path=self.TEST_OIDC_PATH, ) - logging.debug('list_roles response: %s' % response) + logging.debug("list_roles response: %s" % response) self.assertIn( member=role_name, - container=response['data']['keys'], + container=response["data"]["keys"], ) - @parameterized.expand([ - param( - 'success', - role_name='hvac', - allowed_redirect_uris=['https://localhost:8200/oidc-test/callback'], - user_claim='https://vault/user', - ), - ]) + @parameterized.expand( + [ + param( + "success", + role_name="hvac", + allowed_redirect_uris=["https://localhost:8200/oidc-test/callback"], + user_claim="https://vault/user", + ), + ] + ) def test_delete_role(self, label, role_name, allowed_redirect_uris, user_claim): create_role_response = self.client.auth.oidc.create_role( name=role_name, @@ -154,51 +165,59 @@ def test_delete_role(self, label, role_name, allowed_redirect_uris, user_claim): user_claim=user_claim, path=self.TEST_OIDC_PATH, ) - logging.debug('create_role_response: %s' % create_role_response) + logging.debug("create_role_response: %s" % create_role_response) response = self.client.auth.oidc.delete_role( name=role_name, path=self.TEST_OIDC_PATH, ) - logging.debug('delete_role response: %s' % response) + logging.debug("delete_role response: %s" % response) self.assertEqual( first=204, second=response.status_code, ) - @parameterized.expand([ - param( - 'success', - issuer='https://localhost:8200', - role_name='hvac', - allowed_redirect_uris=['https://localhost:8200/oidc-test/callback'], - user_claim='https://vault/user', - ), - ]) - def test_oidc_authorization_url_request(self, label, issuer, role_name, allowed_redirect_uris, user_claim): - if '%s/' % self.TEST_APPROLE_PATH not in self.client.sys.list_auth_methods(): + @parameterized.expand( + [ + param( + "success", + issuer="https://localhost:8200", + role_name="hvac", + allowed_redirect_uris=["https://localhost:8200/oidc-test/callback"], + user_claim="https://vault/user", + ), + ] + ) + def test_oidc_authorization_url_request( + self, label, issuer, role_name, allowed_redirect_uris, user_claim + ): + if "%s/" % self.TEST_APPROLE_PATH not in self.client.sys.list_auth_methods(): self.client.sys.enable_auth_method( - method_type='approle', + method_type="approle", path=self.TEST_APPROLE_PATH, ) - id_token_role_name = 'hvac-oidc-test' - key_name = 'oidc-test-key' - create_or_update_role_response = self.client.secrets.identity.create_or_update_role( - name=id_token_role_name, - key=key_name, + id_token_role_name = "hvac-oidc-test" + key_name = "oidc-test-key" + create_or_update_role_response = ( + self.client.secrets.identity.create_or_update_role( + name=id_token_role_name, + key=key_name, + ) + ) + logging.debug( + "create_or_update_role response: %s" % create_or_update_role_response ) - logging.debug('create_or_update_role response: %s' % create_or_update_role_response) read_role_response = self.client.secrets.identity.read_role( name=id_token_role_name, ) - logging.debug('read_role response: %s' % read_role_response) - token_client_id = read_role_response['data']['client_id'] + logging.debug("read_role response: %s" % read_role_response) + token_client_id = read_role_response["data"]["client_id"] create_named_key_response = self.client.secrets.identity.create_named_key( name=key_name, allowed_client_ids=[ token_client_id, ], ) - logging.debug('create_named_key response: %s' % create_named_key_response) + logging.debug("create_named_key response: %s" % create_named_key_response) # Log in using a dummy approle role so our client token has an associated identity self.login_using_admin_approle_role( role_id=self.TEST_APPROLE_ROLE_ID, @@ -207,46 +226,52 @@ def test_oidc_authorization_url_request(self, label, issuer, role_name, allowed_ generate_token_response = self.client.secrets.identity.generate_signed_id_token( name=id_token_role_name, ) - logging.debug('generate_token_response: %s' % generate_token_response) + logging.debug("generate_token_response: %s" % generate_token_response) - oidc_discovery_url = '{issuer}/v1/identity/oidc'.format(issuer=issuer) + oidc_discovery_url = "{issuer}/v1/identity/oidc".format(issuer=issuer) self.client.secrets.identity.configure_tokens_backend( issuer=issuer, ) response = self.client.auth.oidc.configure( oidc_discovery_url=oidc_discovery_url, - oidc_discovery_ca_pem=''.join(open(utils.get_config_file_path('server-cert.pem')).readlines()), + oidc_discovery_ca_pem="".join( + open(utils.get_config_file_path("server-cert.pem")).readlines() + ), oidc_client_id=self.oidc_client_id, - oidc_client_secret=generate_token_response['data']['token'], + oidc_client_secret=generate_token_response["data"]["token"], path=self.TEST_OIDC_PATH, ) - logging.debug('configure response: %s' % response) + logging.debug("configure response: %s" % response) create_role_response = self.client.auth.oidc.create_role( name=role_name, allowed_redirect_uris=allowed_redirect_uris, user_claim=user_claim, path=self.TEST_OIDC_PATH, ) - logging.debug('create_role_response: %s' % create_role_response) + logging.debug("create_role_response: %s" % create_role_response) response = self.client.auth.oidc.oidc_authorization_url_request( role=role_name, redirect_uri=allowed_redirect_uris[0], path=self.TEST_OIDC_PATH, ) - logging.debug('oidc_authorization_url_request response: %s' % response) + logging.debug("oidc_authorization_url_request response: %s" % response) self.assertIn( - member='?client_id={client_id}'.format(client_id=self.oidc_client_id), - container=response['data']['auth_url'], + member="?client_id={client_id}".format(client_id=self.oidc_client_id), + container=response["data"]["auth_url"], ) - @parameterized.expand([ - param( - 'success', - role_name='hvac-oidc', - allowed_redirect_uris=['https://localhost:8200/v1/auth/oidc-test/oidc/callback'], - user_claim='sub', - ), - ]) + @parameterized.expand( + [ + param( + "success", + role_name="hvac-oidc", + allowed_redirect_uris=[ + "https://localhost:8200/v1/auth/oidc-test/oidc/callback" + ], + user_claim="sub", + ), + ] + ) def test_oidc_callback(self, label, role_name, allowed_redirect_uris, user_claim): self.oidc_server = MockOauthProviderServerThread() self.oidc_server.start() @@ -256,59 +281,66 @@ def test_oidc_callback(self, label, role_name, allowed_redirect_uris, user_claim ) response = self.client.auth.oidc.configure( - oidc_discovery_url=oidc_details['discovery_url'], - oidc_response_mode='form_post', - oidc_response_types=['code'], - oidc_discovery_ca_pem=''.join(open(utils.get_config_file_path('server-cert.pem')).readlines()), - oidc_client_id=oidc_details['client_id'], - oidc_client_secret=oidc_details['client_secret'], + oidc_discovery_url=oidc_details["discovery_url"], + oidc_response_mode="form_post", + oidc_response_types=["code"], + oidc_discovery_ca_pem="".join( + open(utils.get_config_file_path("server-cert.pem")).readlines() + ), + oidc_client_id=oidc_details["client_id"], + oidc_client_secret=oidc_details["client_secret"], path=self.TEST_OIDC_PATH, ) - logging.debug('oidc.configure response: %s' % response) + logging.debug("oidc.configure response: %s" % response) create_role_response = self.client.auth.oidc.create_role( name=role_name, - role_type='oidc', + role_type="oidc", allowed_redirect_uris=allowed_redirect_uris, user_claim=user_claim, verbose_oidc_logging=True, path=self.TEST_OIDC_PATH, ) - logging.debug('create_role_response: %s' % create_role_response) + logging.debug("create_role_response: %s" % create_role_response) - oidc_authorization_url_response = self.client.auth.oidc.oidc_authorization_url_request( - role=role_name, - redirect_uri=allowed_redirect_uris[0], - path=self.TEST_OIDC_PATH, + oidc_authorization_url_response = ( + self.client.auth.oidc.oidc_authorization_url_request( + role=role_name, + redirect_uri=allowed_redirect_uris[0], + path=self.TEST_OIDC_PATH, + ) + ) + logging.debug( + "oidc_authorization_url_request response: %s" + % oidc_authorization_url_response ) - logging.debug('oidc_authorization_url_request response: %s' % oidc_authorization_url_response) - auth_url = oidc_authorization_url_response['data']['auth_url'] - logging.debug('auth_url: %s' % auth_url) + auth_url = oidc_authorization_url_response["data"]["auth_url"] + logging.debug("auth_url: %s" % auth_url) auth_url_qs = urlparse(auth_url).query auth_url_qs_parsed = parse_qs(auth_url_qs) - logging.debug('auth_url_qs_parsed: %s' % auth_url_qs_parsed) + logging.debug("auth_url_qs_parsed: %s" % auth_url_qs_parsed) - authorize_response = oidc_details['session'].get( + authorize_response = oidc_details["session"].get( url=auth_url, ) - logging.debug('authorize_response: %s' % authorize_response.json()) + logging.debug("authorize_response: %s" % authorize_response.json()) authorization = authorize_response.json() - logging.debug('authorization: %s' % authorization) + logging.debug("authorization: %s" % authorization) - client_cert_path = utils.get_config_file_path('client-cert.pem') - client_key_path = utils.get_config_file_path('client-key.pem') - server_cert_path = utils.get_config_file_path('server-cert.pem') - response = oidc_details['session'].post( + client_cert_path = utils.get_config_file_path("client-cert.pem") + client_key_path = utils.get_config_file_path("client-key.pem") + server_cert_path = utils.get_config_file_path("server-cert.pem") + response = oidc_details["session"].post( url=auth_url, cert=(client_cert_path, client_key_path), verify=server_cert_path, data=dict(confirm=True), ) oidc_auth_data = response.json() - logging.debug('oidc_auth_data: %s' % oidc_auth_data) - self.client.token = oidc_auth_data['auth']['client_token'] + logging.debug("oidc_auth_data: %s" % oidc_auth_data) + self.client.token = oidc_auth_data["auth"]["client_token"] self.assertIn( member=role_name, - container=self.client.lookup_token()['data']['meta']['role'], + container=self.client.lookup_token()["data"]["meta"]["role"], ) diff --git a/tests/integration_tests/api/auth_methods/test_okta.py b/tests/integration_tests/api/auth_methods/test_okta.py index 9928e217c..cf1e5df62 100644 --- a/tests/integration_tests/api/auth_methods/test_okta.py +++ b/tests/integration_tests/api/auth_methods/test_okta.py @@ -8,16 +8,16 @@ class TestOkta(HvacIntegrationTestCase, TestCase): - TEST_MOUNT_POINT = 'test-okta' - TEST_ORG_NAME = 'hvac-test' - TEST_BASE_URL = 'python-hvac.org' - TEST_USERNAME = 'hvac-person' - TEST_GROUP = 'hvac-group' + TEST_MOUNT_POINT = "test-okta" + TEST_ORG_NAME = "hvac-test" + TEST_BASE_URL = "python-hvac.org" + TEST_USERNAME = "hvac-person" + TEST_GROUP = "hvac-group" def setUp(self): super(TestOkta, self).setUp() self.client.sys.enable_auth_method( - method_type='okta', + method_type="okta", path=self.TEST_MOUNT_POINT, ) @@ -27,12 +27,14 @@ def tearDown(self): ) super(TestOkta, self).tearDown() - @parameterized.expand([ - param( - 'success', - ), - ]) - def test_configure(self, label, raises=None, exception_msg=''): + @parameterized.expand( + [ + param( + "success", + ), + ] + ) + def test_configure(self, label, raises=None, exception_msg=""): if raises: with self.assertRaises(raises) as cm: self.client.auth.okta.configure( @@ -50,29 +52,33 @@ def test_configure(self, label, raises=None, exception_msg=''): base_url=self.TEST_BASE_URL, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('configure_response: %s' % configure_response) + logging.debug("configure_response: %s" % configure_response) self.assertEqual( first=bool(configure_response), second=True, ) - @parameterized.expand([ - param( - 'success', - ), - param( - 'not configured', - configure_first=False, - raises=exceptions.InvalidPath, - ), - ]) - def test_read_config(self, label, configure_first=True, raises=None, exception_msg=''): + @parameterized.expand( + [ + param( + "success", + ), + param( + "not configured", + configure_first=False, + raises=exceptions.InvalidPath, + ), + ] + ) + def test_read_config( + self, label, configure_first=True, raises=None, exception_msg="" + ): if configure_first: configure_response = self.client.auth.okta.configure( org_name=self.TEST_ORG_NAME, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('configure_response: %s' % configure_response) + logging.debug("configure_response: %s" % configure_response) if raises: with self.assertRaises(raises) as cm: @@ -87,35 +93,39 @@ def test_read_config(self, label, configure_first=True, raises=None, exception_m read_config_response = self.client.auth.okta.read_config( mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('configure_response: %s' % read_config_response) + logging.debug("configure_response: %s" % read_config_response) self.assertEqual( - first=read_config_response['data']['org_name'], + first=read_config_response["data"]["org_name"], second=self.TEST_ORG_NAME, ) - @parameterized.expand([ - param( - 'success', - ), - param( - 'no configuration', - configure_first=False, - raises=exceptions.InvalidPath, - ), - ]) - def test_list_users(self, label, configure_first=True, raises=None, exception_msg=''): + @parameterized.expand( + [ + param( + "success", + ), + param( + "no configuration", + configure_first=False, + raises=exceptions.InvalidPath, + ), + ] + ) + def test_list_users( + self, label, configure_first=True, raises=None, exception_msg="" + ): if configure_first: configure_response = self.client.auth.okta.configure( org_name=self.TEST_ORG_NAME, base_url=self.TEST_BASE_URL, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('configure_response: %s' % configure_response) + logging.debug("configure_response: %s" % configure_response) register_user_response = self.client.auth.okta.register_user( username=self.TEST_USERNAME, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('register_user_response: %s' % register_user_response) + logging.debug("register_user_response: %s" % register_user_response) if raises: with self.assertRaises(raises) as cm: self.client.auth.okta.list_users( @@ -129,34 +139,38 @@ def test_list_users(self, label, configure_first=True, raises=None, exception_ms list_users_response = self.client.auth.okta.list_users( mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('list_users_response: %s' % list_users_response) + logging.debug("list_users_response: %s" % list_users_response) self.assertEqual( - first=list_users_response['data']['keys'], + first=list_users_response["data"]["keys"], second=[self.TEST_USERNAME], ) - @parameterized.expand([ - param( - 'double register', - ), - param( - 'success', - configure_first=False, - ), - ]) - def test_register_user(self, label, configure_first=True, raises=None, exception_msg=''): + @parameterized.expand( + [ + param( + "double register", + ), + param( + "success", + configure_first=False, + ), + ] + ) + def test_register_user( + self, label, configure_first=True, raises=None, exception_msg="" + ): if configure_first: configure_response = self.client.auth.okta.configure( org_name=self.TEST_ORG_NAME, base_url=self.TEST_BASE_URL, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('configure_response: %s' % configure_response) + logging.debug("configure_response: %s" % configure_response) register_user_response = self.client.auth.okta.register_user( username=self.TEST_USERNAME, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('register_user_response: %s' % register_user_response) + logging.debug("register_user_response: %s" % register_user_response) if raises: with self.assertRaises(raises) as cm: self.client.auth.okta.register_user( @@ -172,35 +186,39 @@ def test_register_user(self, label, configure_first=True, raises=None, exception username=self.TEST_USERNAME, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('register_user_response: %s' % register_user_response) + logging.debug("register_user_response: %s" % register_user_response) self.assertEqual( first=bool(register_user_response), second=True, ) - @parameterized.expand([ - param( - 'success', - ), - param( - 'no configuration', - configure_first=False, - raises=exceptions.InvalidPath, - ), - ]) - def test_read_user(self, label, configure_first=True, raises=None, exception_msg=''): + @parameterized.expand( + [ + param( + "success", + ), + param( + "no configuration", + configure_first=False, + raises=exceptions.InvalidPath, + ), + ] + ) + def test_read_user( + self, label, configure_first=True, raises=None, exception_msg="" + ): if configure_first: configure_response = self.client.auth.okta.configure( org_name=self.TEST_ORG_NAME, base_url=self.TEST_BASE_URL, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('configure_response: %s' % configure_response) + logging.debug("configure_response: %s" % configure_response) register_user_response = self.client.auth.okta.register_user( username=self.TEST_USERNAME, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('register_user_response: %s' % register_user_response) + logging.debug("register_user_response: %s" % register_user_response) if raises: with self.assertRaises(raises) as cm: self.client.auth.okta.read_user( @@ -216,34 +234,38 @@ def test_read_user(self, label, configure_first=True, raises=None, exception_msg username=self.TEST_USERNAME, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('read_user_response: %s' % read_user_response) + logging.debug("read_user_response: %s" % read_user_response) self.assertIn( - member='policies', - container=read_user_response['data'], + member="policies", + container=read_user_response["data"], ) - @parameterized.expand([ - param( - 'success', - ), - param( - 'no configuration', - configure_first=False, - ), - ]) - def test_delete_user(self, label, configure_first=True, raises=None, exception_msg=''): + @parameterized.expand( + [ + param( + "success", + ), + param( + "no configuration", + configure_first=False, + ), + ] + ) + def test_delete_user( + self, label, configure_first=True, raises=None, exception_msg="" + ): if configure_first: configure_response = self.client.auth.okta.configure( org_name=self.TEST_ORG_NAME, base_url=self.TEST_BASE_URL, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('configure_response: %s' % configure_response) + logging.debug("configure_response: %s" % configure_response) register_user_response = self.client.auth.okta.register_user( username=self.TEST_USERNAME, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('register_user_response: %s' % register_user_response) + logging.debug("register_user_response: %s" % register_user_response) if raises: with self.assertRaises(raises) as cm: self.client.auth.okta.delete_user( @@ -259,35 +281,39 @@ def test_delete_user(self, label, configure_first=True, raises=None, exception_m username=self.TEST_USERNAME, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('delete_user_response: %s' % delete_user_response) + logging.debug("delete_user_response: %s" % delete_user_response) self.assertEqual( first=bool(delete_user_response), second=True, ) - @parameterized.expand([ - param( - 'success', - ), - param( - 'no configuration', - configure_first=False, - raises=exceptions.InvalidPath, - ), - ]) - def test_list_groups(self, label, configure_first=True, raises=None, exception_msg=''): + @parameterized.expand( + [ + param( + "success", + ), + param( + "no configuration", + configure_first=False, + raises=exceptions.InvalidPath, + ), + ] + ) + def test_list_groups( + self, label, configure_first=True, raises=None, exception_msg="" + ): if configure_first: configure_response = self.client.auth.okta.configure( org_name=self.TEST_ORG_NAME, base_url=self.TEST_BASE_URL, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('configure_response: %s' % configure_response) + logging.debug("configure_response: %s" % configure_response) register_group_response = self.client.auth.okta.register_group( name=self.TEST_GROUP, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('register_group_response: %s' % register_group_response) + logging.debug("register_group_response: %s" % register_group_response) if raises: with self.assertRaises(raises) as cm: self.client.auth.okta.list_groups( @@ -301,34 +327,38 @@ def test_list_groups(self, label, configure_first=True, raises=None, exception_m list_groups_response = self.client.auth.okta.list_groups( mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('list_groups_response: %s' % list_groups_response) + logging.debug("list_groups_response: %s" % list_groups_response) self.assertEqual( - first=list_groups_response['data']['keys'], + first=list_groups_response["data"]["keys"], second=[self.TEST_GROUP], ) - @parameterized.expand([ - param( - 'double register', - ), - param( - 'success', - configure_first=False, - ), - ]) - def test_register_group(self, label, configure_first=True, raises=None, exception_msg=''): + @parameterized.expand( + [ + param( + "double register", + ), + param( + "success", + configure_first=False, + ), + ] + ) + def test_register_group( + self, label, configure_first=True, raises=None, exception_msg="" + ): if configure_first: configure_response = self.client.auth.okta.configure( org_name=self.TEST_ORG_NAME, base_url=self.TEST_BASE_URL, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('configure_response: %s' % configure_response) + logging.debug("configure_response: %s" % configure_response) register_group_response = self.client.auth.okta.register_group( name=self.TEST_GROUP, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('register_group_response: %s' % register_group_response) + logging.debug("register_group_response: %s" % register_group_response) if raises: with self.assertRaises(raises) as cm: self.client.auth.okta.register_group( @@ -344,35 +374,39 @@ def test_register_group(self, label, configure_first=True, raises=None, exceptio name=self.TEST_GROUP, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('register_group_response: %s' % register_group_response) + logging.debug("register_group_response: %s" % register_group_response) self.assertEqual( first=bool(register_group_response), second=True, ) - @parameterized.expand([ - param( - 'success', - ), - param( - 'no configuration', - configure_first=False, - raises=exceptions.InvalidPath, - ), - ]) - def test_read_group(self, label, configure_first=True, raises=None, exception_msg=''): + @parameterized.expand( + [ + param( + "success", + ), + param( + "no configuration", + configure_first=False, + raises=exceptions.InvalidPath, + ), + ] + ) + def test_read_group( + self, label, configure_first=True, raises=None, exception_msg="" + ): if configure_first: configure_response = self.client.auth.okta.configure( org_name=self.TEST_ORG_NAME, base_url=self.TEST_BASE_URL, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('configure_response: %s' % configure_response) + logging.debug("configure_response: %s" % configure_response) register_group_response = self.client.auth.okta.register_group( name=self.TEST_GROUP, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('register_group_response: %s' % register_group_response) + logging.debug("register_group_response: %s" % register_group_response) if raises: with self.assertRaises(raises) as cm: self.client.auth.okta.read_group( @@ -388,34 +422,38 @@ def test_read_group(self, label, configure_first=True, raises=None, exception_ms name=self.TEST_GROUP, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('read_group_response: %s' % read_group_response) + logging.debug("read_group_response: %s" % read_group_response) self.assertIn( - member='policies', - container=read_group_response['data'], + member="policies", + container=read_group_response["data"], ) - @parameterized.expand([ - param( - 'success', - ), - param( - 'no configuration', - configure_first=False, - ), - ]) - def test_delete_group(self, label, configure_first=True, raises=None, exception_msg=''): + @parameterized.expand( + [ + param( + "success", + ), + param( + "no configuration", + configure_first=False, + ), + ] + ) + def test_delete_group( + self, label, configure_first=True, raises=None, exception_msg="" + ): if configure_first: configure_response = self.client.auth.okta.configure( org_name=self.TEST_ORG_NAME, base_url=self.TEST_BASE_URL, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('configure_response: %s' % configure_response) + logging.debug("configure_response: %s" % configure_response) register_group_response = self.client.auth.okta.register_group( name=self.TEST_GROUP, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('register_group_response: %s' % register_group_response) + logging.debug("register_group_response: %s" % register_group_response) if raises: with self.assertRaises(raises) as cm: self.client.auth.okta.delete_group( @@ -431,7 +469,7 @@ def test_delete_group(self, label, configure_first=True, raises=None, exception_ name=self.TEST_GROUP, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('delete_group_response: %s' % delete_group_response) + logging.debug("delete_group_response: %s" % delete_group_response) self.assertEqual( first=bool(delete_group_response), second=True, diff --git a/tests/integration_tests/api/auth_methods/test_token.py b/tests/integration_tests/api/auth_methods/test_token.py new file mode 100644 index 000000000..a7ad8af6c --- /dev/null +++ b/tests/integration_tests/api/auth_methods/test_token.py @@ -0,0 +1,153 @@ +from unittest import TestCase +from hvac import exceptions + +from tests.utils.hvac_integration_test_case import HvacIntegrationTestCase + + +class TestToken(HvacIntegrationTestCase, TestCase): + def test_auth_token_manipulation(self): + result = self.client.auth.token.create(ttl="1h", renewable=True) + assert result["auth"]["client_token"] + + lookup = self.client.auth.token.lookup(result["auth"]["client_token"]) + assert result["auth"]["client_token"] == lookup["data"]["id"] + + renew = self.client.auth.token.renew(lookup["data"]["id"]) + assert result["auth"]["client_token"] == renew["auth"]["client_token"] + + self.client.auth.token.revoke(lookup["data"]["id"]) + + try: + lookup = self.client.auth.token.lookup(result["auth"]["client_token"]) + assert False + except exceptions.Forbidden: + assert True + except exceptions.InvalidPath: + assert True + except exceptions.InvalidRequest: + assert True + + def test_self_auth_token_manipulation(self): + result = self.client.auth.token.create(ttl="1h", renewable=True) + assert result["auth"]["client_token"] + self.client.token = result["auth"]["client_token"] + + lookup = self.client.auth.token.lookup(result["auth"]["client_token"]) + assert result["auth"]["client_token"] == lookup["data"]["id"] + + renew = self.client.auth.token.renew_self() + assert result["auth"]["client_token"] == renew["auth"]["client_token"] + + self.client.auth.token.revoke(lookup["data"]["id"]) + + try: + lookup = self.client.auth.token.lookup(result["auth"]["client_token"]) + assert False + except exceptions.Forbidden: + assert True + except exceptions.InvalidPath: + assert True + except exceptions.InvalidRequest: + assert True + + def test_token_accessor(self): + # Create token, check accessor is provided + result = self.client.auth.token.create(ttl="1h") + token_accessor = result["auth"].get("accessor", None) + assert token_accessor + + # Look up token by accessor, make sure token is excluded from results + lookup = self.client.auth.token.lookup_accessor(token_accessor) + assert lookup["data"]["accessor"] == token_accessor + assert not lookup["data"]["id"] + + # Revoke token using the accessor + self.client.auth.token.revoke_accessor(token_accessor) + + # Look up by accessor should fail + with self.assertRaises(exceptions.InvalidRequest): + lookup = self.client.auth.token.lookup_accessor(token_accessor) + + # As should regular lookup + with self.assertRaises(exceptions.Forbidden): + lookup = self.client.auth.token.lookup(result["auth"]["client_token"]) + + def test_create_token_explicit_max_ttl(self): + + token = self.client.auth.token.create(ttl="30m", explicit_max_ttl="5m") + + assert token["auth"]["client_token"] + + assert token["auth"]["lease_duration"] == 300 + + # Validate token + lookup = self.client.auth.token.lookup(token["auth"]["client_token"]) + assert token["auth"]["client_token"] == lookup["data"]["id"] + + def test_create_token_max_ttl(self): + + token = self.client.auth.token.create(ttl="5m") + + assert token["auth"]["client_token"] + + assert token["auth"]["lease_duration"] == 300 + + # Validate token + lookup = self.client.auth.token.lookup(token["auth"]["client_token"]) + assert token["auth"]["client_token"] == lookup["data"]["id"] + + def test_create_token_periodic(self): + + token = self.client.auth.token.create(period="30m") + + assert token["auth"]["client_token"] + + assert token["auth"]["lease_duration"] == 1800 + + # Validate token + lookup = self.client.auth.token.lookup(token["auth"]["client_token"]) + assert token["auth"]["client_token"] == lookup["data"]["id"] + assert lookup["data"]["period"] == 1800 + + def test_token_roles(self): + # No roles, list_token_roles == None + with self.assertRaises(exceptions.InvalidPath): + self.client.auth.token.list_roles() + + # Create token role + assert ( + self.client.auth.token.create_or_update_role("testrole").status_code == 204 + ) + + # List token roles + during = self.client.auth.token.list_roles()["data"]["keys"] + assert len(during) == 1 + assert during[0] == "testrole" + + # Delete token role + self.client.auth.token.delete_role("testrole") + + # No roles, list_token_roles == None + with self.assertRaises(exceptions.InvalidPath): + self.client.auth.token.list_roles() + + def test_create_token_w_role(self): + # Create policy + self.prep_policy("testpolicy") + + # Create token role w/ policy + assert ( + self.client.auth.token.create_or_update_role( + "testrole", allowed_policies="testpolicy" + ).status_code + == 204 + ) + + # Create token against role + token = self.client.auth.token.create(ttl="1h", role_name="testrole") + assert token["auth"]["client_token"] + assert token["auth"]["policies"] == ["default", "testpolicy"] + + # Cleanup + self.client.auth.token.delete_role("testrole") + self.client.sys.delete_policy("testpolicy") diff --git a/tests/integration_tests/api/secrets_engines/test_aws.py b/tests/integration_tests/api/secrets_engines/test_aws.py index b32d29397..dbbefb9f5 100644 --- a/tests/integration_tests/api/secrets_engines/test_aws.py +++ b/tests/integration_tests/api/secrets_engines/test_aws.py @@ -12,24 +12,20 @@ class TestAws(HvacIntegrationTestCase, TestCase): - TEST_MOUNT_POINT = 'aws-test' - TEST_ROLE_NAME = 'hvac-test-role' + TEST_MOUNT_POINT = "aws-test" + TEST_ROLE_NAME = "hvac-test-role" TEST_POLICY_DOCUMENT = { - 'Statement': [ - { - 'Action': 'ec2:Describe*', - 'Effect': 'Allow', - 'Resource': '*' - }, + "Statement": [ + {"Action": "ec2:Describe*", "Effect": "Allow", "Resource": "*"}, ], - 'Version': '2012-10-17' + "Version": "2012-10-17", } def setUp(self): super(TestAws, self).setUp() - if '%s/' % self.TEST_MOUNT_POINT not in self.client.list_auth_backends(): + if "%s/" % self.TEST_MOUNT_POINT not in self.client.sys.list_auth_methods(): self.client.sys.enable_secrets_engine( - backend_type='aws', + backend_type="aws", path=self.TEST_MOUNT_POINT, ) @@ -39,14 +35,18 @@ def tearDown(self): ) super(TestAws, self).tearDown() - @parameterized.expand([ - param( - 'success', - ), - ]) - def test_configure_root_iam_credentials(self, label, credentials='', raises=None, exception_message=''): - access_key = 'butts' - secret_key = 'secret-butts' + @parameterized.expand( + [ + param( + "success", + ), + ] + ) + def test_configure_root_iam_credentials( + self, label, credentials="", raises=None, exception_message="" + ): + access_key = "butts" + secret_key = "secret-butts" if raises: with self.assertRaises(raises) as cm: self.client.secrets.aws.configure_root_iam_credentials( @@ -62,22 +62,26 @@ def test_configure_root_iam_credentials(self, label, credentials='', raises=None configure_response = self.client.secrets.aws.configure_root_iam_credentials( access_key=access_key, secret_key=secret_key, - iam_endpoint='localhost', - sts_endpoint='localhost', + iam_endpoint="localhost", + sts_endpoint="localhost", mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('configure_response: %s' % configure_response) + logging.debug("configure_response: %s" % configure_response) self.assertEqual( first=bool(configure_response), second=True, ) - @parameterized.expand([ - param( - 'success', - ), - ]) - def test_configure_lease(self, label, lease='60s', lease_max='120s', raises=None, exception_message=''): + @parameterized.expand( + [ + param( + "success", + ), + ] + ) + def test_configure_lease( + self, label, lease="60s", lease_max="120s", raises=None, exception_message="" + ): if raises: with self.assertRaises(raises) as cm: self.client.secrets.aws.configure_lease( @@ -95,25 +99,35 @@ def test_configure_lease(self, label, lease='60s', lease_max='120s', raises=None lease_max=lease_max, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('configure_response: %s' % configure_response) + logging.debug("configure_response: %s" % configure_response) self.assertEqual( first=bool(configure_response), second=True, ) - @parameterized.expand([ - param( - 'success', - ), - ]) - def test_read_lease(self, label, lease='60s', lease_max='120s', configure_first=True, raises=None, exception_message=''): + @parameterized.expand( + [ + param( + "success", + ), + ] + ) + def test_read_lease( + self, + label, + lease="60s", + lease_max="120s", + configure_first=True, + raises=None, + exception_message="", + ): if configure_first: configure_response = self.client.secrets.aws.configure_lease( lease=lease, lease_max=lease_max, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('configure_response: %s' % configure_response) + logging.debug("configure_response: %s" % configure_response) if raises: with self.assertRaises(raises) as cm: @@ -128,56 +142,59 @@ def test_read_lease(self, label, lease='60s', lease_max='120s', configure_first= read_response = self.client.secrets.aws.read_lease_config( mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('read_response: %s' % read_response) + logging.debug("read_response: %s" % read_response) self.assertEqual( - first=int(lease_max.replace('s', '')), + first=int(lease_max.replace("s", "")), second=self.convert_python_ttl_value_to_expected_vault_response( - ttl_value=read_response['data']['lease_max'], + ttl_value=read_response["data"]["lease_max"], ), ) - @parameterized.expand([ - param( - 'success', - policy_document={ - 'Statement': [ - { - 'Action': 'ec2:Describe*', - 'Effect': 'Allow', - 'Resource': '*' - }, - ], - 'Version': '2012-10-17' - } - ), - param( - 'with policy_arns', - policy_arns=['arn:aws:iam::aws:policy/AmazonVPCReadOnlyAccess'], - ), - param( - 'assumed_role with policy document', - policy_document={ - 'Statement': [ - { - 'Action': 'ec2:Describe*', - 'Effect': 'Allow', - 'Resource': '*' - }, - ], - 'Version': '2012-10-17' - }, - credential_type='assumed_role', - ), - param( - 'invalid credential type', - credential_type='cat', - raises=ParamValidationError, - exception_message='invalid credential_type argument provided', - ), - ]) - def test_create_or_update_role(self, label, credential_type='iam_user', policy_document=None, default_sts_ttl=None, - max_sts_ttl=None, role_arns=None, policy_arns=None, raises=None, - exception_message=''): + @parameterized.expand( + [ + param( + "success", + policy_document={ + "Statement": [ + {"Action": "ec2:Describe*", "Effect": "Allow", "Resource": "*"}, + ], + "Version": "2012-10-17", + }, + ), + param( + "with policy_arns", + policy_arns=["arn:aws:iam::aws:policy/AmazonVPCReadOnlyAccess"], + ), + param( + "assumed_role with policy document", + policy_document={ + "Statement": [ + {"Action": "ec2:Describe*", "Effect": "Allow", "Resource": "*"}, + ], + "Version": "2012-10-17", + }, + credential_type="assumed_role", + ), + param( + "invalid credential type", + credential_type="cat", + raises=ParamValidationError, + exception_message="invalid credential_type argument provided", + ), + ] + ) + def test_create_or_update_role( + self, + label, + credential_type="iam_user", + policy_document=None, + default_sts_ttl=None, + max_sts_ttl=None, + role_arns=None, + policy_arns=None, + raises=None, + exception_message="", + ): if raises: with self.assertRaises(raises) as cm: self.client.secrets.aws.create_or_update_role( @@ -188,7 +205,7 @@ def test_create_or_update_role(self, label, credential_type='iam_user', policy_d max_sts_ttl=max_sts_ttl, role_arns=role_arns, policy_arns=policy_arns, - legacy_params=vault_version_lt('0.11.0'), + legacy_params=vault_version_lt("0.11.0"), mount_point=self.TEST_MOUNT_POINT, ) self.assertIn( @@ -204,28 +221,32 @@ def test_create_or_update_role(self, label, credential_type='iam_user', policy_d max_sts_ttl=max_sts_ttl, role_arns=role_arns, policy_arns=policy_arns, - legacy_params=vault_version_lt('0.11.0'), + legacy_params=vault_version_lt("0.11.0"), mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('role_response: %s' % role_response) + logging.debug("role_response: %s" % role_response) self.assertEqual( first=bool(role_response), second=True, ) - @parameterized.expand([ - param( - 'success', - ), - ]) - def test_read_role(self, label, configure_first=True, raises=None, exception_message=''): + @parameterized.expand( + [ + param( + "success", + ), + ] + ) + def test_read_role( + self, label, configure_first=True, raises=None, exception_message="" + ): if configure_first: self.client.secrets.aws.create_or_update_role( name=self.TEST_ROLE_NAME, - credential_type='iam_user', + credential_type="iam_user", policy_document=self.TEST_POLICY_DOCUMENT, - legacy_params=vault_version_lt('0.11.0'), + legacy_params=vault_version_lt("0.11.0"), mount_point=self.TEST_MOUNT_POINT, ) if raises: @@ -243,36 +264,40 @@ def test_read_role(self, label, configure_first=True, raises=None, exception_mes name=self.TEST_ROLE_NAME, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('read_role_response: %s' % read_role_response) - if vault_version_lt('0.11.0'): + logging.debug("read_role_response: %s" % read_role_response) + if vault_version_lt("0.11.0"): self.assertDictEqual( - d1=json.loads(read_role_response['data']['policy']), + d1=json.loads(read_role_response["data"]["policy"]), d2=self.TEST_POLICY_DOCUMENT, ) # https://github.com/hashicorp/vault/commit/2dcd0aed2a242f53dae03318b4d68693f7d92b81 - elif vault_version_lt('1.0.2'): + elif vault_version_lt("1.0.2"): self.assertEqual( - first=read_role_response['data']['credential_types'], - second=['iam_user'], + first=read_role_response["data"]["credential_types"], + second=["iam_user"], ) else: self.assertEqual( - first=read_role_response['data']['credential_type'], - second='iam_user', + first=read_role_response["data"]["credential_type"], + second="iam_user", ) - @parameterized.expand([ - param( - 'success', - ), - ]) - def test_list_roles(self, label, configure_first=True, raises=None, exception_message=''): + @parameterized.expand( + [ + param( + "success", + ), + ] + ) + def test_list_roles( + self, label, configure_first=True, raises=None, exception_message="" + ): if configure_first: self.client.secrets.aws.create_or_update_role( name=self.TEST_ROLE_NAME, - credential_type='iam_user', + credential_type="iam_user", policy_document=self.TEST_POLICY_DOCUMENT, - legacy_params=vault_version_lt('0.11.0'), + legacy_params=vault_version_lt("0.11.0"), mount_point=self.TEST_MOUNT_POINT, ) if raises: @@ -288,24 +313,28 @@ def test_list_roles(self, label, configure_first=True, raises=None, exception_me list_roles_response = self.client.secrets.aws.list_roles( mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('list_roles_response: %s' % list_roles_response) + logging.debug("list_roles_response: %s" % list_roles_response) self.assertEqual( - first=list_roles_response['data']['keys'], + first=list_roles_response["data"]["keys"], second=[self.TEST_ROLE_NAME], ) - @parameterized.expand([ - param( - 'success', - ), - ]) - def test_delete_role(self, label, configure_first=True, raises=None, exception_message=''): + @parameterized.expand( + [ + param( + "success", + ), + ] + ) + def test_delete_role( + self, label, configure_first=True, raises=None, exception_message="" + ): if configure_first: self.client.secrets.aws.create_or_update_role( name=self.TEST_ROLE_NAME, - credential_type='iam_user', + credential_type="iam_user", policy_document=self.TEST_POLICY_DOCUMENT, - legacy_params=vault_version_lt('0.11.0'), + legacy_params=vault_version_lt("0.11.0"), mount_point=self.TEST_MOUNT_POINT, ) if raises: @@ -323,7 +352,7 @@ def test_delete_role(self, label, configure_first=True, raises=None, exception_m name=self.TEST_ROLE_NAME, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('delete_role_response: %s' % delete_role_response) + logging.debug("delete_role_response: %s" % delete_role_response) self.assertEqual( first=bool(delete_role_response), second=True, diff --git a/tests/integration_tests/api/secrets_engines/test_azure.py b/tests/integration_tests/api/secrets_engines/test_azure.py index d396130dc..22290e391 100644 --- a/tests/integration_tests/api/secrets_engines/test_azure.py +++ b/tests/integration_tests/api/secrets_engines/test_azure.py @@ -9,36 +9,48 @@ from tests.utils.hvac_integration_test_case import HvacIntegrationTestCase -@skipIf(utils.vault_version_lt('0.11.0'), "Azure secret engine not available before Vault version 0.11.0") +@skipIf( + utils.vault_version_lt("0.11.0"), + "Azure secret engine not available before Vault version 0.11.0", +) class TestAzure(HvacIntegrationTestCase, TestCase): - TENANT_ID = '00000000-0000-0000-0000-000000000000' - SUBSCRIPTION_ID = '00000000-0000-0000-0000-000000000000' - DEFAULT_MOUNT_POINT = 'azure-integration-test' + TENANT_ID = "00000000-0000-0000-0000-000000000000" + SUBSCRIPTION_ID = "00000000-0000-0000-0000-000000000000" + DEFAULT_MOUNT_POINT = "azure-integration-test" def setUp(self): super(TestAzure, self).setUp() - self.client.enable_secret_backend( - backend_type='azure', - mount_point=self.DEFAULT_MOUNT_POINT, + self.client.sys.enable_secrets_engine( + backend_type="azure", + path=self.DEFAULT_MOUNT_POINT, ) def tearDown(self): - self.client.disable_secret_backend(mount_point=self.DEFAULT_MOUNT_POINT) + self.client.sys.disable_secrets_engine(path=self.DEFAULT_MOUNT_POINT) super(TestAzure, self).tearDown() - @parameterized.expand([ - ('no parameters',), - ('valid environment argument', 'AzureUSGovernmentCloud'), - ('invalid environment argument', 'AzureCityKity', exceptions.ParamValidationError, 'invalid environment argument provided'), - ]) - def test_configure_and_read_configuration(self, test_label, environment=None, raises=False, exception_message=''): + @parameterized.expand( + [ + ("no parameters",), + ("valid environment argument", "AzureUSGovernmentCloud"), + ( + "invalid environment argument", + "AzureCityKity", + exceptions.ParamValidationError, + "invalid environment argument provided", + ), + ] + ) + def test_configure_and_read_configuration( + self, test_label, environment=None, raises=False, exception_message="" + ): configure_arguments = { - 'subscription_id': self.SUBSCRIPTION_ID, - 'tenant_id': self.TENANT_ID, - 'mount_point': self.DEFAULT_MOUNT_POINT, + "subscription_id": self.SUBSCRIPTION_ID, + "tenant_id": self.TENANT_ID, + "mount_point": self.DEFAULT_MOUNT_POINT, } if environment is not None: - configure_arguments['environment'] = environment + configure_arguments["environment"] = environment if raises: with self.assertRaises(raises) as cm: self.client.secrets.azure.configure(**configure_arguments) @@ -47,46 +59,52 @@ def test_configure_and_read_configuration(self, test_label, environment=None, ra container=str(cm.exception), ) else: - configure_response = self.client.secrets.azure.configure(**configure_arguments) - logging.debug('configure_response: %s' % configure_response) + configure_response = self.client.secrets.azure.configure( + **configure_arguments + ) + logging.debug("configure_response: %s" % configure_response) read_configuration_response = self.client.secrets.azure.read_config( mount_point=self.DEFAULT_MOUNT_POINT, ) - logging.debug('read_configuration_response: %s' % read_configuration_response) + logging.debug( + "read_configuration_response: %s" % read_configuration_response + ) # raise Exception() self.assertEqual( first=self.SUBSCRIPTION_ID, - second=read_configuration_response['subscription_id'], + second=read_configuration_response["subscription_id"], ) self.assertEqual( first=self.TENANT_ID, - second=read_configuration_response['tenant_id'], + second=read_configuration_response["tenant_id"], ) if environment is not None: self.assertEqual( first=environment, - second=read_configuration_response['environment'], + second=read_configuration_response["environment"], ) - @parameterized.expand([ - ('create and then delete config',), - ]) + @parameterized.expand( + [ + ("create and then delete config",), + ] + ) def test_delete_config(self, test_label): configure_response = self.client.secrets.azure.configure( subscription_id=self.SUBSCRIPTION_ID, tenant_id=self.TENANT_ID, - mount_point=self.DEFAULT_MOUNT_POINT + mount_point=self.DEFAULT_MOUNT_POINT, ) - logging.debug('configure_response: %s' % configure_response) + logging.debug("configure_response: %s" % configure_response) self.client.secrets.azure.delete_config( mount_point=self.DEFAULT_MOUNT_POINT, ) read_configuration_response = self.client.secrets.azure.read_config( mount_point=self.DEFAULT_MOUNT_POINT, ) - logging.debug('read_configuration_response: %s' % read_configuration_response) + logging.debug("read_configuration_response: %s" % read_configuration_response) for key in read_configuration_response.keys(): self.assertEqual( - first='', + first="", second=read_configuration_response[key], ) diff --git a/tests/integration_tests/api/secrets_engines/test_gcp.py b/tests/integration_tests/api/secrets_engines/test_gcp.py index 492e805e8..3bf0f34dc 100644 --- a/tests/integration_tests/api/secrets_engines/test_gcp.py +++ b/tests/integration_tests/api/secrets_engines/test_gcp.py @@ -8,28 +8,32 @@ class TestGcp(HvacIntegrationTestCase, TestCase): - TEST_MOUNT_POINT = 'test-gcp' - TEST_ROLESET_NAME = 'hvac-roleset' - TEST_PROJECT_ID = 'test-hvac' + TEST_MOUNT_POINT = "test-gcp" + TEST_ROLESET_NAME = "hvac-roleset" + TEST_PROJECT_ID = "test-hvac" def setUp(self): super(TestGcp, self).setUp() - self.client.enable_secret_backend( - backend_type='gcp', - mount_point=self.TEST_MOUNT_POINT, + self.client.sys.enable_secrets_engine( + backend_type="gcp", + path=self.TEST_MOUNT_POINT, ) def tearDown(self): - self.client.disable_secret_backend(mount_point=self.TEST_MOUNT_POINT) + self.client.sys.disable_secrets_engine(path=self.TEST_MOUNT_POINT) super(TestGcp, self).tearDown() - @parameterized.expand([ - param( - 'success', - ), - ]) - def test_write_config(self, label, max_ttl=3600, raises=False, exception_message=''): - credentials = utils.load_config_file('example.jwt.json') + @parameterized.expand( + [ + param( + "success", + ), + ] + ) + def test_write_config( + self, label, max_ttl=3600, raises=False, exception_message="" + ): + credentials = utils.load_config_file("example.jwt.json") if raises: with self.assertRaises(raises) as cm: self.client.secrets.gcp.configure( @@ -47,7 +51,7 @@ def test_write_config(self, label, max_ttl=3600, raises=False, exception_message max_ttl=max_ttl, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('configure_response: %s' % configure_response) + logging.debug("configure_response: %s" % configure_response) self.assertEqual( first=bool(configure_response), second=True, @@ -55,8 +59,10 @@ def test_write_config(self, label, max_ttl=3600, raises=False, exception_message read_configuration_response = self.client.secrets.gcp.read_config( mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('read_configuration_response: %s' % read_configuration_response) + logging.debug( + "read_configuration_response: %s" % read_configuration_response + ) self.assertEqual( - first=read_configuration_response['data']['max_ttl'], + first=read_configuration_response["data"]["max_ttl"], second=max_ttl, ) diff --git a/tests/integration_tests/api/secrets_engines/test_identity.py b/tests/integration_tests/api/secrets_engines/test_identity.py index 8d241bcd8..b14b8d6ef 100644 --- a/tests/integration_tests/api/secrets_engines/test_identity.py +++ b/tests/integration_tests/api/secrets_engines/test_identity.py @@ -9,28 +9,33 @@ from tests.utils.hvac_integration_test_case import HvacIntegrationTestCase -@skipIf(utils.vault_version_lt('0.9.0'), "Identity secrets engine open sourced in Vault version >=0.9.0") +@skipIf( + utils.vault_version_lt("0.9.0"), + "Identity secrets engine open sourced in Vault version >=0.9.0", +) class TestIdentity(HvacIntegrationTestCase, TestCase): - TEST_APPROLE_PATH = 'identity-test-approle' - TEST_APPROLE_ROLE_ID = 'identity-test-role-id' - TEST_MOUNT_POINT = 'identity' - TEST_ENTITY_NAME = 'test-entity' - TEST_ALIAS_NAME = 'test-alias' - TEST_GROUP_NAME = 'test-group' - TEST_MEMBER_GROUP_NAME = 'test-group-member' - TEST_GROUP_ALIAS_NAME = 'test-group-alias' + TEST_APPROLE_PATH = "identity-test-approle" + TEST_APPROLE_ROLE_ID = "identity-test-role-id" + TEST_MOUNT_POINT = "identity" + TEST_ENTITY_NAME = "test-entity" + TEST_ALIAS_NAME = "test-alias" + TEST_GROUP_NAME = "test-group" + TEST_MEMBER_GROUP_NAME = "test-group-member" + TEST_GROUP_ALIAS_NAME = "test-group-alias" test_approle_accessor = None def setUp(self): super(TestIdentity, self).setUp() - if '%s/' % self.TEST_APPROLE_PATH not in self.client.sys.list_auth_methods(): + if "%s/" % self.TEST_APPROLE_PATH not in self.client.sys.list_auth_methods(): self.client.sys.enable_auth_method( - method_type='approle', + method_type="approle", path=self.TEST_APPROLE_PATH, ) list_auth_response = self.client.sys.list_auth_methods() - self.test_approle_accessor = list_auth_response['data']['%s/' % self.TEST_APPROLE_PATH]['accessor'] + self.test_approle_accessor = list_auth_response["data"][ + "%s/" % self.TEST_APPROLE_PATH + ]["accessor"] def tearDown(self): super(TestIdentity, self).tearDown() @@ -43,14 +48,20 @@ def tearDown(self): def tear_down_entities(self): try: - list_entities_response = self.client.secrets.identity.list_entities(mount_point=self.TEST_MOUNT_POINT) - logging.debug('list_entities_response in tearDown: %s' % list_entities_response) - entity_ids = list_entities_response['data']['keys'] + list_entities_response = self.client.secrets.identity.list_entities( + mount_point=self.TEST_MOUNT_POINT + ) + logging.debug( + "list_entities_response in tearDown: %s" % list_entities_response + ) + entity_ids = list_entities_response["data"]["keys"] except exceptions.InvalidPath: - logging.debug('InvalidPath raised when calling list_entites_by_id in tearDown...') + logging.debug( + "InvalidPath raised when calling list_entites_by_id in tearDown..." + ) entity_ids = [] for entity_id in entity_ids: - logging.debug('Deleting entity ID: %s' % entity_id) + logging.debug("Deleting entity ID: %s" % entity_id) self.client.secrets.identity.delete_entity( entity_id=entity_id, mount_point=self.TEST_MOUNT_POINT, @@ -58,14 +69,23 @@ def tear_down_entities(self): def tear_down_entity_aliases(self): try: - list_entity_aliases_response = self.client.secrets.identity.list_entity_aliases(mount_point=self.TEST_MOUNT_POINT) - logging.debug('list_entity_aliases_response in tearDown: %s' % list_entity_aliases_response) - alias_ids = list_entity_aliases_response['keys'] + list_entity_aliases_response = ( + self.client.secrets.identity.list_entity_aliases( + mount_point=self.TEST_MOUNT_POINT + ) + ) + logging.debug( + "list_entity_aliases_response in tearDown: %s" + % list_entity_aliases_response + ) + alias_ids = list_entity_aliases_response["keys"] except exceptions.InvalidPath: - logging.debug('InvalidPath raised when calling list_entites_by_id in tearDown...') + logging.debug( + "InvalidPath raised when calling list_entites_by_id in tearDown..." + ) alias_ids = [] for alias_id in alias_ids: - logging.debug('Deleting alias ID: %s' % alias_id) + logging.debug("Deleting alias ID: %s" % alias_id) self.client.secrets.identity.delete_entity_alias( alias_id=alias_id, mount_point=self.TEST_MOUNT_POINT, @@ -73,49 +93,59 @@ def tear_down_entity_aliases(self): def tear_down_groups(self): try: - list_group_response = self.client.secrets.identity.list_groups(mount_point=self.TEST_MOUNT_POINT) - logging.debug('list_group_response in tearDown: %s' % list_group_response) - group_ids = list_group_response['data']['keys'] + list_group_response = self.client.secrets.identity.list_groups( + mount_point=self.TEST_MOUNT_POINT + ) + logging.debug("list_group_response in tearDown: %s" % list_group_response) + group_ids = list_group_response["data"]["keys"] except exceptions.InvalidPath: - logging.debug('InvalidPath raised when calling list_groups in tearDown...') + logging.debug("InvalidPath raised when calling list_groups in tearDown...") group_ids = [] for group_id in group_ids: - logging.debug('Deleting group ID: %s' % group_id) + logging.debug("Deleting group ID: %s" % group_id) self.client.secrets.identity.delete_group( group_id=group_id, mount_point=self.TEST_MOUNT_POINT, ) - @parameterized.expand([ - param( - 'create success', - ), - param( - 'create success with metadata', - metadata=dict(something='meta') - ), - param( - 'create failure with metadata', - metadata='not a dict', - raises=exceptions.ParamValidationError, - exception_message='unsupported metadata argument provided', - ), - param( - 'update success', - create_first=True, - ), - ]) - def test_create_or_update_entity(self, label, metadata=None, create_first=False, raises=None, exception_message=''): + @parameterized.expand( + [ + param( + "create success", + ), + param("create success with metadata", metadata=dict(something="meta")), + param( + "create failure with metadata", + metadata="not a dict", + raises=exceptions.ParamValidationError, + exception_message="unsupported metadata argument provided", + ), + param( + "update success", + create_first=True, + ), + ] + ) + def test_create_or_update_entity( + self, + label, + metadata=None, + create_first=False, + raises=None, + exception_message="", + ): entity_id = None if create_first: - create_first_response = self.client.secrets.identity.create_or_update_entity( + create_first_response = ( + self.client.secrets.identity.create_or_update_entity( name=self.TEST_ENTITY_NAME, entity_id=entity_id, metadata=metadata, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('create_first_response: %s' % create_first_response) - entity_id = create_first_response['data']['id'] + ) + logging.debug("create_first_response: %s" % create_first_response) + entity_id = create_first_response["data"]["id"] if raises: with self.assertRaises(raises) as cm: self.client.secrets.identity.create_or_update_entity( @@ -128,22 +158,24 @@ def test_create_or_update_entity(self, label, metadata=None, create_first=False, container=str(cm.exception), ) else: - create_or_update_response = self.client.secrets.identity.create_or_update_entity( + create_or_update_response = ( + self.client.secrets.identity.create_or_update_entity( name=self.TEST_ENTITY_NAME, entity_id=entity_id, metadata=metadata, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('create_or_update_response: %s' % create_or_update_response) + ) + logging.debug("create_or_update_response: %s" % create_or_update_response) if isinstance(create_or_update_response, dict): self.assertIn( - member='id', - container=create_or_update_response['data'], + member="id", + container=create_or_update_response["data"], ) if entity_id is not None: self.assertEqual( first=entity_id, - second=create_or_update_response['data']['id'], + second=create_or_update_response["data"]["id"], ) else: self.assertEqual( @@ -151,37 +183,47 @@ def test_create_or_update_entity(self, label, metadata=None, create_first=False, second=True, ) - @parameterized.expand([ - param( - 'create success', - ), - param( - 'create success with metadata', - metadata=dict(something='meta') - ), - param( - 'create failure with metadata', - metadata='not a dict', - raises=exceptions.ParamValidationError, - exception_message='unsupported metadata argument provided', - ), - param( - 'update success', - create_first=True, - ), - ]) - @skipIf(utils.vault_version_lt('0.11.2'), '"by name" operations added in Vault v0.11.2') - def test_create_or_update_entity_by_name(self, label, metadata=None, create_first=False, raises=None, exception_message=''): + @parameterized.expand( + [ + param( + "create success", + ), + param("create success with metadata", metadata=dict(something="meta")), + param( + "create failure with metadata", + metadata="not a dict", + raises=exceptions.ParamValidationError, + exception_message="unsupported metadata argument provided", + ), + param( + "update success", + create_first=True, + ), + ] + ) + @skipIf( + utils.vault_version_lt("0.11.2"), '"by name" operations added in Vault v0.11.2' + ) + def test_create_or_update_entity_by_name( + self, + label, + metadata=None, + create_first=False, + raises=None, + exception_message="", + ): entity_id = None if create_first: - create_first_response = self.client.secrets.identity.create_or_update_entity( + create_first_response = ( + self.client.secrets.identity.create_or_update_entity( name=self.TEST_ENTITY_NAME, entity_id=entity_id, metadata=metadata, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('create_first_response: %s' % create_first_response) - entity_id = create_first_response['data']['id'] + ) + logging.debug("create_first_response: %s" % create_first_response) + entity_id = create_first_response["data"]["id"] if raises: with self.assertRaises(raises) as cm: self.client.secrets.identity.create_or_update_entity_by_name( @@ -194,21 +236,23 @@ def test_create_or_update_entity_by_name(self, label, metadata=None, create_firs container=str(cm.exception), ) else: - create_or_update_response = self.client.secrets.identity.create_or_update_entity_by_name( + create_or_update_response = ( + self.client.secrets.identity.create_or_update_entity_by_name( name=self.TEST_ENTITY_NAME, metadata=metadata, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('create_or_update_response: %s' % create_or_update_response) + ) + logging.debug("create_or_update_response: %s" % create_or_update_response) if not create_first: self.assertIn( - member='id', - container=create_or_update_response['data'], + member="id", + container=create_or_update_response["data"], ) if entity_id is not None: self.assertEqual( first=entity_id, - second=create_or_update_response['data']['id'], + second=create_or_update_response["data"]["id"], ) else: self.assertEqual( @@ -216,25 +260,27 @@ def test_create_or_update_entity_by_name(self, label, metadata=None, create_firs second=True, ) - @parameterized.expand([ - param( - 'read success', - ), - param( - 'read failure', - create_first=False, - raises=exceptions.InvalidPath - ), - ]) - def test_read_entity_by_id(self, label, create_first=True, raises=None, exception_message=''): + @parameterized.expand( + [ + param( + "read success", + ), + param("read failure", create_first=False, raises=exceptions.InvalidPath), + ] + ) + def test_read_entity_by_id( + self, label, create_first=True, raises=None, exception_message="" + ): entity_id = None if create_first: - create_first_response = self.client.secrets.identity.create_or_update_entity( + create_first_response = ( + self.client.secrets.identity.create_or_update_entity( name=self.TEST_ENTITY_NAME, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('create_first_response: %s' % create_first_response) - entity_id = create_first_response['data']['id'] + ) + logging.debug("create_first_response: %s" % create_first_response) + entity_id = create_first_response["data"]["id"] if raises: with self.assertRaises(raises) as cm: self.client.secrets.identity.read_entity( @@ -250,32 +296,36 @@ def test_read_entity_by_id(self, label, create_first=True, raises=None, exceptio entity_id=entity_id, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('read_entity_by_id_response: %s' % read_entity_by_id_response) + logging.debug("read_entity_by_id_response: %s" % read_entity_by_id_response) self.assertEqual( first=entity_id, - second=read_entity_by_id_response['data']['id'], + second=read_entity_by_id_response["data"]["id"], ) - @parameterized.expand([ - param( - 'read success', - ), - param( - 'read failure', - create_first=False, - raises=exceptions.InvalidPath - ), - ]) - @skipIf(utils.vault_version_lt('0.11.2'), '"by name" operations added in Vault v0.11.2') - def test_read_entity_by_name(self, label, create_first=True, raises=None, exception_message=''): + @parameterized.expand( + [ + param( + "read success", + ), + param("read failure", create_first=False, raises=exceptions.InvalidPath), + ] + ) + @skipIf( + utils.vault_version_lt("0.11.2"), '"by name" operations added in Vault v0.11.2' + ) + def test_read_entity_by_name( + self, label, create_first=True, raises=None, exception_message="" + ): entity_id = None if create_first: - create_first_response = self.client.secrets.identity.create_or_update_entity( + create_first_response = ( + self.client.secrets.identity.create_or_update_entity( name=self.TEST_ENTITY_NAME, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('create_first_response: %s' % create_first_response) - entity_id = create_first_response['data']['id'] + ) + logging.debug("create_first_response: %s" % create_first_response) + entity_id = create_first_response["data"]["id"] if raises: with self.assertRaises(raises) as cm: self.client.secrets.identity.read_entity_by_name( @@ -287,38 +337,43 @@ def test_read_entity_by_name(self, label, create_first=True, raises=None, except container=str(cm.exception), ) else: - read_entity_by_name_response = self.client.secrets.identity.read_entity_by_name( - name=self.TEST_ENTITY_NAME, - mount_point=self.TEST_MOUNT_POINT, + read_entity_by_name_response = ( + self.client.secrets.identity.read_entity_by_name( + name=self.TEST_ENTITY_NAME, + mount_point=self.TEST_MOUNT_POINT, + ) + ) + logging.debug( + "read_entity_by_name_response: %s" % read_entity_by_name_response ) - logging.debug('read_entity_by_name_response: %s' % read_entity_by_name_response) self.assertEqual( first=entity_id, - second=read_entity_by_name_response['data']['id'], + second=read_entity_by_name_response["data"]["id"], ) - @parameterized.expand([ - param( - 'update success', - ), - param( - 'update success with metadata', - metadata=dict(something='meta') - ), - param( - 'update failure with metadata', - metadata='not a dict', - raises=exceptions.ParamValidationError, - exception_message='unsupported metadata argument provided', - ), - ]) - def test_update_entity(self, label, metadata=None, raises=None, exception_message=''): + @parameterized.expand( + [ + param( + "update success", + ), + param("update success with metadata", metadata=dict(something="meta")), + param( + "update failure with metadata", + metadata="not a dict", + raises=exceptions.ParamValidationError, + exception_message="unsupported metadata argument provided", + ), + ] + ) + def test_update_entity( + self, label, metadata=None, raises=None, exception_message="" + ): create_first_response = self.client.secrets.identity.create_or_update_entity( - name=self.TEST_ENTITY_NAME, - mount_point=self.TEST_MOUNT_POINT, - ) - logging.debug('create_first_response: %s' % create_first_response) - entity_id = create_first_response['data']['id'] + name=self.TEST_ENTITY_NAME, + mount_point=self.TEST_MOUNT_POINT, + ) + logging.debug("create_first_response: %s" % create_first_response) + entity_id = create_first_response["data"]["id"] if raises: with self.assertRaises(raises) as cm: self.client.secrets.identity.update_entity( @@ -332,14 +387,14 @@ def test_update_entity(self, label, metadata=None, raises=None, exception_messag ) else: update_entity_response = self.client.secrets.identity.update_entity( - entity_id=entity_id, - metadata=metadata, - mount_point=self.TEST_MOUNT_POINT, - ) - logging.debug('update_entity_response: %s' % update_entity_response) + entity_id=entity_id, + metadata=metadata, + mount_point=self.TEST_MOUNT_POINT, + ) + logging.debug("update_entity_response: %s" % update_entity_response) if isinstance(update_entity_response, dict): self.assertEqual( - first=update_entity_response['data']['id'], + first=update_entity_response["data"]["id"], second=entity_id, ) else: @@ -348,24 +403,30 @@ def test_update_entity(self, label, metadata=None, raises=None, exception_messag second=True, ) - @parameterized.expand([ - param( - 'delete success', - ), - param( - 'delete success with no corresponding entity', - create_first=False, - ), - ]) - def test_delete_entity_by_id(self, label, create_first=True, raises=None, exception_message=''): + @parameterized.expand( + [ + param( + "delete success", + ), + param( + "delete success with no corresponding entity", + create_first=False, + ), + ] + ) + def test_delete_entity_by_id( + self, label, create_first=True, raises=None, exception_message="" + ): entity_id = None if create_first: - create_first_response = self.client.secrets.identity.create_or_update_entity( + create_first_response = ( + self.client.secrets.identity.create_or_update_entity( name=self.TEST_ENTITY_NAME, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('create_first_response: %s' % create_first_response) - entity_id = create_first_response['data']['id'] + ) + logging.debug("create_first_response: %s" % create_first_response) + entity_id = create_first_response["data"]["id"] if raises: with self.assertRaises(raises) as cm: self.client.secrets.identity.delete_entity( @@ -378,32 +439,40 @@ def test_delete_entity_by_id(self, label, create_first=True, raises=None, except ) else: delete_entity_response = self.client.secrets.identity.delete_entity( - entity_id=entity_id, - mount_point=self.TEST_MOUNT_POINT, - ) - logging.debug('update_entity_response: %s' % delete_entity_response) + entity_id=entity_id, + mount_point=self.TEST_MOUNT_POINT, + ) + logging.debug("update_entity_response: %s" % delete_entity_response) self.assertEqual( first=bool(delete_entity_response), second=True, ) - @parameterized.expand([ - param( - 'delete success', - ), - param( - 'delete success with no corresponding entity', - create_first=False, - ), - ]) - @skipIf(utils.vault_version_lt('0.11.2'), '"by name" operations added in Vault v0.11.2') - def test_delete_entity_by_name(self, label, create_first=True, raises=None, exception_message=''): + @parameterized.expand( + [ + param( + "delete success", + ), + param( + "delete success with no corresponding entity", + create_first=False, + ), + ] + ) + @skipIf( + utils.vault_version_lt("0.11.2"), '"by name" operations added in Vault v0.11.2' + ) + def test_delete_entity_by_name( + self, label, create_first=True, raises=None, exception_message="" + ): if create_first: - create_first_response = self.client.secrets.identity.create_or_update_entity( + create_first_response = ( + self.client.secrets.identity.create_or_update_entity( name=self.TEST_ENTITY_NAME, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('create_first_response: %s' % create_first_response) + ) + logging.debug("create_first_response: %s" % create_first_response) if raises: with self.assertRaises(raises) as cm: self.client.secrets.identity.delete_entity_by_name( @@ -416,37 +485,41 @@ def test_delete_entity_by_name(self, label, create_first=True, raises=None, exce ) else: delete_entity_response = self.client.secrets.identity.delete_entity_by_name( - name=self.TEST_ENTITY_NAME, - mount_point=self.TEST_MOUNT_POINT, - ) - logging.debug('update_entity_response: %s' % delete_entity_response) + name=self.TEST_ENTITY_NAME, + mount_point=self.TEST_MOUNT_POINT, + ) + logging.debug("update_entity_response: %s" % delete_entity_response) self.assertEqual( first=bool(delete_entity_response), second=True, ) - @parameterized.expand([ - param( - 'list success - LIST method', - ), - param( - 'list success - GET method', - method='GET', - ), - param( - 'list failure - invalid method', - method='PUT', - raises=exceptions.ParamValidationError, - exception_message='"method" parameter provided invalid value', - ), - ]) - def test_list_entities_by_id(self, label, method='LIST', raises=None, exception_message=''): + @parameterized.expand( + [ + param( + "list success - LIST method", + ), + param( + "list success - GET method", + method="GET", + ), + param( + "list failure - invalid method", + method="PUT", + raises=exceptions.ParamValidationError, + exception_message='"method" parameter provided invalid value', + ), + ] + ) + def test_list_entities_by_id( + self, label, method="LIST", raises=None, exception_message="" + ): create_response = self.client.secrets.identity.create_or_update_entity( - name=self.TEST_ENTITY_NAME, - mount_point=self.TEST_MOUNT_POINT, - ) - logging.debug('create_response: %s' % create_response) - entity_id = create_response['data']['id'] + name=self.TEST_ENTITY_NAME, + mount_point=self.TEST_MOUNT_POINT, + ) + logging.debug("create_response: %s" % create_response) + entity_id = create_response["data"]["id"] if raises: with self.assertRaises(raises) as cm: self.client.secrets.identity.list_entities( @@ -459,37 +532,43 @@ def test_list_entities_by_id(self, label, method='LIST', raises=None, exception_ ) else: list_entities_response = self.client.secrets.identity.list_entities( - method=method, - mount_point=self.TEST_MOUNT_POINT, - ) - logging.debug('list_entities_response: %s' % list_entities_response) + method=method, + mount_point=self.TEST_MOUNT_POINT, + ) + logging.debug("list_entities_response: %s" % list_entities_response) self.assertEqual( first=[entity_id], - second=list_entities_response['data']['keys'], + second=list_entities_response["data"]["keys"], ) - @parameterized.expand([ - param( - 'list success - LIST method', - ), - param( - 'list success - GET method', - method='GET', - ), - param( - 'list failure - invalid method', - method='PUT', - raises=exceptions.ParamValidationError, - exception_message='"method" parameter provided invalid value', - ), - ]) - @skipIf(utils.vault_version_lt('0.11.2'), '"by name" operations added in Vault v0.11.2') - def test_list_entities_by_name(self, label, method='LIST', raises=None, exception_message=''): + @parameterized.expand( + [ + param( + "list success - LIST method", + ), + param( + "list success - GET method", + method="GET", + ), + param( + "list failure - invalid method", + method="PUT", + raises=exceptions.ParamValidationError, + exception_message='"method" parameter provided invalid value', + ), + ] + ) + @skipIf( + utils.vault_version_lt("0.11.2"), '"by name" operations added in Vault v0.11.2' + ) + def test_list_entities_by_name( + self, label, method="LIST", raises=None, exception_message="" + ): create_response = self.client.secrets.identity.create_or_update_entity( - name=self.TEST_ENTITY_NAME, - mount_point=self.TEST_MOUNT_POINT, - ) - logging.debug('create_response: %s' % create_response) + name=self.TEST_ENTITY_NAME, + mount_point=self.TEST_MOUNT_POINT, + ) + logging.debug("create_response: %s" % create_response) if raises: with self.assertRaises(raises) as cm: self.client.secrets.identity.list_entities_by_name( @@ -502,36 +581,38 @@ def test_list_entities_by_name(self, label, method='LIST', raises=None, exceptio ) else: list_entities_response = self.client.secrets.identity.list_entities_by_name( - method=method, - mount_point=self.TEST_MOUNT_POINT, - ) - logging.debug('list_entities_response: %s' % list_entities_response) + method=method, + mount_point=self.TEST_MOUNT_POINT, + ) + logging.debug("list_entities_response: %s" % list_entities_response) self.assertEqual( first=[self.TEST_ENTITY_NAME], - second=list_entities_response['data']['keys'], + second=list_entities_response["data"]["keys"], ) - @parameterized.expand([ - param( - 'merge success', - ), - param( - 'merge failure', - ), - ]) - def test_merge_entities(self, label, raises=None, exception_message=''): + @parameterized.expand( + [ + param( + "merge success", + ), + param( + "merge failure", + ), + ] + ) + def test_merge_entities(self, label, raises=None, exception_message=""): create_response = self.client.secrets.identity.create_or_update_entity( - name=self.TEST_ENTITY_NAME, - mount_point=self.TEST_MOUNT_POINT, - ) - logging.debug('create_response: %s' % create_response) + name=self.TEST_ENTITY_NAME, + mount_point=self.TEST_MOUNT_POINT, + ) + logging.debug("create_response: %s" % create_response) create_response2 = self.client.secrets.identity.create_or_update_entity( - name='%s2' % self.TEST_ENTITY_NAME, - mount_point=self.TEST_MOUNT_POINT, - ) - logging.debug('create_response2: %s' % create_response) - to_entity_id = create_response['data']['id'] - from_entity_ids = [create_response2['data']['id']] + name="%s2" % self.TEST_ENTITY_NAME, + mount_point=self.TEST_MOUNT_POINT, + ) + logging.debug("create_response2: %s" % create_response) + to_entity_id = create_response["data"]["id"] + from_entity_ids = [create_response2["data"]["id"]] if raises: with self.assertRaises(raises) as cm: self.client.secrets.identity.merge_entities( @@ -545,35 +626,41 @@ def test_merge_entities(self, label, raises=None, exception_message=''): ) else: merge_entities_response = self.client.secrets.identity.merge_entities( - from_entity_ids=from_entity_ids, - to_entity_id=to_entity_id, - mount_point=self.TEST_MOUNT_POINT, - ) - logging.debug('merge_entities_response: %s' % merge_entities_response) + from_entity_ids=from_entity_ids, + to_entity_id=to_entity_id, + mount_point=self.TEST_MOUNT_POINT, + ) + logging.debug("merge_entities_response: %s" % merge_entities_response) self.assertEqual( first=bool(merge_entities_response), second=True, ) - @parameterized.expand([ - param( - 'create success', - ), - param( - 'update success', - create_first=True, - ), - ]) - def test_create_or_update_entity_alias(self, label, create_first=False, raises=None, exception_message=''): + @parameterized.expand( + [ + param( + "create success", + ), + param( + "update success", + create_first=True, + ), + ] + ) + def test_create_or_update_entity_alias( + self, label, create_first=False, raises=None, exception_message="" + ): entity_id = None if create_first: - create_first_response = self.client.secrets.identity.create_or_update_entity( + create_first_response = ( + self.client.secrets.identity.create_or_update_entity( name=self.TEST_ENTITY_NAME, entity_id=entity_id, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('create_first_response: %s' % create_first_response) - entity_id = create_first_response['data']['id'] + ) + logging.debug("create_first_response: %s" % create_first_response) + entity_id = create_first_response["data"]["id"] if raises: with self.assertRaises(raises) as cm: self.client.secrets.identity.create_or_update_entity_alias( @@ -587,51 +674,66 @@ def test_create_or_update_entity_alias(self, label, create_first=False, raises=N container=str(cm.exception), ) else: - create_or_update_response = self.client.secrets.identity.create_or_update_entity_alias( + create_or_update_response = ( + self.client.secrets.identity.create_or_update_entity_alias( name=self.TEST_ALIAS_NAME, canonical_id=entity_id, mount_accessor=self.test_approle_accessor, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('create_or_update_response: %s' % create_or_update_response) + ) + logging.debug("create_or_update_response: %s" % create_or_update_response) self.assertIn( - member='id', - container=create_or_update_response['data'], + member="id", + container=create_or_update_response["data"], ) if entity_id is not None: self.assertEqual( - first=create_or_update_response['data']['canonical_id'], + first=create_or_update_response["data"]["canonical_id"], second=entity_id, ) - @parameterized.expand([ - param( - 'read success', - ), - param( - 'read failure', - create_first=False, - raises=exceptions.InvalidPath, - ), - ]) - def test_read_entity_alias_by_id(self, label, create_first=True, raises=None, exception_message=''): + @parameterized.expand( + [ + param( + "read success", + ), + param( + "read failure", + create_first=False, + raises=exceptions.InvalidPath, + ), + ] + ) + def test_read_entity_alias_by_id( + self, label, create_first=True, raises=None, exception_message="" + ): alias_id = None if create_first: - create_entity_first_response = self.client.secrets.identity.create_or_update_entity( + create_entity_first_response = ( + self.client.secrets.identity.create_or_update_entity( name=self.TEST_ENTITY_NAME, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('create_entity_first_response: %s' % create_entity_first_response) - entity_id = create_entity_first_response['data']['id'] - create_entity_alias_first_response = self.client.secrets.identity.create_or_update_entity_alias( + ) + logging.debug( + "create_entity_first_response: %s" % create_entity_first_response + ) + entity_id = create_entity_first_response["data"]["id"] + create_entity_alias_first_response = ( + self.client.secrets.identity.create_or_update_entity_alias( name=self.TEST_ALIAS_NAME, canonical_id=entity_id, mount_accessor=self.test_approle_accessor, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('create_entity_alias_first_response: %s' % create_entity_alias_first_response) - alias_id = create_entity_alias_first_response['data']['id'] + ) + logging.debug( + "create_entity_alias_first_response: %s" + % create_entity_alias_first_response + ) + alias_id = create_entity_alias_first_response["data"]["id"] if raises: with self.assertRaises(raises) as cm: self.client.secrets.identity.read_entity_alias( @@ -644,49 +746,60 @@ def test_read_entity_alias_by_id(self, label, create_first=True, raises=None, ex ) else: read_entity_alias_response = self.client.secrets.identity.read_entity_alias( - alias_id=alias_id, - mount_point=self.TEST_MOUNT_POINT, - ) - logging.debug('read_entity_alias_response: %s' % read_entity_alias_response) + alias_id=alias_id, + mount_point=self.TEST_MOUNT_POINT, + ) + logging.debug("read_entity_alias_response: %s" % read_entity_alias_response) self.assertIn( - member='id', - container=read_entity_alias_response['data'], + member="id", + container=read_entity_alias_response["data"], ) if alias_id is not None: self.assertEqual( - first=read_entity_alias_response['data']['id'], + first=read_entity_alias_response["data"]["id"], second=alias_id, ) - @parameterized.expand([ - param( - 'update success', - ), - param( - 'update failure with invalid mount accessor', - mount_accessor='not a valid accessor', - raises=exceptions.InvalidRequest, - exception_message='invalid mount accessor', - ), - ]) - def test_update_entity_alias_by_id(self, label, mount_accessor=None, raises=None, exception_message=''): + @parameterized.expand( + [ + param( + "update success", + ), + param( + "update failure with invalid mount accessor", + mount_accessor="not a valid accessor", + raises=exceptions.InvalidRequest, + exception_message="invalid mount accessor", + ), + ] + ) + def test_update_entity_alias_by_id( + self, label, mount_accessor=None, raises=None, exception_message="" + ): if mount_accessor is None: mount_accessor = self.test_approle_accessor - create_entity_first_response = self.client.secrets.identity.create_or_update_entity( + create_entity_first_response = ( + self.client.secrets.identity.create_or_update_entity( name=self.TEST_ENTITY_NAME, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('create_entity_first_response: %s' % create_entity_first_response) - entity_id = create_entity_first_response['data']['id'] - create_entity_alias_first_response = self.client.secrets.identity.create_or_update_entity_alias( + ) + logging.debug("create_entity_first_response: %s" % create_entity_first_response) + entity_id = create_entity_first_response["data"]["id"] + create_entity_alias_first_response = ( + self.client.secrets.identity.create_or_update_entity_alias( name=self.TEST_ALIAS_NAME, canonical_id=entity_id, mount_accessor=self.test_approle_accessor, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('create_entity_alias_first_response: %s' % create_entity_alias_first_response) - alias_id = create_entity_alias_first_response['data']['id'] + ) + logging.debug( + "create_entity_alias_first_response: %s" + % create_entity_alias_first_response + ) + alias_id = create_entity_alias_first_response["data"]["id"] if raises: with self.assertRaises(raises) as cm: self.client.secrets.identity.update_entity_alias( @@ -702,20 +815,20 @@ def test_update_entity_alias_by_id(self, label, mount_accessor=None, raises=None ) else: update_entity_response = self.client.secrets.identity.update_entity_alias( - alias_id=alias_id, - name=self.TEST_ALIAS_NAME, - canonical_id=entity_id, - mount_accessor=mount_accessor, - mount_point=self.TEST_MOUNT_POINT, - ) - logging.debug('update_entity_response: %s' % update_entity_response) + alias_id=alias_id, + name=self.TEST_ALIAS_NAME, + canonical_id=entity_id, + mount_accessor=mount_accessor, + mount_point=self.TEST_MOUNT_POINT, + ) + logging.debug("update_entity_response: %s" % update_entity_response) if isinstance(update_entity_response, dict): self.assertIn( - member='id', - container=update_entity_response['data'], + member="id", + container=update_entity_response["data"], ) self.assertEqual( - first=update_entity_response['data']['id'], + first=update_entity_response["data"]["id"], second=alias_id, ) else: @@ -724,35 +837,41 @@ def test_update_entity_alias_by_id(self, label, mount_accessor=None, raises=None second=True, ) - @parameterized.expand([ - param( - 'list success - LIST method', - ), - param( - 'list success - GET method', - method='GET', - ), - param( - 'list failure - invalid method', - method='PUT', - raises=exceptions.ParamValidationError, - exception_message='"method" parameter provided invalid value', - ), - ]) - def test_list_entity_aliases_by_id(self, label, method='LIST', raises=None, exception_message=''): + @parameterized.expand( + [ + param( + "list success - LIST method", + ), + param( + "list success - GET method", + method="GET", + ), + param( + "list failure - invalid method", + method="PUT", + raises=exceptions.ParamValidationError, + exception_message='"method" parameter provided invalid value', + ), + ] + ) + def test_list_entity_aliases_by_id( + self, label, method="LIST", raises=None, exception_message="" + ): create_response = self.client.secrets.identity.create_or_update_entity( - name=self.TEST_ENTITY_NAME, - mount_point=self.TEST_MOUNT_POINT, - ) - logging.debug('create_response: %s' % create_response) - entity_id = create_response['data']['id'] - create_entity_alias_first_response = self.client.secrets.identity.create_or_update_entity_alias( + name=self.TEST_ENTITY_NAME, + mount_point=self.TEST_MOUNT_POINT, + ) + logging.debug("create_response: %s" % create_response) + entity_id = create_response["data"]["id"] + create_entity_alias_first_response = ( + self.client.secrets.identity.create_or_update_entity_alias( name=self.TEST_ALIAS_NAME, canonical_id=entity_id, mount_accessor=self.test_approle_accessor, mount_point=self.TEST_MOUNT_POINT, ) - alias_id = create_entity_alias_first_response['data']['id'] + ) + alias_id = create_entity_alias_first_response["data"]["id"] if raises: with self.assertRaises(raises) as cm: self.client.secrets.identity.list_entity_aliases( @@ -765,40 +884,48 @@ def test_list_entity_aliases_by_id(self, label, method='LIST', raises=None, exce ) else: list_entities_response = self.client.secrets.identity.list_entity_aliases( - method=method, - mount_point=self.TEST_MOUNT_POINT, - ) - logging.debug('list_entities_response: %s' % list_entities_response) + method=method, + mount_point=self.TEST_MOUNT_POINT, + ) + logging.debug("list_entities_response: %s" % list_entities_response) self.assertEqual( first=[alias_id], - second=list_entities_response['data']['keys'], + second=list_entities_response["data"]["keys"], ) - @parameterized.expand([ - param( - 'delete success', - ), - param( - 'delete success with no corresponding entity', - create_first=False, - ), - ]) - def test_delete_entity_alias_by_id(self, label, create_first=True, raises=None, exception_message=''): + @parameterized.expand( + [ + param( + "delete success", + ), + param( + "delete success with no corresponding entity", + create_first=False, + ), + ] + ) + def test_delete_entity_alias_by_id( + self, label, create_first=True, raises=None, exception_message="" + ): alias_id = None if create_first: - create_first_response = self.client.secrets.identity.create_or_update_entity( + create_first_response = ( + self.client.secrets.identity.create_or_update_entity( name=self.TEST_ENTITY_NAME, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('create_first_response: %s' % create_first_response) - entity_id = create_first_response['data']['id'] - create_entity_alias_first_response = self.client.secrets.identity.create_or_update_entity_alias( + ) + logging.debug("create_first_response: %s" % create_first_response) + entity_id = create_first_response["data"]["id"] + create_entity_alias_first_response = ( + self.client.secrets.identity.create_or_update_entity_alias( name=self.TEST_ALIAS_NAME, canonical_id=entity_id, mount_accessor=self.test_approle_accessor, mount_point=self.TEST_MOUNT_POINT, ) - alias_id = create_entity_alias_first_response['data']['id'] + ) + alias_id = create_entity_alias_first_response["data"]["id"] if raises: with self.assertRaises(raises) as cm: self.client.secrets.identity.delete_entity_alias( @@ -811,72 +938,81 @@ def test_delete_entity_alias_by_id(self, label, create_first=True, raises=None, ) else: delete_entity_response = self.client.secrets.identity.delete_entity_alias( - alias_id=alias_id, - mount_point=self.TEST_MOUNT_POINT, - ) - logging.debug('update_entity_response: %s' % delete_entity_response) + alias_id=alias_id, + mount_point=self.TEST_MOUNT_POINT, + ) + logging.debug("update_entity_response: %s" % delete_entity_response) self.assertEqual( first=bool(delete_entity_response), second=True, ) - @parameterized.expand([ - param( - 'create success', - ), - param( - 'create success with metadata', - metadata=dict(something='meta') - ), - param( - 'create failure with metadata', - metadata='not a dict', - raises=exceptions.ParamValidationError, - exception_message='unsupported metadata argument provided', - ), - param( - 'create success with group type', - group_type='external', - add_members=False, - ), - param( - 'create failure with invalid group type', - group_type='cosmic', - raises=exceptions.ParamValidationError, - exception_message='unsupported group_type argument provided "cosmic"', - ), - param( - 'update success', - create_first=True, - ), - ]) - def test_create_or_update_group(self, label, metadata=None, group_type='internal', create_first=False, - add_members=True, raises=None, exception_message=''): + @parameterized.expand( + [ + param( + "create success", + ), + param("create success with metadata", metadata=dict(something="meta")), + param( + "create failure with metadata", + metadata="not a dict", + raises=exceptions.ParamValidationError, + exception_message="unsupported metadata argument provided", + ), + param( + "create success with group type", + group_type="external", + add_members=False, + ), + param( + "create failure with invalid group type", + group_type="cosmic", + raises=exceptions.ParamValidationError, + exception_message='unsupported group_type argument provided "cosmic"', + ), + param( + "update success", + create_first=True, + ), + ] + ) + def test_create_or_update_group( + self, + label, + metadata=None, + group_type="internal", + create_first=False, + add_members=True, + raises=None, + exception_message="", + ): group_id = None member_entity_ids = None member_group_ids = None if add_members: - create_entity_response = self.client.secrets.identity.create_or_update_entity( + create_entity_response = ( + self.client.secrets.identity.create_or_update_entity( name=self.TEST_ENTITY_NAME, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('create_entity_response: %s' % create_entity_response) - member_entity_ids = [create_entity_response['data']['id']] + ) + logging.debug("create_entity_response: %s" % create_entity_response) + member_entity_ids = [create_entity_response["data"]["id"]] create_member_group = self.client.secrets.identity.create_or_update_group( - name=self.TEST_MEMBER_GROUP_NAME, - mount_point=self.TEST_MOUNT_POINT, - ) - logging.debug('create_member_group: %s' % create_member_group) - member_group_ids = [create_member_group['data']['id']] + name=self.TEST_MEMBER_GROUP_NAME, + mount_point=self.TEST_MOUNT_POINT, + ) + logging.debug("create_member_group: %s" % create_member_group) + member_group_ids = [create_member_group["data"]["id"]] if create_first: create_first_response = self.client.secrets.identity.create_or_update_group( - name=self.TEST_GROUP_NAME, - group_type=group_type, - metadata=metadata, - mount_point=self.TEST_MOUNT_POINT, - ) - logging.debug('create_first_response: %s' % create_first_response) - group_id = create_first_response['data']['id'] + name=self.TEST_GROUP_NAME, + group_type=group_type, + metadata=metadata, + mount_point=self.TEST_MOUNT_POINT, + ) + logging.debug("create_first_response: %s" % create_first_response) + group_id = create_first_response["data"]["id"] if raises: with self.assertRaises(raises) as cm: self.client.secrets.identity.create_or_update_group( @@ -893,7 +1029,8 @@ def test_create_or_update_group(self, label, metadata=None, group_type='internal container=str(cm.exception), ) else: - create_or_update_response = self.client.secrets.identity.create_or_update_group( + create_or_update_response = ( + self.client.secrets.identity.create_or_update_group( name=self.TEST_GROUP_NAME, group_id=group_id, group_type=group_type, @@ -902,29 +1039,32 @@ def test_create_or_update_group(self, label, metadata=None, group_type='internal member_entity_ids=member_entity_ids, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('create_or_update_response: %s' % create_or_update_response) + ) + logging.debug("create_or_update_response: %s" % create_or_update_response) if isinstance(create_or_update_response, dict): self.assertIn( - member='id', - container=create_or_update_response['data'], + member="id", + container=create_or_update_response["data"], ) if group_id is not None: self.assertEqual( first=group_id, - second=create_or_update_response['data']['id'], + second=create_or_update_response["data"]["id"], ) read_group_response = self.client.secrets.identity.read_group( - group_id=create_or_update_response['data']['id'], + group_id=create_or_update_response["data"]["id"], mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('read_group_response: %s' % read_group_response) + logging.debug("read_group_response: %s" % read_group_response) self.assertEqual( - first=read_group_response['data']['member_group_ids'], + first=read_group_response["data"]["member_group_ids"], second=member_group_ids, ) - expected_member_entity_ids = member_entity_ids if member_entity_ids is not None else [] + expected_member_entity_ids = ( + member_entity_ids if member_entity_ids is not None else [] + ) self.assertEqual( - first=read_group_response['data']['member_entity_ids'], + first=read_group_response["data"]["member_entity_ids"], second=expected_member_entity_ids, ) else: @@ -933,64 +1073,73 @@ def test_create_or_update_group(self, label, metadata=None, group_type='internal second=True, ) - @parameterized.expand([ - param( - 'update success', - ), - param( - 'update success with metadata', - metadata=dict(something='meta') - ), - param( - 'update failure with metadata', - metadata='not a dict', - raises=exceptions.ParamValidationError, - exception_message='unsupported metadata argument provided', - ), - param( - 'update failure with changed group type', - group_type='external', - raises=exceptions.InvalidRequest, - exception_message='group type cannot be changed', - ), - param( - 'update failure with invalid group type', - group_type='cosmic', - raises=exceptions.ParamValidationError, - exception_message='unsupported group_type argument provided "cosmic"', - ), - param( - 'update success', - create_first=True, - ), - ]) - def test_update_group_by_id(self, label, metadata=None, group_type='internal', create_first=True, - update_members=True, raises=None, exception_message=''): + @parameterized.expand( + [ + param( + "update success", + ), + param("update success with metadata", metadata=dict(something="meta")), + param( + "update failure with metadata", + metadata="not a dict", + raises=exceptions.ParamValidationError, + exception_message="unsupported metadata argument provided", + ), + param( + "update failure with changed group type", + group_type="external", + raises=exceptions.InvalidRequest, + exception_message="group type cannot be changed", + ), + param( + "update failure with invalid group type", + group_type="cosmic", + raises=exceptions.ParamValidationError, + exception_message='unsupported group_type argument provided "cosmic"', + ), + param( + "update success", + create_first=True, + ), + ] + ) + def test_update_group_by_id( + self, + label, + metadata=None, + group_type="internal", + create_first=True, + update_members=True, + raises=None, + exception_message="", + ): group_id = None member_entity_ids = None member_group_ids = None if update_members: - create_entity_response = self.client.secrets.identity.create_or_update_entity( + create_entity_response = ( + self.client.secrets.identity.create_or_update_entity( name=self.TEST_ENTITY_NAME, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('create_entity_response: %s' % create_entity_response) - member_entity_ids = [create_entity_response['data']['id']] + ) + logging.debug("create_entity_response: %s" % create_entity_response) + member_entity_ids = [create_entity_response["data"]["id"]] create_member_group = self.client.secrets.identity.create_or_update_group( - name=self.TEST_MEMBER_GROUP_NAME, - mount_point=self.TEST_MOUNT_POINT, - ) - logging.debug('create_member_group: %s' % create_member_group) - member_group_ids = [create_member_group['data']['id']] + name=self.TEST_MEMBER_GROUP_NAME, + mount_point=self.TEST_MOUNT_POINT, + ) + logging.debug("create_member_group: %s" % create_member_group) + member_group_ids = [create_member_group["data"]["id"]] if create_first: create_first_response = self.client.secrets.identity.create_or_update_group( - name=self.TEST_GROUP_NAME, - group_type='internal', - metadata=None, - mount_point=self.TEST_MOUNT_POINT, - ) - logging.debug('create_first_response: %s' % create_first_response) - group_id = create_first_response['data']['id'] + name=self.TEST_GROUP_NAME, + group_type="internal", + metadata=None, + mount_point=self.TEST_MOUNT_POINT, + ) + logging.debug("create_first_response: %s" % create_first_response) + group_id = create_first_response["data"]["id"] if raises: with self.assertRaises(raises) as cm: self.client.secrets.identity.update_group( @@ -1008,19 +1157,19 @@ def test_update_group_by_id(self, label, metadata=None, group_type='internal', c ) else: update_response = self.client.secrets.identity.update_group( - name=self.TEST_GROUP_NAME, - group_id=group_id, - group_type=group_type, - metadata=metadata, - member_group_ids=member_group_ids, - member_entity_ids=member_entity_ids, - mount_point=self.TEST_MOUNT_POINT, - ) - logging.debug('update_response: %s' % update_response) + name=self.TEST_GROUP_NAME, + group_id=group_id, + group_type=group_type, + metadata=metadata, + member_group_ids=member_group_ids, + member_entity_ids=member_entity_ids, + mount_point=self.TEST_MOUNT_POINT, + ) + logging.debug("update_response: %s" % update_response) if isinstance(update_response, dict): self.assertEqual( - first=update_response['data']['id'], + first=update_response["data"]["id"], second=group_id, ) else: @@ -1032,39 +1181,47 @@ def test_update_group_by_id(self, label, metadata=None, group_type='internal', c group_id=group_id, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('read_group_response: %s' % read_group_response) + logging.debug("read_group_response: %s" % read_group_response) self.assertEqual( - first=read_group_response['data']['member_group_ids'], + first=read_group_response["data"]["member_group_ids"], second=member_group_ids, ) - expected_member_entity_ids = member_entity_ids if member_entity_ids is not None else [] + expected_member_entity_ids = ( + member_entity_ids if member_entity_ids is not None else [] + ) self.assertEqual( - first=read_group_response['data']['member_entity_ids'], + first=read_group_response["data"]["member_entity_ids"], second=expected_member_entity_ids, ) - @parameterized.expand([ - param( - 'list success - LIST method', - ), - param( - 'list success - GET method', - method='GET', - ), - param( - 'list failure - invalid method', - method='PUT', - raises=exceptions.ParamValidationError, - exception_message='"method" parameter provided invalid value', - ), - ]) - @skipIf(utils.vault_version_lt('0.11.2'), '"by name" operations added in Vault v0.11.2') - def test_list_groups_by_name(self, label, method='LIST', raises=None, exception_message=''): + @parameterized.expand( + [ + param( + "list success - LIST method", + ), + param( + "list success - GET method", + method="GET", + ), + param( + "list failure - invalid method", + method="PUT", + raises=exceptions.ParamValidationError, + exception_message='"method" parameter provided invalid value', + ), + ] + ) + @skipIf( + utils.vault_version_lt("0.11.2"), '"by name" operations added in Vault v0.11.2' + ) + def test_list_groups_by_name( + self, label, method="LIST", raises=None, exception_message="" + ): create_response = self.client.secrets.identity.create_or_update_group( - name=self.TEST_GROUP_NAME, - mount_point=self.TEST_MOUNT_POINT, - ) - logging.debug('create_response: %s' % create_response) + name=self.TEST_GROUP_NAME, + mount_point=self.TEST_MOUNT_POINT, + ) + logging.debug("create_response: %s" % create_response) if raises: with self.assertRaises(raises) as cm: self.client.secrets.identity.list_groups_by_name( @@ -1077,56 +1234,65 @@ def test_list_groups_by_name(self, label, method='LIST', raises=None, exception_ ) else: list_groups_response = self.client.secrets.identity.list_groups_by_name( - method=method, - mount_point=self.TEST_MOUNT_POINT, - ) - logging.debug('list_groups_response: %s' % list_groups_response) + method=method, + mount_point=self.TEST_MOUNT_POINT, + ) + logging.debug("list_groups_response: %s" % list_groups_response) self.assertEqual( first=[self.TEST_GROUP_NAME], - second=list_groups_response['data']['keys'], + second=list_groups_response["data"]["keys"], ) - @parameterized.expand([ - param( - 'update success', - ), - param( - 'update success with metadata', - metadata=dict(something='meta') - ), - param( - 'update failure with metadata', - metadata='not a dict', - raises=exceptions.ParamValidationError, - exception_message='unsupported metadata argument provided', - ), - param( - 'update failure with changed group type', - group_type='external', - raises=exceptions.InvalidRequest, - exception_message='group type cannot be changed', - ), - param( - 'update failure with invalid group type', - group_type='cosmic', - raises=exceptions.ParamValidationError, - exception_message='unsupported group_type argument provided "cosmic"', - ), - param( - 'update success', - create_first=True, - ), - ]) - @skipIf(utils.vault_version_lt('0.11.2'), '"by name" operations added in Vault v0.11.2') - def test_create_or_update_group_by_name(self, label, metadata=None, group_type='internal', create_first=True, raises=None, exception_message=''): + @parameterized.expand( + [ + param( + "update success", + ), + param("update success with metadata", metadata=dict(something="meta")), + param( + "update failure with metadata", + metadata="not a dict", + raises=exceptions.ParamValidationError, + exception_message="unsupported metadata argument provided", + ), + param( + "update failure with changed group type", + group_type="external", + raises=exceptions.InvalidRequest, + exception_message="group type cannot be changed", + ), + param( + "update failure with invalid group type", + group_type="cosmic", + raises=exceptions.ParamValidationError, + exception_message='unsupported group_type argument provided "cosmic"', + ), + param( + "update success", + create_first=True, + ), + ] + ) + @skipIf( + utils.vault_version_lt("0.11.2"), '"by name" operations added in Vault v0.11.2' + ) + def test_create_or_update_group_by_name( + self, + label, + metadata=None, + group_type="internal", + create_first=True, + raises=None, + exception_message="", + ): if create_first: create_first_response = self.client.secrets.identity.create_or_update_group( - name=self.TEST_GROUP_NAME, - group_type='internal', - metadata=None, - mount_point=self.TEST_MOUNT_POINT, - ) - logging.debug('create_first_response: %s' % create_first_response) + name=self.TEST_GROUP_NAME, + group_type="internal", + metadata=None, + mount_point=self.TEST_MOUNT_POINT, + ) + logging.debug("create_first_response: %s" % create_first_response) if raises: with self.assertRaises(raises) as cm: self.client.secrets.identity.create_or_update_group_by_name( @@ -1140,40 +1306,44 @@ def test_create_or_update_group_by_name(self, label, metadata=None, group_type=' container=str(cm.exception), ) else: - update_response = self.client.secrets.identity.create_or_update_group_by_name( + update_response = ( + self.client.secrets.identity.create_or_update_group_by_name( name=self.TEST_GROUP_NAME, group_type=group_type, metadata=metadata, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('update_response: %s' % update_response) + ) + logging.debug("update_response: %s" % update_response) self.assertEqual( first=bool(update_response), second=True, ) - @parameterized.expand([ - param( - 'read success', - ), - param( - 'read failure', - create_first=False, - raises=exceptions.InvalidPath - ), - ]) - @skipIf(utils.vault_version_lt('0.11.2'), '"by name" operations added in Vault v0.11.2') - def test_read_group_by_name(self, label, create_first=True, raises=None, exception_message=''): + @parameterized.expand( + [ + param( + "read success", + ), + param("read failure", create_first=False, raises=exceptions.InvalidPath), + ] + ) + @skipIf( + utils.vault_version_lt("0.11.2"), '"by name" operations added in Vault v0.11.2' + ) + def test_read_group_by_name( + self, label, create_first=True, raises=None, exception_message="" + ): group_id = None if create_first: create_first_response = self.client.secrets.identity.create_or_update_group( - name=self.TEST_GROUP_NAME, - group_type='internal', - metadata=None, - mount_point=self.TEST_MOUNT_POINT, - ) - logging.debug('create_first_response: %s' % create_first_response) - group_id = create_first_response['data']['id'] + name=self.TEST_GROUP_NAME, + group_type="internal", + metadata=None, + mount_point=self.TEST_MOUNT_POINT, + ) + logging.debug("create_first_response: %s" % create_first_response) + group_id = create_first_response["data"]["id"] if raises: with self.assertRaises(raises) as cm: self.client.secrets.identity.read_entity_by_name( @@ -1189,36 +1359,42 @@ def test_read_group_by_name(self, label, create_first=True, raises=None, excepti name=self.TEST_GROUP_NAME, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('read_group_response: %s' % read_group_response) + logging.debug("read_group_response: %s" % read_group_response) self.assertEqual( first=group_id, - second=read_group_response['data']['id'], + second=read_group_response["data"]["id"], ) - @parameterized.expand([ - param( - 'create success', - ), - param( - 'update success', - create_first=True, - ), - ]) - def test_create_or_update_group_alias(self, label, create_first=False, raises=None, exception_message=''): + @parameterized.expand( + [ + param( + "create success", + ), + param( + "update success", + create_first=True, + ), + ] + ) + def test_create_or_update_group_alias( + self, label, create_first=False, raises=None, exception_message="" + ): alias_id = None create_first_response = self.client.secrets.identity.create_or_update_group( - name=self.TEST_ENTITY_NAME, - mount_point=self.TEST_MOUNT_POINT, - ) - logging.debug('create_first_response: %s' % create_first_response) + name=self.TEST_ENTITY_NAME, + mount_point=self.TEST_MOUNT_POINT, + ) + logging.debug("create_first_response: %s" % create_first_response) if create_first: - create_alias_response = self.client.secrets.identity.create_or_update_group_alias( + create_alias_response = ( + self.client.secrets.identity.create_or_update_group_alias( name=self.TEST_GROUP_NAME, mount_accessor=self.test_approle_accessor, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('create_alias_response: %s' % create_alias_response) - alias_id = create_alias_response['data']['id'] + ) + logging.debug("create_alias_response: %s" % create_alias_response) + alias_id = create_alias_response["data"]["id"] if raises: with self.assertRaises(raises) as cm: self.client.secrets.identity.create_or_update_group_alias( @@ -1232,22 +1408,24 @@ def test_create_or_update_group_alias(self, label, create_first=False, raises=No container=str(cm.exception), ) else: - create_or_update_response = self.client.secrets.identity.create_or_update_group_alias( + create_or_update_response = ( + self.client.secrets.identity.create_or_update_group_alias( name=self.TEST_GROUP_NAME, alias_id=alias_id, mount_accessor=self.test_approle_accessor, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('create_or_update_response: %s' % create_or_update_response) - if 'data' in create_or_update_response: + ) + logging.debug("create_or_update_response: %s" % create_or_update_response) + if "data" in create_or_update_response: self.assertIn( - member='id', - container=create_or_update_response['data'], + member="id", + container=create_or_update_response["data"], ) if alias_id is not None: self.assertEqual( first=alias_id, - second=create_or_update_response['data']['id'], + second=create_or_update_response["data"]["id"], ) else: self.assertEqual( @@ -1255,31 +1433,37 @@ def test_create_or_update_group_alias(self, label, create_first=False, raises=No second=204, ) - @parameterized.expand([ - param( - 'read success', - ), - param( - 'read failure', - create_first=False, - raises=exceptions.InvalidPath, - ), - ]) - def test_read_group_alias(self, label, create_first=True, raises=None, exception_message=''): + @parameterized.expand( + [ + param( + "read success", + ), + param( + "read failure", + create_first=False, + raises=exceptions.InvalidPath, + ), + ] + ) + def test_read_group_alias( + self, label, create_first=True, raises=None, exception_message="" + ): alias_id = None create_first_response = self.client.secrets.identity.create_or_update_group( - name=self.TEST_ENTITY_NAME, - mount_point=self.TEST_MOUNT_POINT, - ) - logging.debug('create_first_response: %s' % create_first_response) + name=self.TEST_ENTITY_NAME, + mount_point=self.TEST_MOUNT_POINT, + ) + logging.debug("create_first_response: %s" % create_first_response) if create_first: - create_alias_response = self.client.secrets.identity.create_or_update_group_alias( + create_alias_response = ( + self.client.secrets.identity.create_or_update_group_alias( name=self.TEST_GROUP_NAME, mount_accessor=self.test_approle_accessor, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('create_alias_response: %s' % create_alias_response) - alias_id = create_alias_response['data']['id'] + ) + logging.debug("create_alias_response: %s" % create_alias_response) + alias_id = create_alias_response["data"]["id"] if raises: with self.assertRaises(raises) as cm: self.client.secrets.identity.read_group_alias( @@ -1292,51 +1476,57 @@ def test_read_group_alias(self, label, create_first=True, raises=None, exception ) else: read_group_alias_response = self.client.secrets.identity.read_group_alias( - alias_id=alias_id, - mount_point=self.TEST_MOUNT_POINT, - ) - logging.debug('read_group_alias_response: %s' % read_group_alias_response) + alias_id=alias_id, + mount_point=self.TEST_MOUNT_POINT, + ) + logging.debug("read_group_alias_response: %s" % read_group_alias_response) self.assertIn( - member='id', - container=read_group_alias_response['data'], + member="id", + container=read_group_alias_response["data"], ) if alias_id is not None: self.assertEqual( - first=read_group_alias_response['data']['id'], + first=read_group_alias_response["data"]["id"], second=alias_id, ) - @parameterized.expand([ - param( - 'list success - LIST method', - ), - param( - 'list success - GET method', - method='GET', - ), - param( - 'list failure - invalid method', - method='PUT', - raises=exceptions.ParamValidationError, - exception_message='"method" parameter provided invalid value', - ), - ]) - def test_list_group_aliases(self, label, method='LIST', raises=None, exception_message=''): + @parameterized.expand( + [ + param( + "list success - LIST method", + ), + param( + "list success - GET method", + method="GET", + ), + param( + "list failure - invalid method", + method="PUT", + raises=exceptions.ParamValidationError, + exception_message='"method" parameter provided invalid value', + ), + ] + ) + def test_list_group_aliases( + self, label, method="LIST", raises=None, exception_message="" + ): create_group_response = self.client.secrets.identity.create_or_update_group( - name=self.TEST_GROUP_ALIAS_NAME, - group_type='internal', - metadata=None, - mount_point=self.TEST_MOUNT_POINT, - ) - logging.debug('create_group_response: %s' % create_group_response) - create_alias_response = self.client.secrets.identity.create_or_update_group_alias( + name=self.TEST_GROUP_ALIAS_NAME, + group_type="internal", + metadata=None, + mount_point=self.TEST_MOUNT_POINT, + ) + logging.debug("create_group_response: %s" % create_group_response) + create_alias_response = ( + self.client.secrets.identity.create_or_update_group_alias( name=self.TEST_GROUP_NAME, mount_accessor=self.test_approle_accessor, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('create_alias_response: %s' % create_alias_response) - alias_id = create_alias_response['data']['id'] + ) + logging.debug("create_alias_response: %s" % create_alias_response) + alias_id = create_alias_response["data"]["id"] if raises: with self.assertRaises(raises) as cm: self.client.secrets.identity.list_group_aliases( @@ -1349,60 +1539,67 @@ def test_list_group_aliases(self, label, method='LIST', raises=None, exception_m ) else: list_groups_response = self.client.secrets.identity.list_group_aliases( - method=method, - mount_point=self.TEST_MOUNT_POINT, - ) - logging.debug('list_groups_response: %s' % list_groups_response) + method=method, + mount_point=self.TEST_MOUNT_POINT, + ) + logging.debug("list_groups_response: %s" % list_groups_response) self.assertEqual( first=[alias_id], - second=list_groups_response['data']['keys'], + second=list_groups_response["data"]["keys"], ) - @parameterized.expand([ - param( - 'lookup entity', - criteria=['entity_id'], - ), - param( - 'lookup entity alias', - criteria=['alias_id'], - ), - param( - 'lookup missing entity', - criteria=['entity_id'], - create_first=False, - ), - ]) - def test_lookup_entity(self, label, criteria, create_first=True, raises=None, exception_message=''): + @parameterized.expand( + [ + param( + "lookup entity", + criteria=["entity_id"], + ), + param( + "lookup entity alias", + criteria=["alias_id"], + ), + param( + "lookup missing entity", + criteria=["entity_id"], + create_first=False, + ), + ] + ) + def test_lookup_entity( + self, label, criteria, create_first=True, raises=None, exception_message="" + ): lookup_params = {} if create_first: - create_entity_response = self.client.secrets.identity.create_or_update_entity( + create_entity_response = ( + self.client.secrets.identity.create_or_update_entity( name=self.TEST_ENTITY_NAME, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('create_entity_response: %s' % create_entity_response) - entity_id = create_entity_response['data']['id'] - create_alias_response = self.client.secrets.identity.create_or_update_entity_alias( + ) + logging.debug("create_entity_response: %s" % create_entity_response) + entity_id = create_entity_response["data"]["id"] + create_alias_response = ( + self.client.secrets.identity.create_or_update_entity_alias( name=self.TEST_ALIAS_NAME, canonical_id=entity_id, mount_accessor=self.test_approle_accessor, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('create_alias_response: %s' % create_alias_response) - alias_id = create_alias_response['data']['id'] - if 'entity_id' in criteria: - lookup_params['entity_id'] = entity_id - elif 'alias_id' in criteria: - lookup_params['alias_id'] = alias_id + ) + logging.debug("create_alias_response: %s" % create_alias_response) + alias_id = create_alias_response["data"]["id"] + if "entity_id" in criteria: + lookup_params["entity_id"] = entity_id + elif "alias_id" in criteria: + lookup_params["alias_id"] = alias_id else: for key in criteria: lookup_params[key] = key - logging.debug('lookup_params: %s' % lookup_params) + logging.debug("lookup_params: %s" % lookup_params) if raises: with self.assertRaises(raises) as cm: self.client.secrets.identity.lookup_entity( - mount_point=self.TEST_MOUNT_POINT, - **lookup_params + mount_point=self.TEST_MOUNT_POINT, **lookup_params ) self.assertIn( member=exception_message, @@ -1410,19 +1607,18 @@ def test_lookup_entity(self, label, criteria, create_first=True, raises=None, ex ) else: lookup_entity_response = self.client.secrets.identity.lookup_entity( - mount_point=self.TEST_MOUNT_POINT, - **lookup_params - ) - logging.debug('lookup_entity_response: %s' % lookup_entity_response) + mount_point=self.TEST_MOUNT_POINT, **lookup_params + ) + logging.debug("lookup_entity_response: %s" % lookup_entity_response) if create_first: - if 'entity_id' in criteria: + if "entity_id" in criteria: self.assertEqual( - first=lookup_entity_response['data']['name'], + first=lookup_entity_response["data"]["name"], second=self.TEST_ENTITY_NAME, ) - elif 'alias_id' in criteria: + elif "alias_id" in criteria: self.assertEqual( - first=lookup_entity_response['data']['aliases'][0]['name'], + first=lookup_entity_response["data"]["aliases"][0]["name"], second=self.TEST_ALIAS_NAME, ) else: @@ -1431,65 +1627,70 @@ def test_lookup_entity(self, label, criteria, create_first=True, raises=None, ex second=204, ) - @parameterized.expand([ - param( - 'lookup group', - criteria=['group_id'], - ), - param( - 'lookup group alias', - criteria=['alias_id'], - ), - param( - 'lookup name', - criteria=['name'], - ), - param( - 'lookup alias', - criteria=['alias_name', 'alias_mount_accessor'], - ), - param( - 'lookup missing group', - criteria=['group_id'], - create_first=False, - ), - ]) - def test_lookup_group(self, label, criteria, create_first=True, raises=None, exception_message=''): + @parameterized.expand( + [ + param( + "lookup group", + criteria=["group_id"], + ), + param( + "lookup group alias", + criteria=["alias_id"], + ), + param( + "lookup name", + criteria=["name"], + ), + param( + "lookup alias", + criteria=["alias_name", "alias_mount_accessor"], + ), + param( + "lookup missing group", + criteria=["group_id"], + create_first=False, + ), + ] + ) + def test_lookup_group( + self, label, criteria, create_first=True, raises=None, exception_message="" + ): lookup_params = {} if create_first: create_group_response = self.client.secrets.identity.create_or_update_group( - name=self.TEST_GROUP_NAME, - group_type='external', + name=self.TEST_GROUP_NAME, + group_type="external", + mount_point=self.TEST_MOUNT_POINT, + ) + logging.debug("create_group_response: %s" % create_group_response) + group_id = create_group_response["data"]["id"] + create_alias_response = ( + self.client.secrets.identity.create_or_update_group_alias( + name=self.TEST_GROUP_ALIAS_NAME, + canonical_id=group_id, + mount_accessor=self.test_approle_accessor, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('create_group_response: %s' % create_group_response) - group_id = create_group_response['data']['id'] - create_alias_response = self.client.secrets.identity.create_or_update_group_alias( - name=self.TEST_GROUP_ALIAS_NAME, - canonical_id=group_id, - mount_accessor=self.test_approle_accessor, - mount_point=self.TEST_MOUNT_POINT, - ) - logging.debug('create_alias_response: %s' % create_alias_response) - alias_id = create_alias_response['data']['id'] - if 'group_id' in criteria: - lookup_params['group_id'] = group_id - elif 'alias_id' in criteria: - lookup_params['alias_id'] = alias_id - elif 'name' in criteria: - lookup_params['name'] = self.TEST_GROUP_NAME - elif 'alias_name' in criteria and 'alias_mount_accessor' in criteria: - lookup_params['alias_name'] = self.TEST_GROUP_ALIAS_NAME - lookup_params['alias_mount_accessor'] = self.test_approle_accessor + ) + logging.debug("create_alias_response: %s" % create_alias_response) + alias_id = create_alias_response["data"]["id"] + if "group_id" in criteria: + lookup_params["group_id"] = group_id + elif "alias_id" in criteria: + lookup_params["alias_id"] = alias_id + elif "name" in criteria: + lookup_params["name"] = self.TEST_GROUP_NAME + elif "alias_name" in criteria and "alias_mount_accessor" in criteria: + lookup_params["alias_name"] = self.TEST_GROUP_ALIAS_NAME + lookup_params["alias_mount_accessor"] = self.test_approle_accessor else: for key in criteria: lookup_params[key] = key - logging.debug('lookup_params: %s' % lookup_params) + logging.debug("lookup_params: %s" % lookup_params) if raises: with self.assertRaises(raises) as cm: self.client.secrets.identity.lookup_group( - mount_point=self.TEST_MOUNT_POINT, - **lookup_params + mount_point=self.TEST_MOUNT_POINT, **lookup_params ) self.assertIn( member=exception_message, @@ -1497,19 +1698,20 @@ def test_lookup_group(self, label, criteria, create_first=True, raises=None, exc ) else: lookup_group_response = self.client.secrets.identity.lookup_group( - mount_point=self.TEST_MOUNT_POINT, - **lookup_params - ) - logging.debug('lookup_group_response: %s' % lookup_group_response) + mount_point=self.TEST_MOUNT_POINT, **lookup_params + ) + logging.debug("lookup_group_response: %s" % lookup_group_response) if create_first: - if 'group_id' in criteria or 'name' in criteria: + if "group_id" in criteria or "name" in criteria: self.assertEqual( - first=lookup_group_response['data']['name'], + first=lookup_group_response["data"]["name"], second=self.TEST_GROUP_NAME, ) - elif 'alias_id' in criteria or ('alias_name' in criteria and 'alias_mount_accessor' in criteria): + elif "alias_id" in criteria or ( + "alias_name" in criteria and "alias_mount_accessor" in criteria + ): self.assertEqual( - first=lookup_group_response['data']['alias']['name'], + first=lookup_group_response["data"]["alias"]["name"], second=self.TEST_GROUP_ALIAS_NAME, ) else: @@ -1518,25 +1720,27 @@ def test_lookup_group(self, label, criteria, create_first=True, raises=None, exc second=204, ) - @parameterized.expand([ - param( - 'empty issuer', - issuer='', - ), - param( - 'issuer set', - issuer='https://python-hvac.org:1234', - ), - ]) + @parameterized.expand( + [ + param( + "empty issuer", + issuer="", + ), + param( + "issuer set", + issuer="https://python-hvac.org:1234", + ), + ] + ) def test_configure_tokens_backend(self, label, issuer): response = self.client.secrets.identity.configure_tokens_backend( issuer=issuer, ) - logging.debug('configure_tokens_backend response: %s' % response) + logging.debug("configure_tokens_backend response: %s" % response) if issuer: # e.g.: 'warnings': ['If "issuer" is set explicitly, [...]'] self.assertGreaterEqual( - a=len(response['warnings']), + a=len(response["warnings"]), b=1, ) else: @@ -1546,122 +1750,138 @@ def test_configure_tokens_backend(self, label, issuer): second=response.status_code, ) - @parameterized.expand([ - param( - 'empty issuer', - issuer='', - ), - param( - 'issuer set', - issuer='', - ), - ]) + @parameterized.expand( + [ + param( + "empty issuer", + issuer="", + ), + param( + "issuer set", + issuer="", + ), + ] + ) def test_read_tokens_backend_configuration(self, label, issuer): - configure_tokens_backend_response = self.client.secrets.identity.configure_tokens_backend( - issuer=issuer, + configure_tokens_backend_response = ( + self.client.secrets.identity.configure_tokens_backend( + issuer=issuer, + ) + ) + logging.debug( + "configure_tokens_backend_response: %s" % configure_tokens_backend_response ) - logging.debug('configure_tokens_backend_response: %s' % configure_tokens_backend_response) response = self.client.secrets.identity.read_tokens_backend_configuration() - logging.debug('read_tokens_backend_configuration response: %s' % response) + logging.debug("read_tokens_backend_configuration response: %s" % response) self.assertEqual( first=issuer, - second=response['data']['issuer'], + second=response["data"]["issuer"], ) - @parameterized.expand([ - param( - 'name set', - name='hvac', - ), - ]) + @parameterized.expand( + [ + param( + "name set", + name="hvac", + ), + ] + ) def test_create_named_key(self, label, name): response = self.client.secrets.identity.create_named_key( name=name, ) - logging.debug('create_named_key response: %s' % response) + logging.debug("create_named_key response: %s" % response) self.assertEqual( first=204, second=response.status_code, ) - @parameterized.expand([ - param( - 'success', - name='hvac', - algorithm='ES256', - ), - ]) + @parameterized.expand( + [ + param( + "success", + name="hvac", + algorithm="ES256", + ), + ] + ) def test_read_named_key(self, label, name, algorithm): create_named_key_response = self.client.secrets.identity.create_named_key( name=name, algorithm=algorithm, ) - logging.debug('create_named_key response: %s' % create_named_key_response) + logging.debug("create_named_key response: %s" % create_named_key_response) response = self.client.secrets.identity.read_named_key( name=name, ) - logging.debug('read_named_key response: %s' % response) + logging.debug("read_named_key response: %s" % response) self.assertEqual( first=algorithm, - second=response['data']['algorithm'], + second=response["data"]["algorithm"], ) - @parameterized.expand([ - param( - 'success', - name='hvac', - ), - ]) + @parameterized.expand( + [ + param( + "success", + name="hvac", + ), + ] + ) def test_delete_named_key(self, label, name): create_named_key_response = self.client.secrets.identity.create_named_key( name=name, ) - logging.debug('create_named_key response: %s' % create_named_key_response) + logging.debug("create_named_key response: %s" % create_named_key_response) response = self.client.secrets.identity.delete_named_key( name=name, ) - logging.debug('delete_named_key response: %s' % response) + logging.debug("delete_named_key response: %s" % response) self.assertEqual( first=204, second=response.status_code, ) - @parameterized.expand([ - param( - 'success', - name='hvac', - ), - ]) + @parameterized.expand( + [ + param( + "success", + name="hvac", + ), + ] + ) def test_list_named_keys(self, label, name): create_named_key_response = self.client.secrets.identity.create_named_key( name=name, ) - logging.debug('create_named_key response: %s' % create_named_key_response) + logging.debug("create_named_key response: %s" % create_named_key_response) response = self.client.secrets.identity.list_named_keys() - logging.debug('list_named_keys response: %s' % response) + logging.debug("list_named_keys response: %s" % response) self.assertIn( member=name, - container=response['data']['keys'], + container=response["data"]["keys"], ) - @parameterized.expand([ - param( - 'lower ttl than at create time', - name='hvac', - verification_ttl=1800, - ), - ]) + @parameterized.expand( + [ + param( + "lower ttl than at create time", + name="hvac", + verification_ttl=1800, + ), + ] + ) def test_rotate_named_key(self, label, name, verification_ttl): create_named_key_response = self.client.secrets.identity.create_named_key( name=name, verification_ttl=verification_ttl + 1, ) - logging.debug('create_named_key response: %s' % create_named_key_response) + logging.debug("create_named_key response: %s" % create_named_key_response) response = self.client.secrets.identity.rotate_named_key( name=name, verification_ttl=verification_ttl, ) - logging.debug('rotate_named_key response: %s' % response) + logging.debug("rotate_named_key response: %s" % response) self.assertEqual( first=204, second=response.status_code, @@ -1669,135 +1889,163 @@ def test_rotate_named_key(self, label, name, verification_ttl): post_rotate_read_response = self.client.secrets.identity.read_named_key( name=name, ) - logging.debug('post_rotate_read_response response: %s' % post_rotate_read_response) + logging.debug( + "post_rotate_read_response response: %s" % post_rotate_read_response + ) self.assertEqual( first=verification_ttl, - second=post_rotate_read_response['data']['verification_ttl'], + second=post_rotate_read_response["data"]["verification_ttl"], ) - @parameterized.expand([ - param( - 'success', - name='hvac', - key_name='hvac_key', - ), - ]) + @parameterized.expand( + [ + param( + "success", + name="hvac", + key_name="hvac_key", + ), + ] + ) def test_create_or_update_role(self, label, name, key_name): create_named_key_response = self.client.secrets.identity.create_named_key( name=key_name, ) - logging.debug('create_named_key response: %s' % create_named_key_response) + logging.debug("create_named_key response: %s" % create_named_key_response) response = self.client.secrets.identity.create_or_update_role( name=name, key=key_name, ) - logging.debug('create_or_update_role response: %s' % response) + logging.debug("create_or_update_role response: %s" % response) self.assertEqual( first=204, second=response.status_code, ) - @parameterized.expand([ - param( - 'success', - name='hvac', - key_name='hvac_key', - ), - ]) + @parameterized.expand( + [ + param( + "success", + name="hvac", + key_name="hvac_key", + ), + ] + ) def test_read_role(self, label, name, key_name): create_named_key_response = self.client.secrets.identity.create_named_key( name=key_name, ) - logging.debug('create_named_key response: %s' % create_named_key_response) - create_or_update_role_response = self.client.secrets.identity.create_or_update_role( - name=name, - key=key_name, + logging.debug("create_named_key response: %s" % create_named_key_response) + create_or_update_role_response = ( + self.client.secrets.identity.create_or_update_role( + name=name, + key=key_name, + ) + ) + logging.debug( + "create_or_update_role response: %s" % create_or_update_role_response ) - logging.debug('create_or_update_role response: %s' % create_or_update_role_response) response = self.client.secrets.identity.read_role( name=name, ) - logging.debug('read_role response: %s' % response) + logging.debug("read_role response: %s" % response) self.assertEqual( first=key_name, - second=response['data']['key'], + second=response["data"]["key"], ) - @parameterized.expand([ - param( - 'success', - name='hvac', - key_name='hvac_key', - ), - ]) + @parameterized.expand( + [ + param( + "success", + name="hvac", + key_name="hvac_key", + ), + ] + ) def test_delete_role(self, label, name, key_name): create_named_key_response = self.client.secrets.identity.create_named_key( name=key_name, ) - logging.debug('create_named_key response: %s' % create_named_key_response) - create_or_update_role_response = self.client.secrets.identity.create_or_update_role( - name=name, - key=key_name, + logging.debug("create_named_key response: %s" % create_named_key_response) + create_or_update_role_response = ( + self.client.secrets.identity.create_or_update_role( + name=name, + key=key_name, + ) + ) + logging.debug( + "create_or_update_role response: %s" % create_or_update_role_response ) - logging.debug('create_or_update_role response: %s' % create_or_update_role_response) response = self.client.secrets.identity.delete_role( name=name, ) - logging.debug('delete_role response: %s' % response) + logging.debug("delete_role response: %s" % response) self.assertEqual( first=204, second=response.status_code, ) - @parameterized.expand([ - param( - 'success', - name='hvac', - key_name='hvac_key', - ), - ]) + @parameterized.expand( + [ + param( + "success", + name="hvac", + key_name="hvac_key", + ), + ] + ) def test_list_roles(self, label, name, key_name): create_named_key_response = self.client.secrets.identity.create_named_key( name=key_name, ) - logging.debug('create_named_key response: %s' % create_named_key_response) - create_or_update_role_response = self.client.secrets.identity.create_or_update_role( - name=name, - key=key_name, + logging.debug("create_named_key response: %s" % create_named_key_response) + create_or_update_role_response = ( + self.client.secrets.identity.create_or_update_role( + name=name, + key=key_name, + ) + ) + logging.debug( + "create_or_update_role response: %s" % create_or_update_role_response ) - logging.debug('create_or_update_role response: %s' % create_or_update_role_response) response = self.client.secrets.identity.list_roles() - logging.debug('list_roles response: %s' % response) + logging.debug("list_roles response: %s" % response) self.assertIn( member=name, - container=response['data']['keys'], + container=response["data"]["keys"], ) - @parameterized.expand([ - param( - 'success', - role_name='hvac', - key_name='hvac_key', - ), - ]) + @parameterized.expand( + [ + param( + "success", + role_name="hvac", + key_name="hvac_key", + ), + ] + ) def test_generate_signed_id_token(self, label, role_name, key_name): - create_or_update_role_response = self.client.secrets.identity.create_or_update_role( - name=role_name, - key=key_name, + create_or_update_role_response = ( + self.client.secrets.identity.create_or_update_role( + name=role_name, + key=key_name, + ) + ) + logging.debug( + "create_or_update_role response: %s" % create_or_update_role_response ) - logging.debug('create_or_update_role response: %s' % create_or_update_role_response) read_role_response = self.client.secrets.identity.read_role( name=role_name, ) - logging.debug('read_role response: %s' % read_role_response) - token_client_id = read_role_response['data']['client_id'] + logging.debug("read_role response: %s" % read_role_response) + token_client_id = read_role_response["data"]["client_id"] create_named_key_response = self.client.secrets.identity.create_named_key( name=key_name, allowed_client_ids=[ token_client_id, ], ) - logging.debug('create_named_key response: %s' % create_named_key_response) + logging.debug("create_named_key response: %s" % create_named_key_response) # Log in using a dummy approle role so our client token has an associated identity self.login_using_admin_approle_role( role_id=self.TEST_APPROLE_ROLE_ID, @@ -1806,89 +2054,103 @@ def test_generate_signed_id_token(self, label, role_name, key_name): response = self.client.secrets.identity.generate_signed_id_token( name=role_name, ) - logging.debug('generate_signed_id_token response: %s' % response) + logging.debug("generate_signed_id_token response: %s" % response) self.assertIn( member=token_client_id, - container=response['data']['client_id'], + container=response["data"]["client_id"], ) - @parameterized.expand([ - param( - 'success', - role_name='hvac', - key_name='hvac_key', - ), - ]) + @parameterized.expand( + [ + param( + "success", + role_name="hvac", + key_name="hvac_key", + ), + ] + ) def test_introspect_signed_id_token(self, label, role_name, key_name): - create_or_update_role_response = self.client.secrets.identity.create_or_update_role( - name=role_name, - key=key_name, + create_or_update_role_response = ( + self.client.secrets.identity.create_or_update_role( + name=role_name, + key=key_name, + ) + ) + logging.debug( + "create_or_update_role response: %s" % create_or_update_role_response ) - logging.debug('create_or_update_role response: %s' % create_or_update_role_response) read_role_response = self.client.secrets.identity.read_role( name=role_name, ) - logging.debug('read_role response: %s' % read_role_response) - token_client_id = read_role_response['data']['client_id'] + logging.debug("read_role response: %s" % read_role_response) + token_client_id = read_role_response["data"]["client_id"] create_named_key_response = self.client.secrets.identity.create_named_key( name=key_name, allowed_client_ids=[ token_client_id, ], ) - logging.debug('create_named_key response: %s' % create_named_key_response) + logging.debug("create_named_key response: %s" % create_named_key_response) # Log in using a dummy approle role so our client token has an associated identity self.login_using_admin_approle_role( role_id=self.TEST_APPROLE_ROLE_ID, path=self.TEST_APPROLE_PATH, ) - generate_signed_id_token_response = self.client.secrets.identity.generate_signed_id_token( - name=role_name, + generate_signed_id_token_response = ( + self.client.secrets.identity.generate_signed_id_token( + name=role_name, + ) + ) + logging.debug( + "generate_signed_id_token response: %s" % generate_signed_id_token_response ) - logging.debug('generate_signed_id_token response: %s' % generate_signed_id_token_response) response = self.client.secrets.identity.introspect_signed_id_token( - token=generate_signed_id_token_response['data']['token'], + token=generate_signed_id_token_response["data"]["token"], client_id=token_client_id, ) - logging.debug('introspect_signed_id_token response: %s' % response) + logging.debug("introspect_signed_id_token response: %s" % response) self.assertIn( - member='active', + member="active", container=response, ) self.assertTrue( - expr=response['active'], + expr=response["active"], ) - @parameterized.expand([ - param( - 'issuer set', - issuer='https://python-hvac.org:1234', - ), - ]) + @parameterized.expand( + [ + param( + "issuer set", + issuer="https://python-hvac.org:1234", + ), + ] + ) def test_read_well_known_configurations(self, label, issuer): response = self.client.secrets.identity.configure_tokens_backend( issuer=issuer, ) response = self.client.secrets.identity.read_well_known_configurations() - logging.debug('read_well_known_configurations response: %s' % response) + logging.debug("read_well_known_configurations response: %s" % response) self.assertIn( member=issuer, - container=response['issuer'], + container=response["issuer"], ) - @parameterized.expand([ - param( - 'success', - issuer='https://python-hvac.org:1234', - ), - ]) + @parameterized.expand( + [ + param( + "success", + issuer="https://python-hvac.org:1234", + ), + ] + ) def test_read_active_public_keys(self, label, issuer): response = self.client.secrets.identity.configure_tokens_backend( issuer=issuer, ) response = self.client.secrets.identity.read_active_public_keys() - logging.debug('read_active_public_keys response: %s' % response) + logging.debug("read_active_public_keys response: %s" % response) self.assertIn( - member='keys', + member="keys", container=response, ) diff --git a/tests/integration_tests/api/secrets_engines/test_kv_v1.py b/tests/integration_tests/api/secrets_engines/test_kv_v1.py index ee7cad1c9..f1315cc09 100644 --- a/tests/integration_tests/api/secrets_engines/test_kv_v1.py +++ b/tests/integration_tests/api/secrets_engines/test_kv_v1.py @@ -7,27 +7,36 @@ class TestKvV1(HvacIntegrationTestCase, TestCase): - DEFAULT_MOUNT_POINT = 'kvv1' + DEFAULT_MOUNT_POINT = "kvv1" def setUp(self): super(TestKvV1, self).setUp() - self.client.enable_secret_backend( - backend_type='kv', - mount_point=self.DEFAULT_MOUNT_POINT, + self.client.sys.enable_secrets_engine( + backend_type="kv", + path=self.DEFAULT_MOUNT_POINT, options=dict(version=1), ) def tearDown(self): - self.client.disable_secret_backend(mount_point=self.DEFAULT_MOUNT_POINT) + self.client.sys.disable_secrets_engine(path=self.DEFAULT_MOUNT_POINT) super(TestKvV1, self).tearDown() - @parameterized.expand([ - ('nonexistent secret', 'no-secret-here', False, exceptions.InvalidPath), - ('read secret', 'top-secret'), - ]) - def test_read_secret(self, test_label, path, write_secret_before_test=True, raises=None, exception_message=''): + @parameterized.expand( + [ + ("nonexistent secret", "no-secret-here", False, exceptions.InvalidPath), + ("read secret", "top-secret"), + ] + ) + def test_read_secret( + self, + test_label, + path, + write_secret_before_test=True, + raises=None, + exception_message="", + ): test_secret = { - 'pssst': 'hi', + "pssst": "hi", } if write_secret_before_test: self.client.secrets.kv.v1.create_or_update_secret( @@ -52,18 +61,32 @@ def test_read_secret(self, test_label, path, write_secret_before_test=True, rais ) self.assertDictEqual( d1=test_secret, - d2=read_secret_result['data'], + d2=read_secret_result["data"], ) - @parameterized.expand([ - ('nonexistent secret', 'hvac/no-secret-here', False, exceptions.InvalidPath), - ('list secret', 'hvac/top-secret'), - ]) - def test_list_secrets(self, test_label, path, write_secret_before_test=True, raises=None, exception_message=''): + @parameterized.expand( + [ + ( + "nonexistent secret", + "hvac/no-secret-here", + False, + exceptions.InvalidPath, + ), + ("list secret", "hvac/top-secret"), + ] + ) + def test_list_secrets( + self, + test_label, + path, + write_secret_before_test=True, + raises=None, + exception_message="", + ): test_secret = { - 'pssst': 'hi', + "pssst": "hi", } - test_path_prefix, test_key = path.split('/')[:2] + test_path_prefix, test_key = path.split("/")[:2] if write_secret_before_test: self.client.secrets.kv.v1.create_or_update_secret( @@ -88,20 +111,44 @@ def test_list_secrets(self, test_label, path, write_secret_before_test=True, rai ) self.assertEqual( first=dict(keys=[test_key]), - second=list_secrets_result['data'], + second=list_secrets_result["data"], ) - @parameterized.expand([ - ('create secret no method specified', 'hvac', None, False), - ('create secret post method specified', 'hvac', 'POST', False), - ('create secret invalid method specified', 'hvac', 'GET', False, exceptions.ParamValidationError, '"method" parameter provided invalid value'), - ('update secret no method specified', 'hvac', None), - ('update secret put method specified', 'hvac', 'PUT'), - ('update secret invalid method specified', 'hvac', 'GET', True, exceptions.ParamValidationError, '"method" parameter provided invalid value'), - ]) - def test_create_or_update_secret(self, test_label, path, method=None, write_secret_before_test=True, raises=None, exception_message=''): + @parameterized.expand( + [ + ("create secret no method specified", "hvac", None, False), + ("create secret post method specified", "hvac", "POST", False), + ( + "create secret invalid method specified", + "hvac", + "GET", + False, + exceptions.ParamValidationError, + '"method" parameter provided invalid value', + ), + ("update secret no method specified", "hvac", None), + ("update secret put method specified", "hvac", "PUT"), + ( + "update secret invalid method specified", + "hvac", + "GET", + True, + exceptions.ParamValidationError, + '"method" parameter provided invalid value', + ), + ] + ) + def test_create_or_update_secret( + self, + test_label, + path, + method=None, + write_secret_before_test=True, + raises=None, + exception_message="", + ): test_secret = { - 'pssst': 'hi', + "pssst": "hi", } if write_secret_before_test: @@ -123,24 +170,35 @@ def test_create_or_update_secret(self, test_label, path, method=None, write_secr container=str(cm.exception), ) else: - create_or_update_secret_result = self.client.secrets.kv.v1.create_or_update_secret( - path=path, - secret=test_secret, - method=method, - mount_point=self.DEFAULT_MOUNT_POINT, + create_or_update_secret_result = ( + self.client.secrets.kv.v1.create_or_update_secret( + path=path, + secret=test_secret, + method=method, + mount_point=self.DEFAULT_MOUNT_POINT, + ) ) self.assertEqual( first=204, second=create_or_update_secret_result.status_code, ) - @parameterized.expand([ - ('nonexistent secret', 'hvac/no-secret-here'), - ('delete secret', 'hvac/top-secret'), - ]) - def test_delete_secret(self, test_label, path, write_secret_before_test=True, raises=None, exception_message=''): + @parameterized.expand( + [ + ("nonexistent secret", "hvac/no-secret-here"), + ("delete secret", "hvac/top-secret"), + ] + ) + def test_delete_secret( + self, + test_label, + path, + write_secret_before_test=True, + raises=None, + exception_message="", + ): test_secret = { - 'pssst': 'hi', + "pssst": "hi", } if write_secret_before_test: diff --git a/tests/integration_tests/api/secrets_engines/test_kv_v2.py b/tests/integration_tests/api/secrets_engines/test_kv_v2.py index c8f776422..ed9992eda 100644 --- a/tests/integration_tests/api/secrets_engines/test_kv_v2.py +++ b/tests/integration_tests/api/secrets_engines/test_kv_v2.py @@ -9,86 +9,106 @@ from tests.utils.hvac_integration_test_case import HvacIntegrationTestCase -@skipIf(utils.vault_version_lt('0.10.0'), "KV version 2 secret engine not available before Vault version 0.10.0") +@skipIf( + utils.vault_version_lt("0.10.0"), + "KV version 2 secret engine not available before Vault version 0.10.0", +) class TestKvV2(HvacIntegrationTestCase, TestCase): - DEFAULT_MOUNT_POINT = 'kvv2' + DEFAULT_MOUNT_POINT = "kvv2" def setUp(self): super(TestKvV2, self).setUp() - self.client.enable_secret_backend( - backend_type='kv', - mount_point=self.DEFAULT_MOUNT_POINT, + self.client.sys.enable_secrets_engine( + backend_type="kv", + path=self.DEFAULT_MOUNT_POINT, options=dict(version=2), ) # We occasionally see issues with the newly enabled secrets engine not becoming available in time for our test cases. # So we wait for it to show up in the mounted secrets engines list here before proceeding. - path = '{mount_point}/'.format(mount_point=self.DEFAULT_MOUNT_POINT) + path = "{mount_point}/".format(mount_point=self.DEFAULT_MOUNT_POINT) attempts = 0 - while attempts < 25 and path not in self.client.sys.list_mounted_secrets_engines()['data']: + while ( + attempts < 25 + and path not in self.client.sys.list_mounted_secrets_engines()["data"] + ): attempts += 1 - logging.debug('Waiting 1 second for KV V2 secrets engine under path {path} to become available...'.format( - path=self.DEFAULT_MOUNT_POINT, - )) + logging.debug( + "Waiting 1 second for KV V2 secrets engine under path {path} to become available...".format( + path=self.DEFAULT_MOUNT_POINT, + ) + ) sleep(1) def tearDown(self): - self.client.disable_secret_backend(mount_point=self.DEFAULT_MOUNT_POINT) + self.client.sys.disable_secrets_engine(path=self.DEFAULT_MOUNT_POINT) super(TestKvV2, self).tearDown() - @parameterized.expand([ - ('no parameters',), - ('set max versions', 1), - ('set cas required', 10, True), - ('set max versions and cas required', 17, True), - ('set delete_version_after to thirty minutes', 10, None, "30m0s"), - ]) - def test_configure_and_read_configuration(self, test_label, max_versions=10, cas_required=None, delete_version_after="0s"): + @parameterized.expand( + [ + ("no parameters",), + ("set max versions", 1), + ("set cas required", 10, True), + ("set max versions and cas required", 17, True), + ("set delete_version_after to thirty minutes", 10, None, "30m0s"), + ] + ) + def test_configure_and_read_configuration( + self, test_label, max_versions=10, cas_required=None, delete_version_after="0s" + ): configure_arguments = dict( delete_version_after=delete_version_after, mount_point=self.DEFAULT_MOUNT_POINT, ) if max_versions is not None: - configure_arguments['max_versions'] = max_versions + configure_arguments["max_versions"] = max_versions if cas_required is not None: - configure_arguments['cas_required'] = cas_required + configure_arguments["cas_required"] = cas_required self.client.secrets.kv.v2.configure(**configure_arguments) read_configuration_response = self.client.secrets.kv.v2.read_configuration( mount_point=self.DEFAULT_MOUNT_POINT, ) - logging.debug('read_configuration_response: %s' % read_configuration_response) + logging.debug("read_configuration_response: %s" % read_configuration_response) self.assertEqual( first=max_versions, - second=read_configuration_response['data']['max_versions'], + second=read_configuration_response["data"]["max_versions"], ) self.assertEqual( first=cas_required or False, - second=read_configuration_response['data']['cas_required'], + second=read_configuration_response["data"]["cas_required"], ) - if utils.vault_version_ge('1.5.0'): + if utils.vault_version_ge("1.5.0"): # delete_version_after wasn't returned in this response when unset before 1.5.0 self.assertEqual( first=delete_version_after, - second=read_configuration_response['data']['delete_version_after'], + second=read_configuration_response["data"]["delete_version_after"], ) - @parameterized.expand([ - ('nonexistent secret', 'no-secret-here', None, False, exceptions.InvalidPath), - ('read secret version 2 back', 'top-secret', 2, 2), - ('read secret version 1 back', 'top-secret', 1, 5), - ('read current secret version', 'top-secret', None, 10), - ('read current secret version', 'top-secret', None, 15), - ]) - def test_read_secret_version(self, test_label, path, version=None, write_secret_before_test=True, raises=None): + @parameterized.expand( + [ + ( + "nonexistent secret", + "no-secret-here", + None, + False, + exceptions.InvalidPath, + ), + ("read secret version 2 back", "top-secret", 2, 2), + ("read secret version 1 back", "top-secret", 1, 5), + ("read current secret version", "top-secret", None, 10), + ("read current secret version", "top-secret", None, 15), + ] + ) + def test_read_secret_version( + self, test_label, path, version=None, write_secret_before_test=True, raises=None + ): if write_secret_before_test: for num in range(1, write_secret_before_test + 1): test_secret = { - 'pssst': num, + "pssst": num, } self.client.secrets.kv.v2.create_or_update_secret( - path=path, - secret=test_secret, - mount_point=self.DEFAULT_MOUNT_POINT + path=path, secret=test_secret, mount_point=self.DEFAULT_MOUNT_POINT ) if raises: with self.assertRaises(raises): @@ -103,24 +123,48 @@ def test_read_secret_version(self, test_label, path, version=None, write_secret_ version=version, mount_point=self.DEFAULT_MOUNT_POINT, ) - logging.debug('read_secret_result: %s' % read_secret_result) + logging.debug("read_secret_result: %s" % read_secret_result) expected_version = version or write_secret_before_test self.assertDictEqual( d1=dict(pssst=expected_version), - d2=read_secret_result['data']['data'], + d2=read_secret_result["data"]["data"], ) - @parameterized.expand([ - ('create secret', 'hvac', None, False), - ('create secret with cas of 0', 'hvac', 0, False), - ('update secret', 'hvac', None), - ('update secret with valid cas of 1', 'hvac', 1, True), - ('update secret with invalid cas', 'hvac', -1, True, exceptions.InvalidRequest, 'did not match the current version'), - ('update with cas of 0 after path already written', 'hvac', 0, True, exceptions.InvalidRequest, 'did not match the current version'), - ]) - def test_create_or_update_secret(self, test_label, path, cas=None, write_secret_before_test=True, raises=None, exception_message=''): + @parameterized.expand( + [ + ("create secret", "hvac", None, False), + ("create secret with cas of 0", "hvac", 0, False), + ("update secret", "hvac", None), + ("update secret with valid cas of 1", "hvac", 1, True), + ( + "update secret with invalid cas", + "hvac", + -1, + True, + exceptions.InvalidRequest, + "did not match the current version", + ), + ( + "update with cas of 0 after path already written", + "hvac", + 0, + True, + exceptions.InvalidRequest, + "did not match the current version", + ), + ] + ) + def test_create_or_update_secret( + self, + test_label, + path, + cas=None, + write_secret_before_test=True, + raises=None, + exception_message="", + ): test_secret = { - 'pssst': 'hi', + "pssst": "hi", } if write_secret_before_test: @@ -142,40 +186,54 @@ def test_create_or_update_secret(self, test_label, path, cas=None, write_secret_ container=str(cm.exception), ) else: - create_or_update_secret_result = self.client.secrets.kv.v2.create_or_update_secret( - path=path, - secret=test_secret, - cas=cas, - mount_point=self.DEFAULT_MOUNT_POINT, + create_or_update_secret_result = ( + self.client.secrets.kv.v2.create_or_update_secret( + path=path, + secret=test_secret, + cas=cas, + mount_point=self.DEFAULT_MOUNT_POINT, + ) ) expected_version = 2 if write_secret_before_test else 1 - logging.debug('create_or_update_secret_result: %s' % create_or_update_secret_result) + logging.debug( + "create_or_update_secret_result: %s" % create_or_update_secret_result + ) self.assertEqual( first=expected_version, - second=create_or_update_secret_result['data']['version'], + second=create_or_update_secret_result["data"]["version"], ) - @parameterized.expand([ - param( - 'add new key to existing secret', - update_dict=dict(new_key='some secret') - ), - param( - 'add new key to nonexistent secret', - update_dict=dict(new_key='some secret'), - write_secret_before_test=False, - raises=exceptions.InvalidPath, - exception_message='patch only works on existing data.', - ), - param( - 'update existing key on existing secret', - update_dict=dict(pssst='some secret') - ), - ]) - def test_patch(self, label, update_dict, mount_point=DEFAULT_MOUNT_POINT, write_secret_before_test=True, raises=None, exception_message=''): - path = 'hvac_kv_v2_test_patch' + @parameterized.expand( + [ + param( + "add new key to existing secret", + update_dict=dict(new_key="some secret"), + ), + param( + "add new key to nonexistent secret", + update_dict=dict(new_key="some secret"), + write_secret_before_test=False, + raises=exceptions.InvalidPath, + exception_message="patch only works on existing data.", + ), + param( + "update existing key on existing secret", + update_dict=dict(pssst="some secret"), + ), + ] + ) + def test_patch( + self, + label, + update_dict, + mount_point=DEFAULT_MOUNT_POINT, + write_secret_before_test=True, + raises=None, + exception_message="", + ): + path = "hvac_kv_v2_test_patch" test_secret = { - 'pssst': 'hi', + "pssst": "hi", } if write_secret_before_test: @@ -202,39 +260,43 @@ def test_patch(self, label, update_dict, mount_point=DEFAULT_MOUNT_POINT, write_ mount_point=mount_point, ) expected_version = 2 if write_secret_before_test else 1 - logging.debug('patch_result: %s' % patch_result) + logging.debug("patch_result: %s" % patch_result) self.assertEqual( first=expected_version, - second=patch_result['data']['version'], + second=patch_result["data"]["version"], ) read_secret_result = self.client.secrets.kv.v2.read_secret_version( path=path, mount_point=mount_point, ) - logging.debug('read_secret_result: %s' % read_secret_result) + logging.debug("read_secret_result: %s" % read_secret_result) for k, v in update_dict.items(): - self.assertEqual( - first=v, - second=read_secret_result['data']['data'][k] - ) + self.assertEqual(first=v, second=read_secret_result["data"]["data"][k]) - @parameterized.expand([ - ('successful delete one version written', 'hvac'), - ('successful delete two versions written', 'hvac', 2), - ('successful delete three versions written', 'hvac', 3), - ('nonexistent path', 'no-secret-here', 0, exceptions.InvalidPath), - ]) - def test_delete_latest_version_of_secret(self, test_label, path, write_secret_before_test=1, raises=None, exception_message=''): + @parameterized.expand( + [ + ("successful delete one version written", "hvac"), + ("successful delete two versions written", "hvac", 2), + ("successful delete three versions written", "hvac", 3), + ("nonexistent path", "no-secret-here", 0, exceptions.InvalidPath), + ] + ) + def test_delete_latest_version_of_secret( + self, + test_label, + path, + write_secret_before_test=1, + raises=None, + exception_message="", + ): if write_secret_before_test: for num in range(1, write_secret_before_test + 1): test_secret = { - 'pssst': num, + "pssst": num, } self.client.secrets.kv.v2.create_or_update_secret( - path=path, - secret=test_secret, - mount_point=self.DEFAULT_MOUNT_POINT + path=path, secret=test_secret, mount_point=self.DEFAULT_MOUNT_POINT ) if raises: self.client.secrets.kv.v2.delete_latest_version_of_secret( @@ -251,51 +313,100 @@ def test_delete_latest_version_of_secret(self, test_label, path, write_secret_be container=str(cm.exception), ) else: - delete_latest_version_of_secret_result = self.client.secrets.kv.v2.delete_latest_version_of_secret( - path=path, - mount_point=self.DEFAULT_MOUNT_POINT, + delete_latest_version_of_secret_result = ( + self.client.secrets.kv.v2.delete_latest_version_of_secret( + path=path, + mount_point=self.DEFAULT_MOUNT_POINT, + ) ) - logging.debug('delete_latest_version_of_secret_result: %s' % delete_latest_version_of_secret_result) - read_secret_metadata_result = self.client.secrets.kv.v2.read_secret_metadata( - path=path, - mount_point=self.DEFAULT_MOUNT_POINT, + logging.debug( + "delete_latest_version_of_secret_result: %s" + % delete_latest_version_of_secret_result + ) + read_secret_metadata_result = ( + self.client.secrets.kv.v2.read_secret_metadata( + path=path, + mount_point=self.DEFAULT_MOUNT_POINT, + ) + ) + logging.debug( + "read_secret_metadata_result: %s" % read_secret_metadata_result ) - logging.debug('read_secret_metadata_result: %s' % read_secret_metadata_result) self.assertNotEqual( - first=read_secret_metadata_result['data']['versions'][str(write_secret_before_test)]['deletion_time'], - second='' + first=read_secret_metadata_result["data"]["versions"][ + str(write_secret_before_test) + ]["deletion_time"], + second="", ) for num in range(1, write_secret_before_test): self.assertEqual( - first=read_secret_metadata_result['data']['versions'][str(num)]['deletion_time'], - second='', + first=read_secret_metadata_result["data"]["versions"][str(num)][ + "deletion_time" + ], + second="", ) - @parameterized.expand([ - ('successful delete one version written', 'hvac', 1, [1]), - ('successful delete one out of two versions written 1', 'hvac', 2, [1]), - ('successful delete one out of two versions written 2', 'hvac', 2, [2]), - ('successful delete two out of two versions written', 'hvac', 2, [1, 2]), - ('successful delete three out of seven versions written 135', 'hvac', 7, [1, 3, 5]), - ('successful delete three out of seven versions written 137', 'hvac', 7, [1, 3, 7]), - ('invalid versions arg none', 'boom', 0, None, exceptions.ParamValidationError), - ('invalid versions arg empty', 'boom', 0, [], exceptions.ParamValidationError), - ('invalid versions arg not a list', 'goes', 0, '1', exceptions.ParamValidationError), - ('nonexistent version 1', 'no-version-here', 3, [5]), - ('nonexistent version 2', 'no-versions-here', 3, [7, 9]), - ('nonexistent version 3', 'no-versions-here', 3, [7, 12]), - ]) - def test_delete_secret_versions(self, test_label, path, write_secret_before_test=1, deleted_versions=None, raises=None, exception_message=''): + @parameterized.expand( + [ + ("successful delete one version written", "hvac", 1, [1]), + ("successful delete one out of two versions written 1", "hvac", 2, [1]), + ("successful delete one out of two versions written 2", "hvac", 2, [2]), + ("successful delete two out of two versions written", "hvac", 2, [1, 2]), + ( + "successful delete three out of seven versions written 135", + "hvac", + 7, + [1, 3, 5], + ), + ( + "successful delete three out of seven versions written 137", + "hvac", + 7, + [1, 3, 7], + ), + ( + "invalid versions arg none", + "boom", + 0, + None, + exceptions.ParamValidationError, + ), + ( + "invalid versions arg empty", + "boom", + 0, + [], + exceptions.ParamValidationError, + ), + ( + "invalid versions arg not a list", + "goes", + 0, + "1", + exceptions.ParamValidationError, + ), + ("nonexistent version 1", "no-version-here", 3, [5]), + ("nonexistent version 2", "no-versions-here", 3, [7, 9]), + ("nonexistent version 3", "no-versions-here", 3, [7, 12]), + ] + ) + def test_delete_secret_versions( + self, + test_label, + path, + write_secret_before_test=1, + deleted_versions=None, + raises=None, + exception_message="", + ): if write_secret_before_test: for num in range(1, write_secret_before_test + 1): test_secret = { - 'pssst': num, + "pssst": num, } self.client.secrets.kv.v2.create_or_update_secret( - path=path, - secret=test_secret, - mount_point=self.DEFAULT_MOUNT_POINT + path=path, secret=test_secret, mount_point=self.DEFAULT_MOUNT_POINT ) if raises: with self.assertRaises(raises) as cm: @@ -309,68 +420,120 @@ def test_delete_secret_versions(self, test_label, path, write_secret_before_test container=str(cm.exception), ) else: - delete_secret_versions_result = self.client.secrets.kv.v2.delete_secret_versions( - path=path, - versions=deleted_versions, - mount_point=self.DEFAULT_MOUNT_POINT, + delete_secret_versions_result = ( + self.client.secrets.kv.v2.delete_secret_versions( + path=path, + versions=deleted_versions, + mount_point=self.DEFAULT_MOUNT_POINT, + ) ) - logging.debug('delete_secret_versions_result: %s' % delete_secret_versions_result) - read_secret_metadata_result = self.client.secrets.kv.v2.read_secret_metadata( - path=path, - mount_point=self.DEFAULT_MOUNT_POINT, + logging.debug( + "delete_secret_versions_result: %s" % delete_secret_versions_result + ) + read_secret_metadata_result = ( + self.client.secrets.kv.v2.read_secret_metadata( + path=path, + mount_point=self.DEFAULT_MOUNT_POINT, + ) + ) + logging.debug( + "read_secret_metadata_result: %s" % read_secret_metadata_result ) - logging.debug('read_secret_metadata_result: %s' % read_secret_metadata_result) for deleted_version in deleted_versions: - if str(deleted_version) in read_secret_metadata_result['data']['versions']: + if ( + str(deleted_version) + in read_secret_metadata_result["data"]["versions"] + ): self.assertNotEqual( - first=read_secret_metadata_result['data']['versions'][str(deleted_version)]['deletion_time'], - second='', + first=read_secret_metadata_result["data"]["versions"][ + str(deleted_version) + ]["deletion_time"], + second="", msg='Version "{num}" should be deleted but is not. Full read metadata response versions: {metadata}'.format( num=deleted_version, - metadata=read_secret_metadata_result['data']['versions'], - ) + metadata=read_secret_metadata_result["data"]["versions"], + ), ) - for nondeleted_version in set(range(1, write_secret_before_test + 1)) - set(deleted_versions): + for nondeleted_version in set(range(1, write_secret_before_test + 1)) - set( + deleted_versions + ): self.assertEqual( - first=read_secret_metadata_result['data']['versions'][str(nondeleted_version)]['deletion_time'], - second='', + first=read_secret_metadata_result["data"]["versions"][ + str(nondeleted_version) + ]["deletion_time"], + second="", msg='Version "{num}" should not be deleted but is. Full read metadata response versions: {metadata}'.format( num=nondeleted_version, - metadata=read_secret_metadata_result['data']['versions'], - ) + metadata=read_secret_metadata_result["data"]["versions"], + ), ) - @parameterized.expand([ - ('successful undelete one version written', 'hvac', 1, [1]), - ('successful undelete one out of two versions written 1', 'hvac', 2, [1]), - ('successful undelete one out of two versions written 2', 'hvac', 2, [2]), - ('successful undelete two out of two versions written', 'hvac', 2, [1, 2]), - ('successful undelete three out of seven versions written 135', 'hvac', 7, [1, 3, 5]), - ('successful undelete three out of seven versions written 137', 'hvac', 7, [1, 3, 7]), - ('invalid versions arg none', 'boom', 0, None, exceptions.ParamValidationError), - ('invalid versions arg empty', 'boom', 0, [], exceptions.ParamValidationError), - ('invalid versions arg not a list', 'goes', 1, '1', exceptions.ParamValidationError), - ('nonexistent version 1', 'no-version-here', 3, [5]), - ('nonexistent version 2', 'no-versions-here', 3, [7, 9]), - ('nonexistent version 3', 'no-versions-here', 3, [7, 12]), - ]) - def test_undelete_secret_versions(self, test_label, path, write_secret_before_test=1, undeleted_versions=None, raises=None, exception_message=''): + @parameterized.expand( + [ + ("successful undelete one version written", "hvac", 1, [1]), + ("successful undelete one out of two versions written 1", "hvac", 2, [1]), + ("successful undelete one out of two versions written 2", "hvac", 2, [2]), + ("successful undelete two out of two versions written", "hvac", 2, [1, 2]), + ( + "successful undelete three out of seven versions written 135", + "hvac", + 7, + [1, 3, 5], + ), + ( + "successful undelete three out of seven versions written 137", + "hvac", + 7, + [1, 3, 7], + ), + ( + "invalid versions arg none", + "boom", + 0, + None, + exceptions.ParamValidationError, + ), + ( + "invalid versions arg empty", + "boom", + 0, + [], + exceptions.ParamValidationError, + ), + ( + "invalid versions arg not a list", + "goes", + 1, + "1", + exceptions.ParamValidationError, + ), + ("nonexistent version 1", "no-version-here", 3, [5]), + ("nonexistent version 2", "no-versions-here", 3, [7, 9]), + ("nonexistent version 3", "no-versions-here", 3, [7, 12]), + ] + ) + def test_undelete_secret_versions( + self, + test_label, + path, + write_secret_before_test=1, + undeleted_versions=None, + raises=None, + exception_message="", + ): if write_secret_before_test: for num in range(1, write_secret_before_test + 1): test_secret = { - 'pssst': num, + "pssst": num, } self.client.secrets.kv.v2.create_or_update_secret( - path=path, - secret=test_secret, - mount_point=self.DEFAULT_MOUNT_POINT + path=path, secret=test_secret, mount_point=self.DEFAULT_MOUNT_POINT ) self.client.secrets.kv.v2.delete_latest_version_of_secret( - path=path, - mount_point=self.DEFAULT_MOUNT_POINT + path=path, mount_point=self.DEFAULT_MOUNT_POINT ) if raises: with self.assertRaises(raises) as cm: @@ -384,64 +547,117 @@ def test_undelete_secret_versions(self, test_label, path, write_secret_before_te container=str(cm.exception), ) else: - delete_secret_versions_result = self.client.secrets.kv.v2.undelete_secret_versions( - path=path, - versions=undeleted_versions, - mount_point=self.DEFAULT_MOUNT_POINT, + delete_secret_versions_result = ( + self.client.secrets.kv.v2.undelete_secret_versions( + path=path, + versions=undeleted_versions, + mount_point=self.DEFAULT_MOUNT_POINT, + ) ) - logging.debug('delete_secret_versions_result: %s' % delete_secret_versions_result) - read_secret_metadata_result = self.client.secrets.kv.v2.read_secret_metadata( - path=path, - mount_point=self.DEFAULT_MOUNT_POINT, + logging.debug( + "delete_secret_versions_result: %s" % delete_secret_versions_result + ) + read_secret_metadata_result = ( + self.client.secrets.kv.v2.read_secret_metadata( + path=path, + mount_point=self.DEFAULT_MOUNT_POINT, + ) + ) + logging.debug( + "read_secret_metadata_result: %s" % read_secret_metadata_result ) - logging.debug('read_secret_metadata_result: %s' % read_secret_metadata_result) for deleted_version in undeleted_versions: - if str(deleted_version) in read_secret_metadata_result['data']['versions']: + if ( + str(deleted_version) + in read_secret_metadata_result["data"]["versions"] + ): self.assertEqual( - first=read_secret_metadata_result['data']['versions'][str(deleted_version)]['deletion_time'], - second='', + first=read_secret_metadata_result["data"]["versions"][ + str(deleted_version) + ]["deletion_time"], + second="", msg='Version "{num}" should be undeleted but is not. Full read metadata response versions: {metadata}'.format( num=deleted_version, - metadata=read_secret_metadata_result['data']['versions'], - ) + metadata=read_secret_metadata_result["data"]["versions"], + ), ) - for nondeleted_version in set(range(1, write_secret_before_test + 1)) - set(undeleted_versions): + for nondeleted_version in set(range(1, write_secret_before_test + 1)) - set( + undeleted_versions + ): self.assertNotEqual( - first=read_secret_metadata_result['data']['versions'][str(nondeleted_version)]['deletion_time'], - second='', + first=read_secret_metadata_result["data"]["versions"][ + str(nondeleted_version) + ]["deletion_time"], + second="", msg='Version "{num}" should be deleted but it is not. Full read metadata response versions: {metadata}'.format( num=nondeleted_version, - metadata=read_secret_metadata_result['data']['versions'], - ) + metadata=read_secret_metadata_result["data"]["versions"], + ), ) - @parameterized.expand([ - ('successful destroy one version written', 'hvac', 1, [1]), - ('successful destroy one out of two versions written 1', 'hvac', 2, [1]), - ('successful destroy one out of two versions written 2', 'hvac', 2, [2]), - ('successful destroy two out of two versions written', 'hvac', 2, [1, 2]), - ('successful destroy three out of seven versions written 135', 'hvac', 7, [1, 3, 5]), - ('successful destroy three out of seven versions written 137', 'hvac', 7, [1, 3, 7]), - ('invalid versions arg None', 'boom', 0, None, exceptions.ParamValidationError), - ('invalid versions arg empty', 'boom', 0, [], exceptions.ParamValidationError), - ('invalid versions arg not a list', 'goes', 0, '1', exceptions.ParamValidationError), - ('nonexistent version 1', 'no-version-here', 3, [5]), - ('nonexistent version 2', 'no-versions-here', 3, [7, 9]), - ('nonexistent version 3', 'no-versions-here', 3, [7, 12]), - ]) - def test_destroy_secret_versions(self, test_label, path, write_secret_before_test=1, destoryed_versions=None, raises=None, exception_message=''): + @parameterized.expand( + [ + ("successful destroy one version written", "hvac", 1, [1]), + ("successful destroy one out of two versions written 1", "hvac", 2, [1]), + ("successful destroy one out of two versions written 2", "hvac", 2, [2]), + ("successful destroy two out of two versions written", "hvac", 2, [1, 2]), + ( + "successful destroy three out of seven versions written 135", + "hvac", + 7, + [1, 3, 5], + ), + ( + "successful destroy three out of seven versions written 137", + "hvac", + 7, + [1, 3, 7], + ), + ( + "invalid versions arg None", + "boom", + 0, + None, + exceptions.ParamValidationError, + ), + ( + "invalid versions arg empty", + "boom", + 0, + [], + exceptions.ParamValidationError, + ), + ( + "invalid versions arg not a list", + "goes", + 0, + "1", + exceptions.ParamValidationError, + ), + ("nonexistent version 1", "no-version-here", 3, [5]), + ("nonexistent version 2", "no-versions-here", 3, [7, 9]), + ("nonexistent version 3", "no-versions-here", 3, [7, 12]), + ] + ) + def test_destroy_secret_versions( + self, + test_label, + path, + write_secret_before_test=1, + destoryed_versions=None, + raises=None, + exception_message="", + ): if write_secret_before_test: logging.error(write_secret_before_test) for num in range(1, write_secret_before_test + 1): test_secret = { - 'pssst': num, + "pssst": num, } self.client.secrets.kv.v2.create_or_update_secret( - path=path, - secret=test_secret, - mount_point=self.DEFAULT_MOUNT_POINT + path=path, secret=test_secret, mount_point=self.DEFAULT_MOUNT_POINT ) if raises: with self.assertRaises(raises) as cm: @@ -455,56 +671,84 @@ def test_destroy_secret_versions(self, test_label, path, write_secret_before_tes container=str(cm.exception), ) else: - destroy_secret_versions_result = self.client.secrets.kv.v2.destroy_secret_versions( - path=path, - versions=destoryed_versions, - mount_point=self.DEFAULT_MOUNT_POINT, + destroy_secret_versions_result = ( + self.client.secrets.kv.v2.destroy_secret_versions( + path=path, + versions=destoryed_versions, + mount_point=self.DEFAULT_MOUNT_POINT, + ) ) - logging.debug('destroy_secret_versions_result: %s' % destroy_secret_versions_result) - read_secret_metadata_result = self.client.secrets.kv.v2.read_secret_metadata( - path=path, - mount_point=self.DEFAULT_MOUNT_POINT, + logging.debug( + "destroy_secret_versions_result: %s" % destroy_secret_versions_result + ) + read_secret_metadata_result = ( + self.client.secrets.kv.v2.read_secret_metadata( + path=path, + mount_point=self.DEFAULT_MOUNT_POINT, + ) + ) + logging.debug( + "read_secret_metadata_result: %s" % read_secret_metadata_result ) - logging.debug('read_secret_metadata_result: %s' % read_secret_metadata_result) for destoryed_version in destoryed_versions: - if str(destoryed_version) in read_secret_metadata_result['data']['versions']: + if ( + str(destoryed_version) + in read_secret_metadata_result["data"]["versions"] + ): self.assertTrue( - expr=read_secret_metadata_result['data']['versions'][str(destoryed_version)]['destroyed'], + expr=read_secret_metadata_result["data"]["versions"][ + str(destoryed_version) + ]["destroyed"], msg='Version "{num}" should be destoryed but is not. Full read metadata response versions: {metadata}'.format( num=destoryed_version, - metadata=read_secret_metadata_result['data']['versions'], - ) + metadata=read_secret_metadata_result["data"]["versions"], + ), ) - for nondestoryed_version in set(range(1, write_secret_before_test + 1)) - set(destoryed_versions): + for nondestoryed_version in set( + range(1, write_secret_before_test + 1) + ) - set(destoryed_versions): self.assertFalse( - expr=read_secret_metadata_result['data']['versions'][str(nondestoryed_version)]['destroyed'], + expr=read_secret_metadata_result["data"]["versions"][ + str(nondestoryed_version) + ]["destroyed"], msg='Version "{num}" should not be destoryed but is. Full read metadata response versions: {metadata}'.format( num=nondestoryed_version, - metadata=read_secret_metadata_result['data']['versions'], - ) + metadata=read_secret_metadata_result["data"]["versions"], + ), ) - @parameterized.expand([ - ('nonexistent secret', 'hvac/no-secret-here', False, exceptions.InvalidPath), - ('list secret', 'hvac/top-secret'), - ]) - def test_list_secrets(self, test_label, path, write_secret_before_test=True, raises=None, exception_message=''): + @parameterized.expand( + [ + ( + "nonexistent secret", + "hvac/no-secret-here", + False, + exceptions.InvalidPath, + ), + ("list secret", "hvac/top-secret"), + ] + ) + def test_list_secrets( + self, + test_label, + path, + write_secret_before_test=True, + raises=None, + exception_message="", + ): test_secret = { - 'pssst': 'hi', + "pssst": "hi", } - test_path_prefix, test_key = path.split('/')[:2] + test_path_prefix, test_key = path.split("/")[:2] if write_secret_before_test: self.client.secrets.kv.v2.create_or_update_secret( - path=path, - secret=test_secret, - mount_point=self.DEFAULT_MOUNT_POINT + path=path, secret=test_secret, mount_point=self.DEFAULT_MOUNT_POINT ) if raises: with self.assertRaises(raises) as cm: self.client.secrets.kv.v2.list_secrets( - path=test_path_prefix, - mount_point=self.DEFAULT_MOUNT_POINT + path=test_path_prefix, mount_point=self.DEFAULT_MOUNT_POINT ) self.assertIn( member=exception_message, @@ -512,34 +756,52 @@ def test_list_secrets(self, test_label, path, write_secret_before_test=True, rai ) else: list_secrets_result = self.client.secrets.kv.v2.list_secrets( - path=test_path_prefix, - mount_point=self.DEFAULT_MOUNT_POINT + path=test_path_prefix, mount_point=self.DEFAULT_MOUNT_POINT ) - logging.debug('list_secrets_result: %s' % list_secrets_result) + logging.debug("list_secrets_result: %s" % list_secrets_result) self.assertEqual( first=dict(keys=[test_key]), - second=list_secrets_result['data'], + second=list_secrets_result["data"], ) - @parameterized.expand([ - ('update with no params', 'hvac'), - ('update max versions 7', 'hvac', 7), - ('update max versions 0', 'hvac', 0), - ('update cas_required true', 'hvac', None, True), - ('update cas_required false', 'hvac', None, False), - ('update with invalid cas_required param', 'hvac', None, 'cats', "0s", True, exceptions.ParamValidationError, 'bool expected for cas_required param'), - ('update with delete_version_after set', 'hvac', None, True, "30s"), - ]) - def test_update_metadata(self, test_label, path, max_versions=None, cas_required=None, delete_version_after="0s", write_secret_before_test=True, raises=None, exception_message=''): + @parameterized.expand( + [ + ("update with no params", "hvac"), + ("update max versions 7", "hvac", 7), + ("update max versions 0", "hvac", 0), + ("update cas_required true", "hvac", None, True), + ("update cas_required false", "hvac", None, False), + ( + "update with invalid cas_required param", + "hvac", + None, + "cats", + "0s", + True, + exceptions.ParamValidationError, + "bool expected for cas_required param", + ), + ("update with delete_version_after set", "hvac", None, True, "30s"), + ] + ) + def test_update_metadata( + self, + test_label, + path, + max_versions=None, + cas_required=None, + delete_version_after="0s", + write_secret_before_test=True, + raises=None, + exception_message="", + ): if write_secret_before_test: test_secret = { - 'pssst': 'hi itsame hvac', + "pssst": "hi itsame hvac", } self.client.secrets.kv.v2.create_or_update_secret( - path=path, - secret=test_secret, - mount_point=self.DEFAULT_MOUNT_POINT + path=path, secret=test_secret, mount_point=self.DEFAULT_MOUNT_POINT ) if raises: with self.assertRaises(raises) as cm: @@ -562,42 +824,60 @@ def test_update_metadata(self, test_label, path, max_versions=None, cas_required delete_version_after=delete_version_after, mount_point=self.DEFAULT_MOUNT_POINT, ) - logging.debug('update_metadata_result: %s' % update_metadata_result) - read_secret_metadata_result = self.client.secrets.kv.v2.read_secret_metadata( - path=path, - mount_point=self.DEFAULT_MOUNT_POINT, + logging.debug("update_metadata_result: %s" % update_metadata_result) + read_secret_metadata_result = ( + self.client.secrets.kv.v2.read_secret_metadata( + path=path, + mount_point=self.DEFAULT_MOUNT_POINT, + ) + ) + logging.debug( + "read_secret_metadata_result: %s" % read_secret_metadata_result ) - logging.debug('read_secret_metadata_result: %s' % read_secret_metadata_result) - for key, argument in dict(max_versions=max_versions, cas_required=cas_required, delete_version_after=delete_version_after).items(): + for key, argument in dict( + max_versions=max_versions, + cas_required=cas_required, + delete_version_after=delete_version_after, + ).items(): if argument is not None: self.assertEqual( first=argument, - second=read_secret_metadata_result['data'][key], + second=read_secret_metadata_result["data"][key], ) - @parameterized.expand([ - ('nonexistent secret', 'hvac/no-secret-here', False), - ('delete extant secret metadata', 'hvac/top-secret'), - ]) - def test_delete_metadata_and_all_versions(self, test_label, path, write_secret_before_test=True): + @parameterized.expand( + [ + ("nonexistent secret", "hvac/no-secret-here", False), + ("delete extant secret metadata", "hvac/top-secret"), + ] + ) + def test_delete_metadata_and_all_versions( + self, test_label, path, write_secret_before_test=True + ): test_secret = { - 'pssst': 'hi', + "pssst": "hi", } if write_secret_before_test: self.client.secrets.kv.v2.create_or_update_secret( - path=path, - secret=test_secret, - mount_point=self.DEFAULT_MOUNT_POINT + path=path, secret=test_secret, mount_point=self.DEFAULT_MOUNT_POINT + ) + delete_metadata_and_all_versions_result = ( + self.client.secrets.kv.v2.delete_metadata_and_all_versions( + path=path, mount_point=self.DEFAULT_MOUNT_POINT ) - delete_metadata_and_all_versions_result = self.client.secrets.kv.v2.delete_metadata_and_all_versions( - path=path, - mount_point=self.DEFAULT_MOUNT_POINT ) - logging.debug('delete_metadata_and_all_versions_result: %s' % delete_metadata_and_all_versions_result) + logging.debug( + "delete_metadata_and_all_versions_result: %s" + % delete_metadata_and_all_versions_result + ) with self.assertRaises(exceptions.InvalidPath): - read_secret_metadata_result = self.client.secrets.kv.v2.read_secret_metadata( - path=path, - mount_point=self.DEFAULT_MOUNT_POINT, + read_secret_metadata_result = ( + self.client.secrets.kv.v2.read_secret_metadata( + path=path, + mount_point=self.DEFAULT_MOUNT_POINT, + ) + ) + logging.debug( + "read_secret_metadata_result: %s" % read_secret_metadata_result ) - logging.debug('read_secret_metadata_result: %s' % read_secret_metadata_result) diff --git a/tests/integration_tests/api/secrets_engines/test_pki.py b/tests/integration_tests/api/secrets_engines/test_pki.py index 9ce667e30..a14f122a0 100644 --- a/tests/integration_tests/api/secrets_engines/test_pki.py +++ b/tests/integration_tests/api/secrets_engines/test_pki.py @@ -8,17 +8,17 @@ class TestPki(HvacIntegrationTestCase, TestCase): - TEST_MOUNT_POINT = 'pki-integration-test' - TEST_ROLE = 'role-test' + TEST_MOUNT_POINT = "pki-integration-test" + TEST_ROLE = "role-test" def setUp(self): super(TestPki, self).setUp() - self.client.enable_secret_backend( - backend_type='pki', - mount_point=self.TEST_MOUNT_POINT, + self.client.sys.enable_secrets_engine( + backend_type="pki", + path=self.TEST_MOUNT_POINT, ) - common_name = 'Vault integration tests' - generate_type = 'exported' + common_name = "Vault integration tests" + generate_type = "exported" self.client.secrets.pki.generate_root( type=generate_type, common_name=common_name, @@ -28,161 +28,190 @@ def setUp(self): self.client.secrets.pki.create_or_update_role( name=name, extra_params={ - 'allow_any_name': True, - 'ttl': '6h', - 'max_ttl': '12h', - }, + "allow_any_name": True, + "ttl": "6h", + "max_ttl": "12h", + }, mount_point=self.TEST_MOUNT_POINT, ) def tearDown(self): - self.client.disable_secret_backend(mount_point=self.TEST_MOUNT_POINT) + self.client.sys.disable_secrets_engine(path=self.TEST_MOUNT_POINT) super(TestPki, self).tearDown() # Read CA Certificate - @parameterized.expand([ - param( - 'success', - ), - ]) - def test_read_ca_certificate(self, label, raises=False, exception_message=''): + @parameterized.expand( + [ + param( + "success", + ), + ] + ) + def test_read_ca_certificate(self, label, raises=False, exception_message=""): read_ca_certificate_response = self.client.secrets.pki.read_ca_certificate( mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('read_ca_certificate_response: %s' % read_ca_certificate_response) + logging.debug("read_ca_certificate_response: %s" % read_ca_certificate_response) self.assertIsInstance( obj=read_ca_certificate_response, cls=str, ) # Read CA Certificate Chain - @parameterized.expand([ - param( - 'success', - ), - ]) - def test_read_ca_certificate_chain(self, label, raises=False, exception_message=''): - read_ca_certificate_chain_response = self.client.secrets.pki.read_ca_certificate_chain( - mount_point=self.TEST_MOUNT_POINT, + @parameterized.expand( + [ + param( + "success", + ), + ] + ) + def test_read_ca_certificate_chain(self, label, raises=False, exception_message=""): + read_ca_certificate_chain_response = ( + self.client.secrets.pki.read_ca_certificate_chain( + mount_point=self.TEST_MOUNT_POINT, + ) + ) + logging.debug( + "read_ca_certificate_chain_response: %s" + % read_ca_certificate_chain_response ) - logging.debug('read_ca_certificate_chain_response: %s' % read_ca_certificate_chain_response) self.assertIsInstance( obj=read_ca_certificate_chain_response, cls=str, ) # Read Certificate - @parameterized.expand([ - param( - 'success', - ), - ]) - def test_read_certificate(self, label, raises=False, exception_message=''): + @parameterized.expand( + [ + param( + "success", + ), + ] + ) + def test_read_certificate(self, label, raises=False, exception_message=""): list_certificates_response = self.client.secrets.pki.list_certificates( mount_point=self.TEST_MOUNT_POINT, ) - serial = list_certificates_response['data']['keys'][0] + serial = list_certificates_response["data"]["keys"][0] read_certificate_response = self.client.secrets.pki.read_certificate( serial=serial, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('read_certificate_response: %s' % read_certificate_response) + logging.debug("read_certificate_response: %s" % read_certificate_response) self.assertIsInstance( obj=read_certificate_response, cls=dict, ) # List Certificates - @parameterized.expand([ - param( - 'success', - ), - ]) - def test_list_certificates(self, label, raises=False, exception_message=''): + @parameterized.expand( + [ + param( + "success", + ), + ] + ) + def test_list_certificates(self, label, raises=False, exception_message=""): list_certificates_response = self.client.secrets.pki.list_certificates( mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('list_certificates_response: %s' % list_certificates_response) + logging.debug("list_certificates_response: %s" % list_certificates_response) self.assertIsInstance( obj=list_certificates_response, cls=dict, ) # Submit CA Information - @parameterized.expand([ - param( - 'success', - ), - ]) - def test_submit_ca_information(self, label, raises=False, exception_message=''): - pem_bundle = '{ca_key}{ca_crt}'.format( - ca_key=''.join(open(utils.get_config_file_path('ca-key.pem')).readlines()), - ca_crt=''.join(open(utils.get_config_file_path('ca-cert.pem')).readlines()), + @parameterized.expand( + [ + param( + "success", + ), + ] + ) + def test_submit_ca_information(self, label, raises=False, exception_message=""): + pem_bundle = "{ca_key}{ca_crt}".format( + ca_key="".join(open(utils.get_config_file_path("ca-key.pem")).readlines()), + ca_crt="".join(open(utils.get_config_file_path("ca-cert.pem")).readlines()), ) submit_ca_information_response = self.client.secrets.pki.submit_ca_information( pem_bundle=pem_bundle, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('submit_ca_information_response: %s' % submit_ca_information_response) + logging.debug( + "submit_ca_information_response: %s" % submit_ca_information_response + ) self.assertEqual( first=bool(submit_ca_information_response), second=True, ) # Read CRL Configuration - @parameterized.expand([ - param( - 'success', - ), - ]) - def test_read_crl_configuration(self, label, raises=False, exception_message=''): - expiry = '72h' + @parameterized.expand( + [ + param( + "success", + ), + ] + ) + def test_read_crl_configuration(self, label, raises=False, exception_message=""): + expiry = "72h" self.client.secrets.pki.set_crl_configuration( expiry=expiry, mount_point=self.TEST_MOUNT_POINT, ) - read_crl_configuration_response = self.client.secrets.pki.read_crl_configuration( - mount_point=self.TEST_MOUNT_POINT, + read_crl_configuration_response = ( + self.client.secrets.pki.read_crl_configuration( + mount_point=self.TEST_MOUNT_POINT, + ) + ) + logging.debug( + "read_crl_configuration_response: %s" % read_crl_configuration_response ) - logging.debug('read_crl_configuration_response: %s' % read_crl_configuration_response) self.assertIsInstance( obj=read_crl_configuration_response, cls=dict, ) # Set CRL Configuration - @parameterized.expand([ - param( - 'success', - ), - ]) - def test_set_crl_configuration(self, label, raises=False, exception_message=''): - expiry = '72h' + @parameterized.expand( + [ + param( + "success", + ), + ] + ) + def test_set_crl_configuration(self, label, raises=False, exception_message=""): + expiry = "72h" disable = False set_crl_configuration_response = self.client.secrets.pki.set_crl_configuration( expiry=expiry, disable=disable, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('set_crl_configuration_response: %s' % set_crl_configuration_response) + logging.debug( + "set_crl_configuration_response: %s" % set_crl_configuration_response + ) self.assertEqual( first=bool(set_crl_configuration_response), second=True, ) # Read URLs - @parameterized.expand([ - param( - 'success', - ), - ]) - def test_read_urls(self, label, raises=False, exception_message=''): + @parameterized.expand( + [ + param( + "success", + ), + ] + ) + def test_read_urls(self, label, raises=False, exception_message=""): params = { - 'issuing_certificates': ['http://127.0.0.1:8200/v1/pki/ca'], - 'crl_distribution_points': ['http://127.0.0.1:8200/v1/pki/crl'] - } + "issuing_certificates": ["http://127.0.0.1:8200/v1/pki/ca"], + "crl_distribution_points": ["http://127.0.0.1:8200/v1/pki/crl"], + } self.client.secrets.pki.set_urls( params=params, mount_point=self.TEST_MOUNT_POINT, @@ -190,41 +219,45 @@ def test_read_urls(self, label, raises=False, exception_message=''): read_urls_response = self.client.secrets.pki.read_urls( mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('read_urls_response: %s' % read_urls_response) + logging.debug("read_urls_response: %s" % read_urls_response) self.assertIsInstance( obj=read_urls_response, cls=dict, ) # Set URLs - @parameterized.expand([ - param( - 'success', - ), - ]) - def test_set_urls(self, label, raises=False, exception_message=''): + @parameterized.expand( + [ + param( + "success", + ), + ] + ) + def test_set_urls(self, label, raises=False, exception_message=""): params = { - 'issuing_certificates': ['http://127.0.0.1:8200/v1/pki/ca'], - 'crl_distribution_points': ['http://127.0.0.1:8200/v1/pki/crl'] - } + "issuing_certificates": ["http://127.0.0.1:8200/v1/pki/ca"], + "crl_distribution_points": ["http://127.0.0.1:8200/v1/pki/crl"], + } set_urls_response = self.client.secrets.pki.set_urls( params=params, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('set_urls_response: %s' % set_urls_response) + logging.debug("set_urls_response: %s" % set_urls_response) self.assertEqual( first=bool(set_urls_response), second=True, ) # Read CRL - @parameterized.expand([ - param( - 'success', - ), - ]) - def test_read_crl(self, label, raises=False, exception_message=''): - expiry = '72h' + @parameterized.expand( + [ + param( + "success", + ), + ] + ) + def test_read_crl(self, label, raises=False, exception_message=""): + expiry = "72h" self.client.secrets.pki.set_crl_configuration( expiry=expiry, mount_point=self.TEST_MOUNT_POINT, @@ -233,71 +266,83 @@ def test_read_crl(self, label, raises=False, exception_message=''): read_crl_response = self.client.secrets.pki.read_crl( mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('read_crl_response: %s' % read_crl_response) + logging.debug("read_crl_response: %s" % read_crl_response) self.assertIsInstance( obj=read_crl_response, cls=str, ) # Rotate CRLs - @parameterized.expand([ - param( - 'success', - ), - ]) - def test_rotate_crl(self, label, raises=False, exception_message=''): + @parameterized.expand( + [ + param( + "success", + ), + ] + ) + def test_rotate_crl(self, label, raises=False, exception_message=""): rotate_crl_response = self.client.secrets.pki.rotate_crl( mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('rotate_crl_response: %s' % rotate_crl_response) + logging.debug("rotate_crl_response: %s" % rotate_crl_response) self.assertIsInstance( obj=rotate_crl_response, cls=dict, ) # Generate Intermediate - @parameterized.expand([ - param( - 'success', - ), - ]) - def test_generate_intermediate(self, label, raises=False, exception_message=''): - common_name = 'Vault integration tests' - generate_type = 'exported' + @parameterized.expand( + [ + param( + "success", + ), + ] + ) + def test_generate_intermediate(self, label, raises=False, exception_message=""): + common_name = "Vault integration tests" + generate_type = "exported" generate_intermediate_response = self.client.secrets.pki.generate_intermediate( type=generate_type, common_name=common_name, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('generate_intermediate_response: %s' % generate_intermediate_response) + logging.debug( + "generate_intermediate_response: %s" % generate_intermediate_response + ) self.assertEqual( first=bool(generate_intermediate_response), second=True, ) # Set Signed Intermediate - @parameterized.expand([ - param( - 'success', - ), - ]) - def test_set_signed_intermediate(self, label, raises=False, exception_message=''): + @parameterized.expand( + [ + param( + "success", + ), + ] + ) + def test_set_signed_intermediate(self, label, raises=False, exception_message=""): # Generate intermediate CA mount point - ca_intermediate_pki_mount_point = '{}-signed-intermediate-ca'.format(self.TEST_MOUNT_POINT) - self.client.enable_secret_backend( - backend_type='pki', - mount_point=ca_intermediate_pki_mount_point, + ca_intermediate_pki_mount_point = "{}-signed-intermediate-ca".format( + self.TEST_MOUNT_POINT + ) + self.client.sys.enable_secrets_engine( + backend_type="pki", + path=ca_intermediate_pki_mount_point, ) # Generate intermediate CA - common_name = 'Vault integration tests intermediate CA' - generate_type = 'exported' + common_name = "Vault integration tests intermediate CA" + generate_type = "exported" generate_intermediate_response = self.client.secrets.pki.generate_intermediate( type=generate_type, common_name=common_name, mount_point=ca_intermediate_pki_mount_point, ) - logging.debug('generate_intermediate_response: %s' % generate_intermediate_response) - csr = generate_intermediate_response['data']['csr'] + logging.debug( + "generate_intermediate_response: %s" % generate_intermediate_response + ) + csr = generate_intermediate_response["data"]["csr"] # Sign intermediate CA sign_intermediate_response = self.client.secrets.pki.sign_intermediate( @@ -305,129 +350,151 @@ def test_set_signed_intermediate(self, label, raises=False, exception_message='' common_name=common_name, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('sign_intermediate_response: %s' % sign_intermediate_response) - certificate = sign_intermediate_response['data']['certificate'] + logging.debug("sign_intermediate_response: %s" % sign_intermediate_response) + certificate = sign_intermediate_response["data"]["certificate"] # Finally test Set Signed Intermediate - set_signed_intermediate_response = self.client.secrets.pki.set_signed_intermediate( - certificate=certificate, - mount_point=ca_intermediate_pki_mount_point, + set_signed_intermediate_response = ( + self.client.secrets.pki.set_signed_intermediate( + certificate=certificate, + mount_point=ca_intermediate_pki_mount_point, + ) + ) + logging.debug( + "set_signed_intermediate_response: %s" % set_signed_intermediate_response ) - logging.debug('set_signed_intermediate_response: %s' % set_signed_intermediate_response) self.assertEqual( first=bool(set_signed_intermediate_response), second=True, ) # Now clean intermediate CA - self.client.disable_secret_backend(mount_point=ca_intermediate_pki_mount_point) + self.client.sys.disable_secrets_engine(path=ca_intermediate_pki_mount_point) # Generate Certificate - @parameterized.expand([ - param( - 'success', - ), - ]) - def test_generate_certificate(self, label, raises=False, exception_message=''): + @parameterized.expand( + [ + param( + "success", + ), + ] + ) + def test_generate_certificate(self, label, raises=False, exception_message=""): name = self.TEST_ROLE - common_name = 'test.example.com' + common_name = "test.example.com" generate_certificate_response = self.client.secrets.pki.generate_certificate( name=name, common_name=common_name, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('generate_certificate_response: %s' % generate_certificate_response) + logging.debug( + "generate_certificate_response: %s" % generate_certificate_response + ) self.assertEqual( first=bool(generate_certificate_response), second=True, ) # Revoke Certificate - @parameterized.expand([ - param( - 'success', - ), - ]) - def test_revoke_certificate(self, label, raises=False, exception_message=''): + @parameterized.expand( + [ + param( + "success", + ), + ] + ) + def test_revoke_certificate(self, label, raises=False, exception_message=""): name = self.TEST_ROLE - common_name = 'test.example.com' + common_name = "test.example.com" generate_certificate_response = self.client.secrets.pki.generate_certificate( name=name, common_name=common_name, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('generate_certificate_response: %s' % generate_certificate_response) - serial_number = generate_certificate_response['data']['serial_number'] - logging.debug('serial_number: %s' % serial_number) + logging.debug( + "generate_certificate_response: %s" % generate_certificate_response + ) + serial_number = generate_certificate_response["data"]["serial_number"] + logging.debug("serial_number: %s" % serial_number) revoke_certificate_response = self.client.secrets.pki.revoke_certificate( serial_number=serial_number, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('revoke_certificate_response: %s' % revoke_certificate_response) + logging.debug("revoke_certificate_response: %s" % revoke_certificate_response) self.assertEqual( first=bool(revoke_certificate_response), second=True, ) # Create/Update Role - @parameterized.expand([ - param( - 'success', - ), - ]) - def test_create_or_update_role(self, label, raises=False, exception_message=''): - name = '{}-2'.format(self.TEST_ROLE) + @parameterized.expand( + [ + param( + "success", + ), + ] + ) + def test_create_or_update_role(self, label, raises=False, exception_message=""): + name = "{}-2".format(self.TEST_ROLE) create_or_update_role_response = self.client.secrets.pki.create_or_update_role( name=name, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('create_or_update_role_response: %s' % create_or_update_role_response) + logging.debug( + "create_or_update_role_response: %s" % create_or_update_role_response + ) self.assertEqual( first=bool(create_or_update_role_response), second=True, ) # Read Role - @parameterized.expand([ - param( - 'success', - ), - ]) - def test_read_role(self, label, raises=False, exception_message=''): + @parameterized.expand( + [ + param( + "success", + ), + ] + ) + def test_read_role(self, label, raises=False, exception_message=""): read_role_response = self.client.secrets.pki.read_role( name=self.TEST_ROLE, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('read_role_response: %s' % read_role_response) + logging.debug("read_role_response: %s" % read_role_response) self.assertIsInstance( obj=read_role_response, cls=dict, ) # List Roles - @parameterized.expand([ - param( - 'success', - ), - ]) - def test_list_roles(self, label, raises=False, exception_message=''): + @parameterized.expand( + [ + param( + "success", + ), + ] + ) + def test_list_roles(self, label, raises=False, exception_message=""): list_roles_response = self.client.secrets.pki.list_roles( mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('list_roles_response: %s' % list_roles_response) + logging.debug("list_roles_response: %s" % list_roles_response) self.assertIsInstance( obj=list_roles_response, cls=dict, ) # Delete Role - @parameterized.expand([ - param( - 'success', - ), - ]) - def test_delete_role(self, label, raises=False, exception_message=''): - name = '{}-2'.format(self.TEST_ROLE) + @parameterized.expand( + [ + param( + "success", + ), + ] + ) + def test_delete_role(self, label, raises=False, exception_message=""): + name = "{}-2".format(self.TEST_ROLE) self.client.secrets.pki.create_or_update_role( name=name, mount_point=self.TEST_MOUNT_POINT, @@ -437,52 +504,56 @@ def test_delete_role(self, label, raises=False, exception_message=''): name=name, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('delete_role_response: %s' % delete_role_response) + logging.debug("delete_role_response: %s" % delete_role_response) self.assertEqual( first=bool(delete_role_response), second=True, ) # Generate Root - @parameterized.expand([ - param( - 'success', - ), - ]) - def test_generate_root(self, label, raises=False, exception_message=''): - ca_pki_mount_point = '{}-test-ca'.format(self.TEST_MOUNT_POINT) - self.client.enable_secret_backend( - backend_type='pki', - mount_point=ca_pki_mount_point, - ) - common_name = 'Vault integration tests' - generate_type = 'exported' + @parameterized.expand( + [ + param( + "success", + ), + ] + ) + def test_generate_root(self, label, raises=False, exception_message=""): + ca_pki_mount_point = "{}-test-ca".format(self.TEST_MOUNT_POINT) + self.client.sys.enable_secrets_engine( + backend_type="pki", + path=ca_pki_mount_point, + ) + common_name = "Vault integration tests" + generate_type = "exported" generate_root_response = self.client.secrets.pki.generate_root( type=generate_type, common_name=common_name, mount_point=ca_pki_mount_point, ) - logging.debug('generate_root_response: %s' % generate_root_response) + logging.debug("generate_root_response: %s" % generate_root_response) self.assertEqual( first=bool(generate_root_response), second=True, ) - self.client.disable_secret_backend(mount_point=ca_pki_mount_point) + self.client.sys.disable_secrets_engine(path=ca_pki_mount_point) # Delete Root - @parameterized.expand([ - param( - 'success', - ), - ]) - def test_delete_root(self, label, raises=False, exception_message=''): - ca_pki_mount_point = '{}-test-ca'.format(self.TEST_MOUNT_POINT) - self.client.enable_secret_backend( - backend_type='pki', - mount_point=ca_pki_mount_point, - ) - common_name = 'Vault integration tests' - generate_type = 'exported' + @parameterized.expand( + [ + param( + "success", + ), + ] + ) + def test_delete_root(self, label, raises=False, exception_message=""): + ca_pki_mount_point = "{}-test-ca".format(self.TEST_MOUNT_POINT) + self.client.sys.enable_secrets_engine( + backend_type="pki", + path=ca_pki_mount_point, + ) + common_name = "Vault integration tests" + generate_type = "exported" self.client.secrets.pki.generate_root( type=generate_type, common_name=common_name, @@ -492,118 +563,138 @@ def test_delete_root(self, label, raises=False, exception_message=''): delete_root_response = self.client.secrets.pki.delete_root( mount_point=ca_pki_mount_point, ) - logging.debug('delete_root_response: %s' % delete_root_response) + logging.debug("delete_root_response: %s" % delete_root_response) self.assertEqual( first=bool(delete_root_response), second=True, ) - self.client.disable_secret_backend(mount_point=ca_pki_mount_point) + self.client.sys.disable_secrets_engine(path=ca_pki_mount_point) # Sign Intermediate - @parameterized.expand([ - param( - 'success', - ), - ]) - def test_sign_intermediate(self, label, raises=False, exception_message=''): + @parameterized.expand( + [ + param( + "success", + ), + ] + ) + def test_sign_intermediate(self, label, raises=False, exception_message=""): # Generate intermediate CA - ca_intermediate_pki_mount_point = '{}-intermediate-ca'.format(self.TEST_MOUNT_POINT) - self.client.enable_secret_backend( - backend_type='pki', - mount_point=ca_intermediate_pki_mount_point, + ca_intermediate_pki_mount_point = "{}-intermediate-ca".format( + self.TEST_MOUNT_POINT ) - common_name = 'Vault integration tests intermediate CA' - generate_type = 'exported' + self.client.sys.enable_secrets_engine( + backend_type="pki", + path=ca_intermediate_pki_mount_point, + ) + common_name = "Vault integration tests intermediate CA" + generate_type = "exported" generate_intermediate_response = self.client.secrets.pki.generate_intermediate( type=generate_type, common_name=common_name, mount_point=ca_intermediate_pki_mount_point, ) - logging.debug('generate_intermediate_response: %s' % generate_intermediate_response) - csr = generate_intermediate_response['data']['csr'] + logging.debug( + "generate_intermediate_response: %s" % generate_intermediate_response + ) + csr = generate_intermediate_response["data"]["csr"] sign_intermediate_response = self.client.secrets.pki.sign_intermediate( csr=csr, common_name=common_name, - extra_params={'use_csr_values': True}, + extra_params={"use_csr_values": True}, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('sign_intermediate_response: %s' % sign_intermediate_response) + logging.debug("sign_intermediate_response: %s" % sign_intermediate_response) self.assertEqual( first=bool(sign_intermediate_response), second=True, ) # Now clean intermediate CA - self.client.disable_secret_backend(mount_point=ca_intermediate_pki_mount_point) + self.client.sys.disable_secrets_engine(path=ca_intermediate_pki_mount_point) # Sign Self-Issued - @parameterized.expand([ - param( - 'success', - ), - ]) - def test_sign_self_issued(self, label, raises=False, exception_message=''): + @parameterized.expand( + [ + param( + "success", + ), + ] + ) + def test_sign_self_issued(self, label, raises=False, exception_message=""): sign_self_issued_response = self.client.secrets.pki.sign_self_issued( - certificate=''.join(open(utils.get_config_file_path('ca-cert.pem')).readlines()), + certificate="".join( + open(utils.get_config_file_path("ca-cert.pem")).readlines() + ), mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('sign_self_issued_response: %s' % sign_self_issued_response) + logging.debug("sign_self_issued_response: %s" % sign_self_issued_response) self.assertEqual( first=bool(sign_self_issued_response), second=True, ) # Sign Certificate - @parameterized.expand([ - param( - 'success', - ), - ]) - def test_sign_certificate(self, label, raises=False, exception_message=''): + @parameterized.expand( + [ + param( + "success", + ), + ] + ) + def test_sign_certificate(self, label, raises=False, exception_message=""): name = self.TEST_ROLE - common_name = 'another.example.com' + common_name = "another.example.com" sign_certificate_response = self.client.secrets.pki.sign_certificate( name=name, - csr=''.join(open(utils.get_config_file_path('server-cert.csr')).readlines()), + csr="".join( + open(utils.get_config_file_path("server-cert.csr")).readlines() + ), common_name=common_name, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('sign_certificate_response: %s' % sign_certificate_response) + logging.debug("sign_certificate_response: %s" % sign_certificate_response) self.assertEqual( first=bool(sign_certificate_response), second=True, ) # Sign Verbatim - @parameterized.expand([ - param( - 'success', - ), - ]) - def test_sign_verbatim(self, label, raises=False, exception_message=''): + @parameterized.expand( + [ + param( + "success", + ), + ] + ) + def test_sign_verbatim(self, label, raises=False, exception_message=""): name = self.TEST_ROLE sign_verbatim_response = self.client.secrets.pki.sign_verbatim( - csr=''.join(open(utils.get_config_file_path('server-cert.csr')).readlines()), + csr="".join( + open(utils.get_config_file_path("server-cert.csr")).readlines() + ), name=name, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('sign_verbatim_response: %s' % sign_verbatim_response) + logging.debug("sign_verbatim_response: %s" % sign_verbatim_response) self.assertEqual( first=bool(sign_verbatim_response), second=True, ) # Tidy - @parameterized.expand([ - param( - 'success', - ), - ]) - def test_tidy(self, label, raises=False, exception_message=''): + @parameterized.expand( + [ + param( + "success", + ), + ] + ) + def test_tidy(self, label, raises=False, exception_message=""): tidy_response = self.client.secrets.pki.tidy( mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('tidy_response: %s' % tidy_response) + logging.debug("tidy_response: %s" % tidy_response) self.assertEqual( first=bool(tidy_response), second=True, diff --git a/tests/integration_tests/api/secrets_engines/test_transform.py b/tests/integration_tests/api/secrets_engines/test_transform.py index 156b29cd5..a30f22f2f 100644 --- a/tests/integration_tests/api/secrets_engines/test_transform.py +++ b/tests/integration_tests/api/secrets_engines/test_transform.py @@ -154,7 +154,7 @@ def test_create_or_update_fpe_transformation(self): ) ) logging.debug("create_response: {}".format(create_response)) - self.assertEquals( + self.assertEqual( first=create_response.status_code, second=204, ) diff --git a/tests/integration_tests/api/secrets_engines/test_transit.py b/tests/integration_tests/api/secrets_engines/test_transit.py index 58290ef19..086beb8c4 100644 --- a/tests/integration_tests/api/secrets_engines/test_transit.py +++ b/tests/integration_tests/api/secrets_engines/test_transit.py @@ -10,26 +10,28 @@ class TestTransit(HvacIntegrationTestCase, TestCase): - TEST_MOUNT_POINT = 'transit-integration-test' + TEST_MOUNT_POINT = "transit-integration-test" def setUp(self): super(TestTransit, self).setUp() - self.client.enable_secret_backend( - backend_type='transit', - mount_point=self.TEST_MOUNT_POINT, + self.client.sys.enable_secrets_engine( + backend_type="transit", + path=self.TEST_MOUNT_POINT, ) def tearDown(self): - self.client.disable_secret_backend(mount_point=self.TEST_MOUNT_POINT) + self.client.sys.disable_secrets_engine(path=self.TEST_MOUNT_POINT) super(TestTransit, self).tearDown() - @parameterized.expand([ - param( - 'success', - ), - ]) - def test_create_key(self, label, raises=False, exception_message=''): - key_name = 'testkey' + @parameterized.expand( + [ + param( + "success", + ), + ] + ) + def test_create_key(self, label, raises=False, exception_message=""): + key_name = "testkey" if raises: with self.assertRaises(raises) as cm: self.client.secrets.transit.create_key( @@ -45,24 +47,26 @@ def test_create_key(self, label, raises=False, exception_message=''): name=key_name, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('create_key_response: %s' % create_key_response) + logging.debug("create_key_response: %s" % create_key_response) self.assertEqual( first=bool(create_key_response), second=True, ) - @parameterized.expand([ - param( - 'success', - ), - ]) - def test_read_key(self, label, raises=False, exception_message=''): - key_name = 'testkey' + @parameterized.expand( + [ + param( + "success", + ), + ] + ) + def test_read_key(self, label, raises=False, exception_message=""): + key_name = "testkey" create_key_response = self.client.secrets.transit.create_key( name=key_name, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('create_key_response: %s' % create_key_response) + logging.debug("create_key_response: %s" % create_key_response) if raises: with self.assertRaises(raises) as cm: self.client.secrets.transit.read_key( @@ -78,24 +82,26 @@ def test_read_key(self, label, raises=False, exception_message=''): name=key_name, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('read_key_response: %s' % read_key_response) + logging.debug("read_key_response: %s" % read_key_response) self.assertEqual( - first=read_key_response['data']['name'], + first=read_key_response["data"]["name"], second=key_name, ) - @parameterized.expand([ - param( - 'success', - ), - ]) - def test_list_keys(self, label, raises=False, exception_message=''): - key_name = 'testkey' + @parameterized.expand( + [ + param( + "success", + ), + ] + ) + def test_list_keys(self, label, raises=False, exception_message=""): + key_name = "testkey" create_key_response = self.client.secrets.transit.create_key( name=key_name, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('create_key_response: %s' % create_key_response) + logging.debug("create_key_response: %s" % create_key_response) if raises: with self.assertRaises(raises) as cm: self.client.secrets.transit.list_keys( @@ -109,30 +115,36 @@ def test_list_keys(self, label, raises=False, exception_message=''): list_keys_response = self.client.secrets.transit.list_keys( mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('list_keys_response: %s' % list_keys_response) + logging.debug("list_keys_response: %s" % list_keys_response) self.assertEqual( - first=list_keys_response['data']['keys'], + first=list_keys_response["data"]["keys"], second=[key_name], ) - @parameterized.expand([ - param( - 'success', - ), - ]) - def test_delete_key(self, label, raises=False, exception_message=''): - key_name = 'testkey' + @parameterized.expand( + [ + param( + "success", + ), + ] + ) + def test_delete_key(self, label, raises=False, exception_message=""): + key_name = "testkey" create_key_response = self.client.secrets.transit.create_key( name=key_name, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('create_key_response: %s' % create_key_response) - update_key_configuration_response = self.client.secrets.transit.update_key_configuration( - name=key_name, - deletion_allowed=True, - mount_point=self.TEST_MOUNT_POINT, + logging.debug("create_key_response: %s" % create_key_response) + update_key_configuration_response = ( + self.client.secrets.transit.update_key_configuration( + name=key_name, + deletion_allowed=True, + mount_point=self.TEST_MOUNT_POINT, + ) + ) + logging.debug( + "update_key_configuration_response: %s" % update_key_configuration_response ) - logging.debug('update_key_configuration_response: %s' % update_key_configuration_response) if raises: with self.assertRaises(raises) as cm: self.client.secrets.transit.delete_key( @@ -148,24 +160,26 @@ def test_delete_key(self, label, raises=False, exception_message=''): name=key_name, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('delete_key_response: %s' % delete_key_response) + logging.debug("delete_key_response: %s" % delete_key_response) self.assertEqual( first=bool(delete_key_response), second=True, ) - @parameterized.expand([ - param( - 'success', - ), - ]) - def test_rotate_key(self, label, raises=False, exception_message=''): - key_name = 'testkey' + @parameterized.expand( + [ + param( + "success", + ), + ] + ) + def test_rotate_key(self, label, raises=False, exception_message=""): + key_name = "testkey" create_key_response = self.client.secrets.transit.create_key( name=key_name, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('create_key_response: %s' % create_key_response) + logging.debug("create_key_response: %s" % create_key_response) if raises: with self.assertRaises(raises) as cm: self.client.secrets.transit.rotate_key( @@ -181,31 +195,35 @@ def test_rotate_key(self, label, raises=False, exception_message=''): name=key_name, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('rotate_key_response: %s' % rotate_key_response) + logging.debug("rotate_key_response: %s" % rotate_key_response) self.assertEqual( first=bool(rotate_key_response), second=True, ) - @parameterized.expand([ - param( - 'success', - ), - param( - 'invalid key type', - key_type='kitty-cat-key', - raises=exceptions.ParamValidationError, - exception_message='invalid key_type argument provided', - ), - ]) - def test_export_key(self, label, key_type='hmac-key', raises=False, exception_message=''): - key_name = 'testkey' + @parameterized.expand( + [ + param( + "success", + ), + param( + "invalid key type", + key_type="kitty-cat-key", + raises=exceptions.ParamValidationError, + exception_message="invalid key_type argument provided", + ), + ] + ) + def test_export_key( + self, label, key_type="hmac-key", raises=False, exception_message="" + ): + key_name = "testkey" create_key_response = self.client.secrets.transit.create_key( name=key_name, exportable=True, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('create_key_response: %s' % create_key_response) + logging.debug("create_key_response: %s" % create_key_response) if raises: with self.assertRaises(raises) as cm: self.client.secrets.transit.export_key( @@ -223,29 +241,33 @@ def test_export_key(self, label, key_type='hmac-key', raises=False, exception_me key_type=key_type, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('export_key_response: %s' % export_key_response) + logging.debug("export_key_response: %s" % export_key_response) self.assertEqual( - first=len(export_key_response['data']['keys']), + first=len(export_key_response["data"]["keys"]), second=1, ) self.assertEqual( - first=export_key_response['data']['name'], + first=export_key_response["data"]["name"], second=key_name, ) - @parameterized.expand([ - param( - 'success', - ), - ]) - def test_encrypt_data(self, label, plaintext='hi itsame hvac', raises=False, exception_message=''): - key_name = 'testkey' + @parameterized.expand( + [ + param( + "success", + ), + ] + ) + def test_encrypt_data( + self, label, plaintext="hi itsame hvac", raises=False, exception_message="" + ): + key_name = "testkey" plaintext = utils.base64ify(plaintext) create_key_response = self.client.secrets.transit.create_key( name=key_name, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('create_key_response: %s' % create_key_response) + logging.debug("create_key_response: %s" % create_key_response) if raises: with self.assertRaises(raises) as cm: self.client.secrets.transit.encrypt_data( @@ -263,32 +285,36 @@ def test_encrypt_data(self, label, plaintext='hi itsame hvac', raises=False, exc plaintext=plaintext, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('encrypt_data_response: %s' % encrypt_data_response) + logging.debug("encrypt_data_response: %s" % encrypt_data_response) self.assertIn( - member='ciphertext', - container=encrypt_data_response['data'], + member="ciphertext", + container=encrypt_data_response["data"], ) - @parameterized.expand([ - param( - 'success', - ), - ]) - def test_decrypt_data(self, label, plaintext='hi itsame hvac', raises=False, exception_message=''): - key_name = 'testkey' + @parameterized.expand( + [ + param( + "success", + ), + ] + ) + def test_decrypt_data( + self, label, plaintext="hi itsame hvac", raises=False, exception_message="" + ): + key_name = "testkey" plaintext = utils.base64ify(plaintext) create_key_response = self.client.secrets.transit.create_key( name=key_name, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('create_key_response: %s' % create_key_response) + logging.debug("create_key_response: %s" % create_key_response) encrypt_data_response = self.client.secrets.transit.encrypt_data( name=key_name, plaintext=plaintext, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('encrypt_data_response: %s' % encrypt_data_response) - ciphertext = encrypt_data_response['data']['ciphertext'] + logging.debug("encrypt_data_response: %s" % encrypt_data_response) + ciphertext = encrypt_data_response["data"]["ciphertext"] if raises: with self.assertRaises(raises) as cm: self.client.secrets.transit.decrypt_data( @@ -306,37 +332,41 @@ def test_decrypt_data(self, label, plaintext='hi itsame hvac', raises=False, exc ciphertext=ciphertext, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('decrypt_data_response: %s' % decrypt_data_response) + logging.debug("decrypt_data_response: %s" % decrypt_data_response) self.assertIn( member=plaintext, - container=decrypt_data_response['data']['plaintext'], + container=decrypt_data_response["data"]["plaintext"], ) - @parameterized.expand([ - param( - 'success', - ), - ]) - def test_rewrap_data(self, label, plaintext='hi itsame hvac', raises=False, exception_message=''): - key_name = 'testkey' + @parameterized.expand( + [ + param( + "success", + ), + ] + ) + def test_rewrap_data( + self, label, plaintext="hi itsame hvac", raises=False, exception_message="" + ): + key_name = "testkey" plaintext = utils.base64ify(plaintext) create_key_response = self.client.secrets.transit.create_key( name=key_name, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('create_key_response: %s' % create_key_response) + logging.debug("create_key_response: %s" % create_key_response) encrypt_data_response = self.client.secrets.transit.encrypt_data( name=key_name, plaintext=plaintext, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('encrypt_data_response: %s' % encrypt_data_response) - ciphertext = encrypt_data_response['data']['ciphertext'] + logging.debug("encrypt_data_response: %s" % encrypt_data_response) + ciphertext = encrypt_data_response["data"]["ciphertext"] rotate_key_response = self.client.secrets.transit.rotate_key( name=key_name, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('rotate_key_response: %s' % rotate_key_response) + logging.debug("rotate_key_response: %s" % rotate_key_response) if raises: with self.assertRaises(raises) as cm: self.client.secrets.transit.rewrap_data( @@ -354,30 +384,34 @@ def test_rewrap_data(self, label, plaintext='hi itsame hvac', raises=False, exce ciphertext=ciphertext, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('rewrap_data_response: %s' % rewrap_data_response) + logging.debug("rewrap_data_response: %s" % rewrap_data_response) self.assertIn( - member='ciphertext', - container=rewrap_data_response['data'], + member="ciphertext", + container=rewrap_data_response["data"], ) - @parameterized.expand([ - param( - 'success', - ), - param( - 'invalid key type', - key_type='kitty-cat-key', - raises=exceptions.ParamValidationError, - exception_message='invalid key_type argument provided', - ), - ]) - def test_generate_data_key(self, label, key_type='plaintext', raises=False, exception_message=''): - key_name = 'testkey' + @parameterized.expand( + [ + param( + "success", + ), + param( + "invalid key type", + key_type="kitty-cat-key", + raises=exceptions.ParamValidationError, + exception_message="invalid key_type argument provided", + ), + ] + ) + def test_generate_data_key( + self, label, key_type="plaintext", raises=False, exception_message="" + ): + key_name = "testkey" create_key_response = self.client.secrets.transit.create_key( name=key_name, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('create_key_response: %s' % create_key_response) + logging.debug("create_key_response: %s" % create_key_response) if raises: with self.assertRaises(raises) as cm: self.client.secrets.transit.generate_data_key( @@ -395,18 +429,22 @@ def test_generate_data_key(self, label, key_type='plaintext', raises=False, exce key_type=key_type, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('gen_data_key_response: %s' % gen_data_key_response) + logging.debug("gen_data_key_response: %s" % gen_data_key_response) self.assertIn( - member='ciphertext', - container=gen_data_key_response['data'], + member="ciphertext", + container=gen_data_key_response["data"], ) - @parameterized.expand([ - param( - 'success', - ), - ]) - def test_generate_random_bytes(self, label, n_bytes=32, raises=False, exception_message=''): + @parameterized.expand( + [ + param( + "success", + ), + ] + ) + def test_generate_random_bytes( + self, label, n_bytes=32, raises=False, exception_message="" + ): if raises: with self.assertRaises(raises) as cm: self.client.secrets.transit.generate_random_bytes( @@ -422,30 +460,40 @@ def test_generate_random_bytes(self, label, n_bytes=32, raises=False, exception_ n_bytes=n_bytes, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('gen_data_key_response: %s' % gen_bytes_response) + logging.debug("gen_data_key_response: %s" % gen_bytes_response) self.assertIn( - member='random_bytes', - container=gen_bytes_response['data'], + member="random_bytes", + container=gen_bytes_response["data"], ) - @parameterized.expand([ - param( - 'success', - ), - param( - 'invalid algorithm', - algorithm='meow2-256', - raises=exceptions.ParamValidationError, - exception_message='invalid algorithm argument provided', - ), - param( - 'invalid output_format', - output_format='kitty64', - raises=exceptions.ParamValidationError, - exception_message='invalid output_format argument provided', - ), - ]) - def test_hash_data(self, label, hash_input='hash this ish', algorithm='sha2-256', output_format='hex', raises=False, exception_message=''): + @parameterized.expand( + [ + param( + "success", + ), + param( + "invalid algorithm", + algorithm="meow2-256", + raises=exceptions.ParamValidationError, + exception_message="invalid algorithm argument provided", + ), + param( + "invalid output_format", + output_format="kitty64", + raises=exceptions.ParamValidationError, + exception_message="invalid output_format argument provided", + ), + ] + ) + def test_hash_data( + self, + label, + hash_input="hash this ish", + algorithm="sha2-256", + output_format="hex", + raises=False, + exception_message="", + ): hash_input = utils.base64ify(hash_input) if raises: with self.assertRaises(raises) as cm: @@ -466,31 +514,40 @@ def test_hash_data(self, label, hash_input='hash this ish', algorithm='sha2-256' output_format=output_format, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('hash_data_response: %s' % hash_data_response) + logging.debug("hash_data_response: %s" % hash_data_response) self.assertIn( - member='sum', - container=hash_data_response['data'], + member="sum", + container=hash_data_response["data"], ) - @parameterized.expand([ - param( - 'success', - ), - param( - 'invalid algorithm', - algorithm='meow2-256', - raises=exceptions.ParamValidationError, - exception_message='invalid algorithm argument provided', - ), - ]) - def test_generate_hmac(self, label, hash_input='hash this ish', algorithm='sha2-256', raises=False, exception_message=''): + @parameterized.expand( + [ + param( + "success", + ), + param( + "invalid algorithm", + algorithm="meow2-256", + raises=exceptions.ParamValidationError, + exception_message="invalid algorithm argument provided", + ), + ] + ) + def test_generate_hmac( + self, + label, + hash_input="hash this ish", + algorithm="sha2-256", + raises=False, + exception_message="", + ): hash_input = utils.base64ify(hash_input) - key_name = 'testkey' + key_name = "testkey" create_key_response = self.client.secrets.transit.create_key( name=key_name, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('create_key_response: %s' % create_key_response) + logging.debug("create_key_response: %s" % create_key_response) if raises: with self.assertRaises(raises) as cm: self.client.secrets.transit.generate_hmac( @@ -510,40 +567,49 @@ def test_generate_hmac(self, label, hash_input='hash this ish', algorithm='sha2- algorithm=algorithm, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('generate_hmac_response: %s' % generate_hmac_response) + logging.debug("generate_hmac_response: %s" % generate_hmac_response) self.assertIn( - member='hmac', - container=generate_hmac_response['data'], + member="hmac", + container=generate_hmac_response["data"], ) - @parameterized.expand([ - param( - 'success', - ), - param( - 'invalid algorithm', - hash_algorithm='meow2-256', - raises=exceptions.ParamValidationError, - exception_message='invalid hash_algorithm argument provided', - ), - param( - 'invalid signature_algorithm', - signature_algorithm='pre-shared kitty cats', - raises=exceptions.ParamValidationError, - exception_message='invalid signature_algorithm argument provided', - ), - ]) - def test_sign_data(self, label, hash_input='hash this ish', hash_algorithm='sha2-256', signature_algorithm='pss', - raises=False, exception_message=''): + @parameterized.expand( + [ + param( + "success", + ), + param( + "invalid algorithm", + hash_algorithm="meow2-256", + raises=exceptions.ParamValidationError, + exception_message="invalid hash_algorithm argument provided", + ), + param( + "invalid signature_algorithm", + signature_algorithm="pre-shared kitty cats", + raises=exceptions.ParamValidationError, + exception_message="invalid signature_algorithm argument provided", + ), + ] + ) + def test_sign_data( + self, + label, + hash_input="hash this ish", + hash_algorithm="sha2-256", + signature_algorithm="pss", + raises=False, + exception_message="", + ): hash_input = utils.base64ify(hash_input) - key_name = 'testkey' - key_type = 'ed25519' + key_name = "testkey" + key_type = "ed25519" create_key_response = self.client.secrets.transit.create_key( name=key_name, key_type=key_type, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('create_key_response: %s' % create_key_response) + logging.debug("create_key_response: %s" % create_key_response) if raises: with self.assertRaises(raises) as cm: self.client.secrets.transit.sign_data( @@ -565,49 +631,58 @@ def test_sign_data(self, label, hash_input='hash this ish', hash_algorithm='sha2 signature_algorithm=signature_algorithm, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('sign_data_response: %s' % sign_data_response) + logging.debug("sign_data_response: %s" % sign_data_response) self.assertIn( - member='signature', - container=sign_data_response['data'], + member="signature", + container=sign_data_response["data"], ) - @parameterized.expand([ - param( - 'success', - ), - param( - 'invalid algorithm', - hash_algorithm='meow2-256', - raises=exceptions.ParamValidationError, - exception_message='invalid hash_algorithm argument provided', - ), - param( - 'invalid signature_algorithm', - signature_algorithm='pre-shared kitty cats', - raises=exceptions.ParamValidationError, - exception_message='invalid signature_algorithm argument provided', - ), - ]) - def test_verify_signed_data(self, label, hash_input='hash this ish', hash_algorithm='sha2-256', signature_algorithm='pss', - raises=False, exception_message=''): + @parameterized.expand( + [ + param( + "success", + ), + param( + "invalid algorithm", + hash_algorithm="meow2-256", + raises=exceptions.ParamValidationError, + exception_message="invalid hash_algorithm argument provided", + ), + param( + "invalid signature_algorithm", + signature_algorithm="pre-shared kitty cats", + raises=exceptions.ParamValidationError, + exception_message="invalid signature_algorithm argument provided", + ), + ] + ) + def test_verify_signed_data( + self, + label, + hash_input="hash this ish", + hash_algorithm="sha2-256", + signature_algorithm="pss", + raises=False, + exception_message="", + ): hash_input = utils.base64ify(hash_input) - key_name = 'testkey' - key_type = 'ed25519' + key_name = "testkey" + key_type = "ed25519" create_key_response = self.client.secrets.transit.create_key( name=key_name, key_type=key_type, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('create_key_response: %s' % create_key_response) + logging.debug("create_key_response: %s" % create_key_response) sign_data_response = self.client.secrets.transit.sign_data( name=key_name, hash_input=hash_input, - hash_algorithm='sha2-256', - signature_algorithm='pss', + hash_algorithm="sha2-256", + signature_algorithm="pss", mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('sign_data_response: %s' % sign_data_response) - signature = sign_data_response['data']['signature'] + logging.debug("sign_data_response: %s" % sign_data_response) + signature = sign_data_response["data"]["signature"] if raises: with self.assertRaises(raises) as cm: self.client.secrets.transit.verify_signed_data( @@ -623,45 +698,60 @@ def test_verify_signed_data(self, label, hash_input='hash this ish', hash_algori container=str(cm.exception), ) else: - verify_signed_data_response = self.client.secrets.transit.verify_signed_data( - name=key_name, - hash_input=hash_input, - signature=signature, - hash_algorithm=hash_algorithm, - signature_algorithm=signature_algorithm, - mount_point=self.TEST_MOUNT_POINT, + verify_signed_data_response = ( + self.client.secrets.transit.verify_signed_data( + name=key_name, + hash_input=hash_input, + signature=signature, + hash_algorithm=hash_algorithm, + signature_algorithm=signature_algorithm, + mount_point=self.TEST_MOUNT_POINT, + ) + ) + logging.debug( + "verify_signed_data_response: %s" % verify_signed_data_response ) - logging.debug('verify_signed_data_response: %s' % verify_signed_data_response) self.assertTrue( - expr=verify_signed_data_response['data']['valid'], + expr=verify_signed_data_response["data"]["valid"], ) - @parameterized.expand([ - param( - 'success', - ), - param( - 'allow_plaintext_backup false', - allow_plaintext_backup=False, - raises=exceptions.InternalServerError, - exception_message='plaintext backup is disallowed on the policy', - ), - ]) - @skipIf(utils.vault_version_lt('0.9.1'), "transit key export/restore added in Vault versions >=0.9.1") - def test_backup_key(self, label, allow_plaintext_backup=True, raises=False, exception_message=''): - key_name = 'testkey' + @parameterized.expand( + [ + param( + "success", + ), + param( + "allow_plaintext_backup false", + allow_plaintext_backup=False, + raises=exceptions.InternalServerError, + exception_message="plaintext backup is disallowed on the policy", + ), + ] + ) + @skipIf( + utils.vault_version_lt("0.9.1"), + "transit key export/restore added in Vault versions >=0.9.1", + ) + def test_backup_key( + self, label, allow_plaintext_backup=True, raises=False, exception_message="" + ): + key_name = "testkey" create_key_response = self.client.secrets.transit.create_key( name=key_name, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('create_key_response: %s' % create_key_response) - update_key_configuration_response = self.client.secrets.transit.update_key_configuration( - name=key_name, - exportable=True, - allow_plaintext_backup=allow_plaintext_backup, - mount_point=self.TEST_MOUNT_POINT, + logging.debug("create_key_response: %s" % create_key_response) + update_key_configuration_response = ( + self.client.secrets.transit.update_key_configuration( + name=key_name, + exportable=True, + allow_plaintext_backup=allow_plaintext_backup, + mount_point=self.TEST_MOUNT_POINT, + ) + ) + logging.debug( + "update_key_configuration_response: %s" % update_key_configuration_response ) - logging.debug('update_key_configuration_response: %s' % update_key_configuration_response) if raises: with self.assertRaises(raises) as cm: self.client.secrets.transit.backup_key( @@ -677,48 +767,59 @@ def test_backup_key(self, label, allow_plaintext_backup=True, raises=False, exce name=key_name, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('backup_key_response: %s' % backup_key_response) + logging.debug("backup_key_response: %s" % backup_key_response) self.assertIn( - member='backup', - container=backup_key_response['data'], + member="backup", + container=backup_key_response["data"], ) - @parameterized.expand([ - param( - 'success', - ), - param( - 'success with force', - force=True, - ), - param( - 'existing key without force', - name=None, - raises=exceptions.InternalServerError, - exception_message='already exists', - ), - ]) - @skipIf(utils.vault_version_lt('0.9.1'), "transit key export/restore added in Vault versions >=0.9.1") - def test_restore_key(self, label, name='new_test_ky', force=False, raises=False, exception_message=''): - key_name = 'testkey' + @parameterized.expand( + [ + param( + "success", + ), + param( + "success with force", + force=True, + ), + param( + "existing key without force", + name=None, + raises=exceptions.InternalServerError, + exception_message="already exists", + ), + ] + ) + @skipIf( + utils.vault_version_lt("0.9.1"), + "transit key export/restore added in Vault versions >=0.9.1", + ) + def test_restore_key( + self, label, name="new_test_ky", force=False, raises=False, exception_message="" + ): + key_name = "testkey" create_key_response = self.client.secrets.transit.create_key( name=key_name, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('create_key_response: %s' % create_key_response) - update_key_configuration_response = self.client.secrets.transit.update_key_configuration( - name=key_name, - exportable=True, - allow_plaintext_backup=True, - mount_point=self.TEST_MOUNT_POINT, + logging.debug("create_key_response: %s" % create_key_response) + update_key_configuration_response = ( + self.client.secrets.transit.update_key_configuration( + name=key_name, + exportable=True, + allow_plaintext_backup=True, + mount_point=self.TEST_MOUNT_POINT, + ) + ) + logging.debug( + "update_key_configuration_response: %s" % update_key_configuration_response ) - logging.debug('update_key_configuration_response: %s' % update_key_configuration_response) backup_key_response = self.client.secrets.transit.backup_key( name=key_name, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('backup_key_response: %s' % backup_key_response) - backup = backup_key_response['data']['backup'] + logging.debug("backup_key_response: %s" % backup_key_response) + backup = backup_key_response["data"]["backup"] if raises: with self.assertRaises(raises) as cm: self.client.secrets.transit.restore_key( @@ -738,45 +839,54 @@ def test_restore_key(self, label, name='new_test_ky', force=False, raises=False, force=force, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('restore_key_response: %s' % restore_key_response) + logging.debug("restore_key_response: %s" % restore_key_response) self.assertEqual( first=bool(restore_key_response), second=True, ) - @parameterized.expand([ - param( - 'success', - ), - ]) - @skipIf(utils.vault_version_lt('0.11.4'), "transit key trimming added in Vault versions >=0.11.4") - def test_trim_key(self, label, min_version=2, raises=False, exception_message=''): - key_name = 'testkey' + @parameterized.expand( + [ + param( + "success", + ), + ] + ) + @skipIf( + utils.vault_version_lt("0.11.4"), + "transit key trimming added in Vault versions >=0.11.4", + ) + def test_trim_key(self, label, min_version=2, raises=False, exception_message=""): + key_name = "testkey" create_key_response = self.client.secrets.transit.create_key( name=key_name, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('create_key_response: %s' % create_key_response) + logging.debug("create_key_response: %s" % create_key_response) for _ in range(0, 10): rotate_key_response = self.client.secrets.transit.rotate_key( name=key_name, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('rotate_key_response: %s' % rotate_key_response) + logging.debug("rotate_key_response: %s" % rotate_key_response) - update_key_configuration_response = self.client.secrets.transit.update_key_configuration( - name=key_name, - min_decryption_version=3, - min_encryption_version=9, - mount_point=self.TEST_MOUNT_POINT, + update_key_configuration_response = ( + self.client.secrets.transit.update_key_configuration( + name=key_name, + min_decryption_version=3, + min_encryption_version=9, + mount_point=self.TEST_MOUNT_POINT, + ) + ) + logging.debug( + "update_key_configuration_response: %s" % update_key_configuration_response ) - logging.debug('update_key_configuration_response: %s' % update_key_configuration_response) read_key_response = self.client.secrets.transit.read_key( name=key_name, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('read_key_response: %s' % read_key_response) + logging.debug("read_key_response: %s" % read_key_response) if raises: with self.assertRaises(raises) as cm: self.client.secrets.transit.trim_key( @@ -794,7 +904,7 @@ def test_trim_key(self, label, min_version=2, raises=False, exception_message='' min_version=min_version, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('trim_key_response: %s' % trim_key_response) + logging.debug("trim_key_response: %s" % trim_key_response) self.assertEqual( first=bool(trim_key_response), second=True, diff --git a/tests/integration_tests/api/system_backend/test_audit.py b/tests/integration_tests/api/system_backend/test_audit.py index e319c6d4d..7d9f02a48 100644 --- a/tests/integration_tests/api/system_backend/test_audit.py +++ b/tests/integration_tests/api/system_backend/test_audit.py @@ -8,54 +8,57 @@ class TestAudit(HvacIntegrationTestCase, TestCase): - TEST_AUDIT_DEVICE_PATH = 'test-tempfile' + TEST_AUDIT_DEVICE_PATH = "test-tempfile" def tearDown(self): - self.client.sys.disable_audit_device( - path=self.TEST_AUDIT_DEVICE_PATH - ) + self.client.sys.disable_audit_device(path=self.TEST_AUDIT_DEVICE_PATH) def test_audit_backend_manipulation(self): - options = { - 'path': '/tmp/vault.audit.log' - } + options = {"path": "/tmp/vault.audit.log"} self.client.sys.enable_audit_device( - device_type='file', + device_type="file", options=options, path=self.TEST_AUDIT_DEVICE_PATH, ) self.assertIn( - member='%s/' % self.TEST_AUDIT_DEVICE_PATH, - container=self.client.sys.list_enabled_audit_devices()['data'], + member="%s/" % self.TEST_AUDIT_DEVICE_PATH, + container=self.client.sys.list_enabled_audit_devices()["data"], ) self.client.sys.disable_audit_device( path=self.TEST_AUDIT_DEVICE_PATH, ) self.assertNotIn( - member='%s/' % self.TEST_AUDIT_DEVICE_PATH, - container=self.client.sys.list_enabled_audit_devices()['data'], + member="%s/" % self.TEST_AUDIT_DEVICE_PATH, + container=self.client.sys.list_enabled_audit_devices()["data"], ) - @parameterized.expand([ - param( - 'hash returned', - ), - param( - 'audit backend not enabled', - enable_first=False, - raises=exceptions.InvalidRequest, - exception_message='unknown audit backend', - ), - ]) - def test_audit_hash(self, label, enable_first=True, test_input='hvac-rox', raises=None, exception_message=''): + @parameterized.expand( + [ + param( + "hash returned", + ), + param( + "audit backend not enabled", + enable_first=False, + raises=exceptions.InvalidRequest, + exception_message="unknown audit backend", + ), + ] + ) + def test_audit_hash( + self, + label, + enable_first=True, + test_input="hvac-rox", + raises=None, + exception_message="", + ): if enable_first: - options = { - 'path': '/tmp/vault.audit.log' - } + options = {"path": "/tmp/vault.audit.log"} self.client.sys.enable_audit_device( - device_type='file', + device_type="file", options=options, path=self.TEST_AUDIT_DEVICE_PATH, ) @@ -76,8 +79,8 @@ def test_audit_hash(self, label, enable_first=True, test_input='hvac-rox', raise path=self.TEST_AUDIT_DEVICE_PATH, input_to_hash=test_input, ) - logging.debug('audit_hash_response: %s' % audit_hash_response) + logging.debug("audit_hash_response: %s" % audit_hash_response) self.assertIn( - member='hmac-sha256:', - container=audit_hash_response['data']['hash'], + member="hmac-sha256:", + container=audit_hash_response["data"]["hash"], ) diff --git a/tests/integration_tests/api/system_backend/test_auth.py b/tests/integration_tests/api/system_backend/test_auth.py index 36f795fdc..7c7a09c1e 100644 --- a/tests/integration_tests/api/system_backend/test_auth.py +++ b/tests/integration_tests/api/system_backend/test_auth.py @@ -4,19 +4,17 @@ class TestAuth(HvacIntegrationTestCase, TestCase): - TEST_AUTH_METHOD_TYPE = 'github' - TEST_AUTH_METHOD_PATH = 'test-github' + TEST_AUTH_METHOD_TYPE = "github" + TEST_AUTH_METHOD_PATH = "test-github" def tearDown(self): - self.client.sys.disable_auth_method( - path=self.TEST_AUTH_METHOD_PATH - ) + self.client.sys.disable_auth_method(path=self.TEST_AUTH_METHOD_PATH) super(TestAuth, self).tearDown() def test_auth_backend_manipulation(self): self.assertNotIn( - member='%s/' % self.TEST_AUTH_METHOD_PATH, - container=self.client.sys.list_auth_methods()['data'], + member="%s/" % self.TEST_AUTH_METHOD_PATH, + container=self.client.sys.list_auth_methods()["data"], ) self.client.sys.enable_auth_method( @@ -24,24 +22,23 @@ def test_auth_backend_manipulation(self): path=self.TEST_AUTH_METHOD_PATH, ) self.assertIn( - member='%s/' % self.TEST_AUTH_METHOD_PATH, - container=self.client.sys.list_auth_methods()['data'], + member="%s/" % self.TEST_AUTH_METHOD_PATH, + container=self.client.sys.list_auth_methods()["data"], ) self.client.sys.disable_auth_method( path=self.TEST_AUTH_METHOD_PATH, ) self.assertNotIn( - member='%s/' % self.TEST_AUTH_METHOD_PATH, - container=self.client.sys.list_auth_methods()['data'], + member="%s/" % self.TEST_AUTH_METHOD_PATH, + container=self.client.sys.list_auth_methods()["data"], ) def test_tune_auth_backend(self): - test_description = 'this is a test auth backend' + test_description = "this is a test auth backend" test_max_lease_ttl = 12345678 self.client.sys.enable_auth_method( - method_type='approle', - path=self.TEST_AUTH_METHOD_PATH + method_type="approle", path=self.TEST_AUTH_METHOD_PATH ) expected_status_code = 204 @@ -60,6 +57,5 @@ def test_tune_auth_backend(self): ) self.assertEqual( - first=test_max_lease_ttl, - second=response['data']['max_lease_ttl'] + first=test_max_lease_ttl, second=response["data"]["max_lease_ttl"] ) diff --git a/tests/integration_tests/api/system_backend/test_health.py b/tests/integration_tests/api/system_backend/test_health.py index cb3cb9e4b..62be89043 100644 --- a/tests/integration_tests/api/system_backend/test_health.py +++ b/tests/integration_tests/api/system_backend/test_health.py @@ -14,46 +14,53 @@ def tearDown(self): self.manager.unseal() super(TestHealth, self).tearDown() - @parameterized.expand([ - param( - 'default params', - ), - param( - 'unsealed standby node HEAD method', - use_standby_node=True, - method='HEAD', - expected_status_code=429, - ha_required=True, - ), - param( - 'unsealed standby node GET method', - use_standby_node=True, - method='GET', - expected_status_code=429, - ha_required=True, - ), - param( - 'sealed standby node HEAD method', - use_standby_node=True, - method='HEAD', - expected_status_code=503, - seal_first=True, - ha_required=True, - ), - param( - 'sealed standby node GET method', - use_standby_node=True, - method='GET', - expected_status_code=503, - seal_first=True, - ha_required=True, - ), - param( - 'GET method', - method='GET' - ), - ]) - def test_read_health_status(self, label, method='HEAD', use_standby_node=False, expected_status_code=200, seal_first=False, ha_required=False): + @parameterized.expand( + [ + param( + "default params", + ), + param( + "unsealed standby node HEAD method", + use_standby_node=True, + method="HEAD", + expected_status_code=429, + ha_required=True, + ), + param( + "unsealed standby node GET method", + use_standby_node=True, + method="GET", + expected_status_code=429, + ha_required=True, + ), + param( + "sealed standby node HEAD method", + use_standby_node=True, + method="HEAD", + expected_status_code=503, + seal_first=True, + ha_required=True, + ), + param( + "sealed standby node GET method", + use_standby_node=True, + method="GET", + expected_status_code=503, + seal_first=True, + ha_required=True, + ), + param("GET method", method="GET"), + ] + ) + def test_read_health_status( + self, + label, + method="HEAD", + use_standby_node=False, + expected_status_code=200, + seal_first=False, + ha_required=False, + ): """Test the Health system backend class's "read_health_status" method. :param label: Label for a given parameterized test case. @@ -71,21 +78,23 @@ def test_read_health_status(self, label, method='HEAD', use_standby_node=False, """ if ha_required and not self.enable_vault_ha: # Conditional to allow folks to run this test class without requiring consul to be installed locally. - self.skipTest('Skipping test case, Vault HA required but not available.') + self.skipTest("Skipping test case, Vault HA required but not available.") if seal_first: # Standby nodes can't be sealed directly. # I.e.: "vault cannot seal when in standby mode; please restart instead" self.manager.restart_vault_cluster() # Grab a Vault node address for our desired standby status and create a one-off client configured for that address. - vault_addr = self.get_vault_addr_by_standby_status(standby_status=use_standby_node) - logging.debug('vault_addr being used: %s' % vault_addr) + vault_addr = self.get_vault_addr_by_standby_status( + standby_status=use_standby_node + ) + logging.debug("vault_addr being used: %s" % vault_addr) client = create_client(url=vault_addr) read_status_response = client.sys.read_health_status( method=method, ) - logging.debug('read_status_response: %s' % read_status_response) + logging.debug("read_status_response: %s" % read_status_response) if expected_status_code == 200: self.assertTrue(read_status_response) else: @@ -93,9 +102,7 @@ def test_read_health_status(self, label, method='HEAD', use_standby_node=False, first=read_status_response.status_code, second=expected_status_code, ) - if method != 'HEAD': + if method != "HEAD": if not isinstance(read_status_response, dict): read_status_response = read_status_response.json() - self.assertTrue( - expr=read_status_response['initialized'] - ) + self.assertTrue(expr=read_status_response["initialized"]) diff --git a/tests/integration_tests/api/system_backend/test_init.py b/tests/integration_tests/api/system_backend/test_init.py index 0840fc08f..b1de96ca2 100644 --- a/tests/integration_tests/api/system_backend/test_init.py +++ b/tests/integration_tests/api/system_backend/test_init.py @@ -7,7 +7,5 @@ class TestInit(HvacIntegrationTestCase, TestCase): def test_read_init_status(self): read_response = self.client.sys.read_init_status() - logging.debug('read_response: %s' % read_response) - self.assertTrue( - expr=read_response['initialized'] - ) + logging.debug("read_response: %s" % read_response) + self.assertTrue(expr=read_response["initialized"]) diff --git a/tests/integration_tests/api/system_backend/test_key.py b/tests/integration_tests/api/system_backend/test_key.py index e250c6b3d..9f5846b41 100644 --- a/tests/integration_tests/api/system_backend/test_key.py +++ b/tests/integration_tests/api/system_backend/test_key.py @@ -7,18 +7,17 @@ class TestKey(HvacIntegrationTestCase, TestCase): - def test_start_generate_root_with_completion(self): test_otp = utils.get_generate_root_otp() - self.assertFalse(self.client.sys.read_root_generation_progress()['started']) + self.assertFalse(self.client.sys.read_root_generation_progress()["started"]) start_generate_root_response = self.client.sys.start_root_token_generation( otp=test_otp, ) - logging.debug('generate_root_response: %s' % start_generate_root_response) - self.assertTrue(self.client.sys.read_root_generation_progress()['started']) + logging.debug("generate_root_response: %s" % start_generate_root_response) + self.assertTrue(self.client.sys.read_root_generation_progress()["started"]) - nonce = start_generate_root_response['nonce'] + nonce = start_generate_root_response["nonce"] last_generate_root_response = {} for key in self.manager.keys[0:3]: @@ -26,16 +25,16 @@ def test_start_generate_root_with_completion(self): key=key, nonce=nonce, ) - logging.debug('last_generate_root_response: %s' % last_generate_root_response) - self.assertFalse(self.client.sys.read_root_generation_progress()['started']) + logging.debug("last_generate_root_response: %s" % last_generate_root_response) + self.assertFalse(self.client.sys.read_root_generation_progress()["started"]) new_root_token = utils.decode_generated_root_token( - encoded_token=last_generate_root_response['encoded_root_token'], + encoded_token=last_generate_root_response["encoded_root_token"], otp=test_otp, ) - logging.debug('new_root_token: %s' % new_root_token) + logging.debug("new_root_token: %s" % new_root_token) token_lookup_resp = self.client.lookup_token(token=new_root_token) - logging.debug('token_lookup_resp: %s' % token_lookup_resp) + logging.debug("token_lookup_resp: %s" % token_lookup_resp) # Assert our new root token is properly formed and authenticated self.client.token = new_root_token @@ -44,19 +43,19 @@ def test_start_generate_root_with_completion(self): else: # If our new token was unable to authenticate, set the test client's token back to the original value self.client.token = self.manager.root_token - self.fail('Unable to authenticate with the newly generated root token.') + self.fail("Unable to authenticate with the newly generated root token.") def test_start_generate_root_then_cancel(self): test_otp = utils.get_generate_root_otp() - self.assertFalse(self.client.sys.read_root_generation_progress()['started']) + self.assertFalse(self.client.sys.read_root_generation_progress()["started"]) self.client.sys.start_root_token_generation( otp=test_otp, ) - self.assertTrue(self.client.sys.read_root_generation_progress()['started']) + self.assertTrue(self.client.sys.read_root_generation_progress()["started"]) self.client.sys.cancel_root_generation() - self.assertFalse(self.client.sys.read_root_generation_progress()['started']) + self.assertFalse(self.client.sys.read_root_generation_progress()["started"]) def test_rotate(self): status = self.client.key_status @@ -64,53 +63,55 @@ def test_rotate(self): self.client.sys.rotate_encryption_key() self.assertGreater( - self.client.key_status['term'], - status['term'], + self.client.key_status["term"], + status["term"], ) def test_rekey_multi(self): cls = type(self) - self.assertFalse(self.client.rekey_status['started']) + self.assertFalse(self.client.rekey_status["started"]) self.client.sys.start_rekey() - self.assertTrue(self.client.rekey_status['started']) + self.assertTrue(self.client.rekey_status["started"]) self.client.sys.cancel_rekey() - self.assertFalse(self.client.rekey_status['started']) + self.assertFalse(self.client.rekey_status["started"]) result = self.client.sys.start_rekey() keys = cls.manager.keys - result = self.client.sys.rekey_multi(keys, nonce=result['nonce']) - self.assertTrue(result['complete']) + result = self.client.sys.rekey_multi(keys, nonce=result["nonce"]) + self.assertTrue(result["complete"]) - cls.manager.keys = result['keys'] + cls.manager.keys = result["keys"] cls.manager.unseal() def test_rekey_verify_multi(self): cls = type(self) # Start rekey process with verification required and use operator keys - self.assertFalse(self.client.sys.read_rekey_progress()['started']) + self.assertFalse(self.client.sys.read_rekey_progress()["started"]) result = self.client.sys.start_rekey(require_verification=True) - result = self.client.sys.rekey_multi(cls.manager.keys, nonce=result['nonce']) - self.assertTrue(result['complete']) - cls.manager.keys = result['keys'] + result = self.client.sys.rekey_multi(cls.manager.keys, nonce=result["nonce"]) + self.assertTrue(result["complete"]) + cls.manager.keys = result["keys"] # get the initial verification nonce result = self.client.sys.read_rekey_verify_progress() - first_nonce = result['nonce'] + first_nonce = result["nonce"] # now cancel the process and verify we have a new verification nonce result = self.client.sys.cancel_rekey_verify() - second_nonce = result['nonce'] + second_nonce = result["nonce"] self.assertNotEqual(first_nonce, second_nonce) # finally complete the verification process - result = self.client.sys.rekey_verify_multi(cls.manager.keys, nonce=result['nonce']) - self.assertTrue(result['complete']) + result = self.client.sys.rekey_verify_multi( + cls.manager.keys, nonce=result["nonce"] + ) + self.assertTrue(result["complete"]) # now we unseal cls.manager.unseal() @@ -119,6 +120,6 @@ def test_get_backed_up_keys(self): with self.assertRaises(exceptions.InvalidRequest) as cm: self.client.sys.read_backup_keys() self.assertEqual( - first='no backed-up keys found', + first="no backed-up keys found", second=str(cm.exception), ) diff --git a/tests/integration_tests/api/system_backend/test_leader.py b/tests/integration_tests/api/system_backend/test_leader.py index 9be5ac79f..8bce3eff0 100644 --- a/tests/integration_tests/api/system_backend/test_leader.py +++ b/tests/integration_tests/api/system_backend/test_leader.py @@ -4,9 +4,8 @@ class TestLeader(HvacIntegrationTestCase, TestCase): - def test_read_health_status(self): self.assertIn( - member='ha_enabled', + member="ha_enabled", container=self.client.sys.read_leader_status(), ) diff --git a/tests/integration_tests/api/system_backend/test_lease.py b/tests/integration_tests/api/system_backend/test_lease.py index 969097c78..421f0c28a 100644 --- a/tests/integration_tests/api/system_backend/test_lease.py +++ b/tests/integration_tests/api/system_backend/test_lease.py @@ -7,7 +7,6 @@ class TestLease(HvacIntegrationTestCase, TestCase): - def setUp(self): super(TestLease, self).setUp() # Set up a test pki backend and issue a cert against some role so we. @@ -20,49 +19,49 @@ def tearDown(self): def test_read_lease(self): pki_issue_response = self.client.write( - path='pki/issue/my-role', - common_name='test.hvac.com', + path="pki/issue/my-role", + common_name="test.hvac.com", ) # Read the lease of our test cert that was just issued. read_lease_response = self.client.sys.read_lease( - lease_id=pki_issue_response['lease_id'], + lease_id=pki_issue_response["lease_id"], ) - logging.debug('read_lease_response: %s' % read_lease_response) + logging.debug("read_lease_response: %s" % read_lease_response) # Validate we received the expected lease ID back in our response. - self.assertEquals( - first=pki_issue_response['lease_id'], - second=read_lease_response['data']['id'], + self.assertEqual( + first=pki_issue_response["lease_id"], + second=read_lease_response["data"]["id"], ) def test_list_leases(self): self.client.write( - path='pki/issue/my-role', - common_name='test.hvac.com', + path="pki/issue/my-role", + common_name="test.hvac.com", ) # List the lease of our test cert that was just issued. list_leases_response = self.client.sys.list_leases( - prefix='pki', + prefix="pki", ) - logging.debug('list_leases_response: %s' % list_leases_response) + logging.debug("list_leases_response: %s" % list_leases_response) self.assertIn( - member='issue/', - container=list_leases_response['data']['keys'], + member="issue/", + container=list_leases_response["data"]["keys"], ) def test_revoke_lease(self): pki_issue_response = self.client.write( - path='pki/issue/my-role', - common_name='test.hvac.com', + path="pki/issue/my-role", + common_name="test.hvac.com", ) # Revoke the lease of our test cert that was just issued. revoke_lease_response = self.client.sys.revoke_lease( - lease_id=pki_issue_response['lease_id'], + lease_id=pki_issue_response["lease_id"], ) - logging.debug('revoke_lease_response: %s' % revoke_lease_response) + logging.debug("revoke_lease_response: %s" % revoke_lease_response) self.assertEqual( first=bool(revoke_lease_response), @@ -70,20 +69,20 @@ def test_revoke_lease(self): ) with self.assertRaises(exceptions.InvalidPath): self.client.sys.list_leases( - prefix='pki', + prefix="pki", ) def test_revoke_prefix(self): pki_issue_response = self.client.write( - path='pki/issue/my-role', - common_name='test.hvac.com', + path="pki/issue/my-role", + common_name="test.hvac.com", ) # Revoke the lease prefix of our test cert that was just issued. revoke_prefix_response = self.client.sys.revoke_prefix( - prefix=pki_issue_response['lease_id'], + prefix=pki_issue_response["lease_id"], ) - logging.debug('revoke_prefix_response: %s' % revoke_prefix_response) + logging.debug("revoke_prefix_response: %s" % revoke_prefix_response) self.assertEqual( first=bool(revoke_prefix_response), @@ -92,13 +91,15 @@ def test_revoke_prefix(self): def test_revoke_force(self): pki_issue_response = self.client.write( - path='pki/issue/my-role', - common_name='test.hvac.com', + path="pki/issue/my-role", + common_name="test.hvac.com", ) # Force revoke the lease of our test cert that was just issued. - revoke_force_response = self.client.sys.revoke_force(pki_issue_response['lease_id']) - logging.debug('revoke_force_response: %s' % revoke_force_response) + revoke_force_response = self.client.sys.revoke_force( + pki_issue_response["lease_id"] + ) + logging.debug("revoke_force_response: %s" % revoke_force_response) self.assertEqual( first=bool(revoke_force_response), diff --git a/tests/integration_tests/api/system_backend/test_mount.py b/tests/integration_tests/api/system_backend/test_mount.py index 8ed579f56..7a6113257 100644 --- a/tests/integration_tests/api/system_backend/test_mount.py +++ b/tests/integration_tests/api/system_backend/test_mount.py @@ -4,76 +4,76 @@ class TestMount(HvacIntegrationTestCase, TestCase): - TEST_KVV1_MOUNT_POINT = 'kvv1_mount' + TEST_KVV1_MOUNT_POINT = "kvv1_mount" def setUp(self): super(TestMount, self).setUp() - self.client.enable_secret_backend( - backend_type='kv', - mount_point=self.TEST_KVV1_MOUNT_POINT, + self.client.sys.enable_secrets_engine( + backend_type="kv", + path=self.TEST_KVV1_MOUNT_POINT, options=dict(version=1), ) def tearDown(self): - self.client.disable_secret_backend(mount_point=self.TEST_KVV1_MOUNT_POINT) + self.client.sys.disable_secrets_engine(path=self.TEST_KVV1_MOUNT_POINT) super(TestMount, self).tearDown() def test_secret_backend_manipulation(self): self.assertNotIn( - member='test/', - container=self.client.sys.list_mounted_secrets_engines()['data'], + member="test/", + container=self.client.sys.list_mounted_secrets_engines()["data"], ) self.client.sys.enable_secrets_engine( - backend_type='generic', - path='test', + backend_type="generic", + path="test", ) self.assertIn( - member='test/', - container=self.client.sys.list_mounted_secrets_engines()['data'], + member="test/", + container=self.client.sys.list_mounted_secrets_engines()["data"], ) - secret_backend_tuning = self.client.sys.read_mount_configuration(path='test') - self.assertEqual(secret_backend_tuning['data']['max_lease_ttl'], 2764800) - self.assertEqual(secret_backend_tuning['data']['default_lease_ttl'], 2764800) + secret_backend_tuning = self.client.sys.read_mount_configuration(path="test") + self.assertEqual(secret_backend_tuning["data"]["max_lease_ttl"], 2764800) + self.assertEqual(secret_backend_tuning["data"]["default_lease_ttl"], 2764800) self.client.sys.tune_mount_configuration( - path='test', - default_lease_ttl='3600s', - max_lease_ttl='8600s', + path="test", + default_lease_ttl="3600s", + max_lease_ttl="8600s", ) - secret_backend_tuning = self.client.sys.read_mount_configuration(path='test') + secret_backend_tuning = self.client.sys.read_mount_configuration(path="test") - self.assertIn('max_lease_ttl', secret_backend_tuning['data']) - self.assertEqual(secret_backend_tuning['data']['max_lease_ttl'], 8600) - self.assertIn('default_lease_ttl', secret_backend_tuning['data']) - self.assertEqual(secret_backend_tuning['data']['default_lease_ttl'], 3600) + self.assertIn("max_lease_ttl", secret_backend_tuning["data"]) + self.assertEqual(secret_backend_tuning["data"]["max_lease_ttl"], 8600) + self.assertIn("default_lease_ttl", secret_backend_tuning["data"]) + self.assertEqual(secret_backend_tuning["data"]["default_lease_ttl"], 3600) self.client.sys.move_backend( - from_path='test', - to_path='foobar', + from_path="test", + to_path="foobar", ) self.assertNotIn( - member='test/', - container=self.client.sys.list_mounted_secrets_engines()['data'], + member="test/", + container=self.client.sys.list_mounted_secrets_engines()["data"], ) self.assertIn( - member='foobar/', - container=self.client.sys.list_mounted_secrets_engines()['data'], + member="foobar/", + container=self.client.sys.list_mounted_secrets_engines()["data"], ) self.client.token = self.manager.root_token - self.client.sys.disable_secrets_engine( - path='foobar' - ) + self.client.sys.disable_secrets_engine(path="foobar") self.assertNotIn( - member='foobar/', - container=self.client.sys.list_mounted_secrets_engines()['data'], + member="foobar/", + container=self.client.sys.list_mounted_secrets_engines()["data"], ) def test_get_secret_backend_tuning(self): - secret_backend_tuning = self.client.sys.read_mount_configuration(path=self.TEST_KVV1_MOUNT_POINT) + secret_backend_tuning = self.client.sys.read_mount_configuration( + path=self.TEST_KVV1_MOUNT_POINT + ) self.assertIn( - member='default_lease_ttl', - container=secret_backend_tuning['data'], + member="default_lease_ttl", + container=secret_backend_tuning["data"], ) diff --git a/tests/integration_tests/api/system_backend/test_namespace.py b/tests/integration_tests/api/system_backend/test_namespace.py index 622684511..ba971568e 100644 --- a/tests/integration_tests/api/system_backend/test_namespace.py +++ b/tests/integration_tests/api/system_backend/test_namespace.py @@ -7,16 +7,17 @@ @skipIf(not utils.is_enterprise(), "Namespaces only supported with Enterprise Vault") class TestNamespace(HvacIntegrationTestCase, TestCase): - def test_list_namespaces(self): - test_namespace_name = 'python-hvac' - create_namespace_response = self.client.sys.create_namespace(path=test_namespace_name) - logging.debug('create_namespace_response: %s' % create_namespace_response) + test_namespace_name = "python-hvac" + create_namespace_response = self.client.sys.create_namespace( + path=test_namespace_name + ) + logging.debug("create_namespace_response: %s" % create_namespace_response) # Verify the namespace we just created is retrievable in a listing. list_namespaces_response = self.client.sys.list_namespaces() - logging.debug('list_namespaces_response: %s' % list_namespaces_response) + logging.debug("list_namespaces_response: %s" % list_namespaces_response) self.assertIn( - member='%s/' % test_namespace_name, - container=list_namespaces_response['data']['keys'], + member="%s/" % test_namespace_name, + container=list_namespaces_response["data"]["keys"], ) diff --git a/tests/integration_tests/api/system_backend/test_policy.py b/tests/integration_tests/api/system_backend/test_policy.py index 3be7e8fd4..13ceba5ae 100644 --- a/tests/integration_tests/api/system_backend/test_policy.py +++ b/tests/integration_tests/api/system_backend/test_policy.py @@ -8,9 +8,12 @@ from tests.utils.hvac_integration_test_case import HvacIntegrationTestCase -@skipIf(utils.vault_version_lt('0.9.0'), "Policy class uses new parameters added >= Vault 0.9.0") +@skipIf( + utils.vault_version_lt("0.9.0"), + "Policy class uses new parameters added >= Vault 0.9.0", +) class TestPolicy(HvacIntegrationTestCase, TestCase): - TEST_POLICY_NAME = 'test-policy-policy' + TEST_POLICY_NAME = "test-policy-policy" def tearDown(self): self.client.sys.delete_policy( @@ -18,21 +21,26 @@ def tearDown(self): ) super(TestPolicy, self).tearDown() - @parameterized.expand([ - param( - 'success', - ), - param( - 'pretty print false', - pretty_print=False, - ), - ]) - @skipIf(utils.vault_version_eq('0.11.0'), "Policy parsing broken in Vault version 0.11.0") + @parameterized.expand( + [ + param( + "success", + ), + param( + "pretty print false", + pretty_print=False, + ), + ] + ) + @skipIf( + utils.vault_version_eq("0.11.0"), + "Policy parsing broken in Vault version 0.11.0", + ) def test_create_or_update_policy(self, label, pretty_print=True): test_policy = { - 'path': { - 'test-path': { - 'capabilities': ['read'], + "path": { + "test-path": { + "capabilities": ["read"], }, }, } @@ -41,7 +49,7 @@ def test_create_or_update_policy(self, label, pretty_print=True): policy=test_policy, pretty_print=pretty_print, ) - logging.debug('create_policy_response: %s' % create_policy_response) + logging.debug("create_policy_response: %s" % create_policy_response) self.assertEqual( first=bool(create_policy_response), second=True, @@ -50,59 +58,59 @@ def test_create_or_update_policy(self, label, pretty_print=True): read_policy_response = self.client.sys.read_policy( name=self.TEST_POLICY_NAME, ) - logging.debug('read_policy_response: %s' % read_policy_response) + logging.debug("read_policy_response: %s" % read_policy_response) self.assertDictEqual( - d1=json.loads(read_policy_response['data']['rules']), + d1=json.loads(read_policy_response["data"]["rules"]), d2=test_policy, ) def test_policy_manipulation(self): self.assertIn( - member='root', - container=self.client.sys.list_policies()['data']['policies'], + member="root", + container=self.client.sys.list_policies()["data"]["policies"], ) - self.assertIsNone(self.client.get_policy('test')) - policy, parsed_policy = self.prep_policy('test') + self.assertIsNone(self.client.get_policy("test")) + policy, parsed_policy = self.prep_policy("test") self.assertIn( - member='test', - container=self.client.sys.list_policies()['data']['policies'], + member="test", + container=self.client.sys.list_policies()["data"]["policies"], ) - self.assertEqual(policy, self.client.sys.read_policy('test')['data']['rules']) - self.assertEqual(parsed_policy, self.client.get_policy('test', parse=True)) + self.assertEqual(policy, self.client.sys.read_policy("test")["data"]["rules"]) + self.assertEqual(parsed_policy, self.client.get_policy("test", parse=True)) self.client.sys.delete_policy( - name='test', + name="test", ) self.assertNotIn( - member='test', - container=self.client.sys.list_policies()['data']['policies'], + member="test", + container=self.client.sys.list_policies()["data"]["policies"], ) def test_json_policy_manipulation(self): self.assertIn( - member='root', - container=self.client.sys.list_policies()['data']['policies'], + member="root", + container=self.client.sys.list_policies()["data"]["policies"], ) - policy = ''' + policy = """ path "sys" { policy = "deny" } path "secret" { policy = "write" } - ''' + """ self.client.sys.create_or_update_policy( - name='test', + name="test", policy=policy, ) self.assertIn( - member='test', - container=self.client.sys.list_policies()['data']['policies'], + member="test", + container=self.client.sys.list_policies()["data"]["policies"], ) - self.client.delete_policy('test') + self.client.sys.delete_policy("test") self.assertNotIn( - member='test', - container=self.client.sys.list_policies()['data']['policies'], + member="test", + container=self.client.sys.list_policies()["data"]["policies"], ) diff --git a/tests/integration_tests/api/system_backend/test_seal.py b/tests/integration_tests/api/system_backend/test_seal.py index 575b8dc97..6f2fd128f 100644 --- a/tests/integration_tests/api/system_backend/test_seal.py +++ b/tests/integration_tests/api/system_backend/test_seal.py @@ -4,7 +4,6 @@ class TestSeal(HvacIntegrationTestCase, TestCase): - def test_unseal_multi(self): cls = type(self) @@ -14,17 +13,17 @@ def test_unseal_multi(self): result = self.client.sys.submit_unseal_keys(keys[0:2]) - self.assertTrue(result['sealed']) - self.assertEqual(result['progress'], 2) + self.assertTrue(result["sealed"]) + self.assertEqual(result["progress"], 2) result = self.client.sys.submit_unseal_key(reset=True) - self.assertEqual(result['progress'], 0) + self.assertEqual(result["progress"], 0) result = self.client.sys.submit_unseal_keys(keys[1:3]) - self.assertTrue(result['sealed']) - self.assertEqual(result['progress'], 2) + self.assertTrue(result["sealed"]) + self.assertEqual(result["progress"], 2) self.client.sys.submit_unseal_keys(keys[0:1]) result = self.client.sys.submit_unseal_keys(keys[2:3]) - self.assertFalse(result['sealed']) + self.assertFalse(result["sealed"]) def test_seal_unseal(self): cls = type(self) diff --git a/tests/integration_tests/api/system_backend/test_wrapping.py b/tests/integration_tests/api/system_backend/test_wrapping.py index f785c0a5e..1b20ecb83 100644 --- a/tests/integration_tests/api/system_backend/test_wrapping.py +++ b/tests/integration_tests/api/system_backend/test_wrapping.py @@ -5,8 +5,8 @@ class TestWrapping(HvacIntegrationTestCase, TestCase): - TEST_AUTH_METHOD_TYPE = 'approle' - TEST_AUTH_METHOD_PATH = 'test-approle' + TEST_AUTH_METHOD_TYPE = "approle" + TEST_AUTH_METHOD_PATH = "test-approle" def setUp(self): super(TestWrapping, self).setUp() @@ -20,20 +20,14 @@ def test_unwrap(self): path="auth/{path}/role/testrole".format(path=self.TEST_AUTH_METHOD_PATH), ) result = self.client.write( - path='auth/{path}/role/testrole/secret-id'.format( + path="auth/{path}/role/testrole/secret-id".format( path=self.TEST_AUTH_METHOD_PATH ), wrap_ttl="10s", ) - self.assertIn('token', result['wrap_info']) + self.assertIn("token", result["wrap_info"]) - unwrap_response = self.client.sys.unwrap(result['wrap_info']['token']) - logging.debug('unwrap_response: %s' % unwrap_response) - self.assertIn( - member='secret_id_accessor', - container=unwrap_response['data'] - ) - self.assertIn( - member='secret_id', - container=unwrap_response['data'] - ) + unwrap_response = self.client.sys.unwrap(result["wrap_info"]["token"]) + logging.debug("unwrap_response: %s" % unwrap_response) + self.assertIn(member="secret_id_accessor", container=unwrap_response["data"]) + self.assertIn(member="secret_id", container=unwrap_response["data"]) diff --git a/tests/integration_tests/v1/test_approle.py b/tests/integration_tests/v1/test_approle.py index b5f8b7c71..52fa54a89 100644 --- a/tests/integration_tests/v1/test_approle.py +++ b/tests/integration_tests/v1/test_approle.py @@ -8,126 +8,139 @@ class TestApprole(HvacIntegrationTestCase, TestCase): - TEST_MOUNT_POINT = 'approle' + TEST_MOUNT_POINT = "approle" def setUp(self): super(TestApprole, self).setUp() - self.client.enable_auth_backend( - backend_type='approle', - mount_point=self.TEST_MOUNT_POINT, + self.client.sys.enable_auth_method( + method_type="approle", + path=self.TEST_MOUNT_POINT, ) def tearDown(self): self.client.token = self.manager.root_token - self.client.disable_auth_backend(mount_point=self.TEST_MOUNT_POINT) + self.client.sys.disable_auth_method(path=self.TEST_MOUNT_POINT) super(TestApprole, self).tearDown() - @parameterized.expand([ - param( - 'no secret ids', - num_secrets_to_create=0, - raises=exceptions.InvalidPath, - ), - param( - 'one secret id', - num_secrets_to_create=1, - ), - param( - 'two secret ids', - num_secrets_to_create=2, - ), - ]) + @parameterized.expand( + [ + param( + "no secret ids", + num_secrets_to_create=0, + raises=exceptions.InvalidPath, + ), + param( + "one secret id", + num_secrets_to_create=1, + ), + param( + "two secret ids", + num_secrets_to_create=2, + ), + ] + ) def test_list_role_secrets(self, label, num_secrets_to_create=0, raises=None): - test_role_name = 'testrole' - self.client.create_role( + test_role_name = "testrole" + self.client.auth.approle.create_or_update_approle( role_name=test_role_name, mount_point=self.TEST_MOUNT_POINT, ) for _ in range(0, num_secrets_to_create): - self.client.create_role_secret_id( + self.client.auth.approle.generate_secret_id( role_name=test_role_name, mount_point=self.TEST_MOUNT_POINT, ) if raises: with self.assertRaises(raises): - self.client.list_role_secrets( + self.client.auth.approle.list_secret_id_accessors( role_name=test_role_name, mount_point=self.TEST_MOUNT_POINT, ) else: - list_role_secrets_response = self.client.list_role_secrets( - role_name=test_role_name, - mount_point=self.TEST_MOUNT_POINT, + list_role_secrets_response = ( + self.client.auth.approle.list_secret_id_accessors( + role_name=test_role_name, + mount_point=self.TEST_MOUNT_POINT, + ) ) - logging.debug('list_role_secrets_response: %s' % list_role_secrets_response) + logging.debug("list_role_secrets_response: %s" % list_role_secrets_response) self.assertEqual( first=num_secrets_to_create, - second=len(list_role_secrets_response['data']['keys']) + second=len(list_role_secrets_response["data"]["keys"]), ) def test_create_role(self): - self.client.create_role('testrole') + self.client.auth.approle.create_or_update_approle("testrole") - result = self.client.read('auth/approle/role/testrole') - lib_result = self.client.get_role('testrole') - del result['request_id'] - del lib_result['request_id'] + result = self.client.read("auth/approle/role/testrole") + lib_result = self.client.auth.approle.read_role("testrole") + del result["request_id"] + del lib_result["request_id"] self.assertEqual(result, lib_result) def test_delete_role(self): - test_role_name = 'test-role' + test_role_name = "test-role" - self.client.create_role(test_role_name) + self.client.auth.approle.create_or_update_approle(test_role_name) # We add a second dummy test role so we can still hit the /role?list=true route after deleting the first role - self.client.create_role('test-role-2') + self.client.auth.approle.create_or_update_approle("test-role-2") # Ensure our created role shows up when calling list_roles as expected - result = self.client.list_roles() - actual_list_role_keys = result['data']['keys'] + result = self.client.auth.approle.list_roles() + actual_list_role_keys = result["data"]["keys"] self.assertIn( member=test_role_name, container=actual_list_role_keys, ) # Now delete the role and verify its absence when calling list_roles - self.client.delete_role(test_role_name) - result = self.client.list_roles() - actual_list_role_keys = result['data']['keys'] + self.client.auth.approle.delete_role(test_role_name) + result = self.client.auth.approle.list_roles() + actual_list_role_keys = result["data"]["keys"] self.assertNotIn( member=test_role_name, container=actual_list_role_keys, ) def test_create_delete_role_secret_id(self): - self.client.create_role('testrole') - create_result = self.client.create_role_secret_id('testrole', {'foo': 'bar'}) - secret_id = create_result['data']['secret_id'] - result = self.client.get_role_secret_id('testrole', secret_id) - self.assertEqual(result['data']['metadata']['foo'], 'bar') - self.client.delete_role_secret_id('testrole', secret_id) - missing_secret_response = self.client.get_role_secret_id('testrole', secret_id) - self.assertEquals( + self.client.auth.approle.create_or_update_approle("testrole") + create_result = self.client.auth.approle.generate_secret_id( + "testrole", {"foo": "bar"} + ) + secret_id = create_result["data"]["secret_id"] + result = self.client.auth.approle.read_secret_id("testrole", secret_id) + self.assertEqual(result["data"]["metadata"]["foo"], "bar") + self.client.auth.approle.destroy_secret_id("testrole", secret_id) + missing_secret_response = self.client.auth.approle.read_secret_id( + "testrole", secret_id + ) + self.assertEqual( first=missing_secret_response.status_code, second=204, ) def test_auth_approle(self): - self.client.create_role('testrole') - create_result = self.client.create_role_secret_id('testrole', {'foo': 'bar'}) - secret_id = create_result['data']['secret_id'] - role_id = self.client.get_role_id('testrole') - result = self.client.auth_approle(role_id, secret_id) - self.assertEqual(result['auth']['metadata']['foo'], 'bar') - self.assertEqual(self.client.token, result['auth']['client_token']) + self.client.auth.approle.create_or_update_approle("testrole") + create_result = self.client.auth.approle.generate_secret_id( + "testrole", {"foo": "bar"} + ) + secret_id = create_result["data"]["secret_id"] + role_id = self.client.auth.approle.read_role_id("testrole")["data"]["role_id"] + logging.debug("role_id: %s" % role_id) + result = self.client.auth.approle.login(role_id, secret_id) + self.assertEqual(result["auth"]["metadata"]["foo"], "bar") + self.assertEqual(self.client.token, result["auth"]["client_token"]) self.assertTrue(self.client.is_authenticated()) def test_auth_approle_dont_use_token(self): - self.client.create_role('testrole') - create_result = self.client.create_role_secret_id('testrole', {'foo': 'bar'}) - secret_id = create_result['data']['secret_id'] - role_id = self.client.get_role_id('testrole') - result = self.client.auth_approle(role_id, secret_id, use_token=False) - self.assertEqual(result['auth']['metadata']['foo'], 'bar') - self.assertNotEqual(self.client.token, result['auth']['client_token']) + self.client.auth.approle.create_or_update_approle("testrole") + create_result = self.client.auth.approle.generate_secret_id( + "testrole", {"foo": "bar"} + ) + secret_id = create_result["data"]["secret_id"] + role_id = self.client.auth.approle.read_role_id("testrole")["data"]["role_id"] + result = self.client.auth.approle.login(role_id, secret_id, use_token=False) + self.assertEqual(result["auth"]["metadata"]["foo"], "bar") + self.assertNotEqual(self.client.token, result["auth"]["client_token"]) diff --git a/tests/integration_tests/v1/test_integration.py b/tests/integration_tests/v1/test_integration.py index 9790de44f..fe071c2db 100644 --- a/tests/integration_tests/v1/test_integration.py +++ b/tests/integration_tests/v1/test_integration.py @@ -7,66 +7,65 @@ class IntegrationTest(HvacIntegrationTestCase, TestCase): - def setUp(self): super(IntegrationTest, self).setUp() - if 'secret/' not in self.client.sys.list_mounted_secrets_engines()['data']: - self.client.enable_secret_backend( - backend_type='kv', - mount_point='secret', + if "secret/" not in self.client.sys.list_mounted_secrets_engines()["data"]: + self.client.sys.enable_secrets_engine( + backend_type="kv", + path="secret", options=dict(version=1), ) def test_generic_secret_backend(self): - self.client.write('secret/foo', zap='zip') - result = self.client.read('secret/foo') + self.client.write("secret/foo", zap="zip") + result = self.client.read("secret/foo") - assert result['data']['zap'] == 'zip' + assert result["data"]["zap"] == "zip" - self.client.delete('secret/foo') + self.client.delete("secret/foo") def test_list_directory(self): - self.client.write('secret/test-list/bar/foo', value='bar') - self.client.write('secret/test-list/foo', value='bar') - result = self.client.list('secret/test-list') + self.client.write("secret/test-list/bar/foo", value="bar") + self.client.write("secret/test-list/foo", value="bar") + result = self.client.list("secret/test-list") - assert result['data']['keys'] == ['bar/', 'foo'] + assert result["data"]["keys"] == ["bar/", "foo"] - self.client.delete('secret/test-list/bar/foo') - self.client.delete('secret/test-list/foo') + self.client.delete("secret/test-list/bar/foo") + self.client.delete("secret/test-list/foo") def test_write_with_response(self): - if 'transit/' in self.client.list_secret_backends()['data']: - self.client.disable_secret_backend('transit') - self.client.enable_secret_backend('transit') + if "transit/" in self.client.sys.list_mounted_secrets_engines()["data"]: + self.client.sys.disable_secrets_engine("transit") + self.client.sys.enable_secrets_engine("transit") - plaintext = 'test' + plaintext = "test" - self.client.write('transit/keys/foo') + self.client.write("transit/keys/foo") - result = self.client.write('transit/encrypt/foo', plaintext=plaintext) - ciphertext = result['data']['ciphertext'] + result = self.client.write("transit/encrypt/foo", plaintext=plaintext) + ciphertext = result["data"]["ciphertext"] - result = self.client.write('transit/decrypt/foo', ciphertext=ciphertext) - assert result['data']['plaintext'] == plaintext + result = self.client.write("transit/decrypt/foo", ciphertext=ciphertext) + assert result["data"]["plaintext"] == plaintext def test_read_nonexistent_key(self): - assert not self.client.read('secret/I/dont/exist') + assert not self.client.read("secret/I/dont/exist") def test_auth_token_manipulation(self): - result = self.client.create_token(lease='1h', renewable=True) - assert result['auth']['client_token'] + result = self.client.create_token(lease="1h", renewable=True) + assert result["auth"]["client_token"] - lookup = self.client.lookup_token(result['auth']['client_token']) - assert result['auth']['client_token'] == lookup['data']['id'] + lookup = self.client.lookup_token(result["auth"]["client_token"]) + assert result["auth"]["client_token"] == lookup["data"]["id"] - renew = self.client.renew_token(lookup['data']['id']) - assert result['auth']['client_token'] == renew['auth']['client_token'] + renew = self.client.renew_token(lookup["data"]["id"]) + assert result["auth"]["client_token"] == renew["auth"]["client_token"] - self.client.revoke_token(lookup['data']['id']) + self.client.revoke_token(lookup["data"]["id"]) try: - lookup = self.client.lookup_token(result['auth']['client_token']) + lookup = self.client.lookup_token(result["auth"]["client_token"]) assert False except exceptions.Forbidden: assert True @@ -76,20 +75,20 @@ def test_auth_token_manipulation(self): assert True def test_self_auth_token_manipulation(self): - result = self.client.create_token(lease='1h', renewable=True) - assert result['auth']['client_token'] - self.client.token = result['auth']['client_token'] + result = self.client.create_token(lease="1h", renewable=True) + assert result["auth"]["client_token"] + self.client.token = result["auth"]["client_token"] - lookup = self.client.lookup_token(result['auth']['client_token']) - assert result['auth']['client_token'] == lookup['data']['id'] + lookup = self.client.lookup_token(result["auth"]["client_token"]) + assert result["auth"]["client_token"] == lookup["data"]["id"] renew = self.client.renew_self_token() - assert result['auth']['client_token'] == renew['auth']['client_token'] + assert result["auth"]["client_token"] == renew["auth"]["client_token"] - self.client.revoke_token(lookup['data']['id']) + self.client.revoke_token(lookup["data"]["id"]) try: - lookup = self.client.lookup_token(result['auth']['client_token']) + lookup = self.client.lookup_token(result["auth"]["client_token"]) assert False except exceptions.Forbidden: assert True @@ -99,373 +98,231 @@ def test_self_auth_token_manipulation(self): assert True def test_userpass_auth(self): - if 'userpass/' in self.client.list_auth_backends()['data']: - self.client.disable_auth_backend('userpass') + if "userpass/" in self.client.sys.list_auth_methods()["data"]: + self.client.sys.disable_auth_method("userpass") - self.client.enable_auth_backend('userpass') + self.client.sys.enable_auth_method("userpass") - self.client.write('auth/userpass/users/testuser', password='testpass', policies='not_root') + self.client.write( + "auth/userpass/users/testuser", password="testpass", policies="not_root" + ) - result = self.client.auth_userpass('testuser', 'testpass') + result = self.client.auth_userpass("testuser", "testpass") - assert self.client.token == result['auth']['client_token'] + assert self.client.token == result["auth"]["client_token"] assert self.client.is_authenticated() self.client.token = self.manager.root_token - self.client.disable_auth_backend('userpass') + self.client.sys.disable_auth_method("userpass") def test_create_userpass(self): - if 'userpass/' not in self.client.list_auth_backends()['data']: - self.client.enable_auth_backend('userpass') + if "userpass/" not in self.client.sys.list_auth_methods()["data"]: + self.client.sys.enable_auth_method("userpass") - self.client.create_userpass('testcreateuser', 'testcreateuserpass', policies='not_root') + self.client.create_userpass( + "testcreateuser", "testcreateuserpass", policies="not_root" + ) - result = self.client.auth_userpass('testcreateuser', 'testcreateuserpass') + result = self.client.auth_userpass("testcreateuser", "testcreateuserpass") - assert self.client.token == result['auth']['client_token'] + assert self.client.token == result["auth"]["client_token"] assert self.client.is_authenticated() # Test ttl: self.client.token = self.manager.root_token - self.client.create_userpass('testcreateuser', 'testcreateuserpass', policies='not_root', ttl='10s') - self.client.token = result['auth']['client_token'] + self.client.create_userpass( + "testcreateuser", "testcreateuserpass", policies="not_root", ttl="10s" + ) + self.client.token = result["auth"]["client_token"] - result = self.client.auth_userpass('testcreateuser', 'testcreateuserpass') + result = self.client.auth_userpass("testcreateuser", "testcreateuserpass") - assert result['auth']['lease_duration'] == 10 + assert result["auth"]["lease_duration"] == 10 self.client.token = self.manager.root_token - self.client.disable_auth_backend('userpass') + self.client.sys.disable_auth_method("userpass") def test_list_userpass(self): - if 'userpass/' not in self.client.list_auth_backends()['data']: - self.client.enable_auth_backend('userpass') + if "userpass/" not in self.client.sys.list_auth_methods()["data"]: + self.client.sys.enable_auth_method("userpass") # add some users and confirm that they show up in the list - self.client.create_userpass('testuserone', 'testuseronepass', policies='not_root') - self.client.create_userpass('testusertwo', 'testusertwopass', policies='not_root') + self.client.create_userpass( + "testuserone", "testuseronepass", policies="not_root" + ) + self.client.create_userpass( + "testusertwo", "testusertwopass", policies="not_root" + ) user_list = self.client.list_userpass() - assert 'testuserone' in user_list['data']['keys'] - assert 'testusertwo' in user_list['data']['keys'] + assert "testuserone" in user_list["data"]["keys"] + assert "testusertwo" in user_list["data"]["keys"] # delete all the users and confirm that list_userpass() doesn't fail - for user in user_list['data']['keys']: + for user in user_list["data"]["keys"]: self.client.delete_userpass(user) no_users_list = self.client.list_userpass() assert no_users_list is None def test_read_userpass(self): - if 'userpass/' not in self.client.list_auth_backends()['data']: - self.client.enable_auth_backend('userpass') + if "userpass/" not in self.client.sys.list_auth_methods()["data"]: + self.client.sys.enable_auth_method("userpass") # create user to read - self.client.create_userpass('readme', 'mypassword', policies='not_root') + self.client.create_userpass("readme", "mypassword", policies="not_root") # test that user can be read - read_user = self.client.read_userpass('readme') - assert 'not_root' in read_user['data']['policies'] + read_user = self.client.read_userpass("readme") + assert "not_root" in read_user["data"]["policies"] # teardown - self.client.disable_auth_backend('userpass') + self.client.sys.disable_auth_method("userpass") def test_update_userpass_policies(self): - if 'userpass/' not in self.client.list_auth_backends()['data']: - self.client.enable_auth_backend('userpass') + if "userpass/" not in self.client.sys.list_auth_methods()["data"]: + self.client.sys.enable_auth_method("userpass") # create user and then update its policies - self.client.create_userpass('updatemypolicies', 'mypassword', policies='not_root') - self.client.update_userpass_policies('updatemypolicies', policies='somethingelse') + self.client.create_userpass( + "updatemypolicies", "mypassword", policies="not_root" + ) + self.client.update_userpass_policies( + "updatemypolicies", policies="somethingelse" + ) # test that policies have changed - updated_user = self.client.read_userpass('updatemypolicies') - assert 'somethingelse' in updated_user['data']['policies'] + updated_user = self.client.read_userpass("updatemypolicies") + assert "somethingelse" in updated_user["data"]["policies"] # teardown - self.client.disable_auth_backend('userpass') + self.client.sys.disable_auth_method("userpass") def test_update_userpass_password(self): - if 'userpass/' not in self.client.list_auth_backends()['data']: - self.client.enable_auth_backend('userpass') + if "userpass/" not in self.client.sys.list_auth_methods()["data"]: + self.client.sys.enable_auth_method("userpass") # create user and then change its password - self.client.create_userpass('changeme', 'mypassword', policies='not_root') - self.client.update_userpass_password('changeme', 'mynewpassword') + self.client.create_userpass("changeme", "mypassword", policies="not_root") + self.client.update_userpass_password("changeme", "mynewpassword") # test that new password authenticates user - result = self.client.auth_userpass('changeme', 'mynewpassword') - assert self.client.token == result['auth']['client_token'] + result = self.client.auth_userpass("changeme", "mynewpassword") + assert self.client.token == result["auth"]["client_token"] assert self.client.is_authenticated() # teardown self.client.token = self.manager.root_token - self.client.disable_auth_backend('userpass') + self.client.sys.disable_auth_method("userpass") def test_delete_userpass(self): - if 'userpass/' not in self.client.list_auth_backends()['data']: - self.client.enable_auth_backend('userpass') + if "userpass/" not in self.client.sys.list_auth_methods()["data"]: + self.client.sys.enable_auth_method("userpass") - self.client.create_userpass('testcreateuser', 'testcreateuserpass', policies='not_root') + self.client.create_userpass( + "testcreateuser", "testcreateuserpass", policies="not_root" + ) - result = self.client.auth_userpass('testcreateuser', 'testcreateuserpass') + result = self.client.auth_userpass("testcreateuser", "testcreateuserpass") - assert self.client.token == result['auth']['client_token'] + assert self.client.token == result["auth"]["client_token"] assert self.client.is_authenticated() self.client.token = self.manager.root_token - self.client.delete_userpass('testcreateuser') - self.assertRaises(exceptions.InvalidRequest, self.client.auth_userpass, 'testcreateuser', 'testcreateuserpass') + self.client.delete_userpass("testcreateuser") + self.assertRaises( + exceptions.InvalidRequest, + self.client.auth_userpass, + "testcreateuser", + "testcreateuserpass", + ) def test_app_id_auth(self): - if 'app-id/' in self.client.list_auth_backends()['data']: - self.client.disable_auth_backend('app-id') + if "app-id/" in self.client.sys.list_auth_methods()["data"]: + self.client.sys.disable_auth_method("app-id") - self.client.enable_auth_backend('app-id') + self.client.sys.enable_auth_method("app-id") - self.client.write('auth/app-id/map/app-id/foo', value='not_root') - self.client.write('auth/app-id/map/user-id/bar', value='foo') + self.client.write("auth/app-id/map/app-id/foo", value="not_root") + self.client.write("auth/app-id/map/user-id/bar", value="foo") - result = self.client.auth_app_id('foo', 'bar') + result = self.client.auth_app_id("foo", "bar") - assert self.client.token == result['auth']['client_token'] + assert self.client.token == result["auth"]["client_token"] assert self.client.is_authenticated() self.client.token = self.manager.root_token - self.client.disable_auth_backend('app-id') + self.client.sys.disable_auth_method("app-id") def test_create_app_id(self): - if 'app-id/' not in self.client.list_auth_backends()['data']: - self.client.enable_auth_backend('app-id') + if "app-id/" not in self.client.sys.list_auth_methods()["data"]: + self.client.sys.enable_auth_method("app-id") - self.client.create_app_id('testappid', policies='not_root', display_name='displayname') + self.client.create_app_id( + "testappid", policies="not_root", display_name="displayname" + ) - result = self.client.read('auth/app-id/map/app-id/testappid') - lib_result = self.client.get_app_id('testappid') - del result['request_id'] - del lib_result['request_id'] + result = self.client.read("auth/app-id/map/app-id/testappid") + lib_result = self.client.get_app_id("testappid") + del result["request_id"] + del lib_result["request_id"] assert result == lib_result - assert result['data']['key'] == 'testappid' - assert result['data']['display_name'] == 'displayname' - assert result['data']['value'] == 'not_root' - self.client.delete_app_id('testappid') - assert self.client.get_app_id('testappid')['data'] is None + assert result["data"]["key"] == "testappid" + assert result["data"]["display_name"] == "displayname" + assert result["data"]["value"] == "not_root" + self.client.delete_app_id("testappid") + assert self.client.get_app_id("testappid")["data"] is None self.client.token = self.manager.root_token - self.client.disable_auth_backend('app-id') + self.client.sys.disable_auth_method("app-id") def test_create_user_id(self): - if 'app-id/' not in self.client.list_auth_backends()['data']: - self.client.enable_auth_backend('app-id') + if "app-id/" not in self.client.sys.list_auth_methods()["data"]: + self.client.sys.enable_auth_method("app-id") - self.client.create_app_id('testappid', policies='not_root', display_name='displayname') - self.client.create_user_id('testuserid', app_id='testappid') + self.client.create_app_id( + "testappid", policies="not_root", display_name="displayname" + ) + self.client.create_user_id("testuserid", app_id="testappid") - result = self.client.read('auth/app-id/map/user-id/testuserid') - lib_result = self.client.get_user_id('testuserid') - del result['request_id'] - del lib_result['request_id'] + result = self.client.read("auth/app-id/map/user-id/testuserid") + lib_result = self.client.get_user_id("testuserid") + del result["request_id"] + del lib_result["request_id"] assert result == lib_result - assert result['data']['key'] == 'testuserid' - assert result['data']['value'] == 'testappid' + assert result["data"]["key"] == "testuserid" + assert result["data"]["value"] == "testappid" - result = self.client.auth_app_id('testappid', 'testuserid') + result = self.client.auth_app_id("testappid", "testuserid") - assert self.client.token == result['auth']['client_token'] + assert self.client.token == result["auth"]["client_token"] assert self.client.is_authenticated() self.client.token = self.manager.root_token - self.client.delete_user_id('testuserid') - assert self.client.get_user_id('testuserid')['data'] is None + self.client.delete_user_id("testuserid") + assert self.client.get_user_id("testuserid")["data"] is None self.client.token = self.manager.root_token - self.client.disable_auth_backend('app-id') - - def test_transit_read_write(self): - if 'transit/' in self.client.list_secret_backends()['data']: - self.client.disable_secret_backend('transit') - self.client.enable_secret_backend('transit') - - self.client.transit_create_key('foo') - result = self.client.transit_read_key('foo') - assert not result['data']['exportable'] - - self.client.transit_create_key('foo_export', exportable=True, key_type="ed25519") - result = self.client.transit_read_key('foo_export') - assert result['data']['exportable'] - assert result['data']['type'] == 'ed25519' - - self.client.enable_secret_backend('transit', mount_point='bar') - self.client.transit_create_key('foo', mount_point='bar') - result = self.client.transit_read_key('foo', mount_point='bar') - assert not result['data']['exportable'] - - def test_transit_list_keys(self): - if 'transit/' in self.client.list_secret_backends()['data']: - self.client.disable_secret_backend('transit') - self.client.enable_secret_backend('transit') - - self.client.transit_create_key('foo1') - self.client.transit_create_key('foo2') - self.client.transit_create_key('foo3') - - result = self.client.transit_list_keys() - assert result['data']['keys'] == ["foo1", "foo2", "foo3"] - - def test_transit_update_delete_keys(self): - if 'transit/' in self.client.list_secret_backends()['data']: - self.client.disable_secret_backend('transit') - self.client.enable_secret_backend('transit') - - self.client.transit_create_key('foo') - self.client.transit_update_key('foo', deletion_allowed=True) - result = self.client.transit_read_key('foo') - assert result['data']['deletion_allowed'] - - self.client.transit_delete_key('foo') - - try: - self.client.transit_read_key('foo') - except exceptions.InvalidPath: - assert True - else: - assert False - - def test_transit_rotate_key(self): - if 'transit/' in self.client.list_secret_backends()['data']: - self.client.disable_secret_backend('transit') - self.client.enable_secret_backend('transit') - - self.client.transit_create_key('foo') - - self.client.transit_rotate_key('foo') - response = self.client.transit_read_key('foo') - assert '2' in response['data']['keys'] - - self.client.transit_rotate_key('foo') - response = self.client.transit_read_key('foo') - assert '3' in response['data']['keys'] - - def test_transit_export_key(self): - if 'transit/' in self.client.list_secret_backends()['data']: - self.client.disable_secret_backend('transit') - self.client.enable_secret_backend('transit') - - self.client.transit_create_key('foo', exportable=True) - response = self.client.transit_export_key('foo', key_type='encryption-key') - assert response is not None - - def test_transit_encrypt_data(self): - if 'transit/' in self.client.list_secret_backends()['data']: - self.client.disable_secret_backend('transit') - self.client.enable_secret_backend('transit') - - self.client.transit_create_key('foo') - ciphertext_resp = self.client.transit_encrypt_data('foo', 'abbaabba')['data']['ciphertext'] - plaintext_resp = self.client.transit_decrypt_data('foo', ciphertext_resp)['data']['plaintext'] - assert plaintext_resp == 'abbaabba' - - def test_transit_rewrap_data(self): - if 'transit/' in self.client.list_secret_backends()['data']: - self.client.disable_secret_backend('transit') - self.client.enable_secret_backend('transit') - - self.client.transit_create_key('foo') - ciphertext_resp = self.client.transit_encrypt_data('foo', 'abbaabba')['data']['ciphertext'] - - self.client.transit_rotate_key('foo') - response_wrap = self.client.transit_rewrap_data('foo', ciphertext=ciphertext_resp)['data']['ciphertext'] - plaintext_resp = self.client.transit_decrypt_data('foo', response_wrap)['data']['plaintext'] - assert plaintext_resp == 'abbaabba' - - def test_transit_generate_data_key(self): - if 'transit/' in self.client.list_secret_backends()['data']: - self.client.disable_secret_backend('transit') - self.client.enable_secret_backend('transit') - - self.client.transit_create_key('foo') - - response_plaintext = self.client.transit_generate_data_key('foo', key_type='plaintext')['data']['plaintext'] - assert response_plaintext - - response_ciphertext = self.client.transit_generate_data_key('foo', key_type='wrapped')['data'] - assert 'ciphertext' in response_ciphertext - assert 'plaintext' not in response_ciphertext - - def test_transit_generate_rand_bytes(self): - if 'transit/' in self.client.list_secret_backends()['data']: - self.client.disable_secret_backend('transit') - self.client.enable_secret_backend('transit') - - response_data = self.client.transit_generate_rand_bytes(data_bytes=4)['data']['random_bytes'] - assert response_data - - def test_transit_hash_data(self): - if 'transit/' in self.client.list_secret_backends()['data']: - self.client.disable_secret_backend('transit') - self.client.enable_secret_backend('transit') - - response_hash = self.client.transit_hash_data('abbaabba')['data']['sum'] - assert len(response_hash) == 64 - - response_hash = self.client.transit_hash_data('abbaabba', algorithm="sha2-512")['data']['sum'] - assert len(response_hash) == 128 - - def test_transit_generate_verify_hmac(self): - if 'transit/' in self.client.list_secret_backends()['data']: - self.client.disable_secret_backend('transit') - self.client.enable_secret_backend('transit') - - self.client.transit_create_key('foo') - - response_hmac = self.client.transit_generate_hmac('foo', 'abbaabba')['data']['hmac'] - assert response_hmac - verify_resp = self.client.transit_verify_signed_data('foo', 'abbaabba', hmac=response_hmac)['data']['valid'] - assert verify_resp - - response_hmac = self.client.transit_generate_hmac('foo', 'abbaabba', algorithm='sha2-512')['data']['hmac'] - assert response_hmac - verify_resp = self.client.transit_verify_signed_data('foo', 'abbaabba', - algorithm='sha2-512', hmac=response_hmac)['data']['valid'] - assert verify_resp - - def test_transit_sign_verify_signature_data(self): - if 'transit/' in self.client.list_secret_backends()['data']: - self.client.disable_secret_backend('transit') - self.client.enable_secret_backend('transit') - - self.client.transit_create_key('foo', key_type='ed25519') - - signed_resp = self.client.transit_sign_data('foo', 'abbaabba')['data']['signature'] - assert signed_resp - verify_resp = self.client.transit_verify_signed_data('foo', 'abbaabba', signature=signed_resp)['data']['valid'] - assert verify_resp - - signed_resp = self.client.transit_sign_data('foo', 'abbaabba', algorithm='sha2-512')['data']['signature'] - assert signed_resp - verify_resp = self.client.transit_verify_signed_data('foo', 'abbaabba', - algorithm='sha2-512', - signature=signed_resp)['data']['valid'] - assert verify_resp + self.client.sys.disable_auth_method("app-id") def test_missing_token(self): client = utils.create_client() assert not client.is_authenticated() def test_invalid_token(self): - client = utils.create_client(token='not-a-real-token') + client = utils.create_client(token="not-a-real-token") assert not client.is_authenticated() def test_illegal_token(self): - client = utils.create_client(token='token-with-new-line\n') + client = utils.create_client(token="token-with-new-line\n") try: client.is_authenticated() except ValueError as e: - assert 'Invalid header value' in str(e) + assert "Invalid header value" in str(e) def test_broken_token(self): - client = utils.create_client(token='\x1b') + client = utils.create_client(token="\x1b") try: client.is_authenticated() except exceptions.InvalidRequest as e: @@ -479,48 +336,39 @@ def test_client_logout(self): assert not self.client.is_authenticated() def test_revoke_self_token(self): - if 'userpass/' in self.client.list_auth_backends()['data']: - self.client.disable_auth_backend('userpass') + if "userpass/" in self.client.sys.list_auth_methods()["data"]: + self.client.sys.disable_auth_method("userpass") - self.client.enable_auth_backend('userpass') + self.client.sys.enable_auth_method("userpass") - self.client.write('auth/userpass/users/testuser', password='testpass', policies='not_root') + self.client.write( + "auth/userpass/users/testuser", password="testpass", policies="not_root" + ) - self.client.auth_userpass('testuser', 'testpass') + self.client.auth_userpass("testuser", "testpass") self.client.revoke_self_token() assert not self.client.is_authenticated() - def test_tls_auth(self): - self.client.enable_auth_backend('cert') - - with open(utils.get_config_file_path('client-cert.pem')) as fp: - certificate = fp.read() - - self.client.write('auth/cert/certs/test', display_name='test', - policies='not_root', certificate=certificate) - - self.client.auth_tls() - def test_gh51(self): - key = 'secret/http://test.com' + key = "secret/http://test.com" - self.client.write(key, foo='bar') + self.client.write(key, foo="bar") result = self.client.read(key) - assert result['data']['foo'] == 'bar' + assert result["data"]["foo"] == "bar" def test_token_accessor(self): # Create token, check accessor is provided - result = self.client.create_token(lease='1h') - token_accessor = result['auth'].get('accessor', None) + result = self.client.create_token(lease="1h") + token_accessor = result["auth"].get("accessor", None) assert token_accessor # Look up token by accessor, make sure token is excluded from results lookup = self.client.lookup_token(token_accessor, accessor=True) - assert lookup['data']['accessor'] == token_accessor - assert not lookup['data']['id'] + assert lookup["data"]["accessor"] == token_accessor + assert not lookup["data"]["id"] # Revoke token using the accessor self.client.revoke_token(token_accessor, accessor=True) @@ -531,44 +379,44 @@ def test_token_accessor(self): # As should regular lookup with self.assertRaises(exceptions.Forbidden): - lookup = self.client.lookup_token(result['auth']['client_token']) + lookup = self.client.lookup_token(result["auth"]["client_token"]) def test_create_token_explicit_max_ttl(self): - token = self.client.create_token(ttl='30m', explicit_max_ttl='5m') + token = self.client.create_token(ttl="30m", explicit_max_ttl="5m") - assert token['auth']['client_token'] + assert token["auth"]["client_token"] - assert token['auth']['lease_duration'] == 300 + assert token["auth"]["lease_duration"] == 300 # Validate token - lookup = self.client.lookup_token(token['auth']['client_token']) - assert token['auth']['client_token'] == lookup['data']['id'] + lookup = self.client.lookup_token(token["auth"]["client_token"]) + assert token["auth"]["client_token"] == lookup["data"]["id"] def test_create_token_max_ttl(self): - token = self.client.create_token(ttl='5m') + token = self.client.create_token(ttl="5m") - assert token['auth']['client_token'] + assert token["auth"]["client_token"] - assert token['auth']['lease_duration'] == 300 + assert token["auth"]["lease_duration"] == 300 # Validate token - lookup = self.client.lookup_token(token['auth']['client_token']) - assert token['auth']['client_token'] == lookup['data']['id'] + lookup = self.client.lookup_token(token["auth"]["client_token"]) + assert token["auth"]["client_token"] == lookup["data"]["id"] def test_create_token_periodic(self): - token = self.client.create_token(period='30m') + token = self.client.create_token(period="30m") - assert token['auth']['client_token'] + assert token["auth"]["client_token"] - assert token['auth']['lease_duration'] == 1800 + assert token["auth"]["lease_duration"] == 1800 # Validate token - lookup = self.client.lookup_token(token['auth']['client_token']) - assert token['auth']['client_token'] == lookup['data']['id'] - assert lookup['data']['period'] == 1800 + lookup = self.client.lookup_token(token["auth"]["client_token"]) + assert token["auth"]["client_token"] == lookup["data"]["id"] + assert lookup["data"]["period"] == 1800 def test_token_roles(self): # No roles, list_token_roles == None @@ -576,15 +424,15 @@ def test_token_roles(self): assert not before # Create token role - assert self.client.create_token_role('testrole').status_code == 204 + assert self.client.create_token_role("testrole").status_code == 204 # List token roles - during = self.client.list_token_roles()['data']['keys'] + during = self.client.list_token_roles()["data"]["keys"] assert len(during) == 1 - assert during[0] == 'testrole' + assert during[0] == "testrole" # Delete token role - self.client.delete_token_role('testrole') + self.client.delete_token_role("testrole") # No roles, list_token_roles == None after = self.client.list_token_roles() @@ -592,284 +440,90 @@ def test_token_roles(self): def test_create_token_w_role(self): # Create policy - self.prep_policy('testpolicy') + self.prep_policy("testpolicy") # Create token role w/ policy - assert self.client.create_token_role('testrole', - allowed_policies='testpolicy').status_code == 204 + assert ( + self.client.create_token_role( + "testrole", allowed_policies="testpolicy" + ).status_code + == 204 + ) # Create token against role - token = self.client.create_token(lease='1h', role='testrole') - assert token['auth']['client_token'] - assert token['auth']['policies'] == ['default', 'testpolicy'] + token = self.client.create_token(lease="1h", role="testrole") + assert token["auth"]["client_token"] + assert token["auth"]["policies"] == ["default", "testpolicy"] # Cleanup - self.client.delete_token_role('testrole') - self.client.delete_policy('testpolicy') - - def test_ec2_role_crud(self): - if 'aws-ec2/' in self.client.list_auth_backends()['data']: - self.client.disable_auth_backend('aws-ec2') - self.client.enable_auth_backend('aws-ec2') - - # create a policy to associate with the role - self.prep_policy('ec2rolepolicy') - - # attempt to get a list of roles before any exist - no_roles = self.client.list_ec2_roles() - # doing so should succeed and return None - assert (no_roles is None) - - # test binding by AMI ID (the old way, to ensure backward compatibility) - self.client.create_ec2_role('foo', - 'ami-notarealami', - policies='ec2rolepolicy') - - # test binding by Account ID - self.client.create_ec2_role('bar', - bound_account_id='123456789012', - policies='ec2rolepolicy') - - # test binding by IAM Role ARN - self.client.create_ec2_role('baz', - bound_iam_role_arn='arn:aws:iam::123456789012:role/mockec2role', - policies='ec2rolepolicy') - - # test binding by instance profile ARN - self.client.create_ec2_role('qux', - bound_iam_instance_profile_arn='arn:aws:iam::123456789012:instance-profile/mockprofile', - policies='ec2rolepolicy') - - # test binding by bound region - self.client.create_ec2_role('quux', - bound_region='ap-northeast-2', - policies='ec2rolepolicy') - - # test binding by bound vpc id - self.client.create_ec2_role('corge', - bound_vpc_id='vpc-1a123456', - policies='ec2rolepolicy') - - # test binding by bound subnet id - self.client.create_ec2_role('grault', - bound_subnet_id='subnet-123a456', - policies='ec2rolepolicy') - - roles = self.client.list_ec2_roles() - - assert('foo' in roles['data']['keys']) - assert('bar' in roles['data']['keys']) - assert('baz' in roles['data']['keys']) - assert('qux' in roles['data']['keys']) - assert('quux' in roles['data']['keys']) - assert('corge' in roles['data']['keys']) - assert('grault' in roles['data']['keys']) - - foo_role = self.client.get_ec2_role('foo') - assert ('ami-notarealami' in foo_role['data']['bound_ami_id']) - assert ('ec2rolepolicy' in foo_role['data']['policies']) - - bar_role = self.client.get_ec2_role('bar') - assert ('123456789012' in bar_role['data']['bound_account_id']) - assert ('ec2rolepolicy' in bar_role['data']['policies']) - - baz_role = self.client.get_ec2_role('baz') - assert ('arn:aws:iam::123456789012:role/mockec2role' in baz_role['data']['bound_iam_role_arn']) - assert ('ec2rolepolicy' in baz_role['data']['policies']) - - qux_role = self.client.get_ec2_role('qux') - assert('arn:aws:iam::123456789012:instance-profile/mockprofile' in qux_role['data']['bound_iam_instance_profile_arn']) - assert('ec2rolepolicy' in qux_role['data']['policies']) - - quux_role = self.client.get_ec2_role('quux') - assert('ap-northeast-2' in quux_role['data']['bound_region']) - assert('ec2rolepolicy' in quux_role['data']['policies']) - - corge_role = self.client.get_ec2_role('corge') - assert('vpc-1a123456' in corge_role['data']['bound_vpc_id']) - assert('ec2rolepolicy' in corge_role['data']['policies']) - - grault_role = self.client.get_ec2_role('grault') - assert('subnet-123a456' in grault_role['data']['bound_subnet_id']) - assert('ec2rolepolicy' in grault_role['data']['policies']) - - # teardown - self.client.delete_ec2_role('foo') - self.client.delete_ec2_role('bar') - self.client.delete_ec2_role('baz') - self.client.delete_ec2_role('qux') - self.client.delete_ec2_role('quux') - self.client.delete_ec2_role('corge') - self.client.delete_ec2_role('grault') - - self.client.delete_policy('ec2rolepolicy') - - self.client.disable_auth_backend('aws-ec2') - - def test_ec2_role_token_lifespan(self): - if 'aws-ec2/' not in self.client.list_auth_backends()['data']: - self.client.enable_auth_backend('aws-ec2') - - # create a policy to associate with the role - self.prep_policy('ec2rolepolicy') - - # create a role with no TTL - self.client.create_ec2_role('foo', - 'ami-notarealami', - policies='ec2rolepolicy') - - # create a role with a 1hr TTL - self.client.create_ec2_role('bar', - 'ami-notarealami', - ttl='1h', - policies='ec2rolepolicy') - - # create a role with a 3-day max TTL - self.client.create_ec2_role('baz', - 'ami-notarealami', - max_ttl='72h', - policies='ec2rolepolicy') - - # create a role with 1-day period - self.client.create_ec2_role('qux', - 'ami-notarealami', - period='24h', - policies='ec2rolepolicy') - - foo_role = self.client.get_ec2_role('foo') - ttl_data_key = 'token_ttl' if utils.vault_version_ge('1.2.0') else 'ttl' - assert (foo_role['data'][ttl_data_key] == 0) - - bar_role = self.client.get_ec2_role('bar') - assert (bar_role['data']['ttl'] == 3600) - - baz_role = self.client.get_ec2_role('baz') - max_ttl_data_key = 'token_max_ttl' if utils.vault_version_ge('1.2.0') else 'max_ttl' - assert (baz_role['data'][max_ttl_data_key] == 259200) - - qux_role = self.client.get_ec2_role('qux') - assert (qux_role['data']['period'] == 86400) - - # teardown - self.client.delete_ec2_role('foo') - self.client.delete_ec2_role('bar') - self.client.delete_ec2_role('baz') - self.client.delete_ec2_role('qux') - - self.client.delete_policy('ec2rolepolicy') - - self.client.disable_auth_backend('aws-ec2') - - def test_auth_ec2_alternate_mount_point_with_no_client_token_exception(self): - test_mount_point = 'aws-custom-path' - # Turn on the aws-ec2 backend with a custom mount_point path specified. - if '{0}/'.format(test_mount_point) in self.client.list_auth_backends()['data']: - self.client.disable_auth_backend(test_mount_point) - self.client.enable_auth_backend('aws-ec2', mount_point=test_mount_point) - - # Drop the client's token to replicate a typical end user's use of any auth method. - # I.e., its reasonable to expect the method is being called to _retrieve_ a token in the first place. - self.client.token = None - - # Load a mock PKCS7 encoded self-signed certificate to stand in for a real document from the AWS identity service. - with open(utils.get_config_file_path('identity_document.p7b')) as fp: - pkcs7 = fp.read() - - # When attempting to auth (POST) to an auth backend mounted at a different path than the default, we expect a - # generic 'missing client token' response from Vault. - with self.assertRaises(exceptions.InvalidRequest) as assertRaisesContext: - self.client.auth_ec2(pkcs7=pkcs7) - - expected_exception_message = 'missing client token' - actual_exception_message = str(assertRaisesContext.exception) - self.assertIn(expected_exception_message, actual_exception_message) - - # Reset test state. - self.client.token = self.manager.root_token - self.client.disable_auth_backend(mount_point=test_mount_point) - - def test_auth_ec2_alternate_mount_point_with_no_client_token(self): - test_mount_point = 'aws-custom-path' - # Turn on the aws-ec2 backend with a custom mount_point path specified. - if '{0}/'.format(test_mount_point) in self.client.list_auth_backends()['data']: - self.client.disable_auth_backend(test_mount_point) - self.client.enable_auth_backend('aws-ec2', mount_point=test_mount_point) - - # Drop the client's token to replicate a typical end user's use of any auth method. - # I.e., its reasonable to expect the method is being called to _retrieve_ a token in the first place. - self.client.token = None - - # Load a mock PKCS7 encoded self-signed certificate to stand in for a real document from the AWS identity service. - with open(utils.get_config_file_path('identity_document.p7b')) as fp: - pkcs7 = fp.read() - - # If our custom path is respected, we'll still end up with Vault's inability to decrypt our dummy PKCS7 string. - # However this exception indicates we're correctly hitting the expected auth endpoint. - with self.assertRaises(exceptions.InternalServerError) as assertRaisesContext: - self.client.auth_ec2(pkcs7=pkcs7, mount_point=test_mount_point) - - expected_exception_message = 'failed to decode the PEM encoded PKCS#7 signature' - actual_exception_message = str(assertRaisesContext.exception) - self.assertIn(expected_exception_message, actual_exception_message) - - # Reset test state. - self.client.token = self.manager.root_token - self.client.disable_auth_backend(mount_point=test_mount_point) + self.client.delete_token_role("testrole") + self.client.sys.delete_policy("testpolicy") def test_auth_gcp_alternate_mount_point_with_no_client_token_exception(self): - test_mount_point = 'gcp-custom-path' + test_mount_point = "gcp-custom-path" # Turn on the gcp backend with a custom mount_point path specified. - if '{0}/'.format(test_mount_point) in self.client.list_auth_backends()['data']: - self.client.disable_auth_backend(test_mount_point) - self.client.enable_auth_backend('gcp', mount_point=test_mount_point) + if ( + "{0}/".format(test_mount_point) + in self.client.sys.list_auth_methods()["data"] + ): + self.client.sys.disable_auth_method(test_mount_point) + self.client.sys.enable_auth_method("gcp", path=test_mount_point) # Drop the client's token to replicate a typical end user's use of any auth method. # I.e., its reasonable to expect the method is being called to _retrieve_ a token in the first place. self.client.token = None # Load a mock JWT stand in for a real document from GCP. - with open(utils.get_config_file_path('example.jwt')) as fp: + with open(utils.get_config_file_path("example.jwt")) as fp: jwt = fp.read() # When attempting to auth (POST) to an auth backend mounted at a different path than the default, we expect a # generic 'missing client token' response from Vault. with self.assertRaises(exceptions.InvalidRequest) as assertRaisesContext: - self.client.auth.gcp.login('example-role', jwt) + self.client.auth.gcp.login("example-role", jwt) - expected_exception_message = 'missing client token' + expected_exception_message = "missing client token" actual_exception_message = str(assertRaisesContext.exception) self.assertIn(expected_exception_message, actual_exception_message) # Reset test state. self.client.token = self.manager.root_token - self.client.disable_auth_backend(mount_point=test_mount_point) + self.client.sys.disable_auth_method(path=test_mount_point) - @skipIf(utils.if_vault_version('0.10.0'), "KV version 2 secret engine not available before Vault version 0.10.0") + @skipIf( + utils.if_vault_version("0.10.0"), + "KV version 2 secret engine not available before Vault version 0.10.0", + ) def test_kv2_secret_backend(self): - if 'test/' in self.client.list_secret_backends()['data']: - self.client.disable_secret_backend('test') - self.client.enable_secret_backend('kv', mount_point='test', options={'version': '2'}) + if "test/" in self.client.sys.list_mounted_secrets_engines()["data"]: + self.client.sys.disable_secrets_engine("test") + self.client.sys.enable_secrets_engine( + "kv", path="test", options={"version": "2"} + ) - secret_backends = self.client.list_secret_backends()['data'] + secret_backends = self.client.sys.list_mounted_secrets_engines()["data"] - assert 'test/' in secret_backends - self.assertDictEqual(secret_backends['test/']['options'], {'version': '2'}) + assert "test/" in secret_backends + self.assertDictEqual(secret_backends["test/"]["options"], {"version": "2"}) - self.client.disable_secret_backend('test') + self.client.sys.disable_secrets_engine("test") def test_create_kubernetes_configuration(self): expected_status_code = 204 - test_mount_point = 'k8s' + test_mount_point = "k8s" # Turn on the kubernetes backend with a custom mount_point path specified. - if '{0}/'.format(test_mount_point) in self.client.list_auth_backends()['data']: - self.client.disable_auth_backend(test_mount_point) - self.client.enable_auth_backend('kubernetes', mount_point=test_mount_point) - - with open(utils.get_config_file_path('client-cert.pem')) as fp: + if ( + "{0}/".format(test_mount_point) + in self.client.sys.list_auth_methods()["data"] + ): + self.client.sys.disable_auth_method(test_mount_point) + self.client.sys.enable_auth_method("kubernetes", path=test_mount_point) + + with open(utils.get_config_file_path("client-cert.pem")) as fp: certificate = fp.read() response = self.client.create_kubernetes_configuration( - kubernetes_host='127.0.0.1:80', + kubernetes_host="127.0.0.1:80", pem_keys=[certificate], mount_point=test_mount_point, ) @@ -879,17 +533,20 @@ def test_create_kubernetes_configuration(self): ) # Reset integration test state - self.client.disable_auth_backend(mount_point=test_mount_point) + self.client.sys.disable_auth_method(path=test_mount_point) def test_get_kubernetes_configuration(self): - test_host = '127.0.0.1:80' - test_mount_point = 'k8s' + test_host = "127.0.0.1:80" + test_mount_point = "k8s" # Turn on the kubernetes backend with a custom mount_point path specified. - if '{0}/'.format(test_mount_point) in self.client.list_auth_backends()['data']: - self.client.disable_auth_backend(test_mount_point) - self.client.enable_auth_backend('kubernetes', mount_point=test_mount_point) - with open(utils.get_config_file_path('client-cert.pem')) as fp: + if ( + "{0}/".format(test_mount_point) + in self.client.sys.list_auth_methods()["data"] + ): + self.client.sys.disable_auth_method(test_mount_point) + self.client.sys.enable_auth_method("kubernetes", path=test_mount_point) + with open(utils.get_config_file_path("client-cert.pem")) as fp: certificate = fp.read() self.client.create_kubernetes_configuration( kubernetes_host=test_host, @@ -902,31 +559,33 @@ def test_get_kubernetes_configuration(self): mount_point=test_mount_point ) self.assertIn( - member='data', + member="data", container=response, ) - self.assertEquals( - first=test_host, - second=response['data'].get('kubernetes_host') + self.assertEqual( + first=test_host, second=response["data"].get("kubernetes_host") ) # Reset integration test state - self.client.disable_auth_backend(mount_point=test_mount_point) + self.client.sys.disable_auth_method(path=test_mount_point) def test_create_kubernetes_role(self): - test_role_name = 'test_role' - test_mount_point = 'k8s' + test_role_name = "test_role" + test_mount_point = "k8s" expected_status_code = 204 # Turn on the kubernetes backend with a custom mount_point path specified. - if '{0}/'.format(test_mount_point) in self.client.list_auth_backends()['data']: - self.client.disable_auth_backend(test_mount_point) - self.client.enable_auth_backend('kubernetes', mount_point=test_mount_point) - - with open(utils.get_config_file_path('client-cert.pem')) as fp: + if ( + "{0}/".format(test_mount_point) + in self.client.sys.list_auth_methods()["data"] + ): + self.client.sys.disable_auth_method(test_mount_point) + self.client.sys.enable_auth_method("kubernetes", path=test_mount_point) + + with open(utils.get_config_file_path("client-cert.pem")) as fp: certificate = fp.read() self.client.create_kubernetes_configuration( - kubernetes_host='127.0.0.1:80', + kubernetes_host="127.0.0.1:80", pem_keys=[certificate], mount_point=test_mount_point, ) @@ -934,8 +593,8 @@ def test_create_kubernetes_role(self): # Test that we can createa role response = self.client.create_kubernetes_role( name=test_role_name, - bound_service_account_names='*', - bound_service_account_namespaces='vault_test', + bound_service_account_names="*", + bound_service_account_namespaces="vault_test", mount_point=test_mount_point, ) self.assertEqual( @@ -944,22 +603,25 @@ def test_create_kubernetes_role(self): ) # Reset integration test state - self.client.disable_auth_backend(mount_point=test_mount_point) + self.client.sys.disable_auth_method(path=test_mount_point) def test_get_kubernetes_role(self): - test_role_name = 'test_role' - test_mount_point = 'k8s' - test_bound_service_account_namespaces = ['vault-test'] + test_role_name = "test_role" + test_mount_point = "k8s" + test_bound_service_account_namespaces = ["vault-test"] # Turn on the kubernetes backend with a custom mount_point path specified. - if '{0}/'.format(test_mount_point) in self.client.list_auth_backends()['data']: - self.client.disable_auth_backend(test_mount_point) - self.client.enable_auth_backend('kubernetes', mount_point=test_mount_point) - - with open(utils.get_config_file_path('client-cert.pem')) as fp: + if ( + "{0}/".format(test_mount_point) + in self.client.sys.list_auth_methods()["data"] + ): + self.client.sys.disable_auth_method(test_mount_point) + self.client.sys.enable_auth_method("kubernetes", path=test_mount_point) + + with open(utils.get_config_file_path("client-cert.pem")) as fp: certificate = fp.read() self.client.create_kubernetes_configuration( - kubernetes_host='127.0.0.1:80', + kubernetes_host="127.0.0.1:80", pem_keys=[certificate], mount_point=test_mount_point, ) @@ -967,7 +629,7 @@ def test_get_kubernetes_role(self): # Test that we can createa role self.client.create_kubernetes_role( name=test_role_name, - bound_service_account_names='*', + bound_service_account_names="*", bound_service_account_namespaces=test_bound_service_account_namespaces, mount_point=test_mount_point, ) @@ -976,30 +638,33 @@ def test_get_kubernetes_role(self): mount_point=test_mount_point, ) self.assertIn( - member='data', + member="data", container=response, ) - self.assertEquals( + self.assertEqual( first=test_bound_service_account_namespaces, - second=response['data'].get('bound_service_account_namespaces') + second=response["data"].get("bound_service_account_namespaces"), ) # Reset integration test state - self.client.disable_auth_backend(mount_point=test_mount_point) + self.client.sys.disable_auth_method(path=test_mount_point) def test_list_kubernetes_roles(self): - test_role_name = 'test_role' - test_mount_point = 'k8s' - test_bound_service_account_namespaces = ['vault-test'] + test_role_name = "test_role" + test_mount_point = "k8s" + test_bound_service_account_namespaces = ["vault-test"] # Turn on the kubernetes backend with a custom mount_point path specified. - if '{0}/'.format(test_mount_point) in self.client.list_auth_backends()['data']: - self.client.disable_auth_backend(test_mount_point) - self.client.enable_auth_backend('kubernetes', mount_point=test_mount_point) - - with open(utils.get_config_file_path('client-cert.pem')) as fp: + if ( + "{0}/".format(test_mount_point) + in self.client.sys.list_auth_methods()["data"] + ): + self.client.sys.disable_auth_method(test_mount_point) + self.client.sys.enable_auth_method("kubernetes", path=test_mount_point) + + with open(utils.get_config_file_path("client-cert.pem")) as fp: certificate = fp.read() self.client.create_kubernetes_configuration( - kubernetes_host='127.0.0.1:80', + kubernetes_host="127.0.0.1:80", pem_keys=[certificate], mount_point=test_mount_point, ) @@ -1007,7 +672,7 @@ def test_list_kubernetes_roles(self): # Test that we can createa role self.client.create_kubernetes_role( name=test_role_name, - bound_service_account_names='*', + bound_service_account_names="*", bound_service_account_namespaces=test_bound_service_account_namespaces, mount_point=test_mount_point, ) @@ -1015,38 +680,38 @@ def test_list_kubernetes_roles(self): mount_point=test_mount_point, ) self.assertIn( - member='data', + member="data", container=response, ) - self.assertEquals( - first=[test_role_name], - second=response['data'].get('keys') - ) + self.assertEqual(first=[test_role_name], second=response["data"].get("keys")) # Reset integration test state - self.client.disable_auth_backend(mount_point=test_mount_point) + self.client.sys.disable_auth_method(path=test_mount_point) def test_delete_kubernetes_role(self): - test_role_name = 'test_role' - test_mount_point = 'k8s' + test_role_name = "test_role" + test_mount_point = "k8s" expected_status_code = 204 # Turn on the kubernetes backend with a custom mount_point path specified. - if '{0}/'.format(test_mount_point) in self.client.list_auth_backends()['data']: - self.client.disable_auth_backend(test_mount_point) - self.client.enable_auth_backend('kubernetes', mount_point=test_mount_point) - - with open(utils.get_config_file_path('client-cert.pem')) as fp: + if ( + "{0}/".format(test_mount_point) + in self.client.sys.list_auth_methods()["data"] + ): + self.client.sys.disable_auth_method(test_mount_point) + self.client.sys.enable_auth_method("kubernetes", path=test_mount_point) + + with open(utils.get_config_file_path("client-cert.pem")) as fp: certificate = fp.read() self.client.create_kubernetes_configuration( - kubernetes_host='127.0.0.1:80', + kubernetes_host="127.0.0.1:80", pem_keys=[certificate], mount_point=test_mount_point, ) self.client.create_kubernetes_role( name=test_role_name, - bound_service_account_names='*', - bound_service_account_namespaces='vault_test', + bound_service_account_names="*", + bound_service_account_namespaces="vault_test", mount_point=test_mount_point, ) # Test that we can delete a role @@ -1060,18 +725,21 @@ def test_delete_kubernetes_role(self): ) # Reset integration test state - self.client.disable_auth_backend(mount_point=test_mount_point) + self.client.sys.disable_auth_method(path=test_mount_point) def test_auth_kubernetes(self): - test_role_name = 'test_role' - test_host = '127.0.0.1:80' - test_mount_point = 'k8s' + test_role_name = "test_role" + test_host = "127.0.0.1:80" + test_mount_point = "k8s" # Turn on the kubernetes backend with a custom mount_point path specified. - if '{0}/'.format(test_mount_point) in self.client.list_auth_backends()['data']: - self.client.disable_auth_backend(test_mount_point) - self.client.enable_auth_backend('kubernetes', mount_point=test_mount_point) - with open(utils.get_config_file_path('client-cert.pem')) as fp: + if ( + "{0}/".format(test_mount_point) + in self.client.sys.list_auth_methods()["data"] + ): + self.client.sys.disable_auth_method(test_mount_point) + self.client.sys.enable_auth_method("kubernetes", path=test_mount_point) + with open(utils.get_config_file_path("client-cert.pem")) as fp: certificate = fp.read() self.client.create_kubernetes_configuration( kubernetes_host=test_host, @@ -1081,15 +749,17 @@ def test_auth_kubernetes(self): self.client.create_kubernetes_role( name=test_role_name, - bound_service_account_names='*', - bound_service_account_namespaces='vault_test', + bound_service_account_names="*", + bound_service_account_namespaces="vault_test", mount_point=test_mount_point, ) # Test that we can authenticate - with open(utils.get_config_file_path('example.jwt')) as fp: + with open(utils.get_config_file_path("example.jwt")) as fp: test_jwt = fp.read() - with self.assertRaises(exceptions.InternalServerError) as assertRaisesContext: + with self.assertRaises( + exceptions.InternalServerError + ) as assertRaisesContext: # we don't actually have a valid JWT to provide, so this method will throw an exception self.client.auth_kubernetes( role=test_role_name, @@ -1102,12 +772,12 @@ def test_auth_kubernetes(self): self.assertIn(expected_exception_message, actual_exception_message) # Reset integration test state - self.client.disable_auth_backend(mount_point=test_mount_point) + self.client.sys.disable_auth_method(path=test_mount_point) def test_seal_status(self): seal_status_property = self.client.seal_status - logging.debug('seal_status_property: %s' % seal_status_property) + logging.debug("seal_status_property: %s" % seal_status_property) self.assertIn( - member='sealed', + member="sealed", container=seal_status_property, ) diff --git a/tests/integration_tests/v1/test_system_backend.py b/tests/integration_tests/v1/test_system_backend.py index a7dd07786..c149163b7 100644 --- a/tests/integration_tests/v1/test_system_backend.py +++ b/tests/integration_tests/v1/test_system_backend.py @@ -9,154 +9,173 @@ class TestSystemBackend(HvacIntegrationTestCase, TestCase): - TEST_KVV1_MOUNT_POINT = 'kvv1_mount' + TEST_KVV1_MOUNT_POINT = "kvv1_mount" def setUp(self): super(TestSystemBackend, self).setUp() - if '%s/' % self.TEST_KVV1_MOUNT_POINT not in self.client.sys.list_mounted_secrets_engines()['data']: - self.client.enable_secret_backend( - backend_type='kv', - mount_point=self.TEST_KVV1_MOUNT_POINT, + if ( + "%s/" % self.TEST_KVV1_MOUNT_POINT + not in self.client.sys.list_mounted_secrets_engines()["data"] + ): + self.client.sys.enable_secrets_engine( + backend_type="kv", + path=self.TEST_KVV1_MOUNT_POINT, options=dict(version=1), ) def tearDown(self): self.client.token = self.manager.root_token - self.client.disable_secret_backend(mount_point=self.TEST_KVV1_MOUNT_POINT) + self.client.sys.disable_secrets_engine(path=self.TEST_KVV1_MOUNT_POINT) super(TestSystemBackend, self).tearDown() def test_unseal_multi(self): cls = type(self) - self.client.seal() + self.client.sys.seal() keys = cls.manager.keys - result = self.client.unseal_multi(keys[0:2]) + result = self.client.sys.submit_unseal_keys(keys[0:2]) - self.assertTrue(result['sealed']) - self.assertEqual(result['progress'], 2) + self.assertTrue(result["sealed"]) + self.assertEqual(result["progress"], 2) - result = self.client.unseal_reset() - self.assertEqual(result['progress'], 0) - result = self.client.unseal_multi(keys[1:3]) - self.assertTrue(result['sealed']) - self.assertEqual(result['progress'], 2) - self.client.unseal_multi(keys[0:1]) - result = self.client.unseal_multi(keys[2:3]) - self.assertFalse(result['sealed']) + result = self.client.sys.submit_unseal_key(reset=True) + self.assertEqual(result["progress"], 0) + result = self.client.sys.submit_unseal_keys(keys[1:3]) + self.assertTrue(result["sealed"]) + self.assertEqual(result["progress"], 2) + self.client.sys.submit_unseal_keys(keys[0:1]) + result = self.client.sys.submit_unseal_keys(keys[2:3]) + self.assertFalse(result["sealed"]) def test_seal_unseal(self): cls = type(self) - self.assertFalse(self.client.is_sealed()) + self.assertFalse(self.client.sys.is_sealed()) - self.client.seal() + self.client.sys.seal() - self.assertTrue(self.client.is_sealed()) + self.assertTrue(self.client.sys.is_sealed()) cls.manager.unseal() - self.assertFalse(self.client.is_sealed()) + self.assertFalse(self.client.sys.is_sealed()) def test_ha_status(self): - self.assertIn('ha_enabled', self.client.ha_status) + self.assertIn("ha_enabled", self.client.ha_status) def test_wrap_write(self): - if 'approle/' not in self.client.list_auth_backends(): - self.client.enable_auth_backend("approle") + if "approle/" not in self.client.sys.list_auth_methods(): + self.client.sys.enable_auth_method("approle") self.client.write("auth/approle/role/testrole") - result = self.client.write('auth/approle/role/testrole/secret-id', wrap_ttl="10s") - self.assertIn('token', result['wrap_info']) - self.client.unwrap(result['wrap_info']['token']) - self.client.disable_auth_backend("approle") + result = self.client.write( + "auth/approle/role/testrole/secret-id", wrap_ttl="10s" + ) + self.assertIn("token", result["wrap_info"]) + self.client.sys.unwrap(result["wrap_info"]["token"]) + self.client.sys.disable_auth_method("approle") def test_auth_backend_manipulation(self): - self.assertNotIn('github/', self.client.list_auth_backends()['data']) + self.assertNotIn("github/", self.client.sys.list_auth_methods()["data"]) - self.client.enable_auth_backend('github') - self.assertIn('github/', self.client.list_auth_backends()['data']) + self.client.sys.enable_auth_method("github") + self.assertIn("github/", self.client.sys.list_auth_methods()["data"]) self.client.token = self.manager.root_token - self.client.disable_auth_backend('github') - self.assertNotIn('github/', self.client.list_auth_backends()['data']) + self.client.sys.disable_auth_method("github") + self.assertNotIn("github/", self.client.sys.list_auth_methods()["data"]) def test_secret_backend_manipulation(self): - self.assertNotIn('test/', self.client.list_secret_backends()['data']) + self.assertNotIn( + "test/", self.client.sys.list_mounted_secrets_engines()["data"] + ) - self.client.enable_secret_backend('generic', mount_point='test') - self.assertIn('test/', self.client.list_secret_backends()['data']) + self.client.sys.enable_secrets_engine("kv", path="test") + self.assertIn("test/", self.client.sys.list_mounted_secrets_engines()["data"]) - secret_backend_tuning = self.client.get_secret_backend_tuning('generic', mount_point='test') - self.assertEqual(secret_backend_tuning['data']['max_lease_ttl'], 2764800) - self.assertEqual(secret_backend_tuning['data']['default_lease_ttl'], 2764800) + secret_backend_tuning = self.client.sys.read_mount_configuration(path="test") + self.assertEqual(secret_backend_tuning["data"]["max_lease_ttl"], 2764800) + self.assertEqual(secret_backend_tuning["data"]["default_lease_ttl"], 2764800) - self.client.tune_secret_backend('generic', mount_point='test', default_lease_ttl='3600s', max_lease_ttl='8600s') - secret_backend_tuning = self.client.get_secret_backend_tuning('generic', mount_point='test') + self.client.sys.tune_mount_configuration( + path="test", + default_lease_ttl="3600s", + max_lease_ttl="8600s", + ) + secret_backend_tuning = self.client.sys.read_mount_configuration(path="test") - self.assertIn('max_lease_ttl', secret_backend_tuning['data']) - self.assertEqual(secret_backend_tuning['data']['max_lease_ttl'], 8600) - self.assertIn('default_lease_ttl', secret_backend_tuning['data']) - self.assertEqual(secret_backend_tuning['data']['default_lease_ttl'], 3600) + self.assertIn("max_lease_ttl", secret_backend_tuning["data"]) + self.assertEqual(secret_backend_tuning["data"]["max_lease_ttl"], 8600) + self.assertIn("default_lease_ttl", secret_backend_tuning["data"]) + self.assertEqual(secret_backend_tuning["data"]["default_lease_ttl"], 3600) - self.client.remount_secret_backend('test', 'foobar') - self.assertNotIn('test/', self.client.list_secret_backends()['data']) - self.assertIn('foobar/', self.client.list_secret_backends()['data']) + self.client.sys.move_backend("test", "foobar") + self.assertNotIn( + "test/", self.client.sys.list_mounted_secrets_engines()["data"] + ) + self.assertIn("foobar/", self.client.sys.list_mounted_secrets_engines()["data"]) self.client.token = self.manager.root_token - self.client.disable_secret_backend('foobar') - self.assertNotIn('foobar/', self.client.list_secret_backends()['data']) + self.client.sys.disable_secrets_engine("foobar") + self.assertNotIn( + "foobar/", self.client.sys.list_mounted_secrets_engines()["data"] + ) def test_audit_backend_manipulation(self): - self.assertNotIn('tmpfile/', self.client.list_audit_backends()) + self.assertNotIn("tmpfile/", self.client.sys.list_enabled_audit_devices()) - options = { - 'path': '/tmp/vault.audit.log' - } + options = {"path": "/tmp/vault.audit.log"} - self.client.enable_audit_backend('file', options=options, name='tmpfile') - self.assertIn('tmpfile/', self.client.list_audit_backends()['data']) + self.client.sys.enable_audit_device("file", options=options, path="tmpfile") + self.assertIn("tmpfile/", self.client.sys.list_enabled_audit_devices()["data"]) self.client.token = self.manager.root_token - self.client.disable_audit_backend('tmpfile') - self.assertNotIn('tmpfile/', self.client.list_audit_backends()['data']) + self.client.sys.disable_audit_device("tmpfile") + self.assertNotIn( + "tmpfile/", self.client.sys.list_enabled_audit_devices()["data"] + ) def test_policy_manipulation(self): - self.assertIn('root', self.client.list_policies()) - self.assertIsNone(self.client.get_policy('test')) - policy, parsed_policy = self.prep_policy('test') - self.assertIn('test', self.client.list_policies()) - self.assertEqual(policy, self.client.get_policy('test')) - self.assertEqual(parsed_policy, self.client.get_policy('test', parse=True)) + self.assertIn("root", self.client.sys.list_policies()["keys"]) + with self.assertRaises(exceptions.InvalidPath): + self.client.sys.read_policy("test") - self.client.delete_policy('test') - self.assertNotIn('test', self.client.list_policies()) + policy, parsed_policy = self.prep_policy("test") + self.assertIn("test", self.client.sys.list_policies()["keys"]) + test_policy_read_resp = self.client.sys.read_policy("test") + logging.debug("test_policy_read_resp: %s" % test_policy_read_resp) + self.assertEqual(policy, test_policy_read_resp["rules"]) + self.assertEqual(parsed_policy, self.client.get_policy("test", parse=True)) + + self.client.sys.delete_policy("test") + self.assertNotIn("test", self.client.sys.list_policies()["keys"]) def test_json_policy_manipulation(self): - self.assertIn('root', self.client.list_policies()) + self.assertIn("root", self.client.sys.list_policies()["keys"]) - policy = ''' + policy = """ path "sys" { policy = "deny" } path "secret" { policy = "write" } - ''' - self.client.set_policy('test', policy) - self.assertIn('test', self.client.list_policies()) + """ + self.client.sys.create_or_update_policy("test", policy) + self.assertIn("test", self.client.sys.list_policies()["keys"]) - self.client.delete_policy('test') - self.assertNotIn('test', self.client.list_policies()) + self.client.sys.delete_policy("test") + self.assertNotIn("test", self.client.sys.list_policies()["keys"]) def test_cubbyhole_auth(self): orig_token = self.client.token - resp = self.client.create_token(lease='6h', wrap_ttl='1h') - self.assertEqual(resp['wrap_info']['ttl'], 3600) + resp = self.client.auth.token.create(ttl="6h", wrap_ttl="1h") + self.assertEqual(resp["wrap_info"]["ttl"], 3600) - wrapped_token = resp['wrap_info']['token'] + wrapped_token = resp["wrap_info"]["token"] self.client.auth_cubbyhole(wrapped_token) self.assertNotEqual(self.client.token, orig_token) self.assertNotEqual(self.client.token, wrapped_token) @@ -168,151 +187,150 @@ def test_cubbyhole_auth(self): def test_rekey_multi(self): cls = type(self) - self.assertFalse(self.client.rekey_status['started']) + self.assertFalse(self.client.rekey_status["started"]) - self.client.start_rekey() - self.assertTrue(self.client.rekey_status['started']) + self.client.sys.start_rekey() + self.assertTrue(self.client.rekey_status["started"]) - self.client.cancel_rekey() - self.assertFalse(self.client.rekey_status['started']) + self.client.sys.cancel_rekey() + self.assertFalse(self.client.rekey_status["started"]) - result = self.client.start_rekey() + result = self.client.sys.start_rekey() keys = cls.manager.keys - result = self.client.rekey_multi(keys, nonce=result['nonce']) - self.assertTrue(result['complete']) + result = self.client.sys.rekey_multi(keys, nonce=result["nonce"]) + self.assertTrue(result["complete"]) - cls.manager.keys = result['keys'] + cls.manager.keys = result["keys"] cls.manager.unseal() def test_rotate(self): status = self.client.key_status - self.client.rotate() + self.client.sys.rotate_encryption_key() - self.assertGreater(self.client.key_status['term'], status['term']) + self.assertGreater(self.client.key_status["term"], status["term"]) def test_wrapped_token_success(self): - wrap = self.client.create_token(wrap_ttl='1m') + wrap = self.client.auth.token.create(wrap_ttl="1m") # Unwrap token - result = self.client.unwrap(wrap['wrap_info']['token']) - self.assertTrue(result['auth']['client_token']) + result = self.client.sys.unwrap(wrap["wrap_info"]["token"]) + self.assertTrue(result["auth"]["client_token"]) # Validate token - lookup = self.client.lookup_token(result['auth']['client_token']) - self.assertEqual(result['auth']['client_token'], lookup['data']['id']) + lookup = self.client.auth.token.lookup(result["auth"]["client_token"]) + self.assertEqual(result["auth"]["client_token"], lookup["data"]["id"]) def test_wrapped_token_intercept(self): - wrap = self.client.create_token(wrap_ttl='1m') + wrap = self.client.auth.token.create(wrap_ttl="1m") # Intercept wrapped token - self.client.unwrap(wrap['wrap_info']['token']) + self.client.sys.unwrap(wrap["wrap_info"]["token"]) # Attempt to retrieve the token after it's been intercepted with self.assertRaises(exceptions.InvalidRequest): - self.client.unwrap(wrap['wrap_info']['token']) + self.client.sys.unwrap(wrap["wrap_info"]["token"]) def test_wrapped_token_cleanup(self): - wrap = self.client.create_token(wrap_ttl='1m') + wrap = self.client.auth.token.create(wrap_ttl="1m") _token = self.client.token - self.client.unwrap(wrap['wrap_info']['token']) + self.client.sys.unwrap(wrap["wrap_info"]["token"]) self.assertEqual(self.client.token, _token) def test_wrapped_token_revoke(self): - wrap = self.client.create_token(wrap_ttl='1m') + wrap = self.client.auth.token.create(wrap_ttl="1m") # Revoke token before it's unwrapped - self.client.revoke_token(wrap['wrap_info']['wrapped_accessor'], accessor=True) + self.client.auth.token.revoke_accessor(wrap["wrap_info"]["wrapped_accessor"]) # Unwrap token anyway - result = self.client.unwrap(wrap['wrap_info']['token']) - self.assertTrue(result['auth']['client_token']) + result = self.client.sys.unwrap(wrap["wrap_info"]["token"]) + self.assertTrue(result["auth"]["client_token"]) # Attempt to validate token with self.assertRaises(exceptions.Forbidden): - self.client.lookup_token(result['auth']['client_token']) + self.client.auth.token.lookup(result["auth"]["client_token"]) def test_wrapped_client_token_success(self): - wrap = self.client.create_token(wrap_ttl='1m') - self.client.token = wrap['wrap_info']['token'] + wrap = self.client.auth.token.create(wrap_ttl="1m") + self.client.token = wrap["wrap_info"]["token"] # Unwrap token - result = self.client.unwrap() - self.assertTrue(result['auth']['client_token']) + result = self.client.sys.unwrap() + self.assertTrue(result["auth"]["client_token"]) # Validate token - self.client.token = result['auth']['client_token'] - lookup = self.client.lookup_token(result['auth']['client_token']) - self.assertEqual(result['auth']['client_token'], lookup['data']['id']) + self.client.token = result["auth"]["client_token"] + lookup = self.client.auth.token.lookup(result["auth"]["client_token"]) + self.assertEqual(result["auth"]["client_token"], lookup["data"]["id"]) def test_wrapped_client_token_intercept(self): - wrap = self.client.create_token(wrap_ttl='1m') - self.client.token = wrap['wrap_info']['token'] + wrap = self.client.auth.token.create(wrap_ttl="1m") + self.client.token = wrap["wrap_info"]["token"] # Intercept wrapped token - self.client.unwrap() + self.client.sys.unwrap() # Attempt to retrieve the token after it's been intercepted with self.assertRaises(exceptions.InvalidRequest): - self.client.unwrap() + self.client.sys.unwrap() def test_wrapped_client_token_cleanup(self): - wrap = self.client.create_token(wrap_ttl='1m') + wrap = self.client.auth.token.create(wrap_ttl="1m") _token = self.client.token - self.client.token = wrap['wrap_info']['token'] - self.client.unwrap() + self.client.token = wrap["wrap_info"]["token"] + self.client.sys.unwrap() self.assertNotEqual(self.client.token, wrap) self.assertNotEqual(self.client.token, _token) def test_wrapped_client_token_revoke(self): - wrap = self.client.create_token(wrap_ttl='1m') + wrap = self.client.auth.token.create(wrap_ttl="1m") # Revoke token before it's unwrapped - self.client.revoke_token(wrap['wrap_info']['wrapped_accessor'], accessor=True) + self.client.auth.token.revoke_accessor(wrap["wrap_info"]["wrapped_accessor"]) # Unwrap token anyway - self.client.token = wrap['wrap_info']['token'] - result = self.client.unwrap() - self.assertTrue(result['auth']['client_token']) + self.client.token = wrap["wrap_info"]["token"] + result = self.client.sys.unwrap() + self.assertTrue(result["auth"]["client_token"]) # Attempt to validate token with self.assertRaises(exceptions.Forbidden): - self.client.lookup_token(result['auth']['client_token']) + self.client.auth.token.lookup(result["auth"]["client_token"]) def test_start_generate_root_with_completion(self): test_otp = utils.get_generate_root_otp() - self.assertFalse(self.client.generate_root_status['started']) - start_generate_root_response = self.client.start_generate_root( - key=test_otp, - otp=True, + self.assertFalse(self.client.generate_root_status["started"]) + start_generate_root_response = self.client.sys.start_root_token_generation( + otp=test_otp, ) - logging.debug('generate_root_response: %s' % start_generate_root_response) - self.assertTrue(self.client.generate_root_status['started']) + logging.debug("generate_root_response: %s" % start_generate_root_response) + self.assertTrue(self.client.generate_root_status["started"]) - nonce = start_generate_root_response['nonce'] + nonce = start_generate_root_response["nonce"] last_generate_root_response = {} for key in self.manager.keys[0:3]: - last_generate_root_response = self.client.generate_root( + last_generate_root_response = self.client.sys.generate_root( key=key, nonce=nonce, ) - logging.debug('last_generate_root_response: %s' % last_generate_root_response) - self.assertFalse(self.client.generate_root_status['started']) + logging.debug("last_generate_root_response: %s" % last_generate_root_response) + self.assertFalse(self.client.generate_root_status["started"]) new_root_token = utils.decode_generated_root_token( - encoded_token=last_generate_root_response['encoded_root_token'], + encoded_token=last_generate_root_response["encoded_root_token"], otp=test_otp, ) - logging.debug('new_root_token: %s' % new_root_token) - token_lookup_resp = self.client.lookup_token(token=new_root_token) - logging.debug('token_lookup_resp: %s' % token_lookup_resp) + logging.debug("new_root_token: %s" % new_root_token) + token_lookup_resp = self.client.auth.token.lookup(token=new_root_token) + logging.debug("token_lookup_resp: %s" % token_lookup_resp) # Assert our new root token is properly formed and authenticated self.client.token = new_root_token @@ -321,37 +339,31 @@ def test_start_generate_root_with_completion(self): else: # If our new token was unable to authenticate, set the test client's token back to the original value self.client.token = self.manager.root_token - self.fail('Unable to authenticate with the newly generated root token.') + self.fail("Unable to authenticate with the newly generated root token.") def test_start_generate_root_then_cancel(self): test_otp = utils.get_generate_root_otp() - self.assertFalse(self.client.generate_root_status['started']) - self.client.start_generate_root( - key=test_otp, - otp=True, + self.assertFalse(self.client.generate_root_status["started"]) + self.client.sys.start_root_token_generation( + otp=test_otp, ) - self.assertTrue(self.client.generate_root_status['started']) + self.assertTrue(self.client.generate_root_status["started"]) - self.client.cancel_generate_root() - self.assertFalse(self.client.generate_root_status['started']) + self.client.sys.cancel_root_generation() + self.assertFalse(self.client.generate_root_status["started"]) def test_tune_auth_backend(self): - test_backend_type = 'approle' - test_mount_point = 'tune-approle' - test_description = 'this is a test auth backend' + test_mount_point = "tune-approle" + test_description = "this is a test auth backend" test_max_lease_ttl = 12345678 - if '{0}/'.format(test_mount_point) in self.client.list_auth_backends(): - self.client.disable_auth_backend(test_mount_point) - self.client.enable_auth_backend( - backend_type='approle', - mount_point=test_mount_point - ) + if "{0}/".format(test_mount_point) in self.client.sys.list_auth_methods(): + self.client.sys.disable_auth_method(test_mount_point) + self.client.sys.enable_auth_method(method_type="approle", path=test_mount_point) expected_status_code = 204 - response = self.client.tune_auth_backend( - backend_type=test_backend_type, - mount_point=test_mount_point, + response = self.client.sys.tune_auth_method( + path=test_mount_point, description=test_description, max_lease_ttl=test_max_lease_ttl, ) @@ -360,63 +372,67 @@ def test_tune_auth_backend(self): second=response.status_code, ) - response = self.client.get_auth_backend_tuning( - backend_type=test_backend_type, - mount_point=test_mount_point - ) + response = self.client.sys.read_auth_method_tuning(path=test_mount_point) self.assertEqual( - first=test_max_lease_ttl, - second=response['data']['max_lease_ttl'] + first=test_max_lease_ttl, second=response["data"]["max_lease_ttl"] ) - self.client.disable_auth_backend(mount_point=test_mount_point) + self.client.sys.disable_auth_method(path=test_mount_point) def test_read_lease(self): # Set up a test pki backend and issue a cert against some role so we. utils.configure_pki(client=self.client) pki_issue_response = self.client.write( - path='pki/issue/my-role', - common_name='test.hvac.com', + path="pki/issue/my-role", + common_name="test.hvac.com", ) # Read the lease of our test cert that was just issued. - read_lease_response = self.client.read_lease(pki_issue_response['lease_id']) + read_lease_response = self.client.sys.read_lease(pki_issue_response["lease_id"]) # Validate we received the expected lease ID back in our response. - self.assertEquals( - first=pki_issue_response['lease_id'], - second=read_lease_response['data']['id'], + self.assertEqual( + first=pki_issue_response["lease_id"], + second=read_lease_response["data"]["id"], ) # Reset integration test state. utils.disable_pki(client=self.client) - @parameterized.expand([ - param( - 'hash returned', - ), - param( - 'audit backend not enabled', - enable_first=False, - raises=exceptions.InvalidRequest, - exception_message='unknown audit backend', - ), - ]) - def test_audit_hash(self, label, enable_first=True, test_input='hvac-rox', raises=None, exception_message=''): - audit_backend_path = 'tmpfile' - self.client.disable_audit_backend('tmpfile') + @parameterized.expand( + [ + param( + "hash returned", + ), + param( + "audit backend not enabled", + enable_first=False, + raises=exceptions.InvalidRequest, + exception_message="unknown audit backend", + ), + ] + ) + def test_audit_hash( + self, + label, + enable_first=True, + test_input="hvac-rox", + raises=None, + exception_message="", + ): + audit_backend_path = "tmpfile" + self.client.sys.disable_audit_device("tmpfile") if enable_first: - options = { - 'path': '/tmp/vault.audit.log' - } - self.client.enable_audit_backend('file', options=options, name=audit_backend_path) + options = {"path": "/tmp/vault.audit.log"} + self.client.sys.enable_audit_device( + "file", options=options, path=audit_backend_path + ) if raises: with self.assertRaises(raises) as cm: - self.client.audit_hash( - name=audit_backend_path, - input=test_input + self.client.sys.calculate_hash( + path=audit_backend_path, input_to_hash=test_input ) if exception_message is not None: self.assertIn( @@ -424,28 +440,30 @@ def test_audit_hash(self, label, enable_first=True, test_input='hvac-rox', raise container=str(cm.exception), ) else: - audit_hash_response = self.client.audit_hash( - name=audit_backend_path, - input=test_input, + audit_hash_response = self.client.sys.calculate_hash( + path=audit_backend_path, + input_to_hash=test_input, ) - logging.debug('audit_hash_response: %s' % audit_hash_response) + logging.debug("audit_hash_response: %s" % audit_hash_response) self.assertIn( - member='hmac-sha256:', - container=audit_hash_response['data']['hash'], + member="hmac-sha256:", + container=audit_hash_response["data"]["hash"], ) - self.client.disable_audit_backend('tmpfile') + self.client.sys.disable_audit_device("tmpfile") def test_get_secret_backend_tuning(self): - secret_backend_tuning = self.client.get_secret_backend_tuning(self.TEST_KVV1_MOUNT_POINT) + secret_backend_tuning = self.client.sys.read_mount_configuration( + self.TEST_KVV1_MOUNT_POINT + ) self.assertIn( - member='default_lease_ttl', - container=secret_backend_tuning['data'], + member="default_lease_ttl", + container=secret_backend_tuning["data"], ) def test_get_backed_up_keys(self): with self.assertRaises(exceptions.InvalidRequest) as cm: - self.client.get_backed_up_keys() + self.client.sys.read_backup_keys() self.assertEqual( - first='no backed-up keys found', + first="no backed-up keys found", second=str(cm.exception), ) diff --git a/tests/scripts/install-consul.sh b/tests/scripts/install-consul.sh deleted file mode 100755 index 82247025c..000000000 --- a/tests/scripts/install-consul.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/bash -set -eux - -DEFAULT_CONSUL_VERSION="1.4.0" -DEFAULT_CONSUL_DIRECTORY="${HOME}/.local/bin" -HVAC_CONSUL_VERSION="${1:-$DEFAULT_CONSUL_VERSION}" -HVAC_CONSUL_DIRECTORY="${2:-$DEFAULT_CONSUL_DIRECTORY}" - -function install_consul_release() { - cd "/tmp" - - download_url="https://releases.hashicorp.com/consul/${HVAC_CONSUL_VERSION}/consul_${HVAC_CONSUL_VERSION}_linux_amd64.zip" - download_file="consul_${HVAC_CONSUL_VERSION}.zip" - curl -sL "${download_url}" -o "${download_file}" - unzip "${download_file}" - - mkdir -p "${HVAC_CONSUL_DIRECTORY}" - mv "consul" "${HVAC_CONSUL_DIRECTORY}" -} - -install_consul_release diff --git a/tests/scripts/install-vault.sh b/tests/scripts/install-vault.sh deleted file mode 100755 index 96aa398f2..000000000 --- a/tests/scripts/install-vault.sh +++ /dev/null @@ -1,72 +0,0 @@ -#!/bin/bash -set -eux - -DEFAULT_VAULT_VERSION="1.5.0" -DEFAULT_VAULT_LICENSE="oss" -DEFAULT_VAULT_DIRECTORY="${HOME}/.local/bin" -HVAC_VAULT_VERSION="${1:-$DEFAULT_VAULT_VERSION}" -HVAC_VAULT_LICENSE="${2:-$DEFAULT_VAULT_LICENSE}" -HVAC_VAULT_DIRECTORY="${3:-$DEFAULT_VAULT_DIRECTORY}" - -function build_and_install_vault_ref() { - if command -v gimme &>"/dev/null"; then - eval "$(GIMME_GO_VERSION=1.12.7 gimme)" - fi - export PATH="$(go env GOPATH)/bin:${PATH}" - - build_dir="/tmp/src/github.com/hashicorp/vault" - if [[ ! -d "${build_dir}" ]]; then - git clone "https://github.com/hashicorp/vault.git" "${build_dir}" - fi - cd "${build_dir}" - - case "${HVAC_VAULT_VERSION}" in - "head"|"master") - git checkout master - ;; - "stable") - latest_tag_hash=$(git rev-list --tags --max-count=1) - git checkout "${latest_tag_hash}" - ;; - esac - - make bootstrap dev - - mkdir -p "${HVAC_VAULT_DIRECTORY}" - mv "bin/vault" "${HVAC_VAULT_DIRECTORY}" -} - -function install_vault_release() { - cd "/tmp" - - unameOut="$(uname -s)" - case "${unameOut}" in - Linux*) machine='linux';; - Darwin*) machine='darwin';; - MINGW*) machine='windows';; - *) machine='linux' - esac - - if [[ "${HVAC_VAULT_LICENSE}" == "enterprise" ]]; then - download_url="https://releases.hashicorp.com/vault/${HVAC_VAULT_VERSION}+ent/vault_${HVAC_VAULT_VERSION}+ent_${machine}_amd64.zip" - else - download_url="https://releases.hashicorp.com/vault/${HVAC_VAULT_VERSION}/vault_${HVAC_VAULT_VERSION}_${machine}_amd64.zip" - fi - download_file="vault_${HVAC_VAULT_LICENSE}_${HVAC_VAULT_VERSION}.zip" - - curl -sL "${download_url}" -o "${download_file}" - unzip "${download_file}" - - mkdir -p "${HVAC_VAULT_DIRECTORY}" - mv "vault" "${HVAC_VAULT_DIRECTORY}" -} - -HVAC_VAULT_VERSION=$(tr '[:upper:]' '[:lower:]' <<< "${HVAC_VAULT_VERSION}") -case "${HVAC_VAULT_VERSION}" in - "head"|"master"|"stable") - build_and_install_vault_ref - ;; - *) - install_vault_release - ;; -esac diff --git a/tests/unit_tests/api/auth_methods/test_approle.py b/tests/unit_tests/api/auth_methods/test_approle.py index f86c63715..99a97f531 100644 --- a/tests/unit_tests/api/auth_methods/test_approle.py +++ b/tests/unit_tests/api/auth_methods/test_approle.py @@ -10,23 +10,32 @@ class TestAppRole(TestCase): - - @parameterized.expand([ - ("default mount point", DEFAULT_MOUNT_POINT, 'default', None), - ("custom mount point", 'approle-test', 'default', None), - ("bad token type", DEFAULT_MOUNT_POINT, 'bad_token', exceptions.ParamValidationError) - ]) + @parameterized.expand( + [ + ("default mount point", DEFAULT_MOUNT_POINT, "default", None), + ("custom mount point", "approle-test", "default", None), + ( + "bad token type", + DEFAULT_MOUNT_POINT, + "bad_token", + exceptions.ParamValidationError, + ), + ] + ) @requests_mock.Mocker() - def test_create_or_update_approle(self, test_label, mount_point, token_type, raises, requests_mocker): + def test_create_or_update_approle( + self, test_label, mount_point, token_type, raises, requests_mocker + ): expected_status_code = 204 - role_name = 'testrole' + role_name = "testrole" - mock_url = 'http://localhost:8200/v1/auth/{mount_point}/role/{role_name}'.format( - mount_point=mount_point, - role_name=role_name + mock_url = ( + "http://localhost:8200/v1/auth/{mount_point}/role/{role_name}".format( + mount_point=mount_point, role_name=role_name + ) ) requests_mocker.register_uri( - method='POST', + method="POST", url=mock_url, status_code=expected_status_code, ) @@ -37,224 +46,195 @@ def test_create_or_update_approle(self, test_label, mount_point, token_type, rai with self.assertRaises(raises) as cm: app_role.create_or_update_approle( role_name=role_name, - token_policies=['default'], + token_policies=["default"], token_type=token_type, - mount_point=mount_point + mount_point=mount_point, ) - self.assertIn( - member='unsupported token_type', - container=str(cm.exception) - ) + self.assertIn(member="unsupported token_type", container=str(cm.exception)) else: response = app_role.create_or_update_approle( - role_name=role_name, - token_policies=['default'], - mount_point=mount_point + role_name=role_name, token_policies=["default"], mount_point=mount_point ) - self.assertEqual( - first=expected_status_code, - second=response.status_code - ) + self.assertEqual(first=expected_status_code, second=response.status_code) - @parameterized.expand([ - ("default mount point", DEFAULT_MOUNT_POINT), - ("custom mount point", 'approle-test') - ]) + @parameterized.expand( + [ + ("default mount point", DEFAULT_MOUNT_POINT), + ("custom mount point", "approle-test"), + ] + ) @requests_mock.Mocker() def test_list_roles(self, test_label, mount_point, requests_mocker): expected_status_code = 200 mock_response = { - 'auth': None, - 'data': { - 'keys': [ - 'testrole' - ] - }, - 'lease_duration': 0, - 'lease_id': '', - 'renewable': False, - 'request_id': '860a11a8-b835-cbab-7fce-de4edc4cf533', - 'warnings': None, - 'wrap_info': None + "auth": None, + "data": {"keys": ["testrole"]}, + "lease_duration": 0, + "lease_id": "", + "renewable": False, + "request_id": "860a11a8-b835-cbab-7fce-de4edc4cf533", + "warnings": None, + "wrap_info": None, } - mock_url = 'http://localhost:8200/v1/auth/{mount_point}/role'.format( + mock_url = "http://localhost:8200/v1/auth/{mount_point}/role".format( mount_point=mount_point ) requests_mocker.register_uri( - method='LIST', + method="LIST", url=mock_url, status_code=expected_status_code, json=mock_response, ) app_role = AppRole(adapter=JSONAdapter()) - response = app_role.list_roles( - mount_point=mount_point - ) + response = app_role.list_roles(mount_point=mount_point) - self.assertEqual( - first=mock_response, - second=response - ) + self.assertEqual(first=mock_response, second=response) - @parameterized.expand([ - ("default mount point", DEFAULT_MOUNT_POINT), - ("custom mount point", 'approle-test') - ]) + @parameterized.expand( + [ + ("default mount point", DEFAULT_MOUNT_POINT), + ("custom mount point", "approle-test"), + ] + ) @requests_mock.Mocker() def test_read_role(self, test_label, mount_point, requests_mocker): expected_status_code = 200 - role_name = 'testrole' + role_name = "testrole" mock_response = { - 'auth': None, - 'data': { - 'bind_secret_id': True, - 'local_secret_ids': False, - 'secret_id_bound_cidrs': None, - 'secret_id_num_uses': 0, - 'secret_id_ttl': 0, - 'token_bound_cidrs': None, - 'token_explicit_max_ttl': 0, - 'token_max_ttl': 0, - 'token_no_default_poolicy': False, - 'token_num_uses': 0, - 'token_period': 14400, - 'token_policies': None, - 'token_ttl': 0, - 'token_type': "default" + "auth": None, + "data": { + "bind_secret_id": True, + "local_secret_ids": False, + "secret_id_bound_cidrs": None, + "secret_id_num_uses": 0, + "secret_id_ttl": 0, + "token_bound_cidrs": None, + "token_explicit_max_ttl": 0, + "token_max_ttl": 0, + "token_no_default_poolicy": False, + "token_num_uses": 0, + "token_period": 14400, + "token_policies": None, + "token_ttl": 0, + "token_type": "default", }, - 'lease_duration': 0, - 'lease_id': '', - 'renewable': False, - 'request_id': '860a11a8-b835-cbab-7fce-de4edc4cf533', - 'warnings': None, - 'wrap_info': None + "lease_duration": 0, + "lease_id": "", + "renewable": False, + "request_id": "860a11a8-b835-cbab-7fce-de4edc4cf533", + "warnings": None, + "wrap_info": None, } - mock_url = 'http://localhost:8200/v1/auth/{mount_point}/role/{role_name}'.format( - mount_point=mount_point, - role_name=role_name + mock_url = ( + "http://localhost:8200/v1/auth/{mount_point}/role/{role_name}".format( + mount_point=mount_point, role_name=role_name + ) ) requests_mocker.register_uri( - method='GET', + method="GET", url=mock_url, status_code=expected_status_code, json=mock_response, ) app_role = AppRole(adapter=JSONAdapter()) - response = app_role.read_role( - role_name="testrole", - mount_point=mount_point - ) + response = app_role.read_role(role_name="testrole", mount_point=mount_point) - self.assertEqual( - first=mock_response, - second=response - ) + self.assertEqual(first=mock_response, second=response) - @parameterized.expand([ - ("default mount point", DEFAULT_MOUNT_POINT), - ("custom mount point", 'approle-test') - ]) + @parameterized.expand( + [ + ("default mount point", DEFAULT_MOUNT_POINT), + ("custom mount point", "approle-test"), + ] + ) @requests_mock.Mocker() def test_delete_role(self, test_label, mount_point, requests_mocker): expected_status_code = 204 - role_name = 'testrole' + role_name = "testrole" - mock_url = 'http://localhost:8200/v1/auth/{mount_point}/role/{role_name}'.format( - mount_point=mount_point, - role_name=role_name + mock_url = ( + "http://localhost:8200/v1/auth/{mount_point}/role/{role_name}".format( + mount_point=mount_point, role_name=role_name + ) ) requests_mocker.register_uri( - method='DELETE', + method="DELETE", url=mock_url, status_code=expected_status_code, ) app_role = AppRole(adapter=JSONAdapter()) - response = app_role.delete_role( - role_name=role_name, - mount_point=mount_point - ) + response = app_role.delete_role(role_name=role_name, mount_point=mount_point) - self.assertEqual( - first=expected_status_code, - second=response.status_code - ) + self.assertEqual(first=expected_status_code, second=response.status_code) - @parameterized.expand([ - ("default mount point", DEFAULT_MOUNT_POINT), - ("custom mount point", 'approle-test') - ]) + @parameterized.expand( + [ + ("default mount point", DEFAULT_MOUNT_POINT), + ("custom mount point", "approle-test"), + ] + ) @requests_mock.Mocker() def test_read_role_id(self, test_label, mount_point, requests_mocker): expected_status_code = 200 - role_name = 'testrole' + role_name = "testrole" mock_response = { - 'auth': None, - 'data': { - 'role_id': 'e5a7b66e-5d08-da9c-7075-71984634b882' - }, - 'lease_duration': 0, - 'lease_id': '', - 'renewable': False, - 'request_id': '860a11a8-b835-cbab-7fce-de4edc4cf533', - 'warnings': None, - 'wrap_info': None + "auth": None, + "data": {"role_id": "e5a7b66e-5d08-da9c-7075-71984634b882"}, + "lease_duration": 0, + "lease_id": "", + "renewable": False, + "request_id": "860a11a8-b835-cbab-7fce-de4edc4cf533", + "warnings": None, + "wrap_info": None, } - mock_url = 'http://localhost:8200/v1/auth/{mount_point}/role/{role_name}/role-id'.format( - mount_point=mount_point, - role_name=role_name + mock_url = "http://localhost:8200/v1/auth/{mount_point}/role/{role_name}/role-id".format( + mount_point=mount_point, role_name=role_name ) requests_mocker.register_uri( - method='GET', + method="GET", url=mock_url, status_code=expected_status_code, json=mock_response, ) app_role = AppRole(adapter=JSONAdapter()) - response = app_role.read_role_id( - role_name=role_name, - mount_point=mount_point - ) + response = app_role.read_role_id(role_name=role_name, mount_point=mount_point) - self.assertEqual( - first=mock_response, - second=response - ) + self.assertEqual(first=mock_response, second=response) - @parameterized.expand([ - ("default mount point", DEFAULT_MOUNT_POINT), - ("custom mount point", 'approle-test') - ]) + @parameterized.expand( + [ + ("default mount point", DEFAULT_MOUNT_POINT), + ("custom mount point", "approle-test"), + ] + ) @requests_mock.Mocker() def test_update_role_id(self, test_label, mount_point, requests_mocker): expected_status_code = 200 - role_name = 'testrole' - role_id = 'test_role_id' + role_name = "testrole" + role_id = "test_role_id" mock_response = { - 'auth': None, - 'data': { - 'role_id': role_id - }, - 'lease_duration': 0, - 'lease_id': '', - 'renewable': False, - 'request_id': '860a11a8-b835-cbab-7fce-de4edc4cf533', - 'warnings': None, - 'wrap_info': None + "auth": None, + "data": {"role_id": role_id}, + "lease_duration": 0, + "lease_id": "", + "renewable": False, + "request_id": "860a11a8-b835-cbab-7fce-de4edc4cf533", + "warnings": None, + "wrap_info": None, } - mock_url = 'http://localhost:8200/v1/auth/{mount_point}/role/{role_name}/role-id'.format( - mount_point=mount_point, - role_name=role_name + mock_url = "http://localhost:8200/v1/auth/{mount_point}/role/{role_name}/role-id".format( + mount_point=mount_point, role_name=role_name ) requests_mocker.register_uri( - method='POST', + method="POST", url=mock_url, status_code=expected_status_code, json=mock_response, @@ -262,44 +242,40 @@ def test_update_role_id(self, test_label, mount_point, requests_mocker): app_role = AppRole(adapter=JSONAdapter()) response = app_role.update_role_id( - role_name=role_name, - role_id=role_id, - mount_point=mount_point + role_name=role_name, role_id=role_id, mount_point=mount_point ) - self.assertEqual( - first=mock_response, - second=response - ) + self.assertEqual(first=mock_response, second=response) - @parameterized.expand([ - ("default mount point", DEFAULT_MOUNT_POINT, None), - ("custom mount point", 'approle-test', exceptions.ParamValidationError) - ]) + @parameterized.expand( + [ + ("default mount point", DEFAULT_MOUNT_POINT, None), + ("custom mount point", "approle-test", exceptions.ParamValidationError), + ] + ) @requests_mock.Mocker() def test_generate_secret_id(self, test_label, mount_point, raises, requests_mocker): expected_status_code = 200 - role_name = 'testrole' + role_name = "testrole" mock_response = { - 'auth': None, - 'data': { - 'secret_id': '841771dc-11c9-bbc7-bcac-6a3945a69cd9', - 'secret_id_accessor': '84896a0c-1347-aa90-a4f6-aca8b7558780' + "auth": None, + "data": { + "secret_id": "841771dc-11c9-bbc7-bcac-6a3945a69cd9", + "secret_id_accessor": "84896a0c-1347-aa90-a4f6-aca8b7558780", }, - 'lease_duration': 0, - 'lease_id': '', - 'renewable': False, - 'request_id': '860a11a8-b835-cbab-7fce-de4edc4cf533', - 'warnings': None, - 'wrap_info': None + "lease_duration": 0, + "lease_id": "", + "renewable": False, + "request_id": "860a11a8-b835-cbab-7fce-de4edc4cf533", + "warnings": None, + "wrap_info": None, } - mock_url = 'http://localhost:8200/v1/auth/{mount_point}/role/{role_name}/secret-id'.format( - mount_point=mount_point, - role_name=role_name + mock_url = "http://localhost:8200/v1/auth/{mount_point}/role/{role_name}/secret-id".format( + mount_point=mount_point, role_name=role_name ) requests_mocker.register_uri( - method='POST', + method="POST", url=mock_url, status_code=expected_status_code, json=mock_response, @@ -312,53 +288,50 @@ def test_generate_secret_id(self, test_label, mount_point, raises, requests_mock app_role.generate_secret_id( role_name=role_name, metadata="metadata string", - mount_point=mount_point + mount_point=mount_point, ) self.assertIn( - member='unsupported metadata argument', - container=str(cm.exception) + member="unsupported metadata argument", container=str(cm.exception) ) else: response = app_role.generate_secret_id( - role_name=role_name, - cidr_list=['127.0.0.1/32'], - mount_point=mount_point + role_name=role_name, cidr_list=["127.0.0.1/32"], mount_point=mount_point ) - self.assertEqual( - first=mock_response, - second=response - ) + self.assertEqual(first=mock_response, second=response) - @parameterized.expand([ - ("default mount point", DEFAULT_MOUNT_POINT, None), - ("custom mount point", 'approle-test', exceptions.ParamValidationError) - ]) + @parameterized.expand( + [ + ("default mount point", DEFAULT_MOUNT_POINT, None), + ("custom mount point", "approle-test", exceptions.ParamValidationError), + ] + ) @requests_mock.Mocker() - def test_create_custom_secret_id(self, test_label, mount_point, raises, requests_mocker): + def test_create_custom_secret_id( + self, test_label, mount_point, raises, requests_mocker + ): expected_status_code = 200 - role_name = 'testrole' - secret_id = 'custom_secret' + role_name = "testrole" + secret_id = "custom_secret" mock_response = { - 'auth': None, - 'data': { - 'secret_id': secret_id, - 'secret_id_accessor': '84896a0c-1347-aa90-a4f6-aca8b7558780' + "auth": None, + "data": { + "secret_id": secret_id, + "secret_id_accessor": "84896a0c-1347-aa90-a4f6-aca8b7558780", }, - 'lease_duration': 0, - 'lease_id': '', - 'renewable': False, - 'request_id': '860a11a8-b835-cbab-7fce-de4edc4cf533', - 'warnings': None, - 'wrap_info': None + "lease_duration": 0, + "lease_id": "", + "renewable": False, + "request_id": "860a11a8-b835-cbab-7fce-de4edc4cf533", + "warnings": None, + "wrap_info": None, } - mock_url = 'http://localhost:8200/v1/auth/{mount_point}/role/{role_name}/custom-secret-id'.format( - mount_point=mount_point, - role_name=role_name + mock_url = "http://localhost:8200/v1/auth/{mount_point}/role/{role_name}/custom-secret-id".format( + mount_point=mount_point, role_name=role_name ) requests_mocker.register_uri( - method='POST', + method="POST", url=mock_url, status_code=expected_status_code, json=mock_response, @@ -371,56 +344,53 @@ def test_create_custom_secret_id(self, test_label, mount_point, raises, requests app_role.create_custom_secret_id( role_name=role_name, secret_id=secret_id, - cidr_list=['127.0.0.1/32'], + cidr_list=["127.0.0.1/32"], metadata="metadata string", - mount_point=mount_point + mount_point=mount_point, ) self.assertIn( - member='unsupported metadata argument', - container=str(cm.exception) + member="unsupported metadata argument", container=str(cm.exception) ) else: response = app_role.create_custom_secret_id( role_name=role_name, secret_id=secret_id, - cidr_list=['127.0.0.1/32'], - mount_point=mount_point + cidr_list=["127.0.0.1/32"], + mount_point=mount_point, ) - self.assertEqual( - first=mock_response, - second=response - ) + self.assertEqual(first=mock_response, second=response) - @parameterized.expand([ - ("default mount point", DEFAULT_MOUNT_POINT), - ("custom mount point", 'approle-test') - ]) + @parameterized.expand( + [ + ("default mount point", DEFAULT_MOUNT_POINT), + ("custom mount point", "approle-test"), + ] + ) @requests_mock.Mocker() def test_read_secret_id(self, test_label, mount_point, requests_mocker): expected_status_code = 200 - role_name = 'testrole' - secret_id = 'custom_secret' + role_name = "testrole" + secret_id = "custom_secret" mock_response = { - 'auth': None, - 'data': { - 'secret_id': secret_id, - 'secret_id_accessor': '84896a0c-1347-aa90-a4f6-aca8b7558780' + "auth": None, + "data": { + "secret_id": secret_id, + "secret_id_accessor": "84896a0c-1347-aa90-a4f6-aca8b7558780", }, - 'lease_duration': 0, - 'lease_id': '', - 'renewable': False, - 'request_id': '860a11a8-b835-cbab-7fce-de4edc4cf533', - 'warnings': None, - 'wrap_info': None + "lease_duration": 0, + "lease_id": "", + "renewable": False, + "request_id": "860a11a8-b835-cbab-7fce-de4edc4cf533", + "warnings": None, + "wrap_info": None, } - mock_url = 'http://localhost:8200/v1/auth/{mount_point}/role/{role_name}/secret-id/lookup'.format( - mount_point=mount_point, - role_name=role_name + mock_url = "http://localhost:8200/v1/auth/{mount_point}/role/{role_name}/secret-id/lookup".format( + mount_point=mount_point, role_name=role_name ) requests_mocker.register_uri( - method='POST', + method="POST", url=mock_url, status_code=expected_status_code, json=mock_response, @@ -428,81 +398,73 @@ def test_read_secret_id(self, test_label, mount_point, requests_mocker): app_role = AppRole(adapter=JSONAdapter()) response = app_role.read_secret_id( - role_name=role_name, - secret_id=secret_id, - mount_point=mount_point + role_name=role_name, secret_id=secret_id, mount_point=mount_point ) - self.assertEqual( - first=mock_response, - second=response - ) + self.assertEqual(first=mock_response, second=response) - @parameterized.expand([ - ("default mount point", DEFAULT_MOUNT_POINT), - ("custom mount point", 'approle-test') - ]) + @parameterized.expand( + [ + ("default mount point", DEFAULT_MOUNT_POINT), + ("custom mount point", "approle-test"), + ] + ) @requests_mock.Mocker() def test_destroy_secret_id(self, test_label, mount_point, requests_mocker): expected_status_code = 204 - role_name = 'testrole' - secret_id = 'custom_secret' + role_name = "testrole" + secret_id = "custom_secret" - mock_url = 'http://localhost:8200/v1/auth/{mount_point}/role/{role_name}/secret-id/destroy'.format( - mount_point=mount_point, - role_name=role_name + mock_url = "http://localhost:8200/v1/auth/{mount_point}/role/{role_name}/secret-id/destroy".format( + mount_point=mount_point, role_name=role_name ) requests_mocker.register_uri( - method='POST', + method="POST", url=mock_url, status_code=expected_status_code, ) app_role = AppRole(adapter=JSONAdapter()) response = app_role.destroy_secret_id( - role_name=role_name, - secret_id=secret_id, - mount_point=mount_point + role_name=role_name, secret_id=secret_id, mount_point=mount_point ) - self.assertEqual( - first=expected_status_code, - second=response.status_code - ) + self.assertEqual(first=expected_status_code, second=response.status_code) - @parameterized.expand([ - ("default mount point", DEFAULT_MOUNT_POINT), - ("custom mount point", 'approle-test') - ]) + @parameterized.expand( + [ + ("default mount point", DEFAULT_MOUNT_POINT), + ("custom mount point", "approle-test"), + ] + ) @requests_mock.Mocker() def test_list_secret_id_accessors(self, test_label, mount_point, requests_mocker): expected_status_code = 200 - role_name = 'testrole' + role_name = "testrole" mock_response = { - 'auth': None, - 'data': { - 'keys': [ - 'ce102d2a-8253-c437-bf9a-aceed4241491', - 'a1c8dee4-b869-e68d-3520-2040c1a0849a', - 'be83b7e2-044c-7244-07e1-47560ca1c787', - '84896a0c-1347-aa90-a4f6-aca8b7558780', - '239b1328-6523-15e7-403a-a48038cdc45a' + "auth": None, + "data": { + "keys": [ + "ce102d2a-8253-c437-bf9a-aceed4241491", + "a1c8dee4-b869-e68d-3520-2040c1a0849a", + "be83b7e2-044c-7244-07e1-47560ca1c787", + "84896a0c-1347-aa90-a4f6-aca8b7558780", + "239b1328-6523-15e7-403a-a48038cdc45a", ] }, - 'lease_duration': 0, - 'lease_id': '', - 'renewable': False, - 'request_id': '860a11a8-b835-cbab-7fce-de4edc4cf533', - 'warnings': None, - 'wrap_info': None + "lease_duration": 0, + "lease_id": "", + "renewable": False, + "request_id": "860a11a8-b835-cbab-7fce-de4edc4cf533", + "warnings": None, + "wrap_info": None, } - mock_url = 'http://localhost:8200/v1/auth/{mount_point}/role/{role_name}/secret-id'.format( - mount_point=mount_point, - role_name=role_name + mock_url = "http://localhost:8200/v1/auth/{mount_point}/role/{role_name}/secret-id".format( + mount_point=mount_point, role_name=role_name ) requests_mocker.register_uri( - method='LIST', + method="LIST", url=mock_url, status_code=expected_status_code, json=mock_response, @@ -510,45 +472,42 @@ def test_list_secret_id_accessors(self, test_label, mount_point, requests_mocker app_role = AppRole(adapter=JSONAdapter()) response = app_role.list_secret_id_accessors( - role_name=role_name, - mount_point=mount_point + role_name=role_name, mount_point=mount_point ) - self.assertEqual( - first=mock_response, - second=response - ) + self.assertEqual(first=mock_response, second=response) - @parameterized.expand([ - ("default mount point", DEFAULT_MOUNT_POINT), - ("custom mount point", 'approle-test') - ]) + @parameterized.expand( + [ + ("default mount point", DEFAULT_MOUNT_POINT), + ("custom mount point", "approle-test"), + ] + ) @requests_mock.Mocker() def test_read_secret_id_accessor(self, test_label, mount_point, requests_mocker): expected_status_code = 200 - role_name = 'testrole' - secret_id = 'custom_secret' - secret_id_accessor = '84896a0c-1347-aa90-a4f6-aca8b7558780' + role_name = "testrole" + secret_id = "custom_secret" + secret_id_accessor = "84896a0c-1347-aa90-a4f6-aca8b7558780" mock_response = { - 'auth': None, - 'data': { - 'secret_id': secret_id, - 'secret_id_accessor': '84896a0c-1347-aa90-a4f6-aca8b7558780' + "auth": None, + "data": { + "secret_id": secret_id, + "secret_id_accessor": "84896a0c-1347-aa90-a4f6-aca8b7558780", }, - 'lease_duration': 0, - 'lease_id': '', - 'renewable': False, - 'request_id': '860a11a8-b835-cbab-7fce-de4edc4cf533', - 'warnings': None, - 'wrap_info': None + "lease_duration": 0, + "lease_id": "", + "renewable": False, + "request_id": "860a11a8-b835-cbab-7fce-de4edc4cf533", + "warnings": None, + "wrap_info": None, } - mock_url = 'http://localhost:8200/v1/auth/{mount_point}/role/{role_name}/secret-id-accessor/lookup'.format( - mount_point=mount_point, - role_name=role_name + mock_url = "http://localhost:8200/v1/auth/{mount_point}/role/{role_name}/secret-id-accessor/lookup".format( + mount_point=mount_point, role_name=role_name ) requests_mocker.register_uri( - method='POST', + method="POST", url=mock_url, status_code=expected_status_code, json=mock_response, @@ -558,30 +517,28 @@ def test_read_secret_id_accessor(self, test_label, mount_point, requests_mocker) response = app_role.read_secret_id_accessor( role_name=role_name, secret_id_accessor=secret_id_accessor, - mount_point=mount_point + mount_point=mount_point, ) - self.assertEqual( - first=mock_response, - second=response - ) + self.assertEqual(first=mock_response, second=response) - @parameterized.expand([ - ("default mount point", DEFAULT_MOUNT_POINT), - ("custom mount point", 'approle-test') - ]) + @parameterized.expand( + [ + ("default mount point", DEFAULT_MOUNT_POINT), + ("custom mount point", "approle-test"), + ] + ) @requests_mock.Mocker() def test_destroy_secret_id_accessor(self, test_label, mount_point, requests_mocker): expected_status_code = 204 - role_name = 'testrole' - secret_id_accessor = '84896a0c-1347-aa90-a4f6-aca8b7558780' + role_name = "testrole" + secret_id_accessor = "84896a0c-1347-aa90-a4f6-aca8b7558780" - mock_url = 'http://localhost:8200/v1/auth/{mount_point}/role/{role_name}/secret-id-accessor/destroy'.format( - mount_point=mount_point, - role_name=role_name + mock_url = "http://localhost:8200/v1/auth/{mount_point}/role/{role_name}/secret-id-accessor/destroy".format( + mount_point=mount_point, role_name=role_name ) requests_mocker.register_uri( - method='POST', + method="POST", url=mock_url, status_code=expected_status_code, ) @@ -590,46 +547,45 @@ def test_destroy_secret_id_accessor(self, test_label, mount_point, requests_mock response = app_role.destroy_secret_id_accessor( role_name=role_name, secret_id_accessor=secret_id_accessor, - mount_point=mount_point + mount_point=mount_point, ) - self.assertEqual( - first=expected_status_code, - second=response.status_code - ) + self.assertEqual(first=expected_status_code, second=response.status_code) - @parameterized.expand([ - ("default mount point", DEFAULT_MOUNT_POINT), - ("custom mount point", 'approle-test') - ]) + @parameterized.expand( + [ + ("default mount point", DEFAULT_MOUNT_POINT), + ("custom mount point", "approle-test"), + ] + ) @requests_mock.Mocker() def test_login(self, test_label, mount_point, requests_mocker): expected_status_code = 200 - role_id = 'test_role_id' - secret_id = 'custom_secret' + role_id = "test_role_id" + secret_id = "custom_secret" mock_response = { - 'data': None, - 'auth': { - 'renewable': True, - 'lease_duration': 1200, - 'metadata': None, - 'token_policies': ['default'], - 'accessor': 'fd6c9a00-d2dc-3b11-0be5-af7ae0e1d374', - 'client_token': '5b1a0318-679c-9c45-e5c6-d1b9a9035d49' + "data": None, + "auth": { + "renewable": True, + "lease_duration": 1200, + "metadata": None, + "token_policies": ["default"], + "accessor": "fd6c9a00-d2dc-3b11-0be5-af7ae0e1d374", + "client_token": "5b1a0318-679c-9c45-e5c6-d1b9a9035d49", }, - 'lease_duration': 0, - 'lease_id': '', - 'renewable': False, - 'request_id': '860a11a8-b835-cbab-7fce-de4edc4cf533', - 'warnings': None, - 'wrap_info': None + "lease_duration": 0, + "lease_id": "", + "renewable": False, + "request_id": "860a11a8-b835-cbab-7fce-de4edc4cf533", + "warnings": None, + "wrap_info": None, } - mock_url = 'http://localhost:8200/v1/auth/{mount_point}/login'.format( + mock_url = "http://localhost:8200/v1/auth/{mount_point}/login".format( mount_point=mount_point, ) requests_mocker.register_uri( - method='POST', + method="POST", url=mock_url, status_code=expected_status_code, json=mock_response, @@ -637,12 +593,7 @@ def test_login(self, test_label, mount_point, requests_mocker): app_role = AppRole(adapter=JSONAdapter()) response = app_role.login( - role_id=role_id, - secret_id=secret_id, - mount_point=mount_point + role_id=role_id, secret_id=secret_id, mount_point=mount_point ) - self.assertEqual( - first=mock_response, - second=response - ) + self.assertEqual(first=mock_response, second=response) diff --git a/tests/unit_tests/api/auth_methods/test_azure.py b/tests/unit_tests/api/auth_methods/test_azure.py index b9ab9ea6f..03e234130 100644 --- a/tests/unit_tests/api/auth_methods/test_azure.py +++ b/tests/unit_tests/api/auth_methods/test_azure.py @@ -10,28 +10,57 @@ from tests import utils -@skipIf(utils.vault_version_lt('0.10.0'), "Azure auth method not available before Vault version 0.10.0") +@skipIf( + utils.vault_version_lt("0.10.0"), + "Azure auth method not available before Vault version 0.10.0", +) class TestAzure(TestCase): - TEST_MOUNT_POINT = 'azure-test' + TEST_MOUNT_POINT = "azure-test" - @parameterized.expand([ - ('success', dict(), None,), - ('with subscription_id', dict(subscription_id='my_subscription_id'), None,), - ('with resource_group_name', dict(resource_group_name='my_resource_group_name'), None,), - ('with vm_name', dict(vm_name='my_vm_name'), None,), - ('with vmss_name', dict(vmss_name='my_vmss_name'), None,), - ('with vm_name and vmss_name', dict(vm_name='my_vm_name', vmss_name='my_vmss_name'), None,), - ]) + @parameterized.expand( + [ + ( + "success", + dict(), + None, + ), + ( + "with subscription_id", + dict(subscription_id="my_subscription_id"), + None, + ), + ( + "with resource_group_name", + dict(resource_group_name="my_resource_group_name"), + None, + ), + ( + "with vm_name", + dict(vm_name="my_vm_name"), + None, + ), + ( + "with vmss_name", + dict(vmss_name="my_vmss_name"), + None, + ), + ( + "with vm_name and vmss_name", + dict(vm_name="my_vm_name", vmss_name="my_vmss_name"), + None, + ), + ] + ) @requests_mock.Mocker() def test_login(self, label, test_params, raises, requests_mocker): - role_name = 'hvac' + role_name = "hvac" test_policies = [ "default", "dev", "prod", ] expected_status_code = 200 - mock_url = 'http://localhost:8200/v1/auth/{mount_point}/login'.format( + mock_url = "http://localhost:8200/v1/auth/{mount_point}/login".format( mount_point=self.TEST_MOUNT_POINT, ) mock_response = { @@ -44,7 +73,7 @@ def test_login(self, label, test_params, raises, requests_mocker): }, } requests_mocker.register_uri( - method='POST', + method="POST", url=mock_url, status_code=expected_status_code, json=mock_response, @@ -54,19 +83,19 @@ def test_login(self, label, test_params, raises, requests_mocker): with self.assertRaises(raises): azure.login( role=role_name, - jwt='my-jwt', + jwt="my-jwt", mount_point=self.TEST_MOUNT_POINT, **test_params ) else: login_response = azure.login( role=role_name, - jwt='my-jwt', + jwt="my-jwt", mount_point=self.TEST_MOUNT_POINT, **test_params ) - logging.debug('login_response: %s' % login_response) + logging.debug("login_response: %s" % login_response) self.assertEqual( - first=login_response['auth']['policies'], + first=login_response["auth"]["policies"], second=test_policies, ) diff --git a/tests/unit_tests/api/auth_methods/test_gcp.py b/tests/unit_tests/api/auth_methods/test_gcp.py index b5bc99826..306884b2a 100644 --- a/tests/unit_tests/api/auth_methods/test_gcp.py +++ b/tests/unit_tests/api/auth_methods/test_gcp.py @@ -10,22 +10,28 @@ class TestGcp(TestCase): - TEST_MOUNT_POINT = 'gcp-test' + TEST_MOUNT_POINT = "gcp-test" - @parameterized.expand([ - ('success', dict(), None,), - ]) + @parameterized.expand( + [ + ( + "success", + dict(), + None, + ), + ] + ) @requests_mock.Mocker() def test_login(self, label, test_params, raises, requests_mocker): - role_name = 'hvac' - credentials = utils.load_config_file('example.jwt.json') + role_name = "hvac" + credentials = utils.load_config_file("example.jwt.json") test_policies = [ "default", "dev", "prod", ] expected_status_code = 200 - mock_url = 'http://localhost:8200/v1/auth/{mount_point}/login'.format( + mock_url = "http://localhost:8200/v1/auth/{mount_point}/login".format( mount_point=self.TEST_MOUNT_POINT, ) mock_response = { @@ -38,7 +44,7 @@ def test_login(self, label, test_params, raises, requests_mocker): }, } requests_mocker.register_uri( - method='POST', + method="POST", url=mock_url, status_code=expected_status_code, json=mock_response, @@ -59,8 +65,8 @@ def test_login(self, label, test_params, raises, requests_mocker): mount_point=self.TEST_MOUNT_POINT, **test_params ) - logging.debug('login_response: %s' % login_response) + logging.debug("login_response: %s" % login_response) self.assertEqual( - first=login_response['auth']['policies'], + first=login_response["auth"]["policies"], second=test_policies, ) diff --git a/tests/unit_tests/api/auth_methods/test_github.py b/tests/unit_tests/api/auth_methods/test_github.py index 4e194a7f7..ee835fecd 100644 --- a/tests/unit_tests/api/auth_methods/test_github.py +++ b/tests/unit_tests/api/auth_methods/test_github.py @@ -9,25 +9,26 @@ class TestGithub(TestCase): - - @parameterized.expand([ - ("default mount point", DEFAULT_MOUNT_POINT), - ("custom mount point", 'cathub'), - ]) + @parameterized.expand( + [ + ("default mount point", DEFAULT_MOUNT_POINT), + ("custom mount point", "cathub"), + ] + ) @requests_mock.Mocker() def test_configure(self, test_label, mount_point, requests_mocker): expected_status_code = 204 - mock_url = 'http://localhost:8200/v1/auth/{mount_point}/config'.format( + mock_url = "http://localhost:8200/v1/auth/{mount_point}/config".format( mount_point=mount_point, ) requests_mocker.register_uri( - method='POST', + method="POST", url=mock_url, status_code=expected_status_code, ) github = Github(adapter=JSONAdapter()) response = github.configure( - organization='hvac', + organization="hvac", mount_point=mount_point, ) self.assertEqual( @@ -35,33 +36,30 @@ def test_configure(self, test_label, mount_point, requests_mocker): second=response.status_code, ) - @parameterized.expand([ - ("default mount point", DEFAULT_MOUNT_POINT), - ("custom mount point", 'cathub'), - ]) + @parameterized.expand( + [ + ("default mount point", DEFAULT_MOUNT_POINT), + ("custom mount point", "cathub"), + ] + ) @requests_mock.Mocker() def test_read_configuration(self, test_label, mount_point, requests_mocker): expected_status_code = 200 mock_response = { - 'auth': None, - 'data': { - 'base_url': '', - 'max_ttl': 0, - 'organization': '', - 'ttl': 0 - }, - 'lease_duration': 0, - 'lease_id': '', - 'renewable': False, - 'request_id': '860a11a8-b835-cbab-7fce-de4edc4cf533', - 'warnings': None, - 'wrap_info': None + "auth": None, + "data": {"base_url": "", "max_ttl": 0, "organization": "", "ttl": 0}, + "lease_duration": 0, + "lease_id": "", + "renewable": False, + "request_id": "860a11a8-b835-cbab-7fce-de4edc4cf533", + "warnings": None, + "wrap_info": None, } - mock_url = 'http://localhost:8200/v1/auth/{mount_point}/config'.format( + mock_url = "http://localhost:8200/v1/auth/{mount_point}/config".format( mount_point=mount_point, ) requests_mocker.register_uri( - method='GET', + method="GET", url=mock_url, status_code=expected_status_code, json=mock_response, @@ -75,20 +73,24 @@ def test_read_configuration(self, test_label, mount_point, requests_mocker): second=response, ) - @parameterized.expand([ - ("default mount point", DEFAULT_MOUNT_POINT), - ("custom mount point", 'cathub'), - ]) + @parameterized.expand( + [ + ("default mount point", DEFAULT_MOUNT_POINT), + ("custom mount point", "cathub"), + ] + ) @requests_mock.Mocker() def test_map_team(self, test_label, mount_point, requests_mocker): expected_status_code = 204 - team_name = 'hvac' - mock_url = 'http://localhost:8200/v1/auth/{mount_point}/map/teams/{team_name}'.format( - mount_point=mount_point, - team_name=team_name, + team_name = "hvac" + mock_url = ( + "http://localhost:8200/v1/auth/{mount_point}/map/teams/{team_name}".format( + mount_point=mount_point, + team_name=team_name, + ) ) requests_mocker.register_uri( - method='POST', + method="POST", url=mock_url, status_code=expected_status_code, ) @@ -102,33 +104,34 @@ def test_map_team(self, test_label, mount_point, requests_mocker): second=response.status_code, ) - @parameterized.expand([ - ("default mount point", DEFAULT_MOUNT_POINT), - ("custom mount point", 'cathub'), - ]) + @parameterized.expand( + [ + ("default mount point", DEFAULT_MOUNT_POINT), + ("custom mount point", "cathub"), + ] + ) @requests_mock.Mocker() def test_read_team_mapping(self, test_label, mount_point, requests_mocker): expected_status_code = 200 - team_name = 'hvac' + team_name = "hvac" mock_response = { - 'auth': None, - 'data': { - 'key': 'SOME_TEAM', - 'value': 'some-team-policy' - }, - 'lease_duration': 0, - 'lease_id': '', - 'renewable': False, - 'request_id': '50346cc8-34e7-f2ea-f36a-fcb9d45c1676', - 'warnings': None, - 'wrap_info': None + "auth": None, + "data": {"key": "SOME_TEAM", "value": "some-team-policy"}, + "lease_duration": 0, + "lease_id": "", + "renewable": False, + "request_id": "50346cc8-34e7-f2ea-f36a-fcb9d45c1676", + "warnings": None, + "wrap_info": None, } - mock_url = 'http://localhost:8200/v1/auth/{mount_point}/map/teams/{team_name}'.format( - mount_point=mount_point, - team_name=team_name, + mock_url = ( + "http://localhost:8200/v1/auth/{mount_point}/map/teams/{team_name}".format( + mount_point=mount_point, + team_name=team_name, + ) ) requests_mocker.register_uri( - method='GET', + method="GET", url=mock_url, status_code=expected_status_code, json=mock_response, @@ -143,20 +146,24 @@ def test_read_team_mapping(self, test_label, mount_point, requests_mocker): second=response, ) - @parameterized.expand([ - ("default mount point", DEFAULT_MOUNT_POINT), - ("custom mount point", 'cathub'), - ]) + @parameterized.expand( + [ + ("default mount point", DEFAULT_MOUNT_POINT), + ("custom mount point", "cathub"), + ] + ) @requests_mock.Mocker() def test_map_user(self, test_label, mount_point, requests_mocker): expected_status_code = 204 - user_name = 'hvac' - mock_url = 'http://localhost:8200/v1/auth/{mount_point}/map/users/{user_name}'.format( - mount_point=mount_point, - user_name=user_name, + user_name = "hvac" + mock_url = ( + "http://localhost:8200/v1/auth/{mount_point}/map/users/{user_name}".format( + mount_point=mount_point, + user_name=user_name, + ) ) requests_mocker.register_uri( - method='POST', + method="POST", url=mock_url, status_code=expected_status_code, ) @@ -170,30 +177,34 @@ def test_map_user(self, test_label, mount_point, requests_mocker): second=response.status_code, ) - @parameterized.expand([ - ("default mount point", DEFAULT_MOUNT_POINT), - ("custom mount point", 'cathub'), - ]) + @parameterized.expand( + [ + ("default mount point", DEFAULT_MOUNT_POINT), + ("custom mount point", "cathub"), + ] + ) @requests_mock.Mocker() def test_read_user_mapping(self, test_label, mount_point, requests_mocker): expected_status_code = 200 - user_name = 'hvac' + user_name = "hvac" mock_response = { - 'auth': None, - 'data': None, - 'lease_duration': 0, - 'lease_id': '', - 'renewable': False, - 'request_id': '71ec6e1b-6d4e-6374-ddc2-ff1cdd860e60', - 'warnings': None, - 'wrap_info': None + "auth": None, + "data": None, + "lease_duration": 0, + "lease_id": "", + "renewable": False, + "request_id": "71ec6e1b-6d4e-6374-ddc2-ff1cdd860e60", + "warnings": None, + "wrap_info": None, } - mock_url = 'http://localhost:8200/v1/auth/{mount_point}/map/users/{user_name}'.format( - mount_point=mount_point, - user_name=user_name, + mock_url = ( + "http://localhost:8200/v1/auth/{mount_point}/map/users/{user_name}".format( + mount_point=mount_point, + user_name=user_name, + ) ) requests_mocker.register_uri( - method='GET', + method="GET", url=mock_url, status_code=expected_status_code, json=mock_response, @@ -208,42 +219,46 @@ def test_read_user_mapping(self, test_label, mount_point, requests_mocker): second=response, ) - @parameterized.expand([ - ("default mount point", DEFAULT_MOUNT_POINT), - ("custom mount point", 'cathub'), - ]) + @parameterized.expand( + [ + ("default mount point", DEFAULT_MOUNT_POINT), + ("custom mount point", "cathub"), + ] + ) @requests_mock.Mocker() def test_login(self, test_label, mount_point, requests_mocker): mock_response = { - 'auth': { - 'accessor': 'f578d442-94ec-11e8-afe4-0af6a65f93f6', - 'client_token': 'edf5c2c0-94ec-11e8-afe4-0af6a65f93f6', - 'entity_id': 'f9268760-94ec-11e8-afe4-0af6a65f93f6', - 'lease_duration': 3600, - 'metadata': {'org': 'hvac', 'username': 'hvacbot'}, - 'policies': ['default', ], - 'renewable': True, - 'token_policies': ['default'] + "auth": { + "accessor": "f578d442-94ec-11e8-afe4-0af6a65f93f6", + "client_token": "edf5c2c0-94ec-11e8-afe4-0af6a65f93f6", + "entity_id": "f9268760-94ec-11e8-afe4-0af6a65f93f6", + "lease_duration": 3600, + "metadata": {"org": "hvac", "username": "hvacbot"}, + "policies": [ + "default", + ], + "renewable": True, + "token_policies": ["default"], }, - 'data': None, - 'lease_duration': 0, - 'lease_id': '', - 'renewable': False, - 'request_id': '488cf309-2f81-cc04-51bf-c43063d309eb', - 'warnings': None, - 'wrap_info': None + "data": None, + "lease_duration": 0, + "lease_id": "", + "renewable": False, + "request_id": "488cf309-2f81-cc04-51bf-c43063d309eb", + "warnings": None, + "wrap_info": None, } - mock_url = 'http://localhost:8200/v1/auth/{mount_point}/login'.format( + mock_url = "http://localhost:8200/v1/auth/{mount_point}/login".format( mount_point=mount_point, ) requests_mocker.register_uri( - method='POST', + method="POST", url=mock_url, json=mock_response, ) github = Github(adapter=JSONAdapter()) response = github.login( - token='valid-token', + token="valid-token", mount_point=mount_point, ) self.assertEqual( @@ -251,6 +266,6 @@ def test_login(self, test_label, mount_point, requests_mocker): second=response, ) self.assertEqual( - first=mock_response['auth']['client_token'], + first=mock_response["auth"]["client_token"], second=github._adapter.token, ) diff --git a/tests/unit_tests/api/auth_methods/test_kubernetes.py b/tests/unit_tests/api/auth_methods/test_kubernetes.py index 9cda5d8a9..f2b832094 100644 --- a/tests/unit_tests/api/auth_methods/test_kubernetes.py +++ b/tests/unit_tests/api/auth_methods/test_kubernetes.py @@ -10,23 +10,32 @@ from tests import utils -@skipIf(utils.vault_version_lt('0.8.3'), "Kubernetes auth method not available before Vault version 0.8.3") +@skipIf( + utils.vault_version_lt("0.8.3"), + "Kubernetes auth method not available before Vault version 0.8.3", +) class TestKubernetes(TestCase): - TEST_MOUNT_POINT = 'kubernetes-test' + TEST_MOUNT_POINT = "kubernetes-test" - @parameterized.expand([ - ('success', dict(), None,), - ]) + @parameterized.expand( + [ + ( + "success", + dict(), + None, + ), + ] + ) @requests_mock.Mocker() def test_login(self, label, test_params, raises, requests_mocker): - role_name = 'hvac' + role_name = "hvac" test_policies = [ "default", "dev", "prod", ] expected_status_code = 200 - mock_url = 'http://localhost:8200/v1/auth/{mount_point}/login'.format( + mock_url = "http://localhost:8200/v1/auth/{mount_point}/login".format( mount_point=self.TEST_MOUNT_POINT, ) mock_response = { @@ -39,14 +48,14 @@ def test_login(self, label, test_params, raises, requests_mocker): "service_account_name": "vault-auth", "service_account_namespace": "default", "service_account_secret_name": "vault-auth-token-pd21c", - "service_account_uid": "aa9aa8ff-98d0-11e7-9bb7-0800276d99bf" + "service_account_uid": "aa9aa8ff-98d0-11e7-9bb7-0800276d99bf", }, "lease_duration": 2764800, "renewable": True, }, } requests_mocker.register_uri( - method='POST', + method="POST", url=mock_url, status_code=expected_status_code, json=mock_response, @@ -56,19 +65,19 @@ def test_login(self, label, test_params, raises, requests_mocker): with self.assertRaises(raises): kubernetes.login( role=role_name, - jwt='my-jwt', + jwt="my-jwt", mount_point=self.TEST_MOUNT_POINT, **test_params ) else: login_response = kubernetes.login( role=role_name, - jwt='my-jwt', + jwt="my-jwt", mount_point=self.TEST_MOUNT_POINT, **test_params ) - logging.debug('login_response: %s' % login_response) + logging.debug("login_response: %s" % login_response) self.assertEqual( - first=login_response['auth']['policies'], + first=login_response["auth"]["policies"], second=test_policies, ) diff --git a/tests/unit_tests/api/auth_methods/test_ldap.py b/tests/unit_tests/api/auth_methods/test_ldap.py index 6ff1d2642..d4a932067 100644 --- a/tests/unit_tests/api/auth_methods/test_ldap.py +++ b/tests/unit_tests/api/auth_methods/test_ldap.py @@ -9,27 +9,28 @@ class TestLdap(TestCase): - - @parameterized.expand([ - ("default mount point", DEFAULT_MOUNT_POINT), - ("custom mount point", 'other-ldap-tree'), - ]) + @parameterized.expand( + [ + ("default mount point", DEFAULT_MOUNT_POINT), + ("custom mount point", "other-ldap-tree"), + ] + ) @requests_mock.Mocker() def test_configure(self, test_label, mount_point, requests_mocker): expected_status_code = 204 - mock_url = 'http://localhost:8200/v1/auth/{mount_point}/config'.format( + mock_url = "http://localhost:8200/v1/auth/{mount_point}/config".format( mount_point=mount_point, ) requests_mocker.register_uri( - method='POST', + method="POST", url=mock_url, status_code=expected_status_code, ) ldap = Ldap(adapter=JSONAdapter()) response = ldap.configure( - user_dn='dc=users,cn=hvac,cn=network', - group_dn='ou=groups,cn=hvac,cn=network', - url='ldaps://ldap.python-hvac.org', + user_dn="dc=users,cn=hvac,cn=network", + group_dn="ou=groups,cn=hvac,cn=network", + url="ldaps://ldap.python-hvac.org", mount_point=mount_point, ) self.assertEqual( @@ -37,46 +38,47 @@ def test_configure(self, test_label, mount_point, requests_mocker): second=response.status_code, ) - @parameterized.expand([ - ("default mount point", DEFAULT_MOUNT_POINT), - ("custom mount point", 'other-ldap-tree'), - ]) + @parameterized.expand( + [ + ("default mount point", DEFAULT_MOUNT_POINT), + ("custom mount point", "other-ldap-tree"), + ] + ) @requests_mock.Mocker() def test_read_configuration(self, test_label, mount_point, requests_mocker): expected_status_code = 200 mock_response = { - 'lease_id': '', - 'warnings': None, - 'wrap_info': None, - 'auth': None, - 'lease_duration': 0, - - 'request_id': 'dd7c3635-8e1c-d454-7381-bf11970fe8de', - 'data': { - 'binddn': '', - 'certificate': '', - 'deny_null_bind': True, - 'starttls': False, - 'case_sensitive_names': False, - 'userattr': '', - 'insecure_tls': False, - 'userdn': '', - 'url': 'ldap://ldap.python-hvac.org', - 'groupfilter': '', - 'tls_max_version': 'tls12', - 'tls_min_version': 'tls12', - 'groupdn': '', - 'groupattr': '', - 'upndomain': '', - 'discoverdn': False + "lease_id": "", + "warnings": None, + "wrap_info": None, + "auth": None, + "lease_duration": 0, + "request_id": "dd7c3635-8e1c-d454-7381-bf11970fe8de", + "data": { + "binddn": "", + "certificate": "", + "deny_null_bind": True, + "starttls": False, + "case_sensitive_names": False, + "userattr": "", + "insecure_tls": False, + "userdn": "", + "url": "ldap://ldap.python-hvac.org", + "groupfilter": "", + "tls_max_version": "tls12", + "tls_min_version": "tls12", + "groupdn": "", + "groupattr": "", + "upndomain": "", + "discoverdn": False, }, - 'renewable': False + "renewable": False, } - mock_url = 'http://localhost:8200/v1/auth/{mount_point}/config'.format( + mock_url = "http://localhost:8200/v1/auth/{mount_point}/config".format( mount_point=mount_point, ) requests_mocker.register_uri( - method='GET', + method="GET", url=mock_url, status_code=expected_status_code, json=mock_response, @@ -90,20 +92,24 @@ def test_read_configuration(self, test_label, mount_point, requests_mocker): second=response, ) - @parameterized.expand([ - ("default mount point", DEFAULT_MOUNT_POINT), - ("custom mount point", 'other-ldap-tree'), - ]) + @parameterized.expand( + [ + ("default mount point", DEFAULT_MOUNT_POINT), + ("custom mount point", "other-ldap-tree"), + ] + ) @requests_mock.Mocker() def test_create_or_update_group(self, test_label, mount_point, requests_mocker): expected_status_code = 204 - group_name = 'hvac' - mock_url = 'http://localhost:8200/v1/auth/{mount_point}/groups/{group_name}'.format( - mount_point=mount_point, - group_name=group_name, + group_name = "hvac" + mock_url = ( + "http://localhost:8200/v1/auth/{mount_point}/groups/{group_name}".format( + mount_point=mount_point, + group_name=group_name, + ) ) requests_mocker.register_uri( - method='POST', + method="POST", url=mock_url, status_code=expected_status_code, ) @@ -117,30 +123,30 @@ def test_create_or_update_group(self, test_label, mount_point, requests_mocker): second=response.status_code, ) - @parameterized.expand([ - ("default mount point", DEFAULT_MOUNT_POINT), - ("custom mount point", 'other-ldap-tree'), - ]) + @parameterized.expand( + [ + ("default mount point", DEFAULT_MOUNT_POINT), + ("custom mount point", "other-ldap-tree"), + ] + ) @requests_mock.Mocker() def test_list_groups(self, test_label, mount_point, requests_mocker): expected_status_code = 200 mock_response = { - 'lease_id': '', - 'warnings': None, - 'wrap_info': None, - 'auth': None, - 'lease_duration': 0, - 'request_id': '89144def-b675-4c8a-590c-4f2ad4f1fae7', - 'data': { - 'keys': ['cats'] - }, - 'renewable': False + "lease_id": "", + "warnings": None, + "wrap_info": None, + "auth": None, + "lease_duration": 0, + "request_id": "89144def-b675-4c8a-590c-4f2ad4f1fae7", + "data": {"keys": ["cats"]}, + "renewable": False, } - mock_url = 'http://localhost:8200/v1/auth/{mount_point}/groups'.format( + mock_url = "http://localhost:8200/v1/auth/{mount_point}/groups".format( mount_point=mount_point, ) requests_mocker.register_uri( - method='LIST', + method="LIST", url=mock_url, status_code=expected_status_code, json=mock_response, @@ -154,32 +160,32 @@ def test_list_groups(self, test_label, mount_point, requests_mocker): second=response, ) - @parameterized.expand([ - ("default mount point", DEFAULT_MOUNT_POINT), - ("custom mount point", 'other-ldap-tree'), - ]) + @parameterized.expand( + [ + ("default mount point", DEFAULT_MOUNT_POINT), + ("custom mount point", "other-ldap-tree"), + ] + ) @requests_mock.Mocker() def test_read_group(self, test_label, mount_point, requests_mocker): expected_status_code = 200 - group_name = 'hvac' + group_name = "hvac" mock_response = { - 'lease_id': '', - 'warnings': None, - 'wrap_info': None, - 'auth': None, - 'lease_duration': 0, - 'request_id': '448bc87c-e948-ac5f-907c-9b01fb9d26c6', - 'data': { - 'policies': [] - }, - 'renewable': False + "lease_id": "", + "warnings": None, + "wrap_info": None, + "auth": None, + "lease_duration": 0, + "request_id": "448bc87c-e948-ac5f-907c-9b01fb9d26c6", + "data": {"policies": []}, + "renewable": False, } - mock_url = 'http://localhost:8200/v1/auth/{mount_point}/groups/{name}'.format( + mock_url = "http://localhost:8200/v1/auth/{mount_point}/groups/{name}".format( mount_point=mount_point, name=group_name, ) requests_mocker.register_uri( - method='GET', + method="GET", url=mock_url, status_code=expected_status_code, json=mock_response, @@ -194,20 +200,22 @@ def test_read_group(self, test_label, mount_point, requests_mocker): second=response, ) - @parameterized.expand([ - ("default mount point", DEFAULT_MOUNT_POINT), - ("custom mount point", 'other-ldap-tree'), - ]) + @parameterized.expand( + [ + ("default mount point", DEFAULT_MOUNT_POINT), + ("custom mount point", "other-ldap-tree"), + ] + ) @requests_mock.Mocker() def test_delete_group(self, test_label, mount_point, requests_mocker): expected_status_code = 204 - group_name = 'hvac' - mock_url = 'http://localhost:8200/v1/auth/{mount_point}/groups/{name}'.format( + group_name = "hvac" + mock_url = "http://localhost:8200/v1/auth/{mount_point}/groups/{name}".format( mount_point=mount_point, name=group_name, ) requests_mocker.register_uri( - method='DELETE', + method="DELETE", url=mock_url, status_code=expected_status_code, ) @@ -221,20 +229,22 @@ def test_delete_group(self, test_label, mount_point, requests_mocker): second=response.status_code, ) - @parameterized.expand([ - ("default mount point", DEFAULT_MOUNT_POINT), - ("custom mount point", 'other-ldap-tree'), - ]) + @parameterized.expand( + [ + ("default mount point", DEFAULT_MOUNT_POINT), + ("custom mount point", "other-ldap-tree"), + ] + ) @requests_mock.Mocker() def test_create_or_update_user(self, test_label, mount_point, requests_mocker): expected_status_code = 204 - username = 'somedude' - mock_url = 'http://localhost:8200/v1/auth/{mount_point}/users/{name}'.format( + username = "somedude" + mock_url = "http://localhost:8200/v1/auth/{mount_point}/users/{name}".format( mount_point=mount_point, name=username, ) requests_mocker.register_uri( - method='POST', + method="POST", url=mock_url, status_code=expected_status_code, ) @@ -248,30 +258,30 @@ def test_create_or_update_user(self, test_label, mount_point, requests_mocker): second=response.status_code, ) - @parameterized.expand([ - ("default mount point", DEFAULT_MOUNT_POINT), - ("custom mount point", 'other-ldap-tree'), - ]) + @parameterized.expand( + [ + ("default mount point", DEFAULT_MOUNT_POINT), + ("custom mount point", "other-ldap-tree"), + ] + ) @requests_mock.Mocker() def test_list_users(self, test_label, mount_point, requests_mocker): expected_status_code = 200 mock_response = { - 'lease_id': '', - 'warnings': None, - 'wrap_info': None, - 'auth': None, - 'lease_duration': 0, - 'request_id': '0c34cc02-2f75-7deb-a531-33cf7434a729', - 'data': { - 'keys': ['somedude'] - }, - 'renewable': False + "lease_id": "", + "warnings": None, + "wrap_info": None, + "auth": None, + "lease_duration": 0, + "request_id": "0c34cc02-2f75-7deb-a531-33cf7434a729", + "data": {"keys": ["somedude"]}, + "renewable": False, } - mock_url = 'http://localhost:8200/v1/auth/{mount_point}/users'.format( + mock_url = "http://localhost:8200/v1/auth/{mount_point}/users".format( mount_point=mount_point, ) requests_mocker.register_uri( - method='LIST', + method="LIST", url=mock_url, status_code=expected_status_code, json=mock_response, @@ -285,33 +295,34 @@ def test_list_users(self, test_label, mount_point, requests_mocker): second=response, ) - @parameterized.expand([ - ("default mount point", DEFAULT_MOUNT_POINT), - ("custom mount point", 'other-ldap-tree'), - ]) + @parameterized.expand( + [ + ("default mount point", DEFAULT_MOUNT_POINT), + ("custom mount point", "other-ldap-tree"), + ] + ) @requests_mock.Mocker() def test_read_user(self, test_label, mount_point, requests_mocker): expected_status_code = 200 - username = 'somedude' + username = "somedude" mock_response = { - 'lease_id': '', - 'warnings': None, - 'wrap_info': None, - 'auth': None, - 'lease_duration': 0, - 'request_id': 'c39914d5-70c1-b585-c6bd-ac8f0dcdf997', - 'data': { - 'policies': [], - 'groups': '' - }, - 'renewable': False + "lease_id": "", + "warnings": None, + "wrap_info": None, + "auth": None, + "lease_duration": 0, + "request_id": "c39914d5-70c1-b585-c6bd-ac8f0dcdf997", + "data": {"policies": [], "groups": ""}, + "renewable": False, } - mock_url = 'http://localhost:8200/v1/auth/{mount_point}/users/{username}'.format( - mount_point=mount_point, - username=username, + mock_url = ( + "http://localhost:8200/v1/auth/{mount_point}/users/{username}".format( + mount_point=mount_point, + username=username, + ) ) requests_mocker.register_uri( - method='GET', + method="GET", url=mock_url, status_code=expected_status_code, json=mock_response, @@ -326,20 +337,24 @@ def test_read_user(self, test_label, mount_point, requests_mocker): second=response, ) - @parameterized.expand([ - ("default mount point", DEFAULT_MOUNT_POINT), - ("custom mount point", 'other-ldap-tree'), - ]) + @parameterized.expand( + [ + ("default mount point", DEFAULT_MOUNT_POINT), + ("custom mount point", "other-ldap-tree"), + ] + ) @requests_mock.Mocker() def test_delete_user(self, test_label, mount_point, requests_mocker): expected_status_code = 204 - username = 'somedude' - mock_url = 'http://localhost:8200/v1/auth/{mount_point}/users/{username}'.format( - mount_point=mount_point, - username=username, + username = "somedude" + mock_url = ( + "http://localhost:8200/v1/auth/{mount_point}/users/{username}".format( + mount_point=mount_point, + username=username, + ) ) requests_mocker.register_uri( - method='DELETE', + method="DELETE", url=mock_url, status_code=expected_status_code, ) @@ -353,50 +368,49 @@ def test_delete_user(self, test_label, mount_point, requests_mocker): second=response.status_code, ) - @parameterized.expand([ - ("default mount point", DEFAULT_MOUNT_POINT), - ("custom mount point", 'other-ldap-tree'), - ]) + @parameterized.expand( + [ + ("default mount point", DEFAULT_MOUNT_POINT), + ("custom mount point", "other-ldap-tree"), + ] + ) @requests_mock.Mocker() def test_login(self, test_label, mount_point, requests_mocker): expected_status_code = 200 - username = 'somedude' + username = "somedude" mock_response = { - 'lease_id': '', - 'warnings': None, - 'wrap_info': None, - 'auth': { - 'entity_id': '5bc030bc-2000-1176-aafb-82747ae9c874', - 'lease_duration': 2764800, - 'policies': [ - 'default', - 'test-ldap-policy' - ], - 'client_token': '5a01125e-d823-578e-86c8-049bea022b9e', - 'accessor': '71f512de-18ab-af6e-02f7-e37b3aa48780', - 'renewable': True, - 'metadata': {'username': 'somedude'} + "lease_id": "", + "warnings": None, + "wrap_info": None, + "auth": { + "entity_id": "5bc030bc-2000-1176-aafb-82747ae9c874", + "lease_duration": 2764800, + "policies": ["default", "test-ldap-policy"], + "client_token": "5a01125e-d823-578e-86c8-049bea022b9e", + "accessor": "71f512de-18ab-af6e-02f7-e37b3aa48780", + "renewable": True, + "metadata": {"username": "somedude"}, }, - 'lease_duration': 0, - 'request_id': 'c7a85e6c-fb1f-1d97-83a1-63746cb65551', - 'data': {}, - 'renewable': False + "lease_duration": 0, + "request_id": "c7a85e6c-fb1f-1d97-83a1-63746cb65551", + "data": {}, + "renewable": False, } - mock_url = 'http://localhost:8200/v1/auth/{mount_point}/login/{username}'.format( - mount_point=mount_point, - username=username, + mock_url = ( + "http://localhost:8200/v1/auth/{mount_point}/login/{username}".format( + mount_point=mount_point, + username=username, + ) ) requests_mocker.register_uri( - method='POST', + method="POST", url=mock_url, status_code=expected_status_code, json=mock_response, ) ldap = Ldap(adapter=JSONAdapter()) response = ldap.login( - mount_point=mount_point, - username=username, - password='averynicepassword' + mount_point=mount_point, username=username, password="averynicepassword" ) self.assertEqual( first=mock_response, diff --git a/tests/unit_tests/api/auth_methods/test_mfa.py b/tests/unit_tests/api/auth_methods/test_mfa.py index 470fb9b17..d6f9bbf01 100644 --- a/tests/unit_tests/api/auth_methods/test_mfa.py +++ b/tests/unit_tests/api/auth_methods/test_mfa.py @@ -9,19 +9,20 @@ class TestMfa(TestCase): - - @parameterized.expand([ - ("default mount point", DEFAULT_MOUNT_POINT), - ("custom mount point", 'cathub'), - ]) + @parameterized.expand( + [ + ("default mount point", DEFAULT_MOUNT_POINT), + ("custom mount point", "cathub"), + ] + ) @requests_mock.Mocker() def test_configure(self, test_label, mount_point, requests_mocker): expected_status_code = 204 - mock_url = 'http://localhost:8200/v1/auth/{mount_point}/mfa_config'.format( + mock_url = "http://localhost:8200/v1/auth/{mount_point}/mfa_config".format( mount_point=mount_point, ) requests_mocker.register_uri( - method='POST', + method="POST", url=mock_url, status_code=expected_status_code, ) @@ -34,29 +35,31 @@ def test_configure(self, test_label, mount_point, requests_mocker): second=response.status_code, ) - @parameterized.expand([ - ("default mount point", DEFAULT_MOUNT_POINT), - ("custom mount point", 'cathub'), - ]) + @parameterized.expand( + [ + ("default mount point", DEFAULT_MOUNT_POINT), + ("custom mount point", "cathub"), + ] + ) @requests_mock.Mocker() def test_read_configuration(self, test_label, mount_point, requests_mocker): expected_status_code = 200 mock_response = { - 'lease_id': '', - 'warnings': None, - 'wrap_info': None, - 'auth': None, - 'lease_duration': 0, - 'request_id': '18ecf194-aba2-ba99-ebb5-1b90e5e231c7', - 'data': {'type': 'duo'}, - 'renewable': False + "lease_id": "", + "warnings": None, + "wrap_info": None, + "auth": None, + "lease_duration": 0, + "request_id": "18ecf194-aba2-ba99-ebb5-1b90e5e231c7", + "data": {"type": "duo"}, + "renewable": False, } - mock_url = 'http://localhost:8200/v1/auth/{mount_point}/mfa_config'.format( + mock_url = "http://localhost:8200/v1/auth/{mount_point}/mfa_config".format( mount_point=mount_point, ) requests_mocker.register_uri( - method='GET', + method="GET", url=mock_url, status_code=expected_status_code, json=mock_response, @@ -70,85 +73,88 @@ def test_read_configuration(self, test_label, mount_point, requests_mocker): second=response, ) - @parameterized.expand([ - ("default mount point", DEFAULT_MOUNT_POINT), - ("custom mount point", 'cathub'), - ]) + @parameterized.expand( + [ + ("default mount point", DEFAULT_MOUNT_POINT), + ("custom mount point", "cathub"), + ] + ) @requests_mock.Mocker() def test_configure_duo_access(self, test_label, mount_point, requests_mocker): expected_status_code = 204 - mock_url = 'http://localhost:8200/v1/auth/{mount_point}/duo/access'.format( + mock_url = "http://localhost:8200/v1/auth/{mount_point}/duo/access".format( mount_point=mount_point, ) requests_mocker.register_uri( - method='POST', + method="POST", url=mock_url, status_code=expected_status_code, ) mfa = Mfa(adapter=JSONAdapter()) response = mfa.configure_duo_access( mount_point=mount_point, - host='someapisubdomain.python-hvac.org', - integration_key='ikey', - secret_key='supersecret', + host="someapisubdomain.python-hvac.org", + integration_key="ikey", + secret_key="supersecret", ) self.assertEqual( first=expected_status_code, second=response.status_code, ) - @parameterized.expand([ - ("default mount point", DEFAULT_MOUNT_POINT), - ("custom mount point", 'cathub'), - ]) + @parameterized.expand( + [ + ("default mount point", DEFAULT_MOUNT_POINT), + ("custom mount point", "cathub"), + ] + ) @requests_mock.Mocker() def test_configure_duo_behavior(self, test_label, mount_point, requests_mocker): expected_status_code = 204 - mock_url = 'http://localhost:8200/v1/auth/{mount_point}/duo/config'.format( + mock_url = "http://localhost:8200/v1/auth/{mount_point}/duo/config".format( mount_point=mount_point, ) requests_mocker.register_uri( - method='POST', + method="POST", url=mock_url, status_code=expected_status_code, ) mfa = Mfa(adapter=JSONAdapter()) response = mfa.configure_duo_behavior( - mount_point=mount_point, - push_info='howdy' + mount_point=mount_point, push_info="howdy" ) self.assertEqual( first=expected_status_code, second=response.status_code, ) - @parameterized.expand([ - ("default mount point", DEFAULT_MOUNT_POINT), - ("custom mount point", 'cathub'), - ]) + @parameterized.expand( + [ + ("default mount point", DEFAULT_MOUNT_POINT), + ("custom mount point", "cathub"), + ] + ) @requests_mock.Mocker() - def test_read_duo_behvaior_configuration(self, test_label, mount_point, requests_mocker): + def test_read_duo_behvaior_configuration( + self, test_label, mount_point, requests_mocker + ): expected_status_code = 200 mock_response = { - 'lease_id': '', - 'warnings': None, - 'wrap_info': None, - 'auth': None, - 'lease_duration': 0, - 'request_id': '7ea734e8-bbc4-e2de-2769-d052d6a320c6', - 'data': { - 'username_format': '%s', - 'push_info': '', - 'user_agent': '' - }, - 'renewable': False + "lease_id": "", + "warnings": None, + "wrap_info": None, + "auth": None, + "lease_duration": 0, + "request_id": "7ea734e8-bbc4-e2de-2769-d052d6a320c6", + "data": {"username_format": "%s", "push_info": "", "user_agent": ""}, + "renewable": False, } - mock_url = 'http://localhost:8200/v1/auth/{mount_point}/duo/config'.format( + mock_url = "http://localhost:8200/v1/auth/{mount_point}/duo/config".format( mount_point=mount_point, ) requests_mocker.register_uri( - method='GET', + method="GET", url=mock_url, status_code=expected_status_code, json=mock_response, diff --git a/tests/unit_tests/api/auth_methods/test_okta.py b/tests/unit_tests/api/auth_methods/test_okta.py index 8811b4b12..1a53af85c 100644 --- a/tests/unit_tests/api/auth_methods/test_okta.py +++ b/tests/unit_tests/api/auth_methods/test_okta.py @@ -9,40 +9,45 @@ class TestOkta(TestCase): - TEST_MOUNT_POINT = 'okta-test' - TEST_USERNAME = 'hvac-person' + TEST_MOUNT_POINT = "okta-test" + TEST_USERNAME = "hvac-person" - @parameterized.expand([ - ('success', dict(), None,), - ]) + @parameterized.expand( + [ + ( + "success", + dict(), + None, + ), + ] + ) @requests_mock.Mocker() def test_login(self, label, test_params, raises, requests_mocker): test_policies = [ "default", ] expected_status_code = 200 - mock_url = 'http://localhost:8200/v1/auth/{mount_point}/login/{username}'.format( - mount_point=self.TEST_MOUNT_POINT, - username=self.TEST_USERNAME, + mock_url = ( + "http://localhost:8200/v1/auth/{mount_point}/login/{username}".format( + mount_point=self.TEST_MOUNT_POINT, + username=self.TEST_USERNAME, + ) ) mock_response = { - "lease_id": "", - "data": None, - "warnings": None, - "auth": { - "client_token": "64d2a8f2-2a2f-5688-102b-e6088b76e344", - "accessor": "18bb8f89-826a-56ee-c65b-1736dc5ea27d", - "policies": ["default"], - "metadata": { - "username": self.TEST_USERNAME, - "policies": "default" + "lease_id": "", + "data": None, + "warnings": None, + "auth": { + "client_token": "64d2a8f2-2a2f-5688-102b-e6088b76e344", + "accessor": "18bb8f89-826a-56ee-c65b-1736dc5ea27d", + "policies": ["default"], + "metadata": {"username": self.TEST_USERNAME, "policies": "default"}, }, - }, - "lease_duration": 7200, - "renewable": True, + "lease_duration": 7200, + "renewable": True, } requests_mocker.register_uri( - method='POST', + method="POST", url=mock_url, status_code=expected_status_code, json=mock_response, @@ -52,19 +57,19 @@ def test_login(self, label, test_params, raises, requests_mocker): with self.assertRaises(raises): okta.login( username=self.TEST_USERNAME, - password='badpassword', + password="badpassword", mount_point=self.TEST_MOUNT_POINT, **test_params ) else: login_response = okta.login( - username=self.TEST_USERNAME, - password='badpassword', - mount_point=self.TEST_MOUNT_POINT, - **test_params + username=self.TEST_USERNAME, + password="badpassword", + mount_point=self.TEST_MOUNT_POINT, + **test_params ) - logging.debug('login_response: %s' % login_response) + logging.debug("login_response: %s" % login_response) self.assertEqual( - first=login_response['auth']['policies'], + first=login_response["auth"]["policies"], second=test_policies, ) diff --git a/tests/unit_tests/api/secrets_engines/test_aws.py b/tests/unit_tests/api/secrets_engines/test_aws.py index 9d9924e01..fcc7ebd9a 100644 --- a/tests/unit_tests/api/secrets_engines/test_aws.py +++ b/tests/unit_tests/api/secrets_engines/test_aws.py @@ -13,26 +13,26 @@ class TestAws(TestCase): - @parameterized.expand([ - param( - 'success', - ), - ]) - def test_rotate_root_iam_credentials(self, test_label, mount_point=DEFAULT_MOUNT_POINT): + @parameterized.expand( + [ + param( + "success", + ), + ] + ) + def test_rotate_root_iam_credentials( + self, test_label, mount_point=DEFAULT_MOUNT_POINT + ): expected_status_code = 200 - mock_response = { - "data": { - "access_key": "AKIA..." - } - } + mock_response = {"data": {"access_key": "AKIA..."}} aws = Aws(adapter=JSONAdapter()) - mock_url = 'http://localhost:8200/v1/{mount_point}/config/rotate-root'.format( + mock_url = "http://localhost:8200/v1/{mount_point}/config/rotate-root".format( mount_point=mount_point, ) - logging.debug('Mocking URL: %s' % mock_url) + logging.debug("Mocking URL: %s" % mock_url) with requests_mock.mock() as requests_mocker: requests_mocker.register_uri( - method='POST', + method="POST", url=mock_url, status_code=expected_status_code, json=mock_response, @@ -40,42 +40,51 @@ def test_rotate_root_iam_credentials(self, test_label, mount_point=DEFAULT_MOUNT rotate_root_response = aws.rotate_root_iam_credentials( mount_point=mount_point, ) - logging.debug('rotate_root_response: %s' % rotate_root_response) + logging.debug("rotate_root_response: %s" % rotate_root_response) self.assertEqual( first=mock_response, second=rotate_root_response, ) - @parameterized.expand([ - param( - 'success', - ), - param( - 'invalid endpoint', - endpoint='cats', - raises=ParamValidationError, - exception_msg='cats' - ), - ]) - def test_generate_credentials(self, test_label, role_name='hvac-test-role', mount_point=DEFAULT_MOUNT_POINT, - endpoint='creds', raises=None, exception_msg=''): + @parameterized.expand( + [ + param( + "success", + ), + param( + "invalid endpoint", + endpoint="cats", + raises=ParamValidationError, + exception_msg="cats", + ), + ] + ) + def test_generate_credentials( + self, + test_label, + role_name="hvac-test-role", + mount_point=DEFAULT_MOUNT_POINT, + endpoint="creds", + raises=None, + exception_msg="", + ): expected_status_code = 200 mock_response = { - "data": { - "access_key": "AKIA...", - "secret_key": "xlCs...", - "security_token": None - } + "data": { + "access_key": "AKIA...", + "secret_key": "xlCs...", + "security_token": None, + } } - mock_url = 'http://localhost:8200/v1/{mount_point}/creds/{role_name}'.format( + mock_url = "http://localhost:8200/v1/{mount_point}/creds/{role_name}".format( mount_point=mount_point, role_name=role_name, ) - logging.debug('Mocking URL: %s' % mock_url) + logging.debug("Mocking URL: %s" % mock_url) aws = Aws(adapter=JSONAdapter()) with requests_mock.mock() as requests_mocker: requests_mocker.register_uri( - method='GET', + method="GET", url=mock_url, status_code=expected_status_code, json=mock_response, @@ -98,7 +107,7 @@ def test_generate_credentials(self, test_label, role_name='hvac-test-role', moun endpoint=endpoint, mount_point=mount_point, ) - logging.debug('gen_creds_response: %s' % gen_creds_response) + logging.debug("gen_creds_response: %s" % gen_creds_response) self.assertEqual( first=mock_response, second=gen_creds_response, diff --git a/tests/unit_tests/api/secrets_engines/test_azure.py b/tests/unit_tests/api/secrets_engines/test_azure.py index bd2e0df38..28b9a76ba 100644 --- a/tests/unit_tests/api/secrets_engines/test_azure.py +++ b/tests/unit_tests/api/secrets_engines/test_azure.py @@ -10,111 +10,119 @@ from tests import utils -@skipIf(utils.vault_version_lt('0.11.0'), "Azure secret engine not available before Vault version 0.11.0") +@skipIf( + utils.vault_version_lt("0.11.0"), + "Azure secret engine not available before Vault version 0.11.0", +) class TestAzure(TestCase): - @parameterized.expand([ - ('create role', None), - ]) + @parameterized.expand( + [ + ("create role", None), + ] + ) @requests_mock.Mocker() def test_create_or_update_role(self, test_label, azure_roles, requests_mocker): expected_status_code = 204 - role_name = 'hvac' + role_name = "hvac" if azure_roles is None: azure_roles = [ { - 'role_name': "Contributor", - 'scope': "/subscriptions/95e675fa-307a-455e-8cdf-0a66aeaa35ae", + "role_name": "Contributor", + "scope": "/subscriptions/95e675fa-307a-455e-8cdf-0a66aeaa35ae", }, ] - mock_url = 'http://localhost:8200/v1/{mount_point}/roles/{name}'.format( + mock_url = "http://localhost:8200/v1/{mount_point}/roles/{name}".format( mount_point=DEFAULT_MOUNT_POINT, name=role_name, ) requests_mocker.register_uri( - method='POST', + method="POST", url=mock_url, status_code=expected_status_code, # json=mock_response, ) azure = Azure(adapter=JSONAdapter()) create_or_update_role_response = azure.create_or_update_role( - name=role_name, - azure_roles=azure_roles, - mount_point=DEFAULT_MOUNT_POINT + name=role_name, azure_roles=azure_roles, mount_point=DEFAULT_MOUNT_POINT + ) + logging.debug( + "create_or_update_role_response: %s" % create_or_update_role_response ) - logging.debug('create_or_update_role_response: %s' % create_or_update_role_response) self.assertEqual( first=expected_status_code, second=create_or_update_role_response.status_code, ) - @parameterized.expand([ - ('some_test',), - ]) + @parameterized.expand( + [ + ("some_test",), + ] + ) @requests_mock.Mocker() def test_list_roles(self, test_label, requests_mocker): expected_status_code = 200 - role_names = ['hvac'] + role_names = ["hvac"] mock_response = { - 'data': { - 'roles': role_names, + "data": { + "roles": role_names, }, } - mock_url = 'http://localhost:8200/v1/{mount_point}/roles'.format( + mock_url = "http://localhost:8200/v1/{mount_point}/roles".format( mount_point=DEFAULT_MOUNT_POINT, ) requests_mocker.register_uri( - method='LIST', + method="LIST", url=mock_url, status_code=expected_status_code, json=mock_response, ) azure = Azure(adapter=JSONAdapter()) - list_roles_response = azure.list_roles( - mount_point=DEFAULT_MOUNT_POINT - ) - logging.debug('list_roles_response: %s' % list_roles_response) + list_roles_response = azure.list_roles(mount_point=DEFAULT_MOUNT_POINT) + logging.debug("list_roles_response: %s" % list_roles_response) self.assertEqual( - first=mock_response['data'], + first=mock_response["data"], second=list_roles_response, ) - @parameterized.expand([ - ('some_test',), - ]) + @parameterized.expand( + [ + ("some_test",), + ] + ) @requests_mock.Mocker() def test_generate_credentials(self, test_label, requests_mocker): expected_status_code = 200 - role_name = 'hvac' + role_name = "hvac" mock_response = { - 'data': { - 'client_id': 'some_client_id', - 'client_secret': 'some_client_secret', + "data": { + "client_id": "some_client_id", + "client_secret": "some_client_secret", }, } - mock_url = 'http://localhost:8200/v1/{mount_point}/creds/{name}'.format( + mock_url = "http://localhost:8200/v1/{mount_point}/creds/{name}".format( mount_point=DEFAULT_MOUNT_POINT, name=role_name, ) requests_mocker.register_uri( - method='GET', + method="GET", url=mock_url, status_code=expected_status_code, json=mock_response, ) azure = Azure(adapter=JSONAdapter()) generate_credentials_response = azure.generate_credentials( - name=role_name, - mount_point=DEFAULT_MOUNT_POINT + name=role_name, mount_point=DEFAULT_MOUNT_POINT + ) + logging.debug( + "generate_credentials_response: %s" % generate_credentials_response ) - logging.debug('generate_credentials_response: %s' % generate_credentials_response) self.assertEqual( - first=mock_response['data'], + first=mock_response["data"], second=generate_credentials_response, ) diff --git a/tests/unit_tests/api/secrets_engines/test_gcp.py b/tests/unit_tests/api/secrets_engines/test_gcp.py index 28c0cee9c..8ff0e18c9 100644 --- a/tests/unit_tests/api/secrets_engines/test_gcp.py +++ b/tests/unit_tests/api/secrets_engines/test_gcp.py @@ -10,21 +10,27 @@ class TestGcp(TestCase): - TEST_MOUNT_POINT = 'gcp-test' - TEST_ROLESET_NAME = 'hvac-roleset' - TEST_PROJECT_ID = 'test-hvac' + TEST_MOUNT_POINT = "gcp-test" + TEST_ROLESET_NAME = "hvac-roleset" + TEST_PROJECT_ID = "test-hvac" - @parameterized.expand([ - param( - 'success', - ), - ]) - def test_create_or_update_roleset(self, label, secret_type='access_token', raises=False, exception_message=''): + @parameterized.expand( + [ + param( + "success", + ), + ] + ) + def test_create_or_update_roleset( + self, label, secret_type="access_token", raises=False, exception_message="" + ): bindings = { - 'resource': { - "//cloudresourcemanager.googleapis.com/projects/{project}".format(project=self.TEST_PROJECT_ID): { - "roles": ['roles/viewer'], + "resource": { + "//cloudresourcemanager.googleapis.com/projects/{project}".format( + project=self.TEST_PROJECT_ID + ): { + "roles": ["roles/viewer"], }, }, } @@ -37,14 +43,14 @@ def test_create_or_update_roleset(self, label, secret_type='access_token', raise """ bindings = dedent(bindings) token_scopes = None - if secret_type == 'access_token': + if secret_type == "access_token": token_scopes = [ - 'https://www.googleapis.com/auth/cloud-platform', - 'https://www.googleapis.com/auth/bigquery', + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/bigquery", ] gcp = Gcp(adapter=JSONAdapter()) - mock_url = 'http://localhost:8200/v1/{mount_point}/roleset/{name}'.format( + mock_url = "http://localhost:8200/v1/{mount_point}/roleset/{name}".format( mount_point=self.TEST_MOUNT_POINT, name=self.TEST_ROLESET_NAME, ) @@ -52,7 +58,7 @@ def test_create_or_update_roleset(self, label, secret_type='access_token', raise with requests_mock.mock() as requests_mocker: requests_mocker.register_uri( - method='POST', + method="POST", url=mock_url, status_code=expected_status_code, ) @@ -79,7 +85,7 @@ def test_create_or_update_roleset(self, label, secret_type='access_token', raise token_scopes=token_scopes, mount_point=self.TEST_MOUNT_POINT, ) - logging.debug('configure_response: %s' % create_or_update_response) + logging.debug("configure_response: %s" % create_or_update_response) self.assertEqual( first=create_or_update_response.status_code, second=204, diff --git a/tests/unit_tests/api/secrets_engines/test_kv.py b/tests/unit_tests/api/secrets_engines/test_kv.py index 5eba5a06a..497816690 100644 --- a/tests/unit_tests/api/secrets_engines/test_kv.py +++ b/tests/unit_tests/api/secrets_engines/test_kv.py @@ -9,7 +9,6 @@ class TestKv(TestCase): - def test_v1_property(self): mock_adapter = MagicMock() kv = Kv(adapter=mock_adapter) @@ -26,16 +25,18 @@ def test_v2_property(self): cls=KvV2, ) - @parameterized.expand([ - ('v1', '1'), - ('v2', '2'), - ('v3', '3', ValueError), - ('invalid version', '12345', ValueError), - ]) + @parameterized.expand( + [ + ("v1", "1"), + ("v2", "2"), + ("v3", "3", ValueError), + ("invalid version", "12345", ValueError), + ] + ) def test_default_kv_version_setter(self, test_label, version, raises=False): version_class_map = { - '1': KvV1, - '2': KvV2, + "1": KvV1, + "2": KvV2, } mock_adapter = MagicMock() kv = Kv(adapter=mock_adapter) @@ -46,18 +47,18 @@ def test_default_kv_version_setter(self, test_label, version, raises=False): else: kv.default_kv_version = version self.assertIsInstance( - obj=getattr(kv, 'v%s' % version), + obj=getattr(kv, "v%s" % version), cls=version_class_map.get(version), ) def test_getattr(self): mock_adapter = MagicMock() - kv = Kv(adapter=mock_adapter, default_kv_version='1') + kv = Kv(adapter=mock_adapter, default_kv_version="1") self.assertEqual( first=kv.read_secret, second=kv.v1.read_secret, ) - kv = Kv(adapter=mock_adapter, default_kv_version='2') + kv = Kv(adapter=mock_adapter, default_kv_version="2") self.assertEqual( first=kv.read_secret_version, second=kv.v2.read_secret_version, diff --git a/tests/unit_tests/api/test_vault_api_category.py b/tests/unit_tests/api/test_vault_api_category.py index be94d3e72..5945187b8 100644 --- a/tests/unit_tests/api/test_vault_api_category.py +++ b/tests/unit_tests/api/test_vault_api_category.py @@ -6,9 +6,7 @@ from hvac.api.vault_api_base import VaultApiBase from hvac.api.vault_api_category import VaultApiCategory -UNIMPLEMENTED_CLASSES = [ - 'not_implemented' -] +UNIMPLEMENTED_CLASSES = ["not_implemented"] class ImplementedVaultApiBase(VaultApiBase): @@ -16,7 +14,6 @@ class ImplementedVaultApiBase(VaultApiBase): class ImplementedVaultApiCategory(VaultApiCategory): - @property def implemented_classes(self): return [ImplementedVaultApiBase] @@ -64,7 +61,7 @@ def test_adapter_property(self): cls=Adapter, ) - new_adapter = 'this is my new adapter' + new_adapter = "this is my new adapter" self.mock_vault_api_category.adapter = new_adapter self.assertEqual( diff --git a/tests/unit_tests/test_adapters.py b/tests/unit_tests/test_adapters.py index bb73d283f..5cbe6e828 100644 --- a/tests/unit_tests/test_adapters.py +++ b/tests/unit_tests/test_adapters.py @@ -5,50 +5,51 @@ import requests_mock from parameterized import parameterized, param - +from hvac.constants.client import DEFAULT_URL from hvac import adapters class TestRequest(TestCase): """Unit tests providing coverage for requests-related methods in the hvac Client class.""" - @parameterized.expand([ - param( - "standard Vault address", - url='https://localhost:8200', - ), - param( - "Vault address with route", - url='https://example.com/vault', - ), - param( - "regression test for hvac issue #51", - url='https://localhost:8200', - path='keyring/http://some.url/sub/entry', - ), - param( - "redirect with location header for issue #343", - url='https://localhost:8200', - path='secret/some-secret', - redirect_url='https://some-other-place.com/secret/some-secret', - - ), - ]) - def test_get(self, label, url, path='v1/sys/health', redirect_url=None): - path = path.replace('//', '/') + @parameterized.expand( + [ + param( + "standard Vault address", + url="https://localhost:8200", + ), + param( + "Vault address with route", + url="https://example.com/vault", + ), + param( + "regression test for hvac issue #51", + url="https://localhost:8200", + path="keyring/http://some.url/sub/entry", + ), + param( + "redirect with location header for issue #343", + url="https://localhost:8200", + path="secret/some-secret", + redirect_url="https://some-other-place.com/secret/some-secret", + ), + ] + ) + def test_get(self, label, url, path="v1/sys/health", redirect_url=None): + path = path.replace("//", "/") expected_status_code = 200 - mock_url = '{0}/{1}'.format(url, path) + mock_url = "{0}/{1}".format(url, path) expected_request_urls = [mock_url] adapter = adapters.RawAdapter(base_uri=url) response_headers = {} response_status_code = 200 if redirect_url is not None: - response_headers['Location'] = redirect_url + response_headers["Location"] = redirect_url response_status_code = 301 with requests_mock.mock() as requests_mocker: logging.debug('Registering "mock_url": %s' % mock_url) requests_mocker.register_uri( - method='GET', + method="GET", url=mock_url, headers=response_headers, status_code=response_status_code, @@ -57,7 +58,7 @@ def test_get(self, label, url, path='v1/sys/health', redirect_url=None): expected_request_urls.append(redirect_url) logging.debug('Registering "redirect_url": %s' % redirect_url) requests_mocker.register_uri( - method='GET', + method="GET", url=redirect_url, ) @@ -69,37 +70,33 @@ def test_get(self, label, url, path='v1/sys/health', redirect_url=None): for request_num, expected_request_url in enumerate(expected_request_urls): self.assertEqual( first=expected_request_url, - second=requests_mocker.request_history[request_num].url + second=requests_mocker.request_history[request_num].url, ) self.assertEqual( first=expected_status_code, second=response.status_code, ) - @parameterized.expand([ - ("kv secret lookup", 'v1/secret/some-secret'), - ]) + @parameterized.expand( + [ + ("kv secret lookup", "v1/secret/some-secret"), + ] + ) @requests_mock.Mocker() def test_list(self, test_label, test_path, requests_mocker): mock_response = { - 'auth': None, - 'data': { - 'keys': ['things1', 'things2'] - }, - 'lease_duration': 0, - 'lease_id': '', - 'renewable': False, - 'request_id': 'ba933afe-84d4-410f-161b-592a5c016009', - 'warnings': None, - 'wrap_info': None + "auth": None, + "data": {"keys": ["things1", "things2"]}, + "lease_duration": 0, + "lease_id": "", + "renewable": False, + "request_id": "ba933afe-84d4-410f-161b-592a5c016009", + "warnings": None, + "wrap_info": None, } expected_status_code = 200 - mock_url = '{0}/{1}'.format(adapters.DEFAULT_BASE_URI, test_path) - requests_mocker.register_uri( - method='LIST', - url=mock_url, - json=mock_response - ) + mock_url = "{0}/{1}".format(DEFAULT_URL, test_path) + requests_mocker.register_uri(method="LIST", url=mock_url, json=mock_response) adapter = adapters.RawAdapter() response = adapter.list( url=test_path, @@ -108,7 +105,4 @@ def test_list(self, test_label, test_path, requests_mocker): first=expected_status_code, second=response.status_code, ) - self.assertEqual( - first=mock_response, - second=response.json() - ) + self.assertEqual(first=mock_response, second=response.json()) diff --git a/tests/unit_tests/v1/test_approle_routes.py b/tests/unit_tests/v1/test_approle_routes.py index 47242fc1f..d272c4ad3 100644 --- a/tests/unit_tests/v1/test_approle_routes.py +++ b/tests/unit_tests/v1/test_approle_routes.py @@ -9,42 +9,46 @@ class TestApproleRoutes(TestCase): """Unit tests providing coverage for approle auth backend-related methods/routes.""" - @parameterized.expand([ - ("default mount point", None, "application1"), - ("custom mount point", "my-approle-path", "application2"), - ]) + @parameterized.expand( + [ + ("default mount point", None, "application1"), + ("custom mount point", "my-approle-path", "application2"), + ] + ) @requests_mock.Mocker() def test_create_role(self, test_label, mount_point, role_name, requests_mocker): expected_status_code = 204 - mock_url = 'http://localhost:8200/v1/auth/{0}/role/{1}'.format( - 'approle' if mount_point is None else mount_point, + mock_url = "http://localhost:8200/v1/auth/{0}/role/{1}".format( + "approle" if mount_point is None else mount_point, role_name, ) requests_mocker.register_uri( - method='POST', + method="POST", url=mock_url, status_code=expected_status_code, ) client = Client() if mount_point is None: - actual_response = client.create_role( + actual_response = client.auth.approle.create_or_update_approle( role_name=role_name, ) else: - actual_response = client.create_role( + actual_response = client.auth.approle.create_or_update_approle( role_name=role_name, mount_point=mount_point, ) - self.assertEquals( + self.assertEqual( first=expected_status_code, second=actual_response.status_code, ) - @parameterized.expand([ - ("default mount point", None, "application1"), - ("custom mount point", "my-approle-path", "application2"), - ]) + @parameterized.expand( + [ + ("default mount point", None, "application1"), + ("custom mount point", "my-approle-path", "application2"), + ] + ) @requests_mock.Mocker() def test_list_roles(self, test_label, mount_point, role_name, requests_mocker): expected_status_code = 200 @@ -60,112 +64,128 @@ def test_list_roles(self, test_label, mount_point, role_name, requests_mocker): "renewable": False, "request_id": "e4c219fb-0a78-2be2-8d3c-b3715dccb920", "warnings": None, - "wrap_info": None + "wrap_info": None, } - mock_url = 'http://localhost:8200/v1/auth/{0}/role?list=true'.format( - 'approle' if mount_point is None else mount_point, + mock_url = "http://localhost:8200/v1/auth/{0}/role".format( + "approle" if mount_point is None else mount_point, ) requests_mocker.register_uri( - method='GET', + method="LIST", url=mock_url, status_code=expected_status_code, json=mock_response, ) client = Client() if mount_point is None: - actual_response = client.list_roles() + actual_response = client.auth.approle.list_roles() else: - actual_response = client.list_roles( + actual_response = client.auth.approle.list_roles( mount_point=mount_point, ) # ensure we received our mock response data back successfully self.assertEqual(mock_response, actual_response) - @parameterized.expand([ - ("default mount point", None, "application1", "40b3c82d-12a6-838c-9e74-1f1133867e06"), - ("custom mount point", "my-approle-path", "application2", "5fs3c82d-12a6-838c-9e74-1f1133867esf"), - ]) + @parameterized.expand( + [ + ( + "default mount point", + None, + "application1", + "40b3c82d-12a6-838c-9e74-1f1133867e06", + ), + ( + "custom mount point", + "my-approle-path", + "application2", + "5fs3c82d-12a6-838c-9e74-1f1133867esf", + ), + ] + ) @requests_mock.Mocker() - def test_get_role_id(self, test_label, mount_point, role_name, role_id, requests_mocker): + def test_get_role_id( + self, test_label, mount_point, role_name, role_id, requests_mocker + ): expected_status_code = 200 mock_response = { "auth": None, - "data": { - "role_id": role_id - }, + "data": {"role_id": role_id}, "lease_duration": 0, "lease_id": "", "renewable": False, "request_id": "85590a1a-6dd7-de79-01b0-1c285d505bf2", "warnings": None, - "wrap_info": None + "wrap_info": None, } - mock_url = 'http://localhost:8200/v1/auth/{0}/role/{1}/role-id'.format( - 'approle' if mount_point is None else mount_point, + mock_url = "http://localhost:8200/v1/auth/{0}/role/{1}/role-id".format( + "approle" if mount_point is None else mount_point, role_name, ) requests_mocker.register_uri( - method='GET', + method="GET", url=mock_url, status_code=expected_status_code, json=mock_response, ) client = Client() if mount_point is None: - actual_response = client.get_role_id( - role_name=role_name - ) + actual_response = client.auth.approle.read_role_id(role_name=role_name) else: - actual_response = client.get_role_id( - role_name=role_name, - mount_point=mount_point + actual_response = client.auth.approle.read_role_id( + role_name=role_name, mount_point=mount_point ) # ensure we received our mock response data back successfully - self.assertEqual( - first=role_id, - second=actual_response - ) - - @parameterized.expand([ - ("default mount point", None, "application1", "custom-role-id-1"), - ("custom mount point", "my-approle-path", "application2", "custom-role-id-2"), - ]) + self.assertEqual(first=role_id, second=actual_response["data"]["role_id"]) + + @parameterized.expand( + [ + ("default mount point", None, "application1", "custom-role-id-1"), + ( + "custom mount point", + "my-approle-path", + "application2", + "custom-role-id-2", + ), + ] + ) @requests_mock.Mocker() - def test_set_role_id(self, test_label, mount_point, role_name, role_id, requests_mocker): + def test_set_role_id( + self, test_label, mount_point, role_name, role_id, requests_mocker + ): expected_status_code = 204 - mock_url = 'http://localhost:8200/v1/auth/{0}/role/{1}/role-id'.format( - 'approle' if mount_point is None else mount_point, + mock_url = "http://localhost:8200/v1/auth/{0}/role/{1}/role-id".format( + "approle" if mount_point is None else mount_point, role_name, ) requests_mocker.register_uri( - method='POST', + method="POST", url=mock_url, status_code=expected_status_code, ) client = Client() if mount_point is None: - actual_response = client.set_role_id( - role_name=role_name, - role_id=role_id + actual_response = client.auth.approle.update_role_id( + role_name=role_name, role_id=role_id ) else: - actual_response = client.set_role_id( + actual_response = client.auth.approle.update_role_id( role_name=role_name, role_id=role_id, mount_point=mount_point, ) - self.assertEquals( + self.assertEqual( first=expected_status_code, second=actual_response.status_code, ) - @parameterized.expand([ - ("default mount point", None, "application1"), - ("custom mount point", "my-approle-path", "application2"), - ]) + @parameterized.expand( + [ + ("default mount point", None, "application1"), + ("custom mount point", "my-approle-path", "application2"), + ] + ) @requests_mock.Mocker() def test_get_role(self, test_label, mount_point, role_name, requests_mocker): expected_status_code = 200 @@ -175,101 +195,117 @@ def test_get_role(self, test_label, mount_point, role_name, requests_mocker): "bind_secret_id": True, "bound_cidr_list": "", "period": 0, - "policies": [ - "default" - ], + "policies": ["default"], "secret_id_num_uses": 0, "secret_id_ttl": 0, "token_max_ttl": 900, "token_num_uses": 0, - "token_ttl": 600 + "token_ttl": 600, }, "lease_duration": 0, "lease_id": "", "renewable": False, "request_id": "0aab655f-ecd2-b3d4-3817-35b5bdfd3f28", "warnings": None, - "wrap_info": None + "wrap_info": None, } - mock_url = 'http://localhost:8200/v1/auth/{0}/role/{1}'.format( - 'approle' if mount_point is None else mount_point, + mock_url = "http://localhost:8200/v1/auth/{0}/role/{1}".format( + "approle" if mount_point is None else mount_point, role_name, ) requests_mocker.register_uri( - method='GET', + method="GET", url=mock_url, status_code=expected_status_code, json=mock_response, ) client = Client() if mount_point is None: - actual_response = client.get_role( + actual_response = client.auth.approle.read_role( role_name=role_name, ) else: - actual_response = client.get_role( + actual_response = client.auth.approle.read_role( role_name=role_name, mount_point=mount_point, ) - self.assertEquals( + self.assertEqual( first=mock_response, second=actual_response, ) - @parameterized.expand([ - ("default mount point", None, "application1"), - ("custom mount point", "my-approle-path", "application2"), - ]) + @parameterized.expand( + [ + ("default mount point", None, "application1"), + ("custom mount point", "my-approle-path", "application2"), + ] + ) @requests_mock.Mocker() - def test_create_role_secret_id(self, test_label, mount_point, role_name, requests_mocker): + def test_create_role_secret_id( + self, test_label, mount_point, role_name, requests_mocker + ): expected_status_code = 200 mock_response = { "auth": None, "data": { "secret_id": "be78e3ca-f644-b099-3291-e8a6f5985cfe", - "secret_id_accessor": "b58fd0ee-130c-33bb-5f69-6d4fd1731e5f" + "secret_id_accessor": "b58fd0ee-130c-33bb-5f69-6d4fd1731e5f", }, "lease_duration": 0, "lease_id": "", "renewable": False, "request_id": "2310dc21-0fea-a2de-2d94-bb4edd59f1e9", "warnings": None, - "wrap_info": None + "wrap_info": None, } - mock_url = 'http://localhost:8200/v1/auth/{0}/role/{1}/secret-id'.format( - 'approle' if mount_point is None else mount_point, + mock_url = "http://localhost:8200/v1/auth/{0}/role/{1}/secret-id".format( + "approle" if mount_point is None else mount_point, role_name, ) requests_mocker.register_uri( - method='POST', + method="POST", url=mock_url, status_code=expected_status_code, json=mock_response, ) client = Client() if mount_point is None: - actual_response = client.create_role_secret_id( + actual_response = client.auth.approle.generate_secret_id( role_name=role_name, ) else: - actual_response = client.create_role_secret_id( + actual_response = client.auth.approle.generate_secret_id( role_name=role_name, mount_point=mount_point, ) - self.assertEquals( + self.assertEqual( first=mock_response, second=actual_response, ) - @parameterized.expand([ - ("default mount point", None, "application1", "be78e3ca-f644-b099-3291-e8a6f5985cfe"), - ("custom mount point", "my-approle-path", "application2", "ce78e3ca-f644-b099-3291-e8a6f5985cfe"), - ]) + @parameterized.expand( + [ + ( + "default mount point", + None, + "application1", + "be78e3ca-f644-b099-3291-e8a6f5985cfe", + ), + ( + "custom mount point", + "my-approle-path", + "application2", + "ce78e3ca-f644-b099-3291-e8a6f5985cfe", + ), + ] + ) @requests_mock.Mocker() - def test_get_role_secret_id(self, test_label, mount_point, role_name, secret_id, requests_mocker): + def test_get_role_secret_id( + self, test_label, mount_point, role_name, secret_id, requests_mocker + ): expected_status_code = 200 mock_response = { "auth": None, @@ -282,97 +318,121 @@ def test_get_role_secret_id(self, test_label, mount_point, role_name, secret_id, "metadata": {}, "secret_id_accessor": "b58fd0ee-130c-33bb-5f69-6d4fd1731e5f", "secret_id_num_uses": 0, - "secret_id_ttl": 0 + "secret_id_ttl": 0, }, "lease_duration": 0, "lease_id": "", "renewable": False, "request_id": "718a00fa-e76f-f1fc-9b9e-f9c4baa766b3", - "wrap_info": None + "wrap_info": None, } - mock_url = 'http://localhost:8200/v1/auth/{0}/role/{1}/secret-id/lookup'.format( - 'approle' if mount_point is None else mount_point, + mock_url = "http://localhost:8200/v1/auth/{0}/role/{1}/secret-id/lookup".format( + "approle" if mount_point is None else mount_point, role_name, ) requests_mocker.register_uri( - method='POST', + method="POST", url=mock_url, status_code=expected_status_code, json=mock_response, ) client = Client() if mount_point is None: - actual_response = client.get_role_secret_id( + actual_response = client.auth.approle.read_secret_id( role_name=role_name, secret_id=secret_id, ) else: - actual_response = client.get_role_secret_id( + actual_response = client.auth.approle.read_secret_id( role_name=role_name, secret_id=secret_id, mount_point=mount_point, ) - self.assertEquals( + self.assertEqual( first=mock_response, second=actual_response, ) - @parameterized.expand([ - ("default mount point", None, "application1", "be78e3ca-f644-b099-3291-e8a6f5985cfe"), - ("custom mount point", "my-approle-path", "application2", "ce78e3ca-f644-b099-3291-e8a6f5985cfe"), - ]) + @parameterized.expand( + [ + ( + "default mount point", + None, + "application1", + "be78e3ca-f644-b099-3291-e8a6f5985cfe", + ), + ( + "custom mount point", + "my-approle-path", + "application2", + "ce78e3ca-f644-b099-3291-e8a6f5985cfe", + ), + ] + ) @requests_mock.Mocker() - def test_list_role_secrets(self, test_label, mount_point, role_name, secret_id, requests_mocker): + def test_list_role_secrets( + self, test_label, mount_point, role_name, secret_id, requests_mocker + ): expected_status_code = 200 mock_response = { "auth": None, - "data": { - "keys": [ - secret_id - ] - }, + "data": {"keys": [secret_id]}, "lease_duration": 0, "lease_id": "", "renewable": False, "request_id": "eb805845-f6ce-a514-9238-6914664dd601", "warnings": None, - "wrap_info": None + "wrap_info": None, } - mock_url = 'http://localhost:8200/v1/auth/{0}/role/{1}/secret-id'.format( - 'approle' if mount_point is None else mount_point, + mock_url = "http://localhost:8200/v1/auth/{0}/role/{1}/secret-id".format( + "approle" if mount_point is None else mount_point, role_name, ) requests_mocker.register_uri( - method='LIST', + method="LIST", url=mock_url, status_code=expected_status_code, json=mock_response, ) client = Client() if mount_point is None: - actual_response = client.list_role_secrets( + actual_response = client.auth.approle.list_secret_id_accessors( role_name=role_name, ) else: - actual_response = client.list_role_secrets( + actual_response = client.auth.approle.list_secret_id_accessors( role_name=role_name, mount_point=mount_point, ) - self.assertEquals( + self.assertEqual( first=mock_response, second=actual_response, ) - @parameterized.expand([ - ("default mount point", None, "application1", "be78e3ca-f644-b099-3291-e8a6f5985cfe"), - ("custom mount point", "my-approle-path", "application2", "ce78e3ca-f644-b099-3291-e8a6f5985cfe"), - ]) + @parameterized.expand( + [ + ( + "default mount point", + None, + "application1", + "be78e3ca-f644-b099-3291-e8a6f5985cfe", + ), + ( + "custom mount point", + "my-approle-path", + "application2", + "ce78e3ca-f644-b099-3291-e8a6f5985cfe", + ), + ] + ) @requests_mock.Mocker() - def test_get_role_secret_id_accessor(self, test_label, mount_point, role_name, secret_id_accessor, requests_mocker): + def test_get_role_secret_id_accessor( + self, test_label, mount_point, role_name, secret_id_accessor, requests_mocker + ): expected_status_code = 200 mock_response = { "auth": None, @@ -385,180 +445,234 @@ def test_get_role_secret_id_accessor(self, test_label, mount_point, role_name, s "metadata": {}, "secret_id_accessor": secret_id_accessor, "secret_id_num_uses": 0, - "secret_id_ttl": 0 + "secret_id_ttl": 0, }, "lease_duration": 0, "lease_id": "", "renewable": False, "request_id": "2c9fcba6-425d-e4c0-45fa-ee90450a3c00", - "wrap_info": None + "wrap_info": None, } - mock_url = 'http://localhost:8200/v1/auth/{0}/role/{1}/secret-id-accessor/lookup'.format( - 'approle' if mount_point is None else mount_point, + mock_url = "http://localhost:8200/v1/auth/{0}/role/{1}/secret-id-accessor/lookup".format( + "approle" if mount_point is None else mount_point, role_name, ) requests_mocker.register_uri( - method='POST', + method="POST", url=mock_url, status_code=expected_status_code, json=mock_response, ) client = Client() if mount_point is None: - actual_response = client.get_role_secret_id_accessor( + actual_response = client.auth.approle.read_secret_id_accessor( role_name=role_name, secret_id_accessor=secret_id_accessor, ) else: - actual_response = client.get_role_secret_id_accessor( + actual_response = client.auth.approle.read_secret_id_accessor( role_name=role_name, secret_id_accessor=secret_id_accessor, mount_point=mount_point, ) - self.assertEquals( + self.assertEqual( first=mock_response, second=actual_response, ) - @parameterized.expand([ - ("default mount point", None, "application1", "be78e3ca-f644-b099-3291-e8a6f5985cfe"), - ("custom mount point", "my-approle-path", "application2", "ce78e3ca-f644-b099-3291-e8a6f5985cfe"), - ]) + @parameterized.expand( + [ + ( + "default mount point", + None, + "application1", + "be78e3ca-f644-b099-3291-e8a6f5985cfe", + ), + ( + "custom mount point", + "my-approle-path", + "application2", + "ce78e3ca-f644-b099-3291-e8a6f5985cfe", + ), + ] + ) @requests_mock.Mocker() - def test_delete_role_secret_id(self, test_label, mount_point, role_name, secret_id, requests_mocker): + def test_delete_role_secret_id( + self, test_label, mount_point, role_name, secret_id, requests_mocker + ): expected_status_code = 204 - mock_url = 'http://localhost:8200/v1/auth/{0}/role/{1}/secret-id/destroy'.format( - 'approle' if mount_point is None else mount_point, - role_name, + mock_url = ( + "http://localhost:8200/v1/auth/{0}/role/{1}/secret-id/destroy".format( + "approle" if mount_point is None else mount_point, + role_name, + ) ) requests_mocker.register_uri( - method='POST', + method="POST", url=mock_url, status_code=expected_status_code, ) client = Client() if mount_point is None: - actual_response = client.delete_role_secret_id( + actual_response = client.auth.approle.destroy_secret_id( role_name=role_name, secret_id=secret_id, ) else: - actual_response = client.delete_role_secret_id( + actual_response = client.auth.approle.destroy_secret_id( role_name=role_name, secret_id=secret_id, mount_point=mount_point, ) - self.assertEquals( + self.assertEqual( first=expected_status_code, second=actual_response.status_code, ) - @parameterized.expand([ - ("default mount point", None, "application1", "be78e3ca-f644-b099-3291-e8a6f5985cfe"), - ("custom mount point", "my-approle-path", "application2", "ce78e3ca-f644-b099-3291-e8a6f5985cfe"), - ]) + @parameterized.expand( + [ + ( + "default mount point", + None, + "application1", + "be78e3ca-f644-b099-3291-e8a6f5985cfe", + ), + ( + "custom mount point", + "my-approle-path", + "application2", + "ce78e3ca-f644-b099-3291-e8a6f5985cfe", + ), + ] + ) @requests_mock.Mocker() - def test_delete_role_secret_id_accessor(self, test_label, mount_point, role_name, secret_id_accessor, requests_mocker): + def test_delete_role_secret_id_accessor( + self, test_label, mount_point, role_name, secret_id_accessor, requests_mocker + ): expected_status_code = 204 - mock_url = 'http://localhost:8200/v1/auth/{0}/role/{1}/secret-id-accessor/destroy'.format( - 'approle' if mount_point is None else mount_point, + mock_url = "http://localhost:8200/v1/auth/{0}/role/{1}/secret-id-accessor/destroy".format( + "approle" if mount_point is None else mount_point, role_name, ) requests_mocker.register_uri( - method='POST', + method="POST", url=mock_url, status_code=expected_status_code, ) client = Client() if mount_point is None: - actual_response = client.delete_role_secret_id_accessor( + actual_response = client.auth.approle.destroy_secret_id_accessor( role_name=role_name, secret_id_accessor=secret_id_accessor, ) else: - actual_response = client.delete_role_secret_id_accessor( + actual_response = client.auth.approle.destroy_secret_id_accessor( role_name=role_name, secret_id_accessor=secret_id_accessor, mount_point=mount_point, ) - self.assertEquals( + self.assertEqual( first=expected_status_code, second=actual_response.status_code, ) - @parameterized.expand([ - ("default mount point", None, "application1", "be78e3ca-f644-b099-3291-e8a6f5985cfe"), - ("custom mount point", "my-approle-path", "application2", "ce78e3ca-f644-b099-3291-e8a6f5985cfe"), - ]) + @parameterized.expand( + [ + ( + "default mount point", + None, + "application1", + "be78e3ca-f644-b099-3291-e8a6f5985cfe", + ), + ( + "custom mount point", + "my-approle-path", + "application2", + "ce78e3ca-f644-b099-3291-e8a6f5985cfe", + ), + ] + ) @requests_mock.Mocker() - def test_create_role_custom_secret_id(self, test_label, mount_point, role_name, secret_id, requests_mocker): + def test_create_role_custom_secret_id( + self, test_label, mount_point, role_name, secret_id, requests_mocker + ): expected_status_code = 200 mock_response = { "auth": None, "data": { "secret_id": secret_id, - "secret_id_accessor": "f5cb4b7d-9111-320e-6f24-73bf45d3845d" + "secret_id_accessor": "f5cb4b7d-9111-320e-6f24-73bf45d3845d", }, "lease_duration": 0, "lease_id": "", "renewable": False, "request_id": "e7c8b2e1-95e8-cb17-e98a-6c428201f1d5", "warnings": None, - "wrap_info": None + "wrap_info": None, } - mock_url = 'http://localhost:8200/v1/auth/{0}/role/{1}/custom-secret-id'.format( - 'approle' if mount_point is None else mount_point, + mock_url = "http://localhost:8200/v1/auth/{0}/role/{1}/custom-secret-id".format( + "approle" if mount_point is None else mount_point, role_name, ) requests_mocker.register_uri( - method='POST', + method="POST", url=mock_url, status_code=expected_status_code, json=mock_response, ) client = Client() if mount_point is None: - actual_response = client.create_role_custom_secret_id( + actual_response = client.auth.approle.create_custom_secret_id( role_name=role_name, secret_id=secret_id, ) else: - actual_response = client.create_role_custom_secret_id( + actual_response = client.auth.approle.create_custom_secret_id( role_name=role_name, secret_id=secret_id, mount_point=mount_point, ) - self.assertEquals( + self.assertEqual( first=mock_response, second=actual_response, ) - @parameterized.expand([ - ("default mount point", None, "c7f93182-c6b1-4b6a-9dfb-03bdb6df0026", "26089502-b7d3-412a-b3e6-3d44300f9bd1"), - ("custom mount point", "my-approle-path", "cf6b7c2e-3866-48f8-a764-3bcb5782a85a", "7156c666-0491-4c49-af40-7a97300fbaff"), - ]) + @parameterized.expand( + [ + ( + "default mount point", + None, + "c7f93182-c6b1-4b6a-9dfb-03bdb6df0026", + "26089502-b7d3-412a-b3e6-3d44300f9bd1", + ), + ( + "custom mount point", + "my-approle-path", + "cf6b7c2e-3866-48f8-a764-3bcb5782a85a", + "7156c666-0491-4c49-af40-7a97300fbaff", + ), + ] + ) @requests_mock.Mocker() - def test_auth_approle(self, test_label, mount_point, role_id, secret_id, requests_mocker): + def test_auth_approle( + self, test_label, mount_point, role_id, secret_id, requests_mocker + ): expected_status_code = 200 mock_response = { "auth": { "accessor": "f8b576f9-9146-4173-e174-40257d58015a", "client_token": "3db3d089-7d3c-f531-cd3e-bfe44696a92c", "lease_duration": 600, - "metadata": { - "role_name": "application1" - }, - "policies": [ - "default" - ], - "renewable": True + "metadata": {"role_name": "application1"}, + "policies": ["default"], + "renewable": True, }, "data": None, "lease_duration": 0, @@ -566,31 +680,31 @@ def test_auth_approle(self, test_label, mount_point, role_id, secret_id, request "renewable": False, "request_id": "2eb635ad-a763-926a-9815-4cb4d14a40f9", "warnings": None, - "wrap_info": None + "wrap_info": None, } - mock_url = 'http://localhost:8200/v1/auth/{0}/login'.format( - 'approle' if mount_point is None else mount_point, + mock_url = "http://localhost:8200/v1/auth/{0}/login".format( + "approle" if mount_point is None else mount_point, ) requests_mocker.register_uri( - method='POST', + method="POST", url=mock_url, status_code=expected_status_code, json=mock_response, ) client = Client() if mount_point is None: - actual_response = client.auth_approle( + actual_response = client.auth.approle.login( role_id=role_id, secret_id=secret_id, ) else: - actual_response = client.auth_approle( + actual_response = client.auth.approle.login( role_id=role_id, secret_id=secret_id, mount_point=mount_point, ) - self.assertEquals( + self.assertEqual( first=mock_response, second=actual_response, ) diff --git a/tests/unit_tests/v1/test_auth_methods.py b/tests/unit_tests/v1/test_auth_methods.py index 4d0d49edb..8887eb35f 100644 --- a/tests/unit_tests/v1/test_auth_methods.py +++ b/tests/unit_tests/v1/test_auth_methods.py @@ -11,18 +11,16 @@ class TestAuthMethods(TestCase): @requests_mock.Mocker() def test_tune_auth_backend(self, requests_mocker): expected_status_code = 204 - test_backend_type = 'approle' - test_mount_point = 'approle-test' - test_description = 'this is a test description' + test_mount_point = "approle-test" + test_description = "this is a test description" requests_mocker.register_uri( - method='POST', - url='http://localhost:8200/v1/sys/auth/{0}/tune'.format(test_mount_point), + method="POST", + url="http://localhost:8200/v1/sys/auth/{0}/tune".format(test_mount_point), status_code=expected_status_code, ) client = Client() - actual_response = client.tune_auth_backend( - backend_type=test_backend_type, - mount_point=test_mount_point, + actual_response = client.sys.tune_auth_method( + path=test_mount_point, description=test_description, ) @@ -36,41 +34,39 @@ def test_tune_auth_backend(self, requests_mocker): # Ensure we sent through an optional tune parameter as expected self.assertEqual( first=test_description, - second=actual_request_params['description'], + second=actual_request_params["description"], ) @requests_mock.Mocker() def test_get_auth_backend_tuning(self, requests_mocker): expected_status_code = 200 - test_backend_type = 'approle' - test_mount_point = 'approle-test' + test_mount_point = "approle-test" mock_response = { - 'max_lease_ttl': 12345678, - 'lease_id': '', - 'force_no_cache': False, - 'warnings': None, - 'data': { - 'force_no_cache': False, - 'default_lease_ttl': 2764800, - 'max_lease_ttl': 12345678 + "max_lease_ttl": 12345678, + "lease_id": "", + "force_no_cache": False, + "warnings": None, + "data": { + "force_no_cache": False, + "default_lease_ttl": 2764800, + "max_lease_ttl": 12345678, }, - 'wrap_info': None, - 'auth': None, - 'lease_duration': 0, - 'request_id': '673f2336-3235-b988-2194-c68261a02bfe', - 'default_lease_ttl': 2764800, - 'renewable': False + "wrap_info": None, + "auth": None, + "lease_duration": 0, + "request_id": "673f2336-3235-b988-2194-c68261a02bfe", + "default_lease_ttl": 2764800, + "renewable": False, } requests_mocker.register_uri( - method='GET', - url='http://localhost:8200/v1/sys/auth/{0}/tune'.format(test_mount_point), + method="GET", + url="http://localhost:8200/v1/sys/auth/{0}/tune".format(test_mount_point), status_code=expected_status_code, - json=mock_response + json=mock_response, ) client = Client() - actual_response = client.get_auth_backend_tuning( - backend_type=test_backend_type, - mount_point=test_mount_point, + actual_response = client.sys.read_auth_method_tuning( + path=test_mount_point, ) self.assertEqual( diff --git a/tests/unit_tests/v1/test_aws_ec2_methods.py b/tests/unit_tests/v1/test_aws_ec2_methods.py index 750ea12b7..9cefa2740 100644 --- a/tests/unit_tests/v1/test_aws_ec2_methods.py +++ b/tests/unit_tests/v1/test_aws_ec2_methods.py @@ -9,121 +9,118 @@ class TestAwsEc2Methods(TestCase): """Unit tests providing coverage for AWS (EC2) auth backend-related methods/routes.""" - @parameterized.expand([ - ("default mount point", None), - ("custom mount point", 'aws-ec2'), - ]) + @parameterized.expand( + [ + ("default mount point", None), + ("custom mount point", "aws"), + ] + ) @requests_mock.Mocker() def test_auth_ec2(self, test_label, mount_point, requests_mocker): mock_response = { - 'auth': { - 'accessor': 'accessor-1234-5678-9012-345678901234', - 'client_token': 'cltoken-1234-5678-9012-345678901234', - 'lease_duration': 10000, - 'metadata': { - 'account_id': '12345678912', - 'ami_id': 'ami-someami', - 'instance_id': 'i-instanceid', - 'nonce': 'thenonce-1234-5678-9012-345678901234', - 'region': 'us-east-1', - 'role': 'custom_role', - 'role_tag_max_ttl': '0s' + "auth": { + "accessor": "accessor-1234-5678-9012-345678901234", + "client_token": "cltoken-1234-5678-9012-345678901234", + "lease_duration": 10000, + "metadata": { + "account_id": "12345678912", + "ami_id": "ami-someami", + "instance_id": "i-instanceid", + "nonce": "thenonce-1234-5678-9012-345678901234", + "region": "us-east-1", + "role": "custom_role", + "role_tag_max_ttl": "0s", }, - 'policies': [ - 'default', - 'custom_role' - ], - 'renewable': True + "policies": ["default", "custom_role"], + "renewable": True, }, - 'data': None, - 'lease_duration': 0, - 'lease_id': '', - 'renewable': False, - 'request_id': 'requesti-1234-5678-9012-345678901234', - 'warnings': [], - 'wrap_info': None + "data": None, + "lease_duration": 0, + "lease_id": "", + "renewable": False, + "request_id": "requesti-1234-5678-9012-345678901234", + "warnings": [], + "wrap_info": None, } - mock_url = 'http://localhost:8200/v1/auth/{0}/login'.format( - 'aws-ec2' if mount_point is None else mount_point - ) - requests_mocker.register_uri( - method='POST', - url=mock_url, - json=mock_response + mock_url = "http://localhost:8200/v1/auth/{0}/login".format( + "aws" if mount_point is None else mount_point ) + requests_mocker.register_uri(method="POST", url=mock_url, json=mock_response) client = Client() if mount_point is None: - actual_response = client.auth_ec2( - pkcs7='mock_pcks7' - ) + actual_response = client.auth.aws.ec2_login(pkcs7="mock_pcks7") else: - actual_response = client.auth_ec2( - pkcs7='mock_pcks7', - mount_point=mount_point + actual_response = client.auth.aws.ec2_login( + pkcs7="mock_pcks7", mount_point=mount_point ) # ensure we received our mock response data back successfully self.assertEqual(mock_response, actual_response) - @parameterized.expand([ - ("default mount point", None), - ("custom mount point", 'aws-ec2'), - ]) + @parameterized.expand( + [ + ("default mount point", None), + ("custom mount point", "aws"), + ] + ) @requests_mock.Mocker() - def test_create_vault_ec2_client_configuration(self, test_label, mount_point, requests_mocker): - test_access_key = 'AKIAABCDEFGUE1234567' - test_secret_key = 'thisisasecretyall' + def test_create_vault_ec2_client_configuration( + self, test_label, mount_point, requests_mocker + ): + test_access_key = "AKIAABCDEFGUE1234567" + test_secret_key = "thisisasecretyall" expected_status_code = 204 - mock_url = 'http://localhost:8200/v1/auth/{0}/config/client'.format( - 'aws-ec2' if mount_point is None else mount_point + mock_url = "http://localhost:8200/v1/auth/{0}/config/client".format( + "aws" if mount_point is None else mount_point ) requests_mocker.register_uri( - method='POST', + method="POST", url=mock_url, status_code=expected_status_code, ) client = Client() if mount_point is None: - actual_response = client.create_vault_ec2_client_configuration( + actual_response = client.auth.aws.configure( access_key=test_access_key, secret_key=test_secret_key, ) else: - actual_response = client.create_vault_ec2_client_configuration( + actual_response = client.auth.aws.configure( access_key=test_access_key, secret_key=test_secret_key, - mount_point=mount_point + mount_point=mount_point, ) - self.assertEqual( - first=expected_status_code, - second=actual_response.status_code - ) + self.assertEqual(first=expected_status_code, second=actual_response.status_code) - @parameterized.expand([ - ("default mount point", None), - ("custom mount point", 'aws-ec2'), - ]) + @parameterized.expand( + [ + ("default mount point", None), + ("custom mount point", "aws"), + ] + ) @requests_mock.Mocker() - def test_get_vault_ec2_client_configuration(self, test_label, mount_point, requests_mocker): + def test_get_vault_ec2_client_configuration( + self, test_label, mount_point, requests_mocker + ): mock_response = { - "data": { - "secret_key": "vCtSM8ZUEQ3mOFVlYPBQkf2sO6F/W7a5TVzrl3Oj", - "access_key": "VKIAJBRHKH6EVTTNXDHA", - "endpoint": "", - "iam_endpoint": "", - "sts_endpoint": "", - "iam_server_id_header_value": "" - } + "data": { + "secret_key": "vCtSM8ZUEQ3mOFVlYPBQkf2sO6F/W7a5TVzrl3Oj", + "access_key": "VKIAJBRHKH6EVTTNXDHA", + "endpoint": "", + "iam_endpoint": "", + "sts_endpoint": "", + "iam_server_id_header_value": "", + } } expected_status_code = 200 - mock_url = 'http://localhost:8200/v1/auth/{0}/config/client'.format( - 'aws-ec2' if mount_point is None else mount_point + mock_url = "http://localhost:8200/v1/auth/{0}/config/client".format( + "aws" if mount_point is None else mount_point ) requests_mocker.register_uri( - method='GET', + method="GET", url=mock_url, json=mock_response, status_code=expected_status_code, @@ -131,75 +128,79 @@ def test_get_vault_ec2_client_configuration(self, test_label, mount_point, reque client = Client() if mount_point is None: - actual_response = client.get_vault_ec2_client_configuration() + actual_response = client.auth.aws.read_config() else: - actual_response = client.get_vault_ec2_client_configuration( - mount_point=mount_point - ) + actual_response = client.auth.aws.read_config(mount_point=mount_point) self.assertEqual( - first=mock_response, + first=mock_response.get("data"), second=actual_response, ) - @parameterized.expand([ - ("default mount point", None), - ("custom mount point", 'aws-ec2'), - ]) + @parameterized.expand( + [ + ("default mount point", None), + ("custom mount point", "aws"), + ] + ) @requests_mock.Mocker() - def test_delete_vault_ec2_client_configuration(self, test_label, mount_point, requests_mocker): + def test_delete_vault_ec2_client_configuration( + self, test_label, mount_point, requests_mocker + ): expected_status_code = 204 - mock_url = 'http://localhost:8200/v1/auth/{0}/config/client'.format( - 'aws-ec2' if mount_point is None else mount_point + mock_url = "http://localhost:8200/v1/auth/{0}/config/client".format( + "aws" if mount_point is None else mount_point ) requests_mocker.register_uri( - method='DELETE', + method="DELETE", url=mock_url, status_code=expected_status_code, ) client = Client() if mount_point is None: - actual_response = client.delete_vault_ec2_client_configuration() + actual_response = client.auth.aws.delete_config() else: - actual_response = client.delete_vault_ec2_client_configuration( - mount_point=mount_point - ) + actual_response = client.auth.aws.delete_config(mount_point=mount_point) self.assertEqual( first=expected_status_code, second=actual_response.status_code, ) - @parameterized.expand([ - ("default mount point", None, 'my-cool-cert-1'), - ("custom mount point", 'aws-ec2', 'my-cool-cert-2'), - ]) + @parameterized.expand( + [ + ("default mount point", None, "my-cool-cert-1"), + ("custom mount point", "aws", "my-cool-cert-2"), + ] + ) @requests_mock.Mocker() - def test_create_vault_ec2_certificate_configuration(self, test_label, mount_point, cert_name, requests_mocker): - test_cert_info = 'this is some test cert info' + def test_create_vault_ec2_certificate_configuration( + self, test_label, mount_point, cert_name, requests_mocker + ): + test_cert_info = "this is some test cert info" expected_status_code = 204 - mock_url = 'http://localhost:8200/v1/auth/{0}/config/certificate/{1}'.format( - 'aws-ec2' if mount_point is None else mount_point, + mock_url = "http://localhost:8200/v1/auth/{0}/config/certificate/{1}".format( + "aws" if mount_point is None else mount_point, cert_name, ) requests_mocker.register_uri( - method='POST', + method="POST", url=mock_url, status_code=expected_status_code, ) client = Client() if mount_point is None: - actual_response = client.create_vault_ec2_certificate_configuration( + actual_response = client.auth.aws.create_certificate_configuration( cert_name=cert_name, aws_public_cert=test_cert_info, ) else: - actual_response = client.create_vault_ec2_certificate_configuration( + actual_response = client.auth.aws.create_certificate_configuration( cert_name=cert_name, aws_public_cert=test_cert_info, - mount_point=mount_point + mount_point=mount_point, ) self.assertEqual( @@ -207,25 +208,29 @@ def test_create_vault_ec2_certificate_configuration(self, test_label, mount_poin second=actual_response.status_code, ) - @parameterized.expand([ - ("default mount point", None, 'my-cool-cert-1'), - ("custom mount point", 'aws-ec2', 'my-cool-cert-2'), - ]) + @parameterized.expand( + [ + ("default mount point", None, "my-cool-cert-1"), + ("custom mount point", "aws", "my-cool-cert-2"), + ] + ) @requests_mock.Mocker() - def test_get_vault_ec2_certificate_configuration(self, test_label, mount_point, cert_name, requests_mocker): + def test_get_vault_ec2_certificate_configuration( + self, test_label, mount_point, cert_name, requests_mocker + ): mock_response = { "data": { "aws_public_cert": "-----BEGIN CERTIFICATE-----\nblah blah9K\n-----END CERTIFICATE-----\n", - "type": "pkcs7" + "type": "pkcs7", } } expected_status_code = 200 - mock_url = 'http://localhost:8200/v1/auth/{0}/config/certificate/{1}'.format( - 'aws-ec2' if mount_point is None else mount_point, + mock_url = "http://localhost:8200/v1/auth/{0}/config/certificate/{1}".format( + "aws" if mount_point is None else mount_point, cert_name, ) requests_mocker.register_uri( - method='GET', + method="GET", url=mock_url, json=mock_response, status_code=expected_status_code, @@ -233,40 +238,37 @@ def test_get_vault_ec2_certificate_configuration(self, test_label, mount_point, client = Client() if mount_point is None: - actual_response = client.get_vault_ec2_certificate_configuration( + actual_response = client.auth.aws.read_certificate_configuration( cert_name=cert_name, ) else: - actual_response = client.get_vault_ec2_certificate_configuration( - cert_name=cert_name, - mount_point=mount_point + actual_response = client.auth.aws.read_certificate_configuration( + cert_name=cert_name, mount_point=mount_point ) self.assertEqual( - first=mock_response, + first=mock_response.get("data"), second=actual_response, ) - @parameterized.expand([ - ("default mount point", None), - ("custom mount point", 'aws-ec2'), - ]) + @parameterized.expand( + [ + ("default mount point", None), + ("custom mount point", "aws"), + ] + ) @requests_mock.Mocker() - def test_list_vault_ec2_certificate_configurations(self, test_label, mount_point, requests_mocker): - mock_response = { - "data": { - "keys": [ - "cert1" - ] - } - } + def test_list_vault_ec2_certificate_configurations( + self, test_label, mount_point, requests_mocker + ): + mock_response = {"data": {"keys": ["cert1"]}} expected_status_code = 200 - mock_url = 'http://localhost:8200/v1/auth/{0}/config/certificates?list=true'.format( - 'aws-ec2' if mount_point is None else mount_point, + mock_url = "http://localhost:8200/v1/auth/{0}/config/certificates".format( + "aws" if mount_point is None else mount_point, ) requests_mocker.register_uri( - method='GET', + method="LIST", url=mock_url, json=mock_response, status_code=expected_status_code, @@ -274,43 +276,42 @@ def test_list_vault_ec2_certificate_configurations(self, test_label, mount_point client = Client() if mount_point is None: - actual_response = client.list_vault_ec2_certificate_configurations() + actual_response = client.auth.aws.list_certificate_configurations() else: - actual_response = client.list_vault_ec2_certificate_configurations( + actual_response = client.auth.aws.list_certificate_configurations( mount_point=mount_point ) self.assertEqual( - first=mock_response, + first=mock_response.get("data"), second=actual_response, ) - @parameterized.expand([ - ("default mount point", None, 'my-role-1'), - ("custom mount point", 'aws-ec2', 'my-role-2'), - ]) + @parameterized.expand( + [ + ("default mount point", None, "my-role-1"), + ("custom mount point", "aws", "my-role-2"), + ] + ) @requests_mock.Mocker() def test_create_ec2_role(self, test_label, mount_point, role_name, requests_mocker): expected_status_code = 204 - mock_url = 'http://localhost:8200/v1/auth/{0}/role/{1}'.format( - 'aws-ec2' if mount_point is None else mount_point, + mock_url = "http://localhost:8200/v1/auth/{0}/role/{1}".format( + "aws" if mount_point is None else mount_point, role_name, ) requests_mocker.register_uri( - method='POST', + method="POST", url=mock_url, status_code=expected_status_code, ) client = Client() if mount_point is None: - actual_response = client.create_ec2_role( - role=role_name - ) + actual_response = client.auth.aws.create_role(role=role_name) else: - actual_response = client.create_ec2_role( - role=role_name, - mount_point=mount_point + actual_response = client.auth.aws.create_role( + role=role_name, mount_point=mount_point ) self.assertEqual( @@ -318,33 +319,31 @@ def test_create_ec2_role(self, test_label, mount_point, role_name, requests_mock second=actual_response.status_code, ) - @parameterized.expand([ - ("default mount point", None, 'my-role-1'), - ("custom mount point", 'aws-ec2', 'my-role-2'), - ]) + @parameterized.expand( + [ + ("default mount point", None, "my-role-1"), + ("custom mount point", "aws", "my-role-2"), + ] + ) @requests_mock.Mocker() def test_get_ec2_role(self, test_label, mount_point, role_name, requests_mocker): mock_response = { "data": { "bound_ami_id": ["ami-fce36987"], "role_tag": "", - "policies": [ - "default", - "dev", - "prod" - ], + "policies": ["default", "dev", "prod"], "max_ttl": 1800000, "disallow_reauthentication": False, - "allow_instance_migration": False + "allow_instance_migration": False, } } expected_status_code = 200 - mock_url = 'http://localhost:8200/v1/auth/{0}/role/{1}'.format( - 'aws-ec2' if mount_point is None else mount_point, + mock_url = "http://localhost:8200/v1/auth/{0}/role/{1}".format( + "aws" if mount_point is None else mount_point, role_name, ) requests_mocker.register_uri( - method='GET', + method="GET", url=mock_url, json=mock_response, status_code=expected_status_code, @@ -352,46 +351,42 @@ def test_get_ec2_role(self, test_label, mount_point, role_name, requests_mocker) client = Client() if mount_point is None: - actual_response = client.get_ec2_role( - role=role_name - ) + actual_response = client.auth.aws.read_role(role=role_name) else: - actual_response = client.get_ec2_role( - role=role_name, - mount_point=mount_point + actual_response = client.auth.aws.read_role( + role=role_name, mount_point=mount_point ) self.assertEqual( - first=mock_response, + first=mock_response.get("data"), second=actual_response, ) - @parameterized.expand([ - ("default mount point", None, 'my-role-1'), - ("custom mount point", 'aws-ec2', 'my-role-2'), - ]) + @parameterized.expand( + [ + ("default mount point", None, "my-role-1"), + ("custom mount point", "aws", "my-role-2"), + ] + ) @requests_mock.Mocker() def test_delete_ec2_role(self, test_label, mount_point, role_name, requests_mocker): expected_status_code = 204 - mock_url = 'http://localhost:8200/v1/auth/{0}/role/{1}'.format( - 'aws-ec2' if mount_point is None else mount_point, + mock_url = "http://localhost:8200/v1/auth/{0}/role/{1}".format( + "aws" if mount_point is None else mount_point, role_name, ) requests_mocker.register_uri( - method='DELETE', + method="DELETE", url=mock_url, status_code=expected_status_code, ) client = Client() if mount_point is None: - actual_response = client.delete_ec2_role( - role=role_name - ) + actual_response = client.auth.aws.delete_role(role=role_name) else: - actual_response = client.delete_ec2_role( - role=role_name, - mount_point=mount_point + actual_response = client.auth.aws.delete_role( + role=role_name, mount_point=mount_point ) self.assertEqual( @@ -399,26 +394,21 @@ def test_delete_ec2_role(self, test_label, mount_point, role_name, requests_mock second=actual_response.status_code, ) - @parameterized.expand([ - ("default mount point", None), - ("custom mount point", 'aws-ec2'), - ]) + @parameterized.expand( + [ + ("default mount point", None), + ("custom mount point", "aws"), + ] + ) @requests_mock.Mocker() def test_list_ec2_roles(self, test_label, mount_point, requests_mocker): - mock_response = { - "data": { - "keys": [ - "dev-role", - "prod-role" - ] - } - } + mock_response = {"data": {"keys": ["dev-role", "prod-role"]}} expected_status_code = 200 - mock_url = 'http://localhost:8200/v1/auth/{0}/roles?list=true'.format( - 'aws-ec2' if mount_point is None else mount_point, + mock_url = "http://localhost:8200/v1/auth/{0}/roles".format( + "aws" if mount_point is None else mount_point, ) requests_mocker.register_uri( - method='GET', + method="LIST", url=mock_url, json=mock_response, status_code=expected_status_code, @@ -426,36 +416,37 @@ def test_list_ec2_roles(self, test_label, mount_point, requests_mocker): client = Client() if mount_point is None: - actual_response = client.list_ec2_roles() + actual_response = client.auth.aws.list_roles() else: - actual_response = client.list_ec2_roles( - mount_point=mount_point - ) + actual_response = client.auth.aws.list_roles(mount_point=mount_point) self.assertEqual( - first=mock_response, + first=mock_response.get("data"), second=actual_response, ) - @parameterized.expand([ - ("default mount point", None, 'my-role-1'), - ("custom mount point", 'aws-ec2', 'my-role-2'), - ]) + @parameterized.expand( + [ + ("default mount point", None, "my-role-1"), + ("custom mount point", "aws", "my-role-2"), + ] + ) @requests_mock.Mocker() - def test_create_ec2_role_tag(self, test_label, mount_point, role_name, requests_mocker): + def test_create_ec2_role_tag( + self, test_label, mount_point, role_name, requests_mocker + ): mock_response = { "data": { "tag_value": "v1:09Vp0qGuyB8=:r=dev-role:p=default,dev-api:d=false:t=300h0m0s:uPLKCQxqsefRhrp1qmVa1wsQVUXXJG8UZP/pJIdVyOI=", - "tag_key": "VaultRole" + "tag_key": "VaultRole", } } expected_status_code = 200 - mock_url = 'http://localhost:8200/v1/auth/{0}/role/{1}/tag'.format( - 'aws-ec2' if mount_point is None else mount_point, - role_name + mock_url = "http://localhost:8200/v1/auth/{0}/role/{1}/tag".format( + "aws" if mount_point is None else mount_point, role_name ) requests_mocker.register_uri( - method='POST', + method="POST", url=mock_url, json=mock_response, status_code=expected_status_code, @@ -463,13 +454,12 @@ def test_create_ec2_role_tag(self, test_label, mount_point, role_name, requests_ client = Client() if mount_point is None: - actual_response = client.create_ec2_role_tag( + actual_response = client.auth.aws.create_role_tags( role=role_name, ) else: - actual_response = client.create_ec2_role_tag( - role=role_name, - mount_point=mount_point + actual_response = client.auth.aws.create_role_tags( + role=role_name, mount_point=mount_point ) self.assertEqual( diff --git a/tests/unit_tests/v1/test_aws_iam_methods.py b/tests/unit_tests/v1/test_aws_iam_methods.py index 98623a91c..bec913b1e 100644 --- a/tests/unit_tests/v1/test_aws_iam_methods.py +++ b/tests/unit_tests/v1/test_aws_iam_methods.py @@ -11,40 +11,54 @@ class TestAwsIamMethods(TestCase): """Unit tests providing coverage for AWS (EC2) auth backend-related methods/routes.""" - @mock.patch('hvac.aws_utils.datetime') - @mock.patch('hvac.v1.Client.login') + @mock.patch("hvac.aws_utils.datetime") + @mock.patch("hvac.adapters.Adapter.login") def test_auth_aws_iam(self, login_mock, datetime_mock): datetime_mock.utcnow.return_value = datetime(2015, 8, 30, 12, 36, 0) client = Client() - client.auth_aws_iam('AKIDEXAMPLE', 'wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY') + client.auth.aws.iam_login( + "AKIDEXAMPLE", "wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY" + ) login_mock.assert_called() args, kwargs = login_mock.call_args - actual_params = kwargs['json'] + actual_params = kwargs["json"] - actual_iam_http_request_method = actual_params['iam_http_request_method'] - self.assertEqual('POST', actual_iam_http_request_method) + actual_iam_http_request_method = actual_params["iam_http_request_method"] + self.assertEqual("POST", actual_iam_http_request_method) - actual_iam_request_url = b64decode(actual_params['iam_request_url']).decode('utf-8') - self.assertEqual('https://sts.amazonaws.com/', actual_iam_request_url) + actual_iam_request_url = b64decode(actual_params["iam_request_url"]).decode( + "utf-8" + ) + self.assertEqual("https://sts.amazonaws.com/", actual_iam_request_url) expected_auth_header_parts = [ - 'Credential=AKIDEXAMPLE/20150830/us-east-1/sts/aws4_request', - 'SignedHeaders=content-length;content-type;host;x-amz-date', - 'Signature=0268ea4a725deae1116f5228d6b177fb047f9f3a9e1c5fd4baa0dc1fbb0d1a99', + "Credential=AKIDEXAMPLE/20150830/us-east-1/sts/aws4_request", + "SignedHeaders=content-length;content-type;host;x-amz-date", + "Signature=0268ea4a725deae1116f5228d6b177fb047f9f3a9e1c5fd4baa0dc1fbb0d1a99", ] expected_iam_request_headers = { - 'Authorization': ['{0} {1}'.format('AWS4-HMAC-SHA256', ', '.join(expected_auth_header_parts))], - 'Content-Length': ['43'], - 'Content-Type': ['application/x-www-form-urlencoded; charset=utf-8'], - 'Host': ['sts.amazonaws.com'], - 'X-Amz-Date': ['20150830T123600Z'], + "Authorization": [ + "{0} {1}".format( + "AWS4-HMAC-SHA256", ", ".join(expected_auth_header_parts) + ) + ], + "Content-Length": ["43"], + "Content-Type": ["application/x-www-form-urlencoded; charset=utf-8"], + "Host": ["sts.amazonaws.com"], + "X-Amz-Date": ["20150830T123600Z"], } - actual_iam_request_headers = json.loads(b64decode(actual_params['iam_request_headers'])) + actual_iam_request_headers = json.loads( + b64decode(actual_params["iam_request_headers"]) + ) self.assertEqual(expected_iam_request_headers, actual_iam_request_headers) - actual_iam_request_body = b64decode(actual_params['iam_request_body']).decode('utf-8') - self.assertEqual('Action=GetCallerIdentity&Version=2011-06-15', actual_iam_request_body) + actual_iam_request_body = b64decode(actual_params["iam_request_body"]).decode( + "utf-8" + ) + self.assertEqual( + "Action=GetCallerIdentity&Version=2011-06-15", actual_iam_request_body + ) - actual_role = actual_params['role'] - self.assertEqual('', actual_role) + actual_role = actual_params["role"] + self.assertEqual(None, actual_role) diff --git a/tests/unit_tests/v1/test_gcp_methods.py b/tests/unit_tests/v1/test_gcp_methods.py index 8de972e8c..53d5a6471 100644 --- a/tests/unit_tests/v1/test_gcp_methods.py +++ b/tests/unit_tests/v1/test_gcp_methods.py @@ -9,55 +9,58 @@ class TestGcpMethods(TestCase): """Unit tests providing coverage for GCP auth backend-related methods/routes.""" - @parameterized.expand([ - ("default mount point", "custom_role", "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9", None), - ("custom mount point", "custom_role", "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9", "gcp-not-default") - ]) + @parameterized.expand( + [ + ( + "default mount point", + "custom_role", + "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9", + None, + ), + ( + "custom mount point", + "custom_role", + "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9", + "gcp-not-default", + ), + ] + ) @requests_mock.Mocker() - def test_auth_gcp(self, test_label, test_role, test_jwt, mount_point, requests_mocker): + def test_auth_gcp( + self, test_label, test_role, test_jwt, mount_point, requests_mocker + ): mock_response = { - 'auth': { - 'accessor': 'accessor-1234-5678-9012-345678901234', - 'client_token': 'cltoken-1234-5678-9012-345678901234', - 'lease_duration': 10000, - 'metadata': { - 'role': 'custom_role', - 'service_account_email': 'dev1@project-123456.iam.gserviceaccount.com', - 'service_account_id': '111111111111111111111' + "auth": { + "accessor": "accessor-1234-5678-9012-345678901234", + "client_token": "cltoken-1234-5678-9012-345678901234", + "lease_duration": 10000, + "metadata": { + "role": "custom_role", + "service_account_email": "dev1@project-123456.iam.gserviceaccount.com", + "service_account_id": "111111111111111111111", }, - 'policies': [ - 'default', - 'custom_role' - ], - 'renewable': True + "policies": ["default", "custom_role"], + "renewable": True, }, - 'data': None, - 'lease_duration': 0, - 'lease_id': '', - 'renewable': False, - 'request_id': 'requesti-1234-5678-9012-345678901234', - 'warnings': [], - 'wrap_info': None + "data": None, + "lease_duration": 0, + "lease_id": "", + "renewable": False, + "request_id": "requesti-1234-5678-9012-345678901234", + "warnings": [], + "wrap_info": None, } - mock_url = 'http://localhost:8200/v1/auth/{0}/login'.format( - 'gcp' if mount_point is None else mount_point) - requests_mocker.register_uri( - method='POST', - url=mock_url, - json=mock_response + mock_url = "http://localhost:8200/v1/auth/{0}/login".format( + "gcp" if mount_point is None else mount_point ) + requests_mocker.register_uri(method="POST", url=mock_url, json=mock_response) client = Client() if mount_point is None: - actual_response = client.auth_gcp( - role=test_role, - jwt=test_jwt - ) + actual_response = client.auth.gcp.login(role=test_role, jwt=test_jwt) else: - actual_response = client.auth_gcp( - role=test_role, - jwt=test_jwt, - mount_point=mount_point + actual_response = client.auth.gcp.login( + role=test_role, jwt=test_jwt, mount_point=mount_point ) # ensure we received our mock response data back successfully diff --git a/tests/unit_tests/v1/test_kubernetes_methods.py b/tests/unit_tests/v1/test_kubernetes_methods.py index 785478978..55628aea6 100644 --- a/tests/unit_tests/v1/test_kubernetes_methods.py +++ b/tests/unit_tests/v1/test_kubernetes_methods.py @@ -9,18 +9,22 @@ class TestKubernetesMethods(TestCase): """Unit tests providing coverage for Kubernetes auth backend-related methods/routes.""" - @parameterized.expand([ - ("default mount point", None, '127.0.0.1:80', ['test_key']), - ("custom mount point", "k8s", 'some_k8s_host.com', ['test_key']), - ]) + @parameterized.expand( + [ + ("default mount point", None, "127.0.0.1:80", ["test_key"]), + ("custom mount point", "k8s", "some_k8s_host.com", ["test_key"]), + ] + ) @requests_mock.Mocker() - def test_create_kubernetes_configuration(self, test_label, mount_point, kubernetes_host, pem_keys, requests_mocker): + def test_create_kubernetes_configuration( + self, test_label, mount_point, kubernetes_host, pem_keys, requests_mocker + ): expected_status_code = 204 - mock_url = 'http://localhost:8200/v1/auth/{0}/config'.format( - 'kubernetes' if mount_point is None else mount_point, + mock_url = "http://localhost:8200/v1/auth/{0}/config".format( + "kubernetes" if mount_point is None else mount_point, ) requests_mocker.register_uri( - method='POST', + method="POST", url=mock_url, status_code=expected_status_code, ) @@ -31,42 +35,46 @@ def test_create_kubernetes_configuration(self, test_label, mount_point, kubernet pem_keys=pem_keys, ) if mount_point: - test_arguments['mount_point'] = mount_point + test_arguments["mount_point"] = mount_point actual_response = client.create_kubernetes_configuration(**test_arguments) - self.assertEquals( + self.assertEqual( first=expected_status_code, second=actual_response.status_code, ) - @parameterized.expand([ - ("default mount point", None), - ("custom mount point", "k8s"), - ]) + @parameterized.expand( + [ + ("default mount point", None), + ("custom mount point", "k8s"), + ] + ) @requests_mock.Mocker() - def test_get_kubernetes_configuration(self, test_label, mount_point, requests_mocker): + def test_get_kubernetes_configuration( + self, test_label, mount_point, requests_mocker + ): expected_status_code = 200 mock_response = { - 'auth': None, - 'data': { - 'kubernetes_ca_cert': '', - 'kubernetes_host': '127.0.0.1:80', - 'pem_keys': ['some key'], - 'token_reviewer_jwt': '' + "auth": None, + "data": { + "kubernetes_ca_cert": "", + "kubernetes_host": "127.0.0.1:80", + "pem_keys": ["some key"], + "token_reviewer_jwt": "", }, - 'lease_duration': 0, - 'lease_id': '', - 'renewable': False, - 'request_id': '12687b5f-b4f5-2ba4-aae2-2a8d7e53ca55', - 'warnings': None, - 'wrap_info': None + "lease_duration": 0, + "lease_id": "", + "renewable": False, + "request_id": "12687b5f-b4f5-2ba4-aae2-2a8d7e53ca55", + "warnings": None, + "wrap_info": None, } - mock_url = 'http://localhost:8200/v1/auth/{0}/config'.format( - 'kubernetes' if mount_point is None else mount_point, + mock_url = "http://localhost:8200/v1/auth/{0}/config".format( + "kubernetes" if mount_point is None else mount_point, ) requests_mocker.register_uri( - method='GET', + method="GET", url=mock_url, status_code=expected_status_code, json=mock_response, @@ -75,28 +83,38 @@ def test_get_kubernetes_configuration(self, test_label, mount_point, requests_mo test_arguments = dict() if mount_point: - test_arguments['mount_point'] = mount_point + test_arguments["mount_point"] = mount_point actual_response = client.get_kubernetes_configuration(**test_arguments) - self.assertEquals( + self.assertEqual( first=mock_response, second=actual_response, ) - @parameterized.expand([ - ("default mount point", None, "application1", '*', 'some-namespace'), - ("custom mount point", "k8s", "application2", 'some-service-account', '*'), - ]) + @parameterized.expand( + [ + ("default mount point", None, "application1", "*", "some-namespace"), + ("custom mount point", "k8s", "application2", "some-service-account", "*"), + ] + ) @requests_mock.Mocker() - def test_create_role(self, test_label, mount_point, role_name, bound_service_account_names, bound_service_account_namespaces, requests_mocker): + def test_create_role( + self, + test_label, + mount_point, + role_name, + bound_service_account_names, + bound_service_account_namespaces, + requests_mocker, + ): expected_status_code = 204 - mock_url = 'http://localhost:8200/v1/auth/{0}/role/{1}'.format( - 'kubernetes' if mount_point is None else mount_point, + mock_url = "http://localhost:8200/v1/auth/{0}/role/{1}".format( + "kubernetes" if mount_point is None else mount_point, role_name, ) requests_mocker.register_uri( - method='POST', + method="POST", url=mock_url, status_code=expected_status_code, ) @@ -108,18 +126,20 @@ def test_create_role(self, test_label, mount_point, role_name, bound_service_acc bound_service_account_namespaces=bound_service_account_namespaces, ) if mount_point: - test_arguments['mount_point'] = mount_point + test_arguments["mount_point"] = mount_point actual_response = client.create_kubernetes_role(**test_arguments) - self.assertEquals( + self.assertEqual( first=expected_status_code, second=actual_response.status_code, ) - @parameterized.expand([ - ("default mount point", None, "application1"), - ("custom mount point", "k8s", "application2"), - ]) + @parameterized.expand( + [ + ("default mount point", None, "application1"), + ("custom mount point", "k8s", "application2"), + ] + ) @requests_mock.Mocker() def test_get_role(self, test_label, mount_point, role_name, requests_mocker): expected_status_code = 200 @@ -129,28 +149,26 @@ def test_get_role(self, test_label, mount_point, role_name, requests_mocker): "bind_secret_id": True, "bound_cidr_list": "", "period": 0, - "policies": [ - "default" - ], + "policies": ["default"], "secret_id_num_uses": 0, "secret_id_ttl": 0, "token_max_ttl": 900, "token_num_uses": 0, - "token_ttl": 600 + "token_ttl": 600, }, "lease_duration": 0, "lease_id": "", "renewable": False, "request_id": "0aab655f-ecd2-b3d4-3817-35b5bdfd3f28", "warnings": None, - "wrap_info": None + "wrap_info": None, } - mock_url = 'http://localhost:8200/v1/auth/{0}/role/{1}'.format( - 'kubernetes' if mount_point is None else mount_point, + mock_url = "http://localhost:8200/v1/auth/{0}/role/{1}".format( + "kubernetes" if mount_point is None else mount_point, role_name, ) requests_mocker.register_uri( - method='GET', + method="GET", url=mock_url, status_code=expected_status_code, json=mock_response, @@ -161,21 +179,25 @@ def test_get_role(self, test_label, mount_point, role_name, requests_mocker): name=role_name, ) if mount_point: - test_arguments['mount_point'] = mount_point + test_arguments["mount_point"] = mount_point actual_response = client.get_kubernetes_role(**test_arguments) - self.assertEquals( + self.assertEqual( first=mock_response, second=actual_response, ) - @parameterized.expand([ - ("default mount point", None, ['test-role-1', 'test-role-2']), - ("custom mount point", "k8s", ['test-role']), - ]) + @parameterized.expand( + [ + ("default mount point", None, ["test-role-1", "test-role-2"]), + ("custom mount point", "k8s", ["test-role"]), + ] + ) @requests_mock.Mocker() - def test_list_kubernetes_roles(self, test_label, mount_point, role_names, requests_mocker): + def test_list_kubernetes_roles( + self, test_label, mount_point, role_names, requests_mocker + ): expected_status_code = 200 mock_response = { "auth": None, @@ -187,13 +209,13 @@ def test_list_kubernetes_roles(self, test_label, mount_point, role_names, reques "renewable": False, "request_id": "e4c219fb-0a78-2be2-8d3c-b3715dccb920", "warnings": None, - "wrap_info": None + "wrap_info": None, } - mock_url = 'http://localhost:8200/v1/auth/{0}/role?list=true'.format( - 'kubernetes' if mount_point is None else mount_point, + mock_url = "http://localhost:8200/v1/auth/{0}/role?list=true".format( + "kubernetes" if mount_point is None else mount_point, ) requests_mocker.register_uri( - method='GET', + method="GET", url=mock_url, status_code=expected_status_code, json=mock_response, @@ -202,25 +224,29 @@ def test_list_kubernetes_roles(self, test_label, mount_point, role_names, reques test_arguments = dict() if mount_point: - test_arguments['mount_point'] = mount_point + test_arguments["mount_point"] = mount_point actual_response = client.list_kubernetes_roles(**test_arguments) # ensure we received our mock response data back successfully self.assertEqual(mock_response, actual_response) - @parameterized.expand([ - ("default mount point", None, "application1"), - ("custom mount point", "k8s", "application2"), - ]) + @parameterized.expand( + [ + ("default mount point", None, "application1"), + ("custom mount point", "k8s", "application2"), + ] + ) @requests_mock.Mocker() - def test_delete_kubernetes_role(self, test_label, mount_point, role_name, requests_mocker): + def test_delete_kubernetes_role( + self, test_label, mount_point, role_name, requests_mocker + ): expected_status_code = 204 - mock_url = 'http://localhost:8200/v1/auth/{0}/role/{1}'.format( - 'kubernetes' if mount_point is None else mount_point, + mock_url = "http://localhost:8200/v1/auth/{0}/role/{1}".format( + "kubernetes" if mount_point is None else mount_point, role_name, ) requests_mocker.register_uri( - method='DELETE', + method="DELETE", url=mock_url, status_code=expected_status_code, ) @@ -230,61 +256,69 @@ def test_delete_kubernetes_role(self, test_label, mount_point, role_name, reques role=role_name, ) if mount_point: - test_arguments['mount_point'] = mount_point + test_arguments["mount_point"] = mount_point actual_response = client.delete_kubernetes_role(**test_arguments) - self.assertEquals( + self.assertEqual( first=expected_status_code, second=actual_response.status_code, ) - @parameterized.expand([ - ("default mount point", "custom_role", "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9", None), - ("custom mount point", "custom_role", "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9", "gcp-not-default") - ]) + @parameterized.expand( + [ + ( + "default mount point", + "custom_role", + "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9", + None, + ), + ( + "custom mount point", + "custom_role", + "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9", + "gcp-not-default", + ), + ] + ) @requests_mock.Mocker() - def test_auth_kubernetes(self, test_label, test_role, test_jwt, mount_point, requests_mocker): + def test_auth_kubernetes( + self, test_label, test_role, test_jwt, mount_point, requests_mocker + ): mock_response = { - 'auth': { - 'accessor': 'accessor-1234-5678-9012-345678901234', - 'client_token': 'cltoken-1234-5678-9012-345678901234', - 'lease_duration': 10000, - 'metadata': { - 'role': 'custom_role', - 'service_account_name': 'vault-auth', - 'service_account_namespace': 'default', - 'service_account_secret_name': 'vault-auth-token-pd21c', - 'service_account_uid': 'aa9aa8ff-98d0-11e7-9bb7-0800276d99bf' + "auth": { + "accessor": "accessor-1234-5678-9012-345678901234", + "client_token": "cltoken-1234-5678-9012-345678901234", + "lease_duration": 10000, + "metadata": { + "role": "custom_role", + "service_account_name": "vault-auth", + "service_account_namespace": "default", + "service_account_secret_name": "vault-auth-token-pd21c", + "service_account_uid": "aa9aa8ff-98d0-11e7-9bb7-0800276d99bf", }, - 'policies': [ - 'default', - 'custom_role' - ], - 'renewable': True + "policies": ["default", "custom_role"], + "renewable": True, }, - 'data': None, - 'lease_duration': 0, - 'lease_id': '', - 'renewable': False, - 'request_id': 'requesti-1234-5678-9012-345678901234', - 'warnings': [], - 'wrap_info': None + "data": None, + "lease_duration": 0, + "lease_id": "", + "renewable": False, + "request_id": "requesti-1234-5678-9012-345678901234", + "warnings": [], + "wrap_info": None, } - mock_url = 'http://localhost:8200/v1/auth/{0}/login'.format( - 'kubernetes' if mount_point is None else mount_point) - requests_mocker.register_uri( - method='POST', - url=mock_url, - json=mock_response + mock_url = "http://localhost:8200/v1/auth/{0}/login".format( + "kubernetes" if mount_point is None else mount_point ) + requests_mocker.register_uri(method="POST", url=mock_url, json=mock_response) client = Client() test_arguments = dict( role=test_role, jwt=test_jwt, ) if mount_point: - test_arguments['mount_point'] = mount_point + test_arguments["mount_point"] = mount_point actual_response = client.auth_kubernetes(**test_arguments) # ensure we received our mock response data back successfully diff --git a/tests/unit_tests/v1/test_system_backend_methods.py b/tests/unit_tests/v1/test_system_backend_methods.py index c8fb642d6..4576bfca0 100644 --- a/tests/unit_tests/v1/test_system_backend_methods.py +++ b/tests/unit_tests/v1/test_system_backend_methods.py @@ -9,30 +9,32 @@ class TestSystemBackendMethods(TestCase): """Unit tests providing coverage for Vault system backend-related methods in the hvac Client class.""" - @parameterized.expand([ - ("pki lease ID", 'pki/issue/my-role/12c7e036-b59e-5e79-3370-03826fc6f34b'), - ]) + @parameterized.expand( + [ + ("pki lease ID", "pki/issue/my-role/12c7e036-b59e-5e79-3370-03826fc6f34b"), + ] + ) @requests_mock.Mocker() def test_read_lease(self, test_label, test_lease_id, requests_mocker): - test_path = 'http://localhost:8200/v1/sys/leases/lookup' + test_path = "http://localhost:8200/v1/sys/leases/lookup" mock_response = { - 'issue_time': '2018-07-15T08:35:34.775859245-05:00', - 'renewable': False, - 'id': test_lease_id, - 'ttl': 259199, - 'expire_time': '2018-07-18T08:35:34.00004241-05:00', - 'last_renewal': None + "issue_time": "2018-07-15T08:35:34.775859245-05:00", + "renewable": False, + "id": test_lease_id, + "ttl": 259199, + "expire_time": "2018-07-18T08:35:34.00004241-05:00", + "last_renewal": None, } requests_mocker.register_uri( - method='PUT', + method="PUT", url=test_path, json=mock_response, ) client = Client() - response = client.read_lease( + response = client.sys.read_lease( lease_id=test_lease_id, ) - self.assertEquals( + self.assertEqual( first=mock_response, second=response, ) diff --git a/tests/utils/__init__.py b/tests/utils/__init__.py index b3de6dfde..6de6f7dd3 100644 --- a/tests/utils/__init__.py +++ b/tests/utils/__init__.py @@ -1,5 +1,6 @@ """Collection of methods used by various hvac test cases.""" import base64 +import json import logging import operator import os @@ -7,27 +8,27 @@ import socket import subprocess import sys -from unittest import SkipTest from distutils.spawn import find_executable from distutils.version import StrictVersion +from unittest import SkipTest from hvac import Client logger = logging.getLogger(__name__) -VERSION_REGEX = re.compile(r'Vault v([0-9.]+)') -LATEST_VAULT_VERSION = '1.1.3' +VERSION_REGEX = re.compile(r"Vault v([0-9.]+)") +LATEST_VAULT_VERSION = "1.1.3" def get_vault_version_string(): - if 'cache' in get_vault_version_string.__dict__: + if "cache" in get_vault_version_string.__dict__: return get_vault_version_string.cache - if not find_executable('vault'): - raise SkipTest('Vault executable not found') - command = ['vault', '-version'] + if not find_executable("vault"): + raise SkipTest("Vault executable not found") + command = ["vault", "-version"] process = subprocess.Popen(**get_popen_kwargs(args=command, stdout=subprocess.PIPE)) output, _ = process.communicate() - version_string = output.strip().split()[1].lstrip('v') + version_string = output.strip().split()[1].lstrip("v") get_vault_version_string.cache = version_string return version_string @@ -35,14 +36,14 @@ def get_vault_version_string(): def get_installed_vault_version(): version_string = get_vault_version_string() # replace any '-beta1' type substrings with a StrictVersion parsable version. E.g., 1.0.0-beta1 => 1.0.0b1 - version = version_string.replace('-', '').replace('beta', 'b') - version = version.replace('+ent', '') + version = version_string.replace("-", "").replace("beta", "b") + version = version.replace("+ent", "") return version def is_enterprise(): version_string = get_vault_version_string() - if re.search(r'\+ent$', version_string) is not None: + if re.search(r"\+ent$", version_string) is not None: return True return False @@ -70,14 +71,14 @@ def get_generate_root_otp(): :return: OTP to use in generate root operations :rtype: str """ - if vault_version_ge('1.0.0'): - test_otp = 'ygs0vL8GIxu0AjRVEmJ5jLCVq8' + if vault_version_ge("1.0.0"): + test_otp = "ygs0vL8GIxu0AjRVEmJ5jLCVq8" else: - test_otp = 'RSMGkAqBH5WnVLrDTbZ+UQ==' + test_otp = "RSMGkAqBH5WnVLrDTbZ+UQ==" return test_otp -def create_client(url='https://localhost:8200', **kwargs): +def create_client(url="https://localhost:8200", **kwargs): """Small helper to instantiate a :py:class:`hvac.v1.Client` class with the appropriate parameters for the test env. :param url: Vault address to configure the client with. @@ -87,9 +88,9 @@ def create_client(url='https://localhost:8200', **kwargs): :return: Instantiated :py:class:`hvac.v1.Client` class. :rtype: hvac.v1.Client """ - client_cert_path = get_config_file_path('client-cert.pem') - client_key_path = get_config_file_path('client-key.pem') - server_cert_path = get_config_file_path('server-cert.pem') + client_cert_path = get_config_file_path("client-cert.pem") + client_key_path = get_config_file_path("client-key.pem") + server_cert_path = get_config_file_path("server-cert.pem") return Client( url=url, @@ -106,7 +107,7 @@ def get_free_port(): :rtype: int """ s = socket.socket(socket.AF_INET, type=socket.SOCK_STREAM) - s.bind(('localhost', 0)) + s.bind(("localhost", 0)) address, port = s.getsockname() s.close() return port @@ -121,7 +122,7 @@ def load_config_file(filename): :rtype: str | unicode """ test_data_path = get_config_file_path(filename) - with open(test_data_path, 'r') as f: + with open(test_data_path, "r") as f: test_data = f.read() return test_data @@ -137,7 +138,9 @@ def get_config_file_path(filename): :rtype: str | unicode """ # Use __file__ to derive a path relative to this module's location which points to the tests data directory. - relative_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), '..', 'config_files') + relative_path = os.path.join( + os.path.dirname(os.path.realpath(__file__)), "..", "config_files" + ) return os.path.join(os.path.abspath(relative_path), filename) @@ -151,33 +154,38 @@ def decode_generated_root_token(encoded_token, otp): :return: The decoded root token. :rtype: str | unicode """ - command = ['vault'] - if vault_version_ge('0.9.6'): + command = ["vault"] + if vault_version_ge("0.9.6"): # before Vault ~0.9.6, the generate-root command was the first positional argument # afterwards, it was moved under the "operator" category - command.append('operator') + command.append("operator") command.extend( [ - 'generate-root', - '-address', 'https://127.0.0.1:8200', - '-tls-skip-verify', - '-decode', encoded_token, - '-otp', otp, + "generate-root", + "-address", + "https://127.0.0.1:8200", + "-tls-skip-verify", + "-decode", + encoded_token, + "-otp", + otp, ] ) - process = subprocess.Popen(**get_popen_kwargs( - args=command, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE - )) + process = subprocess.Popen( + **get_popen_kwargs(args=command, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + ) stdout, stderr = process.communicate() logging.debug('decode_generated_root_token stdout: "%s"' % str(stdout)) - if stderr != '': - logging.error('decode_generated_root_token stderr: %s' % stderr) - - new_token = stdout.replace('Root token:', '') + if stderr != "": + logging.error("decode_generated_root_token stderr: %s" % stderr) + + try: + # On the off chance VAULT_FORMAT=json or such is set in the test environment: + new_token = json.loads(stdout)["token"] + except ValueError: + new_token = stdout.replace("Root token:", "") new_token = new_token.strip() return new_token @@ -191,7 +199,7 @@ def get_popen_kwargs(**popen_kwargs): :rtype: dict """ if sys.version_info[0] >= 3: - popen_kwargs['encoding'] = 'utf-8' + popen_kwargs["encoding"] = "utf-8" return popen_kwargs @@ -204,18 +212,20 @@ def base64ify(bytes_or_str): :rtype: """ if sys.version_info[0] >= 3 and isinstance(bytes_or_str, str): - input_bytes = bytes_or_str.encode('utf8') + input_bytes = bytes_or_str.encode("utf8") else: input_bytes = bytes_or_str output_bytes = base64.urlsafe_b64encode(input_bytes) if sys.version_info[0] >= 3: - return output_bytes.decode('ascii') + return output_bytes.decode("ascii") else: return output_bytes -def configure_pki(client, common_name='hvac.com', role_name='my-role', mount_point='pki'): +def configure_pki( + client, common_name="hvac.com", role_name="my-role", mount_point="pki" +): """Helper function to configure a pki backend for integration tests that need to work with lease IDs. :param client: Authenticated hvac Client instance. @@ -229,31 +239,31 @@ def configure_pki(client, common_name='hvac.com', role_name='my-role', mount_poi :return: Nothing. :rtype: None. """ - if '{path}/'.format(path=mount_point) in client.sys.list_mounted_secrets_engines(): + if "{path}/".format(path=mount_point) in client.sys.list_mounted_secrets_engines(): client.sys.disable_secrets_engine(mount_point) - client.sys.enable_secrets_engine(backend_type='pki', path=mount_point) + client.sys.enable_secrets_engine(backend_type="pki", path=mount_point) client.write( - path='{path}/root/generate/internal'.format(path=mount_point), + path="{path}/root/generate/internal".format(path=mount_point), common_name=common_name, - ttl='8760h', + ttl="8760h", ) client.write( - path='{path}/config/urls'.format(path=mount_point), + path="{path}/config/urls".format(path=mount_point), issuing_certificates="http://127.0.0.1:8200/v1/pki/ca", crl_distribution_points="http://127.0.0.1:8200/v1/pki/crl", ) client.write( - path='{path}/roles/{name}'.format(path=mount_point, name=role_name), + path="{path}/roles/{name}".format(path=mount_point, name=role_name), allowed_domains=common_name, allow_subdomains=True, generate_lease=True, - max_ttl='72h', + max_ttl="72h", ) -def disable_pki(client, mount_point='pki'): +def disable_pki(client, mount_point="pki"): """Disable a previously configured pki backend. :param client: Authenticated hvac Client instance. diff --git a/tests/utils/hvac_integration_test_case.py b/tests/utils/hvac_integration_test_case.py index 97193a357..6edaca189 100644 --- a/tests/utils/hvac_integration_test_case.py +++ b/tests/utils/hvac_integration_test_case.py @@ -22,18 +22,22 @@ class HvacIntegrationTestCase(object): @classmethod def setUpClass(cls): """Use the ServerManager class to launch a vault server process.""" - config_paths = [get_config_file_path('vault-tls.hcl')] - if distutils.spawn.find_executable('consul') is None and cls.enable_vault_ha: - logging.warning('Unable to run Vault in HA mode, consul binary not found in path.') + config_paths = [get_config_file_path("vault-tls.hcl")] + if distutils.spawn.find_executable("consul") is None and cls.enable_vault_ha: + logging.warning( + "Unable to run Vault in HA mode, consul binary not found in path." + ) cls.enable_vault_ha = False if is_enterprise(): # TODO: figure out why this bit isn't working - logging.warning('Unable to run Vault in HA mode, enterprise Vault version not currently supported.') + logging.warning( + "Unable to run Vault in HA mode, enterprise Vault version not currently supported." + ) cls.enable_vault_ha = False if cls.enable_vault_ha: config_paths = [ - get_config_file_path('vault-ha-node1.hcl'), - get_config_file_path('vault-ha-node2.hcl'), + get_config_file_path("vault-ha-node1.hcl"), + get_config_file_path("vault-ha-node2.hcl"), ] cls.manager = ServerManager( config_paths=config_paths, @@ -60,7 +64,7 @@ def setUp(self): # Squelch deprecating warnings during tests as we may want to deliberately call deprecated methods and/or verify # warnings invocations. - warnings_patcher = patch('hvac.utils.warnings', spec=warnings) + warnings_patcher = patch("hvac.utils.warnings", spec=warnings) self.mock_warnings = warnings_patcher.start() def tearDown(self): @@ -85,21 +89,23 @@ def convert_python_ttl_value_to_expected_vault_response(ttl_value): :rtype: int """ expected_ttl = 0 - if not isinstance(ttl_value, int) and ttl_value != '': - regexp_matches = re.findall(r'(?P[0-9]+)(?P[smh])', ttl_value) + if not isinstance(ttl_value, int) and ttl_value != "": + regexp_matches = re.findall( + r"(?P[0-9]+)(?P[smh])", ttl_value + ) if regexp_matches: for regexp_match in regexp_matches: duration, unit = regexp_match - if unit == 'm': + if unit == "m": # convert minutes to seconds expected_ttl += int(duration) * 60 - elif unit == 'h': + elif unit == "h": # convert hours to seconds expected_ttl += int(duration) * 60 * 60 else: expected_ttl += int(duration) - elif ttl_value == '': + elif ttl_value == "": expected_ttl = 0 return expected_ttl @@ -113,15 +119,8 @@ def prep_policy(self, name): policy = "write" } """ - obj = { - 'path': { - 'sys': { - 'policy': 'deny'}, - 'secret': { - 'policy': 'write'} - } - } - self.client.set_policy(name, text) + obj = {"path": {"sys": {"policy": "deny"}, "secret": {"policy": "write"}}} + self.client.sys.create_or_update_policy(name, text) return text, obj def get_vault_addr_by_standby_status(self, standby_status=True): @@ -134,21 +133,32 @@ def get_vault_addr_by_standby_status(self, standby_status=True): """ vault_addresses = self.manager.get_active_vault_addresses() for vault_address in vault_addresses: - health_status = create_client(url=vault_address).sys.read_health_status(method='GET') + health_status = create_client(url=vault_address).sys.read_health_status( + method="GET" + ) if not isinstance(health_status, dict): health_status = health_status.json() - if health_status['standby'] == standby_status: + if health_status["standby"] == standby_status: return vault_address - def add_admin_approle_role(self, role_id, role_name='test-admin-role', path='approle'): + def add_admin_approle_role( + self, role_id, role_name="test-admin-role", path="approle" + ): test_admin_policy = { - 'path': { - '*': { - 'capabilities': ["sudo", "create", "read", "update", "delete", "list"], + "path": { + "*": { + "capabilities": [ + "sudo", + "create", + "read", + "update", + "delete", + "list", + ], }, }, } - test_admin_policy_name = 'test-admin-approle-policy' + test_admin_policy_name = "test-admin-approle-policy" self.client.sys.create_or_update_policy( name=test_admin_policy_name, policy=test_admin_policy, @@ -167,13 +177,13 @@ def add_admin_approle_role(self, role_id, role_name='test-admin-role', path='app role_name=role_name, mount_point=self.TEST_APPROLE_PATH, ) - return secret_id_resp['data']['secret_id'] + return secret_id_resp["data"]["secret_id"] - def login_using_admin_approle_role(self, role_id, role_name='test-admin-role', path='approle'): + def login_using_admin_approle_role( + self, role_id, role_name="test-admin-role", path="approle" + ): secret_id = self.add_admin_approle_role( - role_id=role_id, - role_name=role_name, - path=path + role_id=role_id, role_name=role_name, path=path ) self.client.auth.approle.login( diff --git a/tests/utils/mock_github_request_handler.py b/tests/utils/mock_github_request_handler.py index 627217f62..a7392c29a 100644 --- a/tests/utils/mock_github_request_handler.py +++ b/tests/utils/mock_github_request_handler.py @@ -2,12 +2,7 @@ # -*- coding: utf-8 -*- import json -try: - # Python 2.7 - from http.server import BaseHTTPRequestHandler -except ImportError: - # Python 3.x - from BaseHTTPServer import BaseHTTPRequestHandler +from http.server import BaseHTTPRequestHandler class MockGithubRequestHandler(BaseHTTPRequestHandler): @@ -16,14 +11,14 @@ class MockGithubRequestHandler(BaseHTTPRequestHandler): def do_GET(self): """Dispatch GET requests to associated mock GitHub 'handlers'.""" self.send_response(200) - self.send_header('Content-Type', 'application/json') + self.send_header("Content-Type", "application/json") self.end_headers() - if self.path == '/user': + if self.path == "/user": self.do_user() - elif self.path == '/user/orgs?per_page=100': + elif self.path == "/user/orgs?per_page=100": self.do_organizations_list() - elif self.path == '/user/teams?per_page=100': + elif self.path == "/user/teams?per_page=100": self.do_team_list() return @@ -46,7 +41,7 @@ def do_organizations_list(self): Only returns data if the request Authorization header has a contrived github token value of "valid-token". """ response = [] - if self.headers.get('Authorization') == 'Bearer valid-token': + if self.headers.get("Authorization") == "Bearer valid-token": response.append( { "login": "hvac", @@ -62,14 +57,14 @@ def do_team_list(self): Only returns data if the request Authorization header has a contrived github token value of "valid-token". """ response = [] - if self.headers.get('Authorization') == 'Bearer valid-token': + if self.headers.get("Authorization") == "Bearer valid-token": response.append( { "name": "hvac-team", "slug": "hvac-team", "organization": { "id": 1, - } + }, } ) self.wfile.write(json.dumps(response).encode()) diff --git a/tests/utils/mock_ldap_server.py b/tests/utils/mock_ldap_server.py index 8f1c29a22..b4787250a 100644 --- a/tests/utils/mock_ldap_server.py +++ b/tests/utils/mock_ldap_server.py @@ -5,68 +5,65 @@ class MockLdapServer(object): - ldap_url = 'ldap://ldap.python-hvac.org' - ldap_group_name = 'vault-users' - ldap_user_name = 'somedude' - ldap_user_password = 'hvacrox' - ldap_base_dc = 'hvac' - ldap_base_dn = 'dc={dc},dc=network'.format(dc=ldap_base_dc) - ldap_bind_dn = 'cn=admin,{base_dn}'.format(base_dn=ldap_base_dn) - ldap_bind_password = 'notaverygoodpassword' - ldap_users_dn = 'dc=users,{base_dn}'.format(base_dn=ldap_base_dn) - ldap_groups_ou = 'groups' - ldap_groups_dn = 'ou={ou},{base_dn}'.format(ou=ldap_groups_ou, base_dn=ldap_base_dn) - ldap_login_user_dn = 'uid={username},{users_dn}'.format(username=ldap_user_name, users_dn=ldap_users_dn) + ldap_url = "ldap://ldap.python-hvac.org" + ldap_group_name = "vault-users" + ldap_user_name = "somedude" + ldap_user_password = "hvacrox" + ldap_base_dc = "hvac" + ldap_base_dn = "dc={dc},dc=network".format(dc=ldap_base_dc) + ldap_bind_dn = "cn=admin,{base_dn}".format(base_dn=ldap_base_dn) + ldap_bind_password = "notaverygoodpassword" + ldap_users_dn = "dc=users,{base_dn}".format(base_dn=ldap_base_dn) + ldap_groups_ou = "groups" + ldap_groups_dn = "ou={ou},{base_dn}".format(ou=ldap_groups_ou, base_dn=ldap_base_dn) + ldap_login_user_dn = "uid={username},{users_dn}".format( + username=ldap_user_name, users_dn=ldap_users_dn + ) ldap_entries = [ + {"objectclass": "domain", "dn": ldap_users_dn, "attributes": {"dc": "users"}}, { - 'objectclass': 'domain', - 'dn': ldap_users_dn, - 'attributes': { - 'dc': 'users' - } + "objectclass": ["inetorgperson", "posixgroup", "top"], + "dn": ldap_login_user_dn, + "attributes": {"uid": ldap_user_name, "userpassword": ldap_user_password}, }, { - 'objectclass': ['inetorgperson', 'posixgroup', 'top'], - 'dn': ldap_login_user_dn, - 'attributes': { - 'uid': ldap_user_name, - 'userpassword': ldap_user_password - } - }, - { - 'objectclass': 'organizationalunit', - 'dn': ldap_groups_dn, - 'attributes': { - 'ou': 'groups', - } + "objectclass": "organizationalunit", + "dn": ldap_groups_dn, + "attributes": { + "ou": "groups", + }, }, { - 'objectclass': 'groupofnames', - 'dn': 'cn={cn},{groups_dn}'.format(cn=ldap_group_name, groups_dn=ldap_groups_dn), - 'attributes': { - 'cn': ldap_group_name, - 'member': ldap_login_user_dn, - } + "objectclass": "groupofnames", + "dn": "cn={cn},{groups_dn}".format( + cn=ldap_group_name, groups_dn=ldap_groups_dn + ), + "attributes": { + "cn": ldap_group_name, + "member": ldap_login_user_dn, + }, }, ] def __init__(self): self.server_port = get_free_port() - self.ldap_server = LdapServer({ - 'port': self.server_port, - 'bind_dn': self.ldap_bind_dn, - 'password': self.ldap_bind_password, - 'base': { - 'objectclass': ['domain'], - 'dn': self.ldap_base_dn, - 'attributes': {'dc': self.ldap_base_dc} - }, - 'entries': self.ldap_entries, - }) + self.ldap_server = LdapServer( + { + "port": self.server_port, + "bind_dn": self.ldap_bind_dn, + "password": self.ldap_bind_password, + "base": { + "objectclass": ["domain"], + "dn": self.ldap_base_dn, + "attributes": {"dc": self.ldap_base_dc}, + }, + "entries": self.ldap_entries, + } + ) @property def url(self): - return 'ldap://localhost:{port}'.format(port=self.server_port) + return "ldap://localhost:{port}".format(port=self.server_port) def start(self): self.ldap_server.start() diff --git a/tests/utils/mock_oauth_provider/app.py b/tests/utils/mock_oauth_provider/app.py index fc401cb57..2a8c8e012 100644 --- a/tests/utils/mock_oauth_provider/app.py +++ b/tests/utils/mock_oauth_provider/app.py @@ -9,17 +9,17 @@ def create_app(config=None): app = Flask(__name__) # load default configuration - app.config.from_object('tests.utils.mock_oauth_provider.settings') + app.config.from_object("tests.utils.mock_oauth_provider.settings") # load environment configuration - if 'WEBSITE_CONF' in os.environ: - app.config.from_envvar('WEBSITE_CONF') + if "WEBSITE_CONF" in os.environ: + app.config.from_envvar("WEBSITE_CONF") # load app sepcified configuration if config is not None: if isinstance(config, dict): app.config.update(config) - elif config.endswith('.py'): + elif config.endswith(".py"): app.config.from_pyfile(config) setup_app(app) @@ -34,4 +34,4 @@ def create_tables(): db.init_app(app) config_oauth(app) - app.register_blueprint(bp, url_prefix='') + app.register_blueprint(bp, url_prefix="") diff --git a/tests/utils/mock_oauth_provider/mock_oauth_provider.py b/tests/utils/mock_oauth_provider/mock_oauth_provider.py index f0abec959..869768302 100755 --- a/tests/utils/mock_oauth_provider/mock_oauth_provider.py +++ b/tests/utils/mock_oauth_provider/mock_oauth_provider.py @@ -13,82 +13,87 @@ class MockOauthProviderServerThread(Thread): - - def __init__(self, app_config=None, address='localhost', port='80'): + def __init__(self, app_config=None, address="localhost", port="80"): Thread.__init__(self) self.address = address self.server_port = get_free_port() if app_config is None: app_config = { - 'SECRET_KEY': 'secret', - 'SQLALCHEMY_DATABASE_URI': 'sqlite:///:memory:', - 'SQLALCHEMY_TRACK_MODIFICATIONS': False, + "SECRET_KEY": "secret", + "SQLALCHEMY_DATABASE_URI": "sqlite:///:memory:", + "SQLALCHEMY_TRACK_MODIFICATIONS": False, + } + app_config.update( + { + "OAUTH2_JWT_ISS": "http://{address}:{port}/oauth".format( + address=self.address, port=self.server_port + ), } - app_config.update({ - 'OAUTH2_JWT_ISS': 'http://{address}:{port}/oauth'.format( - address=self.address, - port=self.server_port - ), - }) + ) app = create_app(app_config) - self.srv = make_server('127.0.0.1', self.server_port, app) + self.srv = make_server("127.0.0.1", self.server_port, app) self.ctx = app.app_context() self.ctx.push() @property def url(self): - return 'http://{address}:{port}'.format( + return "http://{address}:{port}".format( address=self.address, port=self.server_port, ) def run(self): - logger.info('starting server') + logger.info("starting server") self.srv.serve_forever() def shutdown(self): self.srv.shutdown() -def create_user_session_and_client(server_url, oauth_redirect_uri, oauth_username='hvac-oauth-user', - oauth_client_name='hvac-integration-tests', oauth_client_uri='https://python-hvac.org'): +def create_user_session_and_client( + server_url, + oauth_redirect_uri, + oauth_username="hvac-oauth-user", + oauth_client_name="hvac-integration-tests", + oauth_client_uri="https://python-hvac.org", +): # Persist our "user" session in between requests oauth_session = requests.Session() # Create our auth user create_user_response = oauth_session.post( - url='{server_url}/api/user'.format(server_url=server_url), + url="{server_url}/api/user".format(server_url=server_url), data=dict( username=oauth_username, ), ) create_user = create_user_response.json() - logger.debug('create_user_response:\n%s\n' % create_user) + logger.debug("create_user_response:\n%s\n" % create_user) # Set up the auth client details create_client_response = oauth_session.post( - url='{server_url}/api/create_client'.format(server_url=server_url), + url="{server_url}/api/create_client".format(server_url=server_url), data=dict( client_name=oauth_client_name, client_uri=oauth_client_uri, - scope='openid profile', + scope="openid profile", redirect_uris=oauth_redirect_uri, - grant_types='authorization_code', - response_types='code', - token_endpoint_auth_method='client_secret_basic', + grant_types="authorization_code", + response_types="code", + token_endpoint_auth_method="client_secret_basic", ), ) client = create_client_response.json() - logger.debug('create_client_data:\n%s\n' % client) + logger.debug("create_client_data:\n%s\n" % client) return { - 'session': oauth_session, - 'client_id': client['client_id'], - 'client_secret': client['client_secret'], - 'discovery_url': '{server_url}/oauth'.format(server_url=server_url), + "session": oauth_session, + "client_id": client["client_id"], + "client_secret": client["client_secret"], + "discovery_url": "{server_url}/oauth".format(server_url=server_url), } -if __name__ == '__main__': +if __name__ == "__main__": # Set up our test oidc provider / server's configuration and start it server = MockOauthProviderServerThread() server.start() @@ -97,57 +102,66 @@ def create_user_session_and_client(server_url, oauth_redirect_uri, oauth_usernam oauth_session = requests.Session() # Generic inputs - oauth_username = 'hvac-oauth-user' - oauth_client_name = 'hvac-integration-tests' - oauth_client_uri = 'https://python-hvac.org' - oauth_redirect_uri = 'https://localhost:8200/jwt-test/oidc/callback' + oauth_username = "hvac-oauth-user" + oauth_client_name = "hvac-integration-tests" + oauth_client_uri = "https://python-hvac.org" + oauth_redirect_uri = "https://localhost:8200/jwt-test/oidc/callback" # Unauthorized GET to the user API route - unauth_get_response = oauth_session.get('{server_url}/api/user'.format(server_url=server.url)) - logger.debug('Unauthorized GET to the user API route:\n%s\n' % unauth_get_response.json()) + unauth_get_response = oauth_session.get( + "{server_url}/api/user".format(server_url=server.url) + ) + logger.debug( + "Unauthorized GET to the user API route:\n%s\n" % unauth_get_response.json() + ) # Create our user create_user_response = oauth_session.post( - url='{server_url}/api/user'.format(server_url=server.url), + url="{server_url}/api/user".format(server_url=server.url), data=dict( username=oauth_username, ), ) create_user = create_user_response.text - logger.debug('create_user_response:\n%s\n' % create_user) + logger.debug("create_user_response:\n%s\n" % create_user) # Create a client create_client_response = oauth_session.post( - url='{server_url}/api/create_client'.format(server_url=server.url), + url="{server_url}/api/create_client".format(server_url=server.url), data=dict( client_name=oauth_client_name, client_uri=oauth_client_uri, - scope='openid profile', + scope="openid profile", redirect_uris=oauth_redirect_uri, - grant_types='authorization_code', - response_types='code', - token_endpoint_auth_method='client_secret_basic', + grant_types="authorization_code", + response_types="code", + token_endpoint_auth_method="client_secret_basic", ), ) client = create_client_response.json() - logger.debug('create_client_data:\n%s\n' % client) + logger.debug("create_client_data:\n%s\n" % client) # Authorized GET to the user API route after creating a client - auth_get_response = oauth_session.get('{server_url}/api/user'.format(server_url=server.url)) - logger.debug('Authorized GET to the user API route after creating a client:\n%s\n' % auth_get_response.json()) + auth_get_response = oauth_session.get( + "{server_url}/api/user".format(server_url=server.url) + ) + logger.debug( + "Authorized GET to the user API route after creating a client:\n%s\n" + % auth_get_response.json() + ) authorize_response = oauth_session.get( - url='{server_url}/oauth/authorize'.format(server_url=server.url), + url="{server_url}/oauth/authorize".format(server_url=server.url), data=dict( - client_id=client['client_id'], - scope='openid profile', - response_type='code', - nonce='abc', + client_id=client["client_id"], + scope="openid profile", + response_type="code", + nonce="abc", ), ) # authorization = authorize_response.json() authorization = authorize_response.text - logger.debug('authorize_response:\n%s\n' % authorization) + logger.debug("authorize_response:\n%s\n" % authorization) # Finally stop our test oidc provider / server server.shutdown() diff --git a/tests/utils/mock_oauth_provider/models.py b/tests/utils/mock_oauth_provider/models.py index 1fb004cae..891b55e07 100644 --- a/tests/utils/mock_oauth_provider/models.py +++ b/tests/utils/mock_oauth_provider/models.py @@ -2,7 +2,7 @@ from authlib.integrations.sqla_oauth2 import ( OAuth2ClientMixin, OAuth2TokenMixin, - OAuth2AuthorizationCodeMixin + OAuth2AuthorizationCodeMixin, ) @@ -24,33 +24,30 @@ def as_dict(self): class OAuth2Client(db.Model, OAuth2ClientMixin): - __tablename__ = 'oauth2_client' + __tablename__ = "oauth2_client" id = db.Column(db.Integer, primary_key=True) - user_id = db.Column( - db.Integer, db.ForeignKey('user.id', ondelete='CASCADE')) - user = db.relationship('User') + user_id = db.Column(db.Integer, db.ForeignKey("user.id", ondelete="CASCADE")) + user = db.relationship("User") def as_dict(self): return_dict = {c.name: getattr(self, c.name) for c in self.__table__.columns} - return_dict['info'] = self.client_info - return_dict['metadata'] = self.client_metadata + return_dict["info"] = self.client_info + return_dict["metadata"] = self.client_metadata return return_dict class OAuth2AuthorizationCode(db.Model, OAuth2AuthorizationCodeMixin): - __tablename__ = 'oauth2_code' + __tablename__ = "oauth2_code" id = db.Column(db.Integer, primary_key=True) - user_id = db.Column( - db.Integer, db.ForeignKey('user.id', ondelete='CASCADE')) - user = db.relationship('User') + user_id = db.Column(db.Integer, db.ForeignKey("user.id", ondelete="CASCADE")) + user = db.relationship("User") class OAuth2Token(db.Model, OAuth2TokenMixin): - __tablename__ = 'oauth2_token' + __tablename__ = "oauth2_token" id = db.Column(db.Integer, primary_key=True) - user_id = db.Column( - db.Integer, db.ForeignKey('user.id', ondelete='CASCADE')) - user = db.relationship('User') + user_id = db.Column(db.Integer, db.ForeignKey("user.id", ondelete="CASCADE")) + user = db.relationship("User") diff --git a/tests/utils/mock_oauth_provider/oauth2.py b/tests/utils/mock_oauth_provider/oauth2.py index 3727aaa7f..6ee20e8d1 100644 --- a/tests/utils/mock_oauth_provider/oauth2.py +++ b/tests/utils/mock_oauth_provider/oauth2.py @@ -1,25 +1,30 @@ -from authlib.integrations.flask_oauth2 import (AuthorizationServer, - ResourceProtector) -from authlib.integrations.sqla_oauth2 import (create_bearer_token_validator, - create_query_client_func, - create_save_token_func) -from authlib.oauth2.rfc6749.grants import \ - AuthorizationCodeGrant as _AuthorizationCodeGrant +from authlib.integrations.flask_oauth2 import AuthorizationServer, ResourceProtector +from authlib.integrations.sqla_oauth2 import ( + create_bearer_token_validator, + create_query_client_func, + create_save_token_func, +) +from authlib.oauth2.rfc6749.grants import ( + AuthorizationCodeGrant as _AuthorizationCodeGrant, +) from authlib.oidc.core import UserInfo from authlib.oidc.core.grants import OpenIDCode as _OpenIDCode from authlib.oidc.core.grants import OpenIDHybridGrant as _OpenIDHybridGrant -from authlib.oidc.core.grants import \ - OpenIDImplicitGrant as _OpenIDImplicitGrant +from authlib.oidc.core.grants import OpenIDImplicitGrant as _OpenIDImplicitGrant from werkzeug.security import gen_salt from tests.utils import get_config_file_path -from tests.utils.mock_oauth_provider.models import (OAuth2AuthorizationCode, - OAuth2Client, OAuth2Token, - User, db) +from tests.utils.mock_oauth_provider.models import ( + OAuth2AuthorizationCode, + OAuth2Client, + OAuth2Token, + User, + db, +) JWT_CONFIG = { - 'key': ''.join(open(get_config_file_path('oidc_private.pem')).readlines()), - 'alg': 'RS256', - 'exp': 3600, + "key": "".join(open(get_config_file_path("oidc_private.pem")).readlines()), + "alg": "RS256", + "exp": 3600, } @@ -36,7 +41,7 @@ def generate_user_info(user, scope): def create_authorization_code(client, grant_user, request): code = gen_salt(48) - nonce = request.data.get('nonce') + nonce = request.data.get("nonce") item = OAuth2AuthorizationCode( code=code, client_id=client.client_id, @@ -51,12 +56,11 @@ def create_authorization_code(client, grant_user, request): class AuthorizationCodeGrant(_AuthorizationCodeGrant): - def generate_authorization_code(self): return gen_salt(48) def save_authorization_code(self, code, request): - nonce = request.data.get('nonce') + nonce = request.data.get("nonce") client = request.client item = OAuth2AuthorizationCode( code=code, @@ -72,7 +76,8 @@ def save_authorization_code(self, code, request): def query_authorization_code(self, code, client): item = OAuth2AuthorizationCode.query.filter_by( - code=code, client_id=client.client_id).first() + code=code, client_id=client.client_id + ).first() if item and not item.is_expired(): return item @@ -88,7 +93,6 @@ def get_jwt_config(self, grant): class OpenIDCode(_OpenIDCode): - def exists_nonce(self, nonce, request): return exists_nonce(nonce, request) @@ -130,19 +134,18 @@ def generate_user_info(self, user, scope): def config_oauth(app): global JWT_CONFIG - JWT_CONFIG['iss'] = app.config.get('OAUTH2_JWT_ISS') + JWT_CONFIG["iss"] = app.config.get("OAUTH2_JWT_ISS") query_client = create_query_client_func(db.session, OAuth2Client) save_token = create_save_token_func(db.session, OAuth2Token) - authorization.init_app( - app, - query_client=query_client, - save_token=save_token - ) + authorization.init_app(app, query_client=query_client, save_token=save_token) # support all openid grants - authorization.register_grant(AuthorizationCodeGrant, [ - OpenIDCode(require_nonce=True), - ]) + authorization.register_grant( + AuthorizationCodeGrant, + [ + OpenIDCode(require_nonce=True), + ], + ) authorization.register_grant(ImplicitGrant) authorization.register_grant(HybridGrant) diff --git a/tests/utils/mock_oauth_provider/routes.py b/tests/utils/mock_oauth_provider/routes.py index b1254ea0a..db2e04384 100644 --- a/tests/utils/mock_oauth_provider/routes.py +++ b/tests/utils/mock_oauth_provider/routes.py @@ -4,56 +4,55 @@ import jwcrypto.jwk as jwk from authlib.integrations.flask_oauth2 import current_token from authlib.oauth2 import OAuth2Error -from flask import (Blueprint, jsonify, request, - session, url_for) +from flask import Blueprint, jsonify, request, session, url_for from werkzeug.security import gen_salt from tests.utils import get_config_file_path -from tests.utils.mock_oauth_provider.models import (OAuth2Client, User, db) -from tests.utils.mock_oauth_provider.oauth2 import (authorization, require_oauth) +from tests.utils.mock_oauth_provider.models import OAuth2Client, User, db +from tests.utils.mock_oauth_provider.oauth2 import authorization, require_oauth logger = logging.getLogger(__name__) -bp = Blueprint(__name__, 'home') +bp = Blueprint("mock-oauth-provider", "home") def current_user(): - if 'id' in session: - uid = session['id'] + if "id" in session: + uid = session["id"] return User.query.get(uid) return None -@bp.route('/api/user', methods=('GET', 'POST')) +@bp.route("/api/user", methods=("GET", "POST")) def user(): user = current_user() - if request.method == 'POST': - username = request.form.get('username') + if request.method == "POST": + username = request.form.get("username") user = User.query.filter_by(username=username).first() if not user: user = User(username=username) db.session.add(user) db.session.commit() - session['id'] = user.id + session["id"] = user.id clients = [] if user: clients = OAuth2Client.query.filter_by(user=user).all() response = { - 'user': user.as_dict() if user else None, - 'clients': {c.client_metadata['client_name']: c.as_dict() for c in clients}, + "user": user.as_dict() if user else None, + "clients": {c.client_metadata["client_name"]: c.as_dict() for c in clients}, } return jsonify(response) -@bp.route('/api/create_client', methods=['POST']) +@bp.route("/api/create_client", methods=["POST"]) def create_client(): user = current_user() if not user: response = jsonify( { - 'message': 'Unauthorized, no active user session found', + "message": "Unauthorized, no active user session found", } ) return response, 401 @@ -63,8 +62,8 @@ def create_client(): client = OAuth2Client(client_id=client_id, user_id=user.id) # Mixin doesn't set the issue_at date client.client_id_issued_at = int(time.time()) - if client.token_endpoint_auth_method == 'none': - client.client_secret = '' + if client.token_endpoint_auth_method == "none": + client.client_secret = "" else: client.client_secret = gen_salt(48) @@ -75,7 +74,7 @@ def create_client(): "redirect_uris": form["redirect_uris"], "response_types": form["response_types"], "scope": form["scope"], - "token_endpoint_auth_method": form["token_endpoint_auth_method"] + "token_endpoint_auth_method": form["token_endpoint_auth_method"], } client.set_client_metadata(client_metadata) db.session.add(client) @@ -83,61 +82,71 @@ def create_client(): return jsonify(client.as_dict()) -@bp.route('/oauth/.well-known/openid-configuration', methods=['GET']) +@bp.route("/oauth/.well-known/openid-configuration", methods=["GET"]) def well_known(): - base_url = request.host_url.rstrip('/') + base_url = request.host_url.rstrip("/") response = { - 'issuer': '{url}/oauth'.format(url=base_url), - 'authorization_endpoint': '{url}{authorize}'.format(url=base_url, authorize=url_for(".authorize")), - 'token_endpoint': '{url}{issue}'.format(url=base_url, issue=url_for(".issue_token")), - 'jwks_uri': '{url}{get_keys}'.format(url=base_url, get_keys=url_for(".get_keys")), + "issuer": "{url}/oauth".format(url=base_url), + "authorization_endpoint": "{url}{authorize}".format( + url=base_url, authorize=url_for(".authorize") + ), + "token_endpoint": "{url}{issue}".format( + url=base_url, issue=url_for(".issue_token") + ), + "jwks_uri": "{url}{get_keys}".format( + url=base_url, get_keys=url_for(".get_keys") + ), } return jsonify(response) -@bp.route('/oauth/authorize', methods=['GET', 'POST']) +@bp.route("/oauth/authorize", methods=["GET", "POST"]) def authorize(): user = current_user() - if request.method == 'GET': + if request.method == "GET": try: - logger.debug('validate_consent_request for user: %s' % user) + logger.debug("validate_consent_request for user: %s" % user) grant = authorization.validate_consent_request(end_user=user) - logger.debug('grant for user %s: %s' % (user, grant)) + logger.debug("grant for user %s: %s" % (user, grant)) except OAuth2Error as error: return jsonify(dict(error.get_body())) - return jsonify({ - 'requesting_client': grant.client.client_name, - 'requested_scope': grant.request.scope, - 'user': user.username, - }) - if not user and 'username' in request.form: - username = request.form.get('username') + return jsonify( + { + "requesting_client": grant.client.client_name, + "requested_scope": grant.request.scope, + "user": user.username, + } + ) + if not user and "username" in request.form: + username = request.form.get("username") user = User.query.filter_by(username=username).first() - if request.form['confirm']: + if request.form["confirm"]: grant_user = user else: grant_user = None return authorization.create_authorization_response(grant_user=grant_user) -@bp.route('/oauth/token', methods=['POST']) +@bp.route("/oauth/token", methods=["POST"]) def issue_token(): return authorization.create_token_response() -@bp.route('/oauth/keys') +@bp.route("/oauth/keys") def get_keys(): - with open(get_config_file_path('oidc_private.pem'), 'rb') as fh: + with open(get_config_file_path("oidc_private.pem"), "rb") as fh: signing_key = jwk.JWK.from_pem(fh.read())._public_params() - return jsonify({ - 'keys': [ - signing_key, - ] - }) + return jsonify( + { + "keys": [ + signing_key, + ] + } + ) -@bp.route('/api/me') -@require_oauth('profile') +@bp.route("/api/me") +@require_oauth("profile") def api_me(): user = current_token.user return jsonify(id=user.id, username=user.username) diff --git a/tests/utils/mock_oauth_provider/settings.py b/tests/utils/mock_oauth_provider/settings.py index b58be4dd1..4b7df4171 100644 --- a/tests/utils/mock_oauth_provider/settings.py +++ b/tests/utils/mock_oauth_provider/settings.py @@ -1,5 +1,5 @@ # OAUTH2_JWT_ENABLED = True # OAUTH2_JWT_ISS = 'https://authlib.org' -OAUTH2_JWT_KEY = 'secret-key' -OAUTH2_JWT_ALG = 'HS256' +OAUTH2_JWT_KEY = "secret-key" +OAUTH2_JWT_ALG = "HS256" diff --git a/tests/utils/mock_okta_request_handler.py b/tests/utils/mock_okta_request_handler.py index d98de3058..23181e909 100644 --- a/tests/utils/mock_okta_request_handler.py +++ b/tests/utils/mock_okta_request_handler.py @@ -2,13 +2,7 @@ # -*- coding: utf-8 -*- import json import logging - -try: - # Python 2.7 - from http.server import BaseHTTPRequestHandler -except ImportError: - # Python 3.x - from BaseHTTPServer import BaseHTTPRequestHandler +from http.server import BaseHTTPRequestHandler class MockOktaRequestHandler(BaseHTTPRequestHandler): @@ -17,15 +11,15 @@ class MockOktaRequestHandler(BaseHTTPRequestHandler): def do_GET(self): """Dispatch GET requests to associated mock Okta 'handlers'.""" self.send_response(200) - self.send_header('Content-Type', 'application/json') + self.send_header("Content-Type", "application/json") self.end_headers() logging.debug(self.headers) return - if self.path == '/user': + if self.path == "/user": self.do_user() - elif self.path == '/user/orgs?per_page=100': + elif self.path == "/user/orgs?per_page=100": self.do_organizations_list() - elif self.path == '/user/teams?per_page=100': + elif self.path == "/user/teams?per_page=100": self.do_team_list() return @@ -48,7 +42,7 @@ def do_organizations_list(self): Only returns data if the request Authorization header has a contrived Okta token value of "valid-token". """ response = [] - if self.headers.get('Authorization') == 'Bearer valid-token': + if self.headers.get("Authorization") == "Bearer valid-token": response.append( { "login": "hvac", @@ -64,14 +58,14 @@ def do_team_list(self): Only returns data if the request Authorization header has a contrived Okta token value of "valid-token". """ response = [] - if self.headers.get('Authorization') == 'Bearer valid-token': + if self.headers.get("Authorization") == "Bearer valid-token": response.append( { "name": "hvac-team", "slug": "hvac-team", "organization": { "id": 1, - } + }, } ) self.wfile.write(json.dumps(response).encode()) diff --git a/tests/utils/server_manager.py b/tests/utils/server_manager.py index a7979372f..cbdb1285c 100644 --- a/tests/utils/server_manager.py +++ b/tests/utils/server_manager.py @@ -39,8 +39,8 @@ def start(self): if self.use_consul: self.start_consul() - if distutils.spawn.find_executable('vault') is None: - raise SkipTest('Vault executable not found') + if distutils.spawn.find_executable("vault") is None: + raise SkipTest("Vault executable not found") # If a vault server is already running then we won't be able to start another one. # If we can't start our vault server then we don't know what we're testing against. @@ -49,28 +49,32 @@ def start(self): except Exception: pass else: - raise Exception('Vault server already running') + raise Exception("Vault server already running") cluster_ready = False for config_path in self.config_paths: - command = ['vault', 'server', '-config=' + config_path] - logger.debug('Starting vault server with command: {cmd}'.format(cmd=command)) - process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + command = ["vault", "server", "-config=" + config_path] + logger.debug( + "Starting vault server with command: {cmd}".format(cmd=command) + ) + process = subprocess.Popen( + command, stdout=subprocess.PIPE, stderr=subprocess.PIPE + ) self._processes.append(process) - logger.debug('Spawned vault server with PID {pid}'.format(pid=process.pid)) + logger.debug("Spawned vault server with PID {pid}".format(pid=process.pid)) attempts_left = 20 last_exception = None while attempts_left > 0 and not cluster_ready: try: - logger.debug('Checking if vault is ready...') + logger.debug("Checking if vault is ready...") self.client.sys.is_initialized() cluster_ready = True break except Exception as ex: if process.poll() is not None: - raise Exception('Vault server terminated before becoming ready') - logger.debug('Waiting for Vault to start') + raise Exception("Vault server terminated before becoming ready") + logger.debug("Waiting for Vault to start") time.sleep(0.5) attempts_left -= 1 last_exception = ex @@ -79,7 +83,7 @@ def start(self): process.kill() stdout, stderr = process.communicate() raise Exception( - 'Unable to start Vault in background:\n{err}\n{stdout}\n{stderr}'.format( + "Unable to start Vault in background:\n{err}\n{stdout}\n{stderr}".format( err=last_exception, stdout=stdout, stderr=stderr, @@ -87,58 +91,78 @@ def start(self): ) def start_consul(self): - if distutils.spawn.find_executable('consul') is None: - raise SkipTest('Consul executable not found') + if distutils.spawn.find_executable("consul") is None: + raise SkipTest("Consul executable not found") try: - requests.get('http://127.0.0.1:8500/v1/catalog/nodes') + requests.get("http://127.0.0.1:8500/v1/catalog/nodes") except Exception: pass else: - raise Exception('Consul service already running') + raise Exception("Consul service already running") - command = ['consul', 'agent', '-dev'] - logger.debug('Starting consul service with command: {cmd}'.format(cmd=command)) - process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + command = ["consul", "agent", "-dev"] + logger.debug("Starting consul service with command: {cmd}".format(cmd=command)) + process = subprocess.Popen( + command, stdout=subprocess.PIPE, stderr=subprocess.PIPE + ) self._processes.append(process) attempts_left = 20 last_exception = None while attempts_left > 0: try: - catalog_nodes_response = requests.get('http://127.0.0.1:8500/v1/catalog/nodes') + catalog_nodes_response = requests.get( + "http://127.0.0.1:8500/v1/catalog/nodes" + ) nodes_list = catalog_nodes_response.json() - logger.debug('JSON response from request to consul/v1/catalog/noses: {resp}'.format(resp=nodes_list)) - node_name = nodes_list[0]['Node'] - logger.debug('Current consul node name: {name}'.format(name=node_name)) - node_health_response = requests.get('http://127.0.0.1:8500/v1/health/node/{name}'.format(name=node_name)) + logger.debug( + "JSON response from request to consul/v1/catalog/noses: {resp}".format( + resp=nodes_list + ) + ) + node_name = nodes_list[0]["Node"] + logger.debug("Current consul node name: {name}".format(name=node_name)) + node_health_response = requests.get( + "http://127.0.0.1:8500/v1/health/node/{name}".format(name=node_name) + ) node_health = node_health_response.json() - logger.debug('Node health response: {resp}'.format(resp=node_health)) - assert node_health[0]['Status'] == 'passing', 'Node {name} status != "passing"'.format(name=node_name) + logger.debug("Node health response: {resp}".format(resp=node_health)) + assert ( + node_health[0]["Status"] == "passing" + ), 'Node {name} status != "passing"'.format(name=node_name) return True except Exception as error: if process.poll() is not None: - raise Exception('Consul service terminated before becoming ready') - logger.debug('Unable to connect to consul while waiting for process to start: {err}'.format(err=error)) + raise Exception("Consul service terminated before becoming ready") + logger.debug( + "Unable to connect to consul while waiting for process to start: {err}".format( + err=error + ) + ) time.sleep(0.5) attempts_left -= 1 last_exception = error - raise Exception('Unable to start consul in background: {0}'.format(last_exception)) + raise Exception( + "Unable to start consul in background: {0}".format(last_exception) + ) def stop(self): """Stop the vault server process being managed by this class.""" for process_num, process in enumerate(self._processes): - logger.debug('Terminating vault server with PID {pid}'.format(pid=process.pid)) + logger.debug( + "Terminating vault server with PID {pid}".format(pid=process.pid) + ) if process.poll() is None: process.kill() - if os.getenv('HVAC_OUTPUT_VAULT_STDERR', False): + if os.getenv("HVAC_OUTPUT_VAULT_STDERR", False): stdout_lines, stderr_lines = process.communicate() - stderr_filename = 'vault{num}_stderr.log'.format(num=process_num) - with open(get_config_file_path(stderr_filename), 'w') as f: + stderr_filename = "vault{num}_stderr.log".format(num=process_num) + with open(get_config_file_path(stderr_filename), "w") as f: logger.debug(stderr_lines.decode()) f.writelines(stderr_lines.decode()) - stdout_filename = 'vault{num}_stdout.log'.format(num=process_num) - with open(get_config_file_path(stdout_filename), 'w') as f: + stdout_filename = "vault{num}_stdout.log".format(num=process_num) + with open(get_config_file_path(stdout_filename), "w") as f: logger.debug(stdout_lines.decode()) f.writelines(stdout_lines.decode()) @@ -148,8 +172,8 @@ def initialize(self): result = self.client.sys.initialize() - self.root_token = result['root_token'] - self.keys = result['keys'] + self.root_token = result["root_token"] + self.keys = result["keys"] def restart_vault_cluster(self, perform_init=True): self.stop() @@ -163,14 +187,18 @@ def get_active_vault_addresses(self): config_hcl = load_config_file(config_path) config = hcl.loads(config_hcl) try: - vault_address = 'https://{addr}'.format(addr=config['listener']['tcp']['address']) + vault_address = "https://{addr}".format( + addr=config["listener"]["tcp"]["address"] + ) except KeyError as error: - logger.debug('Unable to find explict Vault address in config file {path}: {err}'.format( - path=config_path, - err=error, - )) - vault_address = 'https://127.0.0.1:8200' - logger.debug('Using default address: {addr}'.format(addr=vault_address)) + logger.debug( + "Unable to find explict Vault address in config file {path}: {err}".format( + path=config_path, + err=error, + ) + ) + vault_address = "https://127.0.0.1:8200" + logger.debug("Using default address: {addr}".format(addr=vault_address)) vault_addresses.append(vault_address) return vault_addresses