Skip to content

Commit d3e4973

Browse files
committed
feat: add secretsmanager wrapper
Signed-off-by: sebastien.heurtematte <[email protected]>
1 parent 9be3bf4 commit d3e4973

File tree

2 files changed

+492
-0
lines changed

2 files changed

+492
-0
lines changed

pass/secretsmanager_wrapper.sh

Lines changed: 242 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,242 @@
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

Comments
 (0)