fix: add support for sha256 and sha512 in htpasswd (#3497)

feat: add support for sha256 and sha512 htpasswd formats

Fixes issue #3495

We currently support only bcrypt htpasswd hashes, however bcrypt is not
FIPS-140 approved since it uses Blowfish.

This PR adds support for sha256 and sha512 formats and enforces that
bcrypt be disabled when fips140 mode is enabled.

Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>
This commit is contained in:
Ramkumar Chinchani
2025-11-09 05:28:29 -08:00
committed by GitHub
parent aaba362b4f
commit 04ae0a9409
26 changed files with 673 additions and 131 deletions
+3 -3
View File
@@ -99,7 +99,7 @@ func TestAPIKeys(t *testing.T) {
username, seedUser := test.GenerateRandomString()
password, seedPass := test.GenerateRandomString()
htpasswdPath := test.MakeHtpasswdFileFromString(test.GetCredString(username, password))
htpasswdPath := test.MakeHtpasswdFileFromString(test.GetBcryptCredString(username, password))
defer os.Remove(htpasswdPath)
@@ -871,7 +871,7 @@ func TestAPIKeysOpenDBError(t *testing.T) {
conf := config.New()
username, seedUser := test.GenerateRandomString()
password, seedPass := test.GenerateRandomString()
htpasswdPath := test.MakeHtpasswdFileFromString(test.GetCredString(username, password))
htpasswdPath := test.MakeHtpasswdFileFromString(test.GetBcryptCredString(username, password))
defer os.Remove(htpasswdPath)
@@ -1154,7 +1154,7 @@ func TestCookieSecureFlag(t *testing.T) {
username, _ := test.GenerateRandomString()
password, _ := test.GenerateRandomString()
htpasswdPath := test.MakeHtpasswdFileFromString(test.GetCredString(username, password))
htpasswdPath := test.MakeHtpasswdFileFromString(test.GetBcryptCredString(username, password))
defer os.Remove(htpasswdPath)
+86 -78
View File
@@ -719,54 +719,62 @@ func TestHtpasswdSingleCred(t *testing.T) {
Convey("Single cred", t, func() {
port := test.GetFreePort()
baseURL := test.GetBaseURL(port)
singleCredtests := []string{}
user, seedUser := test.GenerateRandomString()
password, seedPass := test.GenerateRandomString()
singleCredtests = append(singleCredtests, test.GetCredString(user, password))
singleCredtests = append(singleCredtests, test.GetCredString(user, password))
credFuncs := []func(string, string) string{
test.GetBcryptCredString,
test.GetSHA256CredString,
test.GetSHA512CredString,
}
for _, testString := range singleCredtests {
func() {
conf := config.New()
conf.HTTP.Port = port
for _, credFunc := range credFuncs {
singleCredtests := []string{}
user, seedUser := test.GenerateRandomString()
password, seedPass := test.GenerateRandomString()
singleCredtests = append(singleCredtests, credFunc(user, password))
singleCredtests = append(singleCredtests, credFunc(user, password))
htpasswdPath := test.MakeHtpasswdFileFromString(testString)
defer os.Remove(htpasswdPath)
conf.HTTP.Auth = &config.AuthConfig{
HTPasswd: config.AuthHTPasswd{
Path: htpasswdPath,
},
}
for _, testString := range singleCredtests {
func() {
conf := config.New()
conf.HTTP.Port = port
conf.HTTP.AllowOrigin = conf.HTTP.Address
htpasswdPath := test.MakeHtpasswdFileFromString(testString)
defer os.Remove(htpasswdPath)
conf.HTTP.Auth = &config.AuthConfig{
HTPasswd: config.AuthHTPasswd{
Path: htpasswdPath,
},
}
ctlr := makeController(conf, t.TempDir())
ctlr.Log.Info().Int64("seedUser", seedUser).Int64("seedPass", seedPass).Msg("random seed for username & password")
conf.HTTP.AllowOrigin = conf.HTTP.Address
cm := test.NewControllerManager(ctlr)
cm.StartAndWait(port)
ctlr := makeController(conf, t.TempDir())
ctlr.Log.Info().Int64("seedUser", seedUser).Int64("seedPass", seedPass).Msg("random seed for username & password")
defer cm.StopServer()
cm := test.NewControllerManager(ctlr)
cm.StartAndWait(port)
// with creds, should get expected status code
resp, _ := resty.R().SetBasicAuth(user, password).Get(baseURL + "/v2/")
So(resp, ShouldNotBeNil)
So(resp.StatusCode(), ShouldEqual, http.StatusOK)
defer cm.StopServer()
header := []string{"Authorization,content-type," + constants.SessionClientHeaderName}
// with creds, should get expected status code
resp, _ := resty.R().SetBasicAuth(user, password).Get(baseURL + "/v2/")
So(resp, ShouldNotBeNil)
So(resp.StatusCode(), ShouldEqual, http.StatusOK)
resp, _ = resty.R().SetBasicAuth(user, password).Options(baseURL + "/v2/")
So(resp, ShouldNotBeNil)
So(resp.StatusCode(), ShouldEqual, http.StatusNoContent)
So(len(resp.Header()), ShouldEqual, 5)
So(resp.Header()["Access-Control-Allow-Headers"], ShouldResemble, header)
So(resp.Header().Get("Access-Control-Allow-Methods"), ShouldResemble, "GET,OPTIONS")
header := []string{"Authorization,content-type," + constants.SessionClientHeaderName}
// with invalid creds, it should fail
resp, _ = resty.R().SetBasicAuth("chuck", "chuck").Get(baseURL + "/v2/")
So(resp, ShouldNotBeNil)
So(resp.StatusCode(), ShouldEqual, http.StatusUnauthorized)
}()
resp, _ = resty.R().SetBasicAuth(user, password).Options(baseURL + "/v2/")
So(resp, ShouldNotBeNil)
So(resp.StatusCode(), ShouldEqual, http.StatusNoContent)
So(len(resp.Header()), ShouldEqual, 5)
So(resp.Header()["Access-Control-Allow-Headers"], ShouldResemble, header)
So(resp.Header().Get("Access-Control-Allow-Methods"), ShouldResemble, "GET,OPTIONS")
// with invalid creds, it should fail
resp, _ = resty.R().SetBasicAuth("chuck", "chuck").Get(baseURL + "/v2/")
So(resp, ShouldNotBeNil)
So(resp.StatusCode(), ShouldEqual, http.StatusUnauthorized)
}()
}
}
})
}
@@ -783,7 +791,7 @@ func TestAllowMethodsHeader(t *testing.T) {
simpleUser := "simpleUser"
simpleUserPassword := "simpleUserPass"
htpasswdPath := test.MakeHtpasswdFileFromString(test.GetCredString(simpleUser, simpleUserPassword))
htpasswdPath := test.MakeHtpasswdFileFromString(test.GetBcryptCredString(simpleUser, simpleUserPassword))
defer os.Remove(htpasswdPath)
@@ -860,14 +868,14 @@ func TestHtpasswdTwoCreds(t *testing.T) {
password1 := "aliciapassword"
user2 := "bob"
password2 := "robert"
twoCredTests = append(twoCredTests, test.GetCredString(user1, password1)+"\n"+
test.GetCredString(user2, password2))
twoCredTests = append(twoCredTests, test.GetBcryptCredString(user1, password1)+"\n"+
test.GetBcryptCredString(user2, password2))
twoCredTests = append(twoCredTests, test.GetCredString(user1, password1)+"\n"+
test.GetCredString(user2, password2)+"\n")
twoCredTests = append(twoCredTests, test.GetBcryptCredString(user1, password1)+"\n"+
test.GetBcryptCredString(user2, password2)+"\n")
twoCredTests = append(twoCredTests, test.GetCredString(user1, password1)+"\n\n"+
test.GetCredString(user2, password2)+"\n\n")
twoCredTests = append(twoCredTests, test.GetBcryptCredString(user1, password1)+"\n\n"+
test.GetBcryptCredString(user2, password2)+"\n\n")
for _, testString := range twoCredTests {
func() {
@@ -920,7 +928,7 @@ func TestHtpasswdFiveCreds(t *testing.T) {
credString := strings.Builder{}
for key, val := range tests {
credString.WriteString(test.GetCredString(key, val) + "\n")
credString.WriteString(test.GetBcryptCredString(key, val) + "\n")
}
func() {
@@ -1074,7 +1082,7 @@ func TestBasicAuth(t *testing.T) {
username, seedUser := test.GenerateRandomString()
password, seedPass := test.GenerateRandomString()
htpasswdPath := test.MakeHtpasswdFileFromString(test.GetCredString(username, password))
htpasswdPath := test.MakeHtpasswdFileFromString(test.GetBcryptCredString(username, password))
defer os.Remove(htpasswdPath)
@@ -1363,7 +1371,7 @@ func TestScaleOutRequestProxy(t *testing.T) {
username, _ := test.GenerateRandomString()
password, _ := test.GenerateRandomString()
htpasswdPath := test.MakeHtpasswdFileFromString(test.GetCredString(username, password))
htpasswdPath := test.MakeHtpasswdFileFromString(test.GetBcryptCredString(username, password))
defer os.Remove(htpasswdPath)
@@ -1935,7 +1943,7 @@ func TestMultipleInstance(t *testing.T) {
username, seedUser := test.GenerateRandomString()
password, seedPass := test.GenerateRandomString()
htpasswdPath := test.MakeHtpasswdFileFromString(test.GetCredString(username, password))
htpasswdPath := test.MakeHtpasswdFileFromString(test.GetBcryptCredString(username, password))
defer os.Remove(htpasswdPath)
@@ -1979,7 +1987,7 @@ func TestMultipleInstance(t *testing.T) {
username, seedUser := test.GenerateRandomString()
password, seedPass := test.GenerateRandomString()
htpasswdPath := test.MakeHtpasswdFileFromString(test.GetCredString(username, password))
htpasswdPath := test.MakeHtpasswdFileFromString(test.GetBcryptCredString(username, password))
defer os.Remove(htpasswdPath)
@@ -2029,7 +2037,7 @@ func TestMultipleInstance(t *testing.T) {
username, seedUser := test.GenerateRandomString()
password, seedPass := test.GenerateRandomString()
htpasswdPath := test.MakeHtpasswdFileFromString(test.GetCredString(username, password))
htpasswdPath := test.MakeHtpasswdFileFromString(test.GetBcryptCredString(username, password))
defer os.Remove(htpasswdPath)
@@ -2083,7 +2091,7 @@ func TestTLSWithBasicAuth(t *testing.T) {
username, seedUser := test.GenerateRandomString()
password, seedPass := test.GenerateRandomString()
htpasswdPath := test.MakeHtpasswdFileFromString(test.GetCredString(username, password))
htpasswdPath := test.MakeHtpasswdFileFromString(test.GetBcryptCredString(username, password))
defer os.Remove(htpasswdPath)
@@ -2154,7 +2162,7 @@ func TestTLSWithBasicAuthAllowReadAccess(t *testing.T) {
username, seedUser := test.GenerateRandomString()
password, seedPass := test.GenerateRandomString()
htpasswdPath := test.MakeHtpasswdFileFromString(test.GetCredString(username, password))
htpasswdPath := test.MakeHtpasswdFileFromString(test.GetBcryptCredString(username, password))
defer os.Remove(htpasswdPath)
@@ -2826,7 +2834,7 @@ func TestTLSMutualAndBasicAuth(t *testing.T) {
username, seedUser := test.GenerateRandomString()
password, seedPass := test.GenerateRandomString()
htpasswdPath := test.MakeHtpasswdFileFromString(test.GetCredString(username, password))
htpasswdPath := test.MakeHtpasswdFileFromString(test.GetBcryptCredString(username, password))
defer os.Remove(htpasswdPath)
@@ -2913,7 +2921,7 @@ func TestTLSMutualAndBasicAuthAllowReadAccess(t *testing.T) {
username, seedUser := test.GenerateRandomString()
password, seedPass := test.GenerateRandomString()
htpasswdPath := test.MakeHtpasswdFileFromString(test.GetCredString(username, password))
htpasswdPath := test.MakeHtpasswdFileFromString(test.GetBcryptCredString(username, password))
defer os.Remove(htpasswdPath)
@@ -4579,7 +4587,7 @@ func TestOpenIDMiddleware(t *testing.T) {
// need a username different than ldap one, to test both logic
htpasswdUsername, seedUser := test.GenerateRandomString()
htpasswdPassword, seedPass := test.GenerateRandomString()
htpasswdPath := test.MakeHtpasswdFileFromString(test.GetCredString(htpasswdUsername, htpasswdPassword))
htpasswdPath := test.MakeHtpasswdFileFromString(test.GetBcryptCredString(htpasswdUsername, htpasswdPassword))
defer os.Remove(htpasswdPath)
@@ -4995,7 +5003,7 @@ func TestOpenIDMiddlewareWithRedisSessionDriver(t *testing.T) {
// need a username different than ldap one, to test both logic
htpasswdUsername, seedUser := test.GenerateRandomString()
htpasswdPassword, seedPass := test.GenerateRandomString()
htpasswdPath := test.MakeHtpasswdFileFromString(test.GetCredString(htpasswdUsername, htpasswdPassword))
htpasswdPath := test.MakeHtpasswdFileFromString(test.GetBcryptCredString(htpasswdUsername, htpasswdPassword))
defer os.Remove(htpasswdPath)
@@ -5481,7 +5489,7 @@ func TestAuthnSessionErrors(t *testing.T) {
htpasswdUsername, seedUser := test.GenerateRandomString()
htpasswdPassword, seedPass := test.GenerateRandomString()
htpasswdPath := test.MakeHtpasswdFileFromString(test.GetCredString(htpasswdUsername, htpasswdPassword))
htpasswdPath := test.MakeHtpasswdFileFromString(test.GetBcryptCredString(htpasswdUsername, htpasswdPassword))
defer os.Remove(htpasswdPath)
@@ -5886,7 +5894,7 @@ func TestAuthnMetaDBErrors(t *testing.T) {
username, seedUser := test.GenerateRandomString()
password, seedPass := test.GenerateRandomString()
htpasswdPath := test.MakeHtpasswdFileFromString(test.GetCredString(username, password))
htpasswdPath := test.MakeHtpasswdFileFromString(test.GetBcryptCredString(username, password))
defer os.Remove(htpasswdPath)
@@ -5999,7 +6007,7 @@ func TestAuthorization(t *testing.T) {
conf.HTTP.Port = port
username, seedUser := test.GenerateRandomString()
password, seedPass := test.GenerateRandomString()
htpasswdPath := test.MakeHtpasswdFileFromString(test.GetCredString(username, password))
htpasswdPath := test.MakeHtpasswdFileFromString(test.GetBcryptCredString(username, password))
defer os.Remove(htpasswdPath)
@@ -6119,7 +6127,7 @@ func TestGetUsername(t *testing.T) {
username, seedUser := test.GenerateRandomString()
password, seedPass := test.GenerateRandomString()
htpasswdPath := test.MakeHtpasswdFileFromString(test.GetCredString(username, password))
htpasswdPath := test.MakeHtpasswdFileFromString(test.GetBcryptCredString(username, password))
defer os.Remove(htpasswdPath)
@@ -6190,7 +6198,7 @@ func TestAuthorizationMountBlob(t *testing.T) {
username1 = strings.ToLower(username1)
username2 = strings.ToLower(username2)
content := test.GetCredString(username1, password1) + test.GetCredString(username2, password2)
content := test.GetBcryptCredString(username1, password1) + test.GetBcryptCredString(username2, password2)
htpasswdPath := test.MakeHtpasswdFileFromString(content)
@@ -6548,7 +6556,7 @@ func TestAuthorizationWithAnonymousPolicyBasicAuthAndSessionHeader(t *testing.T)
badpassphrase := "bad"
htpasswdUsername, seedUser := test.GenerateRandomString()
htpasswdPassword, seedPass := test.GenerateRandomString()
htpasswdPath := test.MakeHtpasswdFileFromString(test.GetCredString(htpasswdUsername, htpasswdPassword))
htpasswdPath := test.MakeHtpasswdFileFromString(test.GetBcryptCredString(htpasswdUsername, htpasswdPassword))
defer os.Remove(htpasswdPath)
@@ -6758,7 +6766,7 @@ func TestAuthorizationWithMultiplePolicies(t *testing.T) {
password1, seedPass1 := test.GenerateRandomString()
username2, seedUser2 := test.GenerateRandomString()
password2, seedPass2 := test.GenerateRandomString()
content := test.GetCredString(username1, password1) + test.GetCredString(username2, password2)
content := test.GetBcryptCredString(username1, password1) + test.GetBcryptCredString(username2, password2)
htpasswdPath := test.MakeHtpasswdFileFromString(content)
@@ -6917,7 +6925,7 @@ func TestInvalidCases(t *testing.T) {
username, seedUser := test.GenerateRandomString()
password, seedPass := test.GenerateRandomString()
htpasswdPath := test.MakeHtpasswdFileFromString(test.GetCredString(username, password))
htpasswdPath := test.MakeHtpasswdFileFromString(test.GetBcryptCredString(username, password))
defer os.Remove(htpasswdPath)
@@ -6977,8 +6985,8 @@ func TestHTTPReadOnly(t *testing.T) {
singleCredtests := []string{}
user, seedUser := test.GenerateRandomString()
password, seedPass := test.GenerateRandomString()
singleCredtests = append(singleCredtests, test.GetCredString(user, password))
singleCredtests = append(singleCredtests, test.GetCredString(user, password)+"\n")
singleCredtests = append(singleCredtests, test.GetBcryptCredString(user, password))
singleCredtests = append(singleCredtests, test.GetBcryptCredString(user, password)+"\n")
port := test.GetFreePort()
baseURL := test.GetBaseURL(port)
@@ -7048,7 +7056,7 @@ func TestCrossRepoMount(t *testing.T) {
conf.HTTP.Port = port
username, seedUser := test.GenerateRandomString()
password, seedPass := test.GenerateRandomString()
htpasswdPath := test.MakeHtpasswdFileFromString(test.GetCredString(username, password))
htpasswdPath := test.MakeHtpasswdFileFromString(test.GetBcryptCredString(username, password))
defer os.Remove(htpasswdPath)
@@ -7263,7 +7271,7 @@ func TestCrossRepoMount(t *testing.T) {
conf := config.New()
conf.HTTP.Port = port
htpasswdPath := test.MakeHtpasswdFileFromString(test.GetCredString(username, password))
htpasswdPath := test.MakeHtpasswdFileFromString(test.GetBcryptCredString(username, password))
defer os.Remove(htpasswdPath)
@@ -7407,7 +7415,7 @@ func TestParallelRequests(t *testing.T) {
conf.HTTP.Port = port
username, seedUser := test.GenerateRandomString()
password, seedPass := test.GenerateRandomString()
htpasswdPath := test.MakeHtpasswdFileFromString(test.GetCredString(username, password))
htpasswdPath := test.MakeHtpasswdFileFromString(test.GetBcryptCredString(username, password))
t.Cleanup(func() {
os.Remove(htpasswdPath)
@@ -8971,7 +8979,7 @@ func TestPagedRepositoriesWithAuthorization(t *testing.T) {
conf.HTTP.Port = port
username, _ := test.GenerateRandomString()
password, _ := test.GenerateRandomString()
htpasswdPath := test.MakeHtpasswdFileFromString(test.GetCredString(username, password))
htpasswdPath := test.MakeHtpasswdFileFromString(test.GetBcryptCredString(username, password))
defer os.Remove(htpasswdPath)
@@ -12380,7 +12388,7 @@ func TestSearchRoutes(t *testing.T) {
user1 := "test"
password1 := "test"
testString1 := test.GetCredString(user1, password1)
testString1 := test.GetBcryptCredString(user1, password1)
htpasswdPath := test.MakeHtpasswdFileFromString(testString1)
@@ -12523,7 +12531,7 @@ func TestSearchRoutes(t *testing.T) {
user1 := "test1"
password1 := "test1"
group1 := "testgroup3"
testString1 := test.GetCredString(user1, password1)
testString1 := test.GetBcryptCredString(user1, password1)
htpasswdPath := test.MakeHtpasswdFileFromString(testString1)
@@ -12611,7 +12619,7 @@ func TestSearchRoutes(t *testing.T) {
password1 := "test2"
group1 := "testgroup1"
group2 := "secondtestgroup"
testString1 := test.GetCredString(user1, password1)
testString1 := test.GetBcryptCredString(user1, password1)
htpasswdPath := test.MakeHtpasswdFileFromString(testString1)
defer os.Remove(htpasswdPath)
@@ -12681,7 +12689,7 @@ func TestSearchRoutes(t *testing.T) {
user1 := "test3"
password1 := "test3"
group1 := "testgroup"
testString1 := test.GetCredString(user1, password1)
testString1 := test.GetBcryptCredString(user1, password1)
htpasswdPath := test.MakeHtpasswdFileFromString(testString1)
defer os.Remove(htpasswdPath)
@@ -12751,7 +12759,7 @@ func TestSearchRoutes(t *testing.T) {
user1 := "test4"
password1 := "test4"
group1 := "testgroup1"
testString1 := test.GetCredString(user1, password1)
testString1 := test.GetBcryptCredString(user1, password1)
htpasswdPath := test.MakeHtpasswdFileFromString(testString1)
@@ -12823,7 +12831,7 @@ func TestSearchRoutes(t *testing.T) {
user1 := "test5"
password1 := "test5"
group1 := "testgroup2"
testString1 := test.GetCredString(user1, password1)
testString1 := test.GetBcryptCredString(user1, password1)
htpasswdPath := test.MakeHtpasswdFileFromString(testString1)
defer os.Remove(htpasswdPath)
@@ -12883,7 +12891,7 @@ func TestSearchRoutes(t *testing.T) {
user1, seedUser1 := test.GenerateRandomString()
password1, seedPass1 := test.GenerateRandomString()
htpasswdPath := test.MakeHtpasswdFileFromString(test.GetCredString(user1, password1))
htpasswdPath := test.MakeHtpasswdFileFromString(test.GetBcryptCredString(user1, password1))
defer os.Remove(htpasswdPath)
conf.HTTP.Auth = &config.AuthConfig{
+44 -6
View File
@@ -3,6 +3,7 @@ package api
import (
"bufio"
"context"
"crypto/fips140"
"errors"
"os"
"os/signal"
@@ -11,6 +12,7 @@ import (
"syscall"
"github.com/fsnotify/fsnotify"
cpass "github.com/nathanaelle/password"
"golang.org/x/crypto/bcrypt"
"zotregistry.dev/zot/v2/pkg/log"
@@ -87,15 +89,51 @@ func (s *HTPasswd) Authenticate(username, passphrase string) (ok, present bool)
return false, false
}
err := bcrypt.CompareHashAndPassword([]byte(passphraseHash), []byte(passphrase))
ok = err == nil
// first try bcrypt (although disabled if fips140 mode is enabled)
if strings.HasPrefix(passphraseHash, "$2a$") || strings.HasPrefix(passphraseHash, "$2b$") ||
strings.HasPrefix(passphraseHash, "$2y$") {
if fips140.Enabled() {
s.log.Warn().Str("username", username).Msg("htpasswd bcrypt failed since fips140 is enabled")
if err != nil && !errors.Is(err, bcrypt.ErrMismatchedHashAndPassword) {
// Log that user's hash has unsupported format. Better than silently return 401.
s.log.Warn().Err(err).Str("username", username).Msg("htpasswd bcrypt compare failed")
return false, present
}
err := bcrypt.CompareHashAndPassword([]byte(passphraseHash), []byte(passphrase))
if err != nil {
// Log that user's hash has unsupported format. Better than silently return 401.
s.log.Warn().Err(err).Str("username", username).Msg("htpasswd bcrypt compare failed")
return false, present
}
return true, present // success: bcrypt
}
return
var crypter cpass.Crypter
if strings.HasPrefix(passphraseHash, "$5$") { //nolint:gocritic // errorslint conflicts with gocritic:IfElseChain
crypter, ok = cpass.SHA256.CrypterFound(passphraseHash)
} else if strings.HasPrefix(passphraseHash, "$6$") {
crypter, ok = cpass.SHA512.CrypterFound(passphraseHash)
} else {
s.log.Warn().Str("username", username).Msg("htpasswd entry has unsupported hash type")
return false, present
}
if !ok {
s.log.Warn().Str("username", username).Msg("htpasswd entry parsing failed")
return false, present
}
if !crypter.Verify([]byte(passphrase)) {
s.log.Warn().Str("username", username).Msg("htpasswd sha compare failed")
return false, present
}
return true, present // success: sha
}
// HTPasswdWatcher helper which triggers htpasswd reload on file change event.
+15 -14
View File
@@ -19,7 +19,7 @@ func TestHTPasswdWatcherOriginal(t *testing.T) {
username, _ := test.GenerateRandomString()
password1, _ := test.GenerateRandomString()
password2, _ := test.GenerateRandomString()
htpasswdPath := test.MakeHtpasswdFileFromString(test.GetCredString(username, password1))
htpasswdPath := test.MakeHtpasswdFileFromString(test.GetBcryptCredString(username, password1))
defer os.Remove(htpasswdPath)
@@ -49,7 +49,7 @@ func TestHTPasswdWatcherOriginal(t *testing.T) {
So(present, ShouldBeTrue)
// 2. Change file
err = os.WriteFile(htpasswdPath, []byte(test.GetCredString(username, password2)), 0o600)
err = os.WriteFile(htpasswdPath, []byte(test.GetBcryptCredString(username, password2)), 0o600)
So(err, ShouldBeNil)
// 3. Give some time for the background task
@@ -98,8 +98,8 @@ func TestHTPasswdWatcher(t *testing.T) {
username2, _ := test.GenerateRandomString()
password2, _ := test.GenerateRandomString()
htpasswdPath1 := test.MakeHtpasswdFileFromString(test.GetCredString(username1, password1))
htpasswdPath2 := test.MakeHtpasswdFileFromString(test.GetCredString(username2, password2))
htpasswdPath1 := test.MakeHtpasswdFileFromString(test.GetBcryptCredString(username1, password1))
htpasswdPath2 := test.MakeHtpasswdFileFromString(test.GetBcryptCredString(username2, password2))
defer os.Remove(htpasswdPath1)
defer os.Remove(htpasswdPath2)
@@ -150,7 +150,7 @@ func TestHTPasswdWatcher(t *testing.T) {
So(present, ShouldBeTrue)
// Change file content and verify automatic reload
err = os.WriteFile(htpasswdPath1, []byte(test.GetCredString(username1, password2)), 0o600)
err = os.WriteFile(htpasswdPath1, []byte(test.GetBcryptCredString(username1, password2)), 0o600)
So(err, ShouldBeNil)
time.Sleep(100 * time.Millisecond)
ok, present = htp.Authenticate(username1, password2)
@@ -158,7 +158,8 @@ func TestHTPasswdWatcher(t *testing.T) {
So(present, ShouldBeTrue)
// Test multiple users
multiUserContent := test.GetCredString(username1, password1) + "\n" + test.GetCredString(username2, password2)
multiUserContent := test.GetBcryptCredString(username1, password1) +
"\n" + test.GetBcryptCredString(username2, password2)
err = os.WriteFile(htpasswdPath1, []byte(multiUserContent), 0o600)
So(err, ShouldBeNil)
time.Sleep(100 * time.Millisecond)
@@ -194,8 +195,8 @@ func TestHTPasswdWatcher(t *testing.T) {
username2, _ := test.GenerateRandomString()
password2, _ := test.GenerateRandomString()
htpasswdPath1 := test.MakeHtpasswdFileFromString(test.GetCredString(username1, password1))
htpasswdPath2 := test.MakeHtpasswdFileFromString(test.GetCredString(username2, password2))
htpasswdPath1 := test.MakeHtpasswdFileFromString(test.GetBcryptCredString(username1, password1))
htpasswdPath2 := test.MakeHtpasswdFileFromString(test.GetBcryptCredString(username2, password2))
defer os.Remove(htpasswdPath1)
defer os.Remove(htpasswdPath2)
@@ -236,7 +237,7 @@ func TestHTPasswdWatcher(t *testing.T) {
So(present, ShouldBeTrue)
// Test file rename (should not trigger reload)
htpasswdPath3 := test.MakeHtpasswdFileFromString(test.GetCredString(username1, password1))
htpasswdPath3 := test.MakeHtpasswdFileFromString(test.GetBcryptCredString(username1, password1))
defer os.Remove(htpasswdPath3)
err = htw.ChangeFile(htpasswdPath3)
So(err, ShouldBeNil)
@@ -302,8 +303,8 @@ func TestHTPasswdWatcher(t *testing.T) {
username2, _ := test.GenerateRandomString()
password2, _ := test.GenerateRandomString()
htpasswdPath1 := test.MakeHtpasswdFileFromString(test.GetCredString(username1, password1))
htpasswdPath2 := test.MakeHtpasswdFileFromString(test.GetCredString(username2, password2))
htpasswdPath1 := test.MakeHtpasswdFileFromString(test.GetBcryptCredString(username1, password1))
htpasswdPath2 := test.MakeHtpasswdFileFromString(test.GetBcryptCredString(username2, password2))
defer os.Remove(htpasswdPath1)
defer os.Remove(htpasswdPath2)
@@ -408,7 +409,7 @@ func TestHTPasswdWatcher(t *testing.T) {
// Test 2: File watching with fsnotify resources cleanup
username, _ := test.GenerateRandomString()
password, _ := test.GenerateRandomString()
htpasswdPath := test.MakeHtpasswdFileFromString(test.GetCredString(username, password))
htpasswdPath := test.MakeHtpasswdFileFromString(test.GetBcryptCredString(username, password))
defer os.Remove(htpasswdPath)
@@ -490,7 +491,7 @@ func TestHTPasswdWatcher(t *testing.T) {
So(test.WaitForLogMessages(logBuffer, "htpasswd watcher terminating...", 1, 5*time.Second), ShouldBeTrue)
// Test file with empty lines and comments
content := "\n\n" + test.GetCredString(username, password) + "\n# comment\n"
content := "\n\n" + test.GetBcryptCredString(username, password) + "\n# comment\n"
commentedPath := test.MakeHtpasswdFileFromString(content)
defer os.Remove(commentedPath)
@@ -520,7 +521,7 @@ func TestHTPasswdWatcher(t *testing.T) {
So(err, ShouldBeNil)
// Load some initial data
htpasswdPath := test.MakeHtpasswdFileFromString(test.GetCredString(username, password))
htpasswdPath := test.MakeHtpasswdFileFromString(test.GetBcryptCredString(username, password))
defer os.Remove(htpasswdPath)
// Load initial file (this will populate the store)
+1 -1
View File
@@ -46,7 +46,7 @@ func TestRoutes(t *testing.T) {
username, seedUser := test.GenerateRandomString()
password, seedPass := test.GenerateRandomString()
htpasswdPath := test.MakeHtpasswdFileFromString(test.GetCredString(username, password))
htpasswdPath := test.MakeHtpasswdFileFromString(test.GetBcryptCredString(username, password))
defer os.Remove(htpasswdPath)