mirror of https://github.com/grpc/grpc-java.git
ALTS: add ComputeEngineChannelBuilder (#5473)
This commit is contained in:
parent
f155d60e75
commit
b4af5ad986
|
|
@ -0,0 +1,47 @@
|
||||||
|
/*
|
||||||
|
* 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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,118 @@
|
||||||
|
/*
|
||||||
|
* 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 com.google.auth.oauth2.ComputeEngineCredentials;
|
||||||
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
|
import io.grpc.CallCredentials;
|
||||||
|
import io.grpc.ForwardingChannelBuilder;
|
||||||
|
import io.grpc.ManagedChannelBuilder;
|
||||||
|
import io.grpc.Status;
|
||||||
|
import io.grpc.alts.internal.AltsClientOptions;
|
||||||
|
import io.grpc.alts.internal.AltsProtocolNegotiator.LazyChannel;
|
||||||
|
import io.grpc.alts.internal.AltsTsiHandshaker;
|
||||||
|
import io.grpc.alts.internal.GoogleDefaultProtocolNegotiator;
|
||||||
|
import io.grpc.alts.internal.HandshakerServiceGrpc;
|
||||||
|
import io.grpc.alts.internal.RpcProtocolVersionsUtil;
|
||||||
|
import io.grpc.alts.internal.TsiHandshaker;
|
||||||
|
import io.grpc.alts.internal.TsiHandshakerFactory;
|
||||||
|
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.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
|
||||||
|
* using ALTS if applicable and using TLS as fallback.
|
||||||
|
*/
|
||||||
|
public final class ComputeEngineChannelBuilder
|
||||||
|
extends ForwardingChannelBuilder<GoogleDefaultChannelBuilder> {
|
||||||
|
|
||||||
|
private final NettyChannelBuilder delegate;
|
||||||
|
private GoogleDefaultProtocolNegotiator negotiatorForTest;
|
||||||
|
|
||||||
|
private ComputeEngineChannelBuilder(String target) {
|
||||||
|
delegate = NettyChannelBuilder.forTarget(target);
|
||||||
|
InternalNettyChannelBuilder.setProtocolNegotiatorFactory(
|
||||||
|
delegate(), new ProtocolNegotiatorFactory());
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** "Overrides" the static method in {@link ManagedChannelBuilder}. */
|
||||||
|
public static final ComputeEngineChannelBuilder forTarget(String target) {
|
||||||
|
return new ComputeEngineChannelBuilder(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** "Overrides" the static method in {@link ManagedChannelBuilder}. */
|
||||||
|
public static ComputeEngineChannelBuilder forAddress(String name, int port) {
|
||||||
|
return forTarget(GrpcUtil.authorityFromHostAndPort(name, port));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected NettyChannelBuilder delegate() {
|
||||||
|
return delegate;
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
GoogleDefaultProtocolNegotiator getProtocolNegotiatorForTest() {
|
||||||
|
return negotiatorForTest;
|
||||||
|
}
|
||||||
|
|
||||||
|
private final class ProtocolNegotiatorFactory
|
||||||
|
implements InternalNettyChannelBuilder.ProtocolNegotiatorFactory {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public GoogleDefaultProtocolNegotiator buildProtocolNegotiator() {
|
||||||
|
final LazyChannel lazyHandshakerChannel =
|
||||||
|
new LazyChannel(
|
||||||
|
SharedResourcePool.forResource(HandshakerServiceChannel.SHARED_HANDSHAKER_CHANNEL));
|
||||||
|
TsiHandshakerFactory altsHandshakerFactory =
|
||||||
|
new TsiHandshakerFactory() {
|
||||||
|
@Override
|
||||||
|
public TsiHandshaker newHandshaker(String authority) {
|
||||||
|
AltsClientOptions handshakerOptions =
|
||||||
|
new AltsClientOptions.Builder()
|
||||||
|
.setRpcProtocolVersions(RpcProtocolVersionsUtil.getRpcProtocolVersions())
|
||||||
|
.setTargetName(authority)
|
||||||
|
.build();
|
||||||
|
return AltsTsiHandshaker.newClient(
|
||||||
|
HandshakerServiceGrpc.newStub(lazyHandshakerChannel.get()), handshakerOptions);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
SslContext sslContext;
|
||||||
|
try {
|
||||||
|
sslContext = GrpcSslContexts.forClient().build();
|
||||||
|
} catch (SSLException ex) {
|
||||||
|
throw new RuntimeException(ex);
|
||||||
|
}
|
||||||
|
return negotiatorForTest =
|
||||||
|
new GoogleDefaultProtocolNegotiator(
|
||||||
|
altsHandshakerFactory, lazyHandshakerChannel, sslContext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -19,13 +19,8 @@ package io.grpc.alts;
|
||||||
import com.google.auth.oauth2.GoogleCredentials;
|
import com.google.auth.oauth2.GoogleCredentials;
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
import io.grpc.CallCredentials;
|
import io.grpc.CallCredentials;
|
||||||
import io.grpc.CallOptions;
|
|
||||||
import io.grpc.Channel;
|
|
||||||
import io.grpc.ClientCall;
|
|
||||||
import io.grpc.ClientInterceptor;
|
|
||||||
import io.grpc.ForwardingChannelBuilder;
|
import io.grpc.ForwardingChannelBuilder;
|
||||||
import io.grpc.ManagedChannelBuilder;
|
import io.grpc.ManagedChannelBuilder;
|
||||||
import io.grpc.MethodDescriptor;
|
|
||||||
import io.grpc.Status;
|
import io.grpc.Status;
|
||||||
import io.grpc.alts.internal.AltsClientOptions;
|
import io.grpc.alts.internal.AltsClientOptions;
|
||||||
import io.grpc.alts.internal.AltsProtocolNegotiator.LazyChannel;
|
import io.grpc.alts.internal.AltsProtocolNegotiator.LazyChannel;
|
||||||
|
|
@ -70,7 +65,7 @@ public final class GoogleDefaultChannelBuilder
|
||||||
.withDescription("Failed to get Google default credentials")
|
.withDescription("Failed to get Google default credentials")
|
||||||
.withCause(e);
|
.withCause(e);
|
||||||
}
|
}
|
||||||
delegate().intercept(new GoogleDefaultInterceptor(credentials, status));
|
delegate().intercept(new CallCredentialsInterceptor(credentials, status));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** "Overrides" the static method in {@link ManagedChannelBuilder}. */
|
/** "Overrides" the static method in {@link ManagedChannelBuilder}. */
|
||||||
|
|
@ -125,27 +120,4 @@ public final class GoogleDefaultChannelBuilder
|
||||||
altsHandshakerFactory, lazyHandshakerChannel, sslContext);
|
altsHandshakerFactory, lazyHandshakerChannel, sslContext);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* An implementation of {@link ClientInterceptor} that adds Google call credentials on each call.
|
|
||||||
*/
|
|
||||||
static final class GoogleDefaultInterceptor implements ClientInterceptor {
|
|
||||||
|
|
||||||
@Nullable private final CallCredentials credentials;
|
|
||||||
private final Status status;
|
|
||||||
|
|
||||||
public GoogleDefaultInterceptor(@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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
/*
|
||||||
|
* 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 static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
|
import io.grpc.alts.internal.GoogleDefaultProtocolNegotiator;
|
||||||
|
import io.grpc.netty.InternalProtocolNegotiator.ProtocolNegotiator;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.junit.runners.JUnit4;
|
||||||
|
|
||||||
|
@RunWith(JUnit4.class)
|
||||||
|
public final class ComputeEngineChannelBuilderTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void buildsNettyChannel() throws Exception {
|
||||||
|
ComputeEngineChannelBuilder builder = ComputeEngineChannelBuilder.forTarget("localhost:8080");
|
||||||
|
builder.build();
|
||||||
|
|
||||||
|
ProtocolNegotiator protocolNegotiator = builder.getProtocolNegotiatorForTest();
|
||||||
|
assertThat(protocolNegotiator).isInstanceOf(GoogleDefaultProtocolNegotiator.class);
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue