diff --git a/google-api-client/src/main/java/com/google/api/client/googleapis/auth/oauth2/OAuth2Utils.java b/google-api-client/src/main/java/com/google/api/client/googleapis/auth/oauth2/OAuth2Utils.java index f0b64a608..8bda75008 100644 --- a/google-api-client/src/main/java/com/google/api/client/googleapis/auth/oauth2/OAuth2Utils.java +++ b/google-api-client/src/main/java/com/google/api/client/googleapis/auth/oauth2/OAuth2Utils.java @@ -22,6 +22,8 @@ import com.google.api.client.util.Beta; import java.io.IOException; import java.net.SocketTimeoutException; +import java.net.URI; +import java.net.URISyntaxException; import java.nio.charset.Charset; import java.util.Collection; import java.util.logging.Level; @@ -103,9 +105,38 @@ public static String getMetadataServerUrl() { } static String getMetadataServerUrl(SystemEnvironmentProvider environment) { - String metadataServerAddress = environment.getEnv("GCE_METADATA_HOST"); - if (metadataServerAddress != null) { - return "http://" + metadataServerAddress; + String metadataServerHost = environment.getEnv("GCE_METADATA_HOST"); + if (metadataServerHost != null) { + try { + int idx = metadataServerHost.indexOf(":"); + if (idx >= 0 && idx == metadataServerHost.lastIndexOf(":")) { + // only one occurrence of ':' indicate this is ipv4/domain and port + return new URI( + "http", + null, + metadataServerHost.substring(0, idx), + Integer.parseInt(metadataServerHost.substring(idx + 1)), + null, + null, + null) + .toString(); + } + return new URI("http", metadataServerHost, null, null).toString(); + } catch (NumberFormatException e) { + LOGGER.log( + Level.WARNING, + "Invalid GCE_METADATA_HOST env provided, falling back to '" + + DEFAULT_METADATA_SERVER_URL + + "'.", + e); + } catch (URISyntaxException e) { + LOGGER.log( + Level.WARNING, + "Invalid GCE_METADATA_HOST env provided, falling back to '" + + DEFAULT_METADATA_SERVER_URL + + "'.", + e); + } } return DEFAULT_METADATA_SERVER_URL; } diff --git a/google-api-client/src/test/java/com/google/api/client/googleapis/auth/oauth2/DefaultCredentialProviderTest.java b/google-api-client/src/test/java/com/google/api/client/googleapis/auth/oauth2/DefaultCredentialProviderTest.java index d3ea60ccc..114aa864c 100644 --- a/google-api-client/src/test/java/com/google/api/client/googleapis/auth/oauth2/DefaultCredentialProviderTest.java +++ b/google-api-client/src/test/java/com/google/api/client/googleapis/auth/oauth2/DefaultCredentialProviderTest.java @@ -239,7 +239,33 @@ public void testDefaultCredentialNoGceCheck() throws IOException { assertEquals(0, transport.getRequestCount()); } - public void testDefaultCredentialWithCustomMetadataServerAddress() throws IOException { + public void testDefaultCredentialWithInvalidCustomMetadataServerAddress() throws IOException { + MockRequestUrlRecordingTransport transport = new MockRequestUrlRecordingTransport(); + TestDefaultCredentialProvider testProvider = new TestDefaultCredentialProvider(); + testProvider.setEnv("GCE_METADATA_HOST", "this::domain.contains.invalid.chars"); + + try { + testProvider.getDefaultCredential(transport, JSON_FACTORY); + fail("No credential expected for default test provider."); + } catch (IOException expected) { + } + assertTrue(transport.urlWasRequested("http://169.254.169.254")); + } + + public void testDefaultCredentialWithInvalidCustomMetadataServerPort() throws IOException { + MockRequestUrlRecordingTransport transport = new MockRequestUrlRecordingTransport(); + TestDefaultCredentialProvider testProvider = new TestDefaultCredentialProvider(); + testProvider.setEnv("GCE_METADATA_HOST", "test.metadata.server.address:portShouldBeANumber"); + + try { + testProvider.getDefaultCredential(transport, JSON_FACTORY); + fail("No credential expected for default test provider."); + } catch (IOException expected) { + } + assertTrue(transport.urlWasRequested("http://169.254.169.254")); + } + + public void testDefaultCredentialWithCustomMetadataServerDomainAddress() throws IOException { MockRequestUrlRecordingTransport transport = new MockRequestUrlRecordingTransport(); TestDefaultCredentialProvider testProvider = new TestDefaultCredentialProvider(); testProvider.setEnv("GCE_METADATA_HOST", "test.metadata.server.address"); @@ -252,6 +278,88 @@ public void testDefaultCredentialWithCustomMetadataServerAddress() throws IOExce assertTrue(transport.urlWasRequested("http://test.metadata.server.address")); } + public void testDefaultCredentialWithCustomMetadataServerDomainAddressAndCustomPort() + throws IOException { + MockRequestUrlRecordingTransport transport = new MockRequestUrlRecordingTransport(); + TestDefaultCredentialProvider testProvider = new TestDefaultCredentialProvider(); + testProvider.setEnv("GCE_METADATA_HOST", "test.metadata.server.address:8080"); + + try { + testProvider.getDefaultCredential(transport, JSON_FACTORY); + fail("No credential expected for default test provider."); + } catch (IOException expected) { + } + assertTrue(transport.urlWasRequested("http://test.metadata.server.address:8080")); + } + + public void testDefaultCredentialWithCustomMetadataServerIPv4Address() throws IOException { + MockRequestUrlRecordingTransport transport = new MockRequestUrlRecordingTransport(); + TestDefaultCredentialProvider testProvider = new TestDefaultCredentialProvider(); + testProvider.setEnv("GCE_METADATA_HOST", "169.254.0.1"); + + try { + testProvider.getDefaultCredential(transport, JSON_FACTORY); + fail("No credential expected for default test provider."); + } catch (IOException expected) { + } + assertTrue(transport.urlWasRequested("http://169.254.0.1")); + } + + public void testDefaultCredentialWithCustomMetadataServerIPv4AddressAndCustomPort() + throws IOException { + MockRequestUrlRecordingTransport transport = new MockRequestUrlRecordingTransport(); + TestDefaultCredentialProvider testProvider = new TestDefaultCredentialProvider(); + testProvider.setEnv("GCE_METADATA_HOST", "169.254.0.1:8080"); + + try { + testProvider.getDefaultCredential(transport, JSON_FACTORY); + fail("No credential expected for default test provider."); + } catch (IOException expected) { + } + assertTrue(transport.urlWasRequested("http://169.254.0.1:8080")); + } + + public void testDefaultCredentialWithCustomMetadataServerIPv6Address() throws IOException { + MockRequestUrlRecordingTransport transport = new MockRequestUrlRecordingTransport(); + TestDefaultCredentialProvider testProvider = new TestDefaultCredentialProvider(); + testProvider.setEnv("GCE_METADATA_HOST", "fe80::1"); + + try { + testProvider.getDefaultCredential(transport, JSON_FACTORY); + fail("No credential expected for default test provider."); + } catch (IOException expected) { + } + assertTrue(transport.urlWasRequested("http://[fe80::1]")); + } + + public void testDefaultCredentialWithCustomMetadataServerIPv6AddressProvidedWithBrackets() + throws IOException { + MockRequestUrlRecordingTransport transport = new MockRequestUrlRecordingTransport(); + TestDefaultCredentialProvider testProvider = new TestDefaultCredentialProvider(); + testProvider.setEnv("GCE_METADATA_HOST", "[fe80::1]"); + + try { + testProvider.getDefaultCredential(transport, JSON_FACTORY); + fail("No credential expected for default test provider."); + } catch (IOException expected) { + } + assertTrue(transport.urlWasRequested("http://[fe80::1]")); + } + + public void testDefaultCredentialWithCustomMetadataServerIPv6AddressAndCustomPort() + throws IOException { + MockRequestUrlRecordingTransport transport = new MockRequestUrlRecordingTransport(); + TestDefaultCredentialProvider testProvider = new TestDefaultCredentialProvider(); + testProvider.setEnv("GCE_METADATA_HOST", "[fe80::1]:8080"); + + try { + testProvider.getDefaultCredential(transport, JSON_FACTORY); + fail("No credential expected for default test provider."); + } catch (IOException expected) { + } + assertTrue(transport.urlWasRequested("http://[fe80::1]:8080")); + } + public void testDefaultCredentialNonExistentFileThrows() throws Exception { File nonExistentFile = new java.io.File(getTempDirectory(), "DefaultCredentialBadFile.json"); assertFalse(nonExistentFile.exists());