-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
## 📝 Summary Enables basic auth support for API requests. The basic auth password is configurable through API and/or file. If set via API, the salted hash is stored in the file to persist across reboots. Config-file updates: ```toml [general] # HTTP Basic Auth basic_auth_secret_path = "basic-auth-secret.txt" # basic auth is supported if a path is provided basic_auth_secret_salt = "D;%yL9TS:5PalS/d" # use a random string for the salt ``` `basic_auth_secret_path` specifies the file to store the salted, hashed secret in. It's loaded (or created) on startup. - if the file is not empty, API requests need to include a http basic auth password that matches that sha256 hash (user `admin`) - if empty, no authentication is required for API requests until secret is configured through API or file. if `/api/v1/set-basic-auth` is called, it uses the payload as secret (immediately) and writes the hash of the secret it to the file (for reuse across restarts). - if file does not exist, it is created (empty) Only the salted SHA256 hash of the password is stored, both in the file as well as in memory. The secret can be overwritten (updated) via API call, if the request provides the previous http basic auth secret. Also added tests and updated the README. --- ## ✅ I have run these commands * [x] `make lint` * [x] `make test` * [x] `go mod tidy`
- Loading branch information
Showing
8 changed files
with
405 additions
and
52 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,4 +21,5 @@ | |
/build | ||
/cert.pem | ||
/key.pem | ||
/pipe.fifo | ||
/pipe.fifo | ||
/basic-auth-secret.txt |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,23 @@ | ||
[general] | ||
listen_addr = "0.0.0.0:3535" | ||
pipe_file = "pipe.fifo" | ||
pprof = true | ||
log_json = false | ||
log_debug = true | ||
|
||
# HTTP Basic Auth | ||
basic_auth_secret_path = "basic-auth-secret.txt" # basic auth is supported if a path is provided | ||
basic_auth_secret_salt = "D;%yL9TS:5PalS/d" # use a random string for the salt | ||
|
||
# HTTP server timeouts | ||
# http_read_timeout_ms = 2500 | ||
# http_write_timeout_ms = 2500 | ||
|
||
[actions] | ||
echo_test = "echo test" | ||
# reboot = "reboot" | ||
# rbuilder_restart = "/etc/init.d/rbuilder restart" | ||
# rbuilder_stop = "/etc/init.d/rbuilder stop" | ||
echo_test = "echo test" | ||
|
||
[file_uploads] | ||
testfile = "/tmp/testfile.txt" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
package systemapi | ||
|
||
import ( | ||
"crypto/sha256" | ||
"crypto/subtle" | ||
"encoding/hex" | ||
"fmt" | ||
"net/http" | ||
) | ||
|
||
// BasicAuth implements a simple middleware handler for adding basic http auth to a route. | ||
func BasicAuth(realm, salt string, getHashedCredentials func() map[string]string) func(next http.Handler) http.Handler { | ||
return func(next http.Handler) http.Handler { | ||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | ||
// Loading credentials dynamically because they can be updated at runtime | ||
hashedCredentials := getHashedCredentials() | ||
|
||
// If no credentials are set, just pass through (unauthenticated) | ||
if len(hashedCredentials) == 0 { | ||
next.ServeHTTP(w, r) | ||
return | ||
} | ||
|
||
// Load credentials from request | ||
user, pass, ok := r.BasicAuth() | ||
if !ok { | ||
basicAuthFailed(w, realm) | ||
return | ||
} | ||
|
||
// Hash the password and see if credentials are allowed | ||
h := sha256.New() | ||
h.Write([]byte(pass)) | ||
h.Write([]byte(salt)) | ||
userPassHash := hex.EncodeToString(h.Sum(nil)) | ||
|
||
// Compare to allowed credentials | ||
credPassHash, credUserOk := hashedCredentials[user] | ||
if !credUserOk || subtle.ConstantTimeCompare([]byte(userPassHash), []byte(credPassHash)) != 1 { | ||
basicAuthFailed(w, realm) | ||
return | ||
} | ||
|
||
next.ServeHTTP(w, r) | ||
}) | ||
} | ||
} | ||
|
||
func basicAuthFailed(w http.ResponseWriter, realm string) { | ||
w.Header().Add("WWW-Authenticate", fmt.Sprintf(`Basic realm="%s"`, realm)) | ||
w.WriteHeader(http.StatusUnauthorized) | ||
} |
Oops, something went wrong.