mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-25 12:43:23 +00:00
Merge pull request #31271 from deads2k/self-sar
Automatic merge from submit-queue add selfsubjectaccessreview API Exposes the REST API for self subject access reviews. This allows a user to see whether or not they can perform a particular action. @kubernetes/sig-auth
This commit is contained in:
commit
7a4d81ea43
@ -8,6 +8,51 @@
|
||||
"description": ""
|
||||
},
|
||||
"apis": [
|
||||
{
|
||||
"path": "/apis/authorization.k8s.io/v1beta1/selfsubjectaccessreviews",
|
||||
"description": "API at /apis/authorization.k8s.io/v1beta1",
|
||||
"operations": [
|
||||
{
|
||||
"type": "v1beta1.SelfSubjectAccessReview",
|
||||
"method": "POST",
|
||||
"summary": "create a SelfSubjectAccessReview",
|
||||
"nickname": "createSelfSubjectAccessReview",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"paramType": "query",
|
||||
"name": "pretty",
|
||||
"description": "If 'true', then the output is pretty printed.",
|
||||
"required": false,
|
||||
"allowMultiple": false
|
||||
},
|
||||
{
|
||||
"type": "v1beta1.SelfSubjectAccessReview",
|
||||
"paramType": "body",
|
||||
"name": "body",
|
||||
"description": "",
|
||||
"required": true,
|
||||
"allowMultiple": false
|
||||
}
|
||||
],
|
||||
"responseMessages": [
|
||||
{
|
||||
"code": 200,
|
||||
"message": "OK",
|
||||
"responseModel": "v1beta1.SelfSubjectAccessReview"
|
||||
}
|
||||
],
|
||||
"produces": [
|
||||
"application/json",
|
||||
"application/yaml",
|
||||
"application/vnd.kubernetes.protobuf"
|
||||
],
|
||||
"consumes": [
|
||||
"*/*"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/apis/authorization.k8s.io/v1beta1/subjectaccessreviews",
|
||||
"description": "API at /apis/authorization.k8s.io/v1beta1",
|
||||
@ -78,9 +123,9 @@
|
||||
}
|
||||
],
|
||||
"models": {
|
||||
"v1beta1.SubjectAccessReview": {
|
||||
"id": "v1beta1.SubjectAccessReview",
|
||||
"description": "SubjectAccessReview checks whether or not a user or group can perform an action.",
|
||||
"v1beta1.SelfSubjectAccessReview": {
|
||||
"id": "v1beta1.SelfSubjectAccessReview",
|
||||
"description": "SelfSubjectAccessReview checks whether or the current user can perform an action. Not filling in a spec.namespace means \"in all namespaces\". Self is a special case, because users should always be able to check whether they can perform an action",
|
||||
"required": [
|
||||
"spec"
|
||||
],
|
||||
@ -97,8 +142,8 @@
|
||||
"$ref": "v1.ObjectMeta"
|
||||
},
|
||||
"spec": {
|
||||
"$ref": "v1beta1.SubjectAccessReviewSpec",
|
||||
"description": "Spec holds information about the request being evaluated"
|
||||
"$ref": "v1beta1.SelfSubjectAccessReviewSpec",
|
||||
"description": "Spec holds information about the request being evaluated. user and groups must be empty"
|
||||
},
|
||||
"status": {
|
||||
"$ref": "v1beta1.SubjectAccessReviewStatus",
|
||||
@ -214,9 +259,9 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"v1beta1.SubjectAccessReviewSpec": {
|
||||
"id": "v1beta1.SubjectAccessReviewSpec",
|
||||
"description": "SubjectAccessReviewSpec is a description of the access request. Exactly one of ResourceAuthorizationAttributes and NonResourceAuthorizationAttributes must be set",
|
||||
"v1beta1.SelfSubjectAccessReviewSpec": {
|
||||
"id": "v1beta1.SelfSubjectAccessReviewSpec",
|
||||
"description": "SelfSubjectAccessReviewSpec is a description of the access request. Exactly one of ResourceAuthorizationAttributes and NonResourceAuthorizationAttributes must be set",
|
||||
"properties": {
|
||||
"resourceAttributes": {
|
||||
"$ref": "v1beta1.ResourceAttributes",
|
||||
@ -225,21 +270,6 @@
|
||||
"nonResourceAttributes": {
|
||||
"$ref": "v1beta1.NonResourceAttributes",
|
||||
"description": "NonResourceAttributes describes information for a non-resource access request"
|
||||
},
|
||||
"user": {
|
||||
"type": "string",
|
||||
"description": "User is the user you're testing for. If you specify \"User\" but not \"Group\", then is it interpreted as \"What if User were not a member of any groups"
|
||||
},
|
||||
"group": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": "Groups is the groups you're testing for."
|
||||
},
|
||||
"extra": {
|
||||
"type": "object",
|
||||
"description": "Extra corresponds to the user.Info.GetExtra() method from the authenticator. Since that is input to the authorizer it needs a reflection here."
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -312,6 +342,63 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"v1beta1.SubjectAccessReview": {
|
||||
"id": "v1beta1.SubjectAccessReview",
|
||||
"description": "SubjectAccessReview checks whether or not a user or group can perform an action.",
|
||||
"required": [
|
||||
"spec"
|
||||
],
|
||||
"properties": {
|
||||
"kind": {
|
||||
"type": "string",
|
||||
"description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#types-kinds"
|
||||
},
|
||||
"apiVersion": {
|
||||
"type": "string",
|
||||
"description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#resources"
|
||||
},
|
||||
"metadata": {
|
||||
"$ref": "v1.ObjectMeta"
|
||||
},
|
||||
"spec": {
|
||||
"$ref": "v1beta1.SubjectAccessReviewSpec",
|
||||
"description": "Spec holds information about the request being evaluated"
|
||||
},
|
||||
"status": {
|
||||
"$ref": "v1beta1.SubjectAccessReviewStatus",
|
||||
"description": "Status is filled in by the server and indicates whether the request is allowed or not"
|
||||
}
|
||||
}
|
||||
},
|
||||
"v1beta1.SubjectAccessReviewSpec": {
|
||||
"id": "v1beta1.SubjectAccessReviewSpec",
|
||||
"description": "SubjectAccessReviewSpec is a description of the access request. Exactly one of ResourceAuthorizationAttributes and NonResourceAuthorizationAttributes must be set",
|
||||
"properties": {
|
||||
"resourceAttributes": {
|
||||
"$ref": "v1beta1.ResourceAttributes",
|
||||
"description": "ResourceAuthorizationAttributes describes information for a resource access request"
|
||||
},
|
||||
"nonResourceAttributes": {
|
||||
"$ref": "v1beta1.NonResourceAttributes",
|
||||
"description": "NonResourceAttributes describes information for a non-resource access request"
|
||||
},
|
||||
"user": {
|
||||
"type": "string",
|
||||
"description": "User is the user you're testing for. If you specify \"User\" but not \"Group\", then is it interpreted as \"What if User were not a member of any groups"
|
||||
},
|
||||
"group": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": "Groups is the groups you're testing for."
|
||||
},
|
||||
"extra": {
|
||||
"type": "object",
|
||||
"description": "Extra corresponds to the user.Info.GetExtra() method from the authenticator. Since that is input to the authorizer it needs a reflection here."
|
||||
}
|
||||
}
|
||||
},
|
||||
"unversioned.APIResourceList": {
|
||||
"id": "unversioned.APIResourceList",
|
||||
"description": "APIResourceList is a list of APIResource, it is used to expose the name of the resources supported in a specific group and version, and if the resource is namespaced.",
|
||||
|
@ -38,6 +38,10 @@ type SubjectAccessReview struct {
|
||||
Status SubjectAccessReviewStatus
|
||||
}
|
||||
|
||||
// +genclient=true
|
||||
// +nonNamespaced=true
|
||||
// +noMethods=true
|
||||
|
||||
// SelfSubjectAccessReview checks whether or the current user can perform an action. Not filling in a
|
||||
// spec.namespace means "in all namespaces". Self is a special case, because users should always be able
|
||||
// to check whether they can perform an action
|
||||
|
@ -39,6 +39,10 @@ type SubjectAccessReview struct {
|
||||
Status SubjectAccessReviewStatus `json:"status,omitempty" protobuf:"bytes,3,opt,name=status"`
|
||||
}
|
||||
|
||||
// +genclient=true
|
||||
// +nonNamespaced=true
|
||||
// +noMethods=true
|
||||
|
||||
// SelfSubjectAccessReview checks whether or the current user can perform an action. Not filling in a
|
||||
// spec.namespace means "in all namespaces". Self is a special case, because users should always be able
|
||||
// to check whether they can perform an action
|
||||
|
@ -24,6 +24,7 @@ import (
|
||||
|
||||
type AuthorizationInterface interface {
|
||||
GetRESTClient() *restclient.RESTClient
|
||||
SelfSubjectAccessReviewsGetter
|
||||
SubjectAccessReviewsGetter
|
||||
}
|
||||
|
||||
@ -32,6 +33,10 @@ type AuthorizationClient struct {
|
||||
*restclient.RESTClient
|
||||
}
|
||||
|
||||
func (c *AuthorizationClient) SelfSubjectAccessReviews() SelfSubjectAccessReviewInterface {
|
||||
return newSelfSubjectAccessReviews(c)
|
||||
}
|
||||
|
||||
func (c *AuthorizationClient) SubjectAccessReviews() SubjectAccessReviewInterface {
|
||||
return newSubjectAccessReviews(c)
|
||||
}
|
||||
|
@ -26,6 +26,10 @@ type FakeAuthorization struct {
|
||||
*core.Fake
|
||||
}
|
||||
|
||||
func (c *FakeAuthorization) SelfSubjectAccessReviews() unversioned.SelfSubjectAccessReviewInterface {
|
||||
return &FakeSelfSubjectAccessReviews{c}
|
||||
}
|
||||
|
||||
func (c *FakeAuthorization) SubjectAccessReviews() unversioned.SubjectAccessReviewInterface {
|
||||
return &FakeSubjectAccessReviews{c}
|
||||
}
|
||||
|
@ -26,3 +26,8 @@ func (c *FakeSubjectAccessReviews) Create(sar *authorizationapi.SubjectAccessRev
|
||||
obj, err := c.Fake.Invokes(core.NewRootCreateAction(authorizationapi.SchemeGroupVersion.WithResource("subjectaccessreviews"), sar), &authorizationapi.SubjectAccessReview{})
|
||||
return obj.(*authorizationapi.SubjectAccessReview), err
|
||||
}
|
||||
|
||||
func (c *FakeSelfSubjectAccessReviews) Create(sar *authorizationapi.SelfSubjectAccessReview) (result *authorizationapi.SelfSubjectAccessReview, err error) {
|
||||
obj, err := c.Fake.Invokes(core.NewRootCreateAction(authorizationapi.SchemeGroupVersion.WithResource("selfsubjectaccessreviews"), sar), &authorizationapi.SelfSubjectAccessReview{})
|
||||
return obj.(*authorizationapi.SelfSubjectAccessReview), err
|
||||
}
|
||||
|
@ -0,0 +1,22 @@
|
||||
/*
|
||||
Copyright 2016 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package fake
|
||||
|
||||
// FakeSelfSubjectAccessReviews implements SelfSubjectAccessReviewInterface
|
||||
type FakeSelfSubjectAccessReviews struct {
|
||||
Fake *FakeAuthorization
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
/*
|
||||
Copyright 2016 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package unversioned
|
||||
|
||||
// SelfSubjectAccessReviewsGetter has a method to return a SelfSubjectAccessReviewInterface.
|
||||
// A group's client should implement this interface.
|
||||
type SelfSubjectAccessReviewsGetter interface {
|
||||
SelfSubjectAccessReviews() SelfSubjectAccessReviewInterface
|
||||
}
|
||||
|
||||
// SelfSubjectAccessReviewInterface has methods to work with SelfSubjectAccessReview resources.
|
||||
type SelfSubjectAccessReviewInterface interface {
|
||||
SelfSubjectAccessReviewExpansion
|
||||
}
|
||||
|
||||
// selfSubjectAccessReviews implements SelfSubjectAccessReviewInterface
|
||||
type selfSubjectAccessReviews struct {
|
||||
client *AuthorizationClient
|
||||
}
|
||||
|
||||
// newSelfSubjectAccessReviews returns a SelfSubjectAccessReviews
|
||||
func newSelfSubjectAccessReviews(c *AuthorizationClient) *selfSubjectAccessReviews {
|
||||
return &selfSubjectAccessReviews{
|
||||
client: c,
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
/*
|
||||
Copyright 2016 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package unversioned
|
||||
|
||||
import (
|
||||
authorizationapi "k8s.io/kubernetes/pkg/apis/authorization"
|
||||
)
|
||||
|
||||
type SelfSubjectAccessReviewExpansion interface {
|
||||
Create(sar *authorizationapi.SelfSubjectAccessReview) (result *authorizationapi.SelfSubjectAccessReview, err error)
|
||||
}
|
||||
|
||||
func (c *selfSubjectAccessReviews) Create(sar *authorizationapi.SelfSubjectAccessReview) (result *authorizationapi.SelfSubjectAccessReview, err error) {
|
||||
result = &authorizationapi.SelfSubjectAccessReview{}
|
||||
err = c.client.Post().
|
||||
Resource("selfsubjectaccessreviews").
|
||||
Body(sar).
|
||||
Do().
|
||||
Into(result)
|
||||
return
|
||||
}
|
@ -20,7 +20,6 @@ import (
|
||||
authorizationapi "k8s.io/kubernetes/pkg/apis/authorization"
|
||||
)
|
||||
|
||||
// The PodExpansion interface allows manually adding extra methods to the PodInterface.
|
||||
type SubjectAccessReviewExpansion interface {
|
||||
Create(sar *authorizationapi.SubjectAccessReview) (result *authorizationapi.SubjectAccessReview, err error)
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ import (
|
||||
|
||||
type AuthorizationInterface interface {
|
||||
GetRESTClient() *restclient.RESTClient
|
||||
SelfSubjectAccessReviewsGetter
|
||||
SubjectAccessReviewsGetter
|
||||
}
|
||||
|
||||
@ -33,6 +34,10 @@ type AuthorizationClient struct {
|
||||
*restclient.RESTClient
|
||||
}
|
||||
|
||||
func (c *AuthorizationClient) SelfSubjectAccessReviews() SelfSubjectAccessReviewInterface {
|
||||
return newSelfSubjectAccessReviews(c)
|
||||
}
|
||||
|
||||
func (c *AuthorizationClient) SubjectAccessReviews() SubjectAccessReviewInterface {
|
||||
return newSubjectAccessReviews(c)
|
||||
}
|
||||
|
@ -26,6 +26,10 @@ type FakeAuthorization struct {
|
||||
*core.Fake
|
||||
}
|
||||
|
||||
func (c *FakeAuthorization) SelfSubjectAccessReviews() v1beta1.SelfSubjectAccessReviewInterface {
|
||||
return &FakeSelfSubjectAccessReviews{c}
|
||||
}
|
||||
|
||||
func (c *FakeAuthorization) SubjectAccessReviews() v1beta1.SubjectAccessReviewInterface {
|
||||
return &FakeSubjectAccessReviews{c}
|
||||
}
|
||||
|
@ -0,0 +1,22 @@
|
||||
/*
|
||||
Copyright 2016 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package fake
|
||||
|
||||
// FakeSelfSubjectAccessReviews implements SelfSubjectAccessReviewInterface
|
||||
type FakeSelfSubjectAccessReviews struct {
|
||||
Fake *FakeAuthorization
|
||||
}
|
@ -26,3 +26,8 @@ func (c *FakeSubjectAccessReviews) Create(sar *authorizationapi.SubjectAccessRev
|
||||
obj, err := c.Fake.Invokes(core.NewRootCreateAction(authorizationapi.SchemeGroupVersion.WithResource("subjectaccessreviews"), sar), &authorizationapi.SubjectAccessReview{})
|
||||
return obj.(*authorizationapi.SubjectAccessReview), err
|
||||
}
|
||||
|
||||
func (c *FakeSelfSubjectAccessReviews) Create(sar *authorizationapi.SelfSubjectAccessReview) (result *authorizationapi.SelfSubjectAccessReview, err error) {
|
||||
obj, err := c.Fake.Invokes(core.NewRootCreateAction(authorizationapi.SchemeGroupVersion.WithResource("selfsubjectaccessreviews"), sar), &authorizationapi.SelfSubjectAccessReview{})
|
||||
return obj.(*authorizationapi.SelfSubjectAccessReview), err
|
||||
}
|
||||
|
@ -0,0 +1,40 @@
|
||||
/*
|
||||
Copyright 2016 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package v1beta1
|
||||
|
||||
// SelfSubjectAccessReviewsGetter has a method to return a SelfSubjectAccessReviewInterface.
|
||||
// A group's client should implement this interface.
|
||||
type SelfSubjectAccessReviewsGetter interface {
|
||||
SelfSubjectAccessReviews() SelfSubjectAccessReviewInterface
|
||||
}
|
||||
|
||||
// SelfSubjectAccessReviewInterface has methods to work with SelfSubjectAccessReview resources.
|
||||
type SelfSubjectAccessReviewInterface interface {
|
||||
SelfSubjectAccessReviewExpansion
|
||||
}
|
||||
|
||||
// selfSubjectAccessReviews implements SelfSubjectAccessReviewInterface
|
||||
type selfSubjectAccessReviews struct {
|
||||
client *AuthorizationClient
|
||||
}
|
||||
|
||||
// newSelfSubjectAccessReviews returns a SelfSubjectAccessReviews
|
||||
func newSelfSubjectAccessReviews(c *AuthorizationClient) *selfSubjectAccessReviews {
|
||||
return &selfSubjectAccessReviews{
|
||||
client: c,
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
/*
|
||||
Copyright 2016 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package v1beta1
|
||||
|
||||
import (
|
||||
authorizationapi "k8s.io/kubernetes/pkg/apis/authorization/v1beta1"
|
||||
)
|
||||
|
||||
type SelfSubjectAccessReviewExpansion interface {
|
||||
Create(sar *authorizationapi.SelfSubjectAccessReview) (result *authorizationapi.SelfSubjectAccessReview, err error)
|
||||
}
|
||||
|
||||
func (c *selfSubjectAccessReviews) Create(sar *authorizationapi.SelfSubjectAccessReview) (result *authorizationapi.SelfSubjectAccessReview, err error) {
|
||||
result = &authorizationapi.SelfSubjectAccessReview{}
|
||||
err = c.client.Post().
|
||||
Resource("selfsubjectaccessreviews").
|
||||
Body(sar).
|
||||
Do().
|
||||
Into(result)
|
||||
return
|
||||
}
|
@ -525,12 +525,13 @@ func (gc *GarbageCollector) monitorFor(resource unversioned.GroupVersionResource
|
||||
}
|
||||
|
||||
var ignoredResources = map[unversioned.GroupVersionResource]struct{}{
|
||||
unversioned.GroupVersionResource{Group: "extensions", Version: "v1beta1", Resource: "replicationcontrollers"}: {},
|
||||
unversioned.GroupVersionResource{Group: "", Version: "v1", Resource: "bindings"}: {},
|
||||
unversioned.GroupVersionResource{Group: "", Version: "v1", Resource: "componentstatuses"}: {},
|
||||
unversioned.GroupVersionResource{Group: "", Version: "v1", Resource: "events"}: {},
|
||||
unversioned.GroupVersionResource{Group: "authentication.k8s.io", Version: "v1beta1", Resource: "tokenreviews"}: {},
|
||||
unversioned.GroupVersionResource{Group: "authorization.k8s.io", Version: "v1beta1", Resource: "subjectaccessreviews"}: {},
|
||||
unversioned.GroupVersionResource{Group: "extensions", Version: "v1beta1", Resource: "replicationcontrollers"}: {},
|
||||
unversioned.GroupVersionResource{Group: "", Version: "v1", Resource: "bindings"}: {},
|
||||
unversioned.GroupVersionResource{Group: "", Version: "v1", Resource: "componentstatuses"}: {},
|
||||
unversioned.GroupVersionResource{Group: "", Version: "v1", Resource: "events"}: {},
|
||||
unversioned.GroupVersionResource{Group: "authentication.k8s.io", Version: "v1beta1", Resource: "tokenreviews"}: {},
|
||||
unversioned.GroupVersionResource{Group: "authorization.k8s.io", Version: "v1beta1", Resource: "subjectaccessreviews"}: {},
|
||||
unversioned.GroupVersionResource{Group: "authorization.k8s.io", Version: "v1beta1", Resource: "selfsubjectaccessreviews"}: {},
|
||||
}
|
||||
|
||||
func NewGarbageCollector(metaOnlyClientPool dynamic.ClientPool, clientPool dynamic.ClientPool, resources []unversioned.GroupVersionResource) (*GarbageCollector, error) {
|
||||
|
@ -22,6 +22,7 @@ import (
|
||||
authorizationv1beta1 "k8s.io/kubernetes/pkg/apis/authorization/v1beta1"
|
||||
"k8s.io/kubernetes/pkg/auth/authorizer"
|
||||
"k8s.io/kubernetes/pkg/genericapiserver"
|
||||
"k8s.io/kubernetes/pkg/registry/authorization/selfsubjectaccessreview"
|
||||
"k8s.io/kubernetes/pkg/registry/authorization/subjectaccessreview"
|
||||
)
|
||||
|
||||
@ -53,6 +54,9 @@ func (p AuthorizationRESTStorageProvider) v1beta1Storage(apiResourceConfigSource
|
||||
if apiResourceConfigSource.ResourceEnabled(version.WithResource("subjectaccessreviews")) {
|
||||
storage["subjectaccessreviews"] = subjectaccessreview.NewREST(p.Authorizer)
|
||||
}
|
||||
if apiResourceConfigSource.ResourceEnabled(version.WithResource("selfsubjectaccessreviews")) {
|
||||
storage["selfsubjectaccessreviews"] = selfsubjectaccessreview.NewREST(p.Authorizer)
|
||||
}
|
||||
|
||||
return storage
|
||||
}
|
||||
|
74
pkg/registry/authorization/selfsubjectaccessreview/rest.go
Normal file
74
pkg/registry/authorization/selfsubjectaccessreview/rest.go
Normal file
@ -0,0 +1,74 @@
|
||||
/*
|
||||
Copyright 2016 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package selfsubjectaccessreview
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
apierrors "k8s.io/kubernetes/pkg/api/errors"
|
||||
authorizationapi "k8s.io/kubernetes/pkg/apis/authorization"
|
||||
authorizationvalidation "k8s.io/kubernetes/pkg/apis/authorization/validation"
|
||||
"k8s.io/kubernetes/pkg/auth/authorizer"
|
||||
authorizationutil "k8s.io/kubernetes/pkg/registry/authorization/util"
|
||||
"k8s.io/kubernetes/pkg/runtime"
|
||||
)
|
||||
|
||||
type REST struct {
|
||||
authorizer authorizer.Authorizer
|
||||
}
|
||||
|
||||
func NewREST(authorizer authorizer.Authorizer) *REST {
|
||||
return &REST{authorizer}
|
||||
}
|
||||
|
||||
func (r *REST) New() runtime.Object {
|
||||
return &authorizationapi.SelfSubjectAccessReview{}
|
||||
}
|
||||
|
||||
func (r *REST) Create(ctx api.Context, obj runtime.Object) (runtime.Object, error) {
|
||||
selfSAR, ok := obj.(*authorizationapi.SelfSubjectAccessReview)
|
||||
if !ok {
|
||||
return nil, apierrors.NewBadRequest(fmt.Sprintf("not a SelfSubjectAccessReview: %#v", obj))
|
||||
}
|
||||
if errs := authorizationvalidation.ValidateSelfSubjectAccessReview(selfSAR); len(errs) > 0 {
|
||||
return nil, apierrors.NewInvalid(authorizationapi.Kind(selfSAR.Kind), "", errs)
|
||||
}
|
||||
userToCheck, exists := api.UserFrom(ctx)
|
||||
if !exists {
|
||||
return nil, apierrors.NewBadRequest("no user present on request")
|
||||
}
|
||||
|
||||
var authorizationAttributes authorizer.AttributesRecord
|
||||
if selfSAR.Spec.ResourceAttributes != nil {
|
||||
authorizationAttributes = authorizationutil.ResourceAttributesFrom(userToCheck, *selfSAR.Spec.ResourceAttributes)
|
||||
} else {
|
||||
authorizationAttributes = authorizationutil.NonResourceAttributesFrom(userToCheck, *selfSAR.Spec.NonResourceAttributes)
|
||||
}
|
||||
|
||||
allowed, reason, evaluationErr := r.authorizer.Authorize(authorizationAttributes)
|
||||
|
||||
selfSAR.Status = authorizationapi.SubjectAccessReviewStatus{
|
||||
Allowed: allowed,
|
||||
Reason: reason,
|
||||
}
|
||||
if evaluationErr != nil {
|
||||
selfSAR.Status.EvaluationError = evaluationErr.Error()
|
||||
}
|
||||
|
||||
return selfSAR, nil
|
||||
}
|
@ -57,7 +57,6 @@ func alwaysAlice(req *http.Request) (user.Info, bool, error) {
|
||||
}
|
||||
|
||||
func TestSubjectAccessReview(t *testing.T) {
|
||||
// Set up a master
|
||||
var m *master.Master
|
||||
s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
||||
m.Handler.ServeHTTP(w, req)
|
||||
@ -153,7 +152,96 @@ func TestSubjectAccessReview(t *testing.T) {
|
||||
t.Errorf("%s: expected %v, got %v", test.name, test.expectedStatus, response.Status)
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSelfSubjectAccessReview(t *testing.T) {
|
||||
var m *master.Master
|
||||
s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
||||
m.Handler.ServeHTTP(w, req)
|
||||
}))
|
||||
defer s.Close()
|
||||
|
||||
username := "alice"
|
||||
masterConfig := framework.NewIntegrationTestMasterConfig()
|
||||
masterConfig.Authenticator = authenticator.RequestFunc(func(req *http.Request) (user.Info, bool, error) {
|
||||
return &user.DefaultInfo{Name: username}, true, nil
|
||||
})
|
||||
masterConfig.Authorizer = sarAuthorizer{}
|
||||
masterConfig.AdmissionControl = admit.NewAlwaysAdmit()
|
||||
m, err := master.New(masterConfig)
|
||||
if err != nil {
|
||||
t.Fatalf("error in bringing up the master: %v", err)
|
||||
}
|
||||
|
||||
clientset := clientset.NewForConfigOrDie(&restclient.Config{Host: s.URL, ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}})
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
username string
|
||||
sar *authorizationapi.SelfSubjectAccessReview
|
||||
expectedError string
|
||||
expectedStatus authorizationapi.SubjectAccessReviewStatus
|
||||
}{
|
||||
{
|
||||
name: "simple allow",
|
||||
username: "alice",
|
||||
sar: &authorizationapi.SelfSubjectAccessReview{
|
||||
Spec: authorizationapi.SelfSubjectAccessReviewSpec{
|
||||
ResourceAttributes: &authorizationapi.ResourceAttributes{
|
||||
Verb: "list",
|
||||
Group: api.GroupName,
|
||||
Version: "v1",
|
||||
Resource: "pods",
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedStatus: authorizationapi.SubjectAccessReviewStatus{
|
||||
Allowed: true,
|
||||
Reason: "you're not dave",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "simple deny",
|
||||
username: "dave",
|
||||
sar: &authorizationapi.SelfSubjectAccessReview{
|
||||
Spec: authorizationapi.SelfSubjectAccessReviewSpec{
|
||||
ResourceAttributes: &authorizationapi.ResourceAttributes{
|
||||
Verb: "list",
|
||||
Group: api.GroupName,
|
||||
Version: "v1",
|
||||
Resource: "pods",
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedStatus: authorizationapi.SubjectAccessReviewStatus{
|
||||
Allowed: false,
|
||||
Reason: "no",
|
||||
EvaluationError: "I'm sorry, Dave",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
username = test.username
|
||||
|
||||
response, err := clientset.Authorization().SelfSubjectAccessReviews().Create(test.sar)
|
||||
switch {
|
||||
case err == nil && len(test.expectedError) == 0:
|
||||
|
||||
case err != nil && strings.Contains(err.Error(), test.expectedError):
|
||||
continue
|
||||
|
||||
case err != nil && len(test.expectedError) != 0:
|
||||
t.Errorf("%s: unexpected error: %v", test.name, err)
|
||||
continue
|
||||
default:
|
||||
t.Errorf("%s: expected %v, got %v", test.name, test.expectedError, err)
|
||||
continue
|
||||
}
|
||||
if response.Status != test.expectedStatus {
|
||||
t.Errorf("%s: expected %v, got %v", test.name, test.expectedStatus, response.Status)
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user