| @@ -0,0 +1,14 @@ | ||
| + | INDEXER_USERNAME=admin | |
| + | INDEXER_PASSWORD=changeme-indexer | |
| + | DASHBOARD_USERNAME=kibanaserver | |
| + | DASHBOARD_PASSWORD=changeme-dashboard | |
| + | WAZUH_API_USER=wazuh-wui | |
| + | WAZUH_API_PASSWORD=changeme-api | |
| + | ||
| + | THEHIVE_SECRET=replace-with-64-char-random-string | |
| + | THEHIVE_PORT=9000 | |
| + | ||
| + | CORTEX_PORT=9001 | |
| + | ||
| + | SHUFFLE_WEBHOOK_URL=http://shuffle-backend:5001/api/v1/hooks/webhook_REPLACE | |
| + | THEHIVE_API_KEY=replace-with-thehive-api-key |
| @@ -0,0 +1,10 @@ | ||
| + | .env | |
| + | config/wazuh/certs/ | |
| + | *.pem | |
| + | *.key | |
| + | *.crt | |
| + | data/ | |
| + | *.log | |
| + | .DS_Store | |
| + | __pycache__/ | |
| + | *.pyc |
| @@ -0,0 +1,10 @@ | ||
| + | nodes: | |
| + | indexer: | |
| + | - name: wazuh-indexer | |
| + | ip: wazuh-indexer | |
| + | server: | |
| + | - name: wazuh-manager | |
| + | ip: wazuh-manager | |
| + | dashboard: | |
| + | - name: wazuh-dashboard | |
| + | ip: wazuh-dashboard |
| @@ -0,0 +1,31 @@ | ||
| + | network.host: "0.0.0.0" | |
| + | node.name: "wazuh-indexer" | |
| + | cluster.initial_master_nodes: | |
| + | - "wazuh-indexer" | |
| + | cluster.name: "wazuh-cluster" | |
| + | discovery.seed_hosts: | |
| + | - "wazuh-indexer" | |
| + | node.max_local_storage_nodes: "3" | |
| + | path.data: /var/lib/wazuh-indexer | |
| + | path.logs: /var/log/wazuh-indexer | |
| + | ||
| + | plugins.security.ssl.http.pemcert_filepath: /usr/share/wazuh-indexer/certs/wazuh-indexer.pem | |
| + | plugins.security.ssl.http.pemkey_filepath: /usr/share/wazuh-indexer/certs/wazuh-indexer-key.pem | |
| + | plugins.security.ssl.http.pemtrustedcas_filepath: /usr/share/wazuh-indexer/certs/root-ca.pem | |
| + | plugins.security.ssl.transport.pemcert_filepath: /usr/share/wazuh-indexer/certs/wazuh-indexer.pem | |
| + | plugins.security.ssl.transport.pemkey_filepath: /usr/share/wazuh-indexer/certs/wazuh-indexer-key.pem | |
| + | plugins.security.ssl.transport.pemtrustedcas_filepath: /usr/share/wazuh-indexer/certs/root-ca.pem | |
| + | plugins.security.ssl.http.enabled: true | |
| + | plugins.security.ssl.transport.enforce_hostname_verification: false | |
| + | plugins.security.ssl.transport.resolve_hostname: false | |
| + | ||
| + | plugins.security.authcz.admin_dn: | |
| + | - "CN=admin,OU=Wazuh,O=Wazuh,L=California,C=US" | |
| + | plugins.security.nodes_dn: | |
| + | - "CN=wazuh-indexer,OU=Wazuh,O=Wazuh,L=California,C=US" | |
| + | plugins.security.restapi.roles_enabled: | |
| + | - "all_access" | |
| + | - "security_rest_api_access" | |
| + | plugins.security.allow_default_init_securityindex: true | |
| + | plugins.security.check_snapshot_restore_write_privileges: true | |
| + | plugins.security.enable_snapshot_restore_privilege: true |
| @@ -0,0 +1,67 @@ | ||
| + | <ossec_config> | |
| + | <global> | |
| + | <jsonout_output>yes</jsonout_output> | |
| + | <alerts_log>yes</alerts_log> | |
| + | <logall>no</logall> | |
| + | <logall_json>no</logall_json> | |
| + | <email_notification>no</email_notification> | |
| + | </global> | |
| + | ||
| + | <alerts> | |
| + | <log_alert_level>3</log_alert_level> | |
| + | </alerts> | |
| + | ||
| + | <remote> | |
| + | <connection>secure</connection> | |
| + | <port>1514</port> | |
| + | <protocol>tcp</protocol> | |
| + | <queue_size>131072</queue_size> | |
| + | </remote> | |
| + | ||
| + | <auth> | |
| + | <disabled>no</disabled> | |
| + | <port>1515</port> | |
| + | <use_source_ip>no</use_source_ip> | |
| + | <force> | |
| + | <enabled>yes</enabled> | |
| + | <after_registration_time>1h</after_registration_time> | |
| + | </force> | |
| + | <purge>yes</purge> | |
| + | <use_password>no</use_password> | |
| + | </auth> | |
| + | ||
| + | <ruleset> | |
| + | <decoder_dir>ruleset/decoders</decoder_dir> | |
| + | <rule_dir>ruleset/rules</rule_dir> | |
| + | <decoder_dir>etc/decoders</decoder_dir> | |
| + | <rule_dir>etc/rules</rule_dir> | |
| + | <list>etc/lists/cti-malicious-ip</list> | |
| + | <list>etc/lists/cti-malicious-domain</list> | |
| + | <list>etc/lists/cti-malware-hash</list> | |
| + | </ruleset> | |
| + | ||
| + | <integration> | |
| + | <name>custom-thehive</name> | |
| + | <hook_url>SET_FROM_ENV_SHUFFLE_WEBHOOK_URL</hook_url> | |
| + | <level>10</level> | |
| + | <alert_format>json</alert_format> | |
| + | </integration> | |
| + | ||
| + | <command> | |
| + | <name>firewall-drop</name> | |
| + | <executable>firewall-drop</executable> | |
| + | <timeout_allowed>yes</timeout_allowed> | |
| + | </command> | |
| + | ||
| + | <active-response> | |
| + | <command>firewall-drop</command> | |
| + | <location>local</location> | |
| + | <rules_id>100210</rules_id> | |
| + | <timeout>600</timeout> | |
| + | </active-response> | |
| + | ||
| + | <vulnerability-detection> | |
| + | <enabled>yes</enabled> | |
| + | <index-status>yes</index-status> | |
| + | </vulnerability-detection> | |
| + | </ossec_config> |
| @@ -0,0 +1,148 @@ | ||
| + | name: soc-automation-lab | |
| + | ||
| + | services: | |
| + | wazuh-indexer: | |
| + | image: wazuh/wazuh-indexer:4.9.0 | |
| + | hostname: wazuh-indexer | |
| + | restart: always | |
| + | ports: | |
| + | - "9200:9200" | |
| + | environment: | |
| + | - OPENSEARCH_JAVA_OPTS=-Xms1g -Xmx1g | |
| + | - bootstrap.memory_lock=true | |
| + | ulimits: | |
| + | memlock: | |
| + | soft: -1 | |
| + | hard: -1 | |
| + | nofile: | |
| + | soft: 65536 | |
| + | hard: 65536 | |
| + | volumes: | |
| + | - indexer-data:/var/lib/wazuh-indexer | |
| + | - ./config/wazuh/certs/wazuh-indexer.pem:/usr/share/wazuh-indexer/certs/wazuh-indexer.pem | |
| + | - ./config/wazuh/certs/wazuh-indexer-key.pem:/usr/share/wazuh-indexer/certs/wazuh-indexer-key.pem | |
| + | - ./config/wazuh/certs/root-ca.pem:/usr/share/wazuh-indexer/certs/root-ca.pem | |
| + | - ./config/wazuh/certs/admin.pem:/usr/share/wazuh-indexer/certs/admin.pem | |
| + | - ./config/wazuh/certs/admin-key.pem:/usr/share/wazuh-indexer/certs/admin-key.pem | |
| + | - ./config/wazuh/indexer/wazuh.indexer.yml:/usr/share/wazuh-indexer/opensearch.yml | |
| + | ||
| + | wazuh-manager: | |
| + | image: wazuh/wazuh-manager:4.9.0 | |
| + | hostname: wazuh-manager | |
| + | restart: always | |
| + | depends_on: | |
| + | - wazuh-indexer | |
| + | ports: | |
| + | - "1514:1514" | |
| + | - "1515:1515" | |
| + | - "514:514/udp" | |
| + | - "55000:55000" | |
| + | environment: | |
| + | - INDEXER_URL=https://wazuh-indexer:9200 | |
| + | - INDEXER_USERNAME=${INDEXER_USERNAME} | |
| + | - INDEXER_PASSWORD=${INDEXER_PASSWORD} | |
| + | - API_USERNAME=${WAZUH_API_USER} | |
| + | - API_PASSWORD=${WAZUH_API_PASSWORD} | |
| + | volumes: | |
| + | - manager-config:/var/ossec/etc | |
| + | - manager-logs:/var/ossec/logs | |
| + | - ./config/wazuh/manager/ossec.conf:/wazuh-config-mount/etc/ossec.conf | |
| + | - ./config/wazuh/rules/local_rules.xml:/var/ossec/etc/rules/local_rules.xml | |
| + | - ./config/wazuh/decoders/local_decoder.xml:/var/ossec/etc/decoders/local_decoder.xml | |
| + | - ./integrations/custom-thehive.py:/var/ossec/integrations/custom-thehive.py | |
| + | - ./integrations/custom-thehive:/var/ossec/integrations/custom-thehive | |
| + | - ./config/wazuh/lists/cti-malicious-ip:/var/ossec/etc/lists/cti-malicious-ip | |
| + | - ./config/wazuh/lists/cti-malicious-domain:/var/ossec/etc/lists/cti-malicious-domain | |
| + | - ./config/wazuh/lists/cti-malware-hash:/var/ossec/etc/lists/cti-malware-hash | |
| + | - ./config/wazuh/certs/root-ca.pem:/usr/share/wazuh/certs/root-ca.pem | |
| + | ||
| + | wazuh-dashboard: | |
| + | image: wazuh/wazuh-dashboard:4.9.0 | |
| + | hostname: wazuh-dashboard | |
| + | restart: always | |
| + | depends_on: | |
| + | - wazuh-indexer | |
| + | ports: | |
| + | - "5601:5601" | |
| + | environment: | |
| + | - INDEXER_USERNAME=${INDEXER_USERNAME} | |
| + | - INDEXER_PASSWORD=${INDEXER_PASSWORD} | |
| + | - DASHBOARD_USERNAME=${DASHBOARD_USERNAME} | |
| + | - DASHBOARD_PASSWORD=${DASHBOARD_PASSWORD} | |
| + | volumes: | |
| + | - ./config/wazuh/certs/wazuh-dashboard.pem:/usr/share/wazuh-dashboard/certs/wazuh-dashboard.pem | |
| + | - ./config/wazuh/certs/wazuh-dashboard-key.pem:/usr/share/wazuh-dashboard/certs/wazuh-dashboard-key.pem | |
| + | - ./config/wazuh/certs/root-ca.pem:/usr/share/wazuh-dashboard/certs/root-ca.pem | |
| + | ||
| + | cassandra: | |
| + | image: cassandra:4.1 | |
| + | hostname: cassandra | |
| + | restart: always | |
| + | environment: | |
| + | - MAX_HEAP_SIZE=1024M | |
| + | - HEAP_NEWSIZE=1024M | |
| + | - CASSANDRA_CLUSTER_NAME=thehive | |
| + | volumes: | |
| + | - cassandra-data:/var/lib/cassandra | |
| + | ||
| + | elasticsearch: | |
| + | image: docker.elastic.co/elasticsearch/elasticsearch:7.17.20 | |
| + | hostname: elasticsearch | |
| + | restart: always | |
| + | environment: | |
| + | - discovery.type=single-node | |
| + | - xpack.security.enabled=false | |
| + | - "ES_JAVA_OPTS=-Xms1g -Xmx1g" | |
| + | ulimits: | |
| + | memlock: | |
| + | soft: -1 | |
| + | hard: -1 | |
| + | volumes: | |
| + | - es-data:/usr/share/elasticsearch/data | |
| + | ||
| + | cortex: | |
| + | image: thehiveproject/cortex:3.1.8 | |
| + | hostname: cortex | |
| + | restart: always | |
| + | depends_on: | |
| + | - elasticsearch | |
| + | ports: | |
| + | - "${CORTEX_PORT}:9001" | |
| + | environment: | |
| + | - job_directory=/tmp/cortex-jobs | |
| + | volumes: | |
| + | - /var/run/docker.sock:/var/run/docker.sock | |
| + | - cortex-jobs:/tmp/cortex-jobs | |
| + | ||
| + | thehive: | |
| + | image: strangebee/thehive:5.4.0-1 | |
| + | hostname: thehive | |
| + | restart: always | |
| + | depends_on: | |
| + | - cassandra | |
| + | - elasticsearch | |
| + | - cortex | |
| + | ports: | |
| + | - "${THEHIVE_PORT}:9000" | |
| + | command: | |
| + | - --secret | |
| + | - ${THEHIVE_SECRET} | |
| + | - "--cql-hostnames" | |
| + | - cassandra | |
| + | - "--index-backend" | |
| + | - elasticsearch | |
| + | - "--es-hostnames" | |
| + | - elasticsearch | |
| + | - "--cortex-hostnames" | |
| + | - cortex | |
| + | volumes: | |
| + | - thehive-data:/opt/thp/thehive/data | |
| + | ||
| + | volumes: | |
| + | indexer-data: | |
| + | manager-config: | |
| + | manager-logs: | |
| + | cassandra-data: | |
| + | es-data: | |
| + | cortex-jobs: | |
| + | thehive-data: |
| @@ -0,0 +1,60 @@ | ||
| + | #!/usr/bin/env bash | |
| + | set -euo pipefail | |
| + | ||
| + | ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" | |
| + | CERT_DIR="${ROOT}/config/wazuh/certs" | |
| + | ||
| + | cd "${ROOT}" | |
| + | ||
| + | if [[ ! -f .env ]]; then | |
| + | echo "no .env found - copy .env.example to .env and fill it in first" >&2 | |
| + | exit 1 | |
| + | fi | |
| + | ||
| + | generate_certs() { | |
| + | if [[ -f "${CERT_DIR}/root-ca.pem" ]]; then | |
| + | echo "certs already present, skipping generation" | |
| + | return | |
| + | fi | |
| + | echo "generating indexer certificates" | |
| + | mkdir -p "${CERT_DIR}" | |
| + | docker run --rm \ | |
| + | -v "${CERT_DIR}:/certs" \ | |
| + | -v "${ROOT}/config/wazuh/certs.yml:/config/certs.yml:ro" \ | |
| + | wazuh/wazuh-certs-generator:0.0.2 | |
| + | chmod 640 "${CERT_DIR}"/*.pem | |
| + | } | |
| + | ||
| + | wait_for_indexer() { | |
| + | echo "waiting for the indexer to come up" | |
| + | for _ in $(seq 1 40); do | |
| + | if curl -sk -u "${INDEXER_USERNAME}:${INDEXER_PASSWORD}" \ | |
| + | https://localhost:9200/_cluster/health | grep -q '"status"'; then | |
| + | echo "indexer is responding" | |
| + | return 0 | |
| + | fi | |
| + | sleep 10 | |
| + | done | |
| + | echo "indexer did not become ready in time" >&2 | |
| + | return 1 | |
| + | } | |
| + | ||
| + | set -a | |
| + | source .env | |
| + | set +a | |
| + | ||
| + | generate_certs | |
| + | docker compose up -d | |
| + | wait_for_indexer | |
| + | ||
| + | cat <<EOF | |
| + | ||
| + | stack is up. | |
| + | ||
| + | Wazuh dashboard https://localhost:5601 (${DASHBOARD_USERNAME}) | |
| + | TheHive http://localhost:${THEHIVE_PORT} | |
| + | Cortex http://localhost:${CORTEX_PORT} | |
| + | ||
| + | Next: bring up Shuffle (cd shuffle && docker compose up -d), import the | |
| + | workflow, and paste the webhook URL into config/wazuh/manager/ossec.conf. | |
| + | EOF |