Newer
Older
wg-portal / internal / common / configuration.go
@Christoph Haas Christoph Haas on 6 Nov 2020 2 KB initial commit
package common

import (
	"errors"
	"os"
	"reflect"

	"github.com/h44z/wg-portal/internal/wireguard"

	"github.com/h44z/wg-portal/internal/ldap"
	"github.com/kelseyhightower/envconfig"
	log "github.com/sirupsen/logrus"
	"gopkg.in/yaml.v3"
)

var ErrInvalidSpecification = errors.New("specification must be a struct pointer")

// LoadConfigFile parses yaml files. It uses to yaml annotation to store the data in a struct.
func loadConfigFile(cfg interface{}, filename string) error {
	s := reflect.ValueOf(cfg)

	if s.Kind() != reflect.Ptr {
		return ErrInvalidSpecification
	}
	s = s.Elem()
	if s.Kind() != reflect.Struct {
		return ErrInvalidSpecification
	}

	f, err := os.Open(filename)
	if err != nil {
		return err
	}
	defer f.Close()

	decoder := yaml.NewDecoder(f)
	err = decoder.Decode(cfg)
	if err != nil {
		return err
	}

	return nil
}

// LoadConfigEnv processes envconfig annotations and loads environment variables to the given configuration struct.
func loadConfigEnv(cfg interface{}) error {
	err := envconfig.Process("", cfg)
	if err != nil {
		return err
	}

	return nil
}

type Config struct {
	Core struct {
		ListeningAddress string `yaml:"listeningAddress" envconfig:"LISTENING_ADDRESS"`
		Title            string `yaml:"title" envconfig:"WEBSITE_TITLE"`
	} `yaml:"core"`

	LDAP               ldap.Config      `yaml:"ldap"`
	WG                 wireguard.Config `yaml:"wg"`
	AdminLdapGroup     string           `yaml:"adminLdapGroup" envconfig:"ADMIN_LDAP_GROUP"`
	LogoutRedirectPath string           `yaml:"logoutRedirectPath" envconfig:"LOGOUT_REDIRECT_PATH"`
	AuthRoutePrefix    string           `yaml:"authRoutePrefix" envconfig:"AUTH_ROUTE_PREFIX"`
}

func NewConfig() *Config {
	cfg := &Config{}

	// Default config
	cfg.Core.ListeningAddress = ":8080"
	cfg.Core.Title = "WireGuard VPN"
	cfg.LDAP.URL = "ldap://srv-ad01.company.local:389"
	cfg.LDAP.BaseDN = "DC=COMPANY,DC=LOCAL"
	cfg.LDAP.StartTLS = true
	cfg.LDAP.BindUser = "company\\ldap_wireguard"
	cfg.LDAP.BindPass = "SuperSecret"
	cfg.WG.DeviceName = "wg0"
	cfg.AdminLdapGroup = "CN=WireGuardAdmins,OU=_O_IT,DC=COMPANY,DC=LOCAL"
	cfg.LogoutRedirectPath = "/"
	cfg.AuthRoutePrefix = "/auth"

	// Load config from file and environment
	cfgFile, ok := os.LookupEnv("CONFIG_FILE")
	if !ok {
		cfgFile = "config.yml" // Default config file
	}
	err := loadConfigFile(cfg, cfgFile)
	if err != nil {
		log.Warnf("unable to load config.yml file: %v, using default configuration...", err)
	}
	err = loadConfigEnv(cfg)
	if err != nil {
		log.Warnf("unable to load environment config: %v", err)
	}

	return cfg
}