kubeadm: Cleanup version gates for the Node Authorizer when targeting v1.8

This commit is contained in:
Lucas Käldström 2017-06-24 19:21:41 +03:00
parent a81c659250
commit 051db16083
No known key found for this signature in database
GPG Key ID: 3FA3783D77751514
15 changed files with 111 additions and 223 deletions

View File

@ -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 == "" {

View File

@ -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
}

View File

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

View File

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

View File

@ -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
}

View File

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

View File

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

View File

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

View File

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

View File

@ -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",
},

View File

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

View File

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

View File

@ -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(

View File

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

View File

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