Skip to content

fix(hugegraph-dist): gate init-store on a dedicated init_store.enabled option - #3119

Open
bitflicker64 wants to merge 14 commits into
apache:masterfrom
bitflicker64:fix/no-init
Open

fix(hugegraph-dist): gate init-store on a dedicated init_store.enabled option#3119
bitflicker64 wants to merge 14 commits into
apache:masterfrom
bitflicker64:fix/no-init

Conversation

@bitflicker64

@bitflicker64 bitflicker64 commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

Fixes #3118

Kept in sync with hugegraph#171

Problem

InitStore always performs local initialization: it scans conf/graphs,
initializes non-HStore backends, and bootstraps the built-in admin account. That
is correct for standalone and tarball deployments, but a PD/HStore deployment
already owns its metadata. Its Kubernetes pods also cannot rely on the
container-local docker/init_complete flag surviving a restart.

Solution

This adds a dedicated init_store.enabled option, defaulting to true.
Existing standalone and tarball configurations therefore keep the current full
initialization path. Distributed deployments can set it to false (or set
HG_SERVER_INIT_STORE_ENABLED=false in the server container) to skip backend
and plugin registration, the full graph initialization scan, and local admin
initialization. The disabled path may still inspect graph configuration files
without opening graphs when it validates built-in authentication topology.

The disabled path fails closed for local StandardAuthenticator instances and
subclasses unless usePD=true, the selected auth graph uses HStore, and an
explicit non-empty admin password is available. The public auth.admin_pa=pa
fallback is never accepted as an explicitly configured bootstrap secret.
Remote auth and custom authenticators are exempt because they do not consume
HugeGraph's local built-in admin password.

The Docker entrypoint delegates property parsing, rewriting, auth
classification, and disabled-path validation to Java. The Java helper uses
Commons Configuration, matching HugeConfig for escaped keys, continuations,
duplicate logical definitions, and exact value decoding. Rewrites preserve the
mounted file inode, comments, and mode; secret writes first restrict
rest-server.properties to 0600 and use an unpredictable same-directory
scratch file.

The entrypoint also:

  • completes REST, Gremlin, and HugeFactoryAuthProxy configuration for mounted
    auth configs;
  • persists PASSWORD only for local built-in auth and explicitly ignores it
    for custom or remote auth;
  • passes PASSWORD to enabled local initialization without exposing it as a
    process argument;
  • avoids writing docker/init_complete when initialization is disabled;
  • records non-secret auth topology so a later no-auth-to-auth transition runs
    the required bootstrap once; and
  • uses the same Java property reader for the post-start HStore check.

Cleanup now preserves a primary admin-bootstrap exception and attaches a
simultaneous graph-close failure as suppressed, while still surfacing a
close-only failure. The Docker workflow path filter includes every shell and
Java file that participates in this entrypoint contract.

auth.admin_pa is used only when the PD-backed admin is first created. Changing
PASSWORD on a later restart does not rotate an existing account.

Validation

  • Validated head: 3e505a811b10e42c9e3b80d9a18b09ac80181ce0.
  • Entrypoint lifecycle and properties suite: 217 assertions passed, 0 failed.
  • Focused Java suite: 30 tests passed, 0 failed.
  • Full Java 11 clean compile passed for the reactor.
  • Server distribution packaging and the assembled bin/config-tool.sh smoke
    test passed; the wrapper is executable in the assembled layout.
  • EditorConfig formatting, shell syntax, executable mode, and final diff checks
    passed.
  • Independent read-only review found no actionable findings.
  • Both PRs reference the same commit and the same 14 changed files.

Scope

This change does not alter graph.load_from_local_config, general
GraphManager behavior, Helm job structure, shipped Compose usePD defaults,
unrelated Arthas configuration, or broad test-fixture structure. Deployments
opting out of init-store remain responsible for selecting the PD/HStore metadata
path described above.

…g is false

Honor the existing ServerOptions flag in InitStore so distributed/HStore
can opt out of local backend and admin init. Unset keeps full init for
standalone. Docker maps HG_SERVER_LOAD_FROM_LOCAL_CONFIG to
rest-server.properties.

Fixes apache#3118
@dosubot dosubot Bot added size:M This PR changes 30-99 lines, ignoring generated files. tests Add or improve test cases labels Jul 26, 2026

@imbajin imbajin left a comment

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.

Blocking: yes. Summary: Disabling local graph loading also bypasses the Docker password-based admin bootstrap, so the requested credential is never installed. Evidence: exact-head static trace through docker-entrypoint.sh, InitStore.java, and GraphManager.java; 3/3 focused tests passed; visible checks are green.

…d option

Replace the graph.load_from_local_config gate with a dedicated
init_store.enabled option defaulting to true. That property already means
whether GraphManager loads graph definitions from the local directory, and
existing configs may materialize its declared false default, so reusing it
made an explicit false skip backend and admin initialization for standalone
RocksDB/HBase installs.

The early return also skipped StandardAuthenticator.initAdminUserIfNeeded,
so a Docker PASSWORD was piped into init-store.sh and discarded without
creating the admin, leaving the server on the auth.admin_pa default. In skip
mode the entrypoint now writes PASSWORD to auth.admin_pa instead, and does
not create docker/init_complete since nothing was initialized. The gate is
read back from rest-server.properties so a config mounted without the env
var behaves the same way.

Cover the lifecycle with a main-level test whose graphs directory would fail
if the early exit were missed, and entrypoint smoke tests for default init,
PASSWORD, skip, skip with PASSWORD, mounted property, and false to true
restart. Run those in Docker CI and extend its path filter to the dist
docker directory.
@dosubot dosubot Bot added size:L This PR changes 100-499 lines, ignoring generated files. and removed size:M This PR changes 30-99 lines, ignoring generated files. labels Jul 26, 2026
@bitflicker64 bitflicker64 changed the title fix(hugegraph-dist): skip init-store when graph.load_from_local_config is false fix(hugegraph-dist): gate init-store on a dedicated init_store.enabled option Jul 26, 2026
@codecov

codecov Bot commented Jul 26, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 1.87500% with 157 lines in your changes missing coverage. Please review.
✅ Project coverage is 32.41%. Comparing base (f8e7abf) to head (3e505a8).
⚠️ Report is 1 commits behind head on master.

Files with missing lines Patch % Lines
...main/java/org/apache/hugegraph/cmd/ConfigTool.java 0.00% 75 Missing ⚠️
.../main/java/org/apache/hugegraph/cmd/InitStore.java 0.00% 58 Missing ⚠️
...g/apache/hugegraph/auth/StandardAuthenticator.java 0.00% 24 Missing ⚠️

❗ There is a different number of reports uploaded between BASE (f8e7abf) and HEAD (3e505a8). Click for more details.

HEAD has 2 uploads less than BASE
Flag BASE (f8e7abf) HEAD (3e505a8)
3 1
Additional details and impacted files
@@             Coverage Diff              @@
##             master    #3119      +/-   ##
============================================
- Coverage     39.13%   32.41%   -6.73%     
  Complexity      264      264              
============================================
  Files           770      771       +1     
  Lines         65772    65930     +158     
  Branches       8725     8762      +37     
============================================
- Hits          25741    21368    -4373     
- Misses        37272    42110    +4838     
+ Partials       2759     2452     -307     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@imbajin imbajin left a comment

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.

Blocking: yes. Summary: The skip path still fails admin bootstrap for the shipped HStore configuration and has inconsistent option/password handling; backend and plugin registration also occurs before the gate. Evidence: six independent review lanes, exact-head static traces, an uppercase FALSE regression test failing four assertions, and all visible latest-head checks passing.

Comment thread hugegraph-server/hugegraph-dist/docker/docker-entrypoint.sh
Comment thread hugegraph-server/hugegraph-dist/docker/docker-entrypoint.sh
Comment thread hugegraph-server/hugegraph-dist/docker/docker-entrypoint.sh Outdated
… is true

With init_store.enabled=false the built-in admin account is not created by
init-store, and the only other component that creates it is
GraphManager.initAdminUserIfNeeded(), reached from loadMetaFromPD() and so
gated on usePD. That option defaults to false and the shipped HStore compose
files do not set it, so enabling auth in skip mode would start a server that
enforces authentication with no account to authenticate against.

The entrypoint now refuses that combination and exits with an explanation,
and InitStore logs the same condition for non-Docker installs. Skipping
without auth is unaffected. usePD=true is already the documented pairing for
distributed deployments in the cluster-test rest-server.properties template.

Also align the shell with the server's boolean parsing, which is
case-insensitive, so HG_SERVER_INIT_STORE_ENABLED=FALSE no longer means skip
to Java and run to the entrypoint; read the property through the separators a
properties file allows; escape the password for properties serialization so a
backslash survives; and register backends and plugins only on the enabled
path, since plugin registration runs every plugin's register() and propagates
its failures.

Add entrypoint coverage for these plus a test that disabled mode leaves
backend options unregistered. Note a pre-existing arthas config key mismatch
found while checking the option table.
@bitflicker64

bitflicker64 commented Jul 27, 2026

Copy link
Copy Markdown
Contributor Author

Unrelated to this change, but noticed while checking the ServerOptions table, so I left a TODO on it rather than silently fixing it here.

The arthas options are declared camelCase (arthas.telnetPort, arthas.httpPort, arthas.disabledCommands) while conf/rest-server.properties ships them snake_case (arthas.telnet_port, arthas.http_port, arthas.disabled_commands). Nothing normalizes between the two, so those keys never match and config.get() returns the declared default. Only arthas.ip works.

It is invisible today because each shipped value equals its default. It bites on any change, e.g. arthas.disabled_commands=jad,exec is dropped and exec stays enabled.

@imbajin imbajin left a comment

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.

Blocking: yes. Summary: The mounted-properties override path can create duplicate scalar keys and make init-store or server startup fail. Evidence: six independent review lanes, exact-head static tracing through docker-entrypoint.sh and HugeConfig.java, and all visible latest-head checks passing.

Comment thread hugegraph-server/hugegraph-dist/docker/docker-entrypoint.sh Outdated
get_prop was widened to read the `=`, `:` and whitespace separators a
properties file allows, but set_prop still matched only `key=value`. A mounted
`init_store.enabled:false` overridden by HG_SERVER_INIT_STORE_ENABLED therefore
gained a second definition instead of being replaced, and a key defined twice
collects both values into a list that fails the scalar type check while the
config is still loading. Both init-store and server startup would fail. The
same applied to a colon-form auth.admin_pa overridden by PASSWORD.

set_prop now matches the same separators and collapses every existing
definition into one canonical `key=value` line, leaving comments alone. It is
written in awk, so the key and value are matched and emitted literally and no
regex escaping is involved.

Cover colon-form and whitespace-form overrides asserting a single remaining
definition, a colon-form auth.admin_pa override, and that commented defaults
are not treated as definitions. Add a test loading a duplicated key through
HugeConfig to pin why the collapse is required.
@bitflicker64
bitflicker64 requested a review from imbajin July 27, 2026 15:19

@imbajin imbajin left a comment

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.

Blocking: yes. Summary: The disabled init path can still report success for an unusable auth configuration, and two Docker config rewrite paths can fail or corrupt mounted/protected configs. Evidence: six independent exact-head review lanes; entrypoint smoke tests passed 57 assertions with 2 macOS-only skips; git diff --check passed; codecov/patch and codecov/project are failing.

Comment thread hugegraph-server/hugegraph-dist/docker/docker-entrypoint.sh Outdated
Comment thread hugegraph-server/hugegraph-dist/docker/docker-entrypoint.sh Outdated
Comment thread hugegraph-server/hugegraph-dist/docker/test/test-docker-entrypoint.sh Outdated
…onf in place

Four fixes to the skip path.

InitStore returned zero for a configuration it had just reported as unusable:
init_store.enabled=false with an authenticator set and usePD false means no
component creates the built-in admin. Tarball and init-job callers see only the
exit status, so they continued into an auth-enabled server nobody could reach.
It now fails. Remote auth is exempt, since the auth manager is then an RPC
client and StandardAuthenticator only bootstraps a local one; the entrypoint
guard gains the same exemption, which it was missing.

set_prop replaced the config by rename. A single-file bind mount cannot be
replaced that way, so startup aborted under set -e, and the rename also
discarded the original mode, which matters where auth.admin_pa is written. It
now truncates and rewrites in place, and creates its scratch file under umask
077.

On the skip path enable-auth.sh ran unconditionally, and it appends its keys
without checking, so a mounted config that already enabled auth ended up with
auth.authenticator and auth.graph_store defined twice, which the config parser
rejects. It now runs only when auth is not configured yet, and both keys are
collapsed to single definitions afterwards.

The test guard that skipped two cases without GNU sed was stale once set_prop
moved to awk. Removed, so those cases run everywhere.

Cover the exit status and the remote-auth exemption in the CLI test, and add
entrypoint cases for a mounted auth config, the remote-auth exemption, inode
and mode preservation, and scratch file cleanup.

@imbajin imbajin left a comment

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.

Blocking: yes. Summary: The skip path can leave Gremlin authentication incomplete and rejects supported custom authenticators. Evidence: six independent exact-head review lanes, static traces through enable-auth.sh and HugeAuthenticator.loadAuthenticator(), 74/74 entrypoint assertions passing, git diff --check passing, and all visible latest-head workflows passing.

Comment thread hugegraph-server/hugegraph-dist/docker/docker-entrypoint.sh Outdated
@dosubot dosubot Bot added size:XL This PR changes 500-999 lines, ignoring generated files. and removed size:L This PR changes 100-499 lines, ignoring generated files. labels Jul 28, 2026
…n check

enable-auth.sh also adds the authentication block to gremlin-server.yaml and
switches hugegraph.properties to the auth proxy. Skipping it whenever
auth.authenticator already existed left both undone, so a mounted config that
set only that key could start with REST auth on and Gremlin open. Apply each of
the three changes only where it is missing instead, and point the Gremlin block
at whichever authenticator the REST config names.

The admin-account requirement now applies only to the built-in authenticator
and its subclasses. auth.authenticator takes any implementation class, and a
custom LDAP/OIDC/plugin one manages identities elsewhere, so requiring usePD
for it rejected a deployment that works.

get_prop no longer deletes whitespace inside a value, only around it, as the
properties parser does.
- get_prop uses `sed -E` rather than `-r`, which only GNU sed documents
- the appended gremlin-server.yaml block no longer glues itself onto a last
  line that has no trailing newline
- the option description, the InitStore comment and docker/README no longer
  claim every authenticator needs the built-in admin account, which stopped
  being true when the check was narrowed
- InitStoreConfigTest is imported in suite order in UnitTestSuite
- a test asserts the entrypoint's inlined auth block still names everything
  bin/enable-auth.sh does, so the two cannot drift unnoticed
@bitflicker64

Copy link
Copy Markdown
Contributor Author

Did a self-review pass over the whole diff and pushed 090763a with the follow-ups, no behaviour change beyond the two fixes below:

  • get_prop now uses sed -E rather than -r, which only GNU sed documents.
  • The gremlin-server.yaml block is no longer appended onto a last line that has no trailing newline.

The rest is text and hygiene: the option description, the InitStore comment and docker/README.md still said every auth.authenticator needs the built-in admin account, which stopped being true when the check was narrowed; InitStoreConfigTest is now imported in suite order.

Since the entrypoint reapplies what bin/enable-auth.sh does when it cannot run the script itself, there is now a test asserting the entrypoint still names every class and key that script does, so the two cannot drift silently. Happy to move that logic into enable-auth.sh instead if you would rather have one source of truth there, it just reaches outside the docker path.

Local run: 106 assertions across 30 entrypoint cases, unit suite 626 tests green on JDK 11, rat and editorconfig clean.

# Conflicts:
#	hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/UnitTestSuite.java

@imbajin imbajin left a comment

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.

Blocking: yes. Summary: The skip path still has inconsistent admin-bootstrap decisions across Docker and Java, and several auth configurations can start unusable or incompletely protected. Evidence: six independent exact-head review lanes, static traces through docker-entrypoint.sh, InitStore, GraphManager, and StandardHugeGraph; 106/106 entrypoint assertions and the focused Java test passed; git diff --check passed; visible Actions passed but Codecov statuses failed.

Comment thread hugegraph-server/hugegraph-dist/docker/docker-entrypoint.sh Outdated
Comment thread hugegraph-server/hugegraph-dist/docker/docker-entrypoint.sh Outdated
Comment thread hugegraph-server/hugegraph-dist/docker/docker-entrypoint.sh Outdated
Comment thread .github/workflows/docker-build-ci.yml
Comment thread hugegraph-server/hugegraph-dist/docker/test/test-docker-entrypoint.sh Outdated
Comment thread PR_DESCRIPTION.md Outdated
@bitflicker64

Copy link
Copy Markdown
Contributor Author

Coverage infrastructure note for final head 4b298bf2477685e886516acb54de880904a57ff5:

Both completed Linux server jobs generated and discovered four coverage XML reports, then reached the repository coverage upload step. The tokenless POST was rejected by Codecov with HTTP 429 in both jobs:

  • rocksdb job: Rate limit reached, expected availability 3366 seconds
  • memory job: Rate limit reached, expected availability 3169 seconds

The uploader explicitly exited with status 0 after those errors, so GitHub shows the jobs as successful but Codecov has not produced final-head project or patch statuses. This reproduces the repository-level tokenless-upload failure seen on the baseline; it is not a test or coverage-generation failure. The focused suite has 17 passing tests and the full Java 11 unit profile has 609 passing tests with one existing skip.

Could a maintainer retry coverage after the rate-limit window with the repository upload token, or explicitly waive the Codecov gate for this head?

@dosubot dosubot Bot added size:XXL This PR changes 1000+ lines, ignoring generated files. and removed size:XL This PR changes 500-999 lines, ignoring generated files. labels Jul 29, 2026
@imbajin
imbajin requested a review from Copilot July 29, 2026 22:39

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR adds a dedicated init_store.enabled server option (default true) to gate InitStore’s local initialization behavior, enabling PD/HStore (distributed) deployments to skip local backend/admin initialization while still validating that authentication is usable. It also updates the Docker entrypoint and wrappers to apply the same decision consistently, with improved property-file handling and extensive lifecycle coverage.

Changes:

  • Introduces init_store.enabled (ServerOptions.INIT_STORE_ENABLED) and wires it into InitStore with a validation-only disabled path.
  • Enhances Docker entrypoint behavior for init-store gating, auth bootstrap/persistence, property canonicalization, and safer secret writes.
  • Adds focused Java unit tests, entrypoint smoke tests, and CI wiring for the new entrypoint test suite.

Reviewed changes

Copilot reviewed 10 out of 11 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/UnitTestSuite.java Registers the new InitStore config unit tests in the unit suite.
hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/unit/cmd/InitStoreConfigTest.java Adds unit tests covering init_store.enabled, admin password handling, and disabled-path validation rules.
hugegraph-server/hugegraph-dist/src/main/java/org/apache/hugegraph/cmd/InitStore.java Implements the init_store.enabled gate, disabled-path validation, and optional configured-password mode.
hugegraph-server/hugegraph-dist/src/assembly/static/bin/init-store.sh Updates the init-store wrapper to accept/forward an optional flag and propagate Java exit codes.
hugegraph-server/hugegraph-dist/docker/test/test-docker-entrypoint.sh Adds a comprehensive entrypoint lifecycle smoke test suite.
hugegraph-server/hugegraph-dist/docker/test/JavaPropertiesReader.java Adds a helper to validate Java-properties parsing round-trips (including tricky UTF-8 / escapes).
hugegraph-server/hugegraph-dist/docker/docker-entrypoint.sh Applies init-store gating + auth enablement completion, canonicalizes properties, and persists secrets safely when needed.
hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/config/ServerOptions.java Defines the new init_store.enabled configuration option.
hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/auth/StandardAuthenticator.java Extends admin init to support configured-password mode and ensures auth graph is always closed.
docker/README.md Documents HG_SERVER_INIT_STORE_ENABLED semantics and the auth-related constraints in disabled mode.
.github/workflows/docker-build-ci.yml Adds a CI job to run the entrypoint smoke tests when Docker-related paths change.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@imbajin imbajin left a comment

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.

Blocking: yes. Summary: The latest head can create a predictable admin credential and still has a properties-parser gap that can leave authentication incomplete; three narrower cleanup and test-trigger issues also remain. Evidence: exact-head static traces through the entrypoint, InitStore, StandardAuthenticator, and workflow; visible Actions passed while Codecov patch/project failed.

Comment thread hugegraph-server/hugegraph-dist/docker/docker-entrypoint.sh
Comment thread hugegraph-server/hugegraph-dist/docker/docker-entrypoint.sh Outdated
Comment thread hugegraph-server/hugegraph-dist/docker/docker-entrypoint.sh Outdated
Comment thread .github/workflows/docker-build-ci.yml

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 12 out of 14 changed files in this pull request and generated no new comments.

Suppressed comments (1)

hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/auth/StandardAuthenticator.java:240

  • StandardAuthenticator.initAdminUserIfNeeded() only checks whether auth.authenticator is empty, but it doesn't verify that the configured authenticator is actually StandardAuthenticator (or a subclass). If this helper is invoked with a config that sets a custom/local authenticator, it can still open the auth graph and potentially create HugeGraph's built-in admin account even though that authenticator doesn't use it. Add a defensive check so the method no-ops unless auth.authenticator resolves to StandardAuthenticator (or subclass).
        HugeConfig config = new HugeConfig(confFile);
        String authClass = config.get(ServerOptions.AUTHENTICATOR);
        if (authClass.isEmpty()) {
            return;
        }
        config.addProperty(INITING_STORE, true);
        auth.initAdminUser(config, password, fromConfig);

@imbajin imbajin left a comment

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.

Blocking: yes. Summary: The current head still has upgrade and authentication-consistency regressions, plus configuration durability and deployment-hardening gaps. Evidence: six independent exact-head review lanes; static traces through docker-entrypoint.sh, ConfigTool, and init-store.sh; 217/217 entrypoint assertions passed; Actions passed while codecov/patch and codecov/project failed.

"$(get_prop "auth.graph_store" "${REST_SERVER_CONF}")")
STORED_AUTH_STATE=$(cat \
"${DOCKER_FOLDER}/${AUTH_INIT_STATE_FILE}" 2>/dev/null || true)
if [[ -f "${DOCKER_FOLDER}/${INIT_FLAG_FILE}" &&

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.

‼️ Existing authenticated volumes can fail their first startup after this upgrade. A legacy volume can have docker/init_complete and a working built-in admin but no new auth_init_state; the empty stored state then makes AUTH_INIT_REQUIRED=true, and lines 298-304 reject startup unless the operator supplies PASSWORD or a persisted auth.admin_pa. Previous authenticated initialization passed the password over stdin and did not persist it, so this turns a valid existing deployment into an unavailable one. Please distinguish the legacy/missing-state upgrade case and inspect whether admin bootstrap is actually needed before requiring a new secret; add a regression with init_complete, no auth_init_state, an existing admin, and no supplied password.

esac
}

gremlin_auth_configured() {

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.

‼️ This presence-only grep can leave Gremlin and REST using different authentication providers. For example, after REST moves from StandardAuthenticator to a custom authenticator, an existing Gremlin block is accepted unchanged, so old HugeGraph credentials can remain valid through Gremlin. It also misses valid YAML such as authentication : {...} and appends a duplicate block. Please parse and reconcile the effective top-level YAML authentication configuration with the selected REST authenticator (or fail closed on mismatch), and add transition plus separator-whitespace regressions.

FileHandler handler = new FileHandler(config);
handler.save(scratch.toFile());
try (InputStream input = Files.newInputStream(scratch);
OutputStream output = Files.newOutputStream(

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.

⚠️ This truncates the active configuration before the replacement bytes are known to be fully written. An ENOSPC or I/O failure after TRUNCATE_EXISTING leaves the target partial or empty, and the finally block then deletes the complete scratch copy; that can erase the persisted admin credential and make every restart fail. Please retain a recoverable copy until replacement succeeds, using atomic replacement for ordinary files and a guarded backup/restore path for bind mounts, with an injected mid-copy failure test.


static void setProperty(String file, String key, String value)
throws ConfigurationException, IOException {
PropertiesConfiguration config = load(file);

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.

⚠️ Loading and saving through PropertiesConfiguration silently destroys Commons Configuration include semantics. include and includeoptional files are resolved into the effective configuration, but PropertiesConfigurationLayout documents that saving flattens included properties into the parent and drops the include directive. A single environment override can therefore stop later child-file updates from applying and copy included secrets into a broader-permission parent file. Please preserve include directives during mutation or reject rewriting files that use them, and add a parent/child include regression.

log "ERROR: cannot protect ${REST_SERVER_CONF} before writing auth.admin_pa"
exit 1
fi
if ! set_prop "auth.admin_pa" "${PASSWORD}" \

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.

⚠️ This forwards the administrator password to ConfigTool set as a JVM command-line argument, so it is observable in process listings, /proc/<pid>/cmdline, container inspection, and command-line audit records during startup. The existing enabled bootstrap path already avoids this by using stdin. Please add a sensitive-value mode that reads from stdin or a file descriptor, and test that the launched Java argv never contains the password.


# The gate returns before backend or plugin registration, so this performs
# validation only.
./bin/init-store.sh

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.

⚠️ The documented validation-only disabled path still invokes init-store.sh, whose wrapper unconditionally calls ensure_path_writable "${PLUGINS}" before Java. A hardened deployment with a read-only application/plugins mount therefore fails even though this path deliberately skips backend and plugin registration. Please invoke the validation directly through ConfigTool, or add a validation-only wrapper mode that bypasses plugin writability checks, with a read-only-plugins regression.


echo "==> a read-only mount rejects an init-store env override"
new_install
chmod 444 "${INSTALL}/conf/rest-server.properties"

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.

⚠️ chmod 444 does not model the production container failure this test claims to cover. Both server Dockerfiles run the entrypoint as root, which can still truncate a regular mode-0444 file, while Actions runs this shell suite as a non-root host user; the test therefore never exercises a real read-only bind mount/EROFS path. Please add an image-level case with a genuinely read-only bind mount or filesystem and assert non-zero propagation, no server start, and no leaked scratch file.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XXL This PR changes 1000+ lines, ignoring generated files. tests Add or improve test cases

Projects

None yet

Development

Successfully merging this pull request may close these issues.

InitStore should skip local init when graph.load_from_local_config is explicitly false

3 participants