Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Automated cherry pick of #44570 #44862 #44877

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions staging/src/k8s.io/client-go/tools/clientcmd/client_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -482,13 +482,13 @@ func (config *inClusterClientConfig) Namespace() (string, bool, error) {
// This way assumes you've set the POD_NAMESPACE environment variable using the downward API.
// This check has to be done first for backwards compatibility with the way InClusterConfig was originally set up
if ns := os.Getenv("POD_NAMESPACE"); ns != "" {
return ns, true, nil
return ns, false, nil
}

// Fall back to the namespace associated with the service account token, if available
if data, err := ioutil.ReadFile("/var/run/secrets/kubernetes.io/serviceaccount/namespace"); err == nil {
if ns := strings.TrimSpace(string(data)); len(ns) > 0 {
return ns, true, nil
return ns, false, nil
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (

"github.com/golang/glog"

"k8s.io/client-go/pkg/api"
restclient "k8s.io/client-go/rest"
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
)
Expand Down Expand Up @@ -134,12 +135,26 @@ func (config *DeferredLoadingClientConfig) Namespace() (string, bool, error) {
return "", false, err
}

ns, ok, err := mergedKubeConfig.Namespace()
ns, overridden, err := mergedKubeConfig.Namespace()
// if we get an error and it is not empty config, or if the merged config defined an explicit namespace, or
// if in-cluster config is not possible, return immediately
if (err != nil && !IsEmptyConfig(err)) || ok || !config.icc.Possible() {
if (err != nil && !IsEmptyConfig(err)) || overridden || !config.icc.Possible() {
// return on any error except empty config
return ns, ok, err
return ns, overridden, err
}

if len(ns) > 0 {
// if we got a non-default namespace from the kubeconfig, use it
if ns != api.NamespaceDefault {
return ns, false, nil
}

// if we got a default namespace, determine whether it was explicit or implicit
if raw, err := mergedKubeConfig.RawConfig(); err == nil {
if context := raw.Contexts[raw.CurrentContext]; context != nil && len(context.Namespace) > 0 {
return ns, false, nil
}
}
}

glog.V(4).Infof("Using in-cluster namespace")
Expand Down
87 changes: 75 additions & 12 deletions test/e2e/kubectl.go
Original file line number Diff line number Diff line change
Expand Up @@ -580,7 +580,7 @@ var _ = framework.KubeDescribe("Kubectl client", func() {

It("should handle in-cluster config", func() {
By("adding rbac permissions")
// grant the view permission widely to allow inspection of the `invalid` namespace.
// grant the view permission widely to allow inspection of the `invalid` namespace and the default namespace
framework.BindClusterRole(f.ClientSet.Rbac(), "view", f.Namespace.Name,
rbacv1beta1.Subject{Kind: rbacv1beta1.ServiceAccountKind, Namespace: f.Namespace.Name, Name: "default"})

Expand All @@ -606,11 +606,70 @@ var _ = framework.KubeDescribe("Kubectl client", func() {
framework.Logf("copying %s to the %s pod", kubectlPath, simplePodName)
framework.RunKubectlOrDie("cp", kubectlPath, ns+"/"+simplePodName+":/tmp/")

// Build a kubeconfig file that will make use of the injected ca and token,
// but point at the DNS host and the default namespace
tmpDir, err := ioutil.TempDir("", "icc-override")
overrideKubeconfigName := "icc-override.kubeconfig"
framework.ExpectNoError(err)
defer func() { os.Remove(tmpDir) }()
framework.ExpectNoError(ioutil.WriteFile(filepath.Join(tmpDir, overrideKubeconfigName), []byte(`
kind: Config
apiVersion: v1
clusters:
- cluster:
api-version: v1
server: https://kubernetes.default.svc:443
certificate-authority: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
name: kubeconfig-cluster
contexts:
- context:
cluster: kubeconfig-cluster
namespace: default
user: kubeconfig-user
name: kubeconfig-context
current-context: kubeconfig-context
users:
- name: kubeconfig-user
user:
tokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token
`), os.FileMode(0755)))
framework.Logf("copying override kubeconfig to the %s pod", simplePodName)
framework.RunKubectlOrDie("cp", filepath.Join(tmpDir, overrideKubeconfigName), ns+"/"+simplePodName+":/tmp/")

framework.ExpectNoError(ioutil.WriteFile(filepath.Join(tmpDir, "invalid-configmap-with-namespace.yaml"), []byte(`
kind: ConfigMap
apiVersion: v1
metadata:
name: "configmap with namespace and invalid name"
namespace: configmap-namespace
`), os.FileMode(0755)))
framework.ExpectNoError(ioutil.WriteFile(filepath.Join(tmpDir, "invalid-configmap-without-namespace.yaml"), []byte(`
kind: ConfigMap
apiVersion: v1
metadata:
name: "configmap without namespace and invalid name"
`), os.FileMode(0755)))
framework.Logf("copying configmap manifests to the %s pod", simplePodName)
framework.RunKubectlOrDie("cp", filepath.Join(tmpDir, "invalid-configmap-with-namespace.yaml"), ns+"/"+simplePodName+":/tmp/")
framework.RunKubectlOrDie("cp", filepath.Join(tmpDir, "invalid-configmap-without-namespace.yaml"), ns+"/"+simplePodName+":/tmp/")

By("getting pods with in-cluster configs")
execOutput := framework.RunHostCmdOrDie(ns, simplePodName, "/tmp/kubectl get pods")
if matched, err := regexp.MatchString("nginx +1/1 +Running", execOutput); err != nil || !matched {
framework.Failf("Unexpected kubectl exec output: ", execOutput)
}
execOutput := framework.RunHostCmdOrDie(ns, simplePodName, "/tmp/kubectl get pods --v=7 2>&1")
Expect(execOutput).To(MatchRegexp("nginx +1/1 +Running"))
Expect(execOutput).To(ContainSubstring("Using in-cluster namespace"))
Expect(execOutput).To(ContainSubstring("Using in-cluster configuration"))

By("creating an object containing a namespace with in-cluster config")
_, err = framework.RunHostCmd(ns, simplePodName, "/tmp/kubectl create -f /tmp/invalid-configmap-with-namespace.yaml --v=7 2>&1")
Expect(err).To(ContainSubstring("Using in-cluster namespace"))
Expect(err).To(ContainSubstring("Using in-cluster configuration"))
Expect(err).To(ContainSubstring(fmt.Sprintf("POST https://%s:%s/api/v1/namespaces/configmap-namespace/configmaps", inClusterHost, inClusterPort)))

By("creating an object not containing a namespace with in-cluster config")
_, err = framework.RunHostCmd(ns, simplePodName, "/tmp/kubectl create -f /tmp/invalid-configmap-without-namespace.yaml --v=7 2>&1")
Expect(err).To(ContainSubstring("Using in-cluster namespace"))
Expect(err).To(ContainSubstring("Using in-cluster configuration"))
Expect(err).To(ContainSubstring(fmt.Sprintf("POST https://%s:%s/api/v1/namespaces/%s/configmaps", inClusterHost, inClusterPort, f.Namespace.Name)))

By("trying to use kubectl with invalid token")
_, err = framework.RunHostCmd(ns, simplePodName, "/tmp/kubectl get pods --token=invalid --v=7 2>&1")
Expand All @@ -629,13 +688,17 @@ var _ = framework.KubeDescribe("Kubectl client", func() {
Expect(err).To(ContainSubstring("GET http://invalid/api"))

By("trying to use kubectl with invalid namespace")
output, _ := framework.RunHostCmd(ns, simplePodName, "/tmp/kubectl get pods --namespace=invalid --v=6 2>&1")
Expect(output).To(ContainSubstring("No resources found"))
Expect(output).ToNot(ContainSubstring("Using in-cluster namespace"))
Expect(output).To(ContainSubstring("Using in-cluster configuration"))
if matched, _ := regexp.MatchString(fmt.Sprintf("GET http[s]?://%s:%s/api/v1/namespaces/invalid/pods", inClusterHost, inClusterPort), output); !matched {
framework.Failf("Unexpected kubectl exec output: ", output)
}
execOutput = framework.RunHostCmdOrDie(ns, simplePodName, "/tmp/kubectl get pods --namespace=invalid --v=6 2>&1")
Expect(execOutput).To(ContainSubstring("No resources found"))
Expect(execOutput).ToNot(ContainSubstring("Using in-cluster namespace"))
Expect(execOutput).To(ContainSubstring("Using in-cluster configuration"))
Expect(execOutput).To(MatchRegexp(fmt.Sprintf("GET http[s]?://%s:%s/api/v1/namespaces/invalid/pods", inClusterHost, inClusterPort)))

By("trying to use kubectl with kubeconfig")
execOutput = framework.RunHostCmdOrDie(ns, simplePodName, "/tmp/kubectl get pods --kubeconfig=/tmp/"+overrideKubeconfigName+" --v=6 2>&1")
Expect(execOutput).ToNot(ContainSubstring("Using in-cluster namespace"))
Expect(execOutput).ToNot(ContainSubstring("Using in-cluster configuration"))
Expect(execOutput).To(ContainSubstring("GET https://kubernetes.default.svc:443/api/v1/namespaces/default/pods"))
})
})

Expand Down