Skip to content

Commit d512173

Browse files
committed
Apply caching limits to authorized requests too
1 parent e23c15a commit d512173

File tree

2 files changed

+14
-11
lines changed

2 files changed

+14
-11
lines changed

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

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@ var (
4141

4242
const (
4343
retryBackoff = 500 * time.Millisecond
44-
// The maximum key length for unauthorized request keys to qualify for caching.
45-
maxUnauthorizedCachedKeySize = 10000
44+
// The maximum length of requester-controlled attributes to allow caching.
45+
maxControlledAttrCacheSize = 10000
4646
)
4747

4848
// Ensure Webhook implements the authorizer.Authorizer interface.
@@ -197,10 +197,10 @@ func (w *WebhookAuthorizer) Authorize(attr authorizer.Attributes) (decision auth
197197
return w.decisionOnError, "", err
198198
}
199199
r.Status = result.Status
200-
if r.Status.Allowed {
201-
w.responseCache.Add(string(key), r.Status, w.authorizedTTL)
202-
} else {
203-
if callerControlledAttributeSize(attr) < maxUnauthorizedCachedKeySize {
200+
if shouldCache(attr) {
201+
if r.Status.Allowed {
202+
w.responseCache.Add(string(key), r.Status, w.authorizedTTL)
203+
} else {
204204
w.responseCache.Add(string(key), r.Status, w.unauthorizedTTL)
205205
}
206206
}
@@ -269,13 +269,16 @@ func (t *subjectAccessReviewClient) Create(subjectAccessReview *authorization.Su
269269
return result, err
270270
}
271271

272-
func callerControlledAttributeSize(attr authorizer.Attributes) int64 {
273-
return int64(len(attr.GetNamespace())) +
272+
// shouldCache determines whether it is safe to cache the given request attributes. If the
273+
// requester-controlled attributes are too large, this may be a DoS attempt, so we skip the cache.
274+
func shouldCache(attr authorizer.Attributes) bool {
275+
controlledAttrSize := int64(len(attr.GetNamespace())) +
274276
int64(len(attr.GetVerb())) +
275277
int64(len(attr.GetAPIGroup())) +
276278
int64(len(attr.GetAPIVersion())) +
277279
int64(len(attr.GetResource())) +
278280
int64(len(attr.GetSubresource())) +
279281
int64(len(attr.GetName())) +
280282
int64(len(attr.GetPath()))
283+
return controlledAttrSize < maxControlledAttrCacheSize
281284
}

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -616,10 +616,10 @@ func TestWebhookCache(t *testing.T) {
616616
{name: "ridiculous unauthorized request", attr: bobRidiculousAttr, allow: false, statusCode: 200, expectedErr: false, expectedAuthorized: false, expectedCalls: 1},
617617
// later ridiculous requests within the cache window still hit the backend
618618
{name: "ridiculous unauthorized request again", attr: bobRidiculousAttr, allow: false, statusCode: 200, expectedErr: false, expectedAuthorized: false, expectedCalls: 1},
619-
// ridiculous authorized requests are still cached.
619+
// ridiculous authorized requests are not cached.
620620
{name: "ridiculous authorized request", attr: aliceRidiculousAttr, allow: true, statusCode: 200, expectedErr: false, expectedAuthorized: true, expectedCalls: 1},
621-
// later ridiculous requests within the cache window don't hit the backend
622-
{name: "ridiculous authorized request again", attr: aliceRidiculousAttr, allow: false, statusCode: 500, expectedErr: false, expectedAuthorized: true, expectedCalls: 0},
621+
// later ridiculous requests within the cache window still hit the backend
622+
{name: "ridiculous authorized request again", attr: aliceRidiculousAttr, allow: true, statusCode: 200, expectedErr: false, expectedAuthorized: true, expectedCalls: 1},
623623
}
624624

625625
for i, test := range tests {

0 commit comments

Comments
 (0)