Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's a good way to obtain STS credentials with a SAML federated login via Okta for use in local command line tools?

The Amazon Web Services API provides the AssumeRoleWithSAML endpoint to allow a user to exchange a SAML assertion for a set of temporary API credentials from the AWS Security Token Service.

A SAML provider, like Okta, will generate a SAML assertion after a user logs into their web UI and Okta authenticates the user on that user's enterprise backend (e.g. enterprise LDAP).

Typically this assertion is then relayed from the users browser onto another web service that accepts SAML assertions, the relying party, in order to authenticate the user to this third party (for example when using Okta federated login to enable a user to log into the AWS web console)

What is the best way to enabled a federated user to authenticate with Okta, get an assertion, pass that assertion to STS and get back a set of temporary AWS API credentials that the user could then use with either the AWS command line tools, or with a local python boto script?

  • Launch a web browser from a python tool using the Python webbrowser module?
  • What's a fluid way to get an assertion from a web browser into a form usable by a command line tool?
  • Create a temporary ngrok tunnel to a locally running temporary webserver (e.g. an instance of flask or bottle) for Okta to redirect the users web browser onto in order to deliver the assertion to some local code?
  • How does one typically bridge the world of an interactive web page and local command line tools?
like image 827
gene_wood Avatar asked Nov 01 '22 09:11

gene_wood


1 Answers

This project on GitHub titled: okta-aws-cli-assume-role is by far the easiest way to accomplish this that I've found.

Setup Script

I've created this shell script to pull it down and set things up:

$ cat okta_setup.sh
#!/bin/bash
​
print_usage() {
  echo "Usage: $(basename $0) -a <aws_account> [-h] -r <aws_role> -u <octa_username>" >&2
}
​
print_help() {
  cat <<EOF
Setup Script for Octa AWS CLI tool
==================================
​
To Execute:
​
    $(basename $0) -a <aws_account> -r <aws_role> -u <octa_username>
​
Parameters:
  -a: AWS Account to have setup with octa
  -h: Option to get help
  -r: The role to be assumed when logging into AWS
  -u: The Octa username to be used to log in

EOF
}
​
while getopts ":a:hr:u:" opt; do
  case ${opt} in
    a  )
      awsAcct=$OPTARG;;
    h  )
      print_help
      exit 0
      ;;
    r  ) awsRole=$OPTARG;;
    u  ) octaUser=$OPTARG;;
    \? )
      print_usage
      exit 1
      ;;
  esac
done
​
if [ -z "${awsAcct}" ]; then
  echo "AWS Account is required, use the -a option" >&2
  exit 2
fi
​
if [ -z "${awsRole}" ]; then
  echo "AWS Role is required, use the -r option" >&2
  exit 3
fi
​
if [ -z "${octaUser}" ]; then
  echo "Octa user is required, use the -u option" >&2
  exit 4
fi
​
########################################
### Setup AWS CLI
########################################
echo 'Setting up ~/.aws/config'
echo '------------------------'
echo ''
aws configure set credential_process "okta-credential_process arn:aws:iam::${awsAcct}:role/${awsRole}" \
    --profile "${awsRole}_${awsAcct}"
aws configure set region us-east-1 --profile "${awsRole}_${awsAcct}"
echo ''
echo "Here's the contents..."
echo '----------------------'
cat ~/.aws/config
echo ''
echo ''

########################################
### Setup Okta CLI
########################################
echo 'Setting up Okta CLI'
echo '-------------------'
echo ''
PREFIX=~/.okta bash <(curl -fsSL https://raw.githubusercontent.com/slmingol/okta-aws-cli-assume-role/master/bin/install.sh) -i
echo ''

########################################
### Create My config.properties for Okta
########################################
echo 'Setting up Okta CLI config.properties'
echo '-------------------------------------'
echo ''
cat << EOF > ~/.okta/config.properties
#OktaAWSCLI
OKTA_ORG=myurl.okta.com
OKTA_AWS_APP_URL=https://myurl.okta.com/...
OKTA_USERNAME=${octaUser}
OKTA_BROWSER_AUTH=false
OKTA_ENV_MODE=true
#OKTA_MFA_CHOICE=GOOGLE.token:software:totp
OKTA_STS_DURATION=43200
OKTA_AWS_REGION=us-east-1
OKTA_AWS_ROLE_TO_ASSUME=arn:aws:iam::${awsAcct}:role/${awsRole}
OKTA_PASSWORD_CMD=lpass show --password mydom.com
#OKTA_PASSWORD_CMD=echo "mypassword"
EOF
echo ''
echo "Here's the contents...."
echo '-----------------------'
cat ~/.okta/config.properties
echo ''
echo ''

Example

When you run this script:

$ ./okta_setup.sh -a 1234567890 -r MySystemsAdminAccess -u smingolelli
Setting up ~/.aws/config
------------------------


Here's the contents...
----------------------
[profile MySystemsAdminAccess_1234567890]
credential_process = okta-credential_process arn:aws:iam::1234567890:role/MySystemsAdminAccess
region = us-east-1


Setting up Okta CLI
-------------------

Installing into ~/.okta
Latest release JAR file: https://github.com/oktadeveloper/okta-aws-cli-assume-role/releases/download/v2.0.4/okta-aws-cli-2.0.4.jar
Fetching JAR file → ~/.okta/okta-aws-cli-2.0.4.jar
Symlinking ~/.okta/okta-aws-cli.jar → okta-aws-cli-2.0.4.jar
Creating example ~/.okta/config.properties

Add the following to ~/.bash_profile or ~/.profile:

#OktaAWSCLI
if [[ -f "$HOME/.okta/bash_functions" ]]; then
    . "$HOME/.okta/bash_functions"
fi
if [[ -d "$HOME/.okta/bin" && ":$PATH:" != *":$HOME/.okta/bin:"* ]]; then
    PATH="$HOME/.okta/bin:$PATH"
fi

Setting up Okta CLI config.properties
-------------------------------------


Here's the contents....
-----------------------
#OktaAWSCLI
OKTA_ORG=myurl.okta.com
OKTA_AWS_APP_URL=https://myurl.okta.com/......
OKTA_USERNAME=smingolelli
OKTA_BROWSER_AUTH=false
OKTA_ENV_MODE=true
#OKTA_MFA_CHOICE=GOOGLE.token:software:totp
OKTA_STS_DURATION=43200
OKTA_AWS_REGION=us-east-1
OKTA_AWS_ROLE_TO_ASSUME=arn:aws:iam::1234567890:role/MySystemsAdminAccess
OKTA_PASSWORD_CMD=lpass show --password mydom.com
#OKTA_PASSWORD_CMD=echo "mypassword"

What happened?

The above does several things:

  • Adds a profile configured to use okta-cli's jar as a credential_process
  • Installs and configures okta-cli in directory $HOME/.okta
  • Configures a functioning config.properties file

You'll want to add this directory to your $HOME/.bash_profile or $HOME/.bashrc so that shows up on your $PATH.

if [[ -d "$HOME/.okta/bin" && ":$PATH:" != *":$HOME/.okta/bin:"* ]]; then
    PATH="$HOME/.okta/bin:$PATH"
fi

Getting your STS token

With that you can now run AWS CLI commands or Boto3 Python scripts and they'll either interactively prompt you to log into Okta or do so and retrieve an STS token for you.

$ withokta "env" | grep TOK
AWS_SESSION_TOKEN=FQoGZX................5W4sIwW66bYJn9AEh6XeXO2aGKKrcy+sF

-or-

$ aws --profile MySystemsAdminAccess_1234567890 sts get-caller-identity
{
    "UserId": "XXXXXXXXXXXXXXXX:smingolelli",
    "Account": "1234567890",
    "Arn": "arn:aws:sts::1234567890:assumed-role/MySystemsAdminAccess/smingolelli"
}

Keep in mind that the withokta "<cmd>" can include any command which you'd want to have the traditional environment variables available:

  • AWS_SECRET_ACCESS_KEY
  • AWS_ACCESS_KEY_ID
  • AWS_SESSION_TOKEN

The method above where I'm calling the aws CLI directly is making use of another helper script included with the Okta CLI, okta-credential_process. This is added into your $HOME/.aws/config file and refers to the AWS role you want to assume. You can run it interactively to better see what it returns to aws when called:

$ okta-credential_process arn:aws:iam::1234567890:role/MySystemsAdminAccess
{"Expiration":"2019-09-08T00:49:45.615579Z","Version":1,"SessionToken":"XXXXXXXX","AccessKeyId":"XXXXXXXXXX","SecretAccessKey":"XXXXXXXXXX"}

That payload is the 3 components:

  • AWS_SECRET_ACCESS_KEY
  • AWS_ACCESS_KEY_ID
  • AWS_SESSION_TOKEN
like image 193
slm Avatar answered Nov 15 '22 10:11

slm