Compare commits

...

24 Commits
0.1.1 ... devel

Author SHA1 Message Date
0bb654c2e2
Merge pull request #7 from enpaul/enp/ci
Update CI to always use python3.10 for metaenv
2024-03-21 18:33:05 -04:00
8e621138e9
Update CI to always use python3.10 for metaenv 2024-03-21 18:28:27 -04:00
de4ff0031f
Update changelog for version 0.1.3 2023-04-03 12:01:05 -04:00
50a5481108
Bump version to 0.1.3 2023-04-03 11:58:58 -04:00
3586a4e277
Merge pull request #3 from brycelowe/fix/password-binary-encoding
fix: remove encoding from password file reads
2023-04-03 11:57:12 -04:00
Bryce Lowe
45ab9addb3
fix: remove encoding from password file reads
The password files are opened in binary mode so an encoding argument isn't necessary and causes the script to crash.

Fixes #2
2023-04-01 21:50:40 -07:00
90e4a32753
Merge pull request #4 from enpaul/enp/ci
Fix CI
2023-03-29 20:17:40 -04:00
3dc062c849
Update markdown to new GFM formatting spec 2023-03-29 20:11:23 -04:00
fdad46a945
Remove deprecated option from pylintrc 2023-03-29 20:06:38 -04:00
96bd80db6e
Fix bug with poetry installation on python3.7
Remove python3.6 compatibility
2023-03-29 20:06:36 -04:00
fcaac8ca43
Add workaround for export plugin issue 2023-03-29 19:03:47 -04:00
9c6486ce55
Update poetry CI version to 1.4.1
Update CI env script to move poetry version to main CI workflow config
2023-03-29 19:03:01 -04:00
c3fe7bdef9
Remove python 3.6 CI tests 2023-03-29 18:46:29 -04:00
98d1bf3e8e
Update repo automation to use new command syntax
Update CI to use Poetry 1.3
Update workflows to match patterns from tox-poetry-installer
Update workflows to use newer job versions
Update makefile and CI to use Poetry 1.3 command syntax
2023-03-02 17:03:20 -05:00
d11af1658d
Update to use poetry dev groups 2023-03-02 16:59:44 -05:00
29243223fe
Update dev environment to use Python-3.10 for all dependencies 2023-03-02 16:19:11 -05:00
a98dd16358
Add parallel flag to tox call in makefile 2022-05-07 18:51:34 -04:00
226c717684
Update classifiers for beta status 2022-05-07 18:46:25 -04:00
b55af77051
Update changelog with version 0.1.2 2022-05-07 18:45:37 -04:00
4550a73404
Merge pull request #1 from enpaul/enp/docs
Add documentation
2022-05-07 18:43:33 -04:00
bdb62993a2
Bump patch version 2022-05-07 18:37:21 -04:00
3f6f5cf7e0
Add documentation for the tools usage 2022-05-07 18:36:54 -04:00
2f75180623
Fix styling of introduction docs 2022-05-07 12:27:29 -04:00
c729414b03
Document main logic function for processing filepaths
Fix docstring on confirm function
2022-05-07 12:26:56 -04:00
11 changed files with 2293 additions and 1486 deletions

View File

@ -4,31 +4,34 @@
# to create a repeatable local environment for tests to be run in. The python env # to create a repeatable local environment for tests to be run in. The python env
# this script creates can be accessed at the location defined by the CI_VENV variable # this script creates can be accessed at the location defined by the CI_VENV variable
# below. # below.
#
# POETRY_VERSION can be set to install a specific version of Poetry
set -e; set -e;
CI_CACHE=$HOME/.cache; CI_CACHE=$HOME/.cache;
POETRY_VERSION=1.1.12; INSTALL_POETRY_VERSION="${POETRY_VERSION:-1.3.2}";
mkdir --parents "$CI_CACHE"; mkdir --parents "$CI_CACHE";
command -v python; command -v python;
python --version; python3.10 --version;
curl --location https://install.python-poetry.org \ curl --location https://install.python-poetry.org \
--output "$CI_CACHE/install-poetry.py" \ --output "$CI_CACHE/install-poetry.py" \
--silent \ --silent \
--show-error; --show-error;
python "$CI_CACHE/install-poetry.py" \ python "$CI_CACHE/install-poetry.py" \
--version "$POETRY_VERSION" \ --version "$INSTALL_POETRY_VERSION" \
--yes; --yes;
poetry --version --no-ansi; poetry --version --no-ansi;
poetry run pip --version; poetry run pip --version;
poetry install \ poetry install \
--quiet \ --sync \
--remove-untracked \ --no-ansi \
--no-ansi; --no-root \
--only ci;
poetry env info; poetry env info;
poetry run tox --version; poetry run tox --version;

View File

@ -5,14 +5,16 @@ on:
types: ["opened", "synchronize"] types: ["opened", "synchronize"]
push: push:
branches: ["devel"] branches: ["devel"]
env:
POETRY_VERSION: 1.4.1
jobs: jobs:
Test: Test:
name: Python ${{ matrix.python.version }}
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy: strategy:
fail-fast: true
matrix: matrix:
python: python:
- version: "3.6"
toxenv: py36
- version: "3.7" - version: "3.7"
toxenv: py37 toxenv: py37
- version: "3.8" - version: "3.8"
@ -21,15 +23,24 @@ jobs:
toxenv: py39 toxenv: py39
- version: "3.10" - version: "3.10"
toxenv: py310 toxenv: py310
- version: "3.11"
toxenv: py311
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v2 uses: actions/checkout@v2
- name: Install Python 3.10
uses: actions/setup-python@v4
with:
python-version: "3.10"
- name: Install Python ${{ matrix.python.version }} - name: Install Python ${{ matrix.python.version }}
uses: actions/setup-python@v1 uses: actions/setup-python@v4
with: with:
python-version: ${{ matrix.python.version }} python-version: ${{ matrix.python.version }}
- name: Configure Job Cache - name: Configure Job Cache
uses: actions/cache@v2 uses: actions/cache@v3
with: with:
path: | path: |
~/.cache/pip ~/.cache/pip
@ -39,38 +50,49 @@ jobs:
# will be invalidated, and thus all packages will be redownloaded, if the # will be invalidated, and thus all packages will be redownloaded, if the
# lockfile is updated # lockfile is updated
key: ${{ runner.os }}-${{ matrix.python.toxenv }}-${{ hashFiles('**/poetry.lock') }} key: ${{ runner.os }}-${{ matrix.python.toxenv }}-${{ hashFiles('**/poetry.lock') }}
- name: Configure Path - name: Configure Path
run: echo "$HOME/.local/bin" >> $GITHUB_PATH run: echo "$HOME/.local/bin" >> $GITHUB_PATH
- name: Configure Environment - name: Configure Environment
run: .github/scripts/setup-env.sh run: .github/scripts/setup-env.sh
- name: Run Toxenv ${{ matrix.python.toxenv }} - name: Run Toxenv ${{ matrix.python.toxenv }}
run: poetry run tox -e ${{ matrix.python.toxenv }} run: poetry run tox -e ${{ matrix.python.toxenv }}
Check: Check:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v2 uses: actions/checkout@v2
- name: Install Python 3.8
uses: actions/setup-python@v1 - name: Install Python 3.10
uses: actions/setup-python@v4
with: with:
python-version: 3.8 python-version: "3.10"
- name: Configure Job Cache - name: Configure Job Cache
uses: actions/cache@v2 uses: actions/cache@v3
with: with:
path: | path: |
~/.cache/pip ~/.cache/pip
~/.cache/pypoetry/cache ~/.cache/pypoetry/cache
~/.poetry ~/.poetry
# Hardcoded 'py38' slug here lets this cache piggyback on the 'py38' cache # Hardcoded 'py310' slug here lets this cache piggyback on the 'py310' cache
# that is generated for the tests above # that is generated for the tests above
key: ${{ runner.os }}-py38-${{ hashFiles('**/poetry.lock') }} key: ${{ runner.os }}-py310-${{ hashFiles('**/poetry.lock') }}
- name: Configure Path - name: Configure Path
run: echo "$HOME/.local/bin" >> $GITHUB_PATH run: echo "$HOME/.local/bin" >> $GITHUB_PATH
- name: Configure Environment - name: Configure Environment
run: .github/scripts/setup-env.sh run: .github/scripts/setup-env.sh
- name: Run Static Analysis Checks - name: Run Static Analysis Checks
run: poetry run tox -e static run: poetry run tox -e static
- name: Run Static Analysis Checks (Tests) - name: Run Static Analysis Checks (Tests)
run: poetry run tox -e static-tests run: poetry run tox -e static-tests
- name: Run Security Checks - name: Run Security Checks
run: poetry run tox -e security run: poetry run tox -e security

View File

@ -11,7 +11,6 @@
# --disable=W" # --disable=W"
disable=logging-fstring-interpolation disable=logging-fstring-interpolation
,logging-format-interpolation ,logging-format-interpolation
,bad-continuation
,line-too-long ,line-too-long
,ungrouped-imports ,ungrouped-imports
,typecheck ,typecheck

View File

@ -2,6 +2,23 @@
See also: [Github Release Page](https://github.com/enpaul/vault2vault/releases). See also: [Github Release Page](https://github.com/enpaul/vault2vault/releases).
## Version 0.1.3
View this release on: [Github](https://github.com/enpaul/vault2vault/releases/tag/0.1.3),
[PyPI](https://pypi.org/project/vault2vault/0.1.3/)
- Fix incorrect encoding specification when opening password files. Contributed by
[brycelowe](https://github.com/brycelowe) (#2)
## Version 0.1.2
View this release on: [Github](https://github.com/enpaul/vault2vault/releases/tag/0.1.2),
[PyPI](https://pypi.org/project/vault2vault/0.1.2/)
- Add user documentation
- Add project road map
- Fix incorrect and missing docstrings for internal functions
## Version 0.1.1 ## Version 0.1.1
View this release on: [Github](https://github.com/enpaul/vault2vault/releases/tag/0.1.1), View this release on: [Github](https://github.com/enpaul/vault2vault/releases/tag/0.1.1),
@ -9,8 +26,8 @@ View this release on: [Github](https://github.com/enpaul/vault2vault/releases/ta
- Fix bug causing stack trace when the same vaulted block appears in a YAML file more than - Fix bug causing stack trace when the same vaulted block appears in a YAML file more than
once once
- Fix bug where the `--ignore-undecryptable` option was not respected for vaulted variables - Fix bug where the `--ignore-undecryptable` option was not respected for vaulted
in YAML files variables in YAML files
- Update logging messages and levels to improve verbose output - Update logging messages and levels to improve verbose output
## Version 0.1.0 ## Version 0.1.0

View File

@ -27,9 +27,10 @@ Examples of unacceptable behavior include:
- The use of sexualized language or imagery, and sexual attention or advances of any kind - The use of sexualized language or imagery, and sexual attention or advances of any kind
- Trolling, insulting or derogatory comments, and personal or political attacks - Trolling, insulting or derogatory comments, and personal or political attacks
- Public or private harassment - Public or private harassment
- Publishing others' private information, such as a physical or email address, without their - Publishing others' private information, such as a physical or email address, without
explicit permission their explicit permission
- Other conduct which could reasonably be considered inappropriate in a professional setting - Other conduct which could reasonably be considered inappropriate in a professional
setting
## Enforcement Responsibilities ## Enforcement Responsibilities
@ -52,8 +53,8 @@ offline event.
## Enforcement ## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the
community leaders responsible for enforcement at \[INSERT CONTACT METHOD\]. All community leaders responsible for enforcement at \[INSERT CONTACT METHOD\]. All complaints
complaints will be reviewed and investigated promptly and fairly. will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the reporter of All community leaders are obligated to respect the privacy and security of the reporter of
any incident. any incident.
@ -105,8 +106,8 @@ toward or disparagement of classes of individuals.
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 2.0, This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 2.0,
available at https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. available at https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
Community Impact Guidelines were inspired by [Mozilla's code of conduct Community Impact Guidelines were inspired by
enforcement ladder](https://github.com/mozilla/diversity). [Mozilla's code of conduct enforcement ladder](https://github.com/mozilla/diversity).
For answers to common questions about this code of conduct, see the FAQ at For answers to common questions about this code of conduct, see the FAQ at
https://www.contributor-covenant.org/faq. Translations are available at https://www.contributor-covenant.org/faq. Translations are available at

View File

@ -30,10 +30,10 @@ source: ## Build Python source distribution package
poetry build --format sdist poetry build --format sdist
test: ## Run the project testsuite(s) test: ## Run the project testsuite(s)
poetry run tox --recreate poetry run tox --recreate --parallel
dev: ## Create the local dev environment dev: ## Create the local dev environment
poetry install poetry install --with dev --extras ansible --sync
poetry run pre-commit install poetry run pre-commit install
publish: test wheel source ## Build and upload to pypi (requires $PYPI_API_KEY be set) publish: test wheel source ## Build and upload to pypi (requires $PYPI_API_KEY be set)

144
README.md
View File

@ -10,11 +10,13 @@ but works recursively on encrypted files and in-line variables
[![Python Supported Versions](https://img.shields.io/pypi/pyversions/vault2vault)](https://www.python.org) [![Python Supported Versions](https://img.shields.io/pypi/pyversions/vault2vault)](https://www.python.org)
[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black) [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
⚠️ **This project is alpha software and is under active development** ⚠️ ⚠️ **This project is beta software and is under active development** ⚠️
- [What is this?](#what-is-this) - [What is this?](#what-is-this)
- [Installing](#installing) - [Installing](#installing)
- [Using](#using) - [Usage](#usage)
- [Recovering from a failed migration](#recovering-from-a-failed-migration)
- [Roadmap](#roadmap)
- [Developing](#developer-documentation) - [Developing](#developer-documentation)
## What is this? ## What is this?
@ -27,13 +29,10 @@ terminal. Whatever, these things happen.
The built-in tool Ansible provides, The built-in tool Ansible provides,
[`ansible-vault rekey`](https://docs.ansible.com/ansible/latest/cli/ansible-vault.html#rekey), [`ansible-vault rekey`](https://docs.ansible.com/ansible/latest/cli/ansible-vault.html#rekey),
suffers from two main drawbacks: suffers from two main drawbacks: first, it only works on vault encrypted files and not on
vault encrypted YAML data; and second, it only works on a single vault encrypted file at a
1. It only works on vault encrypted files and not on vault encrypted YAML data time. To rekey everything in a large project you'd need to write a script that recursively
2. It only works on a single vault encrypted file at a time. goes through every file and rekeys every encrypted file and YAML variable all at once.
To rekey everything in a large project you'd need to write a script that goes through
every file and rekeys everything in every format it can find.
This is that script. This is that script.
@ -58,49 +57,110 @@ install `vault2vault` using [PipX](https://pypa.github.io/pipx/) and the `ansibl
pipx install vault2vault[ansible] pipx install vault2vault[ansible]
``` ```
**Note: vault2vault requires an Ansible installation to function. If you are installing to a standalone virtual environment (like with PipX) then you must install it with the `ansible` extra to ensure a version of Ansible is available to the application.** > Note: vault2vault requires an Ansible installation to function. If you are installing to
> a standalone virtual environment (like with PipX) then you must install it with the
> `ansible` extra to ensure a version of Ansible is available to the application.\*\*
## Using ## Usage
These docs are pretty sparse, largely because this project is still under active design > Note: the full command reference is available by running `vault2vault --help`
and redevelopment. Here are the command line options:
``` Vault2Vault works with files in any arbitrary directory structures, so there is no need to
> vault2vault --help have your Ansible project(s) structured in a specific way for the tool to work. The
usage: vault2vault [-h] [--version] [--interactive] [-v] [-b] [-i VAULT_ID] [--ignore-undecryptable] simplest usage of Vault2Vault is by passing the path to your Ansible project directory to
[--old-pass-file OLD_PASS_FILE] [--new-pass-file NEW_PASS_FILE] the command:
[paths ...]
Recursively rekey ansible-vault encrypted files and in-line variables ```bash
vault2vault ./my-ansible-project/
positional arguments:
paths Paths to search for Ansible Vault encrypted content
options:
-h, --help show this help message and exit
--version Show program version and exit
--interactive Step through files and variables interactively, prompting for confirmation before making
each change
-v, --verbose Increase verbosity; can be repeated
-b, --backup Write a backup of every file to be modified, suffixed with '.bak'
-i VAULT_ID, --vault-id VAULT_ID
Limit rekeying to encrypted secrets with the specified Vault ID
--ignore-undecryptable
Ignore any file or variable that is not decryptable with the provided vault secret instead
of raising an error
--old-pass-file OLD_PASS_FILE
Path to a file with the old vault password to decrypt secrets with
--new-pass-file NEW_PASS_FILE
Path to a file with the new vault password to rekey secrets with
``` ```
Please report any bugs or issues you encounter on The tool will prompt for the current vault password and the new vault password and then
[Github](https://github.com/enpaul/vault2vault/issues). process every file under the provided path. You can also specify multiple paths and
they'll all be processed together:
```bash
vault2vault \
./my-ansible-project/playbooks/ \
./my-ansible-project/host_vars/ \
./my-ansible-project/group_vars/
```
To skip the interactive password prompts you can put the password in a file and have the
tool read it in at runtime. The `--old-pass-file` and `--new-pass-file` parameters work
the same way as the `--vault-password-file` option from the `ansible` command:
```bash
vault2vault ./my-ansible-project/ \
--old-pass-file=./oldpass.txt \
--new-pass-file=./newpass.txt
```
If you use multiple vault passwords in your project and want to roll them you'll need to
run `vault2vault` once for each password you want to change. By default, `vault2vault`
will fail with an error if it encounters vaulted data that it cannot decrypt with the
provided current vault password. To change this behavior and instead just ignore any
vaulted data that can't be decrypted (like, for example, if you have data encrypted with
multiple vault passwords) you can pass the `--ignore-undecryptable` flag to turn the
errors into warnings.
> Please report any bugs or issues you encounter on
> [Github](https://github.com/enpaul/vault2vault/issues).
### Recovering from a failed migration
This tool is still pretty early in it's development, and to be honest it hooks into
Ansible's functionality in some fragile ways. I've tested as best I can to ensure it
covers as many edge cases as possible, but there is still the chance that you might get
partway through a password migration and then have the tool fail out, leaving half of your
data successfully rekeyed and the other half not.
In the spirit of the
[Unix philosophy](https://hackaday.com/2018/09/10/doing-one-thing-well-the-unix-philosophy/)
this tool does not include any built-in way to recover from this state. However, it can be
done very effectively using a version control tool.
If you are using Git to track your project files then you can use the command
`git reset --hard` to restore all files to the state of the currently checked out commit.
This does have the side effect of erasing any other un-committed work in the repository,
so it's recommended to always have a clean working tree when using Vault2Vault.
If you are not using a version control system to track your project files then you can
create a temporary Git repository to use in the event of a migration failure:
```bash
cd my-project/
# Initialize the new repository
git init
# Add and commit all your existing files to the git tree
git add .
git commit -m "initial commit"
# Run vault migrations
vault2vault ...
# If no recovery is necessary, delete the git repository data
rm -rf .git
```
## Roadmap
This project is considered feature complete as of the
[0.1.1](https://github.com/enpaul/vault2vault/releases/tag/0.1.1) release. As a result the
roadmap focuses on stability and user experience ahead of a 1.0 release.
- [ ] Reimplement core vaulted data processing function to enable multithreading
- [ ] Implement multithreading for performance in large environments
- [ ] Add unit tests
- [ ] Add integration tests
- [ ] Redesign logging messages to improve clarity and consistency
## Developer Documentation ## Developer Documentation
All project contributors and participants are expected to adhere to the All project contributors and participants are expected to adhere to the
[Contributor Covenant Code of Conduct, v2](CODE_OF_CONDUCT.md) ([external link](https://www.contributor-covenant.org/version/2/0/code_of_conduct/)). [Contributor Covenant Code of Conduct, v2](CODE_OF_CONDUCT.md)
([external link](https://www.contributor-covenant.org/version/2/0/code_of_conduct/)).
The `devel` branch has the latest (and potentially unstable) changes. The stable releases The `devel` branch has the latest (and potentially unstable) changes. The stable releases
are tracked on [Github](https://github.com/enpaul/vault2vault/releases), are tracked on [Github](https://github.com/enpaul/vault2vault/releases),

3415
poetry.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
[tool.poetry] [tool.poetry]
name = "vault2vault" name = "vault2vault"
version = "0.1.1" version = "0.1.3"
license = "MIT" license = "MIT"
authors = ["Ethan Paul <24588726+enpaul@users.noreply.github.com>"] authors = ["Ethan Paul <24588726+enpaul@users.noreply.github.com>"]
description = "Recursively rekey ansible-vault encrypted files and in-line variables" description = "Recursively rekey ansible-vault encrypted files and in-line variables"
@ -12,7 +12,7 @@ packages = [
keywords = ["ansible", "vault", "playbook", "yaml", "password"] keywords = ["ansible", "vault", "playbook", "yaml", "password"]
readme = "README.md" readme = "README.md"
classifiers = [ classifiers = [
"Development Status :: 3 - Alpha", "Development Status :: 4 - Beta",
"Environment :: Console", "Environment :: Console",
"Framework :: Ansible", "Framework :: Ansible",
"Intended Audience :: Developers", "Intended Audience :: Developers",
@ -22,11 +22,11 @@ classifiers = [
"Natural Language :: English", "Natural Language :: English",
"Operating System :: OS Independent", "Operating System :: OS Independent",
"Programming Language :: Python :: 3", "Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: Implementation :: CPython" "Programming Language :: Python :: Implementation :: CPython"
] ]
@ -37,30 +37,43 @@ vault2vault = "vault2vault:main"
ansible = ["ansible-core"] ansible = ["ansible-core"]
[tool.poetry.dependencies] [tool.poetry.dependencies]
python = "^3.6.1" python = "^3.7"
"ruamel.yaml" = "^0.17.16" "ruamel.yaml" = "^0.17.16"
ansible-core = {version = "^2.11.5", optional = true} ansible-core = {version = "^2.11.5", optional = true}
[tool.poetry.dev-dependencies] [tool.poetry.group.dev.dependencies]
bandit = "^1.6.2" black = {version = "^23.1.0", python = "^3.10"}
black = { version = "^21.9b0", allow-prereleases = true, python = "^3.7" } blacken-docs = {version = "^1.13.0", python = "^3.10"}
blacken-docs = "^1.8.0" ipython = {version = "^8.10.1", python = "^3.10"}
ipython = { version = "^7.18.1", python = "^3.7" } mdformat = {version = "^0.7.16", python = "^3.10"}
mypy = "^0.800" mdformat-gfm = {version = "^0.3.5", python = "^3.10"}
pre-commit = "^2.7.1" mypy = {version = "^1.1.1", python = "^3.10"}
pre-commit-hooks = "^3.3.0" pre-commit = {version = "^2.7.1", python = "^3.10"}
pylint = "^2.4.4" pre-commit-hooks = {version = "^3.3.0", python = "^3.10"}
pytest = "^6.0.2" pylint = {version = "^2.4.4", python = "^3.10"}
pytest-cov = "^2.10.1" reorder-python-imports = {version = "^2.3.5", python = "^3.10"}
reorder-python-imports = "^2.3.5" types-toml = {version = "^0.10.4", python = "^3.10"}
safety = "^1.9.0" # Implicit python version check fails for this one
toml = "^0.10.1" packaging = {version = "^23.0", python = "^3.10"}
tox = "^3.20.0"
tox-poetry-installer = { version = "^0.8.1", extras = ["poetry"] } [tool.poetry.group.security.dependencies]
types-toml = "^0.10.4" bandit = {version = "^1.6.2", python = "^3.10"}
mdformat = "^0.6.4" safety = {version = "^2.2.0", python = "^3.10"}
mdformat-gfm = "^0.2" poetry = {version = "^1.2.0", python = "^3.10"}
[tool.poetry.group.test.dependencies]
pytest = {version = "^6.0.2"}
pytest-cov = {version = "^2.10.1"}
toml = {version = "^0.10.1"}
typing-extensions = {version = "^4.5.0", python = "^3.8"}
[tool.poetry.group.ci.dependencies]
tox = {version = "^3.20.0"}
tox-poetry-installer = {version = "^0.10.1", extras = ["poetry"]}
# This doesn't get installed under py3.7 for some reason, but it's
# required for poetry. Will need to debug this more in the future
backports-cached-property = "^1.0.2"
[build-system] [build-system]
requires = ["poetry-core>=1.0.0"] requires = ["poetry-core>=1.1.0"]
build-backend = "poetry.core.masonry.api" build-backend = "poetry.core.masonry.api"

43
tox.ini
View File

@ -1,5 +1,5 @@
[tox] [tox]
envlist = py36, py37, py38, py39, py310, static, static-tests, security envlist = py3{7-11}, static, static-tests, security
isolated_build = true isolated_build = true
skip_missing_interpreters = true skip_missing_interpreters = true
@ -9,10 +9,8 @@ require_locked_deps = true
require_poetry = true require_poetry = true
extras = extras =
ansible ansible
locked_deps = poetry_dep_groups =
pytest test
pytest-cov
toml
commands = commands =
pytest {toxinidir}/tests/ \ pytest {toxinidir}/tests/ \
--cov vault2vault \ --cov vault2vault \
@ -21,20 +19,11 @@ commands =
[testenv:static] [testenv:static]
description = Static formatting and quality enforcement description = Static formatting and quality enforcement
basepython = python3.8 basepython = python3.10
platform = linux platform = linux
ignore_errors = true ignore_errors = true
locked_deps = poetry_dep_groups =
black dev
blacken-docs
mdformat
mdformat-gfm
mypy
reorder-python-imports
pre-commit
pre-commit-hooks
pylint
types-toml
commands = commands =
pre-commit run \ pre-commit run \
--all-files --all-files
@ -46,7 +35,7 @@ commands =
[testenv:static-tests] [testenv:static-tests]
description = Static formatting and quality enforcement for the tests description = Static formatting and quality enforcement for the tests
basepython = python3.8 basepython = python3.10
platform = linux platform = linux
ignore_errors = true ignore_errors = true
locked_deps = locked_deps =
@ -63,14 +52,12 @@ commands =
[testenv:security] [testenv:security]
description = Security checks description = Security checks
basepython = python3.8 basepython = python3.10
platform = linux platform = linux
ignore_errors = true ignore_errors = true
skip_install = true skip_install = true
locked_deps = poetry_dep_groups =
bandit security
safety
poetry
commands = commands =
bandit {toxinidir}/vault2vault.py \ bandit {toxinidir}/vault2vault.py \
--recursive \ --recursive \
@ -82,8 +69,14 @@ commands =
poetry export \ poetry export \
--format requirements.txt \ --format requirements.txt \
--output {envtmpdir}/requirements.txt \ --output {envtmpdir}/requirements.txt \
--without-hashes \ --without-hashes
--dev # For now these groups are disabled until this bug is resolved
# in poetry-plugin-export:
# https://github.com/python-poetry/poetry-plugin-export/issues/176
# --with dev \
# --with ci \
# --with security \
# --with test
safety check \ safety check \
--file {envtmpdir}/requirements.txt \ --file {envtmpdir}/requirements.txt \
--json --json

View File

@ -28,7 +28,7 @@ except ImportError:
__title__ = "vault2vault" __title__ = "vault2vault"
__summary__ = "Recursively rekey ansible-vault encrypted files and in-line variables" __summary__ = "Recursively rekey ansible-vault encrypted files and in-line variables"
__version__ = "0.1.1" __version__ = "0.1.3"
__url__ = "https://github.com/enpaul/vault2vault/" __url__ = "https://github.com/enpaul/vault2vault/"
__license__ = "MIT" __license__ = "MIT"
__authors__ = ["Ethan Paul <24588726+enpaul@users.noreply.github.com>"] __authors__ = ["Ethan Paul <24588726+enpaul@users.noreply.github.com>"]
@ -73,6 +73,19 @@ def _process_file( # pylint: disable=too-many-statements
backup: bool, backup: bool,
ignore: bool, ignore: bool,
) -> None: ) -> None:
"""Determine whether a filepath includes vaulted data and if so, rekey it
:param path: Path to the file to check
:param old: VaultLib object with the current (old) vault password encoded in it
:param new: VaultLib object with the target (new) vault password encoded in it
:param interactive: Whether to prompt interactively for confirmation before each
rekey operation
:param backup: Whether to copy the original file to a backup before making any
in-place changes
:param ignore: Whether to ignore any errors that come from failing to decrypt
any vaulted data
"""
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
logger.debug(f"Processing file {path}") logger.debug(f"Processing file {path}")
@ -348,6 +361,7 @@ def _load_password(
the password will be prompted for interactively. the password will be prompted for interactively.
:param desc: Description text to inject into the interactive password prompt. Useful when using :param desc: Description text to inject into the interactive password prompt. Useful when using
this function multiple times to identify different passwords to the user. this function multiple times to identify different passwords to the user.
:param confirm: Whether to prompt twice for the input and check that the two inputs match
:returns: Populated vault secret object with the loaded password :returns: Populated vault secret object with the loaded password
""" """
@ -355,7 +369,7 @@ def _load_password(
if fpath: if fpath:
try: try:
with Path(fpath).resolve().open("rb", encoding="utf-8") as infile: with Path(fpath).resolve().open("rb") as infile:
return VaultSecret(infile.read()) return VaultSecret(infile.read())
except (FileNotFoundError, PermissionError) as err: except (FileNotFoundError, PermissionError) as err:
raise RuntimeError( raise RuntimeError(