mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-27 05:27:21 +00:00
Merge pull request #28860 from ericchiang/separate-apiserver-authz-options
Automatic merge from submit-queue pkg/genericapiserver/options: don't import pkg/apiserver Refactor the authorization options for the API server so pkg/apiserver isn't directly imported by the options package. Closes #28544 cc @smarterclayton @madhusudancs, @nikhiljindal I've updated `federation/cmd/federation-apiserver/app/server.go` to include the RBAC options with this change. I don't know if this was intentionally left out in the first place but would like your feedback.
This commit is contained in:
commit
7979801e54
@ -46,6 +46,8 @@ import (
|
|||||||
"k8s.io/kubernetes/pkg/controller/framework/informers"
|
"k8s.io/kubernetes/pkg/controller/framework/informers"
|
||||||
serviceaccountcontroller "k8s.io/kubernetes/pkg/controller/serviceaccount"
|
serviceaccountcontroller "k8s.io/kubernetes/pkg/controller/serviceaccount"
|
||||||
"k8s.io/kubernetes/pkg/genericapiserver"
|
"k8s.io/kubernetes/pkg/genericapiserver"
|
||||||
|
"k8s.io/kubernetes/pkg/genericapiserver/authorizer"
|
||||||
|
genericoptions "k8s.io/kubernetes/pkg/genericapiserver/options"
|
||||||
genericvalidation "k8s.io/kubernetes/pkg/genericapiserver/validation"
|
genericvalidation "k8s.io/kubernetes/pkg/genericapiserver/validation"
|
||||||
kubeletclient "k8s.io/kubernetes/pkg/kubelet/client"
|
kubeletclient "k8s.io/kubernetes/pkg/kubelet/client"
|
||||||
"k8s.io/kubernetes/pkg/master"
|
"k8s.io/kubernetes/pkg/master"
|
||||||
@ -225,7 +227,14 @@ func Run(s *options.APIServer) error {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if modeEnabled(apiserver.ModeRBAC) {
|
authorizationConfig := authorizer.AuthorizationConfig{
|
||||||
|
PolicyFile: s.AuthorizationPolicyFile,
|
||||||
|
WebhookConfigFile: s.AuthorizationWebhookConfigFile,
|
||||||
|
WebhookCacheAuthorizedTTL: s.AuthorizationWebhookCacheAuthorizedTTL,
|
||||||
|
WebhookCacheUnauthorizedTTL: s.AuthorizationWebhookCacheUnauthorizedTTL,
|
||||||
|
RBACSuperUser: s.AuthorizationRBACSuperUser,
|
||||||
|
}
|
||||||
|
if modeEnabled(genericoptions.ModeRBAC) {
|
||||||
mustGetRESTOptions := func(resource string) generic.RESTOptions {
|
mustGetRESTOptions := func(resource string) generic.RESTOptions {
|
||||||
config, err := storageFactory.NewConfig(rbac.Resource(resource))
|
config, err := storageFactory.NewConfig(rbac.Resource(resource))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -235,13 +244,13 @@ func Run(s *options.APIServer) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// For initial bootstrapping go directly to etcd to avoid privillege escalation check.
|
// For initial bootstrapping go directly to etcd to avoid privillege escalation check.
|
||||||
s.AuthorizationConfig.RBACRoleRegistry = role.NewRegistry(roleetcd.NewREST(mustGetRESTOptions("roles")))
|
authorizationConfig.RBACRoleRegistry = role.NewRegistry(roleetcd.NewREST(mustGetRESTOptions("roles")))
|
||||||
s.AuthorizationConfig.RBACRoleBindingRegistry = rolebinding.NewRegistry(rolebindingetcd.NewREST(mustGetRESTOptions("rolebindings")))
|
authorizationConfig.RBACRoleBindingRegistry = rolebinding.NewRegistry(rolebindingetcd.NewREST(mustGetRESTOptions("rolebindings")))
|
||||||
s.AuthorizationConfig.RBACClusterRoleRegistry = clusterrole.NewRegistry(clusterroleetcd.NewREST(mustGetRESTOptions("clusterroles")))
|
authorizationConfig.RBACClusterRoleRegistry = clusterrole.NewRegistry(clusterroleetcd.NewREST(mustGetRESTOptions("clusterroles")))
|
||||||
s.AuthorizationConfig.RBACClusterRoleBindingRegistry = clusterrolebinding.NewRegistry(clusterrolebindingetcd.NewREST(mustGetRESTOptions("clusterrolebindings")))
|
authorizationConfig.RBACClusterRoleBindingRegistry = clusterrolebinding.NewRegistry(clusterrolebindingetcd.NewREST(mustGetRESTOptions("clusterrolebindings")))
|
||||||
}
|
}
|
||||||
|
|
||||||
authorizer, err := apiserver.NewAuthorizerFromAuthorizationConfig(authorizationModeNames, s.AuthorizationConfig)
|
authorizer, err := authorizer.NewAuthorizerFromAuthorizationConfig(authorizationModeNames, authorizationConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Fatalf("Invalid Authorization Config: %v", err)
|
glog.Fatalf("Invalid Authorization Config: %v", err)
|
||||||
}
|
}
|
||||||
@ -265,7 +274,7 @@ func Run(s *options.APIServer) error {
|
|||||||
genericConfig.Authenticator = authenticator
|
genericConfig.Authenticator = authenticator
|
||||||
genericConfig.SupportsBasicAuth = len(s.BasicAuthFile) > 0
|
genericConfig.SupportsBasicAuth = len(s.BasicAuthFile) > 0
|
||||||
genericConfig.Authorizer = authorizer
|
genericConfig.Authorizer = authorizer
|
||||||
genericConfig.AuthorizerRBACSuperUser = s.AuthorizationConfig.RBACSuperUser
|
genericConfig.AuthorizerRBACSuperUser = s.AuthorizationRBACSuperUser
|
||||||
genericConfig.AdmissionControl = admissionController
|
genericConfig.AdmissionControl = admissionController
|
||||||
genericConfig.APIResourceConfigSource = storageFactory.APIResourceConfigSource
|
genericConfig.APIResourceConfigSource = storageFactory.APIResourceConfigSource
|
||||||
genericConfig.MasterServiceNamespace = s.MasterServiceNamespace
|
genericConfig.MasterServiceNamespace = s.MasterServiceNamespace
|
||||||
|
@ -31,13 +31,23 @@ import (
|
|||||||
"k8s.io/kubernetes/pkg/admission"
|
"k8s.io/kubernetes/pkg/admission"
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||||
"k8s.io/kubernetes/pkg/apiserver"
|
"k8s.io/kubernetes/pkg/apis/rbac"
|
||||||
"k8s.io/kubernetes/pkg/apiserver/authenticator"
|
"k8s.io/kubernetes/pkg/apiserver/authenticator"
|
||||||
"k8s.io/kubernetes/pkg/controller/framework/informers"
|
"k8s.io/kubernetes/pkg/controller/framework/informers"
|
||||||
"k8s.io/kubernetes/pkg/genericapiserver"
|
"k8s.io/kubernetes/pkg/genericapiserver"
|
||||||
|
"k8s.io/kubernetes/pkg/genericapiserver/authorizer"
|
||||||
|
genericoptions "k8s.io/kubernetes/pkg/genericapiserver/options"
|
||||||
genericvalidation "k8s.io/kubernetes/pkg/genericapiserver/validation"
|
genericvalidation "k8s.io/kubernetes/pkg/genericapiserver/validation"
|
||||||
"k8s.io/kubernetes/pkg/registry/cachesize"
|
"k8s.io/kubernetes/pkg/registry/cachesize"
|
||||||
|
"k8s.io/kubernetes/pkg/registry/clusterrole"
|
||||||
|
clusterroleetcd "k8s.io/kubernetes/pkg/registry/clusterrole/etcd"
|
||||||
|
"k8s.io/kubernetes/pkg/registry/clusterrolebinding"
|
||||||
|
clusterrolebindingetcd "k8s.io/kubernetes/pkg/registry/clusterrolebinding/etcd"
|
||||||
"k8s.io/kubernetes/pkg/registry/generic"
|
"k8s.io/kubernetes/pkg/registry/generic"
|
||||||
|
"k8s.io/kubernetes/pkg/registry/role"
|
||||||
|
roleetcd "k8s.io/kubernetes/pkg/registry/role/etcd"
|
||||||
|
"k8s.io/kubernetes/pkg/registry/rolebinding"
|
||||||
|
rolebindingetcd "k8s.io/kubernetes/pkg/registry/rolebinding/etcd"
|
||||||
"k8s.io/kubernetes/pkg/util/wait"
|
"k8s.io/kubernetes/pkg/util/wait"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -113,7 +123,40 @@ func Run(s *options.ServerRunOptions) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
authorizationModeNames := strings.Split(s.AuthorizationMode, ",")
|
authorizationModeNames := strings.Split(s.AuthorizationMode, ",")
|
||||||
authorizer, err := apiserver.NewAuthorizerFromAuthorizationConfig(authorizationModeNames, s.AuthorizationConfig)
|
|
||||||
|
modeEnabled := func(mode string) bool {
|
||||||
|
for _, m := range authorizationModeNames {
|
||||||
|
if m == mode {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
authorizationConfig := authorizer.AuthorizationConfig{
|
||||||
|
PolicyFile: s.AuthorizationPolicyFile,
|
||||||
|
WebhookConfigFile: s.AuthorizationWebhookConfigFile,
|
||||||
|
WebhookCacheAuthorizedTTL: s.AuthorizationWebhookCacheAuthorizedTTL,
|
||||||
|
WebhookCacheUnauthorizedTTL: s.AuthorizationWebhookCacheUnauthorizedTTL,
|
||||||
|
RBACSuperUser: s.AuthorizationRBACSuperUser,
|
||||||
|
}
|
||||||
|
if modeEnabled(genericoptions.ModeRBAC) {
|
||||||
|
mustGetRESTOptions := func(resource string) generic.RESTOptions {
|
||||||
|
config, err := storageFactory.NewConfig(rbac.Resource(resource))
|
||||||
|
if err != nil {
|
||||||
|
glog.Fatalf("Unable to get %s storage: %v", resource, err)
|
||||||
|
}
|
||||||
|
return generic.RESTOptions{StorageConfig: config, Decorator: generic.UndecoratedStorage, ResourcePrefix: storageFactory.ResourcePrefix(rbac.Resource(resource))}
|
||||||
|
}
|
||||||
|
|
||||||
|
// For initial bootstrapping go directly to etcd to avoid privillege escalation check.
|
||||||
|
authorizationConfig.RBACRoleRegistry = role.NewRegistry(roleetcd.NewREST(mustGetRESTOptions("roles")))
|
||||||
|
authorizationConfig.RBACRoleBindingRegistry = rolebinding.NewRegistry(rolebindingetcd.NewREST(mustGetRESTOptions("rolebindings")))
|
||||||
|
authorizationConfig.RBACClusterRoleRegistry = clusterrole.NewRegistry(clusterroleetcd.NewREST(mustGetRESTOptions("clusterroles")))
|
||||||
|
authorizationConfig.RBACClusterRoleBindingRegistry = clusterrolebinding.NewRegistry(clusterrolebindingetcd.NewREST(mustGetRESTOptions("clusterrolebindings")))
|
||||||
|
}
|
||||||
|
|
||||||
|
authorizer, err := authorizer.NewAuthorizerFromAuthorizationConfig(authorizationModeNames, authorizationConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Fatalf("Invalid Authorization Config: %v", err)
|
glog.Fatalf("Invalid Authorization Config: %v", err)
|
||||||
}
|
}
|
||||||
@ -136,6 +179,7 @@ func Run(s *options.ServerRunOptions) error {
|
|||||||
genericConfig.Authenticator = authenticator
|
genericConfig.Authenticator = authenticator
|
||||||
genericConfig.SupportsBasicAuth = len(s.BasicAuthFile) > 0
|
genericConfig.SupportsBasicAuth = len(s.BasicAuthFile) > 0
|
||||||
genericConfig.Authorizer = authorizer
|
genericConfig.Authorizer = authorizer
|
||||||
|
genericConfig.AuthorizerRBACSuperUser = s.AuthorizationRBACSuperUser
|
||||||
genericConfig.AdmissionControl = admissionController
|
genericConfig.AdmissionControl = admissionController
|
||||||
genericConfig.APIResourceConfigSource = storageFactory.APIResourceConfigSource
|
genericConfig.APIResourceConfigSource = storageFactory.APIResourceConfigSource
|
||||||
genericConfig.MasterServiceNamespace = s.MasterServiceNamespace
|
genericConfig.MasterServiceNamespace = s.MasterServiceNamespace
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright 2014 The Kubernetes Authors.
|
Copyright 2016 The Kubernetes Authors.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package apiserver
|
package authorizer
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
@ -24,6 +24,7 @@ import (
|
|||||||
"k8s.io/kubernetes/pkg/auth/authorizer"
|
"k8s.io/kubernetes/pkg/auth/authorizer"
|
||||||
"k8s.io/kubernetes/pkg/auth/authorizer/abac"
|
"k8s.io/kubernetes/pkg/auth/authorizer/abac"
|
||||||
"k8s.io/kubernetes/pkg/auth/authorizer/union"
|
"k8s.io/kubernetes/pkg/auth/authorizer/union"
|
||||||
|
"k8s.io/kubernetes/pkg/genericapiserver/options"
|
||||||
"k8s.io/kubernetes/pkg/registry/clusterrole"
|
"k8s.io/kubernetes/pkg/registry/clusterrole"
|
||||||
"k8s.io/kubernetes/pkg/registry/clusterrolebinding"
|
"k8s.io/kubernetes/pkg/registry/clusterrolebinding"
|
||||||
"k8s.io/kubernetes/pkg/registry/role"
|
"k8s.io/kubernetes/pkg/registry/role"
|
||||||
@ -32,11 +33,6 @@ import (
|
|||||||
"k8s.io/kubernetes/plugin/pkg/auth/authorizer/webhook"
|
"k8s.io/kubernetes/plugin/pkg/auth/authorizer/webhook"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Attributes implements authorizer.Attributes interface.
|
|
||||||
type Attributes struct {
|
|
||||||
// TODO: add fields and methods when authorizer.Attributes is completed.
|
|
||||||
}
|
|
||||||
|
|
||||||
// alwaysAllowAuthorizer is an implementation of authorizer.Attributes
|
// alwaysAllowAuthorizer is an implementation of authorizer.Attributes
|
||||||
// which always says yes to an authorization request.
|
// which always says yes to an authorization request.
|
||||||
// It is useful in tests and when using kubernetes in an open manner.
|
// It is useful in tests and when using kubernetes in an open manner.
|
||||||
@ -76,17 +72,6 @@ func NewAlwaysFailAuthorizer() authorizer.Authorizer {
|
|||||||
return new(alwaysFailAuthorizer)
|
return new(alwaysFailAuthorizer)
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
|
||||||
ModeAlwaysAllow string = "AlwaysAllow"
|
|
||||||
ModeAlwaysDeny string = "AlwaysDeny"
|
|
||||||
ModeABAC string = "ABAC"
|
|
||||||
ModeWebhook string = "Webhook"
|
|
||||||
ModeRBAC string = "RBAC"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Keep this list in sync with constant list above.
|
|
||||||
var AuthorizationModeChoices = []string{ModeAlwaysAllow, ModeAlwaysDeny, ModeABAC, ModeWebhook, ModeRBAC}
|
|
||||||
|
|
||||||
type AuthorizationConfig struct {
|
type AuthorizationConfig struct {
|
||||||
// Options for ModeABAC
|
// Options for ModeABAC
|
||||||
|
|
||||||
@ -115,7 +100,7 @@ type AuthorizationConfig struct {
|
|||||||
|
|
||||||
// NewAuthorizerFromAuthorizationConfig returns the right sort of union of multiple authorizer.Authorizer objects
|
// NewAuthorizerFromAuthorizationConfig returns the right sort of union of multiple authorizer.Authorizer objects
|
||||||
// based on the authorizationMode or an error. authorizationMode should be a comma separated values
|
// based on the authorizationMode or an error. authorizationMode should be a comma separated values
|
||||||
// of AuthorizationModeChoices.
|
// of options.AuthorizationModeChoices.
|
||||||
func NewAuthorizerFromAuthorizationConfig(authorizationModes []string, config AuthorizationConfig) (authorizer.Authorizer, error) {
|
func NewAuthorizerFromAuthorizationConfig(authorizationModes []string, config AuthorizationConfig) (authorizer.Authorizer, error) {
|
||||||
|
|
||||||
if len(authorizationModes) == 0 {
|
if len(authorizationModes) == 0 {
|
||||||
@ -131,11 +116,11 @@ func NewAuthorizerFromAuthorizationConfig(authorizationModes []string, config Au
|
|||||||
}
|
}
|
||||||
// Keep cases in sync with constant list above.
|
// Keep cases in sync with constant list above.
|
||||||
switch authorizationMode {
|
switch authorizationMode {
|
||||||
case ModeAlwaysAllow:
|
case options.ModeAlwaysAllow:
|
||||||
authorizers = append(authorizers, NewAlwaysAllowAuthorizer())
|
authorizers = append(authorizers, NewAlwaysAllowAuthorizer())
|
||||||
case ModeAlwaysDeny:
|
case options.ModeAlwaysDeny:
|
||||||
authorizers = append(authorizers, NewAlwaysDenyAuthorizer())
|
authorizers = append(authorizers, NewAlwaysDenyAuthorizer())
|
||||||
case ModeABAC:
|
case options.ModeABAC:
|
||||||
if config.PolicyFile == "" {
|
if config.PolicyFile == "" {
|
||||||
return nil, errors.New("ABAC's authorization policy file not passed")
|
return nil, errors.New("ABAC's authorization policy file not passed")
|
||||||
}
|
}
|
||||||
@ -144,7 +129,7 @@ func NewAuthorizerFromAuthorizationConfig(authorizationModes []string, config Au
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
authorizers = append(authorizers, abacAuthorizer)
|
authorizers = append(authorizers, abacAuthorizer)
|
||||||
case ModeWebhook:
|
case options.ModeWebhook:
|
||||||
if config.WebhookConfigFile == "" {
|
if config.WebhookConfigFile == "" {
|
||||||
return nil, errors.New("Webhook's configuration file not passed")
|
return nil, errors.New("Webhook's configuration file not passed")
|
||||||
}
|
}
|
||||||
@ -155,7 +140,7 @@ func NewAuthorizerFromAuthorizationConfig(authorizationModes []string, config Au
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
authorizers = append(authorizers, webhookAuthorizer)
|
authorizers = append(authorizers, webhookAuthorizer)
|
||||||
case ModeRBAC:
|
case options.ModeRBAC:
|
||||||
rbacAuthorizer := rbac.New(
|
rbacAuthorizer := rbac.New(
|
||||||
config.RBACRoleRegistry,
|
config.RBACRoleRegistry,
|
||||||
config.RBACRoleBindingRegistry,
|
config.RBACRoleBindingRegistry,
|
||||||
@ -170,13 +155,13 @@ func NewAuthorizerFromAuthorizationConfig(authorizationModes []string, config Au
|
|||||||
authorizerMap[authorizationMode] = true
|
authorizerMap[authorizationMode] = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if !authorizerMap[ModeABAC] && config.PolicyFile != "" {
|
if !authorizerMap[options.ModeABAC] && config.PolicyFile != "" {
|
||||||
return nil, errors.New("Cannot specify --authorization-policy-file without mode ABAC")
|
return nil, errors.New("Cannot specify --authorization-policy-file without mode ABAC")
|
||||||
}
|
}
|
||||||
if !authorizerMap[ModeWebhook] && config.WebhookConfigFile != "" {
|
if !authorizerMap[options.ModeWebhook] && config.WebhookConfigFile != "" {
|
||||||
return nil, errors.New("Cannot specify --authorization-webhook-config-file without mode Webhook")
|
return nil, errors.New("Cannot specify --authorization-webhook-config-file without mode Webhook")
|
||||||
}
|
}
|
||||||
if !authorizerMap[ModeRBAC] && config.RBACSuperUser != "" {
|
if !authorizerMap[options.ModeRBAC] && config.RBACSuperUser != "" {
|
||||||
return nil, errors.New("Cannot specify --authorization-rbac-super-user without mode RBAC")
|
return nil, errors.New("Cannot specify --authorization-rbac-super-user without mode RBAC")
|
||||||
}
|
}
|
||||||
|
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright 2014 The Kubernetes Authors.
|
Copyright 2016 The Kubernetes Authors.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@ -14,10 +14,12 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package apiserver
|
package authorizer
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"k8s.io/kubernetes/pkg/genericapiserver/options"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewAlwaysAllowAuthorizer must return a struct which implements authorizer.Authorizer
|
// NewAlwaysAllowAuthorizer must return a struct which implements authorizer.Authorizer
|
||||||
@ -42,7 +44,7 @@ func TestNewAlwaysDenyAuthorizer(t *testing.T) {
|
|||||||
// validates that errors are returned only when proper.
|
// validates that errors are returned only when proper.
|
||||||
func TestNewAuthorizerFromAuthorizationConfig(t *testing.T) {
|
func TestNewAuthorizerFromAuthorizationConfig(t *testing.T) {
|
||||||
|
|
||||||
examplePolicyFile := "../auth/authorizer/abac/example_policy_file.jsonl"
|
examplePolicyFile := "../../auth/authorizer/abac/example_policy_file.jsonl"
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
modes []string
|
modes []string
|
||||||
@ -59,25 +61,25 @@ func TestNewAuthorizerFromAuthorizationConfig(t *testing.T) {
|
|||||||
{
|
{
|
||||||
// ModeAlwaysAllow and ModeAlwaysDeny should return without authorizationPolicyFile
|
// ModeAlwaysAllow and ModeAlwaysDeny should return without authorizationPolicyFile
|
||||||
// but error if one is given
|
// but error if one is given
|
||||||
modes: []string{ModeAlwaysAllow, ModeAlwaysDeny},
|
modes: []string{options.ModeAlwaysAllow, options.ModeAlwaysDeny},
|
||||||
msg: "returned an error for valid config",
|
msg: "returned an error for valid config",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// ModeABAC requires a policy file
|
// ModeABAC requires a policy file
|
||||||
modes: []string{ModeAlwaysAllow, ModeAlwaysDeny, ModeABAC},
|
modes: []string{options.ModeAlwaysAllow, options.ModeAlwaysDeny, options.ModeABAC},
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
msg: "specifying ABAC with no policy file should return an error",
|
msg: "specifying ABAC with no policy file should return an error",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// ModeABAC should not error if a valid policy path is provided
|
// ModeABAC should not error if a valid policy path is provided
|
||||||
modes: []string{ModeAlwaysAllow, ModeAlwaysDeny, ModeABAC},
|
modes: []string{options.ModeAlwaysAllow, options.ModeAlwaysDeny, options.ModeABAC},
|
||||||
config: AuthorizationConfig{PolicyFile: examplePolicyFile},
|
config: AuthorizationConfig{PolicyFile: examplePolicyFile},
|
||||||
msg: "errored while using a valid policy file",
|
msg: "errored while using a valid policy file",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
||||||
// Authorization Policy file cannot be used without ModeABAC
|
// Authorization Policy file cannot be used without ModeABAC
|
||||||
modes: []string{ModeAlwaysAllow, ModeAlwaysDeny},
|
modes: []string{options.ModeAlwaysAllow, options.ModeAlwaysDeny},
|
||||||
config: AuthorizationConfig{PolicyFile: examplePolicyFile},
|
config: AuthorizationConfig{PolicyFile: examplePolicyFile},
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
msg: "should have errored when Authorization Policy File is used without ModeABAC",
|
msg: "should have errored when Authorization Policy File is used without ModeABAC",
|
||||||
@ -91,13 +93,13 @@ func TestNewAuthorizerFromAuthorizationConfig(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
// ModeWebhook requires at minimum a target.
|
// ModeWebhook requires at minimum a target.
|
||||||
modes: []string{ModeWebhook},
|
modes: []string{options.ModeWebhook},
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
msg: "should have errored when config was empty with ModeWebhook",
|
msg: "should have errored when config was empty with ModeWebhook",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// Cannot provide webhook flags without ModeWebhook
|
// Cannot provide webhook flags without ModeWebhook
|
||||||
modes: []string{ModeAlwaysAllow},
|
modes: []string{options.ModeAlwaysAllow},
|
||||||
config: AuthorizationConfig{WebhookConfigFile: "authz_webhook_config.yml"},
|
config: AuthorizationConfig{WebhookConfigFile: "authz_webhook_config.yml"},
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
msg: "should have errored when Webhook config file is used without ModeWebhook",
|
msg: "should have errored when Webhook config file is used without ModeWebhook",
|
@ -27,7 +27,6 @@ import (
|
|||||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||||
apiutil "k8s.io/kubernetes/pkg/api/util"
|
apiutil "k8s.io/kubernetes/pkg/api/util"
|
||||||
"k8s.io/kubernetes/pkg/apimachinery/registered"
|
"k8s.io/kubernetes/pkg/apimachinery/registered"
|
||||||
"k8s.io/kubernetes/pkg/apiserver"
|
|
||||||
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
||||||
"k8s.io/kubernetes/pkg/client/restclient"
|
"k8s.io/kubernetes/pkg/client/restclient"
|
||||||
"k8s.io/kubernetes/pkg/storage/storagebackend"
|
"k8s.io/kubernetes/pkg/storage/storagebackend"
|
||||||
@ -47,6 +46,16 @@ const (
|
|||||||
|
|
||||||
var DefaultServiceNodePortRange = utilnet.PortRange{Base: 30000, Size: 2768}
|
var DefaultServiceNodePortRange = utilnet.PortRange{Base: 30000, Size: 2768}
|
||||||
|
|
||||||
|
const (
|
||||||
|
ModeAlwaysAllow string = "AlwaysAllow"
|
||||||
|
ModeAlwaysDeny string = "AlwaysDeny"
|
||||||
|
ModeABAC string = "ABAC"
|
||||||
|
ModeWebhook string = "Webhook"
|
||||||
|
ModeRBAC string = "RBAC"
|
||||||
|
)
|
||||||
|
|
||||||
|
var AuthorizationModeChoices = []string{ModeAlwaysAllow, ModeAlwaysDeny, ModeABAC, ModeWebhook, ModeRBAC}
|
||||||
|
|
||||||
// ServerRunOptions contains the options while running a generic api server.
|
// ServerRunOptions contains the options while running a generic api server.
|
||||||
type ServerRunOptions struct {
|
type ServerRunOptions struct {
|
||||||
APIGroupPrefix string
|
APIGroupPrefix string
|
||||||
@ -54,8 +63,15 @@ type ServerRunOptions struct {
|
|||||||
AdmissionControl string
|
AdmissionControl string
|
||||||
AdmissionControlConfigFile string
|
AdmissionControlConfigFile string
|
||||||
AdvertiseAddress net.IP
|
AdvertiseAddress net.IP
|
||||||
AuthorizationConfig apiserver.AuthorizationConfig
|
|
||||||
|
// Authorization mode and associated flags.
|
||||||
AuthorizationMode string
|
AuthorizationMode string
|
||||||
|
AuthorizationPolicyFile string
|
||||||
|
AuthorizationWebhookConfigFile string
|
||||||
|
AuthorizationWebhookCacheAuthorizedTTL time.Duration
|
||||||
|
AuthorizationWebhookCacheUnauthorizedTTL time.Duration
|
||||||
|
AuthorizationRBACSuperUser string
|
||||||
|
|
||||||
BasicAuthFile string
|
BasicAuthFile string
|
||||||
BindAddress net.IP
|
BindAddress net.IP
|
||||||
CertDirectory string
|
CertDirectory string
|
||||||
@ -114,10 +130,8 @@ func NewServerRunOptions() *ServerRunOptions {
|
|||||||
APIPrefix: "/api",
|
APIPrefix: "/api",
|
||||||
AdmissionControl: "AlwaysAdmit",
|
AdmissionControl: "AlwaysAdmit",
|
||||||
AuthorizationMode: "AlwaysAllow",
|
AuthorizationMode: "AlwaysAllow",
|
||||||
AuthorizationConfig: apiserver.AuthorizationConfig{
|
AuthorizationWebhookCacheAuthorizedTTL: 5 * time.Minute,
|
||||||
WebhookCacheAuthorizedTTL: 5 * time.Minute,
|
AuthorizationWebhookCacheUnauthorizedTTL: 30 * time.Second,
|
||||||
WebhookCacheUnauthorizedTTL: 30 * time.Second,
|
|
||||||
},
|
|
||||||
BindAddress: net.ParseIP("0.0.0.0"),
|
BindAddress: net.ParseIP("0.0.0.0"),
|
||||||
CertDirectory: "/var/run/kubernetes",
|
CertDirectory: "/var/run/kubernetes",
|
||||||
DefaultStorageMediaType: "application/json",
|
DefaultStorageMediaType: "application/json",
|
||||||
@ -238,24 +252,24 @@ func (s *ServerRunOptions) AddUniversalFlags(fs *pflag.FlagSet) {
|
|||||||
|
|
||||||
fs.StringVar(&s.AuthorizationMode, "authorization-mode", s.AuthorizationMode, ""+
|
fs.StringVar(&s.AuthorizationMode, "authorization-mode", s.AuthorizationMode, ""+
|
||||||
"Ordered list of plug-ins to do authorization on secure port. Comma-delimited list of: "+
|
"Ordered list of plug-ins to do authorization on secure port. Comma-delimited list of: "+
|
||||||
strings.Join(apiserver.AuthorizationModeChoices, ",")+".")
|
strings.Join(AuthorizationModeChoices, ",")+".")
|
||||||
|
|
||||||
fs.StringVar(&s.AuthorizationConfig.PolicyFile, "authorization-policy-file", s.AuthorizationConfig.PolicyFile, ""+
|
fs.StringVar(&s.AuthorizationPolicyFile, "authorization-policy-file", s.AuthorizationPolicyFile, ""+
|
||||||
"File with authorization policy in csv format, used with --authorization-mode=ABAC, on the secure port.")
|
"File with authorization policy in csv format, used with --authorization-mode=ABAC, on the secure port.")
|
||||||
|
|
||||||
fs.StringVar(&s.AuthorizationConfig.WebhookConfigFile, "authorization-webhook-config-file", s.AuthorizationConfig.WebhookConfigFile, ""+
|
fs.StringVar(&s.AuthorizationWebhookConfigFile, "authorization-webhook-config-file", s.AuthorizationWebhookConfigFile, ""+
|
||||||
"File with webhook configuration in kubeconfig format, used with --authorization-mode=Webhook. "+
|
"File with webhook configuration in kubeconfig format, used with --authorization-mode=Webhook. "+
|
||||||
"The API server will query the remote service to determine access on the API server's secure port.")
|
"The API server will query the remote service to determine access on the API server's secure port.")
|
||||||
|
|
||||||
fs.DurationVar(&s.AuthorizationConfig.WebhookCacheAuthorizedTTL, "authorization-webhook-cache-authorized-ttl",
|
fs.DurationVar(&s.AuthorizationWebhookCacheAuthorizedTTL, "authorization-webhook-cache-authorized-ttl",
|
||||||
s.AuthorizationConfig.WebhookCacheAuthorizedTTL,
|
s.AuthorizationWebhookCacheAuthorizedTTL,
|
||||||
"The duration to cache 'authorized' responses from the webhook authorizer. Default is 5m.")
|
"The duration to cache 'authorized' responses from the webhook authorizer. Default is 5m.")
|
||||||
|
|
||||||
fs.DurationVar(&s.AuthorizationConfig.WebhookCacheUnauthorizedTTL,
|
fs.DurationVar(&s.AuthorizationWebhookCacheUnauthorizedTTL,
|
||||||
"authorization-webhook-cache-unauthorized-ttl", s.AuthorizationConfig.WebhookCacheUnauthorizedTTL,
|
"authorization-webhook-cache-unauthorized-ttl", s.AuthorizationWebhookCacheUnauthorizedTTL,
|
||||||
"The duration to cache 'unauthorized' responses from the webhook authorizer. Default is 30s.")
|
"The duration to cache 'unauthorized' responses from the webhook authorizer. Default is 30s.")
|
||||||
|
|
||||||
fs.StringVar(&s.AuthorizationConfig.RBACSuperUser, "authorization-rbac-super-user", s.AuthorizationConfig.RBACSuperUser, ""+
|
fs.StringVar(&s.AuthorizationRBACSuperUser, "authorization-rbac-super-user", s.AuthorizationRBACSuperUser, ""+
|
||||||
"If specified, a username which avoids RBAC authorization checks and role binding "+
|
"If specified, a username which avoids RBAC authorization checks and role binding "+
|
||||||
"privilege escalation checks, to be used with --authorization-mode=RBAC.")
|
"privilege escalation checks, to be used with --authorization-mode=RBAC.")
|
||||||
|
|
||||||
|
@ -41,13 +41,13 @@ import (
|
|||||||
authenticationv1beta1 "k8s.io/kubernetes/pkg/apis/authentication/v1beta1"
|
authenticationv1beta1 "k8s.io/kubernetes/pkg/apis/authentication/v1beta1"
|
||||||
"k8s.io/kubernetes/pkg/apis/autoscaling"
|
"k8s.io/kubernetes/pkg/apis/autoscaling"
|
||||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||||
"k8s.io/kubernetes/pkg/apiserver"
|
|
||||||
"k8s.io/kubernetes/pkg/auth/authenticator"
|
"k8s.io/kubernetes/pkg/auth/authenticator"
|
||||||
"k8s.io/kubernetes/pkg/auth/authenticator/bearertoken"
|
"k8s.io/kubernetes/pkg/auth/authenticator/bearertoken"
|
||||||
"k8s.io/kubernetes/pkg/auth/authorizer"
|
"k8s.io/kubernetes/pkg/auth/authorizer"
|
||||||
"k8s.io/kubernetes/pkg/auth/authorizer/abac"
|
"k8s.io/kubernetes/pkg/auth/authorizer/abac"
|
||||||
"k8s.io/kubernetes/pkg/auth/user"
|
"k8s.io/kubernetes/pkg/auth/user"
|
||||||
"k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api/v1"
|
"k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api/v1"
|
||||||
|
apiserverauthorizer "k8s.io/kubernetes/pkg/genericapiserver/authorizer"
|
||||||
"k8s.io/kubernetes/pkg/serviceaccount"
|
"k8s.io/kubernetes/pkg/serviceaccount"
|
||||||
"k8s.io/kubernetes/plugin/pkg/admission/admit"
|
"k8s.io/kubernetes/plugin/pkg/admission/admit"
|
||||||
"k8s.io/kubernetes/plugin/pkg/auth/authenticator/token/tokentest"
|
"k8s.io/kubernetes/plugin/pkg/auth/authenticator/token/tokentest"
|
||||||
@ -500,7 +500,7 @@ func getPreviousResourceVersionKey(url, id string) string {
|
|||||||
func TestAuthModeAlwaysDeny(t *testing.T) {
|
func TestAuthModeAlwaysDeny(t *testing.T) {
|
||||||
// Set up a master
|
// Set up a master
|
||||||
masterConfig := framework.NewIntegrationTestMasterConfig()
|
masterConfig := framework.NewIntegrationTestMasterConfig()
|
||||||
masterConfig.Authorizer = apiserver.NewAlwaysDenyAuthorizer()
|
masterConfig.Authorizer = apiserverauthorizer.NewAlwaysDenyAuthorizer()
|
||||||
_, s := framework.RunAMaster(masterConfig)
|
_, s := framework.RunAMaster(masterConfig)
|
||||||
defer s.Close()
|
defer s.Close()
|
||||||
|
|
||||||
|
@ -37,7 +37,6 @@ import (
|
|||||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||||
"k8s.io/kubernetes/pkg/apis/policy"
|
"k8s.io/kubernetes/pkg/apis/policy"
|
||||||
"k8s.io/kubernetes/pkg/apis/rbac"
|
"k8s.io/kubernetes/pkg/apis/rbac"
|
||||||
"k8s.io/kubernetes/pkg/apiserver"
|
|
||||||
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
||||||
"k8s.io/kubernetes/pkg/client/record"
|
"k8s.io/kubernetes/pkg/client/record"
|
||||||
"k8s.io/kubernetes/pkg/client/restclient"
|
"k8s.io/kubernetes/pkg/client/restclient"
|
||||||
@ -46,6 +45,7 @@ import (
|
|||||||
replicationcontroller "k8s.io/kubernetes/pkg/controller/replication"
|
replicationcontroller "k8s.io/kubernetes/pkg/controller/replication"
|
||||||
"k8s.io/kubernetes/pkg/fields"
|
"k8s.io/kubernetes/pkg/fields"
|
||||||
"k8s.io/kubernetes/pkg/genericapiserver"
|
"k8s.io/kubernetes/pkg/genericapiserver"
|
||||||
|
"k8s.io/kubernetes/pkg/genericapiserver/authorizer"
|
||||||
"k8s.io/kubernetes/pkg/kubectl"
|
"k8s.io/kubernetes/pkg/kubectl"
|
||||||
kubeletclient "k8s.io/kubernetes/pkg/kubelet/client"
|
kubeletclient "k8s.io/kubernetes/pkg/kubelet/client"
|
||||||
"k8s.io/kubernetes/pkg/master"
|
"k8s.io/kubernetes/pkg/master"
|
||||||
@ -216,7 +216,7 @@ func NewMasterConfig() *master.Config {
|
|||||||
APIResourceConfigSource: master.DefaultAPIResourceConfigSource(),
|
APIResourceConfigSource: master.DefaultAPIResourceConfigSource(),
|
||||||
APIPrefix: "/api",
|
APIPrefix: "/api",
|
||||||
APIGroupPrefix: "/apis",
|
APIGroupPrefix: "/apis",
|
||||||
Authorizer: apiserver.NewAlwaysAllowAuthorizer(),
|
Authorizer: authorizer.NewAlwaysAllowAuthorizer(),
|
||||||
AdmissionControl: admit.NewAlwaysAdmit(),
|
AdmissionControl: admit.NewAlwaysAdmit(),
|
||||||
Serializer: api.Codecs,
|
Serializer: api.Codecs,
|
||||||
EnableWatchCache: true,
|
EnableWatchCache: true,
|
||||||
|
Loading…
Reference in New Issue
Block a user