...

Source file src/k8s.io/kubernetes/pkg/kubeapiserver/options/authorization_test.go

Documentation: k8s.io/kubernetes/pkg/kubeapiserver/options

     1  /*
     2  Copyright 2018 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package options
    18  
    19  import (
    20  	"fmt"
    21  	"reflect"
    22  	"strings"
    23  	"testing"
    24  	"time"
    25  
    26  	"github.com/google/go-cmp/cmp"
    27  	"github.com/spf13/pflag"
    28  
    29  	utilerrors "k8s.io/apimachinery/pkg/util/errors"
    30  	"k8s.io/apimachinery/pkg/util/wait"
    31  	"k8s.io/kubernetes/pkg/kubeapiserver/authorizer/modes"
    32  )
    33  
    34  func TestAuthzValidate(t *testing.T) {
    35  	examplePolicyFile := "../../auth/authorizer/abac/example_policy_file.jsonl"
    36  
    37  	testCases := []struct {
    38  		name                 string
    39  		modes                []string
    40  		policyFile           string
    41  		webhookConfigFile    string
    42  		webhookRetryBackoff  *wait.Backoff
    43  		expectErr            bool
    44  		expectErrorSubString string
    45  	}{
    46  		{
    47  			name:                 "Unknown modes should return errors",
    48  			modes:                []string{"DoesNotExist"},
    49  			expectErr:            true,
    50  			expectErrorSubString: "is not a valid mode",
    51  		},
    52  		{
    53  			name:                 "At least one authorizationMode is necessary",
    54  			modes:                []string{},
    55  			expectErr:            true,
    56  			expectErrorSubString: "at least one authorization-mode must be passed",
    57  		},
    58  		{
    59  			name:                 "ModeAlwaysAllow specified more than once",
    60  			modes:                []string{modes.ModeAlwaysAllow, modes.ModeAlwaysAllow},
    61  			expectErr:            true,
    62  			expectErrorSubString: "has mode specified more than once",
    63  		},
    64  		{
    65  			name:      "ModeAlwaysAllow and ModeAlwaysDeny should return without authorizationPolicyFile",
    66  			modes:     []string{modes.ModeAlwaysAllow, modes.ModeAlwaysDeny},
    67  			expectErr: false,
    68  		},
    69  		{
    70  			name:                 "ModeABAC requires a policy file",
    71  			modes:                []string{modes.ModeAlwaysAllow, modes.ModeAlwaysDeny, modes.ModeABAC},
    72  			expectErr:            true,
    73  			expectErrorSubString: "authorization-mode ABAC's authorization policy file not passed",
    74  		},
    75  		{
    76  			name:                 "Authorization Policy file cannot be used without ModeABAC",
    77  			modes:                []string{modes.ModeAlwaysAllow, modes.ModeAlwaysDeny},
    78  			policyFile:           examplePolicyFile,
    79  			webhookConfigFile:    "",
    80  			expectErr:            true,
    81  			expectErrorSubString: "cannot specify --authorization-policy-file without mode ABAC",
    82  		},
    83  		{
    84  			name:              "ModeABAC should not error if a valid policy path is provided",
    85  			modes:             []string{modes.ModeAlwaysAllow, modes.ModeAlwaysDeny, modes.ModeABAC},
    86  			policyFile:        examplePolicyFile,
    87  			webhookConfigFile: "",
    88  			expectErr:         false,
    89  		},
    90  		{
    91  			name:                 "ModeWebhook requires a config file",
    92  			modes:                []string{modes.ModeWebhook},
    93  			expectErr:            true,
    94  			expectErrorSubString: "authorization-mode Webhook's authorization config file not passed",
    95  		},
    96  		{
    97  			name:                 "Cannot provide webhook config file without ModeWebhook",
    98  			modes:                []string{modes.ModeAlwaysAllow},
    99  			webhookConfigFile:    "authz_webhook_config.yaml",
   100  			expectErr:            true,
   101  			expectErrorSubString: "cannot specify --authorization-webhook-config-file without mode Webhook",
   102  		},
   103  		{
   104  			name:              "ModeWebhook should not error if a valid config file is provided",
   105  			modes:             []string{modes.ModeWebhook},
   106  			webhookConfigFile: "authz_webhook_config.yaml",
   107  			expectErr:         false,
   108  		},
   109  		{
   110  			name:                 "ModeWebhook should error if an invalid number of webhook retry attempts is provided",
   111  			modes:                []string{modes.ModeWebhook},
   112  			webhookConfigFile:    "authz_webhook_config.yaml",
   113  			webhookRetryBackoff:  &wait.Backoff{Steps: 0},
   114  			expectErr:            true,
   115  			expectErrorSubString: "number of webhook retry attempts must be greater than 0",
   116  		},
   117  	}
   118  
   119  	for _, testcase := range testCases {
   120  		t.Run(testcase.name, func(t *testing.T) {
   121  			options := NewBuiltInAuthorizationOptions()
   122  			options.Modes = testcase.modes
   123  			options.WebhookConfigFile = testcase.webhookConfigFile
   124  			options.WebhookRetryBackoff = testcase.webhookRetryBackoff
   125  			options.PolicyFile = testcase.policyFile
   126  
   127  			errs := options.Validate()
   128  			if len(errs) > 0 && !testcase.expectErr {
   129  				t.Errorf("got unexpected err %v", errs)
   130  			}
   131  			if testcase.expectErr && len(errs) == 0 {
   132  				t.Errorf("should return an error")
   133  			}
   134  			if len(errs) > 0 && testcase.expectErr {
   135  				if !strings.Contains(utilerrors.NewAggregate(errs).Error(), testcase.expectErrorSubString) {
   136  					t.Errorf("exepected to found error: %s, but no error found", testcase.expectErrorSubString)
   137  				}
   138  			}
   139  		})
   140  	}
   141  }
   142  
   143  func TestBuiltInAuthorizationOptionsAddFlags(t *testing.T) {
   144  	var args = []string{
   145  		fmt.Sprintf("--authorization-mode=%s,%s,%s,%s", modes.ModeAlwaysAllow, modes.ModeAlwaysDeny, modes.ModeABAC, modes.ModeWebhook),
   146  		"--authorization-policy-file=policy_file.json",
   147  		"--authorization-webhook-config-file=webhook_config_file.yaml",
   148  		"--authorization-webhook-version=v1",
   149  		"--authorization-webhook-cache-authorized-ttl=60s",
   150  		"--authorization-webhook-cache-unauthorized-ttl=30s",
   151  	}
   152  
   153  	expected := &BuiltInAuthorizationOptions{
   154  		Modes:                       []string{modes.ModeAlwaysAllow, modes.ModeAlwaysDeny, modes.ModeABAC, modes.ModeWebhook},
   155  		PolicyFile:                  "policy_file.json",
   156  		WebhookConfigFile:           "webhook_config_file.yaml",
   157  		WebhookVersion:              "v1",
   158  		WebhookCacheAuthorizedTTL:   60 * time.Second,
   159  		WebhookCacheUnauthorizedTTL: 30 * time.Second,
   160  		WebhookRetryBackoff: &wait.Backoff{
   161  			Duration: 500 * time.Millisecond,
   162  			Factor:   1.5,
   163  			Jitter:   0.2,
   164  			Steps:    5,
   165  		},
   166  	}
   167  
   168  	opts := NewBuiltInAuthorizationOptions()
   169  	pf := pflag.NewFlagSet("test-builtin-authorization-opts", pflag.ContinueOnError)
   170  	opts.AddFlags(pf)
   171  
   172  	if err := pf.Parse(args); err != nil {
   173  		t.Fatal(err)
   174  	}
   175  
   176  	if !opts.AreLegacyFlagsSet() {
   177  		t.Fatal("legacy flags should have been configured")
   178  	}
   179  
   180  	// setting the method to nil since methods can't be compared with reflect.DeepEqual
   181  	opts.AreLegacyFlagsSet = nil
   182  
   183  	if !reflect.DeepEqual(opts, expected) {
   184  		t.Error(cmp.Diff(opts, expected))
   185  	}
   186  }
   187  

View as plain text