Merge pull request #42557 from xilabao/use-authorizationModes

Automatic merge from submit-queue

Allow multiple providers for authorizationMode

fixes https://github.com/kubernetes/kubeadm/issues/177
This commit is contained in:
Kubernetes Submit Queue 2017-04-06 08:03:04 -07:00 committed by GitHub
commit 2d66f7bd28
10 changed files with 87 additions and 64 deletions

View File

@ -32,7 +32,7 @@ func KubeadmFuzzerFuncs(t apitesting.TestingCommon) []interface{} {
obj.API.AdvertiseAddress = "foo"
obj.Networking.ServiceSubnet = "foo"
obj.Networking.DNSDomain = "foo"
obj.AuthorizationMode = "foo"
obj.AuthorizationModes = []string{"foo"}
obj.CertificatesDir = "foo"
obj.APIServerCertSANs = []string{}
obj.Token = "foo"

View File

@ -33,12 +33,12 @@ type EnvParams struct {
type MasterConfiguration struct {
metav1.TypeMeta
API API
Etcd Etcd
Networking Networking
KubernetesVersion string
CloudProvider string
AuthorizationMode string
API API
Etcd Etcd
Networking Networking
KubernetesVersion string
CloudProvider string
AuthorizationModes []string
Token string
TokenTTL time.Duration

View File

@ -59,8 +59,8 @@ func SetDefaults_MasterConfiguration(obj *MasterConfiguration) {
obj.Networking.DNSDomain = DefaultServiceDNSDomain
}
if obj.AuthorizationMode == "" {
obj.AuthorizationMode = DefaultAuthorizationMode
if len(obj.AuthorizationModes) == 0 {
obj.AuthorizationModes = []string{DefaultAuthorizationMode}
}
if obj.CertificatesDir == "" {

View File

@ -25,12 +25,12 @@ import (
type MasterConfiguration struct {
metav1.TypeMeta `json:",inline"`
API API `json:"api"`
Etcd Etcd `json:"etcd"`
Networking Networking `json:"networking"`
KubernetesVersion string `json:"kubernetesVersion"`
CloudProvider string `json:"cloudProvider"`
AuthorizationMode string `json:"authorizationMode"`
API API `json:"api"`
Etcd Etcd `json:"etcd"`
Networking Networking `json:"networking"`
KubernetesVersion string `json:"kubernetesVersion"`
CloudProvider string `json:"cloudProvider"`
AuthorizationModes []string `json:"authorizationModes"`
Token string `json:"token"`
TokenTTL time.Duration `json:"tokenTTL"`

View File

@ -52,7 +52,7 @@ var cloudproviders = []string{
func ValidateMasterConfiguration(c *kubeadm.MasterConfiguration) field.ErrorList {
allErrs := field.ErrorList{}
allErrs = append(allErrs, ValidateCloudProvider(c.CloudProvider, field.NewPath("cloudprovider"))...)
allErrs = append(allErrs, ValidateAuthorizationMode(c.AuthorizationMode, field.NewPath("authorization-mode"))...)
allErrs = append(allErrs, ValidateAuthorizationModes(c.AuthorizationModes, field.NewPath("authorization-mode"))...)
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"))...)
@ -70,11 +70,23 @@ func ValidateNodeConfiguration(c *kubeadm.NodeConfiguration) field.ErrorList {
return allErrs
}
func ValidateAuthorizationMode(authzMode string, fldPath *field.Path) field.ErrorList {
if !authzmodes.IsValidAuthorizationMode(authzMode) {
return field.ErrorList{field.Invalid(fldPath, authzMode, "invalid authorization mode")}
func ValidateAuthorizationModes(authzModes []string, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
for _, authzMode := range authzModes {
if !authzmodes.IsValidAuthorizationMode(authzMode) {
allErrs = append(allErrs, field.Invalid(fldPath, authzMode, "invalid authorization mode"))
}
}
return field.ErrorList{}
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
}
return allErrs
}
func ValidateDiscovery(c *kubeadm.NodeConfiguration, fldPath *field.Path) field.ErrorList {

View File

@ -45,23 +45,26 @@ func TestValidateTokenDiscovery(t *testing.T) {
}
}
func TestValidateAuthorizationMode(t *testing.T) {
func TestValidateAuthorizationModes(t *testing.T) {
var tests = []struct {
s string
s []string
f *field.Path
expected bool
}{
{"", nil, false},
{"rBAC", nil, false}, // not supported
{"not valid", nil, false}, // not supported
{"RBAC", nil, true}, // supported
{"Webhook", nil, true}, // supported
{[]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
}
for _, rt := range tests {
actual := ValidateAuthorizationMode(rt.s, rt.f)
actual := ValidateAuthorizationModes(rt.s, rt.f)
if (len(actual) == 0) != rt.expected {
t.Errorf(
"failed ValidateAuthorizationMode:\n\texpected: %t\n\t actual: %t",
"failed ValidateAuthorizationModes:\n\texpected: %t\n\t actual: %t",
rt.expected,
(len(actual) == 0),
)
@ -172,7 +175,7 @@ func TestValidateMasterConfiguration(t *testing.T) {
}{
{&kubeadm.MasterConfiguration{}, false},
{&kubeadm.MasterConfiguration{
AuthorizationMode: "RBAC",
AuthorizationModes: []string{"RBAC"},
Networking: kubeadm.Networking{
ServiceSubnet: "10.96.0.1/12",
DNSDomain: "cluster.local",
@ -180,7 +183,7 @@ func TestValidateMasterConfiguration(t *testing.T) {
CertificatesDir: "/some/cert/dir",
}, false},
{&kubeadm.MasterConfiguration{
AuthorizationMode: "RBAC",
AuthorizationModes: []string{"RBAC"},
Networking: kubeadm.Networking{
ServiceSubnet: "10.96.0.1/12",
DNSDomain: "cluster.local",

View File

@ -58,7 +58,7 @@ func setInitDynamicDefaults(cfg *kubeadmapi.MasterConfiguration) error {
}
fmt.Printf("[init] Using Kubernetes version: %s\n", cfg.KubernetesVersion)
fmt.Printf("[init] Using Authorization mode: %s\n", cfg.AuthorizationMode)
fmt.Printf("[init] Using Authorization mode: %v\n", cfg.AuthorizationModes)
// Warn about the limitations with the current cloudprovider solution.
if cfg.CloudProvider != "" {

View File

@ -330,7 +330,7 @@ func getAPIServerCommand(cfg *kubeadmapi.MasterConfiguration, selfHosted bool) [
command = getComponentBaseCommand(apiServer)
command = append(command, getExtraParameters(cfg.APIServerExtraArgs, defaultArguments)...)
command = append(command, getAuthzParameters(cfg.AuthorizationMode)...)
command = append(command, getAuthzParameters(cfg.AuthorizationModes)...)
if selfHosted {
command = append(command, "--advertise-address=$(POD_IP)")
@ -460,22 +460,23 @@ func getSelfHostedAPIServerEnv() []api.EnvVar {
return append(getProxyEnvVars(), podIPEnvVar)
}
func getAuthzParameters(authzMode string) []string {
func getAuthzParameters(modes []string) []string {
command := []string{}
// RBAC is always on. If the user specified
authzModes := []string{authzmodes.ModeRBAC}
if len(authzMode) != 0 && authzMode != authzmodes.ModeRBAC {
authzModes = append(authzModes, authzMode)
for _, authzMode := range modes {
if len(authzMode) != 0 && authzMode != authzmodes.ModeRBAC {
authzModes = append(authzModes, authzMode)
}
switch authzMode {
case authzmodes.ModeABAC:
command = append(command, "--authorization-policy-file="+kubeadmconstants.AuthorizationPolicyPath)
case authzmodes.ModeWebhook:
command = append(command, "--authorization-webhook-config-file="+kubeadmconstants.AuthorizationWebhookConfigPath)
}
}
command = append(command, "--authorization-mode="+strings.Join(authzModes, ","))
switch authzMode {
case authzmodes.ModeABAC:
command = append(command, "--authorization-policy-file="+kubeadmconstants.AuthorizationPolicyPath)
case authzmodes.ModeWebhook:
command = append(command, "--authorization-webhook-config-file="+kubeadmconstants.AuthorizationWebhookConfigPath)
}
return command
}

View File

@ -652,44 +652,53 @@ func TestGetSchedulerCommand(t *testing.T) {
func TestGetAuthzParameters(t *testing.T) {
var tests = []struct {
authMode string
authMode []string
expected []string
}{
{
authMode: "",
authMode: []string{},
expected: []string{
"--authorization-mode=RBAC",
},
},
{
authMode: "RBAC",
authMode: []string{"RBAC"},
expected: []string{
"--authorization-mode=RBAC",
},
},
{
authMode: "AlwaysAllow",
authMode: []string{"AlwaysAllow"},
expected: []string{
"--authorization-mode=RBAC,AlwaysAllow",
},
},
{
authMode: "AlwaysDeny",
authMode: []string{"AlwaysDeny"},
expected: []string{
"--authorization-mode=RBAC,AlwaysDeny",
},
},
{
authMode: "ABAC",
authMode: []string{"ABAC"},
expected: []string{
"--authorization-mode=RBAC,ABAC",
"--authorization-policy-file=/etc/kubernetes/abac_policy.json",
},
},
{
authMode: "Webhook",
authMode: []string{"ABAC", "Webhook"},
expected: []string{
"--authorization-mode=RBAC,Webhook",
"--authorization-mode=RBAC,ABAC,Webhook",
"--authorization-policy-file=/etc/kubernetes/abac_policy.json",
"--authorization-webhook-config-file=/etc/kubernetes/webhook_authz.conf",
},
},
{
authMode: []string{"ABAC", "RBAC", "Webhook"},
expected: []string{
"--authorization-mode=RBAC,ABAC,Webhook",
"--authorization-policy-file=/etc/kubernetes/abac_policy.json",
"--authorization-webhook-config-file=/etc/kubernetes/webhook_authz.conf",
},
},
@ -697,14 +706,10 @@ func TestGetAuthzParameters(t *testing.T) {
for _, rt := range tests {
actual := getAuthzParameters(rt.authMode)
for i := range actual {
if actual[i] != rt.expected[i] {
t.Errorf(
"failed getAuthzParameters:\n\texpected: %s\n\t actual: %s",
rt.expected[i],
actual[i],
)
}
sort.Strings(actual)
sort.Strings(rt.expected)
if !reflect.DeepEqual(actual, rt.expected) {
t.Errorf("failed getAuthzParameters:\nexpected:\n%v\nsaw:\n%v", rt.expected, actual)
}
}
}

View File

@ -525,11 +525,13 @@ func RunInitMasterChecks(cfg *kubeadmapi.MasterConfiguration) error {
}
// Check the config for authorization mode
switch cfg.AuthorizationMode {
case authzmodes.ModeABAC:
checks = append(checks, FileExistingCheck{Path: kubeadmconstants.AuthorizationPolicyPath})
case authzmodes.ModeWebhook:
checks = append(checks, FileExistingCheck{Path: kubeadmconstants.AuthorizationWebhookConfigPath})
for _, authzMode := range cfg.AuthorizationModes {
switch authzMode {
case authzmodes.ModeABAC:
checks = append(checks, FileExistingCheck{Path: kubeadmconstants.AuthorizationPolicyPath})
case authzmodes.ModeWebhook:
checks = append(checks, FileExistingCheck{Path: kubeadmconstants.AuthorizationWebhookConfigPath})
}
}
return RunChecks(checks, os.Stderr)