-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathhttokensh
More file actions
executable file
·208 lines (186 loc) · 5.09 KB
/
httokensh
File metadata and controls
executable file
·208 lines (186 loc) · 5.09 KB
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
#!/bin/bash
#
# Run htgettoken and then start a shell command and keep the access
# token updated for as long as the command runs. See httokensh(1).
#
# Written by Dave Dykstra August 2023
usage()
{
echo "Usage: httokensh [-h] [htgettokenoptions] -- [command]"
echo
echo "Runs htgettoken with given options, starts the command, and runs"
echo "htgettoken again in the background as needed to renew the token"
echo "until the command exits."
echo
echo "Options:"
echo " -h, --help show this help message and exit"
echo
echo "command defaults to \$SHELL"
exit 1
} >&2
if [ $# = 0 ] || [ "$1" = "-h" ] || [ "$1" = "--help" ]; then
usage
fi
HTGETOKENARGS=()
COMMANDARGS=()
GOTSEP=false
MINSECS=60
GOTVERBOSE=false
GOTOUTFILE=false
OUTFILE=""
GOTVTFILE=false
GOTVTTTL=false
# look at HTGETTOKENOPTS in addition to those options on the command line
# but don't explicitly pass them again to htgettoken
HTGETSEP="--HTSEP--"
set -- $HTGETTOKENOPTS $HTGETSEP "$@"
DONEHTGETTOKENOPTS=false
for ARG; do
if $GOTSEP; then
COMMANDARGS+=("$ARG")
elif $GOTOUTFILE; then
OUTFILE="$ARG"
GOTOUTFILE=false
if $DONEHTGETTOKENOPTS; then
HTGETTOKENARGS+=("$ARG")
fi
elif [ "$ARG" = "$HTGETSEP" ]; then
DONEHTGETTOKENOPTS=true
elif [ "$ARG" = "--" ]; then
GOTSEP=true
else
if $DONEHTGETTOKENOPTS; then
HTGETTOKENARGS+=("$ARG")
fi
case "$ARG" in
--minsecs=*)
MINSECS="${ARG/--minsecs=/}"
;;
-v|--verbose)
GOTVERBOSE=true
;;
-o)
GOTOUTFILE=true
;;
--outfile=*)
OUTFILE="${ARG/--outfile=/}"
;;
--vaulttokenfile=*)
GOTVTFILE=true
;;
--vaulttokenttl=*|--vaulttokenminttl=*)
GOTVTTTL=true
;;
esac
fi
done
if ! $GOTSEP; then
echo "No -- separator given" >&2
usage
fi
if [ ${#HTGETTOKENARGS[@]} = 0 ]; then
echo "No htgettoken options given" >&2
usage
fi
if [ ${#COMMANDARGS[@]} = 0 ]; then
COMMANDARGS=("$SHELL")
fi
if [ -z "$BEARER_TOKEN_FILE" ]; then
if [ -n "$OUTFILE" ]; then
BEARER_TOKEN_FILE="$OUTFILE"
else
BTFILE="bt_u$(id -u).sh-$$"
if [ -n "$XDG_RUNTIME_DIR" ]; then
BEARER_TOKEN_FILE=$XDG_RUNTIME_DIR/$BTFILE
else
BEARER_TOKEN_FILE=/tmp/$BTFILE
fi
fi
export BEARER_TOKEN_FILE
fi
if ! $GOTVTFILE; then
ARGHASH="$(echo "${HTGETTOKENARGS[@]}"|md5sum -)"
ARGHASH="${ARGHASH%% *}"
VTFILE="/tmp/vt_u$(id -u).sh-$ARGHASH"
HTGETTOKENARGS+=("--vaulttokenfile=$VTFILE")
fi
if ! $GOTVTTTL; then
HTGETTOKENARGS+=("--vaulttokenminttl=6d")
fi
gettoken()
{
htgettoken "${HTGETTOKENARGS[@]}"
RETVAL="$?"
if [ $RETVAL != 0 ]; then
echo "htgettoken failed, $1" >&2
exit $RETVAL
fi
TOKENJSON="$(htdecodetoken)"
RETVAL="$?"
if [ $RETVAL != 0 ]; then
echo "htdecodetoken failed, $1" >&2
exit $RETVAL
fi
EXP="$(echo $TOKENJSON|jq .exp)"
NOW="$(date +%s)"
let SLEEPSECS="$EXP - $MINSECS - $NOW + 2"
if [ "$SLEEPSECS" -lt $2 ]; then
echo "Calculated renewal time of $SLEEPSECS seconds is less than $2, $1"
exit 1
fi
}
# The first time it is possible to get a cached token that is barely
# beyond the minsecs, so reduce the minimum to just 1 second
gettoken "not running command" 1
# Remove any --vaulttokenminttl option so the background renewal
# gets to be as long as possible
if [[ "$HTGETTOKENOPTS" = *--vaulttokenminttl* ]]; then
HTGETTOKENOPTS="$(echo "$HTGETTOKENOPTS"|sed 's/--vaulttokenminttl=[^ ]*//')"
fi
NEWARGS=()
for ARG in "${HTGETTOKENARGS[@]}"; do
if [[ "$ARG" != --vaulttokenminttl* ]]; then
NEWARGS+=("$ARG")
fi
done
HTGETTOKENARGS=("${NEWARGS[@]}")
# make sure the logged info is verbose for easier diagnosis
if ! $GOTVERBOSE; then
HTGETTOKENARGS+=("-v")
fi
# prevent attempts to get new vault token in background
HTGETTOKENARGS+=("--nooidc" "--nokerberos" "--nossh")
# enable job control so background processes get their own process group
set -m
echo "Renewal log is at \$BEARER_TOKEN_FILE.log"
{
# keep a copy of $PPID because it will change to 1 if parent dies
PARENTPID=$PPID
echo htgettoken args are "${HTGETTOKENARGS[@]}"
while true; do
date
echo "Renewal scheduled in $SLEEPSECS seconds"
sleep $SLEEPSECS
date
if kill -0 $PARENTPID; then
gettoken "exiting" 60
else
echo "Parent process $PARENTPID not running, exiting"
exit 0
fi
done
} >$BEARER_TOKEN_FILE.log 2>&1 &
BACKGROUND_PID=$!
cleanup()
{
if kill -- -$BACKGROUND_PID 2>/dev/null; then
wait 2>/dev/null
rm -f $BEARER_TOKEN_FILE $BEARER_TOKEN_FILE.log
else
echo >&2
echo "Renewal background process failed, see $BEARER_TOKEN_FILE.log" >&2
exit 1
fi
}
trap cleanup 0
"${COMMANDARGS[@]}"