package updateip import ( "fmt" "net" "github.com/hashicorp/hcl/v2/hclsimple" log "github.com/sirupsen/logrus" ) func Load(name string) (*Config, error) { var ( config Config err error ) log.WithField("config", name).Debug("loading configuration file") if err = hclsimple.DecodeFile(name, nil, &config); err != nil { return nil, err } providers := make(map[string]Provider) for _, v := range config.Provider { if providers[v.Name], err = NewProvider(v); err != nil { return nil, fmt.Errorf("error configuring provider %q: %w", v.Name, err) } } for _, v := range config.Domain { if p, ok := providers[v.ProviderName]; ok { v.Provider = p } else { return nil, fmt.Errorf("provider %q in domain %q is not configured", v.ProviderName, v.Name) } if len(v.Update) == 0 { v.Update = append(v.Update, "@") } } return &config, nil } type Config struct { Resolver ResolverConfig `hcl:"resolver,block"` Domain []*DomainConfig `hcl:"domain,block"` Provider []*ProviderConfig `hcl:"provider,block"` } type ResolverConfig struct { Permit []string `hcl:"permit"` } func (r ResolverConfig) CurrentIP() (net.IP, error) { return NewResolver().CurrentIP() } func (r ResolverConfig) IsAllowed(ip net.IP) bool { if len(r.Permit) == 0 { // Fail open if no ACL is configured. log.WithField("ip", ip.String()).Debug("IP allowed by resolver; no ACL") return true } for _, v := range r.Permit { if _, ipnet, err := net.ParseCIDR(v); err == nil { if ipnet.Contains(ip) { log.WithFields(log.Fields{ "ip": ip.String(), "range": ipnet.String(), }).Debug("IP allowed by resolver ACL") return true } } } log.WithField("ip", ip.String()).Warn("IP not allowed by resolver ACL") return false } type DomainConfig struct { Name string `hcl:"name,label"` ProviderName string `hcl:"provider"` Provider Provider `` Update []string `hcl:"update,optional"` } type ProviderConfig struct { Name string `hcl:"name,label"` Type string Username string `hcl:"username"` PrivateKey string `hcl:"private_key"` }