mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-27 21:47:07 +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": ""
|
"description": ""
|
||||||
},
|
},
|
||||||
"apis": [
|
"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",
|
"path": "/apis/authorization.k8s.io/v1beta1/subjectaccessreviews",
|
||||||
"description": "API at /apis/authorization.k8s.io/v1beta1",
|
"description": "API at /apis/authorization.k8s.io/v1beta1",
|
||||||
@ -78,9 +123,9 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"models": {
|
"models": {
|
||||||
"v1beta1.SubjectAccessReview": {
|
"v1beta1.SelfSubjectAccessReview": {
|
||||||
"id": "v1beta1.SubjectAccessReview",
|
"id": "v1beta1.SelfSubjectAccessReview",
|
||||||
"description": "SubjectAccessReview checks whether or not a user or group can perform an action.",
|
"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": [
|
"required": [
|
||||||
"spec"
|
"spec"
|
||||||
],
|
],
|
||||||
@ -97,8 +142,8 @@
|
|||||||
"$ref": "v1.ObjectMeta"
|
"$ref": "v1.ObjectMeta"
|
||||||
},
|
},
|
||||||
"spec": {
|
"spec": {
|
||||||
"$ref": "v1beta1.SubjectAccessReviewSpec",
|
"$ref": "v1beta1.SelfSubjectAccessReviewSpec",
|
||||||
"description": "Spec holds information about the request being evaluated"
|
"description": "Spec holds information about the request being evaluated. user and groups must be empty"
|
||||||
},
|
},
|
||||||
"status": {
|
"status": {
|
||||||
"$ref": "v1beta1.SubjectAccessReviewStatus",
|
"$ref": "v1beta1.SubjectAccessReviewStatus",
|
||||||
@ -214,9 +259,9 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"v1beta1.SubjectAccessReviewSpec": {
|
"v1beta1.SelfSubjectAccessReviewSpec": {
|
||||||
"id": "v1beta1.SubjectAccessReviewSpec",
|
"id": "v1beta1.SelfSubjectAccessReviewSpec",
|
||||||
"description": "SubjectAccessReviewSpec is a description of the access request. Exactly one of ResourceAuthorizationAttributes and NonResourceAuthorizationAttributes must be set",
|
"description": "SelfSubjectAccessReviewSpec is a description of the access request. Exactly one of ResourceAuthorizationAttributes and NonResourceAuthorizationAttributes must be set",
|
||||||
"properties": {
|
"properties": {
|
||||||
"resourceAttributes": {
|
"resourceAttributes": {
|
||||||
"$ref": "v1beta1.ResourceAttributes",
|
"$ref": "v1beta1.ResourceAttributes",
|
||||||
@ -225,21 +270,6 @@
|
|||||||
"nonResourceAttributes": {
|
"nonResourceAttributes": {
|
||||||
"$ref": "v1beta1.NonResourceAttributes",
|
"$ref": "v1beta1.NonResourceAttributes",
|
||||||
"description": "NonResourceAttributes describes information for a non-resource access request"
|
"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": {
|
"unversioned.APIResourceList": {
|
||||||
"id": "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.",
|
"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
|
Status SubjectAccessReviewStatus
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// +genclient=true
|
||||||
|
// +nonNamespaced=true
|
||||||
|
// +noMethods=true
|
||||||
|
|
||||||
// SelfSubjectAccessReview checks whether or the current user can perform an action. Not filling in a
|
// 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
|
// 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
|
// 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"`
|
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
|
// 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
|
// 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
|
// to check whether they can perform an action
|
||||||
|
@ -24,6 +24,7 @@ import (
|
|||||||
|
|
||||||
type AuthorizationInterface interface {
|
type AuthorizationInterface interface {
|
||||||
GetRESTClient() *restclient.RESTClient
|
GetRESTClient() *restclient.RESTClient
|
||||||
|
SelfSubjectAccessReviewsGetter
|
||||||
SubjectAccessReviewsGetter
|
SubjectAccessReviewsGetter
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,6 +33,10 @@ type AuthorizationClient struct {
|
|||||||
*restclient.RESTClient
|
*restclient.RESTClient
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *AuthorizationClient) SelfSubjectAccessReviews() SelfSubjectAccessReviewInterface {
|
||||||
|
return newSelfSubjectAccessReviews(c)
|
||||||
|
}
|
||||||
|
|
||||||
func (c *AuthorizationClient) SubjectAccessReviews() SubjectAccessReviewInterface {
|
func (c *AuthorizationClient) SubjectAccessReviews() SubjectAccessReviewInterface {
|
||||||
return newSubjectAccessReviews(c)
|
return newSubjectAccessReviews(c)
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,10 @@ type FakeAuthorization struct {
|
|||||||
*core.Fake
|
*core.Fake
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *FakeAuthorization) SelfSubjectAccessReviews() unversioned.SelfSubjectAccessReviewInterface {
|
||||||
|
return &FakeSelfSubjectAccessReviews{c}
|
||||||
|
}
|
||||||
|
|
||||||
func (c *FakeAuthorization) SubjectAccessReviews() unversioned.SubjectAccessReviewInterface {
|
func (c *FakeAuthorization) SubjectAccessReviews() unversioned.SubjectAccessReviewInterface {
|
||||||
return &FakeSubjectAccessReviews{c}
|
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{})
|
obj, err := c.Fake.Invokes(core.NewRootCreateAction(authorizationapi.SchemeGroupVersion.WithResource("subjectaccessreviews"), sar), &authorizationapi.SubjectAccessReview{})
|
||||||
return obj.(*authorizationapi.SubjectAccessReview), err
|
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"
|
authorizationapi "k8s.io/kubernetes/pkg/apis/authorization"
|
||||||
)
|
)
|
||||||
|
|
||||||
// The PodExpansion interface allows manually adding extra methods to the PodInterface.
|
|
||||||
type SubjectAccessReviewExpansion interface {
|
type SubjectAccessReviewExpansion interface {
|
||||||
Create(sar *authorizationapi.SubjectAccessReview) (result *authorizationapi.SubjectAccessReview, err error)
|
Create(sar *authorizationapi.SubjectAccessReview) (result *authorizationapi.SubjectAccessReview, err error)
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,7 @@ import (
|
|||||||
|
|
||||||
type AuthorizationInterface interface {
|
type AuthorizationInterface interface {
|
||||||
GetRESTClient() *restclient.RESTClient
|
GetRESTClient() *restclient.RESTClient
|
||||||
|
SelfSubjectAccessReviewsGetter
|
||||||
SubjectAccessReviewsGetter
|
SubjectAccessReviewsGetter
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -33,6 +34,10 @@ type AuthorizationClient struct {
|
|||||||
*restclient.RESTClient
|
*restclient.RESTClient
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *AuthorizationClient) SelfSubjectAccessReviews() SelfSubjectAccessReviewInterface {
|
||||||
|
return newSelfSubjectAccessReviews(c)
|
||||||
|
}
|
||||||
|
|
||||||
func (c *AuthorizationClient) SubjectAccessReviews() SubjectAccessReviewInterface {
|
func (c *AuthorizationClient) SubjectAccessReviews() SubjectAccessReviewInterface {
|
||||||
return newSubjectAccessReviews(c)
|
return newSubjectAccessReviews(c)
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,10 @@ type FakeAuthorization struct {
|
|||||||
*core.Fake
|
*core.Fake
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *FakeAuthorization) SelfSubjectAccessReviews() v1beta1.SelfSubjectAccessReviewInterface {
|
||||||
|
return &FakeSelfSubjectAccessReviews{c}
|
||||||
|
}
|
||||||
|
|
||||||
func (c *FakeAuthorization) SubjectAccessReviews() v1beta1.SubjectAccessReviewInterface {
|
func (c *FakeAuthorization) SubjectAccessReviews() v1beta1.SubjectAccessReviewInterface {
|
||||||
return &FakeSubjectAccessReviews{c}
|
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{})
|
obj, err := c.Fake.Invokes(core.NewRootCreateAction(authorizationapi.SchemeGroupVersion.WithResource("subjectaccessreviews"), sar), &authorizationapi.SubjectAccessReview{})
|
||||||
return obj.(*authorizationapi.SubjectAccessReview), err
|
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{}{
|
var ignoredResources = map[unversioned.GroupVersionResource]struct{}{
|
||||||
unversioned.GroupVersionResource{Group: "extensions", Version: "v1beta1", Resource: "replicationcontrollers"}: {},
|
unversioned.GroupVersionResource{Group: "extensions", Version: "v1beta1", Resource: "replicationcontrollers"}: {},
|
||||||
unversioned.GroupVersionResource{Group: "", Version: "v1", Resource: "bindings"}: {},
|
unversioned.GroupVersionResource{Group: "", Version: "v1", Resource: "bindings"}: {},
|
||||||
unversioned.GroupVersionResource{Group: "", Version: "v1", Resource: "componentstatuses"}: {},
|
unversioned.GroupVersionResource{Group: "", Version: "v1", Resource: "componentstatuses"}: {},
|
||||||
unversioned.GroupVersionResource{Group: "", Version: "v1", Resource: "events"}: {},
|
unversioned.GroupVersionResource{Group: "", Version: "v1", Resource: "events"}: {},
|
||||||
unversioned.GroupVersionResource{Group: "authentication.k8s.io", Version: "v1beta1", Resource: "tokenreviews"}: {},
|
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: "subjectaccessreviews"}: {},
|
||||||
|
unversioned.GroupVersionResource{Group: "authorization.k8s.io", Version: "v1beta1", Resource: "selfsubjectaccessreviews"}: {},
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewGarbageCollector(metaOnlyClientPool dynamic.ClientPool, clientPool dynamic.ClientPool, resources []unversioned.GroupVersionResource) (*GarbageCollector, error) {
|
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"
|
authorizationv1beta1 "k8s.io/kubernetes/pkg/apis/authorization/v1beta1"
|
||||||
"k8s.io/kubernetes/pkg/auth/authorizer"
|
"k8s.io/kubernetes/pkg/auth/authorizer"
|
||||||
"k8s.io/kubernetes/pkg/genericapiserver"
|
"k8s.io/kubernetes/pkg/genericapiserver"
|
||||||
|
"k8s.io/kubernetes/pkg/registry/authorization/selfsubjectaccessreview"
|
||||||
"k8s.io/kubernetes/pkg/registry/authorization/subjectaccessreview"
|
"k8s.io/kubernetes/pkg/registry/authorization/subjectaccessreview"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -53,6 +54,9 @@ func (p AuthorizationRESTStorageProvider) v1beta1Storage(apiResourceConfigSource
|
|||||||
if apiResourceConfigSource.ResourceEnabled(version.WithResource("subjectaccessreviews")) {
|
if apiResourceConfigSource.ResourceEnabled(version.WithResource("subjectaccessreviews")) {
|
||||||
storage["subjectaccessreviews"] = subjectaccessreview.NewREST(p.Authorizer)
|
storage["subjectaccessreviews"] = subjectaccessreview.NewREST(p.Authorizer)
|
||||||
}
|
}
|
||||||
|
if apiResourceConfigSource.ResourceEnabled(version.WithResource("selfsubjectaccessreviews")) {
|
||||||
|
storage["selfsubjectaccessreviews"] = selfsubjectaccessreview.NewREST(p.Authorizer)
|
||||||
|
}
|
||||||
|
|
||||||
return storage
|
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) {
|
func TestSubjectAccessReview(t *testing.T) {
|
||||||
// Set up a master
|
|
||||||
var m *master.Master
|
var m *master.Master
|
||||||
s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
||||||
m.Handler.ServeHTTP(w, req)
|
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)
|
t.Errorf("%s: expected %v, got %v", test.name, test.expectedStatus, response.Status)
|
||||||
continue
|
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