please wait, site is loading

Info Web Hub

Аудит кластера Kubernetes с помощью Wazuh

Wazuh, как SIEM система является мощным компонентом обеспечивающим безопасность кластера K8s. Он анализирует данные журналов в реальном времени, обеспечивая раннее обнаружение угроз и способствуя быстрому реагированию на инциденты. Способность Wazuh собирать и интерпретировать данные из среды Kubernetes позволяет командам безопасности выявлять угрозы и оперативно реагировать на них, сводя к минимуму потенциальный ущерб.

Кроме анализа угроз, Wazuh помогает продемонстрировать соответствие отраслевым стандартам безопасности, создавая подробные отчеты о событиях и мерах безопасности. После инцидента он предоставляет ценные данные для детальной экспертизы, позволяя командам понять причину инцидента и предотвратить его повторение в будущем.

В этой статье мы рассмотрим основной процесс создания оповещений о событиях Kubernetes с помощью Wazuh, в частности для кластера RKE2.

План работ

  1. Создадим Webhook listener на сервере Wazuh, чтобы получать логи из кластера K8s.
  2. Включим аудит в кластере K8s, и настроим отправку логов на сервер Wazuh
  3. Создадим правила обработки событий, полученных сервером Wazuh от кластера K8s.

Требования

  • Сервер Wazuh
  • Кластер Kubernetes

Настраиваем сервер Wazuh

Создадим webhook listener на сервере Wazuh, для получения логов с нашего сервера. Так же в этой части мы создадим сертификаты для обеспечения условно-безопасного взаимодействия между сервером Wazuh и кластером K8s.

Логинимся в сервер Wazuh:

ssh user@wazuhServer

Создаём директорию для webhook endpoint:

 mkdir -p /var/ossec/integrations/kubernetes-webhook/

Создаём конфигурационный файл сертификата - /var/ossec/integrations/kubernetes-webhook/csr.conf:

Файл можно использовать как есть, только заменив <wazuh_server_ip> на адрес своего сервера.

[ req ]prompt = nodefault_bits = 2048default_md = sha256distinguished_name = req_distinguished_namex509_extensions = v3_req[req_distinguished_name]C = USST = CaliforniaL = San JoseO = WazuhOU = Research and developmentemailAddress = Этот адрес электронной почты защищён от спам-ботов. У вас должен быть включен JavaScript для просмотра. = <wazuh_server_ip>[ v3_req ]authorityKeyIdentifier=keyid,issuerbasicConstraints = CA:FALSEkeyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEnciphermentsubjectAltName = @alt_names[alt_names]IP.1 = <wazuh_server_ip>

Создаём публичный и приватны ключи:

openssl req -x509 -new -nodes -newkey rsa:2048 -keyout /var/ossec/integrations/kubernetes-webhook/rootCA.key -out /var/ossec/integrations/kubernetes-webhook/rootCA.pem -batch -subj "/C=US/ST=California/L=San Jose/O=Wazuh"

Создаём запрос на подписание ключей:

openssl req -new -nodes -newkey rsa:2048 -keyout /var/ossec/integrations/kubernetes-webhook/server.key -out /var/ossec/integrations/kubernetes-webhook/server.csr -config /var/ossec/integrations/kubernetes-webhook/csr.conf

Генерируем сертификат сервера:

openssl x509 -req -in /var/ossec/integrations/kubernetes-webhook/server.csr -CA /var/ossec/integrations/kubernetes-webhook/rootCA.pem -CAkey /var/ossec/integrations/kubernetes-webhook/rootCA.key -CAcreateserial -out /var/ossec/integrations/kubernetes-webhook/server.crt -extfile /var/ossec/integrations/kubernetes-webhook/csr.conf -extensions v3_req

Создаём Webhook listener

Установим Flask (впрочем лучшим вариантом будет сделать это с помощью пакетного менеджера)

/var/ossec/framework/python/bin/pip3 install flask

Создадим Python webhook listener /var/ossec/integrations/custom-webhook.py. <wazuh_server_ip> здесь так же будет заменяться вашим IP.

 #!/var/ossec/framework/python/bin/python3 import json from socket import socket, AF_UNIX, SOCK_DGRAM from flask import Flask, request PORT     = 8080 CERT     = ‘/var/ossec/integrations/kubernetes-webhook/server.crt’ CERT_KEY = ‘/var/ossec/integrations/kubernetes-webhook/server.key’ socket_addr = ‘/var/ossec/queue/sockets/queue’ def send_event(msg):     string = ‘1:k8s:{0}’.format(json.dumps(msg))     sock = socket(AF_UNIX, SOCK_DGRAM)     sock.connect(socket_addr)     sock.send(string.encode())     sock.close()     return True app = Flask(__name__) context = (CERT, CERT_KEY) @app.route(’/’, methods=[’POST’]) def webhook():     if request.method == ‘POST’:         if send_event(request.json):             print("Request sent to Wazuh")         else:             print("Failed to send request to Wazuh")     return "Webhook received!" if __name__ == ‘__main__’:     app.run(host=’<wazuh_server_ip>’, port=PORT, ssl_context=context)

Создаём сервис systemd

 [Unit] Description=Wazuh webhook Wants=network-online.target After=network.target network-online.target [Service] ExecStart=/var/ossec/framework/python/bin/python3 /var/ossec/integrations/custom-webhook.py Restart=on-failure [Install] WantedBy=multi-user.target

И сразу запускаем его:

systemctl daemon-reloadsystemctl enable wazuh-webhook.servicesystemctl start wazuh-webhook.service
Если на сервере Wazuh запущен firewall, то не забудьте разрешить подключения по порту 8080

Настройка кластера K8s

Create log directory: mkdir -p -m 700 /var/lib/rancher/k3s/server/logs

Создаём политику аудита /var/lib/rancher/k3s/server/audit.yaml :

apiVersion: [audit.k8s.io/v1](http://audit.k8s.io/v1)kind: Policyrules:# Don’t log requests to the following API endpoints- level: NonenonResourceURLs:- ‘/healthz*’- ‘/logs’- ‘/metrics’- ‘/swagger*’- ‘/version’ # Limit requests containing tokens to Metadata level so the token is not included in the log - level: Metadata   omitStages:       - RequestReceived   resources:       - group: authentication.k8s.io         resources:             - tokenreviews # Extended audit of auth delegation - level: RequestResponse   omitStages:       - RequestReceived   resources:       - group: authorization.k8s.io         resources:             - subjectaccessreviews # Log changes to pods at RequestResponse level - level: RequestResponse   omitStages:       - RequestReceived   resources:       # core API group; add third-party API services and your API services if needed       - group: ‘’         resources: [’pods’]         verbs: [’create’, ‘patch’, ‘update’, ‘delete’] # Log everything else at Metadata level - level: Metadata   omitStages:       - RequestReceived

Создадим конфигурационный файл Webhook /var/lib/rancher/k3s/server/audit-webhook.yaml, не забыв заменить в нём <wazuh_server_ip> своим ip:

apiVersion: v1 kind: Config preferences: {} clusters:   - name: wazuh-webhook     cluster:       insecure-skip-tls-verify: true       server: https://<wazuh_server_ip>:8080 # kubeconfig files require a context. Provide one for the API server. current-context: webhook contexts: - context:     cluster: wazuh-webhook     user: kube-apiserver # Replace with name of API server if it’s different   name: webhook

Добавим параметры Kubeapi, для загрузки конфигурации аудита и webhook (путь к сервису systemd для rke2-server.service - /usr/lib/systemd/system/rke2-server.service)

ExecStart=/usr/local/bin/rke2 \server \’--kube-apiserver-arg=audit-log-path=/var/lib/rancher/rke2/server/logs/audit.log’ \’--kube-apiserver-arg=audit-policy-file=/var/lib/rancher/rke2/server/audit.yaml’ \’--kube-apiserver-arg=audit-webhook-config-file=/var/lib/rancher/rke2/server/audit-webhook.yaml’ \’--kube-apiserver-arg=audit-webhook-batch-max-size=1’ \

Создаём правило обнаружения на сервере Wazuh

Добавляем следующие правила на сервер Wazuh в/var/ossec/etc/rules/local_rules.xml :

 <group name="k8s_audit,">   <rule id="110002" level="0">     <location>k8s</location>     <field name="apiVersion">audit</field>     <description>Kubernetes audit log.</description>   </rule>   <rule id="110003" level="5">     <if_sid>110002</if_sid>     <regex type="pcre2">requestURI\":.+", \"verb\": \"create</regex>     <description>Kubernetes request to create resource</description>   </rule>   <rule id="110004" level="5">     <if_sid>110002</if_sid>     <regex type="pcre2">requestURI\":.+", \"verb\": \"delete</regex>     <description>Kubernetes request to delete resource</description>   </rule> </group>

Перезапускаем сервис wazuh-manager

 systemctl restart wazuh-manager

Тестируем конфигурацию и правила, создавая и удаляя деплойменты на кластере. Например запустим на мастер-ноде команду:

kubectl create deployment hello-minikube --image=[k8s.gcr.io/echoserver:1.4](http://k8s.gcr.io/echoserver:1.4)

И сразу же, после того как дождёмся создания деплоймента, удаляем его:

kubectl delete deployment hello-minikube

В целом всё готово. Можно настроить уведомления в почту, телеграм и так далее, но это уже темы для отдельной статьи.