diff --git a/cmd/kubeadm/app/util/config/masterconfig.go b/cmd/kubeadm/app/util/config/masterconfig.go index c74f93109ea..03ef0374372 100644 --- a/cmd/kubeadm/app/util/config/masterconfig.go +++ b/cmd/kubeadm/app/util/config/masterconfig.go @@ -20,6 +20,7 @@ import ( "fmt" "io/ioutil" "net" + "strings" "github.com/golang/glog" @@ -64,6 +65,9 @@ func SetInitDynamicDefaults(cfg *kubeadmapi.MasterConfiguration) error { return err } + // Downcase SANs. Some domain names (like ELBs) have capitals in them. + LowercaseSANs(cfg.APIServerCertSANs) + // Populate the .Token field with a random value if unset // We do this at this layer, and not the API defaulting layer // because of possible security concerns, and more practically @@ -215,3 +219,14 @@ func NormalizeKubernetesVersion(cfg *kubeadmapi.MasterConfiguration) error { } return nil } + +// LowercaseSANs can be used to force all SANs to be lowercase so it passes IsDNS1123Subdomain +func LowercaseSANs(sans []string) { + for i, san := range sans { + lowercase := strings.ToLower(san) + if lowercase != san { + glog.V(1).Infof("lowercasing SAN %q to %q", san, lowercase) + sans[i] = lowercase + } + } +} diff --git a/cmd/kubeadm/app/util/config/masterconfig_test.go b/cmd/kubeadm/app/util/config/masterconfig_test.go index 997b4bd9c07..a8a6115c7ad 100644 --- a/cmd/kubeadm/app/util/config/masterconfig_test.go +++ b/cmd/kubeadm/app/util/config/masterconfig_test.go @@ -176,3 +176,50 @@ func TestUpgrade(t *testing.T) { t.Errorf("v1alpha1 object after unmarshal, conversion and marshal didn't match expected value.\n\tdiff: \n%s\n", diff(afterExpected, afterActual)) } } + +func TestLowercaseSANs(t *testing.T) { + tests := []struct { + name string + in []string + out []string + }{ + { + name: "empty struct", + }, + { + name: "already lowercase", + in: []string{"example.k8s.io"}, + out: []string{"example.k8s.io"}, + }, + { + name: "ip addresses and uppercase", + in: []string{"EXAMPLE.k8s.io", "10.100.0.1"}, + out: []string{"example.k8s.io", "10.100.0.1"}, + }, + { + name: "punycode and uppercase", + in: []string{"xn--7gq663byk9a.xn--fiqz9s", "ANOTHEREXAMPLE.k8s.io"}, + out: []string{"xn--7gq663byk9a.xn--fiqz9s", "anotherexample.k8s.io"}, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + cfg := &v1alpha2.MasterConfiguration{ + APIServerCertSANs: test.in, + } + + LowercaseSANs(cfg.APIServerCertSANs) + + if len(cfg.APIServerCertSANs) != len(test.out) { + t.Fatalf("expected %d elements, got %d", len(test.out), len(cfg.APIServerCertSANs)) + } + + for i, expected := range test.out { + if cfg.APIServerCertSANs[i] != expected { + t.Errorf("expected element %d to be %q, got %q", i, expected, cfg.APIServerCertSANs[i]) + } + } + }) + } +}