-
Notifications
You must be signed in to change notification settings - Fork 0
/
3.install_vault_postgresql.sh
executable file
·295 lines (241 loc) · 13.8 KB
/
3.install_vault_postgresql.sh
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
#!/usr/bin/env bash
set -eu ; # abort this script when a command fails or an unset variable is used.
#set -x ; # echo all the executed commands.
if [[ ${1-} ]] && [[ (($# == 1)) || $1 == "-h" || $1 == "--help" || $1 == "help" ]] ; then
printf """Usage: VARIABLE='...' ${0##*/} [OPTIONS]
Installs HashiCorp Vault with setup to a PostgreSQL DB to demo Database Secrets Engine.
By default this script only downloads & copies binaries where no inline SETUP
value is provided ('server'). The server instane is a single development node ('-dev')
Some of the inline variables and values that can be set are show below.
For upto date & complete documentation of Vault see: https://www.vaultproject.io/
VARIABLES:
SETUP='' # // default just download binary otherwise 'server'
VAULT_VERSION='' # // default LATEST - '1.3.2+ent' for enterprise or oss by default.
IP_WAN_INTERFACE='eth1' # // default for cluster_address uses where not set eth1.
EXAMPLES:
SETUP='server' ${0##*/} ;
# install latest vault version setting up systemd services too.
SETUP='server' IP_WAN_INTERFACE='eth0' ${0##*/} ;
# Use a differnt interface ip for vault cluster_address binding.
${0##*/} 0.0.1 February 2020
""" ;
fi ;
if ! which curl 2>&1>/dev/null ; then printf 'ERROR: curl utility missing & required. Install & retry again.\n' ; exit 1 ; fi ;
if ! which unzip 2>&1>/dev/null ; then printf 'ERROR: unzip utility missing & required. Install & retry again.\n' ; exit 1 ; fi ;
if ! which jq 2>&1>/dev/null ; then printf 'ERROR: jq utility missing & required. Install & retry again.\n' ; exit 1 ; fi ;
LOGNAME=$(logname) ;
if [[ ! ${SETUP+x} ]]; then SETUP='server' ; fi ; # // default 'server' setup or change to 'client'
if [[ ! ${USER_VAULT+x} ]] ; then USER_VAULT='vault' ; fi ; # // default vault user.
if [[ ! ${URL_VAULT+x} ]]; then URL_VAULT='https://releases.hashicorp.com/vault/' ; fi ;
if [[ ! ${VAULT_VERSION+x} ]]; then VAULT_VERSION='' ; fi ; # // VERSIONS: "1.3.2' for OSS, '1.3.2+ent' for Enterprise, '1.3.2+ent.hsm' for Enterprise with HSM.
if [[ ! ${OS_CPU+x} ]]; then OS_CPU='' ; fi ; # // ARCH CPU's: 'amd64', '386', 'arm64' or 'arm'.
if [[ ! ${OS_VERSION+x} ]]; then OS_VERSION=$(uname -ar) ; fi ; # // OS's: 'Darwin', 'Linux', 'Solaris', 'FreeBSD', 'NetBSD', 'OpenBSD'.
if [[ ! ${PATH_INSTALL+x} ]]; then PATH_INSTALL="$(pwd)/vault_installs" ; fi ; # // where vault install files will be.
if ! mkdir -p ${PATH_INSTALL} 2>/dev/null ; then printf "\nERROR: Could not create directory at: ${PATH_INSTALL}\n"; exit 1; fi ;
if [[ ! ${SYSD_FILE+x} ]]; then SYSD_FILE='/etc/systemd/system/vault.service' ; fi ; # name of SystemD service for vault.
if [[ ! ${PATH_VAULT+x} ]]; then PATH_VAULT='/etc/vault.d' ; fi ; # // Vault Daemon Path where configuration & files are to reside.
if [[ ! ${PATH_BINARY+x} ]]; then PATH_BINARY='/usr/local/bin/vault' ; fi ; # // Target binary location for vault executable.
if [[ ! ${PATH_VAULT_CONFIG+x} ]]; then PATH_VAULT_CONFIG="${PATH_VAULT}/vault.hcl" ; fi ; # // Main vault config.
if [[ ! ${PATH_VAULT_DATA+x} ]]; then PATH_VAULT_DATA='/vault/data' ; fi ; # // Where local storage is used local data path.
if [[ ! ${IP_VAULT_ACTIVE+x} ]]; then IP_VAULT_ACTIVE='192.168.10.252' ; fi ;
if [[ ! ${IP_RAFT_JOIN+x} ]]; then IP_RAFT_JOIN="http://${IP_VAULT_ACTIVE}:8200" ; fi ;
if [[ ! ${IP_WAN_INTERFACE+x} ]]; then IP_WAN_INTERFACE="$(ip a | awk '/: / { print $2 }' | sed -n 3p | cut -d ':' -f1)" ; fi ; # 2nd interface 'eth1'
if [[ ! ${IP_LAN_INTERFACE+x} ]]; then IP_LAN_INTERFACE="$(ip a | awk '/: / { print $2 }' | sed -n 3p | cut -d ':' -f1)" ; fi ; # 2nd interface 'eth1'
if [[ ! ${IP_WAN+x} ]]; then
IP_WAN="$(ip a show ${IP_WAN_INTERFACE} | grep -oE '\b((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b' | head -n 1)" ;
if (( $? != 0 )) ; then printf "ERROR: Unable to determine WAN IP of ${IP_WAN_INTERFACE}\n" ; fi ;
fi ;
if [[ ! ${IP_LAN+x} ]]; then
IP_LAN="$(ip a show ${IP_LAN_INTERFACE} | grep -oE '\b((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b' | head -n 1)" ;
if (( $? != 0 )) ; then printf "ERROR: Unable to determine LAN IP of ${IP_LAN_INTERFACE}\n" ; fi ;
fi ;
VAULT_ADDR="http://${IP_WAN}:8200" ;
if [[ ! ${VAULT_NODENAME+x} ]]; then VAULT_NODENAME=$(hostname) ; fi ; # // will be based on hostname *1 == main, others standby.
# // ----------------------------------------------------------
# // WARNING! DO NOT USE IN REAL LIFE.
# // development mode root key is root.
if [[ ${VAULT_TOKEN+x} ]] ; then return ; else VAULT_TOKEN='root' ; fi ;
# // ----------------------------------------------------------
if [[ ! ${VAULT_CONFIG_SETTINGS+x} ]]; then VAULT_CONFIG_SETTINGS='' ; fi ; # // vault config settings.
if [[ ${VAULT_CONFIG_SETTINGS} == '' ]] ; then VAULT_CONFIG_SETTINGS='# // see systemd start-up\n' ; fi ;
sERR="\nREFER TO: ${URL_VAULT}\n\nERROR: Operating System Not Supported.\n" ;
sERR_DL="\nREFER TO: ${URL_VAULT}\n\nERROR: Could not determined download state.\n" ;
# // PGP Public Key on Security Page which can be piped to file.
#PGP_KEY_PUB=$(curl -s https://www.hashicorp.com/security.html | grep -Pzo '\-\-\-\-\-BEGIN PGP PUBLIC KEY BLOCK\-\-\-\-\-\n.*\n(\n.*){27}?') ;
#curl -s ${VAULT_VERSION}/vault_${VAULT_VERSION}_SHA256SUMS.sig ;
#getconf LONG_BIT ; # // can be handy for 32bit vs 64bit determination
# // DETERMINE LATEST VERSION - where none are provided.
if [[ ${VAULT_VERSION} == '' ]] ; then
VAULT_VERSION=$(curl -s ${URL_VAULT} | grep '<a href="/vault/' | grep -v -E 'rc|ent|beta|hsm' | head -n 1 | grep -E -o '([0-9]{1,3}[\.]){2}[0-9]{1,3}' | head -n 1) ;
if [[ ${VAULT_VERSION} == '' ]] ; then
printf '\nERROR: Could not determine valid / current vault version to download.\n' ;
exit 1 ;
fi ;
fi ;
if [[ ! ${FILE+x} ]] ; then FILE="vault_${VAULT_VERSION}_" ; fi ; # // to be appended later.
if [[ ! ${URL+x} ]] ; then URL="${URL_VAULT}${VAULT_VERSION}/" ; fi ; # // to be appended later.
if [[ ! ${URL2+x} ]] ; then URL2="${URL_VAULT}${VAULT_VERSION}/vault_${VAULT_VERSION}_SHA256SUMS" ; fi ;
set +e ; CHECK=$(vault --version 2>&1) ; set -e ; # // maybe required vault version is already installed.
if [[ ${CHECK} == *"v${VAULT_VERSION}"* ]] && [[ (($# == 0)) || $1 != "-f" || $2 != "-f" ]] ; then printf "Vault v${VAULT_VERSION} already installed; Use '-f' to force this script to run anyway.\nNo action taken.\n" && exit 0 ; fi ;
sAOK="Remember to copy ('cp'), link ('ln') or path the vault executable as required.\n" ;
sAOK+="Try: '${PATH_BINARY} --version' ; # to test.\nSuccessfully installed Vault ${VAULT_VERSION} in: ${PATH_INSTALL}\n" ;
function donwloadUnpack()
{
printf "Downloading from: ${URL}\n" ;
cd ${PATH_INSTALL} && \
if wget -qc ${URL} && wget -qc ${URL2} ; then
if [[ $(shasum -a 256 -c vault_${VAULT_VERSION}_SHA256SUMS 2>&1>/dev/null | grep OK) == "" ]] ; then
if unzip -qo ${FILE} ; then printf "${sAOK}" ; else printf "\nERROR: Could not unzip.\n" ; exit 1 ; fi ;
chown -R ${LOGNAME} ${PATH_INSTALL} ;
else
printf '\nERROR: During shasum - Downloaded .zip corrupted?\n' ;
exit 1 ;
fi ;
else
printf "${sERR_DL}" ;
fi ;
}
if [[ ${OS_CPU} == '' ]] ; then
if [[ ${OS_VERSION} == *'x86_64'* ]] ; then
OS_CPU='amd64' ;
else
if [[ ${OS_VERSION} == *' i386'* || ${OS_VERSION} == *' i686'* ]] ; then OS_CPU='386' ; fi ;
if [[ ${OS_VERSION} == *' armv6'* || ${OS_VERSION} == *' armv7'* ]] ; then OS_CPU='arm' ; fi ;
if [[ ${OS_VERSION} == *' armv8'* || ${OS_VERSION} == *' aarch64'* ]] ; then OS_CPU='arm64' ; fi ;
if [[ ${OS_VERSION} == *'solaris'* ]] ; then OS_CPU='amd64' ; fi ;
fi ;
if [[ ${OS_CPU} == '' ]] ; then printf "${sERR}" ; exit 1 ; fi ;
fi ;
case "$(uname -ar)" in
Darwin*)
printf 'macOS (aka OSX)\n' ;
if which brew > /dev/null ; then
printf 'Consider: "brew install vault" since you have HomeBrew availble.\n' ;
else :; fi ;
FILE="${FILE}darwin_${OS_CPU}.zip" ;
;;
Linux*)
printf 'Linux\n' ;
FILE="${FILE}linux_${OS_CPU}.zip" ;
;;
*Solaris)
printf 'SunOS / Solaris\n' ;
FILE="${FILE}solaris_${OS_CPU}.zip" ;
;;
*FreeBSD*)
printf 'FreeBSD\n' ;
FILE="${FILE}freebsd_${OS_CPU}.zip" ;
;;
*NetBSD*)
printf 'NetBSD\n' ;
FILE="${FILE}netbsd_${OS_CPU}.zip" ;
;;
*OpenBSD*)
printf 'OpenBSD\n' ;
FILE="${FILE}netbsd_${OS_CPU}.zip" ;
;;
*Cygwin)
printf 'Cygwin - POSIX on MS Windows\n'
FILE="${FILE}windows_${OS_CPU}.zip" ;
URL="${URL}${FILE}" ;
printf "Conisder downloading (exe) from: ${URL}.\nUse vault.exe from CMD / Windows Prompt(s).\n" ;
exit 0 ;
;;
*)
printf "${sERR}" ;
exit 1 ;
;;
esac ;
function sudoSetup()
{
if [[ ${FILE} == *"darwin"* ]] ; then printf '\nWARNING: On MacOS - all other setup setps will need to be appropriatly completed by the user.\n' ; exit 0 ; fi ;
if ! [[ $(id -u) == 0 ]] ; then printf 'ERROR: Root privileges lacking to peform all setup tasks. Consider "sudo ..." re-execution.\n' ; exit 1 ; fi ;
# // Move vault to default paths
cd ${PATH_INSTALL} && \
chown root:root vault && \
mv vault ${PATH_BINARY} ;
# Give ability to mlock syscall without running the process as root & preventing memory from being swapped to disk.
setcap cap_ipc_lock=+ep ${PATH_BINARY} ; # // /usr/local/bin/vault
# Create a unique, non-privileged system user to run Vault.
if ! id -u ${USER_VAULT} &>/dev/null ; then
useradd --system --home ${PATH_VAULT} --shell /bin/false ${USER_VAULT} ;
else
printf 'USER: vault - already present.\n' ;
fi ;
# // Enable auto complete
set +e
vault -autocomplete-install 2>/dev/null && complete -C ${PATH_BINARY} vault 2>/dev/null;
USER=$(logname) ;
su -l ${USER} -c "vault -autocomplete-install 2>/dev/null && complete -C ${PATH_BINARY} vault 2>/dev/null;"
set -e
# // SystemD for service / startup
if ! which systemctl 2>&1>/dev/null ; then printf '\nERROR: No systemctl / SystemD installed on system.' ; exit 1 ; fi ;
if [[ ${FILE} == *"darwin"* ]] ; then printf '\nERROR: Only SystemD can be provisioned - build MacOS launchd plist yourself.\n' ; exit 1 ; fi ;
if ! [[ -d ${PATH_VAULT_DATA} ]] ; then mkdir -p ${PATH_VAULT_DATA} && chown -R ${USER_VAULT}:${USER_VAULT} ${PATH_VAULT_DATA} ; fi ;
if mkdir -p ${PATH_VAULT} && touch ${PATH_VAULT_CONFIG} && chown -R ${USER_VAULT}:${USER_VAULT} ${PATH_VAULT} && chmod 640 ${PATH_VAULT_CONFIG} ; then
if ! [[ -s ${PATH_VAULT_CONFIG} ]] ; then
printf "${VAULT_CONFIG_SETTINGS}" >> ${PATH_VAULT_CONFIG} ;
else
printf "VAULT Conifg: ${PATH_VAULT_CONFIG} - already present.\n" ;
fi ;
else
printf "\nERROR: Unable to create ${PATH_VAULT}.\n" ; exit 1 ;
fi ;
if ! [[ -s ${SYSD_FILE} ]] && [[ ${SETUP,,} == *'server'* ]]; then
UNIT_SYSTEMD='[Unit]\nDescription=Vault\nDocumentation=https://www.vaultproject.io/docs/\nRequires=network-online.target\nAfter=network-online.target\n\n[Service]\nEnvironment=VAULT_DEV_ROOT_TOKEN_ID=root\nRestart=on-failure\nExecStart=/usr/local/bin/vault server -dev -dev-listen-address=0.0.0.0:8200\nExecReload=/bin/kill -HUP $MAINPID\nKillSignal=SIGINT\n\n[Install]\nWantedBy=multi-user.target\n' ;
printf "${UNIT_SYSTEMD}" > ${SYSD_FILE} && chmod 664 ${SYSD_FILE} ;
systemctl daemon-reload ;
systemctl enable vault.service ;
systemctl start vault.service ;
fi ;
}
function setupPostgresql()
{
sleep 3 ; # // wait for 3 secs for server to properly start.
# // Env Variable VAULT_TOKEN for CLI
if ! grep VAULT_TOKEN /home/${LOGNAME}/.bashrc ; then
printf "\nexport VAULT_TOKEN=${VAULT_TOKEN}\n" >> /home/${LOGNAME}/.bashrc ;
fi ;
if ! grep VAULT_ADDR /home/${LOGNAME}/.bashrc ; then
printf "\nexport VAULT_ADDR=${VAULT_ADDR}\n" >> /home/${LOGNAME}/.bashrc ;
printf "REMEMBER to: \`source ~/.bashrc ; # // or you'll need: VAULT_ADDR='${VAULT_ADDR}' vault ...\`\n" ;
fi ;
export VAULT_ADDR=${VAULT_ADDR} ;
if [[ ! ${PG_FQDN+x} ]]; then PG_FQDN='192.168.178.190' ; fi ;
if [[ ! ${PG_ADMIN+x} ]]; then PG_ADMIN='myapp_admin' ; fi ;
if [[ ! ${PG_USER+x} ]]; then PG_USER='vault-edu' ; fi ;
if [[ ! ${PG_SECRET+x} ]]; then PG_SECRET='SECRET' ; fi ;
if [[ ! ${PG_DB+x} ]]; then PG_DB='myapp' ; fi ;
if [[ ! ${VAULT_DB_REF+x} ]]; then VAULT_DB_REF="${PG_DB}" ; fi ; # // use te same as DB name by default.
if [[ ! ${VAULT_PG_ROLE+x} ]]; then VAULT_PG_ROLE="${PG_DB}_readonly" ; fi ; # DB folowed by _readonly is the role name.
vault secrets enable database 2>&1 > /dev/null ;
if (($? == 0)) ; then printf "SUCCESSFULLY: Enabled Vault Database Secrets Engine.\n" ; fi ;
vault write database/config/${PG_DB} \
plugin_name=postgresql-database-plugin \
connection_url="postgresql://{{username}}:{{password}}@${PG_FQDN}/${PG_DB}" \
allowed_roles="*" username="${PG_ADMIN}" password="${PG_SECRET}" 2>&1 > /dev/null ;
if (($? == 0)) ; then printf "SUCCESSFULLY: Wrote to database/config/postgresql ????.\n" ; fi ;
vault write database/static-roles/${PG_ADMIN} \
db_name=${PG_DB} \
rotation_statements="ALTER USER \"{{name}}\" WITH PASSWORD '{{password}}';" \
username="${PG_ADMIN}" \
rotation_period=86400 2>&1 > /dev/null ;
if (($? == 0)) ; then printf "SUCCESSFULLY: Created DB static/roles/${PG_USER}.\n" ; fi ;
# vault read database/static-roles/${VAULT_DB_REF} ;
# vault read database/static-creds/${VAULT_DB_REF} ;
# vault write -f database/rotate-role/${VAULT_DB_REF} ; # // Rotate key
# vault read database/static-creds/${VAULT_DB_REF} ; # // Read new key
# // Create Role
printf """CREATE ROLE \"{{name}}\" WITH LOGIN PASSWORD '{{password}' VALID UNTIL '{{expiration}}';
REVOKE ALL ON SCHEMA public FROM public, \"{{name}}\";
GRANT SELECT ON ALL TABLES IN SCHEMA public TO \"{{name}}\";
""" > ${VAULT_PG_ROLE}.sql ;
vault write database/roles/${VAULT_PG_ROLE} db_name=${PG_DB} \
creation_statements=@${VAULT_PG_ROLE}.sql default_ttl=1h max_ttl=24h 2>&1 > /dev/null;
if (($? == 0)) ; then printf "SUCCESSFULLY: Created database/roles/${VAULT_PG_ROLE}.\n" ; fi ;
# // Generate credentials.
# vault read database/creds/${VAULT_PG_ROLE} ;
# psql -U postgres -c "\du;"
}
URL="${URL}${FILE}" ;
donwloadUnpack && if [[ ${SETUP,,} == *"server"* ]]; then sudoSetup && setupPostgresql ; fi ;