2016-12-21 14:53:18 +00:00
|
|
|
/*
|
|
|
|
Copyright 2016 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 authorizer
|
|
|
|
|
|
|
|
import (
|
|
|
|
"errors"
|
|
|
|
"fmt"
|
|
|
|
"time"
|
|
|
|
|
2017-02-15 19:00:29 +00:00
|
|
|
"k8s.io/apimachinery/pkg/labels"
|
2017-01-04 15:39:05 +00:00
|
|
|
"k8s.io/apiserver/pkg/authorization/authorizer"
|
2017-01-25 16:25:56 +00:00
|
|
|
"k8s.io/apiserver/pkg/authorization/authorizerfactory"
|
2017-01-05 19:47:14 +00:00
|
|
|
"k8s.io/apiserver/pkg/authorization/union"
|
2017-01-19 12:04:08 +00:00
|
|
|
"k8s.io/apiserver/plugin/pkg/authorizer/webhook"
|
2017-02-15 19:00:29 +00:00
|
|
|
rbacapi "k8s.io/kubernetes/pkg/apis/rbac"
|
2016-12-21 14:53:18 +00:00
|
|
|
"k8s.io/kubernetes/pkg/auth/authorizer/abac"
|
2017-02-15 19:00:29 +00:00
|
|
|
informers "k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion"
|
|
|
|
rbaclisters "k8s.io/kubernetes/pkg/client/listers/rbac/internalversion"
|
2017-02-23 13:27:16 +00:00
|
|
|
"k8s.io/kubernetes/pkg/kubeapiserver/authorizer/modes"
|
2016-12-21 14:53:18 +00:00
|
|
|
"k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac"
|
|
|
|
)
|
|
|
|
|
|
|
|
type AuthorizationConfig struct {
|
|
|
|
AuthorizationModes []string
|
|
|
|
|
|
|
|
// Options for ModeABAC
|
|
|
|
|
|
|
|
// Path to an ABAC policy file.
|
|
|
|
PolicyFile string
|
|
|
|
|
|
|
|
// Options for ModeWebhook
|
|
|
|
|
|
|
|
// Kubeconfig file for Webhook authorization plugin.
|
|
|
|
WebhookConfigFile string
|
|
|
|
// TTL for caching of authorized responses from the webhook server.
|
|
|
|
WebhookCacheAuthorizedTTL time.Duration
|
|
|
|
// TTL for caching of unauthorized responses from the webhook server.
|
|
|
|
WebhookCacheUnauthorizedTTL time.Duration
|
|
|
|
|
|
|
|
// Options for RBAC
|
|
|
|
|
|
|
|
// User which can bootstrap role policies
|
|
|
|
RBACSuperUser string
|
|
|
|
|
|
|
|
InformerFactory informers.SharedInformerFactory
|
|
|
|
}
|
|
|
|
|
2017-02-15 19:00:29 +00:00
|
|
|
type roleGetter struct {
|
|
|
|
lister rbaclisters.RoleLister
|
|
|
|
}
|
|
|
|
|
|
|
|
func (g *roleGetter) GetRole(namespace, name string) (*rbacapi.Role, error) {
|
|
|
|
return g.lister.Roles(namespace).Get(name)
|
|
|
|
}
|
|
|
|
|
|
|
|
type roleBindingLister struct {
|
|
|
|
lister rbaclisters.RoleBindingLister
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l *roleBindingLister) ListRoleBindings(namespace string) ([]*rbacapi.RoleBinding, error) {
|
|
|
|
return l.lister.RoleBindings(namespace).List(labels.Everything())
|
|
|
|
}
|
|
|
|
|
|
|
|
type clusterRoleGetter struct {
|
|
|
|
lister rbaclisters.ClusterRoleLister
|
|
|
|
}
|
|
|
|
|
|
|
|
func (g *clusterRoleGetter) GetClusterRole(name string) (*rbacapi.ClusterRole, error) {
|
|
|
|
return g.lister.Get(name)
|
|
|
|
}
|
|
|
|
|
|
|
|
type clusterRoleBindingLister struct {
|
|
|
|
lister rbaclisters.ClusterRoleBindingLister
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l *clusterRoleBindingLister) ListClusterRoleBindings() ([]*rbacapi.ClusterRoleBinding, error) {
|
|
|
|
return l.lister.List(labels.Everything())
|
|
|
|
}
|
|
|
|
|
2016-12-21 14:53:18 +00:00
|
|
|
// New returns the right sort of union of multiple authorizer.Authorizer objects
|
|
|
|
// based on the authorizationMode or an error.
|
|
|
|
func (config AuthorizationConfig) New() (authorizer.Authorizer, error) {
|
|
|
|
if len(config.AuthorizationModes) == 0 {
|
|
|
|
return nil, errors.New("At least one authorization mode should be passed")
|
|
|
|
}
|
|
|
|
|
|
|
|
var authorizers []authorizer.Authorizer
|
|
|
|
authorizerMap := make(map[string]bool)
|
|
|
|
|
|
|
|
for _, authorizationMode := range config.AuthorizationModes {
|
|
|
|
if authorizerMap[authorizationMode] {
|
|
|
|
return nil, fmt.Errorf("Authorization mode %s specified more than once", authorizationMode)
|
|
|
|
}
|
|
|
|
// Keep cases in sync with constant list above.
|
|
|
|
switch authorizationMode {
|
2017-02-23 13:27:16 +00:00
|
|
|
case modes.ModeAlwaysAllow:
|
2017-01-25 16:25:56 +00:00
|
|
|
authorizers = append(authorizers, authorizerfactory.NewAlwaysAllowAuthorizer())
|
2017-02-23 13:27:16 +00:00
|
|
|
case modes.ModeAlwaysDeny:
|
2017-01-25 16:25:56 +00:00
|
|
|
authorizers = append(authorizers, authorizerfactory.NewAlwaysDenyAuthorizer())
|
2017-02-23 13:27:16 +00:00
|
|
|
case modes.ModeABAC:
|
2016-12-21 14:53:18 +00:00
|
|
|
if config.PolicyFile == "" {
|
|
|
|
return nil, errors.New("ABAC's authorization policy file not passed")
|
|
|
|
}
|
|
|
|
abacAuthorizer, err := abac.NewFromFile(config.PolicyFile)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
authorizers = append(authorizers, abacAuthorizer)
|
2017-02-23 13:27:16 +00:00
|
|
|
case modes.ModeWebhook:
|
2016-12-21 14:53:18 +00:00
|
|
|
if config.WebhookConfigFile == "" {
|
|
|
|
return nil, errors.New("Webhook's configuration file not passed")
|
|
|
|
}
|
|
|
|
webhookAuthorizer, err := webhook.New(config.WebhookConfigFile,
|
|
|
|
config.WebhookCacheAuthorizedTTL,
|
|
|
|
config.WebhookCacheUnauthorizedTTL)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
authorizers = append(authorizers, webhookAuthorizer)
|
2017-02-23 13:27:16 +00:00
|
|
|
case modes.ModeRBAC:
|
2016-12-21 14:53:18 +00:00
|
|
|
rbacAuthorizer := rbac.New(
|
2017-02-15 19:00:29 +00:00
|
|
|
&roleGetter{config.InformerFactory.Rbac().InternalVersion().Roles().Lister()},
|
|
|
|
&roleBindingLister{config.InformerFactory.Rbac().InternalVersion().RoleBindings().Lister()},
|
|
|
|
&clusterRoleGetter{config.InformerFactory.Rbac().InternalVersion().ClusterRoles().Lister()},
|
|
|
|
&clusterRoleBindingLister{config.InformerFactory.Rbac().InternalVersion().ClusterRoleBindings().Lister()},
|
2016-12-21 14:53:18 +00:00
|
|
|
)
|
|
|
|
authorizers = append(authorizers, rbacAuthorizer)
|
|
|
|
default:
|
|
|
|
return nil, fmt.Errorf("Unknown authorization mode %s specified", authorizationMode)
|
|
|
|
}
|
|
|
|
authorizerMap[authorizationMode] = true
|
|
|
|
}
|
|
|
|
|
2017-02-23 13:27:16 +00:00
|
|
|
if !authorizerMap[modes.ModeABAC] && config.PolicyFile != "" {
|
2016-12-21 14:53:18 +00:00
|
|
|
return nil, errors.New("Cannot specify --authorization-policy-file without mode ABAC")
|
|
|
|
}
|
2017-02-23 13:27:16 +00:00
|
|
|
if !authorizerMap[modes.ModeWebhook] && config.WebhookConfigFile != "" {
|
2016-12-21 14:53:18 +00:00
|
|
|
return nil, errors.New("Cannot specify --authorization-webhook-config-file without mode Webhook")
|
|
|
|
}
|
2017-02-23 13:27:16 +00:00
|
|
|
if !authorizerMap[modes.ModeRBAC] && config.RBACSuperUser != "" {
|
2016-12-21 14:53:18 +00:00
|
|
|
return nil, errors.New("Cannot specify --authorization-rbac-super-user without mode RBAC")
|
|
|
|
}
|
|
|
|
|
|
|
|
return union.New(authorizers...), nil
|
|
|
|
}
|