Skip to content

Commit 2fdcfea

Browse files
author
Kubernetes Submit Queue
authored
Merge pull request kubernetes#61166 from hzxuzhonghu/authz-flag-validate
Automatic merge from submit-queue (batch tested with PRs 60519, 61099, 61218, 61166, 61714). If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>. kube-apiserver add BuiltInAuthorizationOptions validation Validate BuiltInAuthorizationOptions after flags parsed. **Release note**: ```release-note NONE ```
2 parents c14767d + 755df04 commit 2fdcfea

File tree

12 files changed

+167
-164
lines changed

12 files changed

+167
-164
lines changed

cmd/kube-apiserver/app/options/options_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ func TestAddFlags(t *testing.T) {
7575
"--audit-webhook-version=audit.k8s.io/v1alpha1",
7676
"--authentication-token-webhook-cache-ttl=3m",
7777
"--authentication-token-webhook-config-file=/token-webhook-config",
78-
"--authorization-mode=AlwaysDeny",
78+
"--authorization-mode=AlwaysDeny,RBAC",
7979
"--authorization-policy-file=/policy",
8080
"--authorization-webhook-cache-authorized-ttl=3m",
8181
"--authorization-webhook-cache-unauthorized-ttl=1m",
@@ -252,7 +252,7 @@ func TestAddFlags(t *testing.T) {
252252
TokenFailureCacheTTL: 0,
253253
},
254254
Authorization: &kubeoptions.BuiltInAuthorizationOptions{
255-
Mode: "AlwaysDeny",
255+
Modes: []string{"AlwaysDeny", "RBAC"},
256256
PolicyFile: "/policy",
257257
WebhookConfigFile: "/webhook-config",
258258
WebhookCacheAuthorizedTTL: 180000000000,

cmd/kube-apiserver/app/options/validation.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ func (s *ServerRunOptions) Validate() []error {
6767
if errs := s.Authentication.Validate(); len(errs) > 0 {
6868
errors = append(errors, errs...)
6969
}
70+
if errs := s.Authorization.Validate(); len(errs) > 0 {
71+
errors = append(errors, errs...)
72+
}
7073
if errs := s.Audit.Validate(); len(errs) > 0 {
7174
errors = append(errors, errs...)
7275
}

cmd/kube-apiserver/app/server.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -484,7 +484,7 @@ func BuildGenericConfig(s *options.ServerRunOptions, proxyTransport *http.Transp
484484
if err != nil {
485485
return nil, nil, nil, nil, nil, fmt.Errorf("invalid authorization config: %v", err)
486486
}
487-
if !sets.NewString(s.Authorization.Modes()...).Has(modes.ModeRBAC) {
487+
if !sets.NewString(s.Authorization.Modes...).Has(modes.ModeRBAC) {
488488
genericConfig.DisabledPostStartHooks.Insert(rbacrest.PostStartHookName)
489489
}
490490

pkg/kubeapiserver/authorizer/BUILD

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,6 @@ package(default_visibility = ["//visibility:public"])
33
load(
44
"@io_bazel_rules_go//go:def.bzl",
55
"go_library",
6-
"go_test",
7-
)
8-
9-
go_test(
10-
name = "go_default_test",
11-
srcs = ["config_test.go"],
12-
data = [
13-
"//pkg/auth/authorizer/abac:example_policy",
14-
],
15-
embed = [":go_default_library"],
16-
deps = ["//pkg/kubeapiserver/authorizer/modes:go_default_library"],
176
)
187

198
go_library(

pkg/kubeapiserver/authorizer/config.go

Lines changed: 2 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ limitations under the License.
1717
package authorizer
1818

1919
import (
20-
"errors"
2120
"fmt"
2221
"time"
2322

@@ -60,20 +59,15 @@ type AuthorizationConfig struct {
6059
// based on the authorizationMode or an error.
6160
func (config AuthorizationConfig) New() (authorizer.Authorizer, authorizer.RuleResolver, error) {
6261
if len(config.AuthorizationModes) == 0 {
63-
return nil, nil, errors.New("At least one authorization mode should be passed")
62+
return nil, nil, fmt.Errorf("at least one authorization mode must be passed")
6463
}
6564

6665
var (
6766
authorizers []authorizer.Authorizer
6867
ruleResolvers []authorizer.RuleResolver
6968
)
70-
authorizerMap := make(map[string]bool)
7169

7270
for _, authorizationMode := range config.AuthorizationModes {
73-
if authorizerMap[authorizationMode] {
74-
return nil, nil, fmt.Errorf("Authorization mode %s specified more than once", authorizationMode)
75-
}
76-
7771
// Keep cases in sync with constant list above.
7872
switch authorizationMode {
7973
case modes.ModeNode:
@@ -96,19 +90,13 @@ func (config AuthorizationConfig) New() (authorizer.Authorizer, authorizer.RuleR
9690
authorizers = append(authorizers, alwaysDenyAuthorizer)
9791
ruleResolvers = append(ruleResolvers, alwaysDenyAuthorizer)
9892
case modes.ModeABAC:
99-
if config.PolicyFile == "" {
100-
return nil, nil, errors.New("ABAC's authorization policy file not passed")
101-
}
10293
abacAuthorizer, err := abac.NewFromFile(config.PolicyFile)
10394
if err != nil {
10495
return nil, nil, err
10596
}
10697
authorizers = append(authorizers, abacAuthorizer)
10798
ruleResolvers = append(ruleResolvers, abacAuthorizer)
10899
case modes.ModeWebhook:
109-
if config.WebhookConfigFile == "" {
110-
return nil, nil, errors.New("Webhook's configuration file not passed")
111-
}
112100
webhookAuthorizer, err := webhook.New(config.WebhookConfigFile,
113101
config.WebhookCacheAuthorizedTTL,
114102
config.WebhookCacheUnauthorizedTTL)
@@ -127,16 +115,8 @@ func (config AuthorizationConfig) New() (authorizer.Authorizer, authorizer.RuleR
127115
authorizers = append(authorizers, rbacAuthorizer)
128116
ruleResolvers = append(ruleResolvers, rbacAuthorizer)
129117
default:
130-
return nil, nil, fmt.Errorf("Unknown authorization mode %s specified", authorizationMode)
118+
return nil, nil, fmt.Errorf("unknown authorization mode %s specified", authorizationMode)
131119
}
132-
authorizerMap[authorizationMode] = true
133-
}
134-
135-
if !authorizerMap[modes.ModeABAC] && config.PolicyFile != "" {
136-
return nil, nil, errors.New("Cannot specify --authorization-policy-file without mode ABAC")
137-
}
138-
if !authorizerMap[modes.ModeWebhook] && config.WebhookConfigFile != "" {
139-
return nil, nil, errors.New("Cannot specify --authorization-webhook-config-file without mode Webhook")
140120
}
141121

142122
return union.New(authorizers...), union.NewRuleResolvers(ruleResolvers...), nil

pkg/kubeapiserver/authorizer/config_test.go

Lines changed: 0 additions & 101 deletions
This file was deleted.

pkg/kubeapiserver/options/BUILD

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,8 +90,12 @@ go_test(
9090
name = "go_default_test",
9191
srcs = [
9292
"admission_test.go",
93+
"authorization_test.go",
9394
"storage_versions_test.go",
9495
],
9596
embed = [":go_default_library"],
96-
deps = ["//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library"],
97+
deps = [
98+
"//pkg/kubeapiserver/authorizer/modes:go_default_library",
99+
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
100+
],
97101
)

pkg/kubeapiserver/options/authentication.go

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import (
2525
"github.com/golang/glog"
2626
"github.com/spf13/pflag"
2727

28+
"k8s.io/apimachinery/pkg/util/sets"
2829
genericapiserver "k8s.io/apiserver/pkg/server"
2930
genericoptions "k8s.io/apiserver/pkg/server/options"
3031
"k8s.io/kubernetes/pkg/kubeapiserver/authenticator"
@@ -365,17 +366,8 @@ func (o *BuiltInAuthenticationOptions) ApplyAuthorization(authorization *BuiltIn
365366

366367
// authorization ModeAlwaysAllow cannot be combined with AnonymousAuth.
367368
// in such a case the AnonymousAuth is stomped to false and you get a message
368-
if o.Anonymous.Allow {
369-
found := false
370-
for _, mode := range strings.Split(authorization.Mode, ",") {
371-
if mode == authzmodes.ModeAlwaysAllow {
372-
found = true
373-
break
374-
}
375-
}
376-
if found {
377-
glog.Warningf("AnonymousAuth is not allowed with the AllowAll authorizer. Resetting AnonymousAuth to false. You should use a different authorizer")
378-
o.Anonymous.Allow = false
379-
}
369+
if o.Anonymous.Allow && sets.NewString(authorization.Modes...).Has(authzmodes.ModeAlwaysAllow) {
370+
glog.Warningf("AnonymousAuth is not allowed with the AlwaysAllow authorizer. Resetting AnonymousAuth to false. You should use a different authorizer")
371+
o.Anonymous.Allow = false
380372
}
381373
}

pkg/kubeapiserver/options/authorization.go

Lines changed: 44 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,21 @@ limitations under the License.
1717
package options
1818

1919
import (
20+
"fmt"
2021
"strings"
2122
"time"
2223

2324
"github.com/spf13/pflag"
2425

26+
"k8s.io/apimachinery/pkg/util/sets"
2527
versionedinformers "k8s.io/client-go/informers"
2628
informers "k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion"
2729
"k8s.io/kubernetes/pkg/kubeapiserver/authorizer"
2830
authzmodes "k8s.io/kubernetes/pkg/kubeapiserver/authorizer/modes"
2931
)
3032

3133
type BuiltInAuthorizationOptions struct {
32-
Mode string
34+
Modes []string
3335
PolicyFile string
3436
WebhookConfigFile string
3537
WebhookCacheAuthorizedTTL time.Duration
@@ -38,19 +40,57 @@ type BuiltInAuthorizationOptions struct {
3840

3941
func NewBuiltInAuthorizationOptions() *BuiltInAuthorizationOptions {
4042
return &BuiltInAuthorizationOptions{
41-
Mode: authzmodes.ModeAlwaysAllow,
43+
Modes: []string{authzmodes.ModeAlwaysAllow},
4244
WebhookCacheAuthorizedTTL: 5 * time.Minute,
4345
WebhookCacheUnauthorizedTTL: 30 * time.Second,
4446
}
4547
}
4648

4749
func (s *BuiltInAuthorizationOptions) Validate() []error {
50+
if s == nil {
51+
return nil
52+
}
4853
allErrors := []error{}
54+
55+
if len(s.Modes) == 0 {
56+
allErrors = append(allErrors, fmt.Errorf("at least one authorization-mode must be passed"))
57+
}
58+
59+
allowedModes := sets.NewString(authzmodes.AuthorizationModeChoices...)
60+
modes := sets.NewString(s.Modes...)
61+
for _, mode := range s.Modes {
62+
if !allowedModes.Has(mode) {
63+
allErrors = append(allErrors, fmt.Errorf("authorization-mode %q is not a valid mode", mode))
64+
}
65+
if mode == authzmodes.ModeABAC {
66+
if s.PolicyFile == "" {
67+
allErrors = append(allErrors, fmt.Errorf("authorization-mode ABAC's authorization policy file not passed"))
68+
}
69+
}
70+
if mode == authzmodes.ModeWebhook {
71+
if s.WebhookConfigFile == "" {
72+
allErrors = append(allErrors, fmt.Errorf("authorization-mode Webhook's authorization config file not passed"))
73+
}
74+
}
75+
}
76+
77+
if s.PolicyFile != "" && !modes.Has(authzmodes.ModeABAC) {
78+
allErrors = append(allErrors, fmt.Errorf("cannot specify --authorization-policy-file without mode ABAC"))
79+
}
80+
81+
if s.WebhookConfigFile != "" && !modes.Has(authzmodes.ModeWebhook) {
82+
allErrors = append(allErrors, fmt.Errorf("cannot specify --authorization-webhook-config-file without mode Webhook"))
83+
}
84+
85+
if len(s.Modes) != len(modes.List()) {
86+
allErrors = append(allErrors, fmt.Errorf("authorization-mode %q has mode specified more than once", s.Modes))
87+
}
88+
4989
return allErrors
5090
}
5191

5292
func (s *BuiltInAuthorizationOptions) AddFlags(fs *pflag.FlagSet) {
53-
fs.StringVar(&s.Mode, "authorization-mode", s.Mode, ""+
93+
fs.StringSliceVar(&s.Modes, "authorization-mode", s.Modes, ""+
5494
"Ordered list of plug-ins to do authorization on secure port. Comma-delimited list of: "+
5595
strings.Join(authzmodes.AuthorizationModeChoices, ",")+".")
5696

@@ -70,17 +110,9 @@ func (s *BuiltInAuthorizationOptions) AddFlags(fs *pflag.FlagSet) {
70110
"The duration to cache 'unauthorized' responses from the webhook authorizer.")
71111
}
72112

73-
func (s *BuiltInAuthorizationOptions) Modes() []string {
74-
modes := []string{}
75-
if len(s.Mode) > 0 {
76-
modes = strings.Split(s.Mode, ",")
77-
}
78-
return modes
79-
}
80-
81113
func (s *BuiltInAuthorizationOptions) ToAuthorizationConfig(informerFactory informers.SharedInformerFactory, versionedInformerFactory versionedinformers.SharedInformerFactory) authorizer.AuthorizationConfig {
82114
return authorizer.AuthorizationConfig{
83-
AuthorizationModes: s.Modes(),
115+
AuthorizationModes: s.Modes,
84116
PolicyFile: s.PolicyFile,
85117
WebhookConfigFile: s.WebhookConfigFile,
86118
WebhookCacheAuthorizedTTL: s.WebhookCacheAuthorizedTTL,

0 commit comments

Comments
 (0)