v1.0.8: Add configurable log level and immediate service stop
Some checks failed
Build RPM Package / Build RPM Packages (CentOS 7, Rocky 8/9/10) (push) Has been cancelled
Some checks failed
Build RPM Package / Build RPM Packages (CentOS 7, Rocky 8/9/10) (push) Has been cancelled
- Add log_level config option (debug, info, warn, error) - Add JA4SENTINEL_LOG_LEVEL environment variable support - Set TimeoutStopSec=2 for immediate stop on restart/stop - Consolidate config files into single example (config.yml.example) - Update RPM changelog Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
This commit is contained in:
@ -35,7 +35,7 @@ COPY . .
|
|||||||
|
|
||||||
# Build binary for Linux
|
# Build binary for Linux
|
||||||
# Binary will be dynamically linked but compatible with all RHEL-based distros
|
# Binary will be dynamically linked but compatible with all RHEL-based distros
|
||||||
ARG VERSION=1.0.7
|
ARG VERSION=1.0.8
|
||||||
ARG BUILD_TIME=""
|
ARG BUILD_TIME=""
|
||||||
ARG GIT_COMMIT=""
|
ARG GIT_COMMIT=""
|
||||||
RUN mkdir -p dist && \
|
RUN mkdir -p dist && \
|
||||||
@ -53,7 +53,7 @@ FROM rockylinux:9 AS rpm-builder
|
|||||||
WORKDIR /package
|
WORKDIR /package
|
||||||
|
|
||||||
# VERSION must be redeclared for each stage that needs it
|
# VERSION must be redeclared for each stage that needs it
|
||||||
ARG VERSION=1.0.7
|
ARG VERSION=1.0.8
|
||||||
|
|
||||||
# Install rpm-build tools (Rocky Linux 9)
|
# Install rpm-build tools (Rocky Linux 9)
|
||||||
RUN dnf install -y \
|
RUN dnf install -y \
|
||||||
@ -72,7 +72,7 @@ COPY packaging/rpm/ja4sentinel.spec /root/rpmbuild/SPECS/ja4sentinel.spec
|
|||||||
# Copy binary from Go builder and other files to SOURCES
|
# Copy binary from Go builder and other files to SOURCES
|
||||||
COPY --from=builder /build/dist/ja4sentinel /root/rpmbuild/SOURCES/ja4sentinel
|
COPY --from=builder /build/dist/ja4sentinel /root/rpmbuild/SOURCES/ja4sentinel
|
||||||
COPY packaging/systemd/ja4sentinel.service /root/rpmbuild/SOURCES/ja4sentinel.service
|
COPY packaging/systemd/ja4sentinel.service /root/rpmbuild/SOURCES/ja4sentinel.service
|
||||||
COPY packaging/systemd/config.yml /root/rpmbuild/SOURCES/config.yml
|
COPY config.yml.example /root/rpmbuild/SOURCES/config.yml
|
||||||
|
|
||||||
# Set permissions
|
# Set permissions
|
||||||
RUN chmod 755 /root/rpmbuild/SOURCES/ja4sentinel && \
|
RUN chmod 755 /root/rpmbuild/SOURCES/ja4sentinel && \
|
||||||
|
|||||||
@ -23,6 +23,7 @@ type Config struct {
|
|||||||
BPFFilter string `json:"bpf_filter,omitempty"`
|
BPFFilter string `json:"bpf_filter,omitempty"`
|
||||||
FlowTimeoutSec int `json:"flow_timeout_sec,omitempty"` // Timeout for TLS handshake extraction (default: 30)
|
FlowTimeoutSec int `json:"flow_timeout_sec,omitempty"` // Timeout for TLS handshake extraction (default: 30)
|
||||||
PacketBufferSize int `json:"packet_buffer_size,omitempty"` // Buffer size for packet channel (default: 1000)
|
PacketBufferSize int `json:"packet_buffer_size,omitempty"` // Buffer size for packet channel (default: 1000)
|
||||||
|
LogLevel string `json:"log_level,omitempty"` // Log level: debug, info, warn, error (default: info)
|
||||||
}
|
}
|
||||||
|
|
||||||
// IPMeta contains IP metadata for stack fingerprinting
|
// IPMeta contains IP metadata for stack fingerprinting
|
||||||
@ -241,6 +242,7 @@ const (
|
|||||||
DefaultBPFFilter = ""
|
DefaultBPFFilter = ""
|
||||||
DefaultFlowTimeout = 30 // seconds
|
DefaultFlowTimeout = 30 // seconds
|
||||||
DefaultPacketBuffer = 1000 // packet channel buffer size
|
DefaultPacketBuffer = 1000 // packet channel buffer size
|
||||||
|
DefaultLogLevel = "info"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DefaultConfig returns an AppConfig with sensible default values.
|
// DefaultConfig returns an AppConfig with sensible default values.
|
||||||
@ -256,6 +258,7 @@ func DefaultConfig() AppConfig {
|
|||||||
BPFFilter: DefaultBPFFilter,
|
BPFFilter: DefaultBPFFilter,
|
||||||
FlowTimeoutSec: DefaultFlowTimeout,
|
FlowTimeoutSec: DefaultFlowTimeout,
|
||||||
PacketBufferSize: DefaultPacketBuffer,
|
PacketBufferSize: DefaultPacketBuffer,
|
||||||
|
LogLevel: DefaultLogLevel,
|
||||||
},
|
},
|
||||||
Outputs: []OutputConfig{},
|
Outputs: []OutputConfig{},
|
||||||
}
|
}
|
||||||
|
|||||||
@ -22,7 +22,7 @@ import (
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
// Version information (set via ldflags)
|
// Version information (set via ldflags)
|
||||||
Version = "1.0.7"
|
Version = "1.0.8"
|
||||||
BuildTime = "unknown"
|
BuildTime = "unknown"
|
||||||
GitCommit = "unknown"
|
GitCommit = "unknown"
|
||||||
)
|
)
|
||||||
@ -38,9 +38,22 @@ func main() {
|
|||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create logger factory
|
// Load configuration
|
||||||
|
cfgLoader := config.NewLoader(*configPath)
|
||||||
|
appConfig, err := cfgLoader.Load()
|
||||||
|
if err != nil {
|
||||||
|
// Create logger with default level for error reporting
|
||||||
|
loggerFactory := &logging.LoggerFactory{}
|
||||||
|
appLogger := loggerFactory.NewDefaultLogger()
|
||||||
|
appLogger.Error("main", "Failed to load configuration", map[string]string{
|
||||||
|
"error": err.Error(),
|
||||||
|
})
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create logger factory with configured log level
|
||||||
loggerFactory := &logging.LoggerFactory{}
|
loggerFactory := &logging.LoggerFactory{}
|
||||||
appLogger := loggerFactory.NewDefaultLogger()
|
appLogger := loggerFactory.NewLogger(appConfig.Core.LogLevel)
|
||||||
|
|
||||||
appLogger.Info("main", "Starting ja4sentinel", map[string]string{
|
appLogger.Info("main", "Starting ja4sentinel", map[string]string{
|
||||||
"version": Version,
|
"version": Version,
|
||||||
@ -48,19 +61,10 @@ func main() {
|
|||||||
"git_commit": GitCommit,
|
"git_commit": GitCommit,
|
||||||
})
|
})
|
||||||
|
|
||||||
// Load configuration
|
|
||||||
cfgLoader := config.NewLoader(*configPath)
|
|
||||||
appConfig, err := cfgLoader.Load()
|
|
||||||
if err != nil {
|
|
||||||
appLogger.Error("main", "Failed to load configuration", map[string]string{
|
|
||||||
"error": err.Error(),
|
|
||||||
})
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
appLogger.Info("main", "Configuration loaded", map[string]string{
|
appLogger.Info("main", "Configuration loaded", map[string]string{
|
||||||
"interface": appConfig.Core.Interface,
|
"interface": appConfig.Core.Interface,
|
||||||
"listen_ports": formatPorts(appConfig.Core.ListenPorts),
|
"listen_ports": formatPorts(appConfig.Core.ListenPorts),
|
||||||
|
"log_level": appConfig.Core.LogLevel,
|
||||||
})
|
})
|
||||||
|
|
||||||
// Create context with cancellation for graceful shutdown
|
// Create context with cancellation for graceful shutdown
|
||||||
|
|||||||
@ -19,6 +19,10 @@ core:
|
|||||||
# Buffer size for packet channel (default: 1000, increase for high-traffic environments)
|
# Buffer size for packet channel (default: 1000, increase for high-traffic environments)
|
||||||
packet_buffer_size: 1000
|
packet_buffer_size: 1000
|
||||||
|
|
||||||
|
# Log level: debug, info, warn, error (default: info)
|
||||||
|
# Can be overridden by JA4SENTINEL_LOG_LEVEL environment variable
|
||||||
|
log_level: info
|
||||||
|
|
||||||
outputs:
|
outputs:
|
||||||
# Output to stdout (JSON lines)
|
# Output to stdout (JSON lines)
|
||||||
- type: stdout
|
- type: stdout
|
||||||
|
|||||||
@ -104,6 +104,11 @@ func (l *LoaderImpl) loadFromEnv(config api.AppConfig) api.AppConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// JA4SENTINEL_LOG_LEVEL
|
||||||
|
if val := os.Getenv("JA4SENTINEL_LOG_LEVEL"); val != "" {
|
||||||
|
config.Core.LogLevel = val
|
||||||
|
}
|
||||||
|
|
||||||
return config
|
return config
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -166,6 +171,10 @@ func mergeConfigs(base, override api.AppConfig) api.AppConfig {
|
|||||||
result.Core.PacketBufferSize = override.Core.PacketBufferSize
|
result.Core.PacketBufferSize = override.Core.PacketBufferSize
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if override.Core.LogLevel != "" {
|
||||||
|
result.Core.LogLevel = override.Core.LogLevel
|
||||||
|
}
|
||||||
|
|
||||||
if len(override.Outputs) > 0 {
|
if len(override.Outputs) > 0 {
|
||||||
result.Outputs = override.Outputs
|
result.Outputs = override.Outputs
|
||||||
}
|
}
|
||||||
@ -196,6 +205,19 @@ func (l *LoaderImpl) validate(config api.AppConfig) error {
|
|||||||
return fmt.Errorf("packet_buffer_size must be between 1 and 1000000")
|
return fmt.Errorf("packet_buffer_size must be between 1 and 1000000")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Validate log level
|
||||||
|
validLogLevels := map[string]struct{}{
|
||||||
|
"debug": {},
|
||||||
|
"info": {},
|
||||||
|
"warn": {},
|
||||||
|
"error": {},
|
||||||
|
}
|
||||||
|
if config.Core.LogLevel != "" {
|
||||||
|
if _, ok := validLogLevels[config.Core.LogLevel]; !ok {
|
||||||
|
return fmt.Errorf("log_level must be one of: debug, info, warn, error")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
allowedTypes := map[string]struct{}{
|
allowedTypes := map[string]struct{}{
|
||||||
"stdout": {},
|
"stdout": {},
|
||||||
"file": {},
|
"file": {},
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
%if %{defined build_version}
|
%if %{defined build_version}
|
||||||
%define spec_version %{build_version}
|
%define spec_version %{build_version}
|
||||||
%else
|
%else
|
||||||
%define spec_version 1.0.7
|
%define spec_version 1.0.8
|
||||||
%endif
|
%endif
|
||||||
|
|
||||||
Name: ja4sentinel
|
Name: ja4sentinel
|
||||||
@ -117,6 +117,12 @@ fi
|
|||||||
%dir /var/run/logcorrelator
|
%dir /var/run/logcorrelator
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Sun Mar 01 2026 Jacquin Antoine <rpm@arkel.fr> - 1.0.8-1
|
||||||
|
- Add configurable log level (debug, info, warn, error) via config.yml
|
||||||
|
- Add JA4SENTINEL_LOG_LEVEL environment variable support
|
||||||
|
- Set TimeoutStopSec=2 for immediate service stop on restart/stop
|
||||||
|
- Consolidate config files into single example (config.yml.example)
|
||||||
|
|
||||||
* Sat Feb 28 2026 Jacquin Antoine <rpm@arkel.fr> - 1.0.4-1
|
* Sat Feb 28 2026 Jacquin Antoine <rpm@arkel.fr> - 1.0.4-1
|
||||||
- Add systemd sdnotify support (READY, WATCHDOG, STOPPING signals)
|
- Add systemd sdnotify support (READY, WATCHDOG, STOPPING signals)
|
||||||
- Enable systemd watchdog with 30s timeout
|
- Enable systemd watchdog with 30s timeout
|
||||||
|
|||||||
@ -1,39 +0,0 @@
|
|||||||
# Default configuration file for ja4sentinel
|
|
||||||
# This file is installed as /etc/ja4sentinel/config.yml.default
|
|
||||||
|
|
||||||
core:
|
|
||||||
# Network interface to capture traffic from
|
|
||||||
# Will be overridden by JA4SENTINEL_INTERFACE env var if set
|
|
||||||
interface: eth0
|
|
||||||
|
|
||||||
# TCP ports to monitor for TLS handshakes
|
|
||||||
listen_ports:
|
|
||||||
- 443
|
|
||||||
- 8443
|
|
||||||
|
|
||||||
# Optional BPF filter (leave empty for auto-generated filter based on listen_ports)
|
|
||||||
bpf_filter: ""
|
|
||||||
|
|
||||||
# Timeout in seconds for TLS handshake extraction (default: 30)
|
|
||||||
flow_timeout_sec: 30
|
|
||||||
|
|
||||||
# Buffer size for packet channel (default: 1000, increase for high-traffic environments)
|
|
||||||
packet_buffer_size: 1000
|
|
||||||
|
|
||||||
outputs:
|
|
||||||
# Output to stdout (JSON lines) - disabled by default for production
|
|
||||||
- type: stdout
|
|
||||||
enabled: false
|
|
||||||
params: {}
|
|
||||||
|
|
||||||
# Output to file
|
|
||||||
- type: file
|
|
||||||
enabled: true
|
|
||||||
params:
|
|
||||||
path: /var/log/ja4sentinel/ja4.log
|
|
||||||
|
|
||||||
# Output to UNIX socket (for systemd/journald or other consumers)
|
|
||||||
- type: unix_socket
|
|
||||||
enabled: true
|
|
||||||
params:
|
|
||||||
socket_path: /var/run/ja4sentinel.sock
|
|
||||||
@ -13,6 +13,7 @@ ExecStart=/usr/bin/ja4sentinel --config /etc/ja4sentinel/config.yml
|
|||||||
Restart=on-failure
|
Restart=on-failure
|
||||||
RestartSec=5
|
RestartSec=5
|
||||||
WatchdogSec=30
|
WatchdogSec=30
|
||||||
|
TimeoutStopSec=2
|
||||||
NotifyAccess=main
|
NotifyAccess=main
|
||||||
Environment=JA4SENTINEL_LOG_LEVEL=info
|
Environment=JA4SENTINEL_LOG_LEVEL=info
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user