1
+ #! /usr/bin/env bash
2
+ # *******************************************************************************
3
+ # Copyright (c) 2024 Eclipse Foundation and others.
4
+ # This program and the accompanying materials are made available
5
+ # under the terms of the Eclipse Public License 2.0
6
+ # which is available at http://www.eclipse.org/legal/epl-v20.html
7
+ # SPDX-License-Identifier: EPL-2.0
8
+ # *******************************************************************************
9
+
10
+ # TODO: use trap
11
+
12
+ # Bash strict-mode
13
+ set -o errexit
14
+ set -o nounset
15
+ set -o pipefail
16
+ set +u
17
+ IFS=$' \n\t '
18
+
19
+ SCRIPT_FOLDER=" $( dirname " $( readlink -f " ${BASH_SOURCE[0]} " ) " ) "
20
+
21
+ #
22
+ # Login to the Secretsmanager using the 'vault' command using env variables or local cbi config file
23
+ #
24
+ sm_login () {
25
+
26
+ if ! command -v vault > /dev/null; then
27
+ >&2 echo " ERROR: this program requires 'vault' Client, see https://developer.hashicorp.com/vault/install"
28
+ exit 1
29
+ fi
30
+
31
+ connected () {
32
+ echo -e " You are connected to the Secretsmanager: ${VAULT_ADDR} "
33
+ vault token lookup
34
+ # vault token revoke -self # for testing
35
+ }
36
+ # Check if user is already authenticated
37
+ [ " $( vault token lookup & > /dev/null) " ] && connected && return 0
38
+
39
+ # test VAULT_ADDR
40
+ if [ -z " ${VAULT_ADDR} " ]; then
41
+ VAULT_ADDR=" $( " ${SCRIPT_FOLDER} /../utils/local_config.sh" " get_var" " url" " secretsmanager" ) " || true
42
+ if [ -z " $VAULT_ADDR " ]; then
43
+ echo " ERROR: VAULT_ADDR is not set. Please set it in your environment \" export VAULT_ADDR=" https://..." \" or in the local cbi config file: ~/.cbi/config."
44
+ exit 1
45
+ fi
46
+ export VAULT_ADDR
47
+ fi
48
+
49
+ [ " $( vault token lookup & > /dev/null) " ] && connected && return 0
50
+
51
+ # test VAULT_TOKEN
52
+ echo " INFO: Start Auth with VAULT_TOKEN"
53
+ vault_token () {
54
+ VAULT_TOKEN=" $( " ${SCRIPT_FOLDER} /../utils/local_config.sh" " get_var" " token" " secretsmanager" ) " || true
55
+ if [ -z " $VAULT_TOKEN " ]; then
56
+ echo " WARN: VAULT_TOKEN is not set. Please set it in your environment \" export VAULT_TOKEN=" ..." \" or in the local cbi config file: ~/.cbi/config."
57
+ else
58
+ export VAULT_TOKEN
59
+ fi
60
+ }
61
+ validate_vault_token () {
62
+ if vault token lookup & > /dev/null; then
63
+ connected && return 0
64
+ else
65
+ echo " WARN: VAULT_TOKEN is not valid $1 . Please set it in your environment \" export VAULT_TOKEN=\" ...\"\" or in the local cbi config file: ~/.cbi/config."
66
+ unset VAULT_TOKEN
67
+ fi
68
+ }
69
+ if [ -z " ${VAULT_TOKEN} " ]; then
70
+ vault_token
71
+ validate_vault_token " from config file"
72
+ else
73
+ validate_vault_token " from env"
74
+ vault_token
75
+ validate_vault_token " from config file"
76
+ fi
77
+ # test login/password
78
+ echo " INFO: Start Auth with login/password"
79
+ echo " WARN: login/password are optional, prefer using a token"
80
+ VAULT_PASSWORD=" $( " ${SCRIPT_FOLDER} /../utils/local_config.sh" " get_var" " password" " secretsmanager" ) " || true
81
+ if [ -z " $VAULT_PASSWORD " ]; then
82
+ echo " WARN: VAULT_PASSWORD is not set. Please set it in your environment or in the local cbi config file: ~/.cbi/config."
83
+ fi
84
+ VAULT_LOGIN=" $( " ${SCRIPT_FOLDER} /../utils/local_config.sh" " get_var" " login" " secretsmanager" ) " || true
85
+ if [ -z " $VAULT_LOGIN " ]; then
86
+ echo " WARN: VAULT_LOGIN is not set. Please set it in your environment or in the local cbi config file: ~/.cbi/config."
87
+ fi
88
+ if [ -z " ${VAULT_LOGIN} " ]; then
89
+ read -r -p " Username: " VAULT_LOGIN
90
+ vault login -method=ldap username=" ${VAULT_LOGIN} "
91
+ elif [ -z " ${VAULT_PASSWORD} " ]; then
92
+ vault login -method=ldap username=" ${VAULT_LOGIN} "
93
+ else
94
+ echo -n " ${VAULT_PASSWORD} " | vault login -method=ldap username=" ${VAULT_LOGIN} " password=-
95
+ fi
96
+
97
+ [ ! " $( vault token lookup) " ] && echo " ERROR: Unable to login to the Secretsmanager" && exit 1
98
+
99
+ VAULT_TOKEN=$( vault token lookup -format=json | jq -r ' .data.id' )
100
+ export VAULT_TOKEN
101
+ connected
102
+ return 0
103
+ }
104
+
105
+ sm_login
106
+
107
+ #
108
+ # Usage: sm_read <mount> <path>
109
+ # NOTE: path is the full path to the secret, including the field name
110
+ #
111
+ sm_read () {
112
+ local mount=" ${1:- } "
113
+ local path=" ${2:- } "
114
+
115
+ local usage=" Usage: Usage: sm_read <mount> <path>"
116
+ local vault_args=" -mount=\" ${mount} \" \" ${path} \" "
117
+
118
+ if [ -z " $mount " ]; then
119
+ >&2 echo " Error: Mount is required for ${vault_args} . ${usage} "
120
+ return 1
121
+ fi
122
+
123
+ if [ -z " $path " ]; then
124
+ >&2 echo " Error: Path is required for ${vault_args} . ${usage} "
125
+ return 1
126
+ fi
127
+
128
+ # Check if path is valid: don't start with a slash, at least on slash, does not end with a slash
129
+ if [[ ! " $path " =~ ^[^/]+/.+[^/]$ ]]; then
130
+ >&2 echo " Error: Path is invalid, slash issue for ${vault_args} . ${usage} "
131
+ return 1
132
+ fi
133
+
134
+ # Extract secret path and field
135
+ local vault_secret_path=" ${path%/* } "
136
+ local field=" ${path##*/ } "
137
+ data=$( vault kv get -mount=" ${mount} " -field=" ${field} " " ${vault_secret_path} " 2> /dev/null)
138
+ if [ " $? " != " 0" ]; then
139
+ >&2 echo " ERROR: vault entry not found: vault kv get -mount=\" ${mount} \" -field=\" ${field} \" \" ${vault_secret_path} \" "
140
+ return 1
141
+ fi
142
+ echo -n " ${data} "
143
+ return 0
144
+ }
145
+
146
+ #
147
+ # Usage: sm_write <mount> <path> key1=value1 key2=value2 ...
148
+ # NOTE: path is the full path to the secret without the field name
149
+ #
150
+ sm_write () {
151
+ local mount=" ${1:- } "
152
+ local path=" ${2:- } "
153
+ # local fields=${*:3}
154
+ shift 2
155
+
156
+ local fields=" "
157
+ for arg in " $@ " ; do
158
+ if [ -n " $fields " ]; then
159
+ fields=" ${fields} ${arg} "
160
+ else
161
+ fields=" ${arg} "
162
+ fi
163
+ done
164
+
165
+ local usage=" Usage: sm_write <mount> <path> [<key>=<secret> | <key>=@<secret file> | @<secret file>]"
166
+
167
+ local vault_args=" -mount=\" ${mount} \" \" ${path} \" \" ${fields} \" "
168
+
169
+ if [ -z " $mount " ]; then
170
+ >&2 echo " Error: Mount is required for ${vault_args} . ${usage} "
171
+ return 1
172
+ fi
173
+
174
+ if [ -z " $path " ]; then
175
+ >&2 echo " Error: Path is required for ${vault_args} . ${usage} "
176
+ return 1
177
+ fi
178
+
179
+ if [ -z " $fields " ]; then
180
+ >&2 echo " Error: fields are required for ${vault_args} . ${usage} "
181
+ return 1
182
+ fi
183
+
184
+ test_file () {
185
+ local secrets_file=" ${1} "
186
+ if [ ! -f " $secrets_file " ]; then
187
+ >&2 echo " Error: File with secrets not found: ${secrets_file} "
188
+ return 1
189
+ fi
190
+ if [ ! -s " $secrets_file " ]; then
191
+ >&2 echo " Error: Secrets file is empty: ${secrets_file} "
192
+ return 1
193
+ fi
194
+ }
195
+ OLDIFS=$IFS
196
+ IFS=' '
197
+
198
+ for field in ${fields} ; do
199
+ local key=" ${field%% =* } "
200
+ local value=" "
201
+ if echo " ${field} " | grep -q " =" > /dev/null; then
202
+ value=" ${field#* =} "
203
+ fi
204
+
205
+ if [[ -z " $key " || -z " $value " ]] && [[ " $key " != @* && " $value " != @* ]]; then
206
+ >&2 echo " Error: Field key '$key ' or value '$value ' empty for ${vault_args} "
207
+ return 1
208
+ fi
209
+ if [[ " $value " == @* ]]; then
210
+ local secrets_file=" ${value#@ } "
211
+ ! test_file " ${secrets_file} " && return 1
212
+ fi
213
+ if [[ " $key " == @* ]]; then
214
+ local secrets_file=" ${key#@ } "
215
+ ! test_file " ${secrets_file} " && return 1
216
+ fi
217
+ done
218
+ IFS=$OLDIFS
219
+
220
+ write_to_vault () {
221
+ local method=$1
222
+ eval vault kv " ${method} " -mount=" ${mount} " " ${path} " " ${fields} " & > /dev/null
223
+ }
224
+ local method=" put"
225
+ local secret_data
226
+ secret_data=" $( vault kv get -format=" json" -mount=" ${mount} " " ${path} " 2> /dev/null) " || true
227
+ if [ -z " ${secret_data} " ]; then
228
+ >&2 echo " INFO: vault entry not found: add path: ${path} "
229
+ write_to_vault " ${method} "
230
+ return 0
231
+ fi
232
+
233
+ secret_value=$( echo " ${secret_data} " | jq -r ' .data.data' )
234
+ [ " ${secret_value} " != " null" ] && \
235
+ method=" patch"
236
+ write_to_vault " ${method} "
237
+ if [ " $? " == " 0" ]; then
238
+ >&2 echo " INFO: Secret written to Vault: vault kv ${method} -mount=\" ${mount} \" \" ${path} \" \" ${fields} \" "
239
+ else
240
+ >&2 echo " ERROR: writing secret to Vault: ${vault_args} "
241
+ fi
242
+ }
0 commit comments