From 134e1d7af4ee470318df686bf19c5ff54baf1129 Mon Sep 17 00:00:00 2001 From: Curtis Gagliardi Date: Wed, 13 Apr 2016 12:03:10 -0700 Subject: [PATCH] kube-aws: validate externalDNSName is a subdomain of hostedZone fixes #401 --- multi-node/aws/pkg/cluster/cluster_test.go | 2 +- multi-node/aws/pkg/config/config.go | 26 ++++++++ multi-node/aws/pkg/config/config_test.go | 75 +++++++++++++++++++++- 3 files changed, 99 insertions(+), 4 deletions(-) diff --git a/multi-node/aws/pkg/cluster/cluster_test.go b/multi-node/aws/pkg/cluster/cluster_test.go index e8c822039a..215e2e525b 100644 --- a/multi-node/aws/pkg/cluster/cluster_test.go +++ b/multi-node/aws/pkg/cluster/cluster_test.go @@ -12,7 +12,7 @@ import ( ) const minimalConfigYaml = ` -externalDNSName: test-external-dns-name +externalDNSName: test.staging.core-os.net keyName: test-key-name region: us-west-1 availabilityZone: us-west-1c diff --git a/multi-node/aws/pkg/config/config.go b/multi-node/aws/pkg/config/config.go index 381bc54be5..82aa6fc53d 100644 --- a/multi-node/aws/pkg/config/config.go +++ b/multi-node/aws/pkg/config/config.go @@ -339,6 +339,11 @@ func (cfg Cluster) valid() error { if cfg.RecordSetTTL < 1 { return errors.New("TTL must be at least 1 second") } + if !isSubdomain(cfg.ExternalDNSName, cfg.HostedZone) { + return fmt.Errorf("%s is not a subdomain of %s", + cfg.ExternalDNSName, + cfg.HostedZone) + } } else { if cfg.RecordSetTTL != newDefaultCluster().RecordSetTTL { return errors.New( @@ -516,3 +521,24 @@ func withTrailingDot(s string) string { } return s } + +func isSubdomain(sub, parent string) bool { + sub, parent = withTrailingDot(sub), withTrailingDot(parent) + subParts, parentParts := strings.Split(sub, "."), strings.Split(parent, ".") + + if len(parentParts) > len(subParts) { + return false + } + + subSuffixes := subParts[len(subParts)-len(parentParts):] + + if len(subSuffixes) != len(parentParts) { + return false + } + for i := range subSuffixes { + if subSuffixes[i] != parentParts[i] { + return false + } + } + return true +} diff --git a/multi-node/aws/pkg/config/config_test.go b/multi-node/aws/pkg/config/config_test.go index aeb24b4eb6..0241d47207 100644 --- a/multi-node/aws/pkg/config/config_test.go +++ b/multi-node/aws/pkg/config/config_test.go @@ -5,7 +5,7 @@ import ( "testing" ) -const minimalConfigYaml = `externalDNSName: test-external-dns-name +const minimalConfigYaml = `externalDNSName: test.staging.core-os.net keyName: test-key-name region: us-west-1 availabilityZone: us-west-1c @@ -13,7 +13,7 @@ clusterName: test-cluster-name kmsKeyArn: "arn:aws:kms:us-west-1:xxxxxxxxx:key/xxxxxxxxxxxxxxxxxxx" ` -var goodNetworkingConfigs []string = []string{ +var goodNetworkingConfigs = []string{ ``, //Tests validity of default network config values ` vpcCIDR: 10.4.3.0/24 @@ -41,10 +41,13 @@ hostedZone: "" createRecordSet: true recordSetTTL: 400 hostedZone: core-os.net +`, ` +createRecordSet: true +hostedZone: "staging.core-os.net" `, } -var incorrectNetworkingConfigs []string = []string{ +var incorrectNetworkingConfigs = []string{ ` vpcCIDR: 10.4.2.0/23 instanceCIDR: 10.4.3.0/24 @@ -102,6 +105,10 @@ hostedZone: "" # recordSetTTL shouldn't be modified when createRecordSet is false createRecordSet: false recordSetTTL: 400 +`, ` +# whatever.com is not a superdomain of test.staging.core-os.net +createRecordSet: true +hostedZone: "whatever.com" `, } @@ -184,3 +191,65 @@ dnsServiceIP: 10.6.142.100 } } + +func TestIsSubdomain(t *testing.T) { + validData := []struct { + sub string + parent string + }{ + { + // single level + sub: "test.coreos.com", + parent: "coreos.com", + }, + { + // multiple levels + sub: "cgag.staging.coreos.com", + parent: "coreos.com", + }, + { + // trailing dots shouldn't matter + sub: "staging.coreos.com.", + parent: "coreos.com.", + }, + { + // trailing dots shouldn't matter + sub: "a.b.c.", + parent: "b.c", + }, + { + // multiple level parent domain + sub: "a.b.c.staging.core-os.net", + parent: "staging.core-os.net", + }, + } + + invalidData := []struct { + sub string + parent string + }{ + { + // mismatch + sub: "staging.coreos.com", + parent: "example.com", + }, + { + // superdomain is longer than subdomain + sub: "staging.coreos.com", + parent: "cgag.staging.coreos.com", + }, + } + + for _, valid := range validData { + if !isSubdomain(valid.sub, valid.parent) { + t.Errorf("%s should be a valid subdomain of %s", valid.sub, valid.parent) + } + } + + for _, invalid := range invalidData { + if isSubdomain(invalid.sub, invalid.parent) { + t.Errorf("%s should not be a valid subdomain of %s", invalid.sub, invalid.parent) + } + } + +}