Remove SSL initializer from the prober (#378)

The prober now uses the common SSL initializer in the networking
subproject.

Also changed both initializers to take an ImmutableList of certificates
other than an array of those, for better immutability.

I have no idea where these lockfile changes are coming from. They seem
to be pure noise as far as code review is concerned.
This commit is contained in:
Lai Jiang
2019-11-22 17:46:06 -05:00
committed by GitHub
parent e318f47fc6
commit 05d56fe1a2
27 changed files with 257 additions and 770 deletions
@@ -21,6 +21,7 @@ import google.registry.monitoring.blackbox.connection.ProbingAction;
import google.registry.monitoring.blackbox.module.CertificateModule;
import google.registry.monitoring.blackbox.module.EppModule;
import google.registry.monitoring.blackbox.module.WebWhoisModule;
import google.registry.networking.handler.SslClientInitializer;
import google.registry.util.Clock;
import google.registry.util.SystemClock;
import io.netty.bootstrap.Bootstrap;
@@ -45,10 +46,7 @@ public class ProberModule {
/** Default {@link Duration} chosen to be time between each {@link ProbingAction} call. */
private static final Duration DEFAULT_PROBER_INTERVAL = Duration.standardSeconds(4);
/**
* {@link Provides} the {@link SslProvider} used by instances of {@link
* google.registry.monitoring.blackbox.handler.SslClientInitializer}
*/
/** {@link Provides} the {@link SslProvider} used by instances of {@link SslClientInitializer} */
@Provides
@Singleton
static SslProvider provideSslProvider() {
@@ -1,116 +0,0 @@
// Copyright 2019 The Nomulus Authors. All Rights Reserved.
//
// 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 google.registry.monitoring.blackbox.handler;
import static com.google.common.base.Preconditions.checkNotNull;
import static google.registry.monitoring.blackbox.connection.ProbingAction.REMOTE_ADDRESS_KEY;
import static google.registry.monitoring.blackbox.connection.Protocol.PROTOCOL_KEY;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.flogger.FluentLogger;
import google.registry.monitoring.blackbox.connection.Protocol;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler.Sharable;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.embedded.EmbeddedChannel;
import io.netty.handler.ssl.SslContextBuilder;
import io.netty.handler.ssl.SslHandler;
import io.netty.handler.ssl.SslProvider;
import java.security.PrivateKey;
import java.security.cert.X509Certificate;
import java.util.function.Supplier;
import javax.inject.Singleton;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLParameters;
/**
* Adds a client side SSL handler to the channel pipeline.
*
* <p>Code is close to unchanged from {@link SslClientInitializer} in proxy, but is modified for
* revised overall structure of connections, and to accomdate EPP connections
*
* <p>This <b>must</b> be the first handler provided for any handler provider list, if it is
* provided. The type parameter {@code C} is needed so that unit tests can construct this handler
* that works with {@link EmbeddedChannel};
*/
@Singleton
@Sharable
public class SslClientInitializer<C extends Channel> extends ChannelInitializer<C> {
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
private final SslProvider sslProvider;
private final X509Certificate[] trustedCertificates;
private final Supplier<PrivateKey> privateKeySupplier;
private final Supplier<X509Certificate[]> certificateSupplier;
public SslClientInitializer(SslProvider sslProvider) {
// null uses the system default trust store.
// Used for WebWhois, so we don't care about privateKey and certificates, setting them to null
this(sslProvider, null, null, null);
}
public SslClientInitializer(
SslProvider sslProvider,
Supplier<PrivateKey> privateKeySupplier,
Supplier<X509Certificate[]> certificateSupplier) {
// We use the default trust store here as well, setting trustCertificates to null
this(sslProvider, null, privateKeySupplier, certificateSupplier);
}
@VisibleForTesting
SslClientInitializer(SslProvider sslProvider, X509Certificate[] trustCertificates) {
this(sslProvider, trustCertificates, null, null);
}
private SslClientInitializer(
SslProvider sslProvider,
X509Certificate[] trustCertificates,
Supplier<PrivateKey> privateKeySupplier,
Supplier<X509Certificate[]> certificateSupplier) {
logger.atInfo().log("Client SSL Provider: %s", sslProvider);
this.sslProvider = sslProvider;
this.trustedCertificates = trustCertificates;
this.privateKeySupplier = privateKeySupplier;
this.certificateSupplier = certificateSupplier;
}
@Override
protected void initChannel(C channel) throws Exception {
Protocol protocol = channel.attr(PROTOCOL_KEY).get();
String host = channel.attr(REMOTE_ADDRESS_KEY).get();
// Builds SslHandler from Protocol, and based on if we require a privateKey and certificate
checkNotNull(protocol, "Protocol is not set for channel: %s", channel);
SslContextBuilder sslContextBuilder =
SslContextBuilder.forClient().sslProvider(sslProvider).trustManager(trustedCertificates);
if (privateKeySupplier != null && certificateSupplier != null) {
sslContextBuilder =
sslContextBuilder.keyManager(privateKeySupplier.get(), certificateSupplier.get());
}
SslHandler sslHandler =
sslContextBuilder.build().newHandler(channel.alloc(), host, protocol.port());
// Enable hostname verification.
SSLEngine sslEngine = sslHandler.engine();
SSLParameters sslParameters = sslEngine.getSSLParameters();
sslParameters.setEndpointIdentificationAlgorithm("HTTPS");
sslEngine.setSSLParameters(sslParameters);
channel.pipeline().addLast(sslHandler);
}
}
@@ -18,6 +18,7 @@ import static com.google.common.base.Suppliers.memoizeWithExpiration;
import static google.registry.util.ResourceUtils.readResourceBytes;
import static google.registry.util.ResourceUtils.readResourceUtf8;
import com.google.common.collect.ImmutableList;
import dagger.Module;
import dagger.Provides;
import java.io.IOException;
@@ -90,7 +91,8 @@ public class CertificateModule {
@Provides
@LocalSecrets
static X509Certificate[] provideCertificates(@LocalSecrets Provider<String> passwordProvider) {
static ImmutableList<X509Certificate> provideCertificates(
@LocalSecrets Provider<String> passwordProvider) {
try {
InputStream inStream = readResource("secrets/prober-client-tls-sandbox.p12");
@@ -98,7 +100,7 @@ public class CertificateModule {
ks.load(inStream, passwordProvider.get().toCharArray());
String alias = ks.aliases().nextElement();
return new X509Certificate[] {(X509Certificate) ks.getCertificate(alias)};
return ImmutableList.of((X509Certificate) ks.getCertificate(alias));
} catch (Exception e) {
throw new RuntimeException(e);
}
@@ -116,8 +118,8 @@ public class CertificateModule {
@Singleton
@Provides
@LocalSecrets
static Supplier<X509Certificate[]> provideCertificatesSupplier(
@LocalSecrets Provider<X509Certificate[]> certificatesProvider,
static Supplier<ImmutableList<X509Certificate>> provideCertificatesSupplier(
@LocalSecrets Provider<ImmutableList<X509Certificate>> certificatesProvider,
@LocalSecrets Duration duration) {
return memoizeWithExpiration(
certificatesProvider::get, duration.getStandardSeconds(), TimeUnit.SECONDS);
@@ -14,6 +14,8 @@
package google.registry.monitoring.blackbox.module;
import static google.registry.monitoring.blackbox.connection.ProbingAction.REMOTE_ADDRESS_KEY;
import static google.registry.monitoring.blackbox.connection.Protocol.PROTOCOL_KEY;
import static google.registry.monitoring.blackbox.message.EppRequestMessage.CLIENT_ID_KEY;
import static google.registry.monitoring.blackbox.message.EppRequestMessage.CLIENT_PASSWORD_KEY;
import static google.registry.monitoring.blackbox.message.EppRequestMessage.CLIENT_TRID_KEY;
@@ -30,13 +32,13 @@ import google.registry.monitoring.blackbox.ProbingStep;
import google.registry.monitoring.blackbox.connection.Protocol;
import google.registry.monitoring.blackbox.handler.EppActionHandler;
import google.registry.monitoring.blackbox.handler.EppMessageHandler;
import google.registry.monitoring.blackbox.handler.SslClientInitializer;
import google.registry.monitoring.blackbox.message.EppMessage;
import google.registry.monitoring.blackbox.message.EppRequestMessage;
import google.registry.monitoring.blackbox.message.EppResponseMessage;
import google.registry.monitoring.blackbox.metric.MetricsCollector;
import google.registry.monitoring.blackbox.module.CertificateModule.LocalSecrets;
import google.registry.monitoring.blackbox.token.EppToken;
import google.registry.networking.handler.SslClientInitializer;
import google.registry.util.Clock;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelHandler;
@@ -556,9 +558,15 @@ public class EppModule {
static SslClientInitializer<NioSocketChannel> provideSslClientInitializer(
SslProvider sslProvider,
@LocalSecrets Supplier<PrivateKey> privateKeySupplier,
@LocalSecrets Supplier<X509Certificate[]> certificatesSupplier) {
@LocalSecrets Supplier<ImmutableList<X509Certificate>> certificatesSupplier) {
return new SslClientInitializer<>(sslProvider, privateKeySupplier, certificatesSupplier);
return SslClientInitializer
.createSslClientInitializerWithSystemTrustStoreAndClientAuthentication(
sslProvider,
channel -> channel.attr(REMOTE_ADDRESS_KEY).get(),
channel -> channel.attr(PROTOCOL_KEY).get().port(),
privateKeySupplier,
certificatesSupplier);
}
@Provides
@@ -14,6 +14,10 @@
package google.registry.monitoring.blackbox.module;
import static google.registry.monitoring.blackbox.connection.ProbingAction.REMOTE_ADDRESS_KEY;
import static google.registry.monitoring.blackbox.connection.Protocol.PROTOCOL_KEY;
import static google.registry.networking.handler.SslClientInitializer.createSslClientInitializerWithSystemTrustStore;
import com.google.common.collect.ImmutableList;
import dagger.Module;
import dagger.Provides;
@@ -21,12 +25,12 @@ import dagger.multibindings.IntoSet;
import google.registry.monitoring.blackbox.ProbingSequence;
import google.registry.monitoring.blackbox.ProbingStep;
import google.registry.monitoring.blackbox.connection.Protocol;
import google.registry.monitoring.blackbox.handler.SslClientInitializer;
import google.registry.monitoring.blackbox.handler.WebWhoisActionHandler;
import google.registry.monitoring.blackbox.handler.WebWhoisMessageHandler;
import google.registry.monitoring.blackbox.message.HttpRequestMessage;
import google.registry.monitoring.blackbox.metric.MetricsCollector;
import google.registry.monitoring.blackbox.token.WebWhoisToken;
import google.registry.networking.handler.SslClientInitializer;
import google.registry.util.Clock;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
@@ -156,7 +160,10 @@ public class WebWhoisModule {
@HttpsWhoisProtocol
static SslClientInitializer<NioSocketChannel> provideSslClientInitializer(
SslProvider sslProvider) {
return new SslClientInitializer<>(sslProvider);
return createSslClientInitializerWithSystemTrustStore(
sslProvider,
channel -> channel.attr(REMOTE_ADDRESS_KEY).get(),
channel -> channel.attr(PROTOCOL_KEY).get().port());
}
/** {@link Provides} the {@link Bootstrap} used by the WebWhois sequence. */