Skip to content

Commit d4fd675

Browse files
committed
Revert "HADOOP-16524. Reloading SSL keystore for both DataNode and NameNode (#2470)"
This reverts commit e306f59.
1 parent 1ec5c67 commit d4fd675

File tree

7 files changed

+194
-703
lines changed

7 files changed

+194
-703
lines changed

hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/http/HttpServer2.java

Lines changed: 5 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -27,17 +27,14 @@
2727
import java.net.MalformedURLException;
2828
import java.net.URI;
2929
import java.net.URL;
30-
import java.nio.file.Paths;
31-
import java.util.List;
30+
import java.util.Arrays;
3231
import java.util.ArrayList;
33-
import java.util.Map;
34-
import java.util.HashMap;
3532
import java.util.Collections;
36-
import java.util.Optional;
37-
import java.util.Properties;
3833
import java.util.Enumeration;
39-
import java.util.Arrays;
40-
import java.util.Timer;
34+
import java.util.HashMap;
35+
import java.util.List;
36+
import java.util.Map;
37+
import java.util.Properties;
4138
import java.util.regex.Matcher;
4239
import java.util.regex.Pattern;
4340

@@ -77,8 +74,6 @@
7774
import org.apache.hadoop.security.authentication.server.PseudoAuthenticationHandler;
7875
import org.apache.hadoop.security.authentication.util.SignerSecretProvider;
7976
import org.apache.hadoop.security.authorize.AccessControlList;
80-
import org.apache.hadoop.security.ssl.FileBasedKeyStoresFactory;
81-
import org.apache.hadoop.security.ssl.FileMonitoringTimerTask;
8277
import org.apache.hadoop.security.ssl.SSLFactory;
8378
import org.apache.hadoop.util.ReflectionUtils;
8479
import org.apache.hadoop.util.Shell;
@@ -189,7 +184,6 @@ public final class HttpServer2 implements FilterContainer {
189184
static final String STATE_DESCRIPTION_ALIVE = " - alive";
190185
static final String STATE_DESCRIPTION_NOT_LIVE = " - not live";
191186
private final SignerSecretProvider secretProvider;
192-
private final Optional<java.util.Timer> configurationChangeMonitor;
193187
private XFrameOption xFrameOption;
194188
private boolean xFrameOptionIsEnabled;
195189
public static final String HTTP_HEADER_PREFIX = "hadoop.http.header.";
@@ -245,8 +239,6 @@ public static class Builder {
245239

246240
private boolean sniHostCheckEnabled;
247241

248-
private Optional<Timer> configurationChangeMonitor = Optional.empty();
249-
250242
public Builder setName(String name){
251243
this.name = name;
252244
return this;
@@ -577,45 +569,12 @@ private ServerConnector createHttpsChannelConnector(
577569
}
578570

579571
setEnabledProtocols(sslContextFactory);
580-
581-
long storesReloadInterval =
582-
conf.getLong(FileBasedKeyStoresFactory.SSL_STORES_RELOAD_INTERVAL_TPL_KEY,
583-
FileBasedKeyStoresFactory.DEFAULT_SSL_STORES_RELOAD_INTERVAL);
584-
585-
if (storesReloadInterval > 0) {
586-
this.configurationChangeMonitor = Optional.of(
587-
this.makeConfigurationChangeMonitor(storesReloadInterval, sslContextFactory));
588-
}
589-
590572
conn.addFirstConnectionFactory(new SslConnectionFactory(sslContextFactory,
591573
HttpVersion.HTTP_1_1.asString()));
592574

593575
return conn;
594576
}
595577

596-
private Timer makeConfigurationChangeMonitor(long reloadInterval,
597-
SslContextFactory.Server sslContextFactory) {
598-
Timer timer = new Timer("SSL Certificates Store Monitor", true);
599-
//
600-
// The Jetty SSLContextFactory provides a 'reload' method which will reload both
601-
// truststore and keystore certificates.
602-
//
603-
timer.schedule(new FileMonitoringTimerTask(
604-
Paths.get(keyStore),
605-
path -> {
606-
LOG.info("Reloading certificates from store keystore " + keyStore);
607-
try {
608-
sslContextFactory.reload(factory -> { });
609-
} catch (Exception ex) {
610-
LOG.error("Failed to reload SSL keystore certificates", ex);
611-
}
612-
},null),
613-
reloadInterval,
614-
reloadInterval
615-
);
616-
return timer;
617-
}
618-
619578
private void setEnabledProtocols(SslContextFactory sslContextFactory) {
620579
String enabledProtocols = conf.get(SSLFactory.SSL_ENABLED_PROTOCOLS_KEY,
621580
SSLFactory.SSL_ENABLED_PROTOCOLS_DEFAULT);
@@ -658,7 +617,6 @@ private HttpServer2(final Builder b) throws IOException {
658617
this.webAppContext = createWebAppContext(b, adminsAcl, appDir);
659618
this.xFrameOptionIsEnabled = b.xFrameEnabled;
660619
this.xFrameOption = b.xFrameOption;
661-
this.configurationChangeMonitor = b.configurationChangeMonitor;
662620

663621
try {
664622
this.secretProvider =
@@ -1426,16 +1384,6 @@ void openListeners() throws Exception {
14261384
*/
14271385
public void stop() throws Exception {
14281386
MultiException exception = null;
1429-
if (this.configurationChangeMonitor.isPresent()) {
1430-
try {
1431-
this.configurationChangeMonitor.get().cancel();
1432-
} catch (Exception e) {
1433-
LOG.error(
1434-
"Error while canceling configuration monitoring timer for webapp"
1435-
+ webAppContext.getDisplayName(), e);
1436-
exception = addMultiException(exception, e);
1437-
}
1438-
}
14391387
for (ServerConnector c : listeners) {
14401388
try {
14411389
c.close();

hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/ssl/FileBasedKeyStoresFactory.java

Lines changed: 79 additions & 137 deletions
Original file line numberDiff line numberDiff line change
@@ -29,20 +29,20 @@
2929
import javax.net.ssl.KeyManagerFactory;
3030
import javax.net.ssl.TrustManager;
3131
import java.io.IOException;
32+
import java.io.InputStream;
33+
import java.nio.file.Files;
3234
import java.nio.file.Paths;
3335
import java.security.GeneralSecurityException;
3436
import java.security.KeyStore;
3537
import java.text.MessageFormat;
36-
import java.util.Timer;
3738

3839
/**
3940
* {@link KeyStoresFactory} implementation that reads the certificates from
4041
* keystore files.
4142
* <p>
42-
* If either the truststore or the keystore certificates file changes, it
43-
* would be refreshed under the corresponding wrapper implementation -
44-
* {@link ReloadingX509KeystoreManager} or {@link ReloadingX509TrustManager}.
45-
* </p>
43+
* if the trust certificates keystore file changes, the {@link TrustManager}
44+
* is refreshed with the new trust certificate entries (using a
45+
* {@link ReloadingX509TrustManager} trustmanager).
4646
*/
4747
@InterfaceAudience.Private
4848
@InterfaceStability.Evolving
@@ -51,13 +51,6 @@ public class FileBasedKeyStoresFactory implements KeyStoresFactory {
5151
private static final Logger LOG =
5252
LoggerFactory.getLogger(FileBasedKeyStoresFactory.class);
5353

54-
/**
55-
* The refresh interval used to check if either of the truststore or keystore
56-
* certificate file has changed.
57-
*/
58-
public static final String SSL_STORES_RELOAD_INTERVAL_TPL_KEY =
59-
"ssl.{0}.stores.reload.interval";
60-
6154
public static final String SSL_KEYSTORE_LOCATION_TPL_KEY =
6255
"ssl.{0}.keystore.location";
6356
public static final String SSL_KEYSTORE_PASSWORD_TPL_KEY =
@@ -84,119 +77,14 @@ public class FileBasedKeyStoresFactory implements KeyStoresFactory {
8477
public static final String DEFAULT_KEYSTORE_TYPE = "jks";
8578

8679
/**
87-
* The default time interval in milliseconds used to check if either
88-
* of the truststore or keystore certificates file has changed and needs reloading.
80+
* Reload interval in milliseconds.
8981
*/
90-
public static final int DEFAULT_SSL_STORES_RELOAD_INTERVAL = 10000;
82+
public static final int DEFAULT_SSL_TRUSTSTORE_RELOAD_INTERVAL = 10000;
9183

9284
private Configuration conf;
9385
private KeyManager[] keyManagers;
9486
private TrustManager[] trustManagers;
9587
private ReloadingX509TrustManager trustManager;
96-
private Timer fileMonitoringTimer;
97-
98-
99-
private void createTrustManagersFromConfiguration(SSLFactory.Mode mode,
100-
String truststoreType,
101-
String truststoreLocation,
102-
long storesReloadInterval)
103-
throws IOException, GeneralSecurityException {
104-
String passwordProperty = resolvePropertyName(mode,
105-
SSL_TRUSTSTORE_PASSWORD_TPL_KEY);
106-
String truststorePassword = getPassword(conf, passwordProperty, "");
107-
if (truststorePassword.isEmpty()) {
108-
// An empty trust store password is legal; the trust store password
109-
// is only required when writing to a trust store. Otherwise it's
110-
// an optional integrity check.
111-
truststorePassword = null;
112-
}
113-
114-
// Check if obsolete truststore specific reload interval is present for backward compatible
115-
long truststoreReloadInterval =
116-
conf.getLong(
117-
resolvePropertyName(mode, SSL_TRUSTSTORE_RELOAD_INTERVAL_TPL_KEY),
118-
storesReloadInterval);
119-
120-
if (LOG.isDebugEnabled()) {
121-
LOG.debug(mode.toString() + " TrustStore: " + truststoreLocation +
122-
", reloading at " + truststoreReloadInterval + " millis.");
123-
}
124-
125-
trustManager = new ReloadingX509TrustManager(
126-
truststoreType,
127-
truststoreLocation,
128-
truststorePassword);
129-
130-
if (truststoreReloadInterval > 0) {
131-
fileMonitoringTimer.schedule(
132-
new FileMonitoringTimerTask(
133-
Paths.get(truststoreLocation),
134-
path -> trustManager.loadFrom(path),
135-
exception -> LOG.error(ReloadingX509TrustManager.RELOAD_ERROR_MESSAGE, exception)),
136-
truststoreReloadInterval,
137-
truststoreReloadInterval);
138-
}
139-
140-
if (LOG.isDebugEnabled()) {
141-
LOG.debug(mode.toString() + " Loaded TrustStore: " + truststoreLocation);
142-
}
143-
trustManagers = new TrustManager[]{trustManager};
144-
}
145-
146-
/**
147-
* Implements logic of initializing the KeyManagers with the options
148-
* to reload keystores.
149-
* @param mode client or server
150-
* @param keystoreType The keystore type.
151-
* @param storesReloadInterval The interval to check if the keystore certificates
152-
* file has changed.
153-
*/
154-
private void createKeyManagersFromConfiguration(SSLFactory.Mode mode,
155-
String keystoreType, long storesReloadInterval)
156-
throws GeneralSecurityException, IOException {
157-
String locationProperty =
158-
resolvePropertyName(mode, SSL_KEYSTORE_LOCATION_TPL_KEY);
159-
String keystoreLocation = conf.get(locationProperty, "");
160-
if (keystoreLocation.isEmpty()) {
161-
throw new GeneralSecurityException("The property '" + locationProperty +
162-
"' has not been set in the ssl configuration file.");
163-
}
164-
String passwordProperty =
165-
resolvePropertyName(mode, SSL_KEYSTORE_PASSWORD_TPL_KEY);
166-
String keystorePassword = getPassword(conf, passwordProperty, "");
167-
if (keystorePassword.isEmpty()) {
168-
throw new GeneralSecurityException("The property '" + passwordProperty +
169-
"' has not been set in the ssl configuration file.");
170-
}
171-
String keyPasswordProperty =
172-
resolvePropertyName(mode, SSL_KEYSTORE_KEYPASSWORD_TPL_KEY);
173-
// Key password defaults to the same value as store password for
174-
// compatibility with legacy configurations that did not use a separate
175-
// configuration property for key password.
176-
String keystoreKeyPassword = getPassword(
177-
conf, keyPasswordProperty, keystorePassword);
178-
if (LOG.isDebugEnabled()) {
179-
LOG.debug(mode.toString() + " KeyStore: " + keystoreLocation);
180-
}
181-
182-
ReloadingX509KeystoreManager keystoreManager = new ReloadingX509KeystoreManager(
183-
keystoreType,
184-
keystoreLocation,
185-
keystorePassword,
186-
keystoreKeyPassword);
187-
188-
if (storesReloadInterval > 0) {
189-
fileMonitoringTimer.schedule(
190-
new FileMonitoringTimerTask(
191-
Paths.get(keystoreLocation),
192-
path -> keystoreManager.loadFrom(path),
193-
exception -> LOG.error(ReloadingX509KeystoreManager.RELOAD_ERROR_MESSAGE, exception)),
194-
storesReloadInterval,
195-
storesReloadInterval);
196-
}
197-
198-
keyManagers = new KeyManager[] { keystoreManager };
199-
}
20088

20189
/**
20290
* Resolves a property name to its client/server version if applicable.
@@ -251,28 +139,56 @@ public void init(SSLFactory.Mode mode)
251139
conf.getBoolean(SSLFactory.SSL_REQUIRE_CLIENT_CERT_KEY,
252140
SSLFactory.SSL_REQUIRE_CLIENT_CERT_DEFAULT);
253141

254-
long storesReloadInterval = conf.getLong(
255-
resolvePropertyName(mode, SSL_STORES_RELOAD_INTERVAL_TPL_KEY),
256-
DEFAULT_SSL_STORES_RELOAD_INTERVAL);
257-
258-
fileMonitoringTimer = new Timer("SSL Certificates Store Monitor", true);
259-
260142
// certificate store
261143
String keystoreType =
262-
conf.get(resolvePropertyName(mode, SSL_KEYSTORE_TYPE_TPL_KEY),
263-
DEFAULT_KEYSTORE_TYPE);
264-
144+
conf.get(resolvePropertyName(mode, SSL_KEYSTORE_TYPE_TPL_KEY),
145+
DEFAULT_KEYSTORE_TYPE);
146+
KeyStore keystore = KeyStore.getInstance(keystoreType);
147+
String keystoreKeyPassword = null;
265148
if (requireClientCert || mode == SSLFactory.Mode.SERVER) {
266-
createKeyManagersFromConfiguration(mode, keystoreType, storesReloadInterval);
149+
String locationProperty =
150+
resolvePropertyName(mode, SSL_KEYSTORE_LOCATION_TPL_KEY);
151+
String keystoreLocation = conf.get(locationProperty, "");
152+
if (keystoreLocation.isEmpty()) {
153+
throw new GeneralSecurityException("The property '" + locationProperty +
154+
"' has not been set in the ssl configuration file.");
155+
}
156+
String passwordProperty =
157+
resolvePropertyName(mode, SSL_KEYSTORE_PASSWORD_TPL_KEY);
158+
String keystorePassword = getPassword(conf, passwordProperty, "");
159+
if (keystorePassword.isEmpty()) {
160+
throw new GeneralSecurityException("The property '" + passwordProperty +
161+
"' has not been set in the ssl configuration file.");
162+
}
163+
String keyPasswordProperty =
164+
resolvePropertyName(mode, SSL_KEYSTORE_KEYPASSWORD_TPL_KEY);
165+
// Key password defaults to the same value as store password for
166+
// compatibility with legacy configurations that did not use a separate
167+
// configuration property for key password.
168+
keystoreKeyPassword = getPassword(
169+
conf, keyPasswordProperty, keystorePassword);
170+
if (LOG.isDebugEnabled()) {
171+
LOG.debug(mode.toString() + " KeyStore: " + keystoreLocation);
172+
}
173+
174+
InputStream is = Files.newInputStream(Paths.get(keystoreLocation));
175+
try {
176+
keystore.load(is, keystorePassword.toCharArray());
177+
} finally {
178+
is.close();
179+
}
180+
if (LOG.isDebugEnabled()) {
181+
LOG.debug(mode.toString() + " Loaded KeyStore: " + keystoreLocation);
182+
}
267183
} else {
268-
KeyStore keystore = KeyStore.getInstance(keystoreType);
269184
keystore.load(null, null);
270-
KeyManagerFactory keyMgrFactory = KeyManagerFactory
271-
.getInstance(SSLFactory.SSLCERTIFICATE);
272-
273-
keyMgrFactory.init(keystore, null);
274-
keyManagers = keyMgrFactory.getKeyManagers();
275185
}
186+
KeyManagerFactory keyMgrFactory = KeyManagerFactory
187+
.getInstance(SSLFactory.SSLCERTIFICATE);
188+
189+
keyMgrFactory.init(keystore, (keystoreKeyPassword != null) ?
190+
keystoreKeyPassword.toCharArray() : null);
191+
keyManagers = keyMgrFactory.getKeyManagers();
276192

277193
//trust store
278194
String truststoreType =
@@ -283,7 +199,33 @@ public void init(SSLFactory.Mode mode)
283199
resolvePropertyName(mode, SSL_TRUSTSTORE_LOCATION_TPL_KEY);
284200
String truststoreLocation = conf.get(locationProperty, "");
285201
if (!truststoreLocation.isEmpty()) {
286-
createTrustManagersFromConfiguration(mode, truststoreType, truststoreLocation, storesReloadInterval);
202+
String passwordProperty = resolvePropertyName(mode,
203+
SSL_TRUSTSTORE_PASSWORD_TPL_KEY);
204+
String truststorePassword = getPassword(conf, passwordProperty, "");
205+
if (truststorePassword.isEmpty()) {
206+
// An empty trust store password is legal; the trust store password
207+
// is only required when writing to a trust store. Otherwise it's
208+
// an optional integrity check.
209+
truststorePassword = null;
210+
}
211+
long truststoreReloadInterval =
212+
conf.getLong(
213+
resolvePropertyName(mode, SSL_TRUSTSTORE_RELOAD_INTERVAL_TPL_KEY),
214+
DEFAULT_SSL_TRUSTSTORE_RELOAD_INTERVAL);
215+
216+
if (LOG.isDebugEnabled()) {
217+
LOG.debug(mode.toString() + " TrustStore: " + truststoreLocation);
218+
}
219+
220+
trustManager = new ReloadingX509TrustManager(truststoreType,
221+
truststoreLocation,
222+
truststorePassword,
223+
truststoreReloadInterval);
224+
trustManager.init();
225+
if (LOG.isDebugEnabled()) {
226+
LOG.debug(mode.toString() + " Loaded TrustStore: " + truststoreLocation);
227+
}
228+
trustManagers = new TrustManager[]{trustManager};
287229
} else {
288230
if (LOG.isDebugEnabled()) {
289231
LOG.debug("The property '" + locationProperty + "' has not been set, " +
@@ -314,7 +256,7 @@ String getPassword(Configuration conf, String alias, String defaultPass) {
314256
@Override
315257
public synchronized void destroy() {
316258
if (trustManager != null) {
317-
fileMonitoringTimer.cancel();
259+
trustManager.destroy();
318260
trustManager = null;
319261
keyManagers = null;
320262
trustManagers = null;

0 commit comments

Comments
 (0)