-
Notifications
You must be signed in to change notification settings - Fork 12
/
afpre
executable file
·226 lines (178 loc) · 4.59 KB
/
afpre
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
#!/bin/bash
VERSION=VERSION_PLACEHOLDER
set -e
### definitions
CFG=~/.afpre
### functions
error_msg() {
echo "${1}"
exit 1
}
check_deps() {
for D in $*
do
which "${D}" &> /dev/null || error_msg "executable '$D' no found in your \$PATH"
done
}
encode64() {
echo -n "${1}" | openssl base64 -base64
}
check_config_file() {
[ -f "${CFG}" ] || error_msg "missing config file: ${CFG}"
}
check_config_key() {
grep -q "^${1}=" ${CFG} || error_msg "configuration key \"${1}\" not found in config file \"${CFG}\""
}
variable_empty() {
[ -z "${1}" ]
}
variable_true() {
[ "${1}" = true ]
}
options_contain() {
grep -q -- "${1}" <<< ${ARGS%-- *}
}
do_version() {
echo $VERSION
exit 0
}
do_help() {
! read -d '' HELP <<EOF
usage: ${0} [OPTIONS] (-- COMMAND)
OPTIONS
--help ... print this help
--account=<my.account> ... authenticate for this account, supersedes
any definition in ${CFG}
--role=<my.role> ... authenticate as this role, supersedes
any definition in ${CFG}
--example-cfg ... create an example config file at ${CFG}
--debug ... enable debugging
--version ... print version
EOF
echo "${HELP}"
exit 0
}
do_example_cfg() {
[ -f ${CFG} ] && {
echo saving existing ${CFG} to ${CFG}.bak
mv ${CFG} ${CFG}.bak
}
cat > $CFG << EOF
ACCOUNT=my.account
ROLE=my.role
HOST=my.afp.host
_PATH=/afp-api/latest/account
#PATTERN=\\\${ACCOUNT}/\\\${ROLE} # This will appear in front of the prompt
#NAME=my.name
#PW=my.password # I wouldn't put it here
EOF
echo $CFG written
exit 0
}
longoption_value() {
grep -o -- "--${1}=[^ ]*" <<< $ARGS| cut -d"=" -f2
}
get_command() {
grep -o -- '-- .*' <<< ${ARGS} | sed 's/^-- //g'
}
DEBUG=false
ARGS="${@}"
options_contain '--help' && do_help
options_contain '--version' && do_version
options_contain '--account' && ADHOC_ACCOUNT=$(longoption_value account)
options_contain '--role' && ADHOC_ROLE=$(longoption_value role)
options_contain '--example-cfg' && do_example_cfg
options_contain '--debug' && DEBUG=true
$DEBUG && set -x
check_deps which curl jq openssl
check_config_file
variable_empty "${ADHOC_ACCOUNT}" && check_config_key ACCOUNT
variable_empty "${ADHOC_ROLE}" && check_config_key ROLE
check_config_key ROLE
check_config_key _PATH
check_config_key HOST
source $CFG
variable_empty "${ADHOC_ACCOUNT}" || ACCOUNT="${ADHOC_ACCOUNT}"
variable_empty "${ADHOC_ROLE}" || ROLE="${ADHOC_ROLE}"
variable_empty "${NAME}" && read -p "username: " NAME
variable_empty "${PW}" && {
read -p "password: " -s PW
echo
}
variable_true "${INSECURE}" && {
INSECURE_OPTION="--insecure"
echo WARNING: configured to perform \"insecure\" SSL connections and transfers
}
ADHOC_CMD=$(get_command)
variable_empty "${ADHOC_CMD}" || {
CMD_AND_EXIT="eval \"\${PROMPT_COMMAND}\";${ADHOC_CMD};exit"
}
X1XBN02R=$(encode64 "${NAME}:${PW}")
RCFILE=$(mktemp)
cat > $RCFILE <<EOF
$DEBUG && set -x
AWS_VALID_SECONDS=0
RENEW_INT=$RENEW_INT
ACCOUNT=$ACCOUNT
ROLE=$ROLE
export AWS_ACCOUNT=$ACCOUNT
export AWS_ROLE=$ROLE
for F in /etc/bash.bashrc /etc/bashrc ~/.bashrc ~/.profile
do
[ -f "\${F}" ] && . "\${F}"
done
error_msg() {
echo \$1
exit 1
}
basic_auth() {
curl -f -s ${INSECURE_OPTION} -H "Authorization: Basic \${2}" \${1}
}
json_value() {
jq -r ."\${2}" <<<"\${1}"
}
token_renew_interval() {
echo \${RENEW_INT:-\$((\$AWS_VALID_SECONDS - 100 ))}
}
on_mac() {
[ \$(uname -s) == Darwin ]
}
secs_since_epoch() {
on_mac && {
NOZULU=\$(sed 's/Z\$/GMT/g' <<< \${1})
date -jf %Y-%m-%dT%H:%M:%S%Z \${NOZULU} +%s
} || {
date -d \${1} +%s
}
}
awsenv() {
env | grep -i --color=never ^aws
}
ctrl_c () {
echo " Interrupted by user..."
}
renew() {
trap ctrl_c INT
echo authenticating as ${NAME} for ${ACCOUNT}/${ROLE} against ${HOST}
JSON=\$(basic_auth https://${HOST}${_PATH}/${ACCOUNT}/${ROLE} ${X1XBN02R}) || error_msg "... failed!"
export AWS_ACCESS_KEY_ID=\$(json_value "\${JSON}" AccessKeyId)
export AWS_SECRET_ACCESS_KEY=\$(json_value "\${JSON}" SecretAccessKey)
export AWS_SESSION_TOKEN=\$(json_value "\${JSON}" Token)
export AWS_SECURITY_TOKEN=\$(json_value "\${JSON}" Token)
export AWS_VALID_SECONDS=\$((\$(secs_since_epoch \$(json_value "\${JSON}" Expiration))-\$(date +%s)))
SECONDS=0
trap - INT
}
condrenew() {
(( \$SECONDS >= \$(token_renew_interval) )) || (( \${AWS_VALID_SECONDS} == 0 )) && {
echo token expired - need to renew...
renew
echo done.
}
}
PROMPT_COMMAND=condrenew
export -f renew condrenew basic_auth error_msg json_value secs_since_epoch on_mac token_renew_interval
PS1="AFP|${PATTERN} \$PS1"
$CMD_AND_EXIT
EOF
bash --rcfile $RCFILE