alts: Expose ChannelCredentials for the various negotiators

AltsChannelBuilder could be improved a bit more by removing the call to
InternalNettyChannelBuilder.setProtocolNegotiatorFactory. However, to do
that cleanest would require reworking how port is plumbed in
NettyChannelBuilder and potentially AbstractManagedChannelImplBuilder to
move getDefaultPort() to ProtocolNegotiator from ClientFactory. Saving
that for another day.
This commit is contained in:
Eric Anderson 2020-08-05 22:26:50 -07:00 committed by Eric Anderson
parent e595779047
commit 5a687e3da8
12 changed files with 394 additions and 245 deletions

View File

@ -17,26 +17,14 @@
package io.grpc.alts;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
import io.grpc.CallOptions;
import io.grpc.Channel;
import io.grpc.ClientCall;
import io.grpc.ClientInterceptor;
import io.grpc.ExperimentalApi;
import io.grpc.ForwardingChannelBuilder;
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
import io.grpc.MethodDescriptor;
import io.grpc.Status;
import io.grpc.alts.internal.AltsProtocolNegotiator.ClientAltsProtocolNegotiatorFactory;
import io.grpc.internal.GrpcUtil;
import io.grpc.internal.ObjectPool;
import io.grpc.internal.SharedResourcePool;
import io.grpc.netty.InternalNettyChannelBuilder;
import io.grpc.netty.InternalProtocolNegotiator.ProtocolNegotiator;
import io.grpc.netty.NettyChannelBuilder;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.Nullable;
/**
@ -45,14 +33,9 @@ import javax.annotation.Nullable;
*/
@ExperimentalApi("https://github.com/grpc/grpc-java/issues/4151")
public final class AltsChannelBuilder extends ForwardingChannelBuilder<AltsChannelBuilder> {
private static final Logger logger = Logger.getLogger(AltsChannelBuilder.class.getName());
private final NettyChannelBuilder delegate;
private final ImmutableList.Builder<String> targetServiceAccountsBuilder =
ImmutableList.builder();
private ObjectPool<Channel> handshakerChannelPool =
SharedResourcePool.forResource(HandshakerServiceChannel.SHARED_HANDSHAKER_CHANNEL);
private boolean enableUntrustedAlts;
private final AltsChannelCredentials.Builder credentialsBuilder =
new AltsChannelCredentials.Builder();
/** "Overrides" the static method in {@link ManagedChannelBuilder}. */
public static final AltsChannelBuilder forTarget(String target) {
@ -73,7 +56,7 @@ public final class AltsChannelBuilder extends ForwardingChannelBuilder<AltsChann
* service account in the handshaker result. Otherwise, the handshake fails.
*/
public AltsChannelBuilder addTargetServiceAccount(String targetServiceAccount) {
targetServiceAccountsBuilder.add(targetServiceAccount);
credentialsBuilder.addTargetServiceAccount(targetServiceAccount);
return this;
}
@ -82,17 +65,13 @@ public final class AltsChannelBuilder extends ForwardingChannelBuilder<AltsChann
* is running on Google Cloud Platform.
*/
public AltsChannelBuilder enableUntrustedAltsForTesting() {
enableUntrustedAlts = true;
credentialsBuilder.enableUntrustedAltsForTesting();
return this;
}
/** Sets a new handshaker service address for testing. */
public AltsChannelBuilder setHandshakerAddressForTesting(String handshakerAddress) {
// Instead of using the default shared channel to the handshaker service, create a separate
// resource to the test address.
handshakerChannelPool =
SharedResourcePool.forResource(
HandshakerServiceChannel.getHandshakerChannelForTesting(handshakerAddress));
credentialsBuilder.setHandshakerAddressForTesting(handshakerAddress);
return this;
}
@ -103,22 +82,9 @@ public final class AltsChannelBuilder extends ForwardingChannelBuilder<AltsChann
@Override
public ManagedChannel build() {
if (!CheckGcpEnvironment.isOnGcp()) {
if (enableUntrustedAlts) {
logger.log(
Level.WARNING,
"Untrusted ALTS mode is enabled and we cannot guarantee the trustworthiness of the "
+ "ALTS handshaker service");
} else {
Status status =
Status.INTERNAL.withDescription("ALTS is only allowed to run on Google Cloud Platform");
delegate().intercept(new FailingClientInterceptor(status));
}
}
InternalNettyChannelBuilder.setProtocolNegotiatorFactory(
delegate(),
new ClientAltsProtocolNegotiatorFactory(
targetServiceAccountsBuilder.build(), handshakerChannelPool));
credentialsBuilder.buildProtocolNegotiatorFactory());
return delegate().build();
}
@ -126,24 +92,6 @@ public final class AltsChannelBuilder extends ForwardingChannelBuilder<AltsChann
@VisibleForTesting
@Nullable
ProtocolNegotiator getProtocolNegotiatorForTest() {
return new ClientAltsProtocolNegotiatorFactory(
targetServiceAccountsBuilder.build(), handshakerChannelPool)
.buildProtocolNegotiator();
}
/** An implementation of {@link ClientInterceptor} that fails each call. */
static final class FailingClientInterceptor implements ClientInterceptor {
private final Status status;
public FailingClientInterceptor(Status status) {
this.status = status;
}
@Override
public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(
MethodDescriptor<ReqT, RespT> method, CallOptions callOptions, Channel next) {
return new FailingClientCall<>(status);
}
return credentialsBuilder.buildProtocolNegotiatorFactory().newNegotiator();
}
}

View File

@ -0,0 +1,158 @@
/*
* 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.alts;
import com.google.common.collect.ImmutableList;
import io.grpc.Channel;
import io.grpc.ChannelCredentials;
import io.grpc.ExperimentalApi;
import io.grpc.Status;
import io.grpc.alts.internal.AltsProtocolNegotiator.ClientAltsProtocolNegotiatorFactory;
import io.grpc.internal.ObjectPool;
import io.grpc.internal.SharedResourcePool;
import io.grpc.netty.GrpcHttp2ConnectionHandler;
import io.grpc.netty.InternalNettyChannelCredentials;
import io.grpc.netty.InternalProtocolNegotiator;
import io.grpc.netty.InternalProtocolNegotiator.ProtocolNegotiator;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;
import io.netty.util.AsciiString;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Provides secure and authenticated commmunication between two cloud VMs using ALTS.
*/
@ExperimentalApi("https://github.com/grpc/grpc-java/issues/4151")
public final class AltsChannelCredentials {
private static final Logger logger = Logger.getLogger(AltsChannelCredentials.class.getName());
private AltsChannelCredentials() {}
public static ChannelCredentials create() {
return newBuilder().build();
}
public static Builder newBuilder() {
return new Builder();
}
public static final class Builder {
private final ImmutableList.Builder<String> targetServiceAccountsBuilder =
ImmutableList.builder();
private ObjectPool<Channel> handshakerChannelPool =
SharedResourcePool.forResource(HandshakerServiceChannel.SHARED_HANDSHAKER_CHANNEL);
private boolean enableUntrustedAlts;
/**
* Adds an expected target service accounts. One of the added service accounts should match peer
* service account in the handshaker result. Otherwise, the handshake fails.
*/
public Builder addTargetServiceAccount(String targetServiceAccount) {
targetServiceAccountsBuilder.add(targetServiceAccount);
return this;
}
/**
* Enables untrusted ALTS for testing. If this function is called, we will not check whether
* ALTS is running on Google Cloud Platform.
*/
public Builder enableUntrustedAltsForTesting() {
enableUntrustedAlts = true;
return this;
}
/** Sets a new handshaker service address for testing. */
public Builder setHandshakerAddressForTesting(String handshakerAddress) {
// Instead of using the default shared channel to the handshaker service, create a separate
// resource to the test address.
handshakerChannelPool =
SharedResourcePool.forResource(
HandshakerServiceChannel.getHandshakerChannelForTesting(handshakerAddress));
return this;
}
public ChannelCredentials build() {
return InternalNettyChannelCredentials.create(buildProtocolNegotiatorFactory());
}
InternalProtocolNegotiator.ClientFactory buildProtocolNegotiatorFactory() {
if (!CheckGcpEnvironment.isOnGcp()) {
if (enableUntrustedAlts) {
logger.log(
Level.WARNING,
"Untrusted ALTS mode is enabled and we cannot guarantee the trustworthiness of the "
+ "ALTS handshaker service");
} else {
Status status = Status.INTERNAL.withDescription(
"ALTS is only allowed to run on Google Cloud Platform");
return new FailingProtocolNegotiatorFactory(status);
}
}
return new ClientAltsProtocolNegotiatorFactory(
targetServiceAccountsBuilder.build(), handshakerChannelPool);
}
}
private static final class FailingProtocolNegotiatorFactory
implements InternalProtocolNegotiator.ClientFactory {
private final Status status;
public FailingProtocolNegotiatorFactory(Status status) {
this.status = status;
}
@Override
public ProtocolNegotiator newNegotiator() {
return new FailingProtocolNegotiator(status);
}
@Override
public int getDefaultPort() {
return 443;
}
}
private static final AsciiString SCHEME = AsciiString.of("https");
private static final class FailingProtocolNegotiator implements ProtocolNegotiator {
private final Status status;
public FailingProtocolNegotiator(Status status) {
this.status = status;
}
@Override
public AsciiString scheme() {
return SCHEME;
}
@Override
public ChannelHandler newHandler(GrpcHttp2ConnectionHandler grpcHandler) {
return new ChannelHandlerAdapter() {
@Override public void handlerAdded(ChannelHandlerContext ctx) {
ctx.fireExceptionCaught(status.asRuntimeException());
}
};
}
@Override
public void close() {}
}
}

View File

@ -1,47 +0,0 @@
/*
* Copyright 2019 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.alts;
import io.grpc.CallCredentials;
import io.grpc.CallOptions;
import io.grpc.Channel;
import io.grpc.ClientCall;
import io.grpc.ClientInterceptor;
import io.grpc.MethodDescriptor;
import io.grpc.Status;
import javax.annotation.Nullable;
/** An implementation of {@link ClientInterceptor} that adds call credentials on each call. */
final class CallCredentialsInterceptor implements ClientInterceptor {
@Nullable private final CallCredentials credentials;
private final Status status;
public CallCredentialsInterceptor(@Nullable CallCredentials credentials, Status status) {
this.credentials = credentials;
this.status = status;
}
@Override
public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(
MethodDescriptor<ReqT, RespT> method, CallOptions callOptions, Channel next) {
if (!status.isOk()) {
return new FailingClientCall<>(status);
}
return next.newCall(method, callOptions.withCallCredentials(credentials));
}
}

View File

@ -16,23 +16,10 @@
package io.grpc.alts;
import com.google.auth.oauth2.ComputeEngineCredentials;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
import io.grpc.CallCredentials;
import io.grpc.ForwardingChannelBuilder;
import io.grpc.ManagedChannelBuilder;
import io.grpc.Status;
import io.grpc.alts.internal.AltsProtocolNegotiator.GoogleDefaultProtocolNegotiatorFactory;
import io.grpc.auth.MoreCallCredentials;
import io.grpc.internal.GrpcUtil;
import io.grpc.internal.SharedResourcePool;
import io.grpc.netty.GrpcSslContexts;
import io.grpc.netty.InternalNettyChannelBuilder;
import io.grpc.netty.InternalProtocolNegotiator.ProtocolNegotiator;
import io.grpc.netty.NettyChannelBuilder;
import io.netty.handler.ssl.SslContext;
import javax.net.ssl.SSLException;
/**
* {@code ManagedChannelBuilder} for Google Compute Engine. This class sets up a secure channel
@ -44,27 +31,7 @@ public final class ComputeEngineChannelBuilder
private final NettyChannelBuilder delegate;
private ComputeEngineChannelBuilder(String target) {
delegate = NettyChannelBuilder.forTarget(target);
SslContext sslContext;
try {
sslContext = GrpcSslContexts.forClient().build();
} catch (SSLException e) {
throw new RuntimeException(e);
}
InternalNettyChannelBuilder.setProtocolNegotiatorFactory(
delegate(),
new GoogleDefaultProtocolNegotiatorFactory(
/* targetServiceAccounts= */ ImmutableList.<String>of(),
SharedResourcePool.forResource(HandshakerServiceChannel.SHARED_HANDSHAKER_CHANNEL),
sslContext));
CallCredentials credentials = MoreCallCredentials.from(ComputeEngineCredentials.create());
Status status = Status.OK;
if (!CheckGcpEnvironment.isOnGcp()) {
status =
Status.INTERNAL.withDescription(
"Compute Engine Credentials can only be used on Google Cloud Platform");
}
delegate().intercept(new CallCredentialsInterceptor(credentials, status));
delegate = NettyChannelBuilder.forTarget(target, ComputeEngineChannelCredentials.create());
}
/** "Overrides" the static method in {@link ManagedChannelBuilder}. */
@ -81,19 +48,4 @@ public final class ComputeEngineChannelBuilder
protected NettyChannelBuilder delegate() {
return delegate;
}
@VisibleForTesting
ProtocolNegotiator getProtocolNegotiatorForTest() {
SslContext sslContext;
try {
sslContext = GrpcSslContexts.forClient().build();
} catch (SSLException e) {
throw new RuntimeException(e);
}
return new GoogleDefaultProtocolNegotiatorFactory(
/* targetServiceAccounts= */ ImmutableList.<String>of(),
SharedResourcePool.forResource(HandshakerServiceChannel.SHARED_HANDSHAKER_CHANNEL),
sslContext)
.buildProtocolNegotiator();
}
}

View File

@ -0,0 +1,74 @@
/*
* 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.alts;
import com.google.auth.oauth2.ComputeEngineCredentials;
import com.google.common.collect.ImmutableList;
import io.grpc.CallCredentials;
import io.grpc.ChannelCredentials;
import io.grpc.CompositeChannelCredentials;
import io.grpc.ExperimentalApi;
import io.grpc.Status;
import io.grpc.alts.internal.AltsProtocolNegotiator.GoogleDefaultProtocolNegotiatorFactory;
import io.grpc.auth.MoreCallCredentials;
import io.grpc.internal.SharedResourcePool;
import io.grpc.netty.GrpcSslContexts;
import io.grpc.netty.InternalNettyChannelCredentials;
import io.grpc.netty.InternalProtocolNegotiator;
import io.netty.handler.ssl.SslContext;
import javax.net.ssl.SSLException;
/**
* Credentials appropriate to contact Google services when running on Google Compute Engine. This
* class sets up a secure channel using ALTS if applicable and using TLS as fallback. It is a subset
* of the functionality provided by {@link GoogleDefaultChannelCredentials}.
*/
@ExperimentalApi("https://github.com/grpc/grpc-java/issues/7479")
public final class ComputeEngineChannelCredentials {
private ComputeEngineChannelCredentials() {}
/**
* Creates credentials for Google Compute Engine. This class sets up a secure channel using ALTS
* if applicable and using TLS as fallback.
*/
public static ChannelCredentials create() {
ChannelCredentials nettyCredentials =
InternalNettyChannelCredentials.create(createClientFactory());
CallCredentials callCredentials;
if (CheckGcpEnvironment.isOnGcp()) {
callCredentials = MoreCallCredentials.from(ComputeEngineCredentials.create());
} else {
callCredentials = new FailingCallCredentials(
Status.INTERNAL.withDescription(
"Compute Engine Credentials can only be used on Google Cloud Platform"));
}
return CompositeChannelCredentials.create(nettyCredentials, callCredentials);
}
private static InternalProtocolNegotiator.ClientFactory createClientFactory() {
SslContext sslContext;
try {
sslContext = GrpcSslContexts.forClient().build();
} catch (SSLException e) {
throw new RuntimeException(e);
}
return new GoogleDefaultProtocolNegotiatorFactory(
/* targetServiceAccounts= */ ImmutableList.<String>of(),
SharedResourcePool.forResource(HandshakerServiceChannel.SHARED_HANDSHAKER_CHANNEL),
sslContext);
}
}

View File

@ -0,0 +1,44 @@
/*
* 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.alts;
import com.google.common.base.Preconditions;
import io.grpc.CallCredentials;
import io.grpc.Status;
import java.util.concurrent.Executor;
/**
* {@code CallCredentials} that always fail the RPC.
*/
final class FailingCallCredentials extends CallCredentials {
private final Status status;
public FailingCallCredentials(Status status) {
this.status = Preconditions.checkNotNull(status, "status");
}
@Override
public void applyRequestMetadata(
CallCredentials.RequestInfo requestInfo,
Executor appExecutor,
CallCredentials.MetadataApplier applier) {
applier.fail(status);
}
@Override
public void thisUsesUnstableApi() {}
}

View File

@ -16,25 +16,10 @@
package io.grpc.alts;
import com.google.auth.oauth2.GoogleCredentials;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
import io.grpc.CallCredentials;
import io.grpc.ForwardingChannelBuilder;
import io.grpc.ManagedChannelBuilder;
import io.grpc.Status;
import io.grpc.alts.internal.AltsProtocolNegotiator.GoogleDefaultProtocolNegotiatorFactory;
import io.grpc.auth.MoreCallCredentials;
import io.grpc.internal.GrpcUtil;
import io.grpc.internal.SharedResourcePool;
import io.grpc.netty.GrpcSslContexts;
import io.grpc.netty.InternalNettyChannelBuilder;
import io.grpc.netty.InternalProtocolNegotiator.ProtocolNegotiator;
import io.grpc.netty.NettyChannelBuilder;
import io.netty.handler.ssl.SslContext;
import java.io.IOException;
import javax.annotation.Nullable;
import javax.net.ssl.SSLException;
/**
* Google default version of {@code ManagedChannelBuilder}. This class sets up a secure channel
@ -46,30 +31,7 @@ public final class GoogleDefaultChannelBuilder
private final NettyChannelBuilder delegate;
private GoogleDefaultChannelBuilder(String target) {
delegate = NettyChannelBuilder.forTarget(target);
SslContext sslContext;
try {
sslContext = GrpcSslContexts.forClient().build();
} catch (SSLException e) {
throw new RuntimeException(e);
}
InternalNettyChannelBuilder.setProtocolNegotiatorFactory(
delegate(),
new GoogleDefaultProtocolNegotiatorFactory(
/* targetServiceAccounts= */ ImmutableList.<String>of(),
SharedResourcePool.forResource(HandshakerServiceChannel.SHARED_HANDSHAKER_CHANNEL),
sslContext));
@Nullable CallCredentials credentials = null;
Status status = Status.OK;
try {
credentials = MoreCallCredentials.from(GoogleCredentials.getApplicationDefault());
} catch (IOException e) {
status =
Status.UNAUTHENTICATED
.withDescription("Failed to get Google default credentials")
.withCause(e);
}
delegate().intercept(new CallCredentialsInterceptor(credentials, status));
delegate = NettyChannelBuilder.forTarget(target, GoogleDefaultChannelCredentials.create());
}
/** "Overrides" the static method in {@link ManagedChannelBuilder}. */
@ -86,19 +48,4 @@ public final class GoogleDefaultChannelBuilder
protected NettyChannelBuilder delegate() {
return delegate;
}
@VisibleForTesting
ProtocolNegotiator getProtocolNegotiatorForTest() {
SslContext sslContext;
try {
sslContext = GrpcSslContexts.forClient().build();
} catch (SSLException e) {
throw new RuntimeException(e);
}
return new GoogleDefaultProtocolNegotiatorFactory(
/* targetServiceAccounts= */ ImmutableList.<String>of(),
SharedResourcePool.forResource(HandshakerServiceChannel.SHARED_HANDSHAKER_CHANNEL),
sslContext)
.buildProtocolNegotiator();
}
}

View File

@ -0,0 +1,76 @@
/*
* 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.alts;
import com.google.auth.oauth2.GoogleCredentials;
import com.google.common.collect.ImmutableList;
import io.grpc.CallCredentials;
import io.grpc.ChannelCredentials;
import io.grpc.CompositeChannelCredentials;
import io.grpc.ExperimentalApi;
import io.grpc.Status;
import io.grpc.alts.internal.AltsProtocolNegotiator.GoogleDefaultProtocolNegotiatorFactory;
import io.grpc.auth.MoreCallCredentials;
import io.grpc.internal.SharedResourcePool;
import io.grpc.netty.GrpcSslContexts;
import io.grpc.netty.InternalNettyChannelCredentials;
import io.grpc.netty.InternalProtocolNegotiator;
import io.netty.handler.ssl.SslContext;
import java.io.IOException;
import javax.net.ssl.SSLException;
/**
* Credentials appropriate to contact Google services. This class sets up a secure channel using
* ALTS if applicable and uses TLS as fallback.
*/
@ExperimentalApi("https://github.com/grpc/grpc-java/issues/7479")
public final class GoogleDefaultChannelCredentials {
private GoogleDefaultChannelCredentials() {}
/**
* Creates Google default credentials uses a secure channel with ALTS if applicable and uses TLS
* as fallback.
*/
public static ChannelCredentials create() {
ChannelCredentials nettyCredentials =
InternalNettyChannelCredentials.create(createClientFactory());
CallCredentials callCredentials;
try {
callCredentials = MoreCallCredentials.from(GoogleCredentials.getApplicationDefault());
} catch (IOException e) {
// TODO(ejona): Should this just throw?
callCredentials = new FailingCallCredentials(
Status.UNAUTHENTICATED
.withDescription("Failed to get Google default credentials")
.withCause(e));
}
return CompositeChannelCredentials.create(nettyCredentials, callCredentials);
}
private static InternalProtocolNegotiator.ClientFactory createClientFactory() {
SslContext sslContext;
try {
sslContext = GrpcSslContexts.forClient().build();
} catch (SSLException e) {
throw new RuntimeException(e);
}
return new GoogleDefaultProtocolNegotiatorFactory(
/* targetServiceAccounts= */ ImmutableList.<String>of(),
SharedResourcePool.forResource(HandshakerServiceChannel.SHARED_HANDSHAKER_CHANNEL),
sslContext);
}
}

View File

@ -32,8 +32,7 @@ import io.grpc.alts.internal.RpcProtocolVersionsUtil.RpcVersionsCheckResult;
import io.grpc.grpclb.GrpclbConstants;
import io.grpc.internal.ObjectPool;
import io.grpc.netty.GrpcHttp2ConnectionHandler;
import io.grpc.netty.InternalNettyChannelBuilder;
import io.grpc.netty.InternalNettyChannelBuilder.ProtocolNegotiatorFactory;
import io.grpc.netty.InternalProtocolNegotiator;
import io.grpc.netty.InternalProtocolNegotiator.ProtocolNegotiator;
import io.grpc.netty.InternalProtocolNegotiators;
import io.netty.channel.ChannelHandler;
@ -65,23 +64,28 @@ public final class AltsProtocolNegotiator {
* channel.
*/
public static final class ClientAltsProtocolNegotiatorFactory
implements InternalNettyChannelBuilder.ProtocolNegotiatorFactory {
implements InternalProtocolNegotiator.ClientFactory {
private final ImmutableList<String> targetServiceAccounts;
private final LazyChannel lazyHandshakerChannel;
private final ObjectPool<Channel> handshakerChannelPool;
public ClientAltsProtocolNegotiatorFactory(
List<String> targetServiceAccounts,
ObjectPool<Channel> handshakerChannelPool) {
this.targetServiceAccounts = ImmutableList.copyOf(targetServiceAccounts);
this.lazyHandshakerChannel = new LazyChannel(handshakerChannelPool);
this.handshakerChannelPool = checkNotNull(handshakerChannelPool, "handshakerChannelPool");
}
@Override
public ProtocolNegotiator buildProtocolNegotiator() {
public ProtocolNegotiator newNegotiator() {
return new ClientAltsProtocolNegotiator(
new ClientTsiHandshakerFactory(targetServiceAccounts, lazyHandshakerChannel),
lazyHandshakerChannel);
targetServiceAccounts,
handshakerChannelPool);
}
@Override
public int getDefaultPort() {
return 443;
}
}
@ -90,9 +94,10 @@ public final class AltsProtocolNegotiator {
private final LazyChannel lazyHandshakerChannel;
ClientAltsProtocolNegotiator(
TsiHandshakerFactory handshakerFactory, LazyChannel lazyHandshakerChannel) {
this.handshakerFactory = checkNotNull(handshakerFactory, "handshakerFactory");
this.lazyHandshakerChannel = checkNotNull(lazyHandshakerChannel, "lazyHandshakerChannel");
ImmutableList<String> targetServiceAccounts, ObjectPool<Channel> handshakerChannelPool) {
this.lazyHandshakerChannel = new LazyChannel(handshakerChannelPool);
this.handshakerFactory =
new ClientTsiHandshakerFactory(targetServiceAccounts, lazyHandshakerChannel);
}
@Override
@ -177,9 +182,9 @@ public final class AltsProtocolNegotiator {
* A Protocol Negotiator factory which can switch between ALTS and TLS based on EAG Attrs.
*/
public static final class GoogleDefaultProtocolNegotiatorFactory
implements ProtocolNegotiatorFactory {
implements InternalProtocolNegotiator.ClientFactory {
private final ImmutableList<String> targetServiceAccounts;
private final LazyChannel lazyHandshakerChannel;
private final ObjectPool<Channel> handshakerChannelPool;
private final SslContext sslContext;
/**
@ -191,17 +196,22 @@ public final class AltsProtocolNegotiator {
ObjectPool<Channel> handshakerChannelPool,
SslContext sslContext) {
this.targetServiceAccounts = ImmutableList.copyOf(targetServiceAccounts);
this.lazyHandshakerChannel = new LazyChannel(handshakerChannelPool);
this.handshakerChannelPool = checkNotNull(handshakerChannelPool, "handshakerChannelPool");
this.sslContext = checkNotNull(sslContext, "sslContext");
}
@Override
public ProtocolNegotiator buildProtocolNegotiator() {
public ProtocolNegotiator newNegotiator() {
return new GoogleDefaultProtocolNegotiator(
new ClientTsiHandshakerFactory(targetServiceAccounts, lazyHandshakerChannel),
lazyHandshakerChannel,
targetServiceAccounts,
handshakerChannelPool,
sslContext);
}
@Override
public int getDefaultPort() {
return 443;
}
}
private static final class GoogleDefaultProtocolNegotiator implements ProtocolNegotiator {
@ -210,11 +220,12 @@ public final class AltsProtocolNegotiator {
private final SslContext sslContext;
GoogleDefaultProtocolNegotiator(
TsiHandshakerFactory handshakerFactory,
LazyChannel lazyHandshakerChannel,
ImmutableList<String> targetServiceAccounts,
ObjectPool<Channel> handshakerChannelPool,
SslContext sslContext) {
this.handshakerFactory = checkNotNull(handshakerFactory, "handshakerFactory");
this.lazyHandshakerChannel = checkNotNull(lazyHandshakerChannel, "lazyHandshakerChannel");
this.lazyHandshakerChannel = new LazyChannel(handshakerChannelPool);
this.handshakerFactory =
new ClientTsiHandshakerFactory(targetServiceAccounts, lazyHandshakerChannel);
this.sslContext = checkNotNull(sslContext, "checkNotNull");
}

View File

@ -16,9 +16,6 @@
package io.grpc.alts;
import static com.google.common.truth.Truth.assertThat;
import io.grpc.netty.InternalProtocolNegotiator.ProtocolNegotiator;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
@ -30,9 +27,5 @@ public final class ComputeEngineChannelBuilderTest {
public void buildsNettyChannel() throws Exception {
ComputeEngineChannelBuilder builder = ComputeEngineChannelBuilder.forTarget("localhost:8080");
builder.build();
ProtocolNegotiator protocolNegotiator = builder.getProtocolNegotiatorForTest();
assertThat(protocolNegotiator.getClass().getSimpleName())
.isEqualTo("GoogleDefaultProtocolNegotiator");
}
}

View File

@ -16,9 +16,6 @@
package io.grpc.alts;
import static com.google.common.truth.Truth.assertThat;
import io.grpc.netty.InternalProtocolNegotiator.ProtocolNegotiator;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
@ -30,9 +27,5 @@ public final class GoogleDefaultChannelBuilderTest {
public void buildsNettyChannel() throws Exception {
GoogleDefaultChannelBuilder builder = GoogleDefaultChannelBuilder.forTarget("localhost:8080");
builder.build();
ProtocolNegotiator protocolNegotiator = builder.getProtocolNegotiatorForTest();
assertThat(protocolNegotiator.getClass().getSimpleName())
.isEqualTo("GoogleDefaultProtocolNegotiator");
}
}

View File

@ -69,7 +69,7 @@ public final class GoogleDefaultProtocolNegotiatorTest {
ImmutableList.<String>of(),
handshakerChannelPool,
sslContext)
.buildProtocolNegotiator();
.newNegotiator();
}
@After