Skip to content

Commit 31fe461

Browse files
authored
fix: Validate url domain for aws metadata urls (#1079)
* fix: Validate url domain for aws metadata urls * fix external account tests * static method and split tests * rename param:
1 parent eafb051 commit 31fe461

File tree

4 files changed

+78
-12
lines changed

4 files changed

+78
-12
lines changed

oauth2_http/java/com/google/auth/oauth2/AwsCredentials.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@
4343
import com.google.common.annotations.VisibleForTesting;
4444
import java.io.IOException;
4545
import java.io.UnsupportedEncodingException;
46+
import java.net.MalformedURLException;
47+
import java.net.URL;
4648
import java.net.URLEncoder;
4749
import java.util.ArrayList;
4850
import java.util.Collection;
@@ -125,6 +127,29 @@ static class AwsCredentialSource extends CredentialSource {
125127
} else {
126128
this.imdsv2SessionTokenUrl = null;
127129
}
130+
131+
this.validateMetadataServerUrls();
132+
}
133+
134+
private void validateMetadataServerUrls() {
135+
validateMetadataServerUrlIfAny(this.regionUrl, "region_url");
136+
validateMetadataServerUrlIfAny(this.url, "url");
137+
validateMetadataServerUrlIfAny(this.imdsv2SessionTokenUrl, "imdsv2_session_token_url");
138+
}
139+
140+
private static void validateMetadataServerUrlIfAny(String urlString, String nameInConfig) {
141+
if (urlString != null) {
142+
try {
143+
URL url = new URL(urlString);
144+
String host = url.getHost();
145+
if (!host.equals("169.254.169.254") && !host.equals("[fd00:ec2::254]")) {
146+
throw new IllegalArgumentException(
147+
String.format("Invalid host %s for %s.", host, nameInConfig));
148+
}
149+
} catch (MalformedURLException malformedURLException) {
150+
throw new IllegalArgumentException(malformedURLException);
151+
}
152+
}
128153
}
129154
}
130155

oauth2_http/javatests/com/google/auth/oauth2/AwsCredentialsTest.java

Lines changed: 48 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import static org.junit.Assert.assertEquals;
3535
import static org.junit.Assert.assertNotNull;
3636
import static org.junit.Assert.assertNull;
37+
import static org.junit.Assert.assertThrows;
3738
import static org.junit.Assert.assertTrue;
3839
import static org.junit.Assert.fail;
3940

@@ -53,6 +54,7 @@
5354
import java.util.List;
5455
import java.util.Map;
5556
import org.junit.Test;
57+
import org.junit.function.ThrowingRunnable;
5658
import org.junit.runner.RunWith;
5759
import org.junit.runners.JUnit4;
5860

@@ -61,11 +63,10 @@
6163
public class AwsCredentialsTest {
6264

6365
private static final String STS_URL = "https://sts.googleapis.com";
64-
private static final String AWS_CREDENTIALS_URL = "https://www.aws-credentials.com";
65-
private static final String AWS_CREDENTIALS_URL_WITH_ROLE =
66-
"https://www.aws-credentials.com/roleName";
67-
private static final String AWS_REGION_URL = "https://www.aws-region.com";
68-
private static final String AWS_IMDSV2_SESSION_TOKEN_URL = "https://www.aws-session-token.com";
66+
private static final String AWS_CREDENTIALS_URL = "https://169.254.169.254";
67+
private static final String AWS_CREDENTIALS_URL_WITH_ROLE = "https://169.254.169.254/roleName";
68+
private static final String AWS_REGION_URL = "https://169.254.169.254/region";
69+
private static final String AWS_IMDSV2_SESSION_TOKEN_URL = "https://169.254.169.254/imdsv2";
6970
private static final String AWS_IMDSV2_SESSION_TOKEN = "sessiontoken";
7071

7172
private static final String GET_CALLER_IDENTITY_URL =
@@ -78,8 +79,8 @@ public class AwsCredentialsTest {
7879
new HashMap<String, Object>() {
7980
{
8081
put("environment_id", "aws1");
81-
put("region_url", "regionUrl");
82-
put("url", "url");
82+
put("region_url", AWS_REGION_URL);
83+
put("url", AWS_CREDENTIALS_URL);
8384
put("regional_cred_verification_url", "regionalCredVerificationUrl");
8485
}
8586
};
@@ -101,6 +102,32 @@ public class AwsCredentialsTest {
101102
.setCredentialSource(AWS_CREDENTIAL_SOURCE)
102103
.build();
103104

105+
@Test
106+
public void test_awsCredentialSource_ipv6() {
107+
// If no exception is thrown, it means the urls were valid.
108+
new AwsCredentialSource(buildAwsIpv6CredentialSourceMap());
109+
}
110+
111+
@Test
112+
public void test_awsCredentialSource_invalid_urls() {
113+
String keys[] = {"region_url", "url", "imdsv2_session_token_url"};
114+
for (String key : keys) {
115+
Map<String, Object> credentialSourceWithInvalidUrl = buildAwsIpv6CredentialSourceMap();
116+
credentialSourceWithInvalidUrl.put(key, "https://badhost.com/fake");
117+
IllegalArgumentException e =
118+
assertThrows(
119+
IllegalArgumentException.class,
120+
new ThrowingRunnable() {
121+
@Override
122+
public void run() throws Throwable {
123+
new AwsCredentialSource(credentialSourceWithInvalidUrl);
124+
}
125+
});
126+
127+
assertEquals(String.format("Invalid host badhost.com for %s.", key), e.getMessage());
128+
}
129+
}
130+
104131
@Test
105132
public void refreshAccessToken_withoutServiceAccountImpersonation() throws IOException {
106133
MockExternalAccountCredentialsTransportFactory transportFactory =
@@ -734,6 +761,20 @@ private static AwsCredentialSource buildAwsCredentialSource(
734761
return new AwsCredentialSource(credentialSourceMap);
735762
}
736763

764+
private static Map<String, Object> buildAwsIpv6CredentialSourceMap() {
765+
String regionUrl = "http://[fd00:ec2::254]/region";
766+
String url = "http://[fd00:ec2::254]";
767+
String imdsv2SessionTokenUrl = "http://[fd00:ec2::254]/imdsv2";
768+
Map<String, Object> credentialSourceMap = new HashMap<>();
769+
credentialSourceMap.put("environment_id", "aws1");
770+
credentialSourceMap.put("region_url", regionUrl);
771+
credentialSourceMap.put("url", url);
772+
credentialSourceMap.put("imdsv2_session_token_url", imdsv2SessionTokenUrl);
773+
credentialSourceMap.put("regional_cred_verification_url", GET_CALLER_IDENTITY_URL);
774+
775+
return credentialSourceMap;
776+
}
777+
737778
static InputStream writeAwsCredentialsStream(String stsUrl, String regionUrl, String metadataUrl)
738779
throws IOException {
739780
GenericJson json = new GenericJson();

oauth2_http/javatests/com/google/auth/oauth2/ExternalAccountCredentialsTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1117,8 +1117,8 @@ private GenericJson buildJsonAwsCredential() {
11171117

11181118
Map<String, String> map = new HashMap<>();
11191119
map.put("environment_id", "aws1");
1120-
map.put("region_url", "regionUrl");
1121-
map.put("url", "url");
1120+
map.put("region_url", "https://169.254.169.254/region");
1121+
map.put("url", "https://169.254.169.254/");
11221122
map.put("regional_cred_verification_url", "regionalCredVerificationUrl");
11231123
json.put("credential_source", map);
11241124

oauth2_http/javatests/com/google/auth/oauth2/MockExternalAccountCredentialsTransport.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,9 @@ public class MockExternalAccountCredentialsTransport extends MockHttpTransport {
6565
private static final String CLOUD_PLATFORM_SCOPE =
6666
"https://www.googleapis.com/auth/cloud-platform";
6767
private static final String ISSUED_TOKEN_TYPE = "urn:ietf:params:oauth:token-type:access_token";
68-
private static final String AWS_CREDENTIALS_URL = "https://www.aws-credentials.com";
69-
private static final String AWS_REGION_URL = "https://www.aws-region.com";
70-
private static final String AWS_IMDSV2_SESSION_TOKEN_URL = "https://www.aws-session-token.com";
68+
private static final String AWS_CREDENTIALS_URL = "https://169.254.169.254";
69+
private static final String AWS_REGION_URL = "https://169.254.169.254/region";
70+
private static final String AWS_IMDSV2_SESSION_TOKEN_URL = "https://169.254.169.254/imdsv2";
7171
private static final String METADATA_SERVER_URL = "https://www.metadata.google.com";
7272
private static final String STS_URL = "https://sts.googleapis.com";
7373

0 commit comments

Comments
 (0)