Skip to content
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
2 changes: 1 addition & 1 deletion charts/shield/Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,5 @@ maintainers:
- name: mavimo
email: marcovito.moscaritolo@sysdig.com
type: application
version: 1.37.1
version: 1.38.0
appVersion: "1.0.0"
491 changes: 246 additions & 245 deletions charts/shield/README.md

Large diffs are not rendered by default.

40 changes: 40 additions & 0 deletions charts/shield/templates/host/_helpers.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -352,3 +352,43 @@ true
{{- define "host.allowlist_waiter.image" -}}
{{- .Values.gke_autopilot.allowlist_waiter.image.registry -}} / {{- .Values.gke_autopilot.allowlist_waiter.image.repository -}} {{- include "host.allowlist_waiter.tag_separator" . -}} {{- .Values.gke_autopilot.allowlist_waiter.image.tag }}
{{- end }}

{{/*
Kubelet log access RBAC helpers (SMAGENT-10349).

The host-shield's Live Logs feature reads container logs through the kubelet
API. Historically this required the broad `nodes/proxy` subresource — the
same permission flagged as a Remote Code Execution vector by security scans.
Kubernetes 1.36 promotes KEP-2862 (Fine-grained API authorization) to stable,
exposing `nodes/log` as a narrow subresource scoped to log retrieval only.

These helpers gate the kubelet-log RBAC rule on `features.investigations.
live_logs.enabled` and pick the right subresource based on cluster version
(auto) or an explicit override (`fine_grained` / `legacy`).
*/}}
{{- define "host.kubelet_log_access.enabled" -}}
{{- if .Values.features.investigations.live_logs.enabled -}}
true
{{- end -}}
{{- end }}

{{- define "host.kubelet_log_access.is_fine_grained_capable" -}}
{{- $kubeMajor := .Capabilities.KubeVersion.Major | toString | trimSuffix "+" | int -}}
{{- $kubeMinor := .Capabilities.KubeVersion.Minor | toString | trimSuffix "+" | int -}}
{{- if or (gt $kubeMajor 1) (and (eq $kubeMajor 1) (ge $kubeMinor 36)) -}}
true
{{- end -}}
{{- end }}

{{- define "host.kubelet_log_access.subresource" -}}
{{- $mode := default "auto" .Values.host.rbac.kubelet_authorization_mode -}}
{{- if eq $mode "fine_grained" -}}
nodes/log
{{- else if eq $mode "legacy" -}}
nodes/proxy
{{- else if eq (include "host.kubelet_log_access.is_fine_grained_capable" .) "true" -}}
nodes/log
{{- else -}}
nodes/proxy
{{- end -}}
{{- end }}
11 changes: 10 additions & 1 deletion charts/shield/templates/host/clusterrole.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ rules:
- namespaces
- nodes
- nodes/metrics
- nodes/proxy
- resourcequotas
- persistentvolumes
- persistentvolumeclaims
Expand Down Expand Up @@ -113,6 +112,16 @@ rules:
- get
- list
- watch
{{- if eq "true" (include "host.kubelet_log_access.enabled" .) }}
- apiGroups:
- ""
resources:
- {{ include "host.kubelet_log_access.subresource" . }}
verbs:
- get
- list
- watch
{{- end }}
{{- if or (.Capabilities.APIVersions.Has "rbac.authorization.k8s.io/v1beta1/PodSecurityPolicy") (has "rbac.authorization.k8s.io/v1beta1/PodSecurityPolicy" .Values.extra_capabilities_api_versions) }}

- apiGroups:
Expand Down
243 changes: 243 additions & 0 deletions charts/shield/tests/host/clusterrole_test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,243 @@
suite: Host - ClusterRole
templates:
- templates/host/clusterrole.yaml
release:
name: release-name
namespace: shield-namespace
values:
- ../values/base.yaml
tests:
- it: Default values do not grant nodes/proxy or nodes/log (SMAGENT-10349)
asserts:
- containsDocument:
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
name: release-name-shield-host
- notContains:
path: rules
content:
apiGroups:
- ""
resources:
- nodes/proxy
verbs:
- get
- list
- watch
- notContains:
path: rules
content:
apiGroups:
- ""
resources:
- nodes/log
verbs:
- get
- list
- watch

- it: Always-present base rule keeps nodes and nodes/metrics but never nodes/proxy
asserts:
- contains:
path: rules
content:
apiGroups:
- ""
resources:
- pods
- replicationcontrollers
- services
- endpoints
- events
- limitranges
- namespaces
- nodes
- nodes/metrics
- resourcequotas
- persistentvolumes
- persistentvolumeclaims
- configmaps
verbs:
- get
- list
- watch

- it: Live logs enabled on K8s 1.36 grants the narrow nodes/log subresource
capabilities:
majorVersion: "1"
minorVersion: "36"
set:
features:
investigations:
live_logs:
enabled: true
asserts:
- contains:
path: rules
content:
apiGroups:
- ""
resources:
- nodes/log
verbs:
- get
- list
- watch
- notContains:
path: rules
content:
apiGroups:
- ""
resources:
- nodes/proxy
verbs:
- get
- list
- watch

- it: Live logs enabled on K8s 1.35 falls back to nodes/proxy
capabilities:
majorVersion: "1"
minorVersion: "35"
set:
features:
investigations:
live_logs:
enabled: true
asserts:
- contains:
path: rules
content:
apiGroups:
- ""
resources:
- nodes/proxy
verbs:
- get
- list
- watch
- notContains:
path: rules
content:
apiGroups:
- ""
resources:
- nodes/log
verbs:
- get
- list
- watch

- it: Override kubelet_authorization_mode=legacy grants nodes/proxy on a modern cluster
capabilities:
majorVersion: "1"
minorVersion: "40"
set:
features:
investigations:
live_logs:
enabled: true
host:
rbac:
kubelet_authorization_mode: legacy
asserts:
- contains:
path: rules
content:
apiGroups:
- ""
resources:
- nodes/proxy
verbs:
- get
- list
- watch
- notContains:
path: rules
content:
apiGroups:
- ""
resources:
- nodes/log
verbs:
- get
- list
- watch

- it: Override kubelet_authorization_mode=fine_grained grants nodes/log on an old cluster
capabilities:
majorVersion: "1"
minorVersion: "30"
set:
features:
investigations:
live_logs:
enabled: true
host:
rbac:
kubelet_authorization_mode: fine_grained
asserts:
- contains:
path: rules
content:
apiGroups:
- ""
resources:
- nodes/log
verbs:
- get
- list
- watch
- notContains:
path: rules
content:
apiGroups:
- ""
resources:
- nodes/proxy
verbs:
- get
- list
- watch

- it: Live logs explicitly disabled grants neither subresource
capabilities:
majorVersion: "1"
minorVersion: "36"
set:
features:
investigations:
live_logs:
enabled: false
asserts:
- notContains:
path: rules
content:
apiGroups:
- ""
resources:
- nodes/log
verbs:
- get
- list
- watch
- notContains:
path: rules
content:
apiGroups:
- ""
resources:
- nodes/proxy
verbs:
- get
- list
- watch

- it: ClusterRole is not created when host.rbac.create is false
set:
host:
rbac:
create: false
asserts:
- hasDocuments:
count: 0
8 changes: 8 additions & 0 deletions charts/shield/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,14 @@ host:
labels: {}
# The annotations for the service account
annotations: {}
# Authorization mode used to grant the host shield read access to kubelet
# log endpoints when features.investigations.live_logs.enabled is true.
# When live_logs is disabled (the default), no kubelet-log permission is
# granted regardless of this setting.
# auto: detect from the cluster K8s version (>=1.36 ⇒ fine_grained, otherwise legacy)
# fine_grained: grant `nodes/log` (KEP-2862, stable in Kubernetes 1.36+) — recommended
# legacy: grant `nodes/proxy` (broad, RCE-prone — only required on Kubernetes <1.36)
kubelet_authorization_mode: auto
resources:
kmodule:
limits:
Expand Down
Loading