Reputation: 3517
I am trying to shorten my work of getting a aws access token and writing it to ~/.aws/credentials file by writing a bash alias like this on my mac :
alias trial='function mfa(){ aws sts get-session-token --serial-number $2 --token-code $1|python3 -c "import sys,subprocess;obj=eval(''.join(sys.stdin.readlines()).replace('\n',''));AccessKeyId=obj['Credentials']['AccessKeyId'];SecretAccessKey=obj['Credentials']['SecretAccessKey'];SessionToken=obj['Credentials']['SessionToken'];subprocess.check_output('aws configure set aws_access_key_id '+AccessKeyId+' --profile mfa', shell=True);subprocess.check_output('aws configure set aws_secret_access_key '+SecretAccessKey+' --profile mfa', shell=True);subprocess.check_output('aws configure set aws_session_token '+SessionToken+' --profile mfa', shell=True);"};mfa'
But for some reason this is not working. Specifically bash compiler is not happy with the part after python3 -c. Can someone help ?
Upvotes: 0
Views: 423
Reputation: 3517
Thanks everyone for the replies. Eventually I ended up putting everything in a python file like this :
import sys, subprocess, json
output = subprocess.Popen('aws sts get-session-token --serial-number sys.argv[2] --token-code '+sys.argv[1], shell=True,stdout=subprocess.PIPE)
output = json.loads(output.communicate()[0].decode('utf-8').strip())
AccessKeyId=output['Credentials']['AccessKeyId']
SecretAccessKey=output['Credentials']['SecretAccessKey']
SessionToken=output['Credentials']['SessionToken']
subprocess.check_output('aws configure set aws_access_key_id '+AccessKeyId+' --profile mfa', shell=True)
subprocess.check_output('aws configure set aws_secret_access_key '+SecretAccessKey+' --profile mfa', shell=True)
subprocess.check_output('aws configure set aws_session_token '+SessionToken+' --profile mfa', shell=True)
And then on the bash_profile I have an alias :
alias a="python3 ~/bin/python3_mfa.py $1"
And this is working. but if I put some more commands in the alias it stops working. trying to figure that out. for example :
alias a="python3 ~/bin/python3_mfa.py $1;eb ssh env --profile mfa;"
doesn't work.
Upvotes: 0
Reputation: 295678
I wouldn't use Python for this at all; bash with jq
suffices.
mfa() {
[[ $1 && $2 ]] || {
echo "Usage: mfa token-code serial-number" >&2
return 1
}
token_json=$(aws sts get-session-token --serial-number "$2" --token-code "$1") || return
IFS=$'\t' read -r accessKeyId secretAccessKey sessionToken _ < <(
jq -r '
.Credentials | [.AccessKeyId, .SecretAccessKey, .SessionToken] | @tsv
' <<<"$token_json"
) && [[ $accessKeyId && $secretAccessKey && $sessionToken ]] || return
aws configure set aws_access_key_id "$accessKeyId" --profile mfa || return
aws configure set aws_secret_access_key "$secretAccessKey" --profile mfa || return
aws configure set aws_session_token "$sessionToken" --profile mfa
}
If you really want to embed the Python source in your .bashrc
, you can do that too:
mfa_py=$(cat <<'END-OF-PYTHON'
# adopting fixes made by Barmar to the Python code here
import sys, subprocess, json
obj=json.loads(sys.stdin.read())
AccessKeyId=obj['Credentials']['AccessKeyId']
SecretAccessKey=obj['Credentials']['SecretAccessKey']
SessionToken=obj['Credentials']['SessionToken']
subprocess.check_output(['aws', 'configure', 'set', 'aws_access_key_id', AccessKeyId, '--profile', 'mfa'])
subprocess.check_output(['aws', 'configure', 'set', 'aws_secret_access_key', SecretAccessKey, '--profile', 'mfa'])
subprocess.check_output(['aws', 'configure', 'set', 'aws_session_token', SessionToken, '--profile', 'mfa'])
END-OF-PYTHON
)
mfa() {
aws sts get-session-token --serial-number "$2" --token-code "$1" | python -c "$mfa_py"
}
In your original alias definition, quotes that were clearly intended to be literal were being parsed as syntactic by the shell, so they weren't still available to be read by the Python interpreter.
Here, we're using a quoted heredoc to ensure that everything between the <<'END-OF-PYTHON'
and the END-OF-PYTHON
-- quotes included -- is treated as literal.
Upvotes: 3
Reputation: 782025
Don't use an alias, just name the function mfa
. And put the Python code in a file.
mfa.py:
import sys, subprocess, json
obj=json.loads(sys.stdin.read())
AccessKeyId=obj['Credentials']['AccessKeyId']
SecretAccessKey=obj['Credentials']['SecretAccessKey']
SessionToken=obj['Credentials']['SessionToken']
subprocess.check_output(['aws', 'configure', 'set', 'aws_access_key_id', AccessKeyId, '--profile', 'mfa'])
subprocess.check_output(['aws', 'configure', 'set', 'aws_secret_access_key', SecretAccessKey, '--profile', 'mfa'])
subprocess.check_output(['aws', 'configure', 'set', 'aws_session_token', SessionToken, '--profile', 'mfa'])
Note that I give a list to subprocess.check_output
rather than constructing a string, so that shell=True
isn't needed.
Then define the function:
mfa() {
aws sts get-session-token --serial-number "$2" --token-code "$1" | python /path/to/mfa.py
}
I assume the session token is JSON, not Python syntax, so I use json.loads()
rather than eval()
. And to read all of standard input, use sys.stdin.read()
rather than joining readlines()
; that creates a list unnecessarily, just to join it back into one long string.
Upvotes: 2