Imagine if u have an application deployed in a kubernates cluster, you would want to have its log ingested into wazuh, To do it we install fluentd and fluentbit into the cluster and node respectively.
Parts/components
| Component | Description | Usage |
|---|---|---|
| Fluentbit | A lightweight, and highly scalable logging and metrics processor and forwarder | Setup in every node to extract logs from application nodes and store in central location for fluentd access |
| FluentD | an open-source data collector and log processor that unifies data collection and consumption | Deployed in seperate deployment set to transfer logs out of the cluster into wazuh (or any other log collector/viz) |
Basic Steps:
- NOTE the step of configuring fluentbit and forwarding its logs to fluentd is skipped. follow the below tutorial for the same: Link
- Create a fluentd configmap
- Create a fluentd deployment with the syslog plugin
- Configure wazuh to listen to a syslog port
- Configure rules and decoder for the syslog data.
Steps in Detailed
-
Create a fluent.conf configmap.
apiVersion: v1 kind: ConfigMap metadata: namespace: fluentd name: fluent-conf labels: app: fluentd-logging data: fluentConf: | <match **> @type remote_syslog host "#{ENV['SERVER_IP']}" port 514 protocol tcp severity debug program fluentd hostname "#{ENV['HOST_NAME']}" <format> @type json </format> </match> -
Make a fluentd kubeconfig file similar to the below one:
apiVersion: apps/v1 kind: DaemonSet # can be statefulset too metadata: name: fluentd namespace: fluentd labels: app: fluentd-logging version: v1 kubernetes.io/cluster-service: "true" spec: selector: matchLabels: k8s-app: fluentd-logging version: v1 template: metadata: labels: k8s-app: fluentd-logging version: v1 spec: serviceAccount: fluentd serviceAccountName: fluentd containers: - name: fluentd image: fluent/fluentd-kubernetes-daemonset:v1.18.0-debian-elasticsearch8-1.4 command: - /bin/sh - -c - "fluent-gem install fluent-plugin-remote_syslog ; fluentd -c /fluentd/etc/${FLUENTD_CONF} -p /fluentd/plugins --gemfile /fluentd/Gemfile ${FLUENTD_OPT}" env: - name: DESTINATION value: "syslog-ng.fluentd.svc.cluster.local" - name: SOURCE value: "Fluent_D" - name: K8S_NODE_NAME valueFrom: fieldRef: fieldPath: spec.nodeName volumeMounts: - name: varlog mountPath: /var/log - name: dockercontainerlogdirectory mountPath: /var/lib/docker/containers readOnly: true - name: dockercontainerlogdirectory mountPath: /var/log/pods readOnly: true - name: fluentconf-volume mountPath: /fluentd/etc/fluent.conf subPath: fluent.conf readOnly: true securityContext: allowPrivilegeEscalation: false runAsUser: 0 terminationGracePeriodSeconds: 30 volumes: - name: varlog hostPath: path: /var/log - name: dockercontainerlogdirectory hostPath: path: /var/log/pods - name: fluentconf-volume configMap: name: fluent-conf items: - key: fluentConf path: fluent.conf -
Make the following Changes into wazuh’s ossec.conf file, the change ensures that wazuh will monitor the syslog port [514] for traffic, which will be logged in archive.log and archive.json if log all is enabled.
... <remote> <connection>syslog</connection> <port>514</port> <protocol>tcp</protocol> <allowed-ips>0.0.0.0/0</allowed-ips> <local_ip>wazuh-ip</local_ip> </remote> ...
NOTE: /var/ossec/logs/ossec.logs usually contains the logs of all wauzh processes, but since the syslogs from fluentd isnt a wazuh process it will not be logged there. you will have to enable the log all option and view the archive.log/archive.json file to see if the logs are flowing in or not.
-
Before creating the decoder you need to get an idea of how does the log look like (as in how does wazuh get it as an input). For that go to
/var/ossec/logs/archive.log[after enabling log all in ossec.conf]. Sample log will look like:-2024 Jul 18 11:52:01 Fluent_D->10.x.x.x Jul 18 06:22:01 Fluent_D fluentd: {"message":"[in_tail_kube_apiserver] /var/log/pods/kube-system_kube-apiserver-minikube_3c555f828409b009ebee39fdbedfcac0/kube-apiserver/0.log unreadable. It is excluded and would be examined next time."}in which wazuh will interpret it as follows:
2024 Jul 18 11:52:01 Fluent_D->10.160.15.217 Jul 18 06:22:01 Fluent_D fluentd: {“message”:“[in_tail_kube_apiserver] /var/log/pods/kube-system_kube-apiserver-minikube_3c555f828409b009ebee39fdbedfcac0/kube-apiserver/0.log unreadable. It is excluded and would be examined next time.”}
The green part is the syslog and all regex, matches, etc should be made with the green text in mind and not including the red part.
-
Create decoder for the logs ingested
<decoder name="fluent_sample"> <program_name>^fluentd</program_name> <plugin_decoder>JSON_Decoder</plugin_decoder> </decoder> -
Create rules too for the same and then everyone is happy
