feat(config): migrate wallet to use a layered configuration#194
feat(config): migrate wallet to use a layered configuration#194gustavovalverde wants to merge 12 commits intozcash:mainfrom
Conversation
|
LGTM, this is essential for the whole containerization process. |
str4d
left a comment
There was a problem hiding this comment.
I am currently on PTO, but I want to ensure this is blocked on my review.
|
|
||
| /// Returns true if a leaf key name should be considered sensitive and blocked | ||
| /// from environment variable overrides. | ||
| fn is_sensitive_leaf_key(leaf_key: &str) -> bool { |
There was a problem hiding this comment.
zallet/src/config.rs
Outdated
| } | ||
|
|
||
| /// Zallet Configuration Filename | ||
| pub const CONFIG_FILE: &str = "zallet.toml"; |
There was a problem hiding this comment.
We place constants at the top of a file (between the imports, and functions/structs/etc), so that we don't lose track of them. Move this to the equivalent location of where it was in zallet/src/commands.rs.
EDIT: after my review comment that EntryPoint::config_path should be un-deleted, this move should instead be undone.
Cargo.toml
Outdated
| rust-embed = "8" | ||
|
|
||
| # Parsing and serialization | ||
| config = { version = "0.15.13", features = ["toml", "json"] } |
| // Add filtered environment variables (highest precedence) | ||
| builder = builder.add_source( |
There was a problem hiding this comment.
In the group chat, we discussed only supporting env-var setting in Docker images specifically. If we take that approach, this would be where we configure it:
| // Add filtered environment variables (highest precedence) | |
| builder = builder.add_source( | |
| // Add filtered environment variables (highest precedence) | |
| #[cfg(zallet_docker_image)] | |
| builder = builder.add_source( |
There was a problem hiding this comment.
In Zebra we're removing this feature gates that were specific to Docker (unrelated to config) because it requires us to build a specific image just for the sake of testing and confirming that feature is behaving as expected. It also requires to publish an image just with this feature enabled so it's easier for users.
What would be the benefit here? I'm not completely sure what we're trying to avoid. From my perspective—not adding the feature gate—would allow a consistent way to configure Zallet (containerized or not).
There was a problem hiding this comment.
We shouldn’t have different releases, since by avoiding the definition of sensitive parameters as environment variables, I believe there’s no longer a need to maintain two releases
This commit replaces the Abscissa-based configuration system in Zallet with the `config-rs` crate, providing a standard layered configuration approach that unifies the Z3 stack configuration strategy across Zebra, Zaino, and Zallet This change introduces a clear precedence for configuration sources: 1. Hard-coded defaults (lowest precedence) 2. Optional `zallet.toml` configuration file 3. Environment variables with `ZALLET_` prefix (highest precedence) The Abscissa `Configurable` trait remains for application lifecycle integration, CLI argument injection, and command-specific configuration overrides.
- Add is_sensitive_leaf_key() to filter ZALLET_* env vars by leaf key (case-insensitive) - Block env overrides ending with: password, secret, token, cookie, private_key - Pre-filter env vars before passing to config::Environment via .source(Some(filtered_env)) - Preserve existing prefix/separator logic and list parsing for rpc.bind - Keep non-sensitive fields overridable (validator_address, validator_cookie_path, etc.) Aligns with Zebra and Zaino security model for Z3 stack consistency.
Co-authored-by: Jack Grigg <thestr4d@gmail.com>
Co-authored-by: Jack Grigg <thestr4d@gmail.com>
- Move CONFIG_FILE constant from config.rs to commands.rs - Import functions directly in config.rs instead of using fully qualified paths - Move resolve_config_path method from ZalletConfig to EntryPoint::config_path - Position config_path method after datadir method as requested - Fix test compilation errors with mutable env variables as some tests failed because env variables needed mut to call env.set_var()
c1f983a to
c30ceed
Compare
- Trust Ed Page for config crate dependency (already trusted by major orgs)
Update ZalletConfig documentation to explain layered configuration approach: - Document Option<T> field usage for default vs explicit value distinction - Explain serde(default) section header UX balance - Clarify config generation vs parsing behavior differences
…ntly ignoring Replace silent ignoring of sensitive environment variables with explicit errors to prevent: - Silent misconfigurations where users think secrets are configured but aren't - Process table exposure of sensitive values even when ignored
Once we're done I'll squash. In the meanwhile I'll keep them separate for clarity |
|
I've fixed the merge conflicts. Let me know how'd like to proceed @str4d |
Motivation
This pull request migrates Zallet's configuration system from Abscissa to
config-rs, to unify the configuration approach across the Z3 stack (Zebra, Zaino, and Zallet).This work follows the same pattern used in Zebra's configuration migration (Zebra PR #9768) and Zaino's migration (Zaino PR #469).
Solution
The new implementation uses
config-rsto load configuration from three sources in order of precedence:zallet.tomlconfiguration fileZALLET_prefix (highest precedence)Key technical improvements:
config::ConfigErrordirectly, providing structured error information with file paths, keys, and type mismatchesZALLET_SECTION__KEYformat for complex configuration structuresZALLET_RPC__BIND=127.0.0.1:8080,127.0.0.1:8081)Implementation Details
#[serde(default)]to all nested configuration sections to ensure partial configurations work correctlyconfig.rsfor better organizationconfig::ConfigErrortoFrameworkErrorhappens only inprocess_config()--datadirand--configare properly integrated with the configuration systemTests
A test suite has been added at
wallet/zallet/tests/config.rscovering:Specifications & References
config-rscrate documentation