aws / aws-cli

Universal Command Line Interface for Amazon Web Services
Other
15.55k stars 4.13k forks source link

[V2] --access-token should be optional to sso calls #5057

Open mattwillsher opened 4 years ago

mattwillsher commented 4 years ago

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.

KaibaLopez commented 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 ?

mattwillsher commented 4 years ago

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 :)

taingalls commented 4 years ago

I was just looking for aws sso-oidc get-token so I can use that in conjunction with aws sso get-role-credentials.

vvdimov commented 4 years ago

This is related to #5261.

skyzyx commented 3 years ago

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.

reidca commented 2 years ago

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?

apogrebnyak commented 1 year ago

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}")
reidca commented 1 year ago

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?

reidca commented 1 year ago

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
deantray commented 1 year ago

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).

evanstucker-hates-2fa commented 6 months ago

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