diff --git a/pkg/kubeconfig/create_kubecfg.go b/pkg/kubeconfig/create_kubecfg.go index 4e129a075f..8c5a5ff00a 100644 --- a/pkg/kubeconfig/create_kubecfg.go +++ b/pkg/kubeconfig/create_kubecfg.go @@ -99,11 +99,17 @@ func BuildKubecfg(cluster *kops.Cluster, keyStore fi.Keystore, secretStore fi.Se b := NewKubeconfigBuilder() + // Use the secondary load balancer port if a certificate is on the primary listener + if admin != 0 && cluster.Spec.API != nil && cluster.Spec.API.LoadBalancer != nil && cluster.Spec.API.LoadBalancer.SSLCertificate != "" && cluster.Spec.API.LoadBalancer.Class == kops.LoadBalancerClassNetwork { + server = server + ":8443" + } + b.Context = clusterName b.Server = server - // add the CA Cert to the kubeconfig only if we didn't specify a SSL cert for the LB or are targeting the internal DNS name - if cluster.Spec.API == nil || cluster.Spec.API.LoadBalancer == nil || cluster.Spec.API.LoadBalancer.SSLCertificate == "" || internal { + // add the CA Cert to the kubeconfig only if we didn't specify a certificate for the LB + // or if we're using admin credentials and the secondary port + if cluster.Spec.API == nil || cluster.Spec.API.LoadBalancer == nil || cluster.Spec.API.LoadBalancer.SSLCertificate == "" || cluster.Spec.API.LoadBalancer.Class == kops.LoadBalancerClassNetwork || internal { cert, _, _, err := keyStore.FindKeypair(fi.CertificateIDCA) if err != nil { return nil, fmt.Errorf("error fetching CA keypair: %v", err) diff --git a/pkg/kubeconfig/create_kubecfg_test.go b/pkg/kubeconfig/create_kubecfg_test.go index 762f01a7ec..a6f5394f24 100644 --- a/pkg/kubeconfig/create_kubecfg_test.go +++ b/pkg/kubeconfig/create_kubecfg_test.go @@ -71,10 +71,20 @@ func (f fakeKeyStore) MirrorTo(basedir vfs.Path) error { } // build a generic minimal cluster -func buildMinimalCluster(clusterName string, masterPublicName string) *kops.Cluster { +func buildMinimalCluster(clusterName string, masterPublicName string, lbCert bool, nlb bool) *kops.Cluster { cluster := testutils.BuildMinimalCluster(clusterName) cluster.Spec.MasterPublicName = masterPublicName cluster.Spec.MasterInternalName = fmt.Sprintf("internal.%v", masterPublicName) + cluster.Spec.KubernetesVersion = "1.19.3" + cluster.Spec.API = &kops.AccessSpec{ + LoadBalancer: &kops.LoadBalancerAccessSpec{}, + } + if lbCert { + cluster.Spec.API.LoadBalancer.SSLCertificate = "cert-arn" + } + if nlb { + cluster.Spec.API.LoadBalancer.Class = kops.LoadBalancerClassNetwork + } return cluster } @@ -107,9 +117,12 @@ func TestBuildKubecfg(t *testing.T) { useKopsAuthenticationPlugin bool } - publiccluster := buildMinimalCluster("testcluster", "testcluster.test.com") - emptyMasterPublicNameCluster := buildMinimalCluster("emptyMasterPublicNameCluster", "") - gossipCluster := buildMinimalCluster("testgossipcluster.k8s.local", "") + publicCluster := buildMinimalCluster("testcluster", "testcluster.test.com", false, false) + emptyMasterPublicNameCluster := buildMinimalCluster("emptyMasterPublicNameCluster", "", false, false) + gossipCluster := buildMinimalCluster("testgossipcluster.k8s.local", "", false, false) + certCluster := buildMinimalCluster("testcluster", "testcluster.test.com", true, false) + certNLBCluster := buildMinimalCluster("testcluster", "testcluster.test.com", true, true) + certGossipNLBCluster := buildMinimalCluster("testgossipcluster.k8s.local", "", true, true) tests := []struct { name string @@ -121,7 +134,7 @@ func TestBuildKubecfg(t *testing.T) { { name: "Test Kube Config Data For Public DNS with admin", args: args{ - cluster: publiccluster, + cluster: publicCluster, status: fakeStatusStore{}, admin: DefaultKubecfgAdminLifetime, user: "", @@ -134,10 +147,55 @@ func TestBuildKubecfg(t *testing.T) { }, wantClientCert: true, }, + { + name: "Test Kube Config Data For Public DNS with admin and secondary NLB port", + args: args{ + cluster: certNLBCluster, + status: fakeStatusStore{}, + admin: DefaultKubecfgAdminLifetime, + }, + want: &KubeconfigBuilder{ + Context: "testcluster", + Server: "https://testcluster.test.com:8443", + CACert: []byte(certData), + User: "testcluster", + }, + wantClientCert: true, + }, + { + name: "Test Kube Config Data For Public DNS with admin and CLB ACM Certificate", + args: args{ + cluster: certCluster, + status: fakeStatusStore{}, + admin: DefaultKubecfgAdminLifetime, + }, + want: &KubeconfigBuilder{ + Context: "testcluster", + Server: "https://testcluster.test.com", + CACert: nil, + User: "testcluster", + }, + wantClientCert: true, + }, + { + name: "Test Kube Config Data For Public DNS without admin and with ACM certificate", + args: args{ + cluster: certNLBCluster, + status: fakeStatusStore{}, + admin: 0, + }, + want: &KubeconfigBuilder{ + Context: "testcluster", + Server: "https://testcluster.test.com", + CACert: []byte(certData), + User: "testcluster", + }, + wantClientCert: false, + }, { name: "Test Kube Config Data For Public DNS without admin", args: args{ - cluster: publiccluster, + cluster: publicCluster, status: fakeStatusStore{}, admin: 0, user: "myuser", @@ -191,7 +249,7 @@ func TestBuildKubecfg(t *testing.T) { { name: "Public DNS with kops auth plugin", args: args{ - cluster: publiccluster, + cluster: publicCluster, status: fakeStatusStore{}, admin: 0, useKopsAuthenticationPlugin: true, @@ -214,7 +272,7 @@ func TestBuildKubecfg(t *testing.T) { { name: "Test Kube Config Data For internal DNS name with admin", args: args{ - cluster: publiccluster, + cluster: publicCluster, status: fakeStatusStore{}, admin: DefaultKubecfgAdminLifetime, internal: true, @@ -227,6 +285,29 @@ func TestBuildKubecfg(t *testing.T) { }, wantClientCert: true, }, + { + name: "Test Kube Config Data For Gossip cluster with admin and secondary NLB port", + args: args{ + cluster: certGossipNLBCluster, + status: fakeStatusStore{ + GetApiIngressStatusFn: func(cluster *kops.Cluster) ([]kops.ApiIngressStatus, error) { + return []kops.ApiIngressStatus{ + { + Hostname: "nlbHostName", + }, + }, nil + }, + }, + admin: DefaultKubecfgAdminLifetime, + }, + want: &KubeconfigBuilder{ + Context: "testgossipcluster.k8s.local", + Server: "https://nlbHostName:8443", + CACert: []byte(certData), + User: "testgossipcluster.k8s.local", + }, + wantClientCert: true, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) {