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