Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
K
k3s
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Jacklull
k3s
Commits
496b6f67
Commit
496b6f67
authored
Oct 07, 2018
by
Darren Shepherd
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Delete webhook authorizer
parent
20555c30
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
3 additions
and
1558 deletions
+3
-1558
options.go
cmd/kube-controller-manager/app/options/options.go
+0
-9
options.go
cmd/kube-scheduler/app/options/options.go
+1
-5
auth.go
cmd/kubelet/app/auth.go
+0
-11
config.go
pkg/kubeapiserver/authorizer/config.go
+0
-18
modes.go
pkg/kubeapiserver/authorizer/modes/modes.go
+1
-2
authorization.go
pkg/kubeapiserver/options/authorization.go
+1
-32
types.go
pkg/kubelet/apis/config/types.go
+0
-2
delegating.go
...iserver/pkg/authorization/authorizerfactory/delegating.go
+0
-46
authorization.go
.../src/k8s.io/apiserver/pkg/server/options/authorization.go
+0
-172
recommended.go
...ng/src/k8s.io/apiserver/pkg/server/options/recommended.go
+0
-7
BUILD
.../src/k8s.io/apiserver/plugin/pkg/authorizer/webhook/BUILD
+0
-56
certs_test.go
....io/apiserver/plugin/pkg/authorizer/webhook/certs_test.go
+0
-211
gencerts.sh
...8s.io/apiserver/plugin/pkg/authorizer/webhook/gencerts.sh
+0
-102
webhook.go
...k8s.io/apiserver/plugin/pkg/authorizer/webhook/webhook.go
+0
-264
webhook_test.go
...o/apiserver/plugin/pkg/authorizer/webhook/webhook_test.go
+0
-621
No files found.
cmd/kube-controller-manager/app/options/options.go
View file @
496b6f67
...
@@ -83,7 +83,6 @@ type KubeControllerManagerOptions struct {
...
@@ -83,7 +83,6 @@ type KubeControllerManagerOptions struct {
// TODO: remove insecure serving mode
// TODO: remove insecure serving mode
InsecureServing
*
apiserveroptions
.
DeprecatedInsecureServingOptionsWithLoopback
InsecureServing
*
apiserveroptions
.
DeprecatedInsecureServingOptionsWithLoopback
Authentication
*
apiserveroptions
.
DelegatingAuthenticationOptions
Authentication
*
apiserveroptions
.
DelegatingAuthenticationOptions
Authorization
*
apiserveroptions
.
DelegatingAuthorizationOptions
Master
string
Master
string
Kubeconfig
string
Kubeconfig
string
...
@@ -183,12 +182,9 @@ func NewKubeControllerManagerOptions() (*KubeControllerManagerOptions, error) {
...
@@ -183,12 +182,9 @@ func NewKubeControllerManagerOptions() (*KubeControllerManagerOptions, error) {
BindNetwork
:
"tcp"
,
BindNetwork
:
"tcp"
,
})
.
WithLoopback
(),
})
.
WithLoopback
(),
Authentication
:
apiserveroptions
.
NewDelegatingAuthenticationOptions
(),
Authentication
:
apiserveroptions
.
NewDelegatingAuthenticationOptions
(),
Authorization
:
apiserveroptions
.
NewDelegatingAuthorizationOptions
(),
}
}
s
.
Authentication
.
RemoteKubeConfigFileOptional
=
true
s
.
Authentication
.
RemoteKubeConfigFileOptional
=
true
s
.
Authorization
.
RemoteKubeConfigFileOptional
=
true
s
.
Authorization
.
AlwaysAllowPaths
=
[]
string
{
"/healthz"
}
s
.
SecureServing
.
ServerCert
.
CertDirectory
=
"/var/run/kubernetes"
s
.
SecureServing
.
ServerCert
.
CertDirectory
=
"/var/run/kubernetes"
s
.
SecureServing
.
ServerCert
.
PairName
=
"kube-controller-manager"
s
.
SecureServing
.
ServerCert
.
PairName
=
"kube-controller-manager"
...
@@ -235,7 +231,6 @@ func (s *KubeControllerManagerOptions) Flags(allControllers []string, disabledBy
...
@@ -235,7 +231,6 @@ func (s *KubeControllerManagerOptions) Flags(allControllers []string, disabledBy
s
.
SecureServing
.
AddFlags
(
fss
.
FlagSet
(
"secure serving"
))
s
.
SecureServing
.
AddFlags
(
fss
.
FlagSet
(
"secure serving"
))
s
.
InsecureServing
.
AddUnqualifiedFlags
(
fss
.
FlagSet
(
"insecure serving"
))
s
.
InsecureServing
.
AddUnqualifiedFlags
(
fss
.
FlagSet
(
"insecure serving"
))
s
.
Authentication
.
AddFlags
(
fss
.
FlagSet
(
"authentication"
))
s
.
Authentication
.
AddFlags
(
fss
.
FlagSet
(
"authentication"
))
s
.
Authorization
.
AddFlags
(
fss
.
FlagSet
(
"authorization"
))
s
.
AttachDetachController
.
AddFlags
(
fss
.
FlagSet
(
"attachdetach controller"
))
s
.
AttachDetachController
.
AddFlags
(
fss
.
FlagSet
(
"attachdetach controller"
))
s
.
CSRSigningController
.
AddFlags
(
fss
.
FlagSet
(
"csrsigning controller"
))
s
.
CSRSigningController
.
AddFlags
(
fss
.
FlagSet
(
"csrsigning controller"
))
...
@@ -346,9 +341,6 @@ func (s *KubeControllerManagerOptions) ApplyTo(c *kubecontrollerconfig.Config) e
...
@@ -346,9 +341,6 @@ func (s *KubeControllerManagerOptions) ApplyTo(c *kubecontrollerconfig.Config) e
if
err
:=
s
.
Authentication
.
ApplyTo
(
&
c
.
Authentication
,
c
.
SecureServing
);
err
!=
nil
{
if
err
:=
s
.
Authentication
.
ApplyTo
(
&
c
.
Authentication
,
c
.
SecureServing
);
err
!=
nil
{
return
err
return
err
}
}
if
err
:=
s
.
Authorization
.
ApplyTo
(
&
c
.
Authorization
);
err
!=
nil
{
return
err
}
}
}
// sync back to component config
// sync back to component config
...
@@ -388,7 +380,6 @@ func (s *KubeControllerManagerOptions) Validate(allControllers []string, disable
...
@@ -388,7 +380,6 @@ func (s *KubeControllerManagerOptions) Validate(allControllers []string, disable
errs
=
append
(
errs
,
s
.
SecureServing
.
Validate
()
...
)
errs
=
append
(
errs
,
s
.
SecureServing
.
Validate
()
...
)
errs
=
append
(
errs
,
s
.
InsecureServing
.
Validate
()
...
)
errs
=
append
(
errs
,
s
.
InsecureServing
.
Validate
()
...
)
errs
=
append
(
errs
,
s
.
Authentication
.
Validate
()
...
)
errs
=
append
(
errs
,
s
.
Authentication
.
Validate
()
...
)
errs
=
append
(
errs
,
s
.
Authorization
.
Validate
()
...
)
// TODO: validate component config, master and kubeconfig
// TODO: validate component config, master and kubeconfig
...
...
cmd/kube-scheduler/app/options/options.go
View file @
496b6f67
...
@@ -59,7 +59,6 @@ type Options struct {
...
@@ -59,7 +59,6 @@ type Options struct {
SecureServing
*
apiserveroptions
.
SecureServingOptions
SecureServing
*
apiserveroptions
.
SecureServingOptions
CombinedInsecureServing
*
CombinedInsecureServingOptions
CombinedInsecureServing
*
CombinedInsecureServingOptions
Authentication
*
apiserveroptions
.
DelegatingAuthenticationOptions
Authentication
*
apiserveroptions
.
DelegatingAuthenticationOptions
Authorization
*
apiserveroptions
.
DelegatingAuthorizationOptions
Deprecated
*
DeprecatedOptions
Deprecated
*
DeprecatedOptions
// ConfigFile is the location of the scheduler server's configuration file.
// ConfigFile is the location of the scheduler server's configuration file.
...
@@ -97,7 +96,6 @@ func NewOptions() (*Options, error) {
...
@@ -97,7 +96,6 @@ func NewOptions() (*Options, error) {
BindAddress
:
hhost
,
BindAddress
:
hhost
,
},
},
Authentication
:
nil
,
// TODO: enable with apiserveroptions.NewDelegatingAuthenticationOptions()
Authentication
:
nil
,
// TODO: enable with apiserveroptions.NewDelegatingAuthenticationOptions()
Authorization
:
nil
,
// TODO: enable with apiserveroptions.NewDelegatingAuthorizationOptions()
Deprecated
:
&
DeprecatedOptions
{
Deprecated
:
&
DeprecatedOptions
{
UseLegacyPolicyConfig
:
false
,
UseLegacyPolicyConfig
:
false
,
PolicyConfigMapNamespace
:
metav1
.
NamespaceSystem
,
PolicyConfigMapNamespace
:
metav1
.
NamespaceSystem
,
...
@@ -138,7 +136,6 @@ func (o *Options) AddFlags(fs *pflag.FlagSet) {
...
@@ -138,7 +136,6 @@ func (o *Options) AddFlags(fs *pflag.FlagSet) {
o
.
SecureServing
.
AddFlags
(
fs
)
o
.
SecureServing
.
AddFlags
(
fs
)
o
.
CombinedInsecureServing
.
AddFlags
(
fs
)
o
.
CombinedInsecureServing
.
AddFlags
(
fs
)
o
.
Authentication
.
AddFlags
(
fs
)
o
.
Authentication
.
AddFlags
(
fs
)
o
.
Authorization
.
AddFlags
(
fs
)
o
.
Deprecated
.
AddFlags
(
fs
,
&
o
.
ComponentConfig
)
o
.
Deprecated
.
AddFlags
(
fs
,
&
o
.
ComponentConfig
)
leaderelectionconfig
.
BindFlags
(
&
o
.
ComponentConfig
.
LeaderElection
.
LeaderElectionConfiguration
,
fs
)
leaderelectionconfig
.
BindFlags
(
&
o
.
ComponentConfig
.
LeaderElection
.
LeaderElectionConfiguration
,
fs
)
...
@@ -179,7 +176,7 @@ func (o *Options) ApplyTo(c *schedulerappconfig.Config) error {
...
@@ -179,7 +176,7 @@ func (o *Options) ApplyTo(c *schedulerappconfig.Config) error {
if
err
:=
o
.
Authentication
.
ApplyTo
(
&
c
.
Authentication
,
c
.
SecureServing
);
err
!=
nil
{
if
err
:=
o
.
Authentication
.
ApplyTo
(
&
c
.
Authentication
,
c
.
SecureServing
);
err
!=
nil
{
return
err
return
err
}
}
return
o
.
Authorization
.
ApplyTo
(
&
c
.
Authorization
)
return
nil
}
}
// Validate validates all the required options.
// Validate validates all the required options.
...
@@ -192,7 +189,6 @@ func (o *Options) Validate() []error {
...
@@ -192,7 +189,6 @@ func (o *Options) Validate() []error {
errs
=
append
(
errs
,
o
.
SecureServing
.
Validate
()
...
)
errs
=
append
(
errs
,
o
.
SecureServing
.
Validate
()
...
)
errs
=
append
(
errs
,
o
.
CombinedInsecureServing
.
Validate
()
...
)
errs
=
append
(
errs
,
o
.
CombinedInsecureServing
.
Validate
()
...
)
errs
=
append
(
errs
,
o
.
Authentication
.
Validate
()
...
)
errs
=
append
(
errs
,
o
.
Authentication
.
Validate
()
...
)
errs
=
append
(
errs
,
o
.
Authorization
.
Validate
()
...
)
errs
=
append
(
errs
,
o
.
Deprecated
.
Validate
()
...
)
errs
=
append
(
errs
,
o
.
Deprecated
.
Validate
()
...
)
return
errs
return
errs
...
...
cmd/kubelet/app/auth.go
View file @
496b6f67
...
@@ -85,17 +85,6 @@ func BuildAuthz(client authorizationclient.SubjectAccessReviewInterface, authz k
...
@@ -85,17 +85,6 @@ func BuildAuthz(client authorizationclient.SubjectAccessReviewInterface, authz k
case
kubeletconfig
.
KubeletAuthorizationModeAlwaysAllow
:
case
kubeletconfig
.
KubeletAuthorizationModeAlwaysAllow
:
return
authorizerfactory
.
NewAlwaysAllowAuthorizer
(),
nil
return
authorizerfactory
.
NewAlwaysAllowAuthorizer
(),
nil
case
kubeletconfig
.
KubeletAuthorizationModeWebhook
:
if
client
==
nil
{
return
nil
,
errors
.
New
(
"no client provided, cannot use webhook authorization"
)
}
authorizerConfig
:=
authorizerfactory
.
DelegatingAuthorizerConfig
{
SubjectAccessReviewClient
:
client
,
AllowCacheTTL
:
authz
.
Webhook
.
CacheAuthorizedTTL
.
Duration
,
DenyCacheTTL
:
authz
.
Webhook
.
CacheUnauthorizedTTL
.
Duration
,
}
return
authorizerConfig
.
New
()
case
""
:
case
""
:
return
nil
,
fmt
.
Errorf
(
"No authorization mode specified"
)
return
nil
,
fmt
.
Errorf
(
"No authorization mode specified"
)
...
...
pkg/kubeapiserver/authorizer/config.go
View file @
496b6f67
...
@@ -18,12 +18,10 @@ package authorizer
...
@@ -18,12 +18,10 @@ package authorizer
import
(
import
(
"fmt"
"fmt"
"time"
"k8s.io/apiserver/pkg/authorization/authorizer"
"k8s.io/apiserver/pkg/authorization/authorizer"
"k8s.io/apiserver/pkg/authorization/authorizerfactory"
"k8s.io/apiserver/pkg/authorization/authorizerfactory"
"k8s.io/apiserver/pkg/authorization/union"
"k8s.io/apiserver/pkg/authorization/union"
"k8s.io/apiserver/plugin/pkg/authorizer/webhook"
versionedinformers
"k8s.io/client-go/informers"
versionedinformers
"k8s.io/client-go/informers"
"k8s.io/kubernetes/pkg/auth/nodeidentifier"
"k8s.io/kubernetes/pkg/auth/nodeidentifier"
"k8s.io/kubernetes/pkg/kubeapiserver/authorizer/modes"
"k8s.io/kubernetes/pkg/kubeapiserver/authorizer/modes"
...
@@ -39,13 +37,6 @@ type AuthorizationConfig struct {
...
@@ -39,13 +37,6 @@ type AuthorizationConfig struct {
// Options for ModeWebhook
// 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
VersionedInformerFactory
versionedinformers
.
SharedInformerFactory
VersionedInformerFactory
versionedinformers
.
SharedInformerFactory
}
}
...
@@ -84,15 +75,6 @@ func (config AuthorizationConfig) New() (authorizer.Authorizer, authorizer.RuleR
...
@@ -84,15 +75,6 @@ func (config AuthorizationConfig) New() (authorizer.Authorizer, authorizer.RuleR
alwaysDenyAuthorizer
:=
authorizerfactory
.
NewAlwaysDenyAuthorizer
()
alwaysDenyAuthorizer
:=
authorizerfactory
.
NewAlwaysDenyAuthorizer
()
authorizers
=
append
(
authorizers
,
alwaysDenyAuthorizer
)
authorizers
=
append
(
authorizers
,
alwaysDenyAuthorizer
)
ruleResolvers
=
append
(
ruleResolvers
,
alwaysDenyAuthorizer
)
ruleResolvers
=
append
(
ruleResolvers
,
alwaysDenyAuthorizer
)
case
modes
.
ModeWebhook
:
webhookAuthorizer
,
err
:=
webhook
.
New
(
config
.
WebhookConfigFile
,
config
.
WebhookCacheAuthorizedTTL
,
config
.
WebhookCacheUnauthorizedTTL
)
if
err
!=
nil
{
return
nil
,
nil
,
err
}
authorizers
=
append
(
authorizers
,
webhookAuthorizer
)
ruleResolvers
=
append
(
ruleResolvers
,
webhookAuthorizer
)
case
modes
.
ModeRBAC
:
case
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
()},
...
...
pkg/kubeapiserver/authorizer/modes/modes.go
View file @
496b6f67
...
@@ -21,12 +21,11 @@ import "k8s.io/apimachinery/pkg/util/sets"
...
@@ -21,12 +21,11 @@ import "k8s.io/apimachinery/pkg/util/sets"
const
(
const
(
ModeAlwaysAllow
string
=
"AlwaysAllow"
ModeAlwaysAllow
string
=
"AlwaysAllow"
ModeAlwaysDeny
string
=
"AlwaysDeny"
ModeAlwaysDeny
string
=
"AlwaysDeny"
ModeWebhook
string
=
"Webhook"
ModeRBAC
string
=
"RBAC"
ModeRBAC
string
=
"RBAC"
ModeNode
string
=
"Node"
ModeNode
string
=
"Node"
)
)
var
AuthorizationModeChoices
=
[]
string
{
ModeAlwaysAllow
,
ModeAlwaysDeny
,
Mode
Webhook
,
Mode
RBAC
,
ModeNode
}
var
AuthorizationModeChoices
=
[]
string
{
ModeAlwaysAllow
,
ModeAlwaysDeny
,
ModeRBAC
,
ModeNode
}
// IsValidAuthorizationMode returns true if the given authorization mode is a valid one for the apiserver
// IsValidAuthorizationMode returns true if the given authorization mode is a valid one for the apiserver
func
IsValidAuthorizationMode
(
authzMode
string
)
bool
{
func
IsValidAuthorizationMode
(
authzMode
string
)
bool
{
...
...
pkg/kubeapiserver/options/authorization.go
View file @
496b6f67
...
@@ -18,10 +18,8 @@ package options
...
@@ -18,10 +18,8 @@ package options
import
(
import
(
"fmt"
"fmt"
"strings"
"time"
"github.com/spf13/pflag"
"github.com/spf13/pflag"
"strings"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/apimachinery/pkg/util/sets"
versionedinformers
"k8s.io/client-go/informers"
versionedinformers
"k8s.io/client-go/informers"
...
@@ -31,16 +29,11 @@ import (
...
@@ -31,16 +29,11 @@ import (
type
BuiltInAuthorizationOptions
struct
{
type
BuiltInAuthorizationOptions
struct
{
Modes
[]
string
Modes
[]
string
WebhookConfigFile
string
WebhookCacheAuthorizedTTL
time
.
Duration
WebhookCacheUnauthorizedTTL
time
.
Duration
}
}
func
NewBuiltInAuthorizationOptions
()
*
BuiltInAuthorizationOptions
{
func
NewBuiltInAuthorizationOptions
()
*
BuiltInAuthorizationOptions
{
return
&
BuiltInAuthorizationOptions
{
return
&
BuiltInAuthorizationOptions
{
Modes
:
[]
string
{
authzmodes
.
ModeAlwaysAllow
},
Modes
:
[]
string
{
authzmodes
.
ModeAlwaysAllow
},
WebhookCacheAuthorizedTTL
:
5
*
time
.
Minute
,
WebhookCacheUnauthorizedTTL
:
30
*
time
.
Second
,
}
}
}
}
...
@@ -60,15 +53,6 @@ func (s *BuiltInAuthorizationOptions) Validate() []error {
...
@@ -60,15 +53,6 @@ func (s *BuiltInAuthorizationOptions) Validate() []error {
if
!
allowedModes
.
Has
(
mode
)
{
if
!
allowedModes
.
Has
(
mode
)
{
allErrors
=
append
(
allErrors
,
fmt
.
Errorf
(
"authorization-mode %q is not a valid mode"
,
mode
))
allErrors
=
append
(
allErrors
,
fmt
.
Errorf
(
"authorization-mode %q is not a valid mode"
,
mode
))
}
}
if
mode
==
authzmodes
.
ModeWebhook
{
if
s
.
WebhookConfigFile
==
""
{
allErrors
=
append
(
allErrors
,
fmt
.
Errorf
(
"authorization-mode Webhook's authorization config file not passed"
))
}
}
}
if
s
.
WebhookConfigFile
!=
""
&&
!
modes
.
Has
(
authzmodes
.
ModeWebhook
)
{
allErrors
=
append
(
allErrors
,
fmt
.
Errorf
(
"cannot specify --authorization-webhook-config-file without mode Webhook"
))
}
}
if
len
(
s
.
Modes
)
!=
len
(
modes
.
List
())
{
if
len
(
s
.
Modes
)
!=
len
(
modes
.
List
())
{
...
@@ -82,26 +66,11 @@ func (s *BuiltInAuthorizationOptions) AddFlags(fs *pflag.FlagSet) {
...
@@ -82,26 +66,11 @@ func (s *BuiltInAuthorizationOptions) AddFlags(fs *pflag.FlagSet) {
fs
.
StringSliceVar
(
&
s
.
Modes
,
"authorization-mode"
,
s
.
Modes
,
""
+
fs
.
StringSliceVar
(
&
s
.
Modes
,
"authorization-mode"
,
s
.
Modes
,
""
+
"Ordered list of plug-ins to do authorization on secure port. Comma-delimited list of: "
+
"Ordered list of plug-ins to do authorization on secure port. Comma-delimited list of: "
+
strings
.
Join
(
authzmodes
.
AuthorizationModeChoices
,
","
)
+
"."
)
strings
.
Join
(
authzmodes
.
AuthorizationModeChoices
,
","
)
+
"."
)
fs
.
StringVar
(
&
s
.
WebhookConfigFile
,
"authorization-webhook-config-file"
,
s
.
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
.
DurationVar
(
&
s
.
WebhookCacheAuthorizedTTL
,
"authorization-webhook-cache-authorized-ttl"
,
s
.
WebhookCacheAuthorizedTTL
,
"The duration to cache 'authorized' responses from the webhook authorizer."
)
fs
.
DurationVar
(
&
s
.
WebhookCacheUnauthorizedTTL
,
"authorization-webhook-cache-unauthorized-ttl"
,
s
.
WebhookCacheUnauthorizedTTL
,
"The duration to cache 'unauthorized' responses from the webhook authorizer."
)
}
}
func
(
s
*
BuiltInAuthorizationOptions
)
ToAuthorizationConfig
(
versionedInformerFactory
versionedinformers
.
SharedInformerFactory
)
authorizer
.
AuthorizationConfig
{
func
(
s
*
BuiltInAuthorizationOptions
)
ToAuthorizationConfig
(
versionedInformerFactory
versionedinformers
.
SharedInformerFactory
)
authorizer
.
AuthorizationConfig
{
return
authorizer
.
AuthorizationConfig
{
return
authorizer
.
AuthorizationConfig
{
AuthorizationModes
:
s
.
Modes
,
AuthorizationModes
:
s
.
Modes
,
WebhookConfigFile
:
s
.
WebhookConfigFile
,
WebhookCacheAuthorizedTTL
:
s
.
WebhookCacheAuthorizedTTL
,
WebhookCacheUnauthorizedTTL
:
s
.
WebhookCacheUnauthorizedTTL
,
VersionedInformerFactory
:
versionedInformerFactory
,
VersionedInformerFactory
:
versionedInformerFactory
,
}
}
}
}
pkg/kubelet/apis/config/types.go
View file @
496b6f67
...
@@ -312,8 +312,6 @@ type KubeletAuthorizationMode string
...
@@ -312,8 +312,6 @@ type KubeletAuthorizationMode string
const
(
const
(
// KubeletAuthorizationModeAlwaysAllow authorizes all authenticated requests
// KubeletAuthorizationModeAlwaysAllow authorizes all authenticated requests
KubeletAuthorizationModeAlwaysAllow
KubeletAuthorizationMode
=
"AlwaysAllow"
KubeletAuthorizationModeAlwaysAllow
KubeletAuthorizationMode
=
"AlwaysAllow"
// KubeletAuthorizationModeWebhook uses the SubjectAccessReview API to determine authorization
KubeletAuthorizationModeWebhook
KubeletAuthorizationMode
=
"Webhook"
)
)
type
KubeletAuthorization
struct
{
type
KubeletAuthorization
struct
{
...
...
staging/src/k8s.io/apiserver/pkg/authorization/authorizerfactory/delegating.go
deleted
100644 → 0
View file @
20555c30
/*
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
authorizerfactory
import
(
"k8s.io/client-go/kubernetes/typed/authorization/v1"
"time"
"k8s.io/apiserver/pkg/authorization/authorizer"
"k8s.io/apiserver/plugin/pkg/authorizer/webhook"
)
// DelegatingAuthorizerConfig is the minimal configuration needed to create an authenticator
// built to delegate authorization to a kube API server
type
DelegatingAuthorizerConfig
struct
{
SubjectAccessReviewClient
v1
.
SubjectAccessReviewInterface
// AllowCacheTTL is the length of time that a successful authorization response will be cached
AllowCacheTTL
time
.
Duration
// DenyCacheTTL is the length of time that an unsuccessful authorization response will be cached.
// You generally want more responsive, "deny, try again" flows.
DenyCacheTTL
time
.
Duration
}
func
(
c
DelegatingAuthorizerConfig
)
New
()
(
authorizer
.
Authorizer
,
error
)
{
return
webhook
.
NewFromInterface
(
c
.
SubjectAccessReviewClient
,
c
.
AllowCacheTTL
,
c
.
DenyCacheTTL
,
)
}
staging/src/k8s.io/apiserver/pkg/server/options/authorization.go
deleted
100644 → 0
View file @
20555c30
/*
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"
"k8s.io/client-go/kubernetes"
"time"
"github.com/golang/glog"
"github.com/spf13/pflag"
"k8s.io/apiserver/pkg/authorization/authorizer"
"k8s.io/apiserver/pkg/authorization/authorizerfactory"
"k8s.io/apiserver/pkg/authorization/path"
"k8s.io/apiserver/pkg/authorization/union"
"k8s.io/apiserver/pkg/server"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
)
// DelegatingAuthorizationOptions provides an easy way for composing API servers to delegate their authorization to
// the root kube API server.
// WARNING: never assume that every authenticated incoming request already does authorization.
// The aggregator in the kube API server does this today, but this behaviour is not
// guaranteed in the future.
type
DelegatingAuthorizationOptions
struct
{
// RemoteKubeConfigFile is the file to use to connect to a "normal" kube API server which hosts the
// SubjectAccessReview.authorization.k8s.io endpoint for checking tokens.
RemoteKubeConfigFile
string
// RemoteKubeConfigFileOptional is specifying whether not specifying the kubeconfig or
// a missing in-cluster config will be fatal.
RemoteKubeConfigFileOptional
bool
// AllowCacheTTL is the length of time that a successful authorization response will be cached
AllowCacheTTL
time
.
Duration
// DenyCacheTTL is the length of time that an unsuccessful authorization response will be cached.
// You generally want more responsive, "deny, try again" flows.
DenyCacheTTL
time
.
Duration
// AlwaysAllowPaths are HTTP paths which are excluded from authorization. They can be plain
// paths or end in * in which case prefix-match is applied. A leading / is optional.
AlwaysAllowPaths
[]
string
}
func
NewDelegatingAuthorizationOptions
()
*
DelegatingAuthorizationOptions
{
return
&
DelegatingAuthorizationOptions
{
// very low for responsiveness, but high enough to handle storms
AllowCacheTTL
:
10
*
time
.
Second
,
DenyCacheTTL
:
10
*
time
.
Second
,
}
}
func
(
s
*
DelegatingAuthorizationOptions
)
Validate
()
[]
error
{
allErrors
:=
[]
error
{}
return
allErrors
}
func
(
s
*
DelegatingAuthorizationOptions
)
AddFlags
(
fs
*
pflag
.
FlagSet
)
{
if
s
==
nil
{
return
}
var
optionalKubeConfigSentence
string
if
s
.
RemoteKubeConfigFileOptional
{
optionalKubeConfigSentence
=
" This is optional. If empty, all requests not skipped by authorization are forbidden."
}
fs
.
StringVar
(
&
s
.
RemoteKubeConfigFile
,
"authorization-kubeconfig"
,
s
.
RemoteKubeConfigFile
,
"kubeconfig file pointing at the 'core' kubernetes server with enough rights to create "
+
"subjectaccessreviews.authorization.k8s.io."
+
optionalKubeConfigSentence
)
fs
.
DurationVar
(
&
s
.
AllowCacheTTL
,
"authorization-webhook-cache-authorized-ttl"
,
s
.
AllowCacheTTL
,
"The duration to cache 'authorized' responses from the webhook authorizer."
)
fs
.
DurationVar
(
&
s
.
DenyCacheTTL
,
"authorization-webhook-cache-unauthorized-ttl"
,
s
.
DenyCacheTTL
,
"The duration to cache 'unauthorized' responses from the webhook authorizer."
)
fs
.
StringSliceVar
(
&
s
.
AlwaysAllowPaths
,
"authorization-always-allow-paths"
,
s
.
AlwaysAllowPaths
,
"A list of HTTP paths to skip during authorization, i.e. these are authorized without "
+
"contacting the 'core' kubernetes server."
)
}
func
(
s
*
DelegatingAuthorizationOptions
)
ApplyTo
(
c
*
server
.
AuthorizationInfo
)
error
{
if
s
==
nil
{
c
.
Authorizer
=
authorizerfactory
.
NewAlwaysAllowAuthorizer
()
return
nil
}
client
,
err
:=
s
.
getClient
()
if
err
!=
nil
{
return
err
}
c
.
Authorizer
,
err
=
s
.
toAuthorizer
(
client
)
return
err
}
func
(
s
*
DelegatingAuthorizationOptions
)
toAuthorizer
(
client
kubernetes
.
Interface
)
(
authorizer
.
Authorizer
,
error
)
{
var
authorizers
[]
authorizer
.
Authorizer
if
len
(
s
.
AlwaysAllowPaths
)
>
0
{
a
,
err
:=
path
.
NewAuthorizer
(
s
.
AlwaysAllowPaths
)
if
err
!=
nil
{
return
nil
,
err
}
authorizers
=
append
(
authorizers
,
a
)
}
if
client
==
nil
{
glog
.
Warningf
(
"No authorization-kubeconfig provided, so SubjectAccessReview of authorization tokens won't work."
)
}
else
{
cfg
:=
authorizerfactory
.
DelegatingAuthorizerConfig
{
SubjectAccessReviewClient
:
client
.
AuthorizationV1
()
.
SubjectAccessReviews
(),
AllowCacheTTL
:
s
.
AllowCacheTTL
,
DenyCacheTTL
:
s
.
DenyCacheTTL
,
}
delegatedAuthorizer
,
err
:=
cfg
.
New
()
if
err
!=
nil
{
return
nil
,
err
}
authorizers
=
append
(
authorizers
,
delegatedAuthorizer
)
}
return
union
.
New
(
authorizers
...
),
nil
}
func
(
s
*
DelegatingAuthorizationOptions
)
getClient
()
(
kubernetes
.
Interface
,
error
)
{
var
clientConfig
*
rest
.
Config
var
err
error
if
len
(
s
.
RemoteKubeConfigFile
)
>
0
{
loadingRules
:=
&
clientcmd
.
ClientConfigLoadingRules
{
ExplicitPath
:
s
.
RemoteKubeConfigFile
}
loader
:=
clientcmd
.
NewNonInteractiveDeferredLoadingClientConfig
(
loadingRules
,
&
clientcmd
.
ConfigOverrides
{})
clientConfig
,
err
=
loader
.
ClientConfig
()
}
else
{
// without the remote kubeconfig file, try to use the in-cluster config. Most addon API servers will
// use this path. If it is optional, ignore errors.
clientConfig
,
err
=
rest
.
InClusterConfig
()
if
err
!=
nil
&&
s
.
RemoteKubeConfigFileOptional
{
if
err
!=
rest
.
ErrNotInCluster
{
glog
.
Warningf
(
"failed to read in-cluster kubeconfig for delegated authorization: %v"
,
err
)
}
return
nil
,
nil
}
}
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"failed to get delegated authorization kubeconfig: %v"
,
err
)
}
// set high qps/burst limits since this will effectively limit API server responsiveness
clientConfig
.
QPS
=
200
clientConfig
.
Burst
=
400
return
kubernetes
.
NewForConfig
(
clientConfig
)
}
staging/src/k8s.io/apiserver/pkg/server/options/recommended.go
View file @
496b6f67
...
@@ -32,7 +32,6 @@ type RecommendedOptions struct {
...
@@ -32,7 +32,6 @@ type RecommendedOptions struct {
Etcd
*
EtcdOptions
Etcd
*
EtcdOptions
SecureServing
*
SecureServingOptionsWithLoopback
SecureServing
*
SecureServingOptionsWithLoopback
Authentication
*
DelegatingAuthenticationOptions
Authentication
*
DelegatingAuthenticationOptions
Authorization
*
DelegatingAuthorizationOptions
Audit
*
AuditOptions
Audit
*
AuditOptions
Features
*
FeatureOptions
Features
*
FeatureOptions
CoreAPI
*
CoreAPIOptions
CoreAPI
*
CoreAPIOptions
...
@@ -56,7 +55,6 @@ func NewRecommendedOptions(prefix string, codec runtime.Codec) *RecommendedOptio
...
@@ -56,7 +55,6 @@ func NewRecommendedOptions(prefix string, codec runtime.Codec) *RecommendedOptio
Etcd
:
NewEtcdOptions
(
storagebackend
.
NewDefaultConfig
(
prefix
,
codec
)),
Etcd
:
NewEtcdOptions
(
storagebackend
.
NewDefaultConfig
(
prefix
,
codec
)),
SecureServing
:
sso
.
WithLoopback
(),
SecureServing
:
sso
.
WithLoopback
(),
Authentication
:
NewDelegatingAuthenticationOptions
(),
Authentication
:
NewDelegatingAuthenticationOptions
(),
Authorization
:
NewDelegatingAuthorizationOptions
(),
Audit
:
NewAuditOptions
(),
Audit
:
NewAuditOptions
(),
Features
:
NewFeatureOptions
(),
Features
:
NewFeatureOptions
(),
CoreAPI
:
NewCoreAPIOptions
(),
CoreAPI
:
NewCoreAPIOptions
(),
...
@@ -69,7 +67,6 @@ func (o *RecommendedOptions) AddFlags(fs *pflag.FlagSet) {
...
@@ -69,7 +67,6 @@ func (o *RecommendedOptions) AddFlags(fs *pflag.FlagSet) {
o
.
Etcd
.
AddFlags
(
fs
)
o
.
Etcd
.
AddFlags
(
fs
)
o
.
SecureServing
.
AddFlags
(
fs
)
o
.
SecureServing
.
AddFlags
(
fs
)
o
.
Authentication
.
AddFlags
(
fs
)
o
.
Authentication
.
AddFlags
(
fs
)
o
.
Authorization
.
AddFlags
(
fs
)
o
.
Audit
.
AddFlags
(
fs
)
o
.
Audit
.
AddFlags
(
fs
)
o
.
Features
.
AddFlags
(
fs
)
o
.
Features
.
AddFlags
(
fs
)
o
.
CoreAPI
.
AddFlags
(
fs
)
o
.
CoreAPI
.
AddFlags
(
fs
)
...
@@ -89,9 +86,6 @@ func (o *RecommendedOptions) ApplyTo(config *server.RecommendedConfig, scheme *r
...
@@ -89,9 +86,6 @@ func (o *RecommendedOptions) ApplyTo(config *server.RecommendedConfig, scheme *r
if
err
:=
o
.
Authentication
.
ApplyTo
(
&
config
.
Config
.
Authentication
,
config
.
SecureServing
);
err
!=
nil
{
if
err
:=
o
.
Authentication
.
ApplyTo
(
&
config
.
Config
.
Authentication
,
config
.
SecureServing
);
err
!=
nil
{
return
err
return
err
}
}
if
err
:=
o
.
Authorization
.
ApplyTo
(
&
config
.
Config
.
Authorization
);
err
!=
nil
{
return
err
}
if
err
:=
o
.
Audit
.
ApplyTo
(
&
config
.
Config
);
err
!=
nil
{
if
err
:=
o
.
Audit
.
ApplyTo
(
&
config
.
Config
);
err
!=
nil
{
return
err
return
err
}
}
...
@@ -115,7 +109,6 @@ func (o *RecommendedOptions) Validate() []error {
...
@@ -115,7 +109,6 @@ func (o *RecommendedOptions) Validate() []error {
errors
=
append
(
errors
,
o
.
Etcd
.
Validate
()
...
)
errors
=
append
(
errors
,
o
.
Etcd
.
Validate
()
...
)
errors
=
append
(
errors
,
o
.
SecureServing
.
Validate
()
...
)
errors
=
append
(
errors
,
o
.
SecureServing
.
Validate
()
...
)
errors
=
append
(
errors
,
o
.
Authentication
.
Validate
()
...
)
errors
=
append
(
errors
,
o
.
Authentication
.
Validate
()
...
)
errors
=
append
(
errors
,
o
.
Authorization
.
Validate
()
...
)
errors
=
append
(
errors
,
o
.
Audit
.
Validate
()
...
)
errors
=
append
(
errors
,
o
.
Audit
.
Validate
()
...
)
errors
=
append
(
errors
,
o
.
Features
.
Validate
()
...
)
errors
=
append
(
errors
,
o
.
Features
.
Validate
()
...
)
errors
=
append
(
errors
,
o
.
CoreAPI
.
Validate
()
...
)
errors
=
append
(
errors
,
o
.
CoreAPI
.
Validate
()
...
)
...
...
staging/src/k8s.io/apiserver/plugin/pkg/authorizer/webhook/BUILD
deleted
100644 → 0
View file @
20555c30
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_test(
name = "go_default_test",
srcs = [
"certs_test.go",
"webhook_test.go",
],
embed = [":go_default_library"],
deps = [
"//staging/src/k8s.io/api/authorization/v1beta1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/diff:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/authentication/user:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/authorization/authorizer:go_default_library",
"//staging/src/k8s.io/client-go/tools/clientcmd/api/v1:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = ["webhook.go"],
importmap = "k8s.io/kubernetes/vendor/k8s.io/apiserver/plugin/pkg/authorizer/webhook",
importpath = "k8s.io/apiserver/plugin/pkg/authorizer/webhook",
deps = [
"//staging/src/k8s.io/api/authorization/v1beta1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/cache:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/authentication/user:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/authorization/authorizer:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/util/webhook:go_default_library",
"//staging/src/k8s.io/client-go/kubernetes/scheme:go_default_library",
"//staging/src/k8s.io/client-go/kubernetes/typed/authorization/v1beta1:go_default_library",
"//vendor/github.com/golang/glog:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
)
staging/src/k8s.io/apiserver/plugin/pkg/authorizer/webhook/certs_test.go
deleted
100644 → 0
View file @
20555c30
/*
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.
*/
// This file was generated using openssl by the gencerts.sh script
// and holds raw certificates for the webhook tests.
package
webhook
var
caKey
=
[]
byte
(
`-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEA6IVXGPX5yP2Q6TAlQXIQsavzSqZ973iZvpQBGTI6M98gTSVm
eBYE3o7S8e6WTI3DCnWwqc8Md1rT92FtaQLwv+uMNXijLio5RVBqjUEbunD5In/+
T/y5sE9P3CzcWy6CEhIvORAZj6UlvgZzbRwI91+EVFR5jd8JU0e/L9Ds1jLZFyQw
Kc1ADo+Tj9O4l0WtpRlrhzTgoor4C3fAQZm0mq+llTnxCmw+lhy8t88bPG1cMwdd
DtUTbpetc++2JZ62Q3F1nqcX1EcHDidR0x3j+3357BLkXRK4MQsWLYLzeZ3X1ghW
XT062H866PcIV+MX4H58spMN5cVYk5YTneGihQIDAQABAoIBAHU7FQieq4ssXK1U
+tOeQNBzUzxl6MSd11YApPUhH7sbWdvLaXhOEbJr6+rSUbDTIGzbnXBf1XcvsgLd
eh4hv2PjzFMBObSC0VEjFDWXh/VeFB3SzlNhpfVAZ5EohQjrz+RwiqKIfXqw1vCR
rAxswBCIdd1WodpngvocCEaBXYc4MblaPhJDVtxQe8ndEakkSDlX9Z3qIaIGyXRa
NvY/yURVuXhwDDd7C2QBT6CXGWhldAg7xrRVTcIoqAUfZCgfis0H8cQOa1cGNsbW
t/oHm1fYTxMKFPhWQG0oimx+XJ07BeGgraDRLnxxNnGWTg/W33bc0ZCxCVT0Q5p9
kMMfQUECgYEA9cewTK4ZRKC4bTdwqLTh3cyMkbyN4kBHmB1mS2FV/T0l4oZThM//
OZ6KFnRCuvfuJIOa70s2bqUYky8NTQAidnnbTW2nZ/E5JdeIBs1fAfadAqiPdmkf
MhvjBF/XfLnbCuXx3jA7GmNCpunJysuLtQzwlQlZLojN231uS+3LFbkCgYEA8jCC
MgKYaDWssQbT7zfk5MxyZIH3F9N8K2RBIDSVuMo/E1LCIJ06/k+4jdv8nAWYJXcN
eyLG7l0SXqrpMBSc9+ZTJgmbo0Mw+npvJHbJvAtD/XOSPjlIqkzPAUrxuiBYxa5S
IfKZibygXKAbQMEwY7I4sTbBtIyiQmo9csxt2S0CgYEAiBi1VSCquUfOGBw09BaF
Y85aoHCqmHhDrMXK2T7i4MG1csQzBz4t8/gIOvrR4LpdUjbV2l/pmkctXoMVeGf0
rWo4t51ar8HxhTTeC/Y4/9tRgiFYn5cCQTsT8F4p8tTvqA9AaWqHr8r7I3Yd2X/w
sqahqcVtbskuRLYmF0FrzXECgYAeiR0xPwCGSxYt78Vy6OI0Ms7Ne1FzMJf8RJSt
gdPKy70uK4YMZKaWf+iuAimUZmQrfRo3B0h7r0JsqzHhfQfZfbHIHvf/mq4nNp6i
w1NmISl+YD71F3Xg+vQynodhx0hKDFOQsizHn/+8DffBr1nxh/v75AKCSCUBKLH8
sme7NQKBgDHQac2TmDSelE2uXTGxEVDQs/EpdJh7oCTLQ99Xud/DsaCOrt2s7aRX
1FEohsCaUnqwS07/iH2o6Qb/qOteufB9I7FG85nAvqmP5dI4crGNNa8Rl6fXJaR8
TUwpZmylTKEJ9zLt2PADglyDrQ2D+1WNzh966Oo9c+kZt4WJM0aF
-----END RSA PRIVATE KEY-----`
)
var
caCert
=
[]
byte
(
`-----BEGIN CERTIFICATE-----
MIIDCzCCAfOgAwIBAgIJAKK9m2Cfg5uhMA0GCSqGSIb3DQEBCwUAMBsxGTAXBgNV
BAMMEHdlYmhvb2tfYXV0aHpfY2EwIBcNMTYwMjE2MjM0NDI4WhgPMjI4OTEyMDEy
MzQ0MjhaMBsxGTAXBgNVBAMMEHdlYmhvb2tfYXV0aHpfY2EwggEiMA0GCSqGSIb3
DQEBAQUAA4IBDwAwggEKAoIBAQDohVcY9fnI/ZDpMCVBchCxq/NKpn3veJm+lAEZ
Mjoz3yBNJWZ4FgTejtLx7pZMjcMKdbCpzwx3WtP3YW1pAvC/64w1eKMuKjlFUGqN
QRu6cPkif/5P/LmwT0/cLNxbLoISEi85EBmPpSW+BnNtHAj3X4RUVHmN3wlTR78v
0OzWMtkXJDApzUAOj5OP07iXRa2lGWuHNOCiivgLd8BBmbSar6WVOfEKbD6WHLy3
zxs8bVwzB10O1RNul61z77YlnrZDcXWepxfURwcOJ1HTHeP7ffnsEuRdErgxCxYt
gvN5ndfWCFZdPTrYfzro9whX4xfgfnyykw3lxViTlhOd4aKFAgMBAAGjUDBOMB0G
A1UdDgQWBBSumZL6MMwmFGyhQAwl/v0lYDzdZjAfBgNVHSMEGDAWgBSumZL6MMwm
FGyhQAwl/v0lYDzdZjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAG
6k+bZxKYq4PVZHWTKA7RSjv95FMMr4RSFwKn/n8TUD44ANWYqDrEfVmxAMn3NVK9
ckA8mIRym4IGiWD9eBGgPNNtbAq8Wl/9+5qbDMerpXuRnG3wNY7RU75Rl008m52r
c2i86ZPUi2fAJZyMf5StWE21oKiDYYQqlB6xxsIj6OHhf7536vEysoztNX5FpS2n
q8wG0EhJVhG+Qyww8IlZA5Cjoh71Eqkcwb4cuLjPypxmLm0ywZ/6KgzV+IF+CT2v
TJIpMokDUKlRi9cWSqkWXFE6xbCmhrrwKYsi0X6Vvi7a0pmOnSzKCQl8jN8u4A9R
xar2YeJ6mCCzSAPM69DP
-----END CERTIFICATE-----`
)
var
badCAKey
=
[]
byte
(
`-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEAon7dRV4Br10dLcf8zgs/hOHouELveFr8tuWVIFivxSdnac2k
6dM4iQ2uYS9nTXxNhyJJ/TX/MHEYc4gSXoqUbtx9jE3VA4mCKDhO7cJtCYxq0QV/
PlQCiAPjn5nUMt9ACdii7/uTFDl46bK9K6ajvKHfHoWeYaJsF54kxBq5IMj+QaB2
nc+pba00bGG09sYcHyD37QH+ugx64x+21xMYj2LB/uPoqZM0kj1GHPxAs8GqFq2P
gwkv589AlHqt2iMCTAqED2jcg4FeS2r1DeYHwGyGAPfWTdA8RZ+gZ/P0Gj91T+4B
9srR7BybUFjf1KxEcvPXBvP5r8OwOiYjS8hx/wIDAQABAoIBAQCVBQ9bfDjDX/tQ
buVS+FHKRXss8IW4tIiqGqXGQk7/2YEnMKaaoVBpsBhJnDV6hBJ9aV69TnW3MSCh
YxqlhSVW/fJNZ1uAoOyygeEwfmuMpC+ZfRcSS+z+W8K2LVbDSKXr4babqvVZSNOw
TnDZxTrH1RNPZG65T0Ed77P7/B3nB7aeB2UMuHMQNZ3KrYDTck2R2uTGp+29TplN
blS4VAg2/9KqFr7jkS3/C4jjxVd7d9mm0VdAvLcvENVXqSTYV8xDp+VLTnmtXi5f
LXcopS+zKtKqT7MM7RA2sKrmSfrQBIXW2E1kfDFtpZHajhDutdYkSTH665W1G23M
dIgy3ajhAoGBANE4AhMUVfQqXUCU0UjUDxiOy/8XcKiW/dKhRR1DOQY24J/k+UWv
PEGVcBW4tgalYkTl/AW6hsNfubZaJuw05cHIKdL3df6ug7BUiJpmIv3sjrvPRYvA
WY1UTb3EJrswGz8S2l5+2S3WFTCfK7S6N6Stfi1x6rMJBuOss7HGqdh3AoGBAMbU
WavRqGRsvJFfE5bahXbFpkGWT++BTMP+lzK31z24JjmJdwO+ABWU4/xaXayA4skH
PrzlYUcGJWIedb6W4dvz0sA59yflQzYmREkQPE+wbyor003y7mB8LpFiCnfaFhRn
hoowkyIY+xM4UeDXWWt3DhBElgfA8fYZdiNJEhy5AoGBAMwYUw3BvMffu/CQPElL
dR6DzsUeXKxZ/2pGIGIXfb1uM1pHyFQOSj3ARgMqmYeKNn73zA7akzRsYYJeF7I9
OBT96q7+8IBuRdDx5gCYunHzHppf7HwUPEf+gYgpnY7lsu6ouZWNMNfiC/HOlJhN
QJLJHFnA0y+sEqhvhSxbnLypAoGBALHCZ+kVKFegX3YYaosUEv589obsu8qE7vzL
QKI3elfTq1kFbUILPEgPNUUIBXeUQy03LP/0k2PMOt/eG6apfoQHGQSCzlT8w3pF
/AbWXRVhyAEL7X5jEntwirGv1WwRrmvPopkplGGHs/EbCRjbbzaE2i3xI7EK70f2
u4gQbAEBAoGAVR4u8g5Tx2Gunzh7tfJJ5e3xGBGS3Yq+JqUVNI6t6KIAPh0rM+aD
9tDgcwn8Vn5YU7YkqA2T8OOFsbJfrfZ7y7+oeMFukuIyxgmy9n/V/tCIrV/lR7A5
3iYhanTUbQswx19pSRgsXi7fo9Fi/dmUwyHi18uz5FdLyCTsMbf3uA8=
-----END RSA PRIVATE KEY-----`
)
var
badCACert
=
[]
byte
(
`-----BEGIN CERTIFICATE-----
MIIDCzCCAfOgAwIBAgIJAPqJyUfmRxGLMA0GCSqGSIb3DQEBCwUAMBsxGTAXBgNV
BAMMEHdlYmhvb2tfYXV0aHpfY2EwIBcNMTYwMjE2MjM0NDI4WhgPMjI4OTEyMDEy
MzQ0MjhaMBsxGTAXBgNVBAMMEHdlYmhvb2tfYXV0aHpfY2EwggEiMA0GCSqGSIb3
DQEBAQUAA4IBDwAwggEKAoIBAQCift1FXgGvXR0tx/zOCz+E4ei4Qu94Wvy25ZUg
WK/FJ2dpzaTp0ziJDa5hL2dNfE2HIkn9Nf8wcRhziBJeipRu3H2MTdUDiYIoOE7t
wm0JjGrRBX8+VAKIA+OfmdQy30AJ2KLv+5MUOXjpsr0rpqO8od8ehZ5homwXniTE
GrkgyP5BoHadz6ltrTRsYbT2xhwfIPftAf66DHrjH7bXExiPYsH+4+ipkzSSPUYc
/ECzwaoWrY+DCS/nz0CUeq3aIwJMCoQPaNyDgV5LavUN5gfAbIYA99ZN0DxFn6Bn
8/QaP3VP7gH2ytHsHJtQWN/UrERy89cG8/mvw7A6JiNLyHH/AgMBAAGjUDBOMB0G
A1UdDgQWBBS6IGeGHZCylibt0GzY0dP6C0J9VjAfBgNVHSMEGDAWgBS6IGeGHZCy
libt0GzY0dP6C0J9VjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAi
A1dp75kbePFZsUNjxN6B/Pv0vSoaOjQkc4hpxKbI4VRCuPGmMRFYTlKCzoZ53OqQ
2Jmu1Zbzel/bV5vXrW0BOfUpfWYzd/usIJEuTgU8ijBIB+IHAXYwwxeKRcz3C+7+
9RBMF7gSg9pU2hrSvjhh7Q96IMJ42Z7tI3WD8SZaQLjY1NW1jrQVsg66ktdMke7x
zC8oIRIBH4W6l5s7jtZx1k305NE04pigcFLxCxOmicKd66ysI5hAZkD7y0dgwgtL
IqCQy6t7uJDydRiNRfPFr9Eg7uOu83JGw11f3bGVhJVCbzHyKddvkQsQbdaMHRgZ
zgmWLORg+ls1H1oaJiNW
-----END CERTIFICATE-----`
)
var
serverKey
=
[]
byte
(
`-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAtegsP499au5ZxlwM26rk3TnRgakchQi/9bhfMr0LaEKng1lR
XopzzGuGeZQswzbx7iiH89JzFkurZoEmZwtS4Aybit92VOSv0EUnyx7WR3V21ObZ
iQO0rr0UmG84NjdzATkqF+R5Z+HN9shwgBI4PR1j/ybCt7jNz+OM/VmqsgzoKLoa
bGrx7LCTPk8y5G8AoPOrIAP+9WHJsKQSRT8Lru4lYqseBxvhjqo8NRqzZLg79ldY
aKFqa2N2zr5qp94sG3/zihNDxjZvyyn9c8qvPBL0xOyayvOJG8eZUmjQpUMv7Jk3
qFmdMgGaDJRw0Qg6+/Zt6MHNs6Rbb8hmwuMSpwIDAQABAoIBAQCjzeFijwzKKL4w
0B1IBhi3WeReFPG4nkt1ssQPBYrrJPKBZgHO13A1STI78wFn/OdYpajfF8hI8HT1
BiGVsu27Eb9TC60b/x6OtmeCEk+044LRbtu+9NZUb7HHHogI0l++X0KXZ0coE38L
1izwNvfrmLa+QaIgHMtAg9EnJwJ993n4L31GovWh8MGmVyJX/F92y+agNwWkNYYp
iLWFyon+HbNVL13WOOYnYEdA8Me3+Gucy1EOfWMF7mgmuO2vcfnxXd6b16VjAwtE
jGCQfzgpWGHLpgwoBgDmnPUbdNPUT3MbA9jqG2mlnBSBQveYgKrmFdDYnAjnCM4L
uF2ztBzhAoGBAOYc3sF3YjpIIMsyH9omqtfOuxO+oZkpb2vB9kgdXCDcG870M+BC
bNzV7DCSV8QAUqjKQK1r3gq62UZMLXZbG8x5UnM8/EK0X1CSqygwSWjGpYxIQEhh
O2lq69WipkNDnX1ZmrvEdHD2cxqkkXZ7bdRKRasrFJgvJa3XbiJ18KYxAoGBAMpe
/72EcX9oL3KT8tJSpvasrw17p/XkMMCxTp3IDb3krF/4k5bYF61F68/LNSy3xkos
ZrPUK/U160iuHSYCpMq4pPmlWgKq4hmUMOt+8Yy622zDlugarq9VLqvSdGHm+r6F
5fHilXB0UsTXXOuLZWLcSQ0MBgiaVCLb2AmXZhhXAoGAEjSchw/r7JKCTbE0hezj
PVm0wVYmsNhvYUYiNwhjnpHrfU8iv45h0IL4QcuCOBaSc5o0zcOn+I9Z207xldiV
dXLvzAA6MQjWNai08+QGGs0EkfmxZEiVC70S1X8dylqSHjW1oT9kuv80khoNDCOt
x8rsgiNRaMzqHTvbEczk8jECgYB2Od+wSULBSw2FI5fVdcHjFGlEODycs44j1LH4
DZqxmHl3q9IVavMSIGouQCo1kLuAM8ZgQpDXtYNaN5YB0cOSRyLiUc5vBoQGq4OU
4Nme/L8aIH315TiuZ9ZXPSEO3REZ40G9+UCSrPJ52tOHLC2z/ruSqraPqhGDN+pT
WCamCwKBgEPa+kVrPs0khQH8+sbFbU9ifj4fhPAiSwj2fKuXFro2mE205vAMHye/
SYs/mPzYzKSd7F+7Zk6oVrgFVskTiReW3phF+cIl+CdcnIenF0jW1PVgGw8znu+P
SbHSdqV+tB7AW2J7sH8TZtfMUPAK2MJ4S+1uaHK86K79ym4Rz0E2
-----END RSA PRIVATE KEY-----`
)
var
serverCert
=
[]
byte
(
`-----BEGIN CERTIFICATE-----
MIIC/zCCAeegAwIBAgIJAN7rkfhaX8FZMA0GCSqGSIb3DQEBCwUAMBsxGTAXBgNV
BAMMEHdlYmhvb2tfYXV0aHpfY2EwIBcNMTYwMjE2MjM0NDI4WhgPMjI4OTEyMDEy
MzQ0MjhaMB8xHTAbBgNVBAMMFHdlYmhvb2tfYXV0aHpfc2VydmVyMIIBIjANBgkq
hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtegsP499au5ZxlwM26rk3TnRgakchQi/
9bhfMr0LaEKng1lRXopzzGuGeZQswzbx7iiH89JzFkurZoEmZwtS4Aybit92VOSv
0EUnyx7WR3V21ObZiQO0rr0UmG84NjdzATkqF+R5Z+HN9shwgBI4PR1j/ybCt7jN
z+OM/VmqsgzoKLoabGrx7LCTPk8y5G8AoPOrIAP+9WHJsKQSRT8Lru4lYqseBxvh
jqo8NRqzZLg79ldYaKFqa2N2zr5qp94sG3/zihNDxjZvyyn9c8qvPBL0xOyayvOJ
G8eZUmjQpUMv7Jk3qFmdMgGaDJRw0Qg6+/Zt6MHNs6Rbb8hmwuMSpwIDAQABo0Aw
PjAJBgNVHRMEAjAAMAsGA1UdDwQEAwIF4DATBgNVHSUEDDAKBggrBgEFBQcDATAP
BgNVHREECDAGhwR/AAABMA0GCSqGSIb3DQEBCwUAA4IBAQCZHB9UCl2CfylWP3db
xUamawnRoTYlsOcUh4f2tlHMY+vYiEStN+LECk62YpeaHl/nz/lk7g1Jx9aua39z
wFIHiXYhwSWOtgmzpbxYLye1yajKXbbA1T7mEZJTjewDB9i1LcB9W3EV5VJ8Y1GY
AYKuKQ4Cb1HrqLsrw/1PDm0VouWzf2ESv8CBvAv/pYLVfwgS6WsUqn9wycpLEnqQ
RK66/AoiOaxUIjEP0O1q6pi6Mag7XAfeNtx8J0VGt4cRG4rvWCbKVUyvKfUCkipN
gJu09S+KIz3x1CJLRuJX9tB+cFnnykDLQ2IKg7x44O83ikNk8+Di3iT/awCguWPE
rHh5
-----END CERTIFICATE-----`
)
var
clientKey
=
[]
byte
(
`-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEA5ij4WXWGvbmfAYhEafKRvLEHSkUCYIDjwQAlnHoLf/lz+Fh2
DEv4lcBaycwk3+LVUGKgYOg91txYJvGD3HcmVThXZvcgJd4V9Ll3aY/6xVRCenWi
UNgVQVQITGkMn09ZkSXbZCK4wqz9oTVh0Ti5a7apOS2V07yL0q7vw003v5TBqzC/
FgRwE0bv1rKYYQ80WbDlYkkYGf216zQTwS4g/nShCZAX9eqSfbBg6B/A3OwpbIfx
09BWuwWhp5QnS4w002gGWavRFNzu8pUHUv6zMN8OKpasv+Na+ZB+gMt4+e2Y7qNz
76QL23eGwc6oWn8lQBtkDLmLIa6jbWX067U76QIDAQABAoIBAQCJpGzJSzC2W8DM
sMqBNdCUMKZ0cwq13b7W2BimGJKyCOOi3HxUZEaYf/2Leyt+PPBm72SML7dzvDh3
qa269gKVqmkSqa2vF763qQbRuYo14msTQzA7+s3TUMbZs2UaDOE6nZIzs1QdEElp
1DvYXHz+/rD7Adj9VF+mMnouqQoy5kgJTnVZ8sOyl/9R6F67xKBIvcrtPfqVZzuG
2hGAMUnawxFUajQC7BynIeCWrk79SUmQgilyNgRdY6+rGh2uRupIxuiAukPtuag1
Li+wnNl1UGECtv9ZnnboKvg2334k5vhYScGRJbwbr7Zt3ZaNd0Z/DE9kTtnhBS7v
9qWdc7CBAoGBAPR4hz1fhHFiPmMEAGuiNms6WdyIfyonIRYas8ZDKUQGdxn/aO8a
CURktHRlm6iYT+j1cbf3RnLEN9pNr3V2EySOMc+rXUNifcP7Vl53akAQmISUfQWG
UfwaNLicbavf6m9UCiwWByAZghqDZSLiwmLHIjGcSJQiFuhZryioDydxAoGBAPED
q1Z7oNhzwRYie9OB5ylnrCH8G3yFl8egBmQrPJKIQHA9mAGg01LEJwQNoWewyAWx
jfeFtWvIgZkj49cluZgHYyF81jApaNraxtXAgIwC1n7oAIttmeklZ/V1HntknG3Y
ow2bV/NA3aPOTPYxW8oDv7U9lvwve7kIFxeWjE/5AoGASfXI3G1wUSkqvKPySJ3b
ntcZZpm49xS9csWDS+D3tAfMsoXNxkB3O0TIP0qaLAhgbJcM314k5wWr7BSCl6Ow
KOgH887hOUirycXZHF0+PMGIktulcy1u0jlPZ+aTW2MztpiTN0E2yKRO8xx7VXGK
431hP+cLIh2qFoNDdaZaZ1ECgYEArw++PWQxMefqgVxs2vXJZY7TPiA0Ct+ynqKC
4fFx3vGu9JgYuF4MAVtPB6eq7HlA4LnWZ8ssOuz6DbU/AoB5bY84FxPpNDRv4D/3
Gz3nYUuSZ72234+tsuaju2vlxzUOVs97qB+E48Di/N+VkWHKzVKpxkjFScpnsL/K
niyRIGkCgYEAriuxbOCczL/j6u2Xq1ngEsGg+RXjtOYGoJWo7B8qlVL4nF8w1Nbd
FxEmOChQgUnBdwb93qHCSq0Fidf7OfewrfJJkstWIh3zPS4umLZo7R3YblncpdfT
M197uckIWccZml2jF/c7nvK+MjwDRhkOl2a6HzMxcdBwYUJmSwmIZ4k=
-----END RSA PRIVATE KEY-----`
)
var
clientCert
=
[]
byte
(
`-----BEGIN CERTIFICATE-----
MIIC7jCCAdagAwIBAgIJAN7rkfhaX8FaMA0GCSqGSIb3DQEBCwUAMBsxGTAXBgNV
BAMMEHdlYmhvb2tfYXV0aHpfY2EwIBcNMTYwMjE2MjM0NDI4WhgPMjI4OTEyMDEy
MzQ0MjhaMB8xHTAbBgNVBAMMFHdlYmhvb2tfYXV0aHpfY2xpZW50MIIBIjANBgkq
hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5ij4WXWGvbmfAYhEafKRvLEHSkUCYIDj
wQAlnHoLf/lz+Fh2DEv4lcBaycwk3+LVUGKgYOg91txYJvGD3HcmVThXZvcgJd4V
9Ll3aY/6xVRCenWiUNgVQVQITGkMn09ZkSXbZCK4wqz9oTVh0Ti5a7apOS2V07yL
0q7vw003v5TBqzC/FgRwE0bv1rKYYQ80WbDlYkkYGf216zQTwS4g/nShCZAX9eqS
fbBg6B/A3OwpbIfx09BWuwWhp5QnS4w002gGWavRFNzu8pUHUv6zMN8OKpasv+Na
+ZB+gMt4+e2Y7qNz76QL23eGwc6oWn8lQBtkDLmLIa6jbWX067U76QIDAQABoy8w
LTAJBgNVHRMEAjAAMAsGA1UdDwQEAwIF4DATBgNVHSUEDDAKBggrBgEFBQcDAjAN
BgkqhkiG9w0BAQsFAAOCAQEA2IZNhkVrSTAIeP2N2WzOHqbFbGyO+NA8G9Hb5fiX
e1YS2Ku3ERYNr+HLxNHCsXiSUKjjBmXMc4z0XaHJznEKEbotZftjTlTQlHi3/5vm
dIG18pmO/E5ebVXl6pU96v/hBd8N5rWp9WUKgP0y59r/JA+oNpmd10A+RyaOyrFK
rBm8Z8rvDYMrXSpOwx9BNDuhqzbdG8MYw5vO55Er3hwTXoapsMqSh5s9+OFFpUJi
2uEoQlwWiYRtQj6g4wgr4woDEbv8XxsHqGfs+GSnmRsB69xRI24lEtC+nS6Rz3Sh
YWeN0gD8PsQC1KJVv6xCGo1yXSEwytRMB23XYtAZahLdLg==
-----END CERTIFICATE-----`
)
staging/src/k8s.io/apiserver/plugin/pkg/authorizer/webhook/gencerts.sh
deleted
100755 → 0
View file @
20555c30
#!/usr/bin/env bash
# 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.
set
-e
# gencerts.sh generates the certificates for the webhook authz plugin tests.
#
# It is not expected to be run often (there is no go generate rule), and mainly
# exists for documentation purposes.
cat
>
server.conf
<<
EOF
[req]
req_extensions = v3_req
distinguished_name = req_distinguished_name
[req_distinguished_name]
[ v3_req ]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names
[alt_names]
IP.1 = 127.0.0.1
EOF
cat
>
client.conf
<<
EOF
[req]
req_extensions = v3_req
distinguished_name = req_distinguished_name
[req_distinguished_name]
[ v3_req ]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = clientAuth
EOF
# Create a certificate authority
openssl genrsa
-out
caKey.pem 2048
openssl req
-x509
-new
-nodes
-key
caKey.pem
-days
100000
-out
caCert.pem
-subj
"/CN=webhook_authz_ca"
# Create a second certificate authority
openssl genrsa
-out
badCAKey.pem 2048
openssl req
-x509
-new
-nodes
-key
badCAKey.pem
-days
100000
-out
badCACert.pem
-subj
"/CN=webhook_authz_ca"
# Create a server certiticate
openssl genrsa
-out
serverKey.pem 2048
openssl req
-new
-key
serverKey.pem
-out
server.csr
-subj
"/CN=webhook_authz_server"
-config
server.conf
openssl x509
-req
-in
server.csr
-CA
caCert.pem
-CAkey
caKey.pem
-CAcreateserial
-out
serverCert.pem
-days
100000
-extensions
v3_req
-extfile
server.conf
# Create a client certiticate
openssl genrsa
-out
clientKey.pem 2048
openssl req
-new
-key
clientKey.pem
-out
client.csr
-subj
"/CN=webhook_authz_client"
-config
client.conf
openssl x509
-req
-in
client.csr
-CA
caCert.pem
-CAkey
caKey.pem
-CAcreateserial
-out
clientCert.pem
-days
100000
-extensions
v3_req
-extfile
client.conf
outfile
=
certs_test.go
cat
>
$outfile
<<
EOF
/*
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.
*/
EOF
echo
"// This file was generated using openssl by the gencerts.sh script"
>>
$outfile
echo
"// and holds raw certificates for the webhook tests."
>>
$outfile
echo
""
>>
$outfile
echo
"package webhook"
>>
$outfile
for
file
in
caKey caCert badCAKey badCACert serverKey serverCert clientKey clientCert
;
do
data
=
$(
cat
${
file
}
.pem
)
echo
""
>>
$outfile
echo
"var
$file
= []byte(
\`
$data
\`
)"
>>
$outfile
done
# Clean up after we're done.
rm
*
.pem
rm
*
.csr
rm
*
.srl
rm
*
.conf
staging/src/k8s.io/apiserver/plugin/pkg/authorizer/webhook/webhook.go
deleted
100644 → 0
View file @
20555c30
/*
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 webhook implements the authorizer.Authorizer interface using HTTP webhooks.
package
webhook
import
(
"encoding/json"
"fmt"
"time"
"github.com/golang/glog"
authorization
"k8s.io/api/authorization/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/cache"
"k8s.io/apiserver/pkg/authentication/user"
"k8s.io/apiserver/pkg/authorization/authorizer"
"k8s.io/apiserver/pkg/util/webhook"
"k8s.io/client-go/kubernetes/scheme"
authorizationclient
"k8s.io/client-go/kubernetes/typed/authorization/v1"
)
var
(
groupVersions
=
[]
schema
.
GroupVersion
{
authorization
.
SchemeGroupVersion
}
)
const
retryBackoff
=
500
*
time
.
Millisecond
// Ensure Webhook implements the authorizer.Authorizer interface.
var
_
authorizer
.
Authorizer
=
(
*
WebhookAuthorizer
)(
nil
)
type
WebhookAuthorizer
struct
{
subjectAccessReview
authorizationclient
.
SubjectAccessReviewInterface
responseCache
*
cache
.
LRUExpireCache
authorizedTTL
time
.
Duration
unauthorizedTTL
time
.
Duration
initialBackoff
time
.
Duration
decisionOnError
authorizer
.
Decision
}
// NewFromInterface creates a WebhookAuthorizer using the given subjectAccessReview client
func
NewFromInterface
(
subjectAccessReview
authorizationclient
.
SubjectAccessReviewInterface
,
authorizedTTL
,
unauthorizedTTL
time
.
Duration
)
(
*
WebhookAuthorizer
,
error
)
{
return
newWithBackoff
(
subjectAccessReview
,
authorizedTTL
,
unauthorizedTTL
,
retryBackoff
)
}
// New creates a new WebhookAuthorizer from the provided kubeconfig file.
//
// The config's cluster field is used to refer to the remote service, user refers to the returned authorizer.
//
// # clusters refers to the remote service.
// clusters:
// - name: name-of-remote-authz-service
// cluster:
// certificate-authority: /path/to/ca.pem # CA for verifying the remote service.
// server: https://authz.example.com/authorize # URL of remote service to query. Must use 'https'.
//
// # users refers to the API server's webhook configuration.
// users:
// - name: name-of-api-server
// user:
// client-certificate: /path/to/cert.pem # cert for the webhook plugin to use
// client-key: /path/to/key.pem # key matching the cert
//
// For additional HTTP configuration, refer to the kubeconfig documentation
// https://kubernetes.io/docs/user-guide/kubeconfig-file/.
func
New
(
kubeConfigFile
string
,
authorizedTTL
,
unauthorizedTTL
time
.
Duration
)
(
*
WebhookAuthorizer
,
error
)
{
subjectAccessReview
,
err
:=
subjectAccessReviewInterfaceFromKubeconfig
(
kubeConfigFile
)
if
err
!=
nil
{
return
nil
,
err
}
return
newWithBackoff
(
subjectAccessReview
,
authorizedTTL
,
unauthorizedTTL
,
retryBackoff
)
}
// newWithBackoff allows tests to skip the sleep.
func
newWithBackoff
(
subjectAccessReview
authorizationclient
.
SubjectAccessReviewInterface
,
authorizedTTL
,
unauthorizedTTL
,
initialBackoff
time
.
Duration
)
(
*
WebhookAuthorizer
,
error
)
{
return
&
WebhookAuthorizer
{
subjectAccessReview
:
subjectAccessReview
,
responseCache
:
cache
.
NewLRUExpireCache
(
1024
),
authorizedTTL
:
authorizedTTL
,
unauthorizedTTL
:
unauthorizedTTL
,
initialBackoff
:
initialBackoff
,
decisionOnError
:
authorizer
.
DecisionNoOpinion
,
},
nil
}
// Authorize makes a REST request to the remote service describing the attempted action as a JSON
// serialized api.authorization.v1beta1.SubjectAccessReview object. An example request body is
// provided below.
//
// {
// "apiVersion": "authorization.k8s.io/v1beta1",
// "kind": "SubjectAccessReview",
// "spec": {
// "resourceAttributes": {
// "namespace": "kittensandponies",
// "verb": "GET",
// "group": "group3",
// "resource": "pods"
// },
// "user": "jane",
// "group": [
// "group1",
// "group2"
// ]
// }
// }
//
// The remote service is expected to fill the SubjectAccessReviewStatus field to either allow or
// disallow access. A permissive response would return:
//
// {
// "apiVersion": "authorization.k8s.io/v1beta1",
// "kind": "SubjectAccessReview",
// "status": {
// "allowed": true
// }
// }
//
// To disallow access, the remote service would return:
//
// {
// "apiVersion": "authorization.k8s.io/v1beta1",
// "kind": "SubjectAccessReview",
// "status": {
// "allowed": false,
// "reason": "user does not have read access to the namespace"
// }
// }
//
// TODO(mikedanese): We should eventually support failing closed when we
// encounter an error. We are failing open now to preserve backwards compatible
// behavior.
func
(
w
*
WebhookAuthorizer
)
Authorize
(
attr
authorizer
.
Attributes
)
(
decision
authorizer
.
Decision
,
reason
string
,
err
error
)
{
r
:=
&
authorization
.
SubjectAccessReview
{}
if
user
:=
attr
.
GetUser
();
user
!=
nil
{
r
.
Spec
=
authorization
.
SubjectAccessReviewSpec
{
User
:
user
.
GetName
(),
UID
:
user
.
GetUID
(),
Groups
:
user
.
GetGroups
(),
Extra
:
convertToSARExtra
(
user
.
GetExtra
()),
}
}
if
attr
.
IsResourceRequest
()
{
r
.
Spec
.
ResourceAttributes
=
&
authorization
.
ResourceAttributes
{
Namespace
:
attr
.
GetNamespace
(),
Verb
:
attr
.
GetVerb
(),
Group
:
attr
.
GetAPIGroup
(),
Version
:
attr
.
GetAPIVersion
(),
Resource
:
attr
.
GetResource
(),
Subresource
:
attr
.
GetSubresource
(),
Name
:
attr
.
GetName
(),
}
}
else
{
r
.
Spec
.
NonResourceAttributes
=
&
authorization
.
NonResourceAttributes
{
Path
:
attr
.
GetPath
(),
Verb
:
attr
.
GetVerb
(),
}
}
key
,
err
:=
json
.
Marshal
(
r
.
Spec
)
if
err
!=
nil
{
return
w
.
decisionOnError
,
""
,
err
}
if
entry
,
ok
:=
w
.
responseCache
.
Get
(
string
(
key
));
ok
{
r
.
Status
=
entry
.
(
authorization
.
SubjectAccessReviewStatus
)
}
else
{
var
(
result
*
authorization
.
SubjectAccessReview
err
error
)
webhook
.
WithExponentialBackoff
(
w
.
initialBackoff
,
func
()
error
{
result
,
err
=
w
.
subjectAccessReview
.
Create
(
r
)
return
err
})
if
err
!=
nil
{
// An error here indicates bad configuration or an outage. Log for debugging.
glog
.
Errorf
(
"Failed to make webhook authorizer request: %v"
,
err
)
return
w
.
decisionOnError
,
""
,
err
}
r
.
Status
=
result
.
Status
if
r
.
Status
.
Allowed
{
w
.
responseCache
.
Add
(
string
(
key
),
r
.
Status
,
w
.
authorizedTTL
)
}
else
{
w
.
responseCache
.
Add
(
string
(
key
),
r
.
Status
,
w
.
unauthorizedTTL
)
}
}
switch
{
case
r
.
Status
.
Denied
&&
r
.
Status
.
Allowed
:
return
authorizer
.
DecisionDeny
,
r
.
Status
.
Reason
,
fmt
.
Errorf
(
"webhook subject access review returned both allow and deny response"
)
case
r
.
Status
.
Denied
:
return
authorizer
.
DecisionDeny
,
r
.
Status
.
Reason
,
nil
case
r
.
Status
.
Allowed
:
return
authorizer
.
DecisionAllow
,
r
.
Status
.
Reason
,
nil
default
:
return
authorizer
.
DecisionNoOpinion
,
r
.
Status
.
Reason
,
nil
}
}
//TODO: need to finish the method to get the rules when using webhook mode
func
(
w
*
WebhookAuthorizer
)
RulesFor
(
user
user
.
Info
,
namespace
string
)
([]
authorizer
.
ResourceRuleInfo
,
[]
authorizer
.
NonResourceRuleInfo
,
bool
,
error
)
{
var
(
resourceRules
[]
authorizer
.
ResourceRuleInfo
nonResourceRules
[]
authorizer
.
NonResourceRuleInfo
)
incomplete
:=
true
return
resourceRules
,
nonResourceRules
,
incomplete
,
fmt
.
Errorf
(
"webhook authorizer does not support user rule resolution"
)
}
func
convertToSARExtra
(
extra
map
[
string
][]
string
)
map
[
string
]
authorization
.
ExtraValue
{
if
extra
==
nil
{
return
nil
}
ret
:=
map
[
string
]
authorization
.
ExtraValue
{}
for
k
,
v
:=
range
extra
{
ret
[
k
]
=
authorization
.
ExtraValue
(
v
)
}
return
ret
}
// subjectAccessReviewInterfaceFromKubeconfig builds a client from the specified kubeconfig file,
// and returns a SubjectAccessReviewInterface that uses that client. Note that the client submits SubjectAccessReview
// requests to the exact path specified in the kubeconfig file, so arbitrary non-API servers can be targeted.
func
subjectAccessReviewInterfaceFromKubeconfig
(
kubeConfigFile
string
)
(
authorizationclient
.
SubjectAccessReviewInterface
,
error
)
{
localScheme
:=
runtime
.
NewScheme
()
if
err
:=
scheme
.
AddToScheme
(
localScheme
);
err
!=
nil
{
return
nil
,
err
}
if
err
:=
localScheme
.
SetVersionPriority
(
groupVersions
...
);
err
!=
nil
{
return
nil
,
err
}
gw
,
err
:=
webhook
.
NewGenericWebhook
(
localScheme
,
scheme
.
Codecs
,
kubeConfigFile
,
groupVersions
,
0
)
if
err
!=
nil
{
return
nil
,
err
}
return
&
subjectAccessReviewClient
{
gw
},
nil
}
type
subjectAccessReviewClient
struct
{
w
*
webhook
.
GenericWebhook
}
func
(
t
*
subjectAccessReviewClient
)
Create
(
subjectAccessReview
*
authorization
.
SubjectAccessReview
)
(
*
authorization
.
SubjectAccessReview
,
error
)
{
result
:=
&
authorization
.
SubjectAccessReview
{}
err
:=
t
.
w
.
RestClient
.
Post
()
.
Body
(
subjectAccessReview
)
.
Do
()
.
Into
(
result
)
return
result
,
err
}
staging/src/k8s.io/apiserver/plugin/pkg/authorizer/webhook/webhook_test.go
deleted
100644 → 0
View file @
20555c30
/*
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
webhook
import
(
"crypto/tls"
"crypto/x509"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"net/http/httptest"
"net/url"
"os"
"path/filepath"
"reflect"
"testing"
"text/template"
"time"
"k8s.io/api/authorization/v1beta1"
metav1
"k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/diff"
"k8s.io/apiserver/pkg/authentication/user"
"k8s.io/apiserver/pkg/authorization/authorizer"
"k8s.io/client-go/tools/clientcmd/api/v1"
)
func
TestNewFromConfig
(
t
*
testing
.
T
)
{
dir
,
err
:=
ioutil
.
TempDir
(
""
,
""
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
defer
os
.
RemoveAll
(
dir
)
data
:=
struct
{
CA
string
Cert
string
Key
string
}{
CA
:
filepath
.
Join
(
dir
,
"ca.pem"
),
Cert
:
filepath
.
Join
(
dir
,
"clientcert.pem"
),
Key
:
filepath
.
Join
(
dir
,
"clientkey.pem"
),
}
files
:=
[]
struct
{
name
string
data
[]
byte
}{
{
data
.
CA
,
caCert
},
{
data
.
Cert
,
clientCert
},
{
data
.
Key
,
clientKey
},
}
for
_
,
file
:=
range
files
{
if
err
:=
ioutil
.
WriteFile
(
file
.
name
,
file
.
data
,
0400
);
err
!=
nil
{
t
.
Fatal
(
err
)
}
}
tests
:=
[]
struct
{
msg
string
configTmpl
string
wantErr
bool
}{
{
msg
:
"a single cluster and single user"
,
configTmpl
:
`
clusters:
- cluster:
certificate-authority: {{ .CA }}
server: https://authz.example.com
name: foobar
users:
- name: a cluster
user:
client-certificate: {{ .Cert }}
client-key: {{ .Key }}
`
,
wantErr
:
true
,
},
{
msg
:
"multiple clusters with no context"
,
configTmpl
:
`
clusters:
- cluster:
certificate-authority: {{ .CA }}
server: https://authz.example.com
name: foobar
- cluster:
certificate-authority: a bad certificate path
server: https://authz.example.com
name: barfoo
users:
- name: a name
user:
client-certificate: {{ .Cert }}
client-key: {{ .Key }}
`
,
wantErr
:
true
,
},
{
msg
:
"multiple clusters with a context"
,
configTmpl
:
`
clusters:
- cluster:
certificate-authority: a bad certificate path
server: https://authz.example.com
name: foobar
- cluster:
certificate-authority: {{ .CA }}
server: https://authz.example.com
name: barfoo
users:
- name: a name
user:
client-certificate: {{ .Cert }}
client-key: {{ .Key }}
contexts:
- name: default
context:
cluster: barfoo
user: a name
current-context: default
`
,
wantErr
:
false
,
},
{
msg
:
"cluster with bad certificate path specified"
,
configTmpl
:
`
clusters:
- cluster:
certificate-authority: a bad certificate path
server: https://authz.example.com
name: foobar
- cluster:
certificate-authority: {{ .CA }}
server: https://authz.example.com
name: barfoo
users:
- name: a name
user:
client-certificate: {{ .Cert }}
client-key: {{ .Key }}
contexts:
- name: default
context:
cluster: foobar
user: a name
current-context: default
`
,
wantErr
:
true
,
},
}
for
_
,
tt
:=
range
tests
{
// Use a closure so defer statements trigger between loop iterations.
err
:=
func
()
error
{
tempfile
,
err
:=
ioutil
.
TempFile
(
""
,
""
)
if
err
!=
nil
{
return
err
}
p
:=
tempfile
.
Name
()
defer
os
.
Remove
(
p
)
tmpl
,
err
:=
template
.
New
(
"test"
)
.
Parse
(
tt
.
configTmpl
)
if
err
!=
nil
{
return
fmt
.
Errorf
(
"failed to parse test template: %v"
,
err
)
}
if
err
:=
tmpl
.
Execute
(
tempfile
,
data
);
err
!=
nil
{
return
fmt
.
Errorf
(
"failed to execute test template: %v"
,
err
)
}
// Create a new authorizer
sarClient
,
err
:=
subjectAccessReviewInterfaceFromKubeconfig
(
p
)
if
err
!=
nil
{
return
fmt
.
Errorf
(
"error building sar client: %v"
,
err
)
}
_
,
err
=
newWithBackoff
(
sarClient
,
0
,
0
,
0
)
return
err
}()
if
err
!=
nil
&&
!
tt
.
wantErr
{
t
.
Errorf
(
"failed to load plugin from config %q: %v"
,
tt
.
msg
,
err
)
}
if
err
==
nil
&&
tt
.
wantErr
{
t
.
Errorf
(
"wanted an error when loading config, did not get one: %q"
,
tt
.
msg
)
}
}
}
// Service mocks a remote service.
type
Service
interface
{
Review
(
*
v1beta1
.
SubjectAccessReview
)
HTTPStatusCode
()
int
}
// NewTestServer wraps a Service as an httptest.Server.
func
NewTestServer
(
s
Service
,
cert
,
key
,
caCert
[]
byte
)
(
*
httptest
.
Server
,
error
)
{
const
webhookPath
=
"/testserver"
var
tlsConfig
*
tls
.
Config
if
cert
!=
nil
{
cert
,
err
:=
tls
.
X509KeyPair
(
cert
,
key
)
if
err
!=
nil
{
return
nil
,
err
}
tlsConfig
=
&
tls
.
Config
{
Certificates
:
[]
tls
.
Certificate
{
cert
}}
}
if
caCert
!=
nil
{
rootCAs
:=
x509
.
NewCertPool
()
rootCAs
.
AppendCertsFromPEM
(
caCert
)
if
tlsConfig
==
nil
{
tlsConfig
=
&
tls
.
Config
{}
}
tlsConfig
.
ClientCAs
=
rootCAs
tlsConfig
.
ClientAuth
=
tls
.
RequireAndVerifyClientCert
}
serveHTTP
:=
func
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
if
r
.
Method
!=
"POST"
{
http
.
Error
(
w
,
fmt
.
Sprintf
(
"unexpected method: %v"
,
r
.
Method
),
http
.
StatusMethodNotAllowed
)
return
}
if
r
.
URL
.
Path
!=
webhookPath
{
http
.
Error
(
w
,
fmt
.
Sprintf
(
"unexpected path: %v"
,
r
.
URL
.
Path
),
http
.
StatusNotFound
)
return
}
var
review
v1beta1
.
SubjectAccessReview
bodyData
,
_
:=
ioutil
.
ReadAll
(
r
.
Body
)
if
err
:=
json
.
Unmarshal
(
bodyData
,
&
review
);
err
!=
nil
{
http
.
Error
(
w
,
fmt
.
Sprintf
(
"failed to decode body: %v"
,
err
),
http
.
StatusBadRequest
)
return
}
// ensure we received the serialized review as expected
if
review
.
APIVersion
!=
"authorization.k8s.io/v1beta1"
{
http
.
Error
(
w
,
fmt
.
Sprintf
(
"wrong api version: %s"
,
string
(
bodyData
)),
http
.
StatusBadRequest
)
return
}
// once we have a successful request, always call the review to record that we were called
s
.
Review
(
&
review
)
if
s
.
HTTPStatusCode
()
<
200
||
s
.
HTTPStatusCode
()
>=
300
{
http
.
Error
(
w
,
"HTTP Error"
,
s
.
HTTPStatusCode
())
return
}
type
status
struct
{
Allowed
bool
`json:"allowed"`
Reason
string
`json:"reason"`
EvaluationError
string
`json:"evaluationError"`
}
resp
:=
struct
{
APIVersion
string
`json:"apiVersion"`
Status
status
`json:"status"`
}{
APIVersion
:
v1beta1
.
SchemeGroupVersion
.
String
(),
Status
:
status
{
review
.
Status
.
Allowed
,
review
.
Status
.
Reason
,
review
.
Status
.
EvaluationError
},
}
w
.
Header
()
.
Set
(
"Content-Type"
,
"application/json"
)
json
.
NewEncoder
(
w
)
.
Encode
(
resp
)
}
server
:=
httptest
.
NewUnstartedServer
(
http
.
HandlerFunc
(
serveHTTP
))
server
.
TLS
=
tlsConfig
server
.
StartTLS
()
// Adjust the path to point to our custom path
serverURL
,
_
:=
url
.
Parse
(
server
.
URL
)
serverURL
.
Path
=
webhookPath
server
.
URL
=
serverURL
.
String
()
return
server
,
nil
}
// A service that can be set to allow all or deny all authorization requests.
type
mockService
struct
{
allow
bool
statusCode
int
called
int
}
func
(
m
*
mockService
)
Review
(
r
*
v1beta1
.
SubjectAccessReview
)
{
m
.
called
++
r
.
Status
.
Allowed
=
m
.
allow
}
func
(
m
*
mockService
)
Allow
()
{
m
.
allow
=
true
}
func
(
m
*
mockService
)
Deny
()
{
m
.
allow
=
false
}
func
(
m
*
mockService
)
HTTPStatusCode
()
int
{
return
m
.
statusCode
}
// newAuthorizer creates a temporary kubeconfig file from the provided arguments and attempts to load
// a new WebhookAuthorizer from it.
func
newAuthorizer
(
callbackURL
string
,
clientCert
,
clientKey
,
ca
[]
byte
,
cacheTime
time
.
Duration
)
(
*
WebhookAuthorizer
,
error
)
{
tempfile
,
err
:=
ioutil
.
TempFile
(
""
,
""
)
if
err
!=
nil
{
return
nil
,
err
}
p
:=
tempfile
.
Name
()
defer
os
.
Remove
(
p
)
config
:=
v1
.
Config
{
Clusters
:
[]
v1
.
NamedCluster
{
{
Cluster
:
v1
.
Cluster
{
Server
:
callbackURL
,
CertificateAuthorityData
:
ca
},
},
},
AuthInfos
:
[]
v1
.
NamedAuthInfo
{
{
AuthInfo
:
v1
.
AuthInfo
{
ClientCertificateData
:
clientCert
,
ClientKeyData
:
clientKey
},
},
},
}
if
err
:=
json
.
NewEncoder
(
tempfile
)
.
Encode
(
config
);
err
!=
nil
{
return
nil
,
err
}
sarClient
,
err
:=
subjectAccessReviewInterfaceFromKubeconfig
(
p
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"error building sar client: %v"
,
err
)
}
return
newWithBackoff
(
sarClient
,
cacheTime
,
cacheTime
,
0
)
}
func
TestTLSConfig
(
t
*
testing
.
T
)
{
tests
:=
[]
struct
{
test
string
clientCert
,
clientKey
,
clientCA
[]
byte
serverCert
,
serverKey
,
serverCA
[]
byte
wantAuth
,
wantErr
bool
}{
{
test
:
"TLS setup between client and server"
,
clientCert
:
clientCert
,
clientKey
:
clientKey
,
clientCA
:
caCert
,
serverCert
:
serverCert
,
serverKey
:
serverKey
,
serverCA
:
caCert
,
wantAuth
:
true
,
},
{
test
:
"Server does not require client auth"
,
clientCA
:
caCert
,
serverCert
:
serverCert
,
serverKey
:
serverKey
,
wantAuth
:
true
,
},
{
test
:
"Server does not require client auth, client provides it"
,
clientCert
:
clientCert
,
clientKey
:
clientKey
,
clientCA
:
caCert
,
serverCert
:
serverCert
,
serverKey
:
serverKey
,
wantAuth
:
true
,
},
{
test
:
"Client does not trust server"
,
clientCert
:
clientCert
,
clientKey
:
clientKey
,
serverCert
:
serverCert
,
serverKey
:
serverKey
,
wantErr
:
true
,
},
{
test
:
"Server does not trust client"
,
clientCert
:
clientCert
,
clientKey
:
clientKey
,
clientCA
:
caCert
,
serverCert
:
serverCert
,
serverKey
:
serverKey
,
serverCA
:
badCACert
,
wantErr
:
true
,
},
{
// Plugin does not support insecure configurations.
test
:
"Server is using insecure connection"
,
wantErr
:
true
,
},
}
for
_
,
tt
:=
range
tests
{
// Use a closure so defer statements trigger between loop iterations.
func
()
{
service
:=
new
(
mockService
)
service
.
statusCode
=
200
server
,
err
:=
NewTestServer
(
service
,
tt
.
serverCert
,
tt
.
serverKey
,
tt
.
serverCA
)
if
err
!=
nil
{
t
.
Errorf
(
"%s: failed to create server: %v"
,
tt
.
test
,
err
)
return
}
defer
server
.
Close
()
wh
,
err
:=
newAuthorizer
(
server
.
URL
,
tt
.
clientCert
,
tt
.
clientKey
,
tt
.
clientCA
,
0
)
if
err
!=
nil
{
t
.
Errorf
(
"%s: failed to create client: %v"
,
tt
.
test
,
err
)
return
}
attr
:=
authorizer
.
AttributesRecord
{
User
:
&
user
.
DefaultInfo
{}}
// Allow all and see if we get an error.
service
.
Allow
()
decision
,
_
,
err
:=
wh
.
Authorize
(
attr
)
if
tt
.
wantAuth
{
if
decision
!=
authorizer
.
DecisionAllow
{
t
.
Errorf
(
"expected successful authorization"
)
}
}
else
{
if
decision
==
authorizer
.
DecisionAllow
{
t
.
Errorf
(
"expected failed authorization"
)
}
}
if
tt
.
wantErr
{
if
err
==
nil
{
t
.
Errorf
(
"expected error making authorization request: %v"
,
err
)
}
return
}
if
err
!=
nil
{
t
.
Errorf
(
"%s: failed to authorize with AllowAll policy: %v"
,
tt
.
test
,
err
)
return
}
service
.
Deny
()
if
decision
,
_
,
_
:=
wh
.
Authorize
(
attr
);
decision
==
authorizer
.
DecisionAllow
{
t
.
Errorf
(
"%s: incorrectly authorized with DenyAll policy"
,
tt
.
test
)
}
}()
}
}
// recorderService records all access review requests.
type
recorderService
struct
{
last
v1beta1
.
SubjectAccessReview
err
error
}
func
(
rec
*
recorderService
)
Review
(
r
*
v1beta1
.
SubjectAccessReview
)
{
rec
.
last
=
v1beta1
.
SubjectAccessReview
{}
rec
.
last
=
*
r
r
.
Status
.
Allowed
=
true
}
func
(
rec
*
recorderService
)
Last
()
(
v1beta1
.
SubjectAccessReview
,
error
)
{
return
rec
.
last
,
rec
.
err
}
func
(
rec
*
recorderService
)
HTTPStatusCode
()
int
{
return
200
}
func
TestWebhook
(
t
*
testing
.
T
)
{
serv
:=
new
(
recorderService
)
s
,
err
:=
NewTestServer
(
serv
,
serverCert
,
serverKey
,
caCert
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
defer
s
.
Close
()
wh
,
err
:=
newAuthorizer
(
s
.
URL
,
clientCert
,
clientKey
,
caCert
,
0
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
expTypeMeta
:=
metav1
.
TypeMeta
{
APIVersion
:
"authorization.k8s.io/v1beta1"
,
Kind
:
"SubjectAccessReview"
,
}
tests
:=
[]
struct
{
attr
authorizer
.
Attributes
want
v1beta1
.
SubjectAccessReview
}{
{
attr
:
authorizer
.
AttributesRecord
{
User
:
&
user
.
DefaultInfo
{}},
want
:
v1beta1
.
SubjectAccessReview
{
TypeMeta
:
expTypeMeta
,
Spec
:
v1beta1
.
SubjectAccessReviewSpec
{
NonResourceAttributes
:
&
v1beta1
.
NonResourceAttributes
{},
},
},
},
{
attr
:
authorizer
.
AttributesRecord
{
User
:
&
user
.
DefaultInfo
{
Name
:
"jane"
}},
want
:
v1beta1
.
SubjectAccessReview
{
TypeMeta
:
expTypeMeta
,
Spec
:
v1beta1
.
SubjectAccessReviewSpec
{
User
:
"jane"
,
NonResourceAttributes
:
&
v1beta1
.
NonResourceAttributes
{},
},
},
},
{
attr
:
authorizer
.
AttributesRecord
{
User
:
&
user
.
DefaultInfo
{
Name
:
"jane"
,
UID
:
"1"
,
Groups
:
[]
string
{
"group1"
,
"group2"
},
},
Verb
:
"GET"
,
Namespace
:
"kittensandponies"
,
APIGroup
:
"group3"
,
APIVersion
:
"v7beta3"
,
Resource
:
"pods"
,
Subresource
:
"proxy"
,
Name
:
"my-pod"
,
ResourceRequest
:
true
,
Path
:
"/foo"
,
},
want
:
v1beta1
.
SubjectAccessReview
{
TypeMeta
:
expTypeMeta
,
Spec
:
v1beta1
.
SubjectAccessReviewSpec
{
User
:
"jane"
,
UID
:
"1"
,
Groups
:
[]
string
{
"group1"
,
"group2"
},
ResourceAttributes
:
&
v1beta1
.
ResourceAttributes
{
Verb
:
"GET"
,
Namespace
:
"kittensandponies"
,
Group
:
"group3"
,
Version
:
"v7beta3"
,
Resource
:
"pods"
,
Subresource
:
"proxy"
,
Name
:
"my-pod"
,
},
},
},
},
}
for
i
,
tt
:=
range
tests
{
decision
,
_
,
err
:=
wh
.
Authorize
(
tt
.
attr
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
if
decision
!=
authorizer
.
DecisionAllow
{
t
.
Errorf
(
"case %d: authorization failed"
,
i
)
continue
}
gotAttr
,
err
:=
serv
.
Last
()
if
err
!=
nil
{
t
.
Errorf
(
"case %d: failed to deserialize webhook request: %v"
,
i
,
err
)
continue
}
if
!
reflect
.
DeepEqual
(
gotAttr
,
tt
.
want
)
{
t
.
Errorf
(
"case %d: got != want:
\n
%s"
,
i
,
diff
.
ObjectGoPrintDiff
(
gotAttr
,
tt
.
want
))
}
}
}
type
webhookCacheTestCase
struct
{
attr
authorizer
.
AttributesRecord
allow
bool
statusCode
int
expectedErr
bool
expectedAuthorized
bool
expectedCalls
int
}
func
testWebhookCacheCases
(
t
*
testing
.
T
,
serv
*
mockService
,
wh
*
WebhookAuthorizer
,
tests
[]
webhookCacheTestCase
)
{
for
i
,
test
:=
range
tests
{
serv
.
called
=
0
serv
.
allow
=
test
.
allow
serv
.
statusCode
=
test
.
statusCode
authorized
,
_
,
err
:=
wh
.
Authorize
(
test
.
attr
)
if
test
.
expectedErr
&&
err
==
nil
{
t
.
Errorf
(
"%d: Expected error"
,
i
)
continue
}
else
if
!
test
.
expectedErr
&&
err
!=
nil
{
t
.
Errorf
(
"%d: unexpected error: %v"
,
i
,
err
)
continue
}
if
test
.
expectedAuthorized
!=
(
authorized
==
authorizer
.
DecisionAllow
)
{
t
.
Errorf
(
"%d: expected authorized=%v, got %v"
,
i
,
test
.
expectedAuthorized
,
authorized
)
}
if
test
.
expectedCalls
!=
serv
.
called
{
t
.
Errorf
(
"%d: expected %d calls, got %d"
,
i
,
test
.
expectedCalls
,
serv
.
called
)
}
}
}
// TestWebhookCache verifies that error responses from the server are not
// cached, but successful responses are.
func
TestWebhookCache
(
t
*
testing
.
T
)
{
serv
:=
new
(
mockService
)
s
,
err
:=
NewTestServer
(
serv
,
serverCert
,
serverKey
,
caCert
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
defer
s
.
Close
()
// Create an authorizer that caches successful responses "forever" (100 days).
wh
,
err
:=
newAuthorizer
(
s
.
URL
,
clientCert
,
clientKey
,
caCert
,
2400
*
time
.
Hour
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
aliceAttr
:=
authorizer
.
AttributesRecord
{
User
:
&
user
.
DefaultInfo
{
Name
:
"alice"
}}
bobAttr
:=
authorizer
.
AttributesRecord
{
User
:
&
user
.
DefaultInfo
{
Name
:
"bob"
}}
tests
:=
[]
webhookCacheTestCase
{
// server error and 429's retry
{
attr
:
aliceAttr
,
allow
:
false
,
statusCode
:
500
,
expectedErr
:
true
,
expectedAuthorized
:
false
,
expectedCalls
:
5
},
{
attr
:
aliceAttr
,
allow
:
false
,
statusCode
:
429
,
expectedErr
:
true
,
expectedAuthorized
:
false
,
expectedCalls
:
5
},
// regular errors return errors but do not retry
{
attr
:
aliceAttr
,
allow
:
false
,
statusCode
:
404
,
expectedErr
:
true
,
expectedAuthorized
:
false
,
expectedCalls
:
1
},
{
attr
:
aliceAttr
,
allow
:
false
,
statusCode
:
403
,
expectedErr
:
true
,
expectedAuthorized
:
false
,
expectedCalls
:
1
},
{
attr
:
aliceAttr
,
allow
:
false
,
statusCode
:
401
,
expectedErr
:
true
,
expectedAuthorized
:
false
,
expectedCalls
:
1
},
// successful responses are cached
{
attr
:
aliceAttr
,
allow
:
true
,
statusCode
:
200
,
expectedErr
:
false
,
expectedAuthorized
:
true
,
expectedCalls
:
1
},
// later requests within the cache window don't hit the backend
{
attr
:
aliceAttr
,
allow
:
false
,
statusCode
:
500
,
expectedErr
:
false
,
expectedAuthorized
:
true
,
expectedCalls
:
0
},
// a request with different attributes doesn't hit the cache
{
attr
:
bobAttr
,
allow
:
false
,
statusCode
:
500
,
expectedErr
:
true
,
expectedAuthorized
:
false
,
expectedCalls
:
5
},
// successful response for other attributes is cached
{
attr
:
bobAttr
,
allow
:
true
,
statusCode
:
200
,
expectedErr
:
false
,
expectedAuthorized
:
true
,
expectedCalls
:
1
},
// later requests within the cache window don't hit the backend
{
attr
:
bobAttr
,
allow
:
false
,
statusCode
:
500
,
expectedErr
:
false
,
expectedAuthorized
:
true
,
expectedCalls
:
0
},
}
testWebhookCacheCases
(
t
,
serv
,
wh
,
tests
)
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment