diff --git a/.changes/next-release/feature-AWSSDKforJavav2-2f79ee6.json b/.changes/next-release/feature-AWSSDKforJavav2-2f79ee6.json
new file mode 100644
index 000000000000..6a39e27bff87
--- /dev/null
+++ b/.changes/next-release/feature-AWSSDKforJavav2-2f79ee6.json
@@ -0,0 +1,6 @@
+{
+ "type": "feature",
+ "category": "AWS SDK for Java v2",
+ "contributor": "",
+ "description": "Adding 'disable_ec2_metadata' in the profile property, this can be used to disable IMDS credential fetching."
+}
diff --git a/core/auth/src/main/java/software/amazon/awssdk/auth/credentials/InstanceProfileCredentialsProvider.java b/core/auth/src/main/java/software/amazon/awssdk/auth/credentials/InstanceProfileCredentialsProvider.java
index b1ddc5d7faef..32169627bf01 100644
--- a/core/auth/src/main/java/software/amazon/awssdk/auth/credentials/InstanceProfileCredentialsProvider.java
+++ b/core/auth/src/main/java/software/amazon/awssdk/auth/credentials/InstanceProfileCredentialsProvider.java
@@ -55,7 +55,8 @@
/**
* Credentials provider implementation that loads credentials from the Amazon EC2 Instance Metadata Service.
*
- * If {@link SdkSystemSetting#AWS_EC2_METADATA_DISABLED} is set to true, it will not try to load
+ * If {@link SdkSystemSetting#AWS_EC2_METADATA_DISABLED} is set to true, or if the configuration file parameter
+ * {@link ProfileProperty#EC2_METADATA_DISABLED} is set to true, it will not try to load
* credentials from EC2 metadata service and will return null.
*
* If {@link SdkSystemSetting#AWS_EC2_METADATA_V1_DISABLED} or {@link ProfileProperty#EC2_METADATA_V1_DISABLED}
@@ -152,7 +153,8 @@ public AwsCredentials resolveCredentials() {
private RefreshResult refreshCredentials() {
if (isLocalCredentialLoadingDisabled()) {
- throw SdkClientException.create("IMDS credentials have been disabled by environment variable or system property.");
+ throw SdkClientException.create("IMDS credentials have been disabled by environment variable, system property, "
+ + "or configuration file profile setting.");
}
try {
@@ -170,7 +172,7 @@ private RefreshResult refreshCredentials() {
}
private boolean isLocalCredentialLoadingDisabled() {
- return SdkSystemSetting.AWS_EC2_METADATA_DISABLED.getBooleanValueOrThrow();
+ return SdkSystemSetting.AWS_EC2_METADATA_DISABLED.getBooleanValueOrThrow() || configProvider.isMetadataDisabled();
}
private Instant staleTime(Instant expiration) {
diff --git a/core/auth/src/main/java/software/amazon/awssdk/auth/credentials/internal/Ec2MetadataConfigProvider.java b/core/auth/src/main/java/software/amazon/awssdk/auth/credentials/internal/Ec2MetadataConfigProvider.java
index fb73540e75b4..fd9a040f8cb8 100644
--- a/core/auth/src/main/java/software/amazon/awssdk/auth/credentials/internal/Ec2MetadataConfigProvider.java
+++ b/core/auth/src/main/java/software/amazon/awssdk/auth/credentials/internal/Ec2MetadataConfigProvider.java
@@ -45,12 +45,14 @@ public final class Ec2MetadataConfigProvider {
private final String profileName;
private final Lazy metadataV1Disabled;
+ private final Lazy metadataDisabled;
private final Lazy serviceTimeout;
private Ec2MetadataConfigProvider(Builder builder) {
this.profileFile = builder.profileFile;
this.profileName = builder.profileName;
this.metadataV1Disabled = new Lazy<>(this::resolveMetadataV1Disabled);
+ this.metadataDisabled = new Lazy<>(this::resolveMetadataDisabled);
this.serviceTimeout = new Lazy<>(this::resolveServiceTimeout);
}
@@ -120,6 +122,14 @@ public boolean isMetadataV1Disabled() {
return metadataV1Disabled.getValue();
}
+ /**
+ * Resolves whether EC2 Metadata is disabled.
+ * @return true if EC2 Metadata is disabled, false otherwise.
+ */
+ public boolean isMetadataDisabled() {
+ return metadataDisabled.getValue();
+ }
+
/**
* Resolves the EC2 Metadata Service Timeout in milliseconds.
* @return the timeout value in milliseconds.
@@ -137,6 +147,12 @@ private boolean resolveMetadataV1Disabled() {
.orElse(false);
}
+ // Internal resolution logic for Metadata disabled
+ private boolean resolveMetadataDisabled() {
+ return fromProfileFileMetadataDisabled(profileFile, profileName)
+ .orElse(false);
+ }
+
// Internal resolution logic for Service Timeout
private long resolveServiceTimeout() {
return OptionalUtils.firstPresent(
@@ -158,6 +174,15 @@ private static Optional fromProfileFileMetadataV1Disabled(Supplier p.booleanProperty(ProfileProperty.EC2_METADATA_V1_DISABLED));
}
+ // Profile file resolution for Metadata disabled
+ private static Optional fromProfileFileMetadataDisabled(Supplier profileFile, String profileName) {
+ Optional profile = profileFile.get().profile(profileName);
+ if (profile.isPresent()) {
+ return profile.get().booleanProperty(ProfileProperty.EC2_METADATA_DISABLED);
+ }
+ return Optional.empty();
+ }
+
// System settings resolution for Service Timeout
private static Optional fromSystemSettingsServiceTimeout() {
return SdkSystemSetting.AWS_METADATA_SERVICE_TIMEOUT.getNonDefaultStringValue()
diff --git a/core/auth/src/test/java/software/amazon/awssdk/auth/credentials/InstanceProfileCredentialsProviderTest.java b/core/auth/src/test/java/software/amazon/awssdk/auth/credentials/InstanceProfileCredentialsProviderTest.java
index 671e591b17b5..a6b338de69a3 100644
--- a/core/auth/src/test/java/software/amazon/awssdk/auth/credentials/InstanceProfileCredentialsProviderTest.java
+++ b/core/auth/src/test/java/software/amazon/awssdk/auth/credentials/InstanceProfileCredentialsProviderTest.java
@@ -319,12 +319,49 @@ void resolveCredentials_metadataLookupDisabled_throws() {
try {
assertThatThrownBy(() -> InstanceProfileCredentialsProvider.builder().build().resolveCredentials())
.isInstanceOf(SdkClientException.class)
- .hasMessage("IMDS credentials have been disabled by environment variable or system property.");
+ .hasMessage("IMDS credentials have been disabled by environment variable, system property, or configuration file profile setting.");
} finally {
System.clearProperty(SdkSystemSetting.AWS_EC2_METADATA_DISABLED.property());
}
}
+ @Test
+ void resolveCredentials_metadataDisabledThroughConfig_throwsException() {
+ stubSecureCredentialsResponse(aResponse().withBody(STUB_CREDENTIALS));
+ try {
+ InstanceProfileCredentialsProvider.builder()
+ .profileFile(configFile("profile test", Pair.of("disable_ec2_metadata", "true")))
+ .profileName("test")
+ .build()
+ .resolveCredentials();
+ ProfileFile config = configFile("profile test", Pair.of("disable_ec2_metadata", "true"));
+ System.out.println("Test config file: " + config.toString());
+ } catch (Exception e) {
+ assertThat(e).isInstanceOf(SdkClientException.class);
+ assertThat(e).hasMessage("IMDS credentials have been disabled by environment variable, system property, or configuration file profile setting.");
+ }
+
+ // Verify that no calls were made to the IMDS endpoints
+ WireMock.verify(0, putRequestedFor(urlPathEqualTo(TOKEN_RESOURCE_PATH)));
+ WireMock.verify(0, getRequestedFor(urlPathEqualTo(CREDENTIALS_RESOURCE_PATH)));
+ }
+
+ @Test
+ void resolveCredentials_metadataEnabledThroughConfig_returnsCredentials() {
+ stubSecureCredentialsResponse(aResponse().withBody(STUB_CREDENTIALS));
+
+ InstanceProfileCredentialsProvider provider = InstanceProfileCredentialsProvider.builder()
+ .profileFile(configFile("profile test", Pair.of("disable_ec2_metadata", "false")))
+ .profileName("test")
+ .build();
+
+ AwsCredentials credentials = provider.resolveCredentials();
+ assertThat(credentials.accessKeyId()).isEqualTo("ACCESS_KEY_ID");
+ assertThat(credentials.secretAccessKey()).isEqualTo("SECRET_ACCESS_KEY");
+
+ verifyImdsCallWithToken();
+ }
+
@Test
void resolveCredentials_customProfileFileAndName_usesCorrectEndpoint() {
WireMockServer mockMetadataEndpoint_2 = new WireMockServer(WireMockConfiguration.options().dynamicPort());
diff --git a/core/profiles/src/main/java/software/amazon/awssdk/profiles/ProfileProperty.java b/core/profiles/src/main/java/software/amazon/awssdk/profiles/ProfileProperty.java
index cd97c6047a55..fb34cd665847 100644
--- a/core/profiles/src/main/java/software/amazon/awssdk/profiles/ProfileProperty.java
+++ b/core/profiles/src/main/java/software/amazon/awssdk/profiles/ProfileProperty.java
@@ -161,6 +161,12 @@ public final class ProfileProperty {
public static final String EC2_METADATA_V1_DISABLED = "ec2_metadata_v1_disabled";
+ /**
+ * Disables the use of the Amazon EC2 instance metadata service (IMDS). When set to "true", SDK will not try to load
+ * credentials from EC2 metadata service and will return null.
+ */
+ public static final String EC2_METADATA_DISABLED = "disable_ec2_metadata";
+
public static final String METADATA_SERVICE_TIMEOUT = "metadata_service_timeout";
/**