From 7a5ac9caa0287057f57ce476e064022ab7d410ec Mon Sep 17 00:00:00 2001 From: Brian Picciano Date: Mon, 17 Jun 2019 18:18:50 -0400 Subject: [PATCH] totp-proxy: refactor to use new Component logic --- cmd/totp-proxy/main.go | 40 ++++++++++++++++++++++++++-------------- m/m.go | 1 + mlog/cmp.go | 5 +++++ 3 files changed, 32 insertions(+), 14 deletions(-) diff --git a/cmd/totp-proxy/main.go b/cmd/totp-proxy/main.go index 74ef351..2256f1c 100644 --- a/cmd/totp-proxy/main.go +++ b/cmd/totp-proxy/main.go @@ -21,6 +21,7 @@ import ( "github.com/mediocregopher/mediocre-go-lib/mcfg" "github.com/mediocregopher/mediocre-go-lib/mcrypto" "github.com/mediocregopher/mediocre-go-lib/mctx" + "github.com/mediocregopher/mediocre-go-lib/merr" "github.com/mediocregopher/mediocre-go-lib/mhttp" "github.com/mediocregopher/mediocre-go-lib/mlog" "github.com/mediocregopher/mediocre-go-lib/mrand" @@ -30,30 +31,39 @@ import ( ) func main() { - ctx := m.ServiceContext() - ctx, cookieName := mcfg.WithString(ctx, "cookie-name", "_totp_proxy", "String to use as the name for cookies") - ctx, cookieTimeout := mcfg.WithDuration(ctx, "cookie-timeout", mtime.Duration{1 * time.Hour}, "Timeout for cookies") + cmp := m.RootServiceComponent() + cookieName := mcfg.String(cmp, "cookie-name", + mcfg.ParamDefault("_totp_proxy"), + mcfg.ParamUsage("String to use as the name for cookies")) + cookieTimeout := mcfg.Duration(cmp, "cookie-timeout", + mcfg.ParamDefault(mtime.Duration{1 * time.Hour}), + mcfg.ParamUsage("Timeout for cookies")) var userSecrets map[string]string - ctx = mcfg.WithRequiredJSON(ctx, "users", &userSecrets, "JSON object which maps usernames to their TOTP secret strings") + mcfg.JSON(cmp, "users", &userSecrets, + mcfg.ParamRequired(), + mcfg.ParamUsage("JSON object which maps usernames to their TOTP secret strings")) var secret mcrypto.Secret - ctx, secretStr := mcfg.WithString(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.") - ctx = mrun.WithStartHook(ctx, func(context.Context) error { + secretStr := mcfg.String(cmp, "secret", + mcfg.ParamUsage("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.InitHook(cmp, func(context.Context) error { if *secretStr == "" { *secretStr = mrand.Hex(32) } - mlog.Info("generating secret", ctx) + mlog.From(cmp).Info("generating secret") secret = mcrypto.NewSecret([]byte(*secretStr)) return nil }) proxyHandler := new(struct{ http.Handler }) - ctx, proxyURL := mcfg.WithRequiredString(ctx, "dst-url", "URL to proxy requests to. Only the scheme and host should be set.") - ctx = mrun.WithStartHook(ctx, func(context.Context) error { + proxyURL := mcfg.String(cmp, "dst-url", + mcfg.ParamRequired(), + mcfg.ParamUsage("URL to proxy requests to. Only the scheme and host should be set.")) + mrun.InitHook(cmp, func(context.Context) error { u, err := url.Parse(*proxyURL) if err != nil { - return err + return merr.Wrap(err, cmp.Context()) } proxyHandler.Handler = mhttp.ReverseProxy(u) return nil @@ -64,11 +74,13 @@ func main() { ctx := r.Context() unauthorized := func() { + mlog.From(cmp).Debug("connection is unauthorized") w.Header().Add("WWW-Authenticate", "Basic") w.WriteHeader(http.StatusUnauthorized) } authorized := func() { + mlog.From(cmp).Debug("connection is authorized, rewriting cookies") sig := mcrypto.SignString(secret, "") http.SetCookie(w, &http.Cookie{ Name: *cookieName, @@ -79,7 +91,7 @@ func main() { } if cookie, _ := r.Cookie(*cookieName); cookie != nil { - mlog.Debug("authenticating with cookie", + mlog.From(cmp).Debug("authenticating with cookie", mctx.Annotate(ctx, "cookie", cookie.String())) var sig mcrypto.Signature if err := sig.UnmarshalText([]byte(cookie.Value)); err == nil { @@ -92,7 +104,7 @@ func main() { } if user, pass, ok := r.BasicAuth(); ok && pass != "" { - mlog.Debug("authenticating with user", + mlog.From(cmp).Debug("authenticating with user", mctx.Annotate(ctx, "user", user)) if userSecret, ok := userSecrets[user]; ok { if totp.Validate(pass, userSecret) { @@ -105,6 +117,6 @@ func main() { unauthorized() }) - ctx, _ = mhttp.WithListeningServer(ctx, authHandler) - m.StartWaitStop(ctx) + mhttp.InstListeningServer(cmp, authHandler) + m.Exec(cmp) } diff --git a/m/m.go b/m/m.go index 6674df1..eb7c0ba 100644 --- a/m/m.go +++ b/m/m.go @@ -76,6 +76,7 @@ func RootComponent() *mcmp.Component { mctx.Annotated("log-level", *logLevelStr)) } logger.SetMaxLevel(logLevel) + mlog.SetLogger(cmp, logger) return nil }) diff --git a/mlog/cmp.go b/mlog/cmp.go index 302e232..3c1e41d 100644 --- a/mlog/cmp.go +++ b/mlog/cmp.go @@ -9,6 +9,11 @@ type cmpKey int // SetLogger sets the given logger onto the Component. The logger can later be // retrieved from the Component, or any of its children, using From. +// +// NOTE that if a Logger is set onto a Component and then changed, even though +// the Logger is a pointer and so is changed within the Component, SetLogger +// should still be called. This is due to some caching that From does for +// performance. func SetLogger(cmp *mcmp.Component, l *Logger) { cmp.SetValue(cmpKey(0), l)