oth_rvault 0.4.0

Partial Ansible Vault encoder and decoder
Documentation

crates.io Docker Hub

rvault

A tool to encrypt or decrypt JSON or YAML files that contain partial Ansible vault encrypted values.

This is a Rust port from here: https://github.com/OkieOth/partial-vaults/tree/main

Overview

rvault allows you to work with files that have a mix of plain text and Ansible Vault encrypted values. Unlike standard Ansible Vault which encrypts entire files, this tool lets you:

  • Encrypt specific values within JSON or YAML files
  • Decrypt specific values while leaving others encrypted
  • Process nested structures with selective encryption
  • Interactively edit encrypted values in-place
  • Copy decrypted values to the clipboard with auto-clear

Install

# install from crates.io
cargo install oth_rvault

# use
rvault --help

Usage

rvault has four subcommands: encrypt, decrypt, edit, and clip.

Password resolution

All subcommands need a vault password. It is resolved in this priority order:

  1. --password <PASSWORD> — pass the password directly on the command line
  2. --pfile <FILE> — read the password from a file
  3. MY_RVAULT_PWD environment variable — path to a password file
# inline password
rvault decrypt -i secrets.yaml --stdout --password mypassword

# password from file
rvault decrypt -i secrets.yaml --stdout --pfile ~/.vault_pass

# password from environment (recommended for scripts)
export MY_RVAULT_PWD=~/.vault_pass
rvault decrypt -i secrets.yaml --stdout

Output target

For encrypt, decrypt, and edit, exactly one output option must be given:

Flag Behaviour
-o <FILE> Write result to a new file
--overwrite Replace the input file in-place
--stdout Print result to standard output

encrypt

Encrypt scalar values inside a JSON or YAML file using Ansible Vault AES256.

rvault encrypt -i <INPUT> (-o <OUTPUT> | --overwrite | --stdout)
               --password <PASSWORD>
               [-k <KEY>]...
               [--level <DEPTH>]
               [--ansible]

Encrypt all values in a file:

rvault encrypt -i example.json -o encrypted.json --password secret

Encrypt specific keys using dot-notation paths:

# single key
rvault encrypt -i example.json -o encrypted.json --password secret -k first.a

# multiple keys (repeat the flag or use comma-separation)
rvault encrypt -i example.json -o encrypted.json --password secret \
    -k first.a -k first.z

rvault encrypt -i example.json -o encrypted.json --password secret \
    -k first.a,first.z

Encrypt by nesting depth with --level (cannot be combined with --key):

# encrypt all values at the top level (depth 1)
rvault encrypt -i example.json -o encrypted.json --password secret --level 1

# encrypt all values two levels deep
rvault encrypt -i example.yaml --overwrite --password secret --level 2

Overwrite the file in-place:

rvault encrypt -i secrets.yaml --overwrite --password secret

Print to stdout (useful for piping):

rvault encrypt -i example.json --stdout --password secret

decrypt

Decrypt some or all encrypted values in a partially-encrypted file.

rvault decrypt -i <INPUT> (-o <OUTPUT> | --overwrite | --stdout)
               --password <PASSWORD>
               [-k <KEY>]...
               [--value-only]
               [--interactive]

Decrypt all values:

rvault decrypt -i encrypted.json -o plain.json --password secret

Decrypt specific keys:

rvault decrypt -i encrypted.json --stdout --password secret -k second.a.v

Value-only mode (--value-only / -v) — output only the selected key(s) as a minimal nested document (requires at least one --key or --interactive):

# prints just the nested sub-document for the selected keys
rvault decrypt -i encrypted.json --stdout --password secret \
    -k second.a.v --value-only

Interactive (fuzzy) mode — opens an interactive prompt to select which encrypted keys to decrypt:

rvault decrypt -i encrypted.json --stdout --password secret --interactive

# combine with --value-only to output only the selected values
rvault decrypt -i encrypted.json --stdout --password secret \
    --interactive --value-only

edit

Decrypt a value, open it in $EDITOR, then re-encrypt and save.

rvault edit -i <INPUT> (-o <OUTPUT> | --overwrite | --stdout)
            --password <PASSWORD>
            [-k <KEY>]...
            [-a | --interactive]

Edit a specific key:

rvault edit -i secrets.yaml --overwrite --password secret -k database.password

Edit multiple keys:

rvault edit -i secrets.yaml --overwrite --password secret \
    -k database.password -k api.token

Fuzzy-select which key to edit (default when no --key is given):

rvault edit -i secrets.yaml --overwrite --password secret

Edit all encrypted values without selection (-a):

rvault edit -i secrets.yaml --overwrite --password secret -a

clip

Fuzzy-search encrypted values and copy the decrypted result to the clipboard. The clipboard is automatically cleared after a timeout.

rvault clip -i <INPUT> --password <PASSWORD>
            [--timeout <SECONDS>]
            [--pfile <FILE>]
# default: clear clipboard after 30 seconds
rvault clip -i secrets.yaml --password secret

# keep clipboard for 60 seconds
rvault clip -i secrets.yaml --password secret --timeout 60

# never clear the clipboard automatically
rvault clip -i secrets.yaml --password secret --timeout 0

File format

rvault works with plain JSON or YAML files. Encrypted values are stored inline as Ansible Vault strings:

# example.yaml — mixed plain/encrypted YAML
first:
    z: last
    a: first
    m: middle
second:
    a:
        v: true   # plain boolean
        w: 14     # plain integer
        x: "$ANSIBLE_VAULT;1.1;AES256\n..."  # encrypted string
{
  "first": {
    "z": "last",
    "a": "$ANSIBLE_VAULT;1.1;AES256\n...",
    "m": "middle"
  }
}

The original Rust type (bool, integer, float, string) is preserved across an encrypt→decrypt round-trip.


Docker

# decrypt a file
docker run --rm -u $(id -u):$(id -g) \
    -v /path/to/input:/input \
    -v /path/to/output:/output \
    docker.io/okieoth/rvault:latest decrypt \
     -i /input/secrets.yaml -o /output/decrypted.yaml \
     --password mypassword

# encrypt a file
docker run --rm -u $(id -u):$(id -g) \
    -v /path/to/input:/input \
    -v /path/to/output:/output \
    docker.io/okieoth/rvault:latest encrypt \
     -i /input/plain.yaml -o /output/secrets.yaml \
     --password mypassword

Build

# build binary
cargo build

# run tests
cargo test

# build docker image
make docker-build

Mac OS Builds

To do cargo install under Mac OS you need at first to install Rust. That the linking of the final program works you need the Mac OS developer tools too. You can install them with xcode-select --install. Attention, after executing the xcode-select command a new window opens. Sometimes this window is hidden in the stack of other open program windows.

Additional

  • Password for resources/tests/partial.yaml: aa
  • Password for resources/tests/partial_encrypted_example.json: test999
  • Password for resources/tests/partial_encrypted_example.yaml: test999