From 68bb8f5ddbca64b95bdf82f743c6a0119c43e02a Mon Sep 17 00:00:00 2001 From: John Gardiner Myers Date: Fri, 16 Jul 2021 22:55:50 -0700 Subject: [PATCH] Refactor kube-apiserver static credentials --- nodeup/pkg/model/kube_apiserver.go | 84 ++++++++++++++++++++++++++++-- nodeup/pkg/model/secrets.go | 75 -------------------------- 2 files changed, 79 insertions(+), 80 deletions(-) diff --git a/nodeup/pkg/model/kube_apiserver.go b/nodeup/pkg/model/kube_apiserver.go index b35d038555..4226b9bfb9 100644 --- a/nodeup/pkg/model/kube_apiserver.go +++ b/nodeup/pkg/model/kube_apiserver.go @@ -27,6 +27,7 @@ import ( "k8s.io/kops/pkg/kubeconfig" "k8s.io/kops/pkg/kubemanifest" "k8s.io/kops/pkg/model/components" + "k8s.io/kops/pkg/tokens" "k8s.io/kops/pkg/wellknownports" "k8s.io/kops/pkg/wellknownusers" "k8s.io/kops/upup/pkg/fi" @@ -167,6 +168,10 @@ func (b *KubeAPIServerBuilder) Build(c *fi.ModelBuilderContext) error { return err } + if err := b.writeStaticCredentials(c, &kubeAPIServer); err != nil { + return err + } + { pod, err := b.buildPod(&kubeAPIServer) if err != nil { @@ -425,21 +430,90 @@ func (b *KubeAPIServerBuilder) writeServerCertificate(c *fi.ModelBuilderContext, return nil } -// buildPod is responsible for generating the kube-apiserver pod and thus manifest file -func (b *KubeAPIServerBuilder) buildPod(kubeAPIServer *kops.KubeAPIServerConfig) (*v1.Pod, error) { +func (b *KubeAPIServerBuilder) writeStaticCredentials(c *fi.ModelBuilderContext, kubeAPIServer *kops.KubeAPIServerConfig) error { + pathSrvKAPI := filepath.Join(b.PathSrvKubernetes(), "kube-apiserver") + + // Support for basic auth was deprecated 1.16 and removed in 1.19 + // https://github.com/kubernetes/kubernetes/pull/89069 + if b.IsKubernetesLT("1.19") && b.SecretStore != nil { + key := "kube" + token, err := b.SecretStore.FindSecret(key) + if err != nil { + return err + } + if token == nil { + return fmt.Errorf("token not found: %q", key) + } + csv := string(token.Data) + "," + adminUser + "," + adminUser + "," + adminGroup + + t := &nodetasks.File{ + Path: filepath.Join(pathSrvKAPI, "basic_auth.csv"), + Contents: fi.NewStringResource(csv), + Type: nodetasks.FileType_File, + Mode: s("0600"), + } + c.AddTask(t) + } + + if b.SecretStore != nil { + allTokens, err := b.allAuthTokens() + if err != nil { + return err + } + + var lines []string + for id, token := range allTokens { + if id == adminUser { + lines = append(lines, token+","+id+","+id+","+adminGroup) + } else { + lines = append(lines, token+","+id+","+id) + } + } + csv := strings.Join(lines, "\n") + + c.AddTask(&nodetasks.File{ + Path: filepath.Join(pathSrvKAPI, "known_tokens.csv"), + Contents: fi.NewStringResource(csv), + Type: nodetasks.FileType_File, + Mode: s("0600"), + }) + } + // Support for basic auth was deprecated 1.16 and removed in 1.19 // https://github.com/kubernetes/kubernetes/pull/89069 if b.IsKubernetesLT("1.18") { - kubeAPIServer.TokenAuthFile = filepath.Join(b.PathSrvKubernetes(), "known_tokens.csv") + kubeAPIServer.TokenAuthFile = filepath.Join(pathSrvKAPI, "known_tokens.csv") if kubeAPIServer.DisableBasicAuth == nil || !*kubeAPIServer.DisableBasicAuth { - kubeAPIServer.BasicAuthFile = filepath.Join(b.PathSrvKubernetes(), "basic_auth.csv") + kubeAPIServer.BasicAuthFile = filepath.Join(pathSrvKAPI, "basic_auth.csv") } } else if b.IsKubernetesLT("1.19") { if kubeAPIServer.DisableBasicAuth != nil && !*kubeAPIServer.DisableBasicAuth { - kubeAPIServer.BasicAuthFile = filepath.Join(b.PathSrvKubernetes(), "basic_auth.csv") + kubeAPIServer.BasicAuthFile = filepath.Join(pathSrvKAPI, "basic_auth.csv") } } + return nil +} + +// allTokens returns a map of all auth tokens that are present +func (b *KubeAPIServerBuilder) allAuthTokens() (map[string]string, error) { + possibleTokens := tokens.GetKubernetesAuthTokens_Deprecated() + + tokens := make(map[string]string) + for _, id := range possibleTokens { + token, err := b.SecretStore.FindSecret(id) + if err != nil { + return nil, err + } + if token != nil { + tokens[id] = string(token.Data) + } + } + return tokens, nil +} + +// buildPod is responsible for generating the kube-apiserver pod and thus manifest file +func (b *KubeAPIServerBuilder) buildPod(kubeAPIServer *kops.KubeAPIServerConfig) (*v1.Pod, error) { // we need to replace 127.0.0.1 for etcd urls with the dns names in case this apiserver is not // running on master nodes if !b.IsMaster { diff --git a/nodeup/pkg/model/secrets.go b/nodeup/pkg/model/secrets.go index 8d1d23f4ff..b90e7da8c0 100644 --- a/nodeup/pkg/model/secrets.go +++ b/nodeup/pkg/model/secrets.go @@ -17,11 +17,8 @@ limitations under the License. package model import ( - "fmt" "path/filepath" - "strings" - "k8s.io/kops/pkg/tokens" "k8s.io/kops/upup/pkg/fi" "k8s.io/kops/upup/pkg/fi/nodeup/nodetasks" "k8s.io/kops/util/pkg/vfs" @@ -41,10 +38,6 @@ const ( // Build is responsible for pulling down the secrets func (b *SecretBuilder) Build(c *fi.ModelBuilderContext) error { - if b.KeyStore == nil { - return fmt.Errorf("KeyStore not set") - } - // @step: write out the platform ca c.AddTask(&nodetasks.File{ Path: filepath.Join(b.PathSrvKubernetes(), "ca.crt"), @@ -68,77 +61,9 @@ func (b *SecretBuilder) Build(c *fi.ModelBuilderContext) error { } } - // If we do not run the Kubernetes API server we can stop here. - if !b.HasAPIServer { - return nil - } - - // Support for basic auth was deprecated 1.16 and removed in 1.19 - // https://github.com/kubernetes/kubernetes/pull/89069 - if b.IsKubernetesLT("1.19") && b.SecretStore != nil { - key := "kube" - token, err := b.SecretStore.FindSecret(key) - if err != nil { - return err - } - if token == nil { - return fmt.Errorf("token not found: %q", key) - } - csv := string(token.Data) + "," + adminUser + "," + adminUser + "," + adminGroup - - t := &nodetasks.File{ - Path: filepath.Join(b.PathSrvKubernetes(), "basic_auth.csv"), - Contents: fi.NewStringResource(csv), - Type: nodetasks.FileType_File, - Mode: s("0600"), - } - c.AddTask(t) - } - - if b.SecretStore != nil { - allTokens, err := b.allAuthTokens() - if err != nil { - return err - } - - var lines []string - for id, token := range allTokens { - if id == adminUser { - lines = append(lines, token+","+id+","+id+","+adminGroup) - } else { - lines = append(lines, token+","+id+","+id) - } - } - csv := strings.Join(lines, "\n") - - c.AddTask(&nodetasks.File{ - Path: filepath.Join(b.PathSrvKubernetes(), "known_tokens.csv"), - Contents: fi.NewStringResource(csv), - Type: nodetasks.FileType_File, - Mode: s("0600"), - }) - } - return nil } -// allTokens returns a map of all auth tokens that are present -func (b *SecretBuilder) allAuthTokens() (map[string]string, error) { - possibleTokens := tokens.GetKubernetesAuthTokens_Deprecated() - - tokens := make(map[string]string) - for _, id := range possibleTokens { - token, err := b.SecretStore.FindSecret(id) - if err != nil { - return nil, err - } - if token != nil { - tokens[id] = string(token.Data) - } - } - return tokens, nil -} - func getInstanceAddress() (string, error) { addrBytes, err := vfs.Context.ReadFile("metadata://openstack/local-ipv4")