Skip to content

Commit 981a2fd

Browse files
authored
ZOOKEEPER-5050: Disable AdminServer and enhance documentation to highlight security considerations
Reviewers: eolivelli, phunt Author: anmolnar Closes #2389 from anmolnar/ZOOKEEPER-5050
1 parent 7e608ac commit 981a2fd

4 files changed

Lines changed: 180 additions & 33 deletions

File tree

zookeeper-server/src/main/java/org/apache/zookeeper/server/admin/AdminServerFactory.java

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
public class AdminServerFactory {
2929

3030
private static final Logger LOG = LoggerFactory.getLogger(AdminServerFactory.class);
31+
static final String ENABLE_ADMIN_SERVER_PROPERTY = "zookeeper.admin.enableServer";
3132

3233
/**
3334
* This method encapsulates the logic for whether we should use a
@@ -38,21 +39,17 @@ public class AdminServerFactory {
3839
* to pull in Jetty with ZooKeeper.
3940
*/
4041
public static AdminServer createAdminServer() {
41-
if (!"false".equals(System.getProperty("zookeeper.admin.enableServer"))) {
42+
if (Boolean.getBoolean(ENABLE_ADMIN_SERVER_PROPERTY)) {
4243
try {
4344
Class<?> jettyAdminServerC = Class.forName("org.apache.zookeeper.server.admin.JettyAdminServer");
4445
Object adminServer = jettyAdminServerC.getConstructor().newInstance();
4546
return (AdminServer) adminServer;
4647

47-
} catch (ClassNotFoundException e) {
48-
LOG.warn("Unable to start JettyAdminServer", e);
49-
} catch (InstantiationException e) {
50-
LOG.warn("Unable to start JettyAdminServer", e);
51-
} catch (IllegalAccessException e) {
52-
LOG.warn("Unable to start JettyAdminServer", e);
53-
} catch (InvocationTargetException e) {
54-
LOG.warn("Unable to start JettyAdminServer", e);
55-
} catch (NoSuchMethodException e) {
48+
} catch (ClassNotFoundException
49+
| InstantiationException
50+
| IllegalAccessException
51+
| InvocationTargetException
52+
| NoSuchMethodException e) {
5653
LOG.warn("Unable to start JettyAdminServer", e);
5754
} catch (NoClassDefFoundError e) {
5855
LOG.warn("Unable to load jetty, not starting JettyAdminServer", e);
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
package org.apache.zookeeper.server.admin;
20+
21+
import static org.junit.jupiter.api.Assertions.assertFalse;
22+
import static org.junit.jupiter.api.Assertions.assertTrue;
23+
import org.junit.jupiter.api.AfterEach;
24+
import org.junit.jupiter.api.Test;
25+
26+
public class AdminServerFactoryTest {
27+
28+
@AfterEach
29+
public void tearDown() {
30+
System.clearProperty(AdminServerFactory.ENABLE_ADMIN_SERVER_PROPERTY);
31+
}
32+
33+
@Test
34+
public void testAdminServerDisabledByDefault() {
35+
System.clearProperty(AdminServerFactory.ENABLE_ADMIN_SERVER_PROPERTY);
36+
AdminServer adminServer = AdminServerFactory.createAdminServer();
37+
assertTrue(adminServer instanceof DummyAdminServer);
38+
assertFalse(adminServer instanceof JettyAdminServer);
39+
}
40+
41+
@Test
42+
public void testAdminServerEnabled() {
43+
System.setProperty(AdminServerFactory.ENABLE_ADMIN_SERVER_PROPERTY, "true");
44+
AdminServer adminServer = AdminServerFactory.createAdminServer();
45+
assertFalse(adminServer instanceof DummyAdminServer);
46+
assertTrue(adminServer instanceof JettyAdminServer);
47+
}
48+
}

zookeeper-website/app/pages/_docs/docs/_mdx/admin-ops/administrators-guide/commands.mdx

Lines changed: 123 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -183,29 +183,131 @@ $ echo ruok | nc 127.0.0.1 5111
183183

184184
## The AdminServer
185185

186-
**New in 3.5.0:** The AdminServer is
187-
an embedded Jetty server that provides an HTTP interface to the four-letter
188-
word commands. By default, the server is started on port 8080,
189-
and commands are issued by going to the URL "/commands/\[command name]",
190-
e.g., http://localhost:8080/commands/stat. The command response is
191-
returned as JSON. Unlike the original protocol, commands are not
192-
restricted to four-letter names, and commands can have multiple names;
193-
for instance, "stmk" can also be referred to as "set_trace_mask". To
194-
view a list of all available commands, point a browser to the URL
195-
/commands (e.g., http://localhost:8080/commands). See the [AdminServer configuration options](#configuring-adminserver-for-ssltls)
196-
for how to change the port and URLs.
197-
198-
The AdminServer is enabled by default, but can be disabled by either:
199-
200-
- Setting the zookeeper.admin.enableServer system
201-
property to false.
202-
- Removing Jetty from the classpath. (This option is
203-
useful if you would like to override ZooKeeper's jetty
204-
dependency.)
205-
206-
Note that the TCP four-letter word interface is still available if
186+
**New in 3.5.0:** The AdminServer is an embedded Jetty server that provides an HTTP interface to the four-letter word
187+
commands. In ZooKeeper releases 3.5.0 through 3.9.x, the AdminServer was enabled by default. Starting with ZooKeeper
188+
3.10.0, the default configuration disables the AdminServer. When enabled, the server listens on port 8080 by default,
189+
and commands are issued by accessing the URL `/commands/[command name]`, for example, `http://localhost:8080/commands/stat`.
190+
Command responses are returned in JSON format.
191+
192+
Unlike the original protocol, commands are not restricted to four-letter names, and commands can have multiple aliases;
193+
for example, `stmk` can also be referred to as `set_trace_mask`. To view a list of all available commands, access the
194+
`/commands` endpoint (for example, `http://localhost:8080/commands`). See the AdminServer configuration options for
195+
information on changing the port and URL mappings.
196+
197+
Beginning with ZooKeeper 3.10.0, the AdminServer is disabled by default and can be enabled by setting the
198+
`zookeeper.admin.enableServer` system property to `true`. When enabled without additional configuration, the AdminServer
199+
listens on all network interfaces (`0.0.0.0`), uses unencrypted HTTP, and does not require client authentication.
200+
Administrators are strongly encouraged to restrict network access and configure appropriate transport security and
201+
authentication before exposing the AdminServer in production environments.
202+
203+
Make sure that Jetty is available on the classpath, because the AdminServer will automatically remain disabled if Jetty
204+
cannot be found. This behavior can be useful when overriding ZooKeeper's Jetty dependency.
205+
206+
Note that the TCP four-letter word interface is still available for monitoring purposes if
207207
the AdminServer is disabled.
208208

209+
### Security Considerations
210+
211+
> **Important:** The AdminServer is disabled by default. When enabled without additional configuration,
212+
> it listens on all network interfaces (0.0.0.0) on port 8080, uses unencrypted HTTP, and does not
213+
> require client authentication. As a result, most administrative commands are accessible to any client
214+
> that can reach the AdminServer. Administrators should restrict access appropriately and enable transport
215+
> security and authentication when deploying the AdminServer in production.
216+
217+
### Default Security Posture
218+
219+
The default AdminServer configuration is intended for ease of use in trusted environments, but it is **not secure for
220+
exposure to untrusted networks**.
221+
222+
Default settings include:
223+
224+
- `admin.enableServer=false`
225+
- `admin.serverAddress=0.0.0.0`
226+
- `admin.serverPort=8080`
227+
- `admin.forceHttps=false`
228+
- `admin.needClientAuth=false`
229+
230+
With these defaults:
231+
232+
- All traffic is transmitted in clear text over HTTP.
233+
- Administrative data, including configuration and runtime details, can be viewed by anyone with network access.
234+
- Many commands (such as `stat`, `srvr`, `conf`, and `cons`) do not require authentication.
235+
- Sensitive operational information may be disclosed.
236+
- In some environments, unrestricted administrative access can increase the impact of vulnerabilities or misconfiguration.
237+
238+
### Recommended Deployment Practices
239+
240+
Administrators should ensure that the AdminServer is accessible only to authorized users.
241+
242+
#### Option 1: Restrict Access with Firewall Rules (Minimum Recommendation)
243+
244+
Limit access to the AdminServer port to trusted hosts or management networks only.
245+
246+
Examples:
247+
248+
- Bind the server to localhost:
249+
250+
```properties
251+
admin.serverAddress=127.0.0.1
252+
```
253+
254+
- Use host-based firewall rules (such as `iptables`, `firewalld`, or cloud security groups) to allow access only from
255+
- administrative systems.
256+
257+
This is the minimum recommended protection when HTTPS and client authentication are not enabled.
258+
259+
#### Option 2: Enable HTTPS
260+
261+
To encrypt all communication, configure SSL/TLS and force HTTPS:
262+
263+
```properties
264+
admin.forceHttps=true
265+
```
266+
267+
This prevents credentials and administrative data from being transmitted in clear text. ZooKeeper supports configuring
268+
the AdminServer with TLS certificates and trust stores.
269+
270+
#### Option 3: Require Client Authentication
271+
272+
To restrict access to trusted clients using X.509 certificates:
273+
274+
```properties
275+
admin.needClientAuth=true
276+
```
277+
278+
When enabled, only clients presenting valid certificates trusted by the server will be allowed to connect.
279+
280+
### Recommended Secure Configuration
281+
282+
For production environments, the following configuration is strongly recommended:
283+
284+
```properties
285+
admin.forceHttps=true
286+
admin.needClientAuth=true
287+
admin.serverAddress=<management-network-ip>
288+
```
289+
290+
In addition, restrict access to the AdminServer port using firewall rules.
291+
292+
### Leave AdminServer disabled If Not Needed
293+
294+
If you do not use the AdminServer, disable it explicitly:
295+
296+
```properties
297+
admin.enableServer=false
298+
```
299+
300+
### Security Warning
301+
302+
Exposing the AdminServer to untrusted networks with the default configuration may allow unauthorized users to:
303+
304+
- Retrieve server configuration and runtime information
305+
- Inspect connected clients and sessions
306+
- Reset statistics
307+
- Execute other administrative commands
308+
309+
Always protect the AdminServer with **network-level controls** and, preferably, **HTTPS with client certificate authentication**.
310+
209311
## Configuring AdminServer for SSL/TLS
210312

211313
- Generating the **keystore.jks** and **truststore.jks** which can be found in the [Quorum TLS](/admin-ops/administrators-guide/communication-using-the-netty-framework#quorum-tls).

zookeeper-website/app/pages/_docs/docs/_mdx/admin-ops/administrators-guide/configuration-parameters.mdx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1720,8 +1720,8 @@ options are used to configure the [AdminServer](#adminserver-configuration).
17201720

17211721
- _admin.enableServer_ :
17221722
(Java system property: **zookeeper.admin.enableServer**)
1723-
Set to "false" to disable the AdminServer. By default the
1724-
AdminServer is enabled.
1723+
Set to "true" to enable the AdminServer. By default, the
1724+
AdminServer is disabled.
17251725

17261726
- _admin.serverAddress_ :
17271727
(Java system property: **zookeeper.admin.serverAddress**)

0 commit comments

Comments
 (0)