Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JSON format missing versions info #256

Open
nichcuta opened this issue May 11, 2024 · 1 comment · May be fixed by #265
Open

JSON format missing versions info #256

nichcuta opened this issue May 11, 2024 · 1 comment · May be fixed by #265

Comments

@nichcuta
Copy link

Hi,

As the title implies, JSON format currently does not have version number displayed unlike base output format. It would be great to know the version number of the secret when outputting in JSON.

Furthermore, do you have any plans to support extracting all versions of a secret in JSON format? This is highly beneficial if running a search against the export in JSON.

You would know:

  • The Secret name and its version
  • If the value changed in later versions
@nichcuta
Copy link
Author

nichcuta commented May 12, 2024

In the meantime I wrote the below python script which converts the export type 'base' to a JSON format & includes the secret version as a key named 'vault_secret_version'

Tested with vkv version 0.7.0.

#!/usr/bin/env python3

import json
import sys

# Tested on vkv version v0.7.0!
# Usage:
    # ./vkv export -p <KV_ENGINE> --show-values --with-hyperlink=false --max-value-length -1 --format base > output.base
    # save to file: python3 vkv-base-to-json.py output.base output.json
    # output to stdout: python3 vkv-base-to-json.py output.base


addSecretVersion = False     # Variable to decide if we want to display secret version info


def getCurrentPosition(line):
    charCount = 0
    for char in line:
        if not char.isalpha():
            charCount += 1
        else:
            break
    return charCount


try:
    with open(sys.argv[1], 'r') as file:
        fileContent = file.read()
except:
    print("Can't open file. Double check file path provided!")
    exit()


previousPosition = 0
jsonString = ""
for line in fileContent.split('\n'):
    if "│" in line and "──" not in line:    # For incorrectly formatted multiline values.
        if jsonString[-3:] == '",\n':
            jsonString = jsonString[:-3]+"\\n"
        line = line[previousPosition:]  # Removing extra whitespaces due to incorrectly formatted newline
        jsonString += line.replace("\\", "\\\\").replace('"', '\\"')+"\\n"
    elif previousPosition == getCurrentPosition(line) and line != "" and "=" not in line:     # This means new dict
        jsonString += '{"' + line + '": {\n'
    elif previousPosition == getCurrentPosition(line) and "=" in line:  # This means its a password
        if jsonString[-2:] == '\\n':
            jsonString = jsonString[:-2]+'",\n'
        line = line[previousPosition:]
        jsonString += " " * (int(previousPosition/2)) + '"' + line.split("=", 1)[0] + '": "' + line.split("=", 1)[1].replace("\\", "\\\\").replace('"', '\\"') + '",\n'
    elif getCurrentPosition(line) > previousPosition:   # Sub values
        previousPosition = getCurrentPosition(line)
        line = line[previousPosition:]
        if "[v=" in line:   # This means its a secret
            if addSecretVersion:
                jsonString += " " * (int(previousPosition/2)) + '"' + line.split(" [v")[0] + '": {\n' + " " * (int(previousPosition/2)+2) + '"vault_secret_version": "' + line.split(" [v=")[1].replace("]", "") + '",\n'
            else:
                jsonString += " " * (int(previousPosition/2)) + '"' + line.split(" [v")[0] + '": {\n'   #Exactly like JSON output
        elif "=" in line:   # This means its a password
            jsonString += " " * (int(previousPosition/2)) + '"' + line.split("=", 1)[0] + '": "' + line.split("=", 1)[1].replace("\\", "\\\\").replace('"', '\\"') + '",\n'
        else:
            jsonString += " " * (int(previousPosition/2)) + '"' + line + '/": {\n'
    elif getCurrentPosition(line) < previousPosition:   # new Sub Value
        while True:
            if previousPosition - 4 > getCurrentPosition(line):
                if jsonString[-2:] == ",\n":
                    jsonString = jsonString[:-2]+"\n"
                elif jsonString[-2:] == "\\n":
                    jsonString = jsonString[:-2]+'"\n'
                elif jsonString[-2:] == "{\n":
                    jsonString = jsonString[:-2]+'{}\n'
                previousPosition = previousPosition - 4
                jsonString += " " * (int(previousPosition/2)) + '}\n'
            else:
                previousPosition = getCurrentPosition(line)
                if jsonString[-2:] == ",\n":
                    jsonString = jsonString[:-2]+"\n"
                elif jsonString[-2:] == "\\n":
                    jsonString = jsonString[:-2]+'"\n'
                elif jsonString[-2:] == "{\n":
                    jsonString = jsonString[:-2]+'{}\n'
                jsonString += " " * (int(previousPosition/2)) + '},\n'
                break
        line = line[previousPosition:]
        if "[v=" in line:   # This means its a secret
            if addSecretVersion:
                jsonString += " " * (int(previousPosition/2)) + '"' + line.split(" [v")[0] + '": {\n' + " " * (int(previousPosition/2)+2) + '"vault_secret_version": "' + line.split(" [v=")[1].replace("]", "") + '",\n'
            else:
                jsonString += " " * (int(previousPosition/2)) + '"' + line.split(" [v")[0] + '": {\n' #Exactly like JSON output
        elif "=" in line:   # This means its a password
            jsonString += " " * (int(previousPosition/2)) + '"' + line.split("=")[0] + '": "' + line.split("=")[1] + '",\n'
        else:
            jsonString += " " * (int(previousPosition/2)) + '"' + line + '/": {\n'

if len(sys.argv) > 2:
    with open(sys.argv[2], 'w') as file:
        file.write(jsonString[:-9]+'}')
else:
    print(jsonString[:-9]+'}')

This enables me to cross match kubernetes secret value with key in secret and use the secret name & version to populate ExternalSecretsOperator in a dynamic way

@FalcoSuessgott FalcoSuessgott linked a pull request May 28, 2024 that will close this issue
6 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant