chore: remove meaningless comments

This commit is contained in:
Stavros
2025-07-12 13:17:06 +03:00
parent e742603c15
commit 8ebed0ac9a
24 changed files with 81 additions and 876 deletions

View File

@@ -3,9 +3,7 @@ package cmd
import (
"errors"
"fmt"
"os"
"strings"
"time"
totpCmd "tinyauth/cmd/totp"
userCmd "tinyauth/cmd/user"
"tinyauth/internal/auth"
@@ -31,47 +29,37 @@ var rootCmd = &cobra.Command{
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.`,
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
var config types.Config
err := viper.Unmarshal(&config)
HandleError(err, "Failed to parse config")
// Secrets
// Check if secrets have a file associated with them
config.Secret = utils.GetSecret(config.Secret, config.SecretFile)
config.GithubClientSecret = utils.GetSecret(config.GithubClientSecret, config.GithubClientSecretFile)
config.GoogleClientSecret = utils.GetSecret(config.GoogleClientSecret, config.GoogleClientSecretFile)
config.GenericClientSecret = utils.GetSecret(config.GenericClientSecret, config.GenericClientSecretFile)
// Validate config
validator := validator.New()
err = validator.Struct(config)
HandleError(err, "Failed to validate config")
// Logger
log.Logger = log.Level(zerolog.Level(config.LogLevel))
log.Info().Str("version", strings.TrimSpace(constants.Version)).Msg("Starting tinyauth")
// Users
log.Info().Msg("Parsing users")
users, err := utils.GetUsers(config.Users, config.UsersFile)
HandleError(err, "Failed to parse users")
// Get domain
log.Debug().Msg("Getting domain")
domain, err := utils.GetUpperDomain(config.AppURL)
HandleError(err, "Failed to get upper domain")
log.Info().Str("domain", domain).Msg("Using domain for cookie store")
// Generate cookie name
cookieId := utils.GenerateIdentifier(strings.Split(domain, ".")[0])
sessionCookieName := fmt.Sprintf("%s-%s", constants.SessionCookieName, cookieId)
csrfCookieName := fmt.Sprintf("%s-%s", constants.CsrfCookieName, cookieId)
redirectCookieName := fmt.Sprintf("%s-%s", constants.RedirectCookieName, cookieId)
// Generate HMAC and encryption secrets
log.Debug().Msg("Deriving HMAC and encryption secrets")
hmacSecret, err := utils.DeriveKey(config.Secret, "hmac")
@@ -80,7 +68,7 @@ var rootCmd = &cobra.Command{
encryptionSecret, err := utils.DeriveKey(config.Secret, "encryption")
HandleError(err, "Failed to derive encryption secret")
// Create OAuth config
// Split the config into service-specific sub-configs
oauthConfig := types.OAuthConfig{
GithubClientId: config.GithubClientId,
GithubClientSecret: config.GithubClientSecret,
@@ -96,7 +84,6 @@ var rootCmd = &cobra.Command{
AppURL: config.AppURL,
}
// Create handlers config
handlersConfig := types.HandlersConfig{
AppURL: config.AppURL,
DisableContinue: config.DisableContinue,
@@ -111,13 +98,11 @@ var rootCmd = &cobra.Command{
RedirectCookieName: redirectCookieName,
}
// Create server config
serverConfig := types.ServerConfig{
Port: config.Port,
Address: config.Address,
}
// Create auth config
authConfig := types.AuthConfig{
Users: users,
OauthWhitelist: config.OAuthWhitelist,
@@ -131,21 +116,14 @@ var rootCmd = &cobra.Command{
EncryptionSecret: encryptionSecret,
}
// Create hooks config
hooksConfig := types.HooksConfig{
Domain: domain,
}
// Create docker service
docker, err := docker.NewDocker()
HandleError(err, "Failed to initialize docker")
// Create LDAP service if configured
var ldapService *ldap.LDAP
if config.LdapAddress != "" {
log.Info().Msg("Using LDAP for authentication")
ldapConfig := types.LdapConfig{
Address: config.LdapAddress,
BindDN: config.LdapBindDN,
@@ -154,36 +132,28 @@ var rootCmd = &cobra.Command{
Insecure: config.LdapInsecure,
SearchFilter: config.LdapSearchFilter,
}
// Create LDAP service
ldapService, err = ldap.NewLDAP(ldapConfig)
HandleError(err, "Failed to create LDAP service")
} else {
log.Info().Msg("LDAP not configured, using local users or OAuth")
}
// Check if we have any users configured
// Check if we have a source of users
if len(users) == 0 && !utils.OAuthConfigured(config) && ldapService == nil {
HandleError(errors.New("err no users"), "Unable to find a source of users")
}
// Create auth service
// Setup the services
docker, err := docker.NewDocker()
HandleError(err, "Failed to initialize docker")
auth := auth.NewAuth(authConfig, docker, ldapService)
// Create OAuth providers service
providers := providers.NewProviders(oauthConfig)
// Create hooks service
hooks := hooks.NewHooks(hooksConfig, auth, providers)
// Create handlers
handlers := handlers.NewHandlers(handlersConfig, auth, hooks, providers, docker)
// Create server
srv, err := server.NewServer(serverConfig, handlers)
HandleError(err, "Failed to create server")
// Start server
// Start up
err = srv.Start()
HandleError(err, "Failed to start server")
},
@@ -195,23 +165,17 @@ func Execute() {
}
func HandleError(err error, msg string) {
// If error, log it and exit
if err != nil {
log.Fatal().Err(err).Msg(msg)
}
}
func init() {
// Add user command
rootCmd.AddCommand(userCmd.UserCmd())
// Add totp command
rootCmd.AddCommand(totpCmd.TotpCmd())
// Read environment variables
viper.AutomaticEnv()
// Flags
rootCmd.Flags().Int("port", 3000, "Port to run the server on.")
rootCmd.Flags().String("address", "0.0.0.0", "Address to bind the server to.")
rootCmd.Flags().String("secret", "", "Secret to use for the cookie.")
@@ -252,7 +216,6 @@ func init() {
rootCmd.Flags().Bool("ldap-insecure", false, "Skip certificate verification for the LDAP server.")
rootCmd.Flags().String("ldap-search-filter", "(uid=%s)", "LDAP search filter for user lookup.")
// Bind flags to environment
viper.BindEnv("port", "PORT")
viper.BindEnv("address", "ADDRESS")
viper.BindEnv("secret", "SECRET")
@@ -293,6 +256,5 @@ func init() {
viper.BindEnv("ldap-insecure", "LDAP_INSECURE")
viper.BindEnv("ldap-search-filter", "LDAP_SEARCH_FILTER")
// Bind flags to viper
viper.BindPFlags(rootCmd.Flags())
}

View File

@@ -15,7 +15,6 @@ import (
"github.com/spf13/cobra"
)
// Interactive flag
var interactive bool
// Input user
@@ -25,15 +24,9 @@ var GenerateCmd = &cobra.Command{
Use: "generate",
Short: "Generate a totp secret",
Run: func(cmd *cobra.Command, args []string) {
// Setup logger
log.Logger = log.Level(zerolog.InfoLevel)
// Use simple theme
var baseTheme *huh.Theme = huh.ThemeBase()
// Interactive
if interactive {
// Create huh form
form := huh.NewForm(
huh.NewGroup(
huh.NewInput().Title("Current username:hash").Value(&iUser).Validate((func(s string) error {
@@ -44,51 +37,39 @@ var GenerateCmd = &cobra.Command{
})),
),
)
// Run form
var baseTheme *huh.Theme = huh.ThemeBase()
err := form.WithTheme(baseTheme).Run()
if err != nil {
log.Fatal().Err(err).Msg("Form failed")
}
}
// Parse user
user, err := utils.ParseUser(iUser)
if err != nil {
log.Fatal().Err(err).Msg("Failed to parse user")
}
// Check if user was using docker escape
dockerEscape := false
if strings.Contains(iUser, "$$") {
dockerEscape = true
}
// Check it has totp
if user.TotpSecret != "" {
log.Fatal().Msg("User already has a totp secret")
}
// Generate totp secret
key, err := totp.Generate(totp.GenerateOpts{
Issuer: "Tinyauth",
AccountName: user.Username,
})
if err != nil {
log.Fatal().Err(err).Msg("Failed to generate totp secret")
}
// Create secret
secret := key.Secret()
// Print secret and image
log.Info().Str("secret", secret).Msg("Generated totp secret")
// Print QR code
log.Info().Msg("Generated QR code")
config := qrterminal.Config{
@@ -101,7 +82,6 @@ var GenerateCmd = &cobra.Command{
qrterminal.GenerateWithConfig(key.URL(), config)
// Add the secret to the user
user.TotpSecret = secret
// If using docker escape re-escape it
@@ -109,13 +89,11 @@ var GenerateCmd = &cobra.Command{
user.Password = strings.ReplaceAll(user.Password, "$", "$$")
}
// Print success
log.Info().Str("user", fmt.Sprintf("%s:%s:%s", user.Username, user.Password, user.TotpSecret)).Msg("Add the totp secret to your authenticator app then use the verify command to ensure everything is working correctly.")
},
}
func init() {
// Add interactive flag
GenerateCmd.Flags().BoolVarP(&interactive, "interactive", "i", false, "Run in interactive mode")
GenerateCmd.Flags().StringVar(&iUser, "user", "", "Your current username:hash")
}

View File

@@ -7,16 +7,11 @@ import (
)
func TotpCmd() *cobra.Command {
// Create the totp command
totpCmd := &cobra.Command{
Use: "totp",
Short: "Totp utilities",
Long: `Utilities for creating and verifying totp codes.`,
}
// Add the generate command
totpCmd.AddCommand(generate.GenerateCmd)
// Return the totp command
return totpCmd
}

View File

@@ -12,10 +12,7 @@ import (
"golang.org/x/crypto/bcrypt"
)
// Interactive flag
var interactive bool
// Docker flag
var docker bool
// i stands for input
@@ -27,12 +24,9 @@ var CreateCmd = &cobra.Command{
Short: "Create a user",
Long: `Create a user either interactively or by passing flags.`,
Run: func(cmd *cobra.Command, args []string) {
// Setup logger
log.Logger = log.Level(zerolog.InfoLevel)
// Check if interactive
if interactive {
// Create huh form
form := huh.NewForm(
huh.NewGroup(
huh.NewInput().Title("Username").Value(&iUsername).Validate((func(s string) error {
@@ -50,46 +44,35 @@ var CreateCmd = &cobra.Command{
huh.NewSelect[bool]().Title("Format the output for docker?").Options(huh.NewOption("Yes", true), huh.NewOption("No", false)).Value(&docker),
),
)
// Use simple theme
var baseTheme *huh.Theme = huh.ThemeBase()
err := form.WithTheme(baseTheme).Run()
if err != nil {
log.Fatal().Err(err).Msg("Form failed")
}
}
// Do we have username and password?
if iUsername == "" || iPassword == "" {
log.Fatal().Err(errors.New("error invalid input")).Msg("Username and password cannot be empty")
}
log.Info().Str("username", iUsername).Str("password", iPassword).Bool("docker", docker).Msg("Creating user")
// Hash password
password, err := bcrypt.GenerateFromPassword([]byte(iPassword), bcrypt.DefaultCost)
if err != nil {
log.Fatal().Err(err).Msg("Failed to hash password")
}
// Convert password to string
// If docker format is enabled, escape the dollar sign
passwordString := string(password)
// Escape $ for docker
if docker {
passwordString = strings.ReplaceAll(passwordString, "$", "$$")
}
// Log user created
log.Info().Str("user", fmt.Sprintf("%s:%s", iUsername, passwordString)).Msg("User created")
},
}
func init() {
// Flags
CreateCmd.Flags().BoolVarP(&interactive, "interactive", "i", false, "Create a user interactively")
CreateCmd.Flags().BoolVar(&docker, "docker", false, "Format output for docker")
CreateCmd.Flags().StringVar(&iUsername, "username", "", "Username")

View File

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

View File

@@ -12,10 +12,7 @@ import (
"golang.org/x/crypto/bcrypt"
)
// Interactive flag
var interactive bool
// Docker flag
var docker bool
// i stands for input
@@ -29,15 +26,9 @@ var VerifyCmd = &cobra.Command{
Short: "Verify a user is set up correctly",
Long: `Verify a user is set up correctly meaning that it has a correct username, password and totp code.`,
Run: func(cmd *cobra.Command, args []string) {
// Setup logger
log.Logger = log.Level(zerolog.InfoLevel)
// Use simple theme
var baseTheme *huh.Theme = huh.ThemeBase()
// Check if interactive
if interactive {
// Create huh form
form := huh.NewForm(
huh.NewGroup(
huh.NewInput().Title("User (username:hash:totp)").Value(&iUser).Validate((func(s string) error {
@@ -61,35 +52,27 @@ var VerifyCmd = &cobra.Command{
huh.NewInput().Title("Totp Code (if setup)").Value(&iTotp),
),
)
// Run form
var baseTheme *huh.Theme = huh.ThemeBase()
err := form.WithTheme(baseTheme).Run()
if err != nil {
log.Fatal().Err(err).Msg("Form failed")
}
}
// Parse user
user, err := utils.ParseUser(iUser)
if err != nil {
log.Fatal().Err(err).Msg("Failed to parse user")
}
// Compare username
if user.Username != iUsername {
log.Fatal().Msg("Username is incorrect")
}
// Compare password
err = bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(iPassword))
if err != nil {
log.Fatal().Msg("Ppassword is incorrect")
}
// Check if user has 2fa code
if user.TotpSecret == "" {
if iTotp != "" {
log.Warn().Msg("User does not have 2fa secret")
@@ -98,21 +81,17 @@ var VerifyCmd = &cobra.Command{
return
}
// Check totp code
ok := totp.Validate(iTotp, user.TotpSecret)
if !ok {
log.Fatal().Msg("Totp code incorrect")
}
// Done
log.Info().Msg("User verified")
},
}
func init() {
// Flags
VerifyCmd.Flags().BoolVarP(&interactive, "interactive", "i", false, "Create a user interactively")
VerifyCmd.Flags().BoolVar(&docker, "docker", false, "Is the user formatted for docker?")
VerifyCmd.Flags().StringVar(&iUsername, "username", "", "Username")

View File

@@ -7,7 +7,6 @@ import (
"github.com/spf13/cobra"
)
// Create the version command
var versionCmd = &cobra.Command{
Use: "version",
Short: "Print the version number of Tinyauth",