Skip to content

Commit 64d2e2d

Browse files
committed
authorizer/webhook: make webhook authorizer cluster aware
1 parent 50b2aff commit 64d2e2d

File tree

5 files changed

+33
-22
lines changed

5 files changed

+33
-22
lines changed

pkg/kubeapiserver/authorizer/config.go

+1
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ func (config Config) New() (authorizer.Authorizer, authorizer.RuleResolver, erro
116116
}
117117
webhookAuthorizer, err := webhook.New(config.WebhookConfigFile,
118118
config.WebhookVersion,
119+
"",
119120
config.WebhookCacheAuthorizedTTL,
120121
config.WebhookCacheUnauthorizedTTL,
121122
*config.WebhookRetryBackoff,

staging/src/k8s.io/apiserver/pkg/authorization/authorizerfactory/delegating.go

+4
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ type DelegatingAuthorizerConfig struct {
4242
// This allows us to configure the sleep time at each iteration and the maximum number of retries allowed
4343
// before we fail the webhook call in order to limit the fan out that ensues when the system is degraded.
4444
WebhookRetryBackoff *wait.Backoff
45+
46+
// The cluster to execute authorization decisions against (optional).
47+
Cluster string
4548
}
4649

4750
func (c DelegatingAuthorizerConfig) New() (authorizer.Authorizer, error) {
@@ -58,5 +61,6 @@ func (c DelegatingAuthorizerConfig) New() (authorizer.Authorizer, error) {
5861
RecordRequestTotal: RecordRequestTotal,
5962
RecordRequestLatency: RecordRequestLatency,
6063
},
64+
c.Cluster,
6165
)
6266
}

staging/src/k8s.io/apiserver/plugin/pkg/authorizer/webhook/webhook.go

+20-14
Original file line numberDiff line numberDiff line change
@@ -67,11 +67,12 @@ type WebhookAuthorizer struct {
6767
retryBackoff wait.Backoff
6868
decisionOnError authorizer.Decision
6969
metrics AuthorizerMetrics
70+
cluster string
7071
}
7172

7273
// NewFromInterface creates a WebhookAuthorizer using the given subjectAccessReview client
73-
func NewFromInterface(subjectAccessReview authorizationv1client.AuthorizationV1Interface, authorizedTTL, unauthorizedTTL time.Duration, retryBackoff wait.Backoff, metrics AuthorizerMetrics) (*WebhookAuthorizer, error) {
74-
return newWithBackoff(&subjectAccessReviewV1Client{subjectAccessReview.RESTClient()}, authorizedTTL, unauthorizedTTL, retryBackoff, metrics)
74+
func NewFromInterface(subjectAccessReview authorizationv1client.AuthorizationV1Interface, authorizedTTL, unauthorizedTTL time.Duration, retryBackoff wait.Backoff, metrics AuthorizerMetrics, cluster string) (*WebhookAuthorizer, error) {
75+
return newWithBackoff(&subjectAccessReviewV1Client{subjectAccessReview.RESTClient(), cluster}, authorizedTTL, unauthorizedTTL, retryBackoff, metrics, cluster)
7576
}
7677

7778
// New creates a new WebhookAuthorizer from the provided kubeconfig file.
@@ -93,19 +94,19 @@ func NewFromInterface(subjectAccessReview authorizationv1client.AuthorizationV1I
9394
//
9495
// For additional HTTP configuration, refer to the kubeconfig documentation
9596
// https://kubernetes.io/docs/user-guide/kubeconfig-file/.
96-
func New(kubeConfigFile string, version string, authorizedTTL, unauthorizedTTL time.Duration, retryBackoff wait.Backoff, customDial utilnet.DialFunc) (*WebhookAuthorizer, error) {
97-
subjectAccessReview, err := subjectAccessReviewInterfaceFromKubeconfig(kubeConfigFile, version, retryBackoff, customDial)
97+
func New(kubeConfigFile, version, cluster string, authorizedTTL, unauthorizedTTL time.Duration, retryBackoff wait.Backoff, customDial utilnet.DialFunc) (*WebhookAuthorizer, error) {
98+
subjectAccessReview, err := subjectAccessReviewInterfaceFromKubeconfig(kubeConfigFile, version, cluster, retryBackoff, customDial)
9899
if err != nil {
99100
return nil, err
100101
}
101102
return newWithBackoff(subjectAccessReview, authorizedTTL, unauthorizedTTL, retryBackoff, AuthorizerMetrics{
102103
RecordRequestTotal: noopMetrics{}.RecordRequestTotal,
103104
RecordRequestLatency: noopMetrics{}.RecordRequestLatency,
104-
})
105+
}, cluster)
105106
}
106107

107108
// newWithBackoff allows tests to skip the sleep.
108-
func newWithBackoff(subjectAccessReview subjectAccessReviewer, authorizedTTL, unauthorizedTTL time.Duration, retryBackoff wait.Backoff, metrics AuthorizerMetrics) (*WebhookAuthorizer, error) {
109+
func newWithBackoff(subjectAccessReview subjectAccessReviewer, authorizedTTL, unauthorizedTTL time.Duration, retryBackoff wait.Backoff, metrics AuthorizerMetrics, cluster string) (*WebhookAuthorizer, error) {
109110
return &WebhookAuthorizer{
110111
subjectAccessReview: subjectAccessReview,
111112
responseCache: cache.NewLRUExpireCache(8192),
@@ -114,6 +115,7 @@ func newWithBackoff(subjectAccessReview subjectAccessReviewer, authorizedTTL, un
114115
retryBackoff: retryBackoff,
115116
decisionOnError: authorizer.DecisionNoOpinion,
116117
metrics: metrics,
118+
cluster: cluster,
117119
}, nil
118120
}
119121

@@ -272,7 +274,7 @@ func convertToSARExtra(extra map[string][]string) map[string]authorizationv1.Ext
272274
// subjectAccessReviewInterfaceFromKubeconfig builds a client from the specified kubeconfig file,
273275
// and returns a SubjectAccessReviewInterface that uses that client. Note that the client submits SubjectAccessReview
274276
// requests to the exact path specified in the kubeconfig file, so arbitrary non-API servers can be targeted.
275-
func subjectAccessReviewInterfaceFromKubeconfig(kubeConfigFile string, version string, retryBackoff wait.Backoff, customDial utilnet.DialFunc) (subjectAccessReviewer, error) {
277+
func subjectAccessReviewInterfaceFromKubeconfig(kubeConfigFile, version, cluster string, retryBackoff wait.Backoff, customDial utilnet.DialFunc) (subjectAccessReviewer, error) {
276278
localScheme := runtime.NewScheme()
277279
if err := scheme.AddToScheme(localScheme); err != nil {
278280
return nil, err
@@ -288,7 +290,7 @@ func subjectAccessReviewInterfaceFromKubeconfig(kubeConfigFile string, version s
288290
if err != nil {
289291
return nil, err
290292
}
291-
return &subjectAccessReviewV1ClientGW{gw.RestClient}, nil
293+
return &subjectAccessReviewV1ClientGW{gw.RestClient, cluster}, nil
292294

293295
case authorizationv1beta1.SchemeGroupVersion.Version:
294296
groupVersions := []schema.GroupVersion{authorizationv1beta1.SchemeGroupVersion}
@@ -299,7 +301,7 @@ func subjectAccessReviewInterfaceFromKubeconfig(kubeConfigFile string, version s
299301
if err != nil {
300302
return nil, err
301303
}
302-
return &subjectAccessReviewV1beta1ClientGW{gw.RestClient}, nil
304+
return &subjectAccessReviewV1beta1ClientGW{gw.RestClient, cluster}, nil
303305

304306
default:
305307
return nil, fmt.Errorf(
@@ -312,13 +314,15 @@ func subjectAccessReviewInterfaceFromKubeconfig(kubeConfigFile string, version s
312314
}
313315

314316
type subjectAccessReviewV1Client struct {
315-
client rest.Interface
317+
client rest.Interface
318+
cluster string
316319
}
317320

318321
func (t *subjectAccessReviewV1Client) Create(ctx context.Context, subjectAccessReview *authorizationv1.SubjectAccessReview, opts metav1.CreateOptions) (result *authorizationv1.SubjectAccessReview, statusCode int, err error) {
319322
result = &authorizationv1.SubjectAccessReview{}
320323

321324
restResult := t.client.Post().
325+
Cluster(t.cluster).
322326
Resource("subjectaccessreviews").
323327
VersionedParams(&opts, scheme.ParameterCodec).
324328
Body(subjectAccessReview).
@@ -331,14 +335,15 @@ func (t *subjectAccessReviewV1Client) Create(ctx context.Context, subjectAccessR
331335

332336
// subjectAccessReviewV1ClientGW used by the generic webhook, doesn't specify GVR.
333337
type subjectAccessReviewV1ClientGW struct {
334-
client rest.Interface
338+
client rest.Interface
339+
cluster string
335340
}
336341

337342
func (t *subjectAccessReviewV1ClientGW) Create(ctx context.Context, subjectAccessReview *authorizationv1.SubjectAccessReview, _ metav1.CreateOptions) (*authorizationv1.SubjectAccessReview, int, error) {
338343
var statusCode int
339344
result := &authorizationv1.SubjectAccessReview{}
340345

341-
restResult := t.client.Post().Body(subjectAccessReview).Do(ctx)
346+
restResult := t.client.Post().Cluster(t.cluster).Body(subjectAccessReview).Do(ctx)
342347

343348
restResult.StatusCode(&statusCode)
344349
err := restResult.Into(result)
@@ -348,15 +353,16 @@ func (t *subjectAccessReviewV1ClientGW) Create(ctx context.Context, subjectAcces
348353

349354
// subjectAccessReviewV1beta1ClientGW used by the generic webhook, doesn't specify GVR.
350355
type subjectAccessReviewV1beta1ClientGW struct {
351-
client rest.Interface
356+
client rest.Interface
357+
cluster string
352358
}
353359

354360
func (t *subjectAccessReviewV1beta1ClientGW) Create(ctx context.Context, subjectAccessReview *authorizationv1.SubjectAccessReview, _ metav1.CreateOptions) (*authorizationv1.SubjectAccessReview, int, error) {
355361
var statusCode int
356362
v1beta1Review := &authorizationv1beta1.SubjectAccessReview{Spec: v1SpecToV1beta1Spec(&subjectAccessReview.Spec)}
357363
v1beta1Result := &authorizationv1beta1.SubjectAccessReview{}
358364

359-
restResult := t.client.Post().Body(v1beta1Review).Do(ctx)
365+
restResult := t.client.Post().Cluster(t.cluster).Body(v1beta1Review).Do(ctx)
360366

361367
restResult.StatusCode(&statusCode)
362368
err := restResult.Into(v1beta1Result)

staging/src/k8s.io/apiserver/plugin/pkg/authorizer/webhook/webhook_v1_test.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -194,11 +194,11 @@ current-context: default
194194
return fmt.Errorf("failed to execute test template: %v", err)
195195
}
196196
// Create a new authorizer
197-
sarClient, err := subjectAccessReviewInterfaceFromKubeconfig(p, "v1", testRetryBackoff, nil)
197+
sarClient, err := subjectAccessReviewInterfaceFromKubeconfig(p, "v1", "", testRetryBackoff, nil)
198198
if err != nil {
199199
return fmt.Errorf("error building sar client: %v", err)
200200
}
201-
_, err = newWithBackoff(sarClient, 0, 0, testRetryBackoff, noopAuthorizerMetrics())
201+
_, err = newWithBackoff(sarClient, 0, 0, testRetryBackoff, noopAuthorizerMetrics(), "")
202202
return err
203203
}()
204204
if err != nil && !tt.wantErr {
@@ -333,11 +333,11 @@ func newV1Authorizer(callbackURL string, clientCert, clientKey, ca []byte, cache
333333
if err := json.NewEncoder(tempfile).Encode(config); err != nil {
334334
return nil, err
335335
}
336-
sarClient, err := subjectAccessReviewInterfaceFromKubeconfig(p, "v1", testRetryBackoff, nil)
336+
sarClient, err := subjectAccessReviewInterfaceFromKubeconfig(p, "v1", "", testRetryBackoff, nil)
337337
if err != nil {
338338
return nil, fmt.Errorf("error building sar client: %v", err)
339339
}
340-
return newWithBackoff(sarClient, cacheTime, cacheTime, testRetryBackoff, metrics)
340+
return newWithBackoff(sarClient, cacheTime, cacheTime, testRetryBackoff, metrics, "")
341341
}
342342

343343
func TestV1TLSConfig(t *testing.T) {

staging/src/k8s.io/apiserver/plugin/pkg/authorizer/webhook/webhook_v1beta1_test.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -186,11 +186,11 @@ current-context: default
186186
return fmt.Errorf("failed to execute test template: %v", err)
187187
}
188188
// Create a new authorizer
189-
sarClient, err := subjectAccessReviewInterfaceFromKubeconfig(p, "v1beta1", testRetryBackoff, nil)
189+
sarClient, err := subjectAccessReviewInterfaceFromKubeconfig(p, "v1beta1", "", testRetryBackoff, nil)
190190
if err != nil {
191191
return fmt.Errorf("error building sar client: %v", err)
192192
}
193-
_, err = newWithBackoff(sarClient, 0, 0, testRetryBackoff, noopAuthorizerMetrics())
193+
_, err = newWithBackoff(sarClient, 0, 0, testRetryBackoff, noopAuthorizerMetrics(), "")
194194
return err
195195
}()
196196
if err != nil && !tt.wantErr {
@@ -325,11 +325,11 @@ func newV1beta1Authorizer(callbackURL string, clientCert, clientKey, ca []byte,
325325
if err := json.NewEncoder(tempfile).Encode(config); err != nil {
326326
return nil, err
327327
}
328-
sarClient, err := subjectAccessReviewInterfaceFromKubeconfig(p, "v1beta1", testRetryBackoff, nil)
328+
sarClient, err := subjectAccessReviewInterfaceFromKubeconfig(p, "v1beta1", "", testRetryBackoff, nil)
329329
if err != nil {
330330
return nil, fmt.Errorf("error building sar client: %v", err)
331331
}
332-
return newWithBackoff(sarClient, cacheTime, cacheTime, testRetryBackoff, noopAuthorizerMetrics())
332+
return newWithBackoff(sarClient, cacheTime, cacheTime, testRetryBackoff, noopAuthorizerMetrics(), "")
333333
}
334334

335335
func TestV1beta1TLSConfig(t *testing.T) {

0 commit comments

Comments
 (0)