1919import threading
2020import time
2121import uuid
22- from datetime import datetime , timedelta
22+ from datetime import datetime , timedelta , timezone
23+ from unittest .mock import patch
2324
2425import pytest
2526from botocore import UNSIGNED
5152
5253from tests import (
5354 BaseEnvVar ,
55+ ClientHTTPStubber ,
5456 BaseSessionTest ,
5557 IntegerRefresher ,
5658 SessionHTTPStubber ,
6062 temporary_file ,
6163 unittest ,
6264)
65+ from tests .functional .test_useragent import (
66+ get_captured_ua_strings ,
67+ parse_registered_feature_ids ,
68+ )
6369
64- TIME_IN_ONE_HOUR = datetime .utcnow ( ) + timedelta (hours = 1 )
65- TIME_IN_SIX_MONTHS = datetime .utcnow ( ) + timedelta (hours = 4320 )
70+ TIME_IN_ONE_HOUR = datetime .now ( tz = timezone . utc ) + timedelta (hours = 1 )
71+ TIME_IN_SIX_MONTHS = datetime .now ( tz = timezone . utc ) + timedelta (hours = 4320 )
6672
6773
6874class TestCredentialRefreshRaces (unittest .TestCase ):
@@ -1085,3 +1091,91 @@ def add_credential_response(self, stubber):
10851091 }
10861092 }
10871093 stubber .add_response (body = json .dumps (response ).encode ('utf-8' ))
1094+
1095+
1096+ class TestFeatureIdRegistered :
1097+ @patch (
1098+ "botocore.utils.InstanceMetadataFetcher.retrieve_iam_role_credentials"
1099+ )
1100+ @patch ("botocore.credentials.ContainerProvider.load" , return_value = None )
1101+ @patch ("botocore.credentials.ConfigProvider.load" , return_value = None )
1102+ @patch (
1103+ "botocore.credentials.SharedCredentialProvider.load" , return_value = None
1104+ )
1105+ @patch ("botocore.credentials.EnvProvider.load" , return_value = None )
1106+ def test_user_agent_has_imds_credentials_feature_id (
1107+ self ,
1108+ _unused_mock_env_load ,
1109+ _unused_mock_shared_load ,
1110+ _unused_mock_config_load ,
1111+ _unused_mock_container_load ,
1112+ mock_retrieve_iam_role_credentials ,
1113+ patched_session ,
1114+ ):
1115+ fake_creds = {
1116+ "role_name" : "FAKEROLE" ,
1117+ "access_key" : "FAKEACCESSKEY" ,
1118+ "secret_key" : "FAKESECRET" ,
1119+ "token" : "FAKETOKEN" ,
1120+ "expiry_time" : "2099-01-01T00:00:00Z" ,
1121+ }
1122+ mock_retrieve_iam_role_credentials .return_value = fake_creds
1123+
1124+ client = patched_session .create_client ("s3" , region_name = "us-east-1" )
1125+ with ClientHTTPStubber (client , strict = True ) as http_stubber :
1126+ # We want to call this twice to assert that the feature id exists
1127+ # for multiple calls with the same credentials
1128+ http_stubber .add_response ()
1129+ http_stubber .add_response ()
1130+ client .list_buckets ()
1131+ client .list_buckets ()
1132+
1133+ ua_string = get_captured_ua_strings (http_stubber )
1134+ feature_list_one = parse_registered_feature_ids (ua_string [0 ])
1135+ feature_list_two = parse_registered_feature_ids (ua_string [1 ])
1136+ assert '0' in feature_list_one and '0' in feature_list_two
1137+
1138+ @patch ("botocore.credentials.ContainerMetadataFetcher.retrieve_full_uri" )
1139+ @patch ("botocore.credentials.ConfigProvider.load" , return_value = None )
1140+ @patch (
1141+ "botocore.credentials.SharedCredentialProvider.load" , return_value = None
1142+ )
1143+ @patch ("botocore.credentials.EnvProvider.load" , return_value = None )
1144+ def test_user_agent_has_http_credentials_feature_id (
1145+ self ,
1146+ _unused_mock_env_load ,
1147+ _unused_mock_shared_load ,
1148+ _unused_mock_config_load ,
1149+ mock_load_http_credentials ,
1150+ monkeypatch ,
1151+ patched_session ,
1152+ ):
1153+ environ = {
1154+ 'AWS_CONTAINER_CREDENTIALS_FULL_URI' : 'http://localhost/foo' ,
1155+ 'AWS_CONTAINER_AUTHORIZATION_TOKEN' : 'Basic auth-token' ,
1156+ }
1157+ for var in environ :
1158+ monkeypatch .setenv (var , environ [var ])
1159+
1160+ fake_creds = {
1161+ "AccessKeyId" : "FAKEACCESSKEY" ,
1162+ "SecretAccessKey" : "FAKESECRET" ,
1163+ "Token" : "FAKETOKEN" ,
1164+ "Expiration" : "2099-01-01T00:00:00Z" ,
1165+ "AccountId" : "01234567890" ,
1166+ }
1167+ mock_load_http_credentials .return_value = fake_creds
1168+
1169+ client = patched_session .create_client ("s3" , region_name = "us-east-1" )
1170+ with ClientHTTPStubber (client , strict = True ) as http_stubber :
1171+ # We want to call this twice to assert that the feature id exists
1172+ # for multiple calls with the same credentials
1173+ http_stubber .add_response ()
1174+ http_stubber .add_response ()
1175+ client .list_buckets ()
1176+ client .list_buckets ()
1177+
1178+ ua_string = get_captured_ua_strings (http_stubber )
1179+ feature_list_one = parse_registered_feature_ids (ua_string [0 ])
1180+ feature_list_two = parse_registered_feature_ids (ua_string [1 ])
1181+ assert 'z' in feature_list_one and 'z' in feature_list_two
0 commit comments