Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion .github/workflows/server-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,14 @@ jobs:
hugegraph-server/hugegraph-dist/src/assembly/static \
hugegraph-store/hg-store-dist/src/assembly/static/bin/util.sh

- name: Run Java security properties tests
if: ${{ env.BACKEND == 'rocksdb' }}
run: |
mvn package -Dmaven.test.skip=true -pl hugegraph-server/hugegraph-dist -am -ntp
VERSION=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout)
SERVER_DIR=hugegraph-server/apache-hugegraph-server-$VERSION/
$TRAVIS_DIR/test-java-security-properties.sh $SERVER_DIR

- name: Check startup test prerequisites
id: server-preflight
if: ${{ env.BACKEND == 'rocksdb' }}
Expand All @@ -111,7 +119,6 @@ jobs:
- name: Run start-hugegraph.sh foreground mode tests
if: ${{ env.BACKEND == 'rocksdb' && steps.server-preflight.outputs.can_run == 'true' }}
run: |
mvn package -Dmaven.test.skip=true -pl hugegraph-server/hugegraph-dist -am -ntp
VERSION=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout)
SERVER_DIR=hugegraph-server/apache-hugegraph-server-$VERSION/
$TRAVIS_DIR/test-start-hugegraph.sh $SERVER_DIR
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@ ensure_path_writable "$PLUGINS"
MAX_MEM=$((32 * 1024))
MIN_MEM=$((1 * 512))
MIN_JAVA_VERSION=11
# JDK 24 removed the Security Manager (JEP 486): "-Djava.security.manager=allow"
# is a fatal VM initialization error there and System.setSecurityManager() always
# throws, so HugeSecurityManager cannot be installed on newer runtimes.
MAX_SECURITY_JAVA_VERSION=23

# Add the slf4j-log4j12 binding
CP=$(find -L $LIB -name 'log4j-slf4j-impl*.jar' | sort | tr '\n' ':')
Expand Down Expand Up @@ -93,8 +97,18 @@ else
JAVA="$JAVA_HOME/bin/java -server"
fi

JAVA_VERSION=$($JAVA -version 2>&1 | head -1 | cut -d'"' -f2 | sed 's/^1\.//' | cut -d'.' -f1)
if [[ $? -ne 0 || $JAVA_VERSION -lt $MIN_JAVA_VERSION ]]; then
# Pick the JVM banner line explicitly, anchored to its "java version"/"openjdk
# version" prefix: whenever JAVA_TOOL_OPTIONS or _JAVA_OPTIONS is set the JVM
# prints a preamble first ("Picked up JAVA_TOOL_OPTIONS: ..."), and an agent
# loaded that way may print its own banner containing 'version "..."' (an APM
# agent, for example), so matching any line with 'version "' can read the
# agent version instead of the runtime version.
JAVA_VERSION=$($JAVA -version 2>&1 |
awk -F'"' '/^(java|openjdk) version "/ {print $2; exit}' |
sed 's/^1\.//' | cut -d'.' -f1)
# Drop any pre-release suffix, e.g. "24-ea" -> "24"
JAVA_VERSION="${JAVA_VERSION%%[!0-9]*}"
if [[ -z $JAVA_VERSION || $JAVA_VERSION -lt $MIN_JAVA_VERSION ]]; then
echo "Make sure the JDK is installed and the version >= $MIN_JAVA_VERSION, current is $JAVA_VERSION" \
>> "${OUTPUT}"
exit 1
Expand Down Expand Up @@ -142,8 +156,58 @@ case "$GC_OPTION" in
esac

JVM_OPTIONS="-Dlog4j.configurationFile=${CONF}/log4j2.xml"
SECURITY_MANAGER_OPTION=""
if [[ ${OPEN_SECURITY_CHECK} == "true" ]]; then
JVM_OPTIONS="${JVM_OPTIONS} -Djava.security.manager=org.apache.hugegraph.security.HugeSecurityManager"
if [[ ${JAVA_VERSION} -gt ${MAX_SECURITY_JAVA_VERSION} ]]; then
SECURITY_UNSUPPORTED_MSG=$(cat <<EOF
The security check requires Java ${MIN_JAVA_VERSION}-${MAX_SECURITY_JAVA_VERSION}, current is ${JAVA_VERSION}.
JDK 24+ removed the Security Manager (JEP 486), so HugeSecurityManager can no longer be installed.
Run the server on Java ${MAX_SECURITY_JAVA_VERSION} or lower, or start it with the security check
disabled: 'start-hugegraph.sh -s false'.
EOF
)
echo "${SECURITY_UNSUPPORTED_MSG}" >&2
echo "${SECURITY_UNSUPPORTED_MSG}" >> "${OUTPUT}"
exit 1
fi

SECURITY_PROPERTIES="${CONF}/java-security.properties"
if [[ ! -r ${SECURITY_PROPERTIES} ]]; then
# An operator may deliberately replace the bundled policy with their own
# -Djava.security.properties=<file>, which the JVM applies last and which
# makes a missing bundled file harmless. Track the last such option, since
# an empty value clears any earlier override. The override itself is not
# validated here: only the JVM's own properties parsing decides what it
# loads to, so the bootstrap stays the single validator and mirrors its
# rejection into the server log (see hugegraph.bootstrap.error.log below).
SECURITY_PROPERTIES_OVERRIDDEN="false"
for OPTION in ${JAVA_OPTIONS} ${_JAVA_OPTIONS:-}; do
case "${OPTION}" in
-Djava.security.properties=)
SECURITY_PROPERTIES_OVERRIDDEN="false" ;;
-Djava.security.properties=?*)
SECURITY_PROPERTIES_OVERRIDDEN="true" ;;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Any non-empty -Djava.security.properties=... token suppresses the missing bundled-policy diagnostic without checking whether the replacement file exists, is readable, or supplies a valid positive TTL. The bootstrap then rejects the invalid policy, but daemon stderr goes to hugegraph-server-stdout.log while start-hugegraph.sh directs operators to hugegraph-server.log, which now lacks the cause. Please suppress this diagnostic only after validating the effective override, or mirror bootstrap failures into the advertised log, and cover missing/unreadable/invalid override files in daemon mode.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 791947c, via the second option: the bootstrap's rejection is mirrored into the advertised log rather than validated shell-side.

I deliberately did not add launcher-side validation of the override file. Only the JVM's own properties parsing decides what the override loads to — the escaped-key, line-continuation and file:-URL cases in the test suite are all files a plain shell check would mis-classify — so a shell validator could disagree with the bootstrap in both directions and reintroduce exactly this inconsistency. The bootstrap stays the single validator.

Mechanics: in daemon mode the launcher passes -Dhugegraph.bootstrap.error.log=${LOGS}/hugegraph-server.log, and the bootstrap appends the same fatal message it prints to stderr (including the effective java.security.properties value, so the broken override is named) to that file, best-effort, before the security manager is installed and without touching the logging framework. Stdout mode is unchanged since stderr is already operator-visible there.

New daemon-mode tests cover missing, unreadable and infinite-TTL operator overrides, asserting both the cause and the override path land in hugegraph-server.log; the unreadable fixture also carries invalid content so the case still fails closed where permission bits do not apply (root). No-op'ing the error-log property in the packaged launcher makes them fail.

esac
done
fi
if [[ ! -r ${SECURITY_PROPERTIES} &&
${SECURITY_PROPERTIES_OVERRIDDEN:-false} == "false" ]]; then
# The bootstrap validates the effective policy and refuses to start, but
# its stderr goes to the stdout log in daemon mode. Name the cause here
# so it also reaches the log start-hugegraph.sh points operators at.
cat >> "${OUTPUT}" <<EOF
ERROR: Missing or unreadable '${SECURITY_PROPERTIES}'.
An upgraded deployment that reuses an older conf/ directory must add this file,
or supply its own -Djava.security.properties=<file> setting a finite positive
networkaddress.cache.ttl.
EOF
fi
JVM_OPTIONS="${JVM_OPTIONS} \
-Djava.security.properties=${SECURITY_PROPERTIES}"
if [[ ${JAVA_VERSION} -ge 18 ]]; then
Comment thread
bitflicker64 marked this conversation as resolved.
# Required to install HugeSecurityManager programmatically on JDK 18+.
SECURITY_MANAGER_OPTION="-Djava.security.manager=allow"
fi
fi

if [ "${OPEN_TELEMETRY}" == "true" ]; then
Expand Down Expand Up @@ -184,12 +248,24 @@ if [ "${OPEN_TELEMETRY}" == "true" ]; then
export OTEL_RESOURCE_ATTRIBUTES=service.name=server
fi

if [[ "${STDOUT_MODE:-false}" != "true" ]]; then
# Daemon stderr only reaches hugegraph-server-stdout.log, so a bootstrap
# rejection of the effective DNS policy (a broken operator override
# included) would be invisible in the log start-hugegraph.sh points
# operators at. Let the bootstrap mirror its fatal errors there.
JVM_OPTIONS="${JVM_OPTIONS} -Dhugegraph.bootstrap.error.log=${OUTPUT}"
fi

# Turn on security check
if [[ "${STDOUT_MODE:-false}" == "true" ]]; then
exec ${JAVA} -Dname="HugeGraphServer" ${JVM_OPTIONS} ${JAVA_OPTIONS} -cp ${CLASSPATH}: \
org.apache.hugegraph.dist.HugeGraphServer ${GREMLIN_SERVER_CONF} ${REST_SERVER_CONF}
exec ${JAVA} -Dname="HugeGraphServer" ${JVM_OPTIONS} ${JAVA_OPTIONS} \
${SECURITY_MANAGER_OPTION} -cp ${CLASSPATH}: \
org.apache.hugegraph.bootstrap.HugeGraphServerBootstrap \
${OPEN_SECURITY_CHECK} ${GREMLIN_SERVER_CONF} ${REST_SERVER_CONF}
else
exec ${JAVA} -Dname="HugeGraphServer" ${JVM_OPTIONS} ${JAVA_OPTIONS} -cp ${CLASSPATH}: \
org.apache.hugegraph.dist.HugeGraphServer ${GREMLIN_SERVER_CONF} ${REST_SERVER_CONF} \
exec ${JAVA} -Dname="HugeGraphServer" ${JVM_OPTIONS} ${JAVA_OPTIONS} \
${SECURITY_MANAGER_OPTION} -cp ${CLASSPATH}: \
org.apache.hugegraph.bootstrap.HugeGraphServerBootstrap \
${OPEN_SECURITY_CHECK} ${GREMLIN_SERVER_CONF} ${REST_SERVER_CONF} \
>> ${LOGS}/hugegraph-server-stdout.log 2>&1
fi
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# 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.

# Permit failed network clients to resolve a changed address instead of
# retaining the first successful DNS result for the lifetime of the JVM.
networkaddress.cache.ttl=30
Loading
Loading