Skip to content

Commit

Permalink
Add IMDSv2 support to AwsCandidateHarvester and replace URLConnection… (
Browse files Browse the repository at this point in the history
#297)

* Add IMDSv2 support to AwsCandidateHarvester and replace URLConnection with HttpRequest
---------

Co-authored-by: Daniil Meitis <[email protected]>
  • Loading branch information
dsmeytis and Daniil Meitis authored Dec 4, 2024
1 parent 26210ef commit 7846e6c
Showing 1 changed file with 69 additions and 20 deletions.
89 changes: 69 additions & 20 deletions src/main/java/org/ice4j/ice/harvest/AwsCandidateHarvester.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,10 @@

import org.ice4j.*;

import java.io.*;
import java.net.*;
import java.net.http.*;
import java.time.*;
import java.util.*;
import java.util.logging.*;

/**
Expand All @@ -39,6 +41,14 @@ public class AwsCandidateHarvester
private static final Logger logger
= Logger.getLogger(AwsCandidateHarvester.class.getName());

/**
* The <tt>HttpClient</tt> used by the <tt>AwsCandidateHarvester</tt>
* class and its instances for making requests to IMDS.
*/
private static final HttpClient httpClient = HttpClient.newBuilder()
.connectTimeout(Duration.ofMillis(500))
.build();

/**
* The URL where one obtains AWS public addresses.
*/
Expand All @@ -52,10 +62,28 @@ public class AwsCandidateHarvester
= "http://169.254.169.254/latest/meta-data/local-ipv4";

/**
* The URL to use to test whether we are running on Amazon EC2.
* The URL to get IMDSv2 API token for further meta-data requests.
*/
private static final String IMDS_API_TOKEN_URL
= "http://169.254.169.254/latest/api/token";

/**
* The HTTP header name to provide session token.
*/
private static final String EC2_TEST_URL
= "http://169.254.169.254/latest/meta-data/";
private static final String EC2_METADATA_TOKEN_HEADER
= "X-aws-ec2-metadata-token";

/**
* The HTTP header name to request session token TTL.
*/
private static final String EC2_METADATA_TOKEN_TTL_HEADER
= "X-aws-ec2-metadata-token-ttl-seconds";

/**
* The default session token TTL value.
*/
private static final String EC2_METADATA_TOKEN_DEFAULT_TTL
= "21600";

/**
* Whether we are running on Amazon EC2.
Expand Down Expand Up @@ -103,8 +131,11 @@ private static synchronized void obtainEC2Addresses()

try
{
localIPStr = fetch(LOCAL_IP_URL);
publicIPStr = fetch(PUBLIC_IP_URL);
String metaDataToken = fetch(IMDS_API_TOKEN_URL,
Collections.singletonMap(EC2_METADATA_TOKEN_TTL_HEADER, EC2_METADATA_TOKEN_DEFAULT_TTL), "PUT");
Map<String, String> tokenHeader = Collections.singletonMap(EC2_METADATA_TOKEN_HEADER, metaDataToken);
localIPStr = fetch(LOCAL_IP_URL, tokenHeader);
publicIPStr = fetch(PUBLIC_IP_URL, tokenHeader);

//now let's cross our fingers and hope that what we got above are
//real IP addresses
Expand Down Expand Up @@ -183,11 +214,10 @@ private static boolean doTestEc2()
{
try
{
URLConnection conn = new URL(EC2_TEST_URL).openConnection();
conn.setConnectTimeout(500); //don't hang for too long
conn.getContent();
String metaDataToken = fetch(IMDS_API_TOKEN_URL,
Collections.singletonMap(EC2_METADATA_TOKEN_TTL_HEADER, EC2_METADATA_TOKEN_DEFAULT_TTL), "PUT");

return true;
return metaDataToken != null;
}
catch(Exception exc)
{
Expand All @@ -201,21 +231,40 @@ private static boolean doTestEc2()
*
* @param url the URL we'd like to open and query.
*
* @param headers the HTTP headers to put into the request.
*
* @throws Exception if anything goes wrong.
*/
private static String fetch(String url, Map<String, String> headers)
throws Exception
{
return fetch(url, headers, "GET");
}

/**
* Retrieves the content at the specified <tt>url</tt>. No more, no less.
*
* @param url the URL we'd like to open and query.
*
* @param headers the HTTP headers to put into the request.
*
* @param method the HTTP method we'd like to use.
*
* @return the String we retrieved from the URL.
*
* @throws Exception if anything goes wrong.
*/
private static String fetch(String url)
private static String fetch(String url, Map<String, String> headers, String method)
throws Exception
{
URLConnection conn = new URL(url).openConnection();
BufferedReader in = new BufferedReader(new InputStreamReader(
conn.getInputStream(), "UTF-8"));

String retString = in.readLine();

in.close();

return retString;
HttpRequest.Builder builder = HttpRequest.newBuilder()
.uri(new URI(url))
.method(method, HttpRequest.BodyPublishers.noBody());
for (Map.Entry<String, String> header : headers.entrySet())
{
builder.setHeader(header.getKey(), header.getValue());
}
HttpResponse<String> response = httpClient.send(builder.build(), HttpResponse.BodyHandlers.ofString());
return response.body();
}
}

0 comments on commit 7846e6c

Please sign in to comment.