From f989935d5dbf2c6dc715435b2df3172d94eea82f Mon Sep 17 00:00:00 2001 From: Alex Glikson <57493527+chkp-alexgl@users.noreply.github.com> Date: Thu, 11 Mar 2021 16:39:35 +0200 Subject: [PATCH] 2.0.8: misc runtime daemon updates Runtime daemon updates (0.0.301 --> 0.0.347): * improved telemetry * better recovery from unexpected failures * improved updates of signatures * fixed memory leak in profiling --- checkpoint/cloudguard/Chart.yaml | 4 +- checkpoint/cloudguard/README.md | 2 +- checkpoint/cloudguard/templates/_helpers.tpl | 26 +++--- .../enforcer/configmap-fluentbit.yaml | 12 +-- .../runtime/daemon/configmap-fluentbit.yaml | 36 +++------ .../templates/runtime/daemon/daemonset.yaml | 75 +++++++++--------- checkpoint/cloudguard/values.yaml | 2 +- repository/cloudguard-2.0.8.tgz | Bin 0 -> 16362 bytes repository/index.yaml | 72 +++++++++++------ 9 files changed, 120 insertions(+), 109 deletions(-) create mode 100644 repository/cloudguard-2.0.8.tgz diff --git a/checkpoint/cloudguard/Chart.yaml b/checkpoint/cloudguard/Chart.yaml index a2cb4fbb..e3717dec 100644 --- a/checkpoint/cloudguard/Chart.yaml +++ b/checkpoint/cloudguard/Chart.yaml @@ -1,6 +1,6 @@ apiVersion: v2 -appVersion: v1.3.2 -version: 2.0.7 +appVersion: v2.0.8 +version: 2.0.8 description: A Helm chart for Check Point CloudGuard Workload Security name: cloudguard keywords: diff --git a/checkpoint/cloudguard/README.md b/checkpoint/cloudguard/README.md index 63932a4d..acfd1b27 100644 --- a/checkpoint/cloudguard/README.md +++ b/checkpoint/cloudguard/README.md @@ -169,7 +169,7 @@ The following tables list the configurable parameters of this chart and their de | `addons.runtimeProtection.enabled` | Specifies whether the Runtime Protection addon should be | `false` | | | installed | | | `addons.runtimeProtection.daemon.image` | Specify image for the agent | `checkpoint/consec-runtime-daemon` | -| `addons.runtimeProtection.daemon.tag` | Specify image tag for the agent |`0.0.301` | +| `addons.runtimeProtection.daemon.tag` | Specify image tag for the agent |`0.0.347` | | `addons.runtimeProtection.daemon.serviceAccountName` | Specify custom Service Account for the agent | `` | | `addons.runtimeProtection.daemon.env` | Additional environmental variables for the agent | `{}` | | `addons.runtimeProtection.daemon.resources` | Resources restriction (e.g. CPU, memory) | `requests.cpu: 100m` | diff --git a/checkpoint/cloudguard/templates/_helpers.tpl b/checkpoint/cloudguard/templates/_helpers.tpl index 29f4fdea..53a9b1f2 100644 --- a/checkpoint/cloudguard/templates/_helpers.tpl +++ b/checkpoint/cloudguard/templates/_helpers.tpl @@ -161,6 +161,20 @@ imagePullSecrets: {{- end -}} {{- end -}} +{{- /* fluentbit http output parametes */ -}} +{{- define "fluentbit-http-output-param.conf" }} +Name http +Format json_lines +Host ${CP_KUBERNETES_DOME9_URL} +Header Kubernetes-Account ${CP_KUBERNETES_CLUSTER_ID} +Header Node-Name ${NODE_NAME} +Compress gzip +http_User ${CP_KUBERNETES_USER} +http_Passwd ${CP_KUBERNETES_PASS} +Port 443 +tls On +tls.verify On +{{- end -}} {{- /* fluentbit configmap to send metric */ -}} {{- define "fluentbit-metric.conf" -}} @@ -172,21 +186,11 @@ imagePullSecrets: Interval_Sec 30 Interval_NSec 0 [OUTPUT] - Name http Match metrics - Format json_lines - Host ${CP_KUBERNETES_DOME9_URL} Uri ${CP_KUBERNETES_METRIC_URI} - Header Kubernetes-Account ${CP_KUBERNETES_CLUSTER_ID} Header Agent-Version {{ .agentVersion }} - Header Node-Name ${NODE_NAME} Header Telemetry-Version ${TELEMETRY_VERSION} - Compress gzip - http_User ${CP_KUBERNETES_USER} - http_Passwd ${CP_KUBERNETES_PASS} - Port 443 - tls On - tls.verify On +{{ include "fluentbit-http-output-param.conf" . | indent 4 }} {{- end -}} {{/* diff --git a/checkpoint/cloudguard/templates/admission/enforcer/configmap-fluentbit.yaml b/checkpoint/cloudguard/templates/admission/enforcer/configmap-fluentbit.yaml index 62a7989a..dde0ae3d 100644 --- a/checkpoint/cloudguard/templates/admission/enforcer/configmap-fluentbit.yaml +++ b/checkpoint/cloudguard/templates/admission/enforcer/configmap-fluentbit.yaml @@ -19,19 +19,9 @@ data: Tag ac-alert [OUTPUT] - Name http Match ac-alert - Format json_stream - Host ${CP_KUBERNETES_DOME9_URL} Uri ${CP_KUBERNETES_ADMISSION_CONTROLLER_ALERTS_URI} - Port 443 - Compress gzip - tls On - tls.verify On - tls.debug 0 - http_User ${CP_KUBERNETES_USER} - http_Passwd ${CP_KUBERNETES_PASS} - Header Kubernetes-Account ${CP_KUBERNETES_CLUSTER_ID} +{{ include "fluentbit-http-output-param.conf" . | indent 8 }} {{ $params := dict "metricPath" "/metric" "agentVersion" $config.agentConfig.tag }} {{ include "fluentbit-metric.conf" $params | indent 4 }} diff --git a/checkpoint/cloudguard/templates/runtime/daemon/configmap-fluentbit.yaml b/checkpoint/cloudguard/templates/runtime/daemon/configmap-fluentbit.yaml index 33a371dc..7fd542e9 100644 --- a/checkpoint/cloudguard/templates/runtime/daemon/configmap-fluentbit.yaml +++ b/checkpoint/cloudguard/templates/runtime/daemon/configmap-fluentbit.yaml @@ -24,37 +24,25 @@ data: Path /rp4c/profiling/profiling.log Tag rp-profiling + [INPUT] + Name tail + Path /rp4c/telemetry/telemetry.log + Tag rp-telemetry + [OUTPUT] - Name http Match rp-alert - Format json_lines - Host ${CP_KUBERNETES_DOME9_URL} Uri ${CP_KUBERNETES_RUNTIME_ALERT_URI} - Port 443 - Compress gzip - tls On - tls.verify On - tls.debug 0 - http_User ${CP_KUBERNETES_USER} - http_Passwd ${CP_KUBERNETES_PASS} - Header Kubernetes-Account ${CP_KUBERNETES_CLUSTER_ID} - Header Node-Name ${HOSTNAME} +{{ include "fluentbit-http-output-param.conf" . | indent 8 }} [OUTPUT] - Name http Match rp-profiling - Format json_lines - Host ${CP_KUBERNETES_DOME9_URL} Uri ${CP_KUBERNETES_RUNTIME_PROFILING_URI} - Port 443 - Compress gzip - tls On - tls.verify On - tls.debug 0 - http_User ${CP_KUBERNETES_USER} - http_Passwd ${CP_KUBERNETES_PASS} - Header Kubernetes-Account ${CP_KUBERNETES_CLUSTER_ID} - Header Node-Name ${HOSTNAME} +{{ include "fluentbit-http-output-param.conf" . | indent 8 }} + + [OUTPUT] + Match rp-telemetry + Uri ${CP_KUBERNETES_RUNTIME_TELEMETRY_URI} +{{ include "fluentbit-http-output-param.conf" . | indent 8 }} {{ $params := dict "metricPath" "/rp4c/metric" "agentVersion" $config.agentConfig.tag }} {{ include "fluentbit-metric.conf" $params | indent 4 }} diff --git a/checkpoint/cloudguard/templates/runtime/daemon/daemonset.yaml b/checkpoint/cloudguard/templates/runtime/daemon/daemonset.yaml index b0f92669..27e03014 100644 --- a/checkpoint/cloudguard/templates/runtime/daemon/daemonset.yaml +++ b/checkpoint/cloudguard/templates/runtime/daemon/daemonset.yaml @@ -65,6 +65,38 @@ spec: mountPath: /host/dev {{- end }} containers: + # fluentbit + # the fluentbit container needs to be before the daemon container + # so the fluentbit will be up before the daemon to send message that daemon will send once it is up (like telemetry) + - name: fluentbit + image: {{ template "agent.fluentbit.image" $config }} + imagePullPolicy: {{ .Values.imagePullPolicy }} + env: +{{ include "fluentbit.env" $config | indent 8 }} + - name: CP_KUBERNETES_RUNTIME_ALERT_URI + value: {{ template "cloudguardURL_path" . }}runtimeevent/alert + - name: CP_KUBERNETES_RUNTIME_PROFILING_URI + value: {{ template "cloudguardURL_path" . }}runtimeevent/profiling + - name: CP_KUBERNETES_METRIC_URI + value: {{ template "cloudguardURL_path" . }}agenttelemetry + - name: CP_KUBERNETES_RUNTIME_TELEMETRY_URI + value: {{ template "cloudguardURL_path" . }}runtimetelemetry + {{- if $config.agentConfig.fluentbit.resources }} + resources: +{{ toYaml $config.agentConfig.fluentbit.resources | indent 10}} + {{- end }} + volumeMounts: + - name: rp4c-alerts + mountPath: /rp4c/alerts + - name: rp4c-profiling + mountPath: /rp4c/profiling + - name: rp4c-metric + mountPath: /rp4c/metric + - name: rp4c-telemetry + mountPath: /rp4c/telemetry + - name: config-volume-fluentbit + mountPath: /fluent-bit/etc/fluent-bit.conf + subPath: fluent-bit.conf # Main container - name: {{ $config.agentName }} image: {{ template "agent.main.image" $config }} @@ -81,19 +113,12 @@ spec: {{ include "user.defined.env" $config | indent 8 }} - name: LANG value: C.UTF-8 -## TODO : Temporary solution for internal deployment - should omit ############################################################# - - name: CP_KUBERNETES_CLUSTER_ID - valueFrom: - configMapKeyRef: - name: {{ .Release.Name }}-cp-cloudguard-configmap - key: clusterID - - name: SBA_MANAGEMENT_URL - value: https://{{ .Release.Name }}-ClusterID-$(CP_KUBERNETES_CLUSTER_ID) -############################################################################################################################### - name: NAMESPACE_NAME valueFrom: fieldRef: fieldPath: metadata.namespace + - name: SBA_TELEMETRY_SAVE_TO_FILE + value: "1" {{- if $config.featureConfig.BPF }} - name: SYSDIG_BPF_PROBE value: "/sysdig/.sysdig/sysdig-probe-bpf.o" @@ -106,7 +131,9 @@ spec: - name: rp4c-profiling mountPath: /rp4c/profiling - name: rp4c-metric - mountPath: /rp4c/metric + mountPath: /rp4c/metric + - name: rp4c-telemetry + mountPath: /rp4c/telemetry - name: docker-sock mountPath: /var/run/docker.sock readOnly: true @@ -127,32 +154,6 @@ spec: - name: sys-vol mountPath: /sys/kernel/debug/ readOnly: true - # fluentbit - - name: fluentbit - image: {{ template "agent.fluentbit.image" $config }} - imagePullPolicy: {{ .Values.imagePullPolicy }} - env: -{{ include "fluentbit.env" $config | indent 8 }} - - name: CP_KUBERNETES_RUNTIME_ALERT_URI - value: {{ template "cloudguardURL_path" . }}runtimeevent/alert - - name: CP_KUBERNETES_RUNTIME_PROFILING_URI - value: {{ template "cloudguardURL_path" . }}runtimeevent/profiling - - name: CP_KUBERNETES_METRIC_URI - value: {{ template "cloudguardURL_path" . }}agenttelemetry - {{- if $config.agentConfig.fluentbit.resources }} - resources: -{{ toYaml $config.agentConfig.fluentbit.resources | indent 10}} - {{- end }} - volumeMounts: - - name: rp4c-alerts - mountPath: /rp4c/alerts - - name: rp4c-profiling - mountPath: /rp4c/profiling - - name: rp4c-metric - mountPath: /rp4c/metric - - name: config-volume-fluentbit - mountPath: /fluent-bit/etc/fluent-bit.conf - subPath: fluent-bit.conf volumes: - name: config-volume-fluentbit configMap: @@ -162,6 +163,8 @@ spec: - name: rp4c-profiling emptyDir: {} - name: rp4c-metric + emptyDir: {} + - name: rp4c-telemetry emptyDir: {} - name: docker-sock hostPath: diff --git a/checkpoint/cloudguard/values.yaml b/checkpoint/cloudguard/values.yaml index f76c0b43..4ecde6a5 100644 --- a/checkpoint/cloudguard/values.yaml +++ b/checkpoint/cloudguard/values.yaml @@ -291,7 +291,7 @@ addons: ## Main container settings ## Specify image and tag image: checkpoint/consec-runtime-daemon - tag: 0.0.301 + tag: 0.0.347 ## Specify existing service account name ("" to create) serviceAccountName: "" diff --git a/repository/cloudguard-2.0.8.tgz b/repository/cloudguard-2.0.8.tgz new file mode 100644 index 0000000000000000000000000000000000000000..34534869bb3586e1a5d3a014fdeaa907b6d63766 GIT binary patch literal 16362 zcmZv@Wn5I>7d|?Kbf-vnhjh1eBT~X3A>AD^gtT-@BPAdpNY{|kp-6Xk=fE)M^8Nj9 zyt(sY_Gf0Fv(BD1d#`8JLmP)d0{ZU-u!A^1sOa%osb~so_=^cy3cTa9))%rj(H9fe ze)mpT)6mJ`gNwEQTU}Qv6&ojK&~c}~=aT3xNEE1%e(`SDDFtEt&%RyRptIe@RJDE4 z{e4p^%-g1oD*7{16MGnLh>u|1-7nXT^-qUjFZ6T90%9e0JM^Fn1jOiGV_ zXqeMvZZ1z&ze=YMyztOaE+FO8F~Hi1*Ddge+AE+_u69jI^j^7q>C6`&fh11(o3XJa zP3|&rV)4^}jEgds*O+#+4)KzL+nl59Am-CQ@x@786y3ZmJmSfOZr7n~l)O}|EDPiW zTNUUF^7#e|(cOmYglVFC5te4MNVFFDHg%0AyRmaB+@3G5qwtoTM`#(xyFIUYH3zS5 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