Skip to content

Commit 860a865

Browse files
committed
feat(pqc): upgrade gRPC to 1.83.0 and add gRPC Showcase PQC integration tests
- Upgrade gRPC to 1.83.0 across sdk-platform-java, grpc-gcp-java, librarian, and related poms. - Upgrade errorprone.version to 2.50.0 and gson.version to 2.14.0 across parent poms, bigtable, datastore, and auth. - Add testGrpcPqc_withTls Showcase TLS integration test in ITPostQuantumCryptography.java. - Handle empty changed modules in .kokoro/build.sh to avoid whole-repo lint fallthrough on non-reactor changes.
1 parent 385e1f2 commit 860a865

8 files changed

Lines changed: 127 additions & 11 deletions

File tree

.kokoro/build.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,9 @@ case ${JOB_TYPE} in
283283
unique_modules=$(printf '%s\n' "${changed_modules[@]}" | sort -u | paste -sd ',' -)
284284
MODULE_FILTER="-pl ${unique_modules}"
285285
echo "Formatting only changed modules: ${unique_modules}"
286+
else
287+
echo "No lintable java modules affected. Skipping linter check."
288+
exit 0
286289
fi
287290
else
288291
echo "BASE_SHA or HEAD_SHA is empty. Cannot continue linting."

google-auth-library-java/pom.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,12 +80,12 @@
8080
<project.appengine.version>2.0.33</project.appengine.version>
8181
<project.findbugs.version>3.0.2</project.findbugs.version>
8282
<deploy.autorelease>false</deploy.autorelease>
83-
<project.error-prone.version>2.48.0</project.error-prone.version>
83+
<project.error-prone.version>2.50.0</project.error-prone.version>
8484
<project.protobuf.version>4.33.6</project.protobuf.version>
8585
<project.cel.version>0.9.0-proto3</project.cel.version>
8686
<project.tink.version>1.15.0</project.tink.version>
8787
<project.slf4j.version>2.0.17</project.slf4j.version>
88-
<project.gson.version>2.13.2</project.gson.version>
88+
<project.gson.version>2.14.0</project.gson.version>
8989
<project.api-common.version>2.68.0-SNAPSHOT</project.api-common.version><!-- {x-version-update:api-common:current} -->
9090
<project.commons-codec.version>1.18.0</project.commons-codec.version>
9191
<surefire.version>3.5.2</surefire.version>

grpc-gcp-java/pom.xml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,12 +64,12 @@
6464
<site.installationModule>grpc-gcp</site.installationModule>
6565
<api-common.version>2.68.0-SNAPSHOT</api-common.version><!-- {x-version-update:api-common:current} -->
6666
<auto-value.version>1.11.0</auto-value.version>
67-
<error-prone-annotations.version>2.48.0</error-prone-annotations.version>
67+
<error-prone-annotations.version>2.50.0</error-prone-annotations.version>
6868
<google-http-client.version>2.2.0</google-http-client.version>
69-
<gson.version>2.13.2</gson.version>
69+
<gson.version>2.14.0</gson.version>
7070
<guava.version>33.6.0-jre</guava.version>
7171
<protobuf.version>4.33.6</protobuf.version>
72-
<grpc.version>1.82.4</grpc.version>
72+
<grpc.version>1.83.0</grpc.version>
7373
<jsr305.version>3.0.2</jsr305.version>
7474
<junit.version>4.13.2</junit.version>
7575
<opencensus.version>0.31.1</opencensus.version>

java-bigtable/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@
144144
<github.global.server>github</github.global.server>
145145
<site.installationModule>google-cloud-bigtable-parent</site.installationModule>
146146
<project.javadoc.protobufBaseURL>https://googleapis.dev/java/google-api-grpc/latest</project.javadoc.protobufBaseURL>
147-
<errorprone.version>2.48.0</errorprone.version>
147+
<errorprone.version>2.50.0</errorprone.version>
148148
<errorprone.javac.args>-g</errorprone.javac.args>
149149
</properties>
150150

java-datastore/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@
144144
<github.global.server>github</github.global.server>
145145
<site.installationModule>google-cloud-datastore-parent</site.installationModule>
146146
<project.javadoc.protobufBaseURL>https://googleapis.dev/java/google-api-grpc/latest</project.javadoc.protobufBaseURL>
147-
<errorprone.version>2.48.0</errorprone.version>
147+
<errorprone.version>2.50.0</errorprone.version>
148148
<errorprone.javac.args>-g</errorprone.javac.args>
149149
</properties>
150150

java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/ITPostQuantumCryptography.java

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
import com.google.api.client.http.javanet.NetHttpTransport;
2323
import com.google.api.gax.core.NoCredentialsProvider;
24+
import com.google.api.gax.grpc.InstantiatingGrpcChannelProvider;
2425
import com.google.api.gax.httpjson.HttpJsonConscryptUtils;
2526
import com.google.api.gax.httpjson.HttpJsonMetadata;
2627
import com.google.api.gax.httpjson.InstantiatingHttpJsonChannelProvider;
@@ -29,6 +30,16 @@
2930
import com.google.showcase.v1beta1.EchoResponse;
3031
import com.google.showcase.v1beta1.EchoSettings;
3132
import com.google.showcase.v1beta1.it.util.HttpJsonCapturingClientInterceptor;
33+
import io.grpc.CallOptions;
34+
import io.grpc.Channel;
35+
import io.grpc.ClientCall;
36+
import io.grpc.ClientInterceptor;
37+
import io.grpc.ForwardingClientCall;
38+
import io.grpc.ForwardingClientCallListener;
39+
import io.grpc.Metadata;
40+
import io.grpc.MethodDescriptor;
41+
import io.grpc.netty.shaded.io.grpc.netty.GrpcSslContexts;
42+
import io.grpc.netty.shaded.io.grpc.netty.NettyChannelBuilder;
3243
import java.io.File;
3344
import java.io.InputStream;
3445
import java.nio.file.Files;
@@ -266,4 +277,106 @@ private static KeyStore loadCaCert(String certPath) throws Exception {
266277
}
267278
return trustStore;
268279
}
280+
281+
/**
282+
* Integration test to verify Post-Quantum Cryptography (PQC) TLS negotiation for gRPC clients.
283+
*
284+
* <p>In gRPC-Java 1.83.0+, the default Netty transport (`grpc-netty-shaded`) bundles BoringSSL
285+
* (`netty-tcnative-boringssl-static`) with built-in PQC hybrid key exchange support (e.g.,
286+
* X25519MLKEM768). No custom socket configurator or security provider swapping is needed.
287+
*
288+
* <p>Because the local Showcase test server uses a self-signed CA certificate (written to {@link
289+
* #DEFAULT_CA_CERT_PATH}), we configure the gRPC transport channel builder directly to trust this
290+
* certificate via {@link GrpcSslContexts#forClient()}. This avoids mutating global JVM system
291+
* properties in {@code setUp()} and ensures HTTP/JSON tests remain completely isolated.
292+
*/
293+
@Test
294+
void testGrpcPqc_withTls() throws Exception {
295+
GrpcTlsCapturingClientInterceptor interceptor = new GrpcTlsCapturingClientInterceptor();
296+
297+
InstantiatingGrpcChannelProvider transportChannelProvider =
298+
EchoSettings.defaultGrpcTransportProviderBuilder()
299+
.setEndpoint(SECURE_ENDPOINT)
300+
.setInterceptorProvider(() -> Collections.singletonList(interceptor))
301+
.setChannelConfigurator(
302+
managedChannelBuilder -> {
303+
if (managedChannelBuilder instanceof NettyChannelBuilder) {
304+
try {
305+
// Explicitly trust the self-signed CA certificate created by the local
306+
// Showcase TLS connection without altering JVM-wide SSL trust stores.
307+
((NettyChannelBuilder) managedChannelBuilder)
308+
.sslContext(
309+
GrpcSslContexts.forClient()
310+
.trustManager(new File(DEFAULT_CA_CERT_PATH))
311+
.build());
312+
} catch (Exception e) {
313+
throw new RuntimeException("Failed to configure gRPC SSL context", e);
314+
}
315+
}
316+
return managedChannelBuilder;
317+
})
318+
.build();
319+
320+
EchoSettings settings =
321+
EchoSettings.newBuilder()
322+
.setCredentialsProvider(NoCredentialsProvider.create())
323+
.setTransportChannelProvider(transportChannelProvider)
324+
.build();
325+
326+
try (EchoClient client = EchoClient.create(settings)) {
327+
EchoResponse response =
328+
client.echo(EchoRequest.newBuilder().setContent("pqc-grpc-tls-test").build());
329+
assertThat(response.getContent()).isEqualTo("pqc-grpc-tls-test");
330+
331+
Metadata capturedHeaders = interceptor.capturedMetadata;
332+
assertThat(capturedHeaders).isNotNull();
333+
334+
// Verify that TLS 1.3 key exchange negotiated the expected PQC hybrid group (X25519MLKEM768).
335+
String negotiatedGroup = getGrpcSingleHeaderString(capturedHeaders, TLS_GROUP_HEADER);
336+
assertThat(negotiatedGroup).isEqualTo(EXPECTED_PQC_GROUP);
337+
}
338+
}
339+
340+
/**
341+
* Private gRPC client interceptor to capture the response headers from the Showcase server to
342+
* verify the PQC algorithm.
343+
*/
344+
private static class GrpcTlsCapturingClientInterceptor implements ClientInterceptor {
345+
volatile Metadata capturedMetadata;
346+
347+
@Override
348+
public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(
349+
MethodDescriptor<ReqT, RespT> method, CallOptions callOptions, Channel next) {
350+
return new ForwardingClientCall.SimpleForwardingClientCall<ReqT, RespT>(
351+
next.newCall(method, callOptions)) {
352+
@Override
353+
public void start(Listener<RespT> responseListener, Metadata headers) {
354+
super.start(
355+
new ForwardingClientCallListener.SimpleForwardingClientCallListener<RespT>(
356+
responseListener) {
357+
@Override
358+
public void onHeaders(Metadata headers) {
359+
Metadata copy = new Metadata();
360+
copy.merge(headers);
361+
capturedMetadata = copy;
362+
super.onHeaders(headers);
363+
}
364+
},
365+
headers);
366+
}
367+
};
368+
}
369+
}
370+
371+
/**
372+
* Private helper method required to extract a single string header from gRPC {@link Metadata}.
373+
*
374+
* @param metadata the captured gRPC response metadata
375+
* @param name the case-insensitive HTTP/2 header name
376+
* @return the string header value, or {@code null} if not present
377+
*/
378+
private static String getGrpcSingleHeaderString(Metadata metadata, String name) {
379+
Metadata.Key<String> key = Metadata.Key.of(name, Metadata.ASCII_STRING_MARSHALLER);
380+
return metadata.get(key);
381+
}
269382
}

librarian.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ tools:
3030
classifier: all-deps
3131
packaging: jar
3232
- name: protoc-gen-java_grpc
33-
version: 1.82.4
33+
version: 1.83.0
3434
group_id: io.grpc
3535
artifact_id: protoc-gen-grpc-java
3636
classifier: linux-x86_64

sdk-platform-java/gapic-generator-java-pom-parent/pom.xml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,13 @@
2727
<!-- External dependencies, especially gRPC and Protobuf version, should be
2828
consistent across modules in this repository -->
2929
<javax.annotation-api.version>1.3.2</javax.annotation-api.version>
30-
<grpc.version>1.82.4</grpc.version>
30+
<grpc.version>1.83.0</grpc.version>
3131
<google.http-client.version>2.2.0</google.http-client.version>
32-
<gson.version>2.13.2</gson.version>
32+
<gson.version>2.14.0</gson.version>
3333
<guava.version>33.6.0-jre</guava.version>
3434
<protobuf.version>4.33.6</protobuf.version>
3535
<opentelemetry.version>1.62.0</opentelemetry.version>
36-
<errorprone.version>2.48.0</errorprone.version>
36+
<errorprone.version>2.50.0</errorprone.version>
3737
<jspecify.version>1.0.0</jspecify.version>
3838
<j2objc-annotations.version>3.1</j2objc-annotations.version>
3939
<threetenbp.version>1.7.0</threetenbp.version>

0 commit comments

Comments
 (0)