mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-02 00:07:50 +00:00
Merge pull request #14710 from liggitt/authz_attr
Auto commit by PR queue bot
This commit is contained in:
commit
333eaf5893
@ -362,11 +362,10 @@ func (r *requestAttributeGetter) GetAttribs(req *http.Request) authorizer.Attrib
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
attribs.ReadOnly = IsReadOnlyReq(*req)
|
|
||||||
|
|
||||||
apiRequestInfo, _ := r.apiRequestInfoResolver.GetAPIRequestInfo(req)
|
apiRequestInfo, _ := r.apiRequestInfoResolver.GetAPIRequestInfo(req)
|
||||||
|
|
||||||
attribs.APIGroup = apiRequestInfo.APIGroup
|
attribs.APIGroup = apiRequestInfo.APIGroup
|
||||||
|
attribs.Verb = apiRequestInfo.Verb
|
||||||
|
|
||||||
// If a path follows the conventions of the REST object store, then
|
// If a path follows the conventions of the REST object store, then
|
||||||
// we can extract the resource. Otherwise, not.
|
// we can extract the resource. Otherwise, not.
|
||||||
@ -441,7 +440,8 @@ type APIRequestInfoResolver struct {
|
|||||||
// /api/{version}/watch/namespaces/{namespace}/{resource}
|
// /api/{version}/watch/namespaces/{namespace}/{resource}
|
||||||
func (r *APIRequestInfoResolver) GetAPIRequestInfo(req *http.Request) (APIRequestInfo, error) {
|
func (r *APIRequestInfoResolver) GetAPIRequestInfo(req *http.Request) (APIRequestInfo, error) {
|
||||||
requestInfo := APIRequestInfo{
|
requestInfo := APIRequestInfo{
|
||||||
Raw: splitPath(req.URL.Path),
|
Raw: splitPath(req.URL.Path),
|
||||||
|
Verb: strings.ToLower(req.Method),
|
||||||
}
|
}
|
||||||
|
|
||||||
currentParts := requestInfo.Raw
|
currentParts := requestInfo.Raw
|
||||||
@ -489,8 +489,9 @@ func (r *APIRequestInfoResolver) GetAPIRequestInfo(req *http.Request) (APIReques
|
|||||||
requestInfo.Verb = "patch"
|
requestInfo.Verb = "patch"
|
||||||
case "DELETE":
|
case "DELETE":
|
||||||
requestInfo.Verb = "delete"
|
requestInfo.Verb = "delete"
|
||||||
|
default:
|
||||||
|
requestInfo.Verb = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// URL forms: /namespaces/{namespace}/{kind}/*, where parts are adjusted to be relative to kind
|
// URL forms: /namespaces/{namespace}/{kind}/*, where parts are adjusted to be relative to kind
|
||||||
|
@ -75,49 +75,49 @@ func TestNotAuthorized(t *testing.T) {
|
|||||||
|
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
User user.DefaultInfo
|
User user.DefaultInfo
|
||||||
RO bool
|
Verb string
|
||||||
Resource string
|
Resource string
|
||||||
NS string
|
NS string
|
||||||
ExpectAllow bool
|
ExpectAllow bool
|
||||||
}{
|
}{
|
||||||
// Scheduler can read pods
|
// Scheduler can read pods
|
||||||
{User: uScheduler, RO: true, Resource: "pods", NS: "ns1", ExpectAllow: true},
|
{User: uScheduler, Verb: "list", Resource: "pods", NS: "ns1", ExpectAllow: true},
|
||||||
{User: uScheduler, RO: true, Resource: "pods", NS: "", ExpectAllow: true},
|
{User: uScheduler, Verb: "list", Resource: "pods", NS: "", ExpectAllow: true},
|
||||||
// Scheduler cannot write pods
|
// Scheduler cannot write pods
|
||||||
{User: uScheduler, RO: false, Resource: "pods", NS: "ns1", ExpectAllow: false},
|
{User: uScheduler, Verb: "create", Resource: "pods", NS: "ns1", ExpectAllow: false},
|
||||||
{User: uScheduler, RO: false, Resource: "pods", NS: "", ExpectAllow: false},
|
{User: uScheduler, Verb: "create", Resource: "pods", NS: "", ExpectAllow: false},
|
||||||
// Scheduler can write bindings
|
// Scheduler can write bindings
|
||||||
{User: uScheduler, RO: true, Resource: "bindings", NS: "ns1", ExpectAllow: true},
|
{User: uScheduler, Verb: "get", Resource: "bindings", NS: "ns1", ExpectAllow: true},
|
||||||
{User: uScheduler, RO: true, Resource: "bindings", NS: "", ExpectAllow: true},
|
{User: uScheduler, Verb: "get", Resource: "bindings", NS: "", ExpectAllow: true},
|
||||||
|
|
||||||
// Alice can read and write anything in the right namespace.
|
// Alice can read and write anything in the right namespace.
|
||||||
{User: uAlice, RO: true, Resource: "pods", NS: "projectCaribou", ExpectAllow: true},
|
{User: uAlice, Verb: "get", Resource: "pods", NS: "projectCaribou", ExpectAllow: true},
|
||||||
{User: uAlice, RO: true, Resource: "widgets", NS: "projectCaribou", ExpectAllow: true},
|
{User: uAlice, Verb: "get", Resource: "widgets", NS: "projectCaribou", ExpectAllow: true},
|
||||||
{User: uAlice, RO: true, Resource: "", NS: "projectCaribou", ExpectAllow: true},
|
{User: uAlice, Verb: "get", Resource: "", NS: "projectCaribou", ExpectAllow: true},
|
||||||
{User: uAlice, RO: false, Resource: "pods", NS: "projectCaribou", ExpectAllow: true},
|
{User: uAlice, Verb: "update", Resource: "pods", NS: "projectCaribou", ExpectAllow: true},
|
||||||
{User: uAlice, RO: false, Resource: "widgets", NS: "projectCaribou", ExpectAllow: true},
|
{User: uAlice, Verb: "update", Resource: "widgets", NS: "projectCaribou", ExpectAllow: true},
|
||||||
{User: uAlice, RO: false, Resource: "", NS: "projectCaribou", ExpectAllow: true},
|
{User: uAlice, Verb: "update", Resource: "", NS: "projectCaribou", ExpectAllow: true},
|
||||||
// .. but not the wrong namespace.
|
// .. but not the wrong namespace.
|
||||||
{User: uAlice, RO: true, Resource: "pods", NS: "ns1", ExpectAllow: false},
|
{User: uAlice, Verb: "get", Resource: "pods", NS: "ns1", ExpectAllow: false},
|
||||||
{User: uAlice, RO: true, Resource: "widgets", NS: "ns1", ExpectAllow: false},
|
{User: uAlice, Verb: "get", Resource: "widgets", NS: "ns1", ExpectAllow: false},
|
||||||
{User: uAlice, RO: true, Resource: "", NS: "ns1", ExpectAllow: false},
|
{User: uAlice, Verb: "get", Resource: "", NS: "ns1", ExpectAllow: false},
|
||||||
|
|
||||||
// Chuck can read events, since anyone can.
|
// Chuck can read events, since anyone can.
|
||||||
{User: uChuck, RO: true, Resource: "events", NS: "ns1", ExpectAllow: true},
|
{User: uChuck, Verb: "get", Resource: "events", NS: "ns1", ExpectAllow: true},
|
||||||
{User: uChuck, RO: true, Resource: "events", NS: "", ExpectAllow: true},
|
{User: uChuck, Verb: "get", Resource: "events", NS: "", ExpectAllow: true},
|
||||||
// Chuck can't do other things.
|
// Chuck can't do other things.
|
||||||
{User: uChuck, RO: false, Resource: "events", NS: "ns1", ExpectAllow: false},
|
{User: uChuck, Verb: "update", Resource: "events", NS: "ns1", ExpectAllow: false},
|
||||||
{User: uChuck, RO: true, Resource: "pods", NS: "ns1", ExpectAllow: false},
|
{User: uChuck, Verb: "get", Resource: "pods", NS: "ns1", ExpectAllow: false},
|
||||||
{User: uChuck, RO: true, Resource: "floop", NS: "ns1", ExpectAllow: false},
|
{User: uChuck, Verb: "get", Resource: "floop", NS: "ns1", ExpectAllow: false},
|
||||||
// Chunk can't access things with no kind or namespace
|
// Chunk can't access things with no kind or namespace
|
||||||
// TODO: find a way to give someone access to miscellaneous endpoints, such as
|
// TODO: find a way to give someone access to miscellaneous endpoints, such as
|
||||||
// /healthz, /version, etc.
|
// /healthz, /version, etc.
|
||||||
{User: uChuck, RO: true, Resource: "", NS: "", ExpectAllow: false},
|
{User: uChuck, Verb: "get", Resource: "", NS: "", ExpectAllow: false},
|
||||||
}
|
}
|
||||||
for i, tc := range testCases {
|
for i, tc := range testCases {
|
||||||
attr := authorizer.AttributesRecord{
|
attr := authorizer.AttributesRecord{
|
||||||
User: &tc.User,
|
User: &tc.User,
|
||||||
ReadOnly: tc.RO,
|
Verb: tc.Verb,
|
||||||
Resource: tc.Resource,
|
Resource: tc.Resource,
|
||||||
Namespace: tc.NS,
|
Namespace: tc.NS,
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,10 @@ type Attributes interface {
|
|||||||
// authentication occurred.
|
// authentication occurred.
|
||||||
GetGroups() []string
|
GetGroups() []string
|
||||||
|
|
||||||
|
// GetVerb returns the kube verb associated with API requests (this includes get, list, watch, create, update, patch, delete, and proxy),
|
||||||
|
// or the lowercased HTTP verb associated with non-API requests (this includes get, put, post, patch, and delete)
|
||||||
|
GetVerb() string
|
||||||
|
|
||||||
// When IsReadOnly() == true, the request has no side effects, other than
|
// When IsReadOnly() == true, the request has no side effects, other than
|
||||||
// caching, logging, and other incidentals.
|
// caching, logging, and other incidentals.
|
||||||
IsReadOnly() bool
|
IsReadOnly() bool
|
||||||
@ -62,7 +66,7 @@ func (f AuthorizerFunc) Authorize(a Attributes) error {
|
|||||||
// AttributesRecord implements Attributes interface.
|
// AttributesRecord implements Attributes interface.
|
||||||
type AttributesRecord struct {
|
type AttributesRecord struct {
|
||||||
User user.Info
|
User user.Info
|
||||||
ReadOnly bool
|
Verb string
|
||||||
Namespace string
|
Namespace string
|
||||||
APIGroup string
|
APIGroup string
|
||||||
Resource string
|
Resource string
|
||||||
@ -76,8 +80,12 @@ func (a AttributesRecord) GetGroups() []string {
|
|||||||
return a.User.GetGroups()
|
return a.User.GetGroups()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a AttributesRecord) GetVerb() string {
|
||||||
|
return a.Verb
|
||||||
|
}
|
||||||
|
|
||||||
func (a AttributesRecord) IsReadOnly() bool {
|
func (a AttributesRecord) IsReadOnly() bool {
|
||||||
return a.ReadOnly
|
return a.Verb == "get" || a.Verb == "list" || a.Verb == "watch"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a AttributesRecord) GetNamespace() string {
|
func (a AttributesRecord) GetNamespace() string {
|
||||||
|
Loading…
Reference in New Issue
Block a user