3131import software .amazon .awssdk .annotations .SdkPublicApi ;
3232import software .amazon .awssdk .annotations .SdkTestInternalApi ;
3333import software .amazon .awssdk .auth .credentials .internal .Ec2MetadataConfigProvider ;
34+ import software .amazon .awssdk .auth .credentials .internal .Ec2MetadataDisableV1Resolver ;
3435import software .amazon .awssdk .auth .credentials .internal .HttpCredentialsLoader ;
3536import software .amazon .awssdk .auth .credentials .internal .HttpCredentialsLoader .LoadedCredentials ;
3637import software .amazon .awssdk .auth .credentials .internal .StaticResourcesEndpointProvider ;
4041import software .amazon .awssdk .profiles .ProfileFile ;
4142import software .amazon .awssdk .profiles .ProfileFileSupplier ;
4243import software .amazon .awssdk .profiles .ProfileFileSystemSetting ;
44+ import software .amazon .awssdk .profiles .ProfileProperty ;
4345import software .amazon .awssdk .regions .util .HttpResourcesUtils ;
4446import software .amazon .awssdk .regions .util .ResourcesEndpointProvider ;
4547import software .amazon .awssdk .utils .Logger ;
5355
5456/**
5557 * Credentials provider implementation that loads credentials from the Amazon EC2 Instance Metadata Service.
56- *
57- * <P>
58+ * <p>
5859 * If {@link SdkSystemSetting#AWS_EC2_METADATA_DISABLED} is set to true, it will not try to load
5960 * credentials from EC2 metadata service and will return null.
61+ * <p>
62+ * If {@link SdkSystemSetting#AWS_EC2_METADATA_V1_DISABLED} or {@link ProfileProperty#EC2_METADATA_V1_DISABLED}
63+ * is set to true, credentials will only be loaded from EC2 metadata service if a token is successfully retrieved -
64+ * fallback to load credentials without a token will be disabled.
6065 */
6166@ SdkPublicApi
6267public final class InstanceProfileCredentialsProvider
@@ -225,17 +230,15 @@ private String getToken(String imdsHostname) {
225230 return HttpResourcesUtils .instance ().readResource (tokenEndpoint , "PUT" );
226231 } catch (SdkServiceException e ) {
227232 if (e .statusCode () == 400 ) {
233+
228234 throw SdkClientException .builder ()
229235 .message ("Unable to fetch metadata token." )
230236 .cause (e )
231237 .build ();
232238 }
233-
234- log .debug (() -> "Ignoring non-fatal exception while attempting to load metadata token from instance profile." , e );
235- return null ;
239+ return handleTokenErrorResponse (e );
236240 } catch (Exception e ) {
237- log .debug (() -> "Ignoring non-fatal exception while attempting to load metadata token from instance profile." , e );
238- return null ;
241+ return handleTokenErrorResponse (e );
239242 }
240243 }
241244
@@ -247,6 +250,27 @@ private URI getTokenEndpoint(String imdsHostname) {
247250 return URI .create (finalHost + TOKEN_RESOURCE );
248251 }
249252
253+ private String handleTokenErrorResponse (Exception e ) {
254+ if (isInsecureFallbackDisabled ()) {
255+ String message = String .format ("Failed to retrieve IMDS token, and fallback to IMDS v1 is disabled via the "
256+ + "%s system property, %s environment variable, or %s configuration file profile"
257+ + " setting." ,
258+ SdkSystemSetting .AWS_EC2_METADATA_V1_DISABLED .environmentVariable (),
259+ SdkSystemSetting .AWS_EC2_METADATA_V1_DISABLED .property (),
260+ ProfileProperty .EC2_METADATA_V1_DISABLED );
261+ throw SdkClientException .builder ()
262+ .message (message )
263+ .cause (e )
264+ .build ();
265+ }
266+ log .debug (() -> "Ignoring non-fatal exception while attempting to load metadata token from instance profile." , e );
267+ return null ;
268+ }
269+
270+ private boolean isInsecureFallbackDisabled () {
271+ return Ec2MetadataDisableV1Resolver .create (profileFile , profileName ).resolve ();
272+ }
273+
250274 private String [] getSecurityCredentials (String imdsHostname , String metadataToken ) {
251275 ResourcesEndpointProvider securityCredentialsEndpoint =
252276 new StaticResourcesEndpointProvider (URI .create (imdsHostname + SECURITY_CREDENTIALS_RESOURCE ),
0 commit comments