diff --git a/cmd/node-cache/app/configmap.go b/cmd/node-cache/app/configmap.go index a42b13534..9efae5337 100644 --- a/cmd/node-cache/app/configmap.go +++ b/cmd/node-cache/app/configmap.go @@ -89,6 +89,12 @@ func (c *CacheApp) updateCorefile(dnsConfig *config.Config) { setupErrCount.WithLabelValues("configmap").Inc() return } + if err = dnsConfig.ValidateNodeLocalCacheConfig(); err != nil { + clog.Errorf("Invalid config: %v", err) + setupErrCount.WithLabelValues("configmap").Inc() + return + } + stubDomainStr := getStubDomainStr(dnsConfig.StubDomains, &stubDomainInfo{Port: c.params.LocalPort, CacheTTL: defaultTTL, LocalIP: strings.Replace(c.params.LocalIPStr, ",", " ", -1)}) upstreamServers := strings.Join(dnsConfig.UpstreamNameservers, " ") diff --git a/pkg/dns/config/config.go b/pkg/dns/config/config.go index 16f1678bd..274702456 100644 --- a/pkg/dns/config/config.go +++ b/pkg/dns/config/config.go @@ -21,6 +21,8 @@ import ( "net" "strconv" + "github.com/coredns/coredns/plugin/pkg/parse" + types "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/validation" fed "k8s.io/dns/pkg/dns/federation" @@ -130,3 +132,39 @@ func (config *Config) validateUpstreamNameserver() error { } return nil } + +// ValidateNodeLocalCacheConfig returns nil if the config can be compiled +// to a valid Corefile. +func (config *Config) ValidateNodeLocalCacheConfig() error { + for _, stubDomains := range config.StubDomains { + if err := validateForwardProxy(stubDomains...); err != nil { + return err + } + } + if err := validateForwardProxy(config.UpstreamNameservers...); err != nil { + return err + } + return nil +} + +// validateForwardProxy returns nil if the nameservers are valid proxy addresses +// for the CoreDNS plugin forward. +// The function is ported from coredns/plugin/forward:parseStanza +func validateForwardProxy(nameservers ...string) error { + if len(nameservers) == 0 { + return nil + } + hosts, err := parse.HostPortOrFile(nameservers...) + if err != nil { + return err + } + for _, host := range hosts { + trans, _ := parse.Transport(host) + switch trans { + case "dns", "tls": + default: + return fmt.Errorf("unsupported transport %s of nameserver %s", trans, host) + } + } + return nil +} diff --git a/pkg/dns/config/config_test.go b/pkg/dns/config/config_test.go index cd1e563fe..1d81adf9c 100644 --- a/pkg/dns/config/config_test.go +++ b/pkg/dns/config/config_test.go @@ -64,3 +64,45 @@ func TestValidate(t *testing.T) { assert.NotNil(t, err, "should not be valid: %+v", testCase) } } + +func TestValidateNodeLocalCacheConfig(t *testing.T) { + for _, tc := range []struct { + name string + config Config + wantError bool + }{ + { + name: "empty config", + config: Config{}, + }, + { + name: "valid config", + config: Config{ + StubDomains: map[string][]string{"": {"1.1.1.1"}}, + UpstreamNameservers: []string{"1.1.1.1", "2.2.2.2"}, + }, + }, + { + name: "invalid config: FQDN stub domain", + config: Config{ + StubDomains: map[string][]string{"": {"cluster.local"}}, + UpstreamNameservers: []string{"1.1.1.1", "2.2.2.2"}, + }, + wantError: true, + }, + { + name: "invalid config: FQDN upstream name server", + config: Config{ + StubDomains: map[string][]string{"": {"1.1.1.1"}}, + UpstreamNameservers: []string{"1.1.1.1", "cluster.local"}, + }, + wantError: true, + }, + } { + err := tc.config.ValidateNodeLocalCacheConfig() + gotError := err != nil + if gotError != tc.wantError { + t.Fatalf("ValidateNodeLocalCacheConfig(%v) got error = %v, want = %v", tc.config, gotError, tc.wantError) + } + } +}