Skip to content

Commit

Permalink
adding TokenReview.auth.k8s.io/v1 webhook support
Browse files Browse the repository at this point in the history
Signed-off-by: Chris Hein <me@chrishein.com>
  • Loading branch information
christopherhein committed Mar 19, 2021
1 parent b5065bd commit 4d07c03
Show file tree
Hide file tree
Showing 13 changed files with 1,172 additions and 0 deletions.
58 changes: 58 additions & 0 deletions examples/tokenreview/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
Copyright 2021 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 main

import (
"os"

_ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
"sigs.k8s.io/controller-runtime/pkg/client/config"
"sigs.k8s.io/controller-runtime/pkg/log"
"sigs.k8s.io/controller-runtime/pkg/log/zap"
"sigs.k8s.io/controller-runtime/pkg/manager"
"sigs.k8s.io/controller-runtime/pkg/manager/signals"
"sigs.k8s.io/controller-runtime/pkg/webhook"
)

func init() {
log.SetLogger(zap.New())
}

func main() {
entryLog := log.Log.WithName("entrypoint")

// Setup a Manager
entryLog.Info("setting up manager")
mgr, err := manager.New(config.GetConfigOrDie(), manager.Options{})
if err != nil {
entryLog.Error(err, "unable to set up overall controller manager")
os.Exit(1)
}

// Setup webhooks
entryLog.Info("setting up webhook server")
hookServer := mgr.GetWebhookServer()

entryLog.Info("registering webhooks to the webhook server")
hookServer.Register("/validate-v1-tokenreview", &webhook.Authentication{Handler: &authenticator{Client: mgr.GetClient()}})

entryLog.Info("starting manager")
if err := mgr.Start(signals.SetupSignalHandler()); err != nil {
entryLog.Error(err, "unable to run manager")
os.Exit(1)
}
}
51 changes: 51 additions & 0 deletions examples/tokenreview/tokenreview.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
Copyright 2021 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 main

import (
"context"

v1 "k8s.io/api/authentication/v1"
"sigs.k8s.io/controller-runtime/pkg/client"

"sigs.k8s.io/controller-runtime/pkg/webhook/authentication"
)

// +kubebuilder:webhook:path=/validate-v1-pod,mutating=false,failurePolicy=fail,groups="",resources=pods,verbs=create;update,versions=v1,name=vpod.kb.io

// authenticator validates tokenreviews
type authenticator struct {
Client client.Client
decoder *authentication.Decoder
}

// authenticator admits a request by the token.
func (v *authenticator) Handle(ctx context.Context, req authentication.Request) authentication.Response {
if req.Spec.Token == "invalid" {
return authentication.Unauthenticated("invalid is an invalid token", v1.UserInfo{})
}
return authentication.Authenticated("", v1.UserInfo{})
}

// authenticator implements authentication.DecoderInjector.
// A decoder will be automatically injected.

// InjectDecoder injects the decoder.
func (v *authenticator) InjectDecoder(d *authentication.Decoder) error {
v.decoder = d
return nil
}
24 changes: 24 additions & 0 deletions pkg/webhook/alias.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package webhook
import (
"gomodules.xyz/jsonpatch/v2"
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
"sigs.k8s.io/controller-runtime/pkg/webhook/authentication"
)

// define some aliases for common bits of the webhook functionality
Expand Down Expand Up @@ -54,6 +55,20 @@ type AdmissionHandler = admission.Handler
// AdmissionDecoder knows how to decode objects from admission requests.
type AdmissionDecoder = admission.Decoder

// AuthenticationRequest defines the input for an authentication handler.
// It contains the token & audiences from the client.
type AuthenticationRequest = authentication.Request

// AuthenticationResponse is the output of an authentication handler.
// It contains a response indicating if a given operation is allowed.
type AuthenticationResponse = authentication.Response

// Authentication is webhook suitable for registration with the server
type Authentication = authentication.Webhook

// AuthenticationHandler knows how to process authentication requests.
type AuthenticationHandler = authentication.Handler

// JSONPatchOp represents a single JSONPatch patch operation.
type JSONPatchOp = jsonpatch.Operation

Expand All @@ -70,4 +85,13 @@ var (

// Errored indicates that an error occurred in the admission request.
Errored = admission.Errored

// Authenticated indicates that the token review should be allowed for the given reason.
Authenticated = authentication.Authenticated

// Unauthenticated indicates that the token review should be unauthorized for the given reson.
Unauthenticated = authentication.Unauthenticated

// AuthenticationErrored indicates that an error occurred in the token review
AuthenticationErrored = authentication.Errored
)
40 changes: 40 additions & 0 deletions pkg/webhook/authentication/authentication_suite_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
Copyright 2021 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 authentication

import (
"testing"

. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"

"sigs.k8s.io/controller-runtime/pkg/envtest/printer"
logf "sigs.k8s.io/controller-runtime/pkg/log"
"sigs.k8s.io/controller-runtime/pkg/log/zap"
)

func TestAuthenticationWebhook(t *testing.T) {
RegisterFailHandler(Fail)
suiteName := "Authentication Webhook Suite"
RunSpecsWithDefaultAndCustomReporters(t, suiteName, []Reporter{printer.NewlineReporter{}, printer.NewProwReporter(suiteName)})
}

var _ = BeforeSuite(func(done Done) {
logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true)))

close(done)
}, 60)
40 changes: 40 additions & 0 deletions pkg/webhook/authentication/decoder.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
Copyright 2021 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 authentication

import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/serializer"
)

// Decoder knows how to decode the contents of a CRD version conversion
// request into a concrete object.
// TODO(droot): consider reusing decoder from admission pkg for this.
type Decoder struct {
codecs serializer.CodecFactory
}

// NewDecoder creates a Decoder given the runtime.Scheme
func NewDecoder(scheme *runtime.Scheme) (*Decoder, error) {
return &Decoder{codecs: serializer.NewCodecFactory(scheme)}, nil
}

// DecodeInto decodes the inlined object in the into the passed-in runtime.Object.
func (d *Decoder) DecodeInto(content []byte, into runtime.Object) error {
deserializer := d.codecs.UniversalDeserializer()
return runtime.DecodeInto(deserializer, content, into)
}
28 changes: 28 additions & 0 deletions pkg/webhook/authentication/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
Copyright 2021 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 authentication provides implementation for authentication webhook and methods to implement authentication webhook handlers.
See examples/authentication.go for an example of authentication webhooks.
*/
package authentication

import (
logf "sigs.k8s.io/controller-runtime/pkg/internal/log"
)

var log = logf.RuntimeLog.WithName("authentication")
Loading

0 comments on commit 4d07c03

Please sign in to comment.