Replace godep with dep
This commit is contained in:
parent
1e7489927c
commit
bf5616c65b
14883 changed files with 3937406 additions and 361781 deletions
69
vendor/k8s.io/kubernetes/plugin/pkg/admission/webhook/BUILD
generated
vendored
Normal file
69
vendor/k8s.io/kubernetes/plugin/pkg/admission/webhook/BUILD
generated
vendored
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
"go_test",
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = [
|
||||
"admission_test.go",
|
||||
"certs_test.go",
|
||||
"rules_test.go",
|
||||
],
|
||||
library = ":go_default_library",
|
||||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/apis/admission/install:go_default_library",
|
||||
"//vendor/k8s.io/api/admission/v1alpha1:go_default_library",
|
||||
"//vendor/k8s.io/api/admissionregistration/v1alpha1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/authentication/user:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"admission.go",
|
||||
"doc.go",
|
||||
"rules.go",
|
||||
],
|
||||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/apis/admission/install:go_default_library",
|
||||
"//pkg/apis/admission/v1alpha1:go_default_library",
|
||||
"//pkg/kubeapiserver/admission:go_default_library",
|
||||
"//pkg/kubeapiserver/admission/configuration:go_default_library",
|
||||
"//vendor/github.com/golang/glog:go_default_library",
|
||||
"//vendor/k8s.io/api/admission/v1alpha1:go_default_library",
|
||||
"//vendor/k8s.io/api/admissionregistration/v1alpha1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
"//vendor/k8s.io/client-go/kubernetes:go_default_library",
|
||||
"//vendor/k8s.io/client-go/rest:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
275
vendor/k8s.io/kubernetes/plugin/pkg/admission/webhook/admission.go
generated
vendored
Normal file
275
vendor/k8s.io/kubernetes/plugin/pkg/admission/webhook/admission.go
generated
vendored
Normal file
|
|
@ -0,0 +1,275 @@
|
|||
/*
|
||||
Copyright 2017 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 delegates admission checks to dynamically configured webhooks.
|
||||
package webhook
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/golang/glog"
|
||||
|
||||
admissionv1alpha1 "k8s.io/api/admission/v1alpha1"
|
||||
"k8s.io/api/admissionregistration/v1alpha1"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
"k8s.io/apiserver/pkg/admission"
|
||||
clientset "k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/rest"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
admissionv1alpha1helper "k8s.io/kubernetes/pkg/apis/admission/v1alpha1"
|
||||
admissioninit "k8s.io/kubernetes/pkg/kubeapiserver/admission"
|
||||
"k8s.io/kubernetes/pkg/kubeapiserver/admission/configuration"
|
||||
|
||||
// install the clientgo admission API for use with api registry
|
||||
_ "k8s.io/kubernetes/pkg/apis/admission/install"
|
||||
)
|
||||
|
||||
var (
|
||||
groupVersions = []schema.GroupVersion{
|
||||
admissionv1alpha1.SchemeGroupVersion,
|
||||
}
|
||||
)
|
||||
|
||||
type ErrCallingWebhook struct {
|
||||
WebhookName string
|
||||
Reason error
|
||||
}
|
||||
|
||||
func (e *ErrCallingWebhook) Error() string {
|
||||
if e.Reason != nil {
|
||||
return fmt.Sprintf("failed calling admission webhook %q: %v", e.WebhookName, e.Reason)
|
||||
}
|
||||
return fmt.Sprintf("failed calling admission webhook %q; no further details available", e.WebhookName)
|
||||
}
|
||||
|
||||
// Register registers a plugin
|
||||
func Register(plugins *admission.Plugins) {
|
||||
plugins.Register("GenericAdmissionWebhook", func(configFile io.Reader) (admission.Interface, error) {
|
||||
plugin, err := NewGenericAdmissionWebhook()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return plugin, nil
|
||||
})
|
||||
}
|
||||
|
||||
// WebhookSource can list dynamic webhook plugins.
|
||||
type WebhookSource interface {
|
||||
Run(stopCh <-chan struct{})
|
||||
ExternalAdmissionHooks() (*v1alpha1.ExternalAdmissionHookConfiguration, error)
|
||||
}
|
||||
|
||||
// NewGenericAdmissionWebhook returns a generic admission webhook plugin.
|
||||
func NewGenericAdmissionWebhook() (*GenericAdmissionWebhook, error) {
|
||||
return &GenericAdmissionWebhook{
|
||||
Handler: admission.NewHandler(
|
||||
admission.Connect,
|
||||
admission.Create,
|
||||
admission.Delete,
|
||||
admission.Update,
|
||||
),
|
||||
negotiatedSerializer: serializer.NegotiatedSerializerWrapper(runtime.SerializerInfo{
|
||||
Serializer: api.Codecs.LegacyCodec(admissionv1alpha1.SchemeGroupVersion),
|
||||
}),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GenericAdmissionWebhook is an implementation of admission.Interface.
|
||||
type GenericAdmissionWebhook struct {
|
||||
*admission.Handler
|
||||
hookSource WebhookSource
|
||||
serviceResolver admissioninit.ServiceResolver
|
||||
negotiatedSerializer runtime.NegotiatedSerializer
|
||||
clientCert []byte
|
||||
clientKey []byte
|
||||
proxyTransport *http.Transport
|
||||
}
|
||||
|
||||
var (
|
||||
_ = admissioninit.WantsServiceResolver(&GenericAdmissionWebhook{})
|
||||
_ = admissioninit.WantsClientCert(&GenericAdmissionWebhook{})
|
||||
_ = admissioninit.WantsExternalKubeClientSet(&GenericAdmissionWebhook{})
|
||||
)
|
||||
|
||||
func (a *GenericAdmissionWebhook) SetProxyTransport(pt *http.Transport) {
|
||||
a.proxyTransport = pt
|
||||
}
|
||||
|
||||
func (a *GenericAdmissionWebhook) SetServiceResolver(sr admissioninit.ServiceResolver) {
|
||||
a.serviceResolver = sr
|
||||
}
|
||||
|
||||
func (a *GenericAdmissionWebhook) SetClientCert(cert, key []byte) {
|
||||
a.clientCert = cert
|
||||
a.clientKey = key
|
||||
}
|
||||
|
||||
func (a *GenericAdmissionWebhook) SetExternalKubeClientSet(client clientset.Interface) {
|
||||
a.hookSource = configuration.NewExternalAdmissionHookConfigurationManager(client.Admissionregistration().ExternalAdmissionHookConfigurations())
|
||||
}
|
||||
|
||||
func (a *GenericAdmissionWebhook) Validate() error {
|
||||
if a.hookSource == nil {
|
||||
return fmt.Errorf("the GenericAdmissionWebhook admission plugin requires a Kubernetes client to be provided")
|
||||
}
|
||||
go a.hookSource.Run(wait.NeverStop)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *GenericAdmissionWebhook) loadConfiguration(attr admission.Attributes) (*v1alpha1.ExternalAdmissionHookConfiguration, error) {
|
||||
hookConfig, err := a.hookSource.ExternalAdmissionHooks()
|
||||
// if ExternalAdmissionHook configuration is disabled, fail open
|
||||
if err == configuration.ErrDisabled {
|
||||
return &v1alpha1.ExternalAdmissionHookConfiguration{}, nil
|
||||
}
|
||||
if err != nil {
|
||||
e := apierrors.NewServerTimeout(attr.GetResource().GroupResource(), string(attr.GetOperation()), 1)
|
||||
e.ErrStatus.Message = fmt.Sprintf("Unable to refresh the ExternalAdmissionHook configuration: %v", err)
|
||||
e.ErrStatus.Reason = "LoadingConfiguration"
|
||||
e.ErrStatus.Details.Causes = append(e.ErrStatus.Details.Causes, metav1.StatusCause{
|
||||
Type: "ExternalAdmissionHookConfigurationFailure",
|
||||
Message: "An error has occurred while refreshing the externalAdmissionHook configuration, no resources can be created/updated/deleted/connected until a refresh succeeds.",
|
||||
})
|
||||
return nil, e
|
||||
}
|
||||
return hookConfig, nil
|
||||
}
|
||||
|
||||
// Admit makes an admission decision based on the request attributes.
|
||||
func (a *GenericAdmissionWebhook) Admit(attr admission.Attributes) error {
|
||||
hookConfig, err := a.loadConfiguration(attr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
hooks := hookConfig.ExternalAdmissionHooks
|
||||
ctx := context.TODO()
|
||||
|
||||
errCh := make(chan error, len(hooks))
|
||||
wg := sync.WaitGroup{}
|
||||
wg.Add(len(hooks))
|
||||
for i := range hooks {
|
||||
go func(hook *v1alpha1.ExternalAdmissionHook) {
|
||||
defer wg.Done()
|
||||
if err := a.callHook(ctx, hook, attr); err == nil {
|
||||
return
|
||||
} else if callErr, ok := err.(*ErrCallingWebhook); ok {
|
||||
glog.Warningf("Failed calling webhook %v: %v", hook.Name, callErr)
|
||||
utilruntime.HandleError(callErr)
|
||||
// Since we are failing open to begin with, we do not send an error down the channel
|
||||
} else {
|
||||
glog.Warningf("rejected by webhook %v %t: %v", hook.Name, err, err)
|
||||
errCh <- err
|
||||
}
|
||||
}(&hooks[i])
|
||||
}
|
||||
wg.Wait()
|
||||
close(errCh)
|
||||
|
||||
var errs []error
|
||||
for e := range errCh {
|
||||
errs = append(errs, e)
|
||||
}
|
||||
if len(errs) == 0 {
|
||||
return nil
|
||||
}
|
||||
if len(errs) > 1 {
|
||||
for i := 1; i < len(errs); i++ {
|
||||
// TODO: merge status errors; until then, just return the first one.
|
||||
utilruntime.HandleError(errs[i])
|
||||
}
|
||||
}
|
||||
return errs[0]
|
||||
}
|
||||
|
||||
func (a *GenericAdmissionWebhook) callHook(ctx context.Context, h *v1alpha1.ExternalAdmissionHook, attr admission.Attributes) error {
|
||||
matches := false
|
||||
for _, r := range h.Rules {
|
||||
m := RuleMatcher{Rule: r, Attr: attr}
|
||||
if m.Matches() {
|
||||
matches = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !matches {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Make the webhook request
|
||||
request := admissionv1alpha1helper.NewAdmissionReview(attr)
|
||||
client, err := a.hookClient(h)
|
||||
if err != nil {
|
||||
return &ErrCallingWebhook{WebhookName: h.Name, Reason: err}
|
||||
}
|
||||
if err := client.Post().Context(ctx).Body(&request).Do().Into(&request); err != nil {
|
||||
return &ErrCallingWebhook{WebhookName: h.Name, Reason: err}
|
||||
}
|
||||
|
||||
if request.Status.Allowed {
|
||||
return nil
|
||||
}
|
||||
|
||||
if request.Status.Result == nil {
|
||||
return fmt.Errorf("admission webhook %q denied the request without explanation", h.Name)
|
||||
}
|
||||
|
||||
return &apierrors.StatusError{
|
||||
ErrStatus: *request.Status.Result,
|
||||
}
|
||||
}
|
||||
|
||||
func (a *GenericAdmissionWebhook) hookClient(h *v1alpha1.ExternalAdmissionHook) (*rest.RESTClient, error) {
|
||||
u, err := a.serviceResolver.ResolveEndpoint(h.ClientConfig.Service.Namespace, h.ClientConfig.Service.Name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var dial func(network, addr string) (net.Conn, error)
|
||||
if a.proxyTransport != nil && a.proxyTransport.Dial != nil {
|
||||
dial = a.proxyTransport.Dial
|
||||
}
|
||||
|
||||
// TODO: cache these instead of constructing one each time
|
||||
cfg := &rest.Config{
|
||||
Host: u.Host,
|
||||
APIPath: u.Path,
|
||||
TLSClientConfig: rest.TLSClientConfig{
|
||||
ServerName: h.ClientConfig.Service.Name + "." + h.ClientConfig.Service.Namespace + ".svc",
|
||||
CAData: h.ClientConfig.CABundle,
|
||||
CertData: a.clientCert,
|
||||
KeyData: a.clientKey,
|
||||
},
|
||||
UserAgent: "kube-apiserver-admission",
|
||||
Timeout: 30 * time.Second,
|
||||
ContentConfig: rest.ContentConfig{
|
||||
NegotiatedSerializer: a.negotiatedSerializer,
|
||||
},
|
||||
Dial: dial,
|
||||
}
|
||||
return rest.UnversionedRESTClientFor(cfg)
|
||||
}
|
||||
271
vendor/k8s.io/kubernetes/plugin/pkg/admission/webhook/admission_test.go
generated
vendored
Normal file
271
vendor/k8s.io/kubernetes/plugin/pkg/admission/webhook/admission_test.go
generated
vendored
Normal file
|
|
@ -0,0 +1,271 @@
|
|||
/*
|
||||
Copyright 2017 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"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"k8s.io/api/admission/v1alpha1"
|
||||
registrationv1alpha1 "k8s.io/api/admissionregistration/v1alpha1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apiserver/pkg/admission"
|
||||
"k8s.io/apiserver/pkg/authentication/user"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
|
||||
_ "k8s.io/kubernetes/pkg/apis/admission/install"
|
||||
)
|
||||
|
||||
type fakeHookSource struct {
|
||||
hooks []registrationv1alpha1.ExternalAdmissionHook
|
||||
err error
|
||||
}
|
||||
|
||||
func (f *fakeHookSource) ExternalAdmissionHooks() (*registrationv1alpha1.ExternalAdmissionHookConfiguration, error) {
|
||||
if f.err != nil {
|
||||
return nil, f.err
|
||||
}
|
||||
return ®istrationv1alpha1.ExternalAdmissionHookConfiguration{ExternalAdmissionHooks: f.hooks}, nil
|
||||
}
|
||||
|
||||
func (f *fakeHookSource) Run(stopCh <-chan struct{}) {}
|
||||
|
||||
type fakeServiceResolver struct {
|
||||
base url.URL
|
||||
path string
|
||||
}
|
||||
|
||||
func (f fakeServiceResolver) ResolveEndpoint(namespace, name string) (*url.URL, error) {
|
||||
if namespace == "failResolve" {
|
||||
return nil, fmt.Errorf("couldn't resolve service location")
|
||||
}
|
||||
u := f.base
|
||||
u.Path = f.path
|
||||
return &u, nil
|
||||
}
|
||||
|
||||
// TestAdmit tests that GenericAdmissionWebhook#Admit works as expected
|
||||
func TestAdmit(t *testing.T) {
|
||||
// Create the test webhook server
|
||||
sCert, err := tls.X509KeyPair(serverCert, serverKey)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
rootCAs := x509.NewCertPool()
|
||||
rootCAs.AppendCertsFromPEM(caCert)
|
||||
testServer := httptest.NewUnstartedServer(http.HandlerFunc(webhookHandler))
|
||||
testServer.TLS = &tls.Config{
|
||||
Certificates: []tls.Certificate{sCert},
|
||||
ClientCAs: rootCAs,
|
||||
ClientAuth: tls.RequireAndVerifyClientCert,
|
||||
}
|
||||
testServer.StartTLS()
|
||||
defer testServer.Close()
|
||||
serverURL, err := url.ParseRequestURI(testServer.URL)
|
||||
if err != nil {
|
||||
t.Fatalf("this should never happen? %v", err)
|
||||
}
|
||||
wh, err := NewGenericAdmissionWebhook()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
wh.clientCert = clientCert
|
||||
wh.clientKey = clientKey
|
||||
|
||||
// Set up a test object for the call
|
||||
kind := api.Kind("Pod").WithVersion("v1")
|
||||
name := "my-pod"
|
||||
namespace := "webhook-test"
|
||||
object := api.Pod{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Labels: map[string]string{
|
||||
"pod.name": name,
|
||||
},
|
||||
Name: name,
|
||||
Namespace: namespace,
|
||||
},
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
APIVersion: "v1",
|
||||
Kind: "Pod",
|
||||
},
|
||||
}
|
||||
oldObject := api.Pod{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: name, Namespace: namespace},
|
||||
}
|
||||
operation := admission.Update
|
||||
resource := api.Resource("pods").WithVersion("v1")
|
||||
subResource := ""
|
||||
userInfo := user.DefaultInfo{
|
||||
Name: "webhook-test",
|
||||
UID: "webhook-test",
|
||||
}
|
||||
|
||||
type test struct {
|
||||
hookSource fakeHookSource
|
||||
path string
|
||||
expectAllow bool
|
||||
errorContains string
|
||||
}
|
||||
ccfg := registrationv1alpha1.AdmissionHookClientConfig{
|
||||
Service: registrationv1alpha1.ServiceReference{
|
||||
Name: "webhook-test",
|
||||
Namespace: "default",
|
||||
},
|
||||
CABundle: caCert,
|
||||
}
|
||||
matchEverythingRules := []registrationv1alpha1.RuleWithOperations{{
|
||||
Operations: []registrationv1alpha1.OperationType{registrationv1alpha1.OperationAll},
|
||||
Rule: registrationv1alpha1.Rule{
|
||||
APIGroups: []string{"*"},
|
||||
APIVersions: []string{"*"},
|
||||
Resources: []string{"*/*"},
|
||||
},
|
||||
}}
|
||||
|
||||
table := map[string]test{
|
||||
"no match": {
|
||||
hookSource: fakeHookSource{
|
||||
hooks: []registrationv1alpha1.ExternalAdmissionHook{{
|
||||
Name: "nomatch",
|
||||
ClientConfig: ccfg,
|
||||
Rules: []registrationv1alpha1.RuleWithOperations{{
|
||||
Operations: []registrationv1alpha1.OperationType{registrationv1alpha1.Create},
|
||||
}},
|
||||
}},
|
||||
},
|
||||
path: "disallow",
|
||||
expectAllow: true,
|
||||
},
|
||||
"match & allow": {
|
||||
hookSource: fakeHookSource{
|
||||
hooks: []registrationv1alpha1.ExternalAdmissionHook{{
|
||||
Name: "allow",
|
||||
ClientConfig: ccfg,
|
||||
Rules: matchEverythingRules,
|
||||
}},
|
||||
},
|
||||
path: "allow",
|
||||
expectAllow: true,
|
||||
},
|
||||
"match & disallow": {
|
||||
hookSource: fakeHookSource{
|
||||
hooks: []registrationv1alpha1.ExternalAdmissionHook{{
|
||||
Name: "disallow",
|
||||
ClientConfig: ccfg,
|
||||
Rules: matchEverythingRules,
|
||||
}},
|
||||
},
|
||||
path: "disallow",
|
||||
errorContains: "without explanation",
|
||||
},
|
||||
"match & disallow ii": {
|
||||
hookSource: fakeHookSource{
|
||||
hooks: []registrationv1alpha1.ExternalAdmissionHook{{
|
||||
Name: "disallowReason",
|
||||
ClientConfig: ccfg,
|
||||
Rules: matchEverythingRules,
|
||||
}},
|
||||
},
|
||||
path: "disallowReason",
|
||||
errorContains: "you shall not pass",
|
||||
},
|
||||
"match & fail (but allow because fail open)": {
|
||||
hookSource: fakeHookSource{
|
||||
hooks: []registrationv1alpha1.ExternalAdmissionHook{{
|
||||
Name: "internalErr A",
|
||||
ClientConfig: ccfg,
|
||||
Rules: matchEverythingRules,
|
||||
}, {
|
||||
Name: "internalErr B",
|
||||
ClientConfig: ccfg,
|
||||
Rules: matchEverythingRules,
|
||||
}, {
|
||||
Name: "internalErr C",
|
||||
ClientConfig: ccfg,
|
||||
Rules: matchEverythingRules,
|
||||
}},
|
||||
},
|
||||
path: "internalErr",
|
||||
expectAllow: true,
|
||||
},
|
||||
}
|
||||
|
||||
for name, tt := range table {
|
||||
wh.hookSource = &tt.hookSource
|
||||
wh.serviceResolver = fakeServiceResolver{base: *serverURL, path: tt.path}
|
||||
|
||||
err = wh.Admit(admission.NewAttributesRecord(&object, &oldObject, kind, namespace, name, resource, subResource, operation, &userInfo))
|
||||
if tt.expectAllow != (err == nil) {
|
||||
t.Errorf("%q: expected allowed=%v, but got err=%v", name, tt.expectAllow, err)
|
||||
}
|
||||
// ErrWebhookRejected is not an error for our purposes
|
||||
if tt.errorContains != "" {
|
||||
if err == nil || !strings.Contains(err.Error(), tt.errorContains) {
|
||||
t.Errorf("%q: expected an error saying %q, but got %v", name, tt.errorContains, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func webhookHandler(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Printf("got req: %v\n", r.URL.Path)
|
||||
switch r.URL.Path {
|
||||
case "/internalErr":
|
||||
http.Error(w, "webhook internal server error", http.StatusInternalServerError)
|
||||
return
|
||||
case "/invalidReq":
|
||||
w.WriteHeader(http.StatusSwitchingProtocols)
|
||||
w.Write([]byte("webhook invalid request"))
|
||||
return
|
||||
case "/invalidResp":
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.Write([]byte("webhook invalid response"))
|
||||
case "/disallow":
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
json.NewEncoder(w).Encode(&v1alpha1.AdmissionReview{
|
||||
Status: v1alpha1.AdmissionReviewStatus{
|
||||
Allowed: false,
|
||||
},
|
||||
})
|
||||
case "/disallowReason":
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
json.NewEncoder(w).Encode(&v1alpha1.AdmissionReview{
|
||||
Status: v1alpha1.AdmissionReviewStatus{
|
||||
Allowed: false,
|
||||
Result: &metav1.Status{
|
||||
Message: "you shall not pass",
|
||||
},
|
||||
},
|
||||
})
|
||||
case "/allow":
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
json.NewEncoder(w).Encode(&v1alpha1.AdmissionReview{
|
||||
Status: v1alpha1.AdmissionReviewStatus{
|
||||
Allowed: true,
|
||||
},
|
||||
})
|
||||
default:
|
||||
http.NotFound(w, r)
|
||||
}
|
||||
}
|
||||
215
vendor/k8s.io/kubernetes/plugin/pkg/admission/webhook/certs_test.go
generated
vendored
Normal file
215
vendor/k8s.io/kubernetes/plugin/pkg/admission/webhook/certs_test.go
generated
vendored
Normal file
|
|
@ -0,0 +1,215 @@
|
|||
/*
|
||||
Copyright 2017 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-----
|
||||
MIIEowIBAAKCAQEArHdRY9333U04xKotqnwKwJ52ihSGwr5hf4XkoZ46+ZYiaPS1
|
||||
sEeKkFPRZEZIK22cd/2glyy+AsEURi8yeFut7exu41Y6M5Cfgf64keY2EgRu9DlB
|
||||
ZyQBTD67TfA64xRbztHmgJpBZHpd00R9o1I05OYso7ALFiqEtHDPvUj3PU17h7c3
|
||||
xEfq1k7kQq8Tr0EbEQ+GWdE/X0IHW4J4pIjK010KHZSJz4W0wuVgsjDDvV4RGPIR
|
||||
cXT/nH36gmM+rcxNgtHgNHCSQ7i6ioUMjvg3utp08Vtw0icK9V5MV2MAGjNh5zCi
|
||||
Uvl+9rTsW5v7tR9Y5puWqBPEWaBpwJwjJlEaAQIDAQABAoIBAC7xMxgJnKOBl0gA
|
||||
Qfm7VXnkJ8OhnqR3CTaajQZoeQjiEm+a27ElZ9Os3Lt8XbxkU0hdok5DgVxijVAl
|
||||
HImh+o9d4TjDiYfrf170o+wiSulQh5q10tVt+WR1Vqn6Dy0rp2l9vE2Yrt/YZp1Q
|
||||
cRn5ECiVdeT/z6Sy4ffzFLgimhj3AUyipDpBUdvqNnC6+OP2T5ZXDGC2LJGU6v4z
|
||||
zLwjFV1pMRgxLJFoCD9Zy200OkbMYYAhYgaiXMyu5ZU3AjWynPdswANshccAtFt8
|
||||
wqVICN20HEoOW1PEM+Z1wOUxpQYUOfL3ieJp9WKklHe7vbY3Iuaotg0Gmg74TNbR
|
||||
8dcJsjkCgYEA4i1TcnUenv7Tdj9ectN6vXNeGrBUvBO4XFHKauBcGnhZQLuS9GRt
|
||||
cUJ+Y3rRLpf7rKE18Zl0YDgJRycfsNjbI6U74pcXZ/XBySPLGcfVrEqaTZ9o5apV
|
||||
UOwbKkP1vtEuGLipFVuvZdinVLAs5QFrO2HoqmXqcYQhjVqHtT0NmGcCgYEAwzT2
|
||||
UI/r14yRH7oaRU/cPmDG0pCfMjaXlKmU/oaqyYypn750NiyZqSWdZf7rhBxOCbPE
|
||||
tEtTGAPgGkEbb5GmpEDuJRtuj25kT0kIGqU6KjnYR0OO3iIr6mQN12Cv16JiFN5B
|
||||
VNpNSXkR8Hi2kQimz1W/KzUXoInbzaEji9WF2VcCgYEA0FWt6t0k8pGJmP8v8ZcJ
|
||||
FR8CjJTlyERl6mvQhvfY/uziUbU13PXwtYXpQ5rquf927IGmXb/bKZIUQb0w/MYT
|
||||
vNbDvaks/y6pbKwStdGT6VrinSN8DSkD40FImHr3DuhBjLXz0V+dxbN2FpUdFWhk
|
||||
LNO369VqyVtLSJgeLvxo3HsCgYA12kaZsxq9PGpM9mqI9J8uFkTDkmJY1/a5bI9O
|
||||
KJi1QbkJ+ODWkTdTEq15lfojWCuvQYjitGUYGvmYRJ3tCaGPbtpEIm095JaHyP4T
|
||||
W8HQJGUmQ90GKycyYqfu4x2fv4yPdUFQx2jK/DuWu7aiDGD4kg9LPDpob5/T+sBz
|
||||
s1RZwQKBgDhwksMQXoEbQLdpllqOL45hmXu06/eOnG4tCY3OXlTf8UQXn31aPXdr
|
||||
75W8VyyyB7vlNj414jI8N5xriGuRt36ihC3vmz+RotcHhCjH4sXnylP7hwg1ZuGh
|
||||
QE9Df6To9LjpRfZZZ9KdAnyx7P/OZPgXPcK7vd9U3+JQ4E8YW4qG
|
||||
-----END RSA PRIVATE KEY-----`)
|
||||
|
||||
var caCert = []byte(`-----BEGIN CERTIFICATE-----
|
||||
MIIDPTCCAiWgAwIBAgIJAKa7yqtdLQh0MA0GCSqGSIb3DQEBCwUAMDQxMjAwBgNV
|
||||
BAMMKWdlbmVyaWNfd2ViaG9va19hZG1pc3Npb25fcGx1Z2luX3Rlc3RzX2NhMCAX
|
||||
DTE3MDkxMzAwMTAwNFoYDzIyOTEwNjI5MDAxMDA0WjA0MTIwMAYDVQQDDClnZW5l
|
||||
cmljX3dlYmhvb2tfYWRtaXNzaW9uX3BsdWdpbl90ZXN0c19jYTCCASIwDQYJKoZI
|
||||
hvcNAQEBBQADggEPADCCAQoCggEBAKx3UWPd991NOMSqLap8CsCedooUhsK+YX+F
|
||||
5KGeOvmWImj0tbBHipBT0WRGSCttnHf9oJcsvgLBFEYvMnhbre3sbuNWOjOQn4H+
|
||||
uJHmNhIEbvQ5QWckAUw+u03wOuMUW87R5oCaQWR6XdNEfaNSNOTmLKOwCxYqhLRw
|
||||
z71I9z1Ne4e3N8RH6tZO5EKvE69BGxEPhlnRP19CB1uCeKSIytNdCh2Uic+FtMLl
|
||||
YLIww71eERjyEXF0/5x9+oJjPq3MTYLR4DRwkkO4uoqFDI74N7radPFbcNInCvVe
|
||||
TFdjABozYecwolL5fva07Fub+7UfWOablqgTxFmgacCcIyZRGgECAwEAAaNQME4w
|
||||
HQYDVR0OBBYEFPa03YxFI220gcsALquzjQkfHztBMB8GA1UdIwQYMBaAFPa03YxF
|
||||
I220gcsALquzjQkfHztBMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEB
|
||||
AJkgjVhVNAoVdNA55qPPYxouOpOUNyy6GV8ZKCSepz4O5uSRl1FHxTIoodnYzBvO
|
||||
RkYBJCMupB4Ee+wuMlZGPd3Tfnl6SaP1V4vGYD1iS4otMM6J2tTJBxoLqQwNaDkc
|
||||
S2E2zfbQ0OxaRNbMBn9AZvZE4lN2TMVuWuTGl1amMLF7Fsxs2ndt+OCpf8d2sWpW
|
||||
Enh475ch0PJfqZU0papeSV0XRdn60lTGwIbRldUowTBLYcbKo4tTMsCE3oOK7yul
|
||||
0QhQ9eJktvMbZNMYwGWz+p4pjs/eqBnlBP0KuXguKFHFXILxPlyRMhsvHKURUnC8
|
||||
ugGtqN9AEw6SF2Hf1rzmNno=
|
||||
-----END CERTIFICATE-----`)
|
||||
|
||||
var badCAKey = []byte(`-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEpQIBAAKCAQEA5T0xQ7mapkcE+h3owavy8NDxc2eKRe9q/5/yFp27F8QpnY13
|
||||
SQS0GXvDiFW1eXdXTg39loy5fG3SZLd/f0eniF2FWKsRvIJbRGyyVBzySbNvbEit
|
||||
ekVeKQJTTH3Xlnb2JdRrr4vxWQC7crVPksS+AsB+MzdB39XIYxvK6hqwF7On8gro
|
||||
tzJ+k9e9+/rk0u8FsOBvnE8Z9MX5qX+00UnHSVZuzQt//rTG4Dqsm1yswwTlUfe9
|
||||
XpjSh7D6fpjp5YNH9p3vLZMjoY/7ZqO0svHlcWjyv/zoN35p0gMwOGrByATYi2lo
|
||||
wYBckI8oC+CzyRO8ThKUDW19fa9jKYcqsIDhwQIDAQABAoIBADFvadFWFFCpXhxm
|
||||
GMyzPRfLp1YgzQPZ5rQrlPRlnXQ5nFParw+zEPex5e/fs9v27X/qqnYt8M4xjL6l
|
||||
h7w2Ap34tQnzEkcZwX7XBfn3qBRWur+aSLbmgLDNTJNhS/2pt9lenr5jqm9sJgBN
|
||||
s1ROUz+arVx0HSOdIbKlyrODf9gMQL6hg/ZYNym2KaaYjnNfyrGtb3GQgYDn5FNQ
|
||||
TSeseXOm82Ev34pSbtQ/oFtU5W4DW72VFA68ciaLM2XslVl/zcncyDk+0LpvSq+W
|
||||
PYSQbwU/xZukMXXxbBoQUaorNK1fDOdYXBzSzs+Yzo+71D3azFaqPv6CMlHCYeA8
|
||||
EUkDRAECgYEA8rmOnzjoHStjkOr7Yb5zqX4UyC0VvB6S9EJxy2a133K0eXJ82KPR
|
||||
L7fkkvZk04PwDUpClTqcTw3gblhIaBYsFqTnCn6+8hS1Lqa6OqUYo5/UD1O4mXVh
|
||||
ebLvss5CNqA2+ii80XkRZSW4w/27CG+u/iBAiS5JeYi0zm89G5PYbCECgYEA8cbR
|
||||
VoUB6rFNC0VOd/D+LPMWaCU7FguAJQ+8Opoh/JgmxFqWwWYeteuX0tbGrKb8LXSA
|
||||
XLEL1vrZjQ2W9tKP4hP9rgiZbvNujPABS1ey5mMFDPMy6q2OYgLY85jpeYU9PpRt
|
||||
dOZiw7a0TFENRU19/WMeSfdDvEzafX6tqA/gwaECgYEA0337V6EuHrx/tPYKs9BO
|
||||
15CUaxddqNy7DzoWDTUho+E+f9PSFLIow3toHuWyVNrRf8ME4SKAsCFXPM6PyKIJ
|
||||
KHHnHq3xkt2YQV3lRtQz895/2BsK7ivpEzFmylYOO6q+PJria2MiVQ/ZPm0HWwJ1
|
||||
Z9iSYvWB7/O+F2G1zSG1ogECgYEAtoV0VY+VsdplokORCGULTV26JactoufNtqzZ
|
||||
WZgwXiNy6LrGonv4ZTfU5tszIvXw3FPd75vMp1+6Soze0biF3JNg6DgftK3bYFRz
|
||||
dbBgIyLPlkYmwxmAqqchp0xhvVaDtLGSrDScjMlp9U8e6JmmqlpgbFBZd1bBfwna
|
||||
CUzrTOECgYEAx98UtYAFWVwoCZwtqSfzTKHerFN/qMFY34cXhdns2ZWn6kEb6alk
|
||||
dXqNDkXV/7EBGWAcvKn/zbrwlhVDwPHUETgjCUpxqST0ly6E/JnwiNbrSOWG4Yg0
|
||||
RoKj46nUcolMbgRub+yeQqcQ48Y2/1OvnRUQ9aQ5MqVSyTyylgMKlB8=
|
||||
-----END RSA PRIVATE KEY-----`)
|
||||
|
||||
var badCACert = []byte(`-----BEGIN CERTIFICATE-----
|
||||
MIIDPTCCAiWgAwIBAgIJAOQ6iHm4OCSMMA0GCSqGSIb3DQEBCwUAMDQxMjAwBgNV
|
||||
BAMMKWdlbmVyaWNfd2ViaG9va19hZG1pc3Npb25fcGx1Z2luX3Rlc3RzX2NhMCAX
|
||||
DTE3MDkxMzAwMTAwNFoYDzIyOTEwNjI5MDAxMDA0WjA0MTIwMAYDVQQDDClnZW5l
|
||||
cmljX3dlYmhvb2tfYWRtaXNzaW9uX3BsdWdpbl90ZXN0c19jYTCCASIwDQYJKoZI
|
||||
hvcNAQEBBQADggEPADCCAQoCggEBAOU9MUO5mqZHBPod6MGr8vDQ8XNnikXvav+f
|
||||
8haduxfEKZ2Nd0kEtBl7w4hVtXl3V04N/ZaMuXxt0mS3f39Hp4hdhVirEbyCW0Rs
|
||||
slQc8kmzb2xIrXpFXikCU0x915Z29iXUa6+L8VkAu3K1T5LEvgLAfjM3Qd/VyGMb
|
||||
yuoasBezp/IK6LcyfpPXvfv65NLvBbDgb5xPGfTF+al/tNFJx0lWbs0Lf/60xuA6
|
||||
rJtcrMME5VH3vV6Y0oew+n6Y6eWDR/ad7y2TI6GP+2ajtLLx5XFo8r/86Dd+adID
|
||||
MDhqwcgE2ItpaMGAXJCPKAvgs8kTvE4SlA1tfX2vYymHKrCA4cECAwEAAaNQME4w
|
||||
HQYDVR0OBBYEFEe2nQ5ONNJFv/+6pWnzvfqRNTR9MB8GA1UdIwQYMBaAFEe2nQ5O
|
||||
NNJFv/+6pWnzvfqRNTR9MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEB
|
||||
AEORwyo3MJZVuYbqft728t9MWw0wFORzxPnFVLXMIrX223flNEmqvkA8UBSulxmq
|
||||
yDYOOkOWByd2eemCZtc/MlmiSeYNFSi/PS+METkAef2cZfSQNdIUwwl5BZ4vW973
|
||||
J+fDNm0LQh3ZPDngylQ3XprQkF7l+UefRVfbDDTALVDzmJCV/FCm05ijg+HssgwX
|
||||
+rYI9ZdJbp2z9xftN0RRIwrBQ3S9vA1mq6OoZFco+9Oq5Li5DHv0BpQgOS64dY1z
|
||||
dtOy4RvQNF8NsITkOlp7f39716448dvq8TJlCdE27ptL44hU82cZib3cwQx8cynu
|
||||
45owbCivEhgee3RUY7gVuc8=
|
||||
-----END CERTIFICATE-----`)
|
||||
|
||||
var serverKey = []byte(`-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEpAIBAAKCAQEAxjTbuWppAQB140aAxVVo0jdcGw5id4IAa8ji3T/X1+mDIkU8
|
||||
dA8kfpwgaeurh3Nai0R6LT9ZZ5aJD8a2udhVivY0Q11snw/4G40avL2yPr1VJSKk
|
||||
lv5/b1knSh53Cvj+7ma6yjn5yBxw8V7v++37yVe6LHP3B0QBvR07n9k507gKHkw/
|
||||
R924I6JUdBtlqoIPwRJlWRVyJ5RawfDZ+KX2d9rY0WAxW60Xge8gWPMv8XKViyw+
|
||||
p5+5ct6aHiu6/vtRP5N70lL8HXQjr+x0qaFd6m3/SajjX8AKvdIQzDocTzmjdlRL
|
||||
Rj8kvLYf8fPazSybqWv0JeXkVxCZPv25SN26BwIDAQABAoIBAGYsqXgTmr2hdyQK
|
||||
HCedt8NmNlzcNXZV1dG6ZPiZCLOM9MSd3GQXykBaS3tOucXBeVOBoVnh5jy4JT+0
|
||||
uE1lb/OKp7ZyWqREnynUu4vAXjppb5MNILuVxiuoUdCrk8JcSU6sNm45JMI7px1G
|
||||
S4AbVkicqKRxw05DiIHsp+fnGyBAPRK5+NxHzvERGH9Fxu6jKngSEfz345hZet07
|
||||
C93tREsRYAPymjMO3Z/vLzO8MjwvLrL+ko6RR1/+VQjWG/tSgnSEhOpGibgWl4ni
|
||||
4MvgipRzxkPfRE0qhAjbiQc/epRKDWWTkVfCDruKPSu5SIqD5NmT+MJTws25ZO4c
|
||||
C3yh08ECgYEA//nPrMwOFft47maJR+y5TS+ym7pemMAztnB+9sLQB1iAF4RP29sK
|
||||
s6WsQmxAiqb0X8lP6N0uRXBD/Cc30hXFfkfx4iWZl5/GYSswEVNXVx7GlFjh1DdB
|
||||
dbAK/04+/pJGHWaWJFyoWy8+HRDezJ33dF/y6BVX85eA1b8jdvrBB/UCgYEAxjmm
|
||||
fo2B1UDVfPb48SbiVV2w8VVo8p6/AOUxUYg10ZkJj5zSB76FC2yfYVPZGCnt2dcZ
|
||||
N3EPQ4ETVbYgL9N1fgukzWSez38SFuYDajJUxJ7tt4G9W881pZPfi3B1by7xcyaW
|
||||
4M9gDvsvM2QYPGiz6mH1DwxG2rtY0ktolWkbyIsCgYEAo8xmYSueY+CsbNl+RWEs
|
||||
3kCEaXRj7hknvjnUdPEKj3jJVsMbGxPakESWq1Z8In1daSH4GYnXfyWsy2EJLk0y
|
||||
OHGvTchDtavPFQS+2IddH2mZJvqNX/AP2lBRaTfXxa0yYsPvlcsZDGh5tb3C5Gq9
|
||||
G2H+nRZzVnP/REfwWMVy2jUCgYEApgsKlT2RwQGTEx+J/e71bk6R9kX2KC2jj2ts
|
||||
+X/gnRbVdHAHWydTKPOvOgbTdjNBItXUMKXLBF+tw4FQyt8VrySvwsEDaoplq7q2
|
||||
p5FLgnwiYjISXUJgDLembJYiOKUY6b0sa1oqe8IakrDIwGlwM+gkL5u4CmceiuFR
|
||||
1L374OsCgYAA5KmaCPoDefbvjpQ0EEZ+EFUyT9zVPHvqJa0aYo9KeWGfD/c9gYcQ
|
||||
WYWmap9Ed7RfMSxSE3oS2JCFIW19Y0HlBiyu+mi3oJ1ErJRmzgNQHmMkzDr1plQ6
|
||||
Zs423AVUJak0hiqLhF2o/I+pbbtGXB1TBaR6d6cGNP3wTCHtCjNc6w==
|
||||
-----END RSA PRIVATE KEY-----`)
|
||||
|
||||
var serverCert = []byte(`-----BEGIN CERTIFICATE-----
|
||||
MIIDJjCCAg6gAwIBAgIJAPJEHs7Aav1jMA0GCSqGSIb3DQEBCwUAMDQxMjAwBgNV
|
||||
BAMMKWdlbmVyaWNfd2ViaG9va19hZG1pc3Npb25fcGx1Z2luX3Rlc3RzX2NhMCAX
|
||||
DTE3MDkxMzAwMTAwNFoYDzIyOTEwNjI5MDAxMDA0WjAjMSEwHwYDVQQDExh3ZWJo
|
||||
b29rLXRlc3QuZGVmYXVsdC5zdmMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
|
||||
AoIBAQDGNNu5amkBAHXjRoDFVWjSN1wbDmJ3ggBryOLdP9fX6YMiRTx0DyR+nCBp
|
||||
66uHc1qLRHotP1lnlokPxra52FWK9jRDXWyfD/gbjRq8vbI+vVUlIqSW/n9vWSdK
|
||||
HncK+P7uZrrKOfnIHHDxXu/77fvJV7osc/cHRAG9HTuf2TnTuAoeTD9H3bgjolR0
|
||||
G2Wqgg/BEmVZFXInlFrB8Nn4pfZ32tjRYDFbrReB7yBY8y/xcpWLLD6nn7ly3poe
|
||||
K7r++1E/k3vSUvwddCOv7HSpoV3qbf9JqONfwAq90hDMOhxPOaN2VEtGPyS8th/x
|
||||
89rNLJupa/Ql5eRXEJk+/blI3boHAgMBAAGjSjBIMAkGA1UdEwQCMAAwCwYDVR0P
|
||||
BAQDAgXgMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATAPBgNVHREECDAG
|
||||
hwR/AAABMA0GCSqGSIb3DQEBCwUAA4IBAQAp99rbIZlUhvNmxhiQCMcltLqtIpGs
|
||||
ZorxbInV4QCdV+Kybot+L7kUDxu/OqERNLqr1qRsjqJRHUhiZZVv8gjZgwz4bO1/
|
||||
ycjUyAoS92OMKEWlvXe1nMnHH3Jw+lXnwiaOumoExhB1gpMjGqsU3mBQrHXGenNS
|
||||
JyJtRsBFnkgk1hGycJPgNc/juaHuGBexLDdPqOy3Zmv1AtzFhvPzOTEFpaIGa5dz
|
||||
vewjDBFBCpFFTqpISD93JX6AbkucPVKnfF97DkBLyj3mr+X9Cy0pLGjwN8Gcp1Ez
|
||||
5MvTqbOmqLypcRJu285K0Yxmv7a38GND7xeoijfnPFjVjYGlacCnI7ps
|
||||
-----END CERTIFICATE-----`)
|
||||
|
||||
var clientKey = []byte(`-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEowIBAAKCAQEA1jCNOxaX7C6bH8YffvoneePNQVAnMejecJqQz+KJHdrwTlOD
|
||||
dqzpBVf21tzUo2AU7xoKzpHnEZ5PvBlgzveBhBy3E48ILWRs4ZCnCXYRG62LD6fI
|
||||
ub0uEt2IwHiT0A6q1fGrAYlrzLkYRz3LQyOQhL0Ca7nB2IeCzY/Vfz0TR2+4bMtY
|
||||
54Go5G+lZRP1N88E2cplS8YEZLPlQqqVS6J15bkpnAMmQWL5x67cUbnXdST4qvns
|
||||
3cSqjjC0LKhOd1aInxdCgwL7dT4lwF64Jz1/25OSUVFN5J5Y8xmPqQWHNtauVTjw
|
||||
/StV1DYfe3LnVhVriQ+aNu/cssfe1Se7x6w7HQIDAQABAoIBACRaOy4jKIfCZTug
|
||||
UaooZNjQK/8AzpYu8snjwd42kZUKmqyAihhzQl1Qz6kp88ECxqrKHblvk+sullPT
|
||||
btXRth6pDP150iZ6G+yws1jsu/yZmLeAf5XeoNo81T/tdxDh3GbRTHfHTg+B/rfg
|
||||
qgXsHFQbDDUiYt8QKMgguFiPEh2WbedyAe1N9LhtEazMhrnLXCUxTXIFddmcKvnk
|
||||
fTcnV6mG4FftXFwh+Qn4HukphENHD+xazxIp/WFGDbbStQ8sbjkUSydU0w5x/eQ/
|
||||
V6z7ibgDmlHoSyKCxc0B0wuNE/BBQzQGvy2T9UhA4V2+vwuQpcXxM77tXMNnmxaX
|
||||
fEXHQBUCgYEA+sYZKOTL7JCJNnGexVVxn6OWZUuSf94LAyVBCveHnItlFgowzwU1
|
||||
NYUFD894SR7orvbnSHvEOvim10C7YoyDcsH5+zt4K7dMnVJ6I6I4mNv0r/1WylHe
|
||||
JyNkYP7jn6znMqVgvo4YHCMrk2OoPIE8jeH1aN+I/YOTi47BIb+MbfcCgYEA2qdG
|
||||
AbgwVoWeQT7Z+3iJxTgaZGjO66Id2164HMK0NGeYjNeWikt58Y5Vitblk6h8JqQy
|
||||
yOipyyIbQFnQbmTo6vlvNTKw2NOrPHkYktridIfFrinYqEmKfhbhQWnZAOTjOnpJ
|
||||
9RFC5LbErmrf5G6HIWV8bfX/kBvi0QbF6VYuKosCgYB2Ztf0PeqmnCuc4BKFu2z1
|
||||
YcidtQvLgawTZSCLrAmEeTBWMqOO6zePOGoGZ/+0DnrwOTVEPOOOsF4d3btbsVpS
|
||||
8ZE09IQtp9LtqMZwUqSET7385hF3XyYTtpsrTM1uU7WpbPn7np11k4l8gp4pSx+r
|
||||
Ide8F2bXw6sDRniblZQZSwKBgQCjN4RZmj1zCLEWcS1UuyjUcEm7NEVpvY1eCLmU
|
||||
tn7AM6i7Ud8NAsRXXXFbf4jGDVoHmkBSmuLMQHxpL+IX1fnMFUA/TMSYRoEnVhnS
|
||||
3dN3OzaECLazAJqB/uBM7Q9QzIsWRtzYM/dkNU5iCGNy6FK0ykX061HHKBnLAKxR
|
||||
vsQdewKBgGCZiy/QYdGR3jdfD7Qytfuptgf6zFLB0BqHJTG/YmnonCDTI8ZxmDOF
|
||||
DspoiVbrjYdHED0IfcnXYNK8+Bv/2vVxAGqqCdA/aJbFXx86zKJvu8ZHcFrWl6Fy
|
||||
vdk6OsJjqpA0RM/lD2kVvHeaBO44qGmMFfZHv52ONu+wE4mVX6Y8
|
||||
-----END RSA PRIVATE KEY-----`)
|
||||
|
||||
var clientCert = []byte(`-----BEGIN CERTIFICATE-----
|
||||
MIIDOzCCAiOgAwIBAgIJAPJEHs7Aav1kMA0GCSqGSIb3DQEBCwUAMDQxMjAwBgNV
|
||||
BAMMKWdlbmVyaWNfd2ViaG9va19hZG1pc3Npb25fcGx1Z2luX3Rlc3RzX2NhMCAX
|
||||
DTE3MDkxMzAwMTAwNFoYDzIyOTEwNjI5MDAxMDA0WjA4MTYwNAYDVQQDFC1nZW5l
|
||||
cmljX3dlYmhvb2tfYWRtaXNzaW9uX3BsdWdpbl90ZXN0c19jbGllbnQwggEiMA0G
|
||||
CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDWMI07FpfsLpsfxh9++id5481BUCcx
|
||||
6N5wmpDP4okd2vBOU4N2rOkFV/bW3NSjYBTvGgrOkecRnk+8GWDO94GEHLcTjwgt
|
||||
ZGzhkKcJdhEbrYsPp8i5vS4S3YjAeJPQDqrV8asBiWvMuRhHPctDI5CEvQJrucHY
|
||||
h4LNj9V/PRNHb7hsy1jngajkb6VlE/U3zwTZymVLxgRks+VCqpVLonXluSmcAyZB
|
||||
YvnHrtxRudd1JPiq+ezdxKqOMLQsqE53VoifF0KDAvt1PiXAXrgnPX/bk5JRUU3k
|
||||
nljzGY+pBYc21q5VOPD9K1XUNh97cudWFWuJD5o279yyx97VJ7vHrDsdAgMBAAGj
|
||||
SjBIMAkGA1UdEwQCMAAwCwYDVR0PBAQDAgXgMB0GA1UdJQQWMBQGCCsGAQUFBwMC
|
||||
BggrBgEFBQcDATAPBgNVHREECDAGhwR/AAABMA0GCSqGSIb3DQEBCwUAA4IBAQBh
|
||||
cqu6S6MkUUtNhlWR33ZfV6Ewoz06IGtUIUDDuRmVuizCDOdCcGOTDvdoXtbZMwUf
|
||||
ZRVVaSyIjqdz5k+C06mHM7uEEgo+Xo7YolK1AiW9VflG8K47l/+XlLoHFv0eB9k/
|
||||
KdlFkzh3pszM4uEiynkLlSpQxyyBOhyaVdQlXdamqmSfIO0HlLza1OAP2rMILeMb
|
||||
GJ0y+DCxxAspwVvmCUzc5nL6t35+oEDihRk9bjGDLhfh+b0AYSO4RUjzhNlayUBG
|
||||
/Kbxh6GiimYmWwpIUTcTAbO7gB7Ya5eXmEB80McS0Z6MY/AEBHnu2Cy8BVEDY30f
|
||||
uOhGOj+iPQxidcxc+wuy
|
||||
-----END CERTIFICATE-----`)
|
||||
18
vendor/k8s.io/kubernetes/plugin/pkg/admission/webhook/doc.go
generated
vendored
Normal file
18
vendor/k8s.io/kubernetes/plugin/pkg/admission/webhook/doc.go
generated
vendored
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
Copyright 2017 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 checks a webhook for configured operation admission
|
||||
package webhook // import "k8s.io/kubernetes/plugin/pkg/admission/webhook"
|
||||
107
vendor/k8s.io/kubernetes/plugin/pkg/admission/webhook/gencerts.sh
generated
vendored
Executable file
107
vendor/k8s.io/kubernetes/plugin/pkg/admission/webhook/gencerts.sh
generated
vendored
Executable file
|
|
@ -0,0 +1,107 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Copyright 2017 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 generic webhook admission plugin tests.
|
||||
#
|
||||
# It is not expected to be run often (there is no go generate rule), and mainly
|
||||
# exists for documentation purposes.
|
||||
|
||||
CN_BASE="generic_webhook_admission_plugin_tests"
|
||||
|
||||
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 = clientAuth, 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, serverAuth
|
||||
subjectAltName = @alt_names
|
||||
[alt_names]
|
||||
IP.1 = 127.0.0.1
|
||||
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=${CN_BASE}_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=${CN_BASE}_ca"
|
||||
|
||||
# Create a server certiticate
|
||||
openssl genrsa -out serverKey.pem 2048
|
||||
openssl req -new -key serverKey.pem -out server.csr -subj "/CN=webhook-test.default.svc" -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=${CN_BASE}_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 2017 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
|
||||
94
vendor/k8s.io/kubernetes/plugin/pkg/admission/webhook/rules.go
generated
vendored
Normal file
94
vendor/k8s.io/kubernetes/plugin/pkg/admission/webhook/rules.go
generated
vendored
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
Copyright 2017 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 checks a webhook for configured operation admission
|
||||
package webhook
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"k8s.io/api/admissionregistration/v1alpha1"
|
||||
"k8s.io/apiserver/pkg/admission"
|
||||
)
|
||||
|
||||
type RuleMatcher struct {
|
||||
Rule v1alpha1.RuleWithOperations
|
||||
Attr admission.Attributes
|
||||
}
|
||||
|
||||
func (r *RuleMatcher) Matches() bool {
|
||||
return r.operation() &&
|
||||
r.group() &&
|
||||
r.version() &&
|
||||
r.resource()
|
||||
}
|
||||
|
||||
func exactOrWildcard(items []string, requested string) bool {
|
||||
for _, item := range items {
|
||||
if item == "*" {
|
||||
return true
|
||||
}
|
||||
if item == requested {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (r *RuleMatcher) group() bool {
|
||||
return exactOrWildcard(r.Rule.APIGroups, r.Attr.GetResource().Group)
|
||||
}
|
||||
|
||||
func (r *RuleMatcher) version() bool {
|
||||
return exactOrWildcard(r.Rule.APIVersions, r.Attr.GetResource().Version)
|
||||
}
|
||||
|
||||
func (r *RuleMatcher) operation() bool {
|
||||
attrOp := r.Attr.GetOperation()
|
||||
for _, op := range r.Rule.Operations {
|
||||
if op == v1alpha1.OperationAll {
|
||||
return true
|
||||
}
|
||||
// The constants are the same such that this is a valid cast (and this
|
||||
// is tested).
|
||||
if op == v1alpha1.OperationType(attrOp) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func splitResource(resSub string) (res, sub string) {
|
||||
parts := strings.SplitN(resSub, "/", 2)
|
||||
if len(parts) == 2 {
|
||||
return parts[0], parts[1]
|
||||
}
|
||||
return parts[0], ""
|
||||
}
|
||||
|
||||
func (r *RuleMatcher) resource() bool {
|
||||
opRes, opSub := r.Attr.GetResource().Resource, r.Attr.GetSubresource()
|
||||
for _, res := range r.Rule.Resources {
|
||||
res, sub := splitResource(res)
|
||||
resMatch := res == "*" || res == opRes
|
||||
subMatch := sub == "*" || sub == opSub
|
||||
if resMatch && subMatch {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
300
vendor/k8s.io/kubernetes/plugin/pkg/admission/webhook/rules_test.go
generated
vendored
Normal file
300
vendor/k8s.io/kubernetes/plugin/pkg/admission/webhook/rules_test.go
generated
vendored
Normal file
|
|
@ -0,0 +1,300 @@
|
|||
/*
|
||||
Copyright 2017 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 (
|
||||
"testing"
|
||||
|
||||
adreg "k8s.io/api/admissionregistration/v1alpha1"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apiserver/pkg/admission"
|
||||
)
|
||||
|
||||
type ruleTest struct {
|
||||
rule adreg.RuleWithOperations
|
||||
match []admission.Attributes
|
||||
noMatch []admission.Attributes
|
||||
}
|
||||
type tests map[string]ruleTest
|
||||
|
||||
func a(group, version, resource, subresource, name string, operation admission.Operation) admission.Attributes {
|
||||
return admission.NewAttributesRecord(
|
||||
nil, nil,
|
||||
schema.GroupVersionKind{Group: group, Version: version, Kind: "k" + resource},
|
||||
"ns", name,
|
||||
schema.GroupVersionResource{Group: group, Version: version, Resource: resource}, subresource,
|
||||
operation,
|
||||
nil,
|
||||
)
|
||||
}
|
||||
|
||||
func attrList(a ...admission.Attributes) []admission.Attributes {
|
||||
return a
|
||||
}
|
||||
|
||||
func TestGroup(t *testing.T) {
|
||||
table := tests{
|
||||
"wildcard": {
|
||||
rule: adreg.RuleWithOperations{
|
||||
Rule: adreg.Rule{
|
||||
APIGroups: []string{"*"},
|
||||
},
|
||||
},
|
||||
match: attrList(
|
||||
a("g", "v", "r", "", "name", admission.Create),
|
||||
),
|
||||
},
|
||||
"exact": {
|
||||
rule: adreg.RuleWithOperations{
|
||||
Rule: adreg.Rule{
|
||||
APIGroups: []string{"g1", "g2"},
|
||||
},
|
||||
},
|
||||
match: attrList(
|
||||
a("g1", "v", "r", "", "name", admission.Create),
|
||||
a("g2", "v2", "r3", "", "name", admission.Create),
|
||||
),
|
||||
noMatch: attrList(
|
||||
a("g3", "v", "r", "", "name", admission.Create),
|
||||
a("g4", "v", "r", "", "name", admission.Create),
|
||||
),
|
||||
},
|
||||
}
|
||||
|
||||
for name, tt := range table {
|
||||
for _, m := range tt.match {
|
||||
r := RuleMatcher{tt.rule, m}
|
||||
if !r.group() {
|
||||
t.Errorf("%v: expected match %#v", name, m)
|
||||
}
|
||||
}
|
||||
for _, m := range tt.noMatch {
|
||||
r := RuleMatcher{tt.rule, m}
|
||||
if r.group() {
|
||||
t.Errorf("%v: expected no match %#v", name, m)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestVersion(t *testing.T) {
|
||||
table := tests{
|
||||
"wildcard": {
|
||||
rule: adreg.RuleWithOperations{
|
||||
Rule: adreg.Rule{
|
||||
APIVersions: []string{"*"},
|
||||
},
|
||||
},
|
||||
match: attrList(
|
||||
a("g", "v", "r", "", "name", admission.Create),
|
||||
),
|
||||
},
|
||||
"exact": {
|
||||
rule: adreg.RuleWithOperations{
|
||||
Rule: adreg.Rule{
|
||||
APIVersions: []string{"v1", "v2"},
|
||||
},
|
||||
},
|
||||
match: attrList(
|
||||
a("g1", "v1", "r", "", "name", admission.Create),
|
||||
a("g2", "v2", "r", "", "name", admission.Create),
|
||||
),
|
||||
noMatch: attrList(
|
||||
a("g1", "v3", "r", "", "name", admission.Create),
|
||||
a("g2", "v4", "r", "", "name", admission.Create),
|
||||
),
|
||||
},
|
||||
}
|
||||
for name, tt := range table {
|
||||
for _, m := range tt.match {
|
||||
r := RuleMatcher{tt.rule, m}
|
||||
if !r.version() {
|
||||
t.Errorf("%v: expected match %#v", name, m)
|
||||
}
|
||||
}
|
||||
for _, m := range tt.noMatch {
|
||||
r := RuleMatcher{tt.rule, m}
|
||||
if r.version() {
|
||||
t.Errorf("%v: expected no match %#v", name, m)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestOperation(t *testing.T) {
|
||||
table := tests{
|
||||
"wildcard": {
|
||||
rule: adreg.RuleWithOperations{Operations: []adreg.OperationType{adreg.OperationAll}},
|
||||
match: attrList(
|
||||
a("g", "v", "r", "", "name", admission.Create),
|
||||
a("g", "v", "r", "", "name", admission.Update),
|
||||
a("g", "v", "r", "", "name", admission.Delete),
|
||||
a("g", "v", "r", "", "name", admission.Connect),
|
||||
),
|
||||
},
|
||||
"create": {
|
||||
rule: adreg.RuleWithOperations{Operations: []adreg.OperationType{adreg.Create}},
|
||||
match: attrList(
|
||||
a("g", "v", "r", "", "name", admission.Create),
|
||||
),
|
||||
noMatch: attrList(
|
||||
a("g", "v", "r", "", "name", admission.Update),
|
||||
a("g", "v", "r", "", "name", admission.Delete),
|
||||
a("g", "v", "r", "", "name", admission.Connect),
|
||||
),
|
||||
},
|
||||
"update": {
|
||||
rule: adreg.RuleWithOperations{Operations: []adreg.OperationType{adreg.Update}},
|
||||
match: attrList(
|
||||
a("g", "v", "r", "", "name", admission.Update),
|
||||
),
|
||||
noMatch: attrList(
|
||||
a("g", "v", "r", "", "name", admission.Create),
|
||||
a("g", "v", "r", "", "name", admission.Delete),
|
||||
a("g", "v", "r", "", "name", admission.Connect),
|
||||
),
|
||||
},
|
||||
"delete": {
|
||||
rule: adreg.RuleWithOperations{Operations: []adreg.OperationType{adreg.Delete}},
|
||||
match: attrList(
|
||||
a("g", "v", "r", "", "name", admission.Delete),
|
||||
),
|
||||
noMatch: attrList(
|
||||
a("g", "v", "r", "", "name", admission.Create),
|
||||
a("g", "v", "r", "", "name", admission.Update),
|
||||
a("g", "v", "r", "", "name", admission.Connect),
|
||||
),
|
||||
},
|
||||
"connect": {
|
||||
rule: adreg.RuleWithOperations{Operations: []adreg.OperationType{adreg.Connect}},
|
||||
match: attrList(
|
||||
a("g", "v", "r", "", "name", admission.Connect),
|
||||
),
|
||||
noMatch: attrList(
|
||||
a("g", "v", "r", "", "name", admission.Create),
|
||||
a("g", "v", "r", "", "name", admission.Update),
|
||||
a("g", "v", "r", "", "name", admission.Delete),
|
||||
),
|
||||
},
|
||||
"multiple": {
|
||||
rule: adreg.RuleWithOperations{Operations: []adreg.OperationType{adreg.Update, adreg.Delete}},
|
||||
match: attrList(
|
||||
a("g", "v", "r", "", "name", admission.Update),
|
||||
a("g", "v", "r", "", "name", admission.Delete),
|
||||
),
|
||||
noMatch: attrList(
|
||||
a("g", "v", "r", "", "name", admission.Create),
|
||||
a("g", "v", "r", "", "name", admission.Connect),
|
||||
),
|
||||
},
|
||||
}
|
||||
for name, tt := range table {
|
||||
for _, m := range tt.match {
|
||||
r := RuleMatcher{tt.rule, m}
|
||||
if !r.operation() {
|
||||
t.Errorf("%v: expected match %#v", name, m)
|
||||
}
|
||||
}
|
||||
for _, m := range tt.noMatch {
|
||||
r := RuleMatcher{tt.rule, m}
|
||||
if r.operation() {
|
||||
t.Errorf("%v: expected no match %#v", name, m)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestResource(t *testing.T) {
|
||||
table := tests{
|
||||
"no subresources": {
|
||||
rule: adreg.RuleWithOperations{
|
||||
Rule: adreg.Rule{
|
||||
Resources: []string{"*"},
|
||||
},
|
||||
},
|
||||
match: attrList(
|
||||
a("g", "v", "r", "", "name", admission.Create),
|
||||
a("2", "v", "r2", "", "name", admission.Create),
|
||||
),
|
||||
noMatch: attrList(
|
||||
a("g", "v", "r", "exec", "name", admission.Create),
|
||||
a("2", "v", "r2", "proxy", "name", admission.Create),
|
||||
),
|
||||
},
|
||||
"r & subresources": {
|
||||
rule: adreg.RuleWithOperations{
|
||||
Rule: adreg.Rule{
|
||||
Resources: []string{"r/*"},
|
||||
},
|
||||
},
|
||||
match: attrList(
|
||||
a("g", "v", "r", "", "name", admission.Create),
|
||||
a("g", "v", "r", "exec", "name", admission.Create),
|
||||
),
|
||||
noMatch: attrList(
|
||||
a("2", "v", "r2", "", "name", admission.Create),
|
||||
a("2", "v", "r2", "proxy", "name", admission.Create),
|
||||
),
|
||||
},
|
||||
"r & subresources or r2": {
|
||||
rule: adreg.RuleWithOperations{
|
||||
Rule: adreg.Rule{
|
||||
Resources: []string{"r/*", "r2"},
|
||||
},
|
||||
},
|
||||
match: attrList(
|
||||
a("g", "v", "r", "", "name", admission.Create),
|
||||
a("g", "v", "r", "exec", "name", admission.Create),
|
||||
a("2", "v", "r2", "", "name", admission.Create),
|
||||
),
|
||||
noMatch: attrList(
|
||||
a("2", "v", "r2", "proxy", "name", admission.Create),
|
||||
),
|
||||
},
|
||||
"proxy or exec": {
|
||||
rule: adreg.RuleWithOperations{
|
||||
Rule: adreg.Rule{
|
||||
Resources: []string{"*/proxy", "*/exec"},
|
||||
},
|
||||
},
|
||||
match: attrList(
|
||||
a("g", "v", "r", "exec", "name", admission.Create),
|
||||
a("2", "v", "r2", "proxy", "name", admission.Create),
|
||||
a("2", "v", "r3", "proxy", "name", admission.Create),
|
||||
),
|
||||
noMatch: attrList(
|
||||
a("g", "v", "r", "", "name", admission.Create),
|
||||
a("2", "v", "r2", "", "name", admission.Create),
|
||||
a("2", "v", "r4", "scale", "name", admission.Create),
|
||||
),
|
||||
},
|
||||
}
|
||||
for name, tt := range table {
|
||||
for _, m := range tt.match {
|
||||
r := RuleMatcher{tt.rule, m}
|
||||
if !r.resource() {
|
||||
t.Errorf("%v: expected match %#v", name, m)
|
||||
}
|
||||
}
|
||||
for _, m := range tt.noMatch {
|
||||
r := RuleMatcher{tt.rule, m}
|
||||
if r.resource() {
|
||||
t.Errorf("%v: expected no match %#v", name, m)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue