Repository: byu-oit/awslogin

Issue:
Support for profiles as cli option
I don't use the default profile at all. This requires me to know in which environment I'm operating, as well as prevent accidental/malicious script execution from executing in a default account, whatever it may be.

CLI option could be --profile <profilename> or just a profile name, e.g.
`awslogin --profile dev`
or
`awslogin dev`
 

Discussion:

Patch:
diff --git a/README.md b/README.md
index 1ee5dff..0be4965 100644
--- a/README.md
+++ b/README.md
@@ -12,14 +12,16 @@ BYU used to use the great [aws-adfs](https://github.com/venth/aws-adfs) CLI tool
 * Run `pip3 install byu-awslogin`
 
 ## Usage
-awslogin automatically sets up the default profile in your ~/.aws/config and ~/.aws/credentials files.  **_If you already have a default profile you want to save in your ~/.aws files make sure to do that before running awslogin._**
+awslogin defaults to the default profile in your ~/.aws/config and ~/.aws/credentials files.  **_If you already have a default profile you want to save in your ~/.aws files make sure to do that before running awslogin._**
 
 Once you're logged in, you can execute commands using the AWS CLI or AWS SDK. Try running `aws s3 ls`.
 Currently, awslogin tokens are only valid for 1 hour due to the assume_role_with_saml AWS API call has a max timeout of 1 hour.
 
 To use it:
 * Run `awslogin` and it will prompt you for the AWS account and role to use.
-* Run `awslogin --account <account name> --role <role name>` to skip the prompting for account and name.  You could specify just one of the arcuments as well.
+* Run `awslogin --account <account name> --role <role name>` to skip the prompting for account and name.  You could specify just one of the arguments as well.
+* Run `awslogin --profile <profile name>` to specifiy an alternative profile
+* Run `awslogin -- --help` for full help message
 
 ## Reporting bugs or requesting features
 * Enter an issue on the github repo.
@@ -34,6 +36,5 @@ To use it:
 * Add support for profiles
 * Authenticate once for 8 hours and rerun `awslogin` to relogin
 * Write tests
-  * (Nate) index.py
   * roles.py
   * assume_role.py
diff --git a/VERSION b/VERSION
index 69010fa..6f16bd3 100644
--- a/VERSION
+++ b/VERSION
@@ -1,1 +1,1 @@
-0.9.14
\ No newline at end of file
+0.9.15
\ No newline at end of file
diff --git a/byu_awslogin/index.py b/byu_awslogin/index.py
index 6c7aff5..a9a3f44 100755
--- a/byu_awslogin/index.py
+++ b/byu_awslogin/index.py
@@ -3,16 +3,16 @@
 import os
 import fire
 import getpass
-import subprocess
 import configparser
 from os.path import expanduser
 from .adfs_auth import authenticate
 from .assume_role import ask_which_role_to_assume, assume_role
 from .roles import action_url_on_validation_success, retrieve_roles_page
 
-def cli(account=None, role=None):
+
+def cli(account=None, role=None, profile='default'):
     # Get the federated credentials from the user
-    cached_netid = load_last_netid()
+    cached_netid = load_last_netid(aws_file('config'), profile)
     if cached_netid:
         net_id_prompt = 'BYU Net ID [{}]: '.format(cached_netid)
     else:
@@ -46,7 +46,6 @@ def cli(account=None, role=None):
     ####
     # Ask user which role to assume
     ####
-    #print(principal_roles)
     account_name, role_name, chosen_role = ask_which_role_to_assume(account_names, principal_roles, account, role)
 
     ####
@@ -54,11 +53,11 @@ def cli(account=None, role=None):
     ####
     aws_session_token = assume_role(*chosen_role, assertion)
 
-    write_to_cred_file(aws_session_token)
-    write_to_config_file(net_id, 'us-west-2')
+    check_for_aws_dir()
+    write_to_cred_file(aws_file('creds'), aws_session_token, profile)
+    write_to_config_file(aws_file('config'), net_id, 'us-west-2', profile)
 
     print("Now logged into {}@{}".format(role_name, account_name))
-    #proc = subprocess.Popen(args, env=os.environ)
 
     # Overwrite and delete the credential variables, just for safety
     username = '##############################################'
@@ -66,52 +65,53 @@ def cli(account=None, role=None):
     del username
     del password
 
+
 def main():
     fire.Fire(cli)
 
 
+def aws_file(file_type):
+    if file_type == 'creds':
+        return "{}/.aws/credentials".format(expanduser('~'))
+    else:
+        return "{}/.aws/config".format(expanduser('~'))
+
+
 def open_config_file(file):
     config = configparser.ConfigParser()
     config.read(file)
     return config
 
 
-def write_to_cred_file(aws_session_token):
-    check_for_aws_dir()
-    file = "{}/.aws/credentials".format(expanduser('~'))
+def check_for_aws_dir(directory="{}/.aws".format(expanduser('~'))):
+    if not os.path.exists(directory):
+        os.makedirs(directory)
+
+
+def write_to_cred_file(file, aws_session_token, profile):
     config = open_config_file(file)
-    config['default'] = {'aws_access_key_id': aws_session_token['Credentials']['AccessKeyId'],
-                         'aws_secret_access_key': aws_session_token['Credentials']['SecretAccessKey'],
-                         'aws_session_token': aws_session_token['Credentials']['SessionToken']
-                        }
+    config[profile] = {'aws_access_key_id': aws_session_token['Credentials']['AccessKeyId'],
+                       'aws_secret_access_key': aws_session_token['Credentials']['SecretAccessKey'],
+                       'aws_session_token': aws_session_token['Credentials']['SessionToken']
+                       }
     with open(file, 'w') as configfile:
         config.write(configfile)
 
 
-def check_for_aws_dir():
-    directory = "{}/.aws".format(expanduser('~'))
-    if not os.path.exists(directory):
-        os.makedirs(directory)
-    file = "{}/config".format(directory)
-
-
-def write_to_config_file(net_id, region):
-    check_for_aws_dir()
-    file = "{}/.aws/config".format(expanduser('~'))
+def write_to_config_file(file, net_id, region, profile):
     config = open_config_file(file)
-    config['default'] = {'region': region, 'adfs_netid': net_id}
+    config[profile] = {'region': region, 'adfs_netid': net_id}
     with open(file, 'w') as configfile:
         config.write(configfile)
 
 
-def load_last_netid():
-    file = "{}/.aws/config".format(expanduser('~'))
+def load_last_netid(file, profile):
     config = open_config_file(file)
-    if config.has_section('default') and config.has_option('default', 'adfs_netid'):
-        return config['default']['adfs_netid']
+    if config.has_section(profile) and config.has_option(profile, 'adfs_netid'):
+        return config[profile]['adfs_netid']
     else:
         return ''
 
 
 if __name__ == '__main__':
-    main()
\ No newline at end of file
+    main()


Test patch:
diff --git a/test/byu_awslogin/test_index.py b/test/byu_awslogin/test_index.py
index d73a854..df88344 100644
--- a/test/byu_awslogin/test_index.py
+++ b/test/byu_awslogin/test_index.py
@@ -1,4 +1,79 @@
+import pytest
+import os.path
+import configparser
 from byu_awslogin import index
 
+
+@pytest.fixture
+def aws_config_file(tmpdir):
+    return tmpdir.dirpath(".aws/config")
+
+
+@pytest.fixture
+def aws_cred_file(tmpdir):
+    return tmpdir.dirpath(".aws/credentials")
+
+
+@pytest.fixture
+def read_config_file(file):
+    config = configparser.ConfigParser()
+    config.read(file)
+    return config
+
+
+@pytest.fixture
+def profile():
+    return 'default'
+
+@pytest.fixture
+def fake_config_file(tmpdir):
+    dir = tmpdir.dirpath(".aws/")
+    file = dir + 'config'
+    if not os.path.exists(dir):
+        os.makedirs(dir)
+    config = configparser.ConfigParser()
+    config['default'] = {'region': 'fake-region-1', 'adfs_netid': 'fake_netid'}
+    with open(file, 'w') as write_file:
+        config.write(write_file)
+    return file
+
+
+def test_open_config_file(aws_config_file):
+    assert index.open_config_file(aws_config_file)
+
+
+def test_aws_file():
+    assert index.aws_file('config')
+
+
+def test_check_for_aws_dir(tmpdir):
+    dir = tmpdir.dirpath(".aws")
+    index.check_for_aws_dir(dir)
+    assert os.path.exists(dir)
+
+
+def test_write_to_cred_file(aws_cred_file, profile):
+    aws_session_token = {'Credentials': {'AccessKeyId': 'keyid', 'SecretAccessKey': 'secretkey', 'SessionToken': 'sessiontoken'}}
+    index.write_to_cred_file(aws_cred_file, aws_session_token, profile)
+    config = read_config_file(aws_cred_file)
+    assert config['default'] == {'aws_access_key_id': 'keyid',
+                                 'aws_secret_access_key': 'secretkey',
+                                 'aws_session_token': 'sessiontoken'
+                                 }
+
+
+def test_write_to_config_file(aws_config_file, profile):
+    net_id = 'fake_netid'
+    region = 'fakeRegion'
+    index.write_to_config_file(aws_config_file, net_id, region, profile)
+    config = read_config_file(aws_config_file)
+    assert config['default'] == {'region': 'fakeRegion', 'adfs_netid': 'fake_netid'}
+
+
+def test_load_last_netid(fake_config_file, profile):
+    assert index.load_last_netid(fake_config_file, profile) == 'fake_netid'
+
+
+@pytest.mark.skip(reason="not sure how to test this yet")
 def test_cli():
-    assert True == True
+    pass