diff --git a/README.rst b/README.rst index 25f4c01..e8d3929 100644 --- a/README.rst +++ b/README.rst @@ -175,6 +175,11 @@ Usage --role-session-name ROLE_SESSION_NAME Friendly session name required when using --assume- role. By default, this is your local username. + --no-mfa-prompt NO_MFA_PROMPT + If you've already created short-term + credentials and don't want to be prompted for + your MFA token when assuming a role, use this flag. + Used with --assume-role **Argument precedence**: Command line arguments take precedence over environment variables. @@ -297,3 +302,20 @@ Assuming a role in multiple accounts and be able to work with both accounts simu $> aws s3 list-objects —bucket my-production-bucket —profile myorganization-production $> aws s3 list-objects —bucket my-staging-bucket —profile myorganization-staging + +If a profile with short-term credentials has the permissions to assume a role _without_ entering an MFA token, you can add the `--no-mfa-prompt` flag to not prompt you for the MFA token. + +.. code-block:: sh + + $> aws-mfa --profile myorganization --device arn:aws:iam::123456788990:mfa/dudeman + INFO - Validating credentials for profile: myorganization + INFO - Short term credentials section myorganization is missing, obtaining new credentials. + Enter AWS MFA code for device [arn:aws:iam::123456788990:mfa/dudeman] (renewing for 43200 seconds):953051 + INFO - Fetching Credentials - Profile: myorganization, Duration: 43200 + INFO - Success! Your credentials will expire in 43200 seconds at: 2018-02-06 03:54:40+00:00 + + $> aws-mfa --profile myorganization --long-term-suffix none --short-term-suffix audit-role --assume-role arn:aws:iam::222222222222:role/AuditRole --role-session-name some-session --no-mfa-prompt True + INFO - Validating credentials for profile: myorganization-audit-role with assumed role: arn:aws:iam::222222222222:role/AuditRole + INFO - Short term credentials section myorganization-audit-role is missing, obtaining new credentials. + INFO - Assuming Role - Profile: myorganization-audit-role, Role: arn:aws:iam::222222222222:role/AuditRole, Duration: 3600 + INFO - Success! Your credentials will expire in 3600 seconds at: 2018-02-05 16:55:54+00:00 \ No newline at end of file diff --git a/aws-mfa b/aws-mfa index 6e05a08..1e2c006 100755 --- a/aws-mfa +++ b/aws-mfa @@ -62,6 +62,12 @@ def main(): "--assume-role", default=getpass.getuser(), required=False) + parser.add_argument('--no-mfa-prompt', + help="If you've already created short-term " + "credentials and don't want to be prompted for " + "your MFA token when assuming a role, use this flag. " + "Used with --assume-role", + required=False) parser.add_argument('--force', help="Refresh credentials even if currently valid.", action="store_true", @@ -130,8 +136,15 @@ def validate(args, config): reup_message = "Obtaining credentials for a new role or profile." try: - key_id = config.get(long_term_name, 'aws_access_key_id') - access_key = config.get(long_term_name, 'aws_secret_access_key') + aws_creds = { + "aws_access_key_id": config.get( + long_term_name, 'aws_access_key_id'), + "aws_secret_access_key": config.get( + long_term_name, 'aws_secret_access_key') + } + if args.no_mfa_prompt: + aws_creds['aws_session_token'] = config.get( + long_term_name, 'aws_session_token') except NoSectionError: log_error_and_exit( "Long term credentials session '[%s]' is missing. " @@ -247,7 +260,7 @@ def validate(args, config): % (diff.total_seconds(), exp)) if should_refresh: - get_credentials(short_term_name, key_id, access_key, args, config) + get_credentials(short_term_name, aws_creds, args, config) def log_error_and_exit(message): @@ -256,21 +269,22 @@ def log_error_and_exit(message): sys.exit(1) -def get_credentials(short_term_name, lt_key_id, lt_access_key, args, config): +def get_credentials(short_term_name, aws_creds, args, config): try: token_input = raw_input except NameError: token_input = input - mfa_token = token_input('Enter AWS MFA code for device [%s] ' - '(renewing for %s seconds):' % - (args.device, args.duration)) + if not args.no_mfa_prompt: + mfa_token = token_input('Enter AWS MFA code for device [%s] ' + '(renewing for %s seconds):' % + (args.device, args.duration)) - client = boto3.client( - 'sts', - aws_access_key_id=lt_key_id, - aws_secret_access_key=lt_access_key - ) + client = boto3.client( + 'sts', + aws_access_key_id=aws_creds['aws_access_key_id'], + aws_secret_access_key=aws_creds['aws_secret_access_key'] + ) if args.assume_role: @@ -279,14 +293,26 @@ def get_credentials(short_term_name, lt_key_id, lt_access_key, args, config): if args.role_session_name is None: log_error_and_exit("You must specify a role session name " "via --role-session-name") - - response = client.assume_role( - RoleArn=args.assume_role, - RoleSessionName=args.role_session_name, - DurationSeconds=args.duration, - SerialNumber=args.device, - TokenCode=mfa_token - ) + if args.no_mfa_prompt: + client = boto3.client( + 'sts', + aws_access_key_id=aws_creds['aws_access_key_id'], + aws_secret_access_key=aws_creds['aws_secret_access_key'], + aws_session_token=aws_creds['aws_session_token'] + ) + response = client.assume_role( + RoleArn=args.assume_role, + RoleSessionName=args.role_session_name, + DurationSeconds=args.duration + ) + else: + response = client.assume_role( + RoleArn=args.assume_role, + RoleSessionName=args.role_session_name, + DurationSeconds=args.duration, + SerialNumber=args.device, + TokenCode=mfa_token + ) config.set( short_term_name,