Chapter 3. Securing the Undertow HTTP Server
Abstract
You can configure the built-in Undertow HTTP server to use SSL/TLS security by editing the contents of the etc/undertow.xml
configuration file. In particular, you can add SSL/TLS security to the Fuse Console in this way.
3.1. Undertow server
The Fuse container is pre-configured with an Undertow server, which acts as a general-purpose HTTP server and HTTP servlet container. Through a single HTTP port (by default, http://localhost:8181
), the Undertow container can host multiple services, for example:
-
Fuse Console (by default,
http://localhost:8181/hawtio
) - Apache CXF Web services endpoints (if the host and port are left unspecified in the endpoint configuration)
- Some Apache Camel endpoints
If you use the default Undertow server for all of your HTTP endpoints, you can conveniently add SSL/TLS security to these HTTP endpoints by following the steps described here.
3.2. Create X.509 certificate and private key
Before you can enable SSL/TLS on the Undertow server, you must create an X.509 certificate and private key, where the certificate and private key must be in Java keystore format (JKS format). For details of how to create a signed certificate and private key, see Appendix A, Managing Certificates.
3.3. Enabling SSL/TLS for Undertow in an Apache Karaf container
For the following procedure, it is assumed that you have already created a signed X.509 certificate and private key pair in the keystore file, alice.ks
, with keystore password, StorePass
, and key password, KeyPass
.
To enable SSL/TLS for Undertow in a Karaf container:
Make sure that the Pax Web server is configured to take its configuration from the
etc/undertow.xml
file. When you look at the contents of theetc/org.ops4j.pax.web.cfg
file, you should see the following setting:org.ops4j.pax.web.config.file=${karaf.etc}/undertow.xml
Open the file,
etc/org.ops4j.pax.web.cfg
, in a text editor and add the following line:org.osgi.service.http.port.secure=8443
Save and close the file,
etc/org.ops4j.pax.web.cfg
.-
Open the file,
etc/undertow.xml
, in a text editor. The next steps assume you are working with the defaultundertow.xml
file, unchanged since installation time. Search for the XML elements,
http-listener
andhttps-listener
. Comment out thehttp-listener
element (by enclosing it between<!--
and-->
) and uncomment thehttps-listener
element (spread over two lines). The edited fragment of XML should now look something like this:<!-- HTTP(S) Listener references Socket Binding (and indirectly - Interfaces) --> <!-- http-listener name="http" socket-binding="http" /> --> <!-- verify-client: org.xnio.SslClientAuthMode.NOT_REQUESTED, org.xnio.SslClientAuthMode.REQUESTED, org.xnio.SslClientAuthMode.REQUIRED --> <https-listener name="https" socket-binding="https" security-realm="https" verify-client="NOT_REQUESTED" />
Search for the
w:keystore
element. By default, thew:keystore
element is configured as follows:<w:keystore path="${karaf.etc}/certs/server.keystore" provider="JKS" alias="server" keystore-password="secret" key-password="secret" generate-self-signed-certificate-host="localhost" />
To install the
alice
certificate as the Undertow server’s certificate, modify thew:keystore
element attributes as follows:-
Set
path
to the absolute location of thealice.ks
file on the file system. -
Set
provider
toJKS
. -
Set
alias
to thealice
certificate alias in the keystore. -
Set
keystore-password
to the value of the password that unlocks the key store. -
Set
key-password
to the value of the password that encrypts thealice
private key. -
Delete the
generate-self-signed-certificate-host
attribute setting.
-
Set
For example, after installing the
alice.ks
keystore, the modifiedw:keystore
element would look something like this:<w:keystore path="${karaf.etc}/certs/alice.ks" provider="JKS" alias="alice" keystore-password="StorePass" key-password="KeyPass" />
Search for the
<interface name="secure">
tag, which is used to specify the IP addresses the secure HTTPS port binds to. By default, this element is commented out, as follows:<!--<interface name="secure">--> <!--<w:inet-address value="127.0.0.1" />--> <!--</interface>-->
Uncomment the element and customize the
value
attribute to specify the IP address which the HTTPS port binds to. For example, the wildcard value,0.0.0.0
, configures HTTPS to bind to all available IP addresses:<interface name="secure"> <w:inet-address value="0.0.0.0" /> </interface>
Search for and uncomment the
<socket-binding name="https"
tag. When this tag is uncommented, it should look something like this:<socket-binding name="https" interface="secure" port="${org.osgi.service.http.port.secure}" />
-
Save and close the file,
etc/undertow.xml
. - Restart the Fuse container, in order for the configuration changes to take effect.
3.4. Customizing allowed TLS protocols and cipher suites
You can customize the allowed TLS protocols and cipher suites by modifying the following attributes of the w:engine
element in the etc/undertow.xml
file:
enabled-cipher-suites
- Specifies the list of allowed TLS/SSL cipher suites.
enabled-protocols
Specifies the list of allowed TLS/SSL protocols.
WarningDo not enable
SSL
protocol versions, as they are vulnerable to attack. Use onlyTLS
protocol versions.
For full details of the available protocols and cipher suites, consult the appropriate JVM documentation and security provider documentation. For example, for Java 8, see Java Cryptography Architecture Oracle Providers Documentation for JDK 8.
3.5. Connect to the secure console
After configuring SSL security for the Undertow server in the Pax Web configuration file, you should be able to open the Fuse Console by browsing to the following URL:
https://localhost:8443/hawtio
Remember to type the https:
scheme, instead of http:
, in this URL.
Initially, the browser will warn you that you are using an untrusted certificate. Skip this warning and you will be presented with the login screen for the Fuse Console.
3.6. Advanced configurations for Undertow
There are three layers of Undertow configuration. The simple way to configure Undertow is by using the org.ops4j.pax.web
PID in the configuration Admin service. In Apache Karaf, you can configure the $KARAF_HOME/etc/org.ops4j.pax.web.cfg
file.
3.6.1. Using undertow.xml file
The org.ops4j.pax.web.config.file
option refers to undertow.xml
or any file with .xml
extension. The referenced file is used to configure advanced aspects of the Undertow embedded server.
Fuse Karaf embeds Undertow.
The pax-web-undertow
reuses XML Schemas from RHEL and the Undertow subsystem. The pax-web
does not use RHEL classes for parsing and processing the XML configuration files, so all the options are valid.
The supported configuration elements are described as follows:
The
pax-web-undertow
bundle uses an XML configuration of the Undertow server according to the following schemas:-
The
pax-web
specific configuration file, see https://raw.githubusercontent.com/ops4j/org.ops4j.pax.web/pax-web-6.1.x/pax-web-undertow/src/main/resources/schema/pax-web-undertow_1_0.xsd - The generic RHEL configuration file, see http://www.jboss.org/schema/jbossas/wildfly-config_5_0.xsd
- RHEL Undertow subsystem configuration file, see http://www.jboss.org/schema/jbossas/wildfly-undertow_4_0.xsd
-
The
-
The
pax-web
specific XML Schema provides a wrapper and the configuration elements are taken from one of the schemas specific to EAP. -
The template XML configuration file is available as a Maven artifact with the
mvn:org.ops4j.pax.web/pax-web-features/7.2.2/xml/undertowconfig
URI and looks like the sample below:
--- <?xml version="1.0" encoding="UTF-8"?>
<!-- Copyright 2005-2018 Red Hat, Inc. Red Hat 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.
-→
<undertow xmlns="urn:org.ops4j.pax.web:undertow:1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:w="urn:jboss:domain:5.0"
xsi:schemaLocation="
urn:jboss:domain:undertow:4.0 http://www.jboss.org/schema/jbossas/wildfly-undertow_4_0.xsd
urn:jboss:domain:5.0 http://www.jboss.org/schema/jbossas/wildfly-config_5_0.xsd">
<!-- https://docs.jboss.org/author/display/WFLY/Undertow+subsystem+configuration -->
<subsystem xmlns="urn:jboss:domain:undertow:4.0">
<!-- org.wildfly.extension.undertow.BufferCacheDefinition -->
<buffer-cache name="default" buffer-size="1024" buffers-per-region="1024" max-regions="10" />
<server name="default-server">
<!-- HTTP(S) Listener references Socket Binding (and indirectly - Interfaces) -->
<http-listener name="http" socket-binding="http" />
<!-- verify-client: org.xnio.SslClientAuthMode.NOT_REQUESTED, org.xnio.SslClientAuthMode.REQUESTED, org.xnio.SslClientAuthMode.REQUIRED -->
<!--<https-listener name="https" socket-binding="https"-->
<!--security-realm="https" verify-client="NOT_REQUESTED" />-->
<host name="default-host" alias="localhost">
<location name="/" handler="welcome-content" />
<!--<location name="/docs" handler="docs-content" />-->
<access-log directory="${karaf.data}/log" pattern="common" prefix="access_log." suffix="log" rotate="true" />
<filter-ref name="server-header" />
<filter-ref name="x-powered-by-header" />
</host>
</server>
<servlet-container name="default">
<jsp-config />
<websockets />
<welcome-files>
<welcome-file name="index.html" />
<welcome-file name="index.txt" />
</welcome-files>
</servlet-container>
<handlers>
<file name="welcome-content" path="${karaf.home}/welcome-content" />
<!--<file name="docs-content" path="${karaf.home}/docs" />-->
</handlers>
<filters>
<!-- filters for reference from /host/filter-ref and /host/location/filter-ref -->
<response-header name="server-header" header-name="Server" header-value="Pax-HTTP-Undertow" />
<response-header name="x-powered-by-header" header-name="X-Powered-By" header-value="Open Source" />
</filters>
</subsystem>
<!-- https://docs.jboss.org/author/display/WFLY/Security+Realms -->
<!--
we'll use "default" security realm by default to configure jaas/properties authentication
(io.undertow.security.idm.IdentityManager):
- w:jaas - org.ops4j.pax.web.service.undertow.internal.security.JaasIdentityManager
w:properties - org.ops4j.pax.web.service.undertow.internal.security.PropertiesIdentityManager
-->
<security-realm name="default">
<w:authentication>
<!-- JaasIdentityManager for given realm -->
<w:jaas name="karaf" />
<!-- OR PropertiesIdentityManager (mutually exclusive with <w:jaas>) -->
<!--<w:properties path="users.properties" />-->
</w:authentication>
<user-principal-class-name>org.apache.karaf.jaas.boot.principal.UserPrincipal</user-principal-class-name>
<role-principal-class-name>org.apache.karaf.jaas.boot.principal.RolePrincipal</role-principal-class-name>
<!--<role-principal-class-name>...</role-principal-class-name>-->
</security-realm>
<!--
Any security realm may be referenced by https-listener to define trust/keystore, protocols and cipher suites
-->
<security-realm name="https">
<w:server-identities>
<w:ssl>
<!-- sun.security.ssl.ProtocolVersion -->
<!-- sun.security.ssl.CipherSuite -->
<!-- openssl ciphers 'ALL:eNULL' | sed -e 's/:/\n/g' | sort -->
<w:engine
enabled-cipher-suites="TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384"
enabled-protocols="TLSv1 TLSv1.1 TLSv1.2" />
<w:keystore path="${karaf.etc}/certs/server.keystore" provider="JKS" alias="server"
keystore-password="secret" key-password="secret"
generate-self-signed-certificate-host="localhost" />
</w:ssl>
</w:server-identities>
<w:authentication>
<w:truststore path="${karaf.etc}/certs/server.truststore" provider="JKS" keystore-password="secret" />
</w:authentication>
</security-realm>
<!-- Interface lists IP addresses to bind to -->
<interface name="default">
<w:inet-address value="0.0.0.0" />
<!--<w:inet-address value="127.0.0.1" />-->
</interface>
<!--<interface name="secure">-->
<!--<w:inet-address value="127.0.0.1" />-->
<!--</interface>-->
<!-- Socket Binding adds port for each IP from referenced Interface -->
<socket-binding name="http" interface="default" port="${org.osgi.service.http.port}" />
<!--<socket-binding name="https" interface="secure" port="${org.osgi.service.http.port.secure}" />-->
</undertow>
The various options available to configure Undertow are explained as follows:
All the values use property placeholders such as ${org.osgi.service.http.port}
that are resolved with properties available in configuration (org.ops4j.pax.web
PID which is configured using etc/org.ops4j.pax.web.cfg
file) or bundle context (configured with etc/config.properties
and etc/custom.properties
).
Networking options
Basic networking configuration requires two elements:
-
The
<interface>/<w:inet-address>
element defines networking addresses that are used for socket binding. The default settings are0.0.0.0
for all interfaces,127.0.0.1
for loopback interface or any interface address bound to a network device. -
The
<socket-binding>
adds port information to the binding address.
Undertow server listener configuration
The address or port options allows configuration for http(s) listener in an Undertow embedded server.
`<subsystem>/<server>/<http[s]-listener>` configures the embedded server to listen on the given address/port.
For <https-listener>
you can use realm to point to the security configuration and verify-client
attribute with one of these values: NOT_REQUESTED
, REQUESTED
, REQUIRED
.
Security configuration
The XML configuration can specify multiple <security-realm name="name">
elements.
The special <security-realm name="default">
realm is used to configure io.undertow.security.idm.IdentityManager
.
- <security-realm name="default">/<w:authentication>/<w:jaas name="karaf" /> defines JAAS authentication and elements <user-principal-class-name> and <role-principal-class-name> are required.
- <security-realm name="default">/<w:authentication>/<w:properties path="users.properties" /> switches to simple authentication where users are specified in a properties file.
When the security realm has a different name it can be referenced from the <subsystem>/<server>/<https-listener>
element to define additional TLS configuration:
The
<security-realm name="https">/<w:server-identities>/<w:ssl>/<w:engine>
allows you to configure the following XML attributes:-
The
enabled-cipher-suites
, for exampleTLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
, and so on. You can refer to the source code ofsun.security.ssl.CipherSuite
to check the list of available cipher suites for standard security engine. -
The
enabled-protocols
, for exampleTLSv1
,TLSv1.1
,TLSv1.2
. See the source code ofsun.security.ssl.ProtocolVersion
to check available protocol identifiers for a standard security engine.
-
The
-
The
<security-realm name="https">/<w:server-identities>/<w:ssl>/<w:keystore>
configures the keystore that contains the server certificate and private key. -
The
<security-realm name="https">/<w:authentication>/<w:truststore>
configures the truststore that contains trusted (CA) certificates.
HTTP server configuration
After the configuration of the networking elements the <subsystem>/<server>
is used to create actual instance of embedded Undertow server.
-
The
<subsystem>/<server>/<http[s]-listener>
is a reference to an already defined listener. -
The
<subsystem>/<server>/<host>
supports only one virtual host. -
The
<subsystem>/<server>/<host>/<location>
maps the referenced<subsystem>/<handler>
to a given HTTP request path. -
The
<subsystem>/<server>/<host>/<access-log>
configures access logging. -
The
<subsystem>/<server>/<host>/<filter-ref>
configures additional filters to be used for all requests handled by the virtual host. Filters are defined in<subsystem>/<filters>
sub elements.
Filter and Handler configuration
Filters and handlers handle HTTP requests. Filters pass the request further down the chain and the handlers are actual endpoints that do something, for example servlets.
Filters:
-
The
<subsystem>/<filters>/<response-header>
adds an HTTP header to the response and proceeds. -
The
<subsystem>/<filters>/<filter>
is not implemented. -
The
<subsystem>/<filters>/<error-page>
is not implemented.
Handlers:
-
The
<subsystem>/<handlers>/<file>
configures a resource handler; that serves static resources from a given location. Thewelcome
handler is configured to serve some initial resources such as Apache Karaf.
Servlet container configuration
The servlet container defines how Undertow handles servlets.
-
The
<subsystem>/<servlet-container>/<welcome-files>/<welcome-file>
configures default files that are returned when there is no match for any configured servlets, filters, or resources. The configuration is the same as in theWEB-INF/web.xml
file.