mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-10-31 02:08:13 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			201 lines
		
	
	
		
			7.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			201 lines
		
	
	
		
			7.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| /*
 | |
| 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 options
 | |
| 
 | |
| import (
 | |
| 	"fmt"
 | |
| 	"strings"
 | |
| 	"time"
 | |
| 
 | |
| 	"github.com/spf13/pflag"
 | |
| 
 | |
| 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | |
| 	"k8s.io/apimachinery/pkg/util/sets"
 | |
| 	"k8s.io/apimachinery/pkg/util/wait"
 | |
| 	authzconfig "k8s.io/apiserver/pkg/apis/apiserver"
 | |
| 	genericoptions "k8s.io/apiserver/pkg/server/options"
 | |
| 	versionedinformers "k8s.io/client-go/informers"
 | |
| 
 | |
| 	"k8s.io/kubernetes/pkg/kubeapiserver/authorizer"
 | |
| 	authzmodes "k8s.io/kubernetes/pkg/kubeapiserver/authorizer/modes"
 | |
| )
 | |
| 
 | |
| const (
 | |
| 	defaultWebhookName = "default"
 | |
| )
 | |
| 
 | |
| // BuiltInAuthorizationOptions contains all build-in authorization options for API Server
 | |
| type BuiltInAuthorizationOptions struct {
 | |
| 	Modes                       []string
 | |
| 	PolicyFile                  string
 | |
| 	WebhookConfigFile           string
 | |
| 	WebhookVersion              string
 | |
| 	WebhookCacheAuthorizedTTL   time.Duration
 | |
| 	WebhookCacheUnauthorizedTTL time.Duration
 | |
| 	// 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
 | |
| 	// before we fail the webhook call in order to limit the fan out that ensues when the system is degraded.
 | |
| 	WebhookRetryBackoff *wait.Backoff
 | |
| }
 | |
| 
 | |
| // NewBuiltInAuthorizationOptions create a BuiltInAuthorizationOptions with default value
 | |
| func NewBuiltInAuthorizationOptions() *BuiltInAuthorizationOptions {
 | |
| 	return &BuiltInAuthorizationOptions{
 | |
| 		Modes:                       []string{authzmodes.ModeAlwaysAllow},
 | |
| 		WebhookVersion:              "v1beta1",
 | |
| 		WebhookCacheAuthorizedTTL:   5 * time.Minute,
 | |
| 		WebhookCacheUnauthorizedTTL: 30 * time.Second,
 | |
| 		WebhookRetryBackoff:         genericoptions.DefaultAuthWebhookRetryBackoff(),
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // Validate checks invalid config combination
 | |
| func (o *BuiltInAuthorizationOptions) Validate() []error {
 | |
| 	if o == nil {
 | |
| 		return nil
 | |
| 	}
 | |
| 	var allErrors []error
 | |
| 	if len(o.Modes) == 0 {
 | |
| 		allErrors = append(allErrors, fmt.Errorf("at least one authorization-mode must be passed"))
 | |
| 	}
 | |
| 
 | |
| 	modes := sets.NewString(o.Modes...)
 | |
| 	for _, mode := range o.Modes {
 | |
| 		if !authzmodes.IsValidAuthorizationMode(mode) {
 | |
| 			allErrors = append(allErrors, fmt.Errorf("authorization-mode %q is not a valid mode", mode))
 | |
| 		}
 | |
| 		if mode == authzmodes.ModeABAC && o.PolicyFile == "" {
 | |
| 			allErrors = append(allErrors, fmt.Errorf("authorization-mode ABAC's authorization policy file not passed"))
 | |
| 		}
 | |
| 		if mode == authzmodes.ModeWebhook && o.WebhookConfigFile == "" {
 | |
| 			allErrors = append(allErrors, fmt.Errorf("authorization-mode Webhook's authorization config file not passed"))
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	if o.PolicyFile != "" && !modes.Has(authzmodes.ModeABAC) {
 | |
| 		allErrors = append(allErrors, fmt.Errorf("cannot specify --authorization-policy-file without mode ABAC"))
 | |
| 	}
 | |
| 
 | |
| 	if o.WebhookConfigFile != "" && !modes.Has(authzmodes.ModeWebhook) {
 | |
| 		allErrors = append(allErrors, fmt.Errorf("cannot specify --authorization-webhook-config-file without mode Webhook"))
 | |
| 	}
 | |
| 
 | |
| 	if len(o.Modes) != modes.Len() {
 | |
| 		allErrors = append(allErrors, fmt.Errorf("authorization-mode %q has mode specified more than once", o.Modes))
 | |
| 	}
 | |
| 
 | |
| 	if o.WebhookRetryBackoff != nil && o.WebhookRetryBackoff.Steps <= 0 {
 | |
| 		allErrors = append(allErrors, fmt.Errorf("number of webhook retry attempts must be greater than 0, but is: %d", o.WebhookRetryBackoff.Steps))
 | |
| 	}
 | |
| 
 | |
| 	return allErrors
 | |
| }
 | |
| 
 | |
| // AddFlags returns flags of authorization for a API Server
 | |
| func (o *BuiltInAuthorizationOptions) AddFlags(fs *pflag.FlagSet) {
 | |
| 	if o == nil {
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	fs.StringSliceVar(&o.Modes, "authorization-mode", o.Modes, ""+
 | |
| 		"Ordered list of plug-ins to do authorization on secure port. Comma-delimited list of: "+
 | |
| 		strings.Join(authzmodes.AuthorizationModeChoices, ",")+".")
 | |
| 
 | |
| 	fs.StringVar(&o.PolicyFile, "authorization-policy-file", o.PolicyFile, ""+
 | |
| 		"File with authorization policy in json line by line format, used with --authorization-mode=ABAC, on the secure port.")
 | |
| 
 | |
| 	fs.StringVar(&o.WebhookConfigFile, "authorization-webhook-config-file", o.WebhookConfigFile, ""+
 | |
| 		"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.")
 | |
| 
 | |
| 	fs.StringVar(&o.WebhookVersion, "authorization-webhook-version", o.WebhookVersion, ""+
 | |
| 		"The API version of the authorization.k8s.io SubjectAccessReview to send to and expect from the webhook.")
 | |
| 
 | |
| 	fs.DurationVar(&o.WebhookCacheAuthorizedTTL, "authorization-webhook-cache-authorized-ttl",
 | |
| 		o.WebhookCacheAuthorizedTTL,
 | |
| 		"The duration to cache 'authorized' responses from the webhook authorizer.")
 | |
| 
 | |
| 	fs.DurationVar(&o.WebhookCacheUnauthorizedTTL,
 | |
| 		"authorization-webhook-cache-unauthorized-ttl", o.WebhookCacheUnauthorizedTTL,
 | |
| 		"The duration to cache 'unauthorized' responses from the webhook authorizer.")
 | |
| }
 | |
| 
 | |
| // ToAuthorizationConfig convert BuiltInAuthorizationOptions to authorizer.Config
 | |
| func (o *BuiltInAuthorizationOptions) ToAuthorizationConfig(versionedInformerFactory versionedinformers.SharedInformerFactory) (*authorizer.Config, error) {
 | |
| 	if o == nil {
 | |
| 		return nil, nil
 | |
| 	}
 | |
| 
 | |
| 	authzConfiguration, err := o.buildAuthorizationConfiguration()
 | |
| 	if err != nil {
 | |
| 		return nil, fmt.Errorf("failed to build authorization config: %s", err)
 | |
| 	}
 | |
| 
 | |
| 	return &authorizer.Config{
 | |
| 		PolicyFile:               o.PolicyFile,
 | |
| 		VersionedInformerFactory: versionedInformerFactory,
 | |
| 		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,
 | |
| 				Name: defaultWebhookName,
 | |
| 				Webhook: &authzconfig.WebhookConfiguration{
 | |
| 					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),
 | |
| 				Name: getNameForAuthorizerMode(mode),
 | |
| 			})
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return &authzconfig.AuthorizationConfiguration{Authorizers: authorizers}, nil
 | |
| }
 | |
| 
 | |
| // getNameForAuthorizerMode returns the name to be set for the mode in AuthorizationConfiguration
 | |
| // For now, lower cases the mode name
 | |
| func getNameForAuthorizerMode(mode string) string {
 | |
| 	return strings.ToLower(mode)
 | |
| }
 | 
