mirror of https://github.com/grpc/grpc-java.git
xds: implement XdsServerCredentials (#7636)
Co-authored-by: Eric Anderson <ejona@google.com>
This commit is contained in:
parent
79d2e0c326
commit
620d266677
|
@ -49,9 +49,9 @@ public final class InternalNettyServerCredentials {
|
|||
* @throws IllegalArgumentException if unable to convert
|
||||
*/
|
||||
public static InternalProtocolNegotiator.ServerFactory toNegotiator(
|
||||
ServerCredentials channelCredentials) {
|
||||
ServerCredentials serverCredentials) {
|
||||
final ProtocolNegotiators.FromServerCredentialsResult result =
|
||||
ProtocolNegotiators.from(channelCredentials);
|
||||
ProtocolNegotiators.from(serverCredentials);
|
||||
if (result.error != null) {
|
||||
throw new IllegalArgumentException(result.error);
|
||||
}
|
||||
|
|
|
@ -17,12 +17,14 @@
|
|||
package io.grpc.xds;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.base.Preconditions;
|
||||
import io.grpc.Attributes;
|
||||
import io.grpc.ExperimentalApi;
|
||||
import io.grpc.ForwardingServerBuilder;
|
||||
import io.grpc.Internal;
|
||||
import io.grpc.Server;
|
||||
import io.grpc.ServerBuilder;
|
||||
import io.grpc.ServerCredentials;
|
||||
import io.grpc.Status;
|
||||
import io.grpc.netty.InternalNettyServerBuilder;
|
||||
import io.grpc.netty.InternalProtocolNegotiator.ProtocolNegotiator;
|
||||
|
@ -46,12 +48,14 @@ public final class XdsServerBuilder extends ForwardingServerBuilder<XdsServerBui
|
|||
|
||||
private final NettyServerBuilder delegate;
|
||||
private final int port;
|
||||
private final boolean freezeNegotiator;
|
||||
private ProtocolNegotiator fallbackProtocolNegotiator;
|
||||
private ErrorNotifier errorNotifier;
|
||||
|
||||
private XdsServerBuilder(NettyServerBuilder nettyDelegate, int port) {
|
||||
private XdsServerBuilder(NettyServerBuilder nettyDelegate, int port, boolean freezeNegotiator) {
|
||||
this.delegate = nettyDelegate;
|
||||
this.port = port;
|
||||
this.freezeNegotiator = freezeNegotiator;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -66,6 +70,7 @@ public final class XdsServerBuilder extends ForwardingServerBuilder<XdsServerBui
|
|||
*/
|
||||
@ExperimentalApi("https://github.com/grpc/grpc-java/issues/7514")
|
||||
public XdsServerBuilder useXdsSecurityWithPlaintextFallback() {
|
||||
Preconditions.checkState(!freezeNegotiator, "Method unavailable when using ServerCredentials");
|
||||
this.fallbackProtocolNegotiator = InternalProtocolNegotiators.serverPlaintext();
|
||||
return this;
|
||||
}
|
||||
|
@ -80,6 +85,7 @@ public final class XdsServerBuilder extends ForwardingServerBuilder<XdsServerBui
|
|||
@ExperimentalApi("https://github.com/grpc/grpc-java/issues/7514")
|
||||
public XdsServerBuilder useXdsSecurityWithTransportSecurityFallback(
|
||||
File certChain, File privateKey) throws SSLException {
|
||||
Preconditions.checkState(!freezeNegotiator, "Method unavailable when using ServerCredentials");
|
||||
SslContext sslContext = SslContextBuilder.forServer(certChain, privateKey).build();
|
||||
this.fallbackProtocolNegotiator = InternalProtocolNegotiators.serverTls(sslContext);
|
||||
return this;
|
||||
|
@ -95,6 +101,7 @@ public final class XdsServerBuilder extends ForwardingServerBuilder<XdsServerBui
|
|||
@ExperimentalApi("https://github.com/grpc/grpc-java/issues/7514")
|
||||
public XdsServerBuilder useXdsSecurityWithTransportSecurityFallback(
|
||||
InputStream certChain, InputStream privateKey) throws SSLException {
|
||||
Preconditions.checkState(!freezeNegotiator, "Method unavailable when using ServerCredentials");
|
||||
SslContext sslContext = SslContextBuilder.forServer(certChain, privateKey).build();
|
||||
this.fallbackProtocolNegotiator = InternalProtocolNegotiators.serverTls(sslContext);
|
||||
return this;
|
||||
|
@ -103,6 +110,7 @@ public final class XdsServerBuilder extends ForwardingServerBuilder<XdsServerBui
|
|||
/** Set the fallback protocolNegotiator. Pass null to unset a previously set value. */
|
||||
public XdsServerBuilder fallbackProtocolNegotiator(
|
||||
ProtocolNegotiator fallbackProtocolNegotiator) {
|
||||
Preconditions.checkState(!freezeNegotiator, "Method unavailable when using ServerCredentials");
|
||||
this.fallbackProtocolNegotiator = fallbackProtocolNegotiator;
|
||||
return this;
|
||||
}
|
||||
|
@ -116,7 +124,13 @@ public final class XdsServerBuilder extends ForwardingServerBuilder<XdsServerBui
|
|||
/** Creates a gRPC server builder for the given port. */
|
||||
public static XdsServerBuilder forPort(int port) {
|
||||
NettyServerBuilder nettyDelegate = NettyServerBuilder.forAddress(new InetSocketAddress(port));
|
||||
return new XdsServerBuilder(nettyDelegate, port);
|
||||
return new XdsServerBuilder(nettyDelegate, port, /* freezeNegotiator= */ false);
|
||||
}
|
||||
|
||||
/** Creates a gRPC server builder for the given port. */
|
||||
public static XdsServerBuilder forPort(int port, ServerCredentials serverCredentials) {
|
||||
NettyServerBuilder nettyDelegate = NettyServerBuilder.forPort(port, serverCredentials);
|
||||
return new XdsServerBuilder(nettyDelegate, port, /* freezeNegotiator= */ true);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright 2020 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.xds;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import io.grpc.ExperimentalApi;
|
||||
import io.grpc.ServerCredentials;
|
||||
import io.grpc.netty.InternalNettyServerCredentials;
|
||||
import io.grpc.netty.InternalProtocolNegotiator;
|
||||
import io.grpc.xds.internal.sds.SdsProtocolNegotiators;
|
||||
|
||||
@ExperimentalApi("https://github.com/grpc/grpc-java/issues/7621")
|
||||
public class XdsServerCredentials {
|
||||
private XdsServerCredentials() {} // prevent instantiation
|
||||
|
||||
/**
|
||||
* Creates credentials to be configured by xDS, falling back to other credentials if no
|
||||
* TLS configuration is provided by xDS.
|
||||
*
|
||||
* @param fallback Credentials to fall back to.
|
||||
*
|
||||
* @throws IllegalArgumentException if fallback is unable to be used
|
||||
*/
|
||||
public static ServerCredentials create(ServerCredentials fallback) {
|
||||
InternalProtocolNegotiator.ServerFactory fallbackNegotiator =
|
||||
InternalNettyServerCredentials.toNegotiator(checkNotNull(fallback, "fallback"));
|
||||
return InternalNettyServerCredentials.create(
|
||||
SdsProtocolNegotiators.serverProtocolNegotiatorFactory(fallbackNegotiator));
|
||||
}
|
||||
}
|
|
@ -21,6 +21,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
|||
import com.google.common.annotations.VisibleForTesting;
|
||||
import io.grpc.Attributes;
|
||||
import io.grpc.internal.GrpcUtil;
|
||||
import io.grpc.internal.ObjectPool;
|
||||
import io.grpc.netty.GrpcHttp2ConnectionHandler;
|
||||
import io.grpc.netty.InternalNettyChannelBuilder;
|
||||
import io.grpc.netty.InternalNettyChannelBuilder.ProtocolNegotiatorFactory;
|
||||
|
@ -42,6 +43,7 @@ import io.netty.util.AsciiString;
|
|||
import java.security.cert.CertStoreException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import javax.annotation.Nullable;
|
||||
|
@ -84,6 +86,11 @@ public final class SdsProtocolNegotiators {
|
|||
return new ClientFactory(fallbackNegotiator);
|
||||
}
|
||||
|
||||
public static InternalProtocolNegotiator.ServerFactory serverProtocolNegotiatorFactory(
|
||||
@Nullable InternalProtocolNegotiator.ServerFactory fallbackNegotiator) {
|
||||
return new ServerFactory(fallbackNegotiator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an SDS based {@link ProtocolNegotiator} for a {@link io.grpc.netty.NettyServerBuilder}.
|
||||
* If xDS returns no DownstreamTlsContext, it will fall back to plaintext.
|
||||
|
@ -95,6 +102,21 @@ public final class SdsProtocolNegotiators {
|
|||
return new ServerSdsProtocolNegotiator(fallbackProtocolNegotiator);
|
||||
}
|
||||
|
||||
private static final class ServerFactory implements InternalProtocolNegotiator.ServerFactory {
|
||||
|
||||
private final InternalProtocolNegotiator.ServerFactory fallbackProtocolNegotiator;
|
||||
|
||||
private ServerFactory(InternalProtocolNegotiator.ServerFactory fallbackNegotiator) {
|
||||
this.fallbackProtocolNegotiator = fallbackNegotiator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProtocolNegotiator newNegotiator(ObjectPool<? extends Executor> offloadExecutorPool) {
|
||||
return new ServerSdsProtocolNegotiator(
|
||||
fallbackProtocolNegotiator.newNegotiator(offloadExecutorPool));
|
||||
}
|
||||
}
|
||||
|
||||
private static final class ClientFactory implements InternalProtocolNegotiator.ClientFactory {
|
||||
|
||||
private final InternalProtocolNegotiator.ClientFactory fallbackProtocolNegotiator;
|
||||
|
|
|
@ -35,13 +35,14 @@ import io.grpc.Attributes;
|
|||
import io.grpc.EquivalentAddressGroup;
|
||||
import io.grpc.Grpc;
|
||||
import io.grpc.InsecureChannelCredentials;
|
||||
import io.grpc.InsecureServerCredentials;
|
||||
import io.grpc.ManagedChannelBuilder;
|
||||
import io.grpc.NameResolver;
|
||||
import io.grpc.NameResolverProvider;
|
||||
import io.grpc.NameResolverRegistry;
|
||||
import io.grpc.ServerCredentials;
|
||||
import io.grpc.Status;
|
||||
import io.grpc.StatusRuntimeException;
|
||||
import io.grpc.netty.InternalProtocolNegotiator.ProtocolNegotiator;
|
||||
import io.grpc.netty.InternalProtocolNegotiators;
|
||||
import io.grpc.stub.StreamObserver;
|
||||
import io.grpc.testing.GrpcCleanupRule;
|
||||
|
@ -51,7 +52,6 @@ import io.grpc.testing.protobuf.SimpleServiceGrpc;
|
|||
import io.grpc.xds.EnvoyServerProtoData.DownstreamTlsContext;
|
||||
import io.grpc.xds.EnvoyServerProtoData.UpstreamTlsContext;
|
||||
import io.grpc.xds.internal.sds.CommonTlsContextTestsUtil;
|
||||
import io.grpc.xds.internal.sds.SdsProtocolNegotiators;
|
||||
import io.grpc.xds.internal.sds.SslContextProviderSupplier;
|
||||
import io.grpc.xds.internal.sds.TlsContextManagerImpl;
|
||||
import io.grpc.xds.internal.sds.XdsChannelBuilder;
|
||||
|
@ -129,18 +129,12 @@ public class XdsSdsClientServerTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void nullFallbackProtocolNegotiator_expectException()
|
||||
throws IOException, URISyntaxException {
|
||||
buildServerWithTlsContext(/* downstreamTlsContext= */ null,
|
||||
/* fallbackProtocolNegotiator= */ null);
|
||||
|
||||
SimpleServiceGrpc.SimpleServiceBlockingStub blockingStub =
|
||||
getBlockingStub(/* upstreamTlsContext= */ null, /* overrideAuthority= */ null);
|
||||
public void nullFallbackCredentials_expectException() throws IOException, URISyntaxException {
|
||||
try {
|
||||
unaryRpc("buddy", blockingStub);
|
||||
buildServerWithTlsContext(/* downstreamTlsContext= */ null, /* fallbackCredentials= */ null);
|
||||
fail("exception expected");
|
||||
} catch (StatusRuntimeException sre) {
|
||||
assertThat(sre.getStatus().getCode()).isEqualTo(Status.UNAVAILABLE.getCode());
|
||||
} catch (NullPointerException npe) {
|
||||
assertThat(npe).hasMessageThat().isEqualTo("fallback");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -309,8 +303,8 @@ public class XdsSdsClientServerTest {
|
|||
final XdsClientWrapperForServerSds xdsClientWrapperForServerSds =
|
||||
XdsClientWrapperForServerSdsTest.createXdsClientWrapperForServerSds(
|
||||
port, /* downstreamTlsContext= */ downstreamTlsContext);
|
||||
buildServerWithFallbackProtocolNegotiator(xdsClientWrapperForServerSds,
|
||||
InternalProtocolNegotiators.serverPlaintext(), downstreamTlsContext);
|
||||
buildServerWithFallbackServerCredentials(
|
||||
xdsClientWrapperForServerSds, InsecureServerCredentials.create(), downstreamTlsContext);
|
||||
|
||||
XdsClient.ListenerWatcher listenerWatcher = xdsClientWrapperForServerSds.getListenerWatcher();
|
||||
|
||||
|
@ -323,46 +317,43 @@ public class XdsSdsClientServerTest {
|
|||
|
||||
private void buildServerWithTlsContext(DownstreamTlsContext downstreamTlsContext)
|
||||
throws IOException {
|
||||
buildServerWithTlsContext(downstreamTlsContext,
|
||||
InternalProtocolNegotiators.serverPlaintext());
|
||||
buildServerWithTlsContext(downstreamTlsContext, InsecureServerCredentials.create());
|
||||
}
|
||||
|
||||
private void buildServerWithTlsContext(DownstreamTlsContext downstreamTlsContext,
|
||||
ProtocolNegotiator fallbackProtocolNegotiator)
|
||||
private void buildServerWithTlsContext(
|
||||
DownstreamTlsContext downstreamTlsContext, ServerCredentials fallbackCredentials)
|
||||
throws IOException {
|
||||
XdsClient mockXdsClient = mock(XdsClient.class);
|
||||
XdsClientWrapperForServerSds xdsClientWrapperForServerSds =
|
||||
new XdsClientWrapperForServerSds(port);
|
||||
xdsClientWrapperForServerSds.start(mockXdsClient);
|
||||
buildServerWithFallbackProtocolNegotiator(
|
||||
xdsClientWrapperForServerSds, fallbackProtocolNegotiator, downstreamTlsContext);
|
||||
buildServerWithFallbackServerCredentials(
|
||||
xdsClientWrapperForServerSds, fallbackCredentials, downstreamTlsContext);
|
||||
}
|
||||
|
||||
private void buildServerWithFallbackProtocolNegotiator(
|
||||
private void buildServerWithFallbackServerCredentials(
|
||||
XdsClientWrapperForServerSds xdsClientWrapperForServerSds,
|
||||
ProtocolNegotiator fallbackProtocolNegotiator,
|
||||
ServerCredentials fallbackCredentials,
|
||||
DownstreamTlsContext downstreamTlsContext)
|
||||
throws IOException {
|
||||
SdsProtocolNegotiators.ServerSdsProtocolNegotiator serverSdsProtocolNegotiator =
|
||||
new SdsProtocolNegotiators.ServerSdsProtocolNegotiator(fallbackProtocolNegotiator);
|
||||
buildServer(
|
||||
port, serverSdsProtocolNegotiator, xdsClientWrapperForServerSds, downstreamTlsContext);
|
||||
ServerCredentials xdsCredentials = XdsServerCredentials.create(fallbackCredentials);
|
||||
buildServer(port, xdsCredentials, xdsClientWrapperForServerSds, downstreamTlsContext);
|
||||
}
|
||||
|
||||
private void buildServer(
|
||||
int port,
|
||||
SdsProtocolNegotiators.ServerSdsProtocolNegotiator serverSdsProtocolNegotiator,
|
||||
ServerCredentials serverCredentials,
|
||||
XdsClientWrapperForServerSds xdsClientWrapperForServerSds,
|
||||
DownstreamTlsContext downstreamTlsContext)
|
||||
throws IOException {
|
||||
XdsServerBuilder builder = XdsServerBuilder.forPort(port).addService(new SimpleServiceImpl());
|
||||
XdsServerBuilder builder = XdsServerBuilder.forPort(port, serverCredentials)
|
||||
.addService(new SimpleServiceImpl());
|
||||
XdsServerTestHelper.generateListenerUpdate(
|
||||
xdsClientWrapperForServerSds.getListenerWatcher(),
|
||||
port,
|
||||
downstreamTlsContext,
|
||||
downstreamTlsContext,
|
||||
/* tlsContext2= */null);
|
||||
cleanupRule.register(
|
||||
builder.buildServer(xdsClientWrapperForServerSds, serverSdsProtocolNegotiator)).start();
|
||||
cleanupRule.register(builder.buildServer(xdsClientWrapperForServerSds, null)).start();
|
||||
}
|
||||
|
||||
static EnvoyServerProtoData.Listener buildListener(
|
||||
|
|
Loading…
Reference in New Issue