Open mattwillsher opened 4 years ago
Hi @mattwillsher , hmm so you're saying that once you're logged in with your sso login, you want to be able to call something --profile "your current login" to use your login's access-token or have something like aws sso get-token ?
Yes @KaibaLopez
I have the following as a workaround in my shell at the moment:
function aws-access-token() { cat $(ls -1d ~/.aws/sso/cache/* | grep -v botocore) | jq -r "{accessToken} | .[]" }
function aws-list-accounts() { aws sso list-accounts --access-token $(aws-access-token) --output table }
Having a more direct method of getting the access token would help reduce the complexity here. Being able to tell people to just call aws sso list-accounts --output table
to get a list of their accounts would be great :)
I was just looking for aws sso-oidc get-token
so I can use that in conjunction with aws sso get-role-credentials
.
This is related to #5261.
Just a note that I recently ran into this, and this thread was helpful (thank you @mattwillsher).
We have hundreds of AWS accounts, and we're just now adopting AWS SSO. Many of us use aws-vault
, so converting ALL of those long-term credentials stored in the system keychain over to an AWS SSO configuration in ~/.aws/config
was going to be incredibly tedious.
If requiring the access token is required, it would be awesome if you could ask the AWS CLI for just the token cached to disk and a way to read back the value. The instructions I ended up writing for my devs includes asking them to type Ctrl+C
after the token is cached, so that it can be read by a script that can update the hundreds of profiles I need to manage, programmatically.
Came across this today and am confused as to why access token is needed.
I create my session based on a profile name, then create the client from that session.
session = boto3.Session(profile_name=profile_name)
sso_client = session.client("sso")
accounts_paginator = sso_client.get_paginator("list_accounts")
The session already has the access token so why do I need to provide it to the list-accounts method?
There is no nice way of getting this token either apart from reading it from the ~/.aws/sso/cache file which feels fundamentally wrong.
Or am I missing something?
Here is a workaround to get to the JSON cache file until this issue is fixed:
For AWS cli > 2.13.5 the name of the cache file is the sha1sum of your sso session name in the profile.
local sso_session=$(aws configure get sso_session --profile "${profile}")
local cache_file="${HOME}/.aws/sso/cache/$(echo -n "${sso_session}" | sha1sum | awk '{print $1}').json"
local access_token=$( jq --raw-output .accessToken "${cache_file}")
Do you know what it uses when the sso_session property for the given profile does not exist? In my case this property is not set in the profile configuration in the config file.
Do you have any documentation that i can refer to?
i worked it out.
If you are using the old legacy format for your SSO config file then the file is the hash of the sso_start_url, if you are using the new format then it is the sso_session.
See example code in python:
AWS_SSO_CACHE_PATH = os.path.join(str(Path.home()), ".aws/sso/cache")
def identify_profile_key(profile: dict) -> str:
if "sso_session" in profile:
logger.info("Profile is associated with SSO token provider configuration.")
return profile["sso_session"]
elif "sso_start_url" in profile:
logger.info("Profile is associated with Legacy non-refreshable configuration.")
return profile["sso_start_url"]
else:
logger.error("Unknown profile configuration.")
raise Exception("Unknown profile configuration")
def get_sso_cached_login(profile: dict) -> dict:
# Identify the correct key to use for SHA-1 hash
try:
key_to_hash = identify_profile_key(profile)
except Exception as e:
logger.error(f"Error identifying profile key: {e}")
raise
# Compute the SHA-1 hash to find the cache file
sha1_hash = hashlib.sha1(key_to_hash.encode()).hexdigest()
cache_file_path = os.path.join(AWS_SSO_CACHE_PATH, f"{sha1_hash}.json")
logger.info(f"Computed cache file path: {cache_file_path}")
# Check if the cache file exists
if not os.path.exists(cache_file_path):
logger.error(f"Cache file '{cache_file_path}' does not exist")
raise Exception(f"Cache file '{cache_file_path}' does not exist")
# Load the JSON data from the cache file
with open(cache_file_path, "r") as f:
data = json.load(f)
# Check for expiration
expires_at = data.get("expiresAt")
if expires_at is None:
logger.error(f"Missing 'expiresAt' in {cache_file_path}")
raise Exception(f"Missing 'expiresAt' in {cache_file_path}")
time_now = datetime.now()
if time_now > parse_timestamp(expires_at):
logger.error("Current cached SSO login is expired or invalid")
raise Exception("Current cached SSO login is expired or invalid")
logger.info("Successfully validated SSO cache.")
return data
I want to aws test-access --profile {profilename} so I can exit script. devs are logged in with SSO and CI/CD is logged in with machine tokens but all use profile to match. is there a way (it seemed so related to this is all).
I wrote a script to configure all AWS IAM Identity Center (SSO) accounts and roles automatically. It requires AWS CLI v2 and jq. Download the aws_configure_all_sso.sh
script here: https://codeberg.org/dedevsecops/aws
aws sso login creates a cache files in ~/.aws/sso/cache which contains an access token aws sso list-accounts and list-account-roles requires an access-token.
It would be helpful to have a mechanise to either output the current valid access token or make the argument optional and use the cached value for the current context.