Skip to content

Commit 50cab92

Browse files
Assume role feature ids (#9751)
* Track assume-role and profile related credential feature ids * formatting nits/feedback
1 parent f065f5e commit 50cab92

File tree

4 files changed

+390
-48
lines changed

4 files changed

+390
-48
lines changed

awscli/botocore/credentials.py

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
UnknownCredentialError,
4242
)
4343
from botocore.tokens import SSOTokenProvider
44-
from botocore.useragent import register_feature_id
44+
from botocore.useragent import register_feature_id, register_feature_ids
4545
from botocore.utils import (
4646
ArnParser,
4747
ContainerMetadataFetcher,
@@ -701,6 +701,7 @@ def __init__(self, cache=None, expiry_window_seconds=None):
701701
if expiry_window_seconds is None:
702702
expiry_window_seconds = self.DEFAULT_EXPIRY_WINDOW_SECONDS
703703
self._expiry_window_seconds = expiry_window_seconds
704+
self.feature_ids = set()
704705

705706
def _create_cache_key(self):
706707
raise NotImplementedError('_create_cache_key()')
@@ -881,6 +882,7 @@ def __init__(
881882

882883
def _get_credentials(self):
883884
"""Get credentials by calling assume role."""
885+
register_feature_ids(self.feature_ids)
884886
kwargs = self._assume_role_kwargs()
885887
client = self._create_client()
886888
response = client.assume_role(**kwargs)
@@ -967,6 +969,7 @@ def __init__(
967969

968970
def _get_credentials(self):
969971
"""Get credentials by calling assume role."""
972+
register_feature_ids(self.feature_ids)
970973
kwargs = self._assume_role_kwargs()
971974
# Assume role with web identity does not require credentials other than
972975
# the token, explicitly configure the client to not sign requests.
@@ -1362,6 +1365,7 @@ def load(self):
13621365
)
13631366
token = self._get_session_token(config)
13641367
account_id = self._get_account_id(config)
1368+
register_feature_id('CREDENTIALS_PROFILE')
13651369
return Credentials(
13661370
access_key,
13671371
secret_key,
@@ -1429,6 +1433,7 @@ def load(self):
14291433
)
14301434
token = self._get_session_token(profile_config)
14311435
account_id = self._get_account_id(profile_config)
1436+
register_feature_id('CREDENTIALS_PROFILE')
14321437
return Credentials(
14331438
access_key,
14341439
secret_key,
@@ -1507,6 +1512,11 @@ class AssumeRoleProvider(CredentialProvider):
15071512
# remaining time left until the credentials expires is less than the
15081513
# EXPIRY_WINDOW.
15091514
EXPIRY_WINDOW_SECONDS = 60 * 15
1515+
NAMED_PROVIDER_FEATURE_MAP = {
1516+
'Ec2InstanceMetadata': 'CREDENTIALS_IMDS',
1517+
'Environment': 'CREDENTIALS_ENV_VARS',
1518+
'EcsContainer': 'CREDENTIALS_HTTP',
1519+
}
15101520

15111521
def __init__(
15121522
self,
@@ -1569,6 +1579,7 @@ def __init__(
15691579
self._credential_sourcer = credential_sourcer
15701580
self._profile_provider_builder = profile_provider_builder
15711581
self._visited_profiles = [self._profile_name]
1582+
self._feature_ids = set()
15721583

15731584
def load(self):
15741585
self._loaded_config = self._load_config()
@@ -1619,10 +1630,13 @@ def _load_creds_via_assume_role(self, profile_name):
16191630
mfa_prompter=self._prompter,
16201631
cache=self.cache,
16211632
)
1633+
fetcher.feature_ids = self._feature_ids.copy()
16221634
refresher = fetcher.fetch_credentials
16231635
if mfa_serial is not None:
16241636
refresher = create_mfa_serial_refresher(refresher)
16251637

1638+
self._feature_ids.add('CREDENTIALS_STS_ASSUME_ROLE')
1639+
register_feature_ids(self._feature_ids)
16261640
# The initial credentials are empty and the expiration time is set
16271641
# to now so that we can delay the call to assume role until it is
16281642
# strictly needed.
@@ -1750,18 +1764,20 @@ def _has_static_credentials(self, profile):
17501764
def _resolve_source_credentials(self, role_config, profile_name):
17511765
credential_source = role_config.get('credential_source')
17521766
if credential_source is not None:
1767+
self._feature_ids.add('CREDENTIALS_PROFILE_NAMED_PROVIDER')
17531768
return self._resolve_credentials_from_source(
17541769
credential_source, profile_name
17551770
)
17561771

17571772
source_profile = role_config['source_profile']
17581773
self._visited_profiles.append(source_profile)
1774+
self._feature_ids.add('CREDENTIALS_PROFILE_SOURCE_PROFILE')
17591775
return self._resolve_credentials_from_profile(source_profile)
17601776

17611777
def _resolve_credentials_from_profile(self, profile_name):
17621778
profiles = self._loaded_config.get('profiles', {})
17631779
profile = profiles[profile_name]
1764-
1780+
self._feature_ids.add('CREDENTIALS_PROFILE')
17651781
if (
17661782
self._has_static_credentials(profile)
17671783
and not self._profile_provider_builder
@@ -1817,6 +1833,11 @@ def _resolve_credentials_from_source(
18171833
f'in profile {profile_name}'
18181834
),
18191835
)
1836+
named_provider_feature_id = self.NAMED_PROVIDER_FEATURE_MAP.get(
1837+
credential_source
1838+
)
1839+
if named_provider_feature_id:
1840+
self._feature_ids.add(named_provider_feature_id)
18201841
return credentials
18211842

18221843

@@ -1847,6 +1868,7 @@ def __init__(
18471868
if token_loader_cls is None:
18481869
token_loader_cls = FileWebIdentityTokenLoader
18491870
self._token_loader_cls = token_loader_cls
1871+
self._feature_ids = set()
18501872

18511873
def load(self):
18521874
return self._assume_role_with_web_identity()
@@ -1869,8 +1891,15 @@ def _get_env_config(self, key):
18691891
def _get_config(self, key):
18701892
env_value = self._get_env_config(key)
18711893
if env_value is not None:
1894+
self._feature_ids.add('CREDENTIALS_ENV_VARS_STS_WEB_ID_TOKEN')
18721895
return env_value
1873-
return self._get_profile_config(key)
1896+
1897+
config_value = self._get_profile_config(key)
1898+
if config_value is not None:
1899+
self._feature_ids.add('CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN')
1900+
return config_value
1901+
1902+
return None
18741903

18751904
def _assume_role_with_web_identity(self):
18761905
token_path = self._get_config('web_identity_token_file')
@@ -1900,6 +1929,10 @@ def _assume_role_with_web_identity(self):
19001929
extra_args=extra_args,
19011930
cache=self.cache,
19021931
)
1932+
fetcher.feature_ids = self._feature_ids.copy()
1933+
1934+
self._feature_ids.add('CREDENTIALS_STS_ASSUME_ROLE_WEB_ID')
1935+
register_feature_ids(self._feature_ids)
19031936
# The initial credentials are empty and the expiration time is set
19041937
# to now so that we can delay the call to assume role until it is
19051938
# strictly needed.

awscli/botocore/useragent.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,13 @@
7878
'FLEXIBLE_CHECKSUMS_RES_WHEN_REQUIRED': 'c',
7979
'CREDENTIALS_CODE': 'e',
8080
'CREDENTIALS_ENV_VARS': 'g',
81+
'CREDENTIALS_ENV_VARS_STS_WEB_ID_TOKEN': 'h',
82+
'CREDENTIALS_STS_ASSUME_ROLE': 'i',
83+
'CREDENTIALS_STS_ASSUME_ROLE_WEB_ID': 'k',
84+
'CREDENTIALS_PROFILE': 'n',
85+
'CREDENTIALS_PROFILE_SOURCE_PROFILE': 'o',
86+
'CREDENTIALS_PROFILE_NAMED_PROVIDER': 'p',
87+
'CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN': 'q',
8188
'CREDENTIALS_HTTP': 'z',
8289
'CREDENTIALS_IMDS': '0',
8390
'BEARER_SERVICE_ENV_VARS': '3',
@@ -86,6 +93,7 @@
8693

8794
def register_feature_id(feature_id):
8895
"""Adds metric value to the current context object's ``features`` set.
96+
8997
:type feature_id: str
9098
:param feature_id: The name of the feature to register. Value must be a key
9199
in the ``_USERAGENT_FEATURE_MAPPINGS`` dict.
@@ -102,6 +110,16 @@ def register_feature_id(feature_id):
102110
ctx.features.add(val)
103111

104112

113+
def register_feature_ids(feature_ids):
114+
"""Adds multiple feature IDs to the current context object's ``features`` set.
115+
:type feature_ids: iterable of str
116+
:param feature_ids: An iterable of feature ID strings to register. Each
117+
value must be a key in the ``_USERAGENT_FEATURE_MAPPINGS`` dict.
118+
"""
119+
for feature_id in feature_ids:
120+
register_feature_id(feature_id)
121+
122+
105123
def sanitize_user_agent_string_component(raw_str, allow_hash):
106124
"""Replaces all not allowed characters in the string with a dash ("-").
107125

0 commit comments

Comments
 (0)