Skip to content

Commit bc3616f

Browse files
committed
Merge branch 'v2' into feature_id_boto2_credentials
2 parents fb13c89 + 82ae9d6 commit bc3616f

File tree

4 files changed

+184
-2
lines changed

4 files changed

+184
-2
lines changed

awscli/botocore/credentials.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1048,7 +1048,9 @@ def load(self):
10481048
if credential_process is None:
10491049
return
10501050

1051+
register_feature_id('CREDENTIALS_PROFILE_PROCESS')
10511052
creds_dict = self._retrieve_credentials_using(credential_process)
1053+
register_feature_id('CREDENTIALS_PROCESS')
10521054
if creds_dict.get('expiry_time') is not None:
10531055
return RefreshableCredentials.create_from_metadata(
10541056
creds_dict,
@@ -2299,6 +2301,7 @@ def _get_credentials(self):
22992301
'accessToken': token,
23002302
}
23012303
try:
2304+
register_feature_ids(self.feature_ids)
23022305
response = client.get_role_credentials(**kwargs)
23032306
except client.exceptions.UnauthorizedException:
23042307
raise UnauthorizedSSOTokenError()
@@ -2354,6 +2357,7 @@ def __init__(
23542357
self._load_config = load_config
23552358
self._client_creator = client_creator
23562359
self._profile_name = profile_name
2360+
self._feature_ids = set()
23572361

23582362
def _load_sso_config(self):
23592363
loaded_config = self._load_config()
@@ -2428,11 +2432,23 @@ def load(self):
24282432
'token_loader': SSOTokenLoader(cache=self._token_cache),
24292433
'cache': self.cache,
24302434
}
2431-
if 'sso_session' in sso_config:
2435+
sso_session_in_config = 'sso_session' in sso_config
2436+
if sso_session_in_config:
24322437
fetcher_kwargs['sso_session_name'] = sso_config['sso_session']
24332438
fetcher_kwargs['token_provider'] = self._token_provider
2439+
self._feature_ids.add('CREDENTIALS_PROFILE_SSO')
2440+
else:
2441+
self._feature_ids.add('CREDENTIALS_PROFILE_SSO_LEGACY')
24342442

24352443
sso_fetcher = SSOCredentialFetcher(**fetcher_kwargs)
2444+
sso_fetcher.feature_ids = self._feature_ids.copy()
2445+
2446+
if sso_session_in_config:
2447+
self._feature_ids.add('CREDENTIALS_SSO')
2448+
else:
2449+
self._feature_ids.add('CREDENTIALS_SSO_LEGACY')
2450+
2451+
register_feature_ids(self._feature_ids)
24362452

24372453
return DeferredRefreshableCredentials(
24382454
method=self.METHOD,

awscli/botocore/useragent.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,13 +78,19 @@
7878
'FLEXIBLE_CHECKSUMS_RES_WHEN_REQUIRED': 'c',
7979
'CREDENTIALS_CODE': 'e',
8080
'CREDENTIALS_ENV_VARS': 'g',
81+
'CREDENTIALS_PROFILE_PROCESS': 'v',
82+
'CREDENTIALS_PROCESS': 'w',
8183
'CREDENTIALS_ENV_VARS_STS_WEB_ID_TOKEN': 'h',
8284
'CREDENTIALS_STS_ASSUME_ROLE': 'i',
8385
'CREDENTIALS_STS_ASSUME_ROLE_WEB_ID': 'k',
8486
'CREDENTIALS_PROFILE': 'n',
8587
'CREDENTIALS_PROFILE_SOURCE_PROFILE': 'o',
8688
'CREDENTIALS_PROFILE_NAMED_PROVIDER': 'p',
8789
'CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN': 'q',
90+
'CREDENTIALS_PROFILE_SSO': 'r',
91+
'CREDENTIALS_SSO': 's',
92+
'CREDENTIALS_PROFILE_SSO_LEGACY': 't',
93+
'CREDENTIALS_SSO_LEGACY': 'u',
8894
'CREDENTIALS_BOTO2_CONFIG_FILE': 'x',
8995
'CREDENTIALS_HTTP': 'z',
9096
'CREDENTIALS_IMDS': '0',

tests/functional/botocore/test_credentials.py

Lines changed: 119 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1183,7 +1183,7 @@ def add_credential_response(self, stubber):
11831183
[],
11841184
'e',
11851185
),
1186-
# Test case 5: Credentials set with Boto2 config
1186+
# Test case 5: Credentials set with Boto2 config
11871187
(
11881188
{},
11891189
{},
@@ -1211,6 +1211,41 @@ def add_credential_response(self, stubber):
12111211
],
12121212
'x',
12131213
),
1214+
# Test case 6: Credentials set via process provider
1215+
(
1216+
{},
1217+
{},
1218+
[
1219+
patch(
1220+
"botocore.credentials.ProcessProvider._retrieve_credentials_using",
1221+
return_value={
1222+
'access_key': "FAKEACCESSKEY",
1223+
'secret_key': "FAKESECRETKEY",
1224+
'token': "FAKETOKEN",
1225+
},
1226+
),
1227+
patch(
1228+
"botocore.credentials.ProcessProvider._credential_process",
1229+
return_value="Mock_credential_process",
1230+
),
1231+
patch(
1232+
"botocore.credentials.ContainerProvider.load",
1233+
return_value=None,
1234+
),
1235+
patch(
1236+
"botocore.credentials.ConfigProvider.load",
1237+
return_value=None,
1238+
),
1239+
patch(
1240+
"botocore.credentials.SharedCredentialProvider.load",
1241+
return_value=None,
1242+
),
1243+
patch(
1244+
"botocore.credentials.EnvProvider.load", return_value=None
1245+
),
1246+
],
1247+
['v', 'w'],
1248+
),
12141249
],
12151250
)
12161251
def test_user_agent_feature_ids(
@@ -1313,6 +1348,89 @@ def _assert_feature_ids_in_ua(client, expected_feature_ids):
13131348
assert expected_id in feature_list
13141349

13151350

1351+
@patch("botocore.credentials.CachedCredentialFetcher._load_from_cache")
1352+
@patch("botocore.credentials.SSOProvider._load_sso_config")
1353+
@patch(
1354+
"botocore.credentials.AssumeRoleWithWebIdentityProvider.load",
1355+
return_value=None,
1356+
)
1357+
@patch("botocore.credentials.AssumeRoleProvider.load", return_value=None)
1358+
@patch("botocore.credentials.EnvProvider.load", return_value=None)
1359+
def test_user_agent_has_sso_legacy_credentials_feature_id(
1360+
_unused_mock_env_load,
1361+
_unused_mock_shared_load,
1362+
_unused_mock_config_load,
1363+
mock_load_sso_config,
1364+
mock_load_sso_credentials,
1365+
monkeypatch,
1366+
patched_session,
1367+
):
1368+
fake_fetcher_kwargs = {
1369+
'sso_start_url': "https://test.awsapps.com/start",
1370+
'sso_region': "us-east-1",
1371+
'sso_role_name': "Administrator",
1372+
'sso_account_id': "1234567890",
1373+
}
1374+
fake_response = {
1375+
"ProviderType": "sso",
1376+
"Credentials": {
1377+
"role_name": "FAKEROLE",
1378+
"AccessKeyId": "FAKEACCESSKEY",
1379+
"SecretAccessKey": "FAKESECRET",
1380+
"SessionToken": "FAKETOKEN",
1381+
"Expiration": "2099-01-01T00:00:00Z",
1382+
},
1383+
}
1384+
1385+
mock_load_sso_config.return_value = fake_fetcher_kwargs
1386+
client_one = patched_session.create_client("s3", region_name="us-east-1")
1387+
mock_load_sso_credentials.return_value = fake_response
1388+
1389+
_assert_feature_ids_in_ua(client_one, ['t', 'u'])
1390+
1391+
1392+
@patch("botocore.credentials.CachedCredentialFetcher._load_from_cache")
1393+
@patch("botocore.credentials.SSOProvider._load_sso_config")
1394+
@patch(
1395+
"botocore.credentials.AssumeRoleWithWebIdentityProvider.load",
1396+
return_value=None,
1397+
)
1398+
@patch("botocore.credentials.AssumeRoleProvider.load", return_value=None)
1399+
@patch("botocore.credentials.EnvProvider.load", return_value=None)
1400+
def test_user_agent_has_sso_credentials_feature_id(
1401+
_unused_mock_env_load,
1402+
_unused_mock_shared_load,
1403+
_unused_mock_config_load,
1404+
mock_load_sso_config,
1405+
mock_load_sso_credentials,
1406+
monkeypatch,
1407+
patched_session,
1408+
):
1409+
fake_fetcher_kwargs = {
1410+
'sso_session': 'sample_test',
1411+
'sso_start_url': "https://test.awsapps.com/start",
1412+
'sso_region': "us-east-1",
1413+
'sso_role_name': "Administrator",
1414+
'sso_account_id': "1234567890",
1415+
}
1416+
fake_response = {
1417+
"ProviderType": "sso",
1418+
"Credentials": {
1419+
"role_name": "FAKEROLE",
1420+
"AccessKeyId": "FAKEACCESSKEY",
1421+
"SecretAccessKey": "FAKESECRET",
1422+
"SessionToken": "FAKETOKEN",
1423+
"Expiration": "2099-01-01T00:00:00Z",
1424+
},
1425+
}
1426+
1427+
mock_load_sso_config.return_value = fake_fetcher_kwargs
1428+
client_one = patched_session.create_client("s3", region_name="us-east-1")
1429+
mock_load_sso_credentials.return_value = fake_response
1430+
1431+
_assert_feature_ids_in_ua(client_one, ['r', 's'])
1432+
1433+
13161434
@pytest.mark.parametrize(
13171435
"config_content,env_vars,expected_source_features,expected_provider_feature",
13181436
[

tests/unit/botocore/test_credentials.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3868,6 +3868,48 @@ def test_expired_legacy_token_has_expected_behavior(self):
38683868
fetcher.fetch_credentials()
38693869
self.assertFalse(mock_client.get_role_credentials.called)
38703870

3871+
@mock.patch('botocore.credentials.register_feature_ids')
3872+
def test_feature_ids_registered_during_get_credentials(
3873+
self, mock_register
3874+
):
3875+
response = {
3876+
'roleCredentials': {
3877+
'accessKeyId': 'foo',
3878+
'secretAccessKey': 'bar',
3879+
'sessionToken': 'baz',
3880+
'expiration': self.now_timestamp + 1000000,
3881+
}
3882+
}
3883+
params = {
3884+
'roleName': self.role_name,
3885+
'accountId': self.account_id,
3886+
'accessToken': self.access_token['accessToken'],
3887+
}
3888+
self.stubber.add_response(
3889+
'get_role_credentials',
3890+
response,
3891+
expected_params=params,
3892+
)
3893+
3894+
self.stubber.activate()
3895+
try:
3896+
fetcher = SSOCredentialFetcher(
3897+
self.start_url,
3898+
self.sso_region,
3899+
self.role_name,
3900+
self.account_id,
3901+
self.mock_session.create_client,
3902+
token_loader=self.loader,
3903+
cache=self.cache,
3904+
time_fetcher=self.mock_time_fetcher,
3905+
)
3906+
test_feature_ids = {'test_feature_1', 'test_feature_2'}
3907+
fetcher.feature_ids = test_feature_ids
3908+
fetcher.fetch_credentials()
3909+
mock_register.assert_called_once_with(test_feature_ids)
3910+
finally:
3911+
self.stubber.deactivate()
3912+
38713913

38723914
class TestSSOProvider(unittest.TestCase):
38733915
def setUp(self):

0 commit comments

Comments
 (0)