Skip to content

Instantly share code, notes, and snippets.

@wilsonjackson
Created July 24, 2019 21:55
Show Gist options
  • Save wilsonjackson/2ec2a6f5c5330bf1207daef3306fbd74 to your computer and use it in GitHub Desktop.
Save wilsonjackson/2ec2a6f5c5330bf1207daef3306fbd74 to your computer and use it in GitHub Desktop.
aws-okta wrapper with GUI prompt for code
#!/usr/bin/env bash
# Detect known terminals and map them to their process name for use with AppleScript.
if [[ ${TERM_PROGRAM} == "Apple_Terminal" ]]; then
terminal="Terminal"
elif [[ ${TERM_PROGRAM} == "iTerm.app" ]]; then
terminal="iTerm2"
fi
function aws_okta() {
aws-okta exec okta-saml -- sh -c 'echo "{\"Version\":1,\"AccessKeyId\":\"$AWS_ACCESS_KEY_ID\",\"SecretAccessKey\":\"$AWS_SECRET_ACCESS_KEY\",\"SessionToken\":\"$AWS_SESSION_TOKEN\",\"Expiration\":\"`date -u -v+15M +"%Y-%m-%dT%H:%M:%SZ"`\"}"'
}
# If the terminal is unrecognized or osascript isn't found, just execute aws-okta.
# Same if the wrapper has been explicitly disabled.
if [[ ${AWS_OKTA_WRAPPER_DISABLE} -eq 1 || ${terminal:-unknown} == "unknown" ]] || ! type osascript >/dev/null 2>/dev/null; then
aws_okta
exit $?
fi
# A bit of AppleScript is used to send a GUI prompt to the user for their MFA code
# so that it doesn't interrupt and break the process originating the request (aws
# or kubernetes cli).
function gimme() {
code=$(osascript <<APPLESCRIPTYAY
tell app "${terminal}"
set code to text returned of (display dialog "Enter an Okta MFA code" buttons {"OK"} default answer "" default button 1 with icon caution with title "Okta MFA Challenge")
end tell
APPLESCRIPTYAY
)
echo ${code}
}
pipe=/tmp/aws-okta-mfa.pipe
mfa_required_string="Requesting MFA"
if [[ ! -e ${pipe} ]]; then
mkfifo ${pipe}
fi
# Read each line sent by aws-okta to stdout or stderr. On the first line, check for a
# match against the expected substring to indicate an MFA challenge, and prompt the
# user for the code. A named pipe is used as input to aws-okta so the entered code can
# be sent to the interactive prompt.
#
# An extra trick is needed to capture the process substitution's exit code: the exit
# code is printed as a final, non-newline-terminated line in the subshell, and specially
# handled in the while condition so it can be assigned to a variable.
first_line=1
while read -r line || { exit_code=${line} && break; }; do
if [[ ${first_line} -eq 1 ]]; then
if [[ ${line} =~ $mfa_required_string ]]; then
gimme > ${pipe}
else
echo "" > ${pipe}
fi
fi
first_line=0
result=${line}
done < <(cat ${pipe} | aws_okta 2>&1; printf $?)
echo "$result"
exit ${exit_code}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment