mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-07 03:03:59 +00:00
use AuthorizationConfiguration in kube-apiserver for storing authorizer config
Signed-off-by: Nabarun Pal <pal.nabarun95@gmail.com>
This commit is contained in:
parent
52c582ca77
commit
108d195595
@ -174,7 +174,10 @@ func BuildGenericConfig(
|
|||||||
|
|
||||||
// BuildAuthorizer constructs the authorizer
|
// BuildAuthorizer constructs the authorizer
|
||||||
func BuildAuthorizer(s controlplaneapiserver.CompletedOptions, EgressSelector *egressselector.EgressSelector, versionedInformers clientgoinformers.SharedInformerFactory) (authorizer.Authorizer, authorizer.RuleResolver, error) {
|
func BuildAuthorizer(s controlplaneapiserver.CompletedOptions, EgressSelector *egressselector.EgressSelector, versionedInformers clientgoinformers.SharedInformerFactory) (authorizer.Authorizer, authorizer.RuleResolver, error) {
|
||||||
authorizationConfig := s.Authorization.ToAuthorizationConfig(versionedInformers)
|
authorizationConfig, err := s.Authorization.ToAuthorizationConfig(versionedInformers)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
if EgressSelector != nil {
|
if EgressSelector != nil {
|
||||||
egressDialer, err := EgressSelector.Lookup(egressselector.ControlPlane.AsNetworkContext())
|
egressDialer, err := EgressSelector.Lookup(egressselector.ControlPlane.AsNetworkContext())
|
||||||
|
@ -19,10 +19,9 @@ package authorizer
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
|
||||||
|
|
||||||
utilnet "k8s.io/apimachinery/pkg/util/net"
|
utilnet "k8s.io/apimachinery/pkg/util/net"
|
||||||
"k8s.io/apimachinery/pkg/util/wait"
|
"k8s.io/apimachinery/pkg/util/wait"
|
||||||
|
authzconfig "k8s.io/apiserver/pkg/apis/apiserver"
|
||||||
"k8s.io/apiserver/pkg/authentication/user"
|
"k8s.io/apiserver/pkg/authentication/user"
|
||||||
"k8s.io/apiserver/pkg/authorization/authorizer"
|
"k8s.io/apiserver/pkg/authorization/authorizer"
|
||||||
"k8s.io/apiserver/pkg/authorization/authorizerfactory"
|
"k8s.io/apiserver/pkg/authorization/authorizerfactory"
|
||||||
@ -40,8 +39,6 @@ import (
|
|||||||
|
|
||||||
// Config contains the data on how to authorize a request to the Kube API Server
|
// Config contains the data on how to authorize a request to the Kube API Server
|
||||||
type Config struct {
|
type Config struct {
|
||||||
AuthorizationModes []string
|
|
||||||
|
|
||||||
// Options for ModeABAC
|
// Options for ModeABAC
|
||||||
|
|
||||||
// Path to an ABAC policy file.
|
// Path to an ABAC policy file.
|
||||||
@ -49,14 +46,6 @@ type Config struct {
|
|||||||
|
|
||||||
// Options for ModeWebhook
|
// Options for ModeWebhook
|
||||||
|
|
||||||
// Kubeconfig file for Webhook authorization plugin.
|
|
||||||
WebhookConfigFile string
|
|
||||||
// API version of subject access reviews to send to the webhook (e.g. "v1", "v1beta1")
|
|
||||||
WebhookVersion 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
|
|
||||||
// WebhookRetryBackoff specifies the backoff parameters for the authorization webhook retry logic.
|
// WebhookRetryBackoff specifies the backoff parameters for the authorization webhook retry logic.
|
||||||
// This allows us to configure the sleep time at each iteration and the maximum number of retries allowed
|
// This allows us to configure the sleep time at each iteration and the maximum number of retries allowed
|
||||||
// before we fail the webhook call in order to limit the fan out that ensues when the system is degraded.
|
// before we fail the webhook call in order to limit the fan out that ensues when the system is degraded.
|
||||||
@ -66,12 +55,16 @@ type Config struct {
|
|||||||
|
|
||||||
// Optional field, custom dial function used to connect to webhook
|
// Optional field, custom dial function used to connect to webhook
|
||||||
CustomDial utilnet.DialFunc
|
CustomDial utilnet.DialFunc
|
||||||
|
|
||||||
|
// AuthorizationConfiguration stores the configuration for the Authorizer chain
|
||||||
|
// It will deprecate most of the above flags when GA
|
||||||
|
AuthorizationConfiguration *authzconfig.AuthorizationConfiguration
|
||||||
}
|
}
|
||||||
|
|
||||||
// New returns the right sort of union of multiple authorizer.Authorizer objects
|
// New returns the right sort of union of multiple authorizer.Authorizer objects
|
||||||
// based on the authorizationMode or an error.
|
// based on the authorizationMode or an error.
|
||||||
func (config Config) New() (authorizer.Authorizer, authorizer.RuleResolver, error) {
|
func (config Config) New() (authorizer.Authorizer, authorizer.RuleResolver, error) {
|
||||||
if len(config.AuthorizationModes) == 0 {
|
if len(config.AuthorizationConfiguration.Authorizers) == 0 {
|
||||||
return nil, nil, fmt.Errorf("at least one authorization mode must be passed")
|
return nil, nil, fmt.Errorf("at least one authorization mode must be passed")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,10 +77,10 @@ func (config Config) New() (authorizer.Authorizer, authorizer.RuleResolver, erro
|
|||||||
superuserAuthorizer := authorizerfactory.NewPrivilegedGroups(user.SystemPrivilegedGroup)
|
superuserAuthorizer := authorizerfactory.NewPrivilegedGroups(user.SystemPrivilegedGroup)
|
||||||
authorizers = append(authorizers, superuserAuthorizer)
|
authorizers = append(authorizers, superuserAuthorizer)
|
||||||
|
|
||||||
for _, authorizationMode := range config.AuthorizationModes {
|
for _, configuredAuthorizer := range config.AuthorizationConfiguration.Authorizers {
|
||||||
// Keep cases in sync with constant list in k8s.io/kubernetes/pkg/kubeapiserver/authorizer/modes/modes.go.
|
// Keep cases in sync with constant list in k8s.io/kubernetes/pkg/kubeapiserver/authorizer/modes/modes.go.
|
||||||
switch authorizationMode {
|
switch configuredAuthorizer.Type {
|
||||||
case modes.ModeNode:
|
case authzconfig.AuthorizerType(modes.ModeNode):
|
||||||
node.RegisterMetrics()
|
node.RegisterMetrics()
|
||||||
graph := node.NewGraph()
|
graph := node.NewGraph()
|
||||||
node.AddGraphEventHandlers(
|
node.AddGraphEventHandlers(
|
||||||
@ -101,33 +94,33 @@ func (config Config) New() (authorizer.Authorizer, authorizer.RuleResolver, erro
|
|||||||
authorizers = append(authorizers, nodeAuthorizer)
|
authorizers = append(authorizers, nodeAuthorizer)
|
||||||
ruleResolvers = append(ruleResolvers, nodeAuthorizer)
|
ruleResolvers = append(ruleResolvers, nodeAuthorizer)
|
||||||
|
|
||||||
case modes.ModeAlwaysAllow:
|
case authzconfig.AuthorizerType(modes.ModeAlwaysAllow):
|
||||||
alwaysAllowAuthorizer := authorizerfactory.NewAlwaysAllowAuthorizer()
|
alwaysAllowAuthorizer := authorizerfactory.NewAlwaysAllowAuthorizer()
|
||||||
authorizers = append(authorizers, alwaysAllowAuthorizer)
|
authorizers = append(authorizers, alwaysAllowAuthorizer)
|
||||||
ruleResolvers = append(ruleResolvers, alwaysAllowAuthorizer)
|
ruleResolvers = append(ruleResolvers, alwaysAllowAuthorizer)
|
||||||
case modes.ModeAlwaysDeny:
|
case authzconfig.AuthorizerType(modes.ModeAlwaysDeny):
|
||||||
alwaysDenyAuthorizer := authorizerfactory.NewAlwaysDenyAuthorizer()
|
alwaysDenyAuthorizer := authorizerfactory.NewAlwaysDenyAuthorizer()
|
||||||
authorizers = append(authorizers, alwaysDenyAuthorizer)
|
authorizers = append(authorizers, alwaysDenyAuthorizer)
|
||||||
ruleResolvers = append(ruleResolvers, alwaysDenyAuthorizer)
|
ruleResolvers = append(ruleResolvers, alwaysDenyAuthorizer)
|
||||||
case modes.ModeABAC:
|
case authzconfig.AuthorizerType(modes.ModeABAC):
|
||||||
abacAuthorizer, err := abac.NewFromFile(config.PolicyFile)
|
abacAuthorizer, err := abac.NewFromFile(config.PolicyFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
authorizers = append(authorizers, abacAuthorizer)
|
authorizers = append(authorizers, abacAuthorizer)
|
||||||
ruleResolvers = append(ruleResolvers, abacAuthorizer)
|
ruleResolvers = append(ruleResolvers, abacAuthorizer)
|
||||||
case modes.ModeWebhook:
|
case authzconfig.AuthorizerType(modes.ModeWebhook):
|
||||||
if config.WebhookRetryBackoff == nil {
|
if config.WebhookRetryBackoff == nil {
|
||||||
return nil, nil, errors.New("retry backoff parameters for authorization webhook has not been specified")
|
return nil, nil, errors.New("retry backoff parameters for authorization webhook has not been specified")
|
||||||
}
|
}
|
||||||
clientConfig, err := webhookutil.LoadKubeconfig(config.WebhookConfigFile, config.CustomDial)
|
clientConfig, err := webhookutil.LoadKubeconfig(*configuredAuthorizer.Webhook.ConnectionInfo.KubeConfigFile, config.CustomDial)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
webhookAuthorizer, err := webhook.New(clientConfig,
|
webhookAuthorizer, err := webhook.New(clientConfig,
|
||||||
config.WebhookVersion,
|
configuredAuthorizer.Webhook.SubjectAccessReviewVersion,
|
||||||
config.WebhookCacheAuthorizedTTL,
|
configuredAuthorizer.Webhook.AuthorizedTTL.Duration,
|
||||||
config.WebhookCacheUnauthorizedTTL,
|
configuredAuthorizer.Webhook.UnauthorizedTTL.Duration,
|
||||||
*config.WebhookRetryBackoff,
|
*config.WebhookRetryBackoff,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -135,7 +128,7 @@ func (config Config) New() (authorizer.Authorizer, authorizer.RuleResolver, erro
|
|||||||
}
|
}
|
||||||
authorizers = append(authorizers, webhookAuthorizer)
|
authorizers = append(authorizers, webhookAuthorizer)
|
||||||
ruleResolvers = append(ruleResolvers, webhookAuthorizer)
|
ruleResolvers = append(ruleResolvers, webhookAuthorizer)
|
||||||
case modes.ModeRBAC:
|
case authzconfig.AuthorizerType(modes.ModeRBAC):
|
||||||
rbacAuthorizer := rbac.New(
|
rbacAuthorizer := rbac.New(
|
||||||
&rbac.RoleGetter{Lister: config.VersionedInformerFactory.Rbac().V1().Roles().Lister()},
|
&rbac.RoleGetter{Lister: config.VersionedInformerFactory.Rbac().V1().Roles().Lister()},
|
||||||
&rbac.RoleBindingLister{Lister: config.VersionedInformerFactory.Rbac().V1().RoleBindings().Lister()},
|
&rbac.RoleBindingLister{Lister: config.VersionedInformerFactory.Rbac().V1().RoleBindings().Lister()},
|
||||||
@ -145,7 +138,7 @@ func (config Config) New() (authorizer.Authorizer, authorizer.RuleResolver, erro
|
|||||||
authorizers = append(authorizers, rbacAuthorizer)
|
authorizers = append(authorizers, rbacAuthorizer)
|
||||||
ruleResolvers = append(ruleResolvers, rbacAuthorizer)
|
ruleResolvers = append(ruleResolvers, rbacAuthorizer)
|
||||||
default:
|
default:
|
||||||
return nil, nil, fmt.Errorf("unknown authorization mode %s specified", authorizationMode)
|
return nil, nil, fmt.Errorf("unknown authorization mode %s specified", configuredAuthorizer.Type)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,14 +23,20 @@ import (
|
|||||||
|
|
||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
|
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/util/sets"
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
"k8s.io/apimachinery/pkg/util/wait"
|
"k8s.io/apimachinery/pkg/util/wait"
|
||||||
|
authzconfig "k8s.io/apiserver/pkg/apis/apiserver"
|
||||||
genericoptions "k8s.io/apiserver/pkg/server/options"
|
genericoptions "k8s.io/apiserver/pkg/server/options"
|
||||||
versionedinformers "k8s.io/client-go/informers"
|
versionedinformers "k8s.io/client-go/informers"
|
||||||
"k8s.io/kubernetes/pkg/kubeapiserver/authorizer"
|
"k8s.io/kubernetes/pkg/kubeapiserver/authorizer"
|
||||||
authzmodes "k8s.io/kubernetes/pkg/kubeapiserver/authorizer/modes"
|
authzmodes "k8s.io/kubernetes/pkg/kubeapiserver/authorizer/modes"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
defaultWebhookName = "default"
|
||||||
|
)
|
||||||
|
|
||||||
// BuiltInAuthorizationOptions contains all build-in authorization options for API Server
|
// BuiltInAuthorizationOptions contains all build-in authorization options for API Server
|
||||||
type BuiltInAuthorizationOptions struct {
|
type BuiltInAuthorizationOptions struct {
|
||||||
Modes []string
|
Modes []string
|
||||||
@ -62,7 +68,6 @@ func (o *BuiltInAuthorizationOptions) Validate() []error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
var allErrors []error
|
var allErrors []error
|
||||||
|
|
||||||
if len(o.Modes) == 0 {
|
if len(o.Modes) == 0 {
|
||||||
allErrors = append(allErrors, fmt.Errorf("at least one authorization-mode must be passed"))
|
allErrors = append(allErrors, fmt.Errorf("at least one authorization-mode must be passed"))
|
||||||
}
|
}
|
||||||
@ -125,15 +130,54 @@ func (o *BuiltInAuthorizationOptions) AddFlags(fs *pflag.FlagSet) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ToAuthorizationConfig convert BuiltInAuthorizationOptions to authorizer.Config
|
// ToAuthorizationConfig convert BuiltInAuthorizationOptions to authorizer.Config
|
||||||
func (o *BuiltInAuthorizationOptions) ToAuthorizationConfig(versionedInformerFactory versionedinformers.SharedInformerFactory) authorizer.Config {
|
func (o *BuiltInAuthorizationOptions) ToAuthorizationConfig(versionedInformerFactory versionedinformers.SharedInformerFactory) (authorizer.Config, error) {
|
||||||
|
|
||||||
|
authzConfiguration, err := o.buildAuthorizationConfiguration()
|
||||||
|
if err != nil {
|
||||||
|
return authorizer.Config{}, fmt.Errorf("failed to build authorization config: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
return authorizer.Config{
|
return authorizer.Config{
|
||||||
AuthorizationModes: o.Modes,
|
|
||||||
PolicyFile: o.PolicyFile,
|
PolicyFile: o.PolicyFile,
|
||||||
WebhookConfigFile: o.WebhookConfigFile,
|
|
||||||
WebhookVersion: o.WebhookVersion,
|
|
||||||
WebhookCacheAuthorizedTTL: o.WebhookCacheAuthorizedTTL,
|
|
||||||
WebhookCacheUnauthorizedTTL: o.WebhookCacheUnauthorizedTTL,
|
|
||||||
VersionedInformerFactory: versionedInformerFactory,
|
VersionedInformerFactory: versionedInformerFactory,
|
||||||
WebhookRetryBackoff: o.WebhookRetryBackoff,
|
WebhookRetryBackoff: o.WebhookRetryBackoff,
|
||||||
}
|
|
||||||
|
AuthorizationConfiguration: authzConfiguration,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// buildAuthorizationConfiguration converts existing flags to the AuthorizationConfiguration format
|
||||||
|
func (o *BuiltInAuthorizationOptions) buildAuthorizationConfiguration() (*authzconfig.AuthorizationConfiguration, error) {
|
||||||
|
var authorizers []authzconfig.AuthorizerConfiguration
|
||||||
|
|
||||||
|
if len(o.Modes) != sets.NewString(o.Modes...).Len() {
|
||||||
|
return nil, fmt.Errorf("modes should not be repeated in --authorization-mode")
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, mode := range o.Modes {
|
||||||
|
switch mode {
|
||||||
|
case authzmodes.ModeWebhook:
|
||||||
|
authorizers = append(authorizers, authzconfig.AuthorizerConfiguration{
|
||||||
|
Type: authzconfig.TypeWebhook,
|
||||||
|
Webhook: &authzconfig.WebhookConfiguration{
|
||||||
|
Name: defaultWebhookName,
|
||||||
|
AuthorizedTTL: metav1.Duration{Duration: o.WebhookCacheAuthorizedTTL},
|
||||||
|
UnauthorizedTTL: metav1.Duration{Duration: o.WebhookCacheUnauthorizedTTL},
|
||||||
|
// Timeout and FailurePolicy are required for the new configuration.
|
||||||
|
// Setting these two implicitly to preserve backward compatibility.
|
||||||
|
Timeout: metav1.Duration{Duration: 30 * time.Second},
|
||||||
|
FailurePolicy: authzconfig.FailurePolicyNoOpinion,
|
||||||
|
SubjectAccessReviewVersion: o.WebhookVersion,
|
||||||
|
ConnectionInfo: authzconfig.WebhookConnectionInfo{
|
||||||
|
Type: authzconfig.AuthorizationWebhookConnectionInfoTypeKubeConfig,
|
||||||
|
KubeConfigFile: &o.WebhookConfigFile,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
default:
|
||||||
|
authorizers = append(authorizers, authzconfig.AuthorizerConfiguration{Type: authzconfig.AuthorizerType(mode)})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &authzconfig.AuthorizationConfiguration{Authorizers: authorizers}, nil
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user