class TestConfig(unittest.TestCase): """Class to test Config Class. Mock is used to mock external calls""" def setUp(self): """Set up for the unit tests""" self.config = Config(ui=ui.cli) def tearDown(self): """Run Clean Up""" self.config.clean_up() @patch( "argparse.ArgumentParser.parse_args", return_value=argparse.Namespace( username="******", profile=None, insecure=False, resolve=None, mfa_code=None, remember_device=False, output_format=None, roles=None, action_register_device=False, action_configure=False, action_list_profiles=False, action_list_roles=False, action_store_json_creds=False, ), ) def test_get_args_username(self, mock_arg): """Test to make sure username gets returned""" self.config.get_args() assert_equals(self.config.username, "ann")
class TestConfig(unittest.TestCase): """Class to test Config Class. Mock is used to mock external calls""" def setUp(self): """Set up for the unit tests""" self.config = Config() def tearDown(self): """Run Clean Up""" self.config.clean_up() @patch('argparse.ArgumentParser.parse_args', return_value=argparse.Namespace(username='******', configure=False, profile=None, insecure=False, resolve=None, mfa_code=None, register_device=False)) def test_get_args_username(self, mock_arg): """Test to make sure username gets returned""" self.config.get_args() assert_equals(self.config.username, 'ann')
def run(self): """ Pulling it all together to make the CLI """ config = Config() config.get_args() # Create/Update config when configure arg set if config.configure is True: config.update_config_file() exit() # get the config dict conf_dict = config.get_config_dict() if not conf_dict.get('okta_org_url'): print( 'No Okta organization URL in configuration. Try running --config again.' ) exit(1) if not conf_dict.get('gimme_creds_server'): print( 'No Gimme-Creds server URL in configuration. Try running --config again.' ) exit(1) okta = OktaClient(conf_dict['okta_org_url'], config.verify_ssl_certs) if config.resolve == True: self.resolver = AwsResolver(config.verify_ssl_certs) else: if conf_dict.get('resolve_aws_alias') and str( conf_dict['resolve_aws_alias']) == 'True': self.resolver = AwsResolver(config.verify_ssl_certs) if config.username is not None: okta.set_username(config.username) else: if conf_dict.get('okta_username'): okta.set_username(conf_dict['okta_username']) if conf_dict.get('preferred_mfa_type'): okta.set_preferred_mfa_type(conf_dict['preferred_mfa_type']) if config.mfa_code is not None: okta.set_mfa_code(config.mfa_code) # AWS Default session duration .... if conf_dict.get('aws_default_duration'): config.aws_default_duration = int( conf_dict['aws_default_duration']) else: config.aws_default_duration = 3600 # Call the Okta APIs and proces data locally if conf_dict.get('gimme_creds_server') == 'internal': # Okta API key is required when calling Okta APIs internally if config.api_key is None: print('OKTA_API_KEY environment variable not found!') exit(1) # Authenticate with Okta auth_result = okta.auth_session() print("Authentication Success! Getting AWS Accounts") aws_results = self._get_aws_account_info(conf_dict['okta_org_url'], config.api_key, auth_result['username']) elif conf_dict.get('gimme_creds_server') == 'appurl': # bypass lambda & API call # Apps url is required when calling with appurl if conf_dict.get('app_url'): config.app_url = conf_dict['app_url'] if config.app_url is None: print('app_url is not defined in your config !') exit(1) # Authenticate with Okta auth_result = okta.auth_session() print("Authentication Success! Getting AWS Accounts") # build app list aws_results = [] newAppEntry = {} newAppEntry['id'] = "fakeid" # not used anyway newAppEntry['name'] = "fakelabel" #not used anyway newAppEntry['links'] = {} newAppEntry['links']['appLink'] = config.app_url aws_results.append(newAppEntry) # Use the gimme_creds_lambda service else: if not conf_dict.get('client_id'): print( 'No OAuth Client ID in configuration. Try running --config again.' ) if not conf_dict.get('okta_auth_server'): print( 'No OAuth Authorization server in configuration. Try running --config again.' ) # Authenticate with Okta and get an OAuth access token okta.auth_oauth(conf_dict['client_id'], authorization_server=conf_dict['okta_auth_server'], access_token=True, id_token=False, scopes=['openid']) # Add Access Tokens to Okta-protected requests okta.use_oauth_access_token(True) print("Authentication Success! Calling Gimme-Creds Server...") aws_results = self._call_gimme_creds_server( okta, conf_dict['gimme_creds_server']) aws_app = self._get_selected_app(conf_dict.get('aws_appname'), aws_results) saml_data = okta.get_saml_response(aws_app['links']['appLink']) # aws_signin_page = aws_signin.get_signinpage(saml_data['SAMLResponse']) roles = self.resolver._enumerate_saml_roles(saml_data['SAMLResponse'], saml_data['TargetUrl']) aws_role = self._get_selected_role(conf_dict.get('aws_rolename'), roles) aws_partition = self._get_partition_from_saml_acs( saml_data['TargetUrl']) for _, role in enumerate(roles): # Skip irrelevant roles if aws_role != 'all' and aws_role not in role.role: continue try: aws_creds = self._get_sts_creds(aws_partition, saml_data['SAMLResponse'], role.idp, role.role, config.aws_default_duration) except ClientError as ex: if ex.response['Error'][ 'Message'] == 'The requested DurationSeconds exceeds the MaxSessionDuration set for this role.': print( "The requested session duration was too long for this role. Falling back to 1 hour." ) aws_creds = self._get_sts_creds(aws_partition, saml_data['SAMLResponse'], role.idp, role.role, 3600) deriv_profname = re.sub('arn:aws:iam:.*/', '', role.role) # check if write_aws_creds is true if so # get the profile name and write out the file if str(conf_dict['write_aws_creds']) == 'True': # set the profile name # Note if there are multiple roles, and 'default' is # selected it will be overwritten multiple times and last role # wins. if conf_dict['cred_profile'].lower() == 'default': profile_name = 'default' elif conf_dict['cred_profile'].lower() == 'role': profile_name = deriv_profname else: profile_name = conf_dict['cred_profile'] # Write out the AWS Config file print('writing role {} to {}'.format(role.role, self.AWS_CONFIG)) self._write_aws_creds(profile_name, aws_creds['AccessKeyId'], aws_creds['SecretAccessKey'], aws_creds['SessionToken']) else: #Print out temporary AWS credentials. Credentials are printed to stderr to simplify #redirection for use in automated scripts print("export AWS_ACCESS_KEY_ID=" + aws_creds['AccessKeyId'], file=sys.stderr) print("export AWS_SECRET_ACCESS_KEY=" + aws_creds['SecretAccessKey'], file=sys.stderr) print("export AWS_SESSION_TOKEN=" + aws_creds['SessionToken'], file=sys.stderr) print("export AWS_SECURITY_TOKEN=" + aws_creds['SessionToken'], file=sys.stderr) config.clean_up()
def run(self): """ Pulling it all together to make the CLI """ config = Config() config.get_args() # Create/Update config when configure arg set if config.configure is True: config.update_config_file() exit() # get the config dict conf_dict = config.get_config_dict() if not conf_dict.get('okta_org_url'): print( 'No Okta organization URL in configuration. Try running --config again.' ) exit(1) if not conf_dict.get('gimme_creds_server'): print( 'No Gimme-Creds server URL in configuration. Try running --config again.' ) exit(1) okta = OktaClient(conf_dict['okta_org_url'], config.verify_ssl_certs) if config.username is not None: okta.set_username(config.username) else: if conf_dict.get('okta_username'): okta.set_username(conf_dict['okta_username']) # Call the Okta APIs and proces data locally if conf_dict.get('gimme_creds_server') == 'internal': # Okta API key is required when calling Okta APIs internally if config.api_key is None: print('OKTA_API_KEY environment variable not found!') exit(1) # Authenticate with Okta auth_result = okta.auth_session() print("Authentication Success! Getting AWS Accounts") aws_results = self._get_aws_account_info(conf_dict['okta_org_url'], config.api_key, auth_result['username']) # Use the gimme_creds_lambda service else: if not conf_dict.get('client_id'): print( 'No OAuth Client ID in configuration. Try running --config again.' ) if not conf_dict.get('okta_auth_server'): print( 'No OAuth Authorization server in configuration. Try running --config again.' ) # Authenticate with Okta and get an OAuth access token okta.auth_oauth(conf_dict['client_id'], authorization_server=conf_dict['okta_auth_server'], access_token=True, id_token=False, scopes=['openid']) # Add Access Tokens to Okta-protected requests okta.use_oauth_access_token(True) print("Authentication Success! Calling Gimme-Creds Server...") aws_results = self._call_gimme_creds_server( okta, conf_dict['gimme_creds_server']) aws_app = self._get_selected_app(conf_dict.get('aws_appname'), aws_results) saml_data = okta.get_saml_response(aws_app['links']['appLink']) roles = self._enumerate_saml_roles(saml_data['SAMLResponse']) aws_role = self._get_selected_role(conf_dict.get('aws_rolename'), roles) aws_partition = self._get_partition_from_saml_acs( saml_data['TargetUrl']) for _, role in enumerate(roles): # Skip irrelevant roles if aws_role != 'all' and aws_role not in role.role: continue aws_creds = self._get_sts_creds(aws_partition, saml_data['SAMLResponse'], role.idp, role.role) deriv_profname = re.sub('arn:aws:iam:.*/', '', role.role) # check if write_aws_creds is true if so # get the profile name and write out the file if str(conf_dict['write_aws_creds']) == 'True': # set the profile name # Note if there are multiple roles, and 'default' is # selected it will be overwritten multiple times and last role # wins. if conf_dict['cred_profile'].lower() == 'default': profile_name = 'default' elif conf_dict['cred_profile'].lower() == 'role': profile_name = deriv_profname else: profile_name = conf_dict['cred_profile'] # Write out the AWS Config file print('writing role {} to {}'.format(role.role, self.AWS_CONFIG)) self._write_aws_creds(profile_name, aws_creds['AccessKeyId'], aws_creds['SecretAccessKey'], aws_creds['SessionToken']) else: #Print out temporary AWS credentials. Credentials are printed to stderr to simplify #redirection for use in automated scripts print("export AWS_ACCESS_KEY_ID=" + aws_creds['AccessKeyId'], file=sys.stderr) print("export AWS_SECRET_ACCESS_KEY=" + aws_creds['SecretAccessKey'], file=sys.stderr) print("export AWS_SESSION_TOKEN=" + aws_creds['SessionToken'], file=sys.stderr) config.clean_up()
class TestConfig(unittest.TestCase): """Class to test Config Class. Mock is used to mock external calls""" def setUp(self): """Set up for the unit tests""" self.config = Config(gac_ui=ui.cli, create_config=False) def tearDown(self): """Run Clean Up""" self.config.clean_up() @patch( "argparse.ArgumentParser.parse_args", return_value=argparse.Namespace( username="******", profile=None, insecure=False, resolve=None, mfa_code=None, remember_device=False, output_format=None, roles=None, action_register_device=False, action_configure=False, action_list_profiles=False, action_list_roles=False, action_store_json_creds=False, ), ) def test_get_args_username(self, mock_arg): """Test to make sure username gets returned""" self.config.get_args() assert_equals(self.config.username, "ann") def test_read_config(self): """Test to make sure getting config works""" test_ui = MockUserInterface(argv=[ "--profile", "myprofile", ]) with open(test_ui.HOME + "/.okta_aws_login_config", "w") as config_file: config_file.write(""" [myprofile] client_id = foo """) config = Config(gac_ui=test_ui, create_config=False) config.conf_profile = "myprofile" profile_config = config.get_config_dict() self.assertEqual(profile_config, {"client_id": "foo"}) def test_read_config_inherited(self): """Test to make sure getting config works when inherited""" test_ui = MockUserInterface(argv=[ "--profile", "myprofile", ]) with open(test_ui.HOME + "/.okta_aws_login_config", "w") as config_file: config_file.write(""" [mybase] client_id = bar aws_appname = baz [myprofile] inherits = mybase client_id = foo aws_rolename = myrole """) config = Config(gac_ui=test_ui, create_config=False) config.conf_profile = "myprofile" profile_config = config.get_config_dict() self.assertEqual(profile_config, { "client_id": "foo", "aws_appname": "baz", "aws_rolename": "myrole", }) def test_read_nested_config_inherited(self): """Test to make sure getting config works when inherited""" test_ui = MockUserInterface(argv=[ "--profile", "myprofile", ]) with open(test_ui.HOME + "/.okta_aws_login_config", "w") as config_file: config_file.write(""" [mybase-level1] client_id = bar [mybase-level2] inherits = mybase-level1 aws_appname = baz [myprofile] inherits = mybase-level2 client_id = foo aws_rolename = myrole """) config = Config(gac_ui=test_ui, create_config=False) config.conf_profile = "myprofile" profile_config = config.get_config_dict() self.assertEqual(profile_config, { "client_id": "foo", "aws_appname": "baz", "aws_rolename": "myrole", })