Skip to content

Commit 78db8e9

Browse files
authored
HIVE-29112: HMS embedded servlets https support (#6002)
HIVE-29912: added configuration variable hive.metastore.httpserver.use.https that drives if catalog/property servlets are using https; - requires the same keystore/truststore configuration than useSSL; - added tests & self signed certificates (good for 10 years); - renamed conditional version of createSslContextFactory to createSslContextFactoryIf; - addressing review comments; - USE_SSL drive https endpoint creation; - refactored ServletServerBuilder#createConnector(); - removed useless method ServletServerBuilder#createSslContextFactory() and ServletSecurity#createSslContextFactory(); - removed junit.jupiter.* that break compilation (?!);
1 parent 52cfa6f commit 78db8e9

File tree

10 files changed

+344
-223
lines changed

10 files changed

+344
-223
lines changed

standalone-metastore/metastore-common/src/main/java/org/apache/hadoop/hive/metastore/properties/HMSPropertyManager.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
* <ul>
3232
* <li>name : when it refers to a cluster property named 'name'</li>
3333
* <li>db.name : when it refers to a database property named 'name' for the database 'db'</li>
34-
* <li>db.table.name : when it refers to a table property named 'name' for the table 'table' in the database 'db</li>
34+
* <li>db.table.name : when it refers to a table property named 'name' for the table 'table' in the database 'db'</li>
3535
* </ul>
3636
*/
3737
public class HMSPropertyManager extends PropertyManager {
@@ -80,7 +80,8 @@ public enum MaintenanceOpStatus {
8080
CLEANUP_NEEDED,
8181
FAILED
8282
}
83-
/** The map form ordinal to OpStatus. */
83+
84+
/** The map from ordinal to OpStatus. */
8485
private static final Map<Integer, MaintenanceOpStatus> MOS;
8586
static {
8687
MOS = new HashMap<>(MaintenanceOpStatus.values().length);
@@ -111,6 +112,7 @@ public static MaintenanceOpStatus findOpStatus(int ordinal) {
111112
}
112113
return parse(value.toString());
113114
}
115+
114116
@Override public MaintenanceOpType parse(String str) {
115117
if (str == null) {
116118
return null;
@@ -142,12 +144,14 @@ public static MaintenanceOpStatus findOpStatus(int ordinal) {
142144
}
143145
return parse(value.toString());
144146
}
147+
145148
@Override public MaintenanceOpStatus parse(String str) {
146149
if (str == null) {
147150
return null;
148151
}
149152
return MaintenanceOpStatus.valueOf(str.toUpperCase());
150153
}
154+
151155
@Override public String format(Object value) {
152156
if (value instanceof MaintenanceOpStatus) {
153157
return value.toString();

standalone-metastore/metastore-server/src/main/java/org/apache/hadoop/hive/metastore/ServletSecurity.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -304,13 +304,13 @@ static void loginServerPrincipal(Configuration conf) throws IOException {
304304
}
305305

306306
/**
307-
* Creates an SSL context factory if configuration states so.
307+
* Creates an SSL context factory if the configuration states so.
308308
* @param conf the configuration
309309
* @return null if no ssl in config, an instance otherwise
310310
* @throws IOException if getting password fails
311311
*/
312312
static SslContextFactory createSslContextFactory(Configuration conf) throws IOException {
313-
final boolean useSsl = MetastoreConf.getBoolVar(conf, MetastoreConf.ConfVars.USE_SSL);
313+
final boolean useSsl = MetastoreConf.getBoolVar(conf, MetastoreConf.ConfVars.USE_SSL);
314314
if (!useSsl) {
315315
return null;
316316
}

standalone-metastore/metastore-server/src/main/java/org/apache/hadoop/hive/metastore/ServletServerBuilder.java

Lines changed: 40 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,14 @@
1818
*/
1919
package org.apache.hadoop.hive.metastore;
2020

21+
import static org.eclipse.jetty.util.URIUtil.HTTP;
22+
import static org.eclipse.jetty.util.URIUtil.HTTPS;
23+
2124
import org.apache.hadoop.conf.Configuration;
2225
import org.apache.hadoop.hive.metastore.conf.MetastoreConf;
2326
import org.eclipse.jetty.server.HttpConfiguration;
2427
import org.eclipse.jetty.server.HttpConnectionFactory;
28+
import org.eclipse.jetty.server.SecureRequestCustomizer;
2529
import org.eclipse.jetty.server.Server;
2630
import org.eclipse.jetty.server.ServerConnector;
2731
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
@@ -32,6 +36,7 @@
3236
import org.eclipse.jetty.util.ssl.SslContextFactory;
3337
import org.eclipse.jetty.util.thread.QueuedThreadPool;
3438
import org.slf4j.Logger;
39+
import org.slf4j.LoggerFactory;
3540

3641
import javax.servlet.Servlet;
3742
import javax.servlet.http.HttpServlet;
@@ -46,10 +51,11 @@
4651
import java.util.function.Function;
4752

4853
/**
49-
* Helper class to ease creation of embedded Jetty serving servlets on
54+
* Helper class to ease the creation of embedded Jetty serving servlets on
5055
* different ports.
5156
*/
5257
public class ServletServerBuilder {
58+
private static final Logger LOGGER = LoggerFactory.getLogger(ServletServerBuilder.class);
5359
/**
5460
* The configuration instance.
5561
*/
@@ -94,7 +100,7 @@ public static ServletServerBuilder builder(Configuration conf,
94100
}
95101

96102
/**
97-
* Helper for generic use case.
103+
* Helper for the generic use case.
98104
*
99105
* @param logger the logger
100106
* @param conf the configuration
@@ -116,7 +122,7 @@ public Configuration getConfiguration() {
116122
/**
117123
* Adds a servlet instance.
118124
* <p>The servlet port can be shared between servlets; if 0, the system will provide
119-
* a port. If the port is &lt; 0, the system will provide a port dedicated (ie non-shared)
125+
* a port. If the port is &lt; 0, the system will provide a port dedicated (i.e., non-shared)
120126
* to the servlet.</p>
121127
*
122128
* @param port the servlet port
@@ -159,24 +165,32 @@ private Server createServer() {
159165
}
160166

161167
/**
162-
* Creates a server instance and a connector on a given port.
168+
* Create an HTTP or HTTPS connector.
163169
*
164-
* @param server the server instance
165-
* @param sslContextFactory the ssl factory
166-
* @param port the port
167-
* @return the server connector listening to the port
170+
* @param server The server to create the connector for
171+
* @param sslContextFactory The ssl context factory to use;
172+
* if null, the connector will be HTTP; if not null, the connector will be HTTPS
173+
* @param port The port to bind the connector to
174+
* @return The created ServerConnector
168175
*/
169176
private ServerConnector createConnector(Server server, SslContextFactory sslContextFactory, int port) {
170-
final ServerConnector connector = new ServerConnector(server, sslContextFactory);
177+
final ServerConnector connector;
178+
HttpConfiguration httpConf = new HttpConfiguration();
179+
// Do not leak information
180+
httpConf.setSendServerVersion(false);
181+
httpConf.setSendXPoweredBy(false);
182+
if (sslContextFactory != null) {
183+
httpConf.setSecureScheme(HTTPS);
184+
httpConf.setSecurePort(port);
185+
httpConf.addCustomizer(new SecureRequestCustomizer());
186+
connector = new ServerConnector(server, sslContextFactory, new HttpConnectionFactory(httpConf));
187+
connector.setName(HTTPS);
188+
} else {
189+
connector = new ServerConnector(server, new HttpConnectionFactory(httpConf));
190+
connector.setName(HTTP);
191+
}
171192
connector.setPort(port);
172193
connector.setReuseAddress(true);
173-
HttpConnectionFactory httpFactory = connector.getConnectionFactory(HttpConnectionFactory.class);
174-
// do not leak information
175-
if (httpFactory != null) {
176-
HttpConfiguration httpConf = httpFactory.getHttpConfiguration();
177-
httpConf.setSendServerVersion(false);
178-
httpConf.setSendXPoweredBy(false);
179-
}
180194
return connector;
181195
}
182196

@@ -204,7 +218,7 @@ private void addServlet(Map<Integer, ServletContextHandler> handlersMap, Descrip
204218
}
205219

206220
/**
207-
* Convenience method to start a http server that serves all configured
221+
* Convenience method to start an http server that serves all configured
208222
* servlets.
209223
*
210224
* @return the server instance or null if no servlet was configured
@@ -222,15 +236,16 @@ public Server startServer() throws Exception {
222236
}
223237
final Server server = createServer();
224238
// create the connectors
225-
final SslContextFactory sslFactory = ServletSecurity.createSslContextFactory(configuration);
239+
final SslContextFactory sslContextFactory = ServletSecurity.createSslContextFactory(configuration);
226240
final ServerConnector[] connectors = new ServerConnector[size];
227241
final ServletContextHandler[] handlers = new ServletContextHandler[size];
228242
Iterator<Map.Entry<Integer, ServletContextHandler>> it = handlersMap.entrySet().iterator();
229243
for (int c = 0; it.hasNext(); ++c) {
230244
Map.Entry<Integer, ServletContextHandler> entry = it.next();
231245
int key = entry.getKey();
232246
int port = Math.max(key, 0);
233-
ServerConnector connector = createConnector(server, sslFactory, port);
247+
ServerConnector connector = createConnector(server, sslContextFactory, port);
248+
LOGGER.info("Adding {} servlet connector on port {}", connector.getName(), port);
234249
connectors[c] = connector;
235250
ServletContextHandler handler = entry.getValue();
236251
handlers[c] = handler;
@@ -268,7 +283,7 @@ public Server startServer() throws Exception {
268283
* Creates and starts the server.
269284
*
270285
* @param logger a logger to output info
271-
* @return the server instance (or null if error)
286+
* @return the server instance (or null if an error occurred)
272287
*/
273288
public Server start(Logger logger) {
274289
try {
@@ -278,21 +293,21 @@ public Server start(Logger logger) {
278293
logger.error("Unable to start servlet server on {}", server.getURI());
279294
} else {
280295
descriptorsMap.values().forEach(descriptor -> logger.info("Started {} servlet on {}:{}",
281-
descriptor.toString(),
296+
descriptor,
282297
descriptor.getPort(),
283298
descriptor.getPath()));
284299
}
285300
}
286301
return server;
287-
} catch (Throwable throwable) {
288-
logger.error("Unable to start servlet server", throwable);
302+
} catch (Exception e) {
303+
logger.error("Unable to start servlet server", e);
289304
return null;
290305
}
291306
}
292307

293308
/**
294309
* A descriptor of a servlet.
295-
* <p>After server is started, unspecified port will be updated to reflect
310+
* <p>After the server is started, unspecified port will be updated to reflect
296311
* what the system allocated.</p>
297312
*/
298313
public static class Descriptor {
@@ -303,7 +318,7 @@ public static class Descriptor {
303318
/**
304319
* Create a servlet descriptor.
305320
*
306-
* @param port the servlet port (or 0 if system allocated)
321+
* @param port the servlet port (or 0 if the port is to be chosen by the system)
307322
* @param path the servlet path
308323
* @param servlet the servlet instance
309324
*/

0 commit comments

Comments
 (0)