Skip to content

Conversation

@weidongkl
Copy link
Contributor

  • Add new -basic-auth-hash-password command line flag accepting bcrypt hashes
  • Preserve legacy -basic-auth-password parameter for backward compatibility

fix: #976

https://prometheus.io/docs/guides/basic-auth/#hashing-a-password

plainpassword
image
error hash password
image
correct hash password

image

set both hash-password and password

image

@codecov
Copy link

codecov bot commented Nov 25, 2025

Codecov Report

❌ Patch coverage is 72.72727% with 6 lines in your changes missing coverage. Please review.
✅ Project coverage is 81.82%. Comparing base (b0a03b2) to head (8f7399b).
⚠️ Report is 2 commits behind head on master.

Files with missing lines Patch % Lines
main.go 53.84% 6 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #1066      +/-   ##
==========================================
- Coverage   81.86%   81.82%   -0.05%     
==========================================
  Files          20       20              
  Lines        2636     2652      +16     
==========================================
+ Hits         2158     2170      +12     
- Misses        358      362       +4     
  Partials      120      120              

☔ View full report in Codecov by Sentry.
📢 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.

@coveralls
Copy link

coveralls commented Nov 25, 2025

Pull Request Test Coverage Report for Build 19915781886

Details

  • 19 of 27 (70.37%) changed or added relevant lines in 2 files are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage decreased (-0.1%) to 85.643%

Changes Missing Coverage Covered Lines Changed/Added Lines %
main.go 9 17 52.94%
Totals Coverage Status
Change from base Build 19625151374: -0.1%
Covered Lines: 2738
Relevant Lines: 3197

💛 - Coveralls

@oliver006
Copy link
Owner

Thanks for the PR!
I'll try to have a look at it over the next few days and will get back to you.

exporter/http.go Outdated
if !authHeaderSet {
return errors.New("Unauthorized")
}
if err := e.verifyBasicUser(user); err != nil {
Copy link
Owner

Choose a reason for hiding this comment

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

nit: verifyBasicUser --> verifyBasicAuthUser ?

exporter/http.go Outdated
passCorrect := subtle.ConstantTimeCompare([]byte(password), []byte(e.options.BasicAuthPassword))

if userCorrect == 0 || passCorrect == 0 {
if passCorrect == 0 {
Copy link
Owner

Choose a reason for hiding this comment

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

I think we should keep the same pattern of always comparing both username and password to avoid timing attacks.

I'd rewrite verifyBasicAuth() and check username first (store result in "userCorrect" and then the password (depending on hash or basic) and store the result in "passCorrect" - then check and return)

main.go Outdated
return nil
}

// validateHashPassword checks if the the hashed password is a valid bcrypt hash
Copy link
Owner

Choose a reason for hiding this comment

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

👍

main.go Outdated
}

// Validate basic auth hashed password
if err := validateHashPassword(*basicAuthHashPassword); err != nil {
Copy link
Owner

Choose a reason for hiding this comment

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

Let's do this inside validateAuthParams() where we validate all the auth params already?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Okay, I will modify the code according to the review comments.

@weidongkl weidongkl force-pushed the master branch 2 times, most recently from 8739ef6 to eea2ba6 Compare November 28, 2025 05:45
Copy link
Owner

@oliver006 oliver006 left a comment

Choose a reason for hiding this comment

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

Thanks, looks good. Two minor nits and then we're good to go.

exporter/http.go Outdated
passCorrect := subtle.ConstantTimeCompare([]byte(password), []byte(e.options.BasicAuthPassword))

if userCorrect == 0 || passCorrect == 0 {
var (
Copy link
Owner

Choose a reason for hiding this comment

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

nit: can we please keep the userCorrect := style?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thank you for the review. You're right, and I've refactored the code to use the := style for immediate assignment where possible.

The key change is with the userCorrect variable, which is now directly assigned with a boolean expression using :=.

For the passCorrect variable, the var declaration is retained because its assignment depends on a conditional branch (if/else). Using var allows us to declare the variable first and then assign its value within the respective code blocks. If we used := inside both branches, they would create new, block-scoped variables, leaving the outer passCorrect variable unused.

} else {
passCorrect = subtle.ConstantTimeCompare([]byte(password), []byte(e.options.BasicAuthPassword)) > 0
}
if !userCorrect || !passCorrect {
Copy link
Owner

Choose a reason for hiding this comment

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

👍

main.go Outdated
}

// validateHashPassword checks if the the hashed password is a valid bcrypt hash
func validateHashPassword(hashPassword string) error {
Copy link
Owner

Choose a reason for hiding this comment

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

nit: can we just inline this in validateAuthParams() ? it's not used anywhere.

}
}

func TestValidateAuthParams(t *testing.T) {
Copy link
Owner

Choose a reason for hiding this comment

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

👍

exporter/http.go Outdated

var passCorrect bool
if e.options.BasicAuthHashPassword != "" {
passCorrect = e.validateBasicAuthHashPassword(password)
Copy link
Owner

Choose a reason for hiding this comment

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

can we add a test that makes sure we hit this line in this if block?

https://app.codecov.io/gh/oliver006/redis_exporter/pull/1066 suggests that it's not covered by tests.

maybe modify the new tests in http_test.go to use "verifyBasicAuth()" as the entry point instead of "validateBasicAuthHashPassword()"

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done! I've updated the tests in http_test.go
image

exporter/http.go Outdated
return nil
}

func (e *Exporter) validateBasicAuthHashPassword(hashedPassword string) bool {
Copy link
Owner

Choose a reason for hiding this comment

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

one more thing: we got to rename hashedPassword to password, it's not the hashed password, the hashed password is the e.options.BasicAuthHashPassword param

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You're absolutely right—what's being passed in are passwords, not hashed passwords. As for changing it to validateBasicPassword, I'd suggest putting the password validation logic directly inside this method.

Copy link
Owner

Choose a reason for hiding this comment

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

e.Options... is a hashed password though, no?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

e.Options... is a hashed password though, no?

Yes, it's a hashed password based on the bcrypt algorithm, consistent with the Prometheus design.

- Add new `-basic-auth-hash-password` command line flag accepting bcrypt hashes
- Preserve legacy `-basic-auth-password` parameter for backward compatibility

Signed-off-by: weidongkl <[email protected]>
Copy link
Owner

@oliver006 oliver006 left a comment

Choose a reason for hiding this comment

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

Thanks for your patience and for pushing this over the finish line!

@oliver006 oliver006 merged commit 7ad99f5 into oliver006:master Dec 4, 2025
6 of 9 checks passed
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.

About password encryption

3 participants