feat(cli): add --raw and --base64 flags for clean SSH key import/export#33
Merged
feat(cli): add --raw and --base64 flags for clean SSH key import/export#33
Conversation
Add output modes to `get` command for clean secret extraction: - --raw: strips trailing whitespace per line, no headers/formatting - --base64: outputs value as single base64-encoded line Add input modes to `set` command for encoded import: - --base64: accepts inline base64-encoded value - --base64-file: reads base64 from file or stdin (-) Add clean_multiline_value() helper that strips trailing whitespace per line and ensures exactly one trailing newline. Applied on --raw export and --file import to prevent YAML multiline formatting artifacts.
0adb17a to
8c601a8
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
SSH private keys and certificates stored in Ansible Vault suffer from whitespace corruption during YAML multiline formatting. This PR adds clean import/export modes to prevent these issues.
get --raw: Outputs value without Type: headers or field labels, strips trailing whitespace per line, ensures single trailing newline. Ideal forvaultctl get key --field privateKey --raw > key.pemget --base64: Outputs value as a single base64-encoded line, suitable for environments that cannot handle multiline valuesset --base64: Accepts an inline base64-encoded value, decodes before storingset --base64-file: Reads base64 from a file or stdin (-), decodes before storingset --file: Now applies whitespace cleanup (trailing space removal) on importclean_multiline_value(): New helper that strips trailing whitespace per line and ensures exactly one trailing newlineProblem
When SSH keys are stored in YAML via
ansible-vault, the multiline formatting introduces trailing spaces on lines. Extracting these keys withvaultctl get ... --json | jq -rproduces keys that SSH rejects. There was no way to get a clean, whitespace-safe export or to import base64-encoded values.Changed Files
src/vaultctl/cli.py--rawand--base64flags toget,--base64and--base64-fileoptions toset, mutual exclusivity validation,_output_raw()and_output_base64_encoded()helperssrc/vaultctl/yaml_util.pyclean_multiline_value()helpertests/test_cli.pytests/test_yaml_util.pyclean_multiline_value()tests/conftest.pyssh_keyfixture entry with trailing whitespace for testingDesign Decisions
clean_multiline_valueinyaml_util.py— It is a value formatting utility closely related to YAML handling, keeping it here avoids a new module for one function--json,--raw,--base64— Validated at runtime with a clear error message rather than Click'scls=MutuallyExclusiveOptionto keep it simple--filenow cleans whitespace on import — Prevents storing corrupted values at the source. This is a minor behavioral change but strictly an improvement--base64-file -for stdin — Follows Unix convention, enables piping:cat key.pem | base64 | vaultctl set key --base64-file -Test Plan
get --rawon plain strings outputs clean valueget --rawon multiline values strips trailing whitespaceget --raw --fieldextracts single field without headersget --rawon structured entries outputs YAML without Type: headerget --base64produces valid single-line base64get --base64on multiline values cleans before encodingget --base64 --fieldworks on individual fields--json,--raw,--base64are mutually exclusiveset --base64decodes and stores correctlyset --base64rejects invalid inputset --base64-filereads from fileset --base64-file -reads from stdinset --filecleans trailing whitespaceclean_multiline_valueunit tests (7 cases)