mirror of https://github.com/knative/caching.git
Auto-update dependencies (#125)
Produced via: `dep ensure -update knative.dev/test-infra knative.dev/pkg` /assign mattmoor
This commit is contained in:
parent
ca2d829d6b
commit
686854829d
|
|
@ -933,7 +933,7 @@
|
|||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
digest = "1:b1b13cac811c873045205cd087aa9d8ce98fc49370e1eac4c4a5838bc9acef31"
|
||||
digest = "1:2cc284a39bc41da614158a089ed2e976cd5461a93ede77f52263c1f3370995c2"
|
||||
name = "knative.dev/pkg"
|
||||
packages = [
|
||||
"apis",
|
||||
|
|
@ -952,7 +952,7 @@
|
|||
"metrics/metricskey",
|
||||
]
|
||||
pruneopts = "T"
|
||||
revision = "349698bdf82bc8d8d406ce9ffa183abeafe6fb02"
|
||||
revision = "3732de5802012193835c9fe65436b761ed3fecea"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
|
|
@ -963,7 +963,7 @@
|
|||
"tools/dep-collector",
|
||||
]
|
||||
pruneopts = "UT"
|
||||
revision = "bb87d561aa59603ec585dbf145e8d9ced5b19d59"
|
||||
revision = "34a629e61afcc53b94725894cdc4caf70b536ee1"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:8730e0150dfb2b7e173890c8b9868e7a273082ef8e39f4940e3506a481cf895c"
|
||||
|
|
|
|||
|
|
@ -1382,6 +1382,7 @@
|
|||
"k8s.io/client-go/kubernetes/fake",
|
||||
"k8s.io/client-go/kubernetes/scheme",
|
||||
"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/rest",
|
||||
"k8s.io/client-go/testing",
|
||||
|
|
|
|||
|
|
@ -44,6 +44,8 @@ import (
|
|||
"knative.dev/pkg/profiling"
|
||||
"knative.dev/pkg/signals"
|
||||
"knative.dev/pkg/system"
|
||||
"knative.dev/pkg/version"
|
||||
"knative.dev/pkg/webhook"
|
||||
)
|
||||
|
||||
// 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)
|
||||
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.
|
||||
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.
|
||||
controllers := make([]*controller.Impl, 0, len(ctors))
|
||||
webhooks := make([]webhook.AdmissionController, 0)
|
||||
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)
|
||||
|
|
@ -176,6 +190,21 @@ func MainWithConfig(ctx context.Context, component string, cfg *rest.Config, cto
|
|||
eg, egCtx := errgroup.WithContext(ctx)
|
||||
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
|
||||
// returns an error.
|
||||
<-egCtx.Done()
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ import (
|
|||
"knative.dev/pkg/configmap"
|
||||
"knative.dev/pkg/logging"
|
||||
"knative.dev/pkg/webhook"
|
||||
certresources "knative.dev/pkg/webhook/certificates/resources"
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
@ -84,7 +85,7 @@ type APICoverageWebhook struct {
|
|||
}
|
||||
|
||||
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 {
|
||||
return nil, fmt.Errorf("Error creating webhook certificates: %v", err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright 2018 The Knative Authors
|
||||
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.
|
||||
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
package webhook
|
||||
package resources
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
@ -27,24 +27,20 @@ import (
|
|||
|
||||
// Injection stuff
|
||||
kubeclient "knative.dev/pkg/client/injection/kube/client"
|
||||
secretinformer "knative.dev/pkg/client/injection/kube/informers/core/v1/secret"
|
||||
|
||||
"go.uber.org/zap"
|
||||
"golang.org/x/sync/errgroup"
|
||||
"knative.dev/pkg/logging"
|
||||
"knative.dev/pkg/logging/logkey"
|
||||
"knative.dev/pkg/system"
|
||||
certresources "knative.dev/pkg/webhook/certificates/resources"
|
||||
|
||||
admissionv1beta1 "k8s.io/api/admission/v1beta1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
)
|
||||
|
||||
const (
|
||||
secretServerKey = "server-key.pem"
|
||||
secretServerCert = "server-cert.pem"
|
||||
secretCACert = "ca-cert.pem"
|
||||
corelisters "k8s.io/client-go/listers/core/v1"
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
@ -99,6 +95,7 @@ type Webhook struct {
|
|||
Options Options
|
||||
Logger *zap.SugaredLogger
|
||||
admissionControllers map[string]AdmissionController
|
||||
secretlister corelisters.SecretLister
|
||||
}
|
||||
|
||||
// New constructs a Webhook
|
||||
|
|
@ -108,6 +105,7 @@ func New(
|
|||
) (*Webhook, error) {
|
||||
|
||||
client := kubeclient.Get(ctx)
|
||||
secretInformer := secretinformer.Get(ctx)
|
||||
opts := GetOptions(ctx)
|
||||
if opts == nil {
|
||||
return nil, errors.New("context must have Options specified")
|
||||
|
|
@ -133,6 +131,7 @@ func New(
|
|||
return &Webhook{
|
||||
Client: client,
|
||||
Options: *opts,
|
||||
secretlister: secretInformer.Lister(),
|
||||
admissionControllers: acs,
|
||||
Logger: logger,
|
||||
}, nil
|
||||
|
|
@ -145,7 +144,7 @@ func (ac *Webhook) Run(stop <-chan struct{}) error {
|
|||
|
||||
// TODO(mattmoor): Separate out the certificate creation process and use listers
|
||||
// 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 {
|
||||
return err
|
||||
}
|
||||
|
|
@ -155,6 +154,19 @@ func (ac *Webhook) Run(stop <-chan struct{}) error {
|
|||
Addr: fmt.Sprintf(":%v", ac.Options.Port),
|
||||
TLSConfig: &tls.Config{
|
||||
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)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
@ -205,7 +217,7 @@ func (ac *Webhook) Run(stop <-chan struct{}) error {
|
|||
case <-stop:
|
||||
return server.Close()
|
||||
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
|
||||
}
|
||||
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 {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
|
@ -293,13 +306,13 @@ func getOrGenerateKeyCertsFromSecret(ctx context.Context, client kubernetes.Inte
|
|||
}
|
||||
|
||||
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")
|
||||
}
|
||||
if serverCert, ok = secret.Data[secretServerCert]; !ok {
|
||||
if serverCert, ok = secret.Data[certresources.ServerCert]; !ok {
|
||||
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 serverKey, serverCert, caCert, nil
|
||||
|
|
@ -312,21 +325,3 @@ func makeErrorStatus(reason string, args ...interface{}) *admissionv1beta1.Admis
|
|||
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
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue