This class handles the processing of GOOGLE_API_USE_CLIENT_CERTIFICATE and + * GOOGLE_API_USE_MTLS_ENDPOINT environment variables according to https://google.aip.dev/auth/4114 + */ +@InternalApi +public class CertificateBasedAccess { + + private final EnvironmentProvider envProvider; + + /** The EnvironmentProvider mechanism supports env var injection for unit tests. */ + public CertificateBasedAccess(EnvironmentProvider envProvider) { + this.envProvider = envProvider; + } + + public static CertificateBasedAccess createWithSystemEnv() { + return new CertificateBasedAccess(System::getenv); + } + + /** + * The policy for mutual TLS endpoint usage. NEVER means always use regular endpoint; ALWAYS means + * always use mTLS endpoint; AUTO means auto switch to mTLS endpoint if client certificate exists + * and should be used. + */ + public enum MtlsEndpointUsagePolicy { + NEVER, + AUTO, + ALWAYS; + } + + /** Returns if mutual TLS client certificate should be used. */ + public boolean useMtlsClientCertificate() { + String useClientCertificate = envProvider.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE"); + return "true".equals(useClientCertificate); + } + + /** Returns the current mutual TLS endpoint usage policy. */ + public MtlsEndpointUsagePolicy getMtlsEndpointUsagePolicy() { + String mtlsEndpointUsagePolicy = envProvider.getenv("GOOGLE_API_USE_MTLS_ENDPOINT"); + if ("never".equals(mtlsEndpointUsagePolicy)) { + return MtlsEndpointUsagePolicy.NEVER; + } else if ("always".equals(mtlsEndpointUsagePolicy)) { + return MtlsEndpointUsagePolicy.ALWAYS; + } + return MtlsEndpointUsagePolicy.AUTO; + } +} diff --git a/gax-java/gax/src/main/java/com/google/api/gax/rpc/mtls/ContextAwareMetadataJson.java b/gax-java/gax/src/main/java/com/google/api/gax/rpc/mtls/ContextAwareMetadataJson.java index 25d7d27de7..9e92ac5ce0 100644 --- a/gax-java/gax/src/main/java/com/google/api/gax/rpc/mtls/ContextAwareMetadataJson.java +++ b/gax-java/gax/src/main/java/com/google/api/gax/rpc/mtls/ContextAwareMetadataJson.java @@ -1,5 +1,5 @@ /* - * Copyright 2021 Google LLC + * Copyright 2025 Google LLC * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -32,12 +32,18 @@ import com.google.api.client.json.GenericJson; import com.google.api.client.util.Key; -import com.google.api.core.BetaApi; import com.google.common.collect.ImmutableList; import java.util.List; -/** Data class representing context_aware_metadata.json file. */ -@BetaApi +/** + * Data class representing context_aware_metadata.json file. + * + *
This class is deprecated. It has been replaced by + * com.google.auth.mtls.ContextAwareMetadataJson from the Java auth library. + * + *
Note: This class is for Google cloud internal use only. + */ +@Deprecated public class ContextAwareMetadataJson extends GenericJson { /** Cert provider command */ @Key("cert_provider_command") diff --git a/gax-java/gax/src/main/java/com/google/api/gax/rpc/mtls/MtlsProvider.java b/gax-java/gax/src/main/java/com/google/api/gax/rpc/mtls/MtlsProvider.java index c24fc80d6f..88e423c47c 100644 --- a/gax-java/gax/src/main/java/com/google/api/gax/rpc/mtls/MtlsProvider.java +++ b/gax-java/gax/src/main/java/com/google/api/gax/rpc/mtls/MtlsProvider.java @@ -48,8 +48,14 @@ /** * Provider class for mutual TLS. It is used to configure the mutual TLS in the transport with the * default client certificate on device. + * + *
This class is deprecated. It has been replaced by com.google.auth.mtls.SecureConnectProvider + * from the Java auth library. + * + *
Note: This class is for Google cloud internal use only.
*/
@BetaApi
+@Deprecated
public class MtlsProvider {
interface ProcessProvider {
public Process createProcess(InputStream metadata) throws IOException;
diff --git a/gax-java/gax/src/test/java/com/google/api/gax/rpc/EndpointContextTest.java b/gax-java/gax/src/test/java/com/google/api/gax/rpc/EndpointContextTest.java
index 59342927ca..ef64ccd726 100644
--- a/gax-java/gax/src/test/java/com/google/api/gax/rpc/EndpointContextTest.java
+++ b/gax-java/gax/src/test/java/com/google/api/gax/rpc/EndpointContextTest.java
@@ -34,9 +34,10 @@
import com.google.api.gax.core.NoCredentialsProvider;
import com.google.api.gax.rpc.internal.EnvironmentProvider;
-import com.google.api.gax.rpc.mtls.MtlsProvider;
+import com.google.api.gax.rpc.mtls.CertificateBasedAccess;
import com.google.api.gax.rpc.testing.FakeMtlsProvider;
import com.google.auth.Credentials;
+import com.google.auth.mtls.MtlsProvider;
import com.google.auth.oauth2.ComputeEngineCredentials;
import com.google.common.truth.Truth;
import io.grpc.Status;
@@ -53,12 +54,15 @@ class EndpointContextTest {
@BeforeEach
void setUp() throws IOException {
+ MtlsProvider mtlsProvider =
+ new FakeMtlsProvider(FakeMtlsProvider.createTestMtlsKeyStore(), "", false);
defaultEndpointContextBuilder =
EndpointContext.newBuilder()
.setServiceName("test")
.setUniverseDomain(Credentials.GOOGLE_DEFAULT_UNIVERSE)
.setClientSettingsEndpoint(DEFAULT_ENDPOINT)
- .setMtlsEndpoint(DEFAULT_MTLS_ENDPOINT);
+ .setMtlsEndpoint(DEFAULT_MTLS_ENDPOINT)
+ .setMtlsProvider(mtlsProvider);
statusCode = Mockito.mock(StatusCode.class);
Mockito.when(statusCode.getCode()).thenReturn(StatusCode.Code.UNAUTHENTICATED);
Mockito.when(statusCode.getTransportCode()).thenReturn(Status.Code.UNAUTHENTICATED);
@@ -66,107 +70,111 @@ void setUp() throws IOException {
@Test
void mtlsEndpointResolver_switchToMtlsAllowedIsFalse() throws IOException {
- boolean useClientCertificate = true;
boolean throwExceptionForGetKeyStore = false;
MtlsProvider mtlsProvider =
new FakeMtlsProvider(
- useClientCertificate,
- MtlsProvider.MtlsEndpointUsagePolicy.AUTO,
- FakeMtlsProvider.createTestMtlsKeyStore(),
- "",
- throwExceptionForGetKeyStore);
+ FakeMtlsProvider.createTestMtlsKeyStore(), "", throwExceptionForGetKeyStore);
boolean switchToMtlsEndpointAllowed = false;
+ CertificateBasedAccess certificateBasedAccess =
+ new CertificateBasedAccess(
+ name -> name.equals("GOOGLE_API_USE_MTLS_ENDPOINT") ? "auto" : "true");
Truth.assertThat(
defaultEndpointContextBuilder.mtlsEndpointResolver(
- DEFAULT_ENDPOINT, DEFAULT_MTLS_ENDPOINT, switchToMtlsEndpointAllowed, mtlsProvider))
+ DEFAULT_ENDPOINT,
+ DEFAULT_MTLS_ENDPOINT,
+ switchToMtlsEndpointAllowed,
+ mtlsProvider,
+ certificateBasedAccess))
.isEqualTo(DEFAULT_ENDPOINT);
}
@Test
void mtlsEndpointResolver_switchToMtlsAllowedIsTrue_mtlsUsageAuto() throws IOException {
- boolean useClientCertificate = true;
boolean throwExceptionForGetKeyStore = false;
MtlsProvider mtlsProvider =
new FakeMtlsProvider(
- useClientCertificate,
- MtlsProvider.MtlsEndpointUsagePolicy.AUTO,
- FakeMtlsProvider.createTestMtlsKeyStore(),
- "",
- throwExceptionForGetKeyStore);
+ FakeMtlsProvider.createTestMtlsKeyStore(), "", throwExceptionForGetKeyStore);
boolean switchToMtlsEndpointAllowed = true;
+ CertificateBasedAccess certificateBasedAccess =
+ new CertificateBasedAccess(
+ name -> name.equals("GOOGLE_API_USE_MTLS_ENDPOINT") ? "auto" : "true");
Truth.assertThat(
defaultEndpointContextBuilder.mtlsEndpointResolver(
- DEFAULT_ENDPOINT, DEFAULT_MTLS_ENDPOINT, switchToMtlsEndpointAllowed, mtlsProvider))
+ DEFAULT_ENDPOINT,
+ DEFAULT_MTLS_ENDPOINT,
+ switchToMtlsEndpointAllowed,
+ mtlsProvider,
+ certificateBasedAccess))
.isEqualTo(DEFAULT_MTLS_ENDPOINT);
}
@Test
void mtlsEndpointResolver_switchToMtlsAllowedIsTrue_mtlsUsageAlways() throws IOException {
- boolean useClientCertificate = true;
boolean throwExceptionForGetKeyStore = false;
MtlsProvider mtlsProvider =
new FakeMtlsProvider(
- useClientCertificate,
- MtlsProvider.MtlsEndpointUsagePolicy.ALWAYS,
- FakeMtlsProvider.createTestMtlsKeyStore(),
- "",
- throwExceptionForGetKeyStore);
+ FakeMtlsProvider.createTestMtlsKeyStore(), "", throwExceptionForGetKeyStore);
boolean switchToMtlsEndpointAllowed = true;
+ CertificateBasedAccess certificateBasedAccess =
+ new CertificateBasedAccess(
+ name -> name.equals("GOOGLE_API_USE_MTLS_ENDPOINT") ? "always" : "true");
Truth.assertThat(
defaultEndpointContextBuilder.mtlsEndpointResolver(
- DEFAULT_ENDPOINT, DEFAULT_MTLS_ENDPOINT, switchToMtlsEndpointAllowed, mtlsProvider))
+ DEFAULT_ENDPOINT,
+ DEFAULT_MTLS_ENDPOINT,
+ switchToMtlsEndpointAllowed,
+ mtlsProvider,
+ certificateBasedAccess))
.isEqualTo(DEFAULT_MTLS_ENDPOINT);
}
@Test
void mtlsEndpointResolver_switchToMtlsAllowedIsTrue_mtlsUsageNever() throws IOException {
- boolean useClientCertificate = true;
boolean throwExceptionForGetKeyStore = false;
MtlsProvider mtlsProvider =
new FakeMtlsProvider(
- useClientCertificate,
- MtlsProvider.MtlsEndpointUsagePolicy.NEVER,
- FakeMtlsProvider.createTestMtlsKeyStore(),
- "",
- throwExceptionForGetKeyStore);
+ FakeMtlsProvider.createTestMtlsKeyStore(), "", throwExceptionForGetKeyStore);
boolean switchToMtlsEndpointAllowed = true;
+ CertificateBasedAccess certificateBasedAccess =
+ new CertificateBasedAccess(
+ name -> name.equals("GOOGLE_API_USE_MTLS_ENDPOINT") ? "never" : "true");
Truth.assertThat(
defaultEndpointContextBuilder.mtlsEndpointResolver(
- DEFAULT_ENDPOINT, DEFAULT_MTLS_ENDPOINT, switchToMtlsEndpointAllowed, mtlsProvider))
+ DEFAULT_ENDPOINT,
+ DEFAULT_MTLS_ENDPOINT,
+ switchToMtlsEndpointAllowed,
+ mtlsProvider,
+ certificateBasedAccess))
.isEqualTo(DEFAULT_ENDPOINT);
}
@Test
void mtlsEndpointResolver_switchToMtlsAllowedIsTrue_useCertificateIsFalse_nullMtlsKeystore()
throws IOException {
- boolean useClientCertificate = false;
boolean throwExceptionForGetKeyStore = false;
- MtlsProvider mtlsProvider =
- new FakeMtlsProvider(
- useClientCertificate,
- MtlsProvider.MtlsEndpointUsagePolicy.AUTO,
- null,
- "",
- throwExceptionForGetKeyStore);
+ MtlsProvider mtlsProvider = new FakeMtlsProvider(null, "", throwExceptionForGetKeyStore);
boolean switchToMtlsEndpointAllowed = true;
+ CertificateBasedAccess certificateBasedAccess =
+ new CertificateBasedAccess(
+ name -> name.equals("GOOGLE_API_USE_MTLS_ENDPOINT") ? "auto" : "false");
Truth.assertThat(
defaultEndpointContextBuilder.mtlsEndpointResolver(
- DEFAULT_ENDPOINT, DEFAULT_MTLS_ENDPOINT, switchToMtlsEndpointAllowed, mtlsProvider))
+ DEFAULT_ENDPOINT,
+ DEFAULT_MTLS_ENDPOINT,
+ switchToMtlsEndpointAllowed,
+ mtlsProvider,
+ certificateBasedAccess))
.isEqualTo(DEFAULT_ENDPOINT);
}
@Test
void mtlsEndpointResolver_getKeyStore_throwsIOException() throws IOException {
- boolean useClientCertificate = true;
boolean throwExceptionForGetKeyStore = true;
- MtlsProvider mtlsProvider =
- new FakeMtlsProvider(
- useClientCertificate,
- MtlsProvider.MtlsEndpointUsagePolicy.AUTO,
- null,
- "",
- throwExceptionForGetKeyStore);
+ MtlsProvider mtlsProvider = new FakeMtlsProvider(null, "", throwExceptionForGetKeyStore);
boolean switchToMtlsEndpointAllowed = true;
+ CertificateBasedAccess certificateBasedAccess =
+ new CertificateBasedAccess(
+ name -> name.equals("GOOGLE_API_USE_MTLS_ENDPOINT") ? "auto" : "true");
assertThrows(
IOException.class,
() ->
@@ -174,7 +182,8 @@ void mtlsEndpointResolver_getKeyStore_throwsIOException() throws IOException {
DEFAULT_ENDPOINT,
DEFAULT_MTLS_ENDPOINT,
switchToMtlsEndpointAllowed,
- mtlsProvider));
+ mtlsProvider,
+ certificateBasedAccess));
}
@Test
@@ -260,18 +269,17 @@ void endpointContextBuild_noUniverseDomain_noEndpoints() throws IOException {
@Test
void endpointContextBuild_mtlsConfigured_GDU() throws IOException {
MtlsProvider mtlsProvider =
- new FakeMtlsProvider(
- true,
- MtlsProvider.MtlsEndpointUsagePolicy.ALWAYS,
- FakeMtlsProvider.createTestMtlsKeyStore(),
- "",
- false);
+ new FakeMtlsProvider(FakeMtlsProvider.createTestMtlsKeyStore(), "", false);
+ CertificateBasedAccess certificateBasedAccess =
+ new CertificateBasedAccess(
+ name -> name.equals("GOOGLE_API_USE_MTLS_ENDPOINT") ? "always" : "true");
EndpointContext endpointContext =
defaultEndpointContextBuilder
.setClientSettingsEndpoint(null)
.setTransportChannelProviderEndpoint(null)
.setSwitchToMtlsEndpointAllowed(true)
.setMtlsProvider(mtlsProvider)
+ .setCertificateBasedAccess(certificateBasedAccess)
.build();
Truth.assertThat(endpointContext.resolvedEndpoint()).isEqualTo(DEFAULT_MTLS_ENDPOINT);
Truth.assertThat(endpointContext.resolvedUniverseDomain())
@@ -282,19 +290,18 @@ void endpointContextBuild_mtlsConfigured_GDU() throws IOException {
void endpointContextBuild_mtlsConfigured_nonGDU_throwsIllegalArgumentException()
throws IOException {
MtlsProvider mtlsProvider =
- new FakeMtlsProvider(
- true,
- MtlsProvider.MtlsEndpointUsagePolicy.ALWAYS,
- FakeMtlsProvider.createTestMtlsKeyStore(),
- "",
- false);
+ new FakeMtlsProvider(FakeMtlsProvider.createTestMtlsKeyStore(), "", false);
+ CertificateBasedAccess certificateBasedAccess =
+ new CertificateBasedAccess(
+ name -> name.equals("GOOGLE_API_USE_MTLS_ENDPOINT") ? "always" : "true");
EndpointContext.Builder endpointContextBuilder =
defaultEndpointContextBuilder
.setUniverseDomain("random.com")
.setClientSettingsEndpoint(null)
.setTransportChannelProviderEndpoint(null)
.setSwitchToMtlsEndpointAllowed(true)
- .setMtlsProvider(mtlsProvider);
+ .setMtlsProvider(mtlsProvider)
+ .setCertificateBasedAccess(certificateBasedAccess);
IllegalArgumentException exception =
assertThrows(IllegalArgumentException.class, endpointContextBuilder::build);
Truth.assertThat(exception.getMessage())
diff --git a/gax-java/gax/src/test/java/com/google/api/gax/rpc/mtls/AbstractMtlsTransportChannelTest.java b/gax-java/gax/src/test/java/com/google/api/gax/rpc/mtls/AbstractMtlsTransportChannelTest.java
index 1251dc47d1..bea4674b76 100644
--- a/gax-java/gax/src/test/java/com/google/api/gax/rpc/mtls/AbstractMtlsTransportChannelTest.java
+++ b/gax-java/gax/src/test/java/com/google/api/gax/rpc/mtls/AbstractMtlsTransportChannelTest.java
@@ -35,8 +35,8 @@
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
-import com.google.api.gax.rpc.mtls.MtlsProvider.MtlsEndpointUsagePolicy;
import com.google.api.gax.rpc.testing.FakeMtlsProvider;
+import com.google.auth.mtls.MtlsProvider;
import java.io.IOException;
import java.security.GeneralSecurityException;
import org.junit.jupiter.api.Test;
@@ -48,42 +48,49 @@ public abstract class AbstractMtlsTransportChannelTest {
* GrpcTransportChannel, the mTLS object is the ChannelCredentials. The transport channel is mTLS
* if and only if the related mTLS object is not null.
*/
- protected abstract Object getMtlsObjectFromTransportChannel(MtlsProvider provider)
+ protected abstract Object getMtlsObjectFromTransportChannel(
+ MtlsProvider provider, CertificateBasedAccess certificateBasedAccess)
throws IOException, GeneralSecurityException;
@Test
void testNotUseClientCertificate() throws IOException, GeneralSecurityException {
- MtlsProvider provider =
- new FakeMtlsProvider(false, MtlsEndpointUsagePolicy.AUTO, null, "", false);
- assertNull(getMtlsObjectFromTransportChannel(provider));
+ CertificateBasedAccess certificateBasedAccess =
+ new CertificateBasedAccess(
+ name -> name.equals("GOOGLE_API_USE_MTLS_ENDPOINT") ? "auto" : "false");
+ MtlsProvider provider = new FakeMtlsProvider(null, "", false);
+ assertNull(getMtlsObjectFromTransportChannel(provider, certificateBasedAccess));
}
@Test
void testUseClientCertificate() throws IOException, GeneralSecurityException {
+ CertificateBasedAccess certificateBasedAccess =
+ new CertificateBasedAccess(
+ name -> name.equals("GOOGLE_API_USE_MTLS_ENDPOINT") ? "auto" : "true");
MtlsProvider provider =
- new FakeMtlsProvider(
- true,
- MtlsEndpointUsagePolicy.AUTO,
- FakeMtlsProvider.createTestMtlsKeyStore(),
- "",
- false);
- assertNotNull(getMtlsObjectFromTransportChannel(provider));
+ new FakeMtlsProvider(FakeMtlsProvider.createTestMtlsKeyStore(), "", false);
+ assertNotNull(getMtlsObjectFromTransportChannel(provider, certificateBasedAccess));
}
@Test
void testNoClientCertificate() throws IOException, GeneralSecurityException {
- MtlsProvider provider =
- new FakeMtlsProvider(true, MtlsEndpointUsagePolicy.AUTO, null, "", false);
- assertNull(getMtlsObjectFromTransportChannel(provider));
+ CertificateBasedAccess certificateBasedAccess =
+ new CertificateBasedAccess(
+ name -> name.equals("GOOGLE_API_USE_MTLS_ENDPOINT") ? "auto" : "true");
+ MtlsProvider provider = new FakeMtlsProvider(null, "", false);
+ assertNull(getMtlsObjectFromTransportChannel(provider, certificateBasedAccess));
}
@Test
void testGetKeyStoreThrows() throws GeneralSecurityException {
// Test the case where provider.getKeyStore() throws.
- MtlsProvider provider =
- new FakeMtlsProvider(true, MtlsEndpointUsagePolicy.AUTO, null, "", true);
+ CertificateBasedAccess certificateBasedAccess =
+ new CertificateBasedAccess(
+ name -> name.equals("GOOGLE_API_USE_MTLS_ENDPOINT") ? "auto" : "true");
+ MtlsProvider provider = new FakeMtlsProvider(null, "", true);
IOException actual =
- assertThrows(IOException.class, () -> getMtlsObjectFromTransportChannel(provider));
+ assertThrows(
+ IOException.class,
+ () -> getMtlsObjectFromTransportChannel(provider, certificateBasedAccess));
assertTrue(actual.getMessage().contains("getKeyStore throws exception"));
}
}
diff --git a/gax-java/gax/src/test/java/com/google/api/gax/rpc/mtls/CertificateBasedAccessTest.java b/gax-java/gax/src/test/java/com/google/api/gax/rpc/mtls/CertificateBasedAccessTest.java
new file mode 100644
index 0000000000..e328e0af47
--- /dev/null
+++ b/gax-java/gax/src/test/java/com/google/api/gax/rpc/mtls/CertificateBasedAccessTest.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2021 Google LLC
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google LLC nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.google.api.gax.rpc.mtls;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.junit.jupiter.api.Test;
+
+class CertificateBasedAccessTest {
+
+ @Test
+ void testUseMtlsEndpointAlways() {
+ CertificateBasedAccess cba =
+ new CertificateBasedAccess(
+ name -> name.equals("GOOGLE_API_USE_MTLS_ENDPOINT") ? "always" : "false");
+ assertEquals(
+ CertificateBasedAccess.MtlsEndpointUsagePolicy.ALWAYS, cba.getMtlsEndpointUsagePolicy());
+ }
+
+ @Test
+ void testUseMtlsEndpointAuto() {
+ CertificateBasedAccess cba =
+ new CertificateBasedAccess(
+ name -> name.equals("GOOGLE_API_USE_MTLS_ENDPOINT") ? "auto" : "false");
+ assertEquals(
+ CertificateBasedAccess.MtlsEndpointUsagePolicy.AUTO, cba.getMtlsEndpointUsagePolicy());
+ }
+
+ @Test
+ void testUseMtlsEndpointNever() {
+ CertificateBasedAccess cba =
+ new CertificateBasedAccess(
+ name -> name.equals("GOOGLE_API_USE_MTLS_ENDPOINT") ? "never" : "false");
+ assertEquals(
+ CertificateBasedAccess.MtlsEndpointUsagePolicy.NEVER, cba.getMtlsEndpointUsagePolicy());
+ }
+
+ @Test
+ void testUseMtlsClientCertificateTrue() {
+ CertificateBasedAccess cba =
+ new CertificateBasedAccess(
+ name -> name.equals("GOOGLE_API_USE_CLIENT_CERTIFICATE") ? "true" : "auto");
+ assertTrue(cba.useMtlsClientCertificate());
+ }
+
+ @Test
+ void testUseMtlsClientCertificateFalse() {
+ CertificateBasedAccess cba =
+ new CertificateBasedAccess(
+ name -> name.equals("GOOGLE_API_USE_CLIENT_CERTIFICATE") ? "false" : "auto");
+ assertFalse(cba.useMtlsClientCertificate());
+ }
+}
diff --git a/gax-java/gax/src/test/java/com/google/api/gax/rpc/mtls/MtlsProviderTest.java b/gax-java/gax/src/test/java/com/google/api/gax/rpc/mtls/MtlsProviderTest.java
deleted file mode 100644
index 9835b4c120..0000000000
--- a/gax-java/gax/src/test/java/com/google/api/gax/rpc/mtls/MtlsProviderTest.java
+++ /dev/null
@@ -1,213 +0,0 @@
-/*
- * Copyright 2021 Google LLC
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google LLC nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-package com.google.api.gax.rpc.mtls;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertNull;
-import static org.junit.jupiter.api.Assertions.assertThrows;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.security.GeneralSecurityException;
-import java.util.List;
-import org.junit.jupiter.api.Test;
-
-class MtlsProviderTest {
-
- private static class TestCertProviderCommandProcess extends Process {
-
- private boolean runForever;
- private int exitValue;
-
- public TestCertProviderCommandProcess(int exitValue, boolean runForever) {
- this.runForever = runForever;
- this.exitValue = exitValue;
- }
-
- @Override
- public OutputStream getOutputStream() {
- return null;
- }
-
- @Override
- public InputStream getInputStream() {
- return null;
- }
-
- @Override
- public InputStream getErrorStream() {
- return null;
- }
-
- @Override
- public int waitFor() throws InterruptedException {
- return 0;
- }
-
- @Override
- public int exitValue() {
- if (runForever) {
- throw new IllegalThreadStateException();
- }
- return exitValue;
- }
-
- @Override
- public void destroy() {}
- }
-
- static class TestProcessProvider implements MtlsProvider.ProcessProvider {
-
- private int exitCode;
-
- public TestProcessProvider(int exitCode) {
- this.exitCode = exitCode;
- }
-
- @Override
- public Process createProcess(InputStream metadata) throws IOException {
- return new TestCertProviderCommandProcess(exitCode, false);
- }
- }
-
- @Test
- void testUseMtlsEndpointAlways() {
- MtlsProvider mtlsProvider =
- new MtlsProvider(
- name -> name.equals("GOOGLE_API_USE_MTLS_ENDPOINT") ? "always" : "false",
- new TestProcessProvider(0),
- "/path/to/missing/file");
- assertEquals(
- MtlsProvider.MtlsEndpointUsagePolicy.ALWAYS, mtlsProvider.getMtlsEndpointUsagePolicy());
- }
-
- @Test
- void testUseMtlsEndpointAuto() {
- MtlsProvider mtlsProvider =
- new MtlsProvider(
- name -> name.equals("GOOGLE_API_USE_MTLS_ENDPOINT") ? "auto" : "false",
- new TestProcessProvider(0),
- "/path/to/missing/file");
- assertEquals(
- MtlsProvider.MtlsEndpointUsagePolicy.AUTO, mtlsProvider.getMtlsEndpointUsagePolicy());
- }
-
- @Test
- void testUseMtlsEndpointNever() {
- MtlsProvider mtlsProvider =
- new MtlsProvider(
- name -> name.equals("GOOGLE_API_USE_MTLS_ENDPOINT") ? "never" : "false",
- new TestProcessProvider(0),
- "/path/to/missing/file");
- assertEquals(
- MtlsProvider.MtlsEndpointUsagePolicy.NEVER, mtlsProvider.getMtlsEndpointUsagePolicy());
- }
-
- @Test
- void testUseMtlsClientCertificateTrue() {
- MtlsProvider mtlsProvider =
- new MtlsProvider(
- name -> name.equals("GOOGLE_API_USE_MTLS_ENDPOINT") ? "auto" : "true",
- new TestProcessProvider(0),
- "/path/to/missing/file");
- assertTrue(mtlsProvider.useMtlsClientCertificate());
- }
-
- @Test
- void testUseMtlsClientCertificateFalse() {
- MtlsProvider mtlsProvider =
- new MtlsProvider(
- name -> name.equals("GOOGLE_API_USE_MTLS_ENDPOINT") ? "auto" : "false",
- new TestProcessProvider(0),
- "/path/to/missing/file");
- assertFalse(mtlsProvider.useMtlsClientCertificate());
- }
-
- @Test
- void testGetKeyStore() throws IOException {
- MtlsProvider mtlsProvider =
- new MtlsProvider(
- name -> name.equals("GOOGLE_API_USE_MTLS_ENDPOINT") ? "always" : "false",
- new TestProcessProvider(0),
- "/path/to/missing/file");
- assertNull(mtlsProvider.getKeyStore());
- }
-
- @Test
- void testGetKeyStoreNonZeroExitCode()
- throws IOException, InterruptedException, GeneralSecurityException {
- InputStream metadata =
- this.getClass()
- .getClassLoader()
- .getResourceAsStream("com/google/api/gax/rpc/mtls/mtlsCertAndKey.pem");
- IOException actual =
- assertThrows(
- IOException.class,
- () -> MtlsProvider.getKeyStore(metadata, new TestProcessProvider(1)));
- assertTrue(
- actual.getMessage().contains("Cert provider command failed with exit code: 1"),
- "expected to fail with nonzero exit code");
- }
-
- @Test
- void testExtractCertificateProviderCommand() throws IOException {
- InputStream inputStream =
- this.getClass()
- .getClassLoader()
- .getResourceAsStream("com/google/api/gax/rpc/mtls/mtls_context_aware_metadata.json");
- List2.61.0
##
[2.61.0](https://github.com/googleapis/sdk-platform-java/compare/v2.60.2...v2.61.0)
(2025-08-04)
### Features
* **mtls:** Add support for X.509-based mTLS-transport in Java GAX lib
([#3852](https://github.com/googleapis/sdk-platform-java/issues/3852))
([2d02344](https://github.com/googleapis/sdk-platform-java/commit/2d02344d79f5cfdca7834aa0d6306f1b72a7505a))
### Bug Fixes
* improve error messaging for LRO CancellationException
([#3873](https://github.com/googleapis/sdk-platform-java/issues/3873))
([9cae675](https://github.com/googleapis/sdk-platform-java/commit/9cae675f0ff44227cea60e6802769e82cce948f2))
* make generation config update logs verbose
([#3764](https://github.com/googleapis/sdk-platform-java/issues/3764))
([9b1a34b](https://github.com/googleapis/sdk-platform-java/commit/9b1a34b0dd08c0eddcf09ef5d81b225d0942f529))