totp-proxy: update to use new mctx/mcfg/mrun framework

This commit is contained in:
Brian Picciano 2019-01-24 22:05:17 -05:00
parent a00a268256
commit 79bf3d6f89

View File

@ -12,7 +12,6 @@ package main
*/ */
import ( import (
"context"
"net/http" "net/http"
"net/url" "net/url"
"time" "time"
@ -20,34 +19,38 @@ import (
"github.com/mediocregopher/mediocre-go-lib/m" "github.com/mediocregopher/mediocre-go-lib/m"
"github.com/mediocregopher/mediocre-go-lib/mcfg" "github.com/mediocregopher/mediocre-go-lib/mcfg"
"github.com/mediocregopher/mediocre-go-lib/mcrypto" "github.com/mediocregopher/mediocre-go-lib/mcrypto"
"github.com/mediocregopher/mediocre-go-lib/mctx"
"github.com/mediocregopher/mediocre-go-lib/mhttp" "github.com/mediocregopher/mediocre-go-lib/mhttp"
"github.com/mediocregopher/mediocre-go-lib/mlog" "github.com/mediocregopher/mediocre-go-lib/mlog"
"github.com/mediocregopher/mediocre-go-lib/mrand" "github.com/mediocregopher/mediocre-go-lib/mrand"
"github.com/mediocregopher/mediocre-go-lib/mrun"
"github.com/mediocregopher/mediocre-go-lib/mtime" "github.com/mediocregopher/mediocre-go-lib/mtime"
"github.com/pquerna/otp/totp" "github.com/pquerna/otp/totp"
) )
func main() { func main() {
cfg := mcfg.New() ctx := mctx.New()
secretStr := cfg.ParamString("secret", "", "String used to sign authentication tokens. If one isn't given a new one will be generated on each startup, invalidating all previous tokens.") logger := mlog.From(ctx)
cookieName := cfg.ParamString("cookie-name", "_totp_proxy", "String to use as the name for cookies") cookieName := mcfg.String(ctx, "cookie-name", "_totp_proxy", "String to use as the name for cookies")
cookieTimeout := cfg.ParamDuration("cookie-timeout", mtime.Duration{1 * time.Hour}, "Timeout for cookies") cookieTimeout := mcfg.Duration(ctx, "cookie-timeout", mtime.Duration{1 * time.Hour}, "Timeout for cookies")
proxyURL := cfg.ParamRequiredString("dst-url", "URL to proxy requests to. Only the scheme and host should be set.")
var userSecrets map[string]string var userSecrets map[string]string
cfg.ParamRequiredJSON("users", &userSecrets, "JSON object which maps usernames to their TOTP secret strings") mcfg.RequiredJSON(ctx, "users", &userSecrets, "JSON object which maps usernames to their TOTP secret strings")
var secret mcrypto.Secret var secret mcrypto.Secret
cfg.Start.Then(func(ctx context.Context) error { secretStr := mcfg.String(ctx, "secret", "", "String used to sign authentication tokens. If one isn't given a new one will be generated on each startup, invalidating all previous tokens.")
mrun.OnStart(ctx, func(mctx.Context) error {
if *secretStr == "" { if *secretStr == "" {
*secretStr = mrand.Hex(32) *secretStr = mrand.Hex(32)
} }
logger.Info("generating secret")
secret = mcrypto.NewSecret([]byte(*secretStr)) secret = mcrypto.NewSecret([]byte(*secretStr))
return nil return nil
}) })
proxyHandler := new(struct{ http.Handler }) proxyHandler := new(struct{ http.Handler })
cfg.Start.Then(func(ctx context.Context) error { proxyURL := mcfg.RequiredString(ctx, "dst-url", "URL to proxy requests to. Only the scheme and host should be set.")
mrun.OnStart(ctx, func(mctx.Context) error {
u, err := url.Parse(*proxyURL) u, err := url.Parse(*proxyURL)
if err != nil { if err != nil {
return err return err
@ -56,9 +59,8 @@ func main() {
return nil return nil
}) })
authLog := m.Log(cfg.Child("auth"))
authHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { authHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
authLog = authLog.WithKV(mlog.CtxKV(r.Context())) authLogger := logger.WithKV(mlog.CtxKV(r.Context()))
unauthorized := func() { unauthorized := func() {
w.Header().Add("WWW-Authenticate", "Basic") w.Header().Add("WWW-Authenticate", "Basic")
@ -76,7 +78,7 @@ func main() {
} }
if cookie, _ := r.Cookie(*cookieName); cookie != nil { if cookie, _ := r.Cookie(*cookieName); cookie != nil {
authLog.Debug("authenticating with cookie", mlog.KV{"cookie": cookie.String()}) authLogger.Debug("authenticating with cookie", mlog.KV{"cookie": cookie.String()})
var sig mcrypto.Signature var sig mcrypto.Signature
if err := sig.UnmarshalText([]byte(cookie.Value)); err == nil { if err := sig.UnmarshalText([]byte(cookie.Value)); err == nil {
err := mcrypto.VerifyString(secret, sig, "") err := mcrypto.VerifyString(secret, sig, "")
@ -88,7 +90,7 @@ func main() {
} }
if user, pass, ok := r.BasicAuth(); ok && pass != "" { if user, pass, ok := r.BasicAuth(); ok && pass != "" {
authLog.Debug("authenticating with user/pass", mlog.KV{ logger.Debug("authenticating with user/pass", mlog.KV{
"user": user, "user": user,
"pass": pass, "pass": pass,
}) })
@ -103,9 +105,6 @@ func main() {
unauthorized() unauthorized()
}) })
mhttp.CfgServer(cfg, authHandler) mhttp.MListenAndServe(ctx, authHandler)
if err := cfg.StartRun(context.Background(), m.CfgSource()); err != nil { m.Run(ctx)
mlog.Fatal("error during startup", mlog.ErrKV(err))
}
select {}
} }