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.40.1
version: 1.41.0
appVersion: "1.0.0"
523 changes: 262 additions & 261 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 @@ -380,3 +380,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.

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
226 changes: 226 additions & 0 deletions charts/shield/tests/host/clusterrole_test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,232 @@ tests:
apiVersion: rbac.authorization.k8s.io/v1
name: release-name-shield-host

- it: Default values do not grant nodes/proxy or nodes/log
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: Creates the ClusterRole with baseline rules by default
asserts:
- isKind:
Expand Down
6 changes: 6 additions & 0 deletions charts/shield/values.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -1440,6 +1440,12 @@
"annotations": {
"type": "object",
"description": "Annotations applied to RBAC resources created by the chart."
},
"kubelet_authorization_mode": {
"type": "string",
"enum": ["auto", "fine_grained", "legacy"],
"description": "Host-only. Authorization mode for kubelet log access RBAC. Inert when features.investigations.live_logs is disabled.",
"default": "auto"
}
},
"additionalProperties": false
Expand Down
8 changes: 8 additions & 0 deletions charts/shield/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,14 @@ host:
labels: {}
# The annotations for the RBAC resources
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