diff --git a/pkg/kubeapiserver/authorizer/BUILD b/pkg/kubeapiserver/authorizer/BUILD index 81b9b921280..89f46026310 100644 --- a/pkg/kubeapiserver/authorizer/BUILD +++ b/pkg/kubeapiserver/authorizer/BUILD @@ -16,6 +16,7 @@ go_test( ], library = ":go_default_library", tags = ["automanaged"], + deps = ["//pkg/kubeapiserver/authorizer/modes:go_default_library"], ) go_library( @@ -25,6 +26,7 @@ go_library( deps = [ "//pkg/auth/authorizer/abac:go_default_library", "//pkg/controller/informers:go_default_library", + "//pkg/kubeapiserver/authorizer/modes:go_default_library", "//plugin/pkg/auth/authorizer/rbac:go_default_library", "//vendor:k8s.io/apiserver/pkg/authorization/authorizer", "//vendor:k8s.io/apiserver/pkg/authorization/authorizerfactory", @@ -42,6 +44,9 @@ filegroup( filegroup( name = "all-srcs", - srcs = [":package-srcs"], + srcs = [ + ":package-srcs", + "//pkg/kubeapiserver/authorizer/modes:all-srcs", + ], tags = ["automanaged"], ) diff --git a/pkg/kubeapiserver/authorizer/config.go b/pkg/kubeapiserver/authorizer/config.go index 750edc2eddd..3d6389ceeed 100644 --- a/pkg/kubeapiserver/authorizer/config.go +++ b/pkg/kubeapiserver/authorizer/config.go @@ -27,17 +27,10 @@ import ( "k8s.io/apiserver/plugin/pkg/authorizer/webhook" "k8s.io/kubernetes/pkg/auth/authorizer/abac" "k8s.io/kubernetes/pkg/controller/informers" + "k8s.io/kubernetes/pkg/kubeapiserver/authorizer/modes" "k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac" ) -const ( - ModeAlwaysAllow string = "AlwaysAllow" - ModeAlwaysDeny string = "AlwaysDeny" - ModeABAC string = "ABAC" - ModeWebhook string = "Webhook" - ModeRBAC string = "RBAC" -) - type AuthorizationConfig struct { AuthorizationModes []string @@ -79,11 +72,11 @@ func (config AuthorizationConfig) New() (authorizer.Authorizer, error) { } // Keep cases in sync with constant list above. switch authorizationMode { - case ModeAlwaysAllow: + case modes.ModeAlwaysAllow: authorizers = append(authorizers, authorizerfactory.NewAlwaysAllowAuthorizer()) - case ModeAlwaysDeny: + case modes.ModeAlwaysDeny: authorizers = append(authorizers, authorizerfactory.NewAlwaysDenyAuthorizer()) - case ModeABAC: + case modes.ModeABAC: if config.PolicyFile == "" { return nil, errors.New("ABAC's authorization policy file not passed") } @@ -92,7 +85,7 @@ func (config AuthorizationConfig) New() (authorizer.Authorizer, error) { return nil, err } authorizers = append(authorizers, abacAuthorizer) - case ModeWebhook: + case modes.ModeWebhook: if config.WebhookConfigFile == "" { return nil, errors.New("Webhook's configuration file not passed") } @@ -103,7 +96,7 @@ func (config AuthorizationConfig) New() (authorizer.Authorizer, error) { return nil, err } authorizers = append(authorizers, webhookAuthorizer) - case ModeRBAC: + case modes.ModeRBAC: rbacAuthorizer := rbac.New( config.InformerFactory.Roles().Lister(), config.InformerFactory.RoleBindings().Lister(), @@ -117,13 +110,13 @@ func (config AuthorizationConfig) New() (authorizer.Authorizer, error) { authorizerMap[authorizationMode] = true } - if !authorizerMap[ModeABAC] && config.PolicyFile != "" { + if !authorizerMap[modes.ModeABAC] && config.PolicyFile != "" { return nil, errors.New("Cannot specify --authorization-policy-file without mode ABAC") } - if !authorizerMap[ModeWebhook] && config.WebhookConfigFile != "" { + if !authorizerMap[modes.ModeWebhook] && config.WebhookConfigFile != "" { return nil, errors.New("Cannot specify --authorization-webhook-config-file without mode Webhook") } - if !authorizerMap[ModeRBAC] && config.RBACSuperUser != "" { + if !authorizerMap[modes.ModeRBAC] && config.RBACSuperUser != "" { return nil, errors.New("Cannot specify --authorization-rbac-super-user without mode RBAC") } diff --git a/pkg/kubeapiserver/authorizer/config_test.go b/pkg/kubeapiserver/authorizer/config_test.go index 2353cbce3c8..ac2d5e983fd 100644 --- a/pkg/kubeapiserver/authorizer/config_test.go +++ b/pkg/kubeapiserver/authorizer/config_test.go @@ -17,6 +17,7 @@ limitations under the License. package authorizer import ( + "k8s.io/kubernetes/pkg/kubeapiserver/authorizer/modes" "testing" ) @@ -39,19 +40,19 @@ func TestNew(t *testing.T) { { // ModeAlwaysAllow and ModeAlwaysDeny should return without authorizationPolicyFile // but error if one is given - config: AuthorizationConfig{AuthorizationModes: []string{ModeAlwaysAllow, ModeAlwaysDeny}}, + config: AuthorizationConfig{AuthorizationModes: []string{modes.ModeAlwaysAllow, modes.ModeAlwaysDeny}}, msg: "returned an error for valid config", }, { // ModeABAC requires a policy file - config: AuthorizationConfig{AuthorizationModes: []string{ModeAlwaysAllow, ModeAlwaysDeny, ModeABAC}}, + config: AuthorizationConfig{AuthorizationModes: []string{modes.ModeAlwaysAllow, modes.ModeAlwaysDeny, modes.ModeABAC}}, wantErr: true, msg: "specifying ABAC with no policy file should return an error", }, { // ModeABAC should not error if a valid policy path is provided config: AuthorizationConfig{ - AuthorizationModes: []string{ModeAlwaysAllow, ModeAlwaysDeny, ModeABAC}, + AuthorizationModes: []string{modes.ModeAlwaysAllow, modes.ModeAlwaysDeny, modes.ModeABAC}, PolicyFile: examplePolicyFile, }, msg: "errored while using a valid policy file", @@ -60,7 +61,7 @@ func TestNew(t *testing.T) { // Authorization Policy file cannot be used without ModeABAC config: AuthorizationConfig{ - AuthorizationModes: []string{ModeAlwaysAllow, ModeAlwaysDeny}, + AuthorizationModes: []string{modes.ModeAlwaysAllow, modes.ModeAlwaysDeny}, PolicyFile: examplePolicyFile, }, wantErr: true, @@ -74,14 +75,14 @@ func TestNew(t *testing.T) { }, { // ModeWebhook requires at minimum a target. - config: AuthorizationConfig{AuthorizationModes: []string{ModeWebhook}}, + config: AuthorizationConfig{AuthorizationModes: []string{modes.ModeWebhook}}, wantErr: true, msg: "should have errored when config was empty with ModeWebhook", }, { // Cannot provide webhook flags without ModeWebhook config: AuthorizationConfig{ - AuthorizationModes: []string{ModeAlwaysAllow}, + AuthorizationModes: []string{modes.ModeAlwaysAllow}, WebhookConfigFile: "authz_webhook_config.yml", }, wantErr: true, diff --git a/pkg/kubeapiserver/authorizer/modes/BUILD b/pkg/kubeapiserver/authorizer/modes/BUILD new file mode 100644 index 00000000000..df54566faef --- /dev/null +++ b/pkg/kubeapiserver/authorizer/modes/BUILD @@ -0,0 +1,35 @@ +package(default_visibility = ["//visibility:public"]) + +licenses(["notice"]) + +load( + "@io_bazel_rules_go//go:def.bzl", + "go_library", + "go_test", +) + +go_test( + name = "go_default_test", + srcs = ["modes_test.go"], + library = ":go_default_library", + tags = ["automanaged"], +) + +go_library( + name = "go_default_library", + srcs = ["modes.go"], + tags = ["automanaged"], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], +) diff --git a/pkg/kubeapiserver/authorizer/modes/modes.go b/pkg/kubeapiserver/authorizer/modes/modes.go new file mode 100644 index 00000000000..0d2c2442090 --- /dev/null +++ b/pkg/kubeapiserver/authorizer/modes/modes.go @@ -0,0 +1,37 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package modes + +const ( + ModeAlwaysAllow string = "AlwaysAllow" + ModeAlwaysDeny string = "AlwaysDeny" + ModeABAC string = "ABAC" + ModeWebhook string = "Webhook" + ModeRBAC string = "RBAC" +) + +var AuthorizationModeChoices = []string{ModeAlwaysAllow, ModeAlwaysDeny, ModeABAC, ModeWebhook, ModeRBAC} + +// IsValidAuthorizationMode returns true if the given authorization mode is a valid one for the apiserver +func IsValidAuthorizationMode(authzMode string) bool { + for _, validMode := range AuthorizationModeChoices { + if authzMode == validMode { + return true + } + } + return false +} diff --git a/pkg/kubeapiserver/authorizer/modes/modes_test.go b/pkg/kubeapiserver/authorizer/modes/modes_test.go new file mode 100644 index 00000000000..63379234bf4 --- /dev/null +++ b/pkg/kubeapiserver/authorizer/modes/modes_test.go @@ -0,0 +1,45 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package modes + +import "testing" + +func TestIsValidAuthorizationMode(t *testing.T) { + var tests = []struct { + authzMode string + expected bool + }{ + {"", false}, + {"rBAC", false}, // not supported + {"falsy value", false}, // not supported + {"RBAC", true}, // supported + {"ABAC", true}, // supported + {"Webhook", true}, // supported + {"AlwaysAllow", true}, // supported + {"AlwaysDeny", true}, // supported + } + for _, rt := range tests { + actual := IsValidAuthorizationMode(rt.authzMode) + if actual != rt.expected { + t.Errorf( + "failed ValidAuthorizationMode:\n\texpected: %t\n\t actual: %t", + rt.expected, + actual, + ) + } + } +} diff --git a/pkg/kubeapiserver/options/BUILD b/pkg/kubeapiserver/options/BUILD index 70efdfed679..15d867467cb 100644 --- a/pkg/kubeapiserver/options/BUILD +++ b/pkg/kubeapiserver/options/BUILD @@ -25,6 +25,7 @@ go_library( "//pkg/controller/informers:go_default_library", "//pkg/kubeapiserver/authenticator:go_default_library", "//pkg/kubeapiserver/authorizer:go_default_library", + "//pkg/kubeapiserver/authorizer/modes:go_default_library", "//vendor:github.com/golang/glog", "//vendor:github.com/spf13/pflag", "//vendor:k8s.io/apimachinery/pkg/runtime/schema", diff --git a/pkg/kubeapiserver/options/authentication.go b/pkg/kubeapiserver/options/authentication.go index da9c3fc1e79..0bdc8da2f21 100644 --- a/pkg/kubeapiserver/options/authentication.go +++ b/pkg/kubeapiserver/options/authentication.go @@ -27,7 +27,7 @@ import ( genericapiserver "k8s.io/apiserver/pkg/server" genericoptions "k8s.io/apiserver/pkg/server/options" "k8s.io/kubernetes/pkg/kubeapiserver/authenticator" - "k8s.io/kubernetes/pkg/kubeapiserver/authorizer" + authzmodes "k8s.io/kubernetes/pkg/kubeapiserver/authorizer/modes" ) type BuiltInAuthenticationOptions struct { @@ -353,7 +353,7 @@ func (o *BuiltInAuthenticationOptions) ApplyAuthorization(authorization *BuiltIn if o.Anonymous.Allow { found := false for _, mode := range strings.Split(authorization.Mode, ",") { - if mode == authorizer.ModeAlwaysAllow { + if mode == authzmodes.ModeAlwaysAllow { found = true break } diff --git a/pkg/kubeapiserver/options/authorization.go b/pkg/kubeapiserver/options/authorization.go index 96d378d3dcc..de46ab3849b 100644 --- a/pkg/kubeapiserver/options/authorization.go +++ b/pkg/kubeapiserver/options/authorization.go @@ -24,10 +24,9 @@ import ( "k8s.io/kubernetes/pkg/controller/informers" "k8s.io/kubernetes/pkg/kubeapiserver/authorizer" + authzmodes "k8s.io/kubernetes/pkg/kubeapiserver/authorizer/modes" ) -var AuthorizationModeChoices = []string{authorizer.ModeAlwaysAllow, authorizer.ModeAlwaysDeny, authorizer.ModeABAC, authorizer.ModeWebhook, authorizer.ModeRBAC} - type BuiltInAuthorizationOptions struct { Mode string PolicyFile string @@ -38,7 +37,7 @@ type BuiltInAuthorizationOptions struct { func NewBuiltInAuthorizationOptions() *BuiltInAuthorizationOptions { return &BuiltInAuthorizationOptions{ - Mode: authorizer.ModeAlwaysAllow, + Mode: authzmodes.ModeAlwaysAllow, WebhookCacheAuthorizedTTL: 5 * time.Minute, WebhookCacheUnauthorizedTTL: 30 * time.Second, } @@ -52,7 +51,7 @@ func (s *BuiltInAuthorizationOptions) Validate() []error { func (s *BuiltInAuthorizationOptions) AddFlags(fs *pflag.FlagSet) { fs.StringVar(&s.Mode, "authorization-mode", s.Mode, ""+ "Ordered list of plug-ins to do authorization on secure port. Comma-delimited list of: "+ - strings.Join(AuthorizationModeChoices, ",")+".") + strings.Join(authzmodes.AuthorizationModeChoices, ",")+".") fs.StringVar(&s.PolicyFile, "authorization-policy-file", s.PolicyFile, ""+ "File with authorization policy in csv format, used with --authorization-mode=ABAC, on the secure port.")