feat(security)!: Remove deprecated SHA512 parameter for password hashing

This commit is contained in:
TwiN 2022-06-14 23:48:28 -04:00
parent 6f3150d936
commit c873b0ba0c
7 changed files with 5 additions and 96 deletions

View File

@ -1210,7 +1210,7 @@ endpoints:
t.Errorf("config.Security.Basic.Username should've been %s, but was %s", expectedUsername, config.Security.Basic.Username) t.Errorf("config.Security.Basic.Username should've been %s, but was %s", expectedUsername, config.Security.Basic.Username)
} }
if config.Security.Basic.PasswordBcryptHashBase64Encoded != expectedPasswordHash { if config.Security.Basic.PasswordBcryptHashBase64Encoded != expectedPasswordHash {
t.Errorf("config.Security.Basic.PasswordBcryptHashBase64Encoded should've been %s, but was %s", expectedPasswordHash, config.Security.Basic.PasswordSha512Hash) t.Errorf("config.Security.Basic.PasswordBcryptHashBase64Encoded should've been %s, but was %s", expectedPasswordHash, config.Security.Basic.PasswordBcryptHashBase64Encoded)
} }
} }

View File

@ -1,17 +1,10 @@
package security package security
import "log"
// BasicConfig is the configuration for Basic authentication // BasicConfig is the configuration for Basic authentication
type BasicConfig struct { type BasicConfig struct {
// Username is the name which will need to be used for a successful authentication // Username is the name which will need to be used for a successful authentication
Username string `yaml:"username"` Username string `yaml:"username"`
// PasswordSha512Hash is the SHA512 hash of the password which will need to be used for a successful authentication
// XXX: Remove this on v4.0.0
// Deprecated: Use PasswordBcryptHashBase64Encoded instead
PasswordSha512Hash string `yaml:"password-sha512"`
// PasswordBcryptHashBase64Encoded is the base64 encoded string of the Bcrypt hash of the password to use to // PasswordBcryptHashBase64Encoded is the base64 encoded string of the Bcrypt hash of the password to use to
// authenticate using basic auth. // authenticate using basic auth.
PasswordBcryptHashBase64Encoded string `yaml:"password-bcrypt-base64"` PasswordBcryptHashBase64Encoded string `yaml:"password-bcrypt-base64"`
@ -19,8 +12,5 @@ type BasicConfig struct {
// isValid returns whether the basic security configuration is valid or not // isValid returns whether the basic security configuration is valid or not
func (c *BasicConfig) isValid() bool { func (c *BasicConfig) isValid() bool {
if len(c.PasswordSha512Hash) > 0 { return len(c.Username) > 0 && len(c.PasswordBcryptHashBase64Encoded) > 0
log.Println("WARNING: security.basic.password-sha512 has been deprecated in favor of security.basic.password-bcrypt-base64")
}
return len(c.Username) > 0 && (len(c.PasswordSha512Hash) == 128 || len(c.PasswordBcryptHashBase64Encoded) > 0)
} }

View File

@ -2,26 +2,6 @@ package security
import "testing" import "testing"
func TestBasicConfig_IsValidUsingSHA512(t *testing.T) {
basicConfig := &BasicConfig{
Username: "admin",
PasswordSha512Hash: Sha512("test"),
}
if !basicConfig.isValid() {
t.Error("basicConfig should've been valid")
}
}
func TestBasicConfig_IsValidWhenPasswordIsInvalidUsingSHA512(t *testing.T) {
basicConfig := &BasicConfig{
Username: "admin",
PasswordSha512Hash: "",
}
if basicConfig.isValid() {
t.Error("basicConfig shouldn't have been valid")
}
}
func TestBasicConfig_IsValidUsingBcrypt(t *testing.T) { func TestBasicConfig_IsValidUsingBcrypt(t *testing.T) {
basicConfig := &BasicConfig{ basicConfig := &BasicConfig{
Username: "admin", Username: "admin",

View File

@ -3,7 +3,6 @@ package security
import ( import (
"encoding/base64" "encoding/base64"
"net/http" "net/http"
"strings"
"github.com/TwiN/g8" "github.com/TwiN/g8"
"github.com/gorilla/mux" "github.com/gorilla/mux"
@ -82,13 +81,6 @@ func (c *Config) ApplySecurityMiddleware(api *mux.Router) error {
_, _ = w.Write([]byte("Unauthorized")) _, _ = w.Write([]byte("Unauthorized"))
return return
} }
} else if len(c.Basic.PasswordSha512Hash) > 0 {
if !ok || usernameEntered != c.Basic.Username || Sha512(passwordEntered) != strings.ToLower(c.Basic.PasswordSha512Hash) {
w.Header().Set("WWW-Authenticate", "Basic")
w.WriteHeader(http.StatusUnauthorized)
_, _ = w.Write([]byte("Unauthorized"))
return
}
} }
handler.ServeHTTP(w, r) handler.ServeHTTP(w, r)
}) })

View File

@ -23,10 +23,10 @@ func TestConfig_ApplySecurityMiddleware(t *testing.T) {
/////////// ///////////
// BASIC // // BASIC //
/////////// ///////////
// SHA512 (DEPRECATED) // Bcrypt
c := &Config{Basic: &BasicConfig{ c := &Config{Basic: &BasicConfig{
Username: "john.doe", Username: "john.doe",
PasswordSha512Hash: "6b97ed68d14eb3f1aa959ce5d49c7dc612e1eb1dafd73b1e705847483fd6a6c809f2ceb4e8df6ff9984c6298ff0285cace6614bf8daa9f0070101b6c89899e22", PasswordBcryptHashBase64Encoded: "JDJhJDA4JDFoRnpPY1hnaFl1OC9ISlFsa21VS09wOGlPU1ZOTDlHZG1qeTFvb3dIckRBUnlHUmNIRWlT",
}} }}
api := mux.NewRouter() api := mux.NewRouter()
api.HandleFunc("/test", func(w http.ResponseWriter, r *http.Request) { api.HandleFunc("/test", func(w http.ResponseWriter, r *http.Request) {
@ -50,33 +50,6 @@ func TestConfig_ApplySecurityMiddleware(t *testing.T) {
if responseRecorder.Code != http.StatusOK { if responseRecorder.Code != http.StatusOK {
t.Error("expected code to be 200, but was", responseRecorder.Code) t.Error("expected code to be 200, but was", responseRecorder.Code)
} }
// Bcrypt
c = &Config{Basic: &BasicConfig{
Username: "john.doe",
PasswordBcryptHashBase64Encoded: "JDJhJDA4JDFoRnpPY1hnaFl1OC9ISlFsa21VS09wOGlPU1ZOTDlHZG1qeTFvb3dIckRBUnlHUmNIRWlT",
}}
api = mux.NewRouter()
api.HandleFunc("/test", func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
})
if err := c.ApplySecurityMiddleware(api); err != nil {
t.Error("expected no error, but was", err)
}
// Try to access the route without basic auth
request, _ = http.NewRequest("GET", "/test", http.NoBody)
responseRecorder = httptest.NewRecorder()
api.ServeHTTP(responseRecorder, request)
if responseRecorder.Code != http.StatusUnauthorized {
t.Error("expected code to be 401, but was", responseRecorder.Code)
}
// Try again, but with basic auth
request, _ = http.NewRequest("GET", "/test", http.NoBody)
responseRecorder = httptest.NewRecorder()
request.SetBasicAuth("john.doe", "hunter2")
api.ServeHTTP(responseRecorder, request)
if responseRecorder.Code != http.StatusOK {
t.Error("expected code to be 200, but was", responseRecorder.Code)
}
////////// //////////
// OIDC // // OIDC //
////////// //////////

View File

@ -1,14 +0,0 @@
package security
import (
"crypto/sha512"
"fmt"
)
// Sha512 hashes a provided string using SHA512 and returns the resulting hash as a string
// Deprecated: Use bcrypt instead
func Sha512(s string) string {
hash := sha512.New()
hash.Write([]byte(s))
return fmt.Sprintf("%x", hash.Sum(nil))
}

View File

@ -1,12 +0,0 @@
package security
import "testing"
func TestSha512(t *testing.T) {
input := "password"
expectedHash := "b109f3bbbc244eb82441917ed06d618b9008dd09b3befd1b5e07394c706a8bb980b1d7785e5976ec049b46df5f1326af5a2ea6d103fd07c95385ffab0cacbc86"
hash := Sha512(input)
if hash != expectedHash {
t.Errorf("Expected hash to be '%s', but was '%s'", expectedHash, hash)
}
}