HADOOP-17665 Ignore missing keystore configuration in reloading mechanism
This commit is contained in:
parent
43db94c7a3
commit
f5ef78d46f
@ -27,6 +27,7 @@
|
|||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -582,7 +583,8 @@ private ServerConnector createHttpsChannelConnector(
|
|||||||
conf.getLong(FileBasedKeyStoresFactory.SSL_STORES_RELOAD_INTERVAL_TPL_KEY,
|
conf.getLong(FileBasedKeyStoresFactory.SSL_STORES_RELOAD_INTERVAL_TPL_KEY,
|
||||||
FileBasedKeyStoresFactory.DEFAULT_SSL_STORES_RELOAD_INTERVAL);
|
FileBasedKeyStoresFactory.DEFAULT_SSL_STORES_RELOAD_INTERVAL);
|
||||||
|
|
||||||
if (storesReloadInterval > 0) {
|
if (storesReloadInterval > 0 &&
|
||||||
|
(keyStore != null || trustStore != null)) {
|
||||||
this.configurationChangeMonitor = Optional.of(
|
this.configurationChangeMonitor = Optional.of(
|
||||||
this.makeConfigurationChangeMonitor(storesReloadInterval, sslContextFactory));
|
this.makeConfigurationChangeMonitor(storesReloadInterval, sslContextFactory));
|
||||||
}
|
}
|
||||||
@ -596,18 +598,26 @@ private ServerConnector createHttpsChannelConnector(
|
|||||||
private Timer makeConfigurationChangeMonitor(long reloadInterval,
|
private Timer makeConfigurationChangeMonitor(long reloadInterval,
|
||||||
SslContextFactory.Server sslContextFactory) {
|
SslContextFactory.Server sslContextFactory) {
|
||||||
java.util.Timer timer = new java.util.Timer(FileBasedKeyStoresFactory.SSL_MONITORING_THREAD_NAME, true);
|
java.util.Timer timer = new java.util.Timer(FileBasedKeyStoresFactory.SSL_MONITORING_THREAD_NAME, true);
|
||||||
|
ArrayList<Path> locations = new ArrayList<Path>();
|
||||||
|
if (keyStore != null) {
|
||||||
|
locations.add(Paths.get(keyStore));
|
||||||
|
}
|
||||||
|
if (trustStore != null) {
|
||||||
|
locations.add(Paths.get(trustStore));
|
||||||
|
}
|
||||||
//
|
//
|
||||||
// The Jetty SSLContextFactory provides a 'reload' method which will reload both
|
// The Jetty SSLContextFactory provides a 'reload' method which will reload both
|
||||||
// truststore and keystore certificates.
|
// truststore and keystore certificates.
|
||||||
//
|
//
|
||||||
timer.schedule(new FileMonitoringTimerTask(
|
timer.schedule(new FileMonitoringTimerTask(
|
||||||
Paths.get(keyStore),
|
locations,
|
||||||
path -> {
|
path -> {
|
||||||
LOG.info("Reloading certificates from store keystore " + keyStore);
|
LOG.info("Reloading keystore and truststore certificates.");
|
||||||
try {
|
try {
|
||||||
sslContextFactory.reload(factory -> { });
|
sslContextFactory.reload(factory -> { });
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
LOG.error("Failed to reload SSL keystore certificates", ex);
|
LOG.error("Failed to reload SSL keystore " +
|
||||||
|
"and truststore certificates", ex);
|
||||||
}
|
}
|
||||||
},null),
|
},null),
|
||||||
reloadInterval,
|
reloadInterval,
|
||||||
|
@ -24,6 +24,9 @@
|
|||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
import java.util.TimerTask;
|
import java.util.TimerTask;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
@ -42,34 +45,59 @@ public class FileMonitoringTimerTask extends TimerTask {
|
|||||||
static final String PROCESS_ERROR_MESSAGE =
|
static final String PROCESS_ERROR_MESSAGE =
|
||||||
"Could not process file change : ";
|
"Could not process file change : ";
|
||||||
|
|
||||||
final private Path filePath;
|
final private List<Path> filePaths;
|
||||||
final private Consumer<Path> onFileChange;
|
final private Consumer<Path> onFileChange;
|
||||||
final Consumer<Throwable> onChangeFailure;
|
final Consumer<Throwable> onChangeFailure;
|
||||||
private long lastProcessed;
|
private List<Long> lastProcessed;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create file monitoring task to be scheduled using a standard Java {@link java.util.Timer}
|
* See {@link #FileMonitoringTimerTask(List, Consumer, Consumer)}.
|
||||||
* instance.
|
|
||||||
*
|
*
|
||||||
* @param filePath The path to the file to monitor.
|
* @param filePath The file to monitor.
|
||||||
* @param onFileChange The function to call when the file has changed.
|
* @param onFileChange What to do when the file changes.
|
||||||
* @param onChangeFailure The function to call when an exception is thrown during the
|
* @param onChangeFailure What to do when <code>onFileChange</code>
|
||||||
* file change processing.
|
* throws an exception.
|
||||||
*/
|
*/
|
||||||
public FileMonitoringTimerTask(Path filePath, Consumer<Path> onFileChange,
|
public FileMonitoringTimerTask(Path filePath, Consumer<Path> onFileChange,
|
||||||
Consumer<Throwable> onChangeFailure) {
|
Consumer<Throwable> onChangeFailure) {
|
||||||
Preconditions.checkNotNull(filePath, "path to monitor disk file is not set");
|
this(Collections.singletonList(filePath), onFileChange, onChangeFailure);
|
||||||
Preconditions.checkNotNull(onFileChange, "action to monitor disk file is not set");
|
}
|
||||||
|
|
||||||
this.filePath = filePath;
|
/**
|
||||||
this.lastProcessed = filePath.toFile().lastModified();
|
* Create file monitoring task to be scheduled using a standard
|
||||||
|
* Java {@link java.util.Timer} instance.
|
||||||
|
*
|
||||||
|
* @param filePaths The path to the file to monitor.
|
||||||
|
* @param onFileChange The function to call when the file has changed.
|
||||||
|
* @param onChangeFailure The function to call when an exception is
|
||||||
|
* thrown during the file change processing.
|
||||||
|
*/
|
||||||
|
public FileMonitoringTimerTask(List<Path> filePaths,
|
||||||
|
Consumer<Path> onFileChange,
|
||||||
|
Consumer<Throwable> onChangeFailure) {
|
||||||
|
Preconditions.checkNotNull(filePaths,
|
||||||
|
"path to monitor disk file is not set");
|
||||||
|
Preconditions.checkNotNull(onFileChange,
|
||||||
|
"action to monitor disk file is not set");
|
||||||
|
|
||||||
|
this.filePaths = new ArrayList<Path>(filePaths);
|
||||||
|
this.lastProcessed = new ArrayList<Long>();
|
||||||
|
this.filePaths.forEach(path ->
|
||||||
|
this.lastProcessed.add(path.toFile().lastModified()));
|
||||||
this.onFileChange = onFileChange;
|
this.onFileChange = onFileChange;
|
||||||
this.onChangeFailure = onChangeFailure;
|
this.onChangeFailure = onChangeFailure;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
if (lastProcessed != filePath.toFile().lastModified()) {
|
int modified = -1;
|
||||||
|
for (int i = 0; i < filePaths.size() && modified < 0; i++) {
|
||||||
|
if (lastProcessed.get(i) != filePaths.get(i).toFile().lastModified()) {
|
||||||
|
modified = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (modified > -1) {
|
||||||
|
Path filePath = filePaths.get(modified);
|
||||||
try {
|
try {
|
||||||
onFileChange.accept(filePath);
|
onFileChange.accept(filePath);
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
@ -79,7 +107,7 @@ public void run() {
|
|||||||
LOG.error(PROCESS_ERROR_MESSAGE + filePath.toString(), t);
|
LOG.error(PROCESS_ERROR_MESSAGE + filePath.toString(), t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
lastProcessed = filePath.toFile().lastModified();
|
lastProcessed.set(modified, filePath.toFile().lastModified());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -246,4 +246,5 @@
|
|||||||
<module>hadoop-yarn-ui</module>
|
<module>hadoop-yarn-ui</module>
|
||||||
<module>hadoop-yarn-csi</module>
|
<module>hadoop-yarn-csi</module>
|
||||||
</modules>
|
</modules>
|
||||||
|
<!-- -->
|
||||||
</project>
|
</project>
|
||||||
|
Loading…
Reference in New Issue
Block a user