v0.4.1 authentication impelemented, not tested and docs not updated

This commit is contained in:
2025-09-23 12:03:42 -04:00
parent 4248d399b3
commit 45b2093569
21 changed files with 1779 additions and 453 deletions

View File

@ -3,8 +3,6 @@ package config
import (
"fmt"
"net"
"strings"
)
type AuthConfig struct {

View File

@ -3,7 +3,6 @@ package config
import (
"fmt"
"net"
"strings"
)
@ -29,37 +28,6 @@ type RateLimitConfig struct {
MaxEntrySizeBytes int64 `toml:"max_entry_size_bytes"`
}
func validateNetAccess(pipelineName string, cfg *NetAccessConfig) error {
if cfg == nil {
return nil
}
// Validate CIDR notation
for _, cidr := range cfg.IPWhitelist {
if !strings.Contains(cidr, "/") {
cidr = cidr + "/32"
}
if _, _, err := net.ParseCIDR(cidr); err != nil {
if net.ParseIP(cidr) == nil {
return fmt.Errorf("pipeline '%s': invalid IP whitelist entry: %s", pipelineName, cidr)
}
}
}
for _, cidr := range cfg.IPBlacklist {
if !strings.Contains(cidr, "/") {
cidr = cidr + "/32"
}
if _, _, err := net.ParseCIDR(cidr); err != nil {
if net.ParseIP(cidr) == nil {
return fmt.Errorf("pipeline '%s': invalid IP blacklist entry: %s", pipelineName, cidr)
}
}
}
return nil
}
func validateRateLimit(pipelineName string, cfg *RateLimitConfig) error {
if cfg == nil {
return nil

View File

@ -20,9 +20,6 @@ type PipelineConfig struct {
// Rate limiting
RateLimit *RateLimitConfig `toml:"rate_limit"`
// Network access control (IP filtering)
NetAccess *NetAccessConfig `toml:"net_access"`
// Filter configuration
Filters []FilterConfig `toml:"filters"`
@ -37,12 +34,6 @@ type PipelineConfig struct {
Auth *AuthConfig `toml:"auth"`
}
// NetAccessConfig defines IP-based access control lists
type NetAccessConfig struct {
IPWhitelist []string `toml:"ip_whitelist"`
IPBlacklist []string `toml:"ip_blacklist"`
}
// SourceConfig represents an input data source
type SourceConfig struct {
// Source type: "directory", "file", "stdin", etc.
@ -132,6 +123,13 @@ func validateSource(pipelineName string, sourceIndex int, cfg *SourceConfig) err
}
}
// CHANGED: Validate SSL if present
if ssl, ok := cfg.Options["ssl"].(map[string]any); ok {
if err := validateSSLOptions("HTTP source", pipelineName, sourceIndex, ssl); err != nil {
return err
}
}
case "tcp":
// Validate TCP source options
port, ok := cfg.Options["port"].(int64)
@ -147,6 +145,13 @@ func validateSource(pipelineName string, sourceIndex int, cfg *SourceConfig) err
}
}
// CHANGED: Validate SSL if present
if ssl, ok := cfg.Options["ssl"].(map[string]any); ok {
if err := validateSSLOptions("TCP source", pipelineName, sourceIndex, ssl); err != nil {
return err
}
}
default:
return fmt.Errorf("pipeline '%s' source[%d]: unknown source type '%s'",
pipelineName, sourceIndex, cfg.Type)

View File

@ -1,7 +1,11 @@
// FILE: logwisp/src/internal/config/server.go
package config
import "fmt"
import (
"fmt"
"net"
"strings"
)
type TCPConfig struct {
Enabled bool `toml:"enabled"`
@ -49,6 +53,10 @@ type NetLimitConfig struct {
// Enable net limiting
Enabled bool `toml:"enabled"`
// IP Access Control Lists
IPWhitelist []string `toml:"ip_whitelist"`
IPBlacklist []string `toml:"ip_blacklist"`
// Requests per second per client
RequestsPerSecond float64 `toml:"requests_per_second"`
@ -90,6 +98,33 @@ func validateNetLimitOptions(serverType, pipelineName string, sinkIndex int, rl
return nil
}
// Validate IP lists if present
if ipWhitelist, ok := rl["ip_whitelist"].([]any); ok {
for i, entry := range ipWhitelist {
entryStr, ok := entry.(string)
if !ok {
continue
}
if err := validateIPv4Entry(entryStr); err != nil {
return fmt.Errorf("pipeline '%s' sink[%d] %s: whitelist[%d] %v",
pipelineName, sinkIndex, serverType, i, err)
}
}
}
if ipBlacklist, ok := rl["ip_blacklist"].([]any); ok {
for i, entry := range ipBlacklist {
entryStr, ok := entry.(string)
if !ok {
continue
}
if err := validateIPv4Entry(entryStr); err != nil {
return fmt.Errorf("pipeline '%s' sink[%d] %s: blacklist[%d] %v",
pipelineName, sinkIndex, serverType, i, err)
}
}
}
// Validate requests per second
rps, ok := rl["requests_per_second"].(float64)
if !ok || rps <= 0 {
@ -132,5 +167,39 @@ func validateNetLimitOptions(serverType, pipelineName string, sinkIndex int, rl
}
}
return nil
}
// validateIPv4Entry ensures an IP or CIDR is IPv4
func validateIPv4Entry(entry string) error {
// Handle single IP
if !strings.Contains(entry, "/") {
ip := net.ParseIP(entry)
if ip == nil {
return fmt.Errorf("invalid IP address: %s", entry)
}
if ip.To4() == nil {
return fmt.Errorf("IPv6 not supported (IPv4-only): %s", entry)
}
return nil
}
// Handle CIDR
ipAddr, ipNet, err := net.ParseCIDR(entry)
if err != nil {
return fmt.Errorf("invalid CIDR: %s", entry)
}
// Check if the IP is IPv4
if ipAddr.To4() == nil {
return fmt.Errorf("IPv6 CIDR not supported (IPv4-only): %s", entry)
}
// Verify the network mask is appropriate for IPv4
_, bits := ipNet.Mask.Size()
if bits != 32 {
return fmt.Errorf("invalid IPv4 CIDR mask (got %d bits, expected 32): %s", bits, entry)
}
return nil
}

View File

@ -1,7 +1,10 @@
// FILE: logwisp/src/internal/config/ssl.go
package config
import "fmt"
import (
"fmt"
"os"
)
type SSLConfig struct {
Enabled bool `toml:"enabled"`
@ -13,6 +16,9 @@ type SSLConfig struct {
ClientCAFile string `toml:"client_ca_file"`
VerifyClientCert bool `toml:"verify_client_cert"`
// Option to skip verification for clients
InsecureSkipVerify bool `toml:"insecure_skip_verify"`
// TLS version constraints
MinVersion string `toml:"min_version"` // "TLS1.2", "TLS1.3"
MaxVersion string `toml:"max_version"`
@ -31,11 +37,27 @@ func validateSSLOptions(serverType, pipelineName string, sinkIndex int, ssl map[
pipelineName, sinkIndex, serverType)
}
// Validate that certificate files exist and are readable
if _, err := os.Stat(certFile); err != nil {
return fmt.Errorf("pipeline '%s' sink[%d] %s: cert_file is not accessible: %w",
pipelineName, sinkIndex, serverType, err)
}
if _, err := os.Stat(keyFile); err != nil {
return fmt.Errorf("pipeline '%s' sink[%d] %s: key_file is not accessible: %w",
pipelineName, sinkIndex, serverType, err)
}
if clientAuth, ok := ssl["client_auth"].(bool); ok && clientAuth {
if caFile, ok := ssl["client_ca_file"].(string); !ok || caFile == "" {
caFile, caOk := ssl["client_ca_file"].(string)
if !caOk || caFile == "" {
return fmt.Errorf("pipeline '%s' sink[%d] %s: client auth enabled but CA file not specified",
pipelineName, sinkIndex, serverType)
}
// Validate that the client CA file exists and is readable
if _, err := os.Stat(caFile); err != nil {
return fmt.Errorf("pipeline '%s' sink[%d] %s: client_ca_file is not accessible: %w",
pipelineName, sinkIndex, serverType, err)
}
}
// Validate TLS versions

View File

@ -72,11 +72,6 @@ func (c *Config) validate() error {
}
}
// Validate net access if present
if err := validateNetAccess(pipeline.Name, pipeline.NetAccess); err != nil {
return err
}
// Validate auth if present
if err := validateAuth(pipeline.Name, pipeline.Auth); err != nil {
return err