Skip to content

Commit 063313f

Browse files
authored
Set read timeout for fetching IMDSv2 token (#104253)
Use the timeout set by AWS_METADATA_SERVICE_TIMEOUT environment variable both as connect and read timeout analogous to the AWS SDK. See https://docs.aws.amazon.com/sdkref/latest/guide/feature-ec2-instance-metadata.html Resolves #104244
1 parent b52d3c0 commit 063313f

File tree

4 files changed

+34
-2
lines changed

4 files changed

+34
-2
lines changed

docs/changelog/104253.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
pr: 104253
2+
summary: Set read timeout for fetching IMDSv2 token
3+
area: Discovery-Plugins
4+
type: enhancement
5+
issues:
6+
- 104244

plugins/discovery-ec2/build.gradle

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,9 @@ tasks.named("test").configure {
102102
} else {
103103
nonInputProperties.systemProperty 'java.security.policy', "file://${buildDir}/tmp/java.policy"
104104
}
105+
if (BuildParams.random.nextBoolean()) {
106+
env 'AWS_METADATA_SERVICE_TIMEOUT', '1'
107+
}
105108
}
106109

107110
tasks.named("check").configure {

plugins/discovery-ec2/src/main/java/org/elasticsearch/discovery/ec2/AwsEc2Utils.java

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88

99
package org.elasticsearch.discovery.ec2;
1010

11+
import com.amazonaws.SDKGlobalConfiguration;
12+
import com.amazonaws.util.StringUtils;
13+
1114
import org.apache.logging.log4j.LogManager;
1215
import org.apache.logging.log4j.Logger;
1316
import org.elasticsearch.common.Strings;
@@ -24,7 +27,11 @@
2427
class AwsEc2Utils {
2528

2629
private static final Logger logger = LogManager.getLogger(AwsEc2Utils.class);
27-
private static final int CONNECT_TIMEOUT = 2000;
30+
// The timeout can be configured via the AWS_METADATA_SERVICE_TIMEOUT environment variable
31+
private static final int TIMEOUT = Optional.ofNullable(System.getenv(SDKGlobalConfiguration.AWS_METADATA_SERVICE_TIMEOUT_ENV_VAR))
32+
.filter(StringUtils::hasValue)
33+
.map(s -> Integer.parseInt(s) * 1000)
34+
.orElse(2000);
2835
private static final int METADATA_TOKEN_TTL_SECONDS = 10;
2936
static final String X_AWS_EC_2_METADATA_TOKEN = "X-aws-ec2-metadata-token";
3037

@@ -39,7 +46,10 @@ static Optional<String> getMetadataToken(String metadataTokenUrl) {
3946
try {
4047
urlConnection = (HttpURLConnection) new URL(metadataTokenUrl).openConnection();
4148
urlConnection.setRequestMethod("PUT");
42-
urlConnection.setConnectTimeout(CONNECT_TIMEOUT);
49+
// Use both timeout for connect and read timeout analogous to AWS SDK.
50+
// See com.amazonaws.internal.HttpURLConnection#connectToEndpoint
51+
urlConnection.setConnectTimeout(TIMEOUT);
52+
urlConnection.setReadTimeout(TIMEOUT);
4353
urlConnection.setRequestProperty("X-aws-ec2-metadata-token-ttl-seconds", String.valueOf(METADATA_TOKEN_TTL_SECONDS));
4454
} catch (IOException e) {
4555
logger.warn("Unable to access the IMDSv2 URI: " + metadataTokenUrl, e);

plugins/discovery-ec2/src/test/java/org/elasticsearch/discovery/ec2/Ec2DiscoveryPluginTests.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,19 @@ public void testTokenMetadataApiIsMisbehaving() throws Exception {
121121
}
122122
}
123123

124+
public void testTokenMetadataApiDoesNotRespond() throws Exception {
125+
try (var metadataServer = new MetadataServer("/metadata", exchange -> {
126+
assertNull(exchange.getRequestHeaders().getFirst("X-aws-ec2-metadata-token"));
127+
exchange.sendResponseHeaders(200, 0);
128+
exchange.getResponseBody().write("us-east-1c".getBytes(StandardCharsets.UTF_8));
129+
exchange.close();
130+
}, "/latest/api/token", ex -> {
131+
// Intentionally don't close the connection, so the client has to time out
132+
})) {
133+
assertNodeAttributes(Settings.EMPTY, metadataServer.metadataUri(), metadataServer.tokenUri(), "us-east-1c");
134+
}
135+
}
136+
124137
public void testTokenMetadataApiIsNotAvailable() throws Exception {
125138
try (var metadataServer = metadataServerWithoutToken()) {
126139
assertNodeAttributes(Settings.EMPTY, metadataServer.metadataUri(), metadataServer.tokenUri(), "us-east-1c");

0 commit comments

Comments
 (0)