Add optional privileged mode to NBRoutingPeerSpec (#92)

Introduced a new optional boolean field `Privileged` in the
`NBRoutingPeerSpec` to allow deployments to specify if containers should
run in privileged mode. Updated the CRD, Helm templates, and controller
logic to support this feature.

A new function `buildSecurityContext` was added to handle the creation
of the appropriate security context based on the `Privileged` setting.
Tests were updated to cover scenarios where privileged mode is enabled,
disabled, or unspecified. This change allows more granular control over
container security settings, potentially increasing compatibility with
certain workloads that require elevated privileges.

see https://github.com/netbirdio/kubernetes-operator/issues/90

**Note:**
I am not a Go developer and have no experience with this architecture. I
may have overlooked some things.
This commit is contained in:
Jan
2026-03-03 08:29:52 +01:00
committed by GitHub
parent 8ec7c8ded8
commit cbe0e3a2a1
7 changed files with 180 additions and 19 deletions
+22 -16
View File
@@ -187,15 +187,9 @@ func (r *NBRoutingPeerReconciler) handleDeployment(ctx context.Context, req ctrl
Value: r.ManagementURL,
},
},
SecurityContext: &corev1.SecurityContext{
Capabilities: &corev1.Capabilities{
Add: []corev1.Capability{
"NET_ADMIN",
},
},
},
Resources: nbrp.Spec.Resources,
VolumeMounts: nbrp.Spec.VolumeMounts,
SecurityContext: r.buildSecurityContext(nbrp),
Resources: nbrp.Spec.Resources,
VolumeMounts: nbrp.Spec.VolumeMounts,
},
},
Volumes: nbrp.Spec.Volumes,
@@ -263,13 +257,7 @@ func (r *NBRoutingPeerReconciler) handleDeployment(ctx context.Context, req ctrl
Value: r.ManagementURL,
},
}
updatedDeployment.Spec.Template.Spec.Containers[0].SecurityContext = &corev1.SecurityContext{
Capabilities: &corev1.Capabilities{
Add: []corev1.Capability{
"NET_ADMIN",
},
},
}
updatedDeployment.Spec.Template.Spec.Containers[0].SecurityContext = r.buildSecurityContext(nbrp)
updatedDeployment.Spec.Template.Spec.Containers[0].Resources = nbrp.Spec.Resources
updatedDeployment.Spec.Template.Spec.Containers[0].VolumeMounts = nbrp.Spec.VolumeMounts
@@ -657,6 +645,24 @@ func (r *NBRoutingPeerReconciler) handleDelete(ctx context.Context, req ctrl.Req
return ctrl.Result{}, nil
}
// buildSecurityContext creates the appropriate SecurityContext based on the NBRoutingPeer spec
func (r *NBRoutingPeerReconciler) buildSecurityContext(nbrp *netbirdiov1.NBRoutingPeer) *corev1.SecurityContext {
securityContext := &corev1.SecurityContext{
Capabilities: &corev1.Capabilities{
Add: []corev1.Capability{
"NET_ADMIN",
},
},
}
// Set privileged mode if specified
if nbrp.Spec.Privileged != nil && *nbrp.Spec.Privileged {
securityContext.Privileged = nbrp.Spec.Privileged
}
return securityContext
}
// SetupWithManager sets up the controller with the Manager.
func (r *NBRoutingPeerReconciler) SetupWithManager(mgr ctrl.Manager) error {
r.netbird = netbird.New(r.ManagementURL, r.APIKey)
@@ -915,6 +915,144 @@ var _ = Describe("NBRoutingPeer Controller", func() {
Expect(deployment.ResourceVersion).To(Equal(resourceVersion))
})
})
When("Privileged mode is enabled", func() {
It("should create deployment with privileged security context", func() {
Expect(k8sClient.Get(ctx, typeNamespacedName, nbroutingpeer)).To(Succeed())
nbroutingpeer.Spec.Privileged = util.Ptr(true)
Expect(k8sClient.Update(ctx, nbroutingpeer)).To(Succeed())
_, err := controllerReconciler.Reconcile(ctx, reconcile.Request{
NamespacedName: typeNamespacedName,
})
Expect(err).NotTo(HaveOccurred())
deployment := &appsv1.Deployment{}
Expect(k8sClient.Get(ctx, typeNamespacedName, deployment)).To(Succeed())
Expect(deployment.Spec.Template.Spec.Containers).To(HaveLen(1))
container := deployment.Spec.Template.Spec.Containers[0]
Expect(container.SecurityContext).NotTo(BeNil())
Expect(container.SecurityContext.Privileged).NotTo(BeNil())
Expect(*container.SecurityContext.Privileged).To(BeTrue())
Expect(container.SecurityContext.Capabilities).NotTo(BeNil())
Expect(container.SecurityContext.Capabilities.Add).To(ContainElement(corev1.Capability("NET_ADMIN")))
})
})
When("Privileged mode is disabled", func() {
It("should create deployment with non-privileged security context", func() {
Expect(k8sClient.Get(ctx, typeNamespacedName, nbroutingpeer)).To(Succeed())
nbroutingpeer.Spec.Privileged = util.Ptr(false)
Expect(k8sClient.Update(ctx, nbroutingpeer)).To(Succeed())
_, err := controllerReconciler.Reconcile(ctx, reconcile.Request{
NamespacedName: typeNamespacedName,
})
Expect(err).NotTo(HaveOccurred())
deployment := &appsv1.Deployment{}
Expect(k8sClient.Get(ctx, typeNamespacedName, deployment)).To(Succeed())
Expect(deployment.Spec.Template.Spec.Containers).To(HaveLen(1))
container := deployment.Spec.Template.Spec.Containers[0]
Expect(container.SecurityContext).NotTo(BeNil())
Expect(container.SecurityContext.Privileged).To(BeNil())
Expect(container.SecurityContext.Capabilities).NotTo(BeNil())
Expect(container.SecurityContext.Capabilities.Add).To(ContainElement(corev1.Capability("NET_ADMIN")))
})
})
When("Privileged mode is not specified", func() {
It("should create deployment with default security context (non-privileged)", func() {
// Ensure Privileged is nil (default)
Expect(k8sClient.Get(ctx, typeNamespacedName, nbroutingpeer)).To(Succeed())
nbroutingpeer.Spec.Privileged = nil
Expect(k8sClient.Update(ctx, nbroutingpeer)).To(Succeed())
_, err := controllerReconciler.Reconcile(ctx, reconcile.Request{
NamespacedName: typeNamespacedName,
})
Expect(err).NotTo(HaveOccurred())
deployment := &appsv1.Deployment{}
Expect(k8sClient.Get(ctx, typeNamespacedName, deployment)).To(Succeed())
Expect(deployment.Spec.Template.Spec.Containers).To(HaveLen(1))
container := deployment.Spec.Template.Spec.Containers[0]
Expect(container.SecurityContext).NotTo(BeNil())
Expect(container.SecurityContext.Privileged).To(BeNil())
Expect(container.SecurityContext.Capabilities).NotTo(BeNil())
Expect(container.SecurityContext.Capabilities.Add).To(ContainElement(corev1.Capability("NET_ADMIN")))
})
})
When("Deployment exists and privileged mode changes", func() {
It("should update deployment security context when privileged mode is enabled", func() {
// First create deployment without privileged mode
_, err := controllerReconciler.Reconcile(ctx, reconcile.Request{
NamespacedName: typeNamespacedName,
})
Expect(err).NotTo(HaveOccurred())
// Verify initial state
deployment := &appsv1.Deployment{}
Expect(k8sClient.Get(ctx, typeNamespacedName, deployment)).To(Succeed())
container := deployment.Spec.Template.Spec.Containers[0]
Expect(container.SecurityContext.Privileged).To(BeNil())
// Enable privileged mode
Expect(k8sClient.Get(ctx, typeNamespacedName, nbroutingpeer)).To(Succeed())
nbroutingpeer.Spec.Privileged = util.Ptr(true)
Expect(k8sClient.Update(ctx, nbroutingpeer)).To(Succeed())
_, err = controllerReconciler.Reconcile(ctx, reconcile.Request{
NamespacedName: typeNamespacedName,
})
Expect(err).NotTo(HaveOccurred())
// Verify privileged mode is now enabled
deployment = &appsv1.Deployment{}
Expect(k8sClient.Get(ctx, typeNamespacedName, deployment)).To(Succeed())
container = deployment.Spec.Template.Spec.Containers[0]
Expect(container.SecurityContext.Privileged).NotTo(BeNil())
Expect(*container.SecurityContext.Privileged).To(BeTrue())
})
It("should update deployment security context when privileged mode is disabled", func() {
// First create deployment with privileged mode enabled
nbroutingpeer.Spec.Privileged = util.Ptr(true)
Expect(k8sClient.Update(ctx, nbroutingpeer)).To(Succeed())
_, err := controllerReconciler.Reconcile(ctx, reconcile.Request{
NamespacedName: typeNamespacedName,
})
Expect(err).NotTo(HaveOccurred())
// Verify initial privileged state
deployment := &appsv1.Deployment{}
Expect(k8sClient.Get(ctx, typeNamespacedName, deployment)).To(Succeed())
container := deployment.Spec.Template.Spec.Containers[0]
Expect(container.SecurityContext.Privileged).NotTo(BeNil())
Expect(*container.SecurityContext.Privileged).To(BeTrue())
// Disable privileged mode
Expect(k8sClient.Get(ctx, typeNamespacedName, nbroutingpeer)).To(Succeed())
nbroutingpeer.Spec.Privileged = util.Ptr(false)
Expect(k8sClient.Update(ctx, nbroutingpeer)).To(Succeed())
_, err = controllerReconciler.Reconcile(ctx, reconcile.Request{
NamespacedName: typeNamespacedName,
})
Expect(err).NotTo(HaveOccurred())
// Verify privileged mode is now disabled
deployment = &appsv1.Deployment{}
Expect(k8sClient.Get(ctx, typeNamespacedName, deployment)).To(Succeed())
container = deployment.Spec.Template.Spec.Containers[0]
Expect(container.SecurityContext.Privileged).To(BeNil())
})
})
})
When("NBRoutingPeer is set for deletion", func() {
networkDeleted := false