Skip to content

Commit bcd343f

Browse files
Todd UnderwoodTodd Underwood
authored andcommitted
Add a --aws-cred-profile flag to allow us to override the aws credential profile the creds will be saved under
1 parent 1d71ca7 commit bcd343f

5 files changed

Lines changed: 97 additions & 2 deletions

File tree

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ A configuration wizard will prompt you to enter the necessary configuration para
210210
- 'internal' for direct interaction with the Okta APIs (`OKTA_API_KEY` environment variable required)
211211
- 'appurl' to set an aws application link url. This setting removes the need of an OKTA API key.
212212
- write_aws_creds - True or False - If True, the AWS credentials will be written to `~/.aws/credentials` otherwise it will be written to stdout.
213-
- cred_profile - If writing to the AWS cred file, this sets the name of the AWS credential profile.
213+
- cred_profile - If writing to the AWS cred file, this sets the name of the AWS credential profile. Can be overridden with the --aws-cred-profile CLI option or the GIMME_AWS_CREDS_CRED_PROFILE environment variable.
214214
- The reserved word `role` will use the name component of the role arn as the profile name. i.e. arn:aws:iam::123456789012:role/okta-1234-role becomes section [okta-1234-role] in the aws credentials file
215215
- The reserved word `acc` will use the account number (or alias if `resolve_aws_alias` is set to y) as the profile name. i.e. arn:aws:iam::123456789012:role/okta-1234-role becomes section [arn:aws:iam::123456789012] or if `resolve_aws_alias` [okta-1234-role] in the aws credentials file.
216216
- The reserved word `acc-role` will use the name component of the role arn prepended with account number (or alias if `resolve_aws_alias` is set to y) to avoid collisions, i.e. arn:aws:iam::123456789012:role/okta-1234-role becomes section [123456789012-okta-1234-role], or if `resolve_aws_alias` [okta-1234-role] in the aws credentials file
@@ -320,7 +320,7 @@ A list of values of to change with environment variables are:
320320
- `AWS_DEFAULT_DURATION` - corresponds to `aws_default_duration` configuration
321321
- `AWS_SHARED_CREDENTIALS_FILE` - file to write credentials to, points to `~/.aws/credentials` by default
322322
- `GIMME_AWS_CREDS_CLIENT_ID` - corresponds to `client_id` configuration
323-
- `GIMME_AWS_CREDS_CRED_PROFILE` - corresponds to `cred_profile` configuration
323+
- `GIMME_AWS_CREDS_CRED_PROFILE` - corresponds to `cred_profile` configuration and `--aws-cred-profile` CLI option
324324
- `GIMME_AWS_CREDS_OUTPUT_FORMAT` - corresponds to `output_format` configuration and `--output-format` CLI option
325325
- `OKTA_AUTH_SERVER` - corresponds to `okta_auth_server` configuration
326326
- `OKTA_DEVICE_TOKEN` - corresponds to `device_token` configuration, can be used in CI

gimme_aws_creds/config.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,11 @@ def get_args(self):
161161
'--force-classic', action='store_true',
162162
help='Force the use of the Okta Classic login process (Okta Identity Engine only)'
163163
)
164+
parser.add_argument(
165+
'--aws-cred-profile',
166+
help="If set, overrides the cred_profile setting from the config file and the "
167+
"GIMME_AWS_CREDS_CRED_PROFILE environment variable."
168+
)
164169
args = parser.parse_args(self.ui.args)
165170

166171
self.action_configure = args.action_configure
@@ -192,6 +197,7 @@ def get_args(self):
192197
self.output_format = args.output_format
193198
if args.roles is not None:
194199
self.roles = [role.strip() for role in args.roles.split(',') if role.strip()]
200+
self.cred_profile = args.aws_cred_profile
195201
self.conf_profile = args.profile or 'DEFAULT'
196202

197203
def _handle_config(self, config, profile_config, include_inherits = True):

gimme_aws_creds/main.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -475,6 +475,9 @@ def generate_config(self):
475475
key = self.envvar_conf_map.get(value, value).lower()
476476
self.conf_dict[key] = self.ui.environ.get(value)
477477

478+
if config.cred_profile is not None:
479+
self.conf_dict['cred_profile'] = config.cred_profile
480+
478481
# AWS Default session duration ....
479482
if self.conf_dict.get('aws_default_duration'):
480483
self.config.aws_default_duration = int(self.conf_dict['aws_default_duration'])

tests/test_config.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ def tearDown(self):
3131
remember_device=False,
3232
output_format=None,
3333
roles=None,
34+
aws_cred_profile=None,
3435
action_register_device=False,
3536
action_configure=False,
3637
action_list_profiles=False,
@@ -47,6 +48,22 @@ def test_get_args_username(self, mock_arg):
4748
self.config.get_args()
4849
self.assertEqual(self.config.username, "ann")
4950

51+
def test_get_args_aws_cred_profile_set(self):
52+
"""Test that --aws-cred-profile is stored on Config when provided"""
53+
test_ui = MockUserInterface(argv=[
54+
'gimme-aws-creds', '--aws-cred-profile', 'my-custom-profile',
55+
])
56+
config = Config(gac_ui=test_ui, create_config=False)
57+
config.get_args()
58+
self.assertEqual(config.cred_profile, "my-custom-profile")
59+
60+
def test_get_args_aws_cred_profile_not_set(self):
61+
"""Test that cred_profile is None on Config when --aws-cred-profile is not provided"""
62+
test_ui = MockUserInterface(argv=['gimme-aws-creds'])
63+
config = Config(gac_ui=test_ui, create_config=False)
64+
config.get_args()
65+
self.assertIsNone(config.cred_profile)
66+
5067
def test_read_config(self):
5168
"""Test to make sure getting config works"""
5269
test_ui = MockUserInterface(argv=[

tests/test_main.py

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1+
import shutil
12
import unittest
23
from unittest.mock import patch
34

45
from gimme_aws_creds import errors
56
from gimme_aws_creds.common import RoleSet
67
from gimme_aws_creds.main import GimmeAWSCreds
8+
from tests.user_interface_mock import MockUserInterface
79

810

911
class TestMain(unittest.TestCase):
@@ -312,3 +314,70 @@ def test_get_profile_name_else(self):
312314
include_path = True
313315
self.assertEqual(creds.get_profile_name(cred_profile, include_path, naming_data, resolve_alias, role),
314316
'foo')
317+
318+
319+
class TestCredProfilePrecedence(unittest.TestCase):
320+
"""Tests for --aws-cred-profile CLI flag precedence over env var and config file.
321+
322+
Expected precedence: CLI flag > env var > config file
323+
"""
324+
325+
CONFIG_TEMPLATE = """[DEFAULT]
326+
client_id = test-client
327+
okta_org_url = https://test.okta.com
328+
cred_profile = {cred_profile}
329+
"""
330+
331+
def setUp(self):
332+
self._temp_dirs = []
333+
334+
def tearDown(self):
335+
for d in self._temp_dirs:
336+
shutil.rmtree(d, ignore_errors=True)
337+
338+
def _build_and_generate(self, argv=None, environ=None, config_cred_profile='file-profile'):
339+
test_ui = MockUserInterface(
340+
argv=argv or [],
341+
environ=environ or {},
342+
)
343+
self._temp_dirs.append(test_ui.HOME)
344+
with open(test_ui.HOME + "/.okta_aws_login_config", "w") as f:
345+
f.write(self.CONFIG_TEMPLATE.format(cred_profile=config_cred_profile))
346+
347+
creds = GimmeAWSCreds(ui=test_ui)
348+
creds.generate_config()
349+
return creds
350+
351+
def test_cli_flag_overrides_config_file(self):
352+
"""--aws-cred-profile should override the cred_profile from config file"""
353+
creds = self._build_and_generate(
354+
argv=['gimme-aws-creds', '--aws-cred-profile', 'cli-profile'],
355+
config_cred_profile='file-profile',
356+
)
357+
self.assertEqual(creds.conf_dict['cred_profile'], 'cli-profile')
358+
359+
def test_cli_flag_overrides_env_var(self):
360+
"""--aws-cred-profile should override GIMME_AWS_CREDS_CRED_PROFILE env var"""
361+
creds = self._build_and_generate(
362+
argv=['gimme-aws-creds', '--aws-cred-profile', 'cli-profile'],
363+
environ={'GIMME_AWS_CREDS_CRED_PROFILE': 'env-profile'},
364+
config_cred_profile='file-profile',
365+
)
366+
self.assertEqual(creds.conf_dict['cred_profile'], 'cli-profile')
367+
368+
def test_env_var_overrides_config_file_when_no_cli_flag(self):
369+
"""Without --aws-cred-profile, GIMME_AWS_CREDS_CRED_PROFILE should override config file"""
370+
creds = self._build_and_generate(
371+
argv=['gimme-aws-creds'],
372+
environ={'GIMME_AWS_CREDS_CRED_PROFILE': 'env-profile'},
373+
config_cred_profile='file-profile',
374+
)
375+
self.assertEqual(creds.conf_dict['cred_profile'], 'env-profile')
376+
377+
def test_config_file_used_when_no_cli_flag_or_env_var(self):
378+
"""Without --aws-cred-profile or env var, config file value should be used"""
379+
creds = self._build_and_generate(
380+
argv=['gimme-aws-creds'],
381+
config_cred_profile='file-profile',
382+
)
383+
self.assertEqual(creds.conf_dict['cred_profile'], 'file-profile')

0 commit comments

Comments
 (0)