@@ -52,16 +52,13 @@ public void testImdsV1() throws IOException {
5252 assertTrue (Strings .hasText (profileName ));
5353
5454 final var credentialsResponse = handleRequest (handler , "GET" , SECURITY_CREDENTIALS_URI + profileName );
55- assertEquals (RestStatus .OK , credentialsResponse .status ());
5655
5756 assertThat (generatedCredentials , aMapWithSize (1 ));
58- final var accessKey = generatedCredentials .keySet ().iterator ().next ();
59- final var sessionToken = generatedCredentials .values ().iterator ().next ();
60-
61- final var responseMap = XContentHelper .convertToMap (XContentType .JSON .xContent (), credentialsResponse .body ().streamInput (), false );
62- assertEquals (Set .of ("AccessKeyId" , "Expiration" , "RoleArn" , "SecretAccessKey" , "Token" ), responseMap .keySet ());
63- assertEquals (accessKey , responseMap .get ("AccessKeyId" ));
64- assertEquals (sessionToken , responseMap .get ("Token" ));
57+ assertValidCredentialsResponse (
58+ credentialsResponse ,
59+ generatedCredentials .keySet ().iterator ().next (),
60+ generatedCredentials .values ().iterator ().next ()
61+ );
6562 }
6663
6764 public void testImdsV2Disabled () {
@@ -78,6 +75,7 @@ public void testImdsV2() throws IOException {
7875
7976 final var tokenResponse = handleRequest (handler , "PUT" , "/latest/api/token" );
8077 assertEquals (RestStatus .OK , tokenResponse .status ());
78+ assertEquals (List .of ("86400" /* seconds in a day */ ), tokenResponse .responseHeaders ().get ("x-aws-ec2-metadata-token-ttl-seconds" ));
8179 final var token = tokenResponse .body ().utf8ToString ();
8280
8381 final var roleResponse = checkImdsV2GetRequest (handler , SECURITY_CREDENTIALS_URI , token );
@@ -86,16 +84,13 @@ public void testImdsV2() throws IOException {
8684 assertTrue (Strings .hasText (profileName ));
8785
8886 final var credentialsResponse = checkImdsV2GetRequest (handler , SECURITY_CREDENTIALS_URI + profileName , token );
89- assertEquals (RestStatus .OK , credentialsResponse .status ());
9087
9188 assertThat (generatedCredentials , aMapWithSize (1 ));
92- final var accessKey = generatedCredentials .keySet ().iterator ().next ();
93- final var sessionToken = generatedCredentials .values ().iterator ().next ();
94-
95- final var responseMap = XContentHelper .convertToMap (XContentType .JSON .xContent (), credentialsResponse .body ().streamInput (), false );
96- assertEquals (Set .of ("AccessKeyId" , "Expiration" , "RoleArn" , "SecretAccessKey" , "Token" ), responseMap .keySet ());
97- assertEquals (accessKey , responseMap .get ("AccessKeyId" ));
98- assertEquals (sessionToken , responseMap .get ("Token" ));
89+ assertValidCredentialsResponse (
90+ credentialsResponse ,
91+ generatedCredentials .keySet ().iterator ().next (),
92+ generatedCredentials .values ().iterator ().next ()
93+ );
9994 }
10095
10196 public void testAvailabilityZone () {
@@ -113,7 +108,54 @@ public void testAvailabilityZone() {
113108 assertEquals (generatedAvailabilityZones , Set .of (availabilityZone ));
114109 }
115110
116- private record TestHttpResponse (RestStatus status , BytesReference body ) {}
111+ public void testAlternativeCredentialsEndpoint () throws IOException {
112+ expectThrows (
113+ IllegalArgumentException .class ,
114+ new Ec2ImdsServiceBuilder (Ec2ImdsVersion .V2 ).alternativeCredentialsEndpoints (Set .of ("/should-not-work" ))::buildHandler
115+ );
116+
117+ final var alternativePaths = randomList (1 , 5 , () -> "/" + randomIdentifier ());
118+ final Map <String , String > generatedCredentials = new HashMap <>();
119+
120+ final var handler = new Ec2ImdsServiceBuilder (Ec2ImdsVersion .V1 ).alternativeCredentialsEndpoints (alternativePaths )
121+ .newCredentialsConsumer (generatedCredentials ::put )
122+ .buildHandler ();
123+
124+ final var credentialsResponse = handleRequest (handler , "GET" , randomFrom (alternativePaths ));
125+
126+ assertThat (generatedCredentials , aMapWithSize (1 ));
127+ assertValidCredentialsResponse (
128+ credentialsResponse ,
129+ generatedCredentials .keySet ().iterator ().next (),
130+ generatedCredentials .values ().iterator ().next ()
131+ );
132+ }
133+
134+ private static void assertValidCredentialsResponse (TestHttpResponse credentialsResponse , String accessKey , String sessionToken )
135+ throws IOException {
136+ assertEquals (RestStatus .OK , credentialsResponse .status ());
137+ final var responseMap = XContentHelper .convertToMap (XContentType .JSON .xContent (), credentialsResponse .body ().streamInput (), false );
138+ assertEquals (Set .of ("AccessKeyId" , "Expiration" , "RoleArn" , "SecretAccessKey" , "Token" ), responseMap .keySet ());
139+ assertEquals (accessKey , responseMap .get ("AccessKeyId" ));
140+ assertEquals (sessionToken , responseMap .get ("Token" ));
141+ }
142+
143+ public void testInstanceIdentityDocument () {
144+ final Set <String > generatedRegions = new HashSet <>();
145+ final var handler = new Ec2ImdsServiceBuilder (Ec2ImdsVersion .V1 ).instanceIdentityDocument ((builder , params ) -> {
146+ final var newRegion = randomIdentifier ();
147+ generatedRegions .add (newRegion );
148+ return builder .field ("region" , newRegion );
149+ }).buildHandler ();
150+
151+ final var instanceIdentityResponse = handleRequest (handler , "GET" , "/latest/dynamic/instance-identity/document" );
152+ assertEquals (RestStatus .OK , instanceIdentityResponse .status ());
153+ final var instanceIdentityString = instanceIdentityResponse .body ().utf8ToString ();
154+
155+ assertEquals (Strings .format ("{\" region\" :\" %s\" }" , generatedRegions .iterator ().next ()), instanceIdentityString );
156+ }
157+
158+ private record TestHttpResponse (RestStatus status , Headers responseHeaders , BytesReference body ) {}
117159
118160 private static TestHttpResponse checkImdsV2GetRequest (Ec2ImdsHttpHandler handler , String uri , String token ) {
119161 final var unauthorizedResponse = handleRequest (handler , "GET" , uri , null );
@@ -145,7 +187,11 @@ private static TestHttpResponse handleRequest(Ec2ImdsHttpHandler handler, String
145187 fail (e );
146188 }
147189 assertNotEquals (0 , httpExchange .getResponseCode ());
148- return new TestHttpResponse (RestStatus .fromCode (httpExchange .getResponseCode ()), httpExchange .getResponseBodyContents ());
190+ return new TestHttpResponse (
191+ RestStatus .fromCode (httpExchange .getResponseCode ()),
192+ httpExchange .getResponseHeaders (),
193+ httpExchange .getResponseBodyContents ()
194+ );
149195 }
150196
151197 private static class TestHttpExchange extends HttpExchange {
0 commit comments