Skip to content

Commit

Permalink
feat(agent): privileged flag for Sysdig Agent (#1743)
Browse files Browse the repository at this point in the history
Co-authored-by: Marco Vito Moscaritolo <[email protected]>
  • Loading branch information
deepskyblue86 and mavimo authored Jul 4, 2024
1 parent 1627aa9 commit 14e85ea
Show file tree
Hide file tree
Showing 10 changed files with 246 additions and 17 deletions.
2 changes: 1 addition & 1 deletion charts/agent/Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,4 @@ sources:
- https://app.sysdigcloud.com/#/settings/user
- https://github.com/draios/sysdig
type: application
version: 1.26.0
version: 1.27.0
1 change: 1 addition & 0 deletions charts/agent/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ The following table lists the configurable parameters of the Sysdig chart and th
| `slim.resources.limits.memory` | Specifies the memory limit for building the kernel module. | `512Mi` |
| `ebpf.enabled` | Enables eBPF support for Sysdig instead of `sysdig-probe` kernel module. | `false` |
| `ebpf.kind` | Define which eBPF driver to use, can be `legacy_ebpf` or `universal_ebpf` | `legacy_ebpf` |
| `privileged` | Run the Sysdig Agent container as privileged. When set to false, eBPF must be enabled | `true` |
| `clusterName` | Sets a unique cluster name which is used to identify events with the `kubernetes.cluster.name` tag. Overrides `global.clusterConfig.name`. | ` ` |
| `sysdig.accessKey` | Your Sysdig Agent Access Key. Overrides `global.sysdig.accessKey` | Either `accessKey` or `existingAccessKeySecret` is required |
| `sysdig.existingAccessKeySecret` | Specifies the name of a Kubernetes secret containing an `access-key ` entry. Overrides `global.sysdig.existingAccessKeySecret` | Either `accessKey` or `existingAccessKeySecret` is required |
Expand Down
76 changes: 71 additions & 5 deletions charts/agent/templates/_helpers.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -585,25 +585,91 @@ true
{{- end }}
{{- end }}
{{/* Check if semver. The regex is from the code of the library Helm uses for semver. */}}
{{- define "agent.isSemVer" -}}
{{- if regexMatch "^v?([0-9]+)(\\.[0-9]+)?(\\.[0-9]+)?(-([0-9A-Za-z\\-]+(\\.[0-9A-Za-z\\-]+)*))?(\\+([0-9A-Za-z\\-]+(\\.[0-9A-Za-z\\-]+)*))?$" . }}
true
{{- end -}}
{{- end -}}
{{/* Return the name of the local forwarder configmap */}}
{{- define "agent.localForwarderConfigMapName" }}
{{- include "agent.configmapName" . | trunc 46 | trimSuffix "-" | printf "%s-local-forwarder" }}
{{- end }}
{{- define "agent.enableHttpProbes" }}
{{- if not (include "agent.gke.autopilot" .) }}
{{- if regexMatch "^v?([0-9]+)(\\.[0-9]+)?(\\.[0-9]+)?(-([0-9A-Za-z\\-]+(\\.[0-9A-Za-z\\-]+)*))?(\\+([0-9A-Za-z\\-]+(\\.[0-9A-Za-z\\-]+)*))?$" .Values.image.tag }}
{{- if semverCompare ">= 12.18.0-0" .Values.image.tag }}
{{- if and (include "agent.isSemVer" .Values.image.tag) (semverCompare ">= 12.18.0-0" .Values.image.tag) }}
{{- printf "true" -}}
{{- end }}
{{- end }}
{{- end }}
{{- end }}
{{- define "agent.enableFalcoBaselineSecureLight" }}
{{- if regexMatch "^v?([0-9]+)(\\.[0-9]+)?(\\.[0-9]+)?(-([0-9A-Za-z\\-]+(\\.[0-9A-Za-z\\-]+)*))?(\\+([0-9A-Za-z\\-]+(\\.[0-9A-Za-z\\-]+)*))?$" .Values.image.tag }}
{{- if semverCompare ">= 12.19.0-0" .Values.image.tag }}
{{- if and (include "agent.isSemVer" .Values.image.tag) (semverCompare ">= 12.19.0-0" .Values.image.tag) }}
{{- printf "true" -}}
{{- end }}
{{- end }}
{{- define "agent.annotationsSection" }}
{{- if (include "agent.gke.autopilot" .) }}
annotations:
autopilot.gke.io/no-connect: "true"
{{- else if or (.Values.daemonset.annotations) (eq "false" (include "agent.privileged" .)) }}
annotations:
{{- if (eq "false" (include "agent.privileged" .)) }}
container.apparmor.security.beta.kubernetes.io/sysdig: unconfined
{{- end }}
{{- if .Values.daemonset.annotations }}
{{- toYaml .Values.daemonset.annotations | nindent 2 }}
{{- end }}
{{- end }}
{{- end }}
{{/*
- .Values.privileged is true: no problem
- .Values.privileged is false:
- eBPF disabled: fail
- eBPF enabled:
- image tag >= 13.3.0: no problem
- image tag not semver: go on at user's risk
*/}}
{{- define "agent.privileged" }}
{{- if or .Values.privileged (include "agent.gke.autopilot" .) }}
{{- /* OK */ -}}
{{- print "true" }}
{{- else }}
{{- $errMsg := "Disabling 'privileged' flag requires eBPF and Sysdig Agent 13.3.0 or newer" }}
{{- /* eBPF is mandatory */ -}}
{{- if not (eq "true" (include "agent.ebpfEnabled" .)) }}
{{- /* FAIL */ -}}
{{- fail $errMsg }}
{{- end }}
{{- /* Version check */ -}}
{{- if (include "agent.isSemVer" .Values.image.tag) }}
{{- /* Check for release version */ -}}
{{- if (semverCompare ">= 13.3.0-0" .Values.image.tag) }}
{{- /* OK */ -}}
{{- print "false" }}
{{- else }}
{{- /* FAIL */ -}}
{{- fail $errMsg }}
{{- end }}
{{- /* Check for dev version */ -}}
{{- else }}
{{- /* Let it go through */ -}}
{{- print "false" }}
{{- end }}
{{- end }}
{{- end }}

{{- define "agent.capabilities" -}}
- SYS_ADMIN
- SYS_RESOURCE
- SYS_PTRACE
- SYS_CHROOT
- DAC_READ_SEARCH
- KILL
- SETUID
- SETGID
{{- end -}}
21 changes: 12 additions & 9 deletions charts/agent/templates/daemonset.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,7 @@ spec:
labels:
{{ include "agent.labels" . | nindent 8 }}
{{ include "agent.daemonsetLabels" . | nindent 8 }}
{{- if (include "agent.gke.autopilot" .) }}
annotations:
autopilot.gke.io/no-connect: "true"
{{- else }}
{{- if .Values.daemonset.annotations }}
annotations:
{{ toYaml .Values.daemonset.annotations | nindent 8 }}
{{- end }}
{{- end }}
{{ include "agent.annotationsSection" . | nindent 6 }}
spec:
serviceAccountName: {{ template "agent.serviceAccountName" .}}
{{- if or .Values.priorityClassName (include "agent.gke.autopilot" .) }}
Expand Down Expand Up @@ -178,11 +170,22 @@ spec:
resources:
{{- include "agent.resources" . | nindent 12 }}
securityContext:
{{- if eq "true" (include "agent.privileged" .) }}
privileged: true
runAsNonRoot: false
runAsUser: 0
readOnlyRootFilesystem: false
allowPrivilegeEscalation: true
{{- else }}
allowPrivilegeEscalation: false
seccompProfile:
type: Unconfined
capabilities:
drop:
- ALL
add:
{{- include "agent.capabilities" . | nindent 14 }}
{{- end }}
env:
- name: K8S_NODE
valueFrom:
Expand Down
5 changes: 5 additions & 0 deletions charts/agent/templates/securitycontextconstraint.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,12 @@ allowHostPID: true
allowHostPorts: false
allowPrivilegeEscalation: true
allowPrivilegedContainer: true
{{- if eq "true" (include "agent.privileged" .) }}
allowedCapabilities: []
{{- else }}
allowedCapabilities:
{{ include "agent.capabilities" . }}
{{- end }}
allowedUnsafeSysctls: []
defaultAddCapabilities: []
fsGroup:
Expand Down
73 changes: 73 additions & 0 deletions charts/agent/tests/conditional_flag_test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,76 @@ tests:
- equal:
path: spec.template.spec.containers[*].image
value: quay.io/sysdig/agent-slim:12.9.0

- it: Checking privileged flag set to true
set:
privileged: true
asserts:
- equal:
path: spec.template.spec.containers[*].securityContext.privileged
value: true

- it: Checking privileged flag set to false with disabled ebpf
set:
privileged: false
ebpf:
enabled: false
asserts:
- failedTemplate:
errorMessage: "Disabling 'privileged' flag requires eBPF and Sysdig Agent 13.3.0 or newer"

- it: Checking privileged flag set to false with old agent version
set:
privileged: false
ebpf:
enabled: true
image:
tag: 13.2.0
asserts:
- failedTemplate:
errorMessage: "Disabling 'privileged' flag requires eBPF and Sysdig Agent 13.3.0 or newer"

- it: Checking privileged flag set to false, agent version 13.3.0
set:
privileged: false
ebpf:
enabled: true
image:
tag: 13.3.0
asserts:
- equal:
path: spec.template.metadata.annotations['container.apparmor.security.beta.kubernetes.io/sysdig']
value: "unconfined"
- notExists:
path: spec.template.spec.containers[*].securityContext.privileged
- equal:
path: spec.template.spec.containers[*].securityContext.seccompProfile.type
value: Unconfined
- contains:
path: spec.template.spec.containers[*].securityContext.capabilities.drop
content: ALL
- exists:
path: spec.template.spec.containers[*].securityContext.capabilities.add

- it: Checking privileged flag set to false, not semver agent version
set:
privileged: false
ebpf:
enabled: true
image:
tag: whatever
asserts:
- equal:
path: spec.template.metadata.annotations
value:
container.apparmor.security.beta.kubernetes.io/sysdig: unconfined
- notExists:
path: spec.template.spec.containers[*].securityContext.privileged
- equal:
path: spec.template.spec.containers[*].securityContext.seccompProfile.type
value: Unconfined
- contains:
path: spec.template.spec.containers[*].securityContext.capabilities.drop
content: ALL
- exists:
path: spec.template.spec.containers[*].securityContext.capabilities.add
76 changes: 76 additions & 0 deletions charts/agent/tests/security_context_constraints_test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
suite: Testing Security Context Constraint
templates:
- securitycontextconstraint.yaml

capabilities:
apiVersions:
- security.openshift.io/v1

kubernetesProvider:
scheme:
"v1/Node":
gvr:
version: "v1"
resource: "nodes"
namespaced: false
objects:
- apiVersion: v1
kind: Node
metadata:
name: fakenode
status:
nodeInfo:
osImage: fake-os-image

tests:
- it: Testing that SCS is not created if not enabled
set:
scc:
create: false
asserts:
- hasDocuments:
count: 0

- it: Testing that SCS is created when required
set:
scc:
create: true
asserts:
- hasDocuments:
count: 1
- isKind:
of: SecurityContextConstraints

- it: Testing that SCS capabilities are empty by default
set:
scc:
create: true
asserts:
- isEmpty:
path: allowedCapabilities

- it: Testing that SCS capabilities are empty when privileged is true
set:
privileged: true
image:
tag: '13.3.0'
ebpf:
enabled: true
scc:
create: true
asserts:
- isEmpty:
path: allowedCapabilities

- it: Testing that SCS capabilities are not empty when privileged is false
set:
privileged: false
image:
tag: '13.3.0'
ebpf:
enabled: true
scc:
create: true
asserts:
- isNotEmpty:
path: allowedCapabilities
3 changes: 3 additions & 0 deletions charts/agent/values.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@
}
}
}
},
"privileged": {
"type": "boolean"
}
},
"$defs": {
Expand Down
2 changes: 2 additions & 0 deletions charts/agent/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,8 @@ ebpf:
enabled: false
# Define the kind of eBPF driver that will be used by the agent. Can be `legacy_ebpf` or `universal_ebpf`
kind: legacy_ebpf
# Run the Sysdig Agent container as privileged. When set to false, eBPF must be enabled
privileged: true
slim:
# Uses a slim version of the Sysdig Agent
enabled: true
Expand Down
4 changes: 2 additions & 2 deletions charts/sysdig-deploy/Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ apiVersion: v2
name: sysdig-deploy
description: A chart with various Sysdig components for Kubernetes
type: application
version: 1.58.0
version: 1.59.0
maintainers:
- name: AlbertoBarba
email: [email protected]
Expand All @@ -26,7 +26,7 @@ dependencies:
- name: agent
# repository: https://charts.sysdig.com
repository: file://../agent
version: ~1.26.0
version: ~1.27.0
alias: agent
condition: agent.enabled
- name: common
Expand Down

0 comments on commit 14e85ea

Please sign in to comment.