Auto-update dependencies (#125)

Produced via:
  `dep ensure -update knative.dev/test-infra knative.dev/pkg`
/assign mattmoor
This commit is contained in:
mattmoor-sockpuppet 2019-10-30 07:26:13 -07:00 committed by Knative Prow Robot
parent ca2d829d6b
commit 686854829d
8 changed files with 230 additions and 39 deletions

6
Gopkg.lock generated
View File

@ -933,7 +933,7 @@
[[projects]] [[projects]]
branch = "master" branch = "master"
digest = "1:b1b13cac811c873045205cd087aa9d8ce98fc49370e1eac4c4a5838bc9acef31" digest = "1:2cc284a39bc41da614158a089ed2e976cd5461a93ede77f52263c1f3370995c2"
name = "knative.dev/pkg" name = "knative.dev/pkg"
packages = [ packages = [
"apis", "apis",
@ -952,7 +952,7 @@
"metrics/metricskey", "metrics/metricskey",
] ]
pruneopts = "T" pruneopts = "T"
revision = "349698bdf82bc8d8d406ce9ffa183abeafe6fb02" revision = "3732de5802012193835c9fe65436b761ed3fecea"
[[projects]] [[projects]]
branch = "master" branch = "master"
@ -963,7 +963,7 @@
"tools/dep-collector", "tools/dep-collector",
] ]
pruneopts = "UT" pruneopts = "UT"
revision = "bb87d561aa59603ec585dbf145e8d9ced5b19d59" revision = "34a629e61afcc53b94725894cdc4caf70b536ee1"
[[projects]] [[projects]]
digest = "1:8730e0150dfb2b7e173890c8b9868e7a273082ef8e39f4940e3506a481cf895c" digest = "1:8730e0150dfb2b7e173890c8b9868e7a273082ef8e39f4940e3506a481cf895c"

1
vendor/knative.dev/pkg/Gopkg.lock generated vendored
View File

@ -1382,6 +1382,7 @@
"k8s.io/client-go/kubernetes/fake", "k8s.io/client-go/kubernetes/fake",
"k8s.io/client-go/kubernetes/scheme", "k8s.io/client-go/kubernetes/scheme",
"k8s.io/client-go/kubernetes/typed/core/v1", "k8s.io/client-go/kubernetes/typed/core/v1",
"k8s.io/client-go/listers/core/v1",
"k8s.io/client-go/plugin/pkg/client/auth/gcp", "k8s.io/client-go/plugin/pkg/client/auth/gcp",
"k8s.io/client-go/rest", "k8s.io/client-go/rest",
"k8s.io/client-go/testing", "k8s.io/client-go/testing",

View File

@ -44,6 +44,8 @@ import (
"knative.dev/pkg/profiling" "knative.dev/pkg/profiling"
"knative.dev/pkg/signals" "knative.dev/pkg/signals"
"knative.dev/pkg/system" "knative.dev/pkg/system"
"knative.dev/pkg/version"
"knative.dev/pkg/webhook"
) )
// GetConfig returns a rest.Config to be used for kubernetes client creation. // GetConfig returns a rest.Config to be used for kubernetes client creation.
@ -138,13 +140,25 @@ func MainWithConfig(ctx context.Context, component string, cfg *rest.Config, cto
defer flush(logger) defer flush(logger)
ctx = logging.WithLogger(ctx, logger) ctx = logging.WithLogger(ctx, logger)
kc := kubeclient.Get(ctx)
if err := version.CheckMinimumVersion(kc.Discovery()); err != nil {
logger.Fatalw("Version check failed", zap.Error(err))
}
// TODO(mattmoor): This should itself take a context and be injection-based. // TODO(mattmoor): This should itself take a context and be injection-based.
cmw := configmap.NewInformedWatcher(kubeclient.Get(ctx), system.Namespace()) cmw := configmap.NewInformedWatcher(kc, system.Namespace())
// Based on the reconcilers we have linked, build up the set of controllers to run. // Based on the reconcilers we have linked, build up the set of controllers to run.
controllers := make([]*controller.Impl, 0, len(ctors)) controllers := make([]*controller.Impl, 0, len(ctors))
webhooks := make([]webhook.AdmissionController, 0)
for _, cf := range ctors { for _, cf := range ctors {
controllers = append(controllers, cf(ctx, cmw)) ctrl := cf(ctx, cmw)
controllers = append(controllers, ctrl)
// Build a list of any reconcilers that implement webhook.AdmissionController
if ac, ok := ctrl.Reconciler.(webhook.AdmissionController); ok {
webhooks = append(webhooks, ac)
}
} }
profilingHandler := profiling.NewHandler(logger, false) profilingHandler := profiling.NewHandler(logger, false)
@ -176,6 +190,21 @@ func MainWithConfig(ctx context.Context, component string, cfg *rest.Config, cto
eg, egCtx := errgroup.WithContext(ctx) eg, egCtx := errgroup.WithContext(ctx)
eg.Go(profilingServer.ListenAndServe) eg.Go(profilingServer.ListenAndServe)
// If we have one or more admission controllers, then start the webhook
// and pass them in.
if len(webhooks) > 0 {
// Register webhook metrics
webhook.RegisterMetrics()
wh, err := webhook.New(ctx, webhooks)
if err != nil {
logger.Fatalw("Failed to create admission controller", zap.Error(err))
}
eg.Go(func() error {
return wh.Run(ctx.Done())
})
}
// This will block until either a signal arrives or one of the grouped functions // This will block until either a signal arrives or one of the grouped functions
// returns an error. // returns an error.
<-egCtx.Done() <-egCtx.Done()

View File

@ -37,6 +37,7 @@ import (
"knative.dev/pkg/configmap" "knative.dev/pkg/configmap"
"knative.dev/pkg/logging" "knative.dev/pkg/logging"
"knative.dev/pkg/webhook" "knative.dev/pkg/webhook"
certresources "knative.dev/pkg/webhook/certificates/resources"
) )
var ( var (
@ -84,7 +85,7 @@ type APICoverageWebhook struct {
} }
func (acw *APICoverageWebhook) generateServerConfig() (*tls.Config, error) { func (acw *APICoverageWebhook) generateServerConfig() (*tls.Config, error) {
serverKey, serverCert, caCert, err := webhook.CreateCerts(context.Background(), acw.ServiceName, acw.Namespace) serverKey, serverCert, caCert, err := certresources.CreateCerts(context.Background(), acw.ServiceName, acw.Namespace)
if err != nil { if err != nil {
return nil, fmt.Errorf("Error creating webhook certificates: %v", err) return nil, fmt.Errorf("Error creating webhook certificates: %v", err)
} }

View File

@ -1,5 +1,5 @@
/* /*
Copyright 2018 The Knative Authors Copyright 2019 The Knative Authors
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
package webhook package resources
import ( import (
"context" "context"

View File

@ -0,0 +1,54 @@
/*
Copyright 2019 The Knative 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 resources
import (
"context"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
const (
// ServerKey is the name of the key associated with the secret's private key.
ServerKey = "server-key.pem"
// ServerCert is the name of the key associated with the secret's public key.
ServerCert = "server-cert.pem"
// CACert is the name of the key associated with the certificate of the CA for
// the keypair.
CACert = "ca-cert.pem"
)
// MakeSecret synthesizes a Kubernetes Secret object with the keys specified by
// ServerKey, ServerCert, and CACert populated with a fresh certificate.
func MakeSecret(ctx context.Context, name, namespace, serviceName string) (*corev1.Secret, error) {
serverKey, serverCert, caCert, err := CreateCerts(ctx, serviceName, namespace)
if err != nil {
return nil, err
}
return &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
},
Data: map[string][]byte{
ServerKey: serverKey,
ServerCert: serverCert,
CACert: caCert,
},
}, nil
}

View File

@ -0,0 +1,111 @@
/*
Copyright 2019 The Knative 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 testing
import (
"encoding/json"
"sort"
"strings"
"testing"
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
"github.com/mattbaird/jsonpatch"
admissionv1beta1 "k8s.io/api/admission/v1beta1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"knative.dev/pkg/system"
// Makes system.Namespace work in tests.
_ "knative.dev/pkg/system/testing"
. "knative.dev/pkg/testing"
)
// CreateResource creates a testing.Resource with the given name in the system namespace.
func CreateResource(name string) *Resource {
return &Resource{
ObjectMeta: metav1.ObjectMeta{
Namespace: system.Namespace(),
Name: name,
},
Spec: ResourceSpec{
FieldWithValidation: "magic value",
},
}
}
// ExpectAllowed checks that a given admission response allows the initiating request through.
func ExpectAllowed(t *testing.T, resp *admissionv1beta1.AdmissionResponse) {
t.Helper()
if !resp.Allowed {
t.Errorf("Expected allowed, but failed with %+v", resp.Result)
}
}
// ExpectFailsWith checks that a given admission response disallows the initiating request
// through and contains the provided string in its error message.
func ExpectFailsWith(t *testing.T, resp *admissionv1beta1.AdmissionResponse, contains string) {
t.Helper()
if resp.Allowed {
t.Error("Expected denial, got allowed")
return
}
if !strings.Contains(resp.Result.Message, contains) {
t.Errorf("Expected failure containing %q got %q", contains, resp.Result.Message)
}
}
// ExpectPatches checks that the provided serialized bytes consist of an expected
// collection of patches. This is used to verify the mutations made in a mutating
// admission webhook's response.
func ExpectPatches(t *testing.T, a []byte, e []jsonpatch.JsonPatchOperation) {
t.Helper()
var got []jsonpatch.JsonPatchOperation
err := json.Unmarshal(a, &got)
if err != nil {
t.Errorf("Failed to unmarshal patches: %s", err)
return
}
// Give the patch a deterministic ordering.
// Technically this can change the meaning, but the ordering is otherwise unstable
// and difficult to test.
sort.Slice(e, func(i, j int) bool {
lhs, rhs := e[i], e[j]
if lhs.Operation != rhs.Operation {
return lhs.Operation < rhs.Operation
}
return lhs.Path < rhs.Path
})
sort.Slice(got, func(i, j int) bool {
lhs, rhs := got[i], got[j]
if lhs.Operation != rhs.Operation {
return lhs.Operation < rhs.Operation
}
return lhs.Path < rhs.Path
})
// Even though diff is useful, seeing the whole objects
// one under another helps a lot.
t.Logf("Got Patches: %#v", got)
t.Logf("Want Patches: %#v", e)
if diff := cmp.Diff(e, got, cmpopts.EquateEmpty()); diff != "" {
t.Logf("diff Patches: %v", diff)
t.Errorf("ExpectPatches (-want, +got) = %s", diff)
}
}

View File

@ -27,24 +27,20 @@ import (
// Injection stuff // Injection stuff
kubeclient "knative.dev/pkg/client/injection/kube/client" kubeclient "knative.dev/pkg/client/injection/kube/client"
secretinformer "knative.dev/pkg/client/injection/kube/informers/core/v1/secret"
"go.uber.org/zap" "go.uber.org/zap"
"golang.org/x/sync/errgroup" "golang.org/x/sync/errgroup"
"knative.dev/pkg/logging" "knative.dev/pkg/logging"
"knative.dev/pkg/logging/logkey" "knative.dev/pkg/logging/logkey"
"knative.dev/pkg/system" "knative.dev/pkg/system"
certresources "knative.dev/pkg/webhook/certificates/resources"
admissionv1beta1 "k8s.io/api/admission/v1beta1" admissionv1beta1 "k8s.io/api/admission/v1beta1"
corev1 "k8s.io/api/core/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors" apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes" "k8s.io/client-go/kubernetes"
) corelisters "k8s.io/client-go/listers/core/v1"
const (
secretServerKey = "server-key.pem"
secretServerCert = "server-cert.pem"
secretCACert = "ca-cert.pem"
) )
var ( var (
@ -99,6 +95,7 @@ type Webhook struct {
Options Options Options Options
Logger *zap.SugaredLogger Logger *zap.SugaredLogger
admissionControllers map[string]AdmissionController admissionControllers map[string]AdmissionController
secretlister corelisters.SecretLister
} }
// New constructs a Webhook // New constructs a Webhook
@ -108,6 +105,7 @@ func New(
) (*Webhook, error) { ) (*Webhook, error) {
client := kubeclient.Get(ctx) client := kubeclient.Get(ctx)
secretInformer := secretinformer.Get(ctx)
opts := GetOptions(ctx) opts := GetOptions(ctx)
if opts == nil { if opts == nil {
return nil, errors.New("context must have Options specified") return nil, errors.New("context must have Options specified")
@ -133,6 +131,7 @@ func New(
return &Webhook{ return &Webhook{
Client: client, Client: client,
Options: *opts, Options: *opts,
secretlister: secretInformer.Lister(),
admissionControllers: acs, admissionControllers: acs,
Logger: logger, Logger: logger,
}, nil }, nil
@ -145,7 +144,7 @@ func (ac *Webhook) Run(stop <-chan struct{}) error {
// TODO(mattmoor): Separate out the certificate creation process and use listers // TODO(mattmoor): Separate out the certificate creation process and use listers
// to fetch this from the secret below. // to fetch this from the secret below.
serverKey, serverCert, caCert, err := getOrGenerateKeyCertsFromSecret(ctx, ac.Client, &ac.Options) _, _, caCert, err := getOrGenerateKeyCertsFromSecret(ctx, ac.Client, &ac.Options)
if err != nil { if err != nil {
return err return err
} }
@ -155,6 +154,19 @@ func (ac *Webhook) Run(stop <-chan struct{}) error {
Addr: fmt.Sprintf(":%v", ac.Options.Port), Addr: fmt.Sprintf(":%v", ac.Options.Port),
TLSConfig: &tls.Config{ TLSConfig: &tls.Config{
GetCertificate: func(*tls.ClientHelloInfo) (*tls.Certificate, error) { GetCertificate: func(*tls.ClientHelloInfo) (*tls.Certificate, error) {
secret, err := ac.secretlister.Secrets(system.Namespace()).Get(ac.Options.SecretName)
if err != nil {
return nil, err
}
serverKey, ok := secret.Data[certresources.ServerKey]
if !ok {
return nil, errors.New("server key missing")
}
serverCert, ok := secret.Data[certresources.ServerCert]
if !ok {
return nil, errors.New("server cert missing")
}
cert, err := tls.X509KeyPair(serverCert, serverKey) cert, err := tls.X509KeyPair(serverCert, serverKey)
if err != nil { if err != nil {
return nil, err return nil, err
@ -205,7 +217,7 @@ func (ac *Webhook) Run(stop <-chan struct{}) error {
case <-stop: case <-stop:
return server.Close() return server.Close()
case <-ctx.Done(): case <-ctx.Done():
return fmt.Errorf("webhook server bootstrap failed %v", err) return fmt.Errorf("webhook server bootstrap failed %v", ctx.Err())
} }
} }
@ -275,7 +287,8 @@ func getOrGenerateKeyCertsFromSecret(ctx context.Context, client kubernetes.Inte
return nil, nil, nil, err return nil, nil, nil, err
} }
logger.Info("Did not find existing secret, creating one") logger.Info("Did not find existing secret, creating one")
newSecret, err := generateSecret(ctx, options) newSecret, err := certresources.MakeSecret(
ctx, options.SecretName, system.Namespace(), options.ServiceName)
if err != nil { if err != nil {
return nil, nil, nil, err return nil, nil, nil, err
} }
@ -293,13 +306,13 @@ func getOrGenerateKeyCertsFromSecret(ctx context.Context, client kubernetes.Inte
} }
var ok bool var ok bool
if serverKey, ok = secret.Data[secretServerKey]; !ok { if serverKey, ok = secret.Data[certresources.ServerKey]; !ok {
return nil, nil, nil, errors.New("server key missing") return nil, nil, nil, errors.New("server key missing")
} }
if serverCert, ok = secret.Data[secretServerCert]; !ok { if serverCert, ok = secret.Data[certresources.ServerCert]; !ok {
return nil, nil, nil, errors.New("server cert missing") return nil, nil, nil, errors.New("server cert missing")
} }
if caCert, ok = secret.Data[secretCACert]; !ok { if caCert, ok = secret.Data[certresources.CACert]; !ok {
return nil, nil, nil, errors.New("ca cert missing") return nil, nil, nil, errors.New("ca cert missing")
} }
return serverKey, serverCert, caCert, nil return serverKey, serverCert, caCert, nil
@ -312,21 +325,3 @@ func makeErrorStatus(reason string, args ...interface{}) *admissionv1beta1.Admis
Allowed: false, Allowed: false,
} }
} }
func generateSecret(ctx context.Context, options *Options) (*corev1.Secret, error) {
serverKey, serverCert, caCert, err := CreateCerts(ctx, options.ServiceName, system.Namespace())
if err != nil {
return nil, err
}
return &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: options.SecretName,
Namespace: system.Namespace(),
},
Data: map[string][]byte{
secretServerKey: serverKey,
secretServerCert: serverCert,
secretCACert: caCert,
},
}, nil
}