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

✨ PoC: Client-side permission evaluation #1804

Draft
wants to merge 5 commits into
base: main
Choose a base branch
from
Draft
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
4 changes: 4 additions & 0 deletions .golangci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ run:
# Default timeout is 1m, up to give more room
timeout: 4m

issues:
exclude-dirs:
- internal/operator-controller/authorization/internal/kubernetes

linters:
enable:
- asciicheck
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ manifests: $(CONTROLLER_GEN) #EXHELP Generate WebhookConfiguration, ClusterRole,

.PHONY: generate
generate: $(CONTROLLER_GEN) #EXHELP Generate code containing DeepCopy, DeepCopyInto, and DeepCopyObject method implementations.
$(CONTROLLER_GEN) object:headerFile="hack/boilerplate.go.txt" paths="./..."
$(CONTROLLER_GEN) object:headerFile="hack/boilerplate.go.txt" paths="./api/..."

.PHONY: verify
verify: tidy fmt generate manifests crd-ref-docs #HELP Verify all generated code is up-to-date.
Expand Down
50 changes: 50 additions & 0 deletions api/v1/clusterextension_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ limitations under the License.
package v1

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

Expand Down Expand Up @@ -454,6 +455,55 @@ type ClusterExtensionStatus struct {
//
// +optional
Install *ClusterExtensionInstallStatus `json:"install,omitempty"`

// rules is a representation of an assessment of permissions related
// to the cluster extension and its service account.
//
// +optional
Rules *ClusterExtensionRulesStatus `json:"rules,omitempty"`
}

type ClusterExtensionRulesStatus struct {
// missing is the group of rules that the cluster extension's service account is likely lacking,
// but which are needed to be able to fully manage all resources in the resolved cluster extension manifest.
//
// +listType=atomic
// +optional
// +kubebuilder:validation:MaxItems:=64
Missing []ClusterExtensionRulesStatusItem `json:"missing,omitempty"`
}

type ClusterExtensionRulesStatusItem struct {
// namespace is a reference to a Kubernetes namespace.
// This is the namespace where the ClusterExtension's service account is lacking
// the rules provided in missingRules.
//
// When namespace is non-empty, one or more RoleBindings should be created to reference
// Roles and/or ClusterRoles that provided the missingRules in the namespace.
//
// When namespace is the empty string, one or more ClusterRoleBindings should be created
// to reference ClusterRoles that provide the missingRules cluster-wide.
//
// namespace is required and follows the DNS label standard
// as defined in [RFC 1123]. It must contain only lowercase alphanumeric characters or hyphens (-),
// start and end with an alphanumeric character, and be no longer than 63 characters
//
// [RFC 1123]: https://tools.ietf.org/html/rfc1123
//
// +kubebuilder:validation:MaxLength:=63
// +kubebuilder:validation:XValidation:rule="self == \"\" || self.matches(\"^[a-z0-9]([-a-z0-9]*[a-z0-9])?$\")",message="namespace must be empty string or a valid DNS1123 label"
// +kubebuilder:validation:Required
Namespace string `json:"namespace"`

// rules is a list of RBAC policy rules that are related to the management of the rendered manifest of the
// ClusterExtension's bundle.
//
// rules is optional. If it is empty or nil, the semantic meaning is that there are no rules in this grouping
// for the named namespace.
//
// +listType=atomic
// +kubebuilder:validation:MaxItems:=1024
Rules []rbacv1.PolicyRule `json:"rules,omitempty"`
}

// ClusterExtensionInstallStatus is a representation of the status of the identified bundle.
Expand Down
50 changes: 50 additions & 0 deletions api/v1/zz_generated.deepcopy.go

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

11 changes: 9 additions & 2 deletions cmd/operator-controller/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import (
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
corev1 "k8s.io/api/core/v1"
rbacv1 "k8s.io/api/rbac/v1"
apiextensionsv1client "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1"
"k8s.io/apimachinery/pkg/fields"
k8slabels "k8s.io/apimachinery/pkg/labels"
Expand All @@ -58,6 +59,7 @@ import (
"github.com/operator-framework/operator-controller/internal/operator-controller/action"
"github.com/operator-framework/operator-controller/internal/operator-controller/applier"
"github.com/operator-framework/operator-controller/internal/operator-controller/authentication"
"github.com/operator-framework/operator-controller/internal/operator-controller/authorization"
"github.com/operator-framework/operator-controller/internal/operator-controller/catalogmetadata/cache"
catalogclient "github.com/operator-framework/operator-controller/internal/operator-controller/catalogmetadata/client"
"github.com/operator-framework/operator-controller/internal/operator-controller/contentmanager"
Expand Down Expand Up @@ -201,8 +203,12 @@ func run() error {
setupLog.Info("set up manager")
cacheOptions := crcache.Options{
ByObject: map[client.Object]crcache.ByObject{
&ocv1.ClusterExtension{}: {Label: k8slabels.Everything()},
&ocv1.ClusterCatalog{}: {Label: k8slabels.Everything()},
&ocv1.ClusterExtension{}: {Label: k8slabels.Everything()},
&ocv1.ClusterCatalog{}: {Label: k8slabels.Everything()},
&rbacv1.ClusterRole{}: {Label: k8slabels.Everything()},
&rbacv1.ClusterRoleBinding{}: {Label: k8slabels.Everything()},
&rbacv1.Role{}: {Namespaces: map[string]crcache.Config{}, Label: k8slabels.Everything()},
&rbacv1.RoleBinding{}: {Namespaces: map[string]crcache.Config{}, Label: k8slabels.Everything()},
},
DefaultNamespaces: map[string]crcache.Config{
cfg.systemNamespace: {LabelSelector: k8slabels.Everything()},
Expand Down Expand Up @@ -409,6 +415,7 @@ func run() error {
helmApplier := &applier.Helm{
ActionClientGetter: acg,
Preflights: preflights,
PreAuthorizer: authorization.NewRBACPreAuthorizer(mgr.GetClient()),
}

cm := contentmanager.NewManager(clientRestConfigMapper, mgr.GetConfig(), mgr.GetRESTMapper())
Expand Down
5 changes: 4 additions & 1 deletion codecov.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,7 @@ coverage:
paths:
- "api/"
- "cmd/"
- "internal/"
- "internal/"

ignore:
- "internal/operator-controller/authorization/internal/kubernetes"
Original file line number Diff line number Diff line change
Expand Up @@ -581,6 +581,105 @@ spec:
required:
- bundle
type: object
rules:
description: |-
rules is a representation of an assessment of permissions related
to the cluster extension and its service account.
properties:
missing:
description: |-
missing is the group of rules that the cluster extension's service account is likely lacking,
but which are needed to be able to fully manage all resources in the resolved cluster extension manifest.
items:
properties:
namespace:
description: |-
namespace is a reference to a Kubernetes namespace.
This is the namespace where the ClusterExtension's service account is lacking
the rules provided in missingRules.

When namespace is non-empty, one or more RoleBindings should be created to reference
Roles and/or ClusterRoles that provided the missingRules in the namespace.

When namespace is the empty string, one or more ClusterRoleBindings should be created
to reference ClusterRoles that provide the missingRules cluster-wide.

namespace is required and follows the DNS label standard
as defined in [RFC 1123]. It must contain only lowercase alphanumeric characters or hyphens (-),
start and end with an alphanumeric character, and be no longer than 63 characters

[RFC 1123]: https://tools.ietf.org/html/rfc1123
maxLength: 63
type: string
x-kubernetes-validations:
- message: namespace must be empty string or a valid DNS1123
label
rule: self == "" || self.matches("^[a-z0-9]([-a-z0-9]*[a-z0-9])?$")
rules:
description: |-
rules is a list of RBAC policy rules that are related to the management of the rendered manifest of the
ClusterExtension's bundle.

rules is optional. If it is empty or nil, the semantic meaning is that there are no rules in this grouping
for the named namespace.
items:
description: |-
PolicyRule holds information that describes a policy rule, but does not contain information
about who the rule applies to or which namespace the rule applies to.
properties:
apiGroups:
description: |-
APIGroups is the name of the APIGroup that contains the resources. If multiple API groups are specified, any action requested against one of
the enumerated resources in any API group will be allowed. "" represents the core API group and "*" represents all API groups.
items:
type: string
type: array
x-kubernetes-list-type: atomic
nonResourceURLs:
description: |-
NonResourceURLs is a set of partial urls that a user should have access to. *s are allowed, but only as the full, final step in the path
Since non-resource URLs are not namespaced, this field is only applicable for ClusterRoles referenced from a ClusterRoleBinding.
Rules can either apply to API resources (such as "pods" or "secrets") or non-resource URL paths (such as "/api"), but not both.
items:
type: string
type: array
x-kubernetes-list-type: atomic
resourceNames:
description: ResourceNames is an optional white list
of names that the rule applies to. An empty set
means that everything is allowed.
items:
type: string
type: array
x-kubernetes-list-type: atomic
resources:
description: Resources is a list of resources this
rule applies to. '*' represents all resources.
items:
type: string
type: array
x-kubernetes-list-type: atomic
verbs:
description: Verbs is a list of Verbs that apply to
ALL the ResourceKinds contained in this rule. '*'
represents all verbs.
items:
type: string
type: array
x-kubernetes-list-type: atomic
required:
- verbs
type: object
maxItems: 1024
type: array
x-kubernetes-list-type: atomic
required:
- namespace
type: object
maxItems: 64
type: array
x-kubernetes-list-type: atomic
type: object
type: object
type: object
served: true
Expand Down
10 changes: 10 additions & 0 deletions config/base/operator-controller/rbac/role.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,16 @@ rules:
verbs:
- patch
- update
- apiGroups:
- rbac.authorization.k8s.io
resources:
- clusterrolebindings
- clusterroles
- rolebindings
- roles
verbs:
- list
- watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
Expand Down
34 changes: 34 additions & 0 deletions docs/api-reference/operator-controller-api-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,39 @@ ClusterExtensionList contains a list of ClusterExtension
| `items` _[ClusterExtension](#clusterextension) array_ | items is a required list of ClusterExtension objects. | | Required: \{\} <br /> |


#### ClusterExtensionRulesStatus







_Appears in:_
- [ClusterExtensionStatus](#clusterextensionstatus)

| Field | Description | Default | Validation |
| --- | --- | --- | --- |
| `missing` _[ClusterExtensionRulesStatusItem](#clusterextensionrulesstatusitem) array_ | missing is the group of rules that the cluster extension's service account is likely lacking,<br />but which are needed to be able to fully manage all resources in the resolved cluster extension manifest. | | MaxItems: 64 <br /> |


#### ClusterExtensionRulesStatusItem







_Appears in:_
- [ClusterExtensionRulesStatus](#clusterextensionrulesstatus)

| Field | Description | Default | Validation |
| --- | --- | --- | --- |
| `namespace` _string_ | namespace is a reference to a Kubernetes namespace.<br />This is the namespace where the ClusterExtension's service account is lacking<br />the rules provided in missingRules.<br /><br />When namespace is non-empty, one or more RoleBindings should be created to reference<br />Roles and/or ClusterRoles that provided the missingRules in the namespace.<br /><br />When namespace is the empty string, one or more ClusterRoleBindings should be created<br />to reference ClusterRoles that provide the missingRules cluster-wide.<br /><br />namespace is required and follows the DNS label standard<br />as defined in [RFC 1123]. It must contain only lowercase alphanumeric characters or hyphens (-),<br />start and end with an alphanumeric character, and be no longer than 63 characters<br /><br />[RFC 1123]: https://tools.ietf.org/html/rfc1123 | | MaxLength: 63 <br />Required: \{\} <br /> |
| `rules` _[PolicyRule](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#policyrule-v1-rbac) array_ | rules is a list of RBAC policy rules that are related to the management of the rendered manifest of the<br />ClusterExtension's bundle.<br /><br />rules is optional. If it is empty or nil, the semantic meaning is that there are no rules in this grouping<br />for the named namespace. | | MaxItems: 1024 <br /> |


#### ClusterExtensionSpec


Expand Down Expand Up @@ -326,6 +359,7 @@ _Appears in:_
| --- | --- | --- | --- |
| `conditions` _[Condition](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#condition-v1-meta) array_ | The set of condition types which apply to all spec.source variations are Installed and Progressing.<br /><br />The Installed condition represents whether or not the bundle has been installed for this ClusterExtension.<br />When Installed is True and the Reason is Succeeded, the bundle has been successfully installed.<br />When Installed is False and the Reason is Failed, the bundle has failed to install.<br /><br />The Progressing condition represents whether or not the ClusterExtension is advancing towards a new state.<br />When Progressing is True and the Reason is Succeeded, the ClusterExtension is making progress towards a new state.<br />When Progressing is True and the Reason is Retrying, the ClusterExtension has encountered an error that could be resolved on subsequent reconciliation attempts.<br />When Progressing is False and the Reason is Blocked, the ClusterExtension has encountered an error that requires manual intervention for recovery.<br /><br />When the ClusterExtension is sourced from a catalog, if may also communicate a deprecation condition.<br />These are indications from a package owner to guide users away from a particular package, channel, or bundle.<br />BundleDeprecated is set if the requested bundle version is marked deprecated in the catalog.<br />ChannelDeprecated is set if the requested channel is marked deprecated in the catalog.<br />PackageDeprecated is set if the requested package is marked deprecated in the catalog.<br />Deprecated is a rollup condition that is present when any of the deprecated conditions are present. | | |
| `install` _[ClusterExtensionInstallStatus](#clusterextensioninstallstatus)_ | install is a representation of the current installation status for this ClusterExtension. | | |
| `rules` _[ClusterExtensionRulesStatus](#clusterextensionrulesstatus)_ | rules is a representation of an assessment of permissions related<br />to the cluster extension and its service account. | | |


#### ImageSource
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ require (
k8s.io/cli-runtime v0.32.1
k8s.io/client-go v0.32.2
k8s.io/component-base v0.32.2
k8s.io/component-helpers v0.32.1
k8s.io/klog/v2 v2.130.1
k8s.io/utils v0.0.0-20241210054802-24370beab758
sigs.k8s.io/controller-runtime v0.20.2
Expand Down
Loading
Loading