Skip to content
Snippets Groups Projects
config.go 2.61 KiB
Newer Older
  • Learn to ignore specific revisions
  • ale's avatar
    ale committed
    package acmeserver
    
    import (
    
    ale's avatar
    ale committed
    	"errors"
    	"fmt"
    
    ale's avatar
    ale committed
    	"io/ioutil"
    	"log"
    	"path/filepath"
    
    	"gopkg.in/yaml.v2"
    
    	"git.autistici.org/ai3/go-common/clientutil"
    )
    
    // Config holds the configuration for an acmeserver instance.
    
    ale's avatar
    ale committed
    //
    // nolint: maligned
    
    ale's avatar
    ale committed
    type Config struct {
    	Addr string `yaml:"addr"`
    
    
    ale's avatar
    ale committed
    	Testing              bool   `yaml:"testing"`
    	DirectoryURL         string `yaml:"directory_url"`
    	DefaultChallengeType string `yaml:"default_challenge"`
    	UseRSA               bool   `yaml:"use_rsa"`
    	RenewalDays          int    `yaml:"renewal_days"`
    	Email                string `yaml:"email"`
    
    
    ale's avatar
    ale committed
    	Dir    string                    `yaml:"cert_dir"`
    	ReplDS *clientutil.BackendConfig `yaml:"replds"`
    
    ale's avatar
    ale committed
    
    	HTTP struct {
    		Enabled bool `yaml:"enabled"`
    	} `yaml:"http"`
    
    	DNS struct {
    		Enabled       bool     `yaml:"enabled"`
    		Nameservers   []string `yaml:"nameservers"`
    		TSIGKeyName   string   `yaml:"tsig_key_name"`
    		TSIGKeyAlgo   string   `yaml:"tsig_key_algo"`
    		TSIGKeySecret string   `yaml:"tsig_key_secret"`
    	} `yaml:"dns"`
    
    ale's avatar
    ale committed
    }
    
    
    ale's avatar
    ale committed
    // This is all the configuration we need to generate a certificate.
    
    ale's avatar
    ale committed
    type certConfig struct {
    
    ale's avatar
    ale committed
    	// List of names for this certificate. The first one will be
    	// the certificate CN, all of them will be subjectAltNames.
    	Names []string `yaml:"names"`
    
    	// Challenge type to use for this domain. If empty, the
    	// defaults will be applied.
    	ChallengeType string `yaml:"challenge,omitempty"`
    
    ale's avatar
    ale committed
    }
    
    
    ale's avatar
    ale committed
    func (c *certConfig) check() error {
    	if len(c.Names) == 0 {
    		return errors.New("empty names list")
    
    ale's avatar
    ale committed
    	}
    
    ale's avatar
    ale committed
    	// We can't check here if the challenge type is actually
    	// configured or not, but at least we can report unknown /
    	// unsupported types as syntax errors.
    	switch c.ChallengeType {
    	case "", dns01Challenge, http01Challenge:
    	default:
    		return fmt.Errorf("unkown or unsupported challenge type '%s'", c.ChallengeType)
    
    ale's avatar
    ale committed
    	}
    
    ale's avatar
    ale committed
    	return nil
    
    ale's avatar
    ale committed
    }
    
    
    ale's avatar
    ale committed
    func readCertConfigs(path string) ([]*certConfig, error) {
    	data, err := ioutil.ReadFile(path) // nolint: gosec
    
    ale's avatar
    ale committed
    	if err != nil {
    		return nil, err
    	}
    
    ale's avatar
    ale committed
    	var cc []*certConfig
    	if err := yaml.Unmarshal(data, &cc); err != nil {
    		return nil, err
    	}
    	return cc, nil
    
    ale's avatar
    ale committed
    }
    
    
    ale's avatar
    ale committed
    func readCertConfigsFromDir(dir string) ([]*certConfig, error) {
    
    ale's avatar
    ale committed
    	files, err := filepath.Glob(filepath.Join(dir, "*.yml"))
    	if err != nil {
    		return nil, err
    	}
    
    ale's avatar
    ale committed
    	var out []*certConfig
    
    ale's avatar
    ale committed
    	for _, f := range files {
    
    ale's avatar
    ale committed
    		cc, err := readCertConfigs(f)
    
    ale's avatar
    ale committed
    		if err != nil {
    			log.Printf("error reading %s: %v", f, err)
    			continue
    		}
    
    ale's avatar
    ale committed
    		// Validate the cert configs, skip ones with errors.
    		for _, c := range cc {
    			if err := c.check(); err != nil {
    				log.Printf("configuration error in %s: %v", f, err)
    				continue
    			}
    			out = append(out, c)
    		}
    
    ale's avatar
    ale committed
    	}
    
    ale's avatar
    ale committed
    	return out, nil
    
    ale's avatar
    ale committed
    }