diff --git a/google-auth-library-java/pom.xml b/google-auth-library-java/pom.xml index 374ec0ed8737..260fe6bfc286 100644 --- a/google-auth-library-java/pom.xml +++ b/google-auth-library-java/pom.xml @@ -80,12 +80,12 @@ 2.0.33 3.0.2 false - 2.48.0 + 2.50.0 4.33.6 0.9.0-proto3 1.15.0 2.0.17 - 2.13.2 + 2.14.0 2.67.0-SNAPSHOT 1.18.0 3.5.2 diff --git a/grpc-gcp-java/pom.xml b/grpc-gcp-java/pom.xml index 17997ee07915..9a6e523f52ec 100644 --- a/grpc-gcp-java/pom.xml +++ b/grpc-gcp-java/pom.xml @@ -64,12 +64,12 @@ grpc-gcp 2.67.0-SNAPSHOT 1.11.0 - 2.48.0 + 2.50.0 2.2.0 - 2.13.2 + 2.14.0 33.6.0-jre 4.33.6 - 1.82.2 + 1.83.0 3.0.2 4.13.2 0.31.1 diff --git a/java-bigtable/pom.xml b/java-bigtable/pom.xml index c6bd75e5f4f7..454eede9bfbd 100644 --- a/java-bigtable/pom.xml +++ b/java-bigtable/pom.xml @@ -144,7 +144,7 @@ github google-cloud-bigtable-parent https://googleapis.dev/java/google-api-grpc/latest - 2.48.0 + 2.50.0 -g diff --git a/java-datastore/pom.xml b/java-datastore/pom.xml index 674bdac579f4..30f3d56b7f25 100644 --- a/java-datastore/pom.xml +++ b/java-datastore/pom.xml @@ -144,7 +144,7 @@ github google-cloud-datastore-parent https://googleapis.dev/java/google-api-grpc/latest - 2.48.0 + 2.50.0 -g diff --git a/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/ITPostQuantumCryptography.java b/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/ITPostQuantumCryptography.java index e1f2ed82560d..0228795f3f39 100644 --- a/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/ITPostQuantumCryptography.java +++ b/java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/ITPostQuantumCryptography.java @@ -21,6 +21,7 @@ import com.google.api.client.http.javanet.NetHttpTransport; import com.google.api.gax.core.NoCredentialsProvider; +import com.google.api.gax.grpc.InstantiatingGrpcChannelProvider; import com.google.api.gax.httpjson.HttpJsonConscryptUtils; import com.google.api.gax.httpjson.HttpJsonMetadata; import com.google.api.gax.httpjson.InstantiatingHttpJsonChannelProvider; @@ -29,6 +30,16 @@ import com.google.showcase.v1beta1.EchoResponse; import com.google.showcase.v1beta1.EchoSettings; import com.google.showcase.v1beta1.it.util.HttpJsonCapturingClientInterceptor; +import io.grpc.CallOptions; +import io.grpc.Channel; +import io.grpc.ClientCall; +import io.grpc.ClientInterceptor; +import io.grpc.ForwardingClientCall; +import io.grpc.ForwardingClientCallListener; +import io.grpc.Metadata; +import io.grpc.MethodDescriptor; +import io.grpc.netty.shaded.io.grpc.netty.GrpcSslContexts; +import io.grpc.netty.shaded.io.grpc.netty.NettyChannelBuilder; import java.io.File; import java.io.InputStream; import java.nio.file.Files; @@ -266,4 +277,104 @@ private static KeyStore loadCaCert(String certPath) throws Exception { } return trustStore; } + + /** + * Integration test to verify Post-Quantum Cryptography (PQC) TLS negotiation for gRPC clients. + * + *

In gRPC-Java 1.83.0+, the default Netty transport (`grpc-netty-shaded`) bundles BoringSSL + * (`netty-tcnative-boringssl-static`) with built-in PQC hybrid key exchange support (e.g., + * X25519MLKEM768). No custom socket configurator or security provider swapping is needed. + * + *

Because the local Showcase test server uses a self-signed CA certificate (written to {@link + * #DEFAULT_CA_CERT_PATH}), we configure the gRPC transport channel builder directly to trust this + * certificate via {@link GrpcSslContexts#forClient()}. This avoids mutating global JVM system + * properties in {@code setUp()} and ensures HTTP/JSON tests remain completely isolated. + */ + @Test + void testGrpcPqc_withTls() throws Exception { + GrpcTlsCapturingClientInterceptor interceptor = new GrpcTlsCapturingClientInterceptor(); + + InstantiatingGrpcChannelProvider transportChannelProvider = + EchoSettings.defaultGrpcTransportProviderBuilder() + .setEndpoint(SECURE_ENDPOINT) + .setInterceptorProvider(() -> Collections.singletonList(interceptor)) + .setChannelConfigurator( + managedChannelBuilder -> { + if (managedChannelBuilder instanceof NettyChannelBuilder) { + try { + // Explicitly trust the self-signed CA certificate created by the local + // Showcase TLS connection without altering JVM-wide SSL trust stores. + ((NettyChannelBuilder) managedChannelBuilder) + .sslContext( + GrpcSslContexts.forClient() + .trustManager(new File(DEFAULT_CA_CERT_PATH)) + .build()); + } catch (Exception e) { + throw new RuntimeException("Failed to configure gRPC SSL context", e); + } + } + return managedChannelBuilder; + }) + .build(); + + EchoSettings settings = + EchoSettings.newBuilder() + .setCredentialsProvider(NoCredentialsProvider.create()) + .setTransportChannelProvider(transportChannelProvider) + .build(); + + try (EchoClient client = EchoClient.create(settings)) { + EchoResponse response = + client.echo(EchoRequest.newBuilder().setContent("pqc-grpc-tls-test").build()); + assertThat(response.getContent()).isEqualTo("pqc-grpc-tls-test"); + + Metadata capturedHeaders = interceptor.capturedMetadata; + assertThat(capturedHeaders).isNotNull(); + + // Verify that TLS 1.3 key exchange negotiated the expected PQC hybrid group (X25519MLKEM768). + String negotiatedGroup = getGrpcSingleHeaderString(capturedHeaders, TLS_GROUP_HEADER); + assertThat(negotiatedGroup).isEqualTo(EXPECTED_PQC_GROUP); + } + } + + /** + * Private gRPC client interceptor to capture the response headers from the Showcase server to + * verify the PQC algorithm. + */ + private static class GrpcTlsCapturingClientInterceptor implements ClientInterceptor { + final Metadata capturedMetadata = new Metadata(); + + @Override + public ClientCall interceptCall( + MethodDescriptor method, CallOptions callOptions, Channel next) { + return new ForwardingClientCall.SimpleForwardingClientCall( + next.newCall(method, callOptions)) { + @Override + public void start(Listener responseListener, Metadata headers) { + super.start( + new ForwardingClientCallListener.SimpleForwardingClientCallListener( + responseListener) { + @Override + public void onHeaders(Metadata headers) { + capturedMetadata.merge(headers); + super.onHeaders(headers); + } + }, + headers); + } + }; + } + } + + /** + * Private helper method required to extract a single string header from gRPC {@link Metadata}. + * + * @param metadata the captured gRPC response metadata + * @param name the case-insensitive HTTP/2 header name + * @return the string header value, or {@code null} if not present + */ + private static String getGrpcSingleHeaderString(Metadata metadata, String name) { + Metadata.Key key = Metadata.Key.of(name, Metadata.ASCII_STRING_MARSHALLER); + return metadata.get(key); + } } diff --git a/librarian.yaml b/librarian.yaml index fe4c6889f47f..0fd0b4b58840 100644 --- a/librarian.yaml +++ b/librarian.yaml @@ -30,7 +30,7 @@ tools: classifier: all-deps packaging: jar - name: protoc-gen-java_grpc - version: 1.82.2 + version: 1.83.0 group_id: io.grpc artifact_id: protoc-gen-grpc-java classifier: linux-x86_64 diff --git a/sdk-platform-java/gapic-generator-java-pom-parent/pom.xml b/sdk-platform-java/gapic-generator-java-pom-parent/pom.xml index 4b7b477219c5..c810ed161d02 100644 --- a/sdk-platform-java/gapic-generator-java-pom-parent/pom.xml +++ b/sdk-platform-java/gapic-generator-java-pom-parent/pom.xml @@ -27,13 +27,13 @@ 1.3.2 - 1.82.2 + 1.83.0 2.2.0 - 2.13.2 + 2.14.0 33.6.0-jre 4.33.6 1.62.0 - 2.48.0 + 2.50.0 1.0.0 3.1 1.7.0