From a140e1bb0cfa662bcdb7823d73320eb8d49046f1 Mon Sep 17 00:00:00 2001 From: Riya Mehta <55350838+rmehta19@users.noreply.github.com> Date: Mon, 30 Sep 2024 09:49:09 -0700 Subject: [PATCH] s2a: Combine MtlsToS2ChannelCredentials and S2AChannelCredentials. (#11544) * Combine MtlsToS2ChannelCredentials and S2AChannelCredentials. * Check if file exists. * S2AChannelCredentials API requires credentials used for client-s2a channel. * remove MtlsToS2A library in BUILD. * Don't check state twice. * Don't check for file existence in tests. --- s2a/BUILD.bazel | 13 -- .../grpc/s2a/MtlsToS2AChannelCredentials.java | 89 ------------ .../io/grpc/s2a/S2AChannelCredentials.java | 25 ++-- .../s2a/MtlsToS2AChannelCredentialsTest.java | 135 ------------------ .../grpc/s2a/S2AChannelCredentialsTest.java | 68 ++++++--- .../grpc/s2a/handshaker/IntegrationTest.java | 35 +++-- 6 files changed, 79 insertions(+), 286 deletions(-) delete mode 100644 s2a/src/main/java/io/grpc/s2a/MtlsToS2AChannelCredentials.java delete mode 100644 s2a/src/test/java/io/grpc/s2a/MtlsToS2AChannelCredentialsTest.java diff --git a/s2a/BUILD.bazel b/s2a/BUILD.bazel index 5aeaedbe358..25ce2624f57 100644 --- a/s2a/BUILD.bazel +++ b/s2a/BUILD.bazel @@ -117,19 +117,6 @@ java_library( ], ) -java_library( - name = "mtls_to_s2av2_credentials", - srcs = ["src/main/java/io/grpc/s2a/MtlsToS2AChannelCredentials.java"], - visibility = ["//visibility:public"], - deps = [ - ":s2a_channel_pool", - ":s2av2_credentials", - "//api", - "//util", - artifact("com.google.guava:guava"), - ], -) - # bazel only accepts proto import with absolute path. genrule( name = "protobuf_imports", diff --git a/s2a/src/main/java/io/grpc/s2a/MtlsToS2AChannelCredentials.java b/s2a/src/main/java/io/grpc/s2a/MtlsToS2AChannelCredentials.java deleted file mode 100644 index e8eb01628ed..00000000000 --- a/s2a/src/main/java/io/grpc/s2a/MtlsToS2AChannelCredentials.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright 2024 The gRPC Authors - * - * 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 - * - * http://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 io.grpc.s2a; - -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkState; -import static com.google.common.base.Strings.isNullOrEmpty; - -import io.grpc.ChannelCredentials; -import io.grpc.ExperimentalApi; -import io.grpc.TlsChannelCredentials; -import java.io.File; -import java.io.IOException; - -/** - * Configures an {@code S2AChannelCredentials.Builder} instance with credentials used to establish a - * connection with the S2A to support talking to the S2A over mTLS. - */ -@ExperimentalApi("https://github.com/grpc/grpc-java/issues/11533") -public final class MtlsToS2AChannelCredentials { - /** - * Creates a {@code S2AChannelCredentials.Builder} builder, that talks to the S2A over mTLS. - * - * @param s2aAddress the address of the S2A server used to secure the connection. - * @param privateKeyPath the path to the private key PEM to use for authenticating to the S2A. - * @param certChainPath the path to the cert chain PEM to use for authenticating to the S2A. - * @param trustBundlePath the path to the trust bundle PEM. - * @return a {@code MtlsToS2AChannelCredentials.Builder} instance. - */ - public static Builder newBuilder( - String s2aAddress, String privateKeyPath, String certChainPath, String trustBundlePath) { - checkArgument(!isNullOrEmpty(s2aAddress), "S2A address must not be null or empty."); - checkArgument(!isNullOrEmpty(privateKeyPath), "privateKeyPath must not be null or empty."); - checkArgument(!isNullOrEmpty(certChainPath), "certChainPath must not be null or empty."); - checkArgument(!isNullOrEmpty(trustBundlePath), "trustBundlePath must not be null or empty."); - return new Builder(s2aAddress, privateKeyPath, certChainPath, trustBundlePath); - } - - /** Builds an {@code MtlsToS2AChannelCredentials} instance. */ - public static final class Builder { - private final String s2aAddress; - private final String privateKeyPath; - private final String certChainPath; - private final String trustBundlePath; - - Builder( - String s2aAddress, String privateKeyPath, String certChainPath, String trustBundlePath) { - this.s2aAddress = s2aAddress; - this.privateKeyPath = privateKeyPath; - this.certChainPath = certChainPath; - this.trustBundlePath = trustBundlePath; - } - - public S2AChannelCredentials.Builder build() throws IOException { - checkState(!isNullOrEmpty(s2aAddress), "S2A address must not be null or empty."); - checkState(!isNullOrEmpty(privateKeyPath), "privateKeyPath must not be null or empty."); - checkState(!isNullOrEmpty(certChainPath), "certChainPath must not be null or empty."); - checkState(!isNullOrEmpty(trustBundlePath), "trustBundlePath must not be null or empty."); - File privateKeyFile = new File(privateKeyPath); - File certChainFile = new File(certChainPath); - File trustBundleFile = new File(trustBundlePath); - - ChannelCredentials channelToS2ACredentials = - TlsChannelCredentials.newBuilder() - .keyManager(certChainFile, privateKeyFile) - .trustManager(trustBundleFile) - .build(); - - return S2AChannelCredentials.newBuilder(s2aAddress) - .setS2AChannelCredentials(channelToS2ACredentials); - } - } - - private MtlsToS2AChannelCredentials() {} -} \ No newline at end of file diff --git a/s2a/src/main/java/io/grpc/s2a/S2AChannelCredentials.java b/s2a/src/main/java/io/grpc/s2a/S2AChannelCredentials.java index ba0f6d72de1..12963a1395c 100644 --- a/s2a/src/main/java/io/grpc/s2a/S2AChannelCredentials.java +++ b/s2a/src/main/java/io/grpc/s2a/S2AChannelCredentials.java @@ -18,14 +18,12 @@ import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; -import static com.google.common.base.Preconditions.checkState; import static com.google.common.base.Strings.isNullOrEmpty; import com.google.errorprone.annotations.CanIgnoreReturnValue; import io.grpc.Channel; import io.grpc.ChannelCredentials; import io.grpc.ExperimentalApi; -import io.grpc.InsecureChannelCredentials; import io.grpc.internal.ObjectPool; import io.grpc.internal.SharedResourcePool; import io.grpc.netty.InternalNettyChannelCredentials; @@ -33,6 +31,7 @@ import io.grpc.s2a.channel.S2AHandshakerServiceChannel; import io.grpc.s2a.handshaker.S2AIdentity; import io.grpc.s2a.handshaker.S2AProtocolNegotiatorFactory; +import java.io.IOException; import javax.annotation.concurrent.NotThreadSafe; import org.checkerframework.checker.nullness.qual.Nullable; @@ -46,25 +45,27 @@ public final class S2AChannelCredentials { * Creates a channel credentials builder for establishing an S2A-secured connection. * * @param s2aAddress the address of the S2A server used to secure the connection. + * @param s2aChannelCredentials the credentials to be used when connecting to the S2A. * @return a {@code S2AChannelCredentials.Builder} instance. */ - public static Builder newBuilder(String s2aAddress) { + public static Builder newBuilder(String s2aAddress, ChannelCredentials s2aChannelCredentials) { checkArgument(!isNullOrEmpty(s2aAddress), "S2A address must not be null or empty."); - return new Builder(s2aAddress); + checkNotNull(s2aChannelCredentials, "S2A channel credentials must not be null"); + return new Builder(s2aAddress, s2aChannelCredentials); } /** Builds an {@code S2AChannelCredentials} instance. */ @NotThreadSafe public static final class Builder { private final String s2aAddress; + private final ChannelCredentials s2aChannelCredentials; private ObjectPool s2aChannelPool; - private ChannelCredentials s2aChannelCredentials; private @Nullable S2AIdentity localIdentity = null; - Builder(String s2aAddress) { + Builder(String s2aAddress, ChannelCredentials s2aChannelCredentials) { this.s2aAddress = s2aAddress; + this.s2aChannelCredentials = s2aChannelCredentials; this.s2aChannelPool = null; - this.s2aChannelCredentials = InsecureChannelCredentials.create(); } /** @@ -106,15 +107,7 @@ public Builder setLocalUid(String localUid) { return this; } - /** Sets the credentials to be used when connecting to the S2A. */ - @CanIgnoreReturnValue - public Builder setS2AChannelCredentials(ChannelCredentials s2aChannelCredentials) { - this.s2aChannelCredentials = s2aChannelCredentials; - return this; - } - - public ChannelCredentials build() { - checkState(!isNullOrEmpty(s2aAddress), "S2A address must not be null or empty."); + public ChannelCredentials build() throws IOException { ObjectPool s2aChannelPool = SharedResourcePool.forResource( S2AHandshakerServiceChannel.getChannelResource(s2aAddress, s2aChannelCredentials)); diff --git a/s2a/src/test/java/io/grpc/s2a/MtlsToS2AChannelCredentialsTest.java b/s2a/src/test/java/io/grpc/s2a/MtlsToS2AChannelCredentialsTest.java deleted file mode 100644 index 0fc4ecb3268..00000000000 --- a/s2a/src/test/java/io/grpc/s2a/MtlsToS2AChannelCredentialsTest.java +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright 2024 The gRPC Authors - * - * 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 - * - * http://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 io.grpc.s2a; - -import static com.google.common.truth.Truth.assertThat; -import static org.junit.Assert.assertThrows; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -public final class MtlsToS2AChannelCredentialsTest { - @Test - public void newBuilder_nullAddress_throwsException() throws Exception { - assertThrows( - IllegalArgumentException.class, - () -> - MtlsToS2AChannelCredentials.newBuilder( - /* s2aAddress= */ null, - /* privateKeyPath= */ "src/test/resources/client_key.pem", - /* certChainPath= */ "src/test/resources/client_cert.pem", - /* trustBundlePath= */ "src/test/resources/root_cert.pem")); - } - - @Test - public void newBuilder_nullPrivateKeyPath_throwsException() throws Exception { - assertThrows( - IllegalArgumentException.class, - () -> - MtlsToS2AChannelCredentials.newBuilder( - /* s2aAddress= */ "s2a_address", - /* privateKeyPath= */ null, - /* certChainPath= */ "src/test/resources/client_cert.pem", - /* trustBundlePath= */ "src/test/resources/root_cert.pem")); - } - - @Test - public void newBuilder_nullCertChainPath_throwsException() throws Exception { - assertThrows( - IllegalArgumentException.class, - () -> - MtlsToS2AChannelCredentials.newBuilder( - /* s2aAddress= */ "s2a_address", - /* privateKeyPath= */ "src/test/resources/client_key.pem", - /* certChainPath= */ null, - /* trustBundlePath= */ "src/test/resources/root_cert.pem")); - } - - @Test - public void newBuilder_nullTrustBundlePath_throwsException() throws Exception { - assertThrows( - IllegalArgumentException.class, - () -> - MtlsToS2AChannelCredentials.newBuilder( - /* s2aAddress= */ "s2a_address", - /* privateKeyPath= */ "src/test/resources/client_key.pem", - /* certChainPath= */ "src/test/resources/client_cert.pem", - /* trustBundlePath= */ null)); - } - - @Test - public void newBuilder_emptyAddress_throwsException() throws Exception { - assertThrows( - IllegalArgumentException.class, - () -> - MtlsToS2AChannelCredentials.newBuilder( - /* s2aAddress= */ "", - /* privateKeyPath= */ "src/test/resources/client_key.pem", - /* certChainPath= */ "src/test/resources/client_cert.pem", - /* trustBundlePath= */ "src/test/resources/root_cert.pem")); - } - - @Test - public void newBuilder_emptyPrivateKeyPath_throwsException() throws Exception { - assertThrows( - IllegalArgumentException.class, - () -> - MtlsToS2AChannelCredentials.newBuilder( - /* s2aAddress= */ "s2a_address", - /* privateKeyPath= */ "", - /* certChainPath= */ "src/test/resources/client_cert.pem", - /* trustBundlePath= */ "src/test/resources/root_cert.pem")); - } - - @Test - public void newBuilder_emptyCertChainPath_throwsException() throws Exception { - assertThrows( - IllegalArgumentException.class, - () -> - MtlsToS2AChannelCredentials.newBuilder( - /* s2aAddress= */ "s2a_address", - /* privateKeyPath= */ "src/test/resources/client_key.pem", - /* certChainPath= */ "", - /* trustBundlePath= */ "src/test/resources/root_cert.pem")); - } - - @Test - public void newBuilder_emptyTrustBundlePath_throwsException() throws Exception { - assertThrows( - IllegalArgumentException.class, - () -> - MtlsToS2AChannelCredentials.newBuilder( - /* s2aAddress= */ "s2a_address", - /* privateKeyPath= */ "src/test/resources/client_key.pem", - /* certChainPath= */ "src/test/resources/client_cert.pem", - /* trustBundlePath= */ "")); - } - - @Test - public void build_s2AChannelCredentials_success() throws Exception { - assertThat( - MtlsToS2AChannelCredentials.newBuilder( - /* s2aAddress= */ "s2a_address", - /* privateKeyPath= */ "src/test/resources/client_key.pem", - /* certChainPath= */ "src/test/resources/client_cert.pem", - /* trustBundlePath= */ "src/test/resources/root_cert.pem") - .build()) - .isInstanceOf(S2AChannelCredentials.Builder.class); - } -} \ No newline at end of file diff --git a/s2a/src/test/java/io/grpc/s2a/S2AChannelCredentialsTest.java b/s2a/src/test/java/io/grpc/s2a/S2AChannelCredentialsTest.java index e766aa3f145..fd5bfd654f3 100644 --- a/s2a/src/test/java/io/grpc/s2a/S2AChannelCredentialsTest.java +++ b/s2a/src/test/java/io/grpc/s2a/S2AChannelCredentialsTest.java @@ -20,6 +20,7 @@ import static org.junit.Assert.assertThrows; import io.grpc.ChannelCredentials; +import io.grpc.InsecureChannelCredentials; import io.grpc.TlsChannelCredentials; import java.io.File; import org.junit.Test; @@ -30,40 +31,51 @@ @RunWith(JUnit4.class) public final class S2AChannelCredentialsTest { @Test - public void newBuilder_nullArgument_throwsException() throws Exception { - assertThrows(IllegalArgumentException.class, () -> S2AChannelCredentials.newBuilder(null)); + public void newBuilder_nullAddress_throwsException() throws Exception { + assertThrows(IllegalArgumentException.class, () -> S2AChannelCredentials.newBuilder(null, + InsecureChannelCredentials.create())); } @Test public void newBuilder_emptyAddress_throwsException() throws Exception { - assertThrows(IllegalArgumentException.class, () -> S2AChannelCredentials.newBuilder("")); + assertThrows(IllegalArgumentException.class, () -> S2AChannelCredentials.newBuilder("", + InsecureChannelCredentials.create())); + } + + @Test + public void newBuilder_nullChannelCreds_throwsException() throws Exception { + assertThrows(NullPointerException.class, () -> S2AChannelCredentials + .newBuilder("s2a_address", null)); } @Test public void setLocalSpiffeId_nullArgument_throwsException() throws Exception { assertThrows( NullPointerException.class, - () -> S2AChannelCredentials.newBuilder("s2a_address").setLocalSpiffeId(null)); + () -> S2AChannelCredentials.newBuilder("s2a_address", + InsecureChannelCredentials.create()).setLocalSpiffeId(null)); } @Test public void setLocalHostname_nullArgument_throwsException() throws Exception { assertThrows( NullPointerException.class, - () -> S2AChannelCredentials.newBuilder("s2a_address").setLocalHostname(null)); + () -> S2AChannelCredentials.newBuilder("s2a_address", + InsecureChannelCredentials.create()).setLocalHostname(null)); } @Test public void setLocalUid_nullArgument_throwsException() throws Exception { assertThrows( NullPointerException.class, - () -> S2AChannelCredentials.newBuilder("s2a_address").setLocalUid(null)); + () -> S2AChannelCredentials.newBuilder("s2a_address", + InsecureChannelCredentials.create()).setLocalUid(null)); } @Test public void build_withLocalSpiffeId_succeeds() throws Exception { assertThat( - S2AChannelCredentials.newBuilder("s2a_address") + S2AChannelCredentials.newBuilder("s2a_address", InsecureChannelCredentials.create()) .setLocalSpiffeId("spiffe://test") .build()) .isNotNull(); @@ -72,7 +84,7 @@ public void build_withLocalSpiffeId_succeeds() throws Exception { @Test public void build_withLocalHostname_succeeds() throws Exception { assertThat( - S2AChannelCredentials.newBuilder("s2a_address") + S2AChannelCredentials.newBuilder("s2a_address", InsecureChannelCredentials.create()) .setLocalHostname("local_hostname") .build()) .isNotNull(); @@ -80,33 +92,47 @@ public void build_withLocalHostname_succeeds() throws Exception { @Test public void build_withLocalUid_succeeds() throws Exception { - assertThat(S2AChannelCredentials.newBuilder("s2a_address").setLocalUid("local_uid").build()) + assertThat(S2AChannelCredentials.newBuilder("s2a_address", + InsecureChannelCredentials.create()).setLocalUid("local_uid").build()) .isNotNull(); } @Test public void build_withNoLocalIdentity_succeeds() throws Exception { - assertThat(S2AChannelCredentials.newBuilder("s2a_address").build()) + assertThat(S2AChannelCredentials.newBuilder("s2a_address", + InsecureChannelCredentials.create()).build()) .isNotNull(); } - + @Test - public void build_withTlsChannelCredentials_succeeds() throws Exception { + public void build_withUseMtlsToS2ANoLocalIdentity_success() throws Exception { + ChannelCredentials s2aChannelCredentials = getTlsChannelCredentials(); assertThat( - S2AChannelCredentials.newBuilder("s2a_address") - .setLocalSpiffeId("spiffe://test") - .setS2AChannelCredentials(getTlsChannelCredentials()) + S2AChannelCredentials.newBuilder("s2a_address", s2aChannelCredentials) + .build()) + .isNotNull(); + } + + @Test + public void build_withUseMtlsToS2AWithLocalUid_success() throws Exception { + ChannelCredentials s2aChannelCredentials = getTlsChannelCredentials(); + assertThat( + S2AChannelCredentials.newBuilder("s2a_address", s2aChannelCredentials) + .setLocalUid("local_uid") .build()) .isNotNull(); } private static ChannelCredentials getTlsChannelCredentials() throws Exception { - File clientCert = new File("src/test/resources/client_cert.pem"); - File clientKey = new File("src/test/resources/client_key.pem"); - File rootCert = new File("src/test/resources/root_cert.pem"); + String privateKeyPath = "src/test/resources/client_key.pem"; + String certChainPath = "src/test/resources/client_cert.pem"; + String trustBundlePath = "src/test/resources/root_cert.pem"; + File privateKeyFile = new File(privateKeyPath); + File certChainFile = new File(certChainPath); + File trustBundleFile = new File(trustBundlePath); return TlsChannelCredentials.newBuilder() - .keyManager(clientCert, clientKey) - .trustManager(rootCert) - .build(); + .keyManager(certChainFile, privateKeyFile) + .trustManager(trustBundleFile) + .build(); } } \ No newline at end of file diff --git a/s2a/src/test/java/io/grpc/s2a/handshaker/IntegrationTest.java b/s2a/src/test/java/io/grpc/s2a/handshaker/IntegrationTest.java index 2a2b1f246ec..0fb9b12cf95 100644 --- a/s2a/src/test/java/io/grpc/s2a/handshaker/IntegrationTest.java +++ b/s2a/src/test/java/io/grpc/s2a/handshaker/IntegrationTest.java @@ -21,15 +21,16 @@ import io.grpc.ChannelCredentials; import io.grpc.Grpc; +import io.grpc.InsecureChannelCredentials; import io.grpc.ManagedChannel; import io.grpc.Server; import io.grpc.ServerBuilder; import io.grpc.ServerCredentials; +import io.grpc.TlsChannelCredentials; import io.grpc.TlsServerCredentials; import io.grpc.benchmarks.Utils; import io.grpc.netty.GrpcSslContexts; import io.grpc.netty.NettyServerBuilder; -import io.grpc.s2a.MtlsToS2AChannelCredentials; import io.grpc.s2a.S2AChannelCredentials; import io.grpc.s2a.handshaker.FakeS2AServer; import io.grpc.stub.StreamObserver; @@ -124,7 +125,8 @@ public void tearDown() throws Exception { @Test public void clientCommunicateUsingS2ACredentials_succeeds() throws Exception { ChannelCredentials credentials = - S2AChannelCredentials.newBuilder(s2aAddress).setLocalSpiffeId("test-spiffe-id").build(); + S2AChannelCredentials.newBuilder(s2aAddress, InsecureChannelCredentials.create()) + .setLocalSpiffeId("test-spiffe-id").build(); ManagedChannel channel = Grpc.newChannelBuilder(serverAddress, credentials).build(); assertThat(doUnaryRpc(channel)).isTrue(); @@ -132,7 +134,8 @@ public void clientCommunicateUsingS2ACredentials_succeeds() throws Exception { @Test public void clientCommunicateUsingS2ACredentialsNoLocalIdentity_succeeds() throws Exception { - ChannelCredentials credentials = S2AChannelCredentials.newBuilder(s2aAddress).build(); + ChannelCredentials credentials = S2AChannelCredentials.newBuilder(s2aAddress, + InsecureChannelCredentials.create()).build(); ManagedChannel channel = Grpc.newChannelBuilder(serverAddress, credentials).build(); assertThat(doUnaryRpc(channel)).isTrue(); @@ -140,15 +143,22 @@ public void clientCommunicateUsingS2ACredentialsNoLocalIdentity_succeeds() throw @Test public void clientCommunicateUsingMtlsToS2ACredentials_succeeds() throws Exception { + String privateKeyPath = "src/test/resources/client_key.pem"; + String certChainPath = "src/test/resources/client_cert.pem"; + String trustBundlePath = "src/test/resources/root_cert.pem"; + File privateKeyFile = new File(privateKeyPath); + File certChainFile = new File(certChainPath); + File trustBundleFile = new File(trustBundlePath); + ChannelCredentials s2aChannelCredentials = + TlsChannelCredentials.newBuilder() + .keyManager(certChainFile, privateKeyFile) + .trustManager(trustBundleFile) + .build(); + ChannelCredentials credentials = - MtlsToS2AChannelCredentials.newBuilder( - /* s2aAddress= */ mtlsS2AAddress, - /* privateKeyPath= */ "src/test/resources/client_key.pem", - /* certChainPath= */ "src/test/resources/client_cert.pem", - /* trustBundlePath= */ "src/test/resources/root_cert.pem") - .build() - .setLocalSpiffeId("test-spiffe-id") - .build(); + S2AChannelCredentials.newBuilder(mtlsS2AAddress, s2aChannelCredentials) + .setLocalSpiffeId("test-spiffe-id") + .build(); ManagedChannel channel = Grpc.newChannelBuilder(serverAddress, credentials).build(); assertThat(doUnaryRpc(channel)).isTrue(); @@ -156,7 +166,8 @@ public void clientCommunicateUsingMtlsToS2ACredentials_succeeds() throws Excepti @Test public void clientCommunicateUsingS2ACredentials_s2AdelayStart_succeeds() throws Exception { - ChannelCredentials credentials = S2AChannelCredentials.newBuilder(s2aDelayAddress).build(); + ChannelCredentials credentials = S2AChannelCredentials.newBuilder(s2aDelayAddress, + InsecureChannelCredentials.create()).build(); ManagedChannel channel = Grpc.newChannelBuilder(serverAddress, credentials).build(); FutureTask rpc = new FutureTask<>(() -> doUnaryRpc(channel));