blob: 639d85521c3ced699d69f4e391bfbdf532422950 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.hadoop.crypto.key.kms.server;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.util.LinkedHashSet;
import java.util.Set;
import org.apache.hadoop.classification.InterfaceAudience;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.http.HttpServer2;
import org.apache.hadoop.metrics2.lib.DefaultMetricsSystem;
import org.apache.hadoop.metrics2.source.JvmMetrics;
import org.apache.hadoop.security.AuthenticationFilterInitializer;
import org.apache.hadoop.security.authentication.server.ProxyUserAuthenticationFilterInitializer;
import org.apache.hadoop.security.authorize.AccessControlList;
import org.apache.hadoop.security.ssl.SSLFactory;
import org.apache.hadoop.util.JvmPauseMonitor;
import org.apache.hadoop.util.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static org.apache.hadoop.crypto.key.kms.server.KMSConfiguration.METRICS_PROCESS_NAME_DEFAULT;
import static org.apache.hadoop.crypto.key.kms.server.KMSConfiguration.METRICS_PROCESS_NAME_KEY;
import static org.apache.hadoop.crypto.key.kms.server.KMSConfiguration.METRICS_SESSION_ID_KEY;
/**
* The KMS web server.
*/
@InterfaceAudience.Private
public class KMSWebServer {
private static final Logger LOG =
LoggerFactory.getLogger(KMSWebServer.class);
private static final String NAME = "kms";
private static final String SERVLET_PATH = "/kms";
private final HttpServer2 httpServer;
private final String scheme;
private final String processName;
private final String sessionId;
private final JvmPauseMonitor pauseMonitor;
KMSWebServer(Configuration conf, Configuration sslConf) throws Exception {
// Override configuration with deprecated environment variables.
deprecateEnv("KMS_TEMP", conf, HttpServer2.HTTP_TEMP_DIR_KEY,
KMSConfiguration.KMS_SITE_XML);
deprecateEnv("KMS_HTTP_PORT", conf,
KMSConfiguration.HTTP_PORT_KEY, KMSConfiguration.KMS_SITE_XML);
deprecateEnv("KMS_MAX_THREADS", conf,
HttpServer2.HTTP_MAX_THREADS_KEY, KMSConfiguration.KMS_SITE_XML);
deprecateEnv("KMS_MAX_HTTP_HEADER_SIZE", conf,
HttpServer2.HTTP_MAX_REQUEST_HEADER_SIZE_KEY,
KMSConfiguration.KMS_SITE_XML);
deprecateEnv("KMS_MAX_HTTP_HEADER_SIZE", conf,
HttpServer2.HTTP_MAX_RESPONSE_HEADER_SIZE_KEY,
KMSConfiguration.KMS_SITE_XML);
deprecateEnv("KMS_SSL_ENABLED", conf,
KMSConfiguration.SSL_ENABLED_KEY, KMSConfiguration.KMS_SITE_XML);
deprecateEnv("KMS_SSL_KEYSTORE_FILE", sslConf,
SSLFactory.SSL_SERVER_KEYSTORE_LOCATION,
SSLFactory.SSL_SERVER_CONF_DEFAULT);
deprecateEnv("KMS_SSL_KEYSTORE_PASS", sslConf,
SSLFactory.SSL_SERVER_KEYSTORE_PASSWORD,
SSLFactory.SSL_SERVER_CONF_DEFAULT);
boolean sslEnabled = conf.getBoolean(KMSConfiguration.SSL_ENABLED_KEY,
KMSConfiguration.SSL_ENABLED_DEFAULT);
scheme = sslEnabled ? HttpServer2.HTTPS_SCHEME : HttpServer2.HTTP_SCHEME;
processName =
conf.get(METRICS_PROCESS_NAME_KEY, METRICS_PROCESS_NAME_DEFAULT);
sessionId = conf.get(METRICS_SESSION_ID_KEY);
pauseMonitor = new JvmPauseMonitor();
pauseMonitor.init(conf);
String host = conf.get(KMSConfiguration.HTTP_HOST_KEY,
KMSConfiguration.HTTP_HOST_DEFAULT);
int port = conf.getInt(KMSConfiguration.HTTP_PORT_KEY,
KMSConfiguration.HTTP_PORT_DEFAULT);
URI endpoint = new URI(scheme, null, host, port, null, null, null);
String configuredInitializers =
conf.get(HttpServer2.FILTER_INITIALIZER_PROPERTY);
if (configuredInitializers != null) {
Set<String> target = new LinkedHashSet<String>();
String[] initializers = configuredInitializers.split(",");
for (String init : initializers) {
if (!init.equals(AuthenticationFilterInitializer.class.getName()) &&
!init.equals(
ProxyUserAuthenticationFilterInitializer.class.getName())) {
target.add(init);
}
}
String actualInitializers = StringUtils.join(",", target);
conf.set(HttpServer2.FILTER_INITIALIZER_PROPERTY, actualInitializers);
}
httpServer = new HttpServer2.Builder()
.setName(NAME)
.setConf(conf)
.setSSLConf(sslConf)
.authFilterConfigurationPrefix(KMSAuthenticationFilter.CONFIG_PREFIX)
.setACL(new AccessControlList(conf.get(
KMSConfiguration.HTTP_ADMINS_KEY, " ")))
.addEndpoint(endpoint)
.build();
}
/**
* Load the deprecated environment variable into the configuration.
*
* @param varName the environment variable name
* @param conf the configuration
* @param propName the configuration property name
* @param confFile the configuration file name
*/
private static void deprecateEnv(String varName, Configuration conf,
String propName, String confFile) {
String value = System.getenv(varName);
if (value == null) {
return;
}
LOG.warn("Environment variable {} is deprecated and overriding"
+ " property {}, please set the property in {} instead.",
varName, propName, confFile);
conf.set(propName, value, "environment variable " + varName);
}
public void start() throws IOException {
httpServer.start();
DefaultMetricsSystem.initialize(processName);
final JvmMetrics jm = JvmMetrics.initSingleton(processName, sessionId);
jm.setPauseMonitor(pauseMonitor);
pauseMonitor.start();
}
public boolean isRunning() {
return httpServer.isAlive();
}
public void join() throws InterruptedException {
httpServer.join();
}
public void stop() throws Exception {
httpServer.stop();
pauseMonitor.stop();
JvmMetrics.shutdownSingleton();
DefaultMetricsSystem.shutdown();
}
public URL getKMSUrl() {
InetSocketAddress addr = httpServer.getConnectorAddress(0);
if (null == addr) {
return null;
}
try {
return new URL(scheme, addr.getHostName(), addr.getPort(),
SERVLET_PATH);
} catch (MalformedURLException ex) {
throw new RuntimeException("It should never happen: " + ex.getMessage(),
ex);
}
}
public static void main(String[] args) throws Exception {
KMSConfiguration.initLogging();
StringUtils.startupShutdownMessage(KMSWebServer.class, args, LOG);
Configuration conf = KMSConfiguration.getKMSConf();
Configuration sslConf = SSLFactory.readSSLConfiguration(conf, SSLFactory.Mode.SERVER);
KMSWebServer kmsWebServer = new KMSWebServer(conf, sslConf);
kmsWebServer.start();
kmsWebServer.join();
}
}