Add PIMONITOR_API_KEY env var and warn about -api-key exposure - #90
Merged
Conversation
A process's command line is world-readable via /proc/<pid>/cmdline, so passing the REST API key with -api-key leaks it to every local user — unlike the config file, which install.sh restricts to 640 root:pimonitor. Add PIMONITOR_API_KEY as a middle ground that systemd can deliver through EnvironmentFile= from a root-only file. It resolves between the config file and the flags, and an unset or empty value is ignored so exporting it blank cannot silently disable an api_key set in the config file. Load now delegates to an unexported load(args, lookupEnv) so the precedence rules are testable without mutating the process environment. Document the flag as development-only in the flag usage text, README, SECURITY.md, docs/API.md, docs/ARCHITECTURE.md, the example config, and the systemd unit (which gains a commented-out EnvironmentFile= example).
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Pull Request
📖 Description
A process's command line is world-readable through
/proc/<pid>/cmdline, so passing the REST API key via the-api-keyflag leaks the secret to every local user on the box — unlike the config file, whichinstall.shkeeps at mode640 root:pimonitor. README anddocs/API.mdpreviously mentioned the flag without any warning.This is a security-hardening fix (no breaking change):
PIMONITOR_API_KEYenvironment variable as the middle ground suggested in the issue: systemd can deliver it viaEnvironmentFile=from a root-only file, so the secret never touches a command line. It resolves between the config file and the CLI flags in precedence (defaults → YAML → env → flags). An unset or empty value is ignored, mirroring how the empty flag default is treated, so exportingPIMONITOR_API_KEY=""cannot silently disable anapi_keyconfigured in the file.-api-keydocumented as development-only in the flag's own usage text,README.md,SECURITY.md,docs/API.md,docs/ARCHITECTURE.md, andpackaging/pimonitor.example.yaml.packaging/pimonitor.servicegains a commented-outEnvironmentFile=/etc/pimonitor/pimonitor.envexample plus a note on the required permissions (systemd reads it as PID 1, before dropping to thepimonitoruser).Loadnow delegates to an unexportedload(args, lookupEnv)so the precedence rules can be tested without mutating the process environment. The exportedLoadsignature and behavior are unchanged for existing callers.🎫 Issues
Closes #68
👩💻 Reviewer Notes
internal/config/config.gothat apply the env var between the YAML merge and the flag overrides; everything else is documentation and packaging comments./api/v1/...response shapes are untouched;docs/API.mdonly gains guidance on where to put the key.bin/pimonitor -config packaging/pimonitor.example.yamlwithPIMONITOR_API_KEY=secretexported, then confirmcurl -s localhost:8080/api/v1/metricsreturns 401 andcurl -H 'X-Api-Key: secret' ...returns 200.📑 Test Plan
New unit tests in
internal/config/config_test.go, followingdocs/TESTS.md(Test<Subject>_<Scenario>naming, no real environment or/procaccess — the environment is injected via alookupEnvstub):TestLoad_APIKeyFromEnv— the env var sets the key.TestLoad_APIKeyEnvOverridesConfigFile— env beatsapi_keyfrom the YAML file.TestLoad_APIKeyFlagOverridesEnv—-api-keystill wins over the env.TestLoad_APIKeyEmptyEnvKeepsConfigFileValue— an exported-but-empty variable does not disable configured authentication.TestLoad_ReadsAPIKeyEnvVar— covers the exportedLoad's wiring to the real process environment viat.Setenv, which the injected-stub tests deliberately bypass.go build ./...,go vet ./...,go test ./... -race -cover(config package at 95.7%), andgolangci-lint run(0 issues) all pass locally. Nothing here depends on real Pi hardware, so this is fully verified.✅ Checklist
General
go test ./... -race -coverpasses locally).go vet ./...andgolangci-lint runare clean.ARCHITECTURE.mdif this changes a documented design decision.REST API / configuration / packaging
docs/API.mdto reflect a REST API change./api/v1/...response shapes, or a new API version (/api/v2/...) was introduced instead.README.md/packaging/pimonitor.example.yamlto reflect a new or changed configuration option.packaging/install.shor the systemd units if this changes installation/packaging, and kept the unprivileged/privileged service split intact (seeSECURITY.md).⏭ Next Steps
The
-api-keyflag is kept for development convenience. If it should disappear entirely, deprecating it (a startup warning first, removal in a later release) would be a natural follow-up.