v0.5.1 minor basic auth bug fixes, dependency udpate, test scripts are being added
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@ -7,6 +7,5 @@ cert
|
|||||||
bin
|
bin
|
||||||
script
|
script
|
||||||
build
|
build
|
||||||
test
|
|
||||||
*.log
|
*.log
|
||||||
*.toml
|
*.toml
|
||||||
|
|||||||
@ -12,7 +12,7 @@ config_save_on_exit = false # Persist runtime changes
|
|||||||
|
|
||||||
### Logging Configuration
|
### Logging Configuration
|
||||||
[logging]
|
[logging]
|
||||||
output = "stdout" # file|stdout|stderr|both|all|none
|
output = "stdout" # file|stdout|stderr|split|all|none
|
||||||
level = "info" # debug|info|warn|error
|
level = "info" # debug|info|warn|error
|
||||||
|
|
||||||
[logging.file]
|
[logging.file]
|
||||||
|
|||||||
2
go.mod
2
go.mod
@ -5,7 +5,7 @@ go 1.25.1
|
|||||||
require (
|
require (
|
||||||
github.com/golang-jwt/jwt/v5 v5.3.0
|
github.com/golang-jwt/jwt/v5 v5.3.0
|
||||||
github.com/lixenwraith/config v0.0.0-20250908085506-537a4d49d2c3
|
github.com/lixenwraith/config v0.0.0-20250908085506-537a4d49d2c3
|
||||||
github.com/lixenwraith/log v0.0.0-20250929084748-210374d95b3e
|
github.com/lixenwraith/log v0.0.0-20250929145347-45cc8a5099c2
|
||||||
github.com/panjf2000/gnet/v2 v2.9.4
|
github.com/panjf2000/gnet/v2 v2.9.4
|
||||||
github.com/valyala/fasthttp v1.66.0
|
github.com/valyala/fasthttp v1.66.0
|
||||||
golang.org/x/crypto v0.42.0
|
golang.org/x/crypto v0.42.0
|
||||||
|
|||||||
2
go.sum
2
go.sum
@ -14,6 +14,8 @@ github.com/lixenwraith/config v0.0.0-20250908085506-537a4d49d2c3 h1:+RwUb7dUz9mG
|
|||||||
github.com/lixenwraith/config v0.0.0-20250908085506-537a4d49d2c3/go.mod h1:I7ddNPT8MouXXz/ae4DQfBKMq5EisxdDLRX0C7Dv4O0=
|
github.com/lixenwraith/config v0.0.0-20250908085506-537a4d49d2c3/go.mod h1:I7ddNPT8MouXXz/ae4DQfBKMq5EisxdDLRX0C7Dv4O0=
|
||||||
github.com/lixenwraith/log v0.0.0-20250929084748-210374d95b3e h1:/XWCqFdSOiUf0/a5a63GHsvEdpglsYfn3qieNxTeyDc=
|
github.com/lixenwraith/log v0.0.0-20250929084748-210374d95b3e h1:/XWCqFdSOiUf0/a5a63GHsvEdpglsYfn3qieNxTeyDc=
|
||||||
github.com/lixenwraith/log v0.0.0-20250929084748-210374d95b3e/go.mod h1:E7REMCVTr6DerzDtd2tpEEaZ9R9nduyAIKQFOqHqKr0=
|
github.com/lixenwraith/log v0.0.0-20250929084748-210374d95b3e/go.mod h1:E7REMCVTr6DerzDtd2tpEEaZ9R9nduyAIKQFOqHqKr0=
|
||||||
|
github.com/lixenwraith/log v0.0.0-20250929145347-45cc8a5099c2 h1:9Qf+BR83sKjok2E1Nct+3Sfzoj2dLGwC/zyQDVNmmqs=
|
||||||
|
github.com/lixenwraith/log v0.0.0-20250929145347-45cc8a5099c2/go.mod h1:E7REMCVTr6DerzDtd2tpEEaZ9R9nduyAIKQFOqHqKr0=
|
||||||
github.com/panjf2000/ants/v2 v2.11.3 h1:AfI0ngBoXJmYOpDh9m516vjqoUu2sLrIVgppI9TZVpg=
|
github.com/panjf2000/ants/v2 v2.11.3 h1:AfI0ngBoXJmYOpDh9m516vjqoUu2sLrIVgppI9TZVpg=
|
||||||
github.com/panjf2000/ants/v2 v2.11.3/go.mod h1:8u92CYMUc6gyvTIw8Ru7Mt7+/ESnJahz5EVtqfrilek=
|
github.com/panjf2000/ants/v2 v2.11.3/go.mod h1:8u92CYMUc6gyvTIw8Ru7Mt7+/ESnJahz5EVtqfrilek=
|
||||||
github.com/panjf2000/gnet/v2 v2.9.4 h1:XvPCcaFwO4XWg4IgSfZnNV4dfDy5g++HIEx7sH0ldHc=
|
github.com/panjf2000/gnet/v2 v2.9.4 h1:XvPCcaFwO4XWg4IgSfZnNV4dfDy5g++HIEx7sH0ldHc=
|
||||||
|
|||||||
@ -50,16 +50,10 @@ func initializeLogger(cfg *config.Config) error {
|
|||||||
logger = log.NewLogger()
|
logger = log.NewLogger()
|
||||||
logCfg := log.DefaultConfig()
|
logCfg := log.DefaultConfig()
|
||||||
|
|
||||||
// Prevent empty directory creation if file logging is not configured
|
|
||||||
if cfg.Logging.Output != "file" && cfg.Logging.Output != "all" {
|
|
||||||
logCfg.DisableFile = true
|
|
||||||
logCfg.Directory = ""
|
|
||||||
}
|
|
||||||
|
|
||||||
if cfg.Quiet {
|
if cfg.Quiet {
|
||||||
// In quiet mode, disable ALL logging output
|
// In quiet mode, disable ALL logging output
|
||||||
logCfg.Level = 255 // A level that disables all output
|
logCfg.Level = 255 // A level that disables all output
|
||||||
logCfg.DisableFile = true
|
logCfg.EnableFile = false
|
||||||
logCfg.EnableConsole = false
|
logCfg.EnableConsole = false
|
||||||
return logger.ApplyConfig(logCfg)
|
return logger.ApplyConfig(logCfg)
|
||||||
}
|
}
|
||||||
@ -74,22 +68,26 @@ func initializeLogger(cfg *config.Config) error {
|
|||||||
// Configure based on output mode
|
// Configure based on output mode
|
||||||
switch cfg.Logging.Output {
|
switch cfg.Logging.Output {
|
||||||
case "none":
|
case "none":
|
||||||
|
logCfg.EnableFile = false
|
||||||
logCfg.EnableConsole = false
|
logCfg.EnableConsole = false
|
||||||
case "stdout":
|
case "stdout":
|
||||||
|
logCfg.EnableFile = false
|
||||||
logCfg.EnableConsole = true
|
logCfg.EnableConsole = true
|
||||||
logCfg.ConsoleTarget = "stdout"
|
logCfg.ConsoleTarget = "stdout"
|
||||||
case "stderr":
|
case "stderr":
|
||||||
|
logCfg.EnableFile = false
|
||||||
logCfg.EnableConsole = true
|
logCfg.EnableConsole = true
|
||||||
logCfg.ConsoleTarget = "stderr"
|
logCfg.ConsoleTarget = "stderr"
|
||||||
case "split":
|
case "split":
|
||||||
|
logCfg.EnableFile = false
|
||||||
logCfg.EnableConsole = true
|
logCfg.EnableConsole = true
|
||||||
logCfg.ConsoleTarget = "split"
|
logCfg.ConsoleTarget = "split"
|
||||||
case "file":
|
case "file":
|
||||||
logCfg.DisableFile = false
|
logCfg.EnableFile = true
|
||||||
logCfg.EnableConsole = false
|
logCfg.EnableConsole = false
|
||||||
configureFileLogging(logCfg, cfg)
|
configureFileLogging(logCfg, cfg)
|
||||||
case "all":
|
case "all":
|
||||||
logCfg.DisableFile = false
|
logCfg.EnableFile = true
|
||||||
logCfg.EnableConsole = true
|
logCfg.EnableConsole = true
|
||||||
logCfg.ConsoleTarget = "split"
|
logCfg.ConsoleTarget = "split"
|
||||||
configureFileLogging(logCfg, cfg)
|
configureFileLogging(logCfg, cfg)
|
||||||
|
|||||||
@ -121,6 +121,11 @@ func (s *Service) NewPipeline(cfg config.PipelineConfig) error {
|
|||||||
pipeline.Sinks = append(pipeline.Sinks, sinkInst)
|
pipeline.Sinks = append(pipeline.Sinks, sinkInst)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Configure authentication for sources that support it before starting them
|
||||||
|
for _, sourceInst := range pipeline.Sources {
|
||||||
|
sourceInst.SetAuth(cfg.Auth)
|
||||||
|
}
|
||||||
|
|
||||||
// Start all sources
|
// Start all sources
|
||||||
for i, src := range pipeline.Sources {
|
for i, src := range pipeline.Sources {
|
||||||
if err := src.Start(); err != nil {
|
if err := src.Start(); err != nil {
|
||||||
@ -129,9 +134,9 @@ func (s *Service) NewPipeline(cfg config.PipelineConfig) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Configure authentication for sources that support it
|
// Configure authentication for sinks that support it before starting them
|
||||||
for _, sourceInst := range pipeline.Sources {
|
for _, sinkInst := range pipeline.Sinks {
|
||||||
sourceInst.SetAuth(cfg.Auth)
|
sinkInst.SetAuth(cfg.Auth)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start all sinks
|
// Start all sinks
|
||||||
@ -142,11 +147,6 @@ func (s *Service) NewPipeline(cfg config.PipelineConfig) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Configure authentication for sinks that support it
|
|
||||||
for _, sinkInst := range pipeline.Sinks {
|
|
||||||
sinkInst.SetAuth(cfg.Auth)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wire sources to sinks through filters
|
// Wire sources to sinks through filters
|
||||||
s.wirePipeline(pipeline)
|
s.wirePipeline(pipeline)
|
||||||
|
|
||||||
|
|||||||
@ -225,6 +225,7 @@ func (h *HTTPSink) Start(ctx context.Context) error {
|
|||||||
fasthttpLogger := compat.NewFastHTTPAdapter(h.logger)
|
fasthttpLogger := compat.NewFastHTTPAdapter(h.logger)
|
||||||
|
|
||||||
h.server = &fasthttp.Server{
|
h.server = &fasthttp.Server{
|
||||||
|
Name: fmt.Sprintf("LogWisp/%s", version.Short()),
|
||||||
Handler: h.requestHandler,
|
Handler: h.requestHandler,
|
||||||
DisableKeepalive: false,
|
DisableKeepalive: false,
|
||||||
StreamRequestBody: true,
|
StreamRequestBody: true,
|
||||||
|
|||||||
@ -8,8 +8,6 @@ import (
|
|||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"fmt"
|
"fmt"
|
||||||
"logwisp/src/internal/auth"
|
|
||||||
"logwisp/src/internal/config"
|
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
@ -17,8 +15,11 @@ import (
|
|||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"logwisp/src/internal/auth"
|
||||||
|
"logwisp/src/internal/config"
|
||||||
"logwisp/src/internal/core"
|
"logwisp/src/internal/core"
|
||||||
"logwisp/src/internal/format"
|
"logwisp/src/internal/format"
|
||||||
|
"logwisp/src/internal/version"
|
||||||
|
|
||||||
"github.com/lixenwraith/log"
|
"github.com/lixenwraith/log"
|
||||||
"github.com/valyala/fasthttp"
|
"github.com/valyala/fasthttp"
|
||||||
@ -441,6 +442,8 @@ func (h *HTTPClientSink) sendBatch(batch []core.LogEntry) {
|
|||||||
req.Header.SetContentType("application/json")
|
req.Header.SetContentType("application/json")
|
||||||
req.SetBody(body)
|
req.SetBody(body)
|
||||||
|
|
||||||
|
req.Header.Set("User-Agent", fmt.Sprintf("LogWisp/%s", version.Short()))
|
||||||
|
|
||||||
// Add Basic Auth header if credentials configured
|
// Add Basic Auth header if credentials configured
|
||||||
if h.config.Username != "" && h.config.Password != "" {
|
if h.config.Username != "" && h.config.Password != "" {
|
||||||
creds := h.config.Username + ":" + h.config.Password
|
creds := h.config.Username + ":" + h.config.Password
|
||||||
|
|||||||
@ -4,16 +4,17 @@ package source
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"logwisp/src/internal/auth"
|
|
||||||
"net"
|
"net"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"logwisp/src/internal/auth"
|
||||||
"logwisp/src/internal/config"
|
"logwisp/src/internal/config"
|
||||||
"logwisp/src/internal/core"
|
"logwisp/src/internal/core"
|
||||||
"logwisp/src/internal/limit"
|
"logwisp/src/internal/limit"
|
||||||
"logwisp/src/internal/tls"
|
"logwisp/src/internal/tls"
|
||||||
|
"logwisp/src/internal/version"
|
||||||
|
|
||||||
"github.com/lixenwraith/log"
|
"github.com/lixenwraith/log"
|
||||||
"github.com/valyala/fasthttp"
|
"github.com/valyala/fasthttp"
|
||||||
@ -180,6 +181,7 @@ func (h *HTTPSource) Subscribe() <-chan core.LogEntry {
|
|||||||
|
|
||||||
func (h *HTTPSource) Start() error {
|
func (h *HTTPSource) Start() error {
|
||||||
h.server = &fasthttp.Server{
|
h.server = &fasthttp.Server{
|
||||||
|
Name: fmt.Sprintf("LogWisp/%s", version.Short()),
|
||||||
Handler: h.requestHandler,
|
Handler: h.requestHandler,
|
||||||
DisableKeepalive: false,
|
DisableKeepalive: false,
|
||||||
StreamRequestBody: true,
|
StreamRequestBody: true,
|
||||||
|
|||||||
12
test/README.md
Normal file
12
test/README.md
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
### Usage:
|
||||||
|
|
||||||
|
- Copy logwisp executable to the test folder (to compile, in logwisp top directory: `make build`).
|
||||||
|
|
||||||
|
- Run the test script for each scenario.
|
||||||
|
|
||||||
|
### Notes:
|
||||||
|
|
||||||
|
- The tests create configuration files and log files. Debug tests do not clean up these files.
|
||||||
|
|
||||||
|
- Some tests may require to be run on different hosts (containers can be used).
|
||||||
|
|
||||||
144
test/test-logwisp-auth-debug.sh
Executable file
144
test/test-logwisp-auth-debug.sh
Executable file
@ -0,0 +1,144 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# FILE: test-logwisp-auth-debug.sh
|
||||||
|
|
||||||
|
# Creates test directories and starts network services
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Create test directories
|
||||||
|
mkdir -p test-logs test-data
|
||||||
|
|
||||||
|
# Generate Argon2id hash using logwisp auth
|
||||||
|
echo "=== Generating Argon2id hash ==="
|
||||||
|
./logwisp auth -u testuser -p secret123 > auth_output.txt 2>&1
|
||||||
|
HASH=$(grep 'password_hash = ' auth_output.txt | cut -d'"' -f2)
|
||||||
|
if [ -z "$HASH" ]; then
|
||||||
|
echo "Failed to generate hash. Output:"
|
||||||
|
cat auth_output.txt
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "Generated hash format: ${HASH:0:15}..." # Show hash format prefix
|
||||||
|
echo "Full hash: $HASH"
|
||||||
|
|
||||||
|
# Determine hash type
|
||||||
|
if [[ "$HASH" == "\$argon2id\$"* ]]; then
|
||||||
|
echo "Hash type: Argon2id"
|
||||||
|
elif [[ "$HASH" == "\$2a\$"* ]] || [[ "$HASH" == "\$2b\$"* ]]; then
|
||||||
|
echo "Hash type: bcrypt"
|
||||||
|
else
|
||||||
|
echo "Hash type: Unknown"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Create test config with debug logging to stdout
|
||||||
|
cat > test-auth.toml << EOF
|
||||||
|
# General LogWisp settings
|
||||||
|
log_dir = "test-logs"
|
||||||
|
log_level = "debug" # CHANGED: Set to debug
|
||||||
|
data_dir = "test-data"
|
||||||
|
|
||||||
|
# Logging configuration for troubleshooting
|
||||||
|
[logging]
|
||||||
|
target = "all"
|
||||||
|
level = "debug"
|
||||||
|
[logging.console]
|
||||||
|
enabled = true
|
||||||
|
target = "stdout" # CHANGED: Log to stdout for visibility
|
||||||
|
format = "txt"
|
||||||
|
|
||||||
|
[[pipelines]]
|
||||||
|
name = "tcp-test"
|
||||||
|
[pipelines.auth]
|
||||||
|
type = "basic"
|
||||||
|
[[pipelines.auth.basic_auth.users]]
|
||||||
|
username = "testuser"
|
||||||
|
password_hash = "$HASH"
|
||||||
|
|
||||||
|
[[pipelines.sources]]
|
||||||
|
type = "tcp"
|
||||||
|
[pipelines.sources.options]
|
||||||
|
port = 5514
|
||||||
|
host = "127.0.0.1"
|
||||||
|
|
||||||
|
[[pipelines.sinks]]
|
||||||
|
type = "stdout"
|
||||||
|
|
||||||
|
# Second pipeline for HTTP
|
||||||
|
[[pipelines]]
|
||||||
|
name = "http-test"
|
||||||
|
[pipelines.auth]
|
||||||
|
type = "basic"
|
||||||
|
[[pipelines.auth.basic_auth.users]]
|
||||||
|
username = "httpuser"
|
||||||
|
password_hash = "$HASH"
|
||||||
|
|
||||||
|
[[pipelines.sources]]
|
||||||
|
type = "http"
|
||||||
|
[pipelines.sources.options]
|
||||||
|
port = 8080
|
||||||
|
host = "127.0.0.1"
|
||||||
|
path = "/ingest"
|
||||||
|
|
||||||
|
[[pipelines.sinks]]
|
||||||
|
type = "stdout" # CHANGED: Simplify to stdout for debugging
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Start LogWisp with visible debug output
|
||||||
|
echo "=== Starting LogWisp with debug logging ==="
|
||||||
|
./logwisp -c test-auth.toml 2>&1 | tee logwisp-debug.log &
|
||||||
|
LOGWISP_PID=$!
|
||||||
|
|
||||||
|
# Wait for startup with longer timeout
|
||||||
|
echo "Waiting for LogWisp to start..."
|
||||||
|
for i in {1..20}; do
|
||||||
|
if nc -z 127.0.0.1 5514 2>/dev/null && nc -z 127.0.0.1 8080 2>/dev/null; then
|
||||||
|
echo "LogWisp started successfully"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
if [ $i -eq 20 ]; then
|
||||||
|
echo "LogWisp failed to start. Check logwisp-debug.log"
|
||||||
|
kill $LOGWISP_PID 2>/dev/null || true
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
|
||||||
|
# Give extra time for auth initialization
|
||||||
|
sleep 2
|
||||||
|
|
||||||
|
echo "=== Testing HTTP Auth ==="
|
||||||
|
|
||||||
|
# Test with verbose curl to see headers
|
||||||
|
echo "Testing no auth (expecting 401)..."
|
||||||
|
curl -v -s -o response.txt -w "STATUS:%{http_code}\n" \
|
||||||
|
http://127.0.0.1:8080/ingest -d '{"test":"data"}' 2>&1 | tee curl-noauth.log | grep -E "STATUS:|< HTTP"
|
||||||
|
|
||||||
|
# Test invalid auth
|
||||||
|
echo "Testing invalid auth (expecting 401)..."
|
||||||
|
curl -v -s -o response.txt -w "STATUS:%{http_code}\n" \
|
||||||
|
-u baduser:badpass http://127.0.0.1:8080/ingest -d '{"test":"data"}' 2>&1 | tee curl-badauth.log | grep -E "STATUS:|< HTTP"
|
||||||
|
|
||||||
|
# Test valid auth with detailed output
|
||||||
|
echo "Testing valid auth (expecting 202/200)..."
|
||||||
|
curl -v -s -o response.txt -w "STATUS:%{http_code}\n" \
|
||||||
|
-u httpuser:secret123 http://127.0.0.1:8080/ingest \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{"message":"test log","level":"info"}' 2>&1 | tee curl-validauth.log | grep -E "STATUS:|< HTTP"
|
||||||
|
|
||||||
|
# Show response body if not 200/202
|
||||||
|
STATUS=$(grep "STATUS:" curl-validauth.log | cut -d: -f2)
|
||||||
|
if [ "$STATUS" != "200" ] && [ "$STATUS" != "202" ]; then
|
||||||
|
echo "Response body:"
|
||||||
|
cat response.txt
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check logs for auth-related errors
|
||||||
|
echo "=== Checking logs for auth errors ==="
|
||||||
|
grep -i "auth" logwisp-debug.log | grep -i "error" | tail -5 || echo "No auth errors found"
|
||||||
|
grep -i "authenticator" logwisp-debug.log | tail -5 || echo "No authenticator messages"
|
||||||
|
|
||||||
|
# Cleanup
|
||||||
|
echo "=== Cleanup ==="
|
||||||
|
kill $LOGWISP_PID 2>/dev/null || true
|
||||||
|
echo "Logs saved to logwisp-debug.log, curl-*.log"
|
||||||
|
# Optionally keep logs for analysis
|
||||||
|
# rm -f test-auth.toml auth_output.txt response.txt
|
||||||
|
# rm -rf test-logs test-data
|
||||||
Reference in New Issue
Block a user