Upgrade k8s package verison (#5358)

* upgrade k8s package version

Signed-off-by: hongzhouzi <hongzhouzi@kubesphere.io>

* Script upgrade and code formatting.

Signed-off-by: hongzhouzi <hongzhouzi@kubesphere.io>

Signed-off-by: hongzhouzi <hongzhouzi@kubesphere.io>
This commit is contained in:
hongzhouzi
2022-11-15 14:56:38 +08:00
committed by GitHub
parent 5f91c1663a
commit 44167aa47a
3106 changed files with 321340 additions and 172080 deletions

View File

@@ -190,10 +190,10 @@ func (b *bufferedBackend) processIncomingEvents(stopCh <-chan struct{}) {
// The following things can cause collectEvents to stop and return the list
// of events:
//
// * Maximum number of events for a batch.
// * Timer has passed.
// * Buffer channel is closed and empty.
// * stopCh is closed.
// - Maximum number of events for a batch.
// - Timer has passed.
// - Buffer channel is closed and empty.
// - stopCh is closed.
func (b *bufferedBackend) collectEvents(timer <-chan time.Time, stopCh <-chan struct{}) []*auditinternal.Event {
var events []*auditinternal.Event

View File

@@ -126,7 +126,12 @@ func truncate(e *auditinternal.Event) *auditinternal.Event {
newEvent.RequestObject = nil
newEvent.ResponseObject = nil
audit.LogAnnotation(newEvent, annotationKey, annotationValue)
if newEvent.Annotations == nil {
newEvent.Annotations = make(map[string]string)
}
newEvent.Annotations[annotationKey] = annotationValue
return newEvent
}

View File

@@ -63,8 +63,12 @@ func retryOnError(err error) bool {
}
func loadWebhook(configFile string, groupVersion schema.GroupVersion, retryBackoff wait.Backoff, customDial utilnet.DialFunc) (*webhook.GenericWebhook, error) {
w, err := webhook.NewGenericWebhook(audit.Scheme, audit.Codecs, configFile,
[]schema.GroupVersion{groupVersion}, retryBackoff, customDial)
clientConfig, err := webhook.LoadKubeconfig(configFile, customDial)
if err != nil {
return nil, err
}
w, err := webhook.NewGenericWebhook(audit.Scheme, audit.Codecs, clientConfig,
[]schema.GroupVersion{groupVersion}, retryBackoff)
if err != nil {
return nil, err
}

View File

@@ -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) {}

View File

@@ -21,6 +21,7 @@ import (
"context"
"errors"
"fmt"
"strconv"
"time"
authenticationv1 "k8s.io/api/authentication/v1"
@@ -28,13 +29,13 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
utilnet "k8s.io/apimachinery/pkg/util/net"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/apiserver/pkg/authentication/authenticator"
"k8s.io/apiserver/pkg/authentication/user"
"k8s.io/apiserver/pkg/util/webhook"
"k8s.io/client-go/kubernetes/scheme"
authenticationv1client "k8s.io/client-go/kubernetes/typed/authentication/v1"
"k8s.io/client-go/rest"
"k8s.io/klog/v2"
)
@@ -48,7 +49,7 @@ func DefaultRetryBackoff() *wait.Backoff {
var _ authenticator.Token = (*WebhookTokenAuthenticator)(nil)
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 {
@@ -56,31 +57,42 @@ type WebhookTokenAuthenticator struct {
retryBackoff wait.Backoff
implicitAuds authenticator.Audiences
requestTimeout time.Duration
metrics AuthenticatorMetrics
}
// NewFromInterface creates a webhook authenticator using the given tokenReview
// client. It is recommend to wrap this authenticator with the token cache
// authenticator implemented in
// k8s.io/apiserver/pkg/authentication/token/cache.
func NewFromInterface(tokenReview authenticationv1client.TokenReviewInterface, implicitAuds authenticator.Audiences, retryBackoff wait.Backoff, requestTimeout time.Duration) (*WebhookTokenAuthenticator, error) {
return newWithBackoff(tokenReview, retryBackoff, implicitAuds, requestTimeout)
func NewFromInterface(tokenReview authenticationv1client.AuthenticationV1Interface, implicitAuds authenticator.Audiences, retryBackoff wait.Backoff, requestTimeout time.Duration, metrics AuthenticatorMetrics) (*WebhookTokenAuthenticator, error) {
tokenReviewClient := &tokenReviewV1Client{tokenReview.RESTClient()}
return newWithBackoff(tokenReviewClient, retryBackoff, implicitAuds, requestTimeout, metrics)
}
// New creates a new WebhookTokenAuthenticator from the provided kubeconfig
// file. It is recommend to wrap this authenticator with the token cache
// New creates a new WebhookTokenAuthenticator from the provided rest
// config. It is recommend to wrap this authenticator with the token cache
// authenticator implemented in
// k8s.io/apiserver/pkg/authentication/token/cache.
func New(kubeConfigFile string, version string, implicitAuds authenticator.Audiences, retryBackoff wait.Backoff, customDial utilnet.DialFunc) (*WebhookTokenAuthenticator, error) {
tokenReview, err := tokenReviewInterfaceFromKubeconfig(kubeConfigFile, version, retryBackoff, customDial)
func New(config *rest.Config, version string, implicitAuds authenticator.Audiences, retryBackoff wait.Backoff) (*WebhookTokenAuthenticator, error) {
tokenReview, err := tokenReviewInterfaceFromConfig(config, version, retryBackoff)
if err != nil {
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.
func newWithBackoff(tokenReview tokenReviewer, retryBackoff wait.Backoff, implicitAuds authenticator.Audiences, requestTimeout time.Duration) (*WebhookTokenAuthenticator, error) {
return &WebhookTokenAuthenticator{tokenReview, retryBackoff, implicitAuds, requestTimeout}, nil
func newWithBackoff(tokenReview tokenReviewer, retryBackoff wait.Backoff, implicitAuds authenticator.Audiences, requestTimeout time.Duration, metrics AuthenticatorMetrics) (*WebhookTokenAuthenticator, error) {
return &WebhookTokenAuthenticator{
tokenReview,
retryBackoff,
implicitAuds,
requestTimeout,
metrics,
}, nil
}
// AuthenticateToken implements the authenticator.Token interface.
@@ -120,7 +132,22 @@ func (w *WebhookTokenAuthenticator) AuthenticateToken(ctx context.Context, token
// WithExponentialBackoff will return tokenreview create error (tokenReviewErr) if any.
if err := webhook.WithExponentialBackoff(ctx, w.retryBackoff, func() 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.Since(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
}, webhook.DefaultShouldRetry); err != nil {
// An error here indicates bad configuration or an outage. Log for debugging.
@@ -167,10 +194,10 @@ func (w *WebhookTokenAuthenticator) AuthenticateToken(ctx context.Context, token
}, true, nil
}
// tokenReviewInterfaceFromKubeconfig builds a client from the specified kubeconfig file,
// tokenReviewInterfaceFromConfig builds a client from the specified kubeconfig file,
// and returns a TokenReviewInterface that uses that client. Note that the client submits TokenReview
// requests to the exact path specified in the kubeconfig file, so arbitrary non-API servers can be targeted.
func tokenReviewInterfaceFromKubeconfig(kubeConfigFile string, version string, retryBackoff wait.Backoff, customDial utilnet.DialFunc) (tokenReviewer, error) {
func tokenReviewInterfaceFromConfig(config *rest.Config, version string, retryBackoff wait.Backoff) (tokenReviewer, error) {
localScheme := runtime.NewScheme()
if err := scheme.AddToScheme(localScheme); err != nil {
return nil, err
@@ -182,22 +209,22 @@ func tokenReviewInterfaceFromKubeconfig(kubeConfigFile string, version string, r
if err := localScheme.SetVersionPriority(groupVersions...); err != nil {
return nil, err
}
gw, err := webhook.NewGenericWebhook(localScheme, scheme.Codecs, kubeConfigFile, groupVersions, retryBackoff, customDial)
gw, err := webhook.NewGenericWebhook(localScheme, scheme.Codecs, config, groupVersions, retryBackoff)
if err != nil {
return nil, err
}
return &tokenReviewV1Client{gw}, nil
return &tokenReviewV1ClientGW{gw.RestClient}, nil
case authenticationv1beta1.SchemeGroupVersion.Version:
groupVersions := []schema.GroupVersion{authenticationv1beta1.SchemeGroupVersion}
if err := localScheme.SetVersionPriority(groupVersions...); err != nil {
return nil, err
}
gw, err := webhook.NewGenericWebhook(localScheme, scheme.Codecs, kubeConfigFile, groupVersions, retryBackoff, customDial)
gw, err := webhook.NewGenericWebhook(localScheme, scheme.Codecs, config, groupVersions, retryBackoff)
if err != nil {
return nil, err
}
return &tokenReviewV1beta1Client{gw}, nil
return &tokenReviewV1beta1ClientGW{gw.RestClient}, nil
default:
return nil, fmt.Errorf(
@@ -211,28 +238,60 @@ func tokenReviewInterfaceFromKubeconfig(kubeConfigFile string, version string, r
}
type tokenReviewV1Client struct {
w *webhook.GenericWebhook
client rest.Interface
}
func (t *tokenReviewV1Client) Create(ctx context.Context, review *authenticationv1.TokenReview, _ metav1.CreateOptions) (*authenticationv1.TokenReview, error) {
result := &authenticationv1.TokenReview{}
err := t.w.RestClient.Post().Body(review).Do(ctx).Into(result)
return result, err
// 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 *tokenReviewV1Client) Create(ctx context.Context, tokenReview *authenticationv1.TokenReview, opts metav1.CreateOptions) (result *authenticationv1.TokenReview, statusCode int, err error) {
result = &authenticationv1.TokenReview{}
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 {
w *webhook.GenericWebhook
// tokenReviewV1ClientGW used by the generic webhook, doesn't specify GVR.
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)}
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 {
return nil, err
return nil, statusCode, err
}
review.Status = v1beta1StatusToV1Status(&v1beta1Result.Status)
return review, nil
return review, statusCode, nil
}
func v1SpecToV1beta1Spec(in *authenticationv1.TokenReviewSpec) authenticationv1beta1.TokenReviewSpec {

View File

@@ -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"
)
// AuthorizerMetrics specifies a set of methods that are used to register various metrics for the webhook authorizer
type AuthorizerMetrics struct {
// RecordRequestTotal increments the total number of requests for the webhook authorizer
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) RecordRequestTotal(context.Context, string) {}
func (noopMetrics) RecordRequestLatency(context.Context, string, float64) {}

View File

@@ -21,23 +21,23 @@ import (
"context"
"encoding/json"
"fmt"
"strconv"
"time"
"k8s.io/klog/v2"
authorizationv1 "k8s.io/api/authorization/v1"
authorizationv1beta1 "k8s.io/api/authorization/v1beta1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/cache"
utilnet "k8s.io/apimachinery/pkg/util/net"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/apiserver/pkg/authentication/user"
"k8s.io/apiserver/pkg/authorization/authorizer"
"k8s.io/apiserver/pkg/util/webhook"
"k8s.io/client-go/kubernetes/scheme"
authorizationv1client "k8s.io/client-go/kubernetes/typed/authorization/v1"
"k8s.io/client-go/rest"
"k8s.io/klog/v2"
)
const (
@@ -55,7 +55,7 @@ func DefaultRetryBackoff() *wait.Backoff {
var _ authorizer.Authorizer = (*WebhookAuthorizer)(nil)
type subjectAccessReviewer interface {
Create(context.Context, *authorizationv1.SubjectAccessReview, metav1.CreateOptions) (*authorizationv1.SubjectAccessReview, error)
Create(context.Context, *authorizationv1.SubjectAccessReview, metav1.CreateOptions) (*authorizationv1.SubjectAccessReview, int, error)
}
type WebhookAuthorizer struct {
@@ -65,42 +65,46 @@ type WebhookAuthorizer struct {
unauthorizedTTL time.Duration
retryBackoff wait.Backoff
decisionOnError authorizer.Decision
metrics AuthorizerMetrics
}
// NewFromInterface creates a WebhookAuthorizer using the given subjectAccessReview client
func NewFromInterface(subjectAccessReview authorizationv1client.SubjectAccessReviewInterface, authorizedTTL, unauthorizedTTL time.Duration, retryBackoff wait.Backoff) (*WebhookAuthorizer, error) {
return newWithBackoff(subjectAccessReview, authorizedTTL, unauthorizedTTL, retryBackoff)
func NewFromInterface(subjectAccessReview authorizationv1client.AuthorizationV1Interface, authorizedTTL, unauthorizedTTL time.Duration, retryBackoff wait.Backoff, metrics AuthorizerMetrics) (*WebhookAuthorizer, error) {
return newWithBackoff(&subjectAccessReviewV1Client{subjectAccessReview.RESTClient()}, authorizedTTL, unauthorizedTTL, retryBackoff, metrics)
}
// New creates a new WebhookAuthorizer from the provided kubeconfig file.
// The config's cluster field is used to refer to the remote service, user refers to the returned authorizer.
//
// # clusters refers to the remote service.
// clusters:
// - name: name-of-remote-authz-service
// cluster:
// certificate-authority: /path/to/ca.pem # CA for verifying the remote service.
// server: https://authz.example.com/authorize # URL of remote service to query. Must use 'https'.
// # clusters refers to the remote service.
// clusters:
// - name: name-of-remote-authz-service
// cluster:
// certificate-authority: /path/to/ca.pem # CA for verifying the remote service.
// server: https://authz.example.com/authorize # URL of remote service to query. Must use 'https'.
//
// # users refers to the API server's webhook configuration.
// users:
// - name: name-of-api-server
// user:
// client-certificate: /path/to/cert.pem # cert for the webhook plugin to use
// client-key: /path/to/key.pem # key matching the cert
// # users refers to the API server's webhook configuration.
// users:
// - name: name-of-api-server
// user:
// client-certificate: /path/to/cert.pem # cert for the webhook plugin to use
// client-key: /path/to/key.pem # key matching the cert
//
// For additional HTTP configuration, refer to the kubeconfig documentation
// https://kubernetes.io/docs/user-guide/kubeconfig-file/.
func New(kubeConfigFile string, version string, authorizedTTL, unauthorizedTTL time.Duration, retryBackoff wait.Backoff, customDial utilnet.DialFunc) (*WebhookAuthorizer, error) {
subjectAccessReview, err := subjectAccessReviewInterfaceFromKubeconfig(kubeConfigFile, version, retryBackoff, customDial)
func New(config *rest.Config, version string, authorizedTTL, unauthorizedTTL time.Duration, retryBackoff wait.Backoff) (*WebhookAuthorizer, error) {
subjectAccessReview, err := subjectAccessReviewInterfaceFromConfig(config, version, retryBackoff)
if err != nil {
return nil, err
}
return newWithBackoff(subjectAccessReview, authorizedTTL, unauthorizedTTL, retryBackoff)
return newWithBackoff(subjectAccessReview, authorizedTTL, unauthorizedTTL, retryBackoff, AuthorizerMetrics{
RecordRequestTotal: noopMetrics{}.RecordRequestTotal,
RecordRequestLatency: noopMetrics{}.RecordRequestLatency,
})
}
// newWithBackoff allows tests to skip the sleep.
func newWithBackoff(subjectAccessReview subjectAccessReviewer, authorizedTTL, unauthorizedTTL time.Duration, retryBackoff wait.Backoff) (*WebhookAuthorizer, error) {
func newWithBackoff(subjectAccessReview subjectAccessReviewer, authorizedTTL, unauthorizedTTL time.Duration, retryBackoff wait.Backoff, metrics AuthorizerMetrics) (*WebhookAuthorizer, error) {
return &WebhookAuthorizer{
subjectAccessReview: subjectAccessReview,
responseCache: cache.NewLRUExpireCache(8192),
@@ -108,6 +112,7 @@ func newWithBackoff(subjectAccessReview subjectAccessReviewer, authorizedTTL, un
unauthorizedTTL: unauthorizedTTL,
retryBackoff: retryBackoff,
decisionOnError: authorizer.DecisionNoOpinion,
metrics: metrics,
}, nil
}
@@ -115,45 +120,45 @@ func newWithBackoff(subjectAccessReview subjectAccessReviewer, authorizedTTL, un
// serialized api.authorization.v1beta1.SubjectAccessReview object. An example request body is
// provided below.
//
// {
// "apiVersion": "authorization.k8s.io/v1beta1",
// "kind": "SubjectAccessReview",
// "spec": {
// "resourceAttributes": {
// "namespace": "kittensandponies",
// "verb": "GET",
// "group": "group3",
// "resource": "pods"
// },
// "user": "jane",
// "group": [
// "group1",
// "group2"
// ]
// }
// }
// {
// "apiVersion": "authorization.k8s.io/v1beta1",
// "kind": "SubjectAccessReview",
// "spec": {
// "resourceAttributes": {
// "namespace": "kittensandponies",
// "verb": "GET",
// "group": "group3",
// "resource": "pods"
// },
// "user": "jane",
// "group": [
// "group1",
// "group2"
// ]
// }
// }
//
// The remote service is expected to fill the SubjectAccessReviewStatus field to either allow or
// disallow access. A permissive response would return:
//
// {
// "apiVersion": "authorization.k8s.io/v1beta1",
// "kind": "SubjectAccessReview",
// "status": {
// "allowed": true
// }
// }
// {
// "apiVersion": "authorization.k8s.io/v1beta1",
// "kind": "SubjectAccessReview",
// "status": {
// "allowed": true
// }
// }
//
// To disallow access, the remote service would return:
//
// {
// "apiVersion": "authorization.k8s.io/v1beta1",
// "kind": "SubjectAccessReview",
// "status": {
// "allowed": false,
// "reason": "user does not have read access to the namespace"
// }
// }
// {
// "apiVersion": "authorization.k8s.io/v1beta1",
// "kind": "SubjectAccessReview",
// "status": {
// "allowed": false,
// "reason": "user does not have read access to the namespace"
// }
// }
//
// TODO(mikedanese): We should eventually support failing closed when we
// encounter an error. We are failing open now to preserve backwards compatible
@@ -196,7 +201,23 @@ func (w *WebhookAuthorizer) Authorize(ctx context.Context, attr authorizer.Attri
// WithExponentialBackoff will return SAR create error (sarErr) if any.
if err := webhook.WithExponentialBackoff(ctx, w.retryBackoff, func() error {
var sarErr error
result, sarErr = w.subjectAccessReview.Create(ctx, r, metav1.CreateOptions{})
var statusCode int
start := time.Now()
result, statusCode, sarErr = w.subjectAccessReview.Create(ctx, r, metav1.CreateOptions{})
latency := time.Since(start)
if statusCode != 0 {
w.metrics.RecordRequestTotal(ctx, strconv.Itoa(statusCode))
w.metrics.RecordRequestLatency(ctx, strconv.Itoa(statusCode), latency.Seconds())
return sarErr
}
if sarErr != nil {
w.metrics.RecordRequestTotal(ctx, "<error>")
w.metrics.RecordRequestLatency(ctx, "<error>", latency.Seconds())
}
return sarErr
}, webhook.DefaultShouldRetry); err != nil {
klog.Errorf("Failed to make webhook authorizer request: %v", err)
@@ -225,7 +246,7 @@ func (w *WebhookAuthorizer) Authorize(ctx context.Context, attr authorizer.Attri
}
//TODO: need to finish the method to get the rules when using webhook mode
// TODO: need to finish the method to get the rules when using webhook mode
func (w *WebhookAuthorizer) RulesFor(user user.Info, namespace string) ([]authorizer.ResourceRuleInfo, []authorizer.NonResourceRuleInfo, bool, error) {
var (
resourceRules []authorizer.ResourceRuleInfo
@@ -247,10 +268,10 @@ func convertToSARExtra(extra map[string][]string) map[string]authorizationv1.Ext
return ret
}
// subjectAccessReviewInterfaceFromKubeconfig builds a client from the specified kubeconfig file,
// subjectAccessReviewInterfaceFromConfig builds a client from the specified kubeconfig file,
// and returns a SubjectAccessReviewInterface that uses that client. Note that the client submits SubjectAccessReview
// requests to the exact path specified in the kubeconfig file, so arbitrary non-API servers can be targeted.
func subjectAccessReviewInterfaceFromKubeconfig(kubeConfigFile string, version string, retryBackoff wait.Backoff, customDial utilnet.DialFunc) (subjectAccessReviewer, error) {
func subjectAccessReviewInterfaceFromConfig(config *rest.Config, version string, retryBackoff wait.Backoff) (subjectAccessReviewer, error) {
localScheme := runtime.NewScheme()
if err := scheme.AddToScheme(localScheme); err != nil {
return nil, err
@@ -262,22 +283,22 @@ func subjectAccessReviewInterfaceFromKubeconfig(kubeConfigFile string, version s
if err := localScheme.SetVersionPriority(groupVersions...); err != nil {
return nil, err
}
gw, err := webhook.NewGenericWebhook(localScheme, scheme.Codecs, kubeConfigFile, groupVersions, retryBackoff, customDial)
gw, err := webhook.NewGenericWebhook(localScheme, scheme.Codecs, config, groupVersions, retryBackoff)
if err != nil {
return nil, err
}
return &subjectAccessReviewV1Client{gw}, nil
return &subjectAccessReviewV1ClientGW{gw.RestClient}, nil
case authorizationv1beta1.SchemeGroupVersion.Version:
groupVersions := []schema.GroupVersion{authorizationv1beta1.SchemeGroupVersion}
if err := localScheme.SetVersionPriority(groupVersions...); err != nil {
return nil, err
}
gw, err := webhook.NewGenericWebhook(localScheme, scheme.Codecs, kubeConfigFile, groupVersions, retryBackoff, customDial)
gw, err := webhook.NewGenericWebhook(localScheme, scheme.Codecs, config, groupVersions, retryBackoff)
if err != nil {
return nil, err
}
return &subjectAccessReviewV1beta1Client{gw}, nil
return &subjectAccessReviewV1beta1ClientGW{gw.RestClient}, nil
default:
return nil, fmt.Errorf(
@@ -290,27 +311,58 @@ func subjectAccessReviewInterfaceFromKubeconfig(kubeConfigFile string, version s
}
type subjectAccessReviewV1Client struct {
w *webhook.GenericWebhook
client rest.Interface
}
func (t *subjectAccessReviewV1Client) Create(ctx context.Context, subjectAccessReview *authorizationv1.SubjectAccessReview, _ metav1.CreateOptions) (*authorizationv1.SubjectAccessReview, error) {
func (t *subjectAccessReviewV1Client) Create(ctx context.Context, subjectAccessReview *authorizationv1.SubjectAccessReview, opts metav1.CreateOptions) (result *authorizationv1.SubjectAccessReview, statusCode int, err error) {
result = &authorizationv1.SubjectAccessReview{}
restResult := t.client.Post().
Resource("subjectaccessreviews").
VersionedParams(&opts, scheme.ParameterCodec).
Body(subjectAccessReview).
Do(ctx)
restResult.StatusCode(&statusCode)
err = restResult.Into(result)
return
}
// subjectAccessReviewV1ClientGW used by the generic webhook, doesn't specify GVR.
type subjectAccessReviewV1ClientGW struct {
client rest.Interface
}
func (t *subjectAccessReviewV1ClientGW) Create(ctx context.Context, subjectAccessReview *authorizationv1.SubjectAccessReview, _ metav1.CreateOptions) (*authorizationv1.SubjectAccessReview, int, error) {
var statusCode int
result := &authorizationv1.SubjectAccessReview{}
err := t.w.RestClient.Post().Body(subjectAccessReview).Do(ctx).Into(result)
return result, err
restResult := t.client.Post().Body(subjectAccessReview).Do(ctx)
restResult.StatusCode(&statusCode)
err := restResult.Into(result)
return result, statusCode, err
}
type subjectAccessReviewV1beta1Client struct {
w *webhook.GenericWebhook
// subjectAccessReviewV1beta1ClientGW used by the generic webhook, doesn't specify GVR.
type subjectAccessReviewV1beta1ClientGW struct {
client rest.Interface
}
func (t *subjectAccessReviewV1beta1Client) Create(ctx context.Context, subjectAccessReview *authorizationv1.SubjectAccessReview, _ metav1.CreateOptions) (*authorizationv1.SubjectAccessReview, error) {
func (t *subjectAccessReviewV1beta1ClientGW) Create(ctx context.Context, subjectAccessReview *authorizationv1.SubjectAccessReview, _ metav1.CreateOptions) (*authorizationv1.SubjectAccessReview, int, error) {
var statusCode int
v1beta1Review := &authorizationv1beta1.SubjectAccessReview{Spec: v1SpecToV1beta1Spec(&subjectAccessReview.Spec)}
v1beta1Result := &authorizationv1beta1.SubjectAccessReview{}
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 {
subjectAccessReview.Status = v1beta1StatusToV1Status(&v1beta1Result.Status)
}
return subjectAccessReview, err
return subjectAccessReview, statusCode, err
}
// shouldCache determines whether it is safe to cache the given request attributes. If the