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.
diff --git a/alts/src/main/java/io/grpc/alts/AltsChannelBuilder.java b/alts/src/main/java/io/grpc/alts/AltsChannelBuilder.java
index 5a774da..969cef9 100644
--- a/alts/src/main/java/io/grpc/alts/AltsChannelBuilder.java
+++ b/alts/src/main/java/io/grpc/alts/AltsChannelBuilder.java
@@ -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 @@
*/
@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 @@
* 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 @@
* 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 @@
@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 @@
@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();
}
}
diff --git a/alts/src/main/java/io/grpc/alts/AltsChannelCredentials.java b/alts/src/main/java/io/grpc/alts/AltsChannelCredentials.java
new file mode 100644
index 0000000..ca304c9
--- /dev/null
+++ b/alts/src/main/java/io/grpc/alts/AltsChannelCredentials.java
@@ -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() {}
+ }
+}
diff --git a/alts/src/main/java/io/grpc/alts/CallCredentialsInterceptor.java b/alts/src/main/java/io/grpc/alts/CallCredentialsInterceptor.java
deleted file mode 100644
index b1ab948..0000000
--- a/alts/src/main/java/io/grpc/alts/CallCredentialsInterceptor.java
+++ /dev/null
@@ -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));
- }
-}
diff --git a/alts/src/main/java/io/grpc/alts/ComputeEngineChannelBuilder.java b/alts/src/main/java/io/grpc/alts/ComputeEngineChannelBuilder.java
index d9eaba8..c8c0a08 100644
--- a/alts/src/main/java/io/grpc/alts/ComputeEngineChannelBuilder.java
+++ b/alts/src/main/java/io/grpc/alts/ComputeEngineChannelBuilder.java
@@ -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 @@
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 @@
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();
- }
}
diff --git a/alts/src/main/java/io/grpc/alts/ComputeEngineChannelCredentials.java b/alts/src/main/java/io/grpc/alts/ComputeEngineChannelCredentials.java
new file mode 100644
index 0000000..387fe6d
--- /dev/null
+++ b/alts/src/main/java/io/grpc/alts/ComputeEngineChannelCredentials.java
@@ -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);
+ }
+}
diff --git a/alts/src/main/java/io/grpc/alts/FailingCallCredentials.java b/alts/src/main/java/io/grpc/alts/FailingCallCredentials.java
new file mode 100644
index 0000000..dbe0821
--- /dev/null
+++ b/alts/src/main/java/io/grpc/alts/FailingCallCredentials.java
@@ -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() {}
+}
diff --git a/alts/src/main/java/io/grpc/alts/GoogleDefaultChannelBuilder.java b/alts/src/main/java/io/grpc/alts/GoogleDefaultChannelBuilder.java
index 39bd416..4e006b6 100644
--- a/alts/src/main/java/io/grpc/alts/GoogleDefaultChannelBuilder.java
+++ b/alts/src/main/java/io/grpc/alts/GoogleDefaultChannelBuilder.java
@@ -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 @@
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 @@
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();
- }
}
diff --git a/alts/src/main/java/io/grpc/alts/GoogleDefaultChannelCredentials.java b/alts/src/main/java/io/grpc/alts/GoogleDefaultChannelCredentials.java
new file mode 100644
index 0000000..9c8b39c
--- /dev/null
+++ b/alts/src/main/java/io/grpc/alts/GoogleDefaultChannelCredentials.java
@@ -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);
+ }
+}
diff --git a/alts/src/main/java/io/grpc/alts/internal/AltsProtocolNegotiator.java b/alts/src/main/java/io/grpc/alts/internal/AltsProtocolNegotiator.java
index c5adbd7..d2040df 100644
--- a/alts/src/main/java/io/grpc/alts/internal/AltsProtocolNegotiator.java
+++ b/alts/src/main/java/io/grpc/alts/internal/AltsProtocolNegotiator.java
@@ -32,8 +32,7 @@
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 @@
* 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 @@
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 @@
* 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 @@
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 @@
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");
}
diff --git a/alts/src/test/java/io/grpc/alts/ComputeEngineChannelBuilderTest.java b/alts/src/test/java/io/grpc/alts/ComputeEngineChannelBuilderTest.java
index f7752a2..03fd113 100644
--- a/alts/src/test/java/io/grpc/alts/ComputeEngineChannelBuilderTest.java
+++ b/alts/src/test/java/io/grpc/alts/ComputeEngineChannelBuilderTest.java
@@ -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 void buildsNettyChannel() throws Exception {
ComputeEngineChannelBuilder builder = ComputeEngineChannelBuilder.forTarget("localhost:8080");
builder.build();
-
- ProtocolNegotiator protocolNegotiator = builder.getProtocolNegotiatorForTest();
- assertThat(protocolNegotiator.getClass().getSimpleName())
- .isEqualTo("GoogleDefaultProtocolNegotiator");
}
}
diff --git a/alts/src/test/java/io/grpc/alts/GoogleDefaultChannelBuilderTest.java b/alts/src/test/java/io/grpc/alts/GoogleDefaultChannelBuilderTest.java
index 4336aff..c73ef44 100644
--- a/alts/src/test/java/io/grpc/alts/GoogleDefaultChannelBuilderTest.java
+++ b/alts/src/test/java/io/grpc/alts/GoogleDefaultChannelBuilderTest.java
@@ -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 void buildsNettyChannel() throws Exception {
GoogleDefaultChannelBuilder builder = GoogleDefaultChannelBuilder.forTarget("localhost:8080");
builder.build();
-
- ProtocolNegotiator protocolNegotiator = builder.getProtocolNegotiatorForTest();
- assertThat(protocolNegotiator.getClass().getSimpleName())
- .isEqualTo("GoogleDefaultProtocolNegotiator");
}
}
diff --git a/alts/src/test/java/io/grpc/alts/internal/GoogleDefaultProtocolNegotiatorTest.java b/alts/src/test/java/io/grpc/alts/internal/GoogleDefaultProtocolNegotiatorTest.java
index 5858fc3..8560363 100644
--- a/alts/src/test/java/io/grpc/alts/internal/GoogleDefaultProtocolNegotiatorTest.java
+++ b/alts/src/test/java/io/grpc/alts/internal/GoogleDefaultProtocolNegotiatorTest.java
@@ -69,7 +69,7 @@
ImmutableList.<String>of(),
handshakerChannelPool,
sslContext)
- .buildProtocolNegotiator();
+ .newNegotiator();
}
@After