mirror of
https://github.com/k3s-io/kubernetes.git
synced 2026-01-13 11:25:19 +00:00
add nonResourceURL detection
This commit is contained in:
@@ -343,13 +343,13 @@ type RequestAttributeGetter interface {
|
||||
}
|
||||
|
||||
type requestAttributeGetter struct {
|
||||
requestContextMapper api.RequestContextMapper
|
||||
apiRequestInfoResolver *APIRequestInfoResolver
|
||||
requestContextMapper api.RequestContextMapper
|
||||
requestInfoResolver *RequestInfoResolver
|
||||
}
|
||||
|
||||
// NewAttributeGetter returns an object which implements the RequestAttributeGetter interface.
|
||||
func NewRequestAttributeGetter(requestContextMapper api.RequestContextMapper, apiRequestInfoResolver *APIRequestInfoResolver) RequestAttributeGetter {
|
||||
return &requestAttributeGetter{requestContextMapper, apiRequestInfoResolver}
|
||||
func NewRequestAttributeGetter(requestContextMapper api.RequestContextMapper, requestInfoResolver *RequestInfoResolver) RequestAttributeGetter {
|
||||
return &requestAttributeGetter{requestContextMapper, requestInfoResolver}
|
||||
}
|
||||
|
||||
func (r *requestAttributeGetter) GetAttribs(req *http.Request) authorizer.Attributes {
|
||||
@@ -363,7 +363,7 @@ func (r *requestAttributeGetter) GetAttribs(req *http.Request) authorizer.Attrib
|
||||
}
|
||||
}
|
||||
|
||||
apiRequestInfo, _ := r.apiRequestInfoResolver.GetAPIRequestInfo(req)
|
||||
apiRequestInfo, _ := r.requestInfoResolver.GetRequestInfo(req)
|
||||
|
||||
attribs.APIGroup = apiRequestInfo.APIGroup
|
||||
attribs.Verb = apiRequestInfo.Verb
|
||||
@@ -392,10 +392,16 @@ func WithAuthorizationCheck(handler http.Handler, getAttribs RequestAttributeGet
|
||||
})
|
||||
}
|
||||
|
||||
// APIRequestInfo holds information parsed from the http.Request
|
||||
type APIRequestInfo struct {
|
||||
// Verb is the kube verb associated with the request, not the http verb. This includes things like list and watch.
|
||||
Verb string
|
||||
// RequestInfo holds information parsed from the http.Request
|
||||
type RequestInfo struct {
|
||||
// IsResourceRequest indicates whether or not the request is for an API resource or subresource
|
||||
IsResourceRequest bool
|
||||
// Path is the URL path of the request
|
||||
Path string
|
||||
// Verb is the kube verb associated with the request for API requests, not the http verb. This includes things like list and watch.
|
||||
// for non-resource requests, this is the lowercase http verb
|
||||
Verb string
|
||||
|
||||
APIPrefix string
|
||||
APIGroup string
|
||||
APIVersion string
|
||||
@@ -410,20 +416,18 @@ type APIRequestInfo struct {
|
||||
Name string
|
||||
// Parts are the path parts for the request, always starting with /{resource}/{name}
|
||||
Parts []string
|
||||
// Raw is the unparsed form of everything other than parts.
|
||||
// Raw + Parts = complete URL path
|
||||
Raw []string
|
||||
}
|
||||
|
||||
type APIRequestInfoResolver struct {
|
||||
type RequestInfoResolver struct {
|
||||
APIPrefixes sets.String
|
||||
GrouplessAPIPrefixes sets.String
|
||||
}
|
||||
|
||||
// TODO write an integration test against the swagger doc to test the APIRequestInfo and match up behavior to responses
|
||||
// GetAPIRequestInfo returns the information from the http request. If error is not nil, APIRequestInfo holds the information as best it is known before the failure
|
||||
// TODO write an integration test against the swagger doc to test the RequestInfo and match up behavior to responses
|
||||
// GetRequestInfo returns the information from the http request. If error is not nil, RequestInfo holds the information as best it is known before the failure
|
||||
// It handles both resource and non-resource requests and fills in all the pertinent information for each.
|
||||
// Valid Inputs:
|
||||
// Storage paths
|
||||
// Resource paths
|
||||
// /apis/{api-group}/{version}/namespaces
|
||||
// /api/{version}/namespaces
|
||||
// /api/{version}/namespaces/{namespace}
|
||||
@@ -439,19 +443,32 @@ type APIRequestInfoResolver struct {
|
||||
// /api/{version}/redirect/{resource}/{resourceName}
|
||||
// /api/{version}/watch/{resource}
|
||||
// /api/{version}/watch/namespaces/{namespace}/{resource}
|
||||
func (r *APIRequestInfoResolver) GetAPIRequestInfo(req *http.Request) (APIRequestInfo, error) {
|
||||
requestInfo := APIRequestInfo{
|
||||
Raw: splitPath(req.URL.Path),
|
||||
Verb: strings.ToLower(req.Method),
|
||||
//
|
||||
// NonResource paths
|
||||
// /apis/{api-group}/{version}
|
||||
// /apis/{api-group}
|
||||
// /apis
|
||||
// /api/{version}
|
||||
// /api
|
||||
// /healthz
|
||||
// /
|
||||
func (r *RequestInfoResolver) GetRequestInfo(req *http.Request) (RequestInfo, error) {
|
||||
// start with a non-resource request until proven otherwise
|
||||
requestInfo := RequestInfo{
|
||||
IsResourceRequest: false,
|
||||
Path: req.URL.Path,
|
||||
Verb: strings.ToLower(req.Method),
|
||||
}
|
||||
|
||||
currentParts := requestInfo.Raw
|
||||
currentParts := splitPath(req.URL.Path)
|
||||
if len(currentParts) < 3 {
|
||||
return requestInfo, fmt.Errorf("a resource request must have a url with at least three parts, not %v", req.URL)
|
||||
// return a non-resource request
|
||||
return requestInfo, nil
|
||||
}
|
||||
|
||||
if !r.APIPrefixes.Has(currentParts[0]) {
|
||||
return requestInfo, &errAPIPrefixNotFound{currentParts[0]}
|
||||
// return a non-resource request
|
||||
return requestInfo, nil
|
||||
}
|
||||
requestInfo.APIPrefix = currentParts[0]
|
||||
currentParts = currentParts[1:]
|
||||
@@ -459,13 +476,15 @@ func (r *APIRequestInfoResolver) GetAPIRequestInfo(req *http.Request) (APIReques
|
||||
if !r.GrouplessAPIPrefixes.Has(requestInfo.APIPrefix) {
|
||||
// one part (APIPrefix) has already been consumed, so this is actually "do we have four parts?"
|
||||
if len(currentParts) < 3 {
|
||||
return requestInfo, fmt.Errorf("a resource request with an API group must have a url with at least four parts, not %v", req.URL)
|
||||
// return a non-resource request
|
||||
return requestInfo, nil
|
||||
}
|
||||
|
||||
requestInfo.APIGroup = currentParts[0]
|
||||
currentParts = currentParts[1:]
|
||||
}
|
||||
|
||||
requestInfo.IsResourceRequest = true
|
||||
requestInfo.APIVersion = currentParts[0]
|
||||
currentParts = currentParts[1:]
|
||||
|
||||
@@ -512,8 +531,6 @@ func (r *APIRequestInfoResolver) GetAPIRequestInfo(req *http.Request) (APIReques
|
||||
|
||||
// parsing successful, so we now know the proper value for .Parts
|
||||
requestInfo.Parts = currentParts
|
||||
// Raw should have everything not in Parts
|
||||
requestInfo.Raw = requestInfo.Raw[:len(requestInfo.Raw)-len(currentParts)]
|
||||
|
||||
// parts look like: resource/resourceName/subresource/other/stuff/we/don't/interpret
|
||||
switch {
|
||||
|
||||
Reference in New Issue
Block a user