AWS STS Credentials and Google Apps Federated User

Tony Tannous
7 min readJul 14, 2020

This write-up outlines methods of working with the AWS Secure Token Service (STS) and Federated user accounts, where Google has been established as the Identity Provider. It is based on a recent experience where AWS programmatic access was only permitted via STS temp credentials.

A summary of the scenario and what we aim to achieve are as follows:

  • You are a developer working with the aws cli for the purposes of testing your Dev stack.
  • Your organisation has enabled SSO via SAML, with Google as the Identity Provider.
  • Your Google account (eg@myexample.com) has been provisioned for access to AWS.
  • Access to AWS resources requires that you authenticate using your Federated user and request temporary credentials using the Secure Token Service (STS). You are advised that the role you need to “assume” to request the credentials is, arn:aws:iam::111222333444:role/saml-init.
  • Once you have your STS temp credentials, you will then be permitted to “assume” a secondary development role, which has been provisioned to allow access to AWS resources such as S3 and Elastic Container Registry (ECR). The arn of the secondary role is arn:aws:iam::888777666555:role/assumed-dev

Federated Login Helper (aws-google-auth)

aws-google-auth is an authentication helper Python package, offered by CEVO (Docker also available at git repo). It is invoked via command line using docker and can be used to generate STS credentials using your Federated Google account. The package can also be installed locally to your existing Python environment, or via building the docker.

Option 1: Local Python Installation

If you prefer to use the your local Python installation, then install aws-google-auth via pip:

$ pip install aws-google-auth

Option 2: Docker Installation

Clone CEVO git repo,

$ git clone https://github.com/cevoaustralia/aws-google-auth \
aws-google-auth

and build the image using:

$ cd aws-google-auth
$ docker build --rm -t aws-google-auth .

The docker image is used for the examples throughout the article.

Locating Google Identity and SAML Provider IDs (IDPID/SPID)

Before being able to use the image, you will need to know the following details:

  • Google Identity Provider ID (idpid)
  • SAML Service Provider ID assigned by Google (spid)

Your AWS System admins should provide these details. If they are not provided, then you should be able to find these through the Google App AWS link address details.

From your web browser, go to Google Apps launcher. Scroll until you see the AWS Google App….hover your mouse over the icon to view the link address details in your browser’s status bar. Alternatively you can right click on the icon and copy/paste the link address into Notepad.

Make a note of your idpid and spid. They are required as parameter inputs to aws-google-auth.

Generate STS Temporary Credentials

The aws-google-auth helper stores/adds authentication data to $HOME/.aws/config and $HOME/.aws/credentials files so it's important that the storage hosting these files is encrypted at rest.

The Docker can be run with a host:container mount $HOME/.aws:/root/.aws. This will allow direct access to files $HOME/.aws/config & $HOME/.aws/credentials. Alternatively, you can setup an alternate host location and have the container generate config/credentials into this location.

To directly edit your default credentials/config files, then specify the following mount option in your docker command:

  • Linux-based hosts -v $HOME/.aws:/root/.aws
  • Windows host -v c:/Users/<username>/.aws:/root/.aws

Run the Docker Image

To get a full list of command line options for aws-google-auth, run the docker with -h option.

For the examples in the article, the following options are used,

$ docker run -it aws-google-auth -h
..
...
-u USERNAME (Google Apps username)
-I IDPID (Google Identity Provider identifier)
-S SPID (SAML Provider identifier )
-R REGION (AWS region endpoint)
-d DURATION (Credential duration in SECONDS)
-p PROFILE (AWS profile - defaults to value of $AWS_PROFILE)
-r ROLE_ARN (The ARN of the role to assume. If not supplied
,a list roles to choose from will be listed)
..
...

with the following sample values,

username=eg@myexample.com
idpid=X7x0Xxxx
spid=000111000111
region=us-east-1
duration=3600
profile=sts-temp
role_arn=arn:aws:iam::111222333444:role/saml-init

Using these values, we generate STS temporary credentials as follows:

$ docker run -it -v $HOME/.aws:/root/.aws aws-google-auth \
-u eg@myexample.com \
-I X7x0Xxxx \
-S 000111000111 \
-R us-east-1 \
-d 3600 \
-p sts-temp \
-r arn:aws:iam::111222333444:role/saml-init

For MFA with SMS verification enabled, you will be required to enter your Google password and respond with the SMS code.

Google Password: *******
Enter SMS token: G-nnnnnn

After authentication is complete, the expiration time for temporary credentials should be displayed

Assuming arn:aws:iam::111222333444:role/saml-init
Credentials Expiration: 2020-07-12 00:41:15+00:00

The AWS profile, sts-temp (-p sts-temp) should now contain the STS temporary credentials.

Verify AWS Config & Credentials

The credentials and config files can be checked to ensure profile sts-temp has been updated/generated with valid entries.

$HOME/.aws/config

[profile sts-temp]
region = us-east-1
google_config.ask_role = False
google_config.keyring = False
google_config.duration = 3600
google_config.google_idp_id = X7x0Xxxx
google_config.role_arn = arn:aws:iam::111222333444:role/saml-init
google_config.google_sp_id = 000111000111
google_config.u2f_disabled = False
google_config.google_username = eg@myexample.com
google_config.bg_response = None

$HOME/.aws/credentials

[sts-temp]
aws_access_key_id = exampleAAAAAAAAAAAAAAAAAAAAAA
aws_secret_access_key = exampleBBBBBBBBBBBBBBBBBBBBB
aws_security_token = exampleCCCCCCCCCCCCCCCCCC
aws_session_expiration = exampleDDDDDDDDDDDDDDDDDDDDDD
aws_session_token = exampleEEEEEEEEEEEEEEEEEEEE

Refreshing AWS STS Credentials

To refresh/update STS credentials for the same profile is only a matter of running the docker command again, supplying the same profile name
(-p sts-temp).

Switch to/Assume Secondary Role using STS Credentials

As mentioned earlier on, to perform Dev activities, we need to assume/switch to secondary role arn:aws:iam::888777666555:role/assumed-dev using the STS temporary credentials.

This secondary role has been provisioned with access to an Elastic Container Registry (ECR) and S3. To use the temporary STS credentials with this role, we need to create a new AWS profile, specifying the role_arn.

The following examples show the AWS profile being created with name dev-env for our secondary role.

$HOME/.aws/config

[profile dev-env]
region = us-east-1
source_profile = sts-temp
role_arn = arn:aws:iam::888777666555:role/assumed-dev

If you prefer, you can use the aws configure command to setup the new AWS profile.

$ aws configure set profile.dev-env.region us-east-1
$ aws configure set profile.dev-env.source_profile sts-temp
$ aws configure \
set profile.dev-env.role_arn \ arn:aws:iam::888777666555:role/assumed-dev

When the profile above is specified in AWS CLI commands (--profile dev-env), the secondary role (arn:aws:iam::888777666555:role/assumed-dev) is "assumed" with the STS temporary credentials being sourced from section [sts-temp] in $HOME/.aws/credentials.

Putting it all Together

The following is a re-cap of the process.

1. Authenticate with Federated User and Retrieve STS Credentials

  • Authenticate with Federated Google account using aws-google-auth and obtain STS temporary credentials for profile sts-temp.
$ docker run -it -v $HOME/.aws:/root/.aws aws-google-auth \
-u eg@myexample.com \
-I X7x0Xxxx \
-S 000111000111 \
-R us-east-1 \
-d 3600 \
-p sts-temp \
-r arn:aws:iam::111222333444:role/saml-init

2. Configure New AWS Profile for Secondary Role to use STS

  • Create new AWS profile for the secondary role

The below shows the setup required for profile dev-env

$HOME/.aws/config

[profile dev-env]
region = us-east-1
source_profile = sts-temp
role_arn = arn:aws:iam::888777666555:role/assumed-dev

or, alternatively, add the profile to $HOME/.aws/config via aws configure.

$ aws configure set profile.dev-env.region us-east-1
$ aws configure set profile.dev-env.source_profile sts-temp
$ aws configure set profile.dev-env.role_arn \ arn:aws:iam::888777666555:role/assumed-dev

3. Start Using CLI Commands

The examples that follow show commands which will transparently “assume” the secondary role arn:aws:iam::888777666555:role/assumed-dev.

  • S3 list bucket subdir/key
$ aws s3 ls s3://mybucket/mydir --profile dev-env
  • ECR get docker registry login, get-login
$ aws ecr get-login --registry-ids xxxxxxxxxxxx --no-include-email --profile dev-env

4. Update/Refresh Expired STS credentials

Once the STS temporary credentials have expired, re-execute aws-google-auth to refresh,

$ docker run -it -v $HOME/.aws:/root/.aws aws-google-auth \
-u eg@myexample.com \
-I X7x0Xxxx \
-S 000111000111 \
-R us-east-1 \
-d 3600 \
-p sts-temp \
-r arn:aws:iam::111222333444:role/saml-init

and continue using the profile for the secondary role.

Programmatic Access with Python & boto

The below sample Python code shows the secondary role being “assumed” by specifying profile dev-env. Authentication happens transparently due to the configuration performed earlier on for this profile.

import boto3

session = boto3.Session(profile_name='dev-env')
dev_s3_client = session.client('s3')

for key in dev_s3_client.list_objects(Bucket='mybucket')['Contents']:
print(key['Key'])

Final Comments

Some of the benefits of enabling Federated logins with temporary credentials are as follow:

  • Removing the user’s account from the linked Identity Provider/Organisation (eg. Google GSuite) ensures the user no longer has access to the AWS account.
  • The use of temporary credentials with a short expiration period (as opposed to issuing non-expiring keys), enforces the concept of key rotation.
  • Managing comprised temporary credentials is likely to be simpler than managing comprised permanent keys.

**UPDATE May 2022 - aws-google-auth Trace ERROR:root:’NoneType’ object has no attribute ‘get’ **

As of now, the latest version of aws-google-auth

~ $ aws-google-auth -Vaws-google-auth 0.0.37

returns an error when authenticating with Google as an IdP,

~ $ aws-google-auth -u xxxx@example.com -I xxxxxxxxx -S 123456789654 -R us-east-1 -d 3600 -p testingGoogle Password:
ERROR:root:’NoneType’ object has no attribute ‘get’
Traceback (most recent call last):
File “/usr/local/lib/python3.8/site-packages/aws_google_auth/__init__.py”, line 79, in cli
process_auth(args, config)
File “/usr/local/lib/python3.8/site-packages/aws_google_auth/__init__.py”, line 243, in process_auth
google_client.do_login()
File “/usr/local/lib/python3.8/site-packages/aws_google_auth/google.py”, line 256, in do_login
passwd_challenge_url = ‘https://accounts.google.com' + form.get(‘action’)
AttributeError: ‘NoneType’ object has no attribute ‘get’

Until the final package is updated, the workaround suggested here fixes the issue.

To implement the workaround, find the location of aws-google-auth installation:

  • Find install location of aws-google-auth:
~ $ pip show aws-google-authName: aws-google-auth
Version: 0.0.37
Summary: Acquire AWS STS (temporary) credentials via Google Apps SAML Single Sign On
Home-page: https://github.com/cevoaustralia/aws-google-auth
Author: Colin Panisset
Author-email: colin.panisset@cevo.com.au
License: MIT
Location: /usr/local/lib/python3.8/site-packages
Requires: beautifulsoup4, boto3, configparser, filelock, keyring, keyrings.alt, lxml, Pillow, requests, six, tabulate, tzlocal
Required-by:
  • Edit the following file:
/usr/local/lib/python3.8/site-packages/aws_google_auth/google.py

by adding lines:

    # Set bg_response in request payload to passwd challenge
if self.config.bg_response:
payload['bgresponse'] = self.config.bg_response

--

--

Tony Tannous

Learner. Interests include Cloud and Devops technologies.