Skip to content

Commit ecb3ef2

Browse files
committed
feat: secret and salt are now optionally configurable
1 parent 4b65659 commit ecb3ef2

File tree

6 files changed

+59
-8
lines changed

6 files changed

+59
-8
lines changed

config.go

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ type Config struct {
44
Hostname string
55
CookieScope string
66
Secret string
7+
Salt string
78
CertDir string
89
Hosts map[string]Host
910
Email string

go.mod

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,20 @@
11
module github.com/gnur/tobab
22

3-
go 1.14
3+
go 1.15
44

55
require (
66
github.com/BurntSushi/toml v0.3.1
77
github.com/caddyserver/certmagic v0.11.2
88
github.com/davecgh/go-spew v1.1.1
99
github.com/gorilla/handlers v1.5.0
1010
github.com/gorilla/mux v1.8.0
11+
github.com/kr/pretty v0.2.0 // indirect
1112
github.com/markbates/goth v1.64.2
1213
github.com/o1egl/paseto v1.0.0
1314
github.com/ryanuber/go-glob v1.0.0
1415
github.com/sirupsen/logrus v1.6.0
16+
github.com/stretchr/testify v1.6.1 // indirect
1517
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a
18+
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
19+
gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c // indirect
1620
)

go.sum

+9
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,8 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxv
185185
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
186186
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
187187
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
188+
github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs=
189+
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
188190
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
189191
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
190192
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
@@ -274,6 +276,8 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV
274276
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
275277
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
276278
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
279+
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
280+
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
277281
github.com/timewasted/linode v0.0.0-20160829202747-37e84520dcf7/go.mod h1:imsgLplxEC/etjIhdr3dNzV3JeT27LbVu5pYWm0JCBY=
278282
github.com/transip/gotransip/v6 v6.0.2/go.mod h1:pQZ36hWWRahCUXkFWlx9Hs711gLd8J4qdgLdRzmtY+g=
279283
github.com/uber-go/atomic v1.3.2/go.mod h1:/Ct5t2lcmbJ4OSe/waGBoaVvVqtO0bmtfVNex1PFV8g=
@@ -496,6 +500,8 @@ gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLks
496500
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
497501
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
498502
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
503+
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
504+
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
499505
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
500506
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
501507
gopkg.in/h2non/gock.v1 v1.0.15/go.mod h1:sX4zAkdYX1TRGJ2JY156cFspQn4yRWn6p9EMdODlynE=
@@ -512,6 +518,9 @@ gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
512518
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
513519
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
514520
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
521+
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
522+
gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c h1:grhR+C34yXImVGp7EzNk+DTIk+323eIUWOmEevy6bDo=
523+
gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
515524
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
516525
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
517526
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=

main.go

+29-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package main
22

33
import (
4+
"crypto/rand"
45
"fmt"
56
"net"
67
"net/http"
@@ -11,6 +12,7 @@ import (
1112

1213
"github.com/BurntSushi/toml"
1314
"github.com/caddyserver/certmagic"
15+
"github.com/gnur/tobab/muxlogger"
1416
"github.com/gorilla/handlers"
1517
"github.com/gorilla/mux"
1618
"github.com/sirupsen/logrus"
@@ -29,6 +31,10 @@ type Tobab struct {
2931

3032
func main() {
3133
logger := logrus.New()
34+
logger.SetFormatter(&logrus.TextFormatter{
35+
ForceColors: true,
36+
FullTimestamp: true,
37+
})
3238

3339
confLoc := os.Getenv("TOBAB_CONFIG")
3440
if confLoc == "" {
@@ -52,7 +58,28 @@ func main() {
5258
certmagic.DefaultACME.CA = certmagic.LetsEncryptStagingCA
5359
}
5460

55-
key := argon2.IDKey([]byte(cfg.Secret), salt, 4, 4*1024, 2, 32)
61+
//only use provided salt if it makes any sense at all
62+
//otherwise use the default salt, shouldn't be a problem
63+
if len(cfg.Salt) > 2 {
64+
salt = []byte(cfg.Salt)
65+
}
66+
67+
secret := []byte(cfg.Secret)
68+
//only use provided secret if is it provided
69+
if len(secret) < 1 {
70+
b := make([]byte, 32)
71+
_, err := rand.Read(b)
72+
if err != nil {
73+
logger.WithError(err).Fatal("unable to generate secure secret, please provide it in config")
74+
}
75+
secret = b
76+
}
77+
78+
//set secret that goth uses
79+
os.Setenv("SESSION_SECRET", string(secret))
80+
81+
//transform provided salt and secret into a 32 byte key that can be used by paseto
82+
key := argon2.IDKey(secret, salt, 4, 4*1024, 2, 32)
5683

5784
app := Tobab{
5885
key: key,
@@ -91,6 +118,7 @@ func main() {
91118
tobabRoutes := r.Host(app.config.Hostname).Subrouter()
92119
app.setupgoth(tobabRoutes)
93120

121+
r.Use(muxlogger.NewLogger(app.logger).Middleware)
94122
r.Use(handlers.CompressHandler)
95123
r.Use(app.getRBACMiddleware())
96124

middleware.go

+15-4
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,22 @@ func (app *Tobab) getRBACMiddleware() func(http.Handler) http.Handler {
1414

1515
h := r.Host
1616
u, err := app.extractUser(r)
17-
if err != nil {
18-
//this shouldn't happen
17+
if err != nil && err != ErrUnauthenticatedRequest {
18+
//this shouldn't happen unless someone tampered with a cookie manually
1919
app.logger.WithError(err).Error("Unable to extract user")
20+
//invalid cookie is present, delete it and force re-auth
21+
c := http.Cookie{
22+
Name: "X-Tobab-Token",
23+
Domain: app.config.CookieScope,
24+
SameSite: http.SameSiteLaxMode,
25+
Secure: true,
26+
HttpOnly: true,
27+
MaxAge: -1,
28+
Path: "/",
29+
}
30+
http.SetCookie(w, &c)
31+
http.Error(w, "bad request", http.StatusBadRequest)
32+
return
2033
}
2134
app.logger.WithFields(logrus.Fields{
2235
"host": h,
@@ -31,7 +44,6 @@ func (app *Tobab) getRBACMiddleware() func(http.Handler) http.Handler {
3144
Path: r.URL.String(),
3245
Scheme: "https",
3346
}
34-
app.logger.Info("should redirect")
3547
c := http.Cookie{
3648
Domain: app.config.CookieScope,
3749
Secure: true,
@@ -43,7 +55,6 @@ func (app *Tobab) getRBACMiddleware() func(http.Handler) http.Handler {
4355
http.SetCookie(w, &c)
4456
http.Redirect(w, r, app.fqdn, 302)
4557
} else {
46-
app.logger.Info("Should return 403")
4758
http.Error(w, "access denied", http.StatusUnauthorized)
4859
}
4960

paseto.go

-2
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ func (app *Tobab) extractUser(r *http.Request) (string, error) {
1818

1919
c, err := r.Cookie("X-Tobab-Token")
2020
if err != nil {
21-
app.logger.WithError(err).Error("unable to read cookie")
2221
return "", ErrUnauthenticatedRequest
2322
}
2423

@@ -36,7 +35,6 @@ func (app *Tobab) decryptToken(t string) (*paseto.JSONToken, error) {
3635
var footer string
3736
err := v2.Decrypt(t, app.key, &token, &footer)
3837
if err != nil {
39-
app.logger.WithError(err).Warning("Unable to parse cookie token")
4038
return nil, ErrInvalidToken
4139
}
4240
err = token.Validate()

0 commit comments

Comments
 (0)