diff --git a/cmd/kubeadm/app/apis/kubeadm/v1alpha1/defaults.go b/cmd/kubeadm/app/apis/kubeadm/v1alpha1/defaults.go index 7674f89d3a6..a4bd946208c 100644 --- a/cmd/kubeadm/app/apis/kubeadm/v1alpha1/defaults.go +++ b/cmd/kubeadm/app/apis/kubeadm/v1alpha1/defaults.go @@ -18,21 +18,21 @@ package v1alpha1 import ( "net/url" + "strings" "k8s.io/apimachinery/pkg/runtime" "k8s.io/kubernetes/cmd/kubeadm/app/constants" ) const ( - DefaultServiceDNSDomain = "cluster.local" - DefaultServicesSubnet = "10.96.0.0/12" - DefaultKubernetesVersion = "stable-1.7" - DefaultAPIBindPort = 6443 - DefaultDiscoveryBindPort = 9898 - DefaultAuthorizationMode = "RBAC" - DefaultCACertPath = "/etc/kubernetes/pki/ca.crt" - DefaultCertificatesDir = "/etc/kubernetes/pki" - DefaultEtcdDataDir = "/var/lib/etcd" + DefaultServiceDNSDomain = "cluster.local" + DefaultServicesSubnet = "10.96.0.0/12" + DefaultKubernetesVersion = "stable-1.7" + DefaultAPIBindPort = 6443 + DefaultAuthorizationModes = "Node,RBAC" + DefaultCACertPath = "/etc/kubernetes/pki/ca.crt" + DefaultCertificatesDir = "/etc/kubernetes/pki" + DefaultEtcdDataDir = "/var/lib/etcd" ) func addDefaultingFuncs(scheme *runtime.Scheme) error { @@ -57,7 +57,7 @@ func SetDefaults_MasterConfiguration(obj *MasterConfiguration) { } if len(obj.AuthorizationModes) == 0 { - obj.AuthorizationModes = []string{DefaultAuthorizationMode} + obj.AuthorizationModes = strings.Split(DefaultAuthorizationModes, ",") } if obj.CertificatesDir == "" { diff --git a/cmd/kubeadm/app/apis/kubeadm/validation/validation.go b/cmd/kubeadm/app/apis/kubeadm/validation/validation.go index e338c4aefcf..ad3ecf674cc 100644 --- a/cmd/kubeadm/app/apis/kubeadm/validation/validation.go +++ b/cmd/kubeadm/app/apis/kubeadm/validation/validation.go @@ -49,10 +49,16 @@ var cloudproviders = []string{ "vsphere", } +// Describes the authorization modes that are enforced by kubeadm +var requiredAuthzModes = []string{ + authzmodes.ModeRBAC, + authzmodes.ModeNode, +} + func ValidateMasterConfiguration(c *kubeadm.MasterConfiguration) field.ErrorList { allErrs := field.ErrorList{} allErrs = append(allErrs, ValidateCloudProvider(c.CloudProvider, field.NewPath("cloudprovider"))...) - allErrs = append(allErrs, ValidateAuthorizationModes(c.AuthorizationModes, field.NewPath("authorization-mode"))...) + allErrs = append(allErrs, ValidateAuthorizationModes(c.AuthorizationModes, field.NewPath("authorization-modes"))...) allErrs = append(allErrs, ValidateNetworking(&c.Networking, field.NewPath("networking"))...) allErrs = append(allErrs, ValidateAPIServerCertSANs(c.APIServerCertSANs, field.NewPath("cert-altnames"))...) allErrs = append(allErrs, ValidateAbsolutePath(c.CertificatesDir, field.NewPath("certificates-dir"))...) @@ -72,20 +78,24 @@ func ValidateNodeConfiguration(c *kubeadm.NodeConfiguration) field.ErrorList { func ValidateAuthorizationModes(authzModes []string, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} + found := map[string]bool{} + for _, authzMode := range authzModes { if !authzmodes.IsValidAuthorizationMode(authzMode) { allErrs = append(allErrs, field.Invalid(fldPath, authzMode, "invalid authorization mode")) } - } - found := map[string]bool{} - for _, authzMode := range authzModes { if found[authzMode] { allErrs = append(allErrs, field.Invalid(fldPath, authzMode, "duplicate authorization mode")) continue } found[authzMode] = true } + for _, requiredMode := range requiredAuthzModes { + if !found[requiredMode] { + allErrs = append(allErrs, field.Required(fldPath, fmt.Sprintf("authorization mode %s must be enabled", requiredMode))) + } + } return allErrs } diff --git a/cmd/kubeadm/app/apis/kubeadm/validation/validation_test.go b/cmd/kubeadm/app/apis/kubeadm/validation/validation_test.go index 038cbd311c7..e892ab3721f 100644 --- a/cmd/kubeadm/app/apis/kubeadm/validation/validation_test.go +++ b/cmd/kubeadm/app/apis/kubeadm/validation/validation_test.go @@ -55,13 +55,14 @@ func TestValidateAuthorizationModes(t *testing.T) { expected bool }{ {[]string{""}, nil, false}, - {[]string{"rBAC"}, nil, false}, // not supported - {[]string{"rBAC", "Webhook"}, nil, false}, // not supported - {[]string{"RBAC", "Webhook", "Webhook"}, nil, false}, // not supported - {[]string{"not valid"}, nil, false}, // not supported - {[]string{"RBAC"}, nil, true}, // supported - {[]string{"Webhook"}, nil, true}, // supported - {[]string{"RBAC", "Webhook"}, nil, true}, // supported + {[]string{"rBAC"}, nil, false}, // mode not supported + {[]string{"rBAC", "Webhook"}, nil, false}, // mode not supported + {[]string{"RBAC", "Webhook"}, nil, false}, // mode Node required + {[]string{"Node", "RBAC", "Webhook", "Webhook"}, nil, false}, // no duplicates allowed + {[]string{"not valid"}, nil, false}, // invalid mode + {[]string{"Node", "RBAC"}, nil, true}, // supported + {[]string{"RBAC", "Node"}, nil, true}, // supported + {[]string{"Node", "RBAC", "Webhook", "ABAC"}, nil, true}, // supported } for _, rt := range tests { actual := ValidateAuthorizationModes(rt.s, rt.f) @@ -180,7 +181,7 @@ func TestValidateMasterConfiguration(t *testing.T) { }{ {&kubeadm.MasterConfiguration{}, false}, {&kubeadm.MasterConfiguration{ - AuthorizationModes: []string{"RBAC"}, + AuthorizationModes: []string{"Node", "RBAC"}, Networking: kubeadm.Networking{ ServiceSubnet: "10.96.0.1/12", DNSDomain: "cluster.local", @@ -188,7 +189,7 @@ func TestValidateMasterConfiguration(t *testing.T) { CertificatesDir: "/some/cert/dir", }, false}, {&kubeadm.MasterConfiguration{ - AuthorizationModes: []string{"RBAC"}, + AuthorizationModes: []string{"Node", "RBAC"}, Networking: kubeadm.Networking{ ServiceSubnet: "10.96.0.1/12", DNSDomain: "cluster.local", @@ -197,7 +198,7 @@ func TestValidateMasterConfiguration(t *testing.T) { Token: "abcdef.0123456789abcdef", }, true}, {&kubeadm.MasterConfiguration{ - AuthorizationModes: []string{"RBAC"}, + AuthorizationModes: []string{"Node", "RBAC"}, Networking: kubeadm.Networking{ ServiceSubnet: "2001:db8::/98", DNSDomain: "cluster.local", @@ -205,7 +206,7 @@ func TestValidateMasterConfiguration(t *testing.T) { CertificatesDir: "/some/cert/dir", }, false}, {&kubeadm.MasterConfiguration{ - AuthorizationModes: []string{"RBAC"}, + AuthorizationModes: []string{"Node", "RBAC"}, Networking: kubeadm.Networking{ ServiceSubnet: "2001:db8::/98", DNSDomain: "cluster.local", diff --git a/cmd/kubeadm/app/cmd/BUILD b/cmd/kubeadm/app/cmd/BUILD index 53b6ecd3769..be4434e1891 100644 --- a/cmd/kubeadm/app/cmd/BUILD +++ b/cmd/kubeadm/app/cmd/BUILD @@ -41,7 +41,6 @@ go_library( "//cmd/kubeadm/app/util/token:go_default_library", "//pkg/api:go_default_library", "//pkg/bootstrap/api:go_default_library", - "//pkg/kubeapiserver/authorizer/modes:go_default_library", "//pkg/kubectl/cmd/util:go_default_library", "//pkg/printers:go_default_library", "//pkg/util/i18n:go_default_library", @@ -56,7 +55,6 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/fields:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/net:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//vendor/k8s.io/apimachinery/pkg/version:go_default_library", "//vendor/k8s.io/apiserver/pkg/util/flag:go_default_library", "//vendor/k8s.io/client-go/kubernetes:go_default_library", @@ -76,7 +74,6 @@ go_test( deps = [ "//cmd/kubeadm/app/constants:go_default_library", "//cmd/kubeadm/app/preflight:go_default_library", - "//pkg/util/version:go_default_library", ], ) diff --git a/cmd/kubeadm/app/cmd/defaults.go b/cmd/kubeadm/app/cmd/defaults.go index f9f8d3aac72..937d5b8bdf9 100644 --- a/cmd/kubeadm/app/cmd/defaults.go +++ b/cmd/kubeadm/app/cmd/defaults.go @@ -21,12 +21,10 @@ import ( "net" netutil "k8s.io/apimachinery/pkg/util/net" - "k8s.io/apimachinery/pkg/util/sets" kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util" tokenutil "k8s.io/kubernetes/cmd/kubeadm/app/util/token" - authzmodes "k8s.io/kubernetes/pkg/kubeapiserver/authorizer/modes" "k8s.io/kubernetes/pkg/util/version" ) @@ -56,10 +54,6 @@ func setInitDynamicDefaults(cfg *kubeadmapi.MasterConfiguration) error { return fmt.Errorf("this version of kubeadm only supports deploying clusters with the control plane version >= %s. Current version: %s", kubeadmconstants.MinimumControlPlaneVersion.String(), cfg.KubernetesVersion) } - // Defaulting is made here because it's dependent on the version currently, which is determined above - // TODO(luxas): Cleanup this once we have dropped v1.6 support and move this code into the API group defaulting - cfg.AuthorizationModes = defaultAuthorizationModes(cfg.AuthorizationModes, k8sVersion) - fmt.Printf("[init] Using Kubernetes version: %s\n", cfg.KubernetesVersion) fmt.Printf("[init] Using Authorization modes: %v\n", cfg.AuthorizationModes) @@ -79,13 +73,3 @@ func setInitDynamicDefaults(cfg *kubeadmapi.MasterConfiguration) error { return nil } - -func defaultAuthorizationModes(authzModes []string, k8sVersion *version.Version) []string { - if kubeadmutil.IsNodeAuthorizerSupported(k8sVersion) { - strset := sets.NewString(authzModes...) - if !strset.Has(authzmodes.ModeNode) { - return append([]string{authzmodes.ModeNode}, authzModes...) - } - } - return authzModes -} diff --git a/cmd/kubeadm/app/cmd/defaults_test.go b/cmd/kubeadm/app/cmd/defaults_test.go index 0b5e46be084..6d428badb54 100644 --- a/cmd/kubeadm/app/cmd/defaults_test.go +++ b/cmd/kubeadm/app/cmd/defaults_test.go @@ -15,40 +15,3 @@ limitations under the License. */ package cmd - -import ( - "strings" - "testing" - - "k8s.io/kubernetes/pkg/util/version" -) - -func TestDefaultAuthorizationModes(t *testing.T) { - var tests = []struct { - authzModes []string - version string - expected []string - }{ - {[]string{"RBAC"}, "v1.6.0", []string{"RBAC"}}, - {[]string{"RBAC", "ABAC"}, "v1.6.4", []string{"RBAC", "ABAC"}}, - {[]string{"RBAC", "ABAC"}, "v1.7.0-beta.0", []string{"RBAC", "ABAC"}}, - {[]string{"RBAC"}, "v1.7.0", []string{"Node", "RBAC"}}, - {[]string{"RBAC", "Webhook"}, "v1.7.0-beta.1", []string{"Node", "RBAC", "Webhook"}}, - {[]string{"RBAC", "Webhook", "Node"}, "v1.7.0", []string{"RBAC", "Webhook", "Node"}}, - {[]string{"Node", "RBAC", "Webhook"}, "v1.7.0", []string{"Node", "RBAC", "Webhook"}}, - } - for _, rt := range tests { - k8sVersion, err := version.ParseSemantic(rt.version) - if err != nil { - t.Fatalf("couldn't parse given version") - } - actual := defaultAuthorizationModes(rt.authzModes, k8sVersion) - if strings.Join(actual, ",") != strings.Join(rt.expected, ",") { - t.Errorf( - "failed TestDefaultAuthorizationModes:\n\texpected: %s\n\t actual: %s", - strings.Join(rt.expected, ","), - strings.Join(actual, ","), - ) - } - } -} diff --git a/cmd/kubeadm/app/constants/constants.go b/cmd/kubeadm/app/constants/constants.go index d5ead117733..4b91728140b 100644 --- a/cmd/kubeadm/app/constants/constants.go +++ b/cmd/kubeadm/app/constants/constants.go @@ -114,7 +114,4 @@ var ( // MinimumAPIAggregationVersion specifies the minimum kubernetes version that can be used enabling the API aggregation in the apiserver and the front proxy flags MinimumAPIAggregationVersion = version.MustParseSemantic("v1.7.0-alpha.1") - - // MinimumNodeAuthorizerVersion specifies the minimum kubernetes version that can be used for enabling the node authorizer - MinimumNodeAuthorizerVersion = version.MustParseSemantic("v1.7.0-beta.1") ) diff --git a/cmd/kubeadm/app/master/BUILD b/cmd/kubeadm/app/master/BUILD index 763d7585835..e7db78a80e2 100644 --- a/cmd/kubeadm/app/master/BUILD +++ b/cmd/kubeadm/app/master/BUILD @@ -21,7 +21,6 @@ go_library( "//cmd/kubeadm/app/apis/kubeadm/v1alpha1:go_default_library", "//cmd/kubeadm/app/constants:go_default_library", "//cmd/kubeadm/app/images:go_default_library", - "//cmd/kubeadm/app/util:go_default_library", "//cmd/kubeadm/app/util/kubeconfig:go_default_library", "//pkg/bootstrap/api:go_default_library", "//pkg/kubeapiserver/authorizer/modes:go_default_library", diff --git a/cmd/kubeadm/app/master/manifests.go b/cmd/kubeadm/app/master/manifests.go index 734ddd13ef7..f047b8c082b 100644 --- a/cmd/kubeadm/app/master/manifests.go +++ b/cmd/kubeadm/app/master/manifests.go @@ -34,7 +34,6 @@ import ( kubeadmapiext "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1" kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" "k8s.io/kubernetes/cmd/kubeadm/app/images" - kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util" bootstrapapi "k8s.io/kubernetes/pkg/bootstrap/api" authzmodes "k8s.io/kubernetes/pkg/kubeapiserver/authorizer/modes" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" @@ -46,7 +45,6 @@ import ( const ( DefaultCloudConfigPath = "/etc/kubernetes/cloud-config" - defaultv16AdmissionControl = "NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,DefaultTolerationSeconds,ResourceQuota" defaultv17AdmissionControl = "Initializers,NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,ResourceQuota" etcd = "etcd" @@ -333,7 +331,7 @@ func getAPIServerCommand(cfg *kubeadmapi.MasterConfiguration, selfHosted bool, k defaultArguments := map[string]string{ "insecure-port": "0", - "admission-control": defaultv16AdmissionControl, + "admission-control": defaultv17AdmissionControl, "service-cluster-ip-range": cfg.Networking.ServiceSubnet, "service-account-key-file": filepath.Join(cfg.CertificatesDir, kubeadmconstants.ServiceAccountPublicKeyName), "client-ca-file": filepath.Join(cfg.CertificatesDir, kubeadmconstants.CACertName), @@ -358,10 +356,6 @@ func getAPIServerCommand(cfg *kubeadmapi.MasterConfiguration, selfHosted bool, k defaultArguments["proxy-client-cert-file"] = filepath.Join(cfg.CertificatesDir, kubeadmconstants.FrontProxyClientCertName) defaultArguments["proxy-client-key-file"] = filepath.Join(cfg.CertificatesDir, kubeadmconstants.FrontProxyClientKeyName) } - if kubeadmutil.IsNodeAuthorizerSupported(k8sVersion) { - // enable the NodeRestriction admission plugin - defaultArguments["admission-control"] = defaultv17AdmissionControl - } command = getComponentBaseCommand(apiServer) command = append(command, getExtraParameters(cfg.APIServerExtraArgs, defaultArguments)...) @@ -514,17 +508,15 @@ func getSelfHostedAPIServerEnv() []api.EnvVar { return append(getProxyEnvVars(), podIPEnvVar) } +// getAuthzParameters gets the authorization-related parameters to the api server +// At this point, we can assume the list of authorization modes is valid (due to that it has been validated in the API machinery code already) +// If the list is empty; it's defaulted (mostly for unit testing) func getAuthzParameters(modes []string) []string { command := []string{} strset := sets.NewString(modes...) - // RBAC must always be set, prepend that if not present in the list - // TODO(luxas): In v1.8, require the Node and RBAC authorizers to be present - // In v1.8 we can utilize the API defaulting/validation to do enforce this, - // currently this logic has to be split up into two places, which is sub-optimal. - // Cleanup work is possible in and should be done in v1.8 - if !strset.Has(authzmodes.ModeRBAC) { - modes = append([]string{authzmodes.ModeRBAC}, modes...) + if len(modes) == 0 { + return []string{fmt.Sprintf("--authorization-mode=%s", kubeadmapiext.DefaultAuthorizationModes)} } if strset.Has(authzmodes.ModeABAC) { diff --git a/cmd/kubeadm/app/master/manifests_test.go b/cmd/kubeadm/app/master/manifests_test.go index 462637aa315..2ff66df5402 100644 --- a/cmd/kubeadm/app/master/manifests_test.go +++ b/cmd/kubeadm/app/master/manifests_test.go @@ -517,12 +517,12 @@ func TestGetAPIServerCommand(t *testing.T) { API: kubeadm.API{BindPort: 123, AdvertiseAddress: "1.2.3.4"}, Networking: kubeadm.Networking{ServiceSubnet: "bar"}, CertificatesDir: testCertsDir, - KubernetesVersion: "v1.6.0", + KubernetesVersion: "v1.7.0", }, expected: []string{ "kube-apiserver", "--insecure-port=0", - "--admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,DefaultTolerationSeconds,ResourceQuota", + "--admission-control=Initializers,NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,ResourceQuota", "--service-cluster-ip-range=bar", "--service-account-key-file=" + testCertsDir + "/sa.pub", "--client-ca-file=" + testCertsDir + "/ca.crt", @@ -530,16 +530,18 @@ func TestGetAPIServerCommand(t *testing.T) { "--tls-private-key-file=" + testCertsDir + "/apiserver.key", "--kubelet-client-certificate=" + testCertsDir + "/apiserver-kubelet-client.crt", "--kubelet-client-key=" + testCertsDir + "/apiserver-kubelet-client.key", - fmt.Sprintf("--secure-port=%d", 123), + "--secure-port=123", "--allow-privileged=true", "--kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname", "--experimental-bootstrap-token-auth=true", + "--proxy-client-cert-file=/var/lib/certs/front-proxy-client.crt", + "--proxy-client-key-file=/var/lib/certs/front-proxy-client.key", "--requestheader-username-headers=X-Remote-User", "--requestheader-group-headers=X-Remote-Group", "--requestheader-extra-headers-prefix=X-Remote-Extra-", "--requestheader-client-ca-file=" + testCertsDir + "/front-proxy-ca.crt", "--requestheader-allowed-names=front-proxy-client", - "--authorization-mode=RBAC", + "--authorization-mode=Node,RBAC", "--advertise-address=1.2.3.4", "--etcd-servers=http://127.0.0.1:2379", }, @@ -549,12 +551,12 @@ func TestGetAPIServerCommand(t *testing.T) { API: kubeadm.API{BindPort: 123, AdvertiseAddress: "4.3.2.1"}, Networking: kubeadm.Networking{ServiceSubnet: "bar"}, CertificatesDir: testCertsDir, - KubernetesVersion: "v1.6.0", + KubernetesVersion: "v1.7.1", }, expected: []string{ "kube-apiserver", "--insecure-port=0", - "--admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,DefaultTolerationSeconds,ResourceQuota", + "--admission-control=Initializers,NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,ResourceQuota", "--service-cluster-ip-range=bar", "--service-account-key-file=" + testCertsDir + "/sa.pub", "--client-ca-file=" + testCertsDir + "/ca.crt", @@ -562,16 +564,18 @@ func TestGetAPIServerCommand(t *testing.T) { "--tls-private-key-file=" + testCertsDir + "/apiserver.key", "--kubelet-client-certificate=" + testCertsDir + "/apiserver-kubelet-client.crt", "--kubelet-client-key=" + testCertsDir + "/apiserver-kubelet-client.key", - fmt.Sprintf("--secure-port=%d", 123), + "--secure-port=123", "--allow-privileged=true", "--kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname", + "--proxy-client-cert-file=/var/lib/certs/front-proxy-client.crt", + "--proxy-client-key-file=/var/lib/certs/front-proxy-client.key", "--experimental-bootstrap-token-auth=true", "--requestheader-username-headers=X-Remote-User", "--requestheader-group-headers=X-Remote-Group", "--requestheader-extra-headers-prefix=X-Remote-Extra-", "--requestheader-client-ca-file=" + testCertsDir + "/front-proxy-ca.crt", "--requestheader-allowed-names=front-proxy-client", - "--authorization-mode=RBAC", + "--authorization-mode=Node,RBAC", "--advertise-address=4.3.2.1", "--etcd-servers=http://127.0.0.1:2379", }, @@ -582,12 +586,12 @@ func TestGetAPIServerCommand(t *testing.T) { Networking: kubeadm.Networking{ServiceSubnet: "bar"}, Etcd: kubeadm.Etcd{CertFile: "fiz", KeyFile: "faz"}, CertificatesDir: testCertsDir, - KubernetesVersion: "v1.6.0", + KubernetesVersion: "v1.7.2", }, expected: []string{ "kube-apiserver", "--insecure-port=0", - "--admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,DefaultTolerationSeconds,ResourceQuota", + "--admission-control=Initializers,NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,ResourceQuota", "--service-cluster-ip-range=bar", "--service-account-key-file=" + testCertsDir + "/sa.pub", "--client-ca-file=" + testCertsDir + "/ca.crt", @@ -595,16 +599,18 @@ func TestGetAPIServerCommand(t *testing.T) { "--tls-private-key-file=" + testCertsDir + "/apiserver.key", "--kubelet-client-certificate=" + testCertsDir + "/apiserver-kubelet-client.crt", "--kubelet-client-key=" + testCertsDir + "/apiserver-kubelet-client.key", - fmt.Sprintf("--secure-port=%d", 123), + "--secure-port=123", "--allow-privileged=true", "--kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname", "--experimental-bootstrap-token-auth=true", + "--proxy-client-cert-file=/var/lib/certs/front-proxy-client.crt", + "--proxy-client-key-file=/var/lib/certs/front-proxy-client.key", "--requestheader-username-headers=X-Remote-User", "--requestheader-group-headers=X-Remote-Group", "--requestheader-extra-headers-prefix=X-Remote-Extra-", "--requestheader-client-ca-file=" + testCertsDir + "/front-proxy-ca.crt", "--requestheader-allowed-names=front-proxy-client", - "--authorization-mode=RBAC", + "--authorization-mode=Node,RBAC", "--advertise-address=4.3.2.1", "--etcd-servers=http://127.0.0.1:2379", "--etcd-certfile=fiz", @@ -617,7 +623,7 @@ func TestGetAPIServerCommand(t *testing.T) { Networking: kubeadm.Networking{ServiceSubnet: "bar"}, Etcd: kubeadm.Etcd{CertFile: "fiz", KeyFile: "faz"}, CertificatesDir: testCertsDir, - KubernetesVersion: "v1.7.0", + KubernetesVersion: "v1.7.3", }, expected: []string{ "kube-apiserver", @@ -641,7 +647,7 @@ func TestGetAPIServerCommand(t *testing.T) { "--requestheader-extra-headers-prefix=X-Remote-Extra-", "--requestheader-client-ca-file=" + testCertsDir + "/front-proxy-ca.crt", "--requestheader-allowed-names=front-proxy-client", - "--authorization-mode=RBAC", + "--authorization-mode=Node,RBAC", "--advertise-address=4.3.2.1", "--etcd-servers=http://127.0.0.1:2379", "--etcd-certfile=fiz", @@ -678,7 +684,7 @@ func TestGetAPIServerCommand(t *testing.T) { "--requestheader-extra-headers-prefix=X-Remote-Extra-", "--requestheader-client-ca-file=" + testCertsDir + "/front-proxy-ca.crt", "--requestheader-allowed-names=front-proxy-client", - "--authorization-mode=RBAC", + "--authorization-mode=Node,RBAC", "--advertise-address=2001:db8::1", "--etcd-servers=http://127.0.0.1:2379", "--etcd-certfile=fiz", @@ -882,7 +888,7 @@ func TestGetAuthzParameters(t *testing.T) { { authMode: []string{}, expected: []string{ - "--authorization-mode=RBAC", + "--authorization-mode=Node,RBAC", }, }, { @@ -894,26 +900,26 @@ func TestGetAuthzParameters(t *testing.T) { { authMode: []string{"AlwaysAllow"}, expected: []string{ - "--authorization-mode=RBAC,AlwaysAllow", + "--authorization-mode=AlwaysAllow", }, }, { authMode: []string{"AlwaysDeny"}, expected: []string{ - "--authorization-mode=RBAC,AlwaysDeny", + "--authorization-mode=AlwaysDeny", }, }, { authMode: []string{"ABAC"}, expected: []string{ - "--authorization-mode=RBAC,ABAC", + "--authorization-mode=ABAC", "--authorization-policy-file=/etc/kubernetes/abac_policy.json", }, }, { authMode: []string{"ABAC", "Webhook"}, expected: []string{ - "--authorization-mode=RBAC,ABAC,Webhook", + "--authorization-mode=ABAC,Webhook", "--authorization-policy-file=/etc/kubernetes/abac_policy.json", "--authorization-webhook-config-file=/etc/kubernetes/webhook_authz.conf", }, diff --git a/cmd/kubeadm/app/phases/apiconfig/BUILD b/cmd/kubeadm/app/phases/apiconfig/BUILD index 537fe78c8de..a36f6b63036 100644 --- a/cmd/kubeadm/app/phases/apiconfig/BUILD +++ b/cmd/kubeadm/app/phases/apiconfig/BUILD @@ -8,6 +8,31 @@ load( "go_test", ) +go_test( + name = "go_default_test", + srcs = [ + "clusterroles_test.go", + "setupmaster_test.go", + ], + library = ":go_default_library", + tags = ["automanaged"], + deps = [ + "//cmd/kubeadm/app/constants:go_default_library", + "//pkg/api:go_default_library", + "//pkg/kubelet/apis:go_default_library", + "//pkg/util/node:go_default_library", + "//vendor/k8s.io/api/core/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", + "//vendor/k8s.io/client-go/kubernetes:go_default_library", + "//vendor/k8s.io/client-go/kubernetes/fake:go_default_library", + "//vendor/k8s.io/client-go/kubernetes/typed/core/v1:go_default_library", + "//vendor/k8s.io/client-go/rest:go_default_library", + "//vendor/k8s.io/client-go/testing:go_default_library", + ], +) + go_library( name = "go_default_library", srcs = [ @@ -17,7 +42,6 @@ go_library( tags = ["automanaged"], deps = [ "//cmd/kubeadm/app/constants:go_default_library", - "//cmd/kubeadm/app/util:go_default_library", "//pkg/apis/rbac/v1beta1:go_default_library", "//pkg/bootstrap/api:go_default_library", "//pkg/kubelet/apis:go_default_library", @@ -46,28 +70,3 @@ filegroup( srcs = [":package-srcs"], tags = ["automanaged"], ) - -go_test( - name = "go_default_test", - srcs = [ - "clusterroles_test.go", - "setupmaster_test.go", - ], - library = ":go_default_library", - tags = ["automanaged"], - deps = [ - "//cmd/kubeadm/app/constants:go_default_library", - "//pkg/api:go_default_library", - "//pkg/kubelet/apis:go_default_library", - "//pkg/util/node:go_default_library", - "//vendor/k8s.io/api/core/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", - "//vendor/k8s.io/client-go/kubernetes:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/fake:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/core/v1:go_default_library", - "//vendor/k8s.io/client-go/rest:go_default_library", - "//vendor/k8s.io/client-go/testing:go_default_library", - ], -) diff --git a/cmd/kubeadm/app/phases/apiconfig/clusterroles.go b/cmd/kubeadm/app/phases/apiconfig/clusterroles.go index 8ae4b1e6412..64d624a3b17 100644 --- a/cmd/kubeadm/app/phases/apiconfig/clusterroles.go +++ b/cmd/kubeadm/app/phases/apiconfig/clusterroles.go @@ -25,7 +25,6 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" clientset "k8s.io/client-go/kubernetes" kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" - kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util" rbachelper "k8s.io/kubernetes/pkg/apis/rbac/v1beta1" bootstrapapi "k8s.io/kubernetes/pkg/bootstrap/api" "k8s.io/kubernetes/pkg/util/version" @@ -254,33 +253,28 @@ func createClusterRoleBindings(clientset *clientset.Clientset) error { func deletePermissiveNodesBindingWhenUsingNodeAuthorization(clientset *clientset.Clientset, k8sVersion *version.Version) error { - // If the server version is higher than the Node Authorizer's minimum, try to delete the Group=system:nodes->ClusterRole=system:node binding - // which is much more permissive than the Node Authorizer - if kubeadmutil.IsNodeAuthorizerSupported(k8sVersion) { - - nodesRoleBinding, err := clientset.RbacV1beta1().ClusterRoleBindings().Get(kubeadmconstants.NodesClusterRoleBinding, metav1.GetOptions{}) - if err != nil { - if apierrors.IsNotFound(err) { - // Nothing to do; the RoleBinding doesn't exist - return nil - } - return err + nodesRoleBinding, err := clientset.RbacV1beta1().ClusterRoleBindings().Get(kubeadmconstants.NodesClusterRoleBinding, metav1.GetOptions{}) + if err != nil { + if apierrors.IsNotFound(err) { + // Nothing to do; the RoleBinding doesn't exist + return nil } + return err + } - newSubjects := []rbac.Subject{} - for _, subject := range nodesRoleBinding.Subjects { - // Skip the subject that binds to the system:nodes group - if subject.Name == kubeadmconstants.NodesGroup && subject.Kind == "Group" { - continue - } - newSubjects = append(newSubjects, subject) + newSubjects := []rbac.Subject{} + for _, subject := range nodesRoleBinding.Subjects { + // Skip the subject that binds to the system:nodes group + if subject.Name == kubeadmconstants.NodesGroup && subject.Kind == "Group" { + continue } + newSubjects = append(newSubjects, subject) + } - nodesRoleBinding.Subjects = newSubjects + nodesRoleBinding.Subjects = newSubjects - if _, err := clientset.RbacV1beta1().ClusterRoleBindings().Update(nodesRoleBinding); err != nil { - return err - } + if _, err := clientset.RbacV1beta1().ClusterRoleBindings().Update(nodesRoleBinding); err != nil { + return err } return nil diff --git a/cmd/kubeadm/app/util/BUILD b/cmd/kubeadm/app/util/BUILD index e6ef04f31cc..aba1277a54a 100644 --- a/cmd/kubeadm/app/util/BUILD +++ b/cmd/kubeadm/app/util/BUILD @@ -17,9 +17,7 @@ go_library( ], tags = ["automanaged"], deps = [ - "//cmd/kubeadm/app/constants:go_default_library", "//cmd/kubeadm/app/preflight:go_default_library", - "//pkg/util/version:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/errors:go_default_library", ], ) @@ -33,10 +31,7 @@ go_test( ], library = ":go_default_library", tags = ["automanaged"], - deps = [ - "//cmd/kubeadm/app/preflight:go_default_library", - "//pkg/util/version:go_default_library", - ], + deps = ["//cmd/kubeadm/app/preflight:go_default_library"], ) filegroup( diff --git a/cmd/kubeadm/app/util/version.go b/cmd/kubeadm/app/util/version.go index fd349bc691e..8f2bf7d44ef 100644 --- a/cmd/kubeadm/app/util/version.go +++ b/cmd/kubeadm/app/util/version.go @@ -22,9 +22,6 @@ import ( "net/http" "regexp" "strings" - - kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" - "k8s.io/kubernetes/pkg/util/version" ) var ( @@ -72,12 +69,3 @@ func KubernetesReleaseVersion(version string) (string, error) { } return "", fmt.Errorf("version %q doesn't match patterns for neither semantic version nor labels (stable, latest, ...)", version) } - -// IsNodeAuthorizerSupported returns true if the provided version of kubernetes is able to use the Node Authorizer feature. -// There is a really nasty problem with the branching here and the timing of this feature implementation. When the release-1.7 branch was -// cut, two new tags were made: v1.7.0-beta.0 and v1.8.0-alpha.0. The Node Authorizer feature merged _after those cuts_. This means the minimum -// version we have to use is v1.7.0-beta.1. BUT since v1.8.0-alpha.0 sorts higher than v1.7.0-beta.1 (the actual version gate), we have to manually -// exclude v1.8.0-alpha.0 from this condition. v1.8.0-alpha.1 will indeed contain the patch. -func IsNodeAuthorizerSupported(k8sVersion *version.Version) bool { - return k8sVersion.AtLeast(kubeadmconstants.MinimumNodeAuthorizerVersion) && k8sVersion.String() != "1.8.0-alpha.0" -} diff --git a/cmd/kubeadm/app/util/version_test.go b/cmd/kubeadm/app/util/version_test.go index 7fe7c002ede..418f7b0dc1f 100644 --- a/cmd/kubeadm/app/util/version_test.go +++ b/cmd/kubeadm/app/util/version_test.go @@ -22,8 +22,6 @@ import ( "path" "strings" "testing" - - "k8s.io/kubernetes/pkg/util/version" ) func TestEmptyVersion(t *testing.T) { @@ -122,38 +120,3 @@ func TestVersionFromNetwork(t *testing.T) { } } } - -func TestIsNodeAuthorizerSupported(t *testing.T) { - versionsSupported := map[string]bool{ - "v1.6.0": false, - "v1.6.9": false, - "v1.7.0-alpha.1": false, - "v1.7.0-alpha.2": false, - "v1.7.0-alpha.3": false, - "v1.7.0-alpha.4": false, - "v1.7.0-beta.0": false, - "v1.7.0-beta.1": true, // BREAKPOINT! - "v1.7.0-beta.2": true, - "v1.7.0-rc.0": true, - "v1.7.0": true, - "v1.7.3": true, - "v1.8.0-alpha.0": false, // EXCEPTION! - "v1.8.0-alpha.1": true, - "v1.8.0-alpha.2": true, - "v1.8.0-beta.0": true, - "v1.8.0-beta.1": true, - "v1.8.0-rc.0": true, - "v1.8.0": true, - "v1.8.6": true, - } - for ver, expected := range versionsSupported { - - parsedVersion, err := version.ParseSemantic(ver) - if err != nil { - t.Fatalf("version %s must parse", ver) - } - if actual := IsNodeAuthorizerSupported(parsedVersion); actual != expected { - t.Errorf("IsNodeAuthorizerSupported: unexpected result for version %s, expected %t but got %t", ver, expected, actual) - } - } -}