mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-29 14:37:00 +00:00
adds metrics for authentication webhook
This commit is contained in:
parent
6010cbe593
commit
322c18c147
@ -41,11 +41,11 @@ import (
|
|||||||
func BuildAuth(nodeName types.NodeName, client clientset.Interface, config kubeletconfig.KubeletConfiguration) (server.AuthInterface, func(<-chan struct{}), error) {
|
func BuildAuth(nodeName types.NodeName, client clientset.Interface, config kubeletconfig.KubeletConfiguration) (server.AuthInterface, func(<-chan struct{}), error) {
|
||||||
// Get clients, if provided
|
// Get clients, if provided
|
||||||
var (
|
var (
|
||||||
tokenClient authenticationclient.TokenReviewInterface
|
tokenClient authenticationclient.AuthenticationV1Interface
|
||||||
sarClient authorizationclient.SubjectAccessReviewInterface
|
sarClient authorizationclient.SubjectAccessReviewInterface
|
||||||
)
|
)
|
||||||
if client != nil && !reflect.ValueOf(client).IsNil() {
|
if client != nil && !reflect.ValueOf(client).IsNil() {
|
||||||
tokenClient = client.AuthenticationV1().TokenReviews()
|
tokenClient = client.AuthenticationV1()
|
||||||
sarClient = client.AuthorizationV1().SubjectAccessReviews()
|
sarClient = client.AuthorizationV1().SubjectAccessReviews()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,7 +65,7 @@ func BuildAuth(nodeName types.NodeName, client clientset.Interface, config kubel
|
|||||||
}
|
}
|
||||||
|
|
||||||
// BuildAuthn creates an authenticator compatible with the kubelet's needs
|
// BuildAuthn creates an authenticator compatible with the kubelet's needs
|
||||||
func BuildAuthn(client authenticationclient.TokenReviewInterface, authn kubeletconfig.KubeletAuthentication) (authenticator.Request, func(<-chan struct{}), error) {
|
func BuildAuthn(client authenticationclient.AuthenticationV1Interface, authn kubeletconfig.KubeletAuthentication) (authenticator.Request, func(<-chan struct{}), error) {
|
||||||
var dynamicCAContentFromFile *dynamiccertificates.DynamicFileCAContent
|
var dynamicCAContentFromFile *dynamiccertificates.DynamicFileCAContent
|
||||||
var err error
|
var err error
|
||||||
if len(authn.X509.ClientCAFile) > 0 {
|
if len(authn.X509.ClientCAFile) > 0 {
|
||||||
|
@ -42,7 +42,7 @@ type DelegatingAuthenticatorConfig struct {
|
|||||||
Anonymous bool
|
Anonymous bool
|
||||||
|
|
||||||
// TokenAccessReviewClient is a client to do token review. It can be nil. Then every token is ignored.
|
// TokenAccessReviewClient is a client to do token review. It can be nil. Then every token is ignored.
|
||||||
TokenAccessReviewClient authenticationclient.TokenReviewInterface
|
TokenAccessReviewClient authenticationclient.AuthenticationV1Interface
|
||||||
|
|
||||||
// TokenAccessReviewTimeout specifies a time limit for requests made by the authorization webhook client.
|
// TokenAccessReviewTimeout specifies a time limit for requests made by the authorization webhook client.
|
||||||
TokenAccessReviewTimeout time.Duration
|
TokenAccessReviewTimeout time.Duration
|
||||||
@ -91,7 +91,10 @@ func (c DelegatingAuthenticatorConfig) New() (authenticator.Request, *spec.Secur
|
|||||||
if c.WebhookRetryBackoff == nil {
|
if c.WebhookRetryBackoff == nil {
|
||||||
return nil, nil, errors.New("retry backoff parameters for delegating authentication webhook has not been specified")
|
return nil, nil, errors.New("retry backoff parameters for delegating authentication webhook has not been specified")
|
||||||
}
|
}
|
||||||
tokenAuth, err := webhooktoken.NewFromInterface(c.TokenAccessReviewClient, c.APIAudiences, *c.WebhookRetryBackoff, c.TokenAccessReviewTimeout)
|
tokenAuth, err := webhooktoken.NewFromInterface(c.TokenAccessReviewClient, c.APIAudiences, *c.WebhookRetryBackoff, c.TokenAccessReviewTimeout, webhooktoken.AuthenticatorMetrics{
|
||||||
|
RecordRequestTotal: RecordRequestTotal,
|
||||||
|
RecordRequestLatency: RecordRequestLatency,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,69 @@
|
|||||||
|
/*
|
||||||
|
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 authenticatorfactory
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
compbasemetrics "k8s.io/component-base/metrics"
|
||||||
|
"k8s.io/component-base/metrics/legacyregistry"
|
||||||
|
)
|
||||||
|
|
||||||
|
type registerables []compbasemetrics.Registerable
|
||||||
|
|
||||||
|
// init registers all metrics.
|
||||||
|
func init() {
|
||||||
|
for _, metric := range metrics {
|
||||||
|
legacyregistry.MustRegister(metric)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
requestTotal = compbasemetrics.NewCounterVec(
|
||||||
|
&compbasemetrics.CounterOpts{
|
||||||
|
Name: "apiserver_delegated_authn_request_total",
|
||||||
|
Help: "Number of HTTP requests partitioned by status code.",
|
||||||
|
StabilityLevel: compbasemetrics.ALPHA,
|
||||||
|
},
|
||||||
|
[]string{"code"},
|
||||||
|
)
|
||||||
|
|
||||||
|
requestLatency = compbasemetrics.NewHistogramVec(
|
||||||
|
&compbasemetrics.HistogramOpts{
|
||||||
|
Name: "apiserver_delegated_authn_request_duration_seconds",
|
||||||
|
Help: "Request latency in seconds. Broken down by status code.",
|
||||||
|
Buckets: []float64{0.25, 0.5, 0.7, 1, 1.5, 3, 5, 10},
|
||||||
|
StabilityLevel: compbasemetrics.ALPHA,
|
||||||
|
},
|
||||||
|
[]string{"code"},
|
||||||
|
)
|
||||||
|
|
||||||
|
metrics = registerables{
|
||||||
|
requestTotal,
|
||||||
|
requestLatency,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// RecordRequestTotal increments the total number of requests for the delegated authentication.
|
||||||
|
func RecordRequestTotal(ctx context.Context, code string) {
|
||||||
|
requestTotal.WithContext(ctx).WithLabelValues(code).Inc()
|
||||||
|
}
|
||||||
|
|
||||||
|
// RecordRequestLatency measures request latency in seconds for the delegated authentication. Broken down by status code.
|
||||||
|
func RecordRequestLatency(ctx context.Context, code string, latency float64) {
|
||||||
|
requestLatency.WithContext(ctx).WithLabelValues(code).Observe(latency)
|
||||||
|
}
|
@ -295,7 +295,7 @@ func (s *DelegatingAuthenticationOptions) ApplyTo(authenticationInfo *server.Aut
|
|||||||
|
|
||||||
// configure token review
|
// configure token review
|
||||||
if client != nil {
|
if client != nil {
|
||||||
cfg.TokenAccessReviewClient = client.AuthenticationV1().TokenReviews()
|
cfg.TokenAccessReviewClient = client.AuthenticationV1()
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the clientCA information
|
// get the clientCA information
|
||||||
|
@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
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 webhook
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AuthenticatorMetrics specifies a set of methods that are used to register various metrics
|
||||||
|
type AuthenticatorMetrics struct {
|
||||||
|
// RecordRequestTotal increments the total number of requests for webhooks
|
||||||
|
RecordRequestTotal func(ctx context.Context, code string)
|
||||||
|
|
||||||
|
// RecordRequestLatency measures request latency in seconds for webhooks. Broken down by status code.
|
||||||
|
RecordRequestLatency func(ctx context.Context, code string, latency float64)
|
||||||
|
}
|
||||||
|
|
||||||
|
type noopMetrics struct{}
|
||||||
|
|
||||||
|
func (noopMetrics) RequestTotal(context.Context, string) {}
|
||||||
|
func (noopMetrics) RequestLatency(context.Context, string, float64) {}
|
@ -0,0 +1,117 @@
|
|||||||
|
/*
|
||||||
|
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 webhook
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAuthenticatorMetrics(t *testing.T) {
|
||||||
|
scenarios := []struct {
|
||||||
|
name string
|
||||||
|
clientCert, clientKey, clientCA []byte
|
||||||
|
serverCert, serverKey, serverCA []byte
|
||||||
|
authnFakeServiceStatusCode int
|
||||||
|
authFakeServiceDeny bool
|
||||||
|
expectedRegisteredStatusCode string
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "happy path",
|
||||||
|
clientCert: clientCert, clientKey: clientKey, clientCA: caCert,
|
||||||
|
serverCert: serverCert, serverKey: serverKey, serverCA: caCert,
|
||||||
|
expectedRegisteredStatusCode: "200",
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
name: "an internal error returned from the webhook",
|
||||||
|
clientCert: clientCert, clientKey: clientKey, clientCA: caCert,
|
||||||
|
serverCert: serverCert, serverKey: serverKey, serverCA: caCert,
|
||||||
|
authnFakeServiceStatusCode: 500,
|
||||||
|
expectedRegisteredStatusCode: "500",
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
name: "incorrect client certificate used, the webhook not called, an error is recorded",
|
||||||
|
clientCert: clientCert, clientKey: clientKey, clientCA: caCert,
|
||||||
|
serverCert: serverCert, serverKey: serverKey, serverCA: badCACert,
|
||||||
|
expectedRegisteredStatusCode: "<error>",
|
||||||
|
wantErr: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, scenario := range scenarios {
|
||||||
|
t.Run(scenario.name, func(t *testing.T) {
|
||||||
|
service := new(mockV1Service)
|
||||||
|
service.statusCode = scenario.authnFakeServiceStatusCode
|
||||||
|
if service.statusCode == 0 {
|
||||||
|
service.statusCode = 200
|
||||||
|
}
|
||||||
|
service.allow = !scenario.authFakeServiceDeny
|
||||||
|
|
||||||
|
server, err := NewV1TestServer(service, scenario.serverCert, scenario.serverKey, scenario.serverCA)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("%s: failed to create server: %v", scenario.name, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
fakeAuthnMetrics := &fakeAuthenticatorMetrics{}
|
||||||
|
authnMetrics := AuthenticatorMetrics{
|
||||||
|
RecordRequestTotal: fakeAuthnMetrics.RequestTotal,
|
||||||
|
RecordRequestLatency: fakeAuthnMetrics.RequestLatency,
|
||||||
|
}
|
||||||
|
wh, err := newV1TokenAuthenticator(server.URL, scenario.clientCert, scenario.clientKey, scenario.clientCA, 0, nil, authnMetrics)
|
||||||
|
if err != nil {
|
||||||
|
t.Error("failed to create client")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
_, _, err = wh.AuthenticateToken(context.Background(), "t0k3n")
|
||||||
|
if scenario.wantErr {
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("expected error making authorization request: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if fakeAuthnMetrics.totalCode != scenario.expectedRegisteredStatusCode {
|
||||||
|
t.Errorf("incorrect status code recorded for RecordRequestTotal method, expected = %v, got %v", scenario.expectedRegisteredStatusCode, fakeAuthnMetrics.totalCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
if fakeAuthnMetrics.latencyCode != scenario.expectedRegisteredStatusCode {
|
||||||
|
t.Errorf("incorrect status code recorded for RecordRequestLatency method, expected = %v, got %v", scenario.expectedRegisteredStatusCode, fakeAuthnMetrics.latencyCode)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type fakeAuthenticatorMetrics struct {
|
||||||
|
totalCode string
|
||||||
|
|
||||||
|
latency float64
|
||||||
|
latencyCode string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *fakeAuthenticatorMetrics) RequestTotal(_ context.Context, code string) {
|
||||||
|
f.totalCode = code
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *fakeAuthenticatorMetrics) RequestLatency(_ context.Context, code string, latency float64) {
|
||||||
|
f.latency = latency
|
||||||
|
f.latencyCode = code
|
||||||
|
}
|
@ -21,6 +21,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
authenticationv1 "k8s.io/api/authentication/v1"
|
authenticationv1 "k8s.io/api/authentication/v1"
|
||||||
@ -35,6 +36,7 @@ import (
|
|||||||
"k8s.io/apiserver/pkg/util/webhook"
|
"k8s.io/apiserver/pkg/util/webhook"
|
||||||
"k8s.io/client-go/kubernetes/scheme"
|
"k8s.io/client-go/kubernetes/scheme"
|
||||||
authenticationv1client "k8s.io/client-go/kubernetes/typed/authentication/v1"
|
authenticationv1client "k8s.io/client-go/kubernetes/typed/authentication/v1"
|
||||||
|
"k8s.io/client-go/rest"
|
||||||
"k8s.io/klog/v2"
|
"k8s.io/klog/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -48,7 +50,7 @@ func DefaultRetryBackoff() *wait.Backoff {
|
|||||||
var _ authenticator.Token = (*WebhookTokenAuthenticator)(nil)
|
var _ authenticator.Token = (*WebhookTokenAuthenticator)(nil)
|
||||||
|
|
||||||
type tokenReviewer interface {
|
type tokenReviewer interface {
|
||||||
Create(ctx context.Context, review *authenticationv1.TokenReview, _ metav1.CreateOptions) (*authenticationv1.TokenReview, error)
|
Create(ctx context.Context, review *authenticationv1.TokenReview, _ metav1.CreateOptions) (*authenticationv1.TokenReview, int, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type WebhookTokenAuthenticator struct {
|
type WebhookTokenAuthenticator struct {
|
||||||
@ -56,14 +58,16 @@ type WebhookTokenAuthenticator struct {
|
|||||||
retryBackoff wait.Backoff
|
retryBackoff wait.Backoff
|
||||||
implicitAuds authenticator.Audiences
|
implicitAuds authenticator.Audiences
|
||||||
requestTimeout time.Duration
|
requestTimeout time.Duration
|
||||||
|
metrics AuthenticatorMetrics
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewFromInterface creates a webhook authenticator using the given tokenReview
|
// NewFromInterface creates a webhook authenticator using the given tokenReview
|
||||||
// client. It is recommend to wrap this authenticator with the token cache
|
// client. It is recommend to wrap this authenticator with the token cache
|
||||||
// authenticator implemented in
|
// authenticator implemented in
|
||||||
// k8s.io/apiserver/pkg/authentication/token/cache.
|
// k8s.io/apiserver/pkg/authentication/token/cache.
|
||||||
func NewFromInterface(tokenReview authenticationv1client.TokenReviewInterface, implicitAuds authenticator.Audiences, retryBackoff wait.Backoff, requestTimeout time.Duration) (*WebhookTokenAuthenticator, error) {
|
func NewFromInterface(tokenReview authenticationv1client.AuthenticationV1Interface, implicitAuds authenticator.Audiences, retryBackoff wait.Backoff, requestTimeout time.Duration, metrics AuthenticatorMetrics) (*WebhookTokenAuthenticator, error) {
|
||||||
return newWithBackoff(tokenReview, retryBackoff, implicitAuds, requestTimeout)
|
tokenReviewClient := &tokenReviewV1Client{tokenReview.RESTClient()}
|
||||||
|
return newWithBackoff(tokenReviewClient, retryBackoff, implicitAuds, requestTimeout, metrics)
|
||||||
}
|
}
|
||||||
|
|
||||||
// New creates a new WebhookTokenAuthenticator from the provided kubeconfig
|
// New creates a new WebhookTokenAuthenticator from the provided kubeconfig
|
||||||
@ -75,12 +79,21 @@ func New(kubeConfigFile string, version string, implicitAuds authenticator.Audie
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return newWithBackoff(tokenReview, retryBackoff, implicitAuds, time.Duration(0))
|
return newWithBackoff(tokenReview, retryBackoff, implicitAuds, time.Duration(0), AuthenticatorMetrics{
|
||||||
|
RecordRequestTotal: noopMetrics{}.RequestTotal,
|
||||||
|
RecordRequestLatency: noopMetrics{}.RequestLatency,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// newWithBackoff allows tests to skip the sleep.
|
// newWithBackoff allows tests to skip the sleep.
|
||||||
func newWithBackoff(tokenReview tokenReviewer, retryBackoff wait.Backoff, implicitAuds authenticator.Audiences, requestTimeout time.Duration) (*WebhookTokenAuthenticator, error) {
|
func newWithBackoff(tokenReview tokenReviewer, retryBackoff wait.Backoff, implicitAuds authenticator.Audiences, requestTimeout time.Duration, metrics AuthenticatorMetrics) (*WebhookTokenAuthenticator, error) {
|
||||||
return &WebhookTokenAuthenticator{tokenReview, retryBackoff, implicitAuds, requestTimeout}, nil
|
return &WebhookTokenAuthenticator{
|
||||||
|
tokenReview,
|
||||||
|
retryBackoff,
|
||||||
|
implicitAuds,
|
||||||
|
requestTimeout,
|
||||||
|
metrics,
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// AuthenticateToken implements the authenticator.Token interface.
|
// AuthenticateToken implements the authenticator.Token interface.
|
||||||
@ -120,7 +133,22 @@ func (w *WebhookTokenAuthenticator) AuthenticateToken(ctx context.Context, token
|
|||||||
// WithExponentialBackoff will return tokenreview create error (tokenReviewErr) if any.
|
// WithExponentialBackoff will return tokenreview create error (tokenReviewErr) if any.
|
||||||
if err := webhook.WithExponentialBackoff(ctx, w.retryBackoff, func() error {
|
if err := webhook.WithExponentialBackoff(ctx, w.retryBackoff, func() error {
|
||||||
var tokenReviewErr error
|
var tokenReviewErr error
|
||||||
result, tokenReviewErr = w.tokenReview.Create(ctx, r, metav1.CreateOptions{})
|
var statusCode int
|
||||||
|
|
||||||
|
start := time.Now()
|
||||||
|
result, statusCode, tokenReviewErr = w.tokenReview.Create(ctx, r, metav1.CreateOptions{})
|
||||||
|
latency := time.Now().Sub(start)
|
||||||
|
|
||||||
|
if statusCode != 0 {
|
||||||
|
w.metrics.RecordRequestTotal(ctx, strconv.Itoa(statusCode))
|
||||||
|
w.metrics.RecordRequestLatency(ctx, strconv.Itoa(statusCode), latency.Seconds())
|
||||||
|
return tokenReviewErr
|
||||||
|
}
|
||||||
|
|
||||||
|
if tokenReviewErr != nil {
|
||||||
|
w.metrics.RecordRequestTotal(ctx, "<error>")
|
||||||
|
w.metrics.RecordRequestLatency(ctx, "<error>", latency.Seconds())
|
||||||
|
}
|
||||||
return tokenReviewErr
|
return tokenReviewErr
|
||||||
}, webhook.DefaultShouldRetry); err != nil {
|
}, webhook.DefaultShouldRetry); err != nil {
|
||||||
// An error here indicates bad configuration or an outage. Log for debugging.
|
// An error here indicates bad configuration or an outage. Log for debugging.
|
||||||
@ -186,7 +214,7 @@ func tokenReviewInterfaceFromKubeconfig(kubeConfigFile string, version string, r
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &tokenReviewV1Client{gw}, nil
|
return &tokenReviewV1ClientGW{gw.RestClient}, nil
|
||||||
|
|
||||||
case authenticationv1beta1.SchemeGroupVersion.Version:
|
case authenticationv1beta1.SchemeGroupVersion.Version:
|
||||||
groupVersions := []schema.GroupVersion{authenticationv1beta1.SchemeGroupVersion}
|
groupVersions := []schema.GroupVersion{authenticationv1beta1.SchemeGroupVersion}
|
||||||
@ -197,7 +225,7 @@ func tokenReviewInterfaceFromKubeconfig(kubeConfigFile string, version string, r
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &tokenReviewV1beta1Client{gw}, nil
|
return &tokenReviewV1beta1ClientGW{gw.RestClient}, nil
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf(
|
return nil, fmt.Errorf(
|
||||||
@ -211,28 +239,60 @@ func tokenReviewInterfaceFromKubeconfig(kubeConfigFile string, version string, r
|
|||||||
}
|
}
|
||||||
|
|
||||||
type tokenReviewV1Client struct {
|
type tokenReviewV1Client struct {
|
||||||
w *webhook.GenericWebhook
|
client rest.Interface
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *tokenReviewV1Client) Create(ctx context.Context, review *authenticationv1.TokenReview, _ metav1.CreateOptions) (*authenticationv1.TokenReview, error) {
|
// Create takes the representation of a tokenReview and creates it. Returns the server's representation of the tokenReview, HTTP status code and an error, if there is any.
|
||||||
result := &authenticationv1.TokenReview{}
|
func (c *tokenReviewV1Client) Create(ctx context.Context, tokenReview *authenticationv1.TokenReview, opts metav1.CreateOptions) (result *authenticationv1.TokenReview, statusCode int, err error) {
|
||||||
err := t.w.RestClient.Post().Body(review).Do(ctx).Into(result)
|
result = &authenticationv1.TokenReview{}
|
||||||
return result, err
|
|
||||||
|
restResult := c.client.Post().
|
||||||
|
Resource("tokenreviews").
|
||||||
|
VersionedParams(&opts, scheme.ParameterCodec).
|
||||||
|
Body(tokenReview).
|
||||||
|
Do(ctx)
|
||||||
|
|
||||||
|
restResult.StatusCode(&statusCode)
|
||||||
|
err = restResult.Into(result)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
type tokenReviewV1beta1Client struct {
|
// tokenReviewV1ClientGW used by the generic webhook, doesn't specify GVR.
|
||||||
w *webhook.GenericWebhook
|
type tokenReviewV1ClientGW struct {
|
||||||
|
client rest.Interface
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *tokenReviewV1beta1Client) Create(ctx context.Context, review *authenticationv1.TokenReview, _ metav1.CreateOptions) (*authenticationv1.TokenReview, error) {
|
// Create takes the representation of a tokenReview and creates it. Returns the server's representation of the tokenReview, HTTP status code and an error, if there is any.
|
||||||
|
func (c *tokenReviewV1ClientGW) Create(ctx context.Context, tokenReview *authenticationv1.TokenReview, opts metav1.CreateOptions) (result *authenticationv1.TokenReview, statusCode int, err error) {
|
||||||
|
result = &authenticationv1.TokenReview{}
|
||||||
|
|
||||||
|
restResult := c.client.Post().
|
||||||
|
Body(tokenReview).
|
||||||
|
Do(ctx)
|
||||||
|
|
||||||
|
restResult.StatusCode(&statusCode)
|
||||||
|
err = restResult.Into(result)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// tokenReviewV1beta1ClientGW used by the generic webhook, doesn't specify GVR.
|
||||||
|
type tokenReviewV1beta1ClientGW struct {
|
||||||
|
client rest.Interface
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *tokenReviewV1beta1ClientGW) Create(ctx context.Context, review *authenticationv1.TokenReview, _ metav1.CreateOptions) (*authenticationv1.TokenReview, int, error) {
|
||||||
|
var statusCode int
|
||||||
v1beta1Review := &authenticationv1beta1.TokenReview{Spec: v1SpecToV1beta1Spec(&review.Spec)}
|
v1beta1Review := &authenticationv1beta1.TokenReview{Spec: v1SpecToV1beta1Spec(&review.Spec)}
|
||||||
v1beta1Result := &authenticationv1beta1.TokenReview{}
|
v1beta1Result := &authenticationv1beta1.TokenReview{}
|
||||||
err := t.w.RestClient.Post().Body(v1beta1Review).Do(ctx).Into(v1beta1Result)
|
|
||||||
|
restResult := t.client.Post().Body(v1beta1Review).Do(ctx)
|
||||||
|
restResult.StatusCode(&statusCode)
|
||||||
|
err := restResult.Into(v1beta1Result)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, statusCode, err
|
||||||
}
|
}
|
||||||
review.Status = v1beta1StatusToV1Status(&v1beta1Result.Status)
|
review.Status = v1beta1StatusToV1Status(&v1beta1Result.Status)
|
||||||
return review, nil
|
return review, statusCode, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func v1SpecToV1beta1Spec(in *authenticationv1.TokenReviewSpec) authenticationv1beta1.TokenReviewSpec {
|
func v1SpecToV1beta1Spec(in *authenticationv1.TokenReviewSpec) authenticationv1beta1.TokenReviewSpec {
|
||||||
|
@ -178,7 +178,7 @@ func (m *mockV1Service) HTTPStatusCode() int { return m.statusCode }
|
|||||||
|
|
||||||
// newV1TokenAuthenticator creates a temporary kubeconfig file from the provided
|
// newV1TokenAuthenticator creates a temporary kubeconfig file from the provided
|
||||||
// arguments and attempts to load a new WebhookTokenAuthenticator from it.
|
// arguments and attempts to load a new WebhookTokenAuthenticator from it.
|
||||||
func newV1TokenAuthenticator(serverURL string, clientCert, clientKey, ca []byte, cacheTime time.Duration, implicitAuds authenticator.Audiences) (authenticator.Token, error) {
|
func newV1TokenAuthenticator(serverURL string, clientCert, clientKey, ca []byte, cacheTime time.Duration, implicitAuds authenticator.Audiences, metrics AuthenticatorMetrics) (authenticator.Token, error) {
|
||||||
tempfile, err := ioutil.TempFile("", "")
|
tempfile, err := ioutil.TempFile("", "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -206,7 +206,7 @@ func newV1TokenAuthenticator(serverURL string, clientCert, clientKey, ca []byte,
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
authn, err := newWithBackoff(c, testRetryBackoff, implicitAuds, 10*time.Second)
|
authn, err := newWithBackoff(c, testRetryBackoff, implicitAuds, 10*time.Second, metrics)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -267,7 +267,7 @@ func TestV1TLSConfig(t *testing.T) {
|
|||||||
}
|
}
|
||||||
defer server.Close()
|
defer server.Close()
|
||||||
|
|
||||||
wh, err := newV1TokenAuthenticator(server.URL, tt.clientCert, tt.clientKey, tt.clientCA, 0, nil)
|
wh, err := newV1TokenAuthenticator(server.URL, tt.clientCert, tt.clientKey, tt.clientCA, 0, nil, noopAuthenticatorMetrics())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("%s: failed to create client: %v", tt.test, err)
|
t.Errorf("%s: failed to create client: %v", tt.test, err)
|
||||||
return
|
return
|
||||||
@ -490,7 +490,7 @@ func TestV1WebhookTokenAuthenticator(t *testing.T) {
|
|||||||
token := "my-s3cr3t-t0ken" // Fake token for testing.
|
token := "my-s3cr3t-t0ken" // Fake token for testing.
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.description, func(t *testing.T) {
|
t.Run(tt.description, func(t *testing.T) {
|
||||||
wh, err := newV1TokenAuthenticator(s.URL, clientCert, clientKey, caCert, 0, tt.implicitAuds)
|
wh, err := newV1TokenAuthenticator(s.URL, clientCert, clientKey, caCert, 0, tt.implicitAuds, noopAuthenticatorMetrics())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -563,7 +563,7 @@ func TestV1WebhookCacheAndRetry(t *testing.T) {
|
|||||||
defer s.Close()
|
defer s.Close()
|
||||||
|
|
||||||
// Create an authenticator that caches successful responses "forever" (100 days).
|
// Create an authenticator that caches successful responses "forever" (100 days).
|
||||||
wh, err := newV1TokenAuthenticator(s.URL, clientCert, clientKey, caCert, 2400*time.Hour, nil)
|
wh, err := newV1TokenAuthenticator(s.URL, clientCert, clientKey, caCert, 2400*time.Hour, nil, noopAuthenticatorMetrics())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -690,3 +690,10 @@ func TestV1WebhookCacheAndRetry(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func noopAuthenticatorMetrics() AuthenticatorMetrics {
|
||||||
|
return AuthenticatorMetrics{
|
||||||
|
RecordRequestTotal: noopMetrics{}.RequestTotal,
|
||||||
|
RecordRequestLatency: noopMetrics{}.RequestLatency,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -200,7 +200,10 @@ func newV1beta1TokenAuthenticator(serverURL string, clientCert, clientKey, ca []
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
authn, err := newWithBackoff(c, testRetryBackoff, implicitAuds, 10*time.Second)
|
authn, err := newWithBackoff(c, testRetryBackoff, implicitAuds, 10*time.Second, AuthenticatorMetrics{
|
||||||
|
RecordRequestTotal: noopMetrics{}.RequestTotal,
|
||||||
|
RecordRequestLatency: noopMetrics{}.RequestLatency,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user