Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
708dad6
feat(httpjson): add Conscrypt PQC support for HttpJson transports
lqiu96 Jul 21, 2026
e1e6de1
refactor(httpjson): restrict ITPqc to HttpJson PQC tests and remove p…
lqiu96 Jul 21, 2026
8bf75d3
refactor(httpjson): remove X25519Kyber768Draft00 from PQC groups and …
lqiu96 Jul 21, 2026
d371aa4
refactor(httpjson): group setSecurityProvider and setSslSocketConfigu…
lqiu96 Jul 21, 2026
d1ce9cd
docs(pqc): add detailed explanatory comments above Conscrypt try-catc…
lqiu96 Jul 21, 2026
086faf0
docs(pqc): add Level.FINE logger to HttpTransportOptions when Conscry…
lqiu96 Jul 21, 2026
94d825b
test(httpjson): remove reflection helper from InstantiatingHttpJsonCh…
lqiu96 Jul 21, 2026
5078cb9
test(pqc): add unit tests for PQC Conscrypt transport configuration i…
lqiu96 Jul 21, 2026
8d936f7
test(pqc): clean up reflection tests from InstantiatingHttpJsonChanne…
lqiu96 Jul 21, 2026
baf5769
refactor(pqc): fallback to fresh NetHttpTransport.Builder on Conscryp…
lqiu96 Jul 21, 2026
afbae79
refactor(showcase): streamline ITPqc transport setup and remove Consc…
lqiu96 Jul 21, 2026
3f0bec3
refactor(showcase): remove isConscryptFunctional fallback and restric…
lqiu96 Jul 21, 2026
e334f80
refactor(showcase): address PR review comments for ITPqc.java and add…
lqiu96 Jul 21, 2026
f17b615
docs(showcase): clarify rationale for classical named groups configur…
lqiu96 Jul 21, 2026
273a3f9
refactor(http): decouple PQC constants and add defensive lambda error…
lqiu96 Jul 21, 2026
46aaed3
fix(http): update log level to FINE and clarify fallback message for …
lqiu96 Jul 21, 2026
bc541e0
perf(http): lazily initialize and cache Conscrypt security provider i…
lqiu96 Jul 21, 2026
ee8b99d
refactor(http): use early returns in createHttpTransport and upgrade …
lqiu96 Jul 21, 2026
36f7601
docs(http): document architectural tradeoff decision for graceful Con…
lqiu96 Jul 21, 2026
f30f266
refactor(http): centralize Conscrypt PQC transport logic in HttpJsonT…
lqiu96 Jul 21, 2026
a52c88e
docs(http): update Conscrypt PQC Javadoc comments and method naming
lqiu96 Jul 21, 2026
7e5b30d
refactor(http): remove duplicate DEFAULT_PQC_GROUPS and simplify Cons…
lqiu96 Jul 21, 2026
b310138
docs(http): move environment fallback explanation to ConscryptProvide…
lqiu96 Jul 21, 2026
8e31771
docs(http): clarify caching rationale vs JDK TLS fallback in Conscryp…
lqiu96 Jul 21, 2026
3f3fcd4
refactor(showcase): rename ITPqc integration test to ITPostQuantumCry…
lqiu96 Jul 21, 2026
18cb2c3
ci(showcase): replace hardcoded sleep 2 with deterministic Bash /dev/…
lqiu96 Jul 21, 2026
5e0e429
deps(grpc): upgrade gRPC-Java to official release v1.83.0 and remove …
lqiu96 Jul 22, 2026
384f672
fix(showcase): fix Java 8 compilation in ITPostQuantumCryptography
lqiu96 Jul 22, 2026
5004ec3
fix(showcase): use Conscrypt.setNamedGroups directly without reflecti…
lqiu96 Jul 22, 2026
c28ce89
revert(pqc): restore grpc, guava, errorprone versions to match main o…
lqiu96 Jul 22, 2026
50e0e64
test(showcase): test default PQC NetHttpTransport creation in ITPostQ…
lqiu96 Jul 22, 2026
44ce5a3
refactor(gax-httpjson): rename createConscryptHttpTransportBuilder to…
lqiu96 Jul 22, 2026
6bd0eea
chore: Catch Exception instead of Throwable
lqiu96 Jul 22, 2026
e2f2456
Merge branch 'main' into pqc-httpjson-support
lqiu96 Jul 22, 2026
9f6ff2e
chore: Fix lint issues
lqiu96 Jul 22, 2026
c555d29
refactor(gax-httpjson): optimize PQC socket configurator with failure…
lqiu96 Jul 22, 2026
b236086
refactor(gax-httpjson): remove pqcNamedGroupsSupported flag and pass …
lqiu96 Jul 22, 2026
d57beae
test(showcase): save and restore original SSLContext in ITPostQuantum…
lqiu96 Jul 22, 2026
9b2b287
refactor(gax-httpjson): configure Conscrypt NetHttpTransport for defa…
lqiu96 Jul 22, 2026
68b7ee2
feat(gax-httpjson): support Conscrypt provider for mTLS and update no…
lqiu96 Jul 22, 2026
615a258
refactor(gax-httpjson): flatten configureMtls with early returns and …
lqiu96 Jul 22, 2026
116e4e8
chore: Address code comments
lqiu96 Jul 23, 2026
39ebb42
refactor(gax-httpjson): rename HttpJsonTransportUtils to HttpJsonCons…
lqiu96 Jul 23, 2026
4dafb68
test(gax-httpjson): add clean non-reflective unit tests for HttpJsonC…
lqiu96 Jul 23, 2026
6055878
fix(gax-httpjson): import Logger in InstantiatingHttpJsonChannelProvi…
lqiu96 Jul 23, 2026
56eb548
test(gax-httpjson): rename testBuilder_defaultHttpTransport_createsNe…
lqiu96 Jul 23, 2026
ed50fed
fix(gax-httpjson): add missing Logger import to InstantiatingHttpJson…
lqiu96 Jul 23, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions .github/workflows/showcase.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
outputs:
library: ${{ steps.filter.outputs.library }}
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4

Check warning on line 16 in .github/workflows/showcase.yaml

View workflow job for this annotation

GitHub Actions / zizmor-output

ref-version-mismatch

showcase.yaml:16: action's hash pin has mismatched or missing version comment: points to commit 11d5960a3267
with:
persist-credentials: false
- uses: dorny/paths-filter@fbd0ab8f3e69293af611ebaee6363fc25e6d187d # v4.0.1
Expand All @@ -32,7 +32,7 @@
name: "showcase (8)"
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4

Check warning on line 35 in .github/workflows/showcase.yaml

View workflow job for this annotation

GitHub Actions / zizmor-output

ref-version-mismatch

showcase.yaml:35: action's hash pin has mismatched or missing version comment: points to commit 11d5960a3267
with:
persist-credentials: false
- uses: actions/setup-java@c1e323688fd81a25caa38c78aa6df2d33d3e20d9 # v4
Expand Down Expand Up @@ -61,7 +61,22 @@
curl --location https://github.com/googleapis/gapic-showcase/releases/download/v${SHOWCASE_VERSION}/gapic-showcase-${SHOWCASE_VERSION}-linux-amd64.tar.gz --output /usr/src/showcase/showcase-${SHOWCASE_VERSION}-linux-amd64.tar.gz
cd /usr/src/showcase/
tar -xf showcase-*
# Start standard insecure showcase server on default port 7469 for standard integration tests
./gapic-showcase run &
# Start secure TLS showcase server on port 7470 for PQC TLS integration tests
./gapic-showcase run --port 7470 --tls --ca-cert-output-file /tmp/showcase-ca.pem &

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we use the secure TLS server for regular showcase tests?

@lqiu96 lqiu96 Jul 23, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Technically, I believe we can. We will just need to update all of the showcase clients to trust the local CA cert generated for the showcase server (since right now it trusts the well known public CA certs by default).

I think it's a bit more overhead unless you need to specifically test a TLS aspect (e.g. PQC TLS negotiation)

# Wait deterministically for both background showcase servers to finish binding ports 7469/7470
# and writing /tmp/showcase-ca.pem. Starting TLS requires RSA key generation and disk I/O,
# which can cause race conditions if tests start before /tmp/showcase-ca.pem is created.
for i in $(seq 1 30); do
if (echo > /dev/tcp/127.0.0.1/7469) 2>/dev/null && \
(echo > /dev/tcp/127.0.0.1/7470) 2>/dev/null && \
[ -f /tmp/showcase-ca.pem ]; then
echo "Showcase servers (ports 7469, 7470) and CA cert ready in attempt $i."
break
fi
sleep 0.2
done
cd -
- name: Showcase integration tests
working-directory: java-showcase
Expand Down Expand Up @@ -110,7 +125,7 @@
matrix:
java: [ 11, 17, 21, 25, 26 ]
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4

Check warning on line 128 in .github/workflows/showcase.yaml

View workflow job for this annotation

GitHub Actions / zizmor-output

ref-version-mismatch

showcase.yaml:128: action's hash pin has mismatched or missing version comment: points to commit 11d5960a3267
with:
persist-credentials: false
- uses: actions/setup-java@c1e323688fd81a25caa38c78aa6df2d33d3e20d9 # v4
Expand Down Expand Up @@ -166,7 +181,22 @@
curl --location https://github.com/googleapis/gapic-showcase/releases/download/v${SHOWCASE_VERSION}/gapic-showcase-${SHOWCASE_VERSION}-linux-amd64.tar.gz --output /usr/src/showcase/showcase-${SHOWCASE_VERSION}-linux-amd64.tar.gz
cd /usr/src/showcase/
tar -xf showcase-*
# Start standard insecure showcase server on default port 7469 for standard integration tests
./gapic-showcase run &
# Start secure TLS showcase server on port 7470 for PQC TLS integration tests
./gapic-showcase run --port 7470 --tls --ca-cert-output-file /tmp/showcase-ca.pem &
# Wait deterministically for both background showcase servers to finish binding ports 7469/7470
# and writing /tmp/showcase-ca.pem. Starting TLS requires RSA key generation and disk I/O,
# which can cause race conditions if tests start before /tmp/showcase-ca.pem is created.
for i in $(seq 1 30); do
if (echo > /dev/tcp/127.0.0.1/7469) 2>/dev/null && \
(echo > /dev/tcp/127.0.0.1/7470) 2>/dev/null && \
[ -f /tmp/showcase-ca.pem ]; then
echo "Showcase servers (ports 7469, 7470) and CA cert ready in attempt $i."
break
fi
sleep 0.2
done
cd -
- name: Showcase integration tests
working-directory: java-showcase
Expand Down Expand Up @@ -216,7 +246,7 @@
runs-on: ubuntu-22.04
steps:
- name: Checkout @ target branch
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4

Check warning on line 249 in .github/workflows/showcase.yaml

View workflow job for this annotation

GitHub Actions / zizmor-output

ref-version-mismatch

showcase.yaml:249: action's hash pin has mismatched or missing version comment: points to commit 11d5960a3267
with:
ref: ${{ github.base_ref }}
persist-credentials: false
Expand All @@ -238,7 +268,7 @@
echo "SHOWCASE_CLIENT_VERSION=$SHOWCASE_CLIENT_VERSION" >> "$GITHUB_ENV"
working-directory: java-showcase
- name: Checkout sdk-platform-java @ PR merge commit
uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3

Check warning on line 271 in .github/workflows/showcase.yaml

View workflow job for this annotation

GitHub Actions / zizmor-output

ref-version-mismatch

showcase.yaml:271: action's hash pin has mismatched or missing version comment: points to commit a37ce9120846
with:
persist-credentials: false
- name: Install sdk-platform-java @ PR merge commit
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,258 @@
/*
* Copyright 2026 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.google.showcase.v1beta1.it;

import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;

import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.gax.core.NoCredentialsProvider;
import com.google.api.gax.httpjson.HttpJsonConscryptUtils;
import com.google.api.gax.httpjson.HttpJsonMetadata;
import com.google.api.gax.httpjson.InstantiatingHttpJsonChannelProvider;
import com.google.showcase.v1beta1.EchoClient;
import com.google.showcase.v1beta1.EchoRequest;
import com.google.showcase.v1beta1.EchoResponse;
import com.google.showcase.v1beta1.EchoSettings;
import com.google.showcase.v1beta1.it.util.HttpJsonCapturingClientInterceptor;
import java.io.File;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.KeyStore;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.util.Collections;
import java.util.List;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;
import org.conscrypt.Conscrypt;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;

/**
* Integration tests to verify Post-Quantum Cryptography (PQC) TLS negotiation for HTTP/JSON (REST)
* clients.
*
* <p>These tests execute calls against a local secure (TLS-enabled) Showcase server. During the TLS
* handshake, the client and server negotiate cipher suites and key exchange groups. Showcase
* injects information about the negotiated TLS connection parameters into custom headers:
*
* <ul>
* <li>{@code x-showcase-tls-group}: The negotiated key exchange named group (e.g.
* X25519MLKEM768).
* <li>{@code x-showcase-tls-version}: The TLS version negotiated (e.g. TLS 1.3).
* <li>{@code x-showcase-tls-cipher}: The negotiated cipher suite (e.g. TLS_AES_128_GCM_SHA256).
* <li>{@code x-showcase-tls-client-supported-groups}: The list of groups offered by the client.
* </ul>
*
* <p>Verification cases:
*
* <ol>
* <li>{@code testHttpJsonPqc}: Verifies that HTTP/JSON transport defaults to Conscrypt and
* negotiates the hybrid post-quantum group {@code X25519MLKEM768}.
* <li>{@code testHttpJsonPqc_withExplicitSecurityProvider}: Verifies that overriding the
* transport's SSLSocketFactory to explicitly use standard JDK JSSE provider (SunJSSE) falls
* back gracefully to classical key exchange ({@code X25519}) instead of crashing.
* </ol>
*/
public class ITPostQuantumCryptography {

// TLS response header names from Showcase server
private static final String TLS_GROUP_HEADER = "x-showcase-tls-group";
private static final String TLS_SUPPORTED_GROUPS_HEADER =
"x-showcase-tls-client-supported-groups";

// Expected TLS parameters
private static final String EXPECTED_PQC_GROUP = "X25519MLKEM768";

private static final String DEFAULT_CA_CERT_PATH = getCaCertPath();

/**
* Resolves the absolute path to the Showcase server's CA certificate PEM file.
*
* @return absolute path to the CA certificate file
*/
private static String getCaCertPath() {
String prop = System.getProperty("showcase.ca.cert.path");
if (prop != null) {
return prop;
}
if (new File("/tmp/showcase-ca.pem").isFile()) {
return "/tmp/showcase-ca.pem";
}
return "target/showcase-ca.pem";
}

private static final String SECURE_ENDPOINT =
System.getProperty("showcase.secure.endpoint", "localhost:7470");

private static SSLContext originalSslContext;

@BeforeAll
static void setUp() throws Exception {
File certFile = new File(DEFAULT_CA_CERT_PATH);
assertWithMessage("CA certificate file not found at " + DEFAULT_CA_CERT_PATH)
.that(certFile.isFile())
.isTrue();

try {
originalSslContext = SSLContext.getDefault();
} catch (Throwable t) {
// Ignore if default SSLContext cannot be retrieved
}

// Register local Showcase CA cert in default SSLContext so the default NetHttpTransport trusts

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this step needed for PQC testing?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for TLS negotation, we need to establish a TLS connection. The showcase cert is a local, self-signed (I think) certificate and we need the ensure that the SSLContext can trust it. Essentially we are adding the local ca cert into our truststore

// the server
KeyStore trustStore = loadCaCert(DEFAULT_CA_CERT_PATH);
TrustManagerFactory tmf =
TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(trustStore);
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, tmf.getTrustManagers(), null);
SSLContext.setDefault(sslContext);
}
Comment thread
lqiu96 marked this conversation as resolved.

@AfterAll
static void tearDown() {
if (originalSslContext != null) {
try {
SSLContext.setDefault(originalSslContext);
} catch (Throwable t) {
// Ignore during test cleanup
}
}
}

@Test
void testHttpJsonPqc() throws Exception {
HttpJsonCapturingClientInterceptor interceptor = new HttpJsonCapturingClientInterceptor();

// Test that the Java client creates a PQC-compliant NetHttpTransport by default (no custom
// transport provided)
InstantiatingHttpJsonChannelProvider transportChannelProvider =
EchoSettings.defaultHttpJsonTransportProviderBuilder()
.setEndpoint("https://" + SECURE_ENDPOINT)
.setInterceptorProvider(() -> Collections.singletonList(interceptor))
.build();

EchoSettings settings =
EchoSettings.newHttpJsonBuilder()
.setCredentialsProvider(NoCredentialsProvider.create())
.setTransportChannelProvider(transportChannelProvider)
.build();

try (EchoClient client = EchoClient.create(settings)) {
EchoResponse response =
client.echo(EchoRequest.newBuilder().setContent("pqc-httpjson-test").build());
assertThat(response.getContent()).isEqualTo("pqc-httpjson-test");

HttpJsonMetadata capturedHeaders = interceptor.metadata;
assertThat(capturedHeaders).isNotNull();

String negotiatedGroup = getSingleHeaderString(capturedHeaders, TLS_GROUP_HEADER);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do these two headers mean? Are they just a way to verify correct algorithms are used?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From Alex's guide: https://github.com/googleapis/gapic-showcase/blob/8d881c63e8fddb82db17d56dcf2130400602d25a/TLS_GUIDE.md?plain=1#L89-L90

group header is the actual negotiated group selected
group header list is a list of possible groups that the client requests to use

assertThat(negotiatedGroup).isEqualTo(EXPECTED_PQC_GROUP);

String supportedGroups = getSingleHeaderString(capturedHeaders, TLS_SUPPORTED_GROUPS_HEADER);
assertThat(supportedGroups).isNotNull();
}
}

@Test
void testHttpJsonPqc_withExplicitClassicalGroupsNoPqc() throws Exception {
// This test explicitly configures non-PQC classical groups (X25519, SecP256r1) on Conscrypt
// to verify that the client falls back gracefully to classical TLS key exchange.
NetHttpTransport transport =
HttpJsonConscryptUtils.configureConscryptSecurityProvider(new NetHttpTransport.Builder())
.setSslSocketConfigurator(
socket -> {
if (Conscrypt.isConscrypt(socket)) {
Conscrypt.setNamedGroups(socket, new String[] {"X25519", "SecP256r1"});
}
})
Comment on lines +182 to +187

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

In testHttpJsonPqc_withExplicitSecurityProviderNoPqcGroups, the transport is explicitly configured to use the SunJSSE provider. Because of this, the socket will not be a Conscrypt socket, and Conscrypt.isConscrypt(socket) will return false. Consequently, the named groups are never restricted to classical curves on SunJSSE. On future JDK versions (e.g., JDK 27+) where SunJSSE enables PQC by default, this test will negotiate PQC and fail. We should use reflection to set the named groups on the standard JDK socket if supported.

            .setSslSocketConfigurator(
                socket -> {
                  if (Conscrypt.isConscrypt(socket)) {
                    Conscrypt.setNamedGroups(socket, new String[] {"X25519", "SecP256r1"});
                  } else {
                    try {
                      javax.net.ssl.SSLParameters params = socket.getSSLParameters();
                      java.lang.reflect.Method setNamedGroupsMethod =
                          javax.net.ssl.SSLParameters.class.getMethod("setNamedGroups", String[].class);
                      setNamedGroupsMethod.invoke(params, (Object) new String[] {"X25519", "SecP256r1"});
                      socket.setSSLParameters(params);
                    } catch (Exception e) {
                      // Ignore if setNamedGroups is not supported on this JDK version
                    }
                  }
                })

.build();

HttpJsonCapturingClientInterceptor interceptor = new HttpJsonCapturingClientInterceptor();

InstantiatingHttpJsonChannelProvider transportChannelProvider =
EchoSettings.defaultHttpJsonTransportProviderBuilder()
.setHttpTransport(transport)
.setEndpoint("https://" + SECURE_ENDPOINT)
.setInterceptorProvider(() -> Collections.singletonList(interceptor))
.build();

EchoSettings settings =
EchoSettings.newHttpJsonBuilder()
.setCredentialsProvider(NoCredentialsProvider.create())
.setTransportChannelProvider(transportChannelProvider)
.build();

try (EchoClient client = EchoClient.create(settings)) {
EchoResponse response =
client.echo(
EchoRequest.newBuilder().setContent("pqc-httpjson-explicit-provider-test").build());
assertThat(response.getContent()).isEqualTo("pqc-httpjson-explicit-provider-test");

HttpJsonMetadata capturedHeaders = interceptor.metadata;
assertThat(capturedHeaders).isNotNull();

String negotiatedGroup = getSingleHeaderString(capturedHeaders, TLS_GROUP_HEADER);
// Under classical non-PQC configuration, negotiated group is a classical curve
assertThat(negotiatedGroup).isAnyOf("X25519", "SecP256r1", "CurveP256");
assertThat(negotiatedGroup).isNotEqualTo(EXPECTED_PQC_GROUP);
}
}

/**
* Extracts the first string value of a specified HTTP response header from metadata.
*
* @param metadata the HTTP metadata containing response headers
* @param name the case-insensitive header key name
* @return header value string, or {@code null} if not found
*/
private static String getSingleHeaderString(HttpJsonMetadata metadata, String name) {
Object valueObj = metadata.getHeaders().get(name);
if (valueObj instanceof List) {
List<?> list = (List<?>) valueObj;
if (!list.isEmpty()) {
return String.valueOf(list.get(0));
}
} else if (valueObj != null) {
return String.valueOf(valueObj);
}
return null;
}

/**
* Loads an X.509 CA certificate file from disk into a new KeyStore instance.
*
* @param certPath path to the X.509 certificate file
* @return initialized KeyStore containing the certificate entry
* @throws Exception if reading or parsing the certificate fails
*/
private static KeyStore loadCaCert(String certPath) throws Exception {
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
trustStore.load(null, null);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
try (InputStream is = Files.newInputStream(Paths.get(certPath))) {
Certificate cert = cf.generateCertificate(is);
trustStore.setCertificateEntry("showcase-ca", cert);
}
return trustStore;
}
}
5 changes: 5 additions & 0 deletions sdk-platform-java/gax-java/gax-httpjson/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,11 @@
<artifactId>error_prone_annotations</artifactId>
<version>${errorprone.version}</version>
</dependency>
<dependency>
<groupId>org.conscrypt</groupId>
<artifactId>conscrypt-openjdk-uber</artifactId>
<version>${conscrypt.version}</version>
</dependency>
</dependencies>

<build>
Expand Down
Loading
Loading