Newer
Older
"io/ioutil"
"log"
"path/filepath"
"gopkg.in/yaml.v2"
"git.autistici.org/ai3/go-common/clientutil"
)
// Config holds the configuration for an acmeserver instance.
// The reason for supporting multiple config_dirs is to allow
// integration with third-party automation systems: in some cases,
// automation tools need control of an entire directory in order to
// safely delete entries that no longer exist.
//
Testing bool `yaml:"testing"`
DirectoryURL string `yaml:"directory_url"`
DefaultChallengeType string `yaml:"default_challenge"`
UseRSA bool `yaml:"use_rsa"`
RenewalDays int `yaml:"renewal_days"`
AccountKeyPath string `yaml:"account_key_path"`
Email string `yaml:"email"`
Dirs []string `yaml:"config_dirs"`
Output struct {
Path string `yaml:"path"`
ReplDS *clientutil.BackendConfig `yaml:"replds"`
} `yaml:"output"`
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"`
// This is all the configuration we need to generate a certificate.
// 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"`
func (c *certConfig) check() error {
if len(c.Names) == 0 {
return errors.New("empty names list")
// 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)
func readCertConfigs(path string) ([]*certConfig, error) {
data, err := ioutil.ReadFile(path) // nolint: gosec
var cc []*certConfig
if err := yaml.Unmarshal(data, &cc); err != nil {
return nil, err
}
return cc, nil
func readCertConfigsFromDir(dir string, certs []*certConfig) ([]*certConfig, error) {
files, err := filepath.Glob(filepath.Join(dir, "*.yml"))
if err != nil {
return nil, err
}
for _, f := range files {
if err != nil {
log.Printf("error reading %s: %v", f, err)
continue
}
// 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
}
certs = append(certs, c)
}
}
return certs, nil
}
func readCertConfigsFromDirs(dirs []string) ([]*certConfig, error) {
var out []*certConfig
for _, dir := range dirs {
certs, err := readCertConfigsFromDir(dir, out)
if err != nil {
return nil, err