Skip to content
Open
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
11 changes: 11 additions & 0 deletions internal/operator/controller/sandbox_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"maps"
"path/filepath"
"strconv"
"strings"
"time"

corev1 "k8s.io/api/core/v1"
Expand Down Expand Up @@ -109,6 +110,10 @@ const (
LabelAllowIPv6Internet = "isola.run/allow-ipv6-internet-egress"
LabelAllowClusterDNS = "isola.run/allow-cluster-dns"

labelAllowPrefix = "isola.run/allow-"

gvisorAnnotationPrefix = "dev.gvisor."

// SidecarVersionAnnotation records on the sandbox pod the isola-operator
// GitVersion at the moment the pod was created. Sandbox.Status.SidecarVersion
// is a mirror of this annotation; the pod is the durable source of truth so
Expand Down Expand Up @@ -275,6 +280,9 @@ func (r *SandboxReconciler) CreateSandboxPod(ctx context.Context, sandbox *sandb
// This prevents templates from overriding app.kubernetes.io/* etc.
labels := make(map[string]string)
maps.Copy(labels, sandbox.Spec.PodTemplate.Labels)
maps.DeleteFunc(labels, func(k, _ string) bool {
return strings.HasPrefix(k, labelAllowPrefix)
})

// Standard Kubernetes recommended labels (https://kubernetes.io/docs/concepts/overview/working-with-objects/common-labels/)
labels["app.kubernetes.io/name"] = "isola-sandbox"
Expand All @@ -290,6 +298,9 @@ func (r *SandboxReconciler) CreateSandboxPod(ctx context.Context, sandbox *sandb

annotations := make(map[string]string, len(sandbox.Spec.PodTemplate.Annotations))
maps.Copy(annotations, sandbox.Spec.PodTemplate.Annotations)
maps.DeleteFunc(annotations, func(k, _ string) bool {
return strings.HasPrefix(k, gvisorAnnotationPrefix)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve safe gVisor flag annotations

For CRD-created sandboxes that set safe per-pod gVisor annotations such as dev.gvisor.flag.strace or dev.gvisor.flag.debug for troubleshooting, this predicate now silently drops them because it removes every dev.gvisor.* key, not just the operator-owned overlay2, qdisc, and rootfs restore annotations. The existing code path deliberately copied template annotations through to the pod, and runsc has an allowlist for safe dev.gvisor.flag.* overrides, so this is a behavior regression; please strip only the specific operator-owned keys/prefixes that can bypass Isola policy.

Useful? React with 👍 / 👎.

})

sandboxPod := &corev1.Pod{
ObjectMeta: metav1.ObjectMeta{
Expand Down
51 changes: 51 additions & 0 deletions internal/operator/controller/sandbox_controller_pod_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,57 @@ var _ = Describe("Sandbox Controller", func() {
Expect(pod.Annotations).To(HaveKeyWithValue("dev.gvisor.flag.overlay2", "root:self"))
})

It("should strip operator-owned egress-authorization labels from the pod template", func() {
sandboxName := "sandbox-strip-labels"

createSandbox(ctx, sandboxName, func(s *sandboxv1alpha1.Sandbox) {
s.Spec.PodTemplate.Labels = map[string]string{
LabelAllowIPv4Internet: "true",
LabelAllowClusterDNS: "true",
"team": "blue",
}
})
defer deleteSandbox(ctx, sandboxName)

podName := sandboxName + "-pod"
defer deletePod(ctx, podName)

_, err := doReconcile(ctx, reconciler, sandboxName)
Expect(err).NotTo(HaveOccurred())

pod := getPod(ctx, podName)
Expect(pod).NotTo(BeNil())
Expect(pod.Labels).NotTo(HaveKey(LabelAllowIPv4Internet))
Expect(pod.Labels).NotTo(HaveKey(LabelAllowClusterDNS))
Expect(pod.Labels).To(HaveKeyWithValue("team", "blue"))
})

It("should strip operator-owned gVisor annotations from the pod template", func() {
sandboxName := "sandbox-strip-annotations"

createSandbox(ctx, sandboxName, func(s *sandboxv1alpha1.Sandbox) {
s.Spec.PodTemplate.Annotations = map[string]string{
"dev.gvisor.tar.rootfs.upper.sandbox": "/host/snapshots/victim/secret.tar",
"dev.gvisor.flag.qdisc": "tbf",
"team": "blue",
}
})
defer deleteSandbox(ctx, sandboxName)

podName := sandboxName + "-pod"
defer deletePod(ctx, podName)

_, err := doReconcile(ctx, reconciler, sandboxName)
Expect(err).NotTo(HaveOccurred())

pod := getPod(ctx, podName)
Expect(pod).NotTo(BeNil())
Expect(pod.Annotations).NotTo(HaveKey("dev.gvisor.tar.rootfs.upper.sandbox"))
Expect(pod.Annotations).NotTo(HaveKey("dev.gvisor.flag.qdisc"))
Expect(pod.Annotations).To(HaveKeyWithValue("dev.gvisor.flag.overlay2", "root:self"))
Expect(pod.Annotations).To(HaveKeyWithValue("team", "blue"))
})

It("should inject sleep infinity when no command is specified", func() {
sandboxName := "sandbox-default-cmd"

Expand Down