refactor: remove sensitive info logging even in debug mode

This commit is contained in:
Stavros
2025-01-28 17:36:06 +02:00
parent c54267f50d
commit 3efcb26db1
13 changed files with 58 additions and 58 deletions

View File

@@ -1,9 +1,12 @@
package cmd package cmd
import ( import (
"os"
"strings" "strings"
"time"
cmd "tinyauth/cmd/user" cmd "tinyauth/cmd/user"
"tinyauth/internal/api" "tinyauth/internal/api"
"tinyauth/internal/assets"
"tinyauth/internal/auth" "tinyauth/internal/auth"
"tinyauth/internal/hooks" "tinyauth/internal/hooks"
"tinyauth/internal/providers" "tinyauth/internal/providers"
@@ -22,29 +25,28 @@ var rootCmd = &cobra.Command{
Short: "The simplest way to protect your apps with a login screen.", Short: "The simplest way to protect your apps with a login screen.",
Long: `Tinyauth is a simple authentication middleware that adds simple username/password login or OAuth with Google, Github and any generic OAuth provider to all of your docker apps.`, Long: `Tinyauth is a simple authentication middleware that adds simple username/password login or OAuth with Google, Github and any generic OAuth provider to all of your docker apps.`,
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
// Logger
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr, TimeFormat: time.RFC3339}).With().Timestamp().Logger().Level(zerolog.FatalLevel)
// Get config // Get config
log.Info().Msg("Parsing config")
var config types.Config var config types.Config
parseErr := viper.Unmarshal(&config) parseErr := viper.Unmarshal(&config)
HandleError(parseErr, "Failed to parse config") HandleError(parseErr, "Failed to parse config")
// Secrets // Secrets
log.Info().Msg("Parsing secrets")
config.Secret = utils.GetSecret(config.Secret, config.SecretFile) config.Secret = utils.GetSecret(config.Secret, config.SecretFile)
config.GithubClientSecret = utils.GetSecret(config.GithubClientSecret, config.GithubClientSecretFile) config.GithubClientSecret = utils.GetSecret(config.GithubClientSecret, config.GithubClientSecretFile)
config.GoogleClientSecret = utils.GetSecret(config.GoogleClientSecret, config.GoogleClientSecretFile) config.GoogleClientSecret = utils.GetSecret(config.GoogleClientSecret, config.GoogleClientSecretFile)
config.GenericClientSecret = utils.GetSecret(config.GenericClientSecret, config.GenericClientSecretFile) config.GenericClientSecret = utils.GetSecret(config.GenericClientSecret, config.GenericClientSecretFile)
// Validate config // Validate config
log.Info().Msg("Validating config")
validator := validator.New() validator := validator.New()
validateErr := validator.Struct(config) validateErr := validator.Struct(config)
HandleError(validateErr, "Invalid config") HandleError(validateErr, "Failed to validate config")
// Set log level // Logger
log.Info().Int8("log_level", config.LogLevel).Msg("Setting log level") log.Logger = log.Level(zerolog.Level(config.LogLevel))
log.Logger = log.Logger.Level(zerolog.Level(config.LogLevel)) log.Info().Str("version", assets.Version).Msg("Starting tinyauth")
// Users // Users
log.Info().Msg("Parsing users") log.Info().Msg("Parsing users")
@@ -56,7 +58,7 @@ var rootCmd = &cobra.Command{
// Create oauth whitelist // Create oauth whitelist
oauthWhitelist := strings.Split(config.OAuthWhitelist, ",") oauthWhitelist := strings.Split(config.OAuthWhitelist, ",")
log.Debug().Strs("oauth_whitelist", oauthWhitelist).Msg("Parsed OAuth whitelist") log.Debug().Msg("Parsed OAuth whitelist")
// Create OAuth config // Create OAuth config
oauthConfig := types.OAuthConfig{ oauthConfig := types.OAuthConfig{
@@ -72,7 +74,8 @@ var rootCmd = &cobra.Command{
GenericUserURL: config.GenericUserURL, GenericUserURL: config.GenericUserURL,
AppURL: config.AppURL, AppURL: config.AppURL,
} }
log.Debug().Interface("oauth_config", oauthConfig).Msg("Parsed OAuth config")
log.Debug().Msg("Parsed OAuth config")
// Create auth service // Create auth service
auth := auth.NewAuth(users, oauthWhitelist) auth := auth.NewAuth(users, oauthWhitelist)

View File

@@ -6,6 +6,7 @@ import (
"strings" "strings"
"github.com/charmbracelet/huh" "github.com/charmbracelet/huh"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"golang.org/x/crypto/bcrypt" "golang.org/x/crypto/bcrypt"
@@ -21,6 +22,8 @@ var CreateCmd = &cobra.Command{
Short: "Create a user", Short: "Create a user",
Long: `Create a user either interactively or by passing flags.`, Long: `Create a user either interactively or by passing flags.`,
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
log.Logger = log.Level(zerolog.InfoLevel)
if interactive { if interactive {
form := huh.NewForm( form := huh.NewForm(
huh.NewGroup( huh.NewGroup(

View File

@@ -8,12 +8,17 @@ import (
) )
func UserCmd() *cobra.Command { func UserCmd() *cobra.Command {
// Create the user command
userCmd := &cobra.Command{ userCmd := &cobra.Command{
Use: "user", Use: "user",
Short: "User utilities", Short: "User utilities",
Long: `Utilities for creating and verifying tinyauth compatible users.`, Long: `Utilities for creating and verifying tinyauth compatible users.`,
} }
// Add subcommands
userCmd.AddCommand(create.CreateCmd) userCmd.AddCommand(create.CreateCmd)
userCmd.AddCommand(verify.VerifyCmd) userCmd.AddCommand(verify.VerifyCmd)
// Return the user command
return userCmd return userCmd
} }

View File

@@ -5,6 +5,7 @@ import (
"strings" "strings"
"github.com/charmbracelet/huh" "github.com/charmbracelet/huh"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"golang.org/x/crypto/bcrypt" "golang.org/x/crypto/bcrypt"
@@ -21,6 +22,8 @@ var VerifyCmd = &cobra.Command{
Short: "Verify a user is set up correctly", Short: "Verify a user is set up correctly",
Long: `Verify a user is set up correctly meaning that it has a correct username and password.`, Long: `Verify a user is set up correctly meaning that it has a correct username and password.`,
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
log.Logger = log.Level(zerolog.InfoLevel)
if interactive { if interactive {
form := huh.NewForm( form := huh.NewForm(
huh.NewGroup( huh.NewGroup(

View File

@@ -114,7 +114,7 @@ func (api *API) SetupRoutes() {
RedirectURI: fmt.Sprintf("%s://%s%s", proto, host, uri), RedirectURI: fmt.Sprintf("%s://%s%s", proto, host, uri),
}) })
log.Debug().Interface("queries", queries).Msg("Redirecting to login") log.Debug().Interface("redirect_uri", fmt.Sprintf("%s://%s%s", proto, host, uri)).Msg("Redirecting to login")
if queryErr != nil { if queryErr != nil {
log.Error().Err(queryErr).Msg("Failed to build query") log.Error().Err(queryErr).Msg("Failed to build query")
@@ -142,7 +142,7 @@ func (api *API) SetupRoutes() {
return return
} }
log.Debug().Interface("login", login).Msg("Got login request") log.Debug().Msg("Got login request")
user := api.Auth.GetUser(login.Username) user := api.Auth.GetUser(login.Username)
@@ -250,7 +250,7 @@ func (api *API) SetupRoutes() {
return return
} }
log.Debug().Interface("request", request).Msg("Got OAuth request") log.Debug().Msg("Got OAuth request")
provider := api.Providers.GetProvider(request.Provider) provider := api.Providers.GetProvider(request.Provider)
@@ -266,7 +266,7 @@ func (api *API) SetupRoutes() {
authURL := provider.GetAuthURL() authURL := provider.GetAuthURL()
log.Debug().Str("authURL", authURL).Msg("Got auth URL") log.Debug().Msg("Got auth URL")
redirectURI := c.Query("redirect_uri") redirectURI := c.Query("redirect_uri")
@@ -291,7 +291,7 @@ func (api *API) SetupRoutes() {
return return
} }
log.Debug().Interface("providerName", providerName).Msg("Got provider name") log.Debug().Interface("provider", providerName.Provider).Msg("Got provider name")
code := c.Query("code") code := c.Query("code")
@@ -301,7 +301,7 @@ func (api *API) SetupRoutes() {
return return
} }
log.Debug().Str("code", code).Msg("Got code") log.Debug().Msg("Got code")
provider := api.Providers.GetProvider(providerName.Provider) provider := api.Providers.GetProvider(providerName.Provider)
@@ -312,9 +312,9 @@ func (api *API) SetupRoutes() {
return return
} }
token, tokenErr := provider.ExchangeToken(code) _, tokenErr := provider.ExchangeToken(code)
log.Debug().Str("token", token).Msg("Got token") log.Debug().Msg("Got token")
if handleApiError(c, "Failed to exchange token", tokenErr) { if handleApiError(c, "Failed to exchange token", tokenErr) {
return return
@@ -363,7 +363,7 @@ func (api *API) SetupRoutes() {
RedirectURI: redirectURI, RedirectURI: redirectURI,
}) })
log.Debug().Interface("redirectQuery", redirectQuery).Msg("Got redirect query") log.Debug().Msg("Got redirect query")
if handleApiError(c, "Failed to build query", redirectQueryErr) { if handleApiError(c, "Failed to build query", redirectQueryErr) {
return return

View File

@@ -50,7 +50,7 @@ func (auth *Auth) EmailWhitelisted(emailSrc string) bool {
func (auth *Auth) CreateSessionCookie(c *gin.Context, data *types.SessionCookie) { func (auth *Auth) CreateSessionCookie(c *gin.Context, data *types.SessionCookie) {
log.Debug().Msg("Creating session cookie") log.Debug().Msg("Creating session cookie")
sessions := sessions.Default(c) sessions := sessions.Default(c)
log.Debug().Interface("data", data).Msg("Setting session cookie") log.Debug().Msg("Setting session cookie")
sessions.Set("username", data.Username) sessions.Set("username", data.Username)
sessions.Set("provider", data.Provider) sessions.Set("provider", data.Provider)
sessions.Save() sessions.Save()
@@ -70,13 +70,10 @@ func (auth *Auth) GetSessionCookie(c *gin.Context) (types.SessionCookie, error)
cookieUsername := sessions.Get("username") cookieUsername := sessions.Get("username")
cookieProvider := sessions.Get("provider") cookieProvider := sessions.Get("provider")
log.Debug().Interface("cookieUsername", cookieUsername).Msg("Got username")
log.Debug().Interface("cookieProvider", cookieProvider).Msg("Got provider")
username, usernameOk := cookieUsername.(string) username, usernameOk := cookieUsername.(string)
provider, providerOk := cookieProvider.(string) provider, providerOk := cookieProvider.(string)
log.Debug().Str("username", username).Bool("usernameOk", usernameOk).Str("provider", provider).Bool("providerOk", providerOk).Msg("Parsed cookie") log.Debug().Str("username", username).Str("provider", provider).Msg("Parsed cookie")
if !usernameOk || !providerOk { if !usernameOk || !providerOk {
log.Warn().Msg("Session cookie invalid") log.Warn().Msg("Session cookie invalid")

View File

@@ -34,8 +34,6 @@ func (hooks *Hooks) UseUserContext(c *gin.Context) types.UserContext {
} }
} }
log.Debug().Interface("cookie", cookie).Msg("Got session cookie")
if cookie.Provider == "username" { if cookie.Provider == "username" {
log.Debug().Msg("Provider is username") log.Debug().Msg("Provider is username")
if hooks.Auth.GetUser(cookie.Username) != nil { if hooks.Auth.GetUser(cookie.Username) != nil {
@@ -55,7 +53,7 @@ func (hooks *Hooks) UseUserContext(c *gin.Context) types.UserContext {
if provider != nil { if provider != nil {
log.Debug().Msg("Provider exists") log.Debug().Msg("Provider exists")
if !hooks.Auth.EmailWhitelisted(cookie.Username) { if !hooks.Auth.EmailWhitelisted(cookie.Username) {
log.Error().Msgf("Email %s not whitelisted", cookie.Username) log.Error().Str("email", cookie.Username).Msg("Email is not whitelisted")
hooks.Auth.DeleteSessionCookie(c) hooks.Auth.DeleteSessionCookie(c)
return types.UserContext{ return types.UserContext{
Username: "", Username: "",

View File

@@ -37,7 +37,7 @@ func GetGenericEmail(client *http.Client, url string) (string, error) {
return "", jsonErr return "", jsonErr
} }
log.Debug().Interface("user", user).Msg("Parsed user from generic provider") log.Debug().Msg("Parsed user from generic provider")
return user.Email, nil return user.Email, nil
} }

View File

@@ -43,7 +43,7 @@ func GetGithubEmail(client *http.Client) (string, error) {
return "", jsonErr return "", jsonErr
} }
log.Debug().Interface("emails", emails).Msg("Parsed emails from github") log.Debug().Msg("Parsed emails from github")
for _, email := range emails { for _, email := range emails {
if email.Primary { if email.Primary {

View File

@@ -41,7 +41,7 @@ func GetGoogleEmail(client *http.Client) (string, error) {
return "", jsonErr return "", jsonErr
} }
log.Debug().Interface("user", user).Msg("Parsed user from google") log.Debug().Msg("Parsed user from google")
return user.Email, nil return user.Email, nil
} }

View File

@@ -19,9 +19,9 @@ type User struct {
type Users []User type Users []User
type Config struct { type Config struct {
Port int `mapstructure:"port"` Port int `mapstructure:"port" validate:"required"`
Address string `validate:"ip4_addr" mapstructure:"address"` Address string `validate:"required,ip4_addr" mapstructure:"address"`
Secret string `validate:"len=32" mapstructure:"secret"` Secret string `validate:"required,len=32" mapstructure:"secret"`
SecretFile string `mapstructure:"secret-file"` SecretFile string `mapstructure:"secret-file"`
AppURL string `validate:"required,url" mapstructure:"app-url"` AppURL string `validate:"required,url" mapstructure:"app-url"`
Users string `mapstructure:"users"` Users string `mapstructure:"users"`
@@ -43,7 +43,7 @@ type Config struct {
DisableContinue bool `mapstructure:"disable-continue"` DisableContinue bool `mapstructure:"disable-continue"`
OAuthWhitelist string `mapstructure:"oauth-whitelist"` OAuthWhitelist string `mapstructure:"oauth-whitelist"`
CookieExpiry int `mapstructure:"cookie-expiry"` CookieExpiry int `mapstructure:"cookie-expiry"`
LogLevel int8 `mapstructure:"log-level"` LogLevel int8 `mapstructure:"log-level" validate:"min=-1,max=5"`
} }
type UserContext struct { type UserContext struct {

View File

@@ -15,15 +15,12 @@ func ParseUsers(users string) (types.Users, error) {
var usersParsed types.Users var usersParsed types.Users
userList := strings.Split(users, ",") userList := strings.Split(users, ",")
log.Debug().Strs("users", userList).Msg("Splitted users")
if len(userList) == 0 { if len(userList) == 0 {
return types.Users{}, errors.New("invalid user format") return types.Users{}, errors.New("invalid user format")
} }
for _, user := range userList { for _, user := range userList {
userSplit := strings.Split(user, ":") userSplit := strings.Split(user, ":")
log.Debug().Strs("user", userSplit).Msg("Splitting user")
if len(userSplit) != 2 { if len(userSplit) != 2 {
return types.Users{}, errors.New("invalid user format") return types.Users{}, errors.New("invalid user format")
} }
@@ -33,7 +30,7 @@ func ParseUsers(users string) (types.Users, error) {
}) })
} }
log.Debug().Interface("users", usersParsed).Msg("Parsed users") log.Debug().Msg("Parsed users")
return usersParsed, nil return usersParsed, nil
} }
@@ -83,15 +80,13 @@ func ParseFileToLine(content string) string {
return strings.Join(users, ",") return strings.Join(users, ",")
} }
func GetSecret(env string, file string) string { func GetSecret(conf string, file string) string {
if env == "" && file == "" { if conf == "" && file == "" {
log.Debug().Msg("No secret provided")
return "" return ""
} }
if env != "" { if conf != "" {
log.Debug().Str("secret", env).Msg("Using secret from env") return conf
return env
} }
contents, err := ReadFile(file) contents, err := ReadFile(file)
@@ -100,28 +95,26 @@ func GetSecret(env string, file string) string {
return "" return ""
} }
log.Debug().Str("secret", contents).Msg("Using secret from file")
return contents return contents
} }
func GetUsers(env string, file string) (types.Users, error) { func GetUsers(conf string, file string) (types.Users, error) {
var users string var users string
if env == "" && file == "" { if conf == "" && file == "" {
return types.Users{}, errors.New("no users provided") return types.Users{}, errors.New("no users provided")
} }
if env != "" { if conf != "" {
log.Debug().Str("users", env).Msg("Using users from env") log.Debug().Msg("Using users from config")
users += env users += conf
} }
if file != "" { if file != "" {
fileContents, fileErr := ReadFile(file) fileContents, fileErr := ReadFile(file)
if fileErr == nil { if fileErr == nil {
log.Debug().Str("users", ParseFileToLine(fileContents)).Msg("Using users from file") log.Debug().Msg("Using users from file")
if users != "" { if users != "" {
users += "," users += ","
} }

View File

@@ -4,7 +4,6 @@ import (
"os" "os"
"time" "time"
"tinyauth/cmd" "tinyauth/cmd"
"tinyauth/internal/assets"
"github.com/rs/zerolog" "github.com/rs/zerolog"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
@@ -12,8 +11,7 @@ import (
func main() { func main() {
// Logger // Logger
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr, TimeFormat: time.RFC3339}).With().Timestamp().Logger() log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr, TimeFormat: time.RFC3339}).With().Timestamp().Logger().Level(zerolog.FatalLevel)
log.Info().Str("version", assets.Version).Msg("Starting tinyauth")
// Run cmd // Run cmd
cmd.Execute() cmd.Execute()