Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add SelfSubjectNamespaceAccessReview api #304

Merged
merged 1 commit into from
Jun 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
815 changes: 469 additions & 346 deletions apis/identity/v1alpha1/openapi_generated.go

Large diffs are not rendered by default.

65 changes: 65 additions & 0 deletions apis/identity/v1alpha1/selfsubjectnamespaceaccessreview.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package v1alpha1

import (
authorization "k8s.io/api/authorization/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

const (
ResourceKindSelfSubjectNamespaceAccessReview = "SelfSubjectNamespaceAccessReview"
ResourceSelfSubjectNamespaceAccessReview = "selfsubjectnamespaceaccessreview"
ResourceSelfSubjectNamespaceAccessReviews = "selfsubjectnamespaceaccessreviews"
)

// SelfSubjectNamespaceAccessReview 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

// +genclient
// +genclient:nonNamespaced
// +genclient:onlyVerbs=create
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// +kubebuilder:object:root=true
// +kubebuilder:resource:scope=Cluster
type SelfSubjectNamespaceAccessReview struct {
metav1.TypeMeta `json:",inline"`
// Standard list metadata.
// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
// +optional
metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`

// Spec holds information about the request being evaluated. user and groups must be empty
Spec SelfSubjectNamespaceAccessReviewSpec `json:"spec" protobuf:"bytes,2,opt,name=spec"`

// Status is filled in by the server and indicates whether the request is allowed or not
// +optional
Status SubjectAccessNamespaceReviewStatus `json:"status,omitempty" protobuf:"bytes,3,opt,name=status"`
}

// SelfSubjectNamespaceAccessReviewSpec is a description of the access request. Exactly one of ResourceAuthorizationAttributes
// and NonResourceAuthorizationAttributes must be set
type SelfSubjectNamespaceAccessReviewSpec struct {
// ResourceAuthorizationAttributes describes information for a resource access request
// +optional
ResourceAttributes []authorization.ResourceAttributes `json:"resourceAttributes,omitempty"`
// NonResourceAttributes describes information for a non-resource access request
// +optional
NonResourceAttributes []authorization.NonResourceAttributes `json:"nonResourceAttributes,omitempty"`
}

type SubjectAccessNamespaceReviewStatus struct {
Namespaces []string `json:"namespaces,omitempty"`
}

// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// +kubebuilder:object:root=true

type SelfSubjectNamespaceAccessReviewList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []SelfSubjectNamespaceAccessReview `json:"items,omitempty"`
}

func init() {
SchemeBuilder.Register(&SelfSubjectNamespaceAccessReview{}, &SelfSubjectNamespaceAccessReviewList{})
}
109 changes: 109 additions & 0 deletions apis/identity/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 15 additions & 0 deletions artifacts/localaccess.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
apiVersion: authorization.k8s.io/v1
kind: LocalSubjectAccessReview
metadata:
namespace: default
spec:
resourceAttributes:
verb: "get"
group: apps
version: "*"
resource: "deployments"
namespace: default
groups:
- kubeadm:cluster-admins
- system:authenticated
user: kubernetes-admin
10 changes: 10 additions & 0 deletions artifacts/nsaccessreview.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
apiVersion: identity.k8s.appscode.com/v1alpha1
kind: SelfSubjectNamespaceAccessReview
metadata:
name: "abc"
spec:
resourceAttributes:
- verb: "get"
group: apps
version: "*"
resource: "deployments"
108 changes: 108 additions & 0 deletions crds/identity.k8s.appscode.com_selfsubjectnamespaceaccessreviews.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@

---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
creationTimestamp: null
name: selfsubjectnamespaceaccessreviews.identity.k8s.appscode.com
spec:
group: identity.k8s.appscode.com
names:
kind: SelfSubjectNamespaceAccessReview
listKind: SelfSubjectNamespaceAccessReviewList
plural: selfsubjectnamespaceaccessreviews
singular: selfsubjectnamespaceaccessreview
scope: Cluster
versions:
- name: v1alpha1
schema:
openAPIV3Schema:
properties:
apiVersion:
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: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
type: string
kind:
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: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
metadata:
type: object
spec:
description: Spec holds information about the request being evaluated. user
and groups must be empty
properties:
nonResourceAttributes:
description: NonResourceAttributes describes information for a non-resource
access request
items:
description: NonResourceAttributes includes the authorization attributes
available for non-resource requests to the Authorizer interface
properties:
path:
description: Path is the URL path of the request
type: string
verb:
description: Verb is the standard HTTP verb
type: string
type: object
type: array
resourceAttributes:
description: ResourceAuthorizationAttributes describes information
for a resource access request
items:
description: ResourceAttributes includes the authorization attributes
available for resource requests to the Authorizer interface
properties:
group:
description: Group is the API Group of the Resource. "*" means
all.
type: string
name:
description: Name is the name of the resource being requested
for a "get" or deleted for a "delete". "" (empty) means all.
type: string
namespace:
description: Namespace is the namespace of the action being
requested. Currently, there is no distinction between no
namespace and all namespaces "" (empty) is defaulted for LocalSubjectAccessReviews
"" (empty) is empty for cluster-scoped resources "" (empty)
means "all" for namespace scoped resources from a SubjectAccessReview
or SelfSubjectAccessReview
type: string
resource:
description: Resource is one of the existing resource types. "*"
means all.
type: string
subresource:
description: Subresource is one of the existing resource types. ""
means none.
type: string
verb:
description: 'Verb is a kubernetes resource API verb, like:
get, list, watch, create, update, delete, proxy. "*" means
all.'
type: string
version:
description: Version is the API Version of the Resource. "*"
means all.
type: string
type: object
type: array
type: object
status:
description: Status is filled in by the server and indicates whether the
request is allowed or not
properties:
namespaces:
items:
type: string
type: array
type: object
required:
- spec
type: object
served: true
storage: true
18 changes: 10 additions & 8 deletions pkg/apiserver/apiserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ import (
coststorage "kubeops.dev/ui-server/pkg/registry/cost/reports"
clusteridstorage "kubeops.dev/ui-server/pkg/registry/identity/clusteridentity"
inboxtokenreqstorage "kubeops.dev/ui-server/pkg/registry/identity/inboxtokenrequest"
"kubeops.dev/ui-server/pkg/registry/identity/selfsubjectnamespaceaccessreview"
"kubeops.dev/ui-server/pkg/registry/meta/chartpresetquery"
clusterprofilestorage "kubeops.dev/ui-server/pkg/registry/meta/clusterprofile"
clusterstatusstorage "kubeops.dev/ui-server/pkg/registry/meta/clusterstatus"
Expand Down Expand Up @@ -236,7 +237,7 @@ func (c completedConfig) New(ctx context.Context) (*UIServer, error) {
return nil, fmt.Errorf("unable to start manager, reason: %v", err)
}
ctrlClient := mgr.GetClient()
disco, err := kubernetes.NewForConfig(cfg)
kc, err := kubernetes.NewForConfig(cfg)
if err != nil {
return nil, fmt.Errorf("unable to create discovery client, reason: %v", err)
}
Expand All @@ -260,7 +261,7 @@ func (c completedConfig) New(ctx context.Context) (*UIServer, error) {
return nil, err
}

pqr, err := projectquotacontroller.NewReconciler(mgr.GetClient(), disco).SetupWithManager(mgr)
pqr, err := projectquotacontroller.NewReconciler(mgr.GetClient(), kc).SetupWithManager(mgr)
if err != nil {
klog.Error(err, "unable to create controller", "controller", "ProjectQuota")
os.Exit(1)
Expand Down Expand Up @@ -296,7 +297,7 @@ func (c completedConfig) New(ctx context.Context) (*UIServer, error) {

v1alpha1storage := map[string]rest.Storage{}
v1alpha1storage[rsapi.ResourceChartPresetQueries] = chartpresetquery.NewStorage(ctrlClient)
v1alpha1storage[rsapi.ResourceClusterStatuses] = clusterstatusstorage.NewStorage(ctrlClient, disco)
v1alpha1storage[rsapi.ResourceClusterStatuses] = clusterstatusstorage.NewStorage(ctrlClient, kc)
v1alpha1storage[rsapi.ResourceRenderDashboards] = renderdashboard.NewStorage(ctrlClient, oc)
v1alpha1storage[rsapi.ResourceRenderRawGraphs] = renderrawgraph.NewStorage(ctrlClient)
v1alpha1storage[rsapi.ResourceRenders] = render.NewStorage(ctrlClient, oc, rbacAuthorizer)
Expand All @@ -312,11 +313,11 @@ func (c completedConfig) New(ctx context.Context) (*UIServer, error) {
v1alpha1storage[rsapi.ResourceResourceTableDefinitions] = resourcetabledefinition.NewStorage()

namespace := meta.PodNamespace()
v1alpha1storage[rsapi.ResourceRenderMenus] = rendermenu.NewStorage(ctrlClient, disco, namespace)
v1alpha1storage["usermenus"] = usermenu.NewStorage(ctrlClient, disco, namespace)
v1alpha1storage["usermenus/available"] = usermenu.NewAvailableStorage(ctrlClient, disco, namespace)
v1alpha1storage[rsapi.ResourceMenus] = vendormenu.NewStorage(ctrlClient, disco)
v1alpha1storage[rsapi.ResourceMenus+"/available"] = vendormenu.NewAvailableStorage(ctrlClient, disco)
v1alpha1storage[rsapi.ResourceRenderMenus] = rendermenu.NewStorage(ctrlClient, kc, namespace)
v1alpha1storage["usermenus"] = usermenu.NewStorage(ctrlClient, kc, namespace)
v1alpha1storage["usermenus/available"] = usermenu.NewAvailableStorage(ctrlClient, kc, namespace)
v1alpha1storage[rsapi.ResourceMenus] = vendormenu.NewStorage(ctrlClient, kc)
v1alpha1storage[rsapi.ResourceMenus+"/available"] = vendormenu.NewAvailableStorage(ctrlClient, kc)

apiGroupInfo.VersionedResourcesStorageMap["v1alpha1"] = v1alpha1storage

Expand Down Expand Up @@ -358,6 +359,7 @@ func (c completedConfig) New(ctx context.Context) (*UIServer, error) {
v1alpha1storage := map[string]rest.Storage{}
v1alpha1storage[identityapi.ResourceClusterIdentities] = clusteridstorage.NewStorage(ctrlClient, bc, cid)
v1alpha1storage[identityapi.ResourceInboxTokenRequests] = inboxtokenreqstorage.NewStorage(ctrlClient, bc, cid)
v1alpha1storage[identityapi.ResourceSelfSubjectNamespaceAccessReviews] = selfsubjectnamespaceaccessreview.NewStorage(kc, ctrlClient)
apiGroupInfo.VersionedResourcesStorageMap["v1alpha1"] = v1alpha1storage

if err := s.GenericAPIServer.InstallAPIGroup(&apiGroupInfo); err != nil {
Expand Down
1 change: 1 addition & 0 deletions pkg/cmds/server/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ func (o *UIServerOptions) Config() (*apiserver.Config, error) {
fmt.Sprintf("/apis/%s", identityapi.GroupVersion),
fmt.Sprintf("/apis/%s/%s", identityapi.GroupVersion, identityapi.ResourceClusterIdentities),
fmt.Sprintf("/apis/%s/%s", identityapi.GroupVersion, identityapi.ResourceInboxTokenRequests),
fmt.Sprintf("/apis/%s/%s", identityapi.GroupVersion, identityapi.ResourceSelfSubjectNamespaceAccessReviews),
}

serverConfig.OpenAPIConfig = genericapiserver.DefaultOpenAPIConfig(
Expand Down
Loading
Loading