Actually use the auth middleware for assets routes
This commit is contained in:
parent
8da42184eb
commit
3664286506
25
config.nix
25
config.nix
@ -1,14 +1,19 @@
|
||||
{
|
||||
runDir = "/tmp/mediocre-blog/run";
|
||||
dataDir = "/tmp/mediocre-blog/data";
|
||||
runDir = "/tmp/mediocre-blog/run";
|
||||
dataDir = "/tmp/mediocre-blog/data";
|
||||
|
||||
powSecret = "ssshhh";
|
||||
mlSMTPAddr = "";
|
||||
mlSMTPAuth = "";
|
||||
mlPublicURL = "http://localhost:4000";
|
||||
listenProto = "tcp";
|
||||
listenAddr = ":4000";
|
||||
powSecret = "ssshhh";
|
||||
mlSMTPAddr = "";
|
||||
mlSMTPAuth = "";
|
||||
mlPublicURL = "http://localhost:4000";
|
||||
listenProto = "tcp";
|
||||
listenAddr = ":4000";
|
||||
|
||||
# If empty then a derived static directory is used
|
||||
staticProxyURL = "http://127.0.0.1:4002";
|
||||
# If empty then a derived static directory is used
|
||||
staticProxyURL = "http://127.0.0.1:4002";
|
||||
|
||||
# password is "bar". This should definitely be changed for prod.
|
||||
apiAuthUsers = {
|
||||
"foo" = "$2a$13$0JdWlUfHc.3XimEMpEu1cuu6RodhUvzD9l7iiAqa4YkM3mcFV5Pxi";
|
||||
};
|
||||
}
|
||||
|
@ -32,6 +32,9 @@
|
||||
# listening
|
||||
export MEDIOCRE_BLOG_LISTEN_PROTO="${config.listenProto}"
|
||||
export MEDIOCRE_BLOG_LISTEN_ADDR="${config.listenAddr}"
|
||||
|
||||
# api
|
||||
export MEDIOCRE_BLOG_API_AUTH_USERS='${builtins.toJSON config.apiAuthUsers}'
|
||||
'';
|
||||
|
||||
build = buildGoModule {
|
||||
|
@ -54,6 +54,11 @@ type Params struct {
|
||||
// reverse-proxied there.
|
||||
StaticDir string
|
||||
StaticProxy *url.URL
|
||||
|
||||
// AuthUsers keys are usernames which are allowed to edit server-side data,
|
||||
// and the values are the password hash which accompanies those users. The
|
||||
// password hash must have been produced by NewPasswordHash.
|
||||
AuthUsers map[string]string
|
||||
}
|
||||
|
||||
// SetupCfg implement the cfg.Cfger interface.
|
||||
@ -176,6 +181,8 @@ func (a *api) handler() http.Handler {
|
||||
return h
|
||||
}
|
||||
|
||||
auther := NewAuther(a.params.AuthUsers)
|
||||
|
||||
mux := http.NewServeMux()
|
||||
|
||||
mux.Handle("/", staticHandler)
|
||||
@ -208,9 +215,13 @@ func (a *api) handler() http.Handler {
|
||||
v2Mux.Handle("/posts/", a.renderPostHandler())
|
||||
v2Mux.Handle("/assets/", http.StripPrefix("/assets",
|
||||
apiutil.MethodMux(map[string]http.Handler{
|
||||
"GET": a.getPostAssetHandler(),
|
||||
"POST": formMiddleware(a.postPostAssetHandler()),
|
||||
"DELETE": formMiddleware(a.deletePostAssetHandler()),
|
||||
"GET": a.getPostAssetHandler(),
|
||||
"POST": authMiddleware(auther,
|
||||
formMiddleware(a.postPostAssetHandler()),
|
||||
),
|
||||
"DELETE": authMiddleware(auther,
|
||||
formMiddleware(a.deletePostAssetHandler()),
|
||||
),
|
||||
}),
|
||||
))
|
||||
v2Mux.Handle("/", a.renderIndexHandler())
|
||||
|
@ -3,13 +3,14 @@ package api
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/mediocregopher/blog.mediocregopher.com/srv/api/apiutil"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
||||
// NewPasswordHash returns the hash of the given plaintext password, for use
|
||||
// with Auther.
|
||||
func NewPasswordHash(plaintext string) string {
|
||||
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(plaintext), 12)
|
||||
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(plaintext), 13)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@ -48,9 +49,10 @@ func (a *auther) Allowed(username, password string) bool {
|
||||
|
||||
func authMiddleware(auther Auther, h http.Handler) http.Handler {
|
||||
|
||||
respondUnauthorized := func(rw http.ResponseWriter) {
|
||||
respondUnauthorized := func(rw http.ResponseWriter, r *http.Request) {
|
||||
rw.Header().Set("WWW-Authenticate", `Basic realm="NOPE"`)
|
||||
rw.WriteHeader(http.StatusUnauthorized)
|
||||
apiutil.GetRequestLogger(r).WarnString(r.Context(), "unauthorized")
|
||||
}
|
||||
|
||||
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
|
||||
@ -58,12 +60,12 @@ func authMiddleware(auther Auther, h http.Handler) http.Handler {
|
||||
username, password, ok := r.BasicAuth()
|
||||
|
||||
if !ok {
|
||||
respondUnauthorized(rw)
|
||||
respondUnauthorized(rw, r)
|
||||
return
|
||||
}
|
||||
|
||||
if !auther.Allowed(username, password) {
|
||||
respondUnauthorized(rw)
|
||||
respondUnauthorized(rw, r)
|
||||
return
|
||||
}
|
||||
|
||||
|
23
srv/src/cmd/hash-password/main.go
Normal file
23
srv/src/cmd/hash-password/main.go
Normal file
@ -0,0 +1,23 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/mediocregopher/blog.mediocregopher.com/srv/api"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
fmt.Fprint(os.Stderr, "Password: ")
|
||||
|
||||
line, err := bufio.NewReader(os.Stdin).ReadString('\n')
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fmt.Println(api.NewPasswordHash(strings.TrimSpace(line)))
|
||||
}
|
@ -2,6 +2,7 @@ package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
@ -55,6 +56,8 @@ func main() {
|
||||
|
||||
pathPrefix := cfg.String("path-prefix", "", "Prefix which is optionally applied to all URL paths rendered by the blog")
|
||||
|
||||
apiAuthUsersStr := cfg.String("api-auth-users", "{}", "JSON object with usernames as values and password hashes (produced by the hash-password binary) as values. Denotes users which are able to edit server-side data")
|
||||
|
||||
// initialization
|
||||
err := cfg.Init(ctx)
|
||||
|
||||
@ -128,6 +131,11 @@ func main() {
|
||||
postStore := post.NewStore(postSQLDB)
|
||||
postAssetStore := post.NewAssetStore(postSQLDB)
|
||||
|
||||
var apiAuthUsers map[string]string
|
||||
if err := json.Unmarshal([]byte(*apiAuthUsersStr), &apiAuthUsers); err != nil {
|
||||
logger.Fatal(ctx, "unmarshaling -api-auth-users", err)
|
||||
}
|
||||
|
||||
apiParams.Logger = logger.WithNamespace("api")
|
||||
apiParams.PowManager = powMgr
|
||||
apiParams.PathPrefix = *pathPrefix
|
||||
@ -136,6 +144,7 @@ func main() {
|
||||
apiParams.MailingList = ml
|
||||
apiParams.GlobalRoom = chatGlobalRoom
|
||||
apiParams.UserIDCalculator = chatUserIDCalc
|
||||
apiParams.AuthUsers = apiAuthUsers
|
||||
|
||||
logger.Info(ctx, "listening")
|
||||
a, err := api.New(apiParams)
|
||||
|
Loading…
Reference in New Issue
Block a user