Versent / saml2aws

CLI tool which enables you to login and retrieve AWS temporary credentials using a SAML IDP
https://github.com/Versent/saml2aws
MIT License
2.06k stars 563 forks source link

exec/script ignores credentials as arguments #695

Open mikeparker opened 3 years ago

mikeparker commented 3 years ago
saml2aws exec --username=.. --password=.. --mfa=TOTP --mfa-token=... --idp-provider=Okta --url=https://... --role=arn:aws:iam.. aws s3 ls
error aws credentials have expired
saml2aws script --username=.. --password=.. --mfa=TOTP --mfa-token=.. --idp-provider=Okta --url=https://... --role=arn:aws:iam::...
error aws credentials have expired

The console and login commands work fine, but script and exec do not. Am I missing something? I note that the console command still gives an 'expired credentials triggering login' message, so presumably its defaulting to stored credentials and then trying the given credentials from the arguments?

 saml2aws console --link --username=.. --password=.. --mfa=TOTP --mfa-token=.. --idp-provider=Okta --url=.. --role=arn:aws:iam::.. --skip-prompt
expired credentials triggering login
Using IDP Account default to access Okta https://..
Authenticating as m.. ...
Selected role: arn:aws:iam::..
Requesting AWS credentials using SAML assertion
Logged in as: arn:aws:sts::..

Your new access key pair has been stored in the AWS configuration
Note that it will expire at 2021-07-17 19:20:09 +0100 BST
mikeparker commented 3 years ago

Maybe the problem is returning here https://github.com/Versent/saml2aws/blob/cd493549dfd492e4bb16cd5f8d3b0dfae410dc9b/cmd/saml2aws/commands/exec.go#L49-L51

instead of trying to login with the provided creds as per here https://github.com/Versent/saml2aws/blob/cd493549dfd492e4bb16cd5f8d3b0dfae410dc9b/cmd/saml2aws/commands/console.go#L86-L88

mikeparker commented 3 years ago

Looks like an empty config file is created https://github.com/Versent/saml2aws/blob/cd493549dfd492e4bb16cd5f8d3b0dfae410dc9b/pkg/awsconfig/awsconfig.go#L146

Which is loaded with a default expiry time of 0, which then is counted as expired.

Shouldnt all this logic just be skipped if we provide credentials on the command line?

The discrepancies in behaviour is potentially caused by all the duplicated (but slightly different) code between these commands - it deviates when console calls loadOrLogin instead of sharedCreds.Load which works with the username/password from the command line:

https://github.com/Versent/saml2aws/blob/cd493549dfd492e4bb16cd5f8d3b0dfae410dc9b/cmd/saml2aws/commands/exec.go#L26-L77

https://github.com/Versent/saml2aws/blob/cd493549dfd492e4bb16cd5f8d3b0dfae410dc9b/cmd/saml2aws/commands/console.go#L27-L67

Maybe all this should be extracted out and shared rather than copy/pasted everywhere?

borissavelev commented 2 years ago
  saml2aws login \
    --credential-process \
    --username=$USERNAME  \
    --password="$PASSWORD" \
    --role "$ROLE" \
    --profile "$PROFILE" \
    --credentials-file="$CRED" \
    --disable-keychain \
    --skip-prompt
saml2aws login --credential-process --username=*** --password=*** --role arn:aws:iam::***:role/OktaAdminAccess --profile oktapreview --credentials-file=/var/folders/sk/***/T//saml2aws.oktapreview --disable-keychain --skip-prompt
? Enter verification code ^C

is asking MFA token as well

maximveksler commented 1 year ago

The naive workaround is to use silent login followed by exec.

#!/bin/bash

set -euo pipefail

saml2aws_credentials_file="$HOME/.aws/saml2aws-credentials"

# Workaround for "credentials have expired" https://github.com/Versent/saml2aws/issues/695#issuecomment-881932210
saml2aws login -a controlplane --quiet --skip-prompt --credentials-file="$saml2aws_credentials_file" 
saml2aws exec --exec-profile "$1" -a controlplane --skip-prompt --credentials-file="$saml2aws_credentials_file" aws "${@:2}"

I.e.

./awsx groundcover-managed-dev1 sts get-caller-identity
maximveksler commented 1 year ago

Better apporach (IMHO) is to use saml2aws credential_process support (https://github.com/Versent/saml2aws/issues/120), which does renew the auth session upon expiration for aws cli commands.

~/.aws/config

[profile controlplane]
credential_process = /opt/homebrew/bin/saml2aws login -a controlplane --credential-process --skip-prompt --credentials-file /Users/maximveksler/.aws/saml2aws-credentials

[profile groundcover-managed-dev1]
source_profile = controlplane
role_arn = arn:aws:iam::XXXXXXXXXXXXX:role/OrganizationAccountAccessRole

awsx

#!/bin/bash

set -euo pipefail

aws "${@:2}" --profile "$1"

Test

# Authenticated session

maximveksler@Maxims-MBP bin % ./awsx groundcover-managed-dev1 sts get-caller-identity
{
    "UserId": "AROAZIMJOEDRK7GH6BPUO:botocore-session-1680564423",
    "Account": "XXXXXXXXXXXXX",
    "Arn": "arn:aws:sts::XXXXXXXXXXXXX:assumed-role/OrganizationAccountAccessRole/botocore-session-1680564423"
}

# No credentials session

maximveksler@Maxims-MBP bin % rm ~/.aws/saml2aws-credentials
maximveksler@Maxims-MBP bin % ./awsx groundcover-managed-dev1 sts get-caller-identity
{
    "UserId": "AROAZIMJOEDRK7GH6BPUO:botocore-session-1680564423",
    "Account": "XXXXXXXXXXXXX",
    "Arn": "arn:aws:sts::XXXXXXXXXXXXX:assumed-role/OrganizationAccountAccessRole/botocore-session-1680564423"
}

# Expired credentials session

maximveksler@Maxims-MBP bin % sed -i '' '/x_security_token_expires/d' ~/.aws/saml2aws-credentials
maximveksler@Maxims-MBP bin % ./awsx groundcover-managed-dev1 sts get-caller-identity
{
    "UserId": "AROAZIMJOEDRK7GH6BPUO:botocore-session-1680564423",
    "Account": "XXXXXXXXXXXXX",
    "Arn": "arn:aws:sts::XXXXXXXXXXXXX:assumed-role/OrganizationAccountAccessRole/botocore-session-1680564423"
}