vendor dependencies

This commit is contained in:
Sergiusz Urbaniak 2019-04-24 11:06:03 +02:00
parent 604208ef4f
commit 72abf135d6
1156 changed files with 78178 additions and 105799 deletions

View file

@ -0,0 +1,211 @@
/*
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 (
"fmt"
"io/ioutil"
"net/http"
"strings"
"time"
corev1 "k8s.io/api/core/v1"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
)
// AuthenticationInfoResolverWrapper can be used to inject Dial function to the
// rest.Config generated by the resolver.
type AuthenticationInfoResolverWrapper func(AuthenticationInfoResolver) AuthenticationInfoResolver
// NewDefaultAuthenticationInfoResolverWrapper builds a default authn resolver wrapper
func NewDefaultAuthenticationInfoResolverWrapper(
proxyTransport *http.Transport,
kubeapiserverClientConfig *rest.Config) AuthenticationInfoResolverWrapper {
webhookAuthResolverWrapper := func(delegate AuthenticationInfoResolver) AuthenticationInfoResolver {
return &AuthenticationInfoResolverDelegator{
ClientConfigForFunc: func(server string) (*rest.Config, error) {
if server == "kubernetes.default.svc" {
return kubeapiserverClientConfig, nil
}
return delegate.ClientConfigFor(server)
},
ClientConfigForServiceFunc: func(serviceName, serviceNamespace string) (*rest.Config, error) {
if serviceName == "kubernetes" && serviceNamespace == corev1.NamespaceDefault {
return kubeapiserverClientConfig, nil
}
ret, err := delegate.ClientConfigForService(serviceName, serviceNamespace)
if err != nil {
return nil, err
}
if proxyTransport != nil && proxyTransport.DialContext != nil {
ret.Dial = proxyTransport.DialContext
}
return ret, err
},
}
}
return webhookAuthResolverWrapper
}
// AuthenticationInfoResolver builds rest.Config base on the server or service
// name and service namespace.
type AuthenticationInfoResolver interface {
// ClientConfigFor builds rest.Config based on the server.
ClientConfigFor(server string) (*rest.Config, error)
// ClientConfigForService builds rest.Config based on the serviceName and
// serviceNamespace.
ClientConfigForService(serviceName, serviceNamespace string) (*rest.Config, error)
}
// AuthenticationInfoResolverDelegator implements AuthenticationInfoResolver.
type AuthenticationInfoResolverDelegator struct {
ClientConfigForFunc func(server string) (*rest.Config, error)
ClientConfigForServiceFunc func(serviceName, serviceNamespace string) (*rest.Config, error)
}
// ClientConfigFor returns client config for given server.
func (a *AuthenticationInfoResolverDelegator) ClientConfigFor(server string) (*rest.Config, error) {
return a.ClientConfigForFunc(server)
}
// ClientConfigForService returns client config for given service.
func (a *AuthenticationInfoResolverDelegator) ClientConfigForService(serviceName, serviceNamespace string) (*rest.Config, error) {
return a.ClientConfigForServiceFunc(serviceName, serviceNamespace)
}
type defaultAuthenticationInfoResolver struct {
kubeconfig clientcmdapi.Config
}
// NewDefaultAuthenticationInfoResolver generates an AuthenticationInfoResolver
// that builds rest.Config based on the kubeconfig file. kubeconfigFile is the
// path to the kubeconfig.
func NewDefaultAuthenticationInfoResolver(kubeconfigFile string) (AuthenticationInfoResolver, error) {
if len(kubeconfigFile) == 0 {
return &defaultAuthenticationInfoResolver{}, nil
}
loadingRules := clientcmd.NewDefaultClientConfigLoadingRules()
loadingRules.ExplicitPath = kubeconfigFile
loader := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(loadingRules, &clientcmd.ConfigOverrides{})
clientConfig, err := loader.RawConfig()
if err != nil {
return nil, err
}
return &defaultAuthenticationInfoResolver{kubeconfig: clientConfig}, nil
}
func (c *defaultAuthenticationInfoResolver) ClientConfigFor(server string) (*rest.Config, error) {
return c.clientConfig(server)
}
func (c *defaultAuthenticationInfoResolver) ClientConfigForService(serviceName, serviceNamespace string) (*rest.Config, error) {
return c.clientConfig(serviceName + "." + serviceNamespace + ".svc")
}
func (c *defaultAuthenticationInfoResolver) clientConfig(target string) (*rest.Config, error) {
// exact match
if authConfig, ok := c.kubeconfig.AuthInfos[target]; ok {
return restConfigFromKubeconfig(authConfig)
}
// star prefixed match
serverSteps := strings.Split(target, ".")
for i := 1; i < len(serverSteps); i++ {
nickName := "*." + strings.Join(serverSteps[i:], ".")
if authConfig, ok := c.kubeconfig.AuthInfos[nickName]; ok {
return restConfigFromKubeconfig(authConfig)
}
}
// if we're trying to hit the kube-apiserver and there wasn't an explicit config, use the in-cluster config
if target == "kubernetes.default.svc" {
// if we can find an in-cluster-config use that. If we can't, fall through.
inClusterConfig, err := rest.InClusterConfig()
if err == nil {
return setGlobalDefaults(inClusterConfig), nil
}
}
// star (default) match
if authConfig, ok := c.kubeconfig.AuthInfos["*"]; ok {
return restConfigFromKubeconfig(authConfig)
}
// use the current context from the kubeconfig if possible
if len(c.kubeconfig.CurrentContext) > 0 {
if currContext, ok := c.kubeconfig.Contexts[c.kubeconfig.CurrentContext]; ok {
if len(currContext.AuthInfo) > 0 {
if currAuth, ok := c.kubeconfig.AuthInfos[currContext.AuthInfo]; ok {
return restConfigFromKubeconfig(currAuth)
}
}
}
}
// anonymous
return setGlobalDefaults(&rest.Config{}), nil
}
func restConfigFromKubeconfig(configAuthInfo *clientcmdapi.AuthInfo) (*rest.Config, error) {
config := &rest.Config{}
// blindly overwrite existing values based on precedence
if len(configAuthInfo.Token) > 0 {
config.BearerToken = configAuthInfo.Token
} else if len(configAuthInfo.TokenFile) > 0 {
tokenBytes, err := ioutil.ReadFile(configAuthInfo.TokenFile)
if err != nil {
return nil, err
}
config.BearerToken = string(tokenBytes)
config.BearerTokenFile = configAuthInfo.TokenFile
}
if len(configAuthInfo.Impersonate) > 0 {
config.Impersonate = rest.ImpersonationConfig{
UserName: configAuthInfo.Impersonate,
Groups: configAuthInfo.ImpersonateGroups,
Extra: configAuthInfo.ImpersonateUserExtra,
}
}
if len(configAuthInfo.ClientCertificate) > 0 || len(configAuthInfo.ClientCertificateData) > 0 {
config.CertFile = configAuthInfo.ClientCertificate
config.CertData = configAuthInfo.ClientCertificateData
config.KeyFile = configAuthInfo.ClientKey
config.KeyData = configAuthInfo.ClientKeyData
}
if len(configAuthInfo.Username) > 0 || len(configAuthInfo.Password) > 0 {
config.Username = configAuthInfo.Username
config.Password = configAuthInfo.Password
}
if configAuthInfo.AuthProvider != nil {
return nil, fmt.Errorf("auth provider not supported")
}
return setGlobalDefaults(config), nil
}
func setGlobalDefaults(config *rest.Config) *rest.Config {
config.UserAgent = "kube-apiserver-admission"
config.Timeout = 30 * time.Second
return config
}

198
vendor/k8s.io/apiserver/pkg/util/webhook/client.go generated vendored Normal file
View file

@ -0,0 +1,198 @@
/*
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 (
"context"
"encoding/json"
"errors"
"fmt"
"net"
"net/url"
"github.com/hashicorp/golang-lru"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/runtime/serializer"
utilerrors "k8s.io/apimachinery/pkg/util/errors"
"k8s.io/client-go/rest"
)
const (
defaultCacheSize = 200
)
// ClientConfig defines parameters required for creating a hook client.
type ClientConfig struct {
Name string
URL string
CABundle []byte
Service *ClientConfigService
}
// ClientConfigService defines service discovery parameters of the webhook.
type ClientConfigService struct {
Name string
Namespace string
Path string
}
// ClientManager builds REST clients to talk to webhooks. It caches the clients
// to avoid duplicate creation.
type ClientManager struct {
authInfoResolver AuthenticationInfoResolver
serviceResolver ServiceResolver
negotiatedSerializer runtime.NegotiatedSerializer
cache *lru.Cache
}
// NewClientManager creates a clientManager.
func NewClientManager(gv schema.GroupVersion, addToSchemaFunc func(s *runtime.Scheme) error) (ClientManager, error) {
cache, err := lru.New(defaultCacheSize)
if err != nil {
return ClientManager{}, err
}
hookScheme := runtime.NewScheme()
if err := addToSchemaFunc(hookScheme); err != nil {
return ClientManager{}, err
}
return ClientManager{
cache: cache,
negotiatedSerializer: serializer.NegotiatedSerializerWrapper(runtime.SerializerInfo{
Serializer: serializer.NewCodecFactory(hookScheme).LegacyCodec(gv),
}),
}, nil
}
// SetAuthenticationInfoResolverWrapper sets the
// AuthenticationInfoResolverWrapper.
func (cm *ClientManager) SetAuthenticationInfoResolverWrapper(wrapper AuthenticationInfoResolverWrapper) {
if wrapper != nil {
cm.authInfoResolver = wrapper(cm.authInfoResolver)
}
}
// SetAuthenticationInfoResolver sets the AuthenticationInfoResolver.
func (cm *ClientManager) SetAuthenticationInfoResolver(resolver AuthenticationInfoResolver) {
cm.authInfoResolver = resolver
}
// SetServiceResolver sets the ServiceResolver.
func (cm *ClientManager) SetServiceResolver(sr ServiceResolver) {
if sr != nil {
cm.serviceResolver = sr
}
}
// Validate checks if ClientManager is properly set up.
func (cm *ClientManager) Validate() error {
var errs []error
if cm.negotiatedSerializer == nil {
errs = append(errs, fmt.Errorf("the clientManager requires a negotiatedSerializer"))
}
if cm.serviceResolver == nil {
errs = append(errs, fmt.Errorf("the clientManager requires a serviceResolver"))
}
if cm.authInfoResolver == nil {
errs = append(errs, fmt.Errorf("the clientManager requires an authInfoResolver"))
}
return utilerrors.NewAggregate(errs)
}
// HookClient get a RESTClient from the cache, or constructs one based on the
// webhook configuration.
func (cm *ClientManager) HookClient(cc ClientConfig) (*rest.RESTClient, error) {
ccWithNoName := cc
ccWithNoName.Name = ""
cacheKey, err := json.Marshal(ccWithNoName)
if err != nil {
return nil, err
}
if client, ok := cm.cache.Get(string(cacheKey)); ok {
return client.(*rest.RESTClient), nil
}
complete := func(cfg *rest.Config) (*rest.RESTClient, error) {
// Combine CAData from the config with any existing CA bundle provided
if len(cfg.TLSClientConfig.CAData) > 0 {
cfg.TLSClientConfig.CAData = append(cfg.TLSClientConfig.CAData, '\n')
}
cfg.TLSClientConfig.CAData = append(cfg.TLSClientConfig.CAData, cc.CABundle...)
cfg.ContentConfig.NegotiatedSerializer = cm.negotiatedSerializer
cfg.ContentConfig.ContentType = runtime.ContentTypeJSON
client, err := rest.UnversionedRESTClientFor(cfg)
if err == nil {
cm.cache.Add(string(cacheKey), client)
}
return client, err
}
if cc.Service != nil {
restConfig, err := cm.authInfoResolver.ClientConfigForService(cc.Service.Name, cc.Service.Namespace)
if err != nil {
return nil, err
}
cfg := rest.CopyConfig(restConfig)
serverName := cc.Service.Name + "." + cc.Service.Namespace + ".svc"
host := serverName + ":443"
cfg.Host = "https://" + host
cfg.APIPath = cc.Service.Path
// Set the server name if not already set
if len(cfg.TLSClientConfig.ServerName) == 0 {
cfg.TLSClientConfig.ServerName = serverName
}
delegateDialer := cfg.Dial
if delegateDialer == nil {
var d net.Dialer
delegateDialer = d.DialContext
}
cfg.Dial = func(ctx context.Context, network, addr string) (net.Conn, error) {
if addr == host {
u, err := cm.serviceResolver.ResolveEndpoint(cc.Service.Namespace, cc.Service.Name)
if err != nil {
return nil, err
}
addr = u.Host
}
return delegateDialer(ctx, network, addr)
}
return complete(cfg)
}
if cc.URL == "" {
return nil, &ErrCallingWebhook{WebhookName: cc.Name, Reason: errors.New("webhook configuration must have either service or URL")}
}
u, err := url.Parse(cc.URL)
if err != nil {
return nil, &ErrCallingWebhook{WebhookName: cc.Name, Reason: fmt.Errorf("Unparsable URL: %v", err)}
}
restConfig, err := cm.authInfoResolver.ClientConfigFor(u.Host)
if err != nil {
return nil, err
}
cfg := rest.CopyConfig(restConfig)
cfg.Host = u.Scheme + "://" + u.Host
cfg.APIPath = u.Path
return complete(cfg)
}

34
vendor/k8s.io/apiserver/pkg/util/webhook/error.go generated vendored Normal file
View file

@ -0,0 +1,34 @@
/*
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 "fmt"
// ErrCallingWebhook is returned for transport-layer errors calling webhooks. It
// represents a failure to talk to the webhook, not the webhook rejecting a
// request.
type ErrCallingWebhook struct {
WebhookName string
Reason error
}
func (e *ErrCallingWebhook) Error() string {
if e.Reason != nil {
return fmt.Sprintf("failed calling webhook %q: %v", e.WebhookName, e.Reason)
}
return fmt.Sprintf("failed calling webhook %q; no further details available", e.WebhookName)
}

View file

@ -88,12 +88,12 @@ 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
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
@ -101,7 +101,7 @@ for file in caKey caCert badCAKey badCACert serverKey serverCert clientKey clien
done
# Clean up after we're done.
rm *.pem
rm *.csr
rm *.srl
rm *.conf
rm ./*.pem
rm ./*.csr
rm ./*.srl
rm ./*.conf

View file

@ -0,0 +1,46 @@
/*
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 (
"errors"
"fmt"
"net/url"
)
// ServiceResolver knows how to convert a service reference into an actual location.
type ServiceResolver interface {
ResolveEndpoint(namespace, name string) (*url.URL, error)
}
type defaultServiceResolver struct{}
// NewDefaultServiceResolver creates a new default server resolver.
func NewDefaultServiceResolver() ServiceResolver {
return &defaultServiceResolver{}
}
// ResolveEndpoint constructs a service URL from a given namespace and name
// note that the name and namespace are required and by default all created addresses use HTTPS scheme.
// for example:
// name=ross namespace=andromeda resolves to https://ross.andromeda.svc:443
func (sr defaultServiceResolver) ResolveEndpoint(namespace, name string) (*url.URL, error) {
if len(name) == 0 || len(namespace) == 0 {
return nil, errors.New("cannot resolve an empty service name or namespace")
}
return &url.URL{Scheme: "https", Host: fmt.Sprintf("%s.%s.svc:443", name, namespace)}, nil
}

101
vendor/k8s.io/apiserver/pkg/util/webhook/validation.go generated vendored Normal file
View file

@ -0,0 +1,101 @@
/*
Copyright 2018 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 (
"fmt"
"net/url"
"strings"
"k8s.io/apimachinery/pkg/util/validation"
"k8s.io/apimachinery/pkg/util/validation/field"
)
// ValidateWebhookURL validates webhook's URL.
func ValidateWebhookURL(fldPath *field.Path, URL string, forceHttps bool) field.ErrorList {
var allErrors field.ErrorList
const form = "; desired format: https://host[/path]"
if u, err := url.Parse(URL); err != nil {
allErrors = append(allErrors, field.Required(fldPath, "url must be a valid URL: "+err.Error()+form))
} else {
if forceHttps && u.Scheme != "https" {
allErrors = append(allErrors, field.Invalid(fldPath, u.Scheme, "'https' is the only allowed URL scheme"+form))
}
if len(u.Host) == 0 {
allErrors = append(allErrors, field.Invalid(fldPath, u.Host, "host must be provided"+form))
}
if u.User != nil {
allErrors = append(allErrors, field.Invalid(fldPath, u.User.String(), "user information is not permitted in the URL"))
}
if len(u.Fragment) != 0 {
allErrors = append(allErrors, field.Invalid(fldPath, u.Fragment, "fragments are not permitted in the URL"))
}
if len(u.RawQuery) != 0 {
allErrors = append(allErrors, field.Invalid(fldPath, u.RawQuery, "query parameters are not permitted in the URL"))
}
}
return allErrors
}
func ValidateWebhookService(fldPath *field.Path, namespace, name string, path *string) field.ErrorList {
var allErrors field.ErrorList
if len(name) == 0 {
allErrors = append(allErrors, field.Required(fldPath.Child("name"), "service name is required"))
}
if len(namespace) == 0 {
allErrors = append(allErrors, field.Required(fldPath.Child("namespace"), "service namespace is required"))
}
if path == nil {
return allErrors
}
// TODO: replace below with url.Parse + verifying that host is empty?
urlPath := *path
if urlPath == "/" || len(urlPath) == 0 {
return allErrors
}
if urlPath == "//" {
allErrors = append(allErrors, field.Invalid(fldPath.Child("path"), urlPath, "segment[0] may not be empty"))
return allErrors
}
if !strings.HasPrefix(urlPath, "/") {
allErrors = append(allErrors, field.Invalid(fldPath.Child("path"), urlPath, "must start with a '/'"))
}
urlPathToCheck := urlPath[1:]
if strings.HasSuffix(urlPathToCheck, "/") {
urlPathToCheck = urlPathToCheck[:len(urlPathToCheck)-1]
}
steps := strings.Split(urlPathToCheck, "/")
for i, step := range steps {
if len(step) == 0 {
allErrors = append(allErrors, field.Invalid(fldPath.Child("path"), urlPath, fmt.Sprintf("segment[%d] may not be empty", i)))
continue
}
failures := validation.IsDNS1123Subdomain(step)
for _, failure := range failures {
allErrors = append(allErrors, field.Invalid(fldPath.Child("path"), urlPath, fmt.Sprintf("segment[%d]: %v", i, failure)))
}
}
return allErrors
}

View file

@ -37,7 +37,7 @@ const defaultRequestTimeout = 30 * time.Second
type GenericWebhook struct {
RestClient *rest.RESTClient
initialBackoff time.Duration
InitialBackoff time.Duration
}
// NewGenericWebhook creates a new GenericWebhook from the provided kubeconfig file.
@ -83,7 +83,7 @@ func newGenericWebhook(scheme *runtime.Scheme, codecFactory serializer.CodecFact
// it returns an error for which apierrors.SuggestsClientDelay() or apierrors.IsInternalError() returns true.
func (g *GenericWebhook) WithExponentialBackoff(webhookFn func() rest.Result) rest.Result {
var result rest.Result
WithExponentialBackoff(g.initialBackoff, func() error {
WithExponentialBackoff(g.InitialBackoff, func() error {
result = webhookFn()
return result.Error()
})