klmmr 53bae9d194
Some checks failed
Docker / Build and Push (push) Has been cancelled
github-pages / deploy (push) Has been cancelled
Docker / release (push) Has been cancelled
config: validate mail configuration certificates by default (#388)
Before this commit, the default was to not validate TLS certificates of
the SMTP server. This is perhaps a rather unexpected default and can be
considered insecure. This commit activates mail server TLS cert validation
by default.

This change might break some users' email configuration, if they did not
explicitly set the `mail.cert_validation` config variable. Nonetheless,
I think that the secure option should be the default option (e.g.,
to prevent man-in-the-middle attacks and breaching mail server login
credentials).

Signed-off-by: klmmr <35450576+klmmr@users.noreply.github.com>
2025-03-05 19:20:57 +01:00

193 lines
6.6 KiB
Go

package config
import (
"fmt"
"os"
"time"
"github.com/a8m/envsubst"
"github.com/sirupsen/logrus"
"gopkg.in/yaml.v2"
)
type Config struct {
Core struct {
// AdminUser defines the default administrator account that will be created
AdminUser string `yaml:"admin_user"`
AdminPassword string `yaml:"admin_password"`
AdminApiToken string `yaml:"admin_api_token"` // if set, the API access is enabled automatically
EditableKeys bool `yaml:"editable_keys"`
CreateDefaultPeer bool `yaml:"create_default_peer"`
CreateDefaultPeerOnCreation bool `yaml:"create_default_peer_on_creation"`
ReEnablePeerAfterUserEnable bool `yaml:"re_enable_peer_after_user_enable"`
DeletePeerAfterUserDeleted bool `yaml:"delete_peer_after_user_deleted"`
SelfProvisioningAllowed bool `yaml:"self_provisioning_allowed"`
ImportExisting bool `yaml:"import_existing"`
RestoreState bool `yaml:"restore_state"`
} `yaml:"core"`
Advanced struct {
LogLevel string `yaml:"log_level"`
LogPretty bool `yaml:"log_pretty"`
LogJson bool `yaml:"log_json"`
StartListenPort int `yaml:"start_listen_port"`
StartCidrV4 string `yaml:"start_cidr_v4"`
StartCidrV6 string `yaml:"start_cidr_v6"`
UseIpV6 bool `yaml:"use_ip_v6"`
ConfigStoragePath string `yaml:"config_storage_path"` // keep empty to disable config export to file
ExpiryCheckInterval time.Duration `yaml:"expiry_check_interval"`
RulePrioOffset int `yaml:"rule_prio_offset"`
RouteTableOffset int `yaml:"route_table_offset"`
ApiAdminOnly bool `yaml:"api_admin_only"` // if true, only admin users can access the API
} `yaml:"advanced"`
Statistics struct {
UsePingChecks bool `yaml:"use_ping_checks"`
PingCheckWorkers int `yaml:"ping_check_workers"`
PingUnprivileged bool `yaml:"ping_unprivileged"`
PingCheckInterval time.Duration `yaml:"ping_check_interval"`
DataCollectionInterval time.Duration `yaml:"data_collection_interval"`
CollectInterfaceData bool `yaml:"collect_interface_data"`
CollectPeerData bool `yaml:"collect_peer_data"`
CollectAuditData bool `yaml:"collect_audit_data"`
ListeningAddress string `yaml:"listening_address"`
} `yaml:"statistics"`
Mail MailConfig `yaml:"mail"`
Auth Auth `yaml:"auth"`
Database DatabaseConfig `yaml:"database"`
Web WebConfig `yaml:"web"`
}
func (c *Config) LogStartupValues() {
logrus.Infof("Log Level: %s", c.Advanced.LogLevel)
logrus.Debug("WireGuard Portal Features:")
logrus.Debugf(" - EditableKeys: %t", c.Core.EditableKeys)
logrus.Debugf(" - CreateDefaultPeerOnCreation: %t", c.Core.CreateDefaultPeerOnCreation)
logrus.Debugf(" - ReEnablePeerAfterUserEnable: %t", c.Core.ReEnablePeerAfterUserEnable)
logrus.Debugf(" - DeletePeerAfterUserDeleted: %t", c.Core.DeletePeerAfterUserDeleted)
logrus.Debugf(" - SelfProvisioningAllowed: %t", c.Core.SelfProvisioningAllowed)
logrus.Debugf(" - ImportExisting: %t", c.Core.ImportExisting)
logrus.Debugf(" - RestoreState: %t", c.Core.RestoreState)
logrus.Debugf(" - UseIpV6: %t", c.Advanced.UseIpV6)
logrus.Debugf(" - CollectInterfaceData: %t", c.Statistics.CollectInterfaceData)
logrus.Debugf(" - CollectPeerData: %t", c.Statistics.CollectPeerData)
logrus.Debugf(" - CollectAuditData: %t", c.Statistics.CollectAuditData)
logrus.Debug("WireGuard Portal Settings:")
logrus.Debugf(" - ConfigStoragePath: %s", c.Advanced.ConfigStoragePath)
logrus.Debugf(" - ExternalUrl: %s", c.Web.ExternalUrl)
logrus.Debug("WireGuard Portal Authentication:")
logrus.Debugf(" - OIDC Providers: %d", len(c.Auth.OpenIDConnect))
logrus.Debugf(" - OAuth Providers: %d", len(c.Auth.OAuth))
logrus.Debugf(" - Ldap Providers: %d", len(c.Auth.Ldap))
}
func defaultConfig() *Config {
cfg := &Config{}
cfg.Core.AdminUser = "admin@wgportal.local"
cfg.Core.AdminPassword = "wgportal"
cfg.Core.AdminApiToken = "" // by default, the API access is disabled
cfg.Core.ImportExisting = true
cfg.Core.RestoreState = true
cfg.Core.CreateDefaultPeer = false
cfg.Core.CreateDefaultPeerOnCreation = false
cfg.Core.EditableKeys = true
cfg.Core.SelfProvisioningAllowed = false
cfg.Core.ReEnablePeerAfterUserEnable = true
cfg.Core.DeletePeerAfterUserDeleted = false
cfg.Database = DatabaseConfig{
Type: "sqlite",
DSN: "data/sqlite.db",
}
cfg.Web = WebConfig{
RequestLogging: false,
ExternalUrl: "http://localhost:8888",
ListeningAddress: ":8888",
SessionIdentifier: "wgPortalSession",
SessionSecret: "very_secret",
CsrfSecret: "extremely_secret",
SiteTitle: "WireGuard Portal",
SiteCompanyName: "WireGuard Portal",
}
cfg.Advanced.LogLevel = "info"
cfg.Advanced.StartListenPort = 51820
cfg.Advanced.StartCidrV4 = "10.11.12.0/24"
cfg.Advanced.StartCidrV6 = "fdfd:d3ad:c0de:1234::0/64"
cfg.Advanced.UseIpV6 = true
cfg.Advanced.ExpiryCheckInterval = 15 * time.Minute
cfg.Advanced.RulePrioOffset = 20000
cfg.Advanced.RouteTableOffset = 20000
cfg.Advanced.ApiAdminOnly = true
cfg.Statistics.UsePingChecks = true
cfg.Statistics.PingCheckWorkers = 10
cfg.Statistics.PingUnprivileged = false
cfg.Statistics.PingCheckInterval = 1 * time.Minute
cfg.Statistics.DataCollectionInterval = 1 * time.Minute
cfg.Statistics.CollectInterfaceData = true
cfg.Statistics.CollectPeerData = true
cfg.Statistics.CollectAuditData = true
cfg.Statistics.ListeningAddress = ":8787"
cfg.Mail = MailConfig{
Host: "127.0.0.1",
Port: 25,
Encryption: MailEncryptionNone,
CertValidation: true,
Username: "",
Password: "",
AuthType: MailAuthPlain,
From: "Wireguard Portal <noreply@wireguard.local>",
LinkOnly: false,
}
return cfg
}
func GetConfig() (*Config, error) {
cfg := defaultConfig()
// override config values from YAML file
cfgFileName := "config/config.yml"
if envCfgFileName := os.Getenv("WG_PORTAL_CONFIG"); envCfgFileName != "" {
cfgFileName = envCfgFileName
}
if err := loadConfigFile(cfg, cfgFileName); err != nil {
return nil, fmt.Errorf("failed to load config from yaml: %w", err)
}
return cfg, nil
}
func loadConfigFile(cfg any, filename string) error {
data, err := envsubst.ReadFile(filename)
if err != nil {
if os.IsNotExist(err) {
logrus.Warnf("Config file %s not found, using default values", filename)
return nil
}
return fmt.Errorf("envsubst error: %v", err)
}
err = yaml.Unmarshal(data, cfg)
if err != nil {
return fmt.Errorf("yaml error: %v", err)
}
return nil
}