Enhance configuration loading by validating direct values and file paths for secrets

This commit is contained in:
Christian Galo 2025-05-18 17:16:01 -05:00
parent 1fa4473244
commit d53f26b59b

View File

@ -3,6 +3,8 @@ package cmd
import ( import (
"context" "context"
"log/slog" "log/slog"
"os"
"strings"
"git.coopcloud.tech/wiki-cafe/member-console/internal/logging" "git.coopcloud.tech/wiki-cafe/member-console/internal/logging"
"git.coopcloud.tech/wiki-cafe/member-console/internal/server" "git.coopcloud.tech/wiki-cafe/member-console/internal/server"
@ -22,17 +24,52 @@ var startCmd = &cobra.Command{
// Create base context for the application // Create base context for the application
ctx := context.Background() ctx := context.Background()
// Retrieve the configuration values from Viper
port := viper.GetString("port")
env := viper.GetString("env")
csrfSecret := viper.GetString("csrf-secret")
// Set up structured logging // Set up structured logging
env := viper.GetString("env")
logger := logging.SetupLogger(env) logger := logging.SetupLogger(env)
// Store logger in context // Store logger in context
ctx = logging.WithContext(ctx, logger) ctx = logging.WithContext(ctx, logger)
// Validate and load configurations from files if specified
configPairs := []struct {
value string
file string
configKey string
}{
{viper.GetString("client-secret"), viper.GetString("client-secret-file"), "client-secret"},
{viper.GetString("session-secret"), viper.GetString("session-secret-file"), "session-secret"},
{viper.GetString("csrf-secret"), viper.GetString("csrf-secret-file"), "csrf-secret"},
}
// Check for conflicts between direct values and file paths
for _, pair := range configPairs {
// Check if both a direct value and a file path are provided
if pair.value != "" && pair.file != "" {
logger.Error("configuration error",
slog.String("config", pair.configKey),
slog.String("error", "both direct value and file path provided; use only one"))
return
}
// If a file path is provided, load the value from the file
if pair.file != "" {
value, err := loadFromFile(pair.file)
if err != nil {
logger.Error("failed to load configuration from file",
slog.String("config", pair.configKey),
slog.String("file", pair.file),
slog.Any("error", err))
return
}
viper.Set(pair.configKey, value)
}
}
// Retrieve the configuration values from Viper
port := viper.GetString("port")
csrfSecret := viper.GetString("csrf-secret")
// Create server config // Create server config
serverConfig := server.Config{ serverConfig := server.Config{
Port: port, Port: port,
@ -52,13 +89,17 @@ func init() {
// Register flags with Cobra // Register flags with Cobra
startCmd.Flags().StringP("port", "p", "", "Port to listen on") startCmd.Flags().StringP("port", "p", "", "Port to listen on")
startCmd.Flags().String("client-id", "", "OIDC Client ID") startCmd.Flags().String("client-id", "", "OIDC Client ID")
startCmd.Flags().String("client-secret", "", "OIDC Client Secret")
startCmd.Flags().String("issuer-url", "", "Identity Provider Issuer URL") startCmd.Flags().String("issuer-url", "", "Identity Provider Issuer URL")
startCmd.Flags().String("hostname", "", "Address at which the server is exposed") startCmd.Flags().String("hostname", "", "Address at which the server is exposed")
startCmd.Flags().String("session-secret", "", "Session encryption secret")
startCmd.Flags().String("csrf-secret", "", "Secret key for CSRF protection (must be exactly 32 bytes)")
startCmd.Flags().String("env", "", "Environment (development/production)") startCmd.Flags().String("env", "", "Environment (development/production)")
startCmd.Flags().String("client-secret", "", "OIDC Client Secret")
startCmd.Flags().String("client-secret-file", "", "Path to file containing OIDC Client Secret")
startCmd.Flags().String("session-secret", "", "Secret key for session management (must be exactly 32 bytes)")
startCmd.Flags().String("session-secret-file", "", "Path to file containing session secret key")
startCmd.Flags().String("csrf-secret", "", "Secret key for CSRF protection (must be exactly 32 bytes)")
startCmd.Flags().String("csrf-secret-file", "", "Path to file containing CSRF secret key")
// Bind all flags to Viper // Bind all flags to Viper
viper.BindPFlags(startCmd.Flags()) viper.BindPFlags(startCmd.Flags())
@ -69,3 +110,12 @@ func init() {
// Add the command to the root command // Add the command to the root command
rootCmd.AddCommand(startCmd) rootCmd.AddCommand(startCmd)
} }
// loadFromFile reads a file and returns its contents as a trimmed string
func loadFromFile(path string) (string, error) {
data, err := os.ReadFile(path)
if err != nil {
return "", err
}
return strings.TrimSpace(string(data)), nil
}