-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathvaultctl_test.sh
More file actions
executable file
·563 lines (467 loc) · 25.3 KB
/
vaultctl_test.sh
File metadata and controls
executable file
·563 lines (467 loc) · 25.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
#!/usr/bin/env bash
#*******************************************************************************
# Copyright (c) 2026 Eclipse Foundation and others.
# This program and the accompanying materials are made available
# under the terms of the Eclipse Public License 2.0
# which is available at http://www.eclipse.org/legal/epl-v20.html
# SPDX-License-Identifier: EPL-2.0
#*******************************************************************************
# // Some portions generated by Co-Pilot
# Bash strict-mode
set -o errexit
set -o nounset
set -o pipefail
IFS=$'\n\t'
SCRIPT_FOLDER="$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")"
VAULTCTL="${SCRIPT_FOLDER}/vaultctl.sh"
# Use same config file location as vaultctl.sh
VAULT_CONFIG_FILE="${VAULT_CONFIG_FILE:-$HOME/.vaultctl_test}"
export VAULT_CONFIG_FILE
# Temporary files array for cleanup
TEMP_FILES=()
# Cleanup function for EXIT trap
cleanup_temp_files() {
for temp_file in "${TEMP_FILES[@]}"; do
if [[ -f "$temp_file" ]]; then
rm -f "$temp_file"
fi
done
# Clean up test config file
if [[ -f "$VAULT_CONFIG_FILE" ]]; then
rm -f "$VAULT_CONFIG_FILE"
fi
}
# Set trap to cleanup temp files on exit
trap cleanup_temp_files EXIT
# Test helper function for assertions
assert_equals() {
local expected="$1"
local actual="$2"
local test_description="$3"
if [[ "$expected" != "$actual" ]]; then
echo -e "INFO: Test failed: $test_description \u274c"
echo "INFO: Expected: $expected"
echo "INFO: Actual: $actual"
exit 1
else
echo -e "INFO: $test_description \u2705"
fi
}
# Function to cleanup vault paths after tests
cleanup_vault() {
local mount="$1"
local path="$2"
# vault kv delete -mount="$mount" "$path" > /dev/null 2>&1 || true
echo "INFO: Start cleanup for path: ${path}"
if ! metadata=$(vault kv metadata get -mount="${mount}" -format=json "${path}" 2> /dev/null); then
echo "INFO: No metadata found for path: ${path}, skipping cleanup"
return
fi
if ! data=$(echo "${metadata}" | jq '.data' 2> /dev/null); then
echo "WARN: Failed to parse metadata for path: ${path}, skipping cleanup"
return
fi
[[ "${data}" == "null" ]] && return
versions=$(echo "${metadata}" | jq '.data.versions | keys_unsorted[] | tonumber' | tr '\n' ',' | sed 's/\(.*\),/\1 /')
echo "INFO: Path to delete ${path}, versions: ${versions}"
if [[ -z "${versions}" ]]; then
echo -e "WARN: Versions for: ${path} is empty!"
else
vault kv destroy -mount="${mount}" -versions="$versions" "${path}" > /dev/null 2>&1 || true
vault kv metadata delete -mount="${mount}" "${path}" > /dev/null 2>&1 || true
fi
echo -e "INFO: End cleanup for path: ${path}\n"
}
# Setup for tests
VAULT_MOUNT="test"
VAULT_PATH="test/path"
VAULT_KEY_1="key1"
VAULT_VALUE_1="secret_value1"
VAULT_KEY_2="key2"
VAULT_VALUE_2="secret_value2"
VAULT_KEY_3="key3"
VAULT_VALUE_3="secret_value3"
VAULT_FILE_PATH="$(mktemp)"
VAULT_FILE_PATH1="$(mktemp)"
VAULT_FILE_PATH2="$(mktemp)"
VAULT_EMPTY_FILE_PATH="$(mktemp)"
# Track temp files for cleanup
TEMP_FILES+=("$VAULT_FILE_PATH" "$VAULT_FILE_PATH1" "$VAULT_FILE_PATH2" "$VAULT_EMPTY_FILE_PATH")
# Populate temp files
echo '{"file_key_value_test":"file_secret_value"}' > "$VAULT_FILE_PATH"
echo '{"file_key_value_test1":"file_secret_value1"}' > "$VAULT_FILE_PATH1"
echo '{"file_key_value_test2":"file_secret_value2"}' > "$VAULT_FILE_PATH2"
# Explicitly create empty file for empty-file test case
: > "$VAULT_EMPTY_FILE_PATH"
# Test cases for vaultctl write and vaultctl read
test_vaultctl_write_read() {
local result
# Cleanup before test
cleanup_vault "$VAULT_MOUNT" "$VAULT_PATH"
######## Test writing a simple value #############################################
"$VAULTCTL" write "$VAULT_MOUNT" "$VAULT_PATH" "$VAULT_KEY_1"="$VAULT_VALUE_1"
result=$("$VAULTCTL" read "$VAULT_MOUNT" "$VAULT_PATH/$VAULT_KEY_1" 2>&1 | sed 's/\x1b\[[0-9;]*m//g')
assert_equals "$VAULT_VALUE_1" "$result" "vaultctl write and read for simple value"
######## Test overwriting a simple value #############################################
"$VAULTCTL" write "$VAULT_MOUNT" "$VAULT_PATH" "$VAULT_KEY_1"="$VAULT_VALUE_2"
result=$("$VAULTCTL" read "$VAULT_MOUNT" "$VAULT_PATH/$VAULT_KEY_1" 2>&1 | sed 's/\x1b\[[0-9;]*m//g')
assert_equals "$VAULT_VALUE_2" "$result" "vaultctl write and read for overwritting same field"
######## Test writing add a new fields #############################################
"$VAULTCTL" write "$VAULT_MOUNT" "$VAULT_PATH" "$VAULT_KEY_2"="$VAULT_VALUE_2"
result=$("$VAULTCTL" read "$VAULT_MOUNT" "$VAULT_PATH/$VAULT_KEY_2" 2>&1 | sed 's/\x1b\[[0-9;]*m//g')
assert_equals "$VAULT_VALUE_2" "$result" "vaultctl write and read for simple value"
######## Test writing from stdin #############################################
echo "$VAULT_VALUE_3" | "$VAULTCTL" write "$VAULT_MOUNT" "$VAULT_PATH" "$VAULT_KEY_3=-"
result=$("$VAULTCTL" read "$VAULT_MOUNT" "$VAULT_PATH/$VAULT_KEY_3" 2>&1 | sed 's/\x1b\[[0-9;]*m//g')
assert_equals "$VAULT_VALUE_3" "$result" "vaultctl write and read from stdin"
######## Test writing from stdin mixed with value #############################################
echo "$VAULT_VALUE_2" | "$VAULTCTL" write "$VAULT_MOUNT" "$VAULT_PATH" "$VAULT_KEY_1=$VAULT_VALUE_3" "$VAULT_KEY_3=-"
result1=$("$VAULTCTL" read "$VAULT_MOUNT" "$VAULT_PATH/$VAULT_KEY_1" 2>&1 | sed 's/\x1b\[[0-9;]*m//g')
result2=$("$VAULTCTL" read "$VAULT_MOUNT" "$VAULT_PATH/$VAULT_KEY_3" 2>&1 | sed 's/\x1b\[[0-9;]*m//g')
assert_equals "$VAULT_VALUE_3" "$result1" "vaultctl write and read from stdin mixed with value"
assert_equals "$VAULT_VALUE_2" "$result2" "vaultctl write and read from stdin mixed with value"
######## Test writing patch both fields #############################################
"$VAULTCTL" write "$VAULT_MOUNT" "$VAULT_PATH" "$VAULT_KEY_1=$VAULT_VALUE_1" "$VAULT_KEY_2=$VAULT_VALUE_1"
result1=$("$VAULTCTL" read "$VAULT_MOUNT" "$VAULT_PATH/$VAULT_KEY_1" 2>&1 | sed 's/\x1b\[[0-9;]*m//g')
result2=$("$VAULTCTL" read "$VAULT_MOUNT" "$VAULT_PATH/$VAULT_KEY_2" 2>&1 | sed 's/\x1b\[[0-9;]*m//g')
assert_equals "$VAULT_VALUE_1" "$result1" "vaultctl write and read patch first key"
assert_equals "$VAULT_VALUE_1" "$result2" "vaultctl write and read patch second key"
######## Test writing a key and a value from a file #############################################
"$VAULTCTL" write "$VAULT_MOUNT" "$VAULT_PATH" "@$VAULT_FILE_PATH"
result=$("$VAULTCTL" read "$VAULT_MOUNT" "$VAULT_PATH/file_key_value_test" 2>&1 | sed 's/\x1b\[[0-9;]*m//g')
assert_equals "file_secret_value" "$result" "vaultctl write and read for file key/value content"
######## Test writing only a value from a file 1 #############################################
"$VAULTCTL" write "$VAULT_MOUNT" "$VAULT_PATH" "import_file1=@$VAULT_FILE_PATH"
result=$("$VAULTCTL" read "$VAULT_MOUNT" "$VAULT_PATH/import_file1" 2>&1 | sed 's/\x1b\[[0-9;]*m//g')
assert_equals "$(cat "$VAULT_FILE_PATH")" "$result" "vaultctl write and read for file content"
######## Test writing only a value from a file 2 #############################################
"$VAULTCTL" write "$VAULT_MOUNT" "$VAULT_PATH" "import_file2=-" < "$VAULT_FILE_PATH"
result=$("$VAULTCTL" read "$VAULT_MOUNT" "$VAULT_PATH/import_file2" 2>&1 | sed 's/\x1b\[[0-9;]*m//g')
assert_equals "$(cat "$VAULT_FILE_PATH")" "$result" "vaultctl write and read for file content"
######## Test writing multiple files #############################################
"$VAULTCTL" write "$VAULT_MOUNT" "$VAULT_PATH" "import_multi_file1=@$VAULT_FILE_PATH1" "import_multi_file2=@$VAULT_FILE_PATH2"
result1=$("$VAULTCTL" read "$VAULT_MOUNT" "$VAULT_PATH/import_multi_file1" 2>&1 | sed 's/\x1b\[[0-9;]*m//g')
result2=$("$VAULTCTL" read "$VAULT_MOUNT" "$VAULT_PATH/import_multi_file2" 2>&1 | sed 's/\x1b\[[0-9;]*m//g')
assert_equals "$(cat "$VAULT_FILE_PATH1")" "$result1" "vaultctl write and read for file content1"
assert_equals "$(cat "$VAULT_FILE_PATH2")" "$result2" "vaultctl write and read for file content2"
######## Test conditionnal read #############################################
if "$VAULTCTL" read "$VAULT_MOUNT" "$VAULT_PATH/$VAULT_KEY_1" &> /dev/null ; then
echo -e "INFO: vaultctl read conditionnal test existing path \u2705"
else
echo -e "ERROR: vaultctl read conditionnal test existing path \u274c"
fi
# Cleanup after test
cleanup_vault "$VAULT_MOUNT" "$VAULT_PATH"
}
# Test cases for error handling
test_vaultctl_read_errors() {
local result
local message
local config_file="$VAULT_CONFIG_FILE"
# Backup and clear config to ensure clean state for error tests
local backup_file=""
if [[ -f "$config_file" ]]; then
backup_file=$(mktemp)
cp "$config_file" "$backup_file"
rm -f "$config_file"
fi
unset VAULT_MOUNT
######## Test missing mount #############################################
result=$("$VAULTCTL" read "" "$VAULT_PATH" 2>&1 | sed 's/\x1b\[[0-9;]*m//g' || true)
message="❌ Usage: vaultctl read [-b] [-c] [-v] [<mount>] <path>
NOTE: If mount is not specified, VAULT_MOUNT environment variable or config will be used
NOTE: path can be either a secret name (to list keys) or secret/field
Options:
-b, --batch Silent mode: suppress all messages, only return exit code
-c, --clip Copy secret to clipboard instead of displaying it
-v, --verbose Verbose mode: display vault commands being executed
Examples:
vaultctl config VAULT_MOUNT=cbi # Set default mount
vaultctl read technology.cbi/github.com/api-token # Uses default mount
vaultctl read cbi technology.cbi # List keys in secret 'technology.cbi'
vaultctl read users <username>/cbi/JENKINS_USERNAME
vaultctl read cbi technology.cbi/github.com/api-token
vaultctl read -b cbi technology.cbi/github.com/api-token && echo ok
vaultctl read -c cbi technology.cbi/github.com/api-token # Copy to clipboard
vaultctl read -v cbi technology.cbi/github.com/api-token"
assert_equals "${message}" "${result}" "vaultctl read with missing mount"
######## Test missing path #############################################
result=$("$VAULTCTL" read "test" "" 2>&1 | sed 's/\x1b\[[0-9;]*m//g' || true)
message="❌ Usage: vaultctl read [-b] [-c] [-v] [<mount>] <path>
NOTE: If mount is not specified, VAULT_MOUNT environment variable or config will be used
NOTE: path can be either a secret name (to list keys) or secret/field
Options:
-b, --batch Silent mode: suppress all messages, only return exit code
-c, --clip Copy secret to clipboard instead of displaying it
-v, --verbose Verbose mode: display vault commands being executed
Examples:
vaultctl config VAULT_MOUNT=cbi # Set default mount
vaultctl read technology.cbi/github.com/api-token # Uses default mount
vaultctl read cbi technology.cbi # List keys in secret 'technology.cbi'
vaultctl read users <username>/cbi/JENKINS_USERNAME
vaultctl read cbi technology.cbi/github.com/api-token
vaultctl read -b cbi technology.cbi/github.com/api-token && echo ok
vaultctl read -c cbi technology.cbi/github.com/api-token # Copy to clipboard
vaultctl read -v cbi technology.cbi/github.com/api-token"
assert_equals "${message}" "${result}" "vaultctl read with missing path"
######## Test path must not start by slash #############################################
result=$("$VAULTCTL" read "test" "/XXXXXX" 2>&1 | sed 's/\x1b\[[0-9;]*m//g' || true)
assert_equals "❌ Path cannot start with a slash: /XXXXXX" "${result}" "vaultctl read path must not start by slash"
######## Test path must not end by slash #############################################
result=$("$VAULTCTL" read "test" "XXXXXX/" 2>&1 | sed 's/\x1b\[[0-9;]*m//g' || true)
# After normalization, "XXXXXX/" becomes "XXXXXX" (no slash), so it tries to list keys
message="⚠️ Not a secret. Trying to list secrets in path...
❌ Vault entry not found: vault kv get -mount=\"test\" \"XXXXXX\""
assert_equals "${message}" "${result}" "vaultctl read path must not end by slash"
######## Test path must have one slash #############################################
result=$("$VAULTCTL" read "test" "XXXXXX" 2>&1 | sed 's/\x1b\[[0-9;]*m//g' || true)
# With no slash, it tries to list keys in secret 'XXXXXX'
message="⚠️ Not a secret. Trying to list secrets in path...
❌ Vault entry not found: vault kv get -mount=\"test\" \"XXXXXX\""
assert_equals "${message}" "${result}" "vaultctl read path must have one slash"
######## Test non exiting path #############################################
result=$("$VAULTCTL" read "test" "XXX/XXX" 2>&1 | sed 's/\x1b\[[0-9;]*m//g' || true)
message="⚠️ Field 'XXX' not found. Trying to list keys of the secret...
⚠️ Secret not found. Trying to list secrets in path...
❌ Vault entry not found: vault kv get -mount=\"test\" -field=\"XXX\" \"XXX\""
assert_equals "${message}" "${result}" "vaultctl read with non existing path"
######## Test conditionnal read #############################################
if ! "$VAULTCTL" read "test" "XXX/XXX" &> /dev/null ; then
echo -e "INFO: vaultctl read conditionnal test non existing path \u2705"
else
echo -e "ERROR: vaultctl read conditionnal test non existing path \u274c"
fi
# Restore backup if any
if [[ -n "$backup_file" ]]; then
mv "$backup_file" "$config_file"
fi
}
test_vaultctl_write_errors() {
local result
local message
local config_file="$VAULT_CONFIG_FILE"
# Backup and clear config to ensure clean state for error tests
local backup_file=""
if [[ -f "$config_file" ]]; then
backup_file=$(mktemp)
cp "$config_file" "$backup_file"
rm -f "$config_file"
fi
unset VAULT_MOUNT
######## Test missing mount #############################################
result=$("$VAULTCTL" write "" "$VAULT_PATH" "$VAULT_KEY_1=$VAULT_VALUE_1" 2>&1 | sed 's/\x1b\[[0-9;]*m//g' || true)
message="❌ Usage: vaultctl write [<mount>] <path> [<key>=<secret> | <key>=@<secret_file> | @<secret_file>]
NOTE: If mount is not specified, VAULT_MOUNT environment variable or config will be used
NOTE: path is the full path to the secret without the field name
Examples:
vaultctl config VAULT_MOUNT=users # Set default mount
vaultctl write myuser/cbi username=john password=secret123 # Uses default mount
vaultctl write users myuser/cbi username=john password=secret123
vaultctl write users myuser/cbi token=@token.txt
vaultctl write users myuser/cbi @secrets.json"
assert_equals "${message}" "${result}" "vaultctl write with missing mount"
######## Test missing path #############################################
result=$("$VAULTCTL" write "test" "" "$VAULT_KEY_1=$VAULT_VALUE_1" 2>&1 | sed 's/\x1b\[[0-9;]*m//g' || true)
message="❌ Usage: vaultctl write [<mount>] <path> [<key>=<secret> | <key>=@<secret_file> | @<secret_file>]
NOTE: If mount is not specified, VAULT_MOUNT environment variable or config will be used
NOTE: path is the full path to the secret without the field name
Examples:
vaultctl config VAULT_MOUNT=users # Set default mount
vaultctl write myuser/cbi username=john password=secret123 # Uses default mount
vaultctl write users myuser/cbi username=john password=secret123
vaultctl write users myuser/cbi token=@token.txt
vaultctl write users myuser/cbi @secrets.json"
assert_equals "${message}" "${result}" "vaultctl write with missing path"
######## Test missing fields #############################################
result=$("$VAULTCTL" write "test" "$VAULT_PATH" 2>&1 | sed 's/\x1b\[[0-9;]*m//g' || true)
message="❌ Usage: vaultctl write [<mount>] <path> [<key>=<secret> | <key>=@<secret_file> | @<secret_file>]
NOTE: If mount is not specified, VAULT_MOUNT environment variable or config will be used
NOTE: path is the full path to the secret without the field name
Examples:
vaultctl config VAULT_MOUNT=users # Set default mount
vaultctl write myuser/cbi username=john password=secret123 # Uses default mount
vaultctl write users myuser/cbi username=john password=secret123
vaultctl write users myuser/cbi token=@token.txt
vaultctl write users myuser/cbi @secrets.json"
assert_equals "${message}" "${result}" "vaultctl write with missing fields"
######## Test missing value in fields #############################################"
result=$("$VAULTCTL" write "test" "$VAULT_PATH" "$VAULT_KEY_1=$VAULT_VALUE_1 $VAULT_KEY_2=" 2>&1 | sed 's/\x1b\[[0-9;]*m//g' || true)
message="❌ Field key '$VAULT_KEY_2' or value '' is empty"
assert_equals "${message}" "${result}" "vaultctl write with missing value in fields"
######## Test missing value in fields with only key ref #############################################"
result=$("$VAULTCTL" write "test" "$VAULT_PATH" "$VAULT_KEY_1=$VAULT_VALUE_1 $VAULT_KEY_2" 2>&1 | sed 's/\x1b\[[0-9;]*m//g' || true)
message="❌ Field key '$VAULT_KEY_2' or value '' is empty"
assert_equals "${message}" "${result}" "vaultctl write with missing value in fields with only key ref"
######## Test missing file for write #############################################"
result=$("$VAULTCTL" write "test" "$VAULT_PATH" "$VAULT_KEY_1=@test.json" 2>&1 | sed 's/\x1b\[[0-9;]*m//g' || true)
message="❌ File with secrets not found: test.json"
assert_equals "${message}" "${result}" "vaultctl write with missing file"
######## Test missing file without key for write #############################################"
result=$("$VAULTCTL" write "test" "$VAULT_PATH" "@test.json" 2>&1 | sed 's/\x1b\[[0-9;]*m//g' || true)
message="❌ File with secrets not found: test.json"
assert_equals "${message}" "${result}" "vaultctl write with missing file without key "
######## Test empty file for write #############################################"
result=$("$VAULTCTL" write "test" "$VAULT_PATH" "$VAULT_KEY_1=@${VAULT_EMPTY_FILE_PATH}" 2>&1 | sed 's/\x1b\[[0-9;]*m//g' || true)
message="❌ Secrets file is empty: ${VAULT_EMPTY_FILE_PATH}"
assert_equals "${message}" "${result}" "vaultctl write with empty file"
######## Test empty file without key for write #############################################"
result=$("$VAULTCTL" write "test" "$VAULT_PATH" "@${VAULT_EMPTY_FILE_PATH}" 2>&1 | sed 's/\x1b\[[0-9;]*m//g' || true)
message="❌ Secrets file is empty: ${VAULT_EMPTY_FILE_PATH}"
assert_equals "${message}" "${result}" "vaultctl write with empty file without key"
# Restore backup if any
if [[ -n "$backup_file" ]]; then
mv "$backup_file" "$config_file"
fi
}
# Test config command
test_vaultctl_config() {
local result
local config_file="$VAULT_CONFIG_FILE"
# Backup existing config if any
local backup_file=""
if [[ -f "$config_file" ]]; then
backup_file=$(mktemp)
cp "$config_file" "$backup_file"
fi
# Ensure clean state
rm -f "$config_file"
unset VAULT_MOUNT
######## Test config without arguments (show config) #############################################
result=$("$VAULTCTL" config 2>&1 | grep -c "Current configuration:" || true)
if [[ "$result" -gt 0 ]]; then
echo -e "INFO: vaultctl config show without file \u2705"
else
echo -e "ERROR: vaultctl config show without file \u274c"
[[ -n "$backup_file" ]] && mv "$backup_file" "$config_file"
exit 1
fi
######## Test setting VAULT_MOUNT #############################################
result=$("$VAULTCTL" config VAULT_MOUNT=test_mount 2>&1 | sed 's/\x1b\[[0-9;]*m//g' || true)
if [[ "$result" == *"Configuration updated: VAULT_MOUNT=test_mount"* ]]; then
echo -e "INFO: vaultctl config set VAULT_MOUNT \u2705"
else
echo -e "ERROR: vaultctl config set VAULT_MOUNT \u274c"
echo "Result: $result"
[[ -n "$backup_file" ]] && mv "$backup_file" "$config_file"
exit 1
fi
# Verify config was written
if [[ -f "$config_file" ]] && grep -q "VAULT_MOUNT=test_mount" "$config_file"; then
echo -e "INFO: vaultctl config file written correctly \u2705"
else
echo -e "ERROR: vaultctl config file not written \u274c"
[[ -n "$backup_file" ]] && mv "$backup_file" "$config_file"
exit 1
fi
######## Test invalid config key #############################################
result=$("$VAULTCTL" config INVALID_KEY=value 2>&1 | sed 's/\x1b\[[0-9;]*m//g' || true)
if [[ "$result" == *"Unknown configuration key: INVALID_KEY"* ]]; then
echo -e "INFO: vaultctl config reject invalid key \u2705"
else
echo -e "ERROR: vaultctl config should reject invalid key \u274c"
[[ -n "$backup_file" ]] && mv "$backup_file" "$config_file"
exit 1
fi
######## Test empty value #############################################
result=$("$VAULTCTL" config VAULT_MOUNT= 2>&1 | sed 's/\x1b\[[0-9;]*m//g' || true)
if [[ "$result" == *"VAULT_MOUNT value cannot be empty"* ]]; then
echo -e "INFO: vaultctl config reject empty value \u2705"
else
echo -e "ERROR: vaultctl config should reject empty value \u274c"
[[ -n "$backup_file" ]] && mv "$backup_file" "$config_file"
exit 1
fi
# Restore backup if any
if [[ -n "$backup_file" ]]; then
mv "$backup_file" "$config_file"
else
rm -f "$config_file"
fi
unset VAULT_MOUNT
}
# Test read with default mount
test_vaultctl_read_default_mount() {
local result
local config_file="$VAULT_CONFIG_FILE"
# Backup existing config
local backup_file=""
if [[ -f "$config_file" ]]; then
backup_file=$(mktemp)
cp "$config_file" "$config_file.backup"
fi
# Setup config with VAULT_MOUNT
local mount_value="test"
echo "VAULT_MOUNT=$mount_value" > "$config_file"
# Cleanup before test
cleanup_vault "$mount_value" "$VAULT_PATH"
######## Test write then read with default mount #############################################
# First write with explicit mount
"$VAULTCTL" write "$mount_value" "$VAULT_PATH" "$VAULT_KEY_1=$VAULT_VALUE_1" > /dev/null 2>&1
# Read with only path (should use default mount from config)
result=$("$VAULTCTL" read "$VAULT_PATH/$VAULT_KEY_1" 2>&1 | grep -v "^[[:space:]]*$" | sed 's/\x1b\[[0-9;]*m//g' || true)
assert_equals "$VAULT_VALUE_1" "$result" "vaultctl read with default mount from config"
######## Test read with VAULT_MOUNT env var #############################################
export VAULT_MOUNT="$mount_value"
rm -f "$config_file"
result=$("$VAULTCTL" read "$VAULT_PATH/$VAULT_KEY_1" 2>&1 | grep -v "^[[:space:]]*$" | sed 's/\x1b\[[0-9;]*m//g' || true)
assert_equals "$VAULT_VALUE_1" "$result" "vaultctl read with default mount from env var"
unset VAULT_MOUNT
######## Test read without mount and no config should fail #############################################
result=$("$VAULTCTL" read "$VAULT_PATH/$VAULT_KEY_1" 2>&1 | sed 's/\x1b\[[0-9;]*m//g' || true)
if [[ "$result" == *"If mount is not specified, VAULT_MOUNT environment variable or config will be used"* ]]; then
echo -e "INFO: vaultctl read fails without mount or config \u2705"
else
echo -e "ERROR: vaultctl read should fail without mount or config \u274c"
[[ -f "$config_file.backup" ]] && mv "$config_file.backup" "$config_file"
exit 1
fi
# Cleanup
cleanup_vault "$mount_value" "$VAULT_PATH"
# Restore backup
if [[ -f "$config_file.backup" ]]; then
mv "$config_file.backup" "$config_file"
fi
}
# Test write with default mount
test_vaultctl_write_default_mount() {
local result
local config_file="$VAULT_CONFIG_FILE"
# Backup existing config
local backup_file=""
if [[ -f "$config_file" ]]; then
backup_file=$(mktemp)
cp "$config_file" "$backup_file"
fi
# Setup config with VAULT_MOUNT
local mount_value="test"
echo "VAULT_MOUNT=$mount_value" > "$config_file"
# Cleanup before test
cleanup_vault "$mount_value" "$VAULT_PATH"
######## Test write with default mount from config #############################################
"$VAULTCTL" write "$VAULT_PATH" "$VAULT_KEY_1=$VAULT_VALUE_1" > /dev/null 2>&1
# Verify with explicit mount
result=$("$VAULTCTL" read "$mount_value" "$VAULT_PATH/$VAULT_KEY_1" 2>&1 | grep -v "^[[:space:]]*$" | sed 's/\x1b\[[0-9;]*m//g' || true)
assert_equals "$VAULT_VALUE_1" "$result" "vaultctl write with default mount from config"
# Cleanup
cleanup_vault "$mount_value" "$VAULT_PATH"
# Restore backup
if [[ -n "$backup_file" ]]; then
mv "$backup_file" "$config_file"
else
rm -f "$config_file"
fi
}
# Run tests
echo -e "Passing tests for vaultctl read and vaultctl write...\n"
test_vaultctl_write_read
echo -e "\nFailure tests for vaultctl read...\n"
test_vaultctl_read_errors
echo -e "\nFailure tests for vaultctl write....\n"
test_vaultctl_write_errors
echo -e "\nTests for vaultctl config...\n"
test_vaultctl_config
echo -e "\nTests for vaultctl read with default mount...\n"
test_vaultctl_read_default_mount
echo -e "\nTests for vaultctl write with default mount...\n"
test_vaultctl_write_default_mount
echo -e "\nAll tests passed! \u2705"