Skip to content

Commit 5fd5f35

Browse files
david-blasbyjodygarnett
authored andcommitted
[GEOS-11401] Introduce environmental variables for Module Status page
turn off system-environment and system-property based on environement variable (default = don't show add doc use optional.empty() changes from miceg's review changes from miceg's review jody and andrea feedback doc changes - miceg
1 parent 7d26b8b commit 5fd5f35

File tree

6 files changed

+301
-2
lines changed

6 files changed

+301
-2
lines changed

doc/en/user/source/configuration/properties/index.rst

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,18 @@ GeoServer Property Reference
3131
- x
3232
- x
3333
- x
34+
* - GEOSERVER_MODULE_SYSTEM_ENVIRONMENT_STATUS_ENABLED
35+
36+
:ref:`module_status_security_environment_vars`
37+
-
38+
-
39+
- x
40+
* - GEOSERVER_MODULE_SYSTEM_PROPERTY_STATUS_ENABLED
41+
42+
:ref:`module_status_security_environment_vars`
43+
-
44+
-
45+
- x
3446
* - GEOWEBCACHE_CACHE_DIR
3547

3648
:doc:`/geowebcache/config`

doc/en/user/source/production/config.rst

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,37 @@ In some circumstances, you might want to completely disable the web administrati
139139
* Set the Java system property ``GEOSERVER_CONSOLE_DISABLED`` to true by adding ``-DGEOSERVER_CONSOLE_DISABLED=true`` to your container's JVM options
140140
* Remove all of the :file:`gs-web*-.jar` files from :file:`WEB-INF/lib`
141141

142+
.. _module_status_security_environment_vars:
143+
144+
Showing Environment Variables and Java System Properties
145+
''''''''''''''''''''''''''''''''''''''''''''''''''''''''
146+
147+
Module status information is available describing the operational environment.
148+
149+
* The :guilabel:`GeoServer Status` page :ref:`config_serverstatus_module`.
150+
* The REST ``/geoserver/rest/about/status`` endpoint lists module status information
151+
152+
1. By default GeoServer does **not** show Environment Variables and Java System Properties.
153+
154+
2. To show environment variables and Java system properties on the status page and REST API, start GeoServer with these environment variables set to ``true``:
155+
156+
* `GEOSERVER_MODULE_SYSTEM_ENVIRONMENT_STATUS_ENABLED`
157+
* `GEOSERVER_MODULE_SYSTEM_PROPERTY_STATUS_ENABLED`
158+
159+
3. In a production system, these should be set to ``false`` (or leave them undefined).
160+
161+
.. warning::
162+
163+
While this feature can help an administrator debug a GeoServer instance's configuration, environment variables can include sensitive information such as database passwords and API access keys/tokens, particularly when running in a containerised environment (such as Docker or Kubernetes) or with ``ALLOW_ENV_PARAMETRIZATION=true``.
164+
165+
.. note:: Linux
166+
167+
Linux administrators can get a list of all environment variables set at GeoServer startup with:
168+
169+
.. code-block:: bash
170+
171+
tr '\0' '\n' < /proc/${GEOSERVER_PID}/environ
172+
142173
Application Server Guidance
143174
---------------------------
144175

src/platform/src/main/java/org/geoserver/platform/SystemEnvironmentStatus.java

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,23 @@
77

88
import java.util.Map.Entry;
99
import java.util.Optional;
10+
import java.util.logging.Level;
11+
import java.util.logging.Logger;
12+
import org.geotools.util.logging.Logging;
1013

1114
/** Report system environment details to server status page. */
1215
public class SystemEnvironmentStatus implements ModuleStatus {
1316

17+
private static final Logger LOGGER = Logging.getLogger(SystemEnvironmentStatus.class);
18+
19+
/**
20+
* Name of the environment variable that turns on the details (listing of all environment
21+
* variables) for this module. "false" = don't show, "true" = show all the environment variables
22+
* on the web interface.
23+
*/
24+
public static final String SystemEnvironmentStatusEnabledEnvironmentVar =
25+
"GEOSERVER_MODULE_SYSTEM_ENVIRONMENT_STATUS_ENABLED";
26+
1427
@Override
1528
public String getModule() {
1629
return "system-environment";
@@ -41,8 +54,44 @@ public boolean isEnabled() {
4154
return true;
4255
}
4356

57+
/** For Testing - this can be mocked to change environment variables. */
58+
String getEnvironmentVariable(String envVar) {
59+
return System.getenv(envVar);
60+
}
61+
62+
/**
63+
* returns true if the message (list of variables) should be shown
64+
*
65+
* <p>Uses environment variable SystemPropertyStatusEnabledEnvironmentVar
66+
* ("GEOSERVER_MODULE_SYSTEM_ENVIRONMENT_STATUS_ENABLED") not defined -> false (default) bad
67+
* value -> false (default)
68+
*/
69+
public boolean isShow() {
70+
String val = getEnvironmentVariable(SystemEnvironmentStatusEnabledEnvironmentVar);
71+
if (val == null) {
72+
return false; // not defined -> default
73+
}
74+
if (val.equalsIgnoreCase("true") || val.equalsIgnoreCase("false")) {
75+
return val.equalsIgnoreCase("true");
76+
}
77+
LOGGER.log(
78+
Level.WARNING,
79+
String.format(
80+
"environment variable '%s' should be 'true' or 'false', but was '%s'",
81+
SystemEnvironmentStatusEnabledEnvironmentVar, val));
82+
return false; // bad value -> default
83+
}
84+
4485
@Override
4586
public Optional<String> getMessage() {
87+
if (!isShow()) {
88+
var message =
89+
String.format(
90+
"Environment variables hidden for security reasons. Set the environment variable '%s' to 'true' to see them.",
91+
SystemEnvironmentStatusEnabledEnvironmentVar);
92+
return Optional.of(message);
93+
}
94+
4695
StringBuffer result = new StringBuffer();
4796
for (Entry<String, String> entry : System.getenv().entrySet()) {
4897
result.append(entry.getKey().toString() + "=" + entry.getValue().toString() + "\n");

src/platform/src/main/java/org/geoserver/platform/SystemPropertyStatus.java

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,22 @@
77

88
import java.util.Map.Entry;
99
import java.util.Optional;
10+
import java.util.logging.Level;
11+
import java.util.logging.Logger;
12+
import org.geotools.util.logging.Logging;
1013

1114
public class SystemPropertyStatus implements ModuleStatus {
1215

16+
private static final Logger LOGGER = Logging.getLogger(SystemPropertyStatus.class);
17+
18+
/**
19+
* Name of the environment variable that turns on the details (listing of all property
20+
* variables) for this module. "false" = don't show, "true" = show all the environment variables
21+
* on the web interface.
22+
*/
23+
public static final String SystemPropertyStatusEnabledEnvironmentVar =
24+
"GEOSERVER_MODULE_SYSTEM_PROPERTY_STATUS_ENABLED";
25+
1326
@Override
1427
public String getModule() {
1528
return "system-properties";
@@ -40,8 +53,43 @@ public boolean isEnabled() {
4053
return true;
4154
}
4255

56+
/** For Testing - this can be mocked to change environment variables. */
57+
String getEnvironmentVariable(String envVar) {
58+
return System.getenv(envVar);
59+
}
60+
61+
/**
62+
* returns true if the message (list of variables) should be shown
63+
*
64+
* <p>Uses environment variable SystemPropertyStatusEnabledEnvironmentVar
65+
* ("GEOSERVER_MODULE_SYSTEM_PROPERTY_STATUS_ENABLED") not defined -> false (default) bad value
66+
* -> false (default)
67+
*/
68+
public boolean isShow() {
69+
String val = getEnvironmentVariable(SystemPropertyStatusEnabledEnvironmentVar);
70+
if (val == null) {
71+
return false; // not defined -> default
72+
}
73+
if (val.equalsIgnoreCase("true") || val.equalsIgnoreCase("false")) {
74+
return val.equalsIgnoreCase("true");
75+
}
76+
LOGGER.log(
77+
Level.WARNING,
78+
String.format(
79+
"environment variable '%s' should be 'true' or 'false', but was '%s'",
80+
SystemPropertyStatusEnabledEnvironmentVar, val));
81+
return false; // bad value -> default
82+
}
83+
4384
@Override
4485
public Optional<String> getMessage() {
86+
if (!isShow()) {
87+
var message =
88+
String.format(
89+
"Java system properties hidden for security reasons. Set the environment variable '%s' to 'true' to see them.",
90+
SystemPropertyStatusEnabledEnvironmentVar);
91+
return Optional.of(message);
92+
}
4593
StringBuffer result = new StringBuffer();
4694
for (Entry<Object, Object> entry : System.getProperties().entrySet()) {
4795
result.append(entry.getKey().toString() + "=" + entry.getValue().toString() + "\n");

src/platform/src/test/java/org/geoserver/platform/SystemEnvironmentTest.java

Lines changed: 80 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import static org.junit.Assert.assertFalse;
99
import static org.junit.Assert.assertTrue;
1010

11+
import java.util.ArrayList;
1112
import java.util.HashMap;
1213
import java.util.Map;
1314
import java.util.logging.Logger;
@@ -26,12 +27,90 @@ public void testSystemPropertiesStatus() {
2627
String key = System.getenv().keySet().iterator().next();
2728
String value = System.getenv(key);
2829

29-
SystemEnvironmentStatus status = new SystemEnvironmentStatus();
30+
SystemEnvironmentStatus status =
31+
new SystemEnvironmentStatus() {
32+
String getEnvironmentVariable(String envVar) {
33+
return "true";
34+
}
35+
};
36+
3037
assertTrue(status.getMessage().isPresent());
3138
assertTrue(status.getMessage().get().contains(key));
3239
assertTrue(status.getMessage().get().contains(value));
3340
}
3441

42+
/**
43+
* Tests the SystemEnvironmentStatusEnabledEnvironmentVar so it turns on/off the message (list
44+
* of environment vars).
45+
*/
46+
@Test
47+
public void testEnabled() {
48+
final var VALUE = new ArrayList<String>();
49+
50+
// create subclass of SystemEnvironmentStatus so we can change the value of the environment
51+
// variable.
52+
// VALUE empty -> null
53+
// otherwise its the first item in the VALUE
54+
// if the request is for a different environment var -> throw
55+
SystemEnvironmentStatus status =
56+
new SystemEnvironmentStatus() {
57+
String getEnvironmentVariable(String envVar) {
58+
if (envVar.equals(
59+
SystemEnvironmentStatus
60+
.SystemEnvironmentStatusEnabledEnvironmentVar)) {
61+
if (VALUE.isEmpty()) {
62+
return null;
63+
}
64+
return VALUE.get(0);
65+
}
66+
throw new RuntimeException("bad var");
67+
}
68+
};
69+
70+
VALUE.clear();
71+
VALUE.add("true");
72+
assertTrue(status.isShow());
73+
assertTrue(!status.getMessage().isEmpty());
74+
75+
VALUE.clear();
76+
VALUE.add("TRUE");
77+
assertTrue(status.isShow());
78+
assertTrue(!status.getMessage().isEmpty());
79+
80+
VALUE.clear();
81+
VALUE.add("FALSE");
82+
assertFalse(status.isShow());
83+
assertTrue(
84+
status.getMessage()
85+
.get()
86+
.startsWith("Environment variables hidden for security reasons."));
87+
88+
VALUE.clear();
89+
VALUE.add("false");
90+
assertFalse(status.isShow());
91+
assertTrue(
92+
status.getMessage()
93+
.get()
94+
.startsWith("Environment variables hidden for security reasons."));
95+
96+
// default -> false
97+
VALUE.clear();
98+
assertFalse(status.isShow());
99+
assertTrue(
100+
status.getMessage()
101+
.get()
102+
.startsWith("Environment variables hidden for security reasons."));
103+
104+
// bad value -> false
105+
VALUE.clear();
106+
VALUE.add("maybe");
107+
assertFalse(status.isShow());
108+
assertTrue(
109+
status.getMessage()
110+
.get()
111+
.startsWith("Environment variables hidden for security reasons."));
112+
}
113+
35114
@Test
36115
public void testGeoServerEnvironmentDefaultValue() {
37116
System.clearProperty("ALLOW_ENV_PARAMETRIZATION");

src/platform/src/test/java/org/geoserver/platform/SystemPropertiesStatusTest.java

Lines changed: 81 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@
55

66
package org.geoserver.platform;
77

8+
import static org.junit.Assert.assertFalse;
89
import static org.junit.Assert.assertTrue;
910

11+
import java.util.ArrayList;
1012
import org.junit.Test;
1113

1214
public class SystemPropertiesStatusTest {
@@ -18,9 +20,87 @@ public class SystemPropertiesStatusTest {
1820
@Test
1921
public void testSystemPropertiesStatus() {
2022
System.setProperty(KEY, VALUE);
21-
SystemPropertyStatus status = new SystemPropertyStatus();
23+
24+
SystemPropertyStatus status =
25+
new SystemPropertyStatus() {
26+
String getEnvironmentVariable(String envVar) {
27+
return "true";
28+
}
29+
};
30+
2231
assertTrue(status.getMessage().isPresent());
2332
assertTrue(status.getMessage().get().contains(KEY));
2433
assertTrue(status.getMessage().get().contains(VALUE));
2534
}
35+
36+
/**
37+
* Tests the SystemPropertyStatusEnabledEnvironmentVar so it turns on/off the message (list of
38+
* property vars).
39+
*/
40+
@Test
41+
public void testEnabled() {
42+
final var VALUE = new ArrayList<String>();
43+
44+
// create subclass of SystemPropertyStatus so we can change the value of the environment
45+
// variable.
46+
// VALUE empty -> null
47+
// otherwise its the first item in the VALUE
48+
// if the request is for a different environment var -> throw
49+
SystemPropertyStatus status =
50+
new SystemPropertyStatus() {
51+
String getEnvironmentVariable(String envVar) {
52+
if (envVar.equals(
53+
SystemPropertyStatus.SystemPropertyStatusEnabledEnvironmentVar)) {
54+
if (VALUE.isEmpty()) {
55+
return null;
56+
}
57+
return VALUE.get(0);
58+
}
59+
throw new RuntimeException("bad var");
60+
}
61+
};
62+
63+
VALUE.clear();
64+
VALUE.add("true");
65+
assertTrue(status.isShow());
66+
assertTrue(!status.getMessage().isEmpty());
67+
68+
VALUE.clear();
69+
VALUE.add("TRUE");
70+
assertTrue(status.isShow());
71+
assertTrue(!status.getMessage().isEmpty());
72+
73+
VALUE.clear();
74+
VALUE.add("FALSE");
75+
assertFalse(status.isShow());
76+
assertTrue(
77+
status.getMessage()
78+
.get()
79+
.startsWith("Java system properties hidden for security reasons."));
80+
81+
VALUE.clear();
82+
VALUE.add("false");
83+
assertFalse(status.isShow());
84+
assertTrue(
85+
status.getMessage()
86+
.get()
87+
.startsWith("Java system properties hidden for security reasons."));
88+
89+
// default -> false
90+
VALUE.clear();
91+
assertFalse(status.isShow());
92+
assertTrue(
93+
status.getMessage()
94+
.get()
95+
.startsWith("Java system properties hidden for security reasons."));
96+
97+
// bad value -> false
98+
VALUE.clear();
99+
VALUE.add("maybe");
100+
assertFalse(status.isShow());
101+
assertTrue(
102+
status.getMessage()
103+
.get()
104+
.startsWith("Java system properties hidden for security reasons."));
105+
}
26106
}

0 commit comments

Comments
 (0)