When authenticating a connection from a daemon, use the FQDN instead of hostname. Use an Eviction cache instead of Set
import javax.security.sasl.SaslException;
import javax.security.sasl.SaslServer;
+import com.google.common.base.Preconditions;
+import com.google.common.cache.Cache;
+import com.google.common.cache.CacheBuilder;
import io.hops.security.HopsUtil;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -441,7 +444,7 @@ protected ResponseBuffer initialValue() {
private final CRLValidator crlValidator;
private SSLFactory sslFactory = null;
private String proxySuperuser = null;
- private Set<String> trustedHostnames;
+ private Cache<InetAddress, String> trustedHostnames;
private boolean logSlowRPC = false;
@@ -2306,11 +2309,15 @@ private void authenticateSSLConnection(UserGroupInformation protocolUser)
return;
}
- // The CN could also be the machine hostname.
+ // The CN could also be the machine FQDN.
// These certificates will be used by Hops services RM, NM, NN, DN
// Assume that reverse DNS will succeed only for machines that we
// trust
- if (trustedHostnames.contains(cn)) {
+ // Try reverse DNS of the address to check if the CN matches
+ InetAddress remoteAddress = socket.getInetAddress();
+ Preconditions.checkNotNull(remoteAddress, "Remote address should not be null");
+ String cachedFqdn = trustedHostnames.getIfPresent(remoteAddress);
+ if (cachedFqdn != null) {
if (LOG.isDebugEnabled()) {
LOG.debug("SSL authentication: CN is hostname and hostname " +
"already authenticated");
@@ -2318,19 +2325,19 @@ private void authenticateSSLConnection(UserGroupInformation protocolUser)
return;
}
- try {
- String remoteHostname = InetAddress.getByName(cn).getHostName();
- if (remoteHostname.equals(cn)) {
- trustedHostnames.add(cn);
- if (LOG.isDebugEnabled()) {
- LOG.debug("SSL authentication: CN is hostname but just " +
- "authenticated");
- }
+ String fqdn = remoteAddress.getCanonicalHostName();
+ if (cn.equals(fqdn)) {
+ trustedHostnames.put(remoteAddress, fqdn);
+ LOG.debug("TLS authentication: CN is the FQDN and just resolved");
+ return;
+ } else {
+ // Check the hostname for backwards compatibility
+ String hostname = socket.getInetAddress().getHostName();
+ if (cn.equals(hostname)) {
+ trustedHostnames.put(remoteAddress, hostname);
+ LOG.debug("TLS authentication: CN is the hostname and just resolved. Warning: hostname is deprecated");
return;
}
- } catch (UnknownHostException ex) {
- // Continue and an authentication exception will be thrown later on
- LOG.error("SSL authentication: Could not resolve CN=" + cn);
}
// Incoming RPC did not manage to authenticate
@@ -2912,7 +2919,11 @@ protected Server(String bindAddress, int port,
proxySuperuser = "glassfish";
}
- trustedHostnames = new ConcurrentSkipListSet<>();
+ // <InetAddress, FQDN>
+ trustedHostnames = CacheBuilder.newBuilder()
+ .maximumSize(500)
+ .expireAfterWrite(30, TimeUnit.MINUTES)
+ .build();
if (conf.getBoolean(CommonConfigurationKeysPublic.HOPS_CRL_VALIDATION_ENABLED_KEY,
CommonConfigurationKeysPublic.HOPS_CRL_VALIDATION_ENABLED_DEFAULT)) {
