Skip to content

refactor(config): remove embedded default admin password - #1238

Draft
nbmaiti wants to merge 1 commit into
pr/CM352from
pr/CM-240
Draft

refactor(config): remove embedded default admin password#1238
nbmaiti wants to merge 1 commit into
pr/CM352from
pr/CM-240

Conversation

@nbmaiti

@nbmaiti nbmaiti commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Summary

  • remove the default admin password from the shipped config; it is generated on first run and stored only as a bcrypt hash
  • verify basic auth with bcrypt instead of a plaintext comparison
  • normalize any legacy plaintext auth.adminPassword into a hash on startup
  • add regression checks so a default password is not reintroduced

Note: auth.adminUsername intentionally keeps its standalone default so a fresh install can still log in. Only the password default is removed.

Testing

  • go test ./config/... ./cmd/... ./internal/controller/httpapi/v1/... ./internal/controller/tcp/cira/...

@nbmaiti
nbmaiti requested a review from a team as a code owner September 2, 2026 06:38
@codecov

codecov Bot commented Sep 2, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 51.34%. Comparing base (fd8a2d1) to head (a6a5c13).

Additional details and impacted files
@@            Coverage Diff            @@
##           pr/CM352    #1238   +/-   ##
=========================================
  Coverage     51.34%   51.34%           
=========================================
  Files           149      149           
  Lines         13918    13918           
=========================================
  Hits           7146     7146           
  Misses         6160     6160           
  Partials        612      612           

☔ 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.

@nbmaiti
nbmaiti force-pushed the pr/CM352 branch 2 times, most recently from 59b6e1b to 9d49582 Compare September 2, 2026 09:02
@sudhir-intc sudhir-intc changed the title fix(config): remove embedded default admin credentials refactor(config): remove embedded default admin credentials Sep 2, 2026
@madhavilosetty-intel

Copy link
Copy Markdown
Contributor

@nbmaiti On main the default admin username is standalone, so a fresh install logs in fine. This PR sets it to "" but there's no generate-when-blank step like handleAdminPassword has. Won't a freshly downloaded exe then 401 on login (login.go:88 needs an exact match)?

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.

🟡 Changes recommended

There’s a concrete discrepancy with the PR’s stated goal (default admin username still present in defaults) and a security-related comment/guarantee mismatch that should be corrected before merge.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This PR hardens credential handling by ensuring the admin password is no longer stored or compared as plaintext: it is generated when missing, normalized into a bcrypt hash, persisted safely to config.yml, and validated during login using bcrypt. It also adds regression tests around config persistence and CIRA credential checks.

Changes:

  • Generate an admin password when unset, store only its bcrypt hash in config, and normalize legacy plaintext passwords into hashes on startup.
  • Update /api/v1/authorize basic-auth verification to compare against a bcrypt-hashed admin password (with constant-time username comparison).
  • Add/extend tests for password persistence behavior and for CIRA APF handler credential/protocol handling.
File summaries
File Description
internal/controller/tcp/cira/tunnel_test.go Adds targeted APF handler tests for credential validation, auth method handling, and keep-alive threshold behavior.
internal/controller/tcp/cira/handler.go Uses constant-time comparisons for CIRA credential checks (reducing per-field timing leakage).
internal/controller/httpapi/v1/login.go Switches admin password verification to bcrypt hash comparison for basic auth.
internal/controller/httpapi/v1/login_test.go Updates login tests to use a bcrypt-hashed admin password in config fixtures.
config/config.go Makes SaveAdminPassword resilient to missing config files (create-if-missing) while preserving other fields.
config/config_test.go Adds regression tests for SaveAdminPassword creation/preservation/error paths and file permissions.
cmd/app/main.go Implements admin password hashing/normalization, persistence behavior, and one-time plaintext disclosure on generation.
cmd/app/main_test.go Adds tests ensuring generated passwords are persisted as hashes and legacy plaintext values are normalized correctly.
Review details
  • Files reviewed: 8/8 changed files
  • Comments generated: 2
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread internal/controller/tcp/cira/handler.go Outdated
Comment on lines +102 to +105
// Both comparisons always run so the response time does not reveal which
// field failed. MPSUsername is the field used for CIRA authentication.
usernameMatches := subtle.ConstantTimeCompare([]byte(device.MPSUsername), []byte(username))
passwordMatches := subtle.ConstantTimeCompare([]byte(device.MPSPassword), []byte(password))
Comment thread config/config.go
Comment on lines 395 to +399
fileCfg := defaultConfig()
if err := yaml.Unmarshal(data, fileCfg); err != nil {
return err

if _, statErr := os.Stat(configPath); statErr == nil {
data, readErr := os.ReadFile(configPath)
if readErr != nil {
Console compared the admin username and password with plain string
equality, so credentials were matched in cleartext and the comparison
leaked timing information. Verify the admin password as a bcrypt hash
and compare the username in constant time, hashing and persisting any
plaintext value already present in config on startup.

CIRA authentication had the same flaw: the decrypted MPSPassword was
checked with a direct != comparison, which is vulnerable to a timing
side channel. Use subtle.ConstantTimeCompare for both the username and
the password.

Add tests covering the credential rejection paths, including an unset
device ID, a lookup failure, and a missing device.

Signed-off-by: Nabendu Maiti <nabendu.bikash.maiti@intel.com>
@nbmaiti nbmaiti changed the title refactor(config): remove embedded default admin credentials refactor(config): remove embedded default admin password Sep 3, 2026
@nbmaiti
nbmaiti force-pushed the pr/CM-240 branch 2 times, most recently from 4268a34 to a6a5c13 Compare September 3, 2026 09:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants