Skip to content

Commit 4a00860

Browse files
committed
Address PR feedback
1 parent 583fff5 commit 4a00860

3 files changed

Lines changed: 153 additions & 134 deletions

File tree

core/auth/src/it/java/software/amazon/awssdk/auth/credentials/ImdsUserAgentIntegrationTest.java

Lines changed: 0 additions & 133 deletions
This file was deleted.

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ public SdkRequest modifyRequest(Context.ModifyRequest context, ExecutionAttribut
4545

4646
private boolean isImdsCredentials(AwsCredentials credentials) {
4747
return credentials.providerName()
48-
.map(name -> name.contains("InstanceProfile"))
48+
.map(name -> name.contains("InstanceProfileCredentialsProvider"))
4949
.orElse(false);
5050
}
5151
}
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License").
5+
* You may not use this file except in compliance with the License.
6+
* A copy of the License is located at
7+
*
8+
* http://aws.amazon.com/apache2.0
9+
*
10+
* or in the "license" file accompanying this file. This file is distributed
11+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12+
* express or implied. See the License for the specific language governing
13+
* permissions and limitations under the License.
14+
*/
15+
16+
package software.amazon.awssdk.auth.source;
17+
18+
import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
19+
import static com.github.tomakehurst.wiremock.client.WireMock.get;
20+
import static com.github.tomakehurst.wiremock.client.WireMock.put;
21+
import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo;
22+
import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig;
23+
import static org.assertj.core.api.Assertions.assertThat;
24+
25+
import com.github.tomakehurst.wiremock.junit5.WireMockExtension;
26+
import com.github.tomakehurst.wiremock.junit5.WireMockTest;
27+
import java.io.UnsupportedEncodingException;
28+
import java.time.Duration;
29+
import java.time.Instant;
30+
import java.util.List;
31+
import java.util.stream.Stream;
32+
import org.junit.jupiter.api.AfterAll;
33+
import org.junit.jupiter.api.BeforeEach;
34+
import org.junit.jupiter.api.extension.RegisterExtension;
35+
import org.junit.jupiter.params.ParameterizedTest;
36+
import org.junit.jupiter.params.provider.Arguments;
37+
import org.junit.jupiter.params.provider.MethodSource;
38+
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
39+
import software.amazon.awssdk.auth.credentials.AwsCredentials;
40+
import software.amazon.awssdk.auth.credentials.InstanceProfileCredentialsProvider;
41+
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
42+
import software.amazon.awssdk.core.SdkSystemSetting;
43+
import software.amazon.awssdk.http.AbortableInputStream;
44+
import software.amazon.awssdk.http.HttpExecuteResponse;
45+
import software.amazon.awssdk.http.SdkHttpClient;
46+
import software.amazon.awssdk.http.SdkHttpRequest;
47+
import software.amazon.awssdk.http.SdkHttpResponse;
48+
import software.amazon.awssdk.identity.spi.AwsCredentialsIdentity;
49+
import software.amazon.awssdk.identity.spi.IdentityProvider;
50+
import software.amazon.awssdk.services.sts.StsClient;
51+
import software.amazon.awssdk.testutils.service.http.MockSyncHttpClient;
52+
import software.amazon.awssdk.utils.DateUtils;
53+
import software.amazon.awssdk.utils.StringInputStream;
54+
55+
@WireMockTest
56+
class ImdsCredentialsUserAgentTest {
57+
private static final String TOKEN_RESOURCE_PATH = "/latest/api/token";
58+
private static final String CREDENTIALS_RESOURCE_PATH = "/latest/meta-data/iam/security-credentials/";
59+
private static final String PROFILE_NAME = "some-profile";
60+
private static final String TOKEN_STUB = "some-token";
61+
62+
private static final String STUB_CREDENTIALS = "{\"AccessKeyId\":\"ACCESS_KEY_ID\",\"SecretAccessKey\":\"SECRET_ACCESS_KEY\","
63+
+ "\"Expiration\":\"" + DateUtils.formatIso8601Date(Instant.now().plus(Duration.ofDays(1)))
64+
+ "\"}";
65+
66+
private static final AwsCredentials BASIC_IDENTITY = basicCredentialsBuilder().build();
67+
68+
@RegisterExtension
69+
static WireMockExtension wireMockServer = WireMockExtension.newInstance()
70+
.options(wireMockConfig().dynamicPort().dynamicPort())
71+
.configureStaticDsl(true)
72+
.build();
73+
74+
private MockSyncHttpClient mockHttpClient;
75+
76+
@BeforeEach
77+
public void setup() throws UnsupportedEncodingException {
78+
System.setProperty(SdkSystemSetting.AWS_EC2_METADATA_SERVICE_ENDPOINT.property(),
79+
"http://localhost:" + wireMockServer.getPort());
80+
81+
stubSecureCredentialsResponse();
82+
83+
mockHttpClient = new MockSyncHttpClient();
84+
mockHttpClient.stubNextResponse(mockResponse());
85+
}
86+
87+
@AfterAll
88+
public static void teardown() {
89+
System.clearProperty(SdkSystemSetting.AWS_EC2_METADATA_SERVICE_ENDPOINT.property());
90+
}
91+
92+
public static HttpExecuteResponse mockResponse() {
93+
return HttpExecuteResponse.builder()
94+
.response(SdkHttpResponse.builder().statusCode(200).build())
95+
.responseBody(AbortableInputStream.create(new StringInputStream("")))
96+
.build();
97+
}
98+
99+
@ParameterizedTest
100+
@MethodSource("credentialProviders")
101+
void userAgentString_containsCredentialProviderNames_IfPresent(IdentityProvider<? extends AwsCredentialsIdentity> provider,
102+
String expected) throws Exception {
103+
stsClient(provider, mockHttpClient).getCallerIdentity();
104+
105+
SdkHttpRequest lastRequest = mockHttpClient.getLastRequest();
106+
assertThat(lastRequest).isNotNull();
107+
108+
List<String> userAgentHeaders = lastRequest.headers().get("User-Agent");
109+
assertThat(userAgentHeaders).isNotNull().hasSize(1);
110+
111+
String userAgent = userAgentHeaders.get(0);
112+
113+
if ("m/0".equals(expected)) {
114+
assertThat(userAgent).matches(".*m/[^\\s]*0[^\\s]*.*");
115+
} else {
116+
assertThat(userAgent).contains(expected);
117+
}
118+
}
119+
120+
private static Stream<Arguments> credentialProviders() {
121+
return Stream.of(
122+
Arguments.of(createRealImdsCredentialsProvider(), "m/0"),
123+
Arguments.of(StaticCredentialsProvider.create(BASIC_IDENTITY), "stat")
124+
);
125+
}
126+
127+
/**
128+
* Creates a InstanceProfileCredentialsProvider that uses mocked IMDS endpoints.
129+
*/
130+
private static InstanceProfileCredentialsProvider createRealImdsCredentialsProvider() {
131+
return InstanceProfileCredentialsProvider.builder().build();
132+
}
133+
134+
private static void stubSecureCredentialsResponse() {
135+
wireMockServer.stubFor(put(urlPathEqualTo(TOKEN_RESOURCE_PATH)).willReturn(aResponse().withBody(TOKEN_STUB)));
136+
wireMockServer.stubFor(get(urlPathEqualTo(CREDENTIALS_RESOURCE_PATH)).willReturn(aResponse().withBody(PROFILE_NAME)));
137+
wireMockServer.stubFor(get(urlPathEqualTo(CREDENTIALS_RESOURCE_PATH + PROFILE_NAME)).willReturn(aResponse().withBody(STUB_CREDENTIALS)));
138+
}
139+
140+
private static StsClient stsClient(IdentityProvider<? extends AwsCredentialsIdentity> provider, SdkHttpClient httpClient) {
141+
return StsClient.builder()
142+
.credentialsProvider(provider)
143+
.httpClient(httpClient)
144+
.build();
145+
}
146+
147+
private static AwsBasicCredentials.Builder basicCredentialsBuilder() {
148+
return AwsBasicCredentials.builder()
149+
.accessKeyId("akid")
150+
.secretAccessKey("secret");
151+
}
152+
}

0 commit comments

Comments
 (0)