Skip to content

Commit 84692c5

Browse files
committed
Add option to disable IMDS v1 fallback when token is not returned for IMDS credential calls
1 parent e5e9fa8 commit 84692c5

File tree

7 files changed

+351
-193
lines changed

7 files changed

+351
-193
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"type": "feature",
3+
"category": "AWS SDK for Java v2",
4+
"contributor": "",
5+
"description": "Adds setting to disable making EC2 Instance Metadata Service (IMDS) calls for credentials without a token header when prefetching a token does not work. This feature can be configured through environment variables (AWS_EC2_METADATA_V1_DISABLED), system property (aws.disableEc2MetadataV1) or AWS config file (ec2_metadata_v1_disabled). When you configure this setting to true, no calls without token headers will be made to IMDS."
6+
}

core/auth/src/main/java/software/amazon/awssdk/auth/credentials/InstanceProfileCredentialsProvider.java

+32-5
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
import software.amazon.awssdk.profiles.ProfileFile;
4141
import software.amazon.awssdk.profiles.ProfileFileSupplier;
4242
import software.amazon.awssdk.profiles.ProfileFileSystemSetting;
43+
import software.amazon.awssdk.profiles.ProfileProperty;
4344
import software.amazon.awssdk.regions.util.HttpResourcesUtils;
4445
import software.amazon.awssdk.regions.util.ResourcesEndpointProvider;
4546
import software.amazon.awssdk.utils.Logger;
@@ -225,17 +226,15 @@ private String getToken(String imdsHostname) {
225226
return HttpResourcesUtils.instance().readResource(tokenEndpoint, "PUT");
226227
} catch (SdkServiceException e) {
227228
if (e.statusCode() == 400) {
229+
228230
throw SdkClientException.builder()
229231
.message("Unable to fetch metadata token.")
230232
.cause(e)
231233
.build();
232234
}
233-
234-
log.debug(() -> "Ignoring non-fatal exception while attempting to load metadata token from instance profile.", e);
235-
return null;
235+
return handleTokenErrorResponse(e);
236236
} catch (Exception e) {
237-
log.debug(() -> "Ignoring non-fatal exception while attempting to load metadata token from instance profile.", e);
238-
return null;
237+
return handleTokenErrorResponse(e);
239238
}
240239
}
241240

@@ -247,6 +246,34 @@ private URI getTokenEndpoint(String imdsHostname) {
247246
return URI.create(finalHost + TOKEN_RESOURCE);
248247
}
249248

249+
private String handleTokenErrorResponse(Exception e) {
250+
if (isInsecureFallbackDisabled()) {
251+
String message = String.format("Failed to retrieve IMDS token, and fallback to IMDS v1 is disabled via the %s "
252+
+ "environment variable and/or %s system property",
253+
SdkSystemSetting.AWS_EC2_METADATA_V1_DISABLED.environmentVariable(),
254+
SdkSystemSetting.AWS_EC2_METADATA_V1_DISABLED.property());
255+
throw SdkClientException.builder()
256+
.message(message)
257+
.cause(e)
258+
.build();
259+
}
260+
log.debug(() -> "Ignoring non-fatal exception while attempting to load metadata token from instance profile.", e);
261+
return null;
262+
}
263+
264+
private boolean isInsecureFallbackDisabled() {
265+
return SdkSystemSetting.AWS_EC2_METADATA_V1_DISABLED.getBooleanValueOrThrow() ||
266+
(profileFile != null && profileHasFallbackDisabled());
267+
}
268+
269+
private boolean profileHasFallbackDisabled() {
270+
return profileFile.get()
271+
.profile(profileName)
272+
.map(p -> p.properties().get(ProfileProperty.EC2_METADATA_V1_DISABLED))
273+
.map(Boolean::parseBoolean)
274+
.orElse(false);
275+
}
276+
250277
private String[] getSecurityCredentials(String imdsHostname, String metadataToken) {
251278
ResourcesEndpointProvider securityCredentialsEndpoint =
252279
new StaticResourcesEndpointProvider(URI.create(imdsHostname + SECURITY_CREDENTIALS_RESOURCE),

core/auth/src/main/java/software/amazon/awssdk/auth/credentials/internal/ProfileCredentialsUtils.java

+7-6
Original file line numberDiff line numberDiff line change
@@ -264,13 +264,14 @@ private AwsCredentialsProvider credentialSourceCredentialProvider(CredentialSour
264264
case EC2_INSTANCE_METADATA:
265265
// The IMDS credentials provider should source the endpoint config properties from the currently active profile
266266
Ec2MetadataConfigProvider configProvider = Ec2MetadataConfigProvider.builder()
267-
.profileFile(() -> profileFile)
268-
.profileName(name)
269-
.build();
270-
267+
.profileFile(() -> profileFile)
268+
.profileName(name)
269+
.build();
271270
return InstanceProfileCredentialsProvider.builder()
272-
.endpoint(configProvider.getEndpoint())
273-
.build();
271+
.endpoint(configProvider.getEndpoint())
272+
.profileFile(profileFile)
273+
.profileName(name)
274+
.build();
274275
case ENVIRONMENT:
275276
return AwsCredentialsProviderChain.builder()
276277
.addCredentialsProvider(SystemPropertyCredentialsProvider.create())

0 commit comments

Comments
 (0)