mirror of
https://github.com/project-zot/zot.git
synced 2026-06-17 21:17:58 +08:00
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:
committed by
GitHub
parent
aaba362b4f
commit
04ae0a9409
@@ -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
@@ -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
@@ -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
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ func TestTLSWithAuth(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)
|
||||
|
||||
conf.HTTP.Auth = &config.AuthConfig{
|
||||
|
||||
@@ -31,7 +31,7 @@ func TestConfigReloader(t *testing.T) {
|
||||
username := "alice"
|
||||
password := "alice"
|
||||
|
||||
htpasswdPath := test.MakeHtpasswdFileFromString(test.GetCredString(username, password))
|
||||
htpasswdPath := test.MakeHtpasswdFileFromString(test.GetBcryptCredString(username, password))
|
||||
defer os.Remove(htpasswdPath)
|
||||
|
||||
defer os.Remove(logFile.Name()) // clean up
|
||||
|
||||
@@ -28,8 +28,8 @@ func TestProfilingAuthz(t *testing.T) {
|
||||
password, seedPass := test.GenerateRandomString()
|
||||
authorizationAllRepos := test.AuthorizationAllRepos
|
||||
|
||||
testCreds := test.GetCredString(adminUsername, adminPassword) +
|
||||
test.GetCredString(username, password)
|
||||
testCreds := test.GetBcryptCredString(adminUsername, adminPassword) +
|
||||
test.GetBcryptCredString(username, password)
|
||||
htpasswdPath := test.MakeHtpasswdFileFromString(testCreds)
|
||||
|
||||
defer os.Remove(htpasswdPath)
|
||||
|
||||
@@ -743,7 +743,7 @@ func RunSignatureUploadAndVerificationTests(t *testing.T, cacheDriverParams map[
|
||||
Convey("Verify uploading cosign public keys with auth configured", func() {
|
||||
globalDir := t.TempDir()
|
||||
port := test.GetFreePort()
|
||||
testCreds := test.GetCredString("admin", "admin") + "\n" + test.GetCredString("test", "test")
|
||||
testCreds := test.GetBcryptCredString("admin", "admin") + "\n" + test.GetBcryptCredString("test", "test")
|
||||
|
||||
htpasswdPath := test.MakeHtpasswdFileFromString(testCreds)
|
||||
defer os.Remove(htpasswdPath)
|
||||
|
||||
@@ -143,7 +143,7 @@ func TestMgmtExtension(t *testing.T) {
|
||||
Convey("Verify mgmt auth info route enabled with htpasswd", t, func() {
|
||||
username, seedUser := test.GenerateRandomString()
|
||||
password, seedPass := test.GenerateRandomString()
|
||||
htpasswdPath := test.MakeHtpasswdFileFromString(test.GetCredString(username, password))
|
||||
htpasswdPath := test.MakeHtpasswdFileFromString(test.GetBcryptCredString(username, password))
|
||||
|
||||
defer func() {
|
||||
conf.HTTP.Auth.HTPasswd.Path = ""
|
||||
@@ -362,7 +362,7 @@ func TestMgmtExtension(t *testing.T) {
|
||||
Convey("Verify mgmt auth info route enabled with htpasswd + ldap", t, func() {
|
||||
username, seedUser := test.GenerateRandomString()
|
||||
password, seedPass := test.GenerateRandomString()
|
||||
htpasswdPath := test.MakeHtpasswdFileFromString(test.GetCredString(username, password))
|
||||
htpasswdPath := test.MakeHtpasswdFileFromString(test.GetBcryptCredString(username, password))
|
||||
|
||||
defer func() {
|
||||
conf.HTTP.Auth.HTPasswd.Path = ""
|
||||
@@ -448,7 +448,7 @@ func TestMgmtExtension(t *testing.T) {
|
||||
Convey("Verify mgmt auth info route enabled with htpasswd + ldap + bearer", t, func() {
|
||||
username, seedUser := test.GenerateRandomString()
|
||||
password, seedPass := test.GenerateRandomString()
|
||||
htpasswdPath := test.MakeHtpasswdFileFromString(test.GetCredString(username, password))
|
||||
htpasswdPath := test.MakeHtpasswdFileFromString(test.GetBcryptCredString(username, password))
|
||||
|
||||
defer func() {
|
||||
conf.HTTP.Auth.HTPasswd.Path = ""
|
||||
@@ -734,7 +734,7 @@ func TestMgmtExtension(t *testing.T) {
|
||||
Convey("Verify mgmt auth info route enabled with empty openID provider list", t, func() {
|
||||
username, seedUser := test.GenerateRandomString()
|
||||
password, seedPass := test.GenerateRandomString()
|
||||
htpasswdPath := test.MakeHtpasswdFileFromString(test.GetCredString(username, password))
|
||||
htpasswdPath := test.MakeHtpasswdFileFromString(test.GetBcryptCredString(username, password))
|
||||
|
||||
defer func() {
|
||||
conf.HTTP.Auth.HTPasswd.Path = ""
|
||||
|
||||
@@ -171,7 +171,7 @@ func TestMetricsAuthentication(t *testing.T) {
|
||||
password := generateRandomString()
|
||||
metricsuser := generateRandomString()
|
||||
metricspass := generateRandomString()
|
||||
content := test.GetCredString(username, password) + "\n" + test.GetCredString(metricsuser, metricspass)
|
||||
content := test.GetBcryptCredString(username, password) + "\n" + test.GetBcryptCredString(metricsuser, metricspass)
|
||||
|
||||
htpasswdPath := test.MakeHtpasswdFileFromString(content)
|
||||
defer os.Remove(htpasswdPath)
|
||||
@@ -236,7 +236,7 @@ func TestMetricsAuthorization(t *testing.T) {
|
||||
password := generateRandomString()
|
||||
metricsuser := generateRandomString()
|
||||
metricspass := generateRandomString()
|
||||
content := test.GetCredString(username, password) + "\n" + test.GetCredString(metricsuser, metricspass)
|
||||
content := test.GetBcryptCredString(username, password) + "\n" + test.GetBcryptCredString(metricsuser, metricspass)
|
||||
|
||||
htpasswdPath := test.MakeHtpasswdFileFromString(content)
|
||||
defer os.Remove(htpasswdPath)
|
||||
|
||||
@@ -424,7 +424,7 @@ func TestCVESearchDisabled(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)
|
||||
|
||||
conf.HTTP.Auth = &config.AuthConfig{
|
||||
@@ -493,7 +493,7 @@ func TestCVESearch(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)
|
||||
|
||||
dbDir, err := testSetup(t)
|
||||
|
||||
@@ -40,8 +40,8 @@ func TestUserData(t *testing.T) {
|
||||
simpleUser := "test"
|
||||
simpleUserPassword := "test123"
|
||||
|
||||
content := test.GetCredString(adminUser, adminPassword) +
|
||||
test.GetCredString(simpleUser, simpleUserPassword)
|
||||
content := test.GetBcryptCredString(adminUser, adminPassword) +
|
||||
test.GetBcryptCredString(simpleUser, simpleUserPassword)
|
||||
|
||||
htpasswdPath := test.MakeHtpasswdFileFromString(content)
|
||||
defer os.Remove(htpasswdPath)
|
||||
@@ -455,7 +455,7 @@ func TestChangingRepoState(t *testing.T) {
|
||||
forbiddenRepo := "forbidden"
|
||||
accesibleRepo := "accesible"
|
||||
|
||||
htpasswdPath := test.MakeHtpasswdFileFromString(test.GetCredString(simpleUser, simpleUserPassword))
|
||||
htpasswdPath := test.MakeHtpasswdFileFromString(test.GetBcryptCredString(simpleUser, simpleUserPassword))
|
||||
defer os.Remove(htpasswdPath)
|
||||
|
||||
conf := config.New()
|
||||
@@ -606,7 +606,7 @@ func TestGlobalSearchWithUserPrefFiltering(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)
|
||||
|
||||
conf.HTTP.Auth = &config.AuthConfig{
|
||||
@@ -801,7 +801,7 @@ func TestExpandedRepoInfoWithUserPrefs(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)
|
||||
|
||||
conf.HTTP.Auth = &config.AuthConfig{
|
||||
|
||||
@@ -137,7 +137,7 @@ func makeUpstreamServer(
|
||||
|
||||
var htpasswdPath string
|
||||
if basicAuth {
|
||||
htpasswdPath = test.MakeHtpasswdFileFromString(test.GetCredString(username, password))
|
||||
htpasswdPath = test.MakeHtpasswdFileFromString(test.GetBcryptCredString(username, password))
|
||||
srcConfig.HTTP.Auth = &config.AuthConfig{
|
||||
HTPasswd: config.AuthHTPasswd{
|
||||
Path: htpasswdPath,
|
||||
|
||||
+1
-1
@@ -53,7 +53,7 @@ func TestAuditLogMessages(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)
|
||||
|
||||
|
||||
+85
-1
@@ -2,6 +2,8 @@ package common
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
@@ -12,6 +14,9 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/GehirnInc/crypt"
|
||||
_ "github.com/GehirnInc/crypt/sha256_crypt"
|
||||
_ "github.com/GehirnInc/crypt/sha512_crypt"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
||||
@@ -213,7 +218,7 @@ func ReadLogFileAndCountStringOccurence(logPath string, stringToMatch string,
|
||||
}
|
||||
}
|
||||
|
||||
func GetCredString(username, password string) string {
|
||||
func GetBcryptCredString(username, password string) string {
|
||||
hash, err := bcrypt.GenerateFromPassword([]byte(password), 10)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
@@ -224,6 +229,85 @@ func GetCredString(username, password string) string {
|
||||
return usernameAndHash
|
||||
}
|
||||
|
||||
const (
|
||||
PrefixCryptSha256 = "$5$"
|
||||
PrefixCryptSha512 = "$6$"
|
||||
Separator = "$"
|
||||
)
|
||||
|
||||
// generateSecureRandomString should only be used in tests with length = 16.
|
||||
func generateSecureRandomString(length int) (string, error) {
|
||||
bytes := make([]byte, length)
|
||||
|
||||
_, err := rand.Read(bytes)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return base64.URLEncoding.EncodeToString(bytes)[:length], nil
|
||||
}
|
||||
|
||||
func shaCrypt(password string, rounds string, salt string, prefix string) string {
|
||||
var ret string
|
||||
|
||||
var strb strings.Builder
|
||||
|
||||
strb.WriteString(prefix)
|
||||
|
||||
if len(rounds) > 0 {
|
||||
strb.WriteString(rounds)
|
||||
strb.WriteString(Separator)
|
||||
}
|
||||
|
||||
strb.WriteString(salt)
|
||||
totalSalt := strb.String()
|
||||
|
||||
var err error
|
||||
|
||||
switch prefix {
|
||||
case PrefixCryptSha256:
|
||||
crypter := crypt.SHA256.New()
|
||||
ret, err = crypter.Generate([]byte(password), []byte(totalSalt))
|
||||
case PrefixCryptSha512:
|
||||
crypter := crypt.SHA512.New()
|
||||
ret, err = crypter.Generate([]byte(password), []byte(totalSalt))
|
||||
default:
|
||||
panic("unsupported password hash")
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
func GetSHA256CredString(username, password string) string {
|
||||
saltstr, err := generateSecureRandomString(16)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
hash := shaCrypt(password, "rounds=5000", saltstr, PrefixCryptSha256)
|
||||
|
||||
usernameAndHash := fmt.Sprintf("%s:%s\n", username, hash)
|
||||
|
||||
return usernameAndHash
|
||||
}
|
||||
|
||||
func GetSHA512CredString(username, password string) string {
|
||||
saltstr, err := generateSecureRandomString(16)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
hash := shaCrypt(password, "rounds=5000", saltstr, PrefixCryptSha512)
|
||||
|
||||
usernameAndHash := fmt.Sprintf("%s:%s\n", username, hash)
|
||||
|
||||
return usernameAndHash
|
||||
}
|
||||
|
||||
func MakeHtpasswdFileFromString(fileContent string) string {
|
||||
htpasswdFile, err := os.CreateTemp("", "htpasswd-")
|
||||
if err != nil {
|
||||
|
||||
@@ -268,8 +268,8 @@ func TestGetProjectRootDir(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestGetCredString(t *testing.T) {
|
||||
Convey("GetCredString panics", t, func() {
|
||||
func TestGetBcryptCredString(t *testing.T) {
|
||||
Convey("GetBcryptCredString panics", t, func() {
|
||||
passwordSize := 100
|
||||
pass := make([]byte, passwordSize)
|
||||
|
||||
@@ -277,7 +277,7 @@ func TestGetCredString(t *testing.T) {
|
||||
pass[i] = 'Y'
|
||||
}
|
||||
|
||||
f := func() { tcommon.GetCredString("testUser", string(pass)) }
|
||||
f := func() { tcommon.GetBcryptCredString("testUser", string(pass)) }
|
||||
So(f, ShouldPanicWith, bcrypt.ErrPasswordTooLong)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -178,7 +178,7 @@ func TestUploadImage(t *testing.T) {
|
||||
|
||||
user1 := "test"
|
||||
password1 := "test"
|
||||
testString1 := tcommon.GetCredString(user1, password1)
|
||||
testString1 := tcommon.GetBcryptCredString(user1, password1)
|
||||
|
||||
htpasswdPath := tcommon.MakeHtpasswdFileFromString(testString1)
|
||||
defer os.Remove(htpasswdPath)
|
||||
@@ -495,7 +495,7 @@ func TestInjectUploadImageWithBasicAuth(t *testing.T) {
|
||||
|
||||
user := "user"
|
||||
password := "password"
|
||||
testString := tcommon.GetCredString(user, password)
|
||||
testString := tcommon.GetBcryptCredString(user, password)
|
||||
|
||||
htpasswdPath := tcommon.MakeHtpasswdFileFromString(testString)
|
||||
defer os.Remove(htpasswdPath)
|
||||
|
||||
Reference in New Issue
Block a user