mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-09-14 13:45:06 +00:00
add support for authorizing subresources
This commit is contained in:
@@ -19,7 +19,6 @@ package apiserver
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"path"
|
||||
"regexp"
|
||||
"runtime/debug"
|
||||
"strings"
|
||||
@@ -43,6 +42,11 @@ var specialVerbs = map[string]bool{
|
||||
"watch": true,
|
||||
}
|
||||
|
||||
// namespaceSubresouces is a set of all the subresources available on a namespace resource. This is a special case because
|
||||
// URLs look like api/v1beta3/namspaces/<namespace name>/[subresource | resource]. We need to be able to distinguish the two
|
||||
// different cases.
|
||||
var namespaceSubresources = util.NewStringSet("status", "finalize")
|
||||
|
||||
// Constant for the retry-after interval on rate limiting.
|
||||
// TODO: maybe make this dynamic? or user-adjustable?
|
||||
const RetryAfter = "1"
|
||||
@@ -240,6 +244,8 @@ type APIRequestInfo struct {
|
||||
Namespace string
|
||||
// Resource is the name of the resource being requested. This is not the kind. For example: pods
|
||||
Resource string
|
||||
// Subresource is the name of the subresource being requested. This is not the kind or the resource. For example: status for a pods/pod-name/status
|
||||
Subresource string
|
||||
// Kind is the type of object being manipulated. For example: Pod
|
||||
Kind string
|
||||
// Name is empty for some verbs, but if the request directly indicates a name (not in body content) then this field is filled in.
|
||||
@@ -251,17 +257,6 @@ type APIRequestInfo struct {
|
||||
Raw []string
|
||||
}
|
||||
|
||||
// URLPath returns the URL path for this request, including /{resource}/{name} if present but nothing
|
||||
// following that.
|
||||
func (info APIRequestInfo) URLPath() string {
|
||||
p := info.Parts
|
||||
if n := len(p); n > 2 {
|
||||
// Only take resource and name
|
||||
p = p[:2]
|
||||
}
|
||||
return path.Join("/", path.Join(info.Raw...), path.Join(p...))
|
||||
}
|
||||
|
||||
type APIRequestInfoResolver struct {
|
||||
APIPrefixes util.StringSet
|
||||
RestMapper meta.RESTMapper
|
||||
@@ -340,22 +335,20 @@ func (r *APIRequestInfoResolver) GetAPIRequestInfo(req *http.Request) (APIReques
|
||||
|
||||
// URL forms: /namespaces/{namespace}/{kind}/*, where parts are adjusted to be relative to kind
|
||||
if currentParts[0] == "namespaces" {
|
||||
if len(currentParts) < 3 {
|
||||
requestInfo.Resource = "namespaces"
|
||||
if len(currentParts) > 1 {
|
||||
requestInfo.Namespace = currentParts[1]
|
||||
}
|
||||
} else {
|
||||
requestInfo.Resource = currentParts[2]
|
||||
if len(currentParts) > 1 {
|
||||
requestInfo.Namespace = currentParts[1]
|
||||
currentParts = currentParts[2:]
|
||||
|
||||
// if there is another step after the namespace name and it is not a known namespace subresource
|
||||
// move currentParts to include it as a resource in its own right
|
||||
if len(currentParts) > 2 && !namespaceSubresources.Has(currentParts[2]) {
|
||||
currentParts = currentParts[2:]
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// URL forms: /{resource}/*
|
||||
// URL forms: POST /{resource} is a legacy API convention to create in "default" namespace
|
||||
// URL forms: /{resource}/{resourceName} use the "default" namespace if omitted from query param
|
||||
// URL forms: /{resource} assume cross-namespace operation if omitted from query param
|
||||
requestInfo.Resource = currentParts[0]
|
||||
requestInfo.Namespace = req.URL.Query().Get("namespace")
|
||||
if len(requestInfo.Namespace) == 0 {
|
||||
if len(currentParts) > 1 || req.Method == "POST" {
|
||||
@@ -371,9 +364,16 @@ func (r *APIRequestInfoResolver) GetAPIRequestInfo(req *http.Request) (APIReques
|
||||
// Raw should have everything not in Parts
|
||||
requestInfo.Raw = requestInfo.Raw[:len(requestInfo.Raw)-len(currentParts)]
|
||||
|
||||
// if there's another part remaining after the kind, then that's the resource name
|
||||
if len(requestInfo.Parts) >= 2 {
|
||||
// parts look like: resource/resourceName/subresource/other/stuff/we/don't/interpret
|
||||
switch {
|
||||
case len(requestInfo.Parts) >= 3:
|
||||
requestInfo.Subresource = requestInfo.Parts[2]
|
||||
fallthrough
|
||||
case len(requestInfo.Parts) == 2:
|
||||
requestInfo.Name = requestInfo.Parts[1]
|
||||
fallthrough
|
||||
case len(requestInfo.Parts) == 1:
|
||||
requestInfo.Resource = requestInfo.Parts[0]
|
||||
}
|
||||
|
||||
// if there's no name on the request and we thought it was a get before, then the actual verb is a list
|
||||
|
Reference in New Issue
Block a user