Skip to content

Commit

Permalink
draft: add namespace scoped operator mode
Browse files Browse the repository at this point in the history
This adds automation and docs for restricting the
operator scope from cluster wide to namespace restricted.

Signed-off-by: NymanRobin <[email protected]>
  • Loading branch information
NymanRobin committed Aug 12, 2024
1 parent efae71e commit 11dcd29
Show file tree
Hide file tree
Showing 11 changed files with 183 additions and 32 deletions.
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,10 @@ manifests-generate: $(CONTROLLER_GEN)
manifests-kustomize: $(KUSTOMIZE)
$< build config/default > config/render/capm3.yaml

.PHONY: manifests-generate-namespaced
manifests-generate-namespaced: manifests-generate $(KUSTOMIZE)
$(KUSTOMIZE) build config/overlays/namespaced > config/render/capm3.yaml

.PHONY: set-manifest-image-bmo
set-manifest-image-bmo: $(KUSTOMIZE) manifests
$(info Updating container image for BMO to use ${MANIFEST_IMG}:${MANIFEST_TAG})
Expand Down
49 changes: 49 additions & 0 deletions config/overlays/namespaced/kustomization.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

bases:
- ../../default

# The subjects and roleRef needs to be update here otherwise we lose name-prefix
# This is of course not ideal if the name-prefix changes
patchesStrategicMerge:
- namespaced-manager-patch.yaml
- |
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: baremetal-operator-manager-rolebinding
roleRef:
kind: Role
name: baremetal-operator-manager-role
subjects:
- kind: ServiceAccount
name: baremetal-operator-controller-manager
namespace: baremetal-operator-system
patches:
- patch: |
# Add a namespace to watch
- op: replace
path: /kind
value: RoleBinding
- op: add
path: /metadata/namespace
value: single-ns-bmh
target:
group: rbac.authorization.k8s.io
kind: ClusterRoleBinding
name: baremetal-operator-manager-rolebinding

- patch: |
# Add a namespace to watch
- op: replace
path: /kind
value: Role
- op: add
path: /metadata/namespace
value: single-ns-bmh
target:
group: rbac.authorization.k8s.io
kind: ClusterRole
name: baremetal-operator-manager-role
13 changes: 13 additions & 0 deletions config/overlays/namespaced/namespaced-manager-patch.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: controller-manager
namespace: system
spec:
template:
spec:
containers:
- name: manager
env:
- name: WATCH_NAMESPACE
value: "single-ns-bmh"
10 changes: 7 additions & 3 deletions config/render/capm3.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2167,9 +2167,10 @@ rules:
- delete
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
kind: Role
metadata:
name: baremetal-operator-manager-role
namespace: single-ns-bmh
rules:
- apiGroups:
- ""
Expand Down Expand Up @@ -2412,12 +2413,13 @@ subjects:
namespace: baremetal-operator-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
kind: RoleBinding
metadata:
name: baremetal-operator-manager-rolebinding
namespace: single-ns-bmh
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
kind: Role
name: baremetal-operator-manager-role
subjects:
- kind: ServiceAccount
Expand Down Expand Up @@ -2525,6 +2527,8 @@ spec:
command:
- /baremetal-operator
env:
- name: WATCH_NAMESPACE
value: single-ns-bmh
- name: POD_NAME
valueFrom:
fieldRef:
Expand Down
28 changes: 14 additions & 14 deletions controllers/metal3.io/baremetalhost_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,24 +82,24 @@ func (info *reconcileInfo) publishEvent(reason, message string) {
info.events = append(info.events, info.host.NewEvent(reason, message))
}

// +kubebuilder:rbac:groups=metal3.io,resources=baremetalhosts,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=metal3.io,resources=baremetalhosts/status,verbs=get;update;patch
// +kubebuilder:rbac:groups=metal3.io,resources=baremetalhosts/finalizers,verbs=update
// +kubebuilder:rbac:groups=metal3.io,resources=preprovisioningimages,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=metal3.io,resources=hardwaredata,verbs=get;list;watch;create;delete;patch;update
// +kubebuilder:rbac:groups=metal3.io,resources=hardware/finalizers,verbs=update
// +kubebuilder:rbac:groups="",resources=secrets,verbs=get;list;watch;update;delete
// +kubebuilder:rbac:groups="",resources=events,verbs=get;list;watch;create;update;patch
// +kubebuilder:rbac:groups=metal3.io,namespace="",resources=baremetalhosts,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=metal3.io,namespace="",resources=baremetalhosts/status,verbs=get;update;patch
// +kubebuilder:rbac:groups=metal3.io,namespace="",resources=baremetalhosts/finalizers,verbs=update
// +kubebuilder:rbac:groups=metal3.io,namespace="",resources=preprovisioningimages,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=metal3.io,namespace="",resources=hardwaredata,verbs=get;list;watch;create;delete;patch;update
// +kubebuilder:rbac:groups=metal3.io,namespace="",resources=hardware/finalizers,verbs=update
// +kubebuilder:rbac:groups="",namespace="",resources=secrets,verbs=get;list;watch;update;delete
// +kubebuilder:rbac:groups="",namespace="",resources=events,verbs=get;list;watch;create;update;patch

// Allow for managing hostfirmwaresettings, firmwareschema, bmceventsubscriptions and hostfirmwarecomponents
//+kubebuilder:rbac:groups=metal3.io,resources=hostfirmwaresettings,verbs=get;list;watch;create;update;patch
//+kubebuilder:rbac:groups=metal3.io,resources=firmwareschemas,verbs=get;list;watch;create;update;patch
//+kubebuilder:rbac:groups=metal3.io,resources=bmceventsubscriptions,verbs=get;list;watch;create;update;patch
//+kubebuilder:rbac:groups=metal3.io,resources=hostfirmwarecomponents,verbs=get;list;watch;create;update;patch
//+kubebuilder:rbac:groups=metal3.io,namespace="",resources=hostfirmwaresettings,verbs=get;list;watch;create;update;patch
//+kubebuilder:rbac:groups=metal3.io,namespace="",resources=firmwareschemas,verbs=get;list;watch;create;update;patch
//+kubebuilder:rbac:groups=metal3.io,namespace="",resources=bmceventsubscriptions,verbs=get;list;watch;create;update;patch
//+kubebuilder:rbac:groups=metal3.io,namespace="",resources=hostfirmwarecomponents,verbs=get;list;watch;create;update;patch

// Allow for updating dataimage
// +kubebuilder:rbac:groups=metal3.io,resources=dataimages,verbs=get;list;watch;create;update;patch
// +kubebuilder:rbac:groups=metal3.io,resources=dataimages/status,verbs=get;update;patch
// +kubebuilder:rbac:groups=metal3.io,namespace="",resources=dataimages,verbs=get;list;watch;create;update;patch
// +kubebuilder:rbac:groups=metal3.io,namespace="",resources=dataimages/status,verbs=get;update;patch

// Reconcile handles changes to BareMetalHost resources.
func (r *BareMetalHostReconciler) Reconcile(ctx context.Context, request ctrl.Request) (result ctrl.Result, err error) {
Expand Down
4 changes: 2 additions & 2 deletions controllers/metal3.io/bmceventsubscription_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ type BMCEventSubscriptionReconciler struct {
APIReader client.Reader
}

//+kubebuilder:rbac:groups=metal3.io,resources=bmceventsubscriptions,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups=metal3.io,resources=bmceventsubscriptions/status,verbs=get;update;patch
//+kubebuilder:rbac:groups=metal3.io,namespace="",resources=bmceventsubscriptions,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups=metal3.io,namespace="",resources=bmceventsubscriptions/status,verbs=get;update;patch

func (r *BMCEventSubscriptionReconciler) Reconcile(ctx context.Context, request ctrl.Request) (result ctrl.Result, err error) {
reqLogger := r.Log.WithValues("bmceventsubscription", request.NamespacedName)
Expand Down
6 changes: 3 additions & 3 deletions controllers/metal3.io/dataimage_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,9 @@ func (info *rdiInfo) publishEvent(reason, message string) {
info.events = append(info.events, dataImageEvent)
}

//+kubebuilder:rbac:groups=metal3.io,resources=dataimages,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups=metal3.io,resources=dataimages/status,verbs=get;update;patch
//+kubebuilder:rbac:groups=metal3.io,resources=dataimages/finalizers,verbs=update
//+kubebuilder:rbac:groups=metal3.io,namespace="",resources=dataimages,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups=metal3.io,namespace="",resources=dataimages/status,verbs=get;update;patch
//+kubebuilder:rbac:groups=metal3.io,namespace="",resources=dataimages/finalizers,verbs=update

// Reconcile is part of the main kubernetes reconciliation loop which aims to
// move the current state of the cluster closer to the desired state.
Expand Down
6 changes: 3 additions & 3 deletions controllers/metal3.io/hostfirmwarecomponents_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,9 @@ func (info *rhfcInfo) publishEvent(reason, message string) {
info.events = append(info.events, hfcEvent)
}

//+kubebuilder:rbac:groups=metal3.io,resources=hostfirmwarecomponents,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups=metal3.io,resources=hostfirmwarecomponents/status,verbs=get;update;patch
//+kubebuilder:rbac:groups=metal3.io,resources=hostfirmwarecomponents/finalizers,verbs=update
//+kubebuilder:rbac:groups=metal3.io,namespace="",resources=hostfirmwarecomponents,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups=metal3.io,namespace="",resources=hostfirmwarecomponents/status,verbs=get;update;patch
//+kubebuilder:rbac:groups=metal3.io,namespace="",resources=hostfirmwarecomponents/finalizers,verbs=update

// Reconcile handles changes to HostFirmwareComponents resources.
func (r *HostFirmwareComponentsReconciler) Reconcile(ctx context.Context, req ctrl.Request) (result ctrl.Result, err error) {
Expand Down
8 changes: 4 additions & 4 deletions controllers/metal3.io/hostfirmwaresettings_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,10 +100,10 @@ func (info *rInfo) publishEvent(reason, message string) {
info.events = append(info.events, hfsEvent)
}

//+kubebuilder:rbac:groups=metal3.io,resources=hostfirmwaresettings,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups=metal3.io,resources=hostfirmwaresettings/status,verbs=get;update;patch
//+kubebuilder:rbac:groups=metal3.io,resources=firmwareschemas,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups=metal3.io,resources=firmwareschemas/status,verbs=get;update;patch
//+kubebuilder:rbac:groups=metal3.io,namespace="",resources=hostfirmwaresettings,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups=metal3.io,namespace="",resources=hostfirmwaresettings/status,verbs=get;update;patch
//+kubebuilder:rbac:groups=metal3.io,namespace="",resources=firmwareschemas,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups=metal3.io,namespace="",resources=firmwareschemas/status,verbs=get;update;patch

// Reconcile is part of the main kubernetes reconciliation loop which aims to
// move the current state of the cluster closer to the desired state.
Expand Down
6 changes: 3 additions & 3 deletions controllers/metal3.io/preprovisioningimage_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,9 @@ const (
reasonImageBuildInvalid imageConditionReason = "ImageBuildInvalid"
)

// +kubebuilder:rbac:groups=metal3.io,resources=preprovisioningimages,verbs=get;list;watch;update;patch
// +kubebuilder:rbac:groups=metal3.io,resources=preprovisioningimages/status,verbs=get;update;patch
// +kubebuilder:rbac:groups="",resources=secrets,verbs=get;list;watch;update
// +kubebuilder:rbac:groups=metal3.io,namespace="",resources=preprovisioningimages,verbs=get;list;watch;update;patch
// +kubebuilder:rbac:groups=metal3.io,namespace="",resources=preprovisioningimages/status,verbs=get;update;patch
// +kubebuilder:rbac:groups="",namespace="",resources=secrets,verbs=get;list;watch;update

func (r *PreprovisioningImageReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
log := r.Log.WithValues("preprovisioningimage", req.NamespacedName)
Expand Down
81 changes: 81 additions & 0 deletions docs/single-ns-deploy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# How to restrict the Baremetal Operator scope

The guide is based on the instructions in the
[operator framework documentation][operator-scope].

[operator-scope]: https://sdk.operatorframework.io/docs/building-operators/golang/operator-scope/


## To generate manifests for namespace scoped BMO

To generate namespace-scoped manifests, run the `manifests-generate-namespaced`
make target. This command will create manifests specifically configured for the
`single-ns-bmh` namespace. It uses the `config/overlays/namespaced` kustomize
overlay to replace cluster-scoped resources with their namespace-scoped counterparts.


## Watching resources in specific Namespaces

When setting up the manager, you can use the environment variable
`WATCH_NAMESPACE` to restrict the operator to a specific namespace. If
`WATCH_NAMESPACE` is unset or set to an empty string, the operator will
monitor all namespaces. To limit it to a specific namespace, set
`WATCH_NAMESPACE` to that namespace.

For example, to configure the operator to watch the same namespace where
it is deployed, update the `config/base/manager.yaml` file. Add the
following configuration under `spec.template.spec.containers.env`:

```yaml
- name: WATCH_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
```
## Restricting Roles and permissions
When BMO is restricted to a single namespace, the RBAC permissions need
to be updated accordingly. Instead of using `ClusterRole`, you will use
`Role`.

The `Role` is defined in the file `config/base/rbac/role_ns.yaml`. This
file is auto-generated based on Kubebuilder RBAC markers, specifically those
in `<some>_controller.go`. The default namespace marking is set to `""`,
which results in a `ClusterRole`. To restrict it to a specific namespace,
update this value accordingly.

After updating the markers, generate the new manifests by running:

```bash
make manifests
```

Ensure that `config/base/rbac/role_ns.yaml` has been updated to a `Role`.

Due to limitations in Kubebuilder generation, the `RoleBinding` will not
be updated automatically.You can manually update `config/base/rbac/role_binding.yaml`
to achieve the desired outcome. Below is an example of how to modify the
`role_binding.yaml` file:

```yaml:
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: manager-rolebinding
namespace: your-namespace
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: manager-role
namespace: your-namespace
subjects:
- kind: ServiceAccount
name: controller-manager
namespace: system
```
Replace `your-namespace` and other fields as necessary to match your
specific configuration.

After this you can run `make manifests-kustomize` to get correct RoleBinding generated

0 comments on commit 11dcd29

Please sign in to comment.