507dee6431
Fuehrt archiving_rules ein (PROJ-43-Basis: Tabelle + CRUD-API + Admin-UI) und erweitert die Retention-Logik (PROJ-34) um Regel-basierte Fristen, eine globale Mindestfrist (min_retention_days) sowie Nachvollziehbarkeit der Frist-Quelle (retain_until_source) in API und Mail-Detailansicht.
158 lines
5.6 KiB
Go
158 lines
5.6 KiB
Go
package config
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"strings"
|
|
|
|
"gopkg.in/yaml.v3"
|
|
)
|
|
|
|
// APIConfig holds configuration for the HTTP API server.
|
|
type APIConfig struct {
|
|
Bind string `yaml:"bind"`
|
|
Secret string `yaml:"secret"`
|
|
// SecureCookies sets the Secure flag on session cookies.
|
|
// Enable when TLS is terminated at this server or at a trusted reverse proxy.
|
|
SecureCookies bool `yaml:"secure_cookies"`
|
|
// TrustedProxies is a list of IP addresses or CIDR ranges whose
|
|
// X-Forwarded-For header is trusted. Empty = trust no proxy (use r.RemoteAddr).
|
|
TrustedProxies []string `yaml:"trusted_proxies"`
|
|
}
|
|
|
|
// MetricsConfig holds settings for the Prometheus /metrics endpoint.
|
|
type MetricsConfig struct {
|
|
Enabled bool `yaml:"enabled"` // default: false
|
|
Token string `yaml:"token"` // optional Bearer token to protect /metrics
|
|
}
|
|
|
|
// Config is the full application configuration loaded from YAML.
|
|
type Config struct {
|
|
Server ServerConfig `yaml:"server"`
|
|
Storage StorageConfig `yaml:"storage"`
|
|
Database DatabaseConfig `yaml:"database"`
|
|
SMTP SMTPConfig `yaml:"smtp"`
|
|
SMTPOut SMTPOutConfig `yaml:"smtp_out"`
|
|
API APIConfig `yaml:"api"`
|
|
Index IndexConfig `yaml:"index"`
|
|
Audit AuditConfig `yaml:"audit"`
|
|
Logging LoggingConfig `yaml:"logging"`
|
|
IMAPServer IMAPServerConfig `yaml:"imap_server"`
|
|
Metrics MetricsConfig `yaml:"metrics"`
|
|
}
|
|
|
|
// IMAPServerConfig holds settings for the embedded read-only IMAP archive server.
|
|
type IMAPServerConfig struct {
|
|
Enabled bool `yaml:"enabled"`
|
|
Bind string `yaml:"bind"` // plain: ":1143", TLS: ":993"
|
|
TLSCert string `yaml:"tls_cert"` // path to PEM certificate; if set, TLS is enabled
|
|
TLSKey string `yaml:"tls_key"` // path to PEM private key
|
|
FQDN string `yaml:"-"` // set at runtime from server.fqdn
|
|
}
|
|
|
|
// ServerConfig holds port settings for the main services.
|
|
type ServerConfig struct {
|
|
FQDN string `yaml:"fqdn"` // Fully Qualified Domain Name — used in SMTP EHLO, IMAP greeting, and generated links
|
|
APIPort int `yaml:"api_port"`
|
|
SMTPPort int `yaml:"smtp_port"`
|
|
}
|
|
|
|
// SMTPOutConfig holds settings for outgoing email (password reset, invitations).
|
|
type SMTPOutConfig struct {
|
|
Host string `yaml:"host"`
|
|
Port int `yaml:"port"`
|
|
User string `yaml:"user"`
|
|
Password string `yaml:"password"`
|
|
TLS bool `yaml:"tls"`
|
|
From string `yaml:"from"` // e.g. "archivmail <noreply@firma.de>"
|
|
}
|
|
|
|
// StorageConfig holds file system paths for email storage.
|
|
type StorageConfig struct {
|
|
StorePath string `yaml:"store_path"`
|
|
AStorePath string `yaml:"astore_path"`
|
|
Keyfile string `yaml:"keyfile"`
|
|
RetentionDays int `yaml:"retention_days"` // 0 = kein Lock (GoBD-Compliance: z.B. 3650 für 10 Jahre)
|
|
MinRetentionDays int `yaml:"min_retention_days"` // PROJ-51: globale Mindestfrist; Regeln/Tenants dürfen nur verlängern (0 = keine)
|
|
Compress bool `yaml:"compress"` // gzip-Kompression vor AES-256-GCM (spart ~40-60% Disk)
|
|
}
|
|
|
|
// DatabaseConfig holds PostgreSQL connection settings.
|
|
type DatabaseConfig struct {
|
|
Host string `yaml:"host"`
|
|
Port int `yaml:"port"`
|
|
Name string `yaml:"name"`
|
|
User string `yaml:"user"`
|
|
Password string `yaml:"password"`
|
|
SSLMode string `yaml:"sslmode"`
|
|
}
|
|
|
|
// DSN builds a PostgreSQL connection string from the config fields.
|
|
func (d DatabaseConfig) DSN() string {
|
|
return fmt.Sprintf("postgres://%s:%s@%s:%d/%s?sslmode=%s",
|
|
d.User, d.Password, d.Host, d.Port, d.Name, d.SSLMode)
|
|
}
|
|
|
|
// SMTPConfig holds settings for the embedded SMTP server.
|
|
// SEC-26: AllowedIPs uses fail-closed logic. An empty list means NO IP is
|
|
// allowed to connect. To accept from any IP, explicitly set:
|
|
// allowed_ips: ["0.0.0.0/0", "::/0"]
|
|
type SMTPConfig struct {
|
|
Enabled bool `yaml:"enabled"`
|
|
Bind string `yaml:"bind"`
|
|
Domain string `yaml:"domain"`
|
|
TLSCert string `yaml:"tls_cert"`
|
|
TLSKey string `yaml:"tls_key"`
|
|
MaxSizeMB int `yaml:"max_size_mb"`
|
|
AllowedIPs []string `yaml:"allowed_ips"`
|
|
TenantRouting string `yaml:"tenant_routing"` // "domain" or "default"
|
|
DefaultTenantID int64 `yaml:"default_tenant_id"` // used when routing is "default" or domain lookup fails
|
|
}
|
|
|
|
// IndexConfig holds full-text index settings.
|
|
type IndexConfig struct {
|
|
Path string `yaml:"path"`
|
|
Backend string `yaml:"backend"`
|
|
BatchSize int `yaml:"batch_size"`
|
|
AsyncQueueSize int `yaml:"async_queue_size"`
|
|
ManticoreDSN string `yaml:"manticore_dsn"` // DSN for Manticore backend (default: "manticore@tcp(127.0.0.1:9306)/")
|
|
}
|
|
|
|
// DefaultAuditLogPath is the default location of the append-only JSON-Lines
|
|
// audit log file (PROJ-48) when audit.log_path is not configured.
|
|
const DefaultAuditLogPath = "/var/log/archivmail/audit.log"
|
|
|
|
// AuditConfig holds audit log settings.
|
|
type AuditConfig struct {
|
|
LogPath string `yaml:"log_path"`
|
|
RetentionDays int `yaml:"retention_days"`
|
|
}
|
|
|
|
// ResolvedLogPath returns the configured audit log file path, falling back to
|
|
// DefaultAuditLogPath when unset.
|
|
func (a AuditConfig) ResolvedLogPath() string {
|
|
if strings.TrimSpace(a.LogPath) == "" {
|
|
return DefaultAuditLogPath
|
|
}
|
|
return a.LogPath
|
|
}
|
|
|
|
// LoggingConfig holds application logging settings.
|
|
type LoggingConfig struct {
|
|
Path string `yaml:"path"`
|
|
Level string `yaml:"level"`
|
|
}
|
|
|
|
// Load reads a YAML config file from path and returns a parsed Config.
|
|
func Load(path string) (*Config, error) {
|
|
data, err := os.ReadFile(path)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var cfg Config
|
|
if err := yaml.Unmarshal(data, &cfg); err != nil {
|
|
return nil, err
|
|
}
|
|
return &cfg, nil
|
|
}
|