Merge pull request #44570 from liggitt/namespace-icc

Automatic merge from submit-queue

Explicit namespace from kubeconfig should override in-cluster config

Fixes #43662 

If an explicitly specified namespace is read from a kubeconfig file, we should not fall back to in-cluster config

```release-note
kubectl commands run inside a pod using a kubeconfig file now use the namespace specified in the kubeconfig file, instead of using the pod namespace. If no kubeconfig file is used, or the kubeconfig does not specify a namespace, the pod namespace is still used as a fallback.
```
pull/6/head
Kubernetes Submit Queue 2017-04-21 14:45:23 -07:00 committed by GitHub
commit fa750c02be
2 changed files with 64 additions and 15 deletions

View File

@ -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"
)
@ -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")

View File

@ -582,7 +582,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"})
@ -608,11 +608,41 @@ 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/"+overrideKubeconfigName)
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("trying to use kubectl with invalid token")
_, err = framework.RunHostCmd(ns, simplePodName, "/tmp/kubectl get pods --token=invalid --v=7 2>&1")
@ -631,13 +661,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"))
})
})