Skip to content

Commit

Permalink
Add support for configuration opt out for IMDS v1
Browse files Browse the repository at this point in the history
This is a port of this upstream botocore PR:
boto/botocore#3045

Note it does not include the updates to it's IMDS region fetcher
as the AWS CLI v2 codebase has a different implementation. That
implementation will be updated in a subsequent commit.
  • Loading branch information
kyleknap committed Dec 11, 2023
1 parent 7372e14 commit 44214bf
Show file tree
Hide file tree
Showing 5 changed files with 33 additions and 2 deletions.
5 changes: 5 additions & 0 deletions .changes/next-release/enhancement-MetadataFetcher-40786.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"type": "enhancement",
"category": "IMDS",
"description": "Adds a config option to opt out of IMDSv1 fallback"
}
6 changes: 6 additions & 0 deletions awscli/botocore/configprovider.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,12 @@
'ec2_metadata_service_endpoint_mode',
'AWS_EC2_METADATA_SERVICE_ENDPOINT_MODE',
None, None),
'ec2_metadata_v1_disabled': (
'ec2_metadata_v1_disabled',
'AWS_EC2_METADATA_V1_DISABLED',
False,
utils.ensure_boolean,
),
'imds_use_ipv6': (
'imds_use_ipv6',
'AWS_IMDS_USE_IPV6',
Expand Down
3 changes: 3 additions & 0 deletions awscli/botocore/credentials.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,9 @@ def create_credential_resolver(session, cache=None, region_name=None):
'ec2_metadata_service_endpoint_mode': resolve_imds_endpoint_mode(
session),
'ec2_credential_refresh_window': _DEFAULT_ADVISORY_REFRESH_TIMEOUT,
'ec2_metadata_v1_disabled': session.get_config_variable(
'ec2_metadata_v1_disabled'
),
}

if cache is None:
Expand Down
14 changes: 12 additions & 2 deletions awscli/botocore/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -333,8 +333,10 @@ def __init__(self, timeout=DEFAULT_METADATA_SERVICE_TIMEOUT,

if env is None:
env = os.environ.copy()
self._disabled = env.get('AWS_EC2_METADATA_DISABLED', 'false').lower()
self._disabled = self._disabled == 'true'
self._disabled = (
env.get('AWS_EC2_METADATA_DISABLED', 'false').lower() == 'true'
)
self._imds_v1_disabled = config.get('ec2_metadata_v1_disabled')
self._user_agent = user_agent
self._session = botocore.httpsession.URLLib3Session(
timeout=self._timeout,
Expand Down Expand Up @@ -419,6 +421,8 @@ def _get_request(self, url_path, retry_func, token=None):
:param token: Metadata token to send along with GET requests to IMDS.
"""
self._assert_enabled()
if not token:
self._assert_v1_enabled()
if retry_func is None:
retry_func = self._default_retry
url = self._base_url + url_path
Expand Down Expand Up @@ -448,6 +452,12 @@ def _assert_enabled(self):
logger.debug("Access to EC2 metadata has been disabled.")
raise self._RETRIES_EXCEEDED_ERROR_CLS()

def _assert_v1_enabled(self):
if self._imds_v1_disabled:
raise MetadataRetrievalError(
error_msg="Unable to retrieve token for use in IMDSv2 call and IMDSv1 has been disabled"
)

def _default_retry(self, response):
return (
self._is_non_ok_response(response) or
Expand Down
7 changes: 7 additions & 0 deletions tests/unit/botocore/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -2808,6 +2808,13 @@ def test_metadata_token_bad_request_yields_no_credentials(self):
user_agent=user_agent).retrieve_iam_role_credentials()
self.assertEqual(result, {})

def test_v1_disabled_by_config(self):
config = {'ec2_metadata_v1_disabled': True}
self.add_imds_response(b'', status_code=404)
fetcher = InstanceMetadataFetcher(num_attempts=1, config=config)
with self.assertRaises(MetadataRetrievalError):
fetcher.retrieve_iam_role_credentials()

def _get_datetime(
self, dt=None, offset=None, offset_func=operator.add
):
Expand Down

0 comments on commit 44214bf

Please sign in to comment.